@dxos/react-ui-form 0.8.4-main.fd6878d → 0.8.4-main.fffef41
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 +806 -572
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +806 -572
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/ControlSection/ControlSection.d.ts +2 -2
- package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +1 -1
- package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts +80 -5
- package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts.map +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +1 -2
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +75 -5
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/ArrayField.d.ts +2 -2
- package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
- package/dist/types/src/components/Form/Defaults.d.ts +5 -5
- package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +6 -4
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +128 -32
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContent.d.ts +16 -10
- package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContext.d.ts +2 -2
- package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
- package/dist/types/src/components/Form/Input.d.ts +5 -2
- package/dist/types/src/components/Form/Input.d.ts.map +1 -1
- package/dist/types/src/components/Form/RefField.d.ts +14 -4
- package/dist/types/src/components/Form/RefField.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +1 -1
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +1 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +75 -4
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/TupleInput.d.ts +1 -1
- package/dist/types/src/components/Form/factory.d.ts +1 -1
- package/dist/types/src/components/Form/factory.d.ts.map +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +41 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +81 -0
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -0
- package/dist/types/src/components/ObjectPicker/index.d.ts +2 -0
- package/dist/types/src/components/ObjectPicker/index.d.ts.map +1 -0
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +20 -6
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +79 -8
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +6 -3
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/useForm.d.ts +2 -2
- package/dist/types/src/hooks/useForm.d.ts.map +1 -1
- package/dist/types/src/hooks/useQueryRefOptions.d.ts +9 -3
- package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +1 -1
- package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +11 -7
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/util/field.d.ts +1 -1
- package/dist/types/src/util/field.d.ts.map +1 -1
- package/dist/types/src/util/formatting.d.ts +1 -1
- package/dist/types/src/util/formatting.d.ts.map +1 -1
- package/dist/types/src/util/refs.d.ts +1 -1
- package/dist/types/src/util/refs.d.ts.map +1 -1
- package/dist/types/src/util/schema.d.ts +1 -1
- package/dist/types/src/util/schema.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +41 -36
- package/src/components/ControlSection/ControlSection.stories.tsx +10 -14
- package/src/components/ControlSection/ControlSection.tsx +26 -12
- package/src/components/FieldEditor/FieldEditor.stories.tsx +10 -11
- package/src/components/FieldEditor/FieldEditor.tsx +12 -14
- package/src/components/Form/ArrayField.tsx +6 -6
- package/src/components/Form/Defaults.tsx +21 -20
- package/src/components/Form/Form.stories.tsx +132 -97
- package/src/components/Form/Form.tsx +27 -14
- package/src/components/Form/FormActions.tsx +2 -2
- package/src/components/Form/FormContent.tsx +166 -45
- package/src/components/Form/FormContext.tsx +3 -3
- package/src/components/Form/Input.tsx +5 -2
- package/src/components/Form/RefField.tsx +107 -38
- package/src/components/Form/custom/GeoPointInput.tsx +28 -20
- package/src/components/Form/custom/SelectOptionsInput.stories.tsx +9 -10
- package/src/components/Form/custom/SelectOptionsInput.tsx +10 -10
- package/src/components/Form/custom/TupleInput.tsx +2 -2
- package/src/components/Form/factory.tsx +1 -1
- package/src/components/ObjectPicker/ObjectPicker.stories.tsx +207 -0
- package/src/components/ObjectPicker/ObjectPicker.tsx +161 -0
- package/src/components/ObjectPicker/index.ts +5 -0
- package/src/components/ViewEditor/ViewEditor.stories.tsx +123 -49
- package/src/components/ViewEditor/ViewEditor.test.tsx +8 -11
- package/src/components/ViewEditor/ViewEditor.tsx +281 -233
- package/src/components/index.ts +1 -2
- package/src/components/testing.tsx +15 -9
- package/src/hooks/useForm.ts +7 -4
- package/src/hooks/useQueryRefOptions.ts +15 -6
- package/src/hooks/useRefQueryLookupHandler.ts +3 -3
- package/src/translations.ts +13 -8
- package/src/util/field.ts +9 -19
- package/src/util/formatting.ts +1 -1
- package/src/util/refs.ts +7 -7
- package/src/util/schema.ts +2 -4
- package/dist/types/src/components/deprecated/Form.d.ts +0 -15
- package/dist/types/src/components/deprecated/Form.d.ts.map +0 -1
- package/dist/types/src/components/deprecated/Form.stories.d.ts +0 -13
- package/dist/types/src/components/deprecated/Form.stories.d.ts.map +0 -1
- package/dist/types/src/components/deprecated/FormInput.d.ts +0 -16
- package/dist/types/src/components/deprecated/FormInput.d.ts.map +0 -1
- package/dist/types/src/components/deprecated/index.d.ts +0 -2
- package/dist/types/src/components/deprecated/index.d.ts.map +0 -1
- package/src/components/deprecated/Form.stories.tsx +0 -63
- package/src/components/deprecated/Form.tsx +0 -119
- package/src/components/deprecated/FormInput.tsx +0 -71
- package/src/components/deprecated/index.ts +0 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-form",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.fffef41",
|
|
4
4
|
"description": "Data components.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -26,52 +26,57 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
|
|
28
28
|
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
|
|
29
|
+
"@fluentui/react-tabster": "^9.24.2",
|
|
29
30
|
"@preact-signals/safe-react": "^0.9.0",
|
|
31
|
+
"@preact/signals-react": "^3.2.0",
|
|
30
32
|
"@radix-ui/react-context": "1.1.1",
|
|
31
33
|
"date-fns": "^3.3.1",
|
|
32
34
|
"jsonpath": "^1.1.1",
|
|
33
|
-
"@dxos/async": "0.8.4-main.
|
|
34
|
-
"@dxos/
|
|
35
|
-
"@dxos/
|
|
36
|
-
"@dxos/echo-
|
|
37
|
-
"@dxos/echo
|
|
38
|
-
"@dxos/effect": "0.8.4-main.
|
|
39
|
-
"@dxos/
|
|
40
|
-
"@dxos/
|
|
41
|
-
"@dxos/
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/log": "0.8.4-main.
|
|
44
|
-
"@dxos/react-
|
|
45
|
-
"@dxos/react-ui-
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/react-ui-
|
|
48
|
-
"@dxos/react-ui-
|
|
49
|
-
"@dxos/
|
|
50
|
-
"@dxos/
|
|
51
|
-
"@dxos/react-ui-
|
|
35
|
+
"@dxos/async": "0.8.4-main.fffef41",
|
|
36
|
+
"@dxos/debug": "0.8.4-main.fffef41",
|
|
37
|
+
"@dxos/echo-db": "0.8.4-main.fffef41",
|
|
38
|
+
"@dxos/echo-query": "0.8.4-main.fffef41",
|
|
39
|
+
"@dxos/echo": "0.8.4-main.fffef41",
|
|
40
|
+
"@dxos/effect": "0.8.4-main.fffef41",
|
|
41
|
+
"@dxos/keys": "0.8.4-main.fffef41",
|
|
42
|
+
"@dxos/live-object": "0.8.4-main.fffef41",
|
|
43
|
+
"@dxos/lit-ui": "0.8.4-main.fffef41",
|
|
44
|
+
"@dxos/react-client": "0.8.4-main.fffef41",
|
|
45
|
+
"@dxos/log": "0.8.4-main.fffef41",
|
|
46
|
+
"@dxos/react-ui-components": "0.8.4-main.fffef41",
|
|
47
|
+
"@dxos/react-ui-editor": "0.8.4-main.fffef41",
|
|
48
|
+
"@dxos/invariant": "0.8.4-main.fffef41",
|
|
49
|
+
"@dxos/react-ui-pickers": "0.8.4-main.fffef41",
|
|
50
|
+
"@dxos/react-ui-searchlist": "0.8.4-main.fffef41",
|
|
51
|
+
"@dxos/react-ui-types": "0.8.4-main.fffef41",
|
|
52
|
+
"@dxos/react-ui-stack": "0.8.4-main.fffef41",
|
|
53
|
+
"@dxos/react-ui-list": "0.8.4-main.fffef41",
|
|
54
|
+
"@dxos/schema": "0.8.4-main.fffef41",
|
|
55
|
+
"@dxos/types": "0.8.4-main.fffef41",
|
|
56
|
+
"@dxos/util": "0.8.4-main.fffef41"
|
|
52
57
|
},
|
|
53
58
|
"devDependencies": {
|
|
54
59
|
"@types/jsonpath": "^0.2.4",
|
|
55
|
-
"@types/react": "~
|
|
56
|
-
"@types/react-dom": "~
|
|
57
|
-
"effect": "3.
|
|
60
|
+
"@types/react": "~19.2.2",
|
|
61
|
+
"@types/react-dom": "~19.2.2",
|
|
62
|
+
"effect": "3.18.3",
|
|
58
63
|
"fast-check": "^3.19.0",
|
|
59
|
-
"react": "~
|
|
60
|
-
"react-dom": "~
|
|
61
|
-
"vite": "
|
|
62
|
-
"@dxos/echo-signals": "0.8.4-main.
|
|
63
|
-
"@dxos/
|
|
64
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
65
|
-
"@dxos/
|
|
66
|
-
"@dxos/
|
|
67
|
-
"@dxos/
|
|
64
|
+
"react": "~19.2.0",
|
|
65
|
+
"react-dom": "~19.2.0",
|
|
66
|
+
"vite": "7.1.9",
|
|
67
|
+
"@dxos/echo-signals": "0.8.4-main.fffef41",
|
|
68
|
+
"@dxos/react-ui": "0.8.4-main.fffef41",
|
|
69
|
+
"@dxos/react-ui-syntax-highlighter": "0.8.4-main.fffef41",
|
|
70
|
+
"@dxos/random": "0.8.4-main.fffef41",
|
|
71
|
+
"@dxos/react-ui-theme": "0.8.4-main.fffef41",
|
|
72
|
+
"@dxos/storybook-utils": "0.8.4-main.fffef41"
|
|
68
73
|
},
|
|
69
74
|
"peerDependencies": {
|
|
70
75
|
"effect": "^3.13.3",
|
|
71
|
-
"react": "
|
|
72
|
-
"react-dom": "
|
|
73
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
74
|
-
"@dxos/react-ui-theme": "0.8.4-main.
|
|
76
|
+
"react": "^19.0.0",
|
|
77
|
+
"react-dom": "^19.0.0",
|
|
78
|
+
"@dxos/react-ui": "0.8.4-main.fffef41",
|
|
79
|
+
"@dxos/react-ui-theme": "0.8.4-main.fffef41"
|
|
75
80
|
},
|
|
76
81
|
"publishConfig": {
|
|
77
82
|
"access": "public"
|
|
@@ -2,37 +2,33 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
6
|
import React from 'react';
|
|
9
7
|
|
|
10
|
-
import {
|
|
11
|
-
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
8
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
12
9
|
|
|
13
10
|
import { translations } from '../../translations';
|
|
14
11
|
|
|
15
|
-
import { ControlPage, ControlSection
|
|
12
|
+
import { ControlPage, ControlSection } from './ControlSection';
|
|
16
13
|
|
|
17
|
-
const meta
|
|
14
|
+
const meta = {
|
|
18
15
|
title: 'ui/react-ui-form/ControlSection',
|
|
19
16
|
component: ControlSection,
|
|
20
17
|
render: (args) => (
|
|
21
|
-
<
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
</ControlPage>
|
|
25
|
-
</StackItem.Content>
|
|
18
|
+
<ControlPage classNames='is-[40rem]'>
|
|
19
|
+
<ControlSection {...args} />
|
|
20
|
+
</ControlPage>
|
|
26
21
|
),
|
|
27
|
-
decorators: [
|
|
22
|
+
decorators: [withTheme],
|
|
28
23
|
parameters: {
|
|
24
|
+
layout: 'centered',
|
|
29
25
|
translations,
|
|
30
26
|
},
|
|
31
|
-
}
|
|
27
|
+
} satisfies Meta<typeof ControlSection>;
|
|
32
28
|
|
|
33
29
|
export default meta;
|
|
34
30
|
|
|
35
|
-
type Story = StoryObj<
|
|
31
|
+
type Story = StoryObj<typeof meta>;
|
|
36
32
|
|
|
37
33
|
export const Default: Story = {
|
|
38
34
|
args: {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
toLocalizedString,
|
|
14
14
|
useTranslation,
|
|
15
15
|
} from '@dxos/react-ui';
|
|
16
|
+
import { StackItem } from '@dxos/react-ui-stack';
|
|
16
17
|
import { mx } from '@dxos/react-ui-theme';
|
|
17
18
|
|
|
18
19
|
import { translationKey } from '../../translations';
|
|
@@ -21,9 +22,11 @@ export type ControlPageProps = ThemedClassName<ComponentPropsWithoutRef<'div'>>;
|
|
|
21
22
|
|
|
22
23
|
export const ControlPage = ({ children, classNames, ...props }: ControlPageProps) => {
|
|
23
24
|
return (
|
|
24
|
-
<
|
|
25
|
-
{
|
|
26
|
-
|
|
25
|
+
<StackItem.Content scrollable classNames='[--control-spacing:var(--dx-trimMd)]'>
|
|
26
|
+
<div role='none' className={mx('pli-cardSpacingInline pbe-trimLg', classNames)} {...props}>
|
|
27
|
+
{children}
|
|
28
|
+
</div>
|
|
29
|
+
</StackItem.Content>
|
|
27
30
|
);
|
|
28
31
|
};
|
|
29
32
|
|
|
@@ -59,12 +62,16 @@ export const ControlGroupButton = ({ classNames, ...props }: ButtonProps) => {
|
|
|
59
62
|
return <Button {...props} classNames={['md:col-span-2', classNames]} />;
|
|
60
63
|
};
|
|
61
64
|
|
|
62
|
-
export type ControlGroupProps = ThemedClassName<PropsWithChildren
|
|
65
|
+
export type ControlGroupProps = ThemedClassName<PropsWithChildren>;
|
|
63
66
|
|
|
64
67
|
export const ControlGroup = ({ children, classNames }: ControlGroupProps) => (
|
|
65
68
|
<div
|
|
66
69
|
role='none'
|
|
67
|
-
className={mx(
|
|
70
|
+
className={mx(
|
|
71
|
+
'group container-max-width grid grid-cols-1 md:grid-cols-[1fr_min-content] gap-trimMd',
|
|
72
|
+
'[--control-spacing:0px] [&_input]:justify-self-end [&_button]:justify-self-end',
|
|
73
|
+
classNames,
|
|
74
|
+
)}
|
|
68
75
|
>
|
|
69
76
|
{children}
|
|
70
77
|
</div>
|
|
@@ -73,23 +80,30 @@ export const ControlGroup = ({ children, classNames }: ControlGroupProps) => (
|
|
|
73
80
|
export const ControlFrame = ({ children }: ControlGroupProps) => (
|
|
74
81
|
<div
|
|
75
82
|
role='none'
|
|
76
|
-
className=
|
|
83
|
+
className={mx(
|
|
84
|
+
'container-max-width grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-trimSm md:gap-trimMd p-trimMd',
|
|
85
|
+
'border border-separator rounded-md',
|
|
86
|
+
)}
|
|
77
87
|
>
|
|
78
88
|
{children}
|
|
79
89
|
</div>
|
|
80
90
|
);
|
|
81
91
|
|
|
92
|
+
export const controlItemClasses = mx([
|
|
93
|
+
'container-max-width grid md:col-span-2 grid-cols-subgrid gap-trimSm items-center',
|
|
94
|
+
// TODO(burdon): Use grid gap consistently or apply margins consistently?
|
|
95
|
+
'mlb-[--control-spacing] *:first:!mbs-0 *:last:!mbe-0 pli-trimMd plb-trimMd',
|
|
96
|
+
'border border-separator rounded-md',
|
|
97
|
+
]);
|
|
98
|
+
|
|
99
|
+
const controlItemTitleClasses = 'mbe-0 text-lg text-baseText font-normal';
|
|
100
|
+
const controlItemDescriptionClasses = 'mlb-trimSm md:mbe-0 text-base text-description';
|
|
101
|
+
|
|
82
102
|
export type ControlItemProps = PropsWithChildren<{
|
|
83
103
|
title: Label;
|
|
84
104
|
description?: Label;
|
|
85
105
|
}>;
|
|
86
106
|
|
|
87
|
-
export const controlItemClasses =
|
|
88
|
-
'pli-trimMd plb-trimMd container-max-width grid md:col-span-2 grid-cols-subgrid items-center gap-trimSm border border-separator rounded-md *:first:!mbs-0 *:last:!mbe-0';
|
|
89
|
-
|
|
90
|
-
const controlItemTitleClasses = 'text-lg font-normal';
|
|
91
|
-
const controlItemDescriptionClasses = 'text-base mlb-trimSm md:mbe-0 text-description';
|
|
92
|
-
|
|
93
107
|
export const ControlItem = ({ title, description, children }: ControlItemProps) => {
|
|
94
108
|
const { t } = useTranslation(translationKey);
|
|
95
109
|
|
|
@@ -2,16 +2,14 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
6
|
import React, { useEffect, useMemo } from 'react';
|
|
9
7
|
|
|
10
|
-
import { createEchoSchema } from '@dxos/
|
|
8
|
+
import { createEchoSchema } from '@dxos/echo/testing';
|
|
11
9
|
import { log } from '@dxos/log';
|
|
10
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
12
11
|
import { ProjectionModel } from '@dxos/schema';
|
|
13
12
|
import { TestSchema, testView } from '@dxos/schema/testing';
|
|
14
|
-
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
15
13
|
|
|
16
14
|
import { translations } from '../../translations';
|
|
17
15
|
import { FIELD_EDITOR_DEBUG_SYMBOL, TestLayout, TestPanel } from '../testing';
|
|
@@ -24,8 +22,6 @@ export type FieldEditorDebugObjects = {
|
|
|
24
22
|
projection: ProjectionModel;
|
|
25
23
|
};
|
|
26
24
|
|
|
27
|
-
type StoryProps = FieldEditorProps;
|
|
28
|
-
|
|
29
25
|
const DefaultStory = (props: FieldEditorProps) => {
|
|
30
26
|
const handleComplete: FieldEditorProps['onSave'] = () => {
|
|
31
27
|
log.info('onClose', { props });
|
|
@@ -33,6 +29,8 @@ const DefaultStory = (props: FieldEditorProps) => {
|
|
|
33
29
|
|
|
34
30
|
// Expose objects on window for test access.
|
|
35
31
|
useEffect(() => {
|
|
32
|
+
props.projection.normalizeView();
|
|
33
|
+
|
|
36
34
|
if (typeof window !== 'undefined') {
|
|
37
35
|
(window as any)[FIELD_EDITOR_DEBUG_SYMBOL] = {
|
|
38
36
|
props,
|
|
@@ -56,19 +54,20 @@ const DefaultStory = (props: FieldEditorProps) => {
|
|
|
56
54
|
);
|
|
57
55
|
};
|
|
58
56
|
|
|
59
|
-
const meta
|
|
57
|
+
const meta = {
|
|
60
58
|
title: 'ui/react-ui-form/FieldEditor',
|
|
61
|
-
component: FieldEditor,
|
|
59
|
+
component: FieldEditor as any,
|
|
62
60
|
render: DefaultStory,
|
|
63
|
-
decorators: [
|
|
61
|
+
decorators: [withTheme],
|
|
64
62
|
parameters: {
|
|
63
|
+
layout: 'fullscreen',
|
|
65
64
|
translations,
|
|
66
65
|
},
|
|
67
|
-
}
|
|
66
|
+
} satisfies Meta<typeof DefaultStory>;
|
|
68
67
|
|
|
69
68
|
export default meta;
|
|
70
69
|
|
|
71
|
-
type Story = StoryObj<
|
|
70
|
+
type Story = StoryObj<typeof meta>;
|
|
72
71
|
|
|
73
72
|
export const Default: Story = {
|
|
74
73
|
args: {
|
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
6
6
|
|
|
7
|
+
import { type EchoSchema, FormatEnum, FormatEnums, formatToType } from '@dxos/echo/internal';
|
|
7
8
|
import { type SchemaRegistry } from '@dxos/echo-db';
|
|
8
|
-
import { type EchoSchema, FormatEnum, FormatEnums, formatToType } from '@dxos/echo-schema';
|
|
9
9
|
import { log } from '@dxos/log';
|
|
10
|
-
import { useTranslation } from '@dxos/react-ui';
|
|
10
|
+
import { useAsyncEffect, useTranslation } from '@dxos/react-ui';
|
|
11
11
|
import {
|
|
12
12
|
type FieldType,
|
|
13
13
|
type ProjectionModel,
|
|
14
14
|
type PropertyType,
|
|
15
15
|
type SchemaProperty,
|
|
16
|
+
formatToAdditionalPropertyAttributes,
|
|
16
17
|
getFormatSchema,
|
|
17
18
|
getSchemaProperties,
|
|
18
19
|
sortProperties,
|
|
@@ -22,13 +23,12 @@ import { translationKey } from '../../translations';
|
|
|
22
23
|
import { Form, type FormProps, type InputComponent, SelectInput, SelectOptionInput } from '../Form';
|
|
23
24
|
|
|
24
25
|
export type FieldEditorProps = {
|
|
25
|
-
readonly?: boolean;
|
|
26
26
|
projection: ProjectionModel;
|
|
27
27
|
field: FieldType;
|
|
28
28
|
registry?: SchemaRegistry;
|
|
29
29
|
onSave: () => void;
|
|
30
30
|
onCancel?: () => void;
|
|
31
|
-
} & Pick<FormProps<any>, 'outerSpacing'>;
|
|
31
|
+
} & Pick<FormProps<any>, 'outerSpacing' | 'readonly'>;
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Displays a Form representing the metadata for a given `Field` and `View`.
|
|
@@ -47,7 +47,7 @@ export const FieldEditor = ({
|
|
|
47
47
|
useEffect(() => setProps(projection.getFieldProjection(field.id).props), [field, projection]);
|
|
48
48
|
|
|
49
49
|
const [schemas, setSchemas] = useState<EchoSchema[]>([]);
|
|
50
|
-
|
|
50
|
+
useAsyncEffect(async () => {
|
|
51
51
|
if (!registry) {
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
@@ -55,14 +55,10 @@ export const FieldEditor = ({
|
|
|
55
55
|
const subscription = registry.query().subscribe((query) => setSchemas(query.results), { fire: true });
|
|
56
56
|
|
|
57
57
|
// TODO(dmaretskyi): This shouldn't be needed.
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return () => {
|
|
63
|
-
clearTimeout(t);
|
|
64
|
-
subscription?.();
|
|
65
|
-
};
|
|
58
|
+
const schemas = await registry.query().run();
|
|
59
|
+
setSchemas(schemas);
|
|
60
|
+
|
|
61
|
+
return () => subscription?.();
|
|
66
62
|
}, [registry]);
|
|
67
63
|
|
|
68
64
|
const [referenceSchema, setReferenceSchema] = useState<EchoSchema>();
|
|
@@ -99,8 +95,10 @@ export const FieldEditor = ({
|
|
|
99
95
|
|
|
100
96
|
setProps((props) => {
|
|
101
97
|
const type = formatToType[_props.format as keyof typeof formatToType];
|
|
98
|
+
const additionalProps =
|
|
99
|
+
formatToAdditionalPropertyAttributes[_props.format as keyof typeof formatToAdditionalPropertyAttributes];
|
|
102
100
|
if (props.type !== type) {
|
|
103
|
-
return { ...props, ..._props, type };
|
|
101
|
+
return { ...props, ..._props, ...additionalProps, type } as PropertyType;
|
|
104
102
|
}
|
|
105
103
|
|
|
106
104
|
return _props as PropertyType;
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import * as Function from 'effect/Function';
|
|
6
|
+
import * as SchemaAST from 'effect/SchemaAST';
|
|
7
|
+
import * as String from 'effect/String';
|
|
7
8
|
import React, { Fragment, useCallback } from 'react';
|
|
8
9
|
|
|
9
10
|
import { SimpleType, findNode, getDiscriminatedType, isDiscriminatedUnion } from '@dxos/effect';
|
|
@@ -15,18 +16,17 @@ import { translationKey } from '../../translations';
|
|
|
15
16
|
import { findArrayElementType } from '../../util';
|
|
16
17
|
|
|
17
18
|
import { type ComponentLookup } from './Form';
|
|
18
|
-
import { FormField } from './FormContent';
|
|
19
|
+
import { FormField, type FormFieldProps } from './FormContent';
|
|
19
20
|
import { type FormInputStateProps, useFormValues } from './FormContext';
|
|
20
21
|
import { type InputComponent, InputHeader } from './Input';
|
|
21
22
|
|
|
22
23
|
type ArrayFieldProps = {
|
|
23
24
|
property: SchemaProperty<any>;
|
|
24
|
-
readonly?: boolean;
|
|
25
25
|
inputProps: FormInputStateProps;
|
|
26
26
|
path?: (string | number)[];
|
|
27
27
|
Custom?: Partial<Record<string, InputComponent>>;
|
|
28
28
|
lookupComponent?: ComponentLookup;
|
|
29
|
-
}
|
|
29
|
+
} & Pick<FormFieldProps, 'readonly'>;
|
|
30
30
|
|
|
31
31
|
export const ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }: ArrayFieldProps) => {
|
|
32
32
|
const { t } = useTranslation(translationKey);
|
|
@@ -35,7 +35,7 @@ export const ArrayField = ({ property, readonly, path, inputProps, Custom, looku
|
|
|
35
35
|
// It doesn't become live until another field is touched, but that's better than the whole form crashing.
|
|
36
36
|
const values = (useFormValues(path ?? []) ?? []) as any[];
|
|
37
37
|
invariant(Array.isArray(values), `Values at path ${path?.join('.')} must be an array.`);
|
|
38
|
-
const label = title ?? pipe(name, capitalize);
|
|
38
|
+
const label = title ?? Function.pipe(name, String.capitalize);
|
|
39
39
|
|
|
40
40
|
const elementType = findArrayElementType(ast);
|
|
41
41
|
|
|
@@ -14,7 +14,7 @@ export const TextInput = ({
|
|
|
14
14
|
type,
|
|
15
15
|
label,
|
|
16
16
|
inputOnly,
|
|
17
|
-
|
|
17
|
+
readonly,
|
|
18
18
|
placeholder,
|
|
19
19
|
getStatus,
|
|
20
20
|
getValue,
|
|
@@ -23,16 +23,16 @@ export const TextInput = ({
|
|
|
23
23
|
}: InputProps) => {
|
|
24
24
|
const { status, error } = getStatus();
|
|
25
25
|
|
|
26
|
-
return
|
|
26
|
+
return readonly && !getValue() ? null : readonly === 'static' && inputOnly ? (
|
|
27
27
|
<p>{getValue() ?? ''}</p>
|
|
28
28
|
) : (
|
|
29
29
|
<Input.Root validationValence={status}>
|
|
30
30
|
{!inputOnly && <InputHeader error={error} label={label} />}
|
|
31
|
-
{
|
|
31
|
+
{readonly === 'static' ? (
|
|
32
32
|
<p>{getValue() ?? ''}</p>
|
|
33
33
|
) : (
|
|
34
34
|
<Input.TextInput
|
|
35
|
-
disabled={
|
|
35
|
+
disabled={!!readonly}
|
|
36
36
|
placeholder={placeholder}
|
|
37
37
|
value={getValue() ?? ''}
|
|
38
38
|
onChange={(event) => onValueChange(type, event.target.value)}
|
|
@@ -48,7 +48,7 @@ export const NumberInput = ({
|
|
|
48
48
|
type,
|
|
49
49
|
label,
|
|
50
50
|
inputOnly,
|
|
51
|
-
|
|
51
|
+
readonly,
|
|
52
52
|
placeholder,
|
|
53
53
|
getStatus,
|
|
54
54
|
getValue,
|
|
@@ -57,19 +57,19 @@ export const NumberInput = ({
|
|
|
57
57
|
}: InputProps) => {
|
|
58
58
|
const { status, error } = getStatus();
|
|
59
59
|
|
|
60
|
-
return
|
|
60
|
+
return readonly && !getValue() ? null : readonly === 'static' && inputOnly ? (
|
|
61
61
|
<p>{getValue() ?? ''}</p>
|
|
62
62
|
) : (
|
|
63
63
|
<Input.Root validationValence={status}>
|
|
64
64
|
{!inputOnly && <InputHeader error={error} label={label} />}
|
|
65
|
-
{
|
|
65
|
+
{readonly === 'static' ? (
|
|
66
66
|
<p>{getValue() ?? ''}</p>
|
|
67
67
|
) : (
|
|
68
68
|
<Input.TextInput
|
|
69
69
|
type='number'
|
|
70
|
-
disabled={
|
|
70
|
+
disabled={!!readonly}
|
|
71
71
|
placeholder={placeholder}
|
|
72
|
-
value={getValue()
|
|
72
|
+
value={getValue()}
|
|
73
73
|
onChange={(event) => onValueChange(type, event.target.value)}
|
|
74
74
|
onBlur={onBlur}
|
|
75
75
|
/>
|
|
@@ -79,7 +79,7 @@ export const NumberInput = ({
|
|
|
79
79
|
);
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
-
export const BooleanInput = ({ type, label, inputOnly, getStatus, getValue, onValueChange,
|
|
82
|
+
export const BooleanInput = ({ type, label, inputOnly, getStatus, getValue, onValueChange, readonly }: InputProps) => {
|
|
83
83
|
const { status, error } = getStatus();
|
|
84
84
|
const checked = Boolean(getValue());
|
|
85
85
|
const { t } = useTranslation(translationKey);
|
|
@@ -87,10 +87,10 @@ export const BooleanInput = ({ type, label, inputOnly, getStatus, getValue, onVa
|
|
|
87
87
|
return (
|
|
88
88
|
<Input.Root validationValence={status}>
|
|
89
89
|
{!inputOnly && <InputHeader error={error} label={label} />}
|
|
90
|
-
{
|
|
90
|
+
{readonly === 'static' ? (
|
|
91
91
|
<p>{t(checked ? 'boolean input true value' : 'boolean input false value')}</p>
|
|
92
92
|
) : (
|
|
93
|
-
<Input.Switch checked={checked} onCheckedChange={(value) => onValueChange(type, value)} />
|
|
93
|
+
<Input.Switch disabled={!!readonly} checked={checked} onCheckedChange={(value) => onValueChange(type, value)} />
|
|
94
94
|
)}
|
|
95
95
|
{inputOnly && <Input.DescriptionAndValidation>{error}</Input.DescriptionAndValidation>}
|
|
96
96
|
</Input.Root>
|
|
@@ -105,7 +105,7 @@ export const SelectInput = ({
|
|
|
105
105
|
type,
|
|
106
106
|
label,
|
|
107
107
|
inputOnly,
|
|
108
|
-
|
|
108
|
+
readonly,
|
|
109
109
|
placeholder,
|
|
110
110
|
options,
|
|
111
111
|
getStatus,
|
|
@@ -117,15 +117,15 @@ export const SelectInput = ({
|
|
|
117
117
|
const value = getValue() as string | undefined;
|
|
118
118
|
const handleValueChange = useCallback((value: string | number) => onValueChange(type, value), [type, onValueChange]);
|
|
119
119
|
|
|
120
|
-
return
|
|
120
|
+
return readonly && !value ? null : (
|
|
121
121
|
<Input.Root validationValence={status}>
|
|
122
122
|
{!inputOnly && <InputHeader error={error} label={label} />}
|
|
123
|
-
{
|
|
123
|
+
{readonly === 'static' ? (
|
|
124
124
|
<p>{options?.find(({ value: optionValue }) => optionValue === value)?.label ?? String(value)}</p>
|
|
125
125
|
) : (
|
|
126
126
|
<Select.Root value={value} onValueChange={handleValueChange}>
|
|
127
127
|
{/* TODO(burdon): Placeholder not working? */}
|
|
128
|
-
<Select.TriggerButton classNames='is-full' disabled={
|
|
128
|
+
<Select.TriggerButton classNames='is-full' disabled={!!readonly} placeholder={placeholder} />
|
|
129
129
|
<Select.Portal>
|
|
130
130
|
<Select.Content>
|
|
131
131
|
<Select.Viewport>
|
|
@@ -136,6 +136,7 @@ export const SelectInput = ({
|
|
|
136
136
|
</Select.Option>
|
|
137
137
|
))}
|
|
138
138
|
</Select.Viewport>
|
|
139
|
+
<Select.Arrow />
|
|
139
140
|
</Select.Content>
|
|
140
141
|
</Select.Portal>
|
|
141
142
|
</Select.Root>
|
|
@@ -149,7 +150,7 @@ export const MarkdownInput = ({
|
|
|
149
150
|
type,
|
|
150
151
|
label,
|
|
151
152
|
inputOnly,
|
|
152
|
-
|
|
153
|
+
readonly,
|
|
153
154
|
placeholder,
|
|
154
155
|
getStatus,
|
|
155
156
|
getValue,
|
|
@@ -183,15 +184,15 @@ export const MarkdownInput = ({
|
|
|
183
184
|
return (
|
|
184
185
|
<Input.Root validationValence={status}>
|
|
185
186
|
{!inputOnly && <InputHeader error={error} label={label} />}
|
|
186
|
-
{
|
|
187
|
+
{readonly === 'static' ? (
|
|
187
188
|
<p>{getValue() ?? ''}</p>
|
|
188
189
|
) : (
|
|
189
190
|
<Input.TextArea
|
|
190
191
|
ref={textareaRef}
|
|
191
|
-
disabled={
|
|
192
|
+
disabled={!!readonly}
|
|
192
193
|
placeholder={placeholder}
|
|
193
194
|
value={getValue() ?? ''}
|
|
194
|
-
classNames={'min-bs-auto max-
|
|
195
|
+
classNames={'min-bs-auto max-bs-40 overflow-auto'}
|
|
195
196
|
onChange={(event) => onValueChange(type, event.target.value)}
|
|
196
197
|
onBlur={onBlur}
|
|
197
198
|
style={{ resize: 'none' }}
|