Skip to content

finding(fields): FieldEditWidget still drops the DECLARED non-DOM host-plumbing keys — error, dataSource, dependentValues, dependsOn, dependsOnLabels, emptyHint, onUploadingChange, onSelectRecord, onCreateNew #7008

Description

@os-sam

Found while implementing objectui#6909 (the DOM pass-through half). Filed rather than folded in, because it is the same SHAPE but not the same fix — see "Why not folded in" below.

What

packages/fields/src/FieldEditWidget.tsx takes FieldWidgetComponentProps, which declares three groups of keys:

  1. the controlled-input contract — value, onChange, field, readonly, disabled, className, error, onUploadingChange;
  2. host plumbingdataSource, dependentValues, dependsOn, dependsOnLabels, emptyHint, compact, onSelectRecord, onCreateNew;
  3. the DOM pass-through block (FieldWidgetDomProps + AriaAttributes + the open data- family).

objectui#6909 closes group 3 (and, via the shared toDomProps whitelist, className / disabled). Group 2 and the remaining group-1 keys are still dropped: a host may pass any of error, dataSource, dependentValues, dependsOn, dependsOnLabels, emptyHint, onUploadingChange, onSelectRecord, onCreateNew to this factory with no type error, and the widget never receives it.

That is the same first-class class named in packages/fields/src/widgets/toDomProps.ts — "a key that type-checks, reads as supported, and silently never reaches the element" (objectui#3290's aria-required, objectui#3222's validation slot).

Measured on the branch for objectui#6909, at the factory boundary: the props object the factory hands the widget contains exactly field, value, onChange, readonly, the toDomProps whitelist, and compact for the three relational types. Nothing from group 2.

Why not folded into the objectui#6909 PR

That card's ruling was direction 1 — forward the DECLARED DOM block — and its fix is mechanical: reuse the package's own executor, which is already compile-time bound to FieldWidgetDomProps in both directions. There is no equivalent executor for group 2, and each key carries a real design question rather than a mechanical answer:

  • error drives aria-invalid on the control. Its documented PRODUCER is the form renderer, from react-hook-form's fieldState. An inline-edit host has no react-hook-form state — so is the answer "forward it" or "these hosts have no validation slot to produce it from"?
  • dependsOnLabels exists because only the FORM knows a sibling field's human label. Whether an inline host can produce it at all is unresolved.
  • dataSource is currently unforwarded by design at one host: InlineFieldInput says so out loud ("No dataSource is needed — every record-querying type is routed above"), while ObjectGrid's inline editor relies on the widgets reading it from SchemaRendererContext instead.
  • onSelectRecord / onCreateNew are also declarable on the field metadata, so "not forwarded as a prop" may be the intended single carrier.

So the honest triage question is whether each key should be DELIVERED or REMOVED from what this factory's props declare — the same enforce-or-remove fork the repo applies elsewhere. Guessing either way inside a repair PR would have been the consumer-side tolerance AGENTS.md #0.1 forbids.

Note on the second direction

Narrowing FieldEditWidget's declared prop type is a published contract change (it would break callers currently passing the keys, even though the keys are dropped today), which is why objectui#6909's dispatch reserved it for the maintainer. Same reservation applies here.

Unassigned and ungraded on purpose.

Generated by Claude Code

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions