fix(web): admit null in the number field's value and default prop types

Copilot review: a nullable number schema really does produce `null` for both
the raw value and the schema default, but the props declared only
`number | undefined` and the call site cast the null away. The runtime already
handled it — the initializer's `?? ""` exists for exactly that — so the types
were the part that was wrong, and a cast hiding it is how a future null bug
goes unseen by the compiler.

Widen both to `number | null | undefined` and drop the narrowing casts, keeping
the distinction the initializer encodes: `undefined` takes the default, `null`
is a value and renders as an empty box.

Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-16 01:00:48 -04:00
commit 27fe15976f

View file

@ -337,10 +337,17 @@ interface SchemaNumberInputProps {
description?: string;
withAsterisk: boolean;
disabled: boolean;
/** Raw, not `resolveValue`-substituted — see `SchemaJsonFieldProps.value`. */
value: number | undefined;
/** The schema `default`, used to seed the draft only (#2026). */
defaultValue: number | undefined;
/**
* Raw, not `resolveValue`-substituted — see `SchemaJsonFieldProps.value`.
*
* `null` is admitted alongside `undefined` because a nullable number schema
* produces it, and the two are not interchangeable here: `undefined` means
* "no value supplied" and takes `defaultValue`, while `null` is a value and
* displays as an empty box.
*/
value: number | null | undefined;
/** The schema `default`, used to seed the draft only (#2026). May be `null`. */
defaultValue: number | null | undefined;
min?: number;
max?: number;
allowDecimal: boolean;
@ -627,9 +634,12 @@ export function SchemaForm({
description={description}
withAsterisk={isRequired}
disabled={disabled}
// Raw and default kept apart, not pre-resolved (#2026).
value={values[fieldName] as number | undefined}
defaultValue={getDefaultValue(fieldSchema) as number | undefined}
// Raw and default kept apart, not pre-resolved (#2026). Both admit
// `null`, which a nullable number schema really produces.
value={values[fieldName] as number | null | undefined}
defaultValue={
getDefaultValue(fieldSchema) as number | null | undefined
}
min={fieldSchema.minimum}
max={fieldSchema.maximum}
// An `integer` field rejects the decimal point outright rather than