Skip to content

feat(sdui-parser): warn on dashboard widget options keys no renderer consumes (#5709) - #5743

Merged
os-zhuang merged 3 commits into
mainfrom
claude/issue-5709-unconsumed-options-key-warning
Aug 23, 2026
Merged

feat(sdui-parser): warn on dashboard widget options keys no renderer consumes (#5709)#5743
os-zhuang merged 3 commits into
mainfrom
claude/issue-5709-unconsumed-options-key-warning

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes#5709

Implements the 2026-08-23 maintainer ruling (option B, 「其他同意你的意见」): a dashboard widget options key riding DashboardWidgetOptionsSchema.passthrough() that no renderer consumes now draws an authoring-time warning naming the consumed set. invert is the first pinned case, pinned as a case of the general mechanism (a different dead key on a different widget type draws the identical diagnostic). Open extras stay open — a document with such keys still parses, saves and renders; warning severity only, no new red gates.

Published API decisions (clause-2 surface — object to these by name)

This widens the diagnose() / validateTree output surface. The decisions, stated explicitly:

  • code: unconsumed-widget-option (exported constant UNCONSUMED_WIDGET_OPTION). One diagnostic per dead key, matching unknown-prop granularity, so consumers switching on d.code and filtering by message keep working unchanged.
  • severity: warning — pinned by a dedicated test; the ruling forbids escalation.
  • message shape: [host] widget "id-or-index" (widgetType): options.key reaches no renderer — dashboard widget renderers read only: dateGranularity, description, limit, sortBy, sortOrder, stageOrder (host tag in angle brackets in the real message; the consumed list is printed from the same exported array the check reads, so message and behavior cannot diverge).
  • scope: fires only on plain-object widgets in a widgets array of a dashboard / dashboard-grid node the manifest resolves, in the spec shorthand form, dataset-bound only, options a plain object, and not suppressed. Deferred $expr values are opaque and never guessed at.
  • escape hatch: the spec's own per-widget suppressWarnings: ["unconsumed-widget-option"] is honoured (spec-legal, verified against the installed 17.1.0 schema).
  • new exports from @object-ui/sdui-parser: checkDashboardWidgetOptions, CONSUMED_WIDGET_OPTION_KEYS, DASHBOARD_WIDGET_HOST_TYPES, UNCONSUMED_WIDGET_OPTION — so other surfaces (designer, save gates) can consume the same census instead of restating it.

The census (measurement-first, as ruled)

Measured on origin/main at 8689166f6, spec 17.1.0:

  • The spec requires dataset on every widget, and both dashboard surfaces (DashboardRenderer, DashboardGridLayout) route every dataset-bound widget through DatasetWidget — so the dataset path is the only spec-legal render path.
  • On that path the consumed options keys are exactly the five the spec declares: dateGranularity, sortBy, sortOrder, limit (query-affecting, DatasetWidget.tsx:436-446), stageOrder (funnel stage order, DatasetWidget.tsx:1160) — all direct options.key reads.
  • Plus one undeclared key with a real read site: description — the metric-card sub-caption channel (DashboardRenderer.tsx:412; the server's translateDashboard writes this key per the subCaption convention, objectstack#8056 / objectstack#5428). Warning on a key the platform's own translation pipeline writes would be a false positive, so it is accepted with documented evidence.
  • Consumption shapes measured (the 2c question): direct member access and one optional-chained cast read on the dataset path; wholesale ...options spreads exist only on the legacy non-dataset branches, which the warning deliberately skips — that is what keeps the census small enough to be maintainable.

Deviation from the ruling's premise — reported, not silently resolved

The ruling's docs instruction assumed gauge reads format / thresholds. The census falsified both for the spec-legal path: thresholds has zero read sites repo-wide, and the dataset-bound metric value is formatted with the dataset measure's own metadata (measureField(...).format/currency/percentScale, DatasetWidget.tsx:768), not options.format. (options.format is read only on the retired non-dataset inline path, via a spread into MetricWidget.) The ruling's own "plus whatever the census finds" makes the census authoritative, so: both keys draw the warning on dataset-bound widgets, and the gauge docs now state the measured truth — the number's format comes from the measure metadata; format / thresholds / invert have no read site there, with the derived-measure recipe (hotcrm's own fix) as the documented alternative. If the maintainer intended format/thresholds to be treated as consumed regardless, that is a one-line edit to CONSUMED_WIDGET_OPTION_KEYS plus its census-test pin — flagging for review rather than guessing.

Maintenance cost (the ruled deliverable)

The accepted set is one pinned array whose every input is re-measured on each test run by dashboard-widget-options-census.test.ts:

  1. the declared set re-derived from the installed @objectstack/spec schema (with a passthrough-premise probe and a dataset-required probe — if the spec changes either, the test names what to re-visit);
  2. the consumed set re-extracted from DatasetWidget.tsx source text, with loud refusal of any consumption shape the extractor cannot see (spread / destructuring / computed access) — under-counting is the false-positive direction and is designed to be impossible to introduce silently;
  3. the description read site re-checked;
  4. a repo tripwire (~70ms over ~1.5k files) pinning the file set that reads widget.options — a new consumer file turns the test red until the census is re-run.

Steady-state cost: a renderer change that adds/removes a consumed key turns one test red; the fix is editing one array plus its census notes. Instrument limits are stated in the test header (text census counts comments as reads — safe direction; the tripwire cannot see a renamed receiver such as w.options — known example documented). On this measurement the census is maintainable; the ruled fallback (D + honest docs) was not needed.

Docs (path outside packages/sdui-parser/**, reported per the fence)

content/docs/plugins/plugin-dashboard.mdx — new section "Widget options — what is actually read" with the consumed-key table, the warning and its escape hatch, and the gauge subsection (no dial renderer per #4295; format comes from the measure; derived-measure recipe for inversion).

Evidence

All commands at final head 83150f062, exit codes captured before any pipe, verdict lines quoted:

  • pnpm exec vitest run packages/sdui-parser/Test Files 9 passed (9), Tests 77 passed (77); lock-runner VERDICT command-exit 0.
  • pnpm run type-check (sdui-parser: tsc --noEmit && tsc -p tsconfig.test.json) — exit 0.
  • Downstream diagnose() consumers (plugin-grid gridNonAuthorKeys, console ga-honoured + union-specimens, schema-catalog pageheader, components record-picker parity): Test Files 5 passed (5), Tests 74 passed (74).
  • Full-repo pnpm lint (eslint . --no-inline-config): LINT_EXIT=0, 4m12s under the shared verify lock.
  • Gates: check:spec-symbols "spec alignment claims: 2 declared deliberate copies, 18 unbacked claims in 5 packages" exit 0 · check:doc-types "Every documented component type is registered" exit 0 · check:control-bytes "OK (scanned 4791 tracked text file(s))" exit 0 · check:esm-specifiers exit 0 · check:self-import exit 0 · check:phantom-deps "Every in-scope import is declared" exit 0 · changeset presence + no-major exit 0.
  • check:doc-snippets exits 1 with the known fresh-worktree shape ([unbuilt-package] ... dist/index.d.ts not on disk — run the build first; "The snippet program was NOT run") — the dispatch-listed worktree-broken gauge, not a diff failure; my docs edit adds no code fences. CI owns the real verdict.

Ablations (commit-first; mutations confirmed on disk by marker counts in both directions; restored under trap ... EXIT INT TERM; no build legs needed — these tests import package src via relative paths and the census reads renderer source text directly, so no dist resolution is involved)

  • A — census emptied (CONSUMED_WIDGET_OPTION_KEYS = []): 2 failed — exactly the two designed guards ("CONSUMED_WIDGET_OPTION_KEYS is non-empty..." and "every declared key is accepted..."). Measured justification for the vacuity guards: with an empty census the invert pin itself stays green (everything warns), so only explicit guards catch it.
  • B — emitter silenced (immediate return []): 7 behavior pins red, census green — the expected split. This leg caught one vacuously-passing loop (the message-naming test) which was hardened in 83150f062 with a non-emptiness assertion.
  • C — unseeable shape added ({ ...options } appended to DatasetWidget.tsx): "contains no consumption shape the extractor cannot see" red.
  • D — new renderer read added (options.ablationProbeKey): "the extracted read set equals the declared set — both directions" red.

Marker counts: mutate leg 1-in / anchors-out, restore leg 0-in / anchors-back, printed by each script.

Out of scope, filed

Generated by Claude Code


Generated by Claude Code

…consumes (#5709)
Maintainer ruling 2026-08-23 (option B): a key riding
DashboardWidgetOptionsSchema.passthrough() that no renderer consumes gets an
authoring-time WARNING naming the consumed set. `invert` is the first pinned
case, pinned as a case of the general mechanism.
Census (measured on 8689166, spec 17.1.0): the spec requires `dataset` on
every widget, both dashboard surfaces route dataset-bound widgets through
DatasetWidget, and on that path the consumed options keys are exactly the five
the spec declares — dateGranularity, sortBy, sortOrder, limit, stageOrder —
plus `description` (the subCaption translation convention,
DashboardRenderer.tsx read site). Notably NOT consumed on that path: `format`
(the metric value is formatted with the dataset measure's own metadata),
`thresholds` (zero read sites repo-wide), and `invert`. The census is
re-measured every test run: spec-declared keys re-derived from the installed
schema, DatasetWidget reads re-extracted from source (with loud failure on any
consumption shape the extractor cannot see), the sub-caption read site
re-checked, and a repo tripwire pinning the set of files that read
widget.options.
Scope: dataset-bound shorthand widgets on dashboard/dashboard-grid hosts only;
legacy inline forms (spec-illegal, spread-shaped consumption) are skipped, as
is the legacy component format. The spec's per-widget
suppressWarnings: ['unconsumed-widget-option'] escape hatch is honoured.
Warning severity only — no new red gates.
Docs: plugin-dashboard page now states what a dataset-bound widget's options
actually drive, and that gauge/solid-gauge/kpi/bullet render as a metric card
whose format comes from the measure metadata (per #4295 there is no dial
renderer).
Fixes#5709
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EuPCi56cnGyykygi3z9w4m
Ablation B (emitter silenced) left this test green: its for-loop asserted
nothing over an empty diagnostic list. Assert non-emptiness first.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EuPCi56cnGyykygi3z9w4m
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 52 chunks)3917.0 KB3990.2 KB
Main entry chunk (gzip)152.5 KB350 KB
Entry fileindex-DrbZl3Wq.js
StatusPASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)10.04KB3.72KB
app-shell (runtime-config.js)12.80KB4.47KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)32.45KB8.06KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)11.67KB4.55KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)510.39KB114.67KB
core (index.js)4.92KB1.97KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)164.55KB45.67KB
fields (index.js)238.40KB59.89KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)38.95KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.53KB3.38KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.64KB1.50KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)1.93KB0.88KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.65KB18.32KB
plugin-chatbot (index.js)181.41KB43.22KB
plugin-dashboard (index.js)128.41KB32.95KB
plugin-designer (index.js)212.30KB42.80KB
plugin-detail (index.js)242.34KB60.98KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)125.63KB30.64KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)200.79KB54.26KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.80KB27.20KB
plugin-map (index.js)20.06KB6.62KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.49KB11.93KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.61KB20.74KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)43.66KB14.77KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)12.13KB3.65KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)7.54KB2.63KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.59KB1.79KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 52 chunks)3225.3 KB3990.2 KB
Main entry chunk (gzip)152.6 KB350 KB
Entry fileindex-xfPThSyd.js
StatusPASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

PackageSizeGzipped
app-shell (consoleActionDispatch.js)0.20KB0.19KB
app-shell (index.js)10.04KB3.72KB
app-shell (runtime-config.js)12.80KB4.47KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)10.06KB3.86KB
auth (ActiveOrganizationStorage.js)25.05KB9.16KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)2.07KB1.00KB
auth (AuthProvider.js)33.99KB8.57KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.15KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.65KB2.22KB
auth (SocialSignInButtons.js)9.61KB3.89KB
auth (UserMenu.js)3.41KB1.23KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.80KB
auth (createAuthenticatedFetch.js)8.46KB3.43KB
auth (index.js)3.19KB1.44KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.30KB1.02KB
auth (useWorkspaceAdminStatus.js)5.13KB2.35KB
collaboration (CommentThread.js)26.08KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.68KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)503.77KB113.91KB
core (index.js)4.92KB1.97KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)164.55KB45.67KB
fields (index.js)238.40KB59.89KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)38.95KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.75KB
mobile (index.js)1.55KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.72KB0.42KB
mobile (useResponsiveConfig.js)1.37KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.53KB3.38KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.64KB1.50KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.93KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.53KB
permissions (usePermissions.js)1.93KB0.88KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.65KB18.32KB
plugin-chatbot (index.js)181.41KB43.22KB
plugin-dashboard (index.js)128.41KB32.95KB
plugin-designer (index.js)212.30KB42.80KB
plugin-detail (index.js)242.33KB60.97KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)125.63KB30.64KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)200.79KB54.26KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.80KB27.20KB
plugin-map (index.js)20.06KB6.62KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)43.49KB11.93KB
plugin-timeline (index.js)26.49KB7.59KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.61KB20.74KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.45KB0.23KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)44.39KB14.99KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)2.32KB1.24KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (dashboard-widget-options.js)3.08KB1.30KB
sdui-parser (index.js)4.93KB2.24KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)12.13KB3.65KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.28KB0.23KB
sdui-parser (validate.js)7.54KB2.63KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-inflight.js)8.87KB3.73KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.88KB1.85KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (spec-ui-namespace.js)0.20KB0.19KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)3.40KB1.68KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@os-zhuang
os-zhuang marked this pull request as ready for review August 23, 2026 10:21
@os-zhuang
os-zhuang added this pull request to the merge queueAug 23, 2026
Merged via the queue into main with commit 8d58f46Aug 23, 2026
23 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-5709-unconsumed-options-key-warning branch August 23, 2026 10:21
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants

@os-zhuang@claude