@dxos/react-ui-form 0.7.5-labs.e27f9b9 → 0.7.5-main.2567c87
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 +467 -726
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +506 -750
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +467 -726
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/Form/Defaults.d.ts +6 -5
- package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +21 -12
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +1 -2
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/Input.d.ts +6 -5
- package/dist/types/src/components/Form/Input.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +2 -1
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/TupleInput.d.ts +2 -1
- package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/index.d.ts +0 -1
- package/dist/types/src/components/Form/custom/index.d.ts.map +1 -1
- package/dist/types/src/components/Form/factory.d.ts +2 -2
- package/dist/types/src/components/Form/factory.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/deprecated/FormInput.d.ts +0 -5
- package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
- package/dist/types/src/hooks/useForm.d.ts +11 -10
- package/dist/types/src/hooks/useForm.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +0 -6
- package/dist/types/src/translations.d.ts.map +1 -1
- package/package.json +27 -28
- package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
- package/src/components/FieldEditor/FieldEditor.tsx +6 -7
- package/src/components/Form/Defaults.tsx +33 -20
- package/src/components/Form/Form.stories.tsx +5 -15
- package/src/components/Form/Form.tsx +355 -46
- package/src/components/Form/Input.tsx +6 -5
- package/src/components/Form/custom/GeoPointInput.tsx +15 -6
- package/src/components/Form/custom/TupleInput.tsx +9 -5
- package/src/components/Form/custom/index.ts +0 -1
- package/src/components/Form/factory.tsx +5 -2
- package/src/components/ViewEditor/ViewEditor.tsx +2 -5
- package/src/components/deprecated/FormInput.tsx +7 -20
- package/src/hooks/useForm.ts +49 -57
- package/src/translations.ts +0 -8
- package/dist/types/src/components/Form/ArrayField.d.ts +0 -16
- package/dist/types/src/components/Form/ArrayField.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormActions.d.ts +0 -7
- package/dist/types/src/components/Form/FormActions.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormContent.d.ts +0 -26
- package/dist/types/src/components/Form/FormContent.d.ts.map +0 -1
- package/dist/types/src/components/Form/FormContext.d.ts +0 -20
- package/dist/types/src/components/Form/FormContext.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +0 -4
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +0 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +0 -7
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +0 -1
- package/src/components/Form/ArrayField.tsx +0 -111
- package/src/components/Form/FormActions.tsx +0 -41
- package/src/components/Form/FormContent.tsx +0 -173
- package/src/components/Form/FormContext.tsx +0 -48
- package/src/components/Form/custom/SelectOptionsInput.stories.tsx +0 -58
- package/src/components/Form/custom/SelectOptionsInput.tsx +0 -192
|
@@ -37,7 +37,6 @@ var translations_default = [
|
|
|
37
37
|
"format ref": "Reference",
|
|
38
38
|
"format regex": "RegExp",
|
|
39
39
|
"format string": "String",
|
|
40
|
-
"format single-select": "Select",
|
|
41
40
|
"format text": "Long text",
|
|
42
41
|
"format time": "Time",
|
|
43
42
|
"format timestamp": "Timestamp",
|
|
@@ -47,13 +46,7 @@ var translations_default = [
|
|
|
47
46
|
"format uuid": "UUID",
|
|
48
47
|
// Placeholders
|
|
49
48
|
"placeholder latitude": "Latitude",
|
|
50
|
-
"placeholder longitude": "Longitude"
|
|
51
|
-
// SelectOptionsInput
|
|
52
|
-
"select option label": "Label",
|
|
53
|
-
"select option label placeholder": "Option label",
|
|
54
|
-
"select option color": "Color",
|
|
55
|
-
"select option delete": "Delete",
|
|
56
|
-
"select option add": "Add option"
|
|
49
|
+
"placeholder longitude": "Longitude"
|
|
57
50
|
}
|
|
58
51
|
}
|
|
59
52
|
}
|
|
@@ -62,16 +55,6 @@ var translations_default = [
|
|
|
62
55
|
// packages/ui/react-ui-form/src/components/deprecated/FormInput.tsx
|
|
63
56
|
import React from "react";
|
|
64
57
|
import { Input } from "@dxos/react-ui";
|
|
65
|
-
import { mx, textBlockWidth } from "@dxos/react-ui-theme";
|
|
66
|
-
var DeprecatedFormContainer = ({ children, classNames }) => {
|
|
67
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
68
|
-
role: "none",
|
|
69
|
-
className: "w-full p-4 justify-center overflow-x-hidden overflow-y-auto"
|
|
70
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
71
|
-
role: "form",
|
|
72
|
-
className: mx("flex flex-col", textBlockWidth, classNames)
|
|
73
|
-
}, children));
|
|
74
|
-
};
|
|
75
58
|
var DeprecatedFormInput = ({ label, description, secondary, children }) => {
|
|
76
59
|
const primary = /* @__PURE__ */ React.createElement("div", {
|
|
77
60
|
role: "none",
|
|
@@ -80,32 +63,30 @@ var DeprecatedFormInput = ({ label, description, secondary, children }) => {
|
|
|
80
63
|
role: "none",
|
|
81
64
|
className: "flex flex-col w-full"
|
|
82
65
|
}, /* @__PURE__ */ React.createElement(Input.Label, {
|
|
83
|
-
classNames: "flex min-
|
|
84
|
-
style: {
|
|
85
|
-
fontSize: "unset"
|
|
86
|
-
}
|
|
66
|
+
classNames: "flex min-h-[40px] items-center"
|
|
87
67
|
}, label), description && /* @__PURE__ */ React.createElement(Input.DescriptionAndValidation, {
|
|
88
68
|
classNames: "mbs-0.5"
|
|
89
69
|
}, /* @__PURE__ */ React.createElement(Input.Description, null, description))), /* @__PURE__ */ React.createElement("div", {
|
|
90
70
|
role: "none"
|
|
91
71
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
92
72
|
role: "none",
|
|
93
|
-
className: "flex min-
|
|
73
|
+
className: "flex min-h-[40px] items-center"
|
|
94
74
|
}, children))));
|
|
95
75
|
if (secondary) {
|
|
96
76
|
return /* @__PURE__ */ React.createElement("div", {
|
|
97
|
-
role: "none"
|
|
77
|
+
role: "none",
|
|
78
|
+
className: "flex flex-col w-full"
|
|
98
79
|
}, primary, secondary);
|
|
99
80
|
}
|
|
100
81
|
return primary;
|
|
101
82
|
};
|
|
102
83
|
|
|
103
84
|
// packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
|
|
104
|
-
import
|
|
85
|
+
import React7, { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo3, useState as useState2 } from "react";
|
|
105
86
|
import { FormatEnum as FormatEnum2, FormatEnums, formatToType } from "@dxos/echo-schema";
|
|
106
|
-
import { log as
|
|
107
|
-
import { useTranslation as
|
|
108
|
-
import { getFormatSchema, getSchemaProperties as
|
|
87
|
+
import { log as log3 } from "@dxos/log";
|
|
88
|
+
import { useTranslation as useTranslation3 } from "@dxos/react-ui";
|
|
89
|
+
import { getFormatSchema, getSchemaProperties as getSchemaProperties2, sortProperties } from "@dxos/schema";
|
|
109
90
|
|
|
110
91
|
// packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
|
|
111
92
|
import React3 from "react";
|
|
@@ -132,10 +113,10 @@ var InputHeader = ({ children, error }) => {
|
|
|
132
113
|
};
|
|
133
114
|
|
|
134
115
|
// packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
|
|
135
|
-
var GeoPointInput = ({ type, label, disabled, getStatus, getValue:
|
|
116
|
+
var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
|
|
136
117
|
const { t } = useTranslation(translationKey);
|
|
137
|
-
const { status, error } = getStatus();
|
|
138
|
-
const [lng = 0, lat = 0] =
|
|
118
|
+
const { status, error } = getStatus?.(property);
|
|
119
|
+
const [lng = 0, lat = 0] = getValue2(property) ?? [];
|
|
139
120
|
return /* @__PURE__ */ React3.createElement(Input2.Root, {
|
|
140
121
|
validationValence: status
|
|
141
122
|
}, /* @__PURE__ */ React3.createElement(InputHeader, {
|
|
@@ -147,7 +128,7 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
147
128
|
disabled,
|
|
148
129
|
placeholder: t("placeholder longitude"),
|
|
149
130
|
value: lng,
|
|
150
|
-
onChange: (event) => onValueChange(type, [
|
|
131
|
+
onChange: (event) => onValueChange(property, type, [
|
|
151
132
|
lat,
|
|
152
133
|
safeParseFloat(event.target.value, 0)
|
|
153
134
|
]),
|
|
@@ -157,7 +138,7 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
157
138
|
disabled,
|
|
158
139
|
placeholder: t("placeholder latitude"),
|
|
159
140
|
value: lat,
|
|
160
|
-
onChange: (event) => onValueChange(type, [
|
|
141
|
+
onChange: (event) => onValueChange(property, type, [
|
|
161
142
|
safeParseFloat(event.target.value, 0),
|
|
162
143
|
lng
|
|
163
144
|
]),
|
|
@@ -165,193 +146,10 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
|
|
|
165
146
|
})));
|
|
166
147
|
};
|
|
167
148
|
|
|
168
|
-
// packages/ui/react-ui-form/src/components/Form/custom/SelectOptionsInput.tsx
|
|
169
|
-
import React4, { useCallback, useEffect, useState, useRef } from "react";
|
|
170
|
-
import { PublicKey } from "@dxos/keys";
|
|
171
|
-
import { Icon as Icon2, IconButton, Input as Input3, Tag, Toolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
172
|
-
import { List } from "@dxos/react-ui-list";
|
|
173
|
-
import { HuePickerToolbarButton } from "@dxos/react-ui-pickers";
|
|
174
|
-
import { hueTokenThemes, mx as mx2 } from "@dxos/react-ui-theme";
|
|
175
|
-
var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
|
|
176
|
-
const [selected, setSelectedId] = useState(null);
|
|
177
|
-
const [isNewOption, setIsNewOption] = useState(false);
|
|
178
|
-
const inputRef = useRef(null);
|
|
179
|
-
const { t } = useTranslation2(translationKey);
|
|
180
|
-
const { status, error } = getStatus();
|
|
181
|
-
const options = getValue3();
|
|
182
|
-
useEffect(() => {
|
|
183
|
-
if (options === void 0) {
|
|
184
|
-
onValueChange(type, []);
|
|
185
|
-
}
|
|
186
|
-
}, [
|
|
187
|
-
options,
|
|
188
|
-
onValueChange,
|
|
189
|
-
type
|
|
190
|
-
]);
|
|
191
|
-
const randomHue = () => {
|
|
192
|
-
const usedHues = new Set(options?.map((option) => option.color) ?? []);
|
|
193
|
-
const hueKeys = Object.keys(hueTokenThemes);
|
|
194
|
-
const unusedHues = hueKeys.filter((hue) => !usedHues.has(hue));
|
|
195
|
-
if (unusedHues.length > 0) {
|
|
196
|
-
return unusedHues[Math.floor(Math.random() * unusedHues.length)];
|
|
197
|
-
}
|
|
198
|
-
const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
|
|
199
|
-
const availableHues = hueKeys.filter((hue) => !lastThree.has(hue));
|
|
200
|
-
return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hueKeys[Math.floor(Math.random() * hueKeys.length)];
|
|
201
|
-
};
|
|
202
|
-
const handleAdd = useCallback(() => {
|
|
203
|
-
const newId = PublicKey.random().truncate();
|
|
204
|
-
const newOption = {
|
|
205
|
-
id: newId,
|
|
206
|
-
title: "",
|
|
207
|
-
color: randomHue()
|
|
208
|
-
};
|
|
209
|
-
onValueChange(type, [
|
|
210
|
-
...options ?? [],
|
|
211
|
-
newOption
|
|
212
|
-
]);
|
|
213
|
-
setSelectedId(newId);
|
|
214
|
-
setIsNewOption(true);
|
|
215
|
-
}, [
|
|
216
|
-
options,
|
|
217
|
-
type,
|
|
218
|
-
onValueChange
|
|
219
|
-
]);
|
|
220
|
-
const handleDelete = useCallback((id) => {
|
|
221
|
-
const newOptions = options?.filter((option) => option.id !== id) ?? [];
|
|
222
|
-
onValueChange(type, newOptions);
|
|
223
|
-
setSelectedId(null);
|
|
224
|
-
}, [
|
|
225
|
-
options,
|
|
226
|
-
type,
|
|
227
|
-
onValueChange
|
|
228
|
-
]);
|
|
229
|
-
const handleMove = useCallback((from, to) => {
|
|
230
|
-
if (!options) {
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
const newOptions = [
|
|
234
|
-
...options
|
|
235
|
-
];
|
|
236
|
-
const [removed] = newOptions.splice(from, 1);
|
|
237
|
-
newOptions.splice(to, 0, removed);
|
|
238
|
-
onValueChange(type, newOptions);
|
|
239
|
-
}, [
|
|
240
|
-
options,
|
|
241
|
-
type,
|
|
242
|
-
onValueChange
|
|
243
|
-
]);
|
|
244
|
-
const handleClick = useCallback((id) => {
|
|
245
|
-
setSelectedId((current) => current === id ? null : id);
|
|
246
|
-
}, []);
|
|
247
|
-
const handleTitleChange = useCallback((id) => (e) => {
|
|
248
|
-
const newOptions = options?.map((o) => o.id === id ? {
|
|
249
|
-
...o,
|
|
250
|
-
title: e.target.value
|
|
251
|
-
} : o);
|
|
252
|
-
onValueChange(type, newOptions ?? []);
|
|
253
|
-
}, [
|
|
254
|
-
options,
|
|
255
|
-
type,
|
|
256
|
-
onValueChange
|
|
257
|
-
]);
|
|
258
|
-
const handleKeyDown = useCallback((e) => {
|
|
259
|
-
if (e.key === "Enter") {
|
|
260
|
-
setSelectedId(null);
|
|
261
|
-
}
|
|
262
|
-
}, []);
|
|
263
|
-
const handleColorChange = useCallback((id) => (hue) => {
|
|
264
|
-
const newOptions = options?.map((o) => o.id === id ? {
|
|
265
|
-
...o,
|
|
266
|
-
color: hue
|
|
267
|
-
} : o);
|
|
268
|
-
onValueChange(type, newOptions ?? []);
|
|
269
|
-
}, [
|
|
270
|
-
options,
|
|
271
|
-
type,
|
|
272
|
-
onValueChange
|
|
273
|
-
]);
|
|
274
|
-
useEffect(() => {
|
|
275
|
-
if (selected && isNewOption && inputRef.current) {
|
|
276
|
-
inputRef.current.focus();
|
|
277
|
-
setIsNewOption(false);
|
|
278
|
-
}
|
|
279
|
-
}, [
|
|
280
|
-
selected,
|
|
281
|
-
isNewOption
|
|
282
|
-
]);
|
|
283
|
-
return /* @__PURE__ */ React4.createElement(Input3.Root, {
|
|
284
|
-
validationValence: status
|
|
285
|
-
}, /* @__PURE__ */ React4.createElement(InputHeader, {
|
|
286
|
-
error
|
|
287
|
-
}, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
|
|
288
|
-
role: "none"
|
|
289
|
-
}, options && /* @__PURE__ */ React4.createElement(List.Root, {
|
|
290
|
-
items: options,
|
|
291
|
-
isItem: (item) => true,
|
|
292
|
-
onMove: handleMove
|
|
293
|
-
}, ({ items }) => /* @__PURE__ */ React4.createElement("div", {
|
|
294
|
-
role: "list",
|
|
295
|
-
className: "w-full overflow-auto"
|
|
296
|
-
}, items?.map((item) => /* @__PURE__ */ React4.createElement("div", {
|
|
297
|
-
key: item.id
|
|
298
|
-
}, /* @__PURE__ */ React4.createElement(List.Item, {
|
|
299
|
-
role: "button",
|
|
300
|
-
item,
|
|
301
|
-
classNames: mx2("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
|
|
302
|
-
"aria-expanded": selected === item.id
|
|
303
|
-
}, /* @__PURE__ */ React4.createElement("div", {
|
|
304
|
-
className: "flex items-center"
|
|
305
|
-
}, /* @__PURE__ */ React4.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React4.createElement(List.ItemTitle, {
|
|
306
|
-
onClick: () => handleClick(item.id),
|
|
307
|
-
classNames: "flex-1"
|
|
308
|
-
}, /* @__PURE__ */ React4.createElement(Tag, {
|
|
309
|
-
palette: item.color
|
|
310
|
-
}, item.title || "\u200B")), /* @__PURE__ */ React4.createElement(Icon2, {
|
|
311
|
-
icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
|
|
312
|
-
onClick: () => handleClick(item.id)
|
|
313
|
-
})), selected === item.id && /* @__PURE__ */ React4.createElement("div", {
|
|
314
|
-
className: "mis-4 mbs-2 flex flex-col gap-1"
|
|
315
|
-
}, /* @__PURE__ */ React4.createElement(Input3.Label, {
|
|
316
|
-
classNames: "text-xs"
|
|
317
|
-
}, t("select option label")), /* @__PURE__ */ React4.createElement("div", {
|
|
318
|
-
className: "flex flex-row items-center gap-1"
|
|
319
|
-
}, /* @__PURE__ */ React4.createElement(Input3.TextInput, {
|
|
320
|
-
placeholder: t("select option label placeholder"),
|
|
321
|
-
ref: selected === item.id ? inputRef : void 0,
|
|
322
|
-
value: item.title,
|
|
323
|
-
onChange: handleTitleChange(item.id),
|
|
324
|
-
onKeyDown: handleKeyDown,
|
|
325
|
-
classNames: "flex-1"
|
|
326
|
-
}), /* @__PURE__ */ React4.createElement(Toolbar.Root, {
|
|
327
|
-
classNames: "p-0 m-0 !is-auto"
|
|
328
|
-
}, /* @__PURE__ */ React4.createElement(HuePickerToolbarButton, {
|
|
329
|
-
hue: item.color,
|
|
330
|
-
onChangeHue: handleColorChange(item.id)
|
|
331
|
-
})), /* @__PURE__ */ React4.createElement(IconButton, {
|
|
332
|
-
icon: "ph--trash--fill",
|
|
333
|
-
iconOnly: true,
|
|
334
|
-
label: t("select option delete"),
|
|
335
|
-
onClick: () => handleDelete(item.id)
|
|
336
|
-
})))))), /* @__PURE__ */ React4.createElement("div", {
|
|
337
|
-
role: "listitem"
|
|
338
|
-
}, /* @__PURE__ */ React4.createElement("div", {
|
|
339
|
-
role: "button",
|
|
340
|
-
className: mx2("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
|
|
341
|
-
onClick: handleAdd
|
|
342
|
-
}, /* @__PURE__ */ React4.createElement("div", {
|
|
343
|
-
className: "flex items-center gap-1"
|
|
344
|
-
}, /* @__PURE__ */ React4.createElement(Icon2, {
|
|
345
|
-
icon: "ph--plus--regular"
|
|
346
|
-
}), /* @__PURE__ */ React4.createElement("span", {
|
|
347
|
-
className: "text-sm"
|
|
348
|
-
}, t("select option add")))))))));
|
|
349
|
-
};
|
|
350
|
-
|
|
351
149
|
// packages/ui/react-ui-form/src/components/Form/custom/TupleInput.tsx
|
|
352
|
-
import
|
|
353
|
-
import { Input as
|
|
354
|
-
import { mx
|
|
150
|
+
import React4 from "react";
|
|
151
|
+
import { Input as Input3 } from "@dxos/react-ui";
|
|
152
|
+
import { mx } from "@dxos/react-ui-theme";
|
|
355
153
|
import { safeParseFloat as safeParseFloat2 } from "@dxos/util";
|
|
356
154
|
var gridCols = [
|
|
357
155
|
"grid-cols-1",
|
|
@@ -359,21 +157,21 @@ var gridCols = [
|
|
|
359
157
|
"grid-cols-3",
|
|
360
158
|
"grid-cols-4"
|
|
361
159
|
];
|
|
362
|
-
var TupleInput = ({ binding, type, label, disabled, getStatus, getValue:
|
|
363
|
-
const { status, error } = getStatus();
|
|
364
|
-
const values =
|
|
365
|
-
return /* @__PURE__ */
|
|
160
|
+
var TupleInput = ({ binding, property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
|
|
161
|
+
const { status, error } = getStatus?.(property);
|
|
162
|
+
const values = getValue2(property) ?? {};
|
|
163
|
+
return /* @__PURE__ */ React4.createElement(Input3.Root, {
|
|
366
164
|
validationValence: status
|
|
367
|
-
}, /* @__PURE__ */
|
|
165
|
+
}, /* @__PURE__ */ React4.createElement(InputHeader, {
|
|
368
166
|
error
|
|
369
|
-
}, /* @__PURE__ */
|
|
370
|
-
className:
|
|
371
|
-
}, binding.map((prop) => /* @__PURE__ */
|
|
167
|
+
}, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
|
|
168
|
+
className: mx("grid gap-2", gridCols[binding.length - 1])
|
|
169
|
+
}, binding.map((prop) => /* @__PURE__ */ React4.createElement(Input3.TextInput, {
|
|
372
170
|
key: prop,
|
|
373
171
|
type: "number",
|
|
374
172
|
disabled,
|
|
375
173
|
value: values[prop],
|
|
376
|
-
onChange: (event) => onValueChange(type, {
|
|
174
|
+
onChange: (event) => onValueChange(property, type, {
|
|
377
175
|
...values,
|
|
378
176
|
[prop]: safeParseFloat2(event.target.value, 0)
|
|
379
177
|
}),
|
|
@@ -382,114 +180,118 @@ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValu
|
|
|
382
180
|
};
|
|
383
181
|
|
|
384
182
|
// packages/ui/react-ui-form/src/components/Form/Defaults.tsx
|
|
385
|
-
import
|
|
386
|
-
import { Input as
|
|
387
|
-
var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue:
|
|
388
|
-
const { status, error } = getStatus();
|
|
389
|
-
return /* @__PURE__ */
|
|
183
|
+
import React5 from "react";
|
|
184
|
+
import { Input as Input4, Select } from "@dxos/react-ui";
|
|
185
|
+
var TextInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
|
|
186
|
+
const { status, error } = getStatus?.(property);
|
|
187
|
+
return /* @__PURE__ */ React5.createElement(Input4.Root, {
|
|
390
188
|
validationValence: status
|
|
391
|
-
}, !inputOnly && /* @__PURE__ */
|
|
189
|
+
}, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
|
|
392
190
|
error
|
|
393
|
-
}, /* @__PURE__ */
|
|
191
|
+
}, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Input4.TextInput, {
|
|
394
192
|
disabled,
|
|
395
193
|
placeholder,
|
|
396
|
-
value:
|
|
397
|
-
onChange: (event) => onValueChange(type, event.target.value),
|
|
194
|
+
value: getValue2(property) ?? "",
|
|
195
|
+
onChange: (event) => onValueChange(property, type, event.target.value),
|
|
398
196
|
onBlur
|
|
399
|
-
}), inputOnly && /* @__PURE__ */
|
|
197
|
+
}), inputOnly && /* @__PURE__ */ React5.createElement(Input4.Validation, null, error));
|
|
400
198
|
};
|
|
401
|
-
var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue:
|
|
402
|
-
const { status, error } = getStatus();
|
|
403
|
-
return /* @__PURE__ */
|
|
199
|
+
var NumberInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
|
|
200
|
+
const { status, error } = getStatus?.(property);
|
|
201
|
+
return /* @__PURE__ */ React5.createElement(Input4.Root, {
|
|
404
202
|
validationValence: status
|
|
405
|
-
}, !inputOnly && /* @__PURE__ */
|
|
203
|
+
}, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
|
|
406
204
|
error
|
|
407
|
-
}, /* @__PURE__ */
|
|
205
|
+
}, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Input4.TextInput, {
|
|
408
206
|
type: "number",
|
|
409
207
|
disabled,
|
|
410
208
|
placeholder,
|
|
411
|
-
value:
|
|
412
|
-
onChange: (event) => onValueChange(type, event.target.value),
|
|
209
|
+
value: getValue2(property) ?? 0,
|
|
210
|
+
onChange: (event) => onValueChange(property, type, event.target.value),
|
|
413
211
|
onBlur
|
|
414
|
-
}), inputOnly && /* @__PURE__ */
|
|
212
|
+
}), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
|
|
415
213
|
};
|
|
416
|
-
var BooleanInput = ({ type, label, inputOnly, getStatus, getValue:
|
|
417
|
-
const { status, error } = getStatus();
|
|
418
|
-
return /* @__PURE__ */
|
|
214
|
+
var BooleanInput = ({ property, type, label, inputOnly, getStatus, getValue: getValue2, onValueChange }) => {
|
|
215
|
+
const { status, error } = getStatus?.(property);
|
|
216
|
+
return /* @__PURE__ */ React5.createElement(Input4.Root, {
|
|
419
217
|
validationValence: status
|
|
420
|
-
}, !inputOnly && /* @__PURE__ */
|
|
218
|
+
}, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
|
|
421
219
|
error
|
|
422
|
-
}, /* @__PURE__ */
|
|
423
|
-
checked:
|
|
424
|
-
onCheckedChange: (value) => onValueChange(type, value)
|
|
425
|
-
}), inputOnly && /* @__PURE__ */
|
|
220
|
+
}, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Input4.Switch, {
|
|
221
|
+
checked: getValue2(property),
|
|
222
|
+
onCheckedChange: (value) => onValueChange(property, type, value)
|
|
223
|
+
}), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
|
|
426
224
|
};
|
|
427
|
-
var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue:
|
|
428
|
-
const { status, error } = getStatus();
|
|
429
|
-
return /* @__PURE__ */
|
|
225
|
+
var SelectInput = ({ property, type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue2, onValueChange }) => {
|
|
226
|
+
const { status, error } = getStatus?.(property);
|
|
227
|
+
return /* @__PURE__ */ React5.createElement(Input4.Root, {
|
|
430
228
|
validationValence: status
|
|
431
|
-
}, !inputOnly && /* @__PURE__ */
|
|
229
|
+
}, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
|
|
432
230
|
error
|
|
433
|
-
}, /* @__PURE__ */
|
|
434
|
-
value:
|
|
435
|
-
onValueChange: (value) => onValueChange(type, value)
|
|
436
|
-
}, /* @__PURE__ */
|
|
231
|
+
}, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Select.Root, {
|
|
232
|
+
value: getValue2(property),
|
|
233
|
+
onValueChange: (value) => onValueChange(property, type, value)
|
|
234
|
+
}, /* @__PURE__ */ React5.createElement(Select.TriggerButton, {
|
|
437
235
|
classNames: "is-full",
|
|
438
236
|
disabled,
|
|
439
237
|
placeholder
|
|
440
|
-
}), /* @__PURE__ */
|
|
238
|
+
}), /* @__PURE__ */ React5.createElement(Select.Portal, null, /* @__PURE__ */ React5.createElement(Select.Content, null, /* @__PURE__ */ React5.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
|
|
441
239
|
// NOTE: Numeric values are converted to and from strings.
|
|
442
|
-
/* @__PURE__ */
|
|
240
|
+
/* @__PURE__ */ React5.createElement(Select.Option, {
|
|
443
241
|
key: String(value),
|
|
444
242
|
value: String(value)
|
|
445
243
|
}, label2 ?? String(value))
|
|
446
|
-
)))))), inputOnly && /* @__PURE__ */
|
|
244
|
+
)))))), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
|
|
447
245
|
};
|
|
448
246
|
|
|
449
247
|
// packages/ui/react-ui-form/src/components/Form/Form.tsx
|
|
450
|
-
import
|
|
451
|
-
import {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
import
|
|
455
|
-
import {
|
|
456
|
-
import {
|
|
248
|
+
import { pipe } from "effect";
|
|
249
|
+
import { capitalize } from "effect/String";
|
|
250
|
+
import React6, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
|
|
251
|
+
import { AST, S } from "@dxos/echo-schema";
|
|
252
|
+
import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
|
|
253
|
+
import { log as log2 } from "@dxos/log";
|
|
254
|
+
import { IconButton, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
255
|
+
import { mx as mx2 } from "@dxos/react-ui-theme";
|
|
256
|
+
import { getSchemaProperties } from "@dxos/schema";
|
|
257
|
+
import { isNotFalsy } from "@dxos/util";
|
|
457
258
|
|
|
458
|
-
// packages/ui/react-ui-form/src/components/Form/
|
|
459
|
-
import
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
259
|
+
// packages/ui/react-ui-form/src/components/Form/factory.tsx
|
|
260
|
+
import { FormatEnum } from "@dxos/echo-schema";
|
|
261
|
+
var getInputComponent = (type, format) => {
|
|
262
|
+
switch (format) {
|
|
263
|
+
case FormatEnum.LatLng:
|
|
264
|
+
return GeoPointInput;
|
|
265
|
+
}
|
|
266
|
+
switch (type) {
|
|
267
|
+
case "string":
|
|
268
|
+
return TextInput;
|
|
269
|
+
case "number":
|
|
270
|
+
return NumberInput;
|
|
271
|
+
case "boolean":
|
|
272
|
+
return BooleanInput;
|
|
273
|
+
}
|
|
274
|
+
};
|
|
463
275
|
|
|
464
276
|
// packages/ui/react-ui-form/src/hooks/useForm.ts
|
|
465
|
-
import { useCallback
|
|
277
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
466
278
|
import { getValue, setValue } from "@dxos/echo-schema";
|
|
467
|
-
import { AST, createJsonPath, fromEffectValidationPath } from "@dxos/effect";
|
|
468
279
|
import { invariant } from "@dxos/invariant";
|
|
469
280
|
import { log } from "@dxos/log";
|
|
470
281
|
import { validateSchema } from "@dxos/schema";
|
|
471
282
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
|
|
472
283
|
var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
L: 91,
|
|
476
|
-
S: void 0,
|
|
477
|
-
A: [
|
|
478
|
-
"AST.isTypeLiteral(schema.ast)",
|
|
479
|
-
""
|
|
480
|
-
]
|
|
481
|
-
});
|
|
482
|
-
const [values, setValues] = useState2(initialValues);
|
|
483
|
-
useEffect2(() => {
|
|
284
|
+
const [values, setValues] = useState(initialValues);
|
|
285
|
+
useEffect(() => {
|
|
484
286
|
setValues(initialValues);
|
|
485
287
|
}, [
|
|
486
288
|
initialValues
|
|
487
289
|
]);
|
|
488
|
-
const [touched, setTouched] =
|
|
489
|
-
const [changed, setChanged] =
|
|
490
|
-
const [errors, setErrors] =
|
|
491
|
-
const [saving, setSaving] =
|
|
492
|
-
const validate =
|
|
290
|
+
const [touched, setTouched] = useState(createKeySet(initialValues, false));
|
|
291
|
+
const [changed, setChanged] = useState(createKeySet(initialValues, false));
|
|
292
|
+
const [errors, setErrors] = useState({});
|
|
293
|
+
const [saving, setSaving] = useState(false);
|
|
294
|
+
const validate = useCallback((values2) => {
|
|
493
295
|
let errors2 = validateSchema(schema, values2) ?? [];
|
|
494
296
|
if (errors2.length === 0 && onValidate) {
|
|
495
297
|
const validatedValues = values2;
|
|
@@ -502,11 +304,11 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
502
304
|
schema,
|
|
503
305
|
onValidate
|
|
504
306
|
]);
|
|
505
|
-
const [schemaDirty, setSchemaDirty] =
|
|
506
|
-
|
|
307
|
+
const [schemaDirty, setSchemaDirty] = useState(false);
|
|
308
|
+
useEffect(() => setSchemaDirty(true), [
|
|
507
309
|
schema
|
|
508
310
|
]);
|
|
509
|
-
|
|
311
|
+
useEffect(() => {
|
|
510
312
|
if (schemaDirty) {
|
|
511
313
|
validate(values);
|
|
512
314
|
setSchemaDirty(false);
|
|
@@ -515,13 +317,13 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
515
317
|
values,
|
|
516
318
|
schemaDirty
|
|
517
319
|
]);
|
|
518
|
-
const canSave = useMemo(() => !saving &&
|
|
519
|
-
|
|
320
|
+
const canSave = useMemo(() => !saving && Object.keys(values).every((property) => touched[property] === false || !errors[property]), [
|
|
321
|
+
values,
|
|
520
322
|
touched,
|
|
521
323
|
errors,
|
|
522
324
|
saving
|
|
523
325
|
]);
|
|
524
|
-
const handleSave =
|
|
326
|
+
const handleSave = useCallback(async () => {
|
|
525
327
|
if (validate(values)) {
|
|
526
328
|
setSaving(true);
|
|
527
329
|
try {
|
|
@@ -538,21 +340,17 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
538
340
|
onSave,
|
|
539
341
|
changed
|
|
540
342
|
]);
|
|
541
|
-
const getStatus =
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
error: matchingError ? matchingError[1] : void 0
|
|
547
|
-
};
|
|
548
|
-
}, [
|
|
343
|
+
const getStatus = useCallback((property) => ({
|
|
344
|
+
status: errors[property] ? "error" : void 0,
|
|
345
|
+
error: errors[property] ? errors[property] : void 0
|
|
346
|
+
}), [
|
|
347
|
+
touched,
|
|
549
348
|
errors
|
|
550
349
|
]);
|
|
551
|
-
const getFormValue = (
|
|
552
|
-
return getValue(values,
|
|
350
|
+
const getFormValue = (property) => {
|
|
351
|
+
return getValue(values, property);
|
|
553
352
|
};
|
|
554
|
-
const onValueChange = (
|
|
555
|
-
const jsonPath = createJsonPath(path);
|
|
353
|
+
const onValueChange = (property, type, value) => {
|
|
556
354
|
let parsedValue = value;
|
|
557
355
|
try {
|
|
558
356
|
if (type === "number") {
|
|
@@ -561,19 +359,19 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
561
359
|
} catch (err) {
|
|
562
360
|
log.catch(err, void 0, {
|
|
563
361
|
F: __dxlog_file,
|
|
564
|
-
L:
|
|
362
|
+
L: 178,
|
|
565
363
|
S: void 0,
|
|
566
364
|
C: (f, a) => f(...a)
|
|
567
365
|
});
|
|
568
366
|
parsedValue = void 0;
|
|
569
367
|
}
|
|
570
368
|
const newValues = {
|
|
571
|
-
...setValue(values,
|
|
369
|
+
...setValue(values, property, parsedValue)
|
|
572
370
|
};
|
|
573
371
|
setValues(newValues);
|
|
574
372
|
setChanged((prev) => ({
|
|
575
373
|
...prev,
|
|
576
|
-
[
|
|
374
|
+
[property]: true
|
|
577
375
|
}));
|
|
578
376
|
onValuesChanged?.(newValues);
|
|
579
377
|
const isValid = validate(newValues);
|
|
@@ -583,12 +381,15 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
583
381
|
});
|
|
584
382
|
}
|
|
585
383
|
};
|
|
586
|
-
const
|
|
587
|
-
const
|
|
384
|
+
const onBlur = useCallback((event) => {
|
|
385
|
+
const { name } = event.target;
|
|
588
386
|
setTouched((touched2) => ({
|
|
589
387
|
...touched2,
|
|
590
|
-
[
|
|
388
|
+
[name]: true
|
|
591
389
|
}));
|
|
390
|
+
if (event.relatedTarget?.getAttribute("type") === "submit") {
|
|
391
|
+
setTouched(createKeySet(values, true));
|
|
392
|
+
}
|
|
592
393
|
validate(values);
|
|
593
394
|
}, [
|
|
594
395
|
validate,
|
|
@@ -606,13 +407,13 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
606
407
|
getStatus,
|
|
607
408
|
getValue: getFormValue,
|
|
608
409
|
onValueChange,
|
|
609
|
-
|
|
410
|
+
onBlur
|
|
610
411
|
};
|
|
611
412
|
};
|
|
612
413
|
var createKeySet = (obj, value) => {
|
|
613
414
|
invariant(obj, void 0, {
|
|
614
415
|
F: __dxlog_file,
|
|
615
|
-
L:
|
|
416
|
+
L: 229,
|
|
616
417
|
S: void 0,
|
|
617
418
|
A: [
|
|
618
419
|
"obj",
|
|
@@ -626,392 +427,338 @@ var createKeySet = (obj, value) => {
|
|
|
626
427
|
};
|
|
627
428
|
var flatMap = (errors) => {
|
|
628
429
|
return errors.reduce((result, { path, message }) => {
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
result[jsonPath] = message;
|
|
430
|
+
if (!(path in result)) {
|
|
431
|
+
result[path] = message;
|
|
632
432
|
}
|
|
633
433
|
return result;
|
|
634
434
|
}, {});
|
|
635
435
|
};
|
|
636
436
|
|
|
637
|
-
// packages/ui/react-ui-form/src/components/Form/
|
|
638
|
-
var
|
|
639
|
-
var useFormContext = () => {
|
|
640
|
-
return useContext(FormContext) ?? raise(new Error("Missing FormContext"));
|
|
641
|
-
};
|
|
642
|
-
var useFormValues = (path = []) => {
|
|
643
|
-
const { values: formValues } = useFormContext();
|
|
644
|
-
const jsonPath = createJsonPath2(path);
|
|
645
|
-
return getValue2(formValues, jsonPath);
|
|
646
|
-
};
|
|
647
|
-
var useInputProps = (path = []) => {
|
|
648
|
-
const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
|
|
649
|
-
return {
|
|
650
|
-
getStatus: () => getStatus(path),
|
|
651
|
-
getValue: () => getFormValue(path),
|
|
652
|
-
onValueChange: (type, value) => onValueChange(path, type, value),
|
|
653
|
-
onBlur: () => onTouched(path)
|
|
654
|
-
};
|
|
655
|
-
};
|
|
656
|
-
var FormProvider = ({ children, ...formOptions }) => {
|
|
657
|
-
const formHandler = useForm(formOptions);
|
|
658
|
-
return /* @__PURE__ */ React7.createElement(FormContext.Provider, {
|
|
659
|
-
value: formHandler
|
|
660
|
-
}, children);
|
|
661
|
-
};
|
|
662
|
-
|
|
663
|
-
// packages/ui/react-ui-form/src/components/Form/FormActions.tsx
|
|
664
|
-
var FormActions = ({ onCancel, readonly }) => {
|
|
665
|
-
const { t } = useTranslation3(translationKey);
|
|
666
|
-
const { canSave, handleSave } = useFormContext();
|
|
667
|
-
return /* @__PURE__ */ React8.createElement("div", {
|
|
668
|
-
role: "none",
|
|
669
|
-
className: "flex justify-center"
|
|
670
|
-
}, /* @__PURE__ */ React8.createElement("div", {
|
|
671
|
-
role: "none",
|
|
672
|
-
className: mx4(onCancel && !readonly && "grid grid-cols-2 gap-2")
|
|
673
|
-
}, onCancel && !readonly && /* @__PURE__ */ React8.createElement(IconButton2, {
|
|
674
|
-
"data-testid": "cancel-button",
|
|
675
|
-
icon: "ph--x--regular",
|
|
676
|
-
label: t("button cancel"),
|
|
677
|
-
onClick: onCancel
|
|
678
|
-
}), handleSave && /* @__PURE__ */ React8.createElement(IconButton2, {
|
|
679
|
-
type: "submit",
|
|
680
|
-
"data-testid": "save-button",
|
|
681
|
-
disabled: !canSave,
|
|
682
|
-
icon: "ph--check--regular",
|
|
683
|
-
label: t("button save"),
|
|
684
|
-
onClick: handleSave
|
|
685
|
-
})));
|
|
686
|
-
};
|
|
687
|
-
|
|
688
|
-
// packages/ui/react-ui-form/src/components/Form/FormContent.tsx
|
|
689
|
-
import { pipe as pipe2 } from "effect";
|
|
690
|
-
import { capitalize as capitalize2 } from "effect/String";
|
|
691
|
-
import React10, { useMemo as useMemo3 } from "react";
|
|
692
|
-
import { AST as AST3, S } from "@dxos/echo-schema";
|
|
693
|
-
import { createJsonPath as createJsonPath3, findNode as findNode2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
|
|
694
|
-
import { mx as mx6 } from "@dxos/react-ui-theme";
|
|
695
|
-
import { getSchemaProperties as getSchemaProperties2 } from "@dxos/schema";
|
|
696
|
-
import { isNotFalsy } from "@dxos/util";
|
|
697
|
-
|
|
698
|
-
// packages/ui/react-ui-form/src/components/Form/ArrayField.tsx
|
|
699
|
-
import { pipe } from "effect";
|
|
700
|
-
import { capitalize } from "effect/String";
|
|
701
|
-
import React9, { useCallback as useCallback3, useMemo as useMemo2 } from "react";
|
|
702
|
-
import { AST as AST2 } from "@dxos/echo-schema";
|
|
703
|
-
import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
|
|
704
|
-
import { invariant as invariant2 } from "@dxos/invariant";
|
|
705
|
-
import { IconButton as IconButton3, useTranslation as useTranslation4 } from "@dxos/react-ui";
|
|
706
|
-
import { mx as mx5 } from "@dxos/react-ui-theme";
|
|
707
|
-
import { getSchemaProperties } from "@dxos/schema";
|
|
708
|
-
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
|
|
437
|
+
// packages/ui/react-ui-form/src/components/Form/Form.tsx
|
|
438
|
+
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/Form.tsx";
|
|
709
439
|
var padding = "px-2";
|
|
710
|
-
var
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
invariant2(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
|
|
715
|
-
F: __dxlog_file2,
|
|
716
|
-
L: 37,
|
|
717
|
-
S: void 0,
|
|
718
|
-
A: [
|
|
719
|
-
"Array.isArray(values)",
|
|
720
|
-
"`Values at path ${path?.join('.')} must be an array.`"
|
|
721
|
-
]
|
|
722
|
-
});
|
|
723
|
-
const label = title ?? pipe(name, capitalize);
|
|
724
|
-
const tupleType = findNode(ast, AST2.isTupleType);
|
|
725
|
-
const elementType = tupleType?.rest[0]?.type;
|
|
726
|
-
const getDefaultObjectValue = (typeNode) => {
|
|
727
|
-
const baseNode = findNode(typeNode, isDiscriminatedUnion);
|
|
728
|
-
const typeLiteral = baseNode ? getDiscriminatedType(baseNode, {}) : findNode(typeNode, AST2.isTypeLiteral);
|
|
729
|
-
if (!typeLiteral) {
|
|
730
|
-
return {};
|
|
731
|
-
}
|
|
732
|
-
return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [
|
|
733
|
-
prop.name,
|
|
734
|
-
prop.defaultValue
|
|
735
|
-
]));
|
|
736
|
-
};
|
|
737
|
-
const newValue = useMemo2(() => {
|
|
738
|
-
if (type === "object" && elementType) {
|
|
739
|
-
return getDefaultObjectValue(elementType);
|
|
740
|
-
} else {
|
|
741
|
-
return SimpleType.getDefaultValue(type);
|
|
742
|
-
}
|
|
743
|
-
}, [
|
|
744
|
-
type,
|
|
745
|
-
elementType
|
|
440
|
+
var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
|
|
441
|
+
const onValid = useMemo2(() => autoSave ? onSave : void 0, [
|
|
442
|
+
autoSave,
|
|
443
|
+
onSave
|
|
746
444
|
]);
|
|
747
|
-
const
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
445
|
+
const { canSave, values, errors, handleSave, ...inputProps } = useForm({
|
|
446
|
+
schema,
|
|
447
|
+
initialValues,
|
|
448
|
+
onValuesChanged,
|
|
449
|
+
onValidate,
|
|
450
|
+
onValid,
|
|
451
|
+
onSave
|
|
452
|
+
});
|
|
453
|
+
const properties = useMemo2(() => {
|
|
454
|
+
const props = getSchemaProperties(schema.ast, values);
|
|
455
|
+
const filtered = filter ? filter(props) : props;
|
|
456
|
+
const findIndex = (props2, prop) => {
|
|
457
|
+
const idx = props2.findIndex((p) => p === prop);
|
|
458
|
+
return idx === -1 ? Infinity : idx;
|
|
459
|
+
};
|
|
460
|
+
return sort ? filtered.sort(({ name: a }, { name: b }) => findIndex(sort, a) - findIndex(sort, b)) : filtered;
|
|
752
461
|
}, [
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
inputProps,
|
|
756
|
-
newValue,
|
|
462
|
+
schema,
|
|
463
|
+
filter,
|
|
757
464
|
values
|
|
758
465
|
]);
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
466
|
+
useEffect2(() => {
|
|
467
|
+
if (errors && Object.keys(errors).length) {
|
|
468
|
+
log2.warn("validation", {
|
|
469
|
+
errors
|
|
470
|
+
}, {
|
|
471
|
+
F: __dxlog_file2,
|
|
472
|
+
L: 106,
|
|
473
|
+
S: void 0,
|
|
474
|
+
C: (f, a) => f(...a)
|
|
475
|
+
});
|
|
476
|
+
}
|
|
762
477
|
}, [
|
|
763
|
-
|
|
764
|
-
inputProps,
|
|
765
|
-
values
|
|
478
|
+
errors
|
|
766
479
|
]);
|
|
767
|
-
|
|
480
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
481
|
+
role: "form",
|
|
482
|
+
className: mx2("flex flex-col w-full gap-2 py-2", classNames),
|
|
483
|
+
"data-testid": testId
|
|
484
|
+
}, properties.map((property) => {
|
|
485
|
+
const { ast, name, type, format, title, description, examples, options, array } = property;
|
|
486
|
+
const key = [
|
|
487
|
+
...path,
|
|
488
|
+
name
|
|
489
|
+
];
|
|
490
|
+
const label = title ?? pipe(name, capitalize);
|
|
491
|
+
const placeholder = examples?.length ? `Example: "${examples[0]}"` : description;
|
|
492
|
+
const FoundComponent = lookupComponent?.({
|
|
493
|
+
prop: name,
|
|
494
|
+
schema: S.make(ast),
|
|
495
|
+
inputProps: {
|
|
496
|
+
property: name,
|
|
497
|
+
type,
|
|
498
|
+
format,
|
|
499
|
+
label,
|
|
500
|
+
disabled: readonly,
|
|
501
|
+
placeholder,
|
|
502
|
+
...inputProps
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
if (FoundComponent) {
|
|
506
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
507
|
+
key: name,
|
|
508
|
+
role: "none",
|
|
509
|
+
className: padding
|
|
510
|
+
}, FoundComponent);
|
|
511
|
+
}
|
|
512
|
+
let InputComponent = Custom?.[key.join(".")];
|
|
513
|
+
if (!InputComponent) {
|
|
514
|
+
if (options) {
|
|
515
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
516
|
+
key: name,
|
|
517
|
+
role: "none",
|
|
518
|
+
className: padding
|
|
519
|
+
}, /* @__PURE__ */ React6.createElement(SelectInput, {
|
|
520
|
+
type,
|
|
521
|
+
format,
|
|
522
|
+
property: name,
|
|
523
|
+
disabled: readonly,
|
|
524
|
+
label,
|
|
525
|
+
options: options.map((option) => ({
|
|
526
|
+
value: option,
|
|
527
|
+
label: String(option)
|
|
528
|
+
})),
|
|
529
|
+
placeholder,
|
|
530
|
+
...inputProps
|
|
531
|
+
}));
|
|
532
|
+
}
|
|
533
|
+
InputComponent = getInputComponent(type, format);
|
|
534
|
+
if (array) {
|
|
535
|
+
return /* @__PURE__ */ React6.createElement(ArrayField, {
|
|
536
|
+
key: name,
|
|
537
|
+
name,
|
|
538
|
+
type,
|
|
539
|
+
array: true,
|
|
540
|
+
label,
|
|
541
|
+
ast,
|
|
542
|
+
values,
|
|
543
|
+
format,
|
|
544
|
+
readonly,
|
|
545
|
+
placeholder,
|
|
546
|
+
inputProps,
|
|
547
|
+
Custom
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
if (!InputComponent) {
|
|
552
|
+
if (type === "object") {
|
|
553
|
+
const baseNode = findNode(ast, isDiscriminatedUnion);
|
|
554
|
+
const typeLiteral = baseNode ? getDiscriminatedType(baseNode, values[name]) : findNode(ast, AST.isTypeLiteral);
|
|
555
|
+
if (typeLiteral) {
|
|
556
|
+
const schema2 = S.make(typeLiteral);
|
|
557
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
558
|
+
key: name,
|
|
559
|
+
role: "none"
|
|
560
|
+
}, /* @__PURE__ */ React6.createElement("div", {
|
|
561
|
+
className: padding
|
|
562
|
+
}, label), /* @__PURE__ */ React6.createElement(Form, {
|
|
563
|
+
schema: schema2,
|
|
564
|
+
path: key,
|
|
565
|
+
values: values[name] ?? {},
|
|
566
|
+
onValuesChanged: (childValues) => {
|
|
567
|
+
inputProps.onValueChange(name, "object", childValues);
|
|
568
|
+
},
|
|
569
|
+
Custom
|
|
570
|
+
}));
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
log2("no renderer for property", {
|
|
574
|
+
name,
|
|
575
|
+
type
|
|
576
|
+
}, {
|
|
577
|
+
F: __dxlog_file2,
|
|
578
|
+
L: 213,
|
|
579
|
+
S: void 0,
|
|
580
|
+
C: (f, a) => f(...a)
|
|
581
|
+
});
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
585
|
+
key: name,
|
|
586
|
+
role: "none",
|
|
587
|
+
className: padding
|
|
588
|
+
}, /* @__PURE__ */ React6.createElement(InputComponent, {
|
|
589
|
+
type,
|
|
590
|
+
format,
|
|
591
|
+
property: name,
|
|
592
|
+
disabled: readonly,
|
|
593
|
+
label,
|
|
594
|
+
placeholder,
|
|
595
|
+
...inputProps
|
|
596
|
+
}));
|
|
597
|
+
}).filter(isNotFalsy), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React6.createElement(FormActions, {
|
|
598
|
+
onCancel,
|
|
599
|
+
onSubmit: handleSave,
|
|
600
|
+
canSubmit: canSave,
|
|
601
|
+
readonly
|
|
602
|
+
}));
|
|
603
|
+
};
|
|
604
|
+
var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholder, inputProps, Custom }) => {
|
|
605
|
+
const { t } = useTranslation2(translationKey);
|
|
606
|
+
const arrayValues = values[name] ?? [];
|
|
607
|
+
const key = [
|
|
608
|
+
name
|
|
609
|
+
];
|
|
610
|
+
const tupleType = findNode(ast, AST.isTupleType);
|
|
611
|
+
const elementType = tupleType?.rest[0]?.type;
|
|
612
|
+
if (type === "object" && elementType) {
|
|
613
|
+
const baseNode = findNode(elementType, isDiscriminatedUnion);
|
|
614
|
+
const typeLiteral = baseNode ? getDiscriminatedType(baseNode, values[name]) : findNode(elementType, AST.isTypeLiteral);
|
|
615
|
+
if (typeLiteral) {
|
|
616
|
+
const schema = S.make(typeLiteral);
|
|
617
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
618
|
+
key: name,
|
|
619
|
+
role: "none",
|
|
620
|
+
className: mx2(padding)
|
|
621
|
+
}, /* @__PURE__ */ React6.createElement(InputHeader, null, label), /* @__PURE__ */ React6.createElement("div", {
|
|
622
|
+
role: "none",
|
|
623
|
+
className: "flex flex-col gap-1"
|
|
624
|
+
}, arrayValues.map((value, index) => {
|
|
625
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
626
|
+
key: index,
|
|
627
|
+
role: "none",
|
|
628
|
+
className: "flex items-center gap-1"
|
|
629
|
+
}, /* @__PURE__ */ React6.createElement("div", {
|
|
630
|
+
role: "none",
|
|
631
|
+
className: "flex-1"
|
|
632
|
+
}, /* @__PURE__ */ React6.createElement(Form, {
|
|
633
|
+
schema,
|
|
634
|
+
path: [
|
|
635
|
+
...key,
|
|
636
|
+
`[${index}]`
|
|
637
|
+
],
|
|
638
|
+
values: value,
|
|
639
|
+
onValuesChanged: (childValues) => {
|
|
640
|
+
const newValues = [
|
|
641
|
+
...arrayValues
|
|
642
|
+
];
|
|
643
|
+
newValues[index] = childValues;
|
|
644
|
+
inputProps.onValueChange(name, "object", newValues);
|
|
645
|
+
},
|
|
646
|
+
Custom
|
|
647
|
+
})), /* @__PURE__ */ React6.createElement(IconButton, {
|
|
648
|
+
icon: "ph--trash--regular",
|
|
649
|
+
iconOnly: true,
|
|
650
|
+
label: t("button remove"),
|
|
651
|
+
onClick: () => {
|
|
652
|
+
const newValues = arrayValues.filter((_, i) => i !== index);
|
|
653
|
+
inputProps.onValueChange(name, type, newValues);
|
|
654
|
+
}
|
|
655
|
+
}));
|
|
656
|
+
})), /* @__PURE__ */ React6.createElement("div", {
|
|
657
|
+
role: "none",
|
|
658
|
+
className: "flex justify-between items-center plb-1"
|
|
659
|
+
}, /* @__PURE__ */ React6.createElement(IconButton, {
|
|
660
|
+
icon: "ph--plus--regular",
|
|
661
|
+
iconOnly: true,
|
|
662
|
+
label: t("button add"),
|
|
663
|
+
onClick: () => {
|
|
664
|
+
const newValues = [
|
|
665
|
+
...arrayValues,
|
|
666
|
+
{}
|
|
667
|
+
];
|
|
668
|
+
inputProps.onValueChange(name, type, newValues);
|
|
669
|
+
}
|
|
670
|
+
})));
|
|
671
|
+
}
|
|
672
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
673
|
+
key: name,
|
|
674
|
+
role: "none"
|
|
675
|
+
}, "Nested form not supported in arrays, yet.");
|
|
676
|
+
}
|
|
677
|
+
const InputComponent = getInputComponent(type, format);
|
|
678
|
+
if (!InputComponent) {
|
|
768
679
|
return null;
|
|
769
680
|
}
|
|
770
|
-
return /* @__PURE__ */
|
|
681
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
771
682
|
role: "none",
|
|
772
|
-
|
|
773
|
-
|
|
683
|
+
key: "meta-input",
|
|
684
|
+
className: mx2(padding)
|
|
685
|
+
}, /* @__PURE__ */ React6.createElement(InputHeader, null, label), /* @__PURE__ */ React6.createElement("div", {
|
|
774
686
|
role: "none",
|
|
775
687
|
className: "flex flex-col gap-1"
|
|
776
|
-
},
|
|
688
|
+
}, arrayValues.map((_, index) => /* @__PURE__ */ React6.createElement("div", {
|
|
777
689
|
key: index,
|
|
778
690
|
role: "none",
|
|
779
|
-
className: "flex items-
|
|
780
|
-
}, /* @__PURE__ */
|
|
691
|
+
className: "flex items-start gap-1"
|
|
692
|
+
}, /* @__PURE__ */ React6.createElement("div", {
|
|
781
693
|
role: "none",
|
|
782
694
|
className: "flex-1"
|
|
783
|
-
}, /* @__PURE__ */
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
readonly,
|
|
794
|
-
inline: true,
|
|
795
|
-
Custom,
|
|
796
|
-
lookupComponent
|
|
797
|
-
})), /* @__PURE__ */ React9.createElement(IconButton3, {
|
|
695
|
+
}, /* @__PURE__ */ React6.createElement(InputComponent, {
|
|
696
|
+
type,
|
|
697
|
+
format,
|
|
698
|
+
label,
|
|
699
|
+
inputOnly: true,
|
|
700
|
+
property: `${name}[${index}]`,
|
|
701
|
+
disabled: readonly,
|
|
702
|
+
placeholder,
|
|
703
|
+
...inputProps
|
|
704
|
+
})), /* @__PURE__ */ React6.createElement(IconButton, {
|
|
798
705
|
icon: "ph--trash--regular",
|
|
799
706
|
iconOnly: true,
|
|
800
707
|
label: t("button remove"),
|
|
801
|
-
onClick: () =>
|
|
802
|
-
|
|
708
|
+
onClick: () => {
|
|
709
|
+
const newValues = arrayValues.filter((_2, i) => i !== index);
|
|
710
|
+
inputProps.onValueChange(name, type, newValues);
|
|
711
|
+
}
|
|
712
|
+
})))), /* @__PURE__ */ React6.createElement("div", {
|
|
803
713
|
role: "none",
|
|
804
714
|
className: "flex justify-between items-center plb-1"
|
|
805
|
-
}, /* @__PURE__ */
|
|
715
|
+
}, /* @__PURE__ */ React6.createElement(IconButton, {
|
|
806
716
|
icon: "ph--plus--regular",
|
|
807
717
|
iconOnly: true,
|
|
808
718
|
label: t("button add"),
|
|
809
|
-
onClick:
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
var getInputComponent = (type, format) => {
|
|
816
|
-
switch (format) {
|
|
817
|
-
case FormatEnum.LatLng:
|
|
818
|
-
return GeoPointInput;
|
|
819
|
-
}
|
|
820
|
-
switch (type) {
|
|
821
|
-
case "string":
|
|
822
|
-
return TextInput;
|
|
823
|
-
case "number":
|
|
824
|
-
return NumberInput;
|
|
825
|
-
case "boolean":
|
|
826
|
-
return BooleanInput;
|
|
827
|
-
}
|
|
828
|
-
};
|
|
829
|
-
|
|
830
|
-
// packages/ui/react-ui-form/src/components/Form/FormContent.tsx
|
|
831
|
-
var FormField = ({ property, path, readonly, inline, lookupComponent, Custom }) => {
|
|
832
|
-
const inputProps = useInputProps(path);
|
|
833
|
-
const { ast, name, type, format, title, description, options, examples, array } = property;
|
|
834
|
-
const label = useMemo3(() => title ?? pipe2(name, capitalize2), [
|
|
835
|
-
title,
|
|
836
|
-
name
|
|
837
|
-
]);
|
|
838
|
-
const placeholder = useMemo3(() => examples?.length ? `Example: "${examples[0]}"` : description, [
|
|
839
|
-
examples,
|
|
840
|
-
description
|
|
841
|
-
]);
|
|
842
|
-
const FoundComponent = lookupComponent?.({
|
|
843
|
-
prop: name,
|
|
844
|
-
schema: S.make(ast),
|
|
845
|
-
inputProps: {
|
|
846
|
-
type,
|
|
847
|
-
format,
|
|
848
|
-
label,
|
|
849
|
-
disabled: readonly,
|
|
850
|
-
placeholder,
|
|
851
|
-
...inputProps
|
|
852
|
-
}
|
|
853
|
-
});
|
|
854
|
-
if (FoundComponent) {
|
|
855
|
-
return /* @__PURE__ */ React10.createElement("div", {
|
|
856
|
-
role: "none"
|
|
857
|
-
}, FoundComponent);
|
|
858
|
-
}
|
|
859
|
-
const jsonPath = createJsonPath3(path ?? []);
|
|
860
|
-
const CustomComponent = Custom?.[jsonPath];
|
|
861
|
-
if (CustomComponent) {
|
|
862
|
-
return (
|
|
863
|
-
// TODO(ZaymonFC): We should try to remove this div wrapper.
|
|
864
|
-
/* @__PURE__ */ React10.createElement("div", {
|
|
865
|
-
role: "none"
|
|
866
|
-
}, /* @__PURE__ */ React10.createElement(CustomComponent, {
|
|
867
|
-
type,
|
|
868
|
-
format,
|
|
869
|
-
label,
|
|
870
|
-
inputOnly: inline,
|
|
871
|
-
placeholder,
|
|
872
|
-
disabled: readonly,
|
|
873
|
-
...inputProps
|
|
874
|
-
}))
|
|
875
|
-
);
|
|
876
|
-
}
|
|
877
|
-
if (array) {
|
|
878
|
-
return /* @__PURE__ */ React10.createElement(ArrayField, {
|
|
879
|
-
property,
|
|
880
|
-
path,
|
|
881
|
-
inputProps,
|
|
882
|
-
readonly,
|
|
883
|
-
Custom
|
|
884
|
-
});
|
|
885
|
-
}
|
|
886
|
-
const InputComponent = getInputComponent(type, format);
|
|
887
|
-
if (InputComponent) {
|
|
888
|
-
return /* @__PURE__ */ React10.createElement("div", {
|
|
889
|
-
role: "none"
|
|
890
|
-
}, /* @__PURE__ */ React10.createElement(InputComponent, {
|
|
891
|
-
type,
|
|
892
|
-
format,
|
|
893
|
-
label,
|
|
894
|
-
inputOnly: inline,
|
|
895
|
-
placeholder,
|
|
896
|
-
disabled: readonly,
|
|
897
|
-
...inputProps
|
|
898
|
-
}));
|
|
899
|
-
}
|
|
900
|
-
if (options) {
|
|
901
|
-
return /* @__PURE__ */ React10.createElement("div", {
|
|
902
|
-
role: "none"
|
|
903
|
-
}, /* @__PURE__ */ React10.createElement(SelectInput, {
|
|
904
|
-
type,
|
|
905
|
-
format,
|
|
906
|
-
disabled: readonly,
|
|
907
|
-
inputOnly: inline,
|
|
908
|
-
label,
|
|
909
|
-
options: options.map((option) => ({
|
|
910
|
-
value: option,
|
|
911
|
-
label: String(option)
|
|
912
|
-
})),
|
|
913
|
-
placeholder,
|
|
914
|
-
...inputProps
|
|
915
|
-
}));
|
|
916
|
-
}
|
|
917
|
-
if (type === "object") {
|
|
918
|
-
const baseNode = findNode2(ast, isDiscriminatedUnion2);
|
|
919
|
-
const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode2(ast, AST3.isTypeLiteral);
|
|
920
|
-
if (typeLiteral) {
|
|
921
|
-
return /* @__PURE__ */ React10.createElement("div", {
|
|
922
|
-
role: "none"
|
|
923
|
-
}, !inline && /* @__PURE__ */ React10.createElement("div", null, label), /* @__PURE__ */ React10.createElement(FormFields, {
|
|
924
|
-
schema: S.make(typeLiteral),
|
|
925
|
-
path,
|
|
926
|
-
readonly,
|
|
927
|
-
Custom
|
|
928
|
-
}));
|
|
719
|
+
onClick: () => {
|
|
720
|
+
const newValues = [
|
|
721
|
+
...arrayValues,
|
|
722
|
+
SimpleType.getDefaultValue(type)
|
|
723
|
+
];
|
|
724
|
+
inputProps.onValueChange(name, type, newValues);
|
|
929
725
|
}
|
|
930
|
-
}
|
|
931
|
-
return null;
|
|
932
|
-
};
|
|
933
|
-
var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custom }) => {
|
|
934
|
-
const values = useFormValues(path);
|
|
935
|
-
const properties = useMemo3(() => {
|
|
936
|
-
const props = getSchemaProperties2(schema.ast, values);
|
|
937
|
-
const filtered = filter ? filter(props) : props;
|
|
938
|
-
return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
|
|
939
|
-
}, [
|
|
940
|
-
schema,
|
|
941
|
-
values,
|
|
942
|
-
filter,
|
|
943
|
-
sort
|
|
944
|
-
]);
|
|
945
|
-
return /* @__PURE__ */ React10.createElement("div", {
|
|
946
|
-
role: "form",
|
|
947
|
-
className: mx6("flex flex-col w-full gap-2 py-2")
|
|
948
|
-
}, properties.map((property) => {
|
|
949
|
-
return /* @__PURE__ */ React10.createElement(FormField, {
|
|
950
|
-
key: property.name,
|
|
951
|
-
property,
|
|
952
|
-
path: [
|
|
953
|
-
...path ?? [],
|
|
954
|
-
property.name
|
|
955
|
-
],
|
|
956
|
-
readonly,
|
|
957
|
-
lookupComponent,
|
|
958
|
-
Custom
|
|
959
|
-
});
|
|
960
|
-
}).filter(isNotFalsy));
|
|
726
|
+
})));
|
|
961
727
|
};
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
const onValid = useMemo4(() => autoSave ? onSave : void 0, [
|
|
966
|
-
autoSave,
|
|
967
|
-
onSave
|
|
968
|
-
]);
|
|
969
|
-
useEffect3(() => {
|
|
970
|
-
if (autoFocus) {
|
|
971
|
-
const input = document.querySelector("input");
|
|
972
|
-
if (input) {
|
|
973
|
-
input.focus();
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
}, [
|
|
977
|
-
autoFocus
|
|
978
|
-
]);
|
|
979
|
-
return /* @__PURE__ */ React11.createElement(FormProvider, {
|
|
980
|
-
schema,
|
|
981
|
-
initialValues,
|
|
982
|
-
onValuesChanged,
|
|
983
|
-
onValidate,
|
|
984
|
-
onValid,
|
|
985
|
-
onSave
|
|
986
|
-
}, /* @__PURE__ */ React11.createElement("div", {
|
|
728
|
+
var FormActions = ({ onCancel, onSubmit, canSubmit, readonly }) => {
|
|
729
|
+
const { t } = useTranslation2(translationKey);
|
|
730
|
+
return /* @__PURE__ */ React6.createElement("div", {
|
|
987
731
|
role: "none",
|
|
988
|
-
className:
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
732
|
+
className: "flex justify-center"
|
|
733
|
+
}, /* @__PURE__ */ React6.createElement("div", {
|
|
734
|
+
role: "none",
|
|
735
|
+
className: mx2(onCancel && !readonly && "grid grid-cols-2 gap-2")
|
|
736
|
+
}, onCancel && !readonly && /* @__PURE__ */ React6.createElement(IconButton, {
|
|
737
|
+
"data-testid": "cancel-button",
|
|
738
|
+
icon: "ph--x--regular",
|
|
739
|
+
label: t("button cancel"),
|
|
740
|
+
onClick: onCancel
|
|
741
|
+
}), onSubmit && /* @__PURE__ */ React6.createElement(IconButton, {
|
|
742
|
+
type: "submit",
|
|
743
|
+
"data-testid": "save-button",
|
|
744
|
+
disabled: !canSubmit,
|
|
745
|
+
icon: "ph--check--regular",
|
|
746
|
+
label: t("button save"),
|
|
747
|
+
onClick: onSubmit
|
|
1001
748
|
})));
|
|
1002
749
|
};
|
|
1003
750
|
|
|
1004
751
|
// packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
|
|
1005
752
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
|
|
1006
753
|
var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
1007
|
-
const { t } =
|
|
1008
|
-
const [props, setProps] =
|
|
1009
|
-
|
|
754
|
+
const { t } = useTranslation3(translationKey);
|
|
755
|
+
const [props, setProps] = useState2(projection.getFieldProjection(field.id).props);
|
|
756
|
+
useEffect3(() => setProps(projection.getFieldProjection(field.id).props), [
|
|
1010
757
|
field,
|
|
1011
758
|
projection
|
|
1012
759
|
]);
|
|
1013
|
-
const [schemas, setSchemas] =
|
|
1014
|
-
|
|
760
|
+
const [schemas, setSchemas] = useState2([]);
|
|
761
|
+
useEffect3(() => {
|
|
1015
762
|
if (!registry) {
|
|
1016
763
|
return;
|
|
1017
764
|
}
|
|
@@ -1029,17 +776,17 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1029
776
|
}, [
|
|
1030
777
|
registry
|
|
1031
778
|
]);
|
|
1032
|
-
const [referenceSchema, setReferenceSchema] =
|
|
1033
|
-
|
|
779
|
+
const [referenceSchema, setReferenceSchema] = useState2();
|
|
780
|
+
useEffect3(() => {
|
|
1034
781
|
setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
|
|
1035
782
|
}, [
|
|
1036
783
|
schemas,
|
|
1037
784
|
props?.referenceSchema
|
|
1038
785
|
]);
|
|
1039
|
-
const [{ fieldSchema }, setFieldSchema] =
|
|
786
|
+
const [{ fieldSchema }, setFieldSchema] = useState2({
|
|
1040
787
|
fieldSchema: getFormatSchema(props?.format)
|
|
1041
788
|
});
|
|
1042
|
-
const handleValuesChanged =
|
|
789
|
+
const handleValuesChanged = useCallback2((_props) => {
|
|
1043
790
|
setFieldSchema((prev) => {
|
|
1044
791
|
const fieldSchema2 = getFormatSchema(_props.format);
|
|
1045
792
|
if (prev.fieldSchema === fieldSchema2) {
|
|
@@ -1067,14 +814,14 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1067
814
|
type
|
|
1068
815
|
};
|
|
1069
816
|
}
|
|
1070
|
-
return
|
|
817
|
+
return props2;
|
|
1071
818
|
});
|
|
1072
819
|
}, [
|
|
1073
820
|
schemas,
|
|
1074
821
|
props.format,
|
|
1075
822
|
props.referenceSchema
|
|
1076
823
|
]);
|
|
1077
|
-
const handleValidate =
|
|
824
|
+
const handleValidate = useCallback2(({ property }) => {
|
|
1078
825
|
if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
|
|
1079
826
|
return [
|
|
1080
827
|
{
|
|
@@ -1087,7 +834,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1087
834
|
view.fields,
|
|
1088
835
|
field
|
|
1089
836
|
]);
|
|
1090
|
-
const handleSave =
|
|
837
|
+
const handleSave = useCallback2((props2) => {
|
|
1091
838
|
projection.setFieldProjection({
|
|
1092
839
|
field,
|
|
1093
840
|
props: props2
|
|
@@ -1098,51 +845,50 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1098
845
|
field,
|
|
1099
846
|
onSave
|
|
1100
847
|
]);
|
|
1101
|
-
const handleCancel =
|
|
848
|
+
const handleCancel = useCallback2(() => {
|
|
1102
849
|
requestAnimationFrame(() => onCancel?.());
|
|
1103
850
|
onSave();
|
|
1104
851
|
}, [
|
|
1105
852
|
onSave
|
|
1106
853
|
]);
|
|
1107
|
-
const Custom =
|
|
1108
|
-
["format"]: (props2) => /* @__PURE__ */
|
|
854
|
+
const Custom = useMemo3(() => ({
|
|
855
|
+
["format"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
|
|
1109
856
|
...props2,
|
|
1110
857
|
options: FormatEnums.filter((value) => value !== FormatEnum2.None).map((value) => ({
|
|
1111
858
|
value,
|
|
1112
859
|
label: t(`format ${value}`)
|
|
1113
860
|
}))
|
|
1114
861
|
}),
|
|
1115
|
-
["referenceSchema"]: (props2) => /* @__PURE__ */
|
|
862
|
+
["referenceSchema"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
|
|
1116
863
|
...props2,
|
|
1117
864
|
options: schemas.map((schema) => ({
|
|
1118
865
|
value: schema.typename
|
|
1119
866
|
}))
|
|
1120
867
|
}),
|
|
1121
|
-
["referencePath"]: (props2) => /* @__PURE__ */
|
|
868
|
+
["referencePath"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
|
|
1122
869
|
...props2,
|
|
1123
|
-
options: referenceSchema ?
|
|
870
|
+
options: referenceSchema ? getSchemaProperties2(referenceSchema.ast).sort(sortProperties).map((p) => ({
|
|
1124
871
|
value: p.name
|
|
1125
872
|
})) : []
|
|
1126
|
-
})
|
|
1127
|
-
["options"]: (props2) => /* @__PURE__ */ React12.createElement(SelectOptionInput, props2)
|
|
873
|
+
})
|
|
1128
874
|
}), [
|
|
1129
875
|
t,
|
|
1130
876
|
schemas,
|
|
1131
877
|
referenceSchema
|
|
1132
878
|
]);
|
|
1133
|
-
const propIsNotType =
|
|
879
|
+
const propIsNotType = useCallback2((props2) => props2.filter((p) => p.name !== "type"), []);
|
|
1134
880
|
if (!fieldSchema) {
|
|
1135
|
-
|
|
881
|
+
log3.warn("invalid format", {
|
|
1136
882
|
props
|
|
1137
883
|
}, {
|
|
1138
884
|
F: __dxlog_file3,
|
|
1139
|
-
L:
|
|
885
|
+
L: 173,
|
|
1140
886
|
S: void 0,
|
|
1141
887
|
C: (f, a) => f(...a)
|
|
1142
888
|
});
|
|
1143
889
|
return null;
|
|
1144
890
|
}
|
|
1145
|
-
return /* @__PURE__ */
|
|
891
|
+
return /* @__PURE__ */ React7.createElement(Form, {
|
|
1146
892
|
key: field.id,
|
|
1147
893
|
autoFocus: true,
|
|
1148
894
|
values: props,
|
|
@@ -1161,29 +907,30 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
|
1161
907
|
};
|
|
1162
908
|
|
|
1163
909
|
// packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
|
|
1164
|
-
import
|
|
1165
|
-
import { AST as
|
|
1166
|
-
import { IconButton as
|
|
1167
|
-
import { List
|
|
1168
|
-
import { ghostHover, inputTextLabel, mx as
|
|
910
|
+
import React8, { useCallback as useCallback3, useMemo as useMemo4, useState as useState3 } from "react";
|
|
911
|
+
import { AST as AST2, Format, S as S2 } from "@dxos/echo-schema";
|
|
912
|
+
import { IconButton as IconButton2, useTranslation as useTranslation4 } from "@dxos/react-ui";
|
|
913
|
+
import { List } from "@dxos/react-ui-list";
|
|
914
|
+
import { ghostHover, inputTextLabel, mx as mx3 } from "@dxos/react-ui-theme";
|
|
1169
915
|
import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
|
|
916
|
+
import { arrayMove } from "@dxos/util";
|
|
1170
917
|
var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
|
|
1171
918
|
var ViewMetaSchema = S2.Struct({
|
|
1172
919
|
name: S2.String.annotations({
|
|
1173
|
-
[
|
|
920
|
+
[AST2.TitleAnnotationId]: "View"
|
|
1174
921
|
}),
|
|
1175
922
|
typename: Format.DXN.annotations({
|
|
1176
|
-
[
|
|
923
|
+
[AST2.TitleAnnotationId]: "Typename"
|
|
1177
924
|
})
|
|
1178
925
|
}).pipe(S2.mutable);
|
|
1179
926
|
var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
|
|
1180
|
-
const { t } =
|
|
1181
|
-
const projection =
|
|
927
|
+
const { t } = useTranslation4(translationKey);
|
|
928
|
+
const projection = useMemo4(() => new ViewProjection(schema, view), [
|
|
1182
929
|
schema,
|
|
1183
930
|
view
|
|
1184
931
|
]);
|
|
1185
|
-
const [field, setField] =
|
|
1186
|
-
const viewValues =
|
|
932
|
+
const [field, setField] = useState3();
|
|
933
|
+
const viewValues = useMemo4(() => {
|
|
1187
934
|
return {
|
|
1188
935
|
name: view.name,
|
|
1189
936
|
// TODO(burdon): Need to warn user of possible consequences of editing.
|
|
@@ -1193,7 +940,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1193
940
|
}, [
|
|
1194
941
|
view
|
|
1195
942
|
]);
|
|
1196
|
-
const handleViewUpdate =
|
|
943
|
+
const handleViewUpdate = useCallback3(({ name, typename }) => {
|
|
1197
944
|
requestAnimationFrame(() => {
|
|
1198
945
|
if (view.name !== name) {
|
|
1199
946
|
view.name = name;
|
|
@@ -1207,72 +954,67 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
1207
954
|
schema,
|
|
1208
955
|
onTypenameChanged
|
|
1209
956
|
]);
|
|
1210
|
-
const handleSelect =
|
|
957
|
+
const handleSelect = useCallback3((field2) => {
|
|
1211
958
|
setField((f) => f === field2 ? void 0 : field2);
|
|
1212
959
|
}, []);
|
|
1213
|
-
const handleAdd =
|
|
960
|
+
const handleAdd = useCallback3(() => {
|
|
1214
961
|
const field2 = projection.createFieldProjection();
|
|
1215
962
|
setField(field2);
|
|
1216
963
|
}, [
|
|
1217
964
|
view
|
|
1218
965
|
]);
|
|
1219
|
-
const handleMove =
|
|
1220
|
-
|
|
1221
|
-
...view.fields
|
|
1222
|
-
];
|
|
1223
|
-
const [moved] = fields.splice(fromIndex, 1);
|
|
1224
|
-
fields.splice(toIndex, 0, moved);
|
|
1225
|
-
view.fields = fields;
|
|
966
|
+
const handleMove = useCallback3((fromIndex, toIndex) => {
|
|
967
|
+
arrayMove(view.fields, fromIndex, toIndex);
|
|
1226
968
|
}, [
|
|
1227
969
|
view.fields
|
|
1228
970
|
]);
|
|
1229
|
-
const handleClose =
|
|
1230
|
-
return /* @__PURE__ */
|
|
971
|
+
const handleClose = useCallback3(() => setField(void 0), []);
|
|
972
|
+
return /* @__PURE__ */ React8.createElement("div", {
|
|
1231
973
|
role: "none",
|
|
1232
|
-
className:
|
|
1233
|
-
}, /* @__PURE__ */
|
|
974
|
+
className: mx3("flex flex-col w-full divide-y divide-separator", classNames)
|
|
975
|
+
}, /* @__PURE__ */ React8.createElement(Form, {
|
|
1234
976
|
autoFocus: true,
|
|
1235
977
|
autoSave: true,
|
|
1236
978
|
schema: ViewMetaSchema,
|
|
1237
979
|
values: viewValues,
|
|
1238
980
|
onSave: handleViewUpdate
|
|
1239
|
-
}), /* @__PURE__ */
|
|
981
|
+
}), /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("div", {
|
|
1240
982
|
role: "none",
|
|
1241
983
|
className: "p-2"
|
|
1242
|
-
}, /* @__PURE__ */
|
|
1243
|
-
className:
|
|
1244
|
-
}, t("fields label"))), /* @__PURE__ */
|
|
984
|
+
}, /* @__PURE__ */ React8.createElement("label", {
|
|
985
|
+
className: mx3(inputTextLabel)
|
|
986
|
+
}, t("fields label"))), /* @__PURE__ */ React8.createElement(List.Root, {
|
|
1245
987
|
items: view.fields,
|
|
1246
988
|
isItem: S2.is(FieldSchema),
|
|
1247
989
|
getId: (field2) => field2.id,
|
|
1248
990
|
onMove: handleMove
|
|
1249
|
-
}, ({ items: fields }) => /* @__PURE__ */
|
|
991
|
+
}, ({ items: fields }) => /* @__PURE__ */ React8.createElement(React8.Fragment, null, showHeading && /* @__PURE__ */ React8.createElement("div", {
|
|
1250
992
|
role: "heading",
|
|
1251
993
|
className: grid
|
|
1252
|
-
}, /* @__PURE__ */
|
|
994
|
+
}, /* @__PURE__ */ React8.createElement("div", null), /* @__PURE__ */ React8.createElement("div", {
|
|
1253
995
|
className: "flex items-center text-sm"
|
|
1254
|
-
}, t("field path label"))), /* @__PURE__ */
|
|
996
|
+
}, t("field path label"))), /* @__PURE__ */ React8.createElement("div", {
|
|
1255
997
|
role: "list",
|
|
1256
998
|
className: "flex flex-col w-full"
|
|
1257
|
-
}, fields?.map((field2) => /* @__PURE__ */
|
|
999
|
+
}, fields?.map((field2) => /* @__PURE__ */ React8.createElement(List.Item, {
|
|
1258
1000
|
key: field2.id,
|
|
1259
1001
|
item: field2,
|
|
1260
|
-
classNames:
|
|
1261
|
-
}, /* @__PURE__ */
|
|
1002
|
+
classNames: mx3(grid, ghostHover, "cursor-pointer")
|
|
1003
|
+
}, /* @__PURE__ */ React8.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React8.createElement(List.ItemTitle, {
|
|
1262
1004
|
onClick: () => handleSelect(field2)
|
|
1263
|
-
}, field2.path), /* @__PURE__ */
|
|
1005
|
+
}, field2.path), /* @__PURE__ */ React8.createElement(List.ItemDeleteButton, {
|
|
1264
1006
|
disabled: view.fields.length <= 1,
|
|
1265
1007
|
onClick: () => onDelete(field2.id)
|
|
1266
|
-
}))))))), field && /* @__PURE__ */
|
|
1008
|
+
}))))))), field && /* @__PURE__ */ React8.createElement(FieldEditor, {
|
|
1267
1009
|
key: field.id,
|
|
1268
1010
|
view,
|
|
1269
1011
|
projection,
|
|
1270
1012
|
field,
|
|
1271
1013
|
registry,
|
|
1272
1014
|
onSave: handleClose
|
|
1273
|
-
}), !readonly && !field && /* @__PURE__ */
|
|
1015
|
+
}), !readonly && !field && /* @__PURE__ */ React8.createElement("div", {
|
|
1274
1016
|
className: "flex p-2 justify-center"
|
|
1275
|
-
}, /* @__PURE__ */
|
|
1017
|
+
}, /* @__PURE__ */ React8.createElement(IconButton2, {
|
|
1276
1018
|
icon: "ph--plus--regular",
|
|
1277
1019
|
label: t("button add property"),
|
|
1278
1020
|
onClick: handleAdd,
|
|
@@ -1502,15 +1244,14 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
|
|
|
1502
1244
|
};
|
|
1503
1245
|
export {
|
|
1504
1246
|
BooleanInput,
|
|
1505
|
-
DeprecatedFormContainer,
|
|
1506
1247
|
DeprecatedFormInput,
|
|
1507
1248
|
FieldEditor,
|
|
1508
1249
|
Form,
|
|
1250
|
+
FormActions,
|
|
1509
1251
|
GeoPointInput,
|
|
1510
1252
|
InputHeader,
|
|
1511
1253
|
NumberInput,
|
|
1512
1254
|
SelectInput,
|
|
1513
|
-
SelectOptionInput,
|
|
1514
1255
|
TextInput,
|
|
1515
1256
|
TupleInput,
|
|
1516
1257
|
ViewEditor,
|