@dxos/react-ui-form 0.7.5-feature-compute.4d9d99a → 0.7.5-labs.071a3e2

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