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