@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
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
7
|
+
import React, { useState } from 'react';
|
|
8
|
+
|
|
9
|
+
import { Format } from '@dxos/echo';
|
|
10
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
|
+
|
|
12
|
+
import { translations } from '#translations';
|
|
13
|
+
|
|
14
|
+
import { TestLayout } from '../../../../../testing';
|
|
15
|
+
import { Form } from '../../../Form';
|
|
16
|
+
|
|
17
|
+
// DateField covers all three temporal formats; show each.
|
|
18
|
+
const schema = Schema.Struct({
|
|
19
|
+
date: Format.DateOnly.annotations({ title: 'Date' }),
|
|
20
|
+
time: Format.TimeOnly.annotations({ title: 'Time' }),
|
|
21
|
+
dateTime: Format.DateTime.annotations({ title: 'Date & time' }),
|
|
22
|
+
}).pipe(Schema.mutable);
|
|
23
|
+
|
|
24
|
+
type Values = Schema.Schema.Type<typeof schema>;
|
|
25
|
+
|
|
26
|
+
const DefaultStory = () => {
|
|
27
|
+
const [values, setValues] = useState<Values>({
|
|
28
|
+
date: '1990-05-12',
|
|
29
|
+
time: '09:00:00',
|
|
30
|
+
dateTime: '2026-06-01T15:30:00.000Z',
|
|
31
|
+
});
|
|
32
|
+
return (
|
|
33
|
+
<TestLayout json={values}>
|
|
34
|
+
<Form.Root
|
|
35
|
+
schema={schema}
|
|
36
|
+
values={values}
|
|
37
|
+
onValuesChanged={(values) => setValues((prev) => ({ ...prev, ...values }))}
|
|
38
|
+
>
|
|
39
|
+
<Form.Viewport>
|
|
40
|
+
<Form.Content>
|
|
41
|
+
<Form.FieldSet />
|
|
42
|
+
</Form.Content>
|
|
43
|
+
</Form.Viewport>
|
|
44
|
+
</Form.Root>
|
|
45
|
+
</TestLayout>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const meta = {
|
|
50
|
+
title: 'ui/react-ui-form/FormField/DateField',
|
|
51
|
+
render: DefaultStory,
|
|
52
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
53
|
+
parameters: { layout: 'fullscreen', translations },
|
|
54
|
+
} satisfies Meta<typeof DefaultStory>;
|
|
55
|
+
|
|
56
|
+
export default meta;
|
|
57
|
+
|
|
58
|
+
type Story = StoryObj<typeof meta>;
|
|
59
|
+
|
|
60
|
+
export const Default: Story = {};
|
|
@@ -8,7 +8,9 @@ import React, { useCallback } from 'react';
|
|
|
8
8
|
import { Format } from '@dxos/echo';
|
|
9
9
|
import { Input } from '@dxos/react-ui';
|
|
10
10
|
|
|
11
|
-
import { type
|
|
11
|
+
import { type FormFieldRendererProps } from '#types';
|
|
12
|
+
|
|
13
|
+
import { FormRow } from '../../FormRow';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Stored value shapes:
|
|
@@ -52,7 +54,7 @@ export const DateField = ({
|
|
|
52
54
|
onValueChange,
|
|
53
55
|
onBlur: _onBlur,
|
|
54
56
|
...props
|
|
55
|
-
}:
|
|
57
|
+
}: FormFieldRendererProps<string>) => {
|
|
56
58
|
const handleSimpleChange = useCallback((next: string) => onValueChange(type, next), [type, onValueChange]);
|
|
57
59
|
|
|
58
60
|
const handleDateTimeChange = useCallback(
|
|
@@ -64,19 +66,19 @@ export const DateField = ({
|
|
|
64
66
|
);
|
|
65
67
|
|
|
66
68
|
return (
|
|
67
|
-
<
|
|
69
|
+
<FormRow<string> {...props} readonly={readonly} format={format}>
|
|
68
70
|
{({ value }) => {
|
|
69
71
|
switch (format) {
|
|
70
72
|
case Format.TypeFormat.Date:
|
|
71
73
|
return (
|
|
72
|
-
<div className='grid grid-cols-[minmax(0,1fr)_min-content] items-stretch
|
|
74
|
+
<div className='grid grid-cols-[minmax(0,1fr)_min-content] gap-1 items-stretch'>
|
|
73
75
|
<Input.Date
|
|
74
76
|
classNames='min-w-0 overflow-hidden'
|
|
75
|
-
disabled={
|
|
77
|
+
disabled={readonly}
|
|
76
78
|
value={value ?? ''}
|
|
77
79
|
onValueChange={handleSimpleChange}
|
|
78
80
|
/>
|
|
79
|
-
<Input.TriggerIcon
|
|
81
|
+
<Input.TriggerIcon />
|
|
80
82
|
</div>
|
|
81
83
|
);
|
|
82
84
|
case Format.TypeFormat.Time:
|
|
@@ -84,18 +86,18 @@ export const DateField = ({
|
|
|
84
86
|
case Format.TypeFormat.DateTime:
|
|
85
87
|
default:
|
|
86
88
|
return (
|
|
87
|
-
<div className='grid grid-cols-[minmax(0,1fr)_min-content] items-stretch
|
|
89
|
+
<div className='grid grid-cols-[minmax(0,1fr)_min-content] gap-1 items-stretch'>
|
|
88
90
|
<Input.DateTime
|
|
89
91
|
classNames='min-w-0 overflow-hidden'
|
|
90
|
-
disabled={
|
|
92
|
+
disabled={readonly}
|
|
91
93
|
value={isoToLocalDateTime(value)}
|
|
92
94
|
onValueChange={handleDateTimeChange}
|
|
93
95
|
/>
|
|
94
|
-
<Input.TriggerIcon
|
|
96
|
+
<Input.TriggerIcon />
|
|
95
97
|
</div>
|
|
96
98
|
);
|
|
97
99
|
}
|
|
98
100
|
}}
|
|
99
|
-
</
|
|
101
|
+
</FormRow>
|
|
100
102
|
);
|
|
101
103
|
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
7
|
+
import React, { useState } from 'react';
|
|
8
|
+
|
|
9
|
+
import { Format } from '@dxos/echo';
|
|
10
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
|
+
|
|
12
|
+
import { translations } from '#translations';
|
|
13
|
+
|
|
14
|
+
import { TestLayout } from '../../../../../testing';
|
|
15
|
+
import { Form } from '../../../Form';
|
|
16
|
+
|
|
17
|
+
const schema = Schema.Struct({
|
|
18
|
+
location: Format.GeoPoint.annotations({ title: 'Location' }),
|
|
19
|
+
}).pipe(Schema.mutable);
|
|
20
|
+
|
|
21
|
+
type Values = Schema.Schema.Type<typeof schema>;
|
|
22
|
+
|
|
23
|
+
const DefaultStory = () => {
|
|
24
|
+
const [values, setValues] = useState<Values>({ location: [-74.006, 40.7128] });
|
|
25
|
+
return (
|
|
26
|
+
<TestLayout json={values}>
|
|
27
|
+
<Form.Root
|
|
28
|
+
schema={schema}
|
|
29
|
+
values={values}
|
|
30
|
+
onValuesChanged={(values) => setValues((prev) => ({ ...prev, ...values }))}
|
|
31
|
+
>
|
|
32
|
+
<Form.Viewport>
|
|
33
|
+
<Form.Content>
|
|
34
|
+
<Form.FieldSet />
|
|
35
|
+
</Form.Content>
|
|
36
|
+
</Form.Viewport>
|
|
37
|
+
</Form.Root>
|
|
38
|
+
</TestLayout>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const meta = {
|
|
43
|
+
title: 'ui/react-ui-form/FormField/GeoPointField',
|
|
44
|
+
render: DefaultStory,
|
|
45
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
46
|
+
parameters: { layout: 'fullscreen', translations },
|
|
47
|
+
} satisfies Meta<typeof DefaultStory>;
|
|
48
|
+
|
|
49
|
+
export default meta;
|
|
50
|
+
|
|
51
|
+
type Story = StoryObj<typeof meta>;
|
|
52
|
+
|
|
53
|
+
export const Default: Story = {};
|
|
@@ -9,22 +9,19 @@ import { Input, useTranslation } from '@dxos/react-ui';
|
|
|
9
9
|
import { safeParseFloat } from '@dxos/util';
|
|
10
10
|
|
|
11
11
|
import { translationKey } from '#translations';
|
|
12
|
+
import { type FormFieldRendererProps } from '#types';
|
|
12
13
|
|
|
13
|
-
import {
|
|
14
|
+
import { FormRow } from '../../FormRow';
|
|
14
15
|
|
|
15
16
|
export const GeoPointField = ({
|
|
16
17
|
type,
|
|
17
|
-
label,
|
|
18
|
-
jsonPath,
|
|
19
18
|
readonly,
|
|
20
|
-
layout,
|
|
21
|
-
getStatus,
|
|
22
19
|
getValue,
|
|
23
20
|
onValueChange,
|
|
24
21
|
onBlur,
|
|
25
|
-
|
|
22
|
+
...props
|
|
23
|
+
}: FormFieldRendererProps<GeoPoint>) => {
|
|
26
24
|
const { t } = useTranslation(translationKey);
|
|
27
|
-
const { status, error } = getStatus();
|
|
28
25
|
const geoPoint = useMemo<GeoPoint>(() => getValue() ?? [0, 0], [getValue]);
|
|
29
26
|
const value = useMemo(() => GeoLocation.fromGeoPoint(geoPoint), [geoPoint]);
|
|
30
27
|
|
|
@@ -54,22 +51,23 @@ export const GeoPointField = ({
|
|
|
54
51
|
[type, getValue, onValueChange],
|
|
55
52
|
);
|
|
56
53
|
|
|
57
|
-
if ((readonly || layout === 'static') && !value?.latitude && !value?.longitude) {
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
54
|
return (
|
|
62
|
-
<
|
|
63
|
-
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
{
|
|
67
|
-
|
|
68
|
-
|
|
55
|
+
<FormRow<GeoPoint>
|
|
56
|
+
readonly={readonly}
|
|
57
|
+
getValue={getValue}
|
|
58
|
+
standalone
|
|
59
|
+
renderStatic={(point) => {
|
|
60
|
+
const location = GeoLocation.fromGeoPoint(point ?? [0, 0]);
|
|
61
|
+
// Treat a zero coordinate pair as empty (no meaningful location to display).
|
|
62
|
+
return !location.latitude && !location.longitude ? null : <LatLng {...location} />;
|
|
63
|
+
}}
|
|
64
|
+
{...props}
|
|
65
|
+
>
|
|
66
|
+
{({ presentation }) => (
|
|
69
67
|
<div className='grid grid-cols-2 gap-form-gap'>
|
|
70
68
|
<div>
|
|
71
69
|
<Input.Root>
|
|
72
|
-
{
|
|
70
|
+
{presentation.showLabel && <Input.Label>{t('latitude.label')}</Input.Label>}
|
|
73
71
|
<Input.TextInput
|
|
74
72
|
type='number'
|
|
75
73
|
step='0.00001'
|
|
@@ -85,7 +83,7 @@ export const GeoPointField = ({
|
|
|
85
83
|
</div>
|
|
86
84
|
<div>
|
|
87
85
|
<Input.Root>
|
|
88
|
-
{
|
|
86
|
+
{presentation.showLabel && <Input.Label>{t('longitude.label')}</Input.Label>}
|
|
89
87
|
<Input.TextInput
|
|
90
88
|
type='number'
|
|
91
89
|
step='0.00001'
|
|
@@ -101,7 +99,7 @@ export const GeoPointField = ({
|
|
|
101
99
|
</div>
|
|
102
100
|
</div>
|
|
103
101
|
)}
|
|
104
|
-
</
|
|
102
|
+
</FormRow>
|
|
105
103
|
);
|
|
106
104
|
};
|
|
107
105
|
|
package/src/components/Form/{fields → FormField/fields/MarkdownField}/MarkdownField.stories.tsx
RENAMED
|
@@ -16,20 +16,20 @@ import { Text } from '@dxos/schema';
|
|
|
16
16
|
|
|
17
17
|
import { translations } from '#translations';
|
|
18
18
|
|
|
19
|
-
import { TestLayout } from '
|
|
20
|
-
import { Form } from '
|
|
19
|
+
import { TestLayout } from '../../../../../testing';
|
|
20
|
+
import { Form } from '../../../Form';
|
|
21
21
|
|
|
22
22
|
//
|
|
23
23
|
// String-backed markdown.
|
|
24
24
|
//
|
|
25
25
|
|
|
26
|
-
const
|
|
26
|
+
const TestSchema = Schema.Struct({
|
|
27
27
|
notes: Schema.String.pipe(Format.FormatAnnotation.set(Format.TypeFormat.Markdown)).annotations({ title: 'Notes' }),
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
const StringStory = () => (
|
|
31
31
|
<TestLayout>
|
|
32
|
-
<Form.Root schema={
|
|
32
|
+
<Form.Root schema={TestSchema} defaultValues={{ notes: '# Hello\n\nMarkdown text *here*.' }}>
|
|
33
33
|
<Form.Viewport>
|
|
34
34
|
<Form.Content>
|
|
35
35
|
<Form.FieldSet />
|
|
@@ -61,7 +61,7 @@ const RefStory = () => {
|
|
|
61
61
|
return (
|
|
62
62
|
<TestLayout>
|
|
63
63
|
<Panel.Root>
|
|
64
|
-
<Panel.Content
|
|
64
|
+
<Panel.Content>
|
|
65
65
|
<Form.Root schema={TextNoteHolder} values={values as any} db={space.db}>
|
|
66
66
|
<Form.Viewport>
|
|
67
67
|
<Form.Content>
|
|
@@ -96,7 +96,7 @@ const EmptyRefStory = () => {
|
|
|
96
96
|
return (
|
|
97
97
|
<TestLayout>
|
|
98
98
|
<Panel.Root>
|
|
99
|
-
<Panel.Content
|
|
99
|
+
<Panel.Content>
|
|
100
100
|
<Form.Root schema={EmptyRefSchema} defaultValues={{}} db={space.db}>
|
|
101
101
|
<Form.Viewport>
|
|
102
102
|
<Form.Content>
|
|
@@ -111,7 +111,7 @@ const EmptyRefStory = () => {
|
|
|
111
111
|
};
|
|
112
112
|
|
|
113
113
|
const meta = {
|
|
114
|
-
title: 'ui/react-ui-form/MarkdownField',
|
|
114
|
+
title: 'ui/react-ui-form/FormField/MarkdownField',
|
|
115
115
|
decorators: [withTheme(), withLayout({ layout: 'column' })],
|
|
116
116
|
parameters: {
|
|
117
117
|
layout: 'fullscreen',
|
|
@@ -134,7 +134,7 @@ export const StringBacked: Story = {
|
|
|
134
134
|
export const StringBackedKeepsFocus: Story = {
|
|
135
135
|
render: () => (
|
|
136
136
|
<TestLayout>
|
|
137
|
-
<Form.Root schema={
|
|
137
|
+
<Form.Root schema={TestSchema} defaultValues={{ notes: '' }}>
|
|
138
138
|
<Form.Viewport>
|
|
139
139
|
<Form.Content>
|
|
140
140
|
<Form.FieldSet />
|
|
@@ -5,19 +5,27 @@
|
|
|
5
5
|
import { useAtomValue } from '@effect-atom/atom-react';
|
|
6
6
|
import React, { useCallback, useMemo } from 'react';
|
|
7
7
|
|
|
8
|
-
import { type Database,
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import { type Database, Ref } from '@dxos/echo';
|
|
9
|
+
import { Doc } from '@dxos/echo-doc';
|
|
10
|
+
import { IconButton, useTranslation } from '@dxos/react-ui';
|
|
11
11
|
import { Editor, useBasicMarkdownExtensions } from '@dxos/react-ui-editor';
|
|
12
12
|
import { Text } from '@dxos/schema';
|
|
13
13
|
import { createDataExtensions } from '@dxos/ui-editor';
|
|
14
14
|
|
|
15
15
|
import { translationKey } from '#translations';
|
|
16
|
+
import { type FormFieldRendererProps } from '#types';
|
|
16
17
|
|
|
17
|
-
import {
|
|
18
|
+
import { FormRow } from '../../FormRow';
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
// Mirror the focus treatment of `Input` (default variant): a `focus-ring-subtle` ring of `dx-focus-line`
|
|
21
|
+
// width rather than a recolored 1px border, and suppress the editor wrapper's `accent-bg` border so a
|
|
22
|
+
// second click never turns the outline blue. Keyed on `focus-within` because focus lands on the inner
|
|
23
|
+
// CodeMirror contenteditable, not this wrapper.
|
|
24
|
+
const editorClassNames = [
|
|
25
|
+
'min-h-[6lh] transition-colors rounded-xs p-1 px-2 bg-input-surface border border-input-separator',
|
|
26
|
+
'focus:border-separator focus-within:border-separator focus-within:bg-focus-surface',
|
|
27
|
+
'focus-within:ring-2 focus-within:ring-offset-0 focus-within:ring-focus-ring-subtle focus-within:z-[1]',
|
|
28
|
+
];
|
|
21
29
|
|
|
22
30
|
/**
|
|
23
31
|
* Form field that edits a markdown value in a CodeMirror editor.
|
|
@@ -29,28 +37,30 @@ const editorClassNames =
|
|
|
29
37
|
export const MarkdownField = ({
|
|
30
38
|
type,
|
|
31
39
|
readonly,
|
|
32
|
-
label,
|
|
33
|
-
jsonPath,
|
|
34
40
|
placeholder,
|
|
35
|
-
layout,
|
|
36
41
|
db,
|
|
37
|
-
getStatus,
|
|
38
42
|
getValue,
|
|
39
43
|
onValueChange,
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
...props
|
|
45
|
+
}: FormFieldRendererProps) => {
|
|
42
46
|
const isRef = Ref.isRefType(type);
|
|
43
|
-
const value = getValue();
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
// The field value is a runtime union the form's value type can't express: a `Ref<Text>` when the
|
|
49
|
+
// property is a markdown ref, or a plain string when it is annotated markdown text. `isRef`
|
|
50
|
+
// selects the branch, so the casts below narrow the opaque value accordingly.
|
|
51
|
+
const renderStatic = (value: unknown) => {
|
|
52
|
+
if (isRef) {
|
|
53
|
+
const reference = value as Ref.Ref<any> | undefined;
|
|
54
|
+
return reference ? <RefStaticText reference={reference} /> : null;
|
|
55
|
+
}
|
|
56
|
+
return <p className='whitespace-pre-wrap'>{(value as string | undefined) ?? ''}</p>;
|
|
57
|
+
};
|
|
48
58
|
|
|
49
|
-
const renderEditor = () => {
|
|
59
|
+
const renderEditor = (value: unknown) => {
|
|
50
60
|
if (isRef) {
|
|
51
61
|
const reference = value as Ref.Ref<any> | undefined;
|
|
52
62
|
if (reference) {
|
|
53
|
-
return <RefMarkdownEditor reference={reference} placeholder={placeholder} />;
|
|
63
|
+
return <RefMarkdownEditor reference={reference} placeholder={placeholder} readonly={!!readonly} />;
|
|
54
64
|
}
|
|
55
65
|
|
|
56
66
|
if (readonly) {
|
|
@@ -70,20 +80,10 @@ export const MarkdownField = ({
|
|
|
70
80
|
);
|
|
71
81
|
};
|
|
72
82
|
|
|
73
|
-
const renderStatic = () => {
|
|
74
|
-
if (isRef) {
|
|
75
|
-
const reference = value as Ref.Ref<any> | undefined;
|
|
76
|
-
return reference ? <RefStaticText reference={reference} /> : null;
|
|
77
|
-
}
|
|
78
|
-
return <p className='whitespace-pre-wrap'>{(value as string | undefined) ?? ''}</p>;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
83
|
return (
|
|
82
|
-
<
|
|
83
|
-
{
|
|
84
|
-
|
|
85
|
-
{layout === 'full' && <Input.Validation>{error}</Input.Validation>}
|
|
86
|
-
</Input.Root>
|
|
84
|
+
<FormRow readonly={readonly} getValue={getValue} renderStatic={renderStatic} {...props}>
|
|
85
|
+
{({ value }) => renderEditor(value)}
|
|
86
|
+
</FormRow>
|
|
87
87
|
);
|
|
88
88
|
};
|
|
89
89
|
|
|
@@ -93,21 +93,23 @@ const RefStaticText = ({ reference }: { reference: Ref.Ref<any> }) => {
|
|
|
93
93
|
if (!text?.content) {
|
|
94
94
|
return null;
|
|
95
95
|
}
|
|
96
|
+
|
|
96
97
|
return <p className='whitespace-pre-wrap'>{text.content}</p>;
|
|
97
98
|
};
|
|
98
99
|
|
|
99
100
|
type RefMarkdownEditorProps = {
|
|
100
101
|
reference: Ref.Ref<any>;
|
|
101
102
|
placeholder?: string;
|
|
103
|
+
readonly?: boolean;
|
|
102
104
|
};
|
|
103
105
|
|
|
104
|
-
const RefMarkdownEditor = ({ reference, placeholder }: RefMarkdownEditorProps) => {
|
|
106
|
+
const RefMarkdownEditor = ({ reference, placeholder, readonly }: RefMarkdownEditorProps) => {
|
|
105
107
|
const text = useAtomValue(useMemo(() => reference.atom, [reference]));
|
|
106
108
|
const dataExtensions = useMemo(
|
|
107
|
-
() => (text ? [createDataExtensions({ id: reference.uri, text:
|
|
109
|
+
() => (text ? [createDataExtensions({ id: reference.uri, text: Doc.createAccessor(text, ['content']) })] : []),
|
|
108
110
|
[text, reference],
|
|
109
111
|
);
|
|
110
|
-
const extensions = useBasicMarkdownExtensions({ placeholder, extensions: dataExtensions });
|
|
112
|
+
const extensions = useBasicMarkdownExtensions({ placeholder, readonly, extensions: dataExtensions });
|
|
111
113
|
if (!text) {
|
|
112
114
|
return null;
|
|
113
115
|
}
|
|
@@ -127,7 +129,7 @@ type StringMarkdownEditorProps = {
|
|
|
127
129
|
};
|
|
128
130
|
|
|
129
131
|
const StringMarkdownEditor = ({ value, placeholder, readonly, onChange }: StringMarkdownEditorProps) => {
|
|
130
|
-
const extensions = useBasicMarkdownExtensions({ placeholder });
|
|
132
|
+
const extensions = useBasicMarkdownExtensions({ placeholder, readonly });
|
|
131
133
|
const handleChange = useCallback((next: string) => onChange(next), [onChange]);
|
|
132
134
|
|
|
133
135
|
return (
|
|
@@ -150,18 +152,16 @@ type CreateTextButtonProps = {
|
|
|
150
152
|
|
|
151
153
|
const CreateTextButton = ({ db, disabled, onCreate }: CreateTextButtonProps) => {
|
|
152
154
|
const { t } = useTranslation(translationKey);
|
|
155
|
+
|
|
153
156
|
const handleClick = useCallback(() => {
|
|
154
157
|
if (!db) {
|
|
155
158
|
return;
|
|
156
159
|
}
|
|
157
|
-
|
|
158
|
-
onCreate(Ref.make(
|
|
160
|
+
|
|
161
|
+
onCreate(Ref.make(db.add(Text.make())));
|
|
159
162
|
}, [db, onCreate]);
|
|
160
163
|
|
|
161
164
|
return (
|
|
162
|
-
<
|
|
163
|
-
<Icon icon='ph--plus--regular' size={4} />
|
|
164
|
-
<span>{t('create-text.label')}</span>
|
|
165
|
-
</Button>
|
|
165
|
+
<IconButton icon='ph--plus--regular' label={t('create-text.label')} onClick={handleClick} disabled={disabled} />
|
|
166
166
|
);
|
|
167
167
|
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
7
|
+
import React, { useState } from 'react';
|
|
8
|
+
|
|
9
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
10
|
+
|
|
11
|
+
import { translations } from '#translations';
|
|
12
|
+
|
|
13
|
+
import { TestLayout } from '../../../../../testing';
|
|
14
|
+
import { Form } from '../../../Form';
|
|
15
|
+
|
|
16
|
+
const schema = Schema.Struct({
|
|
17
|
+
count: Schema.Number.annotations({ title: 'Count' }),
|
|
18
|
+
}).pipe(Schema.mutable);
|
|
19
|
+
|
|
20
|
+
type Values = Schema.Schema.Type<typeof schema>;
|
|
21
|
+
|
|
22
|
+
const DefaultStory = () => {
|
|
23
|
+
const [values, setValues] = useState<Values>({ count: 42 });
|
|
24
|
+
return (
|
|
25
|
+
<TestLayout json={values}>
|
|
26
|
+
<Form.Root
|
|
27
|
+
schema={schema}
|
|
28
|
+
values={values}
|
|
29
|
+
onValuesChanged={(values) => setValues((prev) => ({ ...prev, ...values }))}
|
|
30
|
+
>
|
|
31
|
+
<Form.Viewport>
|
|
32
|
+
<Form.Content>
|
|
33
|
+
<Form.FieldSet />
|
|
34
|
+
</Form.Content>
|
|
35
|
+
</Form.Viewport>
|
|
36
|
+
</Form.Root>
|
|
37
|
+
</TestLayout>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const meta = {
|
|
42
|
+
title: 'ui/react-ui-form/FormField/NumberField',
|
|
43
|
+
render: DefaultStory,
|
|
44
|
+
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
45
|
+
parameters: { layout: 'fullscreen', translations },
|
|
46
|
+
} satisfies Meta<typeof DefaultStory>;
|
|
47
|
+
|
|
48
|
+
export default meta;
|
|
49
|
+
|
|
50
|
+
type Story = StoryObj<typeof meta>;
|
|
51
|
+
|
|
52
|
+
export const Default: Story = {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
|
+
import { describe, test } from 'vitest';
|
|
7
|
+
|
|
8
|
+
import { getNumericConstraints } from './NumberField';
|
|
9
|
+
|
|
10
|
+
describe('getNumericConstraints', () => {
|
|
11
|
+
test('reads min/max from Schema.between (bounds live on separate nested refinements)', ({ expect }) => {
|
|
12
|
+
const { ast } = Schema.Number.pipe(Schema.between(0, 23));
|
|
13
|
+
expect(getNumericConstraints(ast)).toEqual({ min: 0, max: 23, integer: false });
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('detects integer from Schema.int', ({ expect }) => {
|
|
17
|
+
const { ast } = Schema.Number.pipe(Schema.int(), Schema.between(0, 23));
|
|
18
|
+
expect(getNumericConstraints(ast)).toEqual({ min: 0, max: 23, integer: true });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('returns empty constraints for an unconstrained number', ({ expect }) => {
|
|
22
|
+
expect(getNumericConstraints(Schema.Number.ast)).toEqual({ integer: false });
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('aggregates stacked bounds to the strictest (intersection semantics)', ({ expect }) => {
|
|
26
|
+
const { ast } = Schema.Number.pipe(Schema.greaterThanOrEqualTo(5), Schema.greaterThanOrEqualTo(10));
|
|
27
|
+
expect(getNumericConstraints(ast)).toEqual({ min: 10, max: undefined, integer: false });
|
|
28
|
+
});
|
|
29
|
+
});
|