Skip to content

fix(dashboard,report): localize a LOCAL select dimension on table/pivot and the dataset report block (#4330) - #4388

Merged
yinlianghui merged 3 commits into
mainfrom
claude/issue-4330-local-select-dims-localize
Aug 12, 2026
Merged

fix(dashboard,report): localize a LOCAL select dimension on table/pivot and the dataset report block (#4330)#4388
yinlianghui merged 3 commits into
mainfrom
claude/issue-4330-local-select-dims-localize

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes#4330

Residual of #4030 / PR #4324, dispatched with the PM boundary-amendment ruling recorded on the card at queue time.

The gap, and why #4324 could not reach it

A dashboard table grouped by a local select dimension rendered Domestic on a zh-CN console while the related list on the same screen rendered 国内. The label was never missing: the server resolves it (ADR-0021) and sends the object's authored English label. The locale bundle is keyed by the option's stored value (fieldOptions.< obj >.< fld >.< value >), so translating one needs the option list — and #4263's landed pin asserted that this path issues no metadata read at all. There was nothing on the client to translate against. DatasetReportRenderer was the same shape, which is why plugin-report carried no change in #4324.

What this does

Table, pivot and the dataset report block take the one read that gives the bundle an option list, and feed it to the same seam#4324 landed — resolveDimensionFieldMetalocalizeFieldOptions / buildDimensionLabelMaprelabelDimensions, translator useSafeFieldLabel().fieldOptionLabel. One channel, no second dialect.

On the dashboard side the change is the deletion of the table-only branch: dottedOnly = isTable and its resolveDims filter are gone, so table/pivot resolve every dimension exactly as charts already did. Chart-only wiring (per-category colours, declared category order) still stays null on that path — #4330 widened which dimensions get a label map, never what a table consumes.

plugin-report had no such machinery at all, so it gains useDatasetDimensionLabels — fetch-and-memo glue only, calling the same @object-ui/core helpers. Its natural home is core, beside those helpers; it is report-local because packages/core is held by #4040 tranche 5. Applied at the shared map every consumer reads: tabular cells, both matrix axes, the server's marginal totals (relabeled, so their bucket lookup still meets the headers it belongs to), and the report's embedded chart — leaving that last one out would have put 国内 in the table and Domestic on the axis of the very same report.

The amended pin: old boundary → new boundary

The ruling was explicit that #4263's pin is amended deliberately, in this PR, not worked around. #4263 ruled it for label resolution"the label already exists, do not produce it twice" — and it held exactly as long as resolution was the read's only consumer. #4030 added a second one. Three pins were rewritten in place:

file · pin#4263 assertednow asserts
DatasetWidget.dottedDimensionTable.test.tsx · renders a LOCAL-only table …expect(requested).toEqual([]) — no read at alltoEqual(['crm_opportunity']); the rendered string is still byte-identical (no bundle entry ⇒ no map key ⇒ rows returned by identity). That identity, not the absence of a fetch, is what "no double resolution" means now
same file · the mixed dotted/local table, and its CSVlocal cell education, CSV education,Education,10local cell Education, CSV Education,Education,10
DatasetWidget.optionLabelI18n.test.tsx · a LOCAL-only table still resolves nothing and fetches nothingOrion Engineered Carbonsunder a mounted zh bundle — this test's own green was the bug's pin, and #4324's summary said so out loud欧励隆, plus the one read

Each carries the reasoning and cites #4330 at its site; the file headers carry the boundary change. DatasetWidget.localSelectI18n.test.tsx and DatasetReportRenderer.localSelectI18n.test.tsx are the new behaviour's own suites. Untouched and still green: the dotted walk, the multi-hop walk, and the METRIC branch's silence (it renders no dimension value, so it still resolves nothing and reads nothing).

Read gating: measured, and neither of the two the card sketched

The card asked for locale-gated or unconditional-when-select, with the measurement. The measurement disqualified the premise of the second and the architecture of the first, so the shipped rule is unconditional when the widget has dimensions, with the select gate on the read's OUTPUT.

Select-ness is not observable before the read. Three independent confirmations:

  • @objectstack/spec's DatasetDimension.type is string | number | date | boolean | lookup — there is no select member, so no authored dataset can declare one (PR fix(core,plugin-dashboard,plugin-charts): run resolved select-option labels through the i18n bundle on analytics surfaces (#4030) #4324 hit the same wall from the other side and recorded it as "real at authoring time and moot at runtime");
  • every select dimension in the live example apps declares type: 'string'showcase_task.status / .priority, showcase_invoice.status, showcase_account.industry / .sales_region are all Field.select objects behind a type: 'string' dimension;
  • on the wire, AnalyticsResult.fields[].type for a select column is 'string' too (the analytics cube registry's fieldTypeToDimensionType maps everything that is not number/boolean/date to 'string').

So a pre-read gate spelled type === 'select' would pass hand-written fixtures and never fire in production. The gate lands on the output instead, where it is exact rather than heuristic: resolveDimensionFieldMeta returns an entry only for a terminal field that actually carries options, so a text / number / date / lookup dimension yields no map and relabelDimensions hands back the caller's rows by identity. Pinned both ways — pins the read is issued ONCE … and BOUNDARY — a dimension whose field carries no options renders untouched.

The locale gate is not worth the branch, on three measured costs against one saved request:

  1. it would need a provider-safe active-locale reader that does not exist — useSafeFieldLabel exposes no language and useObjectTranslation is not provider-safe — i.e. a new public export in @object-ui/i18n, a package with three tasks in flight;
  2. it puts the locale into the fetch effect's deps, reintroducing the refetch-on-language-switch that fix(core,plugin-dashboard,plugin-charts): run resolved select-option labels through the i18n bundle on analytics surfaces (#4030) #4324 removed on purpose by keeping fetched metadata locale-free and deriving labels in a render memo;
  3. "non-default locale" is the wrong predicate anyway. The right one is "a bundle entry exists", which you can only know after the read (you need the value list to build the keys) — and gating on locale would silently disable the value → label net for en consoles whose server left a local select unresolved, turning an i18n gate into a behaviour gate.

Cost of the choice, stated plainly: +1 GET /meta/object/:name per dataset table / pivot / report that has at least one dimension and a server-supplied object — including one that resolves nothing. Measured as exactly 1 per surface, not one per dimension: resolveDimensionFieldMeta memoizes per call, so the two-dimension table and the two-axis pivot each issue one. In the live corpus (5 dataset table/pivot widgets across app-showcase and platform-objects) 2 carry a select dimension and would resolve, 2 are lookup-only and would not, 1 groups by action.

Pre-fix red evidence (reverse verification, per limb)

Direction predicted in both file headers before running. Committed first, then reverted with git checkout origin/main -- < path > (never git stash), re-run, restored.

Limb 1 — DatasetWidget.tsx reverted (predicted: the zh-CN cells / headers / totals / CSV and every read-count pin red, en and no-bundle-entry green, plugin-report untouched):

 × renders the zh-CN option labels in the CELLS of a table
× pins the read is issued ONCE for a table, whatever its dimension count
× localizes the DOWN axis, the ACROSS headers, and keeps the totals aligned
× exports the localized dimension cell and the RAW numeric measure
× AMENDED (#4330) — a LOCAL select on a table now reads the bundle too
× renders a LOCAL-only table exactly as the server sent it, and issues the ONE read
Test Files 3 failed | 46 passed (49)
Tests 10 failed | 432 passed (442)
AssertionError: expected 'Domestic' to be '国内'
AssertionError: expected [] to deeply equal [ 'crm_opportunity' ]
AssertionError: expected 'education,Education,10' to be 'Education,Education,10'

expected 'Domestic' to be '国内' is the card's screenshot in one line. All three failing files are plugin-dashboard's; plugin-report stayed green, which is what makes it a limb.

Limb 2 — DatasetReportRenderer.tsx + the new hook reverted (predicted: the six new report pins red, en green, dashboard untouched):

 × renders the zh-CN option label in the report cells
× pins the read: ONE metadata fetch, on the dataset base object
× a drilled row carries the values the SERVER sent, AFTER the relabel
× localizes the down axis and the across headers, keeping server totals aligned
× a drilled CELL carries the values the SERVER sent, AFTER the relabel
× plots the localized category, matching the table beneath it
Test Files 1 failed | 48 passed (49)
Tests 6 failed | 436 passed (442)

One prediction was wrong and is corrected rather than re-fitted. The headers first called the no-options pin green in both directions; it measured red on its read-count half (green on its rendered half). That is the pin's whole point after this change — the read is issued for a dimension that owns no options and resolves nothing — so the header now records the measurement, in its own commit.

Two drill pins are also in the red set for a sequencing reason rather than an assertion one, and say so at their site: they wait for the translated cell so the click lands after the metadata read settles, and that wait is what fails without the seam. Clicking as soon as the rows exist raced the read (it produced the one genuine failure during development) and would have proved nothing about a drill after the relabel. Their assertions are direction-independent.

Identity keys stay untranslated

Display translates; identity does not (#4263 / #4273's convention).

Verification

pnpm exec vitest run packages/plugin-dashboard/ packages/plugin-report/ --maxWorkers=2
Test Files 49 passed (49)
Tests 442 passed (442)

Also green: build closure for both packages' dependencies; tsc --noEmit for plugin-dashboard; tsc --noEmit + tsc -p tsconfig.test.json for plugin-report; eslint on the seven touched files (0 errors, warnings only — the one new set-state-in-effect warning is the same shape DatasetWidget's two existing effects and useDatasetRows already have); check-control-bytes, check-changeset-presence, check-changeset-no-major. Changeset: patch for both packages. No locale-pack key is added — these labels live in object metadata, not the i18n packs, so check:i18n-keys / check:i18n-drift have nothing new to see.

Surfaces

packages/plugin-dashboard/** and packages/plugin-report/** only, plus one changeset. packages/core is untouched — the shared helpers already export everything this needed — so #4040 tranche 5, #4363 and the i18n trio are not crossed.


Generated by Claude Code

…ot and the dataset report (#4330)
A dashboard table grouped by a select field rendered `Domestic` on a zh-CN
console while the related list beside it rendered 国内. The label was not
missing — the server resolves it (ADR-0021) and sends the object's AUTHORED
English label — and the locale bundle is keyed by the option's stored VALUE,
so translating one needs the option LIST. objectui#4263's landed pin asserted
that this path issues no metadata read at all, so there was nothing on the
client to translate against; PR #4324 measured that and left the half open.
Table, pivot and `DatasetReportRenderer` now take that one read and feed it to
the SAME seam #4324 landed (`resolveDimensionFieldMeta` → `localizeFieldOptions`
/ `buildDimensionLabelMap` → `relabelDimensions`). One channel, no second
dialect. Applied at the shared map every consumer reads: cells, both pivot axes,
the server's marginal totals (relabeled so their bucket lookup still meets the
headers), the CSV export, and a report's embedded chart.
The read is deliberately NOT gated on "a select dimension is present":
`DatasetDimension.type` has no `select` member, every select dimension in the
live example apps declares `type: 'string'`, and a select column arrives on the
wire typed `'string'`. The gate lands on the read's OUTPUT instead, where it is
exact — `resolveDimensionFieldMeta` yields an entry only for a terminal field
that carries `options`.
Identity keys are untouched: drills still filter by the values the server sent
(`drillRawRows` / `groupKey` / `objectFilter`), and measures still export as
bare numbers. Untranslated apps are unchanged by construction — no bundle
entry means no map key, so the rows come back by identity.
#4263's no-metadata-read pin, and #4324's restatement of it, are rewritten in
place in this commit to assert the new boundary and to say why it moved.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
#4330)
The reverse verification measured that pin RED on its read-count assertion,
not green in both directions as the header predicted: after this change the
read IS issued for a dimension whose field owns no options, and resolves
nothing. Its rendered half is green either way. Recording the measurement
rather than the prediction.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
@vercel

vercelBot commented Aug 12, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectuiIgnoredIgnoredAug 12, 2026 12:53am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)24.7 KB350 KB
Entry fileindex-CUw163tr.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.56KB3.59KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)22.10KB4.37KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)35.76KB9.11KB
auth (createAuthenticatedFetch.js)4.37KB1.69KB
auth (index.js)2.35KB1.07KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)4.91KB0.87KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.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)489.12KB108.41KB
core (index.js)2.99KB1.14KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)151.72KB40.42KB
fields (index.js)228.37KB56.62KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)3.35KB1.38KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.12KB7.62KB
i18n (useDisplayLocale.js)2.33KB1.20KB
i18n (useObjectLabel.js)27.59KB6.63KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)38.98KB10.85KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.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.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)8.75KB3.06KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)3.67KB1.12KB
permissions (evaluator.js)4.41KB1.44KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.55KB0.71KB
plugin-ai (index.js)15.71KB3.79KB
plugin-calendar (index.js)45.23KB12.45KB
plugin-charts (index.js)62.18KB17.67KB
plugin-chatbot (index.js)180.33KB42.79KB
plugin-dashboard (index.js)121.56KB31.63KB
plugin-designer (index.js)210.91KB42.67KB
plugin-detail (index.js)239.00KB59.76KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)114.58KB27.68KB
plugin-gantt (index.js)164.14KB39.98KB
plugin-grid (index.js)188.00KB49.93KB
plugin-kanban (index.js)48.60KB13.41KB
plugin-list (index.js)110.10KB26.74KB
plugin-map (index.js)18.05KB5.80KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.27KB11.36KB
plugin-timeline (index.js)26.21KB7.52KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.03KB20.55KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.71KB3.53KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.67KB2.37KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)23.71KB7.96KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.23KB0.66KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)4.47KB2.03KB
sdui-parser (parse.js)10.04KB2.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)4.69KB1.48KB
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-retry.js)4.32KB2.02KB
types (index.js)3.05KB1.52KB
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
Main entry (gzip)24.7 KB350 KB
Entry fileindex-CUw163tr.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.56KB3.59KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)22.10KB4.37KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)35.76KB9.11KB
auth (createAuthenticatedFetch.js)4.37KB1.69KB
auth (index.js)2.35KB1.07KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)4.91KB0.87KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.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)489.12KB108.41KB
core (index.js)2.99KB1.14KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)151.72KB40.42KB
fields (index.js)228.37KB56.62KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.32KB1.77KB
i18n (index.js)3.35KB1.38KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.12KB7.62KB
i18n (useDisplayLocale.js)2.33KB1.20KB
i18n (useObjectLabel.js)27.59KB6.63KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)38.98KB10.85KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.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.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)8.75KB3.06KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)3.67KB1.12KB
permissions (evaluator.js)4.41KB1.44KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.55KB0.71KB
plugin-ai (index.js)15.71KB3.79KB
plugin-calendar (index.js)45.23KB12.45KB
plugin-charts (index.js)62.18KB17.67KB
plugin-chatbot (index.js)180.33KB42.79KB
plugin-dashboard (index.js)121.56KB31.63KB
plugin-designer (index.js)210.91KB42.67KB
plugin-detail (index.js)239.00KB59.76KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)114.58KB27.68KB
plugin-gantt (index.js)164.14KB39.98KB
plugin-grid (index.js)188.00KB49.93KB
plugin-kanban (index.js)48.60KB13.41KB
plugin-list (index.js)110.10KB26.74KB
plugin-map (index.js)18.05KB5.80KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.27KB11.36KB
plugin-timeline (index.js)26.21KB7.52KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.03KB20.55KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.71KB3.53KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.67KB2.37KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)23.71KB7.96KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.23KB0.66KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)4.09KB1.74KB
sdui-parser (index.js)4.47KB2.03KB
sdui-parser (parse.js)10.04KB2.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)4.69KB1.48KB
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-retry.js)4.32KB2.02KB
types (index.js)3.05KB1.52KB
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

@yinlianghuiClaude

Copy link
Copy Markdown
CollaboratorAuthor

ACCEPT — PM 复核 (session session_017Qqyix2QcnpUC9XeYVDzx3), closes #4330.

Flipping ready + arming auto-merge.


Generated by Claude Code

@yinlianghui
yinlianghui marked this pull request as ready for review August 12, 2026 01:07
@yinlianghui
yinlianghui added this pull request to the merge queueAug 12, 2026
Merged via the queue into main with commit 326a70fAug 12, 2026
21 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-4330-local-select-dims-localize branch August 12, 2026 01:07
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants

@yinlianghui@claude