Skip to content

Verify #5526 round-6 fixes (scratch, do not merge) - #9

Draft
rishilifts wants to merge 45 commits into
v7from
scratch-5526-round6
Draft

rishilifts wants to merge 45 commits into
v7from
scratch-5526-round6

Conversation

@rishilifts

Copy link
Copy Markdown
Owner

Scratch CI check for rjsf-team#5526 round 6 - do not merge.

rishilifts and others added 30 commits October 14, 2026 02:43
Documented the new `itemLabel` array option and updated related examples. Fixed issues with the playground crashing on invalid JSON editor values.
…ared warn suppression

Replaced console warning spy with console suppression utility in getTemplate tests.
Refactor getTemplate to improve template handling and add warnings for non-component overrides.
Refactor getTemplates function to include fieldLabel parameter and use resolveTemplate for template resolution.
Removed unresolved component description mapping.
Added tests to validate warning messages for invalid templates and registry options in getTemplate and getTemplates functions.
This function provides a description for unresolved components, detailing the given value, what it resolved to, and the context of the lookup.
Fixed invalid template overrides being returned as components and updated various schema handling functions to comply with the latest specifications. Introduced breaking changes in error handling for array fields and upgraded ajv-formats.
…ui:globalOptions

The override warnings now fire only in getTemplate()/getTemplates() when the
caller passes a warnSource, and only SchemaField passes one: a lazy
entryLabelForLog() thunk, so an items mistake warns once per uiSchema entry
rather than once per row, and the field's own options, so an own mistake is
told apart from one inherited from ui:globalOptions. The other getTemplates()
callers resolve silently, which removes the second, unlabelled warning.

An invalid own override now falls back to a valid ui:globalOptions template
before the registry's own, as resolveUiField() does for ui:field. A string
registry entry is described as the value it is, not looked up by name. The
registry's templates are checked once per registry, cached in a WeakMap, and
each warning's message is built once per (name, value, entry).

isTemplateName() and resolveTemplate() move to an internal module excluded
from the lib wildcard, and TEMPLATE_NAMES is typed against the declared keys
of TemplatesType so a template added there fails to compile until listed.
The changelog covers the new describeUnresolvedComponent export and
warnSource parameter and the ui:field got-null wording, as do the docs.
Three tests: a ui:globalOptions template named by string is resolved when a
field-level override is invalid; one naming no registered template falls
through to the registry; the ui:globalOptions warning logs once across
fields. Restores the 100% branch coverage the threshold checks.
The keyed dedupe for the invalid-override warnings was a second Set that
resetLogOnce() could not clear and that never dropped anything. It now
lives in loggedMessages.ts, the two-generation store logOnce() uses, so
resetLogOnce() clears it, memory stays capped, and the message is still
built only the first time a key is seen. testSetup no longer needs its
own reset.

The key now tells values apart the way describeUnresolvedComponent()
does (string text, element, null, typeof), so editing {} to <MyTemplate />
logs again. warnOnInvalidRegistryTemplate() checks isTemplateName() again,
so a custom-named registry entry that isn't a component stays silent.
The isTemplateName() comment moves to getTemplate(), where the check is.
…ent the helpers

An own null for a template override now renders the registry's template
without a warning and without falling back to ui:globalOptions, the way a
falsy own ui:field opts out; '', 0 and false still warn.

utility-functions.md gains describeUnresolvedComponent() and describes the
two fields of TemplateWarnSource where warnSource is documented.
rishilifts and others added 14 commits October 22, 2026 21:36
…() and drop the registry-template warning

- warnOnInvalidOverride() now dedupes through logOnce() on the message itself, so loggedMessages.ts, its package.json
  exclusion and the hand-built key are gone
- The registry-template warning never fired from the getTemplates() loop every caller uses, so it is dropped along
  with its changelog and docstring sentences; the Form-level registry check moves to the follow-up PR
- FallbackField now passes getUiOptions() the merged global options, so an invalid own ui:UnsupportedFieldTemplate
  no longer changes which template renders compared with leaving the value out
- The repeated registry lookup in getTemplate() goes through one lookupTemplate() helper
- testing/testSetup.ts restored to its v7 version, taking it out of the PR
…plate names and warn for ui:CyclicSchemaExpandTemplate
…#5636)

* fix 4298: ui:enumOrder orders constant anyOf/oneOf options

optionsList() applied ui:enumOrder only to an enum, so a select over
constant anyOf/oneOf options could be reordered only by editing the
schema. It now orders those options by their constants, after reading
each ui:title by schema position. Options read through a discriminator
or ui:optionsSchemaSelector keep their schema order, since
LayoutMultiSchemaField reads an option's uiSchema at its position in
the list.

This reverses the order half of rjsf-team#5319 (4086e5f): BooleanField applies
ui:enumOrder to its constant options and warns only about ui:enumNames
beside them. Marked breaking, with an upgrade-guide entry, since an
order that was ignored now drops the options it doesn't list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix 4298: order constants no option reads through a selector

optionsList() skipped ui:enumOrder whenever a selector existed, though
the docs say only options read through one keep their schema order.
Constant options that don't declare the selector property are read by
their constant, which LayoutMultiSchemaField can't match a pick by, so
the order now applies to them; it is skipped only once an option is
read through the selector. The docs say so for a mixed list too.

ui:enumOrder is typed (EnumValue | null)[], so a typed UiSchema can
list the null option of a nullable select. Object constants stay
untyped.

The BooleanField changelog bullet describes the change against 6.x,
which ignored the order there, and is marked breaking.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Bump size limit on utils own by 1kb

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…y theme (rjsf-team#5616) (rjsf-team#5646)

* feat(themes)!: take a field's error state from its own errors in every theme (rjsf-team#5616)

Phase 0 of rjsf-team#5616, split out ahead of the class-map stack since it depends on none of it. `SchemaField` hands its `FieldTemplate`, and through it the `WrapIfAdditionalTemplate`, and its `DescriptionField` a new `hasErrors` prop: the field's own errors as `ui:hideError` leaves them, the state its `rjsf-field-error` class already takes. Beneath an `anyOf`/`oneOf` field it differs from the plan's errors, which are the ones the field above shows.

`@rjsf/antd`, `@rjsf/chakra-ui`, `@rjsf/fluentui-rc`, `@rjsf/mui`, `@rjsf/react-bootstrap` and `@rjsf/shadcn` set their `FieldTemplate`'s error state (antd's form item status, chakra-ui's fieldset `invalid`, fluentui-rc's `Field` validation state, mui's form control `error`, react-bootstrap's and shadcn's danger label and description) from it rather than from the field's plan, and core's `WrapIfAdditionalTemplate` sets its `has-error` from it too. An `anyOf`/`oneOf` option then follows its own `ui:hideError` in every theme, as core's class, its help and description already do (rjsf-team#5590). A new shared `optionErrorStateTests()` in `@rjsf/snapshot-tests` renders the option in both `ui:hideError` directions and checks each theme's marker. fluentui-rc keeps a test of its own for the one direction it can show, since its control is marked invalid from the plan whenever the field above shows errors, and Fluent's `Field` marks it invalid where the plan leaves it valid.

With no template reading it, `hasTemplateErrors()` is removed from `@rjsf/utils`. It was added on the v7 branch and never released. The deprecation notes on `rawErrors` and `hasVisibleErrors()`, the utility-function reference, the custom templates guide and the v7 upgrade guide point a template at `hasErrors`, and a container template at whether `presentation.errors.messages` has any; rjsf-team#5590's presentation test reads the plan's messages directly.

A custom field that renders a `FieldTemplate` itself passes `hasErrors` with its `errors`, as the upgrade guide, the custom templates guide and a new "Custom fields" section of antd's README say. Antd, which also decides from the error state whether to show the messages, still shows the messages of a field passing only the deprecated `rawErrors` through v7, without the error status; three tests render its template by hand.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(themes)!: address review of the error state change (rjsf-team#5616)

`FieldTemplateProps.hasErrors` is required, so a custom field that renders a `FieldTemplate` itself is told by the type checker to say whether the field is in error, rather than silently leaving the template out of it. The playground's `customFieldAnyOf` sample and the tests that render a template by hand pass it, and the changelog entry is tagged as a breaking change.

daisyui's `FieldTemplate` takes `hasErrors` out of the props it spreads onto its element, so React no longer warns about an unknown DOM prop, and forwards it to `WrapIfAdditionalTemplate`, as chakra-ui, mui, react-bootstrap, shadcn and fluentui-rc now do too. A new shared `wrapIfAdditionalErrorStateTests()` in `@rjsf/snapshot-tests` checks it in every theme.

antd's fallback for a template rendered by hand with the deprecated `rawErrors` applies `ui:hideError` through `hasVisibleErrors()`, and its README example passes `hasErrors` as `!hideError && errors.length > 0`.

An `anyOf`/`oneOf` option that shows its errors while the field above hides them draws them itself: `resolveFieldPresentation()` uses the field above's errors only where it shows any. A control marked invalid then has the message its `aria-describedby` names; the shared `optionErrorStateTests()` checks the message is drawn once.

`DescriptionFieldProps.hasErrors` is removed until something reads it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: list the review fixes in the changelog and correct the hasErrors doc (rjsf-team#5616)

The changelog lists the new `wrapIfAdditionalErrorStateTests()` under `@rjsf/snapshot-tests`, and under `@rjsf/daisyui` its `FieldTemplate` keeping `hasErrors` off its `div` and handing it to `WrapIfAdditionalTemplate`.

`FieldTemplateProps.hasErrors` and the custom templates guide no longer say a field's description takes its error state: with `DescriptionFieldProps.hasErrors` removed, nothing hands the description that state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(core,daisyui)!: address the second review of the error state change (rjsf-team#5616)

A field that a `ui:field` component renders for its own data plans its errors from the `rawErrors` the component hands it, as its `hasErrors` reads them, rather than from its `errorSchema`, which the field naming it stripped. `useSchemaFieldPlan()` works those errors out once and `SchemaField` reads them for the field's `rawErrors`, `hasErrors` and the template's deprecated props, so the two can't disagree. Where the field naming it hides its errors and the inner field shows them, the inner field draws them, is styled in error and has its control marked `aria-invalid`, as an `anyOf`/`oneOf` option does, where it used to be styled in error with no message. In 6.x it drew nothing for them, so the changelog tags it as a breaking change and the upgrade guide describes it; two `SchemaField` tests expect the inner root's own error beside its child's.

daisyui's `WrapIfAdditionalTemplate` keeps `hasErrors` off the `div` it spreads its other props onto for an extra key. The unknown-prop test moves to a file of its own, since React warns about a prop once per module and earlier tests used that warning up, and covers an extra key.

New tests pin core's `WrapIfAdditionalTemplate` taking `has-error` from `hasErrors` for an `anyOf` option and an extra key, and fluentui-rc's option `Field` taking its validation state from the option's own errors, read through Fluent's field context rather than the control's `aria-invalid`, which follows the plan. The antd test imports its `FieldTemplate` rather than asserting it non-null.

The upgrade guide tells a custom `FieldTemplate` that forwards its props to `WrapIfAdditionalTemplate` one by one to add `hasErrors`, the utility reference describes the new `resolveFieldPresentation()` errors rule, and antd's README example names the error messages it reads apart from the element that draws them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(core): address the third review of the error state change (rjsf-team#5616)

A field that a `ui:field` component renders for its own data takes its errors from the `SchemaField` naming it, through the `NamedFieldContext` that field already provides, rather than from the deprecated `rawErrors` the component hands on, so a wrapper that leaves `rawErrors` out, as v8 will, keeps them. Beside `anyOf`/`oneOf` options of its own, the naming field puts none there, since its errors go to the selected option, so they are drawn once.

`ArrayFieldTemplateProps` and `ObjectFieldTemplateProps` have an optional `hasErrors`, which `ObjectField` and `ArrayField` set from the container's own errors and `ui:hideError`, so an `anyOf`/`oneOf` option's container follows its own `ui:hideError` as its `FieldTemplate` does; the deprecation note on their `rawErrors`, the custom templates guide and the upgrade guide point a container at it for its error state in place of the plan's messages. A container beside options of its own leaves its errors to the selected option, so its `hasErrors` is false there, as the docs say.

`hasErrors` stays required on `FieldTemplateProps` with no fallback to `rawErrors`, and the upgrade guide now says so: TypeScript reports a template rendered without it, and from plain JavaScript such a template, and the `WrapIfAdditionalTemplate` it hands its props to, has no error state in any theme. The custom templates guide lists `hasErrors` among the props a `WrapIfAdditionalTemplate` is handed, and the daisyui changelog entry describes the prop it hands on rather than a warning no release logged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(core): hand a framed field's options the errors it takes from the context (rjsf-team#5616)

A field that a `ui:field` component renders for its own data takes its errors from the `SchemaField` naming it, whose `errorSchema` is handed on without them. Where that field renders `anyOf`/`oneOf` options itself, as below a field the options give way to, it now puts those errors back into the `errorSchema` it hands the options, memoized so the option's `SchemaField` keeps its memo, so the selected option follows its own `ui:hideError` there too, drawing them and taking `rjsf-field-error`. A core test covers it, and the core changelog has an entry.

antd's test of a hand-rendered template under `hideError` is named for what `hasVisibleErrors()` does rather than what it did, since antd's `FieldTemplate` still calls it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…allowed (rjsf-team#5640)

* fix 4630: say on its row that an extra key the object forbids is not allowed

A key matching none of an object's `patternProperties` beside
`additionalProperties: false` (or `unevaluatedProperties: false`, or matching
a `false` pattern) is stubbed as `{ type: 'null' }`, so its row rendered a key
input with no value input and no word of why. ajv8 and ata report the miss on
the object, not the key, and only once validation runs.

utils:
- `TranslatableString.AdditionalPropertyKeyNotAllowed`,
  `'The key "%1" is not allowed here'`.

core:
- `ObjectField` hands each row whether `getAdditionalPropertySchema()` forbids
  its key, and `ObjectFieldProperty` adds the message to the row's errors,
  after any it already has, memoized so the row keeps its error schema's
  identity. It is derived from the schema on every render rather than raised
  on rename, so it shows from the first render, follows no rename onto an
  allowed name, and needs no validation. It does not reach `ErrorList` or
  `onError`; the validator's own error still blocks the submit.

A key only `propertyNames` forbids gets no message. With cfworker, which also
reports the miss on the key, the row shows both messages.

Fixes rjsf-team#4630

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix 4630: mark a forbidden key's input invalid, and pin the review's cases

Follow-up to the review of rjsf-team#5640.

utils:
- `getAdditionalKeyAttributes()` gives an additional property's key input
  `aria-invalid` and an `aria-describedby` naming its row's errors while the
  row shows any, read from the plan or, without one, `rawErrors`/`hideError`.
  The template can't tell a key's error from its value's, so any row error
  marks the key.
- `AdditionalPropertyKeySelect` takes them as `errorAttributes` and merges
  them into its select's plan.

themes and core:
- All 9 `WrapIfAdditionalTemplate`s put them on the key input and the
  `propertyNames` select. Mantine routes them through
  `useAriaDescribedByProps()` and `error` in a `KeyTextInput` of its own,
  since its input overrides both; MUI sets `error`; antd sets the key
  `Form.Item`'s `validateStatus` and react-bootstrap `isInvalid`, so the key
  is drawn invalid as its value is. daisyui keeps them out of its spread.
- The seven theme `FieldTemplate`s that list the wrapper's props forward
  `rawErrors` and `hideError`, so the no-plan fallback reaches it.

tests and docs:
- Pin that the `newKey` the add button picks, where no `propertyNames.enum`
  offers a name the patterns match, says it is not allowed until renamed.
- Pin that an object closed by its selected option, beside options of its
  own, renders no row for an extra key, as any closed object without
  patterns does.
- `objects.md` names all three ways to forbid a key, the `newKey` case and
  the key's ARIA; utility-functions and the upgrade guide cover the new
  helper and prop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix 4630: mark only a forbidden key's input invalid, and settle the second review

Follow-up to the second review of rjsf-team#5640.

core and utils:
- `ObjectField` hands each row `keyNotAllowed`, which `SchemaField` passes
  to the `FieldTemplate` and `WrapIfAdditionalTemplate` (new on
  `FieldTemplateProps` and `WrapIfAdditionalTemplateProps`).
  `getAdditionalKeyAttributes()` marks the key only while that flag is set
  and the row's errors show, so an allowed key whose row has only value
  errors stays unmarked. This replaces d1c25a7's "any row error marks the
  key".
- `getNestedControlPresentation()` takes an `attributes` input, defaulting
  to its `field`'s control's, and is the one place the merge happens;
  `AdditionalPropertyKeySelect` passes `errorAttributes` through it, so
  `aria-invalid` alone is no longer dropped.

themes:
- The six `FieldTemplate`s that list their wrapper's props forward
  `keyNotAllowed`; daisyui's `WrapIfAdditionalTemplate` keeps it out of its
  spread. Mantine's explicit `rawErrors`/`hideError` are dropped, since its
  `{...otherProps}` already passes them.

docs:
- The core and utils entries are marked BREAKING CHANGE and the upgrade
  guide section moves into the breaking changes, telling a custom
  `FieldTemplate` to forward `keyNotAllowed`. The custom
  `WrapIfAdditionalTemplate` advice lives in the `getAdditionalKeyAttributes()`
  reference. `objects.md` notes that the message shows in `readonly` and
  `disabled` forms too, and custom-templates lists `keyNotAllowed`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix 4630: pin the forbidden key's two messages, and settle the third review

Follow-up to the third review of rjsf-team#5640.

utils:
- `FieldProps` declares `keyNotAllowed`, so it is type-checked between
  `ObjectFieldProperty` and `SchemaField` instead of arriving through the
  index signature.
- `getNestedControlPresentation()` without a `field` takes its plan's
  `describedBy` from the `aria-describedby` it is given, so the two agree.

tests and docs:
- Pin that after a submit ajv8's `boolean schema is false` shows ahead of
  the not-allowed message on a key a `false` pattern matches. This replaces
  b7f903e's "deliberately not pinned".
- The upgrade guide tells a custom `WrapIfAdditionalTemplate` that spreads
  its leftover props to leave out `keyNotAllowed`, `rawErrors` and
  `hideError`, which 168f298 had left to the API reference.
- The mui changelog line no longer claims an allowed key drops
  `aria-invalid="false"`; only a forbidden key changes. The utils entry
  names `FieldProps`.

Left for a follow-up: computing the key's attributes once in `SchemaField`
so the six theme `FieldTemplate`s forward one prop instead of three.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix 4630: take the key's error state from hasErrors after rebasing onto rjsf-team#5646

rjsf-team#5646 removed `hasTemplateErrors()` and hands every `FieldTemplate` and
`WrapIfAdditionalTemplate` a required `hasErrors`, with no `rawErrors`
fallback. The rebase ports `getAdditionalKeyAttributes()` to
`keyNotAllowed && hasErrors`, and the six theme `FieldTemplate`s that list
their wrapper's props stop forwarding `rawErrors` and `hideError`, which
reverses d1c25a7's fallback for a template rendered without a plan.

This commit finishes that at the tip:
- daisyui's `WrapIfAdditionalTemplate` no longer keeps `rawErrors` and
  `hideError` out of its spread, since nothing hands them on.
- The upgrade guide, the `getAdditionalKeyAttributes()` reference and the six
  theme changelog bullets name only `keyNotAllowed`.
- `getAdditionalKeyAttributes.test.ts` is formatted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ntext, collapse additional-property keys, simplify to entryLabel (local, unpushed)
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Size limit report

Sizes are minified + brotli, measured by size-limit at 77d00ae.

A package listed twice is measured both as installed and, on the second row, as its own code with its dependencies excluded. Peer dependencies are always excluded.

Check Base PR Δ
@rjsf/antd 7.72 kB 7.75 kB +0.03 kB
@rjsf/antd (without dependencies) 7.26 kB 7.30 kB +0.04 kB
@rjsf/chakra-ui 18.07 kB 18.09 kB +0.02 kB
@rjsf/chakra-ui (without dependencies) 11.84 kB 11.85 kB +0.01 kB
@rjsf/core 38.63 kB 38.72 kB +0.09 kB
@rjsf/core/markdown 25.53 kB 25.53 kB =
@rjsf/core/testing 68.49 kB 68.60 kB +0.11 kB
@rjsf/core: Form 38.33 kB 38.49 kB +0.16 kB
@rjsf/daisyui 55.39 kB 55.50 kB +0.11 kB
@rjsf/daisyui (without dependencies) 12.44 kB 12.49 kB +0.05 kB
@rjsf/fluentui-rc 6.26 kB 6.28 kB +0.02 kB
@rjsf/mantine 14.79 kB 14.89 kB +0.11 kB
@rjsf/mantine (without dependencies) 10.46 kB 10.54 kB +0.09 kB
@rjsf/mui 7.44 kB 7.50 kB +0.06 kB
@rjsf/react-bootstrap 7.97 kB 8.02 kB +0.04 kB
@rjsf/react-bootstrap (without dependencies) 5.56 kB 5.58 kB +0.02 kB
@rjsf/shadcn 44.70 kB 44.78 kB +0.08 kB
@rjsf/shadcn (without dependencies) 10.53 kB 10.56 kB +0.02 kB
@rjsf/utils 47.55 kB 47.91 kB +0.36 kB
@rjsf/utils (without dependencies) 41.98 kB 42.28 kB +0.30 kB
@rjsf/utils: getUiOptions 0.72 kB 0.72 kB =
@rjsf/validator-ajv8 38.56 kB 38.56 kB =
@rjsf/validator-ajv8 (without dependencies) 3.12 kB 3.12 kB =
@rjsf/validator-ajv8: createPrecompiledValidator 1.44 kB 1.44 kB =
@rjsf/validator-ata 110.67 kB 110.67 kB =
@rjsf/validator-ata (without dependencies) 2.44 kB 2.44 kB =
@rjsf/validator-ata: createPrecompiledValidator 1.30 kB 1.30 kB =
@rjsf/validator-cfworker 7.59 kB 7.59 kB =
@rjsf/validator-cfworker (without dependencies) 2.74 kB 2.74 kB =

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants