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