Skip to content

fix(plugin-detail): resolve headerColor through literal Tailwind classes, not a template literal - #6294

Merged
os-litant merged 2 commits into
mainfrom
claude/issue-6178-detailsection-headercolor
Aug 25, 2026
Merged

fix(plugin-detail): resolve headerColor through literal Tailwind classes, not a template literal#6294
os-litant merged 2 commits into
mainfrom
claude/issue-6178-detailsection-headercolor

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes#6178

The premise, re-measured

The card is correct, and the strongest evidence it predicted exists.

The repo's own reading.apps/console/src/__tests__/sdui-preview-page-source-styling.test.ts, header:

The console's Tailwind is compiled at BUILD time by scanning the console's own src (@source '../src/**' in apps/console/src/index.css) with no safelist, so a utility class authored in real page metadata produces no CSS and no error anywhere — the ADR-0065 "works only by coincidence" failure.

The compiled stylesheet, not an inference. I compiled apps/console/src/index.css the way the console build does (@tailwindcss/postcss, v4.3.3), then again with the bg- template literal deleted from both call sites. The two sheets are byte-identical — 441302 bytes, sha256 dffcd88d…e7e3b2. That call site contributed zero rules. Asking Tailwind's design system for the candidate bg- (all the extractor could take from a template literal) returns no rule either.

"Works only by collision" — measured, and it matters. Both values the @object-ui/types mirror documents are present in the built console CSS today: .bg-muted and .bg-primary/10 are 2 of 227 distinct bg-* selectors. They are there because other files author them literally — bg-muted 691 times, bg-primary/10 63 times elsewhere in the workspace. So the key was not inert in effect; it was live by accident, and the fix had to keep the documented examples working rather than simply stop lying.

Two corrections to the card's wording, neither changing its conclusion:

  • "no safelist" is imprecise. apps/console/src/index.cssdoes use @source inline(...) — nine lines of it, for streamdown's runtime classes. There is no bg-* safelist, which is what the argument needs.
  • the third headerColor mention is packages/plugin-detail/src/index.tsx:310 (not :287), and it is the detail-sectionregistry input row — a declaration, not a fourth read site. The two read sites are DetailSection.tsx:513 / :542, exactly as filed.

The issue body shows no sanitizer truncation: it contains no angle-bracket fragments at all, and the split spelling of the template literal in bullet 1 reads as the author working around the sanitizer, not as damage.

The shape, decided by measurement

Triage asked for a closed vocabulary mapped to static literal classes or inline style from the authored value — whichever matches how sibling colour keys here already solved it. Three sibling species exist:

siblingwhat the author writeshow it renders
getBadgeHexAppearance (@object-ui/fields)a CSS colourbg-[color:var(--os-badge-bg)] + inline custom properties — the AGENTS.md carve-out
columnColors (PivotTable)a complete Tailwind classpassed verbatim into cn(), no prefix
useRowColor (@object-ui/plugin-grid)a colour token, or a complete classa lookup of literal classes + a bg- pass-through + undefined otherwise

useRowColor is the same problem, and this PR is the same answer. The custom-property carve-out does not fit: it is for values that are CSS colours, and headerColor's values (muted, primary/10) have no meaning as one. And DetailSection was the only`bg-${…}`-shaped class in the entire workspace — every sibling had already avoided this shape.

New module packages/plugin-detail/src/headerColor.ts:

  • lookup of complete literals, tint-only: muted, muted/50, accent, primary/10, secondary/10, destructive/10. CardHeader sets no foreground, so solid bg-primary / bg-destructive would leave the title unreadable — those need a paired text-*-foreground and are left to the pass-through, where the pairing is the author's explicit choice. Both documented examples are in the map, so nothing that rendered before renders differently;
  • pass-through for a value already spelled as a complete bg-* class. New behaviour: headerColor: 'bg-muted' previously produced the meaningless bg-bg-muted;
  • undefined otherwise — never a fabricated class. hasOwnProperty, not a bare index, so headerColor: 'constructor' cannot hand back an Object.prototype member.

The literals now live in a file every consuming app scans (packages/plugin-detail/src/** appears in apps/console, examples/console-starter, examples/byo-backend-console), so the key works because this module declares it, not because a neighbour happens to.

Evidence

Two instruments, because one of them is blind. Asserting a className in the DOM proves nothing about CSS emission — the old code put bg-<value> in the DOM too. So:

  1. DetailSection.headerColor.test.tsx — renders the real component, asserts which class reaches the header. States in its header that it cannot show CSS generation.
  2. headerColor.test.ts — the generation half. (a) every vocabulary class appears verbatim in the module's source text, the property the v4 extractor needs; (b) every vocabulary class builds a rule against this workspace's real @theme (__unstable__loadDesignSystem from tailwindcss, root devDependency), with bg-, bg-mutedd, bg-not-a-token as the negative controls that prove the instrument can say no. It states what it still cannot show: it does not run the oxide scanner, and it does not verify any app's @source globs.

Every negative pin has a positive probe beside it (the header element is located getBy-style and the assertion fails if no header rendered, so nothing passes vacuously).

Per-point ablation — direction predicted before each run, all four correct:

pointmutation (confirmed on disk, 1 → 0 occurrences)predictedobserved
P1revert only the non-collapsible call sitethat branch reds, collapsible stays green4 red / 17 pass — 3 non-collapsible cases + the interpolation pin; all 5 collapsible cases green
P2revert only the collapsible call sitemirror of P14 red / 17 pass — 3 collapsible cases + the interpolation pin; all 5 non-collapsible cases green
P3bg-mutedbg-mutedd (still a complete literal)design-system test reds, verbatim-source test stays green5 red / 16 pass — "appears VERBATIM in the module source" stayed green
P4'bg-muted'['bg-', 'muted'].join('') (still a valid utility at runtime)verbatim-source test reds, everything else greenexactly 1 red / 20 pass — the design-system test, the resolver tests and every render test stayed green

P4 is #6178 reproduced in miniature: a class that is valid at runtime but unextractable from source, with every instrument except the source-text one reporting green. P1/P2 record the honest limit of the render tests — under P1 the two "a mapped token renders its literal class" cases still passed, because the old concatenation produced the same string for a mapped value.

Each ablation script carries a trap … EXIT INT TERM restore and refuses to run (exit 90) unless the mutation is confirmed on disk; the restore leg is printed each time.

Gates

Run at 799d2385e, which is the HEAD of this branch and byte-identical to the tree every measurement above was taken on (git status --porcelain empty).

  • pnpm exec vitest run packages/plugin-detail106 files / 1007 tests passed (the two new files contribute 21).
  • pnpm --filter @object-ui/plugin-detail type-check — clean (tsc --noEmit && tsc -p tsconfig.test.json, both echoed).
  • check:control-bytes, check:phantom-deps, check:entry-guard, check:self-import, check:vi-mock-specifiers, check:esm-specifiers, check-type-check-coverage, check-lint-coverage, check-changeset-presence, check-changeset-no-major, check-changeset-fixed — all exit 0. Changeset gate prints: 4 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s).
  • Two gates report a broken gauge, both pre-existing to this branch and both self-diagnosing: check:eager-closure ("No eager-closure report at apps/console/dist/eager-closure.json … an absent report means the console was not built") and check:readme-exports ("its type entry ./dist/index.d.ts is not on disk — run pnpm build first"). This worktree had 0 of 40 packages built and no apps/console/dist when they ran; CI builds first. Neither names a file in this diff.

Lint, run narrowed and the narrowing declared.pnpm exec eslint packages/plugin-detail --format json — exit 0, 0 errors across the 159 files eslint's own config resolution judged (count read from the JSON, not from my guess at what counts). My four files: headerColor.ts 0/0, headerColor.test.ts 0/0, DetailSection.headerColor.test.tsx 0/0, DetailSection.tsx 0 errors and 12 pre-existing warnings at lines 70/102/105/111/122/147/221/223/261/261/263/428 — none on the three lines this PR touches (37, 514, 543). The narrowing is a measurement rather than a skip because eslint.config.js configures no type-aware linting (no projectService, no parserOptions.project) and no custom rule in eslint-rules/ reads another file, so a file's verdict is a function of its own text and the shared config — neither of which this diff moves outside packages/plugin-detail. Repo-wide pnpm lint is CI's run.

Scope

packages/plugin-detail/src/** and its tests only, as dispatched. Deliberately not touched:

  • packages/types/src/views.ts / zod/views.zod.ts — the headerColor declaration and its @example 'muted', 'primary/10'. Out of this PR's file surface, and objectui#6267 holds that package. The examples stay accurate: both still render. Naming the vocabulary in that JSDoc is a follow-up for whoever owns it next.
  • the detail-section registry input row (index.tsx:310) — a string input, still accurate.
  • @objectstack/spec, which refusesheaderColor on the strict record:details section schema today, with a pinned test whose comment cites this exact defect ("declaring it would advertise a capability the renderer does not deliver"). That refusal is the thing this PR makes obsolete; flipping it is a spec decision, raised as an open question in the dev report rather than taken here. Back-link: record:details sections: five more renderer-honoured keys remain undeclared by the strict section schema (title / defaultCollapsed / icon / description / headerColor) objectstack#11661.

The one thing a reviewer should rule on

The declared type is unchanged and no value is rejected, but the effective value set is reshaped: an undocumented bare suffix that happened to collide with another file's literal (say headerColor: 'blue-100') no longer reaches the DOM as bg-blue-100. Ending that accidental liveness is the point of the fix, not a side effect of it — no fix satisfying the card can preserve it. Three things bound the risk: zero producers author headerColor anywhere in either repo (only declarations and the spec-side refusal); both documented examples are preserved; and every previously-colliding suffix has a one-word migration through the pass-through ('blue-100''bg-blue-100'). Whether the vocabulary should be exactly these six, and whether the spec should now declare the key over them, is the maintainer's call.


Generated by Claude Code

`DetailSection` built the header background as `bg-` concatenated with the
authored `headerColor`. Tailwind v4 scans source TEXT for complete class
tokens and this workspace ships no `bg-*` safelist, so that expression
contributed nothing to the compiled stylesheet: compiling the console's CSS
with it deleted produced a byte-identical sheet (same sha256). An authored
value rendered only where another file happened to author the identical class
literally.
Resolve through a lookup of complete class literals instead, the shape
`useRowColor` already uses in @object-ui/plugin-grid: tint-only design-system
classes (`muted`, `muted/50`, `accent`, `primary/10`, `secondary/10`,
`destructive/10`), verbatim pass-through for a value that is already a `bg-*`
class, and no class at all for anything else — never a fabricated one.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mn4BZ5AVDM81pvfij1WwM9
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Eager closure (gzip, 52 chunks)3222.9 KB3266.6 KB
Main entry chunk (gzip)154.1 KB350 KB
Entry fileindex-BNTeKidi.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.96KB4.16KB
app-shell (runtime-config.js)18.10KB6.51KB
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)40.18KB10.59KB
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)505.63KB114.68KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)171.74KB47.48KB
fields (index.js)238.40KB59.89KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
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.66KB18.32KB
plugin-chatbot (index.js)188.21KB44.67KB
plugin-dashboard (index.js)133.35KB34.45KB
plugin-designer (index.js)212.33KB42.81KB
plugin-detail (index.js)245.10KB62.31KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)126.42KB30.80KB
plugin-gantt (index.js)164.17KB39.89KB
plugin-grid (index.js)201.14KB54.40KB
plugin-kanban (index.js)52.83KB14.55KB
plugin-list (index.js)111.94KB27.24KB
plugin-map (index.js)20.09KB6.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)9.26KB3.13KB
plugin-view (index.js)84.55KB20.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)4.47KB1.63KB
react (SchemaRenderer.js)54.84KB18.43KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.35KB0.70KB
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)2.74KB1.41KB
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 (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.49KB2.14KB
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)6.28KB2.87KB
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)3222.9 KB3266.6 KB
Main entry chunk (gzip)154.1 KB350 KB
Entry fileindex-BNTeKidi.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.96KB4.16KB
app-shell (runtime-config.js)18.10KB6.51KB
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)40.18KB10.59KB
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)505.63KB114.68KB
core (index.js)5.30KB2.13KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)171.74KB47.48KB
fields (index.js)238.40KB59.89KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (fallbackInterpolation.js)6.25KB2.77KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.44KB1.39KB
i18n (pickLocalized.js)7.62KB3.26KB
i18n (provider.js)26.89KB9.04KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)33.40KB8.71KB
i18n (useSafeTranslation.js)5.60KB2.33KB
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.66KB18.32KB
plugin-chatbot (index.js)188.21KB44.67KB
plugin-dashboard (index.js)133.35KB34.45KB
plugin-designer (index.js)212.33KB42.81KB
plugin-detail (index.js)245.10KB62.31KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)126.42KB30.80KB
plugin-gantt (index.js)164.17KB39.89KB
plugin-grid (index.js)201.14KB54.40KB
plugin-kanban (index.js)52.83KB14.55KB
plugin-list (index.js)111.94KB27.24KB
plugin-map (index.js)20.09KB6.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)9.26KB3.13KB
plugin-view (index.js)84.55KB20.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)4.47KB1.63KB
react (SchemaRenderer.js)54.84KB18.43KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.35KB0.70KB
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)2.74KB1.41KB
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 (icon-key-migration.js)4.26KB1.63KB
types (index.js)4.49KB2.14KB
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)6.28KB2.87KB
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-litant
os-litant marked this pull request as ready for review August 25, 2026 10:27
@os-litant
os-litant added this pull request to the merge queueAug 25, 2026
Merged via the queue into main with commit d3005f7Aug 25, 2026
28 checks passed
@os-litant
os-litant deleted the claude/issue-6178-detailsection-headercolor branch August 25, 2026 10:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

1 participant

@os-litant