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