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