(props: {
readonly schema: JsonSchema;
readonly fieldId: string;
readonly value: unknown;
readonly onChange: (next: unknown) => void;
readonly integer: boolean;
readonly disabled?: boolean;
})
| 583 | // --------------------------------------------------------------------------- |
| 584 | |
| 585 | function NumberField(props: { |
| 586 | readonly schema: JsonSchema; |
| 587 | readonly fieldId: string; |
| 588 | readonly value: unknown; |
| 589 | readonly onChange: (next: unknown) => void; |
| 590 | readonly integer: boolean; |
| 591 | readonly disabled?: boolean; |
| 592 | }): React.ReactElement { |
| 593 | const { fieldId, value, onChange, integer, disabled } = props; |
| 594 | const valueText = typeof value === "number" ? String(value) : ""; |
| 595 | const [draft, setDraft] = useState<string | null>(null); |
| 596 | const display = draft ?? valueText; |
| 597 | const invalid = |
| 598 | draft !== null && draft.trim() !== "" && coerceNumber(draft, integer) === undefined; |
| 599 | |
| 600 | return ( |
| 601 | <Input |
| 602 | id={fieldId} |
| 603 | type="number" |
| 604 | step={integer ? 1 : "any"} |
| 605 | className="text-xs" |
| 606 | value={display} |
| 607 | disabled={disabled} |
| 608 | aria-invalid={invalid} |
| 609 | onChange={(e: React.ChangeEvent<HTMLInputElement>) => { |
| 610 | const raw = e.target.value; |
| 611 | setDraft(raw); |
| 612 | const n = coerceNumber(raw, integer); |
| 613 | if (n !== undefined) onChange(n); |
| 614 | }} |
| 615 | onBlur={() => setDraft(null)} |
| 616 | /> |
| 617 | ); |
| 618 | } |
| 619 | |
| 620 | // --------------------------------------------------------------------------- |
| 621 | // ArrayField — single-`items` arrays; index-keyed add/remove |
nothing calls this directly
no test coverage detected