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