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