Skip to content

fix(fields): close the FieldEditWidget delegation road for retired field types - #4942

Merged
os-steve merged 3 commits into
mainfrom
claude/issue-4931-edit-widgets-retired-gate
Aug 17, 2026
Merged

fix(fields): close the FieldEditWidget delegation road for retired field types#4942
os-steve merged 3 commits into
mainfrom
claude/issue-4931-edit-widgets-retired-gate

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes #4931

Closes the last measured active-contradiction face of #4814's ruling A′: the
inline-edit delegation road. Its parent #4914 stays open — items 4 and 6–15
remain there as ordinary cleanup, and this PR does not reference that card with
a closing keyword.

Why this seam survived two retirement PRs

hasFieldEditWidget answers resolveInlineEditType(type) in EDIT_WIDGETS, and
resolveInlineEditType returns a type unchanged when it is already a key of
EDIT_WIDGETS:

if (type in EDIT_WIDGETS || INLINE_EXCLUDED_FIELD_TYPES.has(type)) return type;
return mapFieldTypeToFormType(type).replace(/^field:/, '');

So while owner: UserField sat in that map, the alias table — where #4814's
retirement lives — was never consulted, and the retirement never applied. No
routing table had to list the spelling for it to stay alive, which is why
deleting memberships in #4932 did not reach it.

Re-measured on this branch (not inherited from the card, which measured on
69dbea20a), at origin/main 25c8007d4:

probe before after
hasFieldEditWidget('owner') true false
isInlineExcludedFieldType('owner') false true
direct FieldEditWidget call, type: 'owner' 1 role=button reading Select… renders nothing, prescription logged
hasFieldEditWidget('user') true true

The user-facing consumer, measured before/after

The real direct consumers are the grid's inline cell editor
(ObjectGrid.tsx:2674), the kanban required-fields dialog
(requiredWhenPrompt.ts:123), and InlineFieldInput's delegation tail. The
grid is the user-facing one:

grid probe before after
isFieldInlineEditable({ type: 'owner' }) true false
column decoration at ObjectGrid.tsx:1989 stays editable forced editable: false
what the user gets on a stored owner field a working person picker a read-only cell
isFieldInlineEditable({ type: 'user' }) true true

So the cell degrades to the grid's normal read-only path — the same
disposition password, formula and composite already get. It does not
crash, and it never saves a string. The read path is unchanged from #4814: the
text cell plus the once-per-spelling console prescription.

What changed, and why the second gate is not optional

The gate consults the live RETIRED_FIELD_TYPES table (imported from
./field-type-alias, never copied, and not via the ./index barrel — that
would cycle), so this closes the class: the next retirement covers this seam
the day it lands in that table, with no edit here.

  1. hasFieldEditWidget()false for any retired spelling, ahead of every
    table lookup
    , so it holds even if a retired spelling is still a key of the
    widget map.
  2. isInlineExcludedFieldType()true for any retired spelling.
  3. FieldEditWidget renders no control for a retired spelling and writes the
    once-per-spelling prescription.
  4. owner dropped from EDIT_WIDGETS and from the cosmetic
    COMPACT_EDIT_TYPES sizing set (owner survives as a live field-type in ~13 more code faces after #4814's retirement — including a published Zod enum that still accepts it #4914 item 11, same stroke).

Gate 2 is load-bearing, and the reverse verification below proves it. ObjectGrid
forces editable: false on a column exactly when isFieldInlineEditable is
false, and that predicate consults isInlineExcludedFieldType. Closing gate 1
alone would have left the column editable, handed the cell editor a null
widget, and let DataTable fall back to its built-in plain text input — which
for a stored person reference displays a coerced value and writes a bare string
straight back over it. That would have traded a visible wrong answer for a
silent one.

Gate 3 answers with the console prescription rather than a rendered
RetiredFieldTombstone deliberately. This component's hosts are cell-sized, and
#4814 settled the same question the same way for the read path — "there is no
visible alert a table CELL can carry without wrecking the row". The visible
refusal remains the record form's job. Returning null is this function's
documented contract for "no dedicated widget", not a new fallback, and every
in-repo host is routed away from it by gates 1–2.

Reverse verification — direction predicted first, both legs from the committed state

Leg A — restore owner: UserField to EDIT_WIDGETS, keep the gates.
Predicted: all pins stay green, because the gates key on the retirement
table rather than on map absence. That is the class-closure property, so a red
here would have disproved it. Observed: Test Files 2 passed (2) / Tests 21 passed (21). Note this is a reversal of the naive "restoring the key reddens
the pins" expectation — reported as observed.

Leg B — strip all three gates, keep the EDIT_WIDGETS deletion (i.e. the
weaker spelling-only fix). Predicted: road 1 and road 3 stay green
(hasFieldEditWidget is already false via map absence; the alias table still
fires the prescription as a side effect), and exactly the two exclusion pins
redden
. Observed exactly that — Tests 2 failed | 10 passed (12):

× `isInlineExcludedFieldType` answers true for every retired spelling
    AssertionError: expected [ 'owner' ] to deeply equal []
× leaves the two answers consistent — never "no editor" AND "not excluded"
    AssertionError: expected false to be true

This is the empirical argument for gate 2: a delegation-road-only fix passes
every other pin in the file while leaving the grid's text-box path open.

Both legs restored with git checkout e255f9123 -- + the edited path; git diff HEAD
empty afterwards.

Tests

New pin packages/fields/src/__tests__/FieldEditWidget.retiredFieldType.test.tsx
is quantified over RETIRED_FIELD_TYPES throughout (the structural shape
#4932 used), with a non-vacuity guard on the table and on the live relational
types. It pins both wrong outcomes in both directions — a working picker and a
quiet text box — plus the once-per-spelling dedupe, the $expand-ed value case,
and the user survivor.

Two existing fixtures were triaged rather than re-spelled, because each pinned
the exact branch this PR removes:

  • FieldEditWidget.test.tshasFieldEditWidget('owner') === true in the
    relational-picker list; owner dropped, the three survivors kept.
  • complex-widgets.test.tsx — "owner field resolves an expanded-object value
    inline" removed, not re-spelled: its value-shape contract is unchanged and
    still pinned by the identical user case directly above it.

One of my own assertions failed on first run and was corrected to measured
reality rather than forced: hasFieldEditWidget('not-a-real-type') is true,
not false — an unknown type resolves through the alias table's || 'field:text'
tail onto the text editor. That sharpens the contrast the card is about, and
the test now says so: the retired spelling is the one type the text tail does
not catch, and had owner merely been dropped from the widget map it would
have landed on exactly that fallback.

hasFieldEditWidget('owner') is deliberately still not pinned by
#4932's InlineFieldInput.retiredFieldType.test.tsx, so this fix does not redden
it — confirmed green in the run below.

Evidence

Union run at e255f9123 (= final commit = pushed remote head), heavy runs under
flock -E 99 -w 540 /tmp/os-heavy-verify.lock, dependency closures built before
every type-check verdict.

  • packages/fields/Test Files 103 passed (103) / Tests 1705 passed (1705)
  • packages/plugin-grid/ packages/plugin-kanban/ packages/plugin-detail/ (the
    three real consumers) → Test Files 167 passed (167) / Tests 1514 passed (1514)
  • type-check for @object-ui/fields, plugin-grid, plugin-kanban,
    plugin-detail → all Done, script echoed as
    tsc --noEmit && tsc -p tsconfig.test.json (no zero-match trap). First attempt
    failed on unbuilt @object-ui/mobile / @object-ui/permissions — the closure
    trap, not this change; green after building the closures.
  • Gates derived from the changed paths: check:control-bytes OK (4419 files),
    check:self-import OK, check:phantom-deps OK, check:published-dist OK (39
    packages), changeset:check OK, check:doc-types OK. Plus a manual
    control-byte scan of the five changed files: clean.

No exported signature changed, so this is a behavior narrowing rather than a type
narrowing; a real patch changeset for @object-ui/fields records it. No
skip-changeset label was created or applied (phantom in this repo, #4912).

user is untouched throughout — it keeps the picker, its compact sizing and its
expanded-object resolution. The record-owner idiom survives verbatim as
{ type: 'user', name: 'owner' }.


Generated by Claude Code

…eld types (#4931)

`hasFieldEditWidget` answered `resolveInlineEditType(type) in EDIT_WIDGETS`, and
`resolveInlineEditType` returns a type unchanged when it is already a key of
`EDIT_WIDGETS`. While `owner: UserField` sat in that map the alias table — where
objectui#4814's retirement lives — was never consulted, so the retirement never
applied: `hasFieldEditWidget('owner')` was `true` and the grid's inline cell
editor still rendered a working person picker for a field the record form
refuses with a tombstone.

Gate on the live `RETIRED_FIELD_TYPES` table so the class closes, not the
spelling: `hasFieldEditWidget` -> false, `isInlineExcludedFieldType` -> true,
and `FieldEditWidget` renders no control while writing the once-per-spelling
prescription. Drop `owner` from `EDIT_WIDGETS` and from the cosmetic
`COMPACT_EDIT_TYPES` set (#4914 item 11).

The exclusion half is load-bearing: `ObjectGrid` forces `editable: false` on a
column exactly when `isFieldInlineEditable` is false, so without it the column
stays editable and DataTable falls back to a plain text input that saves a bare
string over a stored person reference.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 24.7 KB 350 KB
Entry file index-BgL7aJdw.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) 498.79KB 111.24KB
core (index.js) 4.06KB 1.61KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 157.40KB 43.42KB
fields (index.js) 233.27KB 58.22KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.28KB 1.75KB
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) 39.16KB 10.97KB
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) 9.35KB 3.31KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 4.42KB 1.42KB
permissions (evaluator.js) 5.12KB 1.74KB
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.81KB 0.83KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.62KB 12.83KB
plugin-charts (index.js) 64.75KB 18.37KB
plugin-chatbot (index.js) 181.21KB 43.14KB
plugin-dashboard (index.js) 127.85KB 32.73KB
plugin-designer (index.js) 212.39KB 42.83KB
plugin-detail (index.js) 239.90KB 60.01KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 120.42KB 29.03KB
plugin-gantt (index.js) 164.10KB 39.87KB
plugin-grid (index.js) 197.58KB 53.00KB
plugin-kanban (index.js) 52.72KB 14.54KB
plugin-list (index.js) 111.23KB 26.97KB
plugin-map (index.js) 17.91KB 5.72KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 41.97KB 11.33KB
plugin-timeline (index.js) 26.68KB 7.66KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 83.81KB 20.49KB
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.66KB 3.50KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 27.53KB 9.41KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.28KB 0.68KB
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.55KB 2.07KB
sdui-parser (parse.js) 10.76KB 3.17KB
sdui-parser (provenance.js) 3.66KB 1.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

claude added 2 commits August 17, 2026 07:26
…n refuses it

PR #4932 merged after this branch's base and shrank `owner` out of the
published field-type unions in `@object-ui/types`, so the four `type: 'owner'`
field literals in the new pin no longer compile (TS2322) — the contract twin
working exactly as designed.

The suite still has to author the refused spelling, because what it pins is the
RUNTIME disposition for a field that is ALREADY STORED that way, which no
compile-time union can reach. Confine the escape to one helper
(`retiredFieldLiteral`) so strictness holds everywhere else in the file, and
state there that the refusal is the point rather than an obstacle.

Verified the escape is load-bearing, not decorative: removing `as never`
reproduces TS2322 at all four call sites.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 24.8 KB 350 KB
Entry file index-D2ou02Ee.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) 40.21KB 10.79KB
auth (createAuthenticatedFetch.js) 6.34KB 2.43KB
auth (index.js) 2.71KB 1.22KB
auth (invitation-status.js) 1.22KB 0.70KB
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) 498.79KB 111.24KB
core (index.js) 4.06KB 1.61KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 157.40KB 43.42KB
fields (index.js) 233.27KB 58.22KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.28KB 1.75KB
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) 39.16KB 10.97KB
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) 9.35KB 3.31KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 4.42KB 1.42KB
permissions (evaluator.js) 5.12KB 1.74KB
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.81KB 0.83KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.62KB 12.83KB
plugin-charts (index.js) 64.75KB 18.37KB
plugin-chatbot (index.js) 181.21KB 43.14KB
plugin-dashboard (index.js) 127.85KB 32.73KB
plugin-designer (index.js) 212.39KB 42.83KB
plugin-detail (index.js) 239.90KB 60.01KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 120.42KB 29.03KB
plugin-gantt (index.js) 164.10KB 39.87KB
plugin-grid (index.js) 197.58KB 53.00KB
plugin-kanban (index.js) 52.72KB 14.54KB
plugin-list (index.js) 111.23KB 26.97KB
plugin-map (index.js) 17.91KB 5.72KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 41.97KB 11.33KB
plugin-timeline (index.js) 26.68KB 7.66KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 83.81KB 20.49KB
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.66KB 3.50KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 27.53KB 9.41KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.28KB 0.68KB
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.55KB 2.07KB
sdui-parser (parse.js) 10.76KB 3.17KB
sdui-parser (provenance.js) 3.66KB 1.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

@os-steve
os-steve marked this pull request as ready for review August 17, 2026 08:03
@os-steve
os-steve added this pull request to the merge queue Aug 17, 2026
Merged via the queue into main with commit ac2f332 Aug 17, 2026
21 checks passed
@os-steve
os-steve deleted the claude/issue-4931-edit-widgets-retired-gate branch August 17, 2026 08:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EDIT_WIDGETS still maps owner to UserField, so the grid's inline cell editor renders a working person picker for the retired spelling

2 participants