@dxos/react-ui-form 0.7.5-main.9d2a38b → 0.7.5-main.e9bb01b

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