@petrarca/sonnet-forms 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/index.d.ts +352 -20
- package/dist/index.js +2762 -413
- package/dist/index.js.map +1 -1
- package/dist/widget-options.d.ts +2 -1
- package/dist/widget-options.js +74 -1
- package/dist/widget-options.js.map +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -10,8 +10,8 @@ labelled, validated controls.
|
|
|
10
10
|
flattening against the current values, schema defaults, nested objects and
|
|
11
11
|
arrays, buffered or live editing, and a change set on save.
|
|
12
12
|
|
|
13
|
-
**A widget registry.**
|
|
14
|
-
quantities, enums, checkboxes, tags, arrays, objects, entity references and
|
|
13
|
+
**A widget registry.** Twenty-two built-in controls covering text, numbers,
|
|
14
|
+
quantities, coded values and codeable concepts, dates and times, enums, checkboxes, tags, arrays, objects, entity references and
|
|
15
15
|
embedded JSON, plus your own controls keyed by `x-ui-widget`. A parallel
|
|
16
16
|
template registry makes the structure around a field -- the array-item row, the
|
|
17
17
|
object container, the group chrome -- replaceable without touching the widgets.
|
|
@@ -91,8 +91,8 @@ actually enforces are in [getting started](docs/usage/getting-started.md).
|
|
|
91
91
|
[templates](docs/usage/templates.md),
|
|
92
92
|
[field components](docs/usage/field-components.md) and
|
|
93
93
|
[change tracking](docs/usage/change-tracking.md).
|
|
94
|
-
- [Design docs](docs/design/index.md) -- form layout, nested fields
|
|
95
|
-
change-tracking model.
|
|
94
|
+
- [Design docs](docs/design/index.md) -- form layout, nested fields, the
|
|
95
|
+
change-tracking model, and custom validation.
|
|
96
96
|
- [Workspace documentation](../../docs/README.md) -- how the packages layer and
|
|
97
97
|
the shared schema extension contract.
|
|
98
98
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import * as React$1 from 'react';
|
|
3
2
|
import React__default, { ComponentType, ReactNode } from 'react';
|
|
4
3
|
import { Input, Textarea, badgeVariants } from '@petrarca/sonnet-ui';
|
|
5
|
-
import { JsonSchemaProperty,
|
|
4
|
+
import { JsonSchema, JsonSchemaProperty, UISchema, UISchemaOptions, UILayoutConfig, FieldError, FormDiff, RefResolver } from '@petrarca/sonnet-core/schema';
|
|
6
5
|
export { UISchema, UISchemaOptions } from '@petrarca/sonnet-core/schema';
|
|
7
6
|
import { VariantProps } from 'class-variance-authority';
|
|
8
7
|
import { SaveWhenInvalid, ValidationDisplay } from '@petrarca/sonnet-core/config';
|
|
9
8
|
|
|
9
|
+
/**
|
|
10
|
+
* FormFieldWrapper - Shared label / description / error chrome for form fields.
|
|
11
|
+
*
|
|
12
|
+
* Eliminates duplication across FormInput, FormNumberInput, FormQuantityInput,
|
|
13
|
+
* etc. Each field component renders its control as `children` and delegates
|
|
14
|
+
* the surrounding chrome here.
|
|
15
|
+
*
|
|
16
|
+
* Supports two modes:
|
|
17
|
+
* - Normal: label, children, description, error displayed vertically
|
|
18
|
+
* - Compact: suppresses label, description, error text (for grid layouts)
|
|
19
|
+
*/
|
|
20
|
+
|
|
10
21
|
interface FormFieldWrapperProps {
|
|
11
22
|
/** Field id -- wired to the label's htmlFor */
|
|
12
23
|
inputId: string;
|
|
@@ -39,7 +50,7 @@ interface FormFieldWrapperProps {
|
|
|
39
50
|
* FormFieldWrapper renders label, children (the control), description, and
|
|
40
51
|
* error in the standard vertical layout used by all form field components.
|
|
41
52
|
*/
|
|
42
|
-
declare function FormFieldWrapper({ inputId, label, description, error, required, compact, labelPlacement, className, children, }: FormFieldWrapperProps):
|
|
53
|
+
declare function FormFieldWrapper({ inputId, label, description, error, required, compact, labelPlacement, className, children, }: FormFieldWrapperProps): React__default.JSX.Element;
|
|
43
54
|
|
|
44
55
|
/**
|
|
45
56
|
* Shared utility functions for form field components.
|
|
@@ -470,6 +481,14 @@ type TemplateRegistry = {
|
|
|
470
481
|
[templateName: string]: unknown;
|
|
471
482
|
};
|
|
472
483
|
|
|
484
|
+
/**
|
|
485
|
+
* FormSelect - Searchable single-select dropdown with form field wrapper
|
|
486
|
+
*
|
|
487
|
+
* Composable select component using Popover + Command for searchable,
|
|
488
|
+
* keyboard-navigable dropdown. Follows Form wrapper pattern with
|
|
489
|
+
* label, description, error support.
|
|
490
|
+
*/
|
|
491
|
+
|
|
473
492
|
interface FormSelectProps {
|
|
474
493
|
label?: string | false;
|
|
475
494
|
description?: string;
|
|
@@ -509,7 +528,15 @@ interface FormSelectProps {
|
|
|
509
528
|
/** Called with the trimmed search text when the create item is chosen. */
|
|
510
529
|
onCreate?: (label: string) => void;
|
|
511
530
|
}
|
|
512
|
-
declare function FormSelect(props: FormSelectProps):
|
|
531
|
+
declare function FormSelect(props: FormSelectProps): React$1.JSX.Element;
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* FormMultiSelect - Searchable multi-select dropdown with badges
|
|
535
|
+
*
|
|
536
|
+
* Multi-select component using Popover + Command with badge display
|
|
537
|
+
* for selected items. Follows Form wrapper pattern with label,
|
|
538
|
+
* description, error support.
|
|
539
|
+
*/
|
|
513
540
|
|
|
514
541
|
type BadgeColor = NonNullable<VariantProps<typeof badgeVariants>["badgeColor"]>;
|
|
515
542
|
|
|
@@ -539,7 +566,7 @@ interface FormMultiSelectProps {
|
|
|
539
566
|
maxDisplay?: number;
|
|
540
567
|
badgeColor?: BadgeColor;
|
|
541
568
|
}
|
|
542
|
-
declare function FormMultiSelect(props: FormMultiSelectProps):
|
|
569
|
+
declare function FormMultiSelect(props: FormMultiSelectProps): React$1.JSX.Element;
|
|
543
570
|
|
|
544
571
|
/**
|
|
545
572
|
* FormTagsInput - Input field for managing tags with badges
|
|
@@ -570,6 +597,59 @@ interface FormTagsInputProps {
|
|
|
570
597
|
}
|
|
571
598
|
declare const FormTagsInput: React$1.ForwardRefExoticComponent<FormTagsInputProps & React$1.RefAttributes<HTMLInputElement>>;
|
|
572
599
|
|
|
600
|
+
/**
|
|
601
|
+
* FormKeyValueInput - Input for a map of string keys to string values
|
|
602
|
+
*
|
|
603
|
+
* Each pair is entered in two fields (key, value) and added with Enter or the
|
|
604
|
+
* add button. A key is unique: adding it again replaces its value. The entered
|
|
605
|
+
* pairs are displayed one of two ways (`display`):
|
|
606
|
+
*
|
|
607
|
+
* tags (default) as "key:value" tags -- for short labels. Clicking a tag
|
|
608
|
+
* loads it back into the fields to edit it; its X removes it.
|
|
609
|
+
* rows as a list, a row per pair: its key and value editable in
|
|
610
|
+
* place (taken on leaving the field or Enter), a remove
|
|
611
|
+
* button -- for values too long or too many to read as tags,
|
|
612
|
+
* such as templates or paths.
|
|
613
|
+
|
|
614
|
+
* keys only the keys, as badges, each value on hover -- a compact
|
|
615
|
+
* summary, not edited (the host edits the pairs elsewhere,
|
|
616
|
+
* e.g. as rows in a dialog).
|
|
617
|
+
*
|
|
618
|
+
* `valueSuggestions` offers values to pick in the value fields (still free to
|
|
619
|
+
* type) -- e.g. the references a value may name.
|
|
620
|
+
*
|
|
621
|
+
* Follows the Form wrapper pattern with label, description, error support.
|
|
622
|
+
*/
|
|
623
|
+
|
|
624
|
+
interface FormKeyValueInputProps {
|
|
625
|
+
label?: string | false;
|
|
626
|
+
description?: string;
|
|
627
|
+
error?: string;
|
|
628
|
+
required?: boolean;
|
|
629
|
+
wrapperClassName?: string;
|
|
630
|
+
labelPlacement?: "top" | "start";
|
|
631
|
+
id?: string;
|
|
632
|
+
name?: string;
|
|
633
|
+
value: Record<string, string>;
|
|
634
|
+
onChange?: (value: Record<string, string>) => void;
|
|
635
|
+
disabled?: boolean;
|
|
636
|
+
readOnly?: boolean;
|
|
637
|
+
/** Placeholders of the two fields. Default "Key" / "Value". */
|
|
638
|
+
keyPlaceholder?: string;
|
|
639
|
+
valuePlaceholder?: string;
|
|
640
|
+
/** How a pair is shown as a tag. Default ":" ("key:value"). */
|
|
641
|
+
separator?: string;
|
|
642
|
+
/** How the pairs are displayed: as tags (default), as rows, or only their
|
|
643
|
+
* keys (a summary, not edited). */
|
|
644
|
+
display?: "tags" | "rows" | "keys";
|
|
645
|
+
/** Values the value fields suggest; one may still type any other. */
|
|
646
|
+
valueSuggestions?: {
|
|
647
|
+
value: string;
|
|
648
|
+
label?: string;
|
|
649
|
+
}[];
|
|
650
|
+
}
|
|
651
|
+
declare const FormKeyValueInput: React$1.ForwardRefExoticComponent<FormKeyValueInputProps & React$1.RefAttributes<HTMLInputElement>>;
|
|
652
|
+
|
|
573
653
|
/**
|
|
574
654
|
* FormQuantityInput - Compound input for a numeric value paired with a unit selector.
|
|
575
655
|
*
|
|
@@ -612,8 +692,10 @@ interface FormQuantityInputProps {
|
|
|
612
692
|
onChange?: (value: QuantityValue) => void;
|
|
613
693
|
/** Blur handler */
|
|
614
694
|
onBlur?: () => void;
|
|
615
|
-
/** Available unit options. Single = static text, 2+ = dropdown, none = no addon. */
|
|
695
|
+
/** Available unit options. Single = static text, 2+ = dropdown, none = no addon (or a typed unit, with `freeUnit`). */
|
|
616
696
|
units?: UnitOption[];
|
|
697
|
+
/** Without units, the unit is typed -- a code such as `kg`. Default false: no unit at all. */
|
|
698
|
+
freeUnit?: boolean;
|
|
617
699
|
/**
|
|
618
700
|
* Default position for all units. Individual UnitOption.position overrides
|
|
619
701
|
* this. Default: "suffix".
|
|
@@ -673,13 +755,18 @@ interface FormActionsProps {
|
|
|
673
755
|
saveLabel?: string;
|
|
674
756
|
cancelLabel?: string;
|
|
675
757
|
showCancel?: boolean;
|
|
758
|
+
/**
|
|
759
|
+
* True while an async validator is in flight. Save is disabled until it
|
|
760
|
+
* settles (validity is not yet known); Cancel stays enabled.
|
|
761
|
+
*/
|
|
762
|
+
isValidating?: boolean;
|
|
676
763
|
/**
|
|
677
764
|
* Optional content rendered left-aligned in the action row (e.g. a secondary
|
|
678
765
|
* action like "Test connection"). Cancel/Save stay grouped on the right.
|
|
679
766
|
*/
|
|
680
767
|
leadingActions?: ReactNode;
|
|
681
768
|
}
|
|
682
|
-
declare function FormActions({ onSave, onCancel, disabled, hasChanges, isValid, saveWhenInvalid, saveLabel, cancelLabel, showCancel, leadingActions, }: FormActionsProps):
|
|
769
|
+
declare function FormActions({ onSave, onCancel, disabled, hasChanges, isValid, saveWhenInvalid, saveLabel, cancelLabel, showCancel, isValidating, leadingActions, }: FormActionsProps): React$1.JSX.Element;
|
|
683
770
|
|
|
684
771
|
type Props = {
|
|
685
772
|
properties: Record<string, any>;
|
|
@@ -692,7 +779,7 @@ type Props = {
|
|
|
692
779
|
* This is a generic component that can be used anywhere a schema and properties
|
|
693
780
|
* need to be compared to show additional/extra properties.
|
|
694
781
|
*/
|
|
695
|
-
declare function ExtraPropertiesCard({ properties, schema }: Props):
|
|
782
|
+
declare function ExtraPropertiesCard({ properties, schema }: Props): React$1.JSX.Element | null;
|
|
696
783
|
|
|
697
784
|
/**
|
|
698
785
|
* TextInputWidget - Standard text input widget
|
|
@@ -723,7 +810,7 @@ declare function TextInputWidget({ id, name, value, onChange, onBlur, propertySc
|
|
|
723
810
|
*
|
|
724
811
|
* @param props - WidgetProps
|
|
725
812
|
*/
|
|
726
|
-
declare function TextareaWidget({ id, name, value, onChange, onBlur, propertySchema, required, disabled, readonly, rawErrors, label, description, placeholder, autofocus, options, }: WidgetProps):
|
|
813
|
+
declare function TextareaWidget({ id, name, value, onChange, onBlur, propertySchema, required, disabled, readonly, rawErrors, label, description, placeholder, autofocus, options, }: WidgetProps): React$1.JSX.Element;
|
|
727
814
|
|
|
728
815
|
/**
|
|
729
816
|
* NumberWidget renders a number input field.
|
|
@@ -736,7 +823,7 @@ declare function TextareaWidget({ id, name, value, onChange, onBlur, propertySch
|
|
|
736
823
|
*
|
|
737
824
|
* @param props - WidgetProps
|
|
738
825
|
*/
|
|
739
|
-
declare function NumberWidget({ id, name, value, onChange, onBlur, propertySchema, required, disabled, readonly, rawErrors, label, description, placeholder, autofocus, options, }: WidgetProps):
|
|
826
|
+
declare function NumberWidget({ id, name, value, onChange, onBlur, propertySchema, required, disabled, readonly, rawErrors, label, description, placeholder, autofocus, options, }: WidgetProps): React$1.JSX.Element;
|
|
740
827
|
|
|
741
828
|
/**
|
|
742
829
|
* CheckboxWidget - Boolean checkbox widget
|
|
@@ -745,7 +832,8 @@ declare function NumberWidget({ id, name, value, onChange, onBlur, propertySchem
|
|
|
745
832
|
* Used for boolean type fields.
|
|
746
833
|
*
|
|
747
834
|
* Supports tri-state behavior for nullable boolean fields (anyOf[boolean, null]):
|
|
748
|
-
* - null (indeterminate) -> true (checked) -> false (unchecked) -> null
|
|
835
|
+
* - null or no value (indeterminate) -> true (checked) -> false (unchecked) -> null
|
|
836
|
+
* No value is shown as null is: not answered -- unchecked would read as "no".
|
|
749
837
|
*/
|
|
750
838
|
|
|
751
839
|
/**
|
|
@@ -758,13 +846,13 @@ declare function NumberWidget({ id, name, value, onChange, onBlur, propertySchem
|
|
|
758
846
|
* - Description text
|
|
759
847
|
*
|
|
760
848
|
* Tri-state behavior (when anyOf[boolean, null] is detected):
|
|
761
|
-
* - Click on null -> becomes true
|
|
849
|
+
* - Click on null, or no value -> becomes true
|
|
762
850
|
* - Click on true -> becomes false
|
|
763
851
|
* - Click on false -> becomes null
|
|
764
852
|
*/
|
|
765
853
|
declare function CheckboxWidget({ id, value, onChange, onBlur, disabled, readonly, rawErrors, label, description, autofocus, propertySchema, options, }: WidgetProps): React.ReactElement;
|
|
766
854
|
|
|
767
|
-
declare function SelectWidget(props: WidgetProps):
|
|
855
|
+
declare function SelectWidget(props: WidgetProps): React$1.JSX.Element;
|
|
768
856
|
|
|
769
857
|
/**
|
|
770
858
|
* TagsInputWidget - Free-text tag input widget
|
|
@@ -805,9 +893,24 @@ declare function TagsInputWidget({ id, name, value, onChange, required, disabled
|
|
|
805
893
|
* - Full document editing (no readonly regions)
|
|
806
894
|
* - Invalid JSON is silently retained until fixed
|
|
807
895
|
* - Height configurable via x-ui-options.height (default: "240px")
|
|
896
|
+
* - The editor loads on first use (a placeholder of that height meanwhile)
|
|
808
897
|
*/
|
|
809
898
|
declare function JsonEditorWidget({ id, value, onChange, label, description, required, options, }: WidgetProps): React__default.ReactElement;
|
|
810
899
|
|
|
900
|
+
/**
|
|
901
|
+
* KeyValueWidget - Key-value pair input widget
|
|
902
|
+
*
|
|
903
|
+
* Renders FormKeyValueInput for an object of string values (a free map such as
|
|
904
|
+
* labels: `additionalProperties: { type: "string" }`, no declared properties).
|
|
905
|
+
* Pairs are entered in a key and a value field and shown as "key:value" tags,
|
|
906
|
+
* or -- `x-ui-options: { display: "rows" }` -- as rows edited in place, for long
|
|
907
|
+
* values such as templates or paths, or -- `display: "keys"` -- only the keys,
|
|
908
|
+
* a summary not edited. Chosen automatically for such maps;
|
|
909
|
+
* explicitly via x-ui-widget: "key-value".
|
|
910
|
+
*/
|
|
911
|
+
|
|
912
|
+
declare function KeyValueWidget({ id, name, value, onChange, required, disabled, readonly, rawErrors, label, description, options, }: WidgetProps): React__default.ReactElement;
|
|
913
|
+
|
|
811
914
|
/**
|
|
812
915
|
* EntitySelectWidget -- form widget for async entity reference selection.
|
|
813
916
|
*
|
|
@@ -873,9 +976,68 @@ declare function ObjectWidget({ id, propertySchema, value, onChange, onBlur, reg
|
|
|
873
976
|
* never leave the renderer boundary.
|
|
874
977
|
*/
|
|
875
978
|
|
|
876
|
-
declare function ArrayWidget({ propertySchema, value, onChange, registry, uiSchema, disabled, readonly, label, description, options, schema, name, }: WidgetProps): React.ReactElement;
|
|
979
|
+
declare function ArrayWidget({ propertySchema, value, onChange, registry, uiSchema, disabled, readonly, label, description, options, schema, name, onBlur, }: WidgetProps): React.ReactElement;
|
|
877
980
|
|
|
878
|
-
declare function QuantityWidget({ id, name, value, onChange, onBlur, propertySchema, required, disabled, readonly, rawErrors, label, description, placeholder, autofocus, options, }: WidgetProps):
|
|
981
|
+
declare function QuantityWidget({ id, name, value, onChange, onBlur, propertySchema, required, disabled, readonly, rawErrors, label, description, placeholder, autofocus, options, }: WidgetProps): React$1.JSX.Element;
|
|
982
|
+
|
|
983
|
+
/**
|
|
984
|
+
* CodedValueWidget -- a code from a list someone else maintains, asked of the
|
|
985
|
+
* application's terminology service (`TerminologyProvider`).
|
|
986
|
+
*
|
|
987
|
+
* The list is the field's binding (`x-binding`: a value set or a code system,
|
|
988
|
+
* its strength). What is stored the field's type decides: the core coding type
|
|
989
|
+
* stores `{ system, code, version?, display? }`; a string bound to a list stores
|
|
990
|
+
* the code alone, its label looked up to show it; a coding or a text (`anyOf`,
|
|
991
|
+
* an open list) stores a coding, or a text of one's own as a plain string --
|
|
992
|
+
* never a coding without its code. An array of any of them takes several
|
|
993
|
+
* answers, shown as chips. The first search decides whether the list is shown
|
|
994
|
+
* whole (it fits one page) or searched; a hit shows its code and, when the
|
|
995
|
+
* service gives it, its path. An open list -- a coding or a text, or an
|
|
996
|
+
* `extensible` binding on a string -- takes a typed text no code fits.
|
|
997
|
+
*
|
|
998
|
+
* Registered as x-ui-widget: "coded-value"; the core coding type carries that
|
|
999
|
+
* hint, and a string, a coding or a text, or an array bound to a list resolves
|
|
1000
|
+
* to it without one.
|
|
1001
|
+
*
|
|
1002
|
+
* x-ui-options:
|
|
1003
|
+
* mode - "list" | "search": overrides what the list's size decides
|
|
1004
|
+
* minChars - the characters a search waits for (default 1)
|
|
1005
|
+
* store - the hit's property a code-only field stores (default "code")
|
|
1006
|
+
* keep - properties of a hit a coding keeps beside its own -- an
|
|
1007
|
+
* application's, which its service returns on its hits
|
|
1008
|
+
*
|
|
1009
|
+
* See docs/design/coded-values.md (workspace).
|
|
1010
|
+
*/
|
|
1011
|
+
|
|
1012
|
+
declare function CodedValueWidget(props: WidgetProps): React$1.ReactElement;
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* CodeableConceptWidget -- one concept, coded in the field's lists, compact:
|
|
1016
|
+
* the coded-value picker on the first list, and one line of chips for the
|
|
1017
|
+
* codings of the others -- as clinical systems show a concept: its term, the
|
|
1018
|
+
* other codes beside it.
|
|
1019
|
+
*
|
|
1020
|
+
* [ Glucose [Mass/volume] in Serum or Plasma 2345-7 v ]
|
|
1021
|
+
* [Lab GLU-S x] [Registry *] + Coding + Text
|
|
1022
|
+
*
|
|
1023
|
+
* A chip -- or "+ Coding", for a list without one -- opens the same search on
|
|
1024
|
+
* its list. What a person picks is stored as theirs (`userSelected`), with the
|
|
1025
|
+
* list's purpose; a required list without a coding shows as an empty chip. A
|
|
1026
|
+
* coding of a list the field does not name is shown and kept, never dropped.
|
|
1027
|
+
*
|
|
1028
|
+
* The lists are the field's binding (`x-binding`): the first, then
|
|
1029
|
+
* `additional`. Registered as x-ui-widget: "codeable-concept"; the core
|
|
1030
|
+
* codeable concept type carries that hint.
|
|
1031
|
+
*
|
|
1032
|
+
* x-ui-options:
|
|
1033
|
+
* text - offer the text (default: when the first list is extensible)
|
|
1034
|
+
* mode - "list" | "search", for every list (default: each list's size decides)
|
|
1035
|
+
* minChars - the characters a search waits for
|
|
1036
|
+
*
|
|
1037
|
+
* See docs/design/codeable-concepts.md (workspace).
|
|
1038
|
+
*/
|
|
1039
|
+
|
|
1040
|
+
declare function CodeableConceptWidget(props: WidgetProps): React$1.ReactElement;
|
|
879
1041
|
|
|
880
1042
|
/**
|
|
881
1043
|
* DateWidget - date field widget backed by the DateInput primitive.
|
|
@@ -884,6 +1046,9 @@ declare function QuantityWidget({ id, name, value, onChange, onBlur, propertySch
|
|
|
884
1046
|
* string (`YYYY`, `YYYY-MM`, or `YYYY-MM-DD`). Auto-resolves from schema
|
|
885
1047
|
* `format: "date"`, or `x-ui-widget: "date"`.
|
|
886
1048
|
*
|
|
1049
|
+
* Its range is the schema's `formatMinimum` / `formatMaximum`: the calendar
|
|
1050
|
+
* offers only the dates between; validation names a typed one outside.
|
|
1051
|
+
*
|
|
887
1052
|
* x-ui-options:
|
|
888
1053
|
* precision - "year" | "month" | "day" (default "day")
|
|
889
1054
|
* locale - BCP-47 locale override (defaults to the app locale)
|
|
@@ -892,7 +1057,7 @@ declare function QuantityWidget({ id, name, value, onChange, onBlur, propertySch
|
|
|
892
1057
|
* the inline error message and invalid border.
|
|
893
1058
|
*/
|
|
894
1059
|
|
|
895
|
-
declare function DateWidget({ id, value, onChange, onBlur, required, disabled, rawErrors, label, description, placeholder, options, }: WidgetProps): React.ReactElement;
|
|
1060
|
+
declare function DateWidget({ id, value, onChange, onBlur, required, disabled, rawErrors, label, description, placeholder, options, propertySchema, }: WidgetProps): React.ReactElement;
|
|
896
1061
|
|
|
897
1062
|
/**
|
|
898
1063
|
* TimeWidget - time-of-day field widget backed by the TimeInput primitive.
|
|
@@ -925,7 +1090,7 @@ declare function TimeWidget({ id, value, onChange, onBlur, required, disabled, r
|
|
|
925
1090
|
* the inline error message and invalid border.
|
|
926
1091
|
*/
|
|
927
1092
|
|
|
928
|
-
declare function DateTimeWidget({ id, value, onChange, onBlur, required, disabled, rawErrors, label, description, options, }: WidgetProps): React.ReactElement;
|
|
1093
|
+
declare function DateTimeWidget({ id, value, onChange, onBlur, required, disabled, rawErrors, label, description, options, propertySchema, }: WidgetProps): React.ReactElement;
|
|
929
1094
|
|
|
930
1095
|
/**
|
|
931
1096
|
* DisplayWidget - read-only text block, no data binding.
|
|
@@ -954,6 +1119,55 @@ declare function DisplayWidget({ label, description, }: WidgetProps): React.Reac
|
|
|
954
1119
|
|
|
955
1120
|
declare function OneOfWidget({ propertySchema, value, onChange, registry, uiSchema, disabled, readonly, label, description, id, options, }: WidgetProps): React.ReactElement | null;
|
|
956
1121
|
|
|
1122
|
+
/**
|
|
1123
|
+
* RadioWidget -- a single choice as radio buttons, every option in view.
|
|
1124
|
+
*
|
|
1125
|
+
* For an enum property, selected by `x-ui-widget: "radio"`. Labels come from
|
|
1126
|
+
* x-ui-options.enumNames, as for the select. `x-ui-options.orientation`
|
|
1127
|
+
* "horizontal" lays the options out in a row (default: a column).
|
|
1128
|
+
*/
|
|
1129
|
+
|
|
1130
|
+
declare function RadioWidget({ id, name, value, onChange, onBlur, propertySchema, required, disabled, readonly, rawErrors, label, description, options, }: WidgetProps): React.ReactElement;
|
|
1131
|
+
|
|
1132
|
+
/**
|
|
1133
|
+
* CheckboxGroupWidget -- a multiple choice as checkboxes, every option in view.
|
|
1134
|
+
*
|
|
1135
|
+
* For an array of enum items, selected by `x-ui-widget: "checkbox-group"`.
|
|
1136
|
+
* Labels come from x-ui-options.enumNames, as for the select; the value keeps
|
|
1137
|
+
* the options' order. `x-ui-options.orientation` "horizontal" lays them out in
|
|
1138
|
+
* a row (default: a column).
|
|
1139
|
+
*/
|
|
1140
|
+
|
|
1141
|
+
declare function CheckboxGroupWidget({ id, value, onChange, onBlur, propertySchema, required, disabled, readonly, rawErrors, label, description, options, }: WidgetProps): React.ReactElement;
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* ChoiceWithTextWidget -- a choice and a text as one answer: "one of these, and
|
|
1145
|
+
* add detail".
|
|
1146
|
+
*
|
|
1147
|
+
* A container, selected by `x-ui-widget: "choice-with-text"` on an object of
|
|
1148
|
+
* `choice` (an enum) and `text` (a string). It only arranges the two -- the
|
|
1149
|
+
* choice beside the text, the choice unlabelled -- and renders them as any
|
|
1150
|
+
* nested object is (ObjectWidget, inline, under the question's own label):
|
|
1151
|
+
* each child by its own widget, resolved as
|
|
1152
|
+
* for any field. So the choice is a select, radio buttons or an application's
|
|
1153
|
+
* terminology picker, set on the child (`x-ui-fields.choice`), and the text a
|
|
1154
|
+
* line or a textarea.
|
|
1155
|
+
*/
|
|
1156
|
+
|
|
1157
|
+
declare function ChoiceWithTextWidget(props: WidgetProps): React.ReactElement | null;
|
|
1158
|
+
|
|
1159
|
+
/**
|
|
1160
|
+
* AbsentReasonsWidget -- the questions of a section left unanswered, and why:
|
|
1161
|
+
* one row each, the question and its reason (*unknown*, *not applicable*).
|
|
1162
|
+
*
|
|
1163
|
+
* For an object property mapping question keys to reasons, selected by
|
|
1164
|
+
* `x-ui-widget: "absent-reasons"`. The reasons are its `additionalProperties`
|
|
1165
|
+
* enum, labelled by x-ui-options.enumNames; the questions are its siblings in
|
|
1166
|
+
* the form schema it renders in -- every field but itself and static texts.
|
|
1167
|
+
*/
|
|
1168
|
+
|
|
1169
|
+
declare function AbsentReasonsWidget(props: WidgetProps): React.ReactElement;
|
|
1170
|
+
|
|
957
1171
|
/**
|
|
958
1172
|
* Widget Resolution Algorithm
|
|
959
1173
|
*
|
|
@@ -1026,6 +1240,71 @@ declare function getDefaultWidgetForType(type: string): string;
|
|
|
1026
1240
|
*/
|
|
1027
1241
|
declare const DEFAULT_WIDGETS: WidgetRegistry;
|
|
1028
1242
|
|
|
1243
|
+
/**
|
|
1244
|
+
* Custom validation registry -- named field and form validators referenced from
|
|
1245
|
+
* the schema via `x-ui-validate` and implemented here.
|
|
1246
|
+
*
|
|
1247
|
+
* See the custom-validation design in docs/design/custom-validation.md. `field`
|
|
1248
|
+
* and `form` are synchronous, invoked by `runValidators` every validation pass;
|
|
1249
|
+
* `asyncField` and `asyncForm` return a promise and are invoked only by
|
|
1250
|
+
* `useAsyncValidators`, keyed on their inputs so a remote check fires on
|
|
1251
|
+
* change, never per render.
|
|
1252
|
+
*/
|
|
1253
|
+
|
|
1254
|
+
/**
|
|
1255
|
+
* Context handed to every validator so a rule can reach beyond its immediate
|
|
1256
|
+
* value without the caller wiring it. `formData` is the ROOT form data (carried
|
|
1257
|
+
* like x-ui-rule's rootData), so a validator on a nested field can still compare
|
|
1258
|
+
* against a top-level field.
|
|
1259
|
+
*/
|
|
1260
|
+
interface ValidatorContext {
|
|
1261
|
+
/** The whole current form data (root), for cross-field checks. */
|
|
1262
|
+
formData: Record<string, unknown>;
|
|
1263
|
+
/** RFC 6901 JSON Pointer of the field being validated (field validators). */
|
|
1264
|
+
path: string;
|
|
1265
|
+
/** Per-reference config from the `x-ui-validate` object form (`{ name, args }`). */
|
|
1266
|
+
args?: Record<string, unknown>;
|
|
1267
|
+
}
|
|
1268
|
+
/**
|
|
1269
|
+
* What a SYNC validator returns. A field validator may use the `string | null`
|
|
1270
|
+
* shorthand (message attached to its own field, or null when valid); a form
|
|
1271
|
+
* validator returns `FieldError[]` because it decides which field each error
|
|
1272
|
+
* lands on (pointer "" = form-level).
|
|
1273
|
+
*/
|
|
1274
|
+
type ValidatorResult = string | null | FieldError[];
|
|
1275
|
+
/** A per-value sync validator: judges one field's value. */
|
|
1276
|
+
type FieldValidator = (value: unknown, ctx: ValidatorContext) => string | null | FieldError[];
|
|
1277
|
+
/** A whole-data sync validator: cross-field / form-level rules. */
|
|
1278
|
+
type FormValidator = (data: Record<string, unknown>, ctx: ValidatorContext) => FieldError[];
|
|
1279
|
+
/**
|
|
1280
|
+
* An async per-value validator -- returns a promise. Declared in its own
|
|
1281
|
+
* namespace (`asyncField`) so the engine knows it is async without calling it,
|
|
1282
|
+
* and invokes it only when its field value changes (never per render). A failed
|
|
1283
|
+
* promise means "could not check", not "invalid".
|
|
1284
|
+
*/
|
|
1285
|
+
type AsyncFieldValidator = (value: unknown, ctx: ValidatorContext) => Promise<string | null | FieldError[]>;
|
|
1286
|
+
/** An async whole-data validator -- returns a promise. See `dependsOn` on the
|
|
1287
|
+
* `x-ui-validate` reference to control when it re-fires. */
|
|
1288
|
+
type AsyncFormValidator = (data: Record<string, unknown>, ctx: ValidatorContext) => Promise<FieldError[]>;
|
|
1289
|
+
/**
|
|
1290
|
+
* The registry: sync and async namespaces, keeping the signatures -- and the
|
|
1291
|
+
* invocation strategy -- apart. Sync validators run on every validation pass;
|
|
1292
|
+
* async validators are invoked only when their inputs change (the engine can
|
|
1293
|
+
* tell them apart because they are declared separately, so a remote check is
|
|
1294
|
+
* never fired speculatively per render). A plain object, like the widget and
|
|
1295
|
+
* template registries -- no factory, no lifecycle.
|
|
1296
|
+
*/
|
|
1297
|
+
interface ValidatorRegistry {
|
|
1298
|
+
/** Sync per-field validators, referenced by `x-ui-validate` on a property. */
|
|
1299
|
+
field?: Record<string, FieldValidator>;
|
|
1300
|
+
/** Sync whole-data validators, referenced by `x-ui-validate` on the root. */
|
|
1301
|
+
form?: Record<string, FormValidator>;
|
|
1302
|
+
/** Async per-field validators (promise), referenced by `x-ui-validate`. */
|
|
1303
|
+
asyncField?: Record<string, AsyncFieldValidator>;
|
|
1304
|
+
/** Async whole-data validators (promise), referenced by `x-ui-validate`. */
|
|
1305
|
+
asyncForm?: Record<string, AsyncFormValidator>;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1029
1308
|
/**
|
|
1030
1309
|
* JsonSchemaFormRenderer - Generic form renderer based on JSON Schema
|
|
1031
1310
|
*
|
|
@@ -1132,6 +1411,22 @@ type JsonSchemaFormRendererProps = {
|
|
|
1132
1411
|
* a partial registry -- unspecified keys fall back to DEFAULT_TEMPLATES.
|
|
1133
1412
|
*/
|
|
1134
1413
|
templates?: TemplateRegistry;
|
|
1414
|
+
/**
|
|
1415
|
+
* Custom validator registry -- named field and form validators referenced
|
|
1416
|
+
* from the schema via `x-ui-validate`, run alongside the built-in schema
|
|
1417
|
+
* validation. `field`/`form` are synchronous; `asyncField`/`asyncForm`
|
|
1418
|
+
* return a promise and gate Save while in flight. See
|
|
1419
|
+
* docs/design/custom-validation.md.
|
|
1420
|
+
*/
|
|
1421
|
+
validators?: ValidatorRegistry;
|
|
1422
|
+
/**
|
|
1423
|
+
* Externally-supplied errors (e.g. a server 422) shown as persistent field
|
|
1424
|
+
* errors, keyed by JSON Pointer. Always displayed regardless of
|
|
1425
|
+
* `validationDisplay`, and block Save. Should be stable/memoized. A
|
|
1426
|
+
* higher-precedence error (built-in or a custom validator) on the same field
|
|
1427
|
+
* wins over an extraError. See the custom-validation design.
|
|
1428
|
+
*/
|
|
1429
|
+
extraErrors?: FieldError[];
|
|
1135
1430
|
/**
|
|
1136
1431
|
* When true, renders with `display: contents` instead of a SimpleStack.
|
|
1137
1432
|
*
|
|
@@ -1198,7 +1493,7 @@ interface FormFieldRendererProps {
|
|
|
1198
1493
|
/** Validation messages for this field, rendered inline by the widget. */
|
|
1199
1494
|
rawErrors?: string[];
|
|
1200
1495
|
}
|
|
1201
|
-
declare function FormFieldRenderer({ fieldName, property, value, onChange, onBlur, required, disabled, readOnly, schema, uiSchema, registry, globalOptions, formData, idPrefix, rawErrors, }: FormFieldRendererProps): React__default.ReactElement | null;
|
|
1496
|
+
declare function FormFieldRenderer({ fieldName, property: declared, value, onChange, onBlur, required, disabled, readOnly, schema, uiSchema, registry, globalOptions, formData, idPrefix, rawErrors, }: FormFieldRendererProps): React__default.ReactElement | null;
|
|
1202
1497
|
|
|
1203
1498
|
/**
|
|
1204
1499
|
* useFormEngine - Core form state, schema resolution, and update-mode logic
|
|
@@ -1248,6 +1543,29 @@ interface UseFormEngineOptions {
|
|
|
1248
1543
|
* synchronous -- pre-load referenced schemas into a map and pass a lookup.
|
|
1249
1544
|
*/
|
|
1250
1545
|
refResolver?: RefResolver;
|
|
1546
|
+
/**
|
|
1547
|
+
* Externally-supplied errors (e.g. a server 422), keyed by JSON Pointer.
|
|
1548
|
+
* Merged into `fieldErrors` (so they affect `isValid` and block Save) with
|
|
1549
|
+
* the lowest precedence -- a built-in error on the same field wins. The
|
|
1550
|
+
* renderer shows them regardless of `validationDisplay`; see the
|
|
1551
|
+
* custom-validation design.
|
|
1552
|
+
*/
|
|
1553
|
+
extraErrors?: FieldError[];
|
|
1554
|
+
/**
|
|
1555
|
+
* Custom validator registry. Field validators (named by `x-ui-validate` on a
|
|
1556
|
+
* property) and, at the root, form/cross-field validators (named on the root
|
|
1557
|
+
* object) run here and merge into `fieldErrors` between built-in errors and
|
|
1558
|
+
* extraErrors. The sync `field`/`form` namespaces run every pass via
|
|
1559
|
+
* `runValidators`; the async `asyncField`/`asyncForm` namespaces are invoked
|
|
1560
|
+
* by `useAsyncValidators` and gate Save (`isValidating`) while in flight.
|
|
1561
|
+
*/
|
|
1562
|
+
validators?: ValidatorRegistry;
|
|
1563
|
+
/**
|
|
1564
|
+
* Whether this engine is the ROOT form (not a nested sub-form). Root-only
|
|
1565
|
+
* concerns -- currently the whole-form/cross-field validators -- run only when
|
|
1566
|
+
* true, so a nested sub-form does not re-run them against its slice.
|
|
1567
|
+
*/
|
|
1568
|
+
isRoot?: boolean;
|
|
1251
1569
|
}
|
|
1252
1570
|
interface UseFormEngineResult {
|
|
1253
1571
|
/** The current working form data (for controlled field values) */
|
|
@@ -1263,6 +1581,8 @@ interface UseFormEngineResult {
|
|
|
1263
1581
|
orderedProperties: [string, JsonSchemaProperty][];
|
|
1264
1582
|
hasChanges: boolean;
|
|
1265
1583
|
isValid: boolean;
|
|
1584
|
+
/** True while any async validator's promise is in flight. */
|
|
1585
|
+
isValidating: boolean;
|
|
1266
1586
|
/**
|
|
1267
1587
|
* Current validation errors, each attributed to its field by JSON Pointer.
|
|
1268
1588
|
* Lets the renderer surface problems for fields that are not on screen.
|
|
@@ -1277,7 +1597,7 @@ interface UseFormEngineResult {
|
|
|
1277
1597
|
handleSave: () => void;
|
|
1278
1598
|
handleCancel: () => void;
|
|
1279
1599
|
}
|
|
1280
|
-
declare function useFormEngine({ schema, data, uiSchema, onChange, onBlur, onValidationChange, onUpdate, onCancel, readOnly, showActions, deferChanges, deferStateUpdates, allowPristineSave, refResolver, }: UseFormEngineOptions): UseFormEngineResult;
|
|
1600
|
+
declare function useFormEngine({ schema, data, uiSchema, onChange, onBlur, onValidationChange, onUpdate, onCancel, readOnly, showActions, deferChanges, deferStateUpdates, allowPristineSave, refResolver, extraErrors, validators, isRoot, }: UseFormEngineOptions): UseFormEngineResult;
|
|
1281
1601
|
|
|
1282
1602
|
/**
|
|
1283
1603
|
* useResolvedSchema - Schema resolution and property ordering
|
|
@@ -1336,6 +1656,17 @@ interface NestedFormContextValue {
|
|
|
1336
1656
|
* it unchanged.
|
|
1337
1657
|
*/
|
|
1338
1658
|
rootData: Record<string, unknown>;
|
|
1659
|
+
/**
|
|
1660
|
+
* Whether the root form's save has been attempted. A nested sub-form is a
|
|
1661
|
+
* separate form-engine instance with its own submit state, which the root's
|
|
1662
|
+
* Save never flips -- so without this a required field inside a nested object
|
|
1663
|
+
* would never reveal its error on submit (only on touch). Carried down so a
|
|
1664
|
+
* nested renderer ORs it into its own error-visibility.
|
|
1665
|
+
*
|
|
1666
|
+
* The outermost renderer sets this to its own submitAttempted; nested
|
|
1667
|
+
* renderers inherit it unchanged.
|
|
1668
|
+
*/
|
|
1669
|
+
submitAttempted: boolean;
|
|
1339
1670
|
}
|
|
1340
1671
|
|
|
1341
1672
|
/**
|
|
@@ -1434,4 +1765,5 @@ declare const DEFAULT_TEMPLATES: TemplateRegistry;
|
|
|
1434
1765
|
*/
|
|
1435
1766
|
declare function groupTemplateKey(variant: string | undefined): string;
|
|
1436
1767
|
|
|
1437
|
-
export {
|
|
1768
|
+
export { AbsentReasonsWidget, ArrayWidget, CheckboxGroupWidget, CheckboxWidget, ChoiceWithTextWidget, CodeableConceptWidget, CodedValueWidget, DEFAULT_TEMPLATES, DEFAULT_WIDGETS, DEFAULT_WIDGET_MAP, DateTimeWidget, DateWidget, DisplayWidget, EntitySelectWidget, ExtraPropertiesCard, FormActions, FormCheckbox, FormFieldRenderer, FormFieldWrapper, FormInput, FormKeyValueInput, FormMultiSelect, FormNumberInput, FormQuantityInput, FormSelect, FormTagsInput, FormTextarea, GroupErrorBadge, JsonEditorWidget, JsonSchemaFormRenderer, KeyValueWidget, NumberWidget, ObjectWidget, OneOfWidget, QuantityWidget, RadioWidget, SectionsGroupTemplate, SelectWidget, StepperGroupTemplate, TabsGroupTemplate, TagsInputWidget, TextInputWidget, TextareaWidget, TimeWidget, firstError, getAriaDescribedBy, getDefaultWidgetForType, groupTemplateKey, resolveWidget, useFormEngine, useNestedFormContext, useResolvedSchema };
|
|
1769
|
+
export type { ArrayHeaderTemplate, ArrayHeaderTemplateProps, ArrayItemTemplate, ArrayItemTemplateProps, AsyncFieldValidator, AsyncFormValidator, FieldGroup, FieldValidator, FormFieldWrapperProps, FormValidator, GroupLayoutTemplate, GroupLayoutTemplateProps, JsonSchemaFormRendererProps, NestedFormContextValue, NestedRenderer, ObjectContainerTemplate, ObjectContainerTemplateProps, QuantityValue, SelectOption, TemplateRegistry, UnitOption, UnitPosition, ValidatorContext, ValidatorRegistry, ValidatorResult, Widget, WidgetDescriptor, WidgetMap, WidgetProps, WidgetRegistry };
|