@dxos/react-ui-form 0.7.5-main.9d2a38b → 0.7.5-main.e9bb01b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/lib/browser/index.mjs +703 -462
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +730 -504
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +703 -462
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  11. package/dist/types/src/components/Form/ArrayField.d.ts +16 -0
  12. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -0
  13. package/dist/types/src/components/Form/Defaults.d.ts +5 -6
  14. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  15. package/dist/types/src/components/Form/Form.d.ts +11 -20
  16. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  17. package/dist/types/src/components/Form/Form.stories.d.ts +2 -1
  18. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  19. package/dist/types/src/components/Form/FormActions.d.ts +7 -0
  20. package/dist/types/src/components/Form/FormActions.d.ts.map +1 -0
  21. package/dist/types/src/components/Form/FormContent.d.ts +26 -0
  22. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -0
  23. package/dist/types/src/components/Form/FormContext.d.ts +20 -0
  24. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -0
  25. package/dist/types/src/components/Form/Input.d.ts +5 -6
  26. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  27. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +1 -2
  28. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
  29. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +4 -0
  30. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -0
  31. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +7 -0
  32. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -0
  33. package/dist/types/src/components/Form/custom/TupleInput.d.ts +1 -2
  34. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
  35. package/dist/types/src/components/Form/custom/index.d.ts +1 -0
  36. package/dist/types/src/components/Form/custom/index.d.ts.map +1 -1
  37. package/dist/types/src/components/Form/factory.d.ts +2 -2
  38. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  39. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  40. package/dist/types/src/components/deprecated/FormInput.d.ts +5 -0
  41. package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
  42. package/dist/types/src/hooks/useForm.d.ts +9 -10
  43. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  44. package/dist/types/src/translations.d.ts +6 -0
  45. package/dist/types/src/translations.d.ts.map +1 -1
  46. package/package.json +25 -24
  47. package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
  48. package/src/components/FieldEditor/FieldEditor.tsx +7 -6
  49. package/src/components/Form/ArrayField.tsx +111 -0
  50. package/src/components/Form/Defaults.tsx +18 -33
  51. package/src/components/Form/Form.stories.tsx +15 -5
  52. package/src/components/Form/Form.tsx +38 -358
  53. package/src/components/Form/FormActions.tsx +41 -0
  54. package/src/components/Form/FormContent.tsx +173 -0
  55. package/src/components/Form/FormContext.tsx +48 -0
  56. package/src/components/Form/Input.tsx +5 -6
  57. package/src/components/Form/custom/GeoPointInput.tsx +6 -15
  58. package/src/components/Form/custom/SelectOptionsInput.stories.tsx +58 -0
  59. package/src/components/Form/custom/SelectOptionsInput.tsx +192 -0
  60. package/src/components/Form/custom/TupleInput.tsx +5 -9
  61. package/src/components/Form/custom/index.ts +1 -0
  62. package/src/components/Form/factory.tsx +2 -5
  63. package/src/components/ViewEditor/ViewEditor.tsx +5 -2
  64. package/src/components/deprecated/FormInput.tsx +19 -3
  65. package/src/hooks/useForm.ts +54 -47
  66. package/src/translations.ts +8 -0
@@ -29,14 +29,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  var node_exports = {};
30
30
  __export(node_exports, {
31
31
  BooleanInput: () => BooleanInput,
32
+ DeprecatedFormContainer: () => DeprecatedFormContainer,
32
33
  DeprecatedFormInput: () => DeprecatedFormInput,
33
34
  FieldEditor: () => FieldEditor,
34
35
  Form: () => Form,
35
- FormActions: () => FormActions,
36
36
  GeoPointInput: () => GeoPointInput,
37
37
  InputHeader: () => InputHeader,
38
38
  NumberInput: () => NumberInput,
39
39
  SelectInput: () => SelectInput,
40
+ SelectOptionInput: () => SelectOptionInput,
40
41
  TextInput: () => TextInput,
41
42
  TupleInput: () => TupleInput,
42
43
  ViewEditor: () => ViewEditor,
@@ -52,6 +53,7 @@ __export(node_exports, {
52
53
  module.exports = __toCommonJS(node_exports);
53
54
  var import_react = __toESM(require("react"));
54
55
  var import_react_ui = require("@dxos/react-ui");
56
+ var import_react_ui_theme = require("@dxos/react-ui-theme");
55
57
  var import_react2 = __toESM(require("react"));
56
58
  var import_echo_schema = require("@dxos/echo-schema");
57
59
  var import_log = require("@dxos/log");
@@ -62,38 +64,60 @@ var import_react_ui3 = require("@dxos/react-ui");
62
64
  var import_util = require("@dxos/util");
63
65
  var import_react4 = __toESM(require("react"));
64
66
  var import_react_ui4 = require("@dxos/react-ui");
65
- var import_react_ui_theme = require("@dxos/react-ui-theme");
67
+ var import_react_ui_theme2 = require("@dxos/react-ui-theme");
66
68
  var import_react5 = __toESM(require("react"));
69
+ var import_keys = require("@dxos/keys");
67
70
  var import_react_ui5 = require("@dxos/react-ui");
68
- var import_react_ui_theme2 = require("@dxos/react-ui-theme");
69
- var import_util2 = require("@dxos/util");
71
+ var import_react_ui_list = require("@dxos/react-ui-list");
72
+ var import_react_ui_pickers = require("@dxos/react-ui-pickers");
73
+ var import_react_ui_theme3 = require("@dxos/react-ui-theme");
70
74
  var import_react6 = __toESM(require("react"));
71
75
  var import_react_ui6 = require("@dxos/react-ui");
72
- var import_effect = require("effect");
73
- var import_String = require("effect/String");
76
+ var import_react_ui_theme4 = require("@dxos/react-ui-theme");
77
+ var import_util2 = require("@dxos/util");
74
78
  var import_react7 = __toESM(require("react"));
79
+ var import_react_ui7 = require("@dxos/react-ui");
80
+ var import_react8 = __toESM(require("react"));
81
+ var import_react_ui_theme5 = require("@dxos/react-ui-theme");
82
+ var import_react9 = __toESM(require("react"));
83
+ var import_react_ui8 = require("@dxos/react-ui");
84
+ var import_react_ui_theme6 = require("@dxos/react-ui-theme");
85
+ var import_react10 = __toESM(require("react"));
86
+ var import_debug = require("@dxos/debug");
75
87
  var import_echo_schema2 = require("@dxos/echo-schema");
88
+ var import_effect = require("@dxos/effect");
89
+ var import_react11 = require("react");
90
+ var import_echo_schema3 = require("@dxos/echo-schema");
76
91
  var import_effect2 = require("@dxos/effect");
92
+ var import_invariant = require("@dxos/invariant");
77
93
  var import_log2 = require("@dxos/log");
78
- var import_react_ui7 = require("@dxos/react-ui");
79
- var import_react_ui_theme3 = require("@dxos/react-ui-theme");
80
94
  var import_schema2 = require("@dxos/schema");
81
- var import_util3 = require("@dxos/util");
82
- var import_echo_schema3 = require("@dxos/echo-schema");
83
- var import_react8 = require("react");
95
+ var import_effect3 = require("effect");
96
+ var import_String = require("effect/String");
97
+ var import_react12 = __toESM(require("react"));
84
98
  var import_echo_schema4 = require("@dxos/echo-schema");
85
- var import_invariant = require("@dxos/invariant");
86
- var import_log3 = require("@dxos/log");
99
+ var import_effect4 = require("@dxos/effect");
100
+ var import_react_ui_theme7 = require("@dxos/react-ui-theme");
87
101
  var import_schema3 = require("@dxos/schema");
88
- var import_react9 = __toESM(require("react"));
102
+ var import_util3 = require("@dxos/util");
103
+ var import_effect5 = require("effect");
104
+ var import_String2 = require("effect/String");
105
+ var import_react13 = __toESM(require("react"));
89
106
  var import_echo_schema5 = require("@dxos/echo-schema");
90
- var import_react_ui8 = require("@dxos/react-ui");
91
- var import_react_ui_list = require("@dxos/react-ui-list");
92
- var import_react_ui_theme4 = require("@dxos/react-ui-theme");
107
+ var import_effect6 = require("@dxos/effect");
108
+ var import_invariant2 = require("@dxos/invariant");
109
+ var import_react_ui9 = require("@dxos/react-ui");
110
+ var import_react_ui_theme8 = require("@dxos/react-ui-theme");
93
111
  var import_schema4 = require("@dxos/schema");
94
- var import_util4 = require("@dxos/util");
95
112
  var import_echo_schema6 = require("@dxos/echo-schema");
113
+ var import_react14 = __toESM(require("react"));
96
114
  var import_echo_schema7 = require("@dxos/echo-schema");
115
+ var import_react_ui10 = require("@dxos/react-ui");
116
+ var import_react_ui_list2 = require("@dxos/react-ui-list");
117
+ var import_react_ui_theme9 = require("@dxos/react-ui-theme");
118
+ var import_schema5 = require("@dxos/schema");
119
+ var import_echo_schema8 = require("@dxos/echo-schema");
120
+ var import_echo_schema9 = require("@dxos/echo-schema");
97
121
  var translationKey = "react-ui-form";
98
122
  var translations_default = [
99
123
  {
@@ -130,6 +154,7 @@ var translations_default = [
130
154
  "format ref": "Reference",
131
155
  "format regex": "RegExp",
132
156
  "format string": "String",
157
+ "format single-select": "Select",
133
158
  "format text": "Long text",
134
159
  "format time": "Time",
135
160
  "format timestamp": "Timestamp",
@@ -139,11 +164,26 @@ var translations_default = [
139
164
  "format uuid": "UUID",
140
165
  // Placeholders
141
166
  "placeholder latitude": "Latitude",
142
- "placeholder longitude": "Longitude"
167
+ "placeholder longitude": "Longitude",
168
+ // SelectOptionsInput
169
+ "select option label": "Label",
170
+ "select option label placeholder": "Option label",
171
+ "select option color": "Color",
172
+ "select option delete": "Delete",
173
+ "select option add": "Add option"
143
174
  }
144
175
  }
145
176
  }
146
177
  ];
178
+ var DeprecatedFormContainer = ({ children, classNames }) => {
179
+ return /* @__PURE__ */ import_react.default.createElement("div", {
180
+ role: "none",
181
+ className: "w-full p-4 justify-center overflow-x-hidden overflow-y-auto"
182
+ }, /* @__PURE__ */ import_react.default.createElement("div", {
183
+ role: "form",
184
+ className: (0, import_react_ui_theme.mx)("flex flex-col", import_react_ui_theme.textBlockWidth, classNames)
185
+ }, children));
186
+ };
147
187
  var DeprecatedFormInput = ({ label, description, secondary, children }) => {
148
188
  const primary = /* @__PURE__ */ import_react.default.createElement("div", {
149
189
  role: "none",
@@ -152,14 +192,17 @@ var DeprecatedFormInput = ({ label, description, secondary, children }) => {
152
192
  role: "none",
153
193
  className: "flex flex-col w-full"
154
194
  }, /* @__PURE__ */ import_react.default.createElement(import_react_ui.Input.Label, {
155
- classNames: "flex min-h-[40px] items-center"
195
+ classNames: "flex min-bs-[--rail-action] items-center",
196
+ style: {
197
+ fontSize: "unset"
198
+ }
156
199
  }, label), description && /* @__PURE__ */ import_react.default.createElement(import_react_ui.Input.DescriptionAndValidation, {
157
200
  classNames: "mbs-0.5"
158
201
  }, /* @__PURE__ */ import_react.default.createElement(import_react_ui.Input.Description, null, description))), /* @__PURE__ */ import_react.default.createElement("div", {
159
202
  role: "none"
160
203
  }, /* @__PURE__ */ import_react.default.createElement("div", {
161
204
  role: "none",
162
- className: "flex min-h-[40px] items-center"
205
+ className: "flex min-bs-[--rail-action] items-center"
163
206
  }, children))));
164
207
  if (secondary) {
165
208
  return /* @__PURE__ */ import_react.default.createElement("div", {
@@ -178,15 +221,15 @@ var InputHeader = ({ children, error }) => {
178
221
  }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Icon, {
179
222
  icon: "ph--warning--regular",
180
223
  size: 4,
181
- classNames: import_react_ui_theme.errorText
224
+ classNames: import_react_ui_theme2.errorText
182
225
  })), /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Tooltip.Content, {
183
226
  side: "bottom"
184
227
  }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Tooltip.Arrow, null), error)));
185
228
  };
186
- var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
229
+ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
187
230
  const { t } = (0, import_react_ui3.useTranslation)(translationKey);
188
- const { status, error } = getStatus?.(property);
189
- const [lng = 0, lat = 0] = getValue2(property) ?? [];
231
+ const { status, error } = getStatus();
232
+ const [lng = 0, lat = 0] = getValue3() ?? [];
190
233
  return /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.Input.Root, {
191
234
  validationValence: status
192
235
  }, /* @__PURE__ */ import_react3.default.createElement(InputHeader, {
@@ -198,7 +241,7 @@ var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: get
198
241
  disabled,
199
242
  placeholder: t("placeholder longitude"),
200
243
  value: lng,
201
- onChange: (event) => onValueChange(property, type, [
244
+ onChange: (event) => onValueChange(type, [
202
245
  lat,
203
246
  (0, import_util.safeParseFloat)(event.target.value, 0)
204
247
  ]),
@@ -208,129 +251,290 @@ var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: get
208
251
  disabled,
209
252
  placeholder: t("placeholder latitude"),
210
253
  value: lat,
211
- onChange: (event) => onValueChange(property, type, [
254
+ onChange: (event) => onValueChange(type, [
212
255
  (0, import_util.safeParseFloat)(event.target.value, 0),
213
256
  lng
214
257
  ]),
215
258
  onBlur
216
259
  })));
217
260
  };
261
+ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
262
+ const [selected, setSelectedId] = (0, import_react5.useState)(null);
263
+ const [isNewOption, setIsNewOption] = (0, import_react5.useState)(false);
264
+ const inputRef = (0, import_react5.useRef)(null);
265
+ const { t } = (0, import_react_ui5.useTranslation)(translationKey);
266
+ const { status, error } = getStatus();
267
+ const options = getValue3();
268
+ (0, import_react5.useEffect)(() => {
269
+ if (options === void 0) {
270
+ onValueChange(type, []);
271
+ }
272
+ }, [
273
+ options,
274
+ onValueChange,
275
+ type
276
+ ]);
277
+ const randomHue = () => {
278
+ const usedHues = new Set(options?.map((option) => option.color) ?? []);
279
+ const hueKeys = Object.keys(import_react_ui_theme3.hueTokenThemes);
280
+ const unusedHues = hueKeys.filter((hue) => !usedHues.has(hue));
281
+ if (unusedHues.length > 0) {
282
+ return unusedHues[Math.floor(Math.random() * unusedHues.length)];
283
+ }
284
+ const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
285
+ const availableHues = hueKeys.filter((hue) => !lastThree.has(hue));
286
+ return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hueKeys[Math.floor(Math.random() * hueKeys.length)];
287
+ };
288
+ const handleAdd = (0, import_react5.useCallback)(() => {
289
+ const newId = import_keys.PublicKey.random().truncate();
290
+ const newOption = {
291
+ id: newId,
292
+ title: "",
293
+ color: randomHue()
294
+ };
295
+ onValueChange(type, [
296
+ ...options ?? [],
297
+ newOption
298
+ ]);
299
+ setSelectedId(newId);
300
+ setIsNewOption(true);
301
+ }, [
302
+ options,
303
+ type,
304
+ onValueChange
305
+ ]);
306
+ const handleDelete = (0, import_react5.useCallback)((id) => {
307
+ const newOptions = options?.filter((option) => option.id !== id) ?? [];
308
+ onValueChange(type, newOptions);
309
+ setSelectedId(null);
310
+ }, [
311
+ options,
312
+ type,
313
+ onValueChange
314
+ ]);
315
+ const handleMove = (0, import_react5.useCallback)((from, to) => {
316
+ if (!options) {
317
+ return;
318
+ }
319
+ const newOptions = [
320
+ ...options
321
+ ];
322
+ const [removed] = newOptions.splice(from, 1);
323
+ newOptions.splice(to, 0, removed);
324
+ onValueChange(type, newOptions);
325
+ }, [
326
+ options,
327
+ type,
328
+ onValueChange
329
+ ]);
330
+ const handleClick = (0, import_react5.useCallback)((id) => {
331
+ setSelectedId((current) => current === id ? null : id);
332
+ }, []);
333
+ const handleTitleChange = (0, import_react5.useCallback)((id) => (e) => {
334
+ const newOptions = options?.map((o) => o.id === id ? {
335
+ ...o,
336
+ title: e.target.value
337
+ } : o);
338
+ onValueChange(type, newOptions ?? []);
339
+ }, [
340
+ options,
341
+ type,
342
+ onValueChange
343
+ ]);
344
+ const handleKeyDown = (0, import_react5.useCallback)((e) => {
345
+ if (e.key === "Enter") {
346
+ setSelectedId(null);
347
+ }
348
+ }, []);
349
+ const handleColorChange = (0, import_react5.useCallback)((id) => (hue) => {
350
+ const newOptions = options?.map((o) => o.id === id ? {
351
+ ...o,
352
+ color: hue
353
+ } : o);
354
+ onValueChange(type, newOptions ?? []);
355
+ }, [
356
+ options,
357
+ type,
358
+ onValueChange
359
+ ]);
360
+ (0, import_react5.useEffect)(() => {
361
+ if (selected && isNewOption && inputRef.current) {
362
+ inputRef.current.focus();
363
+ setIsNewOption(false);
364
+ }
365
+ }, [
366
+ selected,
367
+ isNewOption
368
+ ]);
369
+ return /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.Root, {
370
+ validationValence: status
371
+ }, /* @__PURE__ */ import_react5.default.createElement(InputHeader, {
372
+ error
373
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.Label, null, label)), /* @__PURE__ */ import_react5.default.createElement("div", {
374
+ role: "none"
375
+ }, options && /* @__PURE__ */ import_react5.default.createElement(import_react_ui_list.List.Root, {
376
+ items: options,
377
+ isItem: (item) => true,
378
+ onMove: handleMove
379
+ }, ({ items }) => /* @__PURE__ */ import_react5.default.createElement("div", {
380
+ role: "list",
381
+ className: "w-full overflow-auto"
382
+ }, items?.map((item) => /* @__PURE__ */ import_react5.default.createElement("div", {
383
+ key: item.id
384
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui_list.List.Item, {
385
+ role: "button",
386
+ item,
387
+ classNames: (0, import_react_ui_theme3.mx)("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
388
+ "aria-expanded": selected === item.id
389
+ }, /* @__PURE__ */ import_react5.default.createElement("div", {
390
+ className: "flex items-center"
391
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui_list.List.ItemDragHandle, null), /* @__PURE__ */ import_react5.default.createElement(import_react_ui_list.List.ItemTitle, {
392
+ onClick: () => handleClick(item.id),
393
+ classNames: "flex-1"
394
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Tag, {
395
+ palette: item.color
396
+ }, item.title || "\u200B")), /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Icon, {
397
+ icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
398
+ onClick: () => handleClick(item.id)
399
+ })), selected === item.id && /* @__PURE__ */ import_react5.default.createElement("div", {
400
+ className: "mis-4 mbs-2 flex flex-col gap-1"
401
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.Label, {
402
+ classNames: "text-xs"
403
+ }, t("select option label")), /* @__PURE__ */ import_react5.default.createElement("div", {
404
+ className: "flex flex-row items-center gap-1"
405
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.TextInput, {
406
+ placeholder: t("select option label placeholder"),
407
+ ref: selected === item.id ? inputRef : void 0,
408
+ value: item.title,
409
+ onChange: handleTitleChange(item.id),
410
+ onKeyDown: handleKeyDown,
411
+ classNames: "flex-1"
412
+ }), /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Toolbar.Root, {
413
+ classNames: "p-0 m-0 !is-auto"
414
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui_pickers.HuePickerToolbarButton, {
415
+ hue: item.color,
416
+ onChangeHue: handleColorChange(item.id)
417
+ })), /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.IconButton, {
418
+ icon: "ph--trash--fill",
419
+ iconOnly: true,
420
+ label: t("select option delete"),
421
+ onClick: () => handleDelete(item.id)
422
+ })))))), /* @__PURE__ */ import_react5.default.createElement("div", {
423
+ role: "listitem"
424
+ }, /* @__PURE__ */ import_react5.default.createElement("div", {
425
+ role: "button",
426
+ className: (0, import_react_ui_theme3.mx)("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
427
+ onClick: handleAdd
428
+ }, /* @__PURE__ */ import_react5.default.createElement("div", {
429
+ className: "flex items-center gap-1"
430
+ }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Icon, {
431
+ icon: "ph--plus--regular"
432
+ }), /* @__PURE__ */ import_react5.default.createElement("span", {
433
+ className: "text-sm"
434
+ }, t("select option add")))))))));
435
+ };
218
436
  var gridCols = [
219
437
  "grid-cols-1",
220
438
  "grid-cols-2",
221
439
  "grid-cols-3",
222
440
  "grid-cols-4"
223
441
  ];
224
- var TupleInput = ({ binding, property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
225
- const { status, error } = getStatus?.(property);
226
- const values = getValue2(property) ?? {};
227
- return /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.Root, {
442
+ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
443
+ const { status, error } = getStatus();
444
+ const values = getValue3() ?? {};
445
+ return /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Root, {
228
446
  validationValence: status
229
- }, /* @__PURE__ */ import_react5.default.createElement(InputHeader, {
447
+ }, /* @__PURE__ */ import_react6.default.createElement(InputHeader, {
230
448
  error
231
- }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.Label, null, label)), /* @__PURE__ */ import_react5.default.createElement("div", {
232
- className: (0, import_react_ui_theme2.mx)("grid gap-2", gridCols[binding.length - 1])
233
- }, binding.map((prop) => /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Input.TextInput, {
449
+ }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react6.default.createElement("div", {
450
+ className: (0, import_react_ui_theme4.mx)("grid gap-2", gridCols[binding.length - 1])
451
+ }, binding.map((prop) => /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.TextInput, {
234
452
  key: prop,
235
453
  type: "number",
236
454
  disabled,
237
455
  value: values[prop],
238
- onChange: (event) => onValueChange(property, type, {
456
+ onChange: (event) => onValueChange(type, {
239
457
  ...values,
240
458
  [prop]: (0, import_util2.safeParseFloat)(event.target.value, 0)
241
459
  }),
242
460
  onBlur
243
461
  }))));
244
462
  };
245
- var TextInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
246
- const { status, error } = getStatus?.(property);
247
- return /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Root, {
463
+ var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
464
+ const { status, error } = getStatus();
465
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Root, {
248
466
  validationValence: status
249
- }, !inputOnly && /* @__PURE__ */ import_react6.default.createElement(InputHeader, {
467
+ }, !inputOnly && /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
250
468
  error
251
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.TextInput, {
469
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.TextInput, {
252
470
  disabled,
253
471
  placeholder,
254
- value: getValue2(property) ?? "",
255
- onChange: (event) => onValueChange(property, type, event.target.value),
472
+ value: getValue3() ?? "",
473
+ onChange: (event) => onValueChange(type, event.target.value),
256
474
  onBlur
257
- }), inputOnly && /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Validation, null, error));
475
+ }), inputOnly && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Validation, null, error));
258
476
  };
259
- var NumberInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
260
- const { status, error } = getStatus?.(property);
261
- return /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Root, {
477
+ var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
478
+ const { status, error } = getStatus();
479
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Root, {
262
480
  validationValence: status
263
- }, !inputOnly && /* @__PURE__ */ import_react6.default.createElement(InputHeader, {
481
+ }, !inputOnly && /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
264
482
  error
265
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.TextInput, {
483
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.TextInput, {
266
484
  type: "number",
267
485
  disabled,
268
486
  placeholder,
269
- value: getValue2(property) ?? 0,
270
- onChange: (event) => onValueChange(property, type, event.target.value),
487
+ value: getValue3() ?? 0,
488
+ onChange: (event) => onValueChange(type, event.target.value),
271
489
  onBlur
272
- }), inputOnly && /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.DescriptionAndValidation, null, error));
490
+ }), inputOnly && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
273
491
  };
274
- var BooleanInput = ({ property, type, label, inputOnly, getStatus, getValue: getValue2, onValueChange }) => {
275
- const { status, error } = getStatus?.(property);
276
- return /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Root, {
492
+ var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
493
+ const { status, error } = getStatus();
494
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Root, {
277
495
  validationValence: status
278
- }, !inputOnly && /* @__PURE__ */ import_react6.default.createElement(InputHeader, {
496
+ }, !inputOnly && /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
279
497
  error
280
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Switch, {
281
- checked: getValue2(property),
282
- onCheckedChange: (value) => onValueChange(property, type, value)
283
- }), inputOnly && /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.DescriptionAndValidation, null, error));
498
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Switch, {
499
+ checked: getValue3(),
500
+ onCheckedChange: (value) => onValueChange(type, value)
501
+ }), inputOnly && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
284
502
  };
285
- var SelectInput = ({ property, type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue2, onValueChange }) => {
286
- const { status, error } = getStatus?.(property);
287
- return /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Root, {
503
+ var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
504
+ const { status, error } = getStatus();
505
+ return /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Root, {
288
506
  validationValence: status
289
- }, !inputOnly && /* @__PURE__ */ import_react6.default.createElement(InputHeader, {
507
+ }, !inputOnly && /* @__PURE__ */ import_react7.default.createElement(InputHeader, {
290
508
  error
291
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.Label, null, label)), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.Root, {
292
- value: getValue2(property),
293
- onValueChange: (value) => onValueChange(property, type, value)
294
- }, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.TriggerButton, {
509
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.Label, null, label)), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.Root, {
510
+ value: getValue3(),
511
+ onValueChange: (value) => onValueChange(type, value)
512
+ }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.TriggerButton, {
295
513
  classNames: "is-full",
296
514
  disabled,
297
515
  placeholder
298
- }), /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.Portal, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.Content, null, /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.Viewport, null, options?.map(({ value, label: label2 }) => (
516
+ }), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.Portal, null, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.Content, null, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.Viewport, null, options?.map(({ value, label: label2 }) => (
299
517
  // NOTE: Numeric values are converted to and from strings.
300
- /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Select.Option, {
518
+ /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Select.Option, {
301
519
  key: String(value),
302
520
  value: String(value)
303
521
  }, label2 ?? String(value))
304
- )))))), inputOnly && /* @__PURE__ */ import_react6.default.createElement(import_react_ui6.Input.DescriptionAndValidation, null, error));
305
- };
306
- var getInputComponent = (type, format) => {
307
- switch (format) {
308
- case import_echo_schema3.FormatEnum.LatLng:
309
- return GeoPointInput;
310
- }
311
- switch (type) {
312
- case "string":
313
- return TextInput;
314
- case "number":
315
- return NumberInput;
316
- case "boolean":
317
- return BooleanInput;
318
- }
522
+ )))))), inputOnly && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.Input.DescriptionAndValidation, null, error));
319
523
  };
320
524
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
321
525
  var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
322
- const [values, setValues] = (0, import_react8.useState)(initialValues);
323
- (0, import_react8.useEffect)(() => {
526
+ const [values, setValues] = (0, import_react11.useState)(initialValues);
527
+ (0, import_react11.useEffect)(() => {
324
528
  setValues(initialValues);
325
529
  }, [
326
530
  initialValues
327
531
  ]);
328
- const [touched, setTouched] = (0, import_react8.useState)(createKeySet(initialValues, false));
329
- const [changed, setChanged] = (0, import_react8.useState)(createKeySet(initialValues, false));
330
- const [errors, setErrors] = (0, import_react8.useState)({});
331
- const [saving, setSaving] = (0, import_react8.useState)(false);
332
- const validate = (0, import_react8.useCallback)((values2) => {
333
- let errors2 = (0, import_schema3.validateSchema)(schema, values2) ?? [];
532
+ const [touched, setTouched] = (0, import_react11.useState)(createKeySet(initialValues, false));
533
+ const [changed, setChanged] = (0, import_react11.useState)(createKeySet(initialValues, false));
534
+ const [errors, setErrors] = (0, import_react11.useState)({});
535
+ const [saving, setSaving] = (0, import_react11.useState)(false);
536
+ const validate = (0, import_react11.useCallback)((values2) => {
537
+ let errors2 = (0, import_schema2.validateSchema)(schema, values2) ?? [];
334
538
  if (errors2.length === 0 && onValidate) {
335
539
  const validatedValues = values2;
336
540
  errors2 = onValidate(validatedValues) ?? [];
@@ -342,11 +546,11 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
342
546
  schema,
343
547
  onValidate
344
548
  ]);
345
- const [schemaDirty, setSchemaDirty] = (0, import_react8.useState)(false);
346
- (0, import_react8.useEffect)(() => setSchemaDirty(true), [
549
+ const [schemaDirty, setSchemaDirty] = (0, import_react11.useState)(false);
550
+ (0, import_react11.useEffect)(() => setSchemaDirty(true), [
347
551
  schema
348
552
  ]);
349
- (0, import_react8.useEffect)(() => {
553
+ (0, import_react11.useEffect)(() => {
350
554
  if (schemaDirty) {
351
555
  validate(values);
352
556
  setSchemaDirty(false);
@@ -355,13 +559,13 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
355
559
  values,
356
560
  schemaDirty
357
561
  ]);
358
- const canSave = (0, import_react8.useMemo)(() => !saving && Object.keys(values).every((property) => touched[property] === false || !errors[property]), [
359
- values,
562
+ const canSave = (0, import_react11.useMemo)(() => !saving && // Check if any error paths that are touched have errors
563
+ !Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
360
564
  touched,
361
565
  errors,
362
566
  saving
363
567
  ]);
364
- const handleSave = (0, import_react8.useCallback)(async () => {
568
+ const handleSave = (0, import_react11.useCallback)(async () => {
365
569
  if (validate(values)) {
366
570
  setSaving(true);
367
571
  try {
@@ -378,38 +582,42 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
378
582
  onSave,
379
583
  changed
380
584
  ]);
381
- const getStatus = (0, import_react8.useCallback)((property) => ({
382
- status: errors[property] ? "error" : void 0,
383
- error: errors[property] ? errors[property] : void 0
384
- }), [
385
- touched,
585
+ const getStatus = (0, import_react11.useCallback)((path) => {
586
+ const jsonPath = Array.isArray(path) ? (0, import_effect2.createJsonPath)(path) : path;
587
+ const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
588
+ return {
589
+ status: matchingError ? "error" : void 0,
590
+ error: matchingError ? matchingError[1] : void 0
591
+ };
592
+ }, [
386
593
  errors
387
594
  ]);
388
- const getFormValue = (property) => {
389
- return (0, import_echo_schema4.getValue)(values, property);
595
+ const getFormValue = (path) => {
596
+ return (0, import_echo_schema3.getValue)(values, (0, import_effect2.createJsonPath)(path));
390
597
  };
391
- const onValueChange = (property, type, value) => {
598
+ const onValueChange = (path, type, value) => {
599
+ const jsonPath = (0, import_effect2.createJsonPath)(path);
392
600
  let parsedValue = value;
393
601
  try {
394
602
  if (type === "number") {
395
603
  parsedValue = parseFloat(value) || 0;
396
604
  }
397
605
  } catch (err) {
398
- import_log3.log.catch(err, void 0, {
606
+ import_log2.log.catch(err, void 0, {
399
607
  F: __dxlog_file,
400
- L: 178,
608
+ L: 192,
401
609
  S: void 0,
402
610
  C: (f, a) => f(...a)
403
611
  });
404
612
  parsedValue = void 0;
405
613
  }
406
614
  const newValues = {
407
- ...(0, import_echo_schema4.setValue)(values, property, parsedValue)
615
+ ...(0, import_echo_schema3.setValue)(values, jsonPath, parsedValue)
408
616
  };
409
617
  setValues(newValues);
410
618
  setChanged((prev) => ({
411
619
  ...prev,
412
- [property]: true
620
+ [jsonPath]: true
413
621
  }));
414
622
  onValuesChanged?.(newValues);
415
623
  const isValid = validate(newValues);
@@ -419,15 +627,12 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
419
627
  });
420
628
  }
421
629
  };
422
- const onBlur = (0, import_react8.useCallback)((event) => {
423
- const { name } = event.target;
630
+ const onTouched = (0, import_react11.useCallback)((path) => {
631
+ const jsonPath = (0, import_effect2.createJsonPath)(path);
424
632
  setTouched((touched2) => ({
425
633
  ...touched2,
426
- [name]: true
634
+ [jsonPath]: true
427
635
  }));
428
- if (event.relatedTarget?.getAttribute("type") === "submit") {
429
- setTouched(createKeySet(values, true));
430
- }
431
636
  validate(values);
432
637
  }, [
433
638
  validate,
@@ -445,13 +650,13 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
445
650
  getStatus,
446
651
  getValue: getFormValue,
447
652
  onValueChange,
448
- onBlur
653
+ onTouched
449
654
  };
450
655
  };
451
656
  var createKeySet = (obj, value) => {
452
657
  (0, import_invariant.invariant)(obj, void 0, {
453
658
  F: __dxlog_file,
454
- L: 229,
659
+ L: 234,
455
660
  S: void 0,
456
661
  A: [
457
662
  "obj",
@@ -465,322 +670,336 @@ var createKeySet = (obj, value) => {
465
670
  };
466
671
  var flatMap = (errors) => {
467
672
  return errors.reduce((result, { path, message }) => {
468
- if (!(path in result)) {
469
- result[path] = message;
673
+ const jsonPath = (0, import_effect2.fromEffectValidationPath)(path);
674
+ if (!(jsonPath in result)) {
675
+ result[jsonPath] = message;
470
676
  }
471
677
  return result;
472
678
  }, {});
473
679
  };
474
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/Form.tsx";
680
+ var FormContext = /* @__PURE__ */ (0, import_react10.createContext)(void 0);
681
+ var useFormContext = () => {
682
+ return (0, import_react10.useContext)(FormContext) ?? (0, import_debug.raise)(new Error("Missing FormContext"));
683
+ };
684
+ var useFormValues = (path = []) => {
685
+ const { values: formValues } = useFormContext();
686
+ const jsonPath = (0, import_effect.createJsonPath)(path);
687
+ return (0, import_echo_schema2.getValue)(formValues, jsonPath);
688
+ };
689
+ var useInputProps = (path = []) => {
690
+ const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
691
+ return {
692
+ getStatus: () => getStatus(path),
693
+ getValue: () => getFormValue(path),
694
+ onValueChange: (type, value) => onValueChange(path, type, value),
695
+ onBlur: () => onTouched(path)
696
+ };
697
+ };
698
+ var FormProvider = ({ children, ...formOptions }) => {
699
+ const formHandler = useForm(formOptions);
700
+ return /* @__PURE__ */ import_react10.default.createElement(FormContext.Provider, {
701
+ value: formHandler
702
+ }, children);
703
+ };
704
+ var FormActions = ({ onCancel, readonly }) => {
705
+ const { t } = (0, import_react_ui8.useTranslation)(translationKey);
706
+ const { canSave, handleSave } = useFormContext();
707
+ return /* @__PURE__ */ import_react9.default.createElement("div", {
708
+ role: "none",
709
+ className: "flex justify-center"
710
+ }, /* @__PURE__ */ import_react9.default.createElement("div", {
711
+ role: "none",
712
+ className: (0, import_react_ui_theme6.mx)(onCancel && !readonly && "grid grid-cols-2 gap-2")
713
+ }, onCancel && !readonly && /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.IconButton, {
714
+ "data-testid": "cancel-button",
715
+ icon: "ph--x--regular",
716
+ label: t("button cancel"),
717
+ onClick: onCancel
718
+ }), handleSave && /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.IconButton, {
719
+ type: "submit",
720
+ "data-testid": "save-button",
721
+ disabled: !canSave,
722
+ icon: "ph--check--regular",
723
+ label: t("button save"),
724
+ onClick: handleSave
725
+ })));
726
+ };
727
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
475
728
  var padding = "px-2";
476
- var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
477
- const onValid = (0, import_react7.useMemo)(() => autoSave ? onSave : void 0, [
478
- autoSave,
479
- onSave
480
- ]);
481
- const { canSave, values, errors, handleSave, ...inputProps } = useForm({
482
- schema,
483
- initialValues,
484
- onValuesChanged,
485
- onValidate,
486
- onValid,
487
- onSave
729
+ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
730
+ const { t } = (0, import_react_ui9.useTranslation)(translationKey);
731
+ const { ast, name, type, title } = property;
732
+ const values = useFormValues(path ?? []);
733
+ (0, import_invariant2.invariant)(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
734
+ F: __dxlog_file2,
735
+ L: 37,
736
+ S: void 0,
737
+ A: [
738
+ "Array.isArray(values)",
739
+ "`Values at path ${path?.join('.')} must be an array.`"
740
+ ]
488
741
  });
489
- const properties = (0, import_react7.useMemo)(() => {
490
- const props = (0, import_schema2.getSchemaProperties)(schema.ast, values);
491
- const filtered = filter ? filter(props) : props;
492
- const findIndex = (props2, prop) => {
493
- const idx = props2.findIndex((p) => p === prop);
494
- return idx === -1 ? Infinity : idx;
495
- };
496
- return sort ? filtered.sort(({ name: a }, { name: b }) => findIndex(sort, a) - findIndex(sort, b)) : filtered;
742
+ const label = title ?? (0, import_effect5.pipe)(name, import_String2.capitalize);
743
+ const tupleType = (0, import_effect6.findNode)(ast, import_echo_schema5.AST.isTupleType);
744
+ const elementType = tupleType?.rest[0]?.type;
745
+ const getDefaultObjectValue = (typeNode) => {
746
+ const baseNode = (0, import_effect6.findNode)(typeNode, import_effect6.isDiscriminatedUnion);
747
+ const typeLiteral = baseNode ? (0, import_effect6.getDiscriminatedType)(baseNode, {}) : (0, import_effect6.findNode)(typeNode, import_echo_schema5.AST.isTypeLiteral);
748
+ if (!typeLiteral) {
749
+ return {};
750
+ }
751
+ return Object.fromEntries((0, import_schema4.getSchemaProperties)(typeLiteral, {}).map((prop) => [
752
+ prop.name,
753
+ prop.defaultValue
754
+ ]));
755
+ };
756
+ const newValue = (0, import_react13.useMemo)(() => {
757
+ if (type === "object" && elementType) {
758
+ return getDefaultObjectValue(elementType);
759
+ } else {
760
+ return import_effect6.SimpleType.getDefaultValue(type);
761
+ }
497
762
  }, [
498
- schema,
499
- filter,
763
+ type,
764
+ elementType
765
+ ]);
766
+ const handleAdd = (0, import_react13.useCallback)(() => {
767
+ inputProps.onValueChange(type, [
768
+ ...values,
769
+ newValue
770
+ ]);
771
+ }, [
772
+ type,
773
+ elementType,
774
+ inputProps,
775
+ newValue,
500
776
  values
501
777
  ]);
502
- (0, import_react7.useEffect)(() => {
503
- if (errors && Object.keys(errors).length) {
504
- import_log2.log.warn("validation", {
505
- errors
506
- }, {
507
- F: __dxlog_file2,
508
- L: 106,
509
- S: void 0,
510
- C: (f, a) => f(...a)
511
- });
512
- }
778
+ const handleRemove = (0, import_react13.useCallback)((index) => {
779
+ const newValues = values.filter((_, i) => i !== index);
780
+ inputProps.onValueChange(type, newValues);
513
781
  }, [
514
- errors
782
+ type,
783
+ inputProps,
784
+ values
515
785
  ]);
516
- return /* @__PURE__ */ import_react7.default.createElement("div", {
517
- role: "form",
518
- className: (0, import_react_ui_theme3.mx)("flex flex-col w-full gap-2 py-2", classNames),
519
- "data-testid": testId
520
- }, properties.map((property) => {
521
- const { ast, name, type, format, title, description, examples, options, array } = property;
522
- const key = [
523
- ...path,
524
- name
525
- ];
526
- const label = title ?? (0, import_effect.pipe)(name, import_String.capitalize);
527
- const placeholder = examples?.length ? `Example: "${examples[0]}"` : description;
528
- const FoundComponent = lookupComponent?.({
529
- prop: name,
530
- schema: import_echo_schema2.S.make(ast),
531
- inputProps: {
532
- property: name,
533
- type,
534
- format,
535
- label,
536
- disabled: readonly,
537
- placeholder,
538
- ...inputProps
539
- }
540
- });
541
- if (FoundComponent) {
542
- return /* @__PURE__ */ import_react7.default.createElement("div", {
543
- key: name,
544
- role: "none",
545
- className: padding
546
- }, FoundComponent);
547
- }
548
- let InputComponent = Custom?.[key.join(".")];
549
- if (!InputComponent) {
550
- if (options) {
551
- return /* @__PURE__ */ import_react7.default.createElement("div", {
552
- key: name,
553
- role: "none",
554
- className: padding
555
- }, /* @__PURE__ */ import_react7.default.createElement(SelectInput, {
556
- type,
557
- format,
558
- property: name,
559
- disabled: readonly,
560
- label,
561
- options: options.map((option) => ({
562
- value: option,
563
- label: String(option)
564
- })),
565
- placeholder,
566
- ...inputProps
567
- }));
568
- }
569
- InputComponent = getInputComponent(type, format);
570
- if (array) {
571
- return /* @__PURE__ */ import_react7.default.createElement(ArrayField, {
572
- key: name,
573
- name,
574
- type,
575
- array: true,
576
- label,
577
- ast,
578
- values,
579
- format,
580
- readonly,
581
- placeholder,
582
- inputProps,
583
- Custom
584
- });
585
- }
586
- }
587
- if (!InputComponent) {
588
- if (type === "object") {
589
- const baseNode = (0, import_effect2.findNode)(ast, import_effect2.isDiscriminatedUnion);
590
- const typeLiteral = baseNode ? (0, import_effect2.getDiscriminatedType)(baseNode, values[name]) : (0, import_effect2.findNode)(ast, import_echo_schema2.AST.isTypeLiteral);
591
- if (typeLiteral) {
592
- const schema2 = import_echo_schema2.S.make(typeLiteral);
593
- return /* @__PURE__ */ import_react7.default.createElement("div", {
594
- key: name,
595
- role: "none"
596
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
597
- className: padding
598
- }, label), /* @__PURE__ */ import_react7.default.createElement(Form, {
599
- schema: schema2,
600
- path: key,
601
- values: values[name] ?? {},
602
- onValuesChanged: (childValues) => {
603
- inputProps.onValueChange(name, "object", childValues);
604
- },
605
- Custom
606
- }));
607
- }
608
- }
609
- (0, import_log2.log)("no renderer for property", {
610
- name,
611
- type
612
- }, {
613
- F: __dxlog_file2,
614
- L: 213,
615
- S: void 0,
616
- C: (f, a) => f(...a)
617
- });
618
- return null;
619
- }
620
- return /* @__PURE__ */ import_react7.default.createElement("div", {
621
- key: name,
622
- role: "none",
623
- className: padding
624
- }, /* @__PURE__ */ import_react7.default.createElement(InputComponent, {
625
- type,
626
- format,
627
- property: name,
628
- disabled: readonly,
629
- label,
630
- placeholder,
631
- ...inputProps
632
- }));
633
- }).filter(import_util3.isNotFalsy), (onCancel || onSave) && !autoSave && /* @__PURE__ */ import_react7.default.createElement(FormActions, {
634
- onCancel,
635
- onSubmit: handleSave,
636
- canSubmit: canSave,
637
- readonly
638
- }));
639
- };
640
- var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholder, inputProps, Custom }) => {
641
- const { t } = (0, import_react_ui7.useTranslation)(translationKey);
642
- const arrayValues = values[name] ?? [];
643
- const key = [
644
- name
645
- ];
646
- const tupleType = (0, import_effect2.findNode)(ast, import_echo_schema2.AST.isTupleType);
647
- const elementType = tupleType?.rest[0]?.type;
648
- if (type === "object" && elementType) {
649
- const baseNode = (0, import_effect2.findNode)(elementType, import_effect2.isDiscriminatedUnion);
650
- const typeLiteral = baseNode ? (0, import_effect2.getDiscriminatedType)(baseNode, values[name]) : (0, import_effect2.findNode)(elementType, import_echo_schema2.AST.isTypeLiteral);
651
- if (typeLiteral) {
652
- const schema = import_echo_schema2.S.make(typeLiteral);
653
- return /* @__PURE__ */ import_react7.default.createElement("div", {
654
- key: name,
655
- role: "none",
656
- className: (0, import_react_ui_theme3.mx)(padding)
657
- }, /* @__PURE__ */ import_react7.default.createElement(InputHeader, null, label), /* @__PURE__ */ import_react7.default.createElement("div", {
658
- role: "none",
659
- className: "flex flex-col gap-1"
660
- }, arrayValues.map((value, index) => {
661
- return /* @__PURE__ */ import_react7.default.createElement("div", {
662
- key: index,
663
- role: "none",
664
- className: "flex items-center gap-1"
665
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
666
- role: "none",
667
- className: "flex-1"
668
- }, /* @__PURE__ */ import_react7.default.createElement(Form, {
669
- schema,
670
- path: [
671
- ...key,
672
- `[${index}]`
673
- ],
674
- values: value,
675
- onValuesChanged: (childValues) => {
676
- const newValues = [
677
- ...arrayValues
678
- ];
679
- newValues[index] = childValues;
680
- inputProps.onValueChange(name, "object", newValues);
681
- },
682
- Custom
683
- })), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
684
- icon: "ph--trash--regular",
685
- iconOnly: true,
686
- label: t("button remove"),
687
- onClick: () => {
688
- const newValues = arrayValues.filter((_, i) => i !== index);
689
- inputProps.onValueChange(name, type, newValues);
690
- }
691
- }));
692
- })), /* @__PURE__ */ import_react7.default.createElement("div", {
693
- role: "none",
694
- className: "flex justify-between items-center plb-1"
695
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
696
- icon: "ph--plus--regular",
697
- iconOnly: true,
698
- label: t("button add"),
699
- onClick: () => {
700
- const newValues = [
701
- ...arrayValues,
702
- {}
703
- ];
704
- inputProps.onValueChange(name, type, newValues);
705
- }
706
- })));
707
- }
708
- return /* @__PURE__ */ import_react7.default.createElement("div", {
709
- key: name,
710
- role: "none"
711
- }, "Nested form not supported in arrays, yet.");
712
- }
713
- const InputComponent = getInputComponent(type, format);
714
- if (!InputComponent) {
786
+ if (!elementType) {
715
787
  return null;
716
788
  }
717
- return /* @__PURE__ */ import_react7.default.createElement("div", {
789
+ return /* @__PURE__ */ import_react13.default.createElement("div", {
718
790
  role: "none",
719
- key: "meta-input",
720
- className: (0, import_react_ui_theme3.mx)(padding)
721
- }, /* @__PURE__ */ import_react7.default.createElement(InputHeader, null, label), /* @__PURE__ */ import_react7.default.createElement("div", {
791
+ className: (0, import_react_ui_theme8.mx)(padding)
792
+ }, /* @__PURE__ */ import_react13.default.createElement(InputHeader, null, label), /* @__PURE__ */ import_react13.default.createElement("div", {
722
793
  role: "none",
723
794
  className: "flex flex-col gap-1"
724
- }, arrayValues.map((_, index) => /* @__PURE__ */ import_react7.default.createElement("div", {
795
+ }, values.map((_value, index) => /* @__PURE__ */ import_react13.default.createElement("div", {
725
796
  key: index,
726
797
  role: "none",
727
- className: "flex items-start gap-1"
728
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
798
+ className: "flex items-center gap-1"
799
+ }, /* @__PURE__ */ import_react13.default.createElement("div", {
729
800
  role: "none",
730
801
  className: "flex-1"
731
- }, /* @__PURE__ */ import_react7.default.createElement(InputComponent, {
732
- type,
733
- format,
734
- label,
735
- inputOnly: true,
736
- property: `${name}[${index}]`,
737
- disabled: readonly,
738
- placeholder,
739
- ...inputProps
740
- })), /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
802
+ }, /* @__PURE__ */ import_react13.default.createElement(FormField, {
803
+ property: {
804
+ ...property,
805
+ array: false,
806
+ ast: elementType
807
+ },
808
+ path: [
809
+ ...path ?? [],
810
+ index
811
+ ],
812
+ readonly,
813
+ inline: true,
814
+ Custom,
815
+ lookupComponent
816
+ })), /* @__PURE__ */ import_react13.default.createElement(import_react_ui9.IconButton, {
741
817
  icon: "ph--trash--regular",
742
818
  iconOnly: true,
743
819
  label: t("button remove"),
744
- onClick: () => {
745
- const newValues = arrayValues.filter((_2, i) => i !== index);
746
- inputProps.onValueChange(name, type, newValues);
747
- }
748
- })))), /* @__PURE__ */ import_react7.default.createElement("div", {
820
+ onClick: () => handleRemove(index)
821
+ })))), /* @__PURE__ */ import_react13.default.createElement("div", {
749
822
  role: "none",
750
823
  className: "flex justify-between items-center plb-1"
751
- }, /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
824
+ }, /* @__PURE__ */ import_react13.default.createElement(import_react_ui9.IconButton, {
752
825
  icon: "ph--plus--regular",
753
826
  iconOnly: true,
754
827
  label: t("button add"),
755
- onClick: () => {
756
- const newValues = [
757
- ...arrayValues,
758
- import_effect2.SimpleType.getDefaultValue(type)
759
- ];
760
- inputProps.onValueChange(name, type, newValues);
761
- }
828
+ onClick: handleAdd
762
829
  })));
763
830
  };
764
- var FormActions = ({ onCancel, onSubmit, canSubmit, readonly }) => {
765
- const { t } = (0, import_react_ui7.useTranslation)(translationKey);
766
- return /* @__PURE__ */ import_react7.default.createElement("div", {
767
- role: "none",
768
- className: "flex justify-center"
769
- }, /* @__PURE__ */ import_react7.default.createElement("div", {
831
+ var getInputComponent = (type, format) => {
832
+ switch (format) {
833
+ case import_echo_schema6.FormatEnum.LatLng:
834
+ return GeoPointInput;
835
+ }
836
+ switch (type) {
837
+ case "string":
838
+ return TextInput;
839
+ case "number":
840
+ return NumberInput;
841
+ case "boolean":
842
+ return BooleanInput;
843
+ }
844
+ };
845
+ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom }) => {
846
+ const inputProps = useInputProps(path);
847
+ const { ast, name, type, format, title, description, options, examples, array } = property;
848
+ const label = (0, import_react12.useMemo)(() => title ?? (0, import_effect3.pipe)(name, import_String.capitalize), [
849
+ title,
850
+ name
851
+ ]);
852
+ const placeholder = (0, import_react12.useMemo)(() => examples?.length ? `Example: "${examples[0]}"` : description, [
853
+ examples,
854
+ description
855
+ ]);
856
+ const FoundComponent = lookupComponent?.({
857
+ prop: name,
858
+ schema: import_echo_schema4.S.make(ast),
859
+ inputProps: {
860
+ type,
861
+ format,
862
+ label,
863
+ disabled: readonly,
864
+ placeholder,
865
+ ...inputProps
866
+ }
867
+ });
868
+ if (FoundComponent) {
869
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
870
+ role: "none"
871
+ }, FoundComponent);
872
+ }
873
+ const jsonPath = (0, import_effect4.createJsonPath)(path ?? []);
874
+ const CustomComponent = Custom?.[jsonPath];
875
+ if (CustomComponent) {
876
+ return (
877
+ // TODO(ZaymonFC): We should try to remove this div wrapper.
878
+ /* @__PURE__ */ import_react12.default.createElement("div", {
879
+ role: "none"
880
+ }, /* @__PURE__ */ import_react12.default.createElement(CustomComponent, {
881
+ type,
882
+ format,
883
+ label,
884
+ inputOnly: inline,
885
+ placeholder,
886
+ disabled: readonly,
887
+ ...inputProps
888
+ }))
889
+ );
890
+ }
891
+ if (array) {
892
+ return /* @__PURE__ */ import_react12.default.createElement(ArrayField, {
893
+ property,
894
+ path,
895
+ inputProps,
896
+ readonly,
897
+ Custom
898
+ });
899
+ }
900
+ const InputComponent = getInputComponent(type, format);
901
+ if (InputComponent) {
902
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
903
+ role: "none"
904
+ }, /* @__PURE__ */ import_react12.default.createElement(InputComponent, {
905
+ type,
906
+ format,
907
+ label,
908
+ inputOnly: inline,
909
+ placeholder,
910
+ disabled: readonly,
911
+ ...inputProps
912
+ }));
913
+ }
914
+ if (options) {
915
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
916
+ role: "none"
917
+ }, /* @__PURE__ */ import_react12.default.createElement(SelectInput, {
918
+ type,
919
+ format,
920
+ disabled: readonly,
921
+ inputOnly: inline,
922
+ label,
923
+ options: options.map((option) => ({
924
+ value: option,
925
+ label: String(option)
926
+ })),
927
+ placeholder,
928
+ ...inputProps
929
+ }));
930
+ }
931
+ if (type === "object") {
932
+ const baseNode = (0, import_effect4.findNode)(ast, import_effect4.isDiscriminatedUnion);
933
+ const typeLiteral = baseNode ? (0, import_effect4.getDiscriminatedType)(baseNode, inputProps.getValue()) : (0, import_effect4.findNode)(ast, import_echo_schema4.AST.isTypeLiteral);
934
+ if (typeLiteral) {
935
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
936
+ role: "none"
937
+ }, !inline && /* @__PURE__ */ import_react12.default.createElement("div", null, label), /* @__PURE__ */ import_react12.default.createElement(FormFields, {
938
+ schema: import_echo_schema4.S.make(typeLiteral),
939
+ path,
940
+ readonly,
941
+ Custom
942
+ }));
943
+ }
944
+ }
945
+ return null;
946
+ };
947
+ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custom }) => {
948
+ const values = useFormValues(path);
949
+ const properties = (0, import_react12.useMemo)(() => {
950
+ const props = (0, import_schema3.getSchemaProperties)(schema.ast, values);
951
+ const filtered = filter ? filter(props) : props;
952
+ return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
953
+ }, [
954
+ schema,
955
+ values,
956
+ filter,
957
+ sort
958
+ ]);
959
+ return /* @__PURE__ */ import_react12.default.createElement("div", {
960
+ role: "form",
961
+ className: (0, import_react_ui_theme7.mx)("flex flex-col w-full gap-2 py-2")
962
+ }, properties.map((property) => {
963
+ return /* @__PURE__ */ import_react12.default.createElement(FormField, {
964
+ key: property.name,
965
+ property,
966
+ path: [
967
+ ...path ?? [],
968
+ property.name
969
+ ],
970
+ readonly,
971
+ lookupComponent,
972
+ Custom
973
+ });
974
+ }).filter(import_util3.isNotFalsy));
975
+ };
976
+ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
977
+ const onValid = (0, import_react8.useMemo)(() => autoSave ? onSave : void 0, [
978
+ autoSave,
979
+ onSave
980
+ ]);
981
+ return /* @__PURE__ */ import_react8.default.createElement(FormProvider, {
982
+ schema,
983
+ initialValues,
984
+ onValuesChanged,
985
+ onValidate,
986
+ onValid,
987
+ onSave
988
+ }, /* @__PURE__ */ import_react8.default.createElement("div", {
770
989
  role: "none",
771
- className: (0, import_react_ui_theme3.mx)(onCancel && !readonly && "grid grid-cols-2 gap-2")
772
- }, onCancel && !readonly && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
773
- "data-testid": "cancel-button",
774
- icon: "ph--x--regular",
775
- label: t("button cancel"),
776
- onClick: onCancel
777
- }), onSubmit && /* @__PURE__ */ import_react7.default.createElement(import_react_ui7.IconButton, {
778
- type: "submit",
779
- "data-testid": "save-button",
780
- disabled: !canSubmit,
781
- icon: "ph--check--regular",
782
- label: t("button save"),
783
- onClick: onSubmit
990
+ className: (0, import_react_ui_theme5.mx)("p-2", classNames),
991
+ "data-testid": testId
992
+ }, /* @__PURE__ */ import_react8.default.createElement(FormFields, {
993
+ schema,
994
+ path,
995
+ readonly,
996
+ filter,
997
+ sort,
998
+ lookupComponent,
999
+ Custom
1000
+ }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ import_react8.default.createElement(FormActions, {
1001
+ onCancel,
1002
+ readonly
784
1003
  })));
785
1004
  };
786
1005
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
@@ -848,7 +1067,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
848
1067
  type
849
1068
  };
850
1069
  }
851
- return props2;
1070
+ return _props;
852
1071
  });
853
1072
  }, [
854
1073
  schemas,
@@ -904,7 +1123,8 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
904
1123
  options: referenceSchema ? (0, import_schema.getSchemaProperties)(referenceSchema.ast).sort(import_schema.sortProperties).map((p) => ({
905
1124
  value: p.name
906
1125
  })) : []
907
- })
1126
+ }),
1127
+ ["options"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectOptionInput, props2)
908
1128
  }), [
909
1129
  t,
910
1130
  schemas,
@@ -916,7 +1136,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
916
1136
  props
917
1137
  }, {
918
1138
  F: __dxlog_file3,
919
- L: 173,
1139
+ L: 174,
920
1140
  S: void 0,
921
1141
  C: (f, a) => f(...a)
922
1142
  });
@@ -940,22 +1160,22 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
940
1160
  });
941
1161
  };
942
1162
  var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
943
- var ViewMetaSchema = import_echo_schema5.S.Struct({
944
- name: import_echo_schema5.S.String.annotations({
945
- [import_echo_schema5.AST.TitleAnnotationId]: "View"
1163
+ var ViewMetaSchema = import_echo_schema7.S.Struct({
1164
+ name: import_echo_schema7.S.String.annotations({
1165
+ [import_echo_schema7.AST.TitleAnnotationId]: "View"
946
1166
  }),
947
- typename: import_echo_schema5.Format.DXN.annotations({
948
- [import_echo_schema5.AST.TitleAnnotationId]: "Typename"
1167
+ typename: import_echo_schema7.Format.DXN.annotations({
1168
+ [import_echo_schema7.AST.TitleAnnotationId]: "Typename"
949
1169
  })
950
- }).pipe(import_echo_schema5.S.mutable);
1170
+ }).pipe(import_echo_schema7.S.mutable);
951
1171
  var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
952
- const { t } = (0, import_react_ui8.useTranslation)(translationKey);
953
- const projection = (0, import_react9.useMemo)(() => new import_schema4.ViewProjection(schema, view), [
1172
+ const { t } = (0, import_react_ui10.useTranslation)(translationKey);
1173
+ const projection = (0, import_react14.useMemo)(() => new import_schema5.ViewProjection(schema, view), [
954
1174
  schema,
955
1175
  view
956
1176
  ]);
957
- const [field, setField] = (0, import_react9.useState)();
958
- const viewValues = (0, import_react9.useMemo)(() => {
1177
+ const [field, setField] = (0, import_react14.useState)();
1178
+ const viewValues = (0, import_react14.useMemo)(() => {
959
1179
  return {
960
1180
  name: view.name,
961
1181
  // TODO(burdon): Need to warn user of possible consequences of editing.
@@ -965,7 +1185,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
965
1185
  }, [
966
1186
  view
967
1187
  ]);
968
- const handleViewUpdate = (0, import_react9.useCallback)(({ name, typename }) => {
1188
+ const handleViewUpdate = (0, import_react14.useCallback)(({ name, typename }) => {
969
1189
  requestAnimationFrame(() => {
970
1190
  if (view.name !== name) {
971
1191
  view.name = name;
@@ -979,72 +1199,77 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
979
1199
  schema,
980
1200
  onTypenameChanged
981
1201
  ]);
982
- const handleSelect = (0, import_react9.useCallback)((field2) => {
1202
+ const handleSelect = (0, import_react14.useCallback)((field2) => {
983
1203
  setField((f) => f === field2 ? void 0 : field2);
984
1204
  }, []);
985
- const handleAdd = (0, import_react9.useCallback)(() => {
1205
+ const handleAdd = (0, import_react14.useCallback)(() => {
986
1206
  const field2 = projection.createFieldProjection();
987
1207
  setField(field2);
988
1208
  }, [
989
1209
  view
990
1210
  ]);
991
- const handleMove = (0, import_react9.useCallback)((fromIndex, toIndex) => {
992
- (0, import_util4.arrayMove)(view.fields, fromIndex, toIndex);
1211
+ const handleMove = (0, import_react14.useCallback)((fromIndex, toIndex) => {
1212
+ const fields = [
1213
+ ...view.fields
1214
+ ];
1215
+ const [moved] = fields.splice(fromIndex, 1);
1216
+ fields.splice(toIndex, 0, moved);
1217
+ view.fields = fields;
993
1218
  }, [
994
1219
  view.fields
995
1220
  ]);
996
- const handleClose = (0, import_react9.useCallback)(() => setField(void 0), []);
997
- return /* @__PURE__ */ import_react9.default.createElement("div", {
1221
+ const handleClose = (0, import_react14.useCallback)(() => setField(void 0), []);
1222
+ return /* @__PURE__ */ import_react14.default.createElement("div", {
998
1223
  role: "none",
999
- className: (0, import_react_ui_theme4.mx)("flex flex-col w-full divide-y divide-separator", classNames)
1000
- }, /* @__PURE__ */ import_react9.default.createElement(Form, {
1224
+ className: (0, import_react_ui_theme9.mx)("flex flex-col w-full divide-y divide-separator", classNames)
1225
+ }, /* @__PURE__ */ import_react14.default.createElement(Form, {
1001
1226
  autoFocus: true,
1002
1227
  autoSave: true,
1003
1228
  schema: ViewMetaSchema,
1004
1229
  values: viewValues,
1005
1230
  onSave: handleViewUpdate
1006
- }), /* @__PURE__ */ import_react9.default.createElement("div", null, /* @__PURE__ */ import_react9.default.createElement("div", {
1231
+ }), /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement("div", {
1007
1232
  role: "none",
1008
1233
  className: "p-2"
1009
- }, /* @__PURE__ */ import_react9.default.createElement("label", {
1010
- className: (0, import_react_ui_theme4.mx)(import_react_ui_theme4.inputTextLabel)
1011
- }, t("fields label"))), /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.Root, {
1234
+ }, /* @__PURE__ */ import_react14.default.createElement("label", {
1235
+ className: (0, import_react_ui_theme9.mx)(import_react_ui_theme9.inputTextLabel)
1236
+ }, t("fields label"))), /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.Root, {
1012
1237
  items: view.fields,
1013
- isItem: import_echo_schema5.S.is(import_schema4.FieldSchema),
1238
+ isItem: import_echo_schema7.S.is(import_schema5.FieldSchema),
1014
1239
  getId: (field2) => field2.id,
1015
1240
  onMove: handleMove
1016
- }, ({ items: fields }) => /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, showHeading && /* @__PURE__ */ import_react9.default.createElement("div", {
1241
+ }, ({ items: fields }) => /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, showHeading && /* @__PURE__ */ import_react14.default.createElement("div", {
1017
1242
  role: "heading",
1018
1243
  className: grid
1019
- }, /* @__PURE__ */ import_react9.default.createElement("div", null), /* @__PURE__ */ import_react9.default.createElement("div", {
1244
+ }, /* @__PURE__ */ import_react14.default.createElement("div", null), /* @__PURE__ */ import_react14.default.createElement("div", {
1020
1245
  className: "flex items-center text-sm"
1021
- }, t("field path label"))), /* @__PURE__ */ import_react9.default.createElement("div", {
1246
+ }, t("field path label"))), /* @__PURE__ */ import_react14.default.createElement("div", {
1022
1247
  role: "list",
1023
1248
  className: "flex flex-col w-full"
1024
- }, fields?.map((field2) => /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.Item, {
1249
+ }, fields?.map((field2) => /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.Item, {
1025
1250
  key: field2.id,
1026
1251
  item: field2,
1027
- classNames: (0, import_react_ui_theme4.mx)(grid, import_react_ui_theme4.ghostHover, "cursor-pointer")
1028
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.ItemDragHandle, null), /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.ItemTitle, {
1252
+ classNames: (0, import_react_ui_theme9.mx)(grid, import_react_ui_theme9.ghostHover, "cursor-pointer")
1253
+ }, /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.ItemDragHandle, null), /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.ItemTitle, {
1029
1254
  onClick: () => handleSelect(field2)
1030
- }, field2.path), /* @__PURE__ */ import_react9.default.createElement(import_react_ui_list.List.ItemDeleteButton, {
1255
+ }, field2.path), /* @__PURE__ */ import_react14.default.createElement(import_react_ui_list2.List.ItemDeleteButton, {
1031
1256
  disabled: view.fields.length <= 1,
1032
1257
  onClick: () => onDelete(field2.id)
1033
- }))))))), field && /* @__PURE__ */ import_react9.default.createElement(FieldEditor, {
1258
+ }))))))), field && /* @__PURE__ */ import_react14.default.createElement(FieldEditor, {
1034
1259
  key: field.id,
1035
1260
  view,
1036
1261
  projection,
1037
1262
  field,
1038
1263
  registry,
1039
1264
  onSave: handleClose
1040
- }), !readonly && !field && /* @__PURE__ */ import_react9.default.createElement("div", {
1265
+ }), !readonly && !field && /* @__PURE__ */ import_react14.default.createElement("div", {
1041
1266
  className: "flex p-2 justify-center"
1042
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui8.IconButton, {
1267
+ }, /* @__PURE__ */ import_react14.default.createElement(import_react_ui10.IconButton, {
1043
1268
  icon: "ph--plus--regular",
1044
1269
  label: t("button add property"),
1045
1270
  onClick: handleAdd,
1046
1271
  // TODO(burdon): Show field limit in ux (not tooltip).
1047
- disabled: view.fields.length >= import_schema4.VIEW_FIELD_LIMIT
1272
+ disabled: view.fields.length >= import_schema5.VIEW_FIELD_LIMIT
1048
1273
  })));
1049
1274
  };
1050
1275
  var parseValue = ({ type, format, value }) => {
@@ -1053,7 +1278,7 @@ var parseValue = ({ type, format, value }) => {
1053
1278
  }
1054
1279
  const parseScalar = (type2) => {
1055
1280
  switch (type2) {
1056
- case import_echo_schema6.TypeEnum.Boolean: {
1281
+ case import_echo_schema8.TypeEnum.Boolean: {
1057
1282
  if (typeof value === "string") {
1058
1283
  const lowercaseValue = value.toLowerCase();
1059
1284
  if (lowercaseValue === "0" || lowercaseValue === "false") {
@@ -1064,13 +1289,13 @@ var parseValue = ({ type, format, value }) => {
1064
1289
  }
1065
1290
  return Boolean(value);
1066
1291
  }
1067
- case import_echo_schema6.TypeEnum.Number: {
1292
+ case import_echo_schema8.TypeEnum.Number: {
1068
1293
  const cleaned = typeof value === "string" ? value.replace(/[^0-9.-]+/g, "") : value;
1069
1294
  const num = Number(cleaned);
1070
1295
  return Number.isNaN(num) ? null : num;
1071
1296
  }
1072
- case import_echo_schema6.TypeEnum.String:
1073
- case import_echo_schema6.TypeEnum.Ref:
1297
+ case import_echo_schema8.TypeEnum.String:
1298
+ case import_echo_schema8.TypeEnum.Ref:
1074
1299
  return String(value);
1075
1300
  default: {
1076
1301
  return value;
@@ -1081,22 +1306,22 @@ var parseValue = ({ type, format, value }) => {
1081
1306
  return parseScalar(type);
1082
1307
  }
1083
1308
  switch (format) {
1084
- case import_echo_schema6.FormatEnum.Boolean:
1085
- return parseScalar(import_echo_schema6.TypeEnum.Boolean);
1086
- case import_echo_schema6.FormatEnum.Number:
1087
- case import_echo_schema6.FormatEnum.Percent:
1088
- case import_echo_schema6.FormatEnum.Currency:
1089
- return parseScalar(import_echo_schema6.TypeEnum.Number);
1090
- case import_echo_schema6.FormatEnum.String:
1091
- case import_echo_schema6.FormatEnum.Markdown: {
1092
- return parseScalar(import_echo_schema6.TypeEnum.String);
1309
+ case import_echo_schema8.FormatEnum.Boolean:
1310
+ return parseScalar(import_echo_schema8.TypeEnum.Boolean);
1311
+ case import_echo_schema8.FormatEnum.Number:
1312
+ case import_echo_schema8.FormatEnum.Percent:
1313
+ case import_echo_schema8.FormatEnum.Currency:
1314
+ return parseScalar(import_echo_schema8.TypeEnum.Number);
1315
+ case import_echo_schema8.FormatEnum.String:
1316
+ case import_echo_schema8.FormatEnum.Markdown: {
1317
+ return parseScalar(import_echo_schema8.TypeEnum.String);
1093
1318
  }
1094
- case import_echo_schema6.FormatEnum.Ref:
1095
- throw new Error(`unexpected format: ${import_echo_schema6.FormatEnum.Ref}`);
1096
- case import_echo_schema6.FormatEnum.DateTime:
1097
- case import_echo_schema6.FormatEnum.Date:
1098
- case import_echo_schema6.FormatEnum.Time:
1099
- case import_echo_schema6.FormatEnum.Timestamp: {
1319
+ case import_echo_schema8.FormatEnum.Ref:
1320
+ throw new Error(`unexpected format: ${import_echo_schema8.FormatEnum.Ref}`);
1321
+ case import_echo_schema8.FormatEnum.DateTime:
1322
+ case import_echo_schema8.FormatEnum.Date:
1323
+ case import_echo_schema8.FormatEnum.Time:
1324
+ case import_echo_schema8.FormatEnum.Timestamp: {
1100
1325
  const date = new Date(value);
1101
1326
  return isNaN(date.getTime()) ? null : date;
1102
1327
  }
@@ -1108,19 +1333,19 @@ var parseValue = ({ type, format, value }) => {
1108
1333
  var cellClassesForFieldType = ({ type, format }) => {
1109
1334
  if (!format) {
1110
1335
  switch (type) {
1111
- case import_echo_schema6.TypeEnum.Number:
1336
+ case import_echo_schema8.TypeEnum.Number:
1112
1337
  return [
1113
1338
  "text-right",
1114
1339
  "font-mono"
1115
1340
  ];
1116
- case import_echo_schema6.TypeEnum.Boolean:
1341
+ case import_echo_schema8.TypeEnum.Boolean:
1117
1342
  return [
1118
1343
  "text-right",
1119
1344
  "font-mono"
1120
1345
  ];
1121
- case import_echo_schema6.TypeEnum.String:
1346
+ case import_echo_schema8.TypeEnum.String:
1122
1347
  return void 0;
1123
- case import_echo_schema6.TypeEnum.Ref:
1348
+ case import_echo_schema8.TypeEnum.Ref:
1124
1349
  return void 0;
1125
1350
  default: {
1126
1351
  return void 0;
@@ -1128,20 +1353,20 @@ var cellClassesForFieldType = ({ type, format }) => {
1128
1353
  }
1129
1354
  }
1130
1355
  switch (format) {
1131
- case import_echo_schema6.FormatEnum.Markdown:
1356
+ case import_echo_schema8.FormatEnum.Markdown:
1132
1357
  return void 0;
1133
- case import_echo_schema6.FormatEnum.Timestamp:
1134
- case import_echo_schema6.FormatEnum.DateTime:
1135
- case import_echo_schema6.FormatEnum.Date:
1136
- case import_echo_schema6.FormatEnum.Time:
1358
+ case import_echo_schema8.FormatEnum.Timestamp:
1359
+ case import_echo_schema8.FormatEnum.DateTime:
1360
+ case import_echo_schema8.FormatEnum.Date:
1361
+ case import_echo_schema8.FormatEnum.Time:
1137
1362
  return [
1138
1363
  "font-mono"
1139
1364
  ];
1140
- case import_echo_schema6.FormatEnum.Currency:
1365
+ case import_echo_schema8.FormatEnum.Currency:
1141
1366
  return [
1142
1367
  "text-right"
1143
1368
  ];
1144
- case import_echo_schema6.FormatEnum.JSON:
1369
+ case import_echo_schema8.FormatEnum.JSON:
1145
1370
  return [
1146
1371
  "font-mono"
1147
1372
  ];
@@ -1159,12 +1384,12 @@ var pathNotUniqueError = (path) => ({
1159
1384
  var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1160
1385
  const formatScalar = (type2) => {
1161
1386
  switch (type2) {
1162
- case import_echo_schema7.TypeEnum.Boolean:
1387
+ case import_echo_schema9.TypeEnum.Boolean:
1163
1388
  return value.toLocaleString().toUpperCase();
1164
- case import_echo_schema7.TypeEnum.Number:
1389
+ case import_echo_schema9.TypeEnum.Number:
1165
1390
  return value.toLocaleString(locale);
1166
- case import_echo_schema7.TypeEnum.String:
1167
- case import_echo_schema7.TypeEnum.Ref:
1391
+ case import_echo_schema9.TypeEnum.String:
1392
+ case import_echo_schema9.TypeEnum.Ref:
1168
1393
  return String(value);
1169
1394
  default: {
1170
1395
  return String(value);
@@ -1175,20 +1400,20 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1175
1400
  return formatScalar(type);
1176
1401
  }
1177
1402
  switch (format) {
1178
- case import_echo_schema7.FormatEnum.Boolean: {
1179
- return formatScalar(import_echo_schema7.TypeEnum.Boolean);
1403
+ case import_echo_schema9.FormatEnum.Boolean: {
1404
+ return formatScalar(import_echo_schema9.TypeEnum.Boolean);
1180
1405
  }
1181
- case import_echo_schema7.FormatEnum.Number: {
1182
- return formatScalar(import_echo_schema7.TypeEnum.Number);
1406
+ case import_echo_schema9.FormatEnum.Number: {
1407
+ return formatScalar(import_echo_schema9.TypeEnum.Number);
1183
1408
  }
1184
- case import_echo_schema7.FormatEnum.String:
1185
- case import_echo_schema7.FormatEnum.Ref: {
1186
- return formatScalar(import_echo_schema7.TypeEnum.String);
1409
+ case import_echo_schema9.FormatEnum.String:
1410
+ case import_echo_schema9.FormatEnum.Ref: {
1411
+ return formatScalar(import_echo_schema9.TypeEnum.String);
1187
1412
  }
1188
- case import_echo_schema7.FormatEnum.Percent: {
1413
+ case import_echo_schema9.FormatEnum.Percent: {
1189
1414
  return `${value * 100}%`;
1190
1415
  }
1191
- case import_echo_schema7.FormatEnum.Currency: {
1416
+ case import_echo_schema9.FormatEnum.Currency: {
1192
1417
  return value.toLocaleString(locale, {
1193
1418
  style: "currency",
1194
1419
  currency: "USD",
@@ -1196,13 +1421,13 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1196
1421
  maximumFractionDigits: 2
1197
1422
  });
1198
1423
  }
1199
- case import_echo_schema7.FormatEnum.DateTime:
1200
- case import_echo_schema7.FormatEnum.Date:
1201
- case import_echo_schema7.FormatEnum.Time: {
1424
+ case import_echo_schema9.FormatEnum.DateTime:
1425
+ case import_echo_schema9.FormatEnum.Date:
1426
+ case import_echo_schema9.FormatEnum.Time: {
1202
1427
  const date = new Date(value);
1203
- if (format === import_echo_schema7.FormatEnum.DateTime) {
1428
+ if (format === import_echo_schema9.FormatEnum.DateTime) {
1204
1429
  return date.toLocaleString(locale);
1205
- } else if (format === import_echo_schema7.FormatEnum.Date) {
1430
+ } else if (format === import_echo_schema9.FormatEnum.Date) {
1206
1431
  return date.toLocaleDateString(locale);
1207
1432
  } else {
1208
1433
  return date.toLocaleTimeString(locale);
@@ -1219,10 +1444,10 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1219
1444
  var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1220
1445
  const formatScalar = (type2) => {
1221
1446
  switch (type2) {
1222
- case import_echo_schema7.TypeEnum.Boolean:
1223
- case import_echo_schema7.TypeEnum.Number:
1224
- case import_echo_schema7.TypeEnum.String:
1225
- case import_echo_schema7.TypeEnum.Ref:
1447
+ case import_echo_schema9.TypeEnum.Boolean:
1448
+ case import_echo_schema9.TypeEnum.Number:
1449
+ case import_echo_schema9.TypeEnum.String:
1450
+ case import_echo_schema9.TypeEnum.Ref:
1226
1451
  return String(value);
1227
1452
  default:
1228
1453
  return String(value);
@@ -1232,27 +1457,27 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1232
1457
  return formatScalar(type);
1233
1458
  }
1234
1459
  switch (format) {
1235
- case import_echo_schema7.FormatEnum.Boolean:
1236
- case import_echo_schema7.FormatEnum.Number:
1237
- case import_echo_schema7.FormatEnum.String:
1238
- case import_echo_schema7.FormatEnum.Ref: {
1460
+ case import_echo_schema9.FormatEnum.Boolean:
1461
+ case import_echo_schema9.FormatEnum.Number:
1462
+ case import_echo_schema9.FormatEnum.String:
1463
+ case import_echo_schema9.FormatEnum.Ref: {
1239
1464
  return formatScalar(type);
1240
1465
  }
1241
- case import_echo_schema7.FormatEnum.Percent: {
1466
+ case import_echo_schema9.FormatEnum.Percent: {
1242
1467
  return String(value * 100);
1243
1468
  }
1244
- case import_echo_schema7.FormatEnum.Currency: {
1469
+ case import_echo_schema9.FormatEnum.Currency: {
1245
1470
  return String(value);
1246
1471
  }
1247
- case import_echo_schema7.FormatEnum.DateTime: {
1472
+ case import_echo_schema9.FormatEnum.DateTime: {
1248
1473
  const date = new Date(value);
1249
1474
  return date.toISOString();
1250
1475
  }
1251
- case import_echo_schema7.FormatEnum.Date: {
1476
+ case import_echo_schema9.FormatEnum.Date: {
1252
1477
  const date = new Date(value);
1253
1478
  return date.toISOString().split("T")[0];
1254
1479
  }
1255
- case import_echo_schema7.FormatEnum.Time: {
1480
+ case import_echo_schema9.FormatEnum.Time: {
1256
1481
  const date = new Date(value);
1257
1482
  return date.toISOString().split("T")[1].split(".")[0];
1258
1483
  }
@@ -1264,14 +1489,15 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1264
1489
  // Annotate the CommonJS export names for ESM import in node:
1265
1490
  0 && (module.exports = {
1266
1491
  BooleanInput,
1492
+ DeprecatedFormContainer,
1267
1493
  DeprecatedFormInput,
1268
1494
  FieldEditor,
1269
1495
  Form,
1270
- FormActions,
1271
1496
  GeoPointInput,
1272
1497
  InputHeader,
1273
1498
  NumberInput,
1274
1499
  SelectInput,
1500
+ SelectOptionInput,
1275
1501
  TextInput,
1276
1502
  TupleInput,
1277
1503
  ViewEditor,