Skip to content

fix(plugin-dashboard): the editable grid renders dataset-bound widgets — and says so visibly when it cannot (#4614) - #4619

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-4614-gridlayout-dataset-path
Aug 14, 2026
Merged

fix(plugin-dashboard): the editable grid renders dataset-bound widgets — and says so visibly when it cannot (#4614)#4619
yinlianghui merged 2 commits into
mainfrom
claude/issue-4614-gridlayout-dataset-path

Conversation

@yinlianghui

@yinlianghui yinlianghui commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Fixes #4614

DashboardGridLayout had no dataset path at all — it never read widget.dataset, never imported DatasetWidget, and took no dataSource prop — so a widget authored in the CURRENT ADR-0021 shape fell through to the static-data branch and rendered nothing.

The defect, measured three ways (not one)

The issue reported a blank chart. Spying on the node the grid handed SchemaRenderer on origin/main (8640cec) showed the silence has one cause and three faces, one per dispatch family:

authored widget node the grid built what the author saw
{ type: 'bar', dataset, values } { type: 'chart', chartType: 'bar', data: [], … } blank chart
{ type: 'metric', dataset, values } { type: 'metric', label: 'metric', value: '—' } an em dash — reads as a value, not an error
{ type: 'table', dataset, … } { type: 'data-table', data: [], … } empty table

The chart node verbatim, pre-fix:

{ "type": "chart", "chartType": "bar", "data": [], "xAxisKey": "name",
  "series": [ { "dataKey": "value" } ],
  "colors": [ "hsl(var(--chart-1))", "", "", "", "hsl(var(--chart-5))" ],
  "isAnimationActive": false, "className": "h-full" }

All three are #4612's defect one level up: that card was the RETIRED authoring shape falling through this same surface, this one is the shape that is current.

Mirror design — the sibling's mechanics, with lines cited

DashboardRenderer.tsx mirrored here
:524 const datasetBound = !!(widget as any).dataset; same predicate, decided per widget at the render site
:849-851 {datasetBound ? < DatasetWidget … / > : < SchemaRenderer … / >} the fork, inside the Card branch
:777-782 isSelfContained = widget.type === 'metric' && !datasetBound same rule — a dataset-bound metric takes the Card so it gets a title and border instead of showing as bare text
:198 dataSource?: any a new optional dataSource prop (typed unknown — see below)

Three deliberate departures, each stated rather than silently copied:

  1. widget is passed whole, not wrapped as effectiveWidget. The sibling builds effectiveWidget (:774-776) only to merge the dashboard FILTER BAR's scopedFilter. This surface has no filter bar and no scopedFilter, so re-creating the wrapper would state a dependency that does not exist. DatasetWidget reads widget.filter itself and forwards it as runtimeFilter, so an authored per-widget filter still applies.
  2. One fork, not two. The sibling carries a second identical fork in its self-contained branch (:820-822) which is unreachable there, because isSelfContained already requires !datasetBound. The reachable mechanics are mirrored; the stranded limb is not. Filed as an observation-class finding: finding(plugin-dashboard): DashboardRenderer's self-contained branch carries a DatasetWidget fork that cannot be reached #4620.
  3. unknown instead of any, in both places. The sibling's dataSource?: any is explicitly historical ("that is precisely what it resolved to before", via an index signature that used to answer for it). This is a NEW declaration with no prior resolution to preserve, and unknown is what the consumer itself declares (DatasetWidget.tsx:655, dataSource: unknown) — the value is forwarded to exactly the type that receives it, and no caller is held to anything new since every value is assignable to unknown. Likewise (widget as { dataset?: unknown }).dataset rather than as any, following this package's own precedent for keys the bundled spec type lacks: legacyRetiredWidget.ts:64-80 names them in a shape of its own, which is "what keeps as any out of both call sites". This also keeps eslint net-zero (below).

Case 2 — measured first, then chosen

The ruling asked whether DatasetWidget's own no-capability rendering is visible here before inventing a placeholder. Measured with dataSource={undefined}:

PROBE-B-TEXT  = "This data source does not support dataset queries."
PROBE-B-HTML  = < div class="… border-destructive/40 …" role="alert" > < svg … / >
                < span class="break-words" >This data sour…
PROBE-B2-TEXT = "This data source does not support dataset queries."   (metric family)
PROBE-B3-TEXT = "Pick measures (values) for this dataset widget."      (no values)

DatasetWidget.tsx:766-771 sets the error state BEFORE the measures check, and :929-934 renders it as a role="alert" box. Visible in this context ⇒ routing through DatasetWidget unconditionally is the fix for both halves, and no new placeholder is declared. One condition, one wording, no third diagnostic surface. This is not a hypothetical branch: dashboard-grid's SDUI registration declares only title / className inputs, so schema-driven hosts render this component with no adapter at all — that path IS case 2, and it is pinned twice (component level, and through the registry).

Red-first, predictions written before the run

Predictions were recorded before any run. Pre-fix, origin/main source, new suite: 8 positives red, 5 negatives green (13 total) — verbatim:

TestingLibraryElementError: Unable to find an element with the text: 42.
TestingLibraryElementError: Unable to find an element with the text: Status.
AssertionError: expected "vi.fn()" to be called with arguments: [ 'invoices', …(1) ]
TestingLibraryElementError: Unable to find an element by: [data-testid="dataset-loading"]
TestingLibraryElementError: Unable to find an element with the text: This data source does not support dataset queries.   (×4 — chart, metric, table, pivot)

Post-fix: 13 passed (13).

One prediction was wrong, and fixing it is the most load-bearing change in the suite. I predicted a test asserting findByRole('alert') would be red pre-fix. It passed pre-fix — because chart was not registered in the test environment, so SchemaRenderer rendered its own red "Unknown component type" box, which also carries role="alert". A control passing for the wrong reason. Two consequences, both applied:

  • The suite now imports @object-ui/components AND @object-ui/plugin-charts (both declared deps; the latter is where chart is registered, and it is a devDependency) at module scope. With the registries populated, the pre-fix tile for a dataset-bound widget is exactly what the issue claims — empty: no alert, no chart, no text, just an injected style tag.
  • The alert assertion is now scoped to the element carrying the message (message.closest('[role="alert"]')), so SchemaRenderer's own error box cannot satisfy it.

The SDUI registration, pinned separately

DashboardGridLayout.sduiDatasetPath.test.tsx renders the component the way a schema-driven host does — as the registered dashboard-grid type resolved by SchemaRenderer — because that registration is the surface the card was filed against, and nothing else in the repo pinned it for this component. Both directions:

  • no dataSource (what the registration actually declares) still yields the visible diagnostic inside a rendered grid, so schema-driven usage is intact rather than merely failing loudly;
  • a dataSource handed to SchemaRenderer reaches DatasetWidget — which works only because SchemaRenderer forwards unread props to the resolved component (...props, spread last, :632) and strips the spec's same-named per-element BINDING before that spread (:564-575, objectstack#5576).

Reverse-verified on its own: with the fix reverted, its two positives go red and its static-data control stays green.

Reverse verification

Fix removed with git checkout origin/main -- DashboardGridLayout.tsx (never git stash), everything else identical: new suite 8 failed | 5 passed, and DashboardGridLayout.legacyRetired.test.tsx 9/9 still green — the #4613 sentinel is independent of this change in both directions.

Must-not-change proofs

  • fix(plugin-dashboard): GridLayout shows the retired-format placeholder instead of a silent blank chart (#4612) #4613 legacy sentinel ordering — untouched, still inside getComponentSchema BEFORE the dispatch branches. The dataset check sits at the RENDER SITE instead, and the two conditions are mutually exclusive by construction: isLegacyRetiredWidget returns false the moment a widget carries dataset (legacyRetiredWidget.ts:107, if (w.dataset) return false). Neither can capture the other's widget, so their relative order cannot change a verdict — which is exactly why that module states step 1 on its own terms rather than inheriting it from a caller's fork (legacyRetiredWidget.ts:97-102). Pinned both ways: a legacy widget still shows the placeholder and runs no dataset query, even when a working dataSource IS supplied.
  • dashboard-grid SDUI registration with no dataSource — that is positive case (b), pinned across chart / metric / table / pivot at component level and again through the registry. index.tsx:271-289 is unchanged.
  • legacyRetiredWidget.ts — untouched, not even a comment.
  • DashboardRenderer's suites — untouched and green (whole package: 55 files / 440 tests).
  • SchemaRenderer prop channel — the new prop cannot be shadowed by the spec's per-element dataSource BINDING, which is stripped before the props spread (SchemaRenderer.tsx:564-575); an explicit React dataSource arrives via ...props, spread last (:632).

Verification

  • Build closure: pnpm --filter '@object-ui/plugin-dashboard^...' --filter '@object-ui/plugin-dashboard' build — green (run before judging anything).
  • pnpm exec vitest run --maxWorkers=2 packages/plugin-dashboard55 files / 440 tests passed.
  • Radius (census importers): app-shell/widget-dom-leak-sweep, components/inline-locale-label-read-sites, console/preview-samples-registry-resolvable3 files / 49 tests passed.
  • Type-check sweep, PREFIX filter = DOWNSTREAM consumers: turbo run type-check --filter='...@object-ui/plugin-dashboard' --force — 41/41 tasks, uncached. Scope: app-shell, console, example-byo-backend-console, example-console-starter, plugin-dashboard, site.
  • .d.ts both ways, dist + tsbuildinfo cleared and rebuilt on each side. The entire diff:
  export interface DashboardGridLayoutProps {
      schema: DashboardComponentSchema;
      className?: string;
+     dataSource?: unknown;
      onLayoutChange?: (layout: RGLLayout[]) => void;

One added OPTIONAL property ⇒ additive ⇒ minor by position analysis, plus the behavior move. Never major. One changeset.

  • eslint net-zero vs an origin/main compare worktree: base errors=0 warnings=327 → branch errors=0 warnings=327 (both new test files contribute zero).
  • Gate battery, all PASS: check-control-bytes (4395 files), check-phantom-dependencies, check-changeset-presence, check-changeset-no-major, check-changeset-fixed, check-type-check-coverage (41/41), check-lint-coverage (46/46), check-doc-links. Plus a control-byte self-scan over the touched files including untracked ones — clean.

Out-of-scope findings

Surface respected

Touches packages/plugin-dashboard/src/** + two tests + one changeset, nothing else. examples/schema-catalog/**, content/docs/**, the plugin README and apps/site/** belong to the in-flight #4600-d1 seat and are untouched; content/docs/releases/** never.


Generated by Claude Code

…s — and says so visibly when it cannot (#4614)

DashboardGridLayout had no dataset path at all: it never read `widget.dataset`,
never imported DatasetWidget, and took no `dataSource` prop. A widget authored in
the current ADR-0021 shape fell through to the static-data branch and rendered
nothing — measured three ways: `{type:'chart',data:[]}` for a chart,
`{type:'metric',value:'—'}` for a metric, `{type:'data-table',data:[]}` for a
table. No data, no diagnostic, no path to fix.

The cure is the sibling's own mechanics, not a second dispatch idiom: the
`datasetBound` predicate decided per widget, DatasetWidget picked at the render
site (DashboardRenderer.tsx:524 / :849-851), and a dataset-bound metric taking
the shared Card wrapper (:777-782).

A dataset-bound widget with NO dataSource renders DatasetWidget's own
no-capability alert rather than a blank tile — measured visible before choosing
it, so no third diagnostic surface is declared. That is the `dashboard-grid`
SDUI path, which passes no adapter.

The #4612 legacy sentinel keeps its position and verdict: the two conditions are
mutually exclusive by construction (legacyRetiredWidget.ts:107).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
@vercel

vercel Bot commented Aug 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Aug 14, 2026 1:51am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 24.7 KB 350 KB
Entry file index-DVD0qlH0.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 9.56KB 3.59KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 8.92KB 3.41KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 25.13KB 5.40KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.13KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.64KB 2.21KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 38.46KB 10.17KB
auth (createAuthenticatedFetch.js) 6.34KB 2.43KB
auth (index.js) 2.35KB 1.07KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.02KB 0.88KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 26.07KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.65KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 489.48KB 108.55KB
core (index.js) 3.79KB 1.52KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 163.56KB 44.83KB
fields (index.js) 230.37KB 57.17KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 3.35KB 1.38KB
i18n (pickLocalized.js) 3.69KB 1.73KB
i18n (provider.js) 23.12KB 7.62KB
i18n (useDisplayLocale.js) 2.84KB 1.45KB
i18n (useObjectLabel.js) 27.59KB 6.63KB
i18n (useSafeTranslation.js) 7.77KB 3.13KB
layout (index.js) 38.98KB 10.85KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.74KB
mobile (index.js) 1.50KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 8.75KB 3.06KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.86KB 12.91KB
plugin-charts (index.js) 62.10KB 17.67KB
plugin-chatbot (index.js) 181.21KB 43.14KB
plugin-dashboard (index.js) 121.35KB 31.64KB
plugin-designer (index.js) 212.58KB 42.83KB
plugin-detail (index.js) 239.93KB 60.01KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 114.72KB 27.70KB
plugin-gantt (index.js) 164.30KB 40.02KB
plugin-grid (index.js) 190.02KB 50.48KB
plugin-kanban (index.js) 52.74KB 14.53KB
plugin-list (index.js) 112.01KB 27.27KB
plugin-map (index.js) 18.16KB 5.81KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 41.38KB 11.09KB
plugin-timeline (index.js) 26.68KB 7.66KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 84.09KB 20.56KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 27.64KB 9.44KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.26KB 0.67KB
react (schema-input.js) 1.45KB 0.83KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 4.47KB 2.03KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 3.05KB 1.52KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

…id SDUI registration (#4614)

The component-level suite renders DashboardGridLayout directly. This one renders
it the way a schema-driven host does — as the registered `dashboard-grid`
component type resolved by SchemaRenderer — because that registration is the
surface #4614 was filed against.

Two directions, neither visible from the component-level suite:

- no `dataSource` passed (what the registration actually declares: `title` and
  `className` only) still yields the visible dataset diagnostic inside a
  rendered grid, so adding an optional prop did not break schema-driven usage;
- a `dataSource` handed to SchemaRenderer reaches DatasetWidget, which works
  only because SchemaRenderer forwards unread props to the resolved component
  (`...props`, spread last) and strips the spec's same-named per-element binding
  before that spread (objectstack#5576). Nothing else pinned that interaction
  for this component.

Reverse-verified: with the fix reverted, the two positives go red and the
static-data control stays green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 24.7 KB 350 KB
Entry file index-DVD0qlH0.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 9.56KB 3.59KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 8.92KB 3.41KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 25.13KB 5.40KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.13KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.64KB 2.21KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 38.46KB 10.17KB
auth (createAuthenticatedFetch.js) 6.34KB 2.43KB
auth (index.js) 2.35KB 1.07KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.02KB 0.88KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 26.07KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.65KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 489.48KB 108.55KB
core (index.js) 3.79KB 1.52KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 163.56KB 44.83KB
fields (index.js) 230.37KB 57.17KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 3.35KB 1.38KB
i18n (pickLocalized.js) 3.69KB 1.73KB
i18n (provider.js) 23.12KB 7.62KB
i18n (useDisplayLocale.js) 2.84KB 1.45KB
i18n (useObjectLabel.js) 27.59KB 6.63KB
i18n (useSafeTranslation.js) 7.77KB 3.13KB
layout (index.js) 38.98KB 10.85KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.74KB
mobile (index.js) 1.50KB 0.62KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 8.75KB 3.06KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.86KB 12.91KB
plugin-charts (index.js) 62.10KB 17.67KB
plugin-chatbot (index.js) 181.21KB 43.14KB
plugin-dashboard (index.js) 121.35KB 31.64KB
plugin-designer (index.js) 212.58KB 42.83KB
plugin-detail (index.js) 239.93KB 60.01KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 114.72KB 27.70KB
plugin-gantt (index.js) 164.30KB 40.02KB
plugin-grid (index.js) 190.02KB 50.48KB
plugin-kanban (index.js) 52.74KB 14.53KB
plugin-list (index.js) 112.01KB 27.27KB
plugin-map (index.js) 18.16KB 5.81KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 41.38KB 11.09KB
plugin-timeline (index.js) 26.68KB 7.66KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 84.09KB 20.56KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 27.64KB 9.44KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.26KB 0.67KB
react (schema-input.js) 1.45KB 0.83KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 4.47KB 2.03KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 3.05KB 1.52KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

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

@yinlianghui
yinlianghui marked this pull request as ready for review August 14, 2026 02:06
@yinlianghui
yinlianghui added this pull request to the merge queue Aug 14, 2026
Merged via the queue into main with commit b8bda9a Aug 14, 2026
21 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-4614-gridlayout-dataset-path branch August 14, 2026 02:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[plugin-dashboard] DashboardGridLayout has no dataset path at all — an ADR-0021 dataset-bound widget renders a silent blank chart on the editable grid

2 participants