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

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 (39) hide show
  1. package/dist/lib/browser/index.mjs +400 -158
  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 +387 -145
  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 +400 -158
  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/Form.d.ts +3 -2
  12. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  13. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
  14. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +4 -0
  15. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -0
  16. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +7 -0
  17. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -0
  18. package/dist/types/src/components/Form/custom/index.d.ts +1 -0
  19. package/dist/types/src/components/Form/custom/index.d.ts.map +1 -1
  20. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  21. package/dist/types/src/components/deprecated/FormInput.d.ts +5 -0
  22. package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
  23. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  24. package/dist/types/src/translations.d.ts +6 -0
  25. package/dist/types/src/translations.d.ts.map +1 -1
  26. package/dist/types/tsconfig.tsbuildinfo +1 -1
  27. package/package.json +25 -24
  28. package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
  29. package/src/components/FieldEditor/FieldEditor.tsx +3 -2
  30. package/src/components/Form/ArrayField.tsx +1 -1
  31. package/src/components/Form/Form.tsx +15 -2
  32. package/src/components/Form/FormContent.tsx +26 -8
  33. package/src/components/Form/custom/SelectOptionsInput.stories.tsx +58 -0
  34. package/src/components/Form/custom/SelectOptionsInput.tsx +192 -0
  35. package/src/components/Form/custom/index.ts +1 -0
  36. package/src/components/ViewEditor/ViewEditor.tsx +5 -2
  37. package/src/components/deprecated/FormInput.tsx +20 -7
  38. package/src/hooks/useForm.ts +0 -1
  39. 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,87 @@ 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
+ return /* @__PURE__ */ React6.createElement(Input5.Root, {
215
417
  validationValence: status
216
- }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
418
+ }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
217
419
  error
218
- }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Input4.Switch, {
420
+ }, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement(Input5.Switch, {
219
421
  checked: getValue3(),
220
422
  onCheckedChange: (value) => onValueChange(type, value)
221
- }), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
423
+ }), inputOnly && /* @__PURE__ */ React6.createElement(Input5.DescriptionAndValidation, null, error));
222
424
  };
223
425
  var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
224
426
  const { status, error } = getStatus();
225
- return /* @__PURE__ */ React5.createElement(Input4.Root, {
427
+ return /* @__PURE__ */ React6.createElement(Input5.Root, {
226
428
  validationValence: status
227
- }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
429
+ }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
228
430
  error
229
- }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Select.Root, {
431
+ }, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement(Select.Root, {
230
432
  value: getValue3(),
231
433
  onValueChange: (value) => onValueChange(type, value)
232
- }, /* @__PURE__ */ React5.createElement(Select.TriggerButton, {
434
+ }, /* @__PURE__ */ React6.createElement(Select.TriggerButton, {
233
435
  classNames: "is-full",
234
436
  disabled,
235
437
  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 }) => (
438
+ }), /* @__PURE__ */ React6.createElement(Select.Portal, null, /* @__PURE__ */ React6.createElement(Select.Content, null, /* @__PURE__ */ React6.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
237
439
  // NOTE: Numeric values are converted to and from strings.
238
- /* @__PURE__ */ React5.createElement(Select.Option, {
440
+ /* @__PURE__ */ React6.createElement(Select.Option, {
239
441
  key: String(value),
240
442
  value: String(value)
241
443
  }, label2 ?? String(value))
242
- )))))), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
444
+ )))))), inputOnly && /* @__PURE__ */ React6.createElement(Input5.DescriptionAndValidation, null, error));
243
445
  };
244
446
 
245
447
  // 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";
448
+ import React11, { useEffect as useEffect3, useMemo as useMemo4 } from "react";
449
+ import { mx as mx7 } from "@dxos/react-ui-theme";
248
450
 
249
451
  // 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";
452
+ import React8 from "react";
453
+ import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
454
+ import { mx as mx4 } from "@dxos/react-ui-theme";
253
455
 
254
456
  // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
255
- import React6, { createContext, useContext } from "react";
457
+ import React7, { createContext, useContext } from "react";
256
458
  import { raise } from "@dxos/debug";
257
459
  import { getValue as getValue2 } from "@dxos/echo-schema";
258
460
  import { createJsonPath as createJsonPath2 } from "@dxos/effect";
259
461
 
260
462
  // packages/ui/react-ui-form/src/hooks/useForm.ts
261
- import { useCallback, useEffect, useMemo, useState } from "react";
463
+ import { useCallback as useCallback2, useEffect as useEffect2, useMemo, useState as useState2 } from "react";
262
464
  import { getValue, setValue } from "@dxos/echo-schema";
263
465
  import { AST, createJsonPath, fromEffectValidationPath } from "@dxos/effect";
264
466
  import { invariant } from "@dxos/invariant";
@@ -275,17 +477,17 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
275
477
  ""
276
478
  ]
277
479
  });
278
- const [values, setValues] = useState(initialValues);
279
- useEffect(() => {
480
+ const [values, setValues] = useState2(initialValues);
481
+ useEffect2(() => {
280
482
  setValues(initialValues);
281
483
  }, [
282
484
  initialValues
283
485
  ]);
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) => {
486
+ const [touched, setTouched] = useState2(createKeySet(initialValues, false));
487
+ const [changed, setChanged] = useState2(createKeySet(initialValues, false));
488
+ const [errors, setErrors] = useState2({});
489
+ const [saving, setSaving] = useState2(false);
490
+ const validate = useCallback2((values2) => {
289
491
  let errors2 = validateSchema(schema, values2) ?? [];
290
492
  if (errors2.length === 0 && onValidate) {
291
493
  const validatedValues = values2;
@@ -298,11 +500,11 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
298
500
  schema,
299
501
  onValidate
300
502
  ]);
301
- const [schemaDirty, setSchemaDirty] = useState(false);
302
- useEffect(() => setSchemaDirty(true), [
503
+ const [schemaDirty, setSchemaDirty] = useState2(false);
504
+ useEffect2(() => setSchemaDirty(true), [
303
505
  schema
304
506
  ]);
305
- useEffect(() => {
507
+ useEffect2(() => {
306
508
  if (schemaDirty) {
307
509
  validate(values);
308
510
  setSchemaDirty(false);
@@ -317,7 +519,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
317
519
  errors,
318
520
  saving
319
521
  ]);
320
- const handleSave = useCallback(async () => {
522
+ const handleSave = useCallback2(async () => {
321
523
  if (validate(values)) {
322
524
  setSaving(true);
323
525
  try {
@@ -334,7 +536,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
334
536
  onSave,
335
537
  changed
336
538
  ]);
337
- const getStatus = useCallback((path) => {
539
+ const getStatus = useCallback2((path) => {
338
540
  const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
339
541
  const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
340
542
  return {
@@ -357,7 +559,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
357
559
  } catch (err) {
358
560
  log.catch(err, void 0, {
359
561
  F: __dxlog_file,
360
- L: 194,
562
+ L: 193,
361
563
  S: void 0,
362
564
  C: (f, a) => f(...a)
363
565
  });
@@ -379,7 +581,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
379
581
  });
380
582
  }
381
583
  };
382
- const onTouched = useCallback((path) => {
584
+ const onTouched = useCallback2((path) => {
383
585
  const jsonPath = createJsonPath(path);
384
586
  setTouched((touched2) => ({
385
587
  ...touched2,
@@ -408,7 +610,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
408
610
  var createKeySet = (obj, value) => {
409
611
  invariant(obj, void 0, {
410
612
  F: __dxlog_file,
411
- L: 236,
613
+ L: 235,
412
614
  S: void 0,
413
615
  A: [
414
616
  "obj",
@@ -451,27 +653,27 @@ var useInputProps = (path = []) => {
451
653
  };
452
654
  var FormProvider = ({ children, ...formOptions }) => {
453
655
  const formHandler = useForm(formOptions);
454
- return /* @__PURE__ */ React6.createElement(FormContext.Provider, {
656
+ return /* @__PURE__ */ React7.createElement(FormContext.Provider, {
455
657
  value: formHandler
456
658
  }, children);
457
659
  };
458
660
 
459
661
  // packages/ui/react-ui-form/src/components/Form/FormActions.tsx
460
662
  var FormActions = ({ onCancel, readonly }) => {
461
- const { t } = useTranslation2(translationKey);
663
+ const { t } = useTranslation3(translationKey);
462
664
  const { canSave, handleSave } = useFormContext();
463
- return /* @__PURE__ */ React7.createElement("div", {
665
+ return /* @__PURE__ */ React8.createElement("div", {
464
666
  role: "none",
465
667
  className: "flex justify-center"
466
- }, /* @__PURE__ */ React7.createElement("div", {
668
+ }, /* @__PURE__ */ React8.createElement("div", {
467
669
  role: "none",
468
- className: mx2(onCancel && !readonly && "grid grid-cols-2 gap-2")
469
- }, onCancel && !readonly && /* @__PURE__ */ React7.createElement(IconButton, {
670
+ className: mx4(onCancel && !readonly && "grid grid-cols-2 gap-2")
671
+ }, onCancel && !readonly && /* @__PURE__ */ React8.createElement(IconButton2, {
470
672
  "data-testid": "cancel-button",
471
673
  icon: "ph--x--regular",
472
674
  label: t("button cancel"),
473
675
  onClick: onCancel
474
- }), handleSave && /* @__PURE__ */ React7.createElement(IconButton, {
676
+ }), handleSave && /* @__PURE__ */ React8.createElement(IconButton2, {
475
677
  type: "submit",
476
678
  "data-testid": "save-button",
477
679
  disabled: !canSave,
@@ -484,36 +686,36 @@ var FormActions = ({ onCancel, readonly }) => {
484
686
  // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
485
687
  import { pipe as pipe2 } from "effect";
486
688
  import { capitalize as capitalize2 } from "effect/String";
487
- import React9, { useMemo as useMemo3 } from "react";
689
+ import React10, { useMemo as useMemo3 } from "react";
488
690
  import { AST as AST3, S } from "@dxos/echo-schema";
489
691
  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";
692
+ import { mx as mx6 } from "@dxos/react-ui-theme";
491
693
  import { getSchemaProperties as getSchemaProperties2 } from "@dxos/schema";
492
694
  import { isNotFalsy } from "@dxos/util";
493
695
 
494
696
  // packages/ui/react-ui-form/src/components/Form/ArrayField.tsx
495
697
  import { pipe } from "effect";
496
698
  import { capitalize } from "effect/String";
497
- import React8, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
699
+ import React9, { useCallback as useCallback3, useMemo as useMemo2 } from "react";
498
700
  import { AST as AST2 } from "@dxos/echo-schema";
499
701
  import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
500
702
  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";
703
+ import { IconButton as IconButton3, useTranslation as useTranslation4 } from "@dxos/react-ui";
704
+ import { mx as mx5 } from "@dxos/react-ui-theme";
503
705
  import { getSchemaProperties } from "@dxos/schema";
504
706
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
505
707
  var padding = "px-2";
506
708
  var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
507
- const { t } = useTranslation3(translationKey);
709
+ const { t } = useTranslation4(translationKey);
508
710
  const { ast, name, type, title } = property;
509
711
  const values = useFormValues(path ?? []);
510
- invariant2(Array.isArray(values), void 0, {
712
+ invariant2(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
511
713
  F: __dxlog_file2,
512
714
  L: 37,
513
715
  S: void 0,
514
716
  A: [
515
717
  "Array.isArray(values)",
516
- ""
718
+ "`Values at path ${path?.join('.')} must be an array.`"
517
719
  ]
518
720
  });
519
721
  const label = title ?? pipe(name, capitalize);
@@ -540,7 +742,7 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
540
742
  type,
541
743
  elementType
542
744
  ]);
543
- const handleAdd = useCallback2(() => {
745
+ const handleAdd = useCallback3(() => {
544
746
  inputProps.onValueChange(type, [
545
747
  ...values,
546
748
  newValue
@@ -552,7 +754,7 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
552
754
  newValue,
553
755
  values
554
756
  ]);
555
- const handleRemove = useCallback2((index) => {
757
+ const handleRemove = useCallback3((index) => {
556
758
  const newValues = values.filter((_, i) => i !== index);
557
759
  inputProps.onValueChange(type, newValues);
558
760
  }, [
@@ -563,20 +765,20 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
563
765
  if (!elementType) {
564
766
  return null;
565
767
  }
566
- return /* @__PURE__ */ React8.createElement("div", {
768
+ return /* @__PURE__ */ React9.createElement("div", {
567
769
  role: "none",
568
- className: mx3(padding)
569
- }, /* @__PURE__ */ React8.createElement(InputHeader, null, label), /* @__PURE__ */ React8.createElement("div", {
770
+ className: mx5(padding)
771
+ }, /* @__PURE__ */ React9.createElement(InputHeader, null, label), /* @__PURE__ */ React9.createElement("div", {
570
772
  role: "none",
571
773
  className: "flex flex-col gap-1"
572
- }, values.map((_value, index) => /* @__PURE__ */ React8.createElement("div", {
774
+ }, values.map((_value, index) => /* @__PURE__ */ React9.createElement("div", {
573
775
  key: index,
574
776
  role: "none",
575
777
  className: "flex items-center gap-1"
576
- }, /* @__PURE__ */ React8.createElement("div", {
778
+ }, /* @__PURE__ */ React9.createElement("div", {
577
779
  role: "none",
578
780
  className: "flex-1"
579
- }, /* @__PURE__ */ React8.createElement(FormField, {
781
+ }, /* @__PURE__ */ React9.createElement(FormField, {
580
782
  property: {
581
783
  ...property,
582
784
  array: false,
@@ -590,15 +792,15 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
590
792
  inline: true,
591
793
  Custom,
592
794
  lookupComponent
593
- })), /* @__PURE__ */ React8.createElement(IconButton2, {
795
+ })), /* @__PURE__ */ React9.createElement(IconButton3, {
594
796
  icon: "ph--trash--regular",
595
797
  iconOnly: true,
596
798
  label: t("button remove"),
597
799
  onClick: () => handleRemove(index)
598
- })))), /* @__PURE__ */ React8.createElement("div", {
800
+ })))), /* @__PURE__ */ React9.createElement("div", {
599
801
  role: "none",
600
802
  className: "flex justify-between items-center plb-1"
601
- }, /* @__PURE__ */ React8.createElement(IconButton2, {
803
+ }, /* @__PURE__ */ React9.createElement(IconButton3, {
602
804
  icon: "ph--plus--regular",
603
805
  iconOnly: true,
604
806
  label: t("button add"),
@@ -635,15 +837,6 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
635
837
  examples,
636
838
  description
637
839
  ]);
638
- if (array) {
639
- return /* @__PURE__ */ React9.createElement(ArrayField, {
640
- property,
641
- path,
642
- inputProps,
643
- readonly,
644
- Custom
645
- });
646
- }
647
840
  const FoundComponent = lookupComponent?.({
648
841
  prop: name,
649
842
  schema: S.make(ast),
@@ -657,12 +850,42 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
657
850
  }
658
851
  });
659
852
  if (FoundComponent) {
660
- return /* @__PURE__ */ React9.createElement("div", null, FoundComponent);
853
+ return /* @__PURE__ */ React10.createElement("div", {
854
+ role: "none"
855
+ }, FoundComponent);
661
856
  }
662
857
  const jsonPath = createJsonPath3(path ?? []);
663
- const InputComponent = Custom?.[jsonPath] || getInputComponent(type, format);
858
+ const CustomComponent = Custom?.[jsonPath];
859
+ if (CustomComponent) {
860
+ return (
861
+ // TODO(ZaymonFC): We should try to remove this div wrapper.
862
+ /* @__PURE__ */ React10.createElement("div", {
863
+ role: "none"
864
+ }, /* @__PURE__ */ React10.createElement(CustomComponent, {
865
+ type,
866
+ format,
867
+ label,
868
+ inputOnly: inline,
869
+ placeholder,
870
+ disabled: readonly,
871
+ ...inputProps
872
+ }))
873
+ );
874
+ }
875
+ if (array) {
876
+ return /* @__PURE__ */ React10.createElement(ArrayField, {
877
+ property,
878
+ path,
879
+ inputProps,
880
+ readonly,
881
+ Custom
882
+ });
883
+ }
884
+ const InputComponent = getInputComponent(type, format);
664
885
  if (InputComponent) {
665
- return /* @__PURE__ */ React9.createElement("div", null, /* @__PURE__ */ React9.createElement(InputComponent, {
886
+ return /* @__PURE__ */ React10.createElement("div", {
887
+ role: "none"
888
+ }, /* @__PURE__ */ React10.createElement(InputComponent, {
666
889
  type,
667
890
  format,
668
891
  label,
@@ -673,9 +896,9 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
673
896
  }));
674
897
  }
675
898
  if (options) {
676
- return /* @__PURE__ */ React9.createElement("div", {
899
+ return /* @__PURE__ */ React10.createElement("div", {
677
900
  role: "none"
678
- }, /* @__PURE__ */ React9.createElement(SelectInput, {
901
+ }, /* @__PURE__ */ React10.createElement(SelectInput, {
679
902
  type,
680
903
  format,
681
904
  disabled: readonly,
@@ -693,7 +916,9 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
693
916
  const baseNode = findNode2(ast, isDiscriminatedUnion2);
694
917
  const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode2(ast, AST3.isTypeLiteral);
695
918
  if (typeLiteral) {
696
- return /* @__PURE__ */ React9.createElement("div", null, !inline && /* @__PURE__ */ React9.createElement("div", null, label), /* @__PURE__ */ React9.createElement(FormFields, {
919
+ return /* @__PURE__ */ React10.createElement("div", {
920
+ role: "none"
921
+ }, !inline && /* @__PURE__ */ React10.createElement("div", null, label), /* @__PURE__ */ React10.createElement(FormFields, {
697
922
  schema: S.make(typeLiteral),
698
923
  path,
699
924
  readonly,
@@ -715,11 +940,11 @@ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custo
715
940
  filter,
716
941
  sort
717
942
  ]);
718
- return /* @__PURE__ */ React9.createElement("div", {
943
+ return /* @__PURE__ */ React10.createElement("div", {
719
944
  role: "form",
720
- className: mx4("flex flex-col w-full gap-2 py-2")
945
+ className: mx6("flex flex-col w-full gap-2 py-2")
721
946
  }, properties.map((property) => {
722
- return /* @__PURE__ */ React9.createElement(FormField, {
947
+ return /* @__PURE__ */ React10.createElement(FormField, {
723
948
  key: property.name,
724
949
  property,
725
950
  path: [
@@ -734,23 +959,33 @@ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custo
734
959
  };
735
960
 
736
961
  // 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 }) => {
962
+ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
738
963
  const onValid = useMemo4(() => autoSave ? onSave : void 0, [
739
964
  autoSave,
740
965
  onSave
741
966
  ]);
742
- return /* @__PURE__ */ React10.createElement(FormProvider, {
967
+ useEffect3(() => {
968
+ if (autoFocus) {
969
+ const input = document.querySelector("input");
970
+ if (input) {
971
+ input.focus();
972
+ }
973
+ }
974
+ }, [
975
+ autoFocus
976
+ ]);
977
+ return /* @__PURE__ */ React11.createElement(FormProvider, {
743
978
  schema,
744
979
  initialValues,
745
980
  onValuesChanged,
746
981
  onValidate,
747
982
  onValid,
748
983
  onSave
749
- }, /* @__PURE__ */ React10.createElement("div", {
984
+ }, /* @__PURE__ */ React11.createElement("div", {
750
985
  role: "none",
751
- className: mx5("p-2", classNames),
986
+ className: mx7("p-2", classNames),
752
987
  "data-testid": testId
753
- }, /* @__PURE__ */ React10.createElement(FormFields, {
988
+ }, /* @__PURE__ */ React11.createElement(FormFields, {
754
989
  schema,
755
990
  path,
756
991
  readonly,
@@ -758,7 +993,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
758
993
  sort,
759
994
  lookupComponent,
760
995
  Custom
761
- }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React10.createElement(FormActions, {
996
+ }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React11.createElement(FormActions, {
762
997
  onCancel,
763
998
  readonly
764
999
  })));
@@ -767,14 +1002,14 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
767
1002
  // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
768
1003
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
769
1004
  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), [
1005
+ const { t } = useTranslation5(translationKey);
1006
+ const [props, setProps] = useState3(projection.getFieldProjection(field.id).props);
1007
+ useEffect4(() => setProps(projection.getFieldProjection(field.id).props), [
773
1008
  field,
774
1009
  projection
775
1010
  ]);
776
- const [schemas, setSchemas] = useState2([]);
777
- useEffect2(() => {
1011
+ const [schemas, setSchemas] = useState3([]);
1012
+ useEffect4(() => {
778
1013
  if (!registry) {
779
1014
  return;
780
1015
  }
@@ -792,17 +1027,17 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
792
1027
  }, [
793
1028
  registry
794
1029
  ]);
795
- const [referenceSchema, setReferenceSchema] = useState2();
796
- useEffect2(() => {
1030
+ const [referenceSchema, setReferenceSchema] = useState3();
1031
+ useEffect4(() => {
797
1032
  setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
798
1033
  }, [
799
1034
  schemas,
800
1035
  props?.referenceSchema
801
1036
  ]);
802
- const [{ fieldSchema }, setFieldSchema] = useState2({
1037
+ const [{ fieldSchema }, setFieldSchema] = useState3({
803
1038
  fieldSchema: getFormatSchema(props?.format)
804
1039
  });
805
- const handleValuesChanged = useCallback3((_props) => {
1040
+ const handleValuesChanged = useCallback4((_props) => {
806
1041
  setFieldSchema((prev) => {
807
1042
  const fieldSchema2 = getFormatSchema(_props.format);
808
1043
  if (prev.fieldSchema === fieldSchema2) {
@@ -830,14 +1065,14 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
830
1065
  type
831
1066
  };
832
1067
  }
833
- return props2;
1068
+ return _props;
834
1069
  });
835
1070
  }, [
836
1071
  schemas,
837
1072
  props.format,
838
1073
  props.referenceSchema
839
1074
  ]);
840
- const handleValidate = useCallback3(({ property }) => {
1075
+ const handleValidate = useCallback4(({ property }) => {
841
1076
  if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
842
1077
  return [
843
1078
  {
@@ -850,7 +1085,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
850
1085
  view.fields,
851
1086
  field
852
1087
  ]);
853
- const handleSave = useCallback3((props2) => {
1088
+ const handleSave = useCallback4((props2) => {
854
1089
  projection.setFieldProjection({
855
1090
  field,
856
1091
  props: props2
@@ -861,50 +1096,51 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
861
1096
  field,
862
1097
  onSave
863
1098
  ]);
864
- const handleCancel = useCallback3(() => {
1099
+ const handleCancel = useCallback4(() => {
865
1100
  requestAnimationFrame(() => onCancel?.());
866
1101
  onSave();
867
1102
  }, [
868
1103
  onSave
869
1104
  ]);
870
1105
  const Custom = useMemo5(() => ({
871
- ["format"]: (props2) => /* @__PURE__ */ React11.createElement(SelectInput, {
1106
+ ["format"]: (props2) => /* @__PURE__ */ React12.createElement(SelectInput, {
872
1107
  ...props2,
873
1108
  options: FormatEnums.filter((value) => value !== FormatEnum2.None).map((value) => ({
874
1109
  value,
875
1110
  label: t(`format ${value}`)
876
1111
  }))
877
1112
  }),
878
- ["referenceSchema"]: (props2) => /* @__PURE__ */ React11.createElement(SelectInput, {
1113
+ ["referenceSchema"]: (props2) => /* @__PURE__ */ React12.createElement(SelectInput, {
879
1114
  ...props2,
880
1115
  options: schemas.map((schema) => ({
881
1116
  value: schema.typename
882
1117
  }))
883
1118
  }),
884
- ["referencePath"]: (props2) => /* @__PURE__ */ React11.createElement(SelectInput, {
1119
+ ["referencePath"]: (props2) => /* @__PURE__ */ React12.createElement(SelectInput, {
885
1120
  ...props2,
886
1121
  options: referenceSchema ? getSchemaProperties3(referenceSchema.ast).sort(sortProperties).map((p) => ({
887
1122
  value: p.name
888
1123
  })) : []
889
- })
1124
+ }),
1125
+ ["options"]: (props2) => /* @__PURE__ */ React12.createElement(SelectOptionInput, props2)
890
1126
  }), [
891
1127
  t,
892
1128
  schemas,
893
1129
  referenceSchema
894
1130
  ]);
895
- const propIsNotType = useCallback3((props2) => props2.filter((p) => p.name !== "type"), []);
1131
+ const propIsNotType = useCallback4((props2) => props2.filter((p) => p.name !== "type"), []);
896
1132
  if (!fieldSchema) {
897
1133
  log2.warn("invalid format", {
898
1134
  props
899
1135
  }, {
900
1136
  F: __dxlog_file3,
901
- L: 173,
1137
+ L: 174,
902
1138
  S: void 0,
903
1139
  C: (f, a) => f(...a)
904
1140
  });
905
1141
  return null;
906
1142
  }
907
- return /* @__PURE__ */ React11.createElement(Form, {
1143
+ return /* @__PURE__ */ React12.createElement(Form, {
908
1144
  key: field.id,
909
1145
  autoFocus: true,
910
1146
  values: props,
@@ -923,13 +1159,12 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
923
1159
  };
924
1160
 
925
1161
  // packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
926
- import React12, { useCallback as useCallback4, useMemo as useMemo6, useState as useState3 } from "react";
1162
+ import React13, { useCallback as useCallback5, useMemo as useMemo6, useState as useState4 } from "react";
927
1163
  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";
1164
+ import { IconButton as IconButton4, useTranslation as useTranslation6 } from "@dxos/react-ui";
1165
+ import { List as List2 } from "@dxos/react-ui-list";
1166
+ import { ghostHover, inputTextLabel, mx as mx8 } from "@dxos/react-ui-theme";
931
1167
  import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
932
- import { arrayMove } from "@dxos/util";
933
1168
  var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
934
1169
  var ViewMetaSchema = S2.Struct({
935
1170
  name: S2.String.annotations({
@@ -940,12 +1175,12 @@ var ViewMetaSchema = S2.Struct({
940
1175
  })
941
1176
  }).pipe(S2.mutable);
942
1177
  var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
943
- const { t } = useTranslation5(translationKey);
1178
+ const { t } = useTranslation6(translationKey);
944
1179
  const projection = useMemo6(() => new ViewProjection(schema, view), [
945
1180
  schema,
946
1181
  view
947
1182
  ]);
948
- const [field, setField] = useState3();
1183
+ const [field, setField] = useState4();
949
1184
  const viewValues = useMemo6(() => {
950
1185
  return {
951
1186
  name: view.name,
@@ -956,7 +1191,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
956
1191
  }, [
957
1192
  view
958
1193
  ]);
959
- const handleViewUpdate = useCallback4(({ name, typename }) => {
1194
+ const handleViewUpdate = useCallback5(({ name, typename }) => {
960
1195
  requestAnimationFrame(() => {
961
1196
  if (view.name !== name) {
962
1197
  view.name = name;
@@ -970,67 +1205,72 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
970
1205
  schema,
971
1206
  onTypenameChanged
972
1207
  ]);
973
- const handleSelect = useCallback4((field2) => {
1208
+ const handleSelect = useCallback5((field2) => {
974
1209
  setField((f) => f === field2 ? void 0 : field2);
975
1210
  }, []);
976
- const handleAdd = useCallback4(() => {
1211
+ const handleAdd = useCallback5(() => {
977
1212
  const field2 = projection.createFieldProjection();
978
1213
  setField(field2);
979
1214
  }, [
980
1215
  view
981
1216
  ]);
982
- const handleMove = useCallback4((fromIndex, toIndex) => {
983
- arrayMove(view.fields, fromIndex, toIndex);
1217
+ const handleMove = useCallback5((fromIndex, toIndex) => {
1218
+ const fields = [
1219
+ ...view.fields
1220
+ ];
1221
+ const [moved] = fields.splice(fromIndex, 1);
1222
+ fields.splice(toIndex, 0, moved);
1223
+ view.fields = fields;
984
1224
  }, [
985
1225
  view.fields
986
1226
  ]);
987
- const handleClose = useCallback4(() => setField(void 0), []);
988
- return /* @__PURE__ */ React12.createElement("div", {
1227
+ const handleClose = useCallback5(() => setField(void 0), []);
1228
+ return /* @__PURE__ */ React13.createElement("div", {
989
1229
  role: "none",
990
- className: mx6("flex flex-col w-full divide-y divide-separator", classNames)
991
- }, /* @__PURE__ */ React12.createElement(Form, {
1230
+ className: mx8("flex flex-col w-full divide-y divide-separator", classNames)
1231
+ }, /* @__PURE__ */ React13.createElement(Form, {
992
1232
  autoFocus: true,
993
1233
  autoSave: true,
994
1234
  schema: ViewMetaSchema,
995
1235
  values: viewValues,
996
1236
  onSave: handleViewUpdate
997
- }), /* @__PURE__ */ React12.createElement("div", null, /* @__PURE__ */ React12.createElement("div", {
1237
+ }), /* @__PURE__ */ React13.createElement("div", null, /* @__PURE__ */ React13.createElement("div", {
998
1238
  role: "none",
999
1239
  className: "p-2"
1000
- }, /* @__PURE__ */ React12.createElement("label", {
1001
- className: mx6(inputTextLabel)
1002
- }, t("fields label"))), /* @__PURE__ */ React12.createElement(List.Root, {
1240
+ }, /* @__PURE__ */ React13.createElement("label", {
1241
+ className: mx8(inputTextLabel)
1242
+ }, t("fields label"))), /* @__PURE__ */ React13.createElement(List2.Root, {
1003
1243
  items: view.fields,
1004
1244
  isItem: S2.is(FieldSchema),
1005
1245
  getId: (field2) => field2.id,
1006
1246
  onMove: handleMove
1007
- }, ({ items: fields }) => /* @__PURE__ */ React12.createElement(React12.Fragment, null, showHeading && /* @__PURE__ */ React12.createElement("div", {
1247
+ }, ({ items: fields }) => /* @__PURE__ */ React13.createElement(React13.Fragment, null, showHeading && /* @__PURE__ */ React13.createElement("div", {
1008
1248
  role: "heading",
1009
1249
  className: grid
1010
- }, /* @__PURE__ */ React12.createElement("div", null), /* @__PURE__ */ React12.createElement("div", {
1250
+ }, /* @__PURE__ */ React13.createElement("div", null), /* @__PURE__ */ React13.createElement("div", {
1011
1251
  className: "flex items-center text-sm"
1012
- }, t("field path label"))), /* @__PURE__ */ React12.createElement("div", {
1252
+ }, t("field path label"))), /* @__PURE__ */ React13.createElement("div", {
1013
1253
  role: "list",
1014
1254
  className: "flex flex-col w-full"
1015
- }, fields?.map((field2) => /* @__PURE__ */ React12.createElement(List.Item, {
1255
+ }, fields?.map((field2) => /* @__PURE__ */ React13.createElement(List2.Item, {
1016
1256
  key: field2.id,
1017
1257
  item: field2,
1018
- classNames: mx6(grid, ghostHover, "cursor-pointer")
1019
- }, /* @__PURE__ */ React12.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React12.createElement(List.ItemTitle, {
1258
+ classNames: mx8(grid, ghostHover, "cursor-pointer")
1259
+ }, /* @__PURE__ */ React13.createElement(List2.ItemDragHandle, null), /* @__PURE__ */ React13.createElement(List2.ItemTitle, {
1020
1260
  onClick: () => handleSelect(field2)
1021
- }, field2.path), /* @__PURE__ */ React12.createElement(List.ItemDeleteButton, {
1261
+ }, field2.path), /* @__PURE__ */ React13.createElement(List2.ItemDeleteButton, {
1022
1262
  disabled: view.fields.length <= 1,
1023
1263
  onClick: () => onDelete(field2.id)
1024
- }))))))), field && /* @__PURE__ */ React12.createElement(FieldEditor, {
1264
+ }))))))), field && /* @__PURE__ */ React13.createElement(FieldEditor, {
1025
1265
  key: field.id,
1026
1266
  view,
1027
1267
  projection,
1028
1268
  field,
1029
1269
  registry,
1030
1270
  onSave: handleClose
1031
- }), !readonly && !field && /* @__PURE__ */ React12.createElement("div", {
1271
+ }), !readonly && !field && /* @__PURE__ */ React13.createElement("div", {
1032
1272
  className: "flex p-2 justify-center"
1033
- }, /* @__PURE__ */ React12.createElement(IconButton3, {
1273
+ }, /* @__PURE__ */ React13.createElement(IconButton4, {
1034
1274
  icon: "ph--plus--regular",
1035
1275
  label: t("button add property"),
1036
1276
  onClick: handleAdd,
@@ -1260,6 +1500,7 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1260
1500
  };
1261
1501
  export {
1262
1502
  BooleanInput,
1503
+ DeprecatedFormContainer,
1263
1504
  DeprecatedFormInput,
1264
1505
  FieldEditor,
1265
1506
  Form,
@@ -1267,6 +1508,7 @@ export {
1267
1508
  InputHeader,
1268
1509
  NumberInput,
1269
1510
  SelectInput,
1511
+ SelectOptionInput,
1270
1512
  TextInput,
1271
1513
  TupleInput,
1272
1514
  ViewEditor,