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