@dxos/react-ui-form 0.7.5-labs.a279d8c → 0.7.5-labs.ea4b4c2

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