@dxos/react-ui-form 0.7.5-labs.5f04cf6 → 0.7.5-labs.8a82073

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