@dxos/react-ui-form 0.9.0 → 0.9.1-staging.ee54ba693a
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/dist/lib/browser/index.mjs +2337 -1919
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +2337 -1919
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/annotations.d.ts +47 -0
- package/dist/types/src/annotations.d.ts.map +1 -0
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +3 -3
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +23 -110
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +48 -101
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.theme.d.ts +252 -0
- package/dist/types/src/components/Form/Form.theme.d.ts.map +1 -0
- package/dist/types/src/components/Form/Form.theme.test.d.ts +2 -0
- package/dist/types/src/components/Form/Form.theme.test.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormControls.d.ts +75 -0
- package/dist/types/src/components/Form/FormControls.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/FormField.d.ts +44 -0
- package/dist/types/src/components/Form/FormField/FormField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/FormFieldHeader.d.ts +27 -0
- package/dist/types/src/components/Form/FormField/FormFieldHeader.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/FormRow.d.ts +85 -0
- package/dist/types/src/components/Form/FormField/FormRow.d.ts.map +1 -0
- package/dist/types/src/components/Form/{FormFieldComponent.stories.d.ts → FormField/FormRow.stories.d.ts} +6 -3
- package/dist/types/src/components/Form/FormField/FormRow.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/{fields → FormField/fields/ArrayField}/ArrayField.d.ts +2 -2
- package/dist/types/src/components/Form/FormField/fields/ArrayField/ArrayField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/ArrayField/ArrayField.stories.d.ts +88 -0
- package/dist/types/src/components/Form/FormField/fields/ArrayField/ArrayField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/ArrayField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/ArrayField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/AsyncSelectField/AsyncSelectField.d.ts +12 -0
- package/dist/types/src/components/Form/FormField/fields/AsyncSelectField/AsyncSelectField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/AsyncSelectField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/AsyncSelectField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/AutofillField/AutofillField.d.ts +12 -0
- package/dist/types/src/components/Form/FormField/fields/AutofillField/AutofillField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/AutofillField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/AutofillField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/BooleanField/BooleanField.d.ts +4 -0
- package/dist/types/src/components/Form/FormField/fields/BooleanField/BooleanField.d.ts.map +1 -0
- package/dist/types/src/components/{Settings/Settings.stories.d.ts → Form/FormField/fields/BooleanField/BooleanField.stories.d.ts} +1 -2
- package/dist/types/src/components/Form/FormField/fields/BooleanField/BooleanField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/BooleanField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/BooleanField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/ComboboxField/ComboboxField.d.ts +12 -0
- package/dist/types/src/components/Form/FormField/fields/ComboboxField/ComboboxField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/ComboboxField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/ComboboxField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/DateField/DateField.d.ts +4 -0
- package/dist/types/src/components/Form/FormField/fields/DateField/DateField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/DateField/DateField.stories.d.ts +88 -0
- package/dist/types/src/components/Form/FormField/fields/DateField/DateField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/DateField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/DateField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/GeoPointField/GeoPointField.d.ts +5 -0
- package/dist/types/src/components/Form/FormField/fields/GeoPointField/GeoPointField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/GeoPointField/GeoPointField.stories.d.ts +88 -0
- package/dist/types/src/components/Form/FormField/fields/GeoPointField/GeoPointField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/GeoPointField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/GeoPointField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/{fields → FormField/fields/MarkdownField}/MarkdownField.d.ts +2 -2
- package/dist/types/src/components/Form/FormField/fields/MarkdownField/MarkdownField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/MarkdownField/MarkdownField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/MarkdownField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/MarkdownField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.d.ts +15 -0
- package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.stories.d.ts +88 -0
- package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.test.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/NumberField/NumberField.test.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/NumberField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/NumberField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/PasswordField/PasswordField.d.ts +4 -0
- package/dist/types/src/components/Form/FormField/fields/PasswordField/PasswordField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/PasswordField/PasswordField.stories.d.ts +88 -0
- package/dist/types/src/components/Form/FormField/fields/PasswordField/PasswordField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/PasswordField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/PasswordField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/InlineRefField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/RefField.d.ts +16 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/RefField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/RefField.stories.d.ts +92 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/RefField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/RefField.test.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/index.d.ts +3 -0
- package/dist/types/src/components/Form/FormField/fields/RefField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.d.ts +29 -0
- package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.stories.d.ts +88 -0
- package/dist/types/src/components/Form/FormField/fields/SelectField/SelectField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/SelectField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/SelectField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/SelectOptionField/SelectOptionField.d.ts +5 -0
- package/dist/types/src/components/Form/FormField/fields/SelectOptionField/SelectOptionField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/SelectOptionField/SelectOptionField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/SelectOptionField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/SelectOptionField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/TextAreaField/TextAreaField.d.ts +4 -0
- package/dist/types/src/components/Form/FormField/fields/TextAreaField/TextAreaField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/TextAreaField/TextAreaField.stories.d.ts +88 -0
- package/dist/types/src/components/Form/FormField/fields/TextAreaField/TextAreaField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/TextAreaField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/TextAreaField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/TextField/TextField.d.ts +4 -0
- package/dist/types/src/components/Form/FormField/fields/TextField/TextField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/TextField/TextField.stories.d.ts +88 -0
- package/dist/types/src/components/Form/FormField/fields/TextField/TextField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/TextField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/TextField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/{fields → FormField/fields/TupleField}/TupleField.d.ts +2 -2
- package/dist/types/src/components/Form/FormField/fields/TupleField/TupleField.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/TupleField/TupleField.stories.d.ts +88 -0
- package/dist/types/src/components/Form/FormField/fields/TupleField/TupleField.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/fields/TupleField/index.d.ts +2 -0
- package/dist/types/src/components/Form/FormField/fields/TupleField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/{fields → FormField/fields}/index.d.ts +4 -1
- package/dist/types/src/components/Form/FormField/fields/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/index.d.ts +6 -0
- package/dist/types/src/components/Form/FormField/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormField/presentation.d.ts +22 -0
- package/dist/types/src/components/Form/FormField/presentation.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormFieldSet/FormFieldSet.d.ts +30 -0
- package/dist/types/src/components/Form/FormFieldSet/FormFieldSet.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormFieldSet/FormFieldSetContainer.d.ts +22 -0
- package/dist/types/src/components/Form/FormFieldSet/FormFieldSetContainer.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormFieldSet/index.d.ts +3 -0
- package/dist/types/src/components/Form/FormFieldSet/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/{Layout → FormLayout}/FormLayout.d.ts +2 -0
- package/dist/types/src/components/Form/FormLayout/FormLayout.d.ts.map +1 -0
- package/dist/types/src/components/Form/{Layout → FormLayout}/FormLayout.stories.d.ts +5 -5
- package/dist/types/src/components/Form/FormLayout/FormLayout.stories.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormLayout/FormLayout.stories.test.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormLayout/FormLayout.test.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormLayout/index.d.ts +3 -0
- package/dist/types/src/components/Form/FormLayout/index.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormLayout/parser.d.ts.map +1 -0
- package/dist/types/src/components/Form/FormLayout/parser.test.d.ts.map +1 -0
- package/dist/types/src/components/Form/index.d.ts +3 -5
- package/dist/types/src/components/Form/index.d.ts.map +1 -1
- package/dist/types/src/components/Form/meta-tags.d.ts +1 -12
- package/dist/types/src/components/Form/meta-tags.d.ts.map +1 -1
- package/dist/types/src/components/ObjectForm/ObjectForm.d.ts.map +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +6 -23
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -1
- package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts +2 -1
- package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts.map +1 -1
- package/dist/types/src/components/RefEditor/RefEditor.stories.d.ts +2 -2
- package/dist/types/src/components/RefEditor/RefEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +2 -2
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +0 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useAsyncFieldEffect.d.ts +24 -0
- package/dist/types/src/hooks/useAsyncFieldEffect.d.ts.map +1 -0
- package/dist/types/src/hooks/useFormContext.d.ts +42 -0
- package/dist/types/src/hooks/useFormContext.d.ts.map +1 -0
- package/dist/types/src/hooks/useFormHandler.d.ts +9 -6
- package/dist/types/src/hooks/useFormHandler.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/{components/testing.d.ts → testing/TestLayout.d.ts} +2 -2
- package/dist/types/src/testing/TestLayout.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +3 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/schema.d.ts +40 -0
- package/dist/types/src/testing/schema.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +161 -0
- package/dist/types/src/types.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +1 -1
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/omit.d.ts +12 -0
- package/dist/types/src/util/omit.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +43 -41
- package/src/annotations.ts +63 -0
- package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
- package/src/components/FieldEditor/FieldEditor.test.tsx +1 -1
- package/src/components/FieldEditor/FieldEditor.tsx +10 -6
- package/src/components/Form/DESIGN.md +24 -0
- package/src/components/Form/Form.stories.tsx +260 -61
- package/src/components/Form/Form.theme.test.ts +33 -0
- package/src/components/Form/Form.theme.ts +86 -0
- package/src/components/Form/Form.tsx +30 -453
- package/src/components/Form/FormControls.tsx +377 -0
- package/src/components/Form/{FormField.tsx → FormField/FormField.tsx} +98 -71
- package/src/components/Form/FormField/FormFieldHeader.tsx +68 -0
- package/src/components/Form/FormField/FormRow.stories.tsx +97 -0
- package/src/components/Form/FormField/FormRow.tsx +298 -0
- package/src/components/Form/FormField/fields/ArrayField/ArrayField.stories.tsx +119 -0
- package/src/components/Form/FormField/fields/ArrayField/ArrayField.tsx +328 -0
- package/src/components/Form/FormField/fields/ArrayField/index.ts +5 -0
- package/src/components/Form/FormField/fields/AsyncSelectField/AsyncSelectField.tsx +59 -0
- package/src/components/Form/FormField/fields/AsyncSelectField/index.ts +5 -0
- package/src/components/Form/FormField/fields/AutofillField/AutofillField.tsx +67 -0
- package/src/components/Form/FormField/fields/AutofillField/index.ts +5 -0
- package/src/components/Form/FormField/fields/BooleanField/BooleanField.stories.tsx +52 -0
- package/src/components/Form/FormField/fields/BooleanField/BooleanField.tsx +28 -0
- package/src/components/Form/FormField/fields/BooleanField/index.ts +5 -0
- package/src/components/Form/FormField/fields/ComboboxField/ComboboxField.tsx +104 -0
- package/src/components/Form/FormField/fields/ComboboxField/index.ts +5 -0
- package/src/components/Form/FormField/fields/DateField/DateField.stories.tsx +60 -0
- package/src/components/Form/{fields → FormField/fields/DateField}/DateField.tsx +12 -10
- package/src/components/Form/FormField/fields/DateField/index.ts +5 -0
- package/src/components/Form/FormField/fields/GeoPointField/GeoPointField.stories.tsx +53 -0
- package/src/components/Form/{fields → FormField/fields/GeoPointField}/GeoPointField.tsx +19 -21
- package/src/components/Form/FormField/fields/GeoPointField/index.ts +5 -0
- package/src/components/Form/{fields → FormField/fields/MarkdownField}/MarkdownField.stories.tsx +8 -8
- package/src/components/Form/{fields → FormField/fields/MarkdownField}/MarkdownField.tsx +41 -41
- package/src/components/Form/FormField/fields/MarkdownField/index.ts +5 -0
- package/src/components/Form/FormField/fields/NumberField/NumberField.stories.tsx +52 -0
- package/src/components/Form/FormField/fields/NumberField/NumberField.test.ts +29 -0
- package/src/components/Form/FormField/fields/NumberField/NumberField.tsx +140 -0
- package/src/components/Form/FormField/fields/NumberField/index.ts +5 -0
- package/src/components/Form/FormField/fields/PasswordField/PasswordField.stories.tsx +53 -0
- package/src/components/Form/FormField/fields/PasswordField/PasswordField.tsx +41 -0
- package/src/components/Form/FormField/fields/PasswordField/index.ts +5 -0
- package/src/components/Form/{fields → FormField/fields/RefField}/InlineRefField.tsx +21 -14
- package/src/components/Form/FormField/fields/RefField/RefField.stories.tsx +97 -0
- package/src/components/Form/{fields → FormField/fields/RefField}/RefField.test.ts +10 -1
- package/src/components/Form/{fields → FormField/fields/RefField}/RefField.tsx +55 -47
- package/src/components/Form/FormField/fields/RefField/index.ts +6 -0
- package/src/components/Form/FormField/fields/SelectField/SelectField.stories.tsx +53 -0
- package/src/components/Form/FormField/fields/SelectField/SelectField.tsx +136 -0
- package/src/components/Form/FormField/fields/SelectField/index.ts +5 -0
- package/src/components/Form/{fields → FormField/fields/SelectOptionField}/SelectOptionField.stories.tsx +5 -5
- package/src/components/Form/{fields → FormField/fields/SelectOptionField}/SelectOptionField.tsx +56 -54
- package/src/components/Form/FormField/fields/SelectOptionField/index.ts +5 -0
- package/src/components/Form/FormField/fields/TextAreaField/TextAreaField.stories.tsx +53 -0
- package/src/components/Form/{fields → FormField/fields/TextAreaField}/TextAreaField.tsx +6 -4
- package/src/components/Form/FormField/fields/TextAreaField/index.ts +5 -0
- package/src/components/Form/FormField/fields/TextField/TextField.stories.tsx +52 -0
- package/src/components/Form/{fields → FormField/fields/TextField}/TextField.tsx +6 -4
- package/src/components/Form/FormField/fields/TextField/index.ts +5 -0
- package/src/components/Form/FormField/fields/TupleField/TupleField.stories.tsx +55 -0
- package/src/components/Form/{fields → FormField/fields/TupleField}/TupleField.tsx +4 -2
- package/src/components/Form/FormField/fields/TupleField/index.ts +5 -0
- package/src/components/Form/{fields → FormField/fields}/index.ts +4 -1
- package/src/components/Form/FormField/index.ts +10 -0
- package/src/components/Form/FormField/presentation.tsx +32 -0
- package/src/components/Form/{FormFieldSet.tsx → FormFieldSet/FormFieldSet.tsx} +53 -90
- package/src/components/Form/FormFieldSet/FormFieldSetContainer.tsx +93 -0
- package/src/components/Form/FormFieldSet/index.ts +6 -0
- package/src/components/Form/{Layout → FormLayout}/FormLayout.stories.tsx +11 -9
- package/src/components/Form/{Layout → FormLayout}/FormLayout.tsx +29 -18
- package/src/components/Form/FormLayout/index.ts +6 -0
- package/src/components/Form/index.ts +3 -5
- package/src/components/Form/meta-tags.test.ts +1 -1
- package/src/components/Form/meta-tags.ts +1 -1
- package/src/components/ObjectForm/ObjectForm.tsx +15 -14
- package/src/components/ObjectPicker/ObjectPicker.tsx +20 -27
- package/src/components/ObjectProperties/ObjectProperties.stories.tsx +2 -2
- package/src/components/ObjectProperties/ObjectProperties.test.tsx +1 -1
- package/src/components/ObjectProperties/ObjectProperties.tsx +13 -8
- package/src/components/RefEditor/RefEditor.stories.tsx +2 -3
- package/src/components/RefEditor/RefEditor.tsx +1 -1
- package/src/components/ViewEditor/ViewEditor.stories.tsx +6 -7
- package/src/components/ViewEditor/ViewEditor.test.tsx +9 -3
- package/src/components/ViewEditor/ViewEditor.tsx +98 -128
- package/src/components/index.ts +0 -1
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useAsyncFieldEffect.ts +81 -0
- package/src/hooks/useFormContext.ts +89 -0
- package/src/hooks/useFormHandler.ts +12 -10
- package/src/index.ts +2 -0
- package/src/{components/testing.tsx → testing/TestLayout.tsx} +16 -13
- package/src/testing/index.ts +7 -0
- package/src/testing/schema.ts +59 -0
- package/src/types.ts +186 -0
- package/src/util/index.ts +1 -1
- package/src/util/omit.ts +61 -0
- package/src/util/properties.test.ts +110 -28
- package/src/util/refs.ts +1 -1
- package/src/vitest-setup.ts +40 -0
- package/dist/types/src/components/Form/FormField.d.ts +0 -52
- package/dist/types/src/components/Form/FormField.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormFieldComponent.d.ts +0 -98
- package/dist/types/src/components/Form/FormFieldComponent.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormFieldSet.d.ts +0 -26
- package/dist/types/src/components/Form/FormFieldSet.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormTooltipsContext.d.ts +0 -19
- package/dist/types/src/components/Form/FormTooltipsContext.d.ts.map +0 -1
- package/dist/types/src/components/Form/Layout/FormLayout.d.ts.map +0 -1
- package/dist/types/src/components/Form/Layout/FormLayout.stories.d.ts.map +0 -1
- package/dist/types/src/components/Form/Layout/FormLayout.stories.test.d.ts.map +0 -1
- package/dist/types/src/components/Form/Layout/FormLayout.test.d.ts.map +0 -1
- package/dist/types/src/components/Form/Layout/annotation.d.ts +0 -30
- package/dist/types/src/components/Form/Layout/annotation.d.ts.map +0 -1
- package/dist/types/src/components/Form/Layout/index.d.ts +0 -4
- package/dist/types/src/components/Form/Layout/index.d.ts.map +0 -1
- package/dist/types/src/components/Form/Layout/parser.d.ts.map +0 -1
- package/dist/types/src/components/Form/Layout/parser.test.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/ArrayField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/BooleanField.d.ts +0 -4
- package/dist/types/src/components/Form/fields/BooleanField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/DateField.d.ts +0 -4
- package/dist/types/src/components/Form/fields/DateField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/GeoPointField.d.ts +0 -5
- package/dist/types/src/components/Form/fields/GeoPointField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/InlineRefField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/MarkdownField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/NumberField.d.ts +0 -4
- package/dist/types/src/components/Form/fields/NumberField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/RefField.d.ts +0 -34
- package/dist/types/src/components/Form/fields/RefField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/RefField.test.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/SelectField.d.ts +0 -13
- package/dist/types/src/components/Form/fields/SelectField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/SelectOptionField.d.ts +0 -5
- package/dist/types/src/components/Form/fields/SelectOptionField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/TextAreaField.d.ts +0 -4
- package/dist/types/src/components/Form/fields/TextAreaField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/TextField.d.ts +0 -4
- package/dist/types/src/components/Form/fields/TextField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/TupleField.d.ts.map +0 -1
- package/dist/types/src/components/Form/fields/index.d.ts.map +0 -1
- package/dist/types/src/components/Settings/Settings.d.ts +0 -51
- package/dist/types/src/components/Settings/Settings.d.ts.map +0 -1
- package/dist/types/src/components/Settings/Settings.stories.d.ts.map +0 -1
- package/dist/types/src/components/Settings/SettingsFieldSet.d.ts +0 -43
- package/dist/types/src/components/Settings/SettingsFieldSet.d.ts.map +0 -1
- package/dist/types/src/components/Settings/SettingsItem.d.ts +0 -16
- package/dist/types/src/components/Settings/SettingsItem.d.ts.map +0 -1
- package/dist/types/src/components/Settings/SettingsSelectField.d.ts +0 -18
- package/dist/types/src/components/Settings/SettingsSelectField.d.ts.map +0 -1
- package/dist/types/src/components/Settings/index.d.ts +0 -4
- package/dist/types/src/components/Settings/index.d.ts.map +0 -1
- package/dist/types/src/components/testing.d.ts.map +0 -1
- package/dist/types/src/util/field-type.d.ts +0 -19
- package/dist/types/src/util/field-type.d.ts.map +0 -1
- package/src/components/Form/AUDIT.md +0 -17
- package/src/components/Form/FormFieldComponent.stories.tsx +0 -65
- package/src/components/Form/FormFieldComponent.tsx +0 -253
- package/src/components/Form/FormTooltipsContext.ts +0 -25
- package/src/components/Form/Layout/annotation.ts +0 -38
- package/src/components/Form/Layout/index.ts +0 -7
- package/src/components/Form/README.md +0 -3
- package/src/components/Form/fields/ArrayField.tsx +0 -173
- package/src/components/Form/fields/BooleanField.tsx +0 -22
- package/src/components/Form/fields/NumberField.tsx +0 -76
- package/src/components/Form/fields/SelectField.tsx +0 -77
- package/src/components/Settings/AUDIT.md +0 -51
- package/src/components/Settings/Settings.stories.tsx +0 -104
- package/src/components/Settings/Settings.tsx +0 -81
- package/src/components/Settings/SettingsFieldSet.tsx +0 -257
- package/src/components/Settings/SettingsItem.tsx +0 -58
- package/src/components/Settings/SettingsSelectField.tsx +0 -59
- package/src/components/Settings/index.ts +0 -7
- package/src/util/field-type.ts +0 -60
- /package/dist/types/src/components/Form/{fields → FormField/fields/MarkdownField}/MarkdownField.stories.d.ts +0 -0
- /package/dist/types/src/components/Form/{fields → FormField/fields/RefField}/InlineRefField.d.ts +0 -0
- /package/dist/types/src/components/Form/{fields → FormField/fields/RefField}/RefField.test.d.ts +0 -0
- /package/dist/types/src/components/Form/{fields → FormField/fields/SelectOptionField}/SelectOptionField.stories.d.ts +0 -0
- /package/dist/types/src/components/Form/{Layout → FormLayout}/FormLayout.stories.test.d.ts +0 -0
- /package/dist/types/src/components/Form/{Layout → FormLayout}/FormLayout.test.d.ts +0 -0
- /package/dist/types/src/components/Form/{Layout → FormLayout}/parser.d.ts +0 -0
- /package/dist/types/src/components/Form/{Layout → FormLayout}/parser.test.d.ts +0 -0
- /package/src/components/Form/{Layout → FormLayout}/FormLayout.stories.test.tsx +0 -0
- /package/src/components/Form/{Layout → FormLayout}/FormLayout.test.ts +0 -0
- /package/src/components/Form/{Layout → FormLayout}/parser.test.ts +0 -0
- /package/src/components/Form/{Layout → FormLayout}/parser.ts +0 -0
|
@@ -3,12 +3,15 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
export * from './ArrayField';
|
|
6
|
+
export * from './AsyncSelectField';
|
|
7
|
+
export * from './AutofillField';
|
|
6
8
|
export * from './BooleanField';
|
|
9
|
+
export * from './ComboboxField';
|
|
7
10
|
export * from './DateField';
|
|
8
11
|
export * from './GeoPointField';
|
|
9
|
-
export * from './InlineRefField';
|
|
10
12
|
export * from './MarkdownField';
|
|
11
13
|
export * from './NumberField';
|
|
14
|
+
export * from './PasswordField';
|
|
12
15
|
export * from './RefField';
|
|
13
16
|
export * from './SelectField';
|
|
14
17
|
export * from './SelectOptionField';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type FormPresentation } from '#types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Resolved presentation strategy for a field — which parts render, derived from {@link FormPresentation}.
|
|
9
|
+
* Visual chrome (borders, grid, spacing) is owned by the Form theme recipe, not here.
|
|
10
|
+
*/
|
|
11
|
+
export type FormFieldPresentation = {
|
|
12
|
+
layout?: FormPresentation;
|
|
13
|
+
/** Render the value as read-only plain DOM rather than an editable control. */
|
|
14
|
+
isStatic: boolean;
|
|
15
|
+
/** Render the field's label row. */
|
|
16
|
+
showLabel: boolean;
|
|
17
|
+
/** Render the inline validation/error block beneath the control. */
|
|
18
|
+
showError: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Derive the {@link FormFieldPresentation} for a layout.
|
|
23
|
+
* - `static` renders read-only plain DOM.
|
|
24
|
+
* - `inline` drops the label (the control stands alone, e.g. an array row).
|
|
25
|
+
* - `full` adds the inline error block.
|
|
26
|
+
*/
|
|
27
|
+
export const presentationFor = (layout?: FormPresentation): FormFieldPresentation => ({
|
|
28
|
+
layout,
|
|
29
|
+
isStatic: layout === 'static',
|
|
30
|
+
showLabel: layout !== 'inline',
|
|
31
|
+
showError: layout === 'full',
|
|
32
|
+
});
|
|
@@ -3,81 +3,66 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import * as Option from 'effect/Option';
|
|
6
|
-
import React, { useMemo
|
|
6
|
+
import React, { useMemo } from 'react';
|
|
7
7
|
|
|
8
|
+
import { DEFAULT_LAYOUT_NAME, FormLayoutAnnotation } from '@dxos/echo/Annotation';
|
|
8
9
|
import { type AnyProperties } from '@dxos/echo/internal';
|
|
9
10
|
import { SchemaEx } from '@dxos/effect';
|
|
10
|
-
import {
|
|
11
|
-
import { mx } from '@dxos/ui-theme';
|
|
11
|
+
import { type Merge } from '@dxos/util';
|
|
12
12
|
|
|
13
|
-
import {
|
|
13
|
+
import { type FieldContext } from '#types';
|
|
14
14
|
|
|
15
|
-
import { type FormHandlerProps } from '
|
|
16
|
-
import { getRootFormProperties } from '
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { DEFAULT_LAYOUT_NAME, FormLayout, FormLayoutAnnotation } from './Layout';
|
|
15
|
+
import { type FormHandlerProps, useFormValues } from '../../../hooks';
|
|
16
|
+
import { getRootFormProperties } from '../../../util';
|
|
17
|
+
import { FormField, FormFieldErrorBoundary, type FormFieldProps, presentationFor } from '../FormField';
|
|
18
|
+
import { FormLayout } from '../FormLayout';
|
|
19
|
+
import { FormFieldSetContainer } from './FormFieldSetContainer';
|
|
21
20
|
|
|
22
21
|
const FORM_FIELDSET_NAME = 'Form.FieldSet';
|
|
23
22
|
|
|
24
|
-
export type FormFieldSetProps<T extends AnyProperties> =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
| 'fieldMap'
|
|
48
|
-
| 'fieldProvider'
|
|
49
|
-
| 'createTypename'
|
|
50
|
-
| 'createOptionLabel'
|
|
51
|
-
| 'createOptionIcon'
|
|
52
|
-
| 'createInitialValuePath'
|
|
53
|
-
| 'createFieldMap'
|
|
54
|
-
| 'db'
|
|
55
|
-
| 'useType'
|
|
56
|
-
| 'getOptions'
|
|
57
|
-
| 'onCreate'
|
|
58
|
-
>;
|
|
23
|
+
export type FormFieldSetProps<T extends AnyProperties> = Merge<
|
|
24
|
+
{
|
|
25
|
+
/** Applied to the field set's container (the bordered box when collapsible). */
|
|
26
|
+
classNames?: string;
|
|
27
|
+
label?: string;
|
|
28
|
+
sort?: string[];
|
|
29
|
+
/**
|
|
30
|
+
* When set, renders a toggle button at the end of the label row that
|
|
31
|
+
* shows/hides the field set body. Used for nested objects.
|
|
32
|
+
*/
|
|
33
|
+
collapsible?: boolean;
|
|
34
|
+
filter?: (props: SchemaEx.SchemaProperty[]) => SchemaEx.SchemaProperty[];
|
|
35
|
+
/**
|
|
36
|
+
* Picks a named layout out of `FormLayoutAnnotation` when present.
|
|
37
|
+
* Falls back to `'default'`. Ignored when the schema has no annotation
|
|
38
|
+
* (linear rendering then takes over).
|
|
39
|
+
*/
|
|
40
|
+
layoutName?: string;
|
|
41
|
+
},
|
|
42
|
+
Pick<FormHandlerProps<T>, 'schema'>,
|
|
43
|
+
Pick<FormFieldProps, 'path' | 'autoFocus'>,
|
|
44
|
+
FieldContext
|
|
45
|
+
>;
|
|
59
46
|
|
|
60
47
|
/**
|
|
61
48
|
* Renders a set of form fields derived from a schema object.
|
|
62
49
|
*/
|
|
63
50
|
export const FormFieldSet = ({
|
|
51
|
+
classNames,
|
|
64
52
|
label,
|
|
65
53
|
schema,
|
|
66
54
|
readonly,
|
|
67
55
|
path,
|
|
68
56
|
sort,
|
|
69
57
|
collapsible,
|
|
70
|
-
|
|
58
|
+
filter,
|
|
71
59
|
projection,
|
|
72
60
|
layout,
|
|
73
61
|
layoutName = DEFAULT_LAYOUT_NAME,
|
|
74
62
|
...props
|
|
75
63
|
}: FormFieldSetProps<any>) => {
|
|
76
|
-
const { t } = useTranslation(translationKey);
|
|
77
64
|
const values = useFormValues(FORM_FIELDSET_NAME, path);
|
|
78
|
-
const properties = useFormFieldSetProperties({ schema, values,
|
|
79
|
-
// TODO(burdon): Generalize collapse state (cf. useSelected in react-ui-attention, plugin-markdown cursor state).
|
|
80
|
-
const [collapsed, setCollapsed] = useState(false);
|
|
65
|
+
const properties = useFormFieldSetProperties({ schema, values, filter, sort, projection });
|
|
81
66
|
if ((readonly || layout === 'static') && values == null) {
|
|
82
67
|
return null;
|
|
83
68
|
}
|
|
@@ -105,6 +90,7 @@ export const FormFieldSet = ({
|
|
|
105
90
|
type={property.type}
|
|
106
91
|
name={name}
|
|
107
92
|
path={[...(path ?? []), name]}
|
|
93
|
+
required={!property.isOptional}
|
|
108
94
|
readonly={readonly}
|
|
109
95
|
layout={layout}
|
|
110
96
|
projection={projection}
|
|
@@ -115,56 +101,33 @@ export const FormFieldSet = ({
|
|
|
115
101
|
})
|
|
116
102
|
);
|
|
117
103
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
{
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
<IconButton
|
|
130
|
-
classNames='px-1 mr-0.5'
|
|
131
|
-
variant='ghost'
|
|
132
|
-
density='xs'
|
|
133
|
-
iconOnly
|
|
134
|
-
icon='ph--caret-right--regular'
|
|
135
|
-
iconClassNames={mx('transition-transform', !collapsed && 'rotate-90')}
|
|
136
|
-
label={t(collapsed ? 'expand-fields.label' : 'collapse-fields.label')}
|
|
137
|
-
/>
|
|
138
|
-
)
|
|
139
|
-
}
|
|
140
|
-
onClick={() => setCollapsed((value) => !value)}
|
|
141
|
-
/>
|
|
142
|
-
)}
|
|
143
|
-
{showBody && (collapsible ? <div className='px-2 pb-2'>{body}</div> : body)}
|
|
144
|
-
</>
|
|
104
|
+
return (
|
|
105
|
+
<FormFieldSetContainer
|
|
106
|
+
classNames={classNames}
|
|
107
|
+
label={label}
|
|
108
|
+
path={SchemaEx.createJsonPath(path ?? [])}
|
|
109
|
+
readonly={readonly}
|
|
110
|
+
presentation={presentationFor(layout)}
|
|
111
|
+
collapsible={collapsible}
|
|
112
|
+
>
|
|
113
|
+
{body}
|
|
114
|
+
</FormFieldSetContainer>
|
|
145
115
|
);
|
|
146
|
-
|
|
147
|
-
// Nested field sets render inside an indented, bordered container with a collapse toggle.
|
|
148
|
-
if (collapsible) {
|
|
149
|
-
return <div className='border border-subdued-separator rounded-sm mt-2'>{content}</div>;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return content;
|
|
153
116
|
};
|
|
154
117
|
|
|
155
118
|
FormFieldSet.displayName = FORM_FIELDSET_NAME;
|
|
156
119
|
|
|
157
|
-
type UseFormFieldSetPropertiesParams = Pick<FormFieldSetProps<any>, 'schema' | '
|
|
120
|
+
type UseFormFieldSetPropertiesParams = Pick<FormFieldSetProps<any>, 'schema' | 'filter' | 'projection' | 'sort'> & {
|
|
158
121
|
values: AnyProperties | undefined;
|
|
159
122
|
sort?: string[];
|
|
160
123
|
};
|
|
161
124
|
|
|
162
125
|
/**
|
|
163
|
-
* Resolves ordered schema properties for a field set (projection order,
|
|
126
|
+
* Resolves ordered schema properties for a field set (projection order, filter, or sort).
|
|
164
127
|
*/
|
|
165
128
|
const useFormFieldSetProperties = ({
|
|
166
129
|
schema,
|
|
167
|
-
|
|
130
|
+
filter,
|
|
168
131
|
projection,
|
|
169
132
|
values,
|
|
170
133
|
sort,
|
|
@@ -176,9 +139,9 @@ const useFormFieldSetProperties = ({
|
|
|
176
139
|
return [];
|
|
177
140
|
}
|
|
178
141
|
|
|
179
|
-
// TODO(wittjosiah): Reconcile FormInputAnnotation with projection hidden properties &
|
|
142
|
+
// TODO(wittjosiah): Reconcile FormInputAnnotation with projection hidden properties & filter function.
|
|
180
143
|
const schemaProps = getRootFormProperties(schema.ast, values);
|
|
181
|
-
const filteredProps =
|
|
144
|
+
const filteredProps = filter ? filter(schemaProps) : schemaProps;
|
|
182
145
|
|
|
183
146
|
// Use projection-based field management when view and projection are available.
|
|
184
147
|
if (projection) {
|
|
@@ -209,5 +172,5 @@ const useFormFieldSetProperties = ({
|
|
|
209
172
|
return sort
|
|
210
173
|
? [...filteredProps].sort(({ name: a }, { name: b }) => sort.indexOf(a.toString()) - sort.indexOf(b.toString()))
|
|
211
174
|
: filteredProps;
|
|
212
|
-
}, [schema, values,
|
|
175
|
+
}, [schema, values, filter, sort, projection]);
|
|
213
176
|
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { type PropsWithChildren, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { type ThemedClassName, ToggleIconButton, useTranslation } from '@dxos/react-ui';
|
|
8
|
+
import { mx } from '@dxos/ui-theme';
|
|
9
|
+
|
|
10
|
+
import { translationKey } from '#translations';
|
|
11
|
+
|
|
12
|
+
import { formTheme } from '../Form.theme';
|
|
13
|
+
import { FormFieldHeader } from '../FormField/FormFieldHeader';
|
|
14
|
+
import { type FormFieldPresentation } from '../FormField/presentation';
|
|
15
|
+
|
|
16
|
+
const styles = formTheme.styles();
|
|
17
|
+
|
|
18
|
+
export type FormFieldSetContainerProps = ThemedClassName<
|
|
19
|
+
PropsWithChildren<{
|
|
20
|
+
label?: string;
|
|
21
|
+
/** JSON path of the group, forwarded to the label as field metadata. */
|
|
22
|
+
path?: string;
|
|
23
|
+
readonly?: boolean;
|
|
24
|
+
presentation: FormFieldPresentation;
|
|
25
|
+
/**
|
|
26
|
+
* Render a collapse toggle in the header and wrap the body in an indented, bordered box.
|
|
27
|
+
* Used for nested objects (struct fields, object-array items, inline refs).
|
|
28
|
+
*/
|
|
29
|
+
collapsible?: boolean;
|
|
30
|
+
}>
|
|
31
|
+
>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Shared chrome for a labelled group of sub-fields: an optional header (label + collapse toggle) and,
|
|
35
|
+
* when collapsible, an indented bordered container around the body. Nested structs, object-array items,
|
|
36
|
+
* and inline refs all reach this via `FormFieldSet`, so their visual containment is identical.
|
|
37
|
+
*/
|
|
38
|
+
export const FormFieldSetContainer = ({
|
|
39
|
+
classNames,
|
|
40
|
+
label,
|
|
41
|
+
path,
|
|
42
|
+
readonly,
|
|
43
|
+
presentation,
|
|
44
|
+
collapsible,
|
|
45
|
+
children,
|
|
46
|
+
}: FormFieldSetContainerProps) => {
|
|
47
|
+
const { t } = useTranslation(translationKey);
|
|
48
|
+
// TODO(burdon): Generalize collapse state (cf. useSelection in react-ui-attention, plugin-markdown cursor state).
|
|
49
|
+
const [collapsed, setCollapsed] = useState(false);
|
|
50
|
+
const showBody = !(collapsible && collapsed);
|
|
51
|
+
|
|
52
|
+
const content = (
|
|
53
|
+
<>
|
|
54
|
+
{presentation.showLabel && label && (
|
|
55
|
+
<FormFieldHeader
|
|
56
|
+
label={label}
|
|
57
|
+
path={path}
|
|
58
|
+
readonly={readonly}
|
|
59
|
+
classNames='pl-2'
|
|
60
|
+
actions={
|
|
61
|
+
collapsible ? (
|
|
62
|
+
<ToggleIconButton
|
|
63
|
+
active={!collapsed}
|
|
64
|
+
classNames='px-1 mr-0.5'
|
|
65
|
+
variant='ghost'
|
|
66
|
+
density='xs'
|
|
67
|
+
iconOnly
|
|
68
|
+
icon='ph--caret-right--regular'
|
|
69
|
+
label={t(collapsed ? 'expand-fields.label' : 'collapse-fields.label')}
|
|
70
|
+
/>
|
|
71
|
+
) : undefined
|
|
72
|
+
}
|
|
73
|
+
onClick={collapsible ? () => setCollapsed((value) => !value) : undefined}
|
|
74
|
+
/>
|
|
75
|
+
)}
|
|
76
|
+
{showBody && (collapsible ? <div className={styles.fieldSetBody()}>{children}</div> : children)}
|
|
77
|
+
</>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
// Nested groups render inside an indented, bordered container with a collapse toggle. A non-collapsible
|
|
81
|
+
// group only materializes a wrapper when `classNames` is supplied — otherwise the body flows straight
|
|
82
|
+
// into the parent grid (the default, grid-transparent behavior).
|
|
83
|
+
if (collapsible) {
|
|
84
|
+
return (
|
|
85
|
+
<div className={styles.fieldSetBoxOuter()}>
|
|
86
|
+
<div className={styles.fieldSetBox({ class: mx(classNames) })}>{content}</div>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Only materialize a wrapper when `classNames` is supplied; otherwise stay grid-transparent.
|
|
92
|
+
return classNames ? <div className={mx(classNames)}>{content}</div> : <>{content}</>;
|
|
93
|
+
};
|
|
@@ -19,9 +19,9 @@ import { trim } from '@dxos/util';
|
|
|
19
19
|
|
|
20
20
|
import { translations } from '#translations';
|
|
21
21
|
|
|
22
|
-
import { TestLayout, TestPanel } from '
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
22
|
+
import { TestLayout, TestPanel } from '../../../testing';
|
|
23
|
+
import { omitId } from '../../../util';
|
|
24
|
+
import { Form, type FormRootProps } from '../Form';
|
|
25
25
|
import { parseLayout } from './parser';
|
|
26
26
|
|
|
27
27
|
/**
|
|
@@ -84,7 +84,7 @@ const FLIGHT_LAYOUT_COMPACT = trim`
|
|
|
84
84
|
*/
|
|
85
85
|
const AnnotatedFlight = Type.getSchema(Flight)
|
|
86
86
|
.annotations({})
|
|
87
|
-
.pipe(FormLayoutAnnotation.set({ default: FLIGHT_LAYOUT, compact: FLIGHT_LAYOUT_COMPACT }));
|
|
87
|
+
.pipe(Annotation.FormLayoutAnnotation.set({ default: FLIGHT_LAYOUT, compact: FLIGHT_LAYOUT_COMPACT }));
|
|
88
88
|
|
|
89
89
|
/**
|
|
90
90
|
* Sample schema with nested `Place` structs carrying a `LabelAnnotation`.
|
|
@@ -125,12 +125,12 @@ const JOURNEY_LAYOUT = trim`
|
|
|
125
125
|
</grid>
|
|
126
126
|
`;
|
|
127
127
|
|
|
128
|
-
type
|
|
128
|
+
type StoryArgs = {
|
|
129
129
|
schema: Schema.Schema<any>;
|
|
130
130
|
template?: string;
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
-
const DefaultStory = ({ schema, template }:
|
|
133
|
+
const DefaultStory = ({ schema, template }: StoryArgs) => {
|
|
134
134
|
const [values, setValues] = useState<Partial<FlightValues>>(flight);
|
|
135
135
|
|
|
136
136
|
const handleSave = useCallback<NonNullable<FormRootProps<any>['onSave']>>((next) => {
|
|
@@ -164,11 +164,11 @@ const meta = {
|
|
|
164
164
|
layout: 'fullscreen',
|
|
165
165
|
translations,
|
|
166
166
|
},
|
|
167
|
-
} satisfies Meta<
|
|
167
|
+
} satisfies Meta<StoryArgs>;
|
|
168
168
|
|
|
169
169
|
export default meta;
|
|
170
170
|
|
|
171
|
-
type Story = StoryObj<
|
|
171
|
+
type Story = StoryObj<StoryArgs>;
|
|
172
172
|
|
|
173
173
|
/** Baseline: no annotation, no override — `Form.FieldSet` renders linearly (one field per row). */
|
|
174
174
|
export const Linear: Story = {
|
|
@@ -383,7 +383,9 @@ const PlaygroundStory = ({ card = false }: PlaygroundStoryProps) => {
|
|
|
383
383
|
onChange={setTemplate}
|
|
384
384
|
/>
|
|
385
385
|
</Editor.Root>
|
|
386
|
-
{error &&
|
|
386
|
+
{error && (
|
|
387
|
+
<div className='border-t border-input-separator p-2 text-sm text-error-text font-mono'>{error}</div>
|
|
388
|
+
)}
|
|
387
389
|
</div>
|
|
388
390
|
</TestPanel>
|
|
389
391
|
<TestPanel>
|
|
@@ -13,11 +13,12 @@ import { type AnyProperties } from '@dxos/echo/internal';
|
|
|
13
13
|
import { SchemaEx } from '@dxos/effect';
|
|
14
14
|
import { Input } from '@dxos/react-ui';
|
|
15
15
|
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
16
|
+
import { type FormPresentation } from '#types';
|
|
17
|
+
|
|
18
|
+
import { useFormContext, useFormFieldState } from '../../../hooks';
|
|
19
|
+
import { formTheme } from '../Form.theme';
|
|
20
|
+
import { FormField, FormFieldErrorBoundary, FormFieldLabel, type FormFieldProps, presentationFor } from '../FormField';
|
|
21
|
+
import { type LayoutNode, LayoutParseError, parseLayout } from './parser';
|
|
21
22
|
|
|
22
23
|
const FORM_LAYOUT_NAME = 'Form.Layout';
|
|
23
24
|
|
|
@@ -57,14 +58,14 @@ type FormFieldSetSubset = Pick<
|
|
|
57
58
|
export const FormLayout = ({
|
|
58
59
|
schema,
|
|
59
60
|
template,
|
|
60
|
-
name = DEFAULT_LAYOUT_NAME,
|
|
61
|
+
name = Annotation.DEFAULT_LAYOUT_NAME,
|
|
61
62
|
path,
|
|
62
63
|
readonly,
|
|
63
64
|
layout,
|
|
64
65
|
projection,
|
|
65
66
|
...props
|
|
66
67
|
}: FormLayoutProps) => {
|
|
67
|
-
const annotated = Option.getOrUndefined(FormLayoutAnnotation.get(schema));
|
|
68
|
+
const annotated = Option.getOrUndefined(Annotation.FormLayoutAnnotation.get(schema));
|
|
68
69
|
const source = template ?? annotated?.[name];
|
|
69
70
|
if (source === undefined) {
|
|
70
71
|
throw new LayoutParseError(
|
|
@@ -114,7 +115,7 @@ const RenderNode = ({ node, schema, basePath, ...props }: RenderNodeProps) => {
|
|
|
114
115
|
throw new LayoutParseError(`field "${node.name}" not found on schema`);
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
const { type, segments, leafName, title, labelType } = resolved;
|
|
118
|
+
const { type, segments, leafName, title, labelType, required } = resolved;
|
|
118
119
|
const path = [...basePath, ...segments];
|
|
119
120
|
const span = node.span ? { gridColumn: `span ${node.span} / span ${node.span}` } : undefined;
|
|
120
121
|
|
|
@@ -129,7 +130,7 @@ const RenderNode = ({ node, schema, basePath, ...props }: RenderNodeProps) => {
|
|
|
129
130
|
layout={props.layout}
|
|
130
131
|
/>
|
|
131
132
|
) : (
|
|
132
|
-
<FormField type={type} name={leafName} path={path} {...props} />
|
|
133
|
+
<FormField type={type} name={leafName} path={path} required={required} {...props} />
|
|
133
134
|
)}
|
|
134
135
|
</FormFieldErrorBoundary>
|
|
135
136
|
</div>
|
|
@@ -151,6 +152,8 @@ export type ResolvedLayoutField = {
|
|
|
151
152
|
* sub-fields. Undefined for ordinary (non-auto-labelled) fields.
|
|
152
153
|
*/
|
|
153
154
|
labelType?: SchemaAST.AST;
|
|
155
|
+
/** Whether the resolved property is required (non-optional). */
|
|
156
|
+
required: boolean;
|
|
154
157
|
};
|
|
155
158
|
|
|
156
159
|
/**
|
|
@@ -215,6 +218,7 @@ export const resolveLayoutField = (schema: Schema.Schema<any>, name: string): Re
|
|
|
215
218
|
leafName: segments[segments.length - 1],
|
|
216
219
|
title,
|
|
217
220
|
labelType: labelled ? labelType : undefined,
|
|
221
|
+
required: !prop.isOptional,
|
|
218
222
|
};
|
|
219
223
|
};
|
|
220
224
|
|
|
@@ -222,7 +226,7 @@ type LabelFieldProps = {
|
|
|
222
226
|
schema: Schema.Schema<any>;
|
|
223
227
|
label: string;
|
|
224
228
|
path: (string | number)[];
|
|
225
|
-
layout?:
|
|
229
|
+
layout?: FormPresentation;
|
|
226
230
|
};
|
|
227
231
|
|
|
228
232
|
/**
|
|
@@ -231,6 +235,8 @@ type LabelFieldProps = {
|
|
|
231
235
|
* presentation of regular fields.
|
|
232
236
|
*/
|
|
233
237
|
const LabelField = ({ schema, label, path, layout }: LabelFieldProps) => {
|
|
238
|
+
const { variant = 'default' } = useFormContext(FORM_LAYOUT_NAME);
|
|
239
|
+
const styles = formTheme.styles({ variant });
|
|
234
240
|
const { getValue } = useFormFieldState(FORM_LAYOUT_NAME, path);
|
|
235
241
|
const value = getValue();
|
|
236
242
|
const text = value == null ? undefined : Annotation.getLabelWithSchema(schema, value);
|
|
@@ -238,14 +244,19 @@ const LabelField = ({ schema, label, path, layout }: LabelFieldProps) => {
|
|
|
238
244
|
return null;
|
|
239
245
|
}
|
|
240
246
|
|
|
247
|
+
const presentation = presentationFor(layout);
|
|
241
248
|
return (
|
|
242
|
-
<
|
|
243
|
-
<
|
|
244
|
-
{
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
249
|
+
<Input.Root>
|
|
250
|
+
<div className={styles.field()}>
|
|
251
|
+
{presentation.showLabel && (
|
|
252
|
+
<FormFieldLabel variant={variant} readonly label={label} path={SchemaEx.createJsonPath(path)} />
|
|
253
|
+
)}
|
|
254
|
+
<div className={styles.fieldControl()}>
|
|
255
|
+
<p className='truncate min-w-0' title={text}>
|
|
256
|
+
{text}
|
|
257
|
+
</p>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
</Input.Root>
|
|
250
261
|
);
|
|
251
262
|
};
|
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './meta-tags';
|
|
6
6
|
|
|
7
7
|
export * from './Form';
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
10
|
-
export * from './meta-tags';
|
|
11
|
-
export * from './Layout';
|
|
8
|
+
export * from './FormField';
|
|
9
|
+
export * from './FormFieldSet';
|
|
@@ -11,7 +11,7 @@ import { Obj, Ref, Tag } from '@dxos/echo';
|
|
|
11
11
|
import { META_TAGS_KEY, withMetaTags } from './meta-tags';
|
|
12
12
|
|
|
13
13
|
// A feed-host schema whose own `tags` field is a `TagIndex` record (tagId -> objectId[]), not an
|
|
14
|
-
// array — mirrors plugin-commerce `Search`, plugin-inbox `Mailbox`, plugin-
|
|
14
|
+
// array — mirrors plugin-commerce `Search`, plugin-inbox `Mailbox`, plugin-magazine `Subscription`.
|
|
15
15
|
const TagIndexHost = Schema.Struct({
|
|
16
16
|
name: Schema.String.pipe(Schema.optional),
|
|
17
17
|
tags: Schema.Record({ key: Schema.String, value: Schema.Array(Obj.ID) }).pipe(Schema.optional),
|
|
@@ -10,27 +10,15 @@ import { invariant } from '@dxos/invariant';
|
|
|
10
10
|
import { HuePicker } from '@dxos/react-ui-pickers';
|
|
11
11
|
|
|
12
12
|
import { translationKey } from '#translations';
|
|
13
|
+
import { type FormFieldMap } from '#types';
|
|
13
14
|
|
|
14
|
-
import { Form,
|
|
15
|
+
import { Form, META_TAGS_KEY, withMetaTags } from '../Form';
|
|
15
16
|
|
|
16
17
|
export type ObjectFormProps = {
|
|
17
18
|
type: Type.AnyEntity;
|
|
18
19
|
object: Obj.Unknown;
|
|
19
20
|
};
|
|
20
21
|
|
|
21
|
-
const createFieldMap: FormFieldMap = {
|
|
22
|
-
hue: ({ type, label, layout, getValue, onValueChange }) => {
|
|
23
|
-
const handleChange = useCallback((nextHue: string) => onValueChange(type, nextHue), [onValueChange, type]);
|
|
24
|
-
const handleReset = useCallback(() => onValueChange(type, undefined), [onValueChange, type]);
|
|
25
|
-
return (
|
|
26
|
-
<>
|
|
27
|
-
{layout !== 'inline' && <Form.Label label={label} />}
|
|
28
|
-
<HuePicker value={getValue()} onChange={handleChange} onReset={handleReset} />
|
|
29
|
-
</>
|
|
30
|
-
);
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
|
|
34
22
|
export const ObjectForm = ({ object, type }: ObjectFormProps) => {
|
|
35
23
|
const db = Obj.getDatabase(object);
|
|
36
24
|
const meta = Obj.getMeta(object);
|
|
@@ -109,3 +97,16 @@ export const ObjectForm = ({ object, type }: ObjectFormProps) => {
|
|
|
109
97
|
</Form.Root>
|
|
110
98
|
);
|
|
111
99
|
};
|
|
100
|
+
|
|
101
|
+
const createFieldMap: FormFieldMap = {
|
|
102
|
+
hue: ({ type, label, presentation, getValue, onValueChange }) => {
|
|
103
|
+
const handleChange = useCallback((nextHue: string) => onValueChange(type, nextHue), [onValueChange, type]);
|
|
104
|
+
const handleReset = useCallback(() => onValueChange(type, undefined), [onValueChange, type]);
|
|
105
|
+
return (
|
|
106
|
+
<>
|
|
107
|
+
{presentation !== 'inline' && <Form.Label label={label} />}
|
|
108
|
+
<HuePicker value={getValue()} onChange={handleChange} onReset={handleReset} />
|
|
109
|
+
</>
|
|
110
|
+
);
|
|
111
|
+
},
|
|
112
|
+
};
|