Skip to content

fix(plugin-form): merge object-form.customFields over the metadata-generated field set - #9948

Merged
os-sales merged 2 commits into
mainfrom
claude/issue-9778-customfields-merge
Sep 18, 2026
Merged

os-sales merged 2 commits into
mainfrom
claude/issue-9778-customfields-merge

Conversation

@os-sales

Copy link
Copy Markdown
Collaborator

Fixes #9778

Clause-②: no

object-form.customFields now MERGES over the metadata-generated field set, per the director-seat ruling on the card (batch #161 item 5, summon #24, maintainer 「其他同意」 2026-09-18T12:07Z). The registration description is the contract and is unchanged.

Clause-② tested against this diff, not inherited: the diff adds 0 lines containing export (lit control on the same corpus: 18 added lines contain customFields) and no new key on any published payload — an existing branch is made reachable. Answer stands at no.

What changed

ObjectForm.tsx, three sites:

  1. The replace path is gone. A non-empty customFields used to run setFormFields(schema.customFields.map(normalizeVisibility)) and return above the metadata branch, so the object's schema was never even fetched.
  2. The metadata is now fetched whenever an objectName and a data source are present, inline members or not — without the generated set there is nothing to merge over, and the merge lookup schema.customFields?.find((f) => f.name === name) stays the dead code objectui#8071 measured. The members-only schema (an object with no fields) became the fallback rather than the inline path's fixed answer: it is what the registration's second sentence describes, "with inline definitions and no data source, this becomes the only field source".
  3. Members naming nothing in the generated set are appended after it, in authored order, right before setFormFields(generatedFields).

Two smaller consequences, both deliberate:

  • The loading flag no longer drops unconditionally on the inline path — it drops when nothing is going to be fetched, otherwise the metadata branch's own willFetchData tail clears it. Without this an empty form sat on screen for the duration of getObjectSchema.
  • A getObjectSchema that throws (or returns nothing) now falls back to the members-only source when inline members are present, instead of replacing a form that used to render with an error panel. The metadata is an overlay on this path, not a prerequisite.

The pins, one row per direction

objectFormCustomFieldsMembers-8071.test.tsx flips from pinning the replace behaviour to pinning the merge:

row direction asserts
1 shape + merge members are whole field definitions keyed by name; the merged set is customer, note, amount, zz
2 override a member takes the declared field's position, supplies its whole definition, and the metadata IS fetched — getObjectSchema inverted from toBe(0) to toBe(1)
3 keep customer / amount, which no member names, still render with the object's own labels
4 append members naming nothing declared come after the generated set, in authored order
5 (unchanged) an EMPTY customFields is UNAUTHORED — the read is .length > 0, not truthiness
6 (unchanged) the same member count exempts the block from the no-adapter panel; doubles as the control for the no-data-source sentence

One collateral red, repaired in place and called out here: ObjectForm.mobileFullscreen.test.tsx's "commits a fullscreen edit back into the form state" mounts a customFields member named summary against an object that also declares changelog, so the merge draws two expand affordances and an unscoped findByTestId found both. The lookup is now scoped to the field the case is about; nothing else in the file moved.

Reverse verification (ablation)

The fix was committed first, then ObjectForm.tsx alone was reverted to this branch's base commit and the flipped pins re-run:

  • mutation landed on disk: the objectui#9778 markers went 5 to 0 and the replace path setFormFields(schema.customFields.map(normalizeVisibility)) came back (1 occurrence); blob 85d6c1c4 against HEAD's cd4bd869
  • result: 4 failed | 2 passed (6) — rows 1-4 red, each for its own reason (expected [ 'zz', 'note' ] to deeply equal [ 'customer', 'note', 'amount', 'zz' ]; expected +0 to be 1; expected null to be 'Customer'; expected [ 'zz', 'yy' ] to deeply equal [ 'customer', 'note', 'amount', …(2) ]), rows 5-6 green as they should be, since neither is about the merge
  • restored by git checkout HEAD -- ObjectForm.tsx (trap-guarded, absolute path): blob back to cd4bd869, git diff HEAD empty, markers back to 5

Tests

Run at 096496e052:

  • pnpm --filter @object-ui/plugin-form test — 100 files passed, 940 passed | 1 skipped (941)
  • pnpm --filter @object-ui/plugin-form type-check — exit 0 (tsc --noEmit plus tsconfig.test.json), after pnpm --filter '@object-ui/plugin-form^...' build — without that dependency-closure build it reports TS2307 Cannot find module '@object-ui/*' on every workspace import, which is a missing dist, not a type error
  • consumers that pass customFields through: packages/plugin-view/ + packages/plugin-designer/ + registry-inputs-spec-parity.test.ts + public-block-binding-reach.test.tsx — 66 files, 757 passed. The fenced ledger's counts do not move, exactly as the dispatch predicted, so it was not edited.
  • gates, each exit code captured before any pipe: check:control-bytes, check:new-line-citations, check:changeset-claims, check:pending-changeset-literals, check:test-path-roots, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:element-data-source-declaration, check-changeset-presence.mjs, check-changeset-no-major.mjs — all exit 0. eslint on the three changed files: 0 errors (64 pre-existing no-explicit-any warnings).
  • check:sdui-registration-pins — NOT MEASURED: exit 2 is its own prerequisite refusal ("No console build to weigh at apps/console/dist/assets"), not a red. This diff adds and removes no registration; CI builds the console and runs it.

Acceptance notes

Out-of-scope findings, neither touched here:

  1. To file (class b). The same registered description still describes the drawer and modal presentations of this block, and both still replace. ObjectForm spreads the schema — customFields included — into DrawerForm / ModalForm for formType: 'drawer' | 'modal', and each of those runs its own if (schema.customFields?.length) { setFormFields(schema.customFields); }. So an author who takes the registration at its word gets a merge on the flat presentation and a replacement on the other two, from one declared key. Out of this card's file surface (the ruling names ObjectForm.tsx) and it needs its own pins. Dedupe words: DrawerForm customFields replace · ModalForm customFields replace · presentation arms merge parity · formType drawer inline fields · customFields merge unreachable.
  2. Noted, not filed. The console ledger entry for object-form.customFields still describes the replace behaviour in prose ("they REPLACE the metadata-generated set … getObjectSchema asserted at zero calls … handed back as a finding rather than repaired"). It is reviewed prose, not a computed assertion — its counts do not move and its test stays green (measured above) — and the file is held by open PR objectui#9924, so it was not edited. Successor: whoever lands objectui#9924, or the next objectui#8071 slice that edits that ledger.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UanLVj6xvbS6puBCewLr8L


Generated by Claude Code

`customFields` is registered as "Field definitions merged over the set
generated from object metadata. With inline definitions and no data source,
this becomes the only field source." The renderer replaced instead: a
non-empty `customFields` took an early return that called
`setFormFields(schema.customFields.map(normalizeVisibility))` above the
metadata branch, and the object's schema was never even fetched — while the
per-member merge the prose describes sat inside that branch as dead code,
its `customFields?.find((f) => f.name === name)` only ever running over an
empty array.

The declared contract wins (objectui#9778, maintainer ruling 2026-09-18):
the metadata is now fetched whenever an object name and a data source are
present, and the members merge over the generated set — override in place,
keep what no member names, append what metadata never declared. With no data
source there is nothing to merge over, so the members stay the only field
source, exactly as the registration's second sentence says; an object the
adapter cannot describe falls back to that same source instead of turning a
form that used to render into an error panel.

The member pin flips with it, one row per direction, and its
`getObjectSchema` row inverts from "never fetched" to "fetched once".

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

github-actions Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

✅ Nothing to re-read

No pending changeset names a file this change touches, no address in this pull request's own prose points at a line this change moves, and no changeset here negates a package it declares. An earlier revision did. That request to re-read does not apply to the current diff.

This comment is updated in place on every re-run rather than posted again, so the thread does not grow one per push.

Compared the checked-out tree with 05a49f2ee (merge-base with origin/main): 3 file(s) changed outside .changeset/, read against 1183 pending declaration(s) that publish a body (1732 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3051.6 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-BCaWRQuZ.js —
Status PASS —

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

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 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.68KB 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) 545.76KB 130.74KB
core (index.js) 8.94KB 3.59KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 216.90KB 60.15KB
fields (index.js) 249.22KB 62.85KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
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.75KB
mobile (index.js) 1.99KB 0.87KB
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.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 14.81KB 3.63KB
plugin-calendar (index.js) 49.92KB 14.22KB
plugin-charts (index.js) 71.73KB 20.08KB
plugin-chatbot (index.js) 195.35KB 46.52KB
plugin-dashboard (index.js) 132.96KB 35.17KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 253.63KB 66.00KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 137.02KB 34.22KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 213.44KB 58.21KB
plugin-kanban (index.js) 48.10KB 14.94KB
plugin-list (index.js) 113.42KB 27.95KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 85.05KB 21.01KB
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.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 104.82KB 34.67KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 14.82KB 4.99KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
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 (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 14.04KB 5.36KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
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

…name its falsifier

`8738-object-form-fields-description.md` publishes verbatim into the CHANGELOG
and still read "silently skipped by `SimpleObjectForm` … and by
`buildFlatFields` … — no throw, no warning, no empty-state". Both named read
sites now call `warnUnresolvedTopLevelField`, so the silence is gone.

The claim ROTTED, it was not born false, and the two take opposite repairs:
the body landed in `fd9bf26df0` at 2026-09-09T14:28:48Z and `8fda009057`
(objectui#8859, route 1 of the same card) added the de-duplicated
`console.warn` at 2026-09-09T16:00:31Z — 92 minutes later. So the original
reading is kept and dated rather than rewritten, with the falsifier named;
rewriting it would erase a true reading and misdate the behaviour for every
CHANGELOG reader.

Read as a paragraph, not a line: the same fact also dated the opening
"route 1 … is a separate ruling still pending", and "Behaviour is unchanged"
was judged in the same pass — still true of this entry's own change (a
registration description), now spelled "unchanged by this entry" so the
scope cannot be read as a claim about the release. What did not change is
stated too: the member is still skipped, with no throw and no empty-state.

Prose only — frontmatter and semver level untouched.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3051.6 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-BCaWRQuZ.js —
Status PASS —

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

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 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.68KB 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) 545.76KB 130.74KB
core (index.js) 8.94KB 3.59KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 216.90KB 60.15KB
fields (index.js) 249.22KB 62.85KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
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.75KB
mobile (index.js) 1.99KB 0.87KB
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.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 14.81KB 3.63KB
plugin-calendar (index.js) 49.92KB 14.22KB
plugin-charts (index.js) 71.73KB 20.08KB
plugin-chatbot (index.js) 195.35KB 46.52KB
plugin-dashboard (index.js) 132.96KB 35.17KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 253.63KB 66.00KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 137.02KB 34.22KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 213.44KB 58.21KB
plugin-kanban (index.js) 48.10KB 14.94KB
plugin-list (index.js) 113.42KB 27.95KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 85.05KB 21.01KB
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.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 104.82KB 34.67KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 14.82KB 4.99KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
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 (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 14.04KB 5.36KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
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-sales
os-sales marked this pull request as ready for review September 18, 2026 19:52
@os-sales
os-sales added this pull request to the merge queue Sep 18, 2026
Merged via the queue into main with commit 5a311a3 Sep 18, 2026
38 checks passed
@os-sales
os-sales deleted the claude/issue-9778-customfields-merge branch September 18, 2026 20:14
os-tesla pushed a commit that referenced this pull request Sep 18, 2026
Ejected from the merge queue on a textual conflict. One file conflicted,
`packages/plugin-form/src/ObjectForm.tsx`, in one hunk — the inline-fields
effect, which objectui#9778 (landed as part of #9948) and this branch both
edited.

Resolved as a UNION, because the two sides answer different questions and
neither is preferred:

  - this branch changed WHAT seeds the form: `setInitialData(schema.initialData
    || schema.initialValues || {})` becomes `setInitialData(
    resolveInitialRecord(schema))`, the per-member merge;
  - objectui#9778 changed WHEN the loading flag may drop: inline members no
    longer short-circuit the metadata read, so `setLoading(false)` is now
    conditional on nothing being about to be fetched, with the comment that
    states why.

Both are kept verbatim. The effect's dependency array auto-merged to the union
of what the two sides read, which is correct for both. The branch's second
`ObjectForm` seed site, in `fetchInitialData`, auto-merged untouched.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HrVaotisyhgmot9o2MLRq
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.

finding(plugin-form): object-form.customFields 注册描述说 merge,渲染器 replace —— 逐成员合并的代码存在但不可达

2 participants