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