@dxos/react-ui-form 0.7.5-labs.e27f9b9 → 0.7.5-main.2567c87

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