@dxos/react-ui-form 0.8.4-main.4a85c3132b → 0.8.4-main.4f23b4e393

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 (141) hide show
  1. package/dist/lib/browser/index.mjs +1020 -623
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/browser/translations.mjs +82 -0
  5. package/dist/lib/browser/translations.mjs.map +7 -0
  6. package/dist/lib/node-esm/index.mjs +1020 -623
  7. package/dist/lib/node-esm/index.mjs.map +4 -4
  8. package/dist/lib/node-esm/meta.json +1 -1
  9. package/dist/lib/node-esm/translations.mjs +84 -0
  10. package/dist/lib/node-esm/translations.mjs.map +7 -0
  11. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  12. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +63 -61
  13. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
  14. package/dist/types/src/components/Form/Form.d.ts +40 -12
  15. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Form.stories.d.ts +76 -74
  17. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/FormField.d.ts +11 -5
  19. package/dist/types/src/components/Form/FormField.d.ts.map +1 -1
  20. package/dist/types/src/components/Form/FormFieldComponent.d.ts +8 -7
  21. package/dist/types/src/components/Form/FormFieldComponent.d.ts.map +1 -1
  22. package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts.map +1 -1
  23. package/dist/types/src/components/Form/FormFieldSet.d.ts +5 -9
  24. package/dist/types/src/components/Form/FormFieldSet.d.ts.map +1 -1
  25. package/dist/types/src/components/Form/fields/ArrayField.d.ts +4 -4
  26. package/dist/types/src/components/Form/fields/ArrayField.d.ts.map +1 -1
  27. package/dist/types/src/components/Form/fields/BooleanField.d.ts.map +1 -1
  28. package/dist/types/src/components/Form/fields/GeoPointField.d.ts.map +1 -1
  29. package/dist/types/src/components/Form/fields/MarkdownField.d.ts +8 -1
  30. package/dist/types/src/components/Form/fields/MarkdownField.d.ts.map +1 -1
  31. package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts +84 -0
  32. package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts.map +1 -0
  33. package/dist/types/src/components/Form/fields/NumberField.d.ts.map +1 -1
  34. package/dist/types/src/components/Form/fields/RefField.d.ts +15 -7
  35. package/dist/types/src/components/Form/fields/RefField.d.ts.map +1 -1
  36. package/dist/types/src/components/Form/fields/SelectField.d.ts.map +1 -1
  37. package/dist/types/src/components/Form/fields/SelectOptionField.d.ts.map +1 -1
  38. package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts +63 -61
  39. package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts.map +1 -1
  40. package/dist/types/src/components/Form/fields/TextAreaField.d.ts.map +1 -1
  41. package/dist/types/src/components/Form/fields/TextField.d.ts +1 -1
  42. package/dist/types/src/components/Form/fields/TextField.d.ts.map +1 -1
  43. package/dist/types/src/components/Form/fields/TupleField.d.ts.map +1 -1
  44. package/dist/types/src/components/ObjectForm/ObjectForm.d.ts +9 -0
  45. package/dist/types/src/components/ObjectForm/ObjectForm.d.ts.map +1 -0
  46. package/dist/types/src/components/ObjectForm/index.d.ts +2 -0
  47. package/dist/types/src/components/ObjectForm/index.d.ts.map +1 -0
  48. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +26 -4
  49. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -1
  50. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +63 -61
  51. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -1
  52. package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts +9 -0
  53. package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts.map +1 -0
  54. package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts +127 -0
  55. package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts.map +1 -0
  56. package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts +2 -0
  57. package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts.map +1 -0
  58. package/dist/types/src/components/ObjectProperties/index.d.ts +2 -0
  59. package/dist/types/src/components/ObjectProperties/index.d.ts.map +1 -0
  60. package/dist/types/src/components/Settings/Settings.d.ts +28 -33
  61. package/dist/types/src/components/Settings/Settings.d.ts.map +1 -1
  62. package/dist/types/src/components/Settings/Settings.stories.d.ts +64 -61
  63. package/dist/types/src/components/Settings/Settings.stories.d.ts.map +1 -1
  64. package/dist/types/src/components/Settings/SettingsFieldSet.d.ts +43 -0
  65. package/dist/types/src/components/Settings/SettingsFieldSet.d.ts.map +1 -0
  66. package/dist/types/src/components/Settings/SettingsItem.d.ts +16 -0
  67. package/dist/types/src/components/Settings/SettingsItem.d.ts.map +1 -0
  68. package/dist/types/src/components/Settings/SettingsSelectField.d.ts +18 -0
  69. package/dist/types/src/components/Settings/SettingsSelectField.d.ts.map +1 -0
  70. package/dist/types/src/components/Settings/index.d.ts +2 -0
  71. package/dist/types/src/components/Settings/index.d.ts.map +1 -1
  72. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +3 -4
  73. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  74. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +65 -63
  75. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  76. package/dist/types/src/components/index.d.ts +2 -0
  77. package/dist/types/src/components/index.d.ts.map +1 -1
  78. package/dist/types/src/components/testing.d.ts +4 -4
  79. package/dist/types/src/components/testing.d.ts.map +1 -1
  80. package/dist/types/src/hooks/useFormHandler.d.ts.map +1 -1
  81. package/dist/types/src/hooks/useKeyHandler.d.ts +2 -1
  82. package/dist/types/src/hooks/useKeyHandler.d.ts.map +1 -1
  83. package/dist/types/src/index.d.ts +0 -2
  84. package/dist/types/src/index.d.ts.map +1 -1
  85. package/dist/types/src/translations.d.ts +63 -61
  86. package/dist/types/src/translations.d.ts.map +1 -1
  87. package/dist/types/src/util/field-type.d.ts +19 -0
  88. package/dist/types/src/util/field-type.d.ts.map +1 -0
  89. package/dist/types/src/util/field.d.ts.map +1 -1
  90. package/dist/types/src/util/formatting.d.ts.map +1 -1
  91. package/dist/types/src/util/index.d.ts +1 -0
  92. package/dist/types/src/util/index.d.ts.map +1 -1
  93. package/dist/types/src/util/properties.d.ts.map +1 -1
  94. package/dist/types/src/util/refs.d.ts +1 -0
  95. package/dist/types/src/util/refs.d.ts.map +1 -1
  96. package/dist/types/tsconfig.tsbuildinfo +1 -1
  97. package/package.json +42 -40
  98. package/src/components/FieldEditor/FieldEditor.stories.tsx +2 -2
  99. package/src/components/FieldEditor/FieldEditor.test.tsx +0 -1
  100. package/src/components/FieldEditor/FieldEditor.tsx +4 -3
  101. package/src/components/Form/AUDIT.md +17 -0
  102. package/src/components/Form/Form.stories.tsx +25 -38
  103. package/src/components/Form/Form.tsx +77 -48
  104. package/src/components/Form/FormField.tsx +27 -15
  105. package/src/components/Form/FormFieldComponent.tsx +6 -4
  106. package/src/components/Form/FormFieldSet.tsx +98 -77
  107. package/src/components/Form/fields/ArrayField.tsx +14 -8
  108. package/src/components/Form/fields/GeoPointField.tsx +8 -7
  109. package/src/components/Form/fields/MarkdownField.stories.tsx +206 -0
  110. package/src/components/Form/fields/MarkdownField.tsx +135 -45
  111. package/src/components/Form/fields/RefField.tsx +79 -39
  112. package/src/components/Form/fields/SelectOptionField.stories.tsx +8 -6
  113. package/src/components/Form/fields/SelectOptionField.tsx +12 -12
  114. package/src/components/Form/fields/TextField.tsx +2 -2
  115. package/src/components/Form/fields/TupleField.tsx +1 -1
  116. package/src/components/ObjectForm/ObjectForm.tsx +114 -0
  117. package/src/components/ObjectForm/index.ts +5 -0
  118. package/src/components/ObjectPicker/ObjectPicker.stories.tsx +11 -9
  119. package/src/components/ObjectPicker/ObjectPicker.tsx +92 -65
  120. package/src/components/ObjectProperties/ObjectProperties.stories.tsx +362 -0
  121. package/src/components/ObjectProperties/ObjectProperties.test.tsx +101 -0
  122. package/src/components/ObjectProperties/ObjectProperties.tsx +141 -0
  123. package/src/components/ObjectProperties/index.ts +5 -0
  124. package/src/components/Settings/AUDIT.md +52 -0
  125. package/src/components/Settings/Settings.stories.tsx +69 -21
  126. package/src/components/Settings/Settings.tsx +33 -183
  127. package/src/components/Settings/SettingsFieldSet.tsx +257 -0
  128. package/src/components/Settings/SettingsItem.tsx +58 -0
  129. package/src/components/Settings/SettingsSelectField.tsx +59 -0
  130. package/src/components/Settings/index.ts +2 -0
  131. package/src/components/ViewEditor/ViewEditor.stories.tsx +14 -15
  132. package/src/components/ViewEditor/ViewEditor.test.tsx +0 -1
  133. package/src/components/ViewEditor/ViewEditor.tsx +40 -36
  134. package/src/components/index.ts +2 -0
  135. package/src/components/testing.tsx +19 -11
  136. package/src/hooks/useKeyHandler.tsx +7 -7
  137. package/src/index.ts +0 -4
  138. package/src/translations.ts +66 -63
  139. package/src/util/field-type.ts +60 -0
  140. package/src/util/index.ts +1 -0
  141. package/src/util/refs.ts +7 -3
@@ -1,89 +1,13 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
 
3
- // src/translations.ts
4
- var translationKey = "@dxos/react-ui-form";
5
- var translations = [
6
- {
7
- "en-US": {
8
- [translationKey]: {
9
- "fields label": "Fields",
10
- "hidden fields label": "Hidden Fields",
11
- "empty readonly ref field label": "(none)",
12
- // TODO(burdon): Standardize field/property.
13
- "add property button label": "Add property",
14
- "field property label": "Property",
15
- "field property placeholder": "Property name",
16
- "field format label": "Type",
17
- "field path label": "Field path",
18
- "add field": "Add field",
19
- "delete field": "Delete field",
20
- "field limit reached": "Maximum number of fields reached",
21
- "boolean input true value": "Yes",
22
- "boolean input false value": "No",
23
- "show field label": "Show field",
24
- "hide field label": "Hide field",
25
- "delete field label": "Delete field",
26
- "ref field combobox input placeholder": "Search\u2026",
27
- "ref field placeholder_one": "Select\u2026",
28
- "ref field placeholder_other": "Select items\u2026",
29
- "example placeholder": "Example",
30
- "latitude placeholder": "Latitude (e.g., 40.7128)",
31
- "longitude placeholder": "Longitude (e.g., -74.0060)",
32
- "cancel button label": "Cancel",
33
- "save button label": "Save",
34
- // FormatEnum
35
- "format boolean": "Boolean",
36
- "format currency": "Currency",
37
- "format date": "Date",
38
- "format date-time": "DateTime",
39
- "format did": "DID",
40
- "format duration": "Duration",
41
- "format dxn": "DXN",
42
- "format email": "Email",
43
- "format formula": "Formula",
44
- "format hostname": "Hostname",
45
- "format integer": "Integer",
46
- "format json": "JSON",
47
- "format lnglat": "Geopoint",
48
- "format markdown": "Markdown",
49
- "format percent": "Percent",
50
- "format ref": "Reference",
51
- "format regex": "RegExp",
52
- "format string": "String",
53
- "format single-select": "Select",
54
- "format multi-select": "Multi-select",
55
- "format text": "Long text",
56
- "format time": "Time",
57
- "format timestamp": "Timestamp",
58
- "format user": "User",
59
- "format number": "Number",
60
- "format uri": "URI",
61
- "format url": "URL",
62
- "format uuid": "UUID",
63
- // GeoPointField.
64
- "latitude label": "Latitude",
65
- "longitude label": "Longitude",
66
- // SelectOptionsField.
67
- "select option label": "Label",
68
- "select option label placeholder": "Option label",
69
- "select option color": "Color",
70
- "select option delete": "Delete",
71
- "select option add": "Add option",
72
- // System schema message.
73
- "system schema title": "System type",
74
- "system schema description": "System type: cannot add or remove fields."
75
- }
76
- }
77
- }
78
- ];
79
-
80
3
  // src/components/FieldEditor/FieldEditor.tsx
81
- import React17, { useCallback as useCallback14, useEffect as useEffect7, useMemo as useMemo7, useState as useState5 } from "react";
82
- import { Obj as Obj2 } from "@dxos/echo";
4
+ import React17, { useCallback as useCallback14, useEffect as useEffect5, useMemo as useMemo8, useState as useState6 } from "react";
5
+ import { Obj as Obj3 } from "@dxos/echo";
83
6
  import { Format as Format4, FormatEnums, formatToType } from "@dxos/echo/internal";
84
7
  import { log as log2 } from "@dxos/log";
85
- import { useAsyncEffect, useTranslation as useTranslation8 } from "@dxos/react-ui";
8
+ import { useAsyncEffect, useTranslation as useTranslation9 } from "@dxos/react-ui";
86
9
  import { formatToAdditionalPropertyAttributes, getFormatSchema } from "@dxos/schema";
10
+ import { translationKey as translationKey9 } from "#translations";
87
11
 
88
12
  // src/util/field.ts
89
13
  import { Format, GeoLocation, TypeEnum } from "@dxos/echo/internal";
@@ -206,6 +130,46 @@ var pathNotUniqueError = (path) => ({
206
130
  message: `'${path}' is already present`
207
131
  });
208
132
 
133
+ // src/util/field-type.ts
134
+ import * as SchemaAST from "effect/SchemaAST";
135
+ import { getAnnotation, isLiteralUnion } from "@dxos/effect";
136
+ var detectFieldType = (ast) => {
137
+ if (isLiteralUnion(ast)) {
138
+ return "select";
139
+ }
140
+ if (SchemaAST.isTypeLiteral(ast)) {
141
+ return "struct";
142
+ }
143
+ switch (ast._tag) {
144
+ case "BooleanKeyword":
145
+ return "boolean";
146
+ case "StringKeyword":
147
+ return "string";
148
+ case "NumberKeyword":
149
+ return "number";
150
+ }
151
+ return void 0;
152
+ };
153
+ var getSelectOptionsFromAst = (ast) => {
154
+ if (!isLiteralUnion(ast)) {
155
+ return void 0;
156
+ }
157
+ return ast.types.flatMap((literalNode) => {
158
+ const value3 = literalNode.literal;
159
+ if (typeof value3 !== "string" && typeof value3 !== "number") {
160
+ return [];
161
+ }
162
+ const title = getAnnotation(SchemaAST.TitleAnnotationId, false)(literalNode);
163
+ const label = title ?? (typeof value3 === "string" ? value3.charAt(0).toUpperCase() + value3.slice(1) : String(value3));
164
+ return [
165
+ {
166
+ value: value3,
167
+ label
168
+ }
169
+ ];
170
+ });
171
+ };
172
+
209
173
  // src/util/formatting.ts
210
174
  import { format as formatDate } from "date-fns/format";
211
175
  import { Format as Format2, GeoLocation as GeoLocation2, TypeEnum as TypeEnum2 } from "@dxos/echo/internal";
@@ -354,43 +318,52 @@ var getFormProperties = (ast) => {
354
318
 
355
319
  // src/util/refs.ts
356
320
  import { Ref } from "@dxos/echo";
357
- import { getArrayElementType, isArrayType } from "@dxos/effect";
321
+ import { ReferenceAnnotationId } from "@dxos/echo/internal";
322
+ import { findAnnotation, getArrayElementType, isArrayType } from "@dxos/effect";
358
323
  var getRefProps = (ast) => {
359
324
  if (isArrayType(ast)) {
360
325
  const elementType = getArrayElementType(ast);
361
326
  if (elementType) {
362
327
  if (Ref.isRefType(elementType)) {
328
+ const typename = findAnnotation(elementType, ReferenceAnnotationId)?.typename;
363
329
  return {
364
330
  ast: elementType,
365
- isArray: true
331
+ isArray: true,
332
+ typename
366
333
  };
367
334
  }
368
335
  }
369
336
  }
370
337
  if (Ref.isRefType(ast)) {
338
+ const typename = findAnnotation(ast, ReferenceAnnotationId)?.typename;
371
339
  return {
372
340
  ast,
373
- isArray: false
341
+ isArray: false,
342
+ typename
374
343
  };
375
344
  }
376
345
  return void 0;
377
346
  };
378
347
 
379
348
  // src/components/Form/fields/ArrayField.tsx
380
- import * as Option3 from "effect/Option";
381
- import * as SchemaAST3 from "effect/SchemaAST";
349
+ import * as Option4 from "effect/Option";
350
+ import * as SchemaAST4 from "effect/SchemaAST";
382
351
  import React5, { useCallback as useCallback3 } from "react";
383
352
  import { findNode as findNode2, getArrayElementType as getArrayElementType2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2, isNestedType as isNestedType2 } from "@dxos/effect";
384
353
  import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
354
+ import { translationKey as translationKey3 } from "#translations";
385
355
 
386
356
  // src/components/Form/Form.tsx
387
357
  import { createContext } from "@radix-ui/react-context";
358
+ import * as Option3 from "effect/Option";
388
359
  import * as Schema2 from "effect/Schema";
389
- import * as SchemaAST2 from "effect/SchemaAST";
390
- import React4, { useEffect as useEffect3, useMemo as useMemo4, useRef } from "react";
360
+ import * as SchemaAST3 from "effect/SchemaAST";
361
+ import React4, { useEffect as useEffect2, useMemo as useMemo4, useRef } from "react";
362
+ import { Annotation as EchoAnnotation } from "@dxos/echo";
391
363
  import { createJsonPath as createJsonPath3, getValue as getValue$2 } from "@dxos/effect";
392
- import { IconButton, ScrollArea, useTranslation as useTranslation2 } from "@dxos/react-ui";
393
- import { mx as mx2 } from "@dxos/ui-theme";
364
+ import { IconButton, ScrollArea, useMergeRefs, useTranslation as useTranslation2 } from "@dxos/react-ui";
365
+ import { composable, composableProps, mx, withColumn } from "@dxos/ui-theme";
366
+ import { translationKey as translationKey2 } from "#translations";
394
367
 
395
368
  // src/hooks/useFormHandler.ts
396
369
  import { useControllableState } from "@radix-ui/react-use-controllable-state";
@@ -428,12 +401,7 @@ var useFormHandler = ({ schema, autoSave, values: valuesProp, defaultValues: def
428
401
  log("validate", {
429
402
  values: values2,
430
403
  errors: errors2
431
- }, {
432
- F: __dxlog_file,
433
- L: 155,
434
- S: void 0,
435
- C: (f, a) => f(...a)
436
- });
404
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 42, S: void 0 });
437
405
  if (errors2.length === 0 && onValidate) {
438
406
  const validatedValues = values2;
439
407
  errors2 = onValidate(validatedValues) ?? [];
@@ -521,12 +489,7 @@ var useFormHandler = ({ schema, autoSave, values: valuesProp, defaultValues: def
521
489
  log("onValueChange", {
522
490
  path,
523
491
  value: value3
524
- }, {
525
- F: __dxlog_file,
526
- L: 254,
527
- S: void 0,
528
- C: (f, a) => f(...a)
529
- });
492
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 138, S: void 0 });
530
493
  const jsonPath = createJsonPath(path);
531
494
  const pathArray = path;
532
495
  let parsedValue = value3;
@@ -535,12 +498,7 @@ var useFormHandler = ({ schema, autoSave, values: valuesProp, defaultValues: def
535
498
  parsedValue = parseFloat(value3) || 0;
536
499
  }
537
500
  } catch (err) {
538
- log.catch(err, void 0, {
539
- F: __dxlog_file,
540
- L: 264,
541
- S: void 0,
542
- C: (f, a) => f(...a)
543
- });
501
+ log.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 150, S: void 0 });
544
502
  parsedValue = void 0;
545
503
  }
546
504
  const newValues = mergeAtPath(values, pathArray, parsedValue);
@@ -649,9 +607,9 @@ var flatMap = (errors) => {
649
607
  };
650
608
 
651
609
  // src/hooks/useKeyHandler.tsx
652
- import { useCallback as useCallback2, useEffect as useEffect2 } from "react";
610
+ import { useCallback as useCallback2, useLayoutEffect } from "react";
653
611
  import { addEventListener } from "@dxos/async";
654
- var useKeyHandler = (formElement, form) => {
612
+ var useKeyHandler = (elRef, form) => {
655
613
  const handleKeyDown = useCallback2((event) => {
656
614
  switch (event.key) {
657
615
  case "Enter": {
@@ -667,13 +625,14 @@ var useKeyHandler = (formElement, form) => {
667
625
  form.onSave,
668
626
  form.autoSave
669
627
  ]);
670
- useEffect2(() => {
671
- if (!formElement) {
628
+ useLayoutEffect(() => {
629
+ const el = elRef.current;
630
+ if (!el) {
672
631
  return;
673
632
  }
674
- return addEventListener(formElement, "keydown", handleKeyDown);
633
+ return addEventListener(el, "keydown", handleKeyDown);
675
634
  }, [
676
- formElement,
635
+ elRef,
677
636
  handleKeyDown
678
637
  ]);
679
638
  };
@@ -685,7 +644,6 @@ import { inputTextLabel } from "@dxos/ui-theme";
685
644
  var FormFieldLabel = ({ label, error, readonly, asChild }) => {
686
645
  const Label = readonly || asChild ? "span" : Input.Label;
687
646
  return /* @__PURE__ */ React.createElement("div", {
688
- role: "none",
689
647
  className: "flex items-center justify-between"
690
648
  }, /* @__PURE__ */ React.createElement(Label, {
691
649
  className: inputTextLabel
@@ -709,7 +667,6 @@ var FormFieldWrapper = (props) => {
709
667
  }
710
668
  const str = String(value3 ?? "");
711
669
  return /* @__PURE__ */ React.createElement("div", {
712
- role: "none",
713
670
  className: "contents"
714
671
  }, /* @__PURE__ */ React.createElement(Input.Root, {
715
672
  validationValence: status
@@ -740,7 +697,7 @@ var FormFieldErrorBoundary = class extends Component {
740
697
  return /* @__PURE__ */ React.createElement("div", {
741
698
  className: "flex gap-2 border border-rose-fill font-mono text-sm"
742
699
  }, /* @__PURE__ */ React.createElement("span", {
743
- className: "bg-rose-fill text-surface-text px-1 font-thin"
700
+ className: "bg-rose-fill text-base-foreground px-1 font-thin"
744
701
  }, "ERROR"), String(this.props.path?.join(".")));
745
702
  }
746
703
  return this.props.children;
@@ -753,20 +710,19 @@ var FormFieldErrorBoundary = class extends Component {
753
710
  };
754
711
 
755
712
  // src/components/Form/FormFieldSet.tsx
756
- import React3, { forwardRef, useMemo as useMemo3 } from "react";
757
- import { mx } from "@dxos/ui-theme";
758
- import { isTruthy } from "@dxos/util";
713
+ import React3, { useMemo as useMemo3 } from "react";
759
714
 
760
715
  // src/components/Form/FormField.tsx
761
716
  import * as Match from "effect/Match";
762
717
  import * as Option2 from "effect/Option";
763
718
  import * as Schema from "effect/Schema";
764
- import * as SchemaAST from "effect/SchemaAST";
719
+ import * as SchemaAST2 from "effect/SchemaAST";
765
720
  import * as String2 from "effect/String";
766
721
  import React2, { useMemo as useMemo2 } from "react";
767
722
  import { Format as Format3 } from "@dxos/echo";
768
- import { createJsonPath as createJsonPath2, findNode, getAnnotation, getDiscriminatedType, isArrayType as isArrayType2, isDiscriminatedUnion, isLiteralUnion, isNestedType } from "@dxos/effect";
723
+ import { createJsonPath as createJsonPath2, findNode, getAnnotation as getAnnotation2, getDiscriminatedType, isArrayType as isArrayType2, isDiscriminatedUnion, isLiteralUnion as isLiteralUnion2, isNestedType } from "@dxos/effect";
769
724
  import { useTranslation } from "@dxos/react-ui";
725
+ import { translationKey } from "#translations";
770
726
  var FormField = (props) => {
771
727
  const {
772
728
  type,
@@ -778,23 +734,25 @@ var FormField = (props) => {
778
734
  readonly,
779
735
  layout,
780
736
  // RefFieldProps
737
+ createTypename,
781
738
  createOptionLabel,
782
739
  createOptionIcon,
783
740
  createInitialValuePath,
741
+ createFieldMap: createFieldMap3,
784
742
  db,
785
- schemaHook,
786
- getOptions: getRefOptions,
743
+ useSchema: schemaHook,
744
+ getOptions,
787
745
  onCreate
788
746
  } = props;
789
747
  const { t } = useTranslation(translationKey);
790
- const title = getAnnotation(SchemaAST.TitleAnnotationId)(type);
791
- const description = getAnnotation(SchemaAST.DescriptionAnnotationId)(type);
792
- const examples = getAnnotation(SchemaAST.ExamplesAnnotationId)(type);
748
+ const title = getAnnotation2(SchemaAST2.TitleAnnotationId)(type);
749
+ const description = getAnnotation2(SchemaAST2.DescriptionAnnotationId)(type);
750
+ const examples = getAnnotation2(SchemaAST2.ExamplesAnnotationId)(type);
793
751
  const label = useMemo2(() => title ?? String2.capitalize(name), [
794
752
  title,
795
753
  name
796
754
  ]);
797
- const placeholder = useMemo2(() => examples?.length ? `${t("example placeholder")}: ${examples[0]}` : description ?? label, [
755
+ const placeholder = useMemo2(() => examples?.length ? `${t("example.placeholder")}: ${examples[0]}` : description ?? label, [
798
756
  examples,
799
757
  description,
800
758
  label
@@ -807,6 +765,7 @@ var FormField = (props) => {
807
765
  label,
808
766
  placeholder,
809
767
  layout,
768
+ db,
810
769
  ...fieldState
811
770
  };
812
771
  const jsonPath = createJsonPath2(path ?? []);
@@ -833,7 +792,7 @@ var FormField = (props) => {
833
792
  if (Field) {
834
793
  return /* @__PURE__ */ React2.createElement(Field, fieldProps);
835
794
  }
836
- const options = getOptions(type);
795
+ const options = getSelectOptions(type);
837
796
  if (options) {
838
797
  const fieldProjections = projection?.getFieldProjections();
839
798
  const fieldProjection = fieldProjections?.find((fp) => fp.field.path === name);
@@ -851,21 +810,23 @@ var FormField = (props) => {
851
810
  }
852
811
  const refProps = getRefProps(type);
853
812
  if (refProps) {
813
+ const isCreateTarget = !createTypename || refProps.typename === createTypename;
854
814
  return /* @__PURE__ */ React2.createElement(RefField, {
855
815
  ...fieldProps,
856
816
  ...refProps,
857
- createOptionLabel,
858
- createOptionIcon,
859
- createInitialValuePath,
817
+ createOptionLabel: isCreateTarget ? createOptionLabel : void 0,
818
+ createOptionIcon: isCreateTarget ? createOptionIcon : void 0,
819
+ createInitialValuePath: isCreateTarget ? createInitialValuePath : void 0,
820
+ createFieldMap: isCreateTarget ? createFieldMap3 : void 0,
860
821
  db,
861
- schemaHook,
862
- getOptions: getRefOptions,
822
+ useSchema: schemaHook,
823
+ getOptions,
863
824
  onCreate
864
825
  });
865
826
  }
866
827
  if (isNestedType(type)) {
867
828
  const baseNode = findNode(type, isDiscriminatedUnion);
868
- const typeLiteral = baseNode ? getDiscriminatedType(baseNode, fieldState.getValue()) : findNode(type, SchemaAST.isTypeLiteral);
829
+ const typeLiteral = baseNode ? getDiscriminatedType(baseNode, fieldState.getValue()) : findNode(type, SchemaAST2.isTypeLiteral);
869
830
  if (typeLiteral) {
870
831
  const schema = Schema.make(typeLiteral);
871
832
  return /* @__PURE__ */ React2.createElement(FormFieldSet, {
@@ -881,8 +842,8 @@ var FormField = (props) => {
881
842
  createOptionIcon,
882
843
  createInitialValuePath,
883
844
  db,
884
- schemaHook,
885
- getOptions: getRefOptions,
845
+ useSchema: schemaHook,
846
+ getOptions,
886
847
  onCreate
887
848
  });
888
849
  }
@@ -906,8 +867,8 @@ var getFormField = ({ type, format }) => {
906
867
  return BooleanField;
907
868
  }
908
869
  };
909
- var getOptions = (ast) => {
910
- if (isLiteralUnion(ast)) {
870
+ var getSelectOptions = (ast) => {
871
+ if (isLiteralUnion2(ast)) {
911
872
  return ast.types.map((type) => type.literal).filter((v) => v !== null);
912
873
  }
913
874
  return Format3.OptionsAnnotation.getFromAst(ast).pipe((annotation) => Option2.getOrUndefined(annotation));
@@ -915,47 +876,19 @@ var getOptions = (ast) => {
915
876
 
916
877
  // src/components/Form/FormFieldSet.tsx
917
878
  var FORM_FIELDSET_NAME = "Form.FieldSet";
918
- var FormFieldSet = /* @__PURE__ */ forwardRef(({ label, schema, readonly, path, exclude, sort, projection, layout, ...props }, forwardRef4) => {
879
+ var FormFieldSet = ({ label, schema, readonly, path, sort, exclude, projection, layout, ...props }) => {
919
880
  const values = useFormValues(FORM_FIELDSET_NAME, path);
920
- const properties = useMemo3(() => {
921
- if (!schema) {
922
- return [];
923
- }
924
- const props2 = getFormProperties(schema.ast);
925
- if (projection) {
926
- const fieldProjections = projection.getFieldProjections();
927
- const hiddenProperties = new Set(projection.getHiddenProperties());
928
- const visibleProps = props2.filter((prop) => !hiddenProperties.has(prop.name.toString()));
929
- const orderedProps = [];
930
- for (const fieldProjection of fieldProjections) {
931
- const fieldPath = String(fieldProjection.field.path);
932
- const prop = visibleProps.find((p) => p.name === fieldPath);
933
- if (prop) {
934
- orderedProps.push(prop);
935
- }
936
- }
937
- const projectionPaths = new Set(fieldProjections.map((projection2) => String(projection2.field.path)));
938
- const remainingProps = visibleProps.filter((prop) => !projectionPaths.has(prop.name.toString()));
939
- orderedProps.push(...remainingProps);
940
- return orderedProps;
941
- }
942
- const filtered = exclude ? exclude(props2) : props2;
943
- return sort ? filtered.sort(({ name: a }, { name: b }) => sort.indexOf(a.toString()) - sort.indexOf(b.toString())) : filtered;
944
- }, [
881
+ const properties = useFormFieldSetProperties({
945
882
  schema,
946
883
  values,
947
884
  exclude,
948
885
  sort,
949
- projection?.fields
950
- ]);
886
+ projection
887
+ });
951
888
  if ((readonly || layout === "static") && values == null) {
952
889
  return null;
953
890
  }
954
- return /* @__PURE__ */ React3.createElement("div", {
955
- role: "form",
956
- className: mx("w-full", layout === "inline" && "flex flex-col gap-2"),
957
- ref: forwardRef4
958
- }, layout !== "inline" && label && /* @__PURE__ */ React3.createElement(FormFieldLabel, {
891
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, layout !== "inline" && label && /* @__PURE__ */ React3.createElement(FormFieldLabel, {
959
892
  label,
960
893
  asChild: true
961
894
  }), properties.map((property) => {
@@ -978,12 +911,52 @@ var FormFieldSet = /* @__PURE__ */ forwardRef(({ label, schema, readonly, path,
978
911
  projection,
979
912
  ...props
980
913
  }));
981
- }).filter(isTruthy));
982
- });
914
+ }));
915
+ };
983
916
  FormFieldSet.displayName = FORM_FIELDSET_NAME;
917
+ var useFormFieldSetProperties = ({ schema, exclude, projection, values, sort }) => {
918
+ return useMemo3(() => {
919
+ if (!schema) {
920
+ return [];
921
+ }
922
+ const schemaProps = getFormProperties(schema.ast);
923
+ const filteredProps = exclude ? exclude(schemaProps) : schemaProps;
924
+ if (projection) {
925
+ const fieldProjections = projection.getFieldProjections();
926
+ const hiddenProperties = new Set(projection.getHiddenProperties());
927
+ const visibleProps = filteredProps.filter((prop) => !hiddenProperties.has(prop.name.toString()));
928
+ const orderedProps = [];
929
+ for (const fieldProjection of fieldProjections) {
930
+ const fieldPath = String(fieldProjection.field.path);
931
+ const prop = visibleProps.find((prop2) => prop2.name === fieldPath);
932
+ if (prop) {
933
+ orderedProps.push(prop);
934
+ }
935
+ }
936
+ const projectionPaths = new Set(fieldProjections.map((projection2) => String(projection2.field.path)));
937
+ const remainingProps = visibleProps.filter((prop) => !projectionPaths.has(prop.name.toString()));
938
+ orderedProps.push(...remainingProps);
939
+ return orderedProps;
940
+ }
941
+ return sort ? [
942
+ ...filteredProps
943
+ ].sort(({ name: a }, { name: b }) => sort.indexOf(a.toString()) - sort.indexOf(b.toString())) : filteredProps;
944
+ }, [
945
+ schema,
946
+ values,
947
+ exclude,
948
+ sort,
949
+ projection
950
+ ]);
951
+ };
984
952
 
985
953
  // src/components/Form/Form.tsx
986
954
  var omitId = (schema) => schema.pipe(Schema2.omit("id"));
955
+ var omitHiddenFormFields = (schema) => {
956
+ const properties = SchemaAST3.getPropertySignatures(schema.ast);
957
+ const hidden = properties.filter((prop) => Option3.getOrElse(EchoAnnotation.FormInputAnnotation.getFromAst(prop.type), () => true) === false).map((prop) => prop.name);
958
+ return hidden.length === 0 ? schema : schema.pipe(Schema2.omit(...hidden));
959
+ };
987
960
  var [FormContextProvider, useFormContext] = createContext("Form");
988
961
  var useFormValues = (componentName, path, defaultValue) => {
989
962
  const stablePath = useMemo4(() => path ?? [], [
@@ -993,10 +966,10 @@ var useFormValues = (componentName, path, defaultValue) => {
993
966
  const { form: { values, onValueChange } } = useFormContext(componentName);
994
967
  const value3 = getValue$2(values, jsonPath);
995
968
  const lastAppliedPathRef = useRef(null);
996
- useEffect3(() => {
969
+ useEffect2(() => {
997
970
  if (value3 == null && defaultValue && lastAppliedPathRef.current !== jsonPath) {
998
971
  lastAppliedPathRef.current = jsonPath;
999
- onValueChange(stablePath, SchemaAST2.stringKeyword, defaultValue());
972
+ onValueChange(stablePath, SchemaAST3.stringKeyword, defaultValue());
1000
973
  }
1001
974
  }, [
1002
975
  value3,
@@ -1040,29 +1013,35 @@ var FormRoot = ({ children, schema, values, onSave, onCancel, ...props }) => {
1040
1013
  };
1041
1014
  FormRoot.displayName = "Form.Root";
1042
1015
  var FORM_VIEWPORT_NAME = "Form.Viewport";
1043
- var FormViewport = ({ children, classNames, margin = true, padding = true, thin = true, ...props }) => {
1016
+ var FormViewport = composable(({ children, ...props }, forwardedRef) => {
1044
1017
  return /* @__PURE__ */ React4.createElement(ScrollArea.Root, {
1018
+ ...composableProps(props),
1045
1019
  orientation: "vertical",
1046
- classNames,
1047
- margin,
1048
- padding,
1049
- thin,
1050
- ...props
1020
+ centered: true,
1021
+ padding: true,
1022
+ thin: true,
1023
+ ref: forwardedRef
1051
1024
  }, /* @__PURE__ */ React4.createElement(ScrollArea.Viewport, null, children));
1052
- };
1025
+ });
1053
1026
  FormViewport.displayName = FORM_VIEWPORT_NAME;
1054
1027
  var FORM_CONTENT_NAME = "Form.Content";
1055
- var FormContent = ({ classNames, children }) => {
1028
+ var FormContent = composable(({ children, ...props }, forwardedRef) => {
1056
1029
  const { form, testId } = useFormContext(FORM_CONTENT_NAME);
1057
- const ref = useRef(null);
1058
- useKeyHandler(ref.current, form);
1030
+ const localRef = useRef(null);
1031
+ const mergedRef = useMergeRefs([
1032
+ forwardedRef,
1033
+ localRef
1034
+ ]);
1035
+ useKeyHandler(localRef, form);
1059
1036
  return /* @__PURE__ */ React4.createElement("div", {
1060
- ref,
1061
- role: "form",
1062
- className: mx2("w-full flex flex-col gap-form-padding", classNames),
1063
- "data-testid": testId
1037
+ ...composableProps(props, {
1038
+ role: "form",
1039
+ classNames: mx(withColumn.center(), "flex flex-col w-full pb-form-gap")
1040
+ }),
1041
+ "data-testid": testId,
1042
+ ref: mergedRef
1064
1043
  }, children);
1065
- };
1044
+ });
1066
1045
  FormContent.displayName = FORM_CONTENT_NAME;
1067
1046
  var FORM_FIELDSET_NAME2 = "Form.FieldSet";
1068
1047
  var FormFieldSet2 = (props) => {
@@ -1076,18 +1055,17 @@ var FormFieldSet2 = (props) => {
1076
1055
  FormFieldSet2.displayName = FORM_FIELDSET_NAME2;
1077
1056
  var FORM_ACTIONS_NAME = "Form.Actions";
1078
1057
  var FormActions = ({ classNames }) => {
1079
- const { t } = useTranslation2(translationKey);
1058
+ const { t } = useTranslation2(translationKey2);
1080
1059
  const { form: { canSave, onSave, onCancel }, readonly, layout } = useFormContext(FORM_ACTIONS_NAME);
1081
1060
  if (readonly || layout === "static") {
1082
1061
  return null;
1083
1062
  }
1084
1063
  return /* @__PURE__ */ React4.createElement("div", {
1085
- role: "none",
1086
- className: mx2("grid grid-flow-col gap-2 auto-cols-fr py-form-padding", classNames)
1064
+ className: mx(withColumn.center(), "grid grid-flow-col gap-form-gap auto-cols-fr py-form-padding", classNames)
1087
1065
  }, onCancel && /* @__PURE__ */ React4.createElement(IconButton, {
1088
1066
  icon: "ph--x--regular",
1089
1067
  iconEnd: true,
1090
- label: t("cancel button label"),
1068
+ label: t("cancel-button.label"),
1091
1069
  onClick: onCancel,
1092
1070
  "data-testid": "cancel-button"
1093
1071
  }), onSave && /* @__PURE__ */ React4.createElement(IconButton, {
@@ -1096,29 +1074,42 @@ var FormActions = ({ classNames }) => {
1096
1074
  disabled: !canSave,
1097
1075
  icon: "ph--check--regular",
1098
1076
  iconEnd: true,
1099
- label: t("save button label"),
1077
+ label: t("save-button.label"),
1100
1078
  onClick: onSave,
1101
1079
  "data-testid": "save-button"
1102
1080
  }));
1103
1081
  };
1104
1082
  FormActions.displayName = FORM_ACTIONS_NAME;
1083
+ var FORM_SECTION_NAME = "Form.Section";
1084
+ var FormSection = composable(({ children, label, description, ...props }, forwardedRef) => {
1085
+ return /* @__PURE__ */ React4.createElement("div", {
1086
+ ...composableProps(props, {
1087
+ classNames: "flex flex-col pt-form-section-gap first:pt-0"
1088
+ }),
1089
+ ref: forwardedRef
1090
+ }, /* @__PURE__ */ React4.createElement("h2", {
1091
+ className: "text-lg"
1092
+ }, label), description && /* @__PURE__ */ React4.createElement("p", {
1093
+ className: "text-description"
1094
+ }, description), children);
1095
+ });
1096
+ FormSection.displayName = FORM_SECTION_NAME;
1105
1097
  var FORM_SUBMIT_NAME = "Form.Submit";
1106
1098
  var FormSubmit = ({ classNames, label, icon, disabled }) => {
1107
- const { t } = useTranslation2(translationKey);
1099
+ const { t } = useTranslation2(translationKey2);
1108
1100
  const { form: { canSave, onSave }, readonly, layout } = useFormContext(FORM_SUBMIT_NAME);
1109
1101
  if (readonly || layout === "static") {
1110
1102
  return null;
1111
1103
  }
1112
1104
  return /* @__PURE__ */ React4.createElement("div", {
1113
- role: "none",
1114
- className: mx2("flex w-full pt-form-padding", classNames)
1105
+ className: mx("flex w-full pt-form-padding", classNames)
1115
1106
  }, /* @__PURE__ */ React4.createElement(IconButton, {
1116
1107
  classNames: "w-full",
1117
1108
  type: "submit",
1118
1109
  variant: "primary",
1119
1110
  disabled: disabled ?? !canSave,
1120
1111
  icon: icon ?? "ph--check--regular",
1121
- label: label ?? t("save button label"),
1112
+ label: label ?? t("save-button.label"),
1122
1113
  onClick: onSave,
1123
1114
  "data-testid": "save-button"
1124
1115
  }));
@@ -1128,6 +1119,7 @@ var Form = {
1128
1119
  Root: FormRoot,
1129
1120
  Viewport: FormViewport,
1130
1121
  Content: FormContent,
1122
+ Section: FormSection,
1131
1123
  FieldSet: FormFieldSet2,
1132
1124
  Label: FormFieldLabel,
1133
1125
  Actions: FormActions,
@@ -1136,18 +1128,18 @@ var Form = {
1136
1128
 
1137
1129
  // src/components/Form/fields/ArrayField.tsx
1138
1130
  var ArrayField = ({ type, path, label, readonly, layout, fieldProps: inputProps, ...props }) => {
1139
- const { t } = useTranslation3(translationKey);
1131
+ const { t } = useTranslation3(translationKey3);
1140
1132
  const elementType = getArrayElementType2(type);
1141
1133
  const { onValueChange } = inputProps;
1142
1134
  const values = useFormValues(ArrayField.displayName, path, () => []);
1143
1135
  const getDefaultObjectValue = (typeNode) => {
1144
1136
  const baseNode = findNode2(typeNode, isDiscriminatedUnion2);
1145
- const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, {}) : findNode2(typeNode, SchemaAST3.isTypeLiteral);
1137
+ const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, {}) : findNode2(typeNode, SchemaAST4.isTypeLiteral);
1146
1138
  if (!typeLiteral) {
1147
1139
  return {};
1148
1140
  }
1149
1141
  return Object.fromEntries(getFormProperties(typeLiteral).map((prop) => {
1150
- const defaultValue = SchemaAST3.getDefaultAnnotation(prop.type).pipe((annotation) => Option3.getOrUndefined(annotation));
1142
+ const defaultValue = SchemaAST4.getDefaultAnnotation(prop.type).pipe((annotation) => Option4.getOrUndefined(annotation));
1151
1143
  return [
1152
1144
  prop.name,
1153
1145
  defaultValue
@@ -1181,13 +1173,11 @@ var ArrayField = ({ type, path, label, readonly, layout, fieldProps: inputProps,
1181
1173
  label,
1182
1174
  asChild: true
1183
1175
  }), /* @__PURE__ */ React5.createElement("div", {
1184
- role: "none",
1185
- className: "flex flex-col gap-2"
1176
+ className: "flex flex-col gap-form-gap"
1186
1177
  }, values?.map((_, index) => {
1187
1178
  return /* @__PURE__ */ React5.createElement("div", {
1188
- role: "none",
1189
1179
  key: index,
1190
- className: "grid grid-cols-[1fr_min-content] gap-2 last:mb-3"
1180
+ className: "grid grid-cols-[1fr_min-content] gap-form-gap last:mb-form-gap items-center"
1191
1181
  }, /* @__PURE__ */ React5.createElement(FormField, {
1192
1182
  autoFocus: index === values.length - 1,
1193
1183
  type: elementType,
@@ -1199,22 +1189,20 @@ var ArrayField = ({ type, path, label, readonly, layout, fieldProps: inputProps,
1199
1189
  layout: "inline",
1200
1190
  ...props
1201
1191
  }), !readonly && layout !== "static" && /* @__PURE__ */ React5.createElement("div", {
1202
- role: "none",
1203
1192
  className: "flex flex-col h-full justify-end"
1204
1193
  }, /* @__PURE__ */ React5.createElement("div", {
1205
- role: "none",
1206
1194
  className: "flex items-center h-[2rem]"
1207
1195
  }, /* @__PURE__ */ React5.createElement(IconButton2, {
1208
1196
  icon: "ph--x--regular",
1209
1197
  iconOnly: true,
1210
- label: t("button remove"),
1198
+ label: t("remove.button"),
1211
1199
  onClick: () => handleDelete(index),
1212
1200
  classNames: "self-center"
1213
1201
  }))));
1214
1202
  })), !readonly && layout !== "static" && /* @__PURE__ */ React5.createElement(IconButton2, {
1215
1203
  classNames: "flex w-full",
1216
1204
  icon: "ph--plus--regular",
1217
- label: t("add field"),
1205
+ label: t("add-item.button"),
1218
1206
  onClick: handleAdd
1219
1207
  }));
1220
1208
  };
@@ -1262,12 +1250,13 @@ var BooleanField = ({ type, readonly, onValueChange, ...props }) => {
1262
1250
  };
1263
1251
 
1264
1252
  // src/components/Form/fields/GeoPointField.tsx
1265
- import React7, { useCallback as useCallback5, useEffect as useEffect4, useMemo as useMemo5, useState as useState2 } from "react";
1253
+ import React7, { useCallback as useCallback5, useEffect as useEffect3, useMemo as useMemo5, useState as useState2 } from "react";
1266
1254
  import { GeoLocation as GeoLocation3 } from "@dxos/echo/internal";
1267
1255
  import { Input as Input3, useTranslation as useTranslation4 } from "@dxos/react-ui";
1268
1256
  import { safeParseFloat } from "@dxos/util";
1257
+ import { translationKey as translationKey4 } from "#translations";
1269
1258
  var GeoPointField = ({ type, label, readonly, layout, getStatus, getValue, onValueChange, onBlur }) => {
1270
- const { t } = useTranslation4(translationKey);
1259
+ const { t } = useTranslation4(translationKey4);
1271
1260
  const { status, error } = getStatus();
1272
1261
  const geoPoint = useMemo5(() => getValue() ?? [
1273
1262
  0,
@@ -1280,7 +1269,7 @@ var GeoPointField = ({ type, label, readonly, layout, getStatus, getValue, onVal
1280
1269
  ]);
1281
1270
  const [longitudeText, setLongitudeText] = useState2(value3.longitude?.toString());
1282
1271
  const [latitudeText, setLatitudeText] = useState2(value3.latitude?.toString());
1283
- useEffect4(() => {
1272
+ useEffect3(() => {
1284
1273
  const location = GeoLocation3.fromGeoPoint(geoPoint);
1285
1274
  setLongitudeText(location.longitude?.toString());
1286
1275
  setLatitudeText(location.latitude?.toString());
@@ -1321,25 +1310,24 @@ var GeoPointField = ({ type, label, readonly, layout, getStatus, getValue, onVal
1321
1310
  label,
1322
1311
  asChild: true
1323
1312
  }), layout === "static" ? /* @__PURE__ */ React7.createElement(LatLng, value3) : /* @__PURE__ */ React7.createElement("div", {
1324
- role: "none",
1325
- className: "grid grid-cols-2 gap-2"
1326
- }, /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("latitude label")), /* @__PURE__ */ React7.createElement(Input3.TextInput, {
1313
+ className: "grid grid-cols-2 gap-form-gap"
1314
+ }, /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("latitude.label")), /* @__PURE__ */ React7.createElement(Input3.TextInput, {
1327
1315
  type: "number",
1328
1316
  step: "0.00001",
1329
1317
  min: "-90",
1330
1318
  max: "90",
1331
1319
  disabled: !!readonly,
1332
- placeholder: t("latitude placeholder"),
1320
+ placeholder: t("latitude.placeholder"),
1333
1321
  value: latitudeText ?? "",
1334
1322
  onChange: handleChange("latitude", setLatitudeText),
1335
1323
  onBlur
1336
- }))), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("longitude label")), /* @__PURE__ */ React7.createElement(Input3.TextInput, {
1324
+ }))), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("longitude.label")), /* @__PURE__ */ React7.createElement(Input3.TextInput, {
1337
1325
  type: "number",
1338
1326
  step: "0.00001",
1339
1327
  min: "-180",
1340
1328
  max: "180",
1341
1329
  disabled: !!readonly,
1342
- placeholder: t("longitude placeholder"),
1330
+ placeholder: t("longitude.placeholder"),
1343
1331
  value: longitudeText ?? "",
1344
1332
  onChange: handleChange("longitude", setLongitudeText),
1345
1333
  onBlur
@@ -1349,7 +1337,7 @@ var LatLng = ({ latitude = 0, longitude = 0 }) => {
1349
1337
  const latHem = latitude >= 0 ? "N" : "S";
1350
1338
  const lngHem = longitude >= 0 ? "E" : "W";
1351
1339
  return /* @__PURE__ */ React7.createElement("span", {
1352
- className: "inline-flex items-center gap-1"
1340
+ className: "inline-flex items-center gap-form-gap"
1353
1341
  }, /* @__PURE__ */ React7.createElement("span", null, /* @__PURE__ */ React7.createElement("span", null, Math.abs(latitude).toFixed(5)), /* @__PURE__ */ React7.createElement("span", {
1354
1342
  className: "text-subdued"
1355
1343
  }, "\xB0", latHem)), /* @__PURE__ */ React7.createElement("span", null, /* @__PURE__ */ React7.createElement("span", null, Math.abs(longitude).toFixed(5)), /* @__PURE__ */ React7.createElement("span", {
@@ -1358,56 +1346,141 @@ var LatLng = ({ latitude = 0, longitude = 0 }) => {
1358
1346
  };
1359
1347
 
1360
1348
  // src/components/Form/fields/MarkdownField.tsx
1361
- import React8, { useCallback as useCallback6, useEffect as useEffect5, useRef as useRef2 } from "react";
1362
- import { Input as Input4 } from "@dxos/react-ui";
1363
- var MarkdownField = ({ type, readonly, label, placeholder, layout, getStatus, getValue, onValueChange, onBlur }) => {
1349
+ import { useAtomValue } from "@effect-atom/atom-react";
1350
+ import React8, { useCallback as useCallback6, useMemo as useMemo6 } from "react";
1351
+ import { Obj, Ref as Ref2 } from "@dxos/echo";
1352
+ import { AtomRef } from "@dxos/echo-atom";
1353
+ import { createDocAccessor } from "@dxos/echo-db";
1354
+ import { Button, Icon as Icon2, Input as Input4, useTranslation as useTranslation5 } from "@dxos/react-ui";
1355
+ import { Editor, useBasicMarkdownExtensions } from "@dxos/react-ui-editor";
1356
+ import { Text } from "@dxos/schema";
1357
+ import { createDataExtensions } from "@dxos/ui-editor";
1358
+ import { translationKey as translationKey5 } from "#translations";
1359
+ var editorClassNames = "transition-colors bg-input-surface focus-within:bg-focus-surface border border-separator rounded-xs p-1 px-2";
1360
+ var MarkdownField = ({ type, readonly, label, placeholder, layout, db, getStatus, getValue, onValueChange }) => {
1364
1361
  const { status, error } = getStatus();
1365
- const textareaRef = useRef2(null);
1366
- const adjustHeight = useCallback6(() => {
1367
- const textarea = textareaRef.current;
1368
- if (textarea) {
1369
- textarea.style.blockSize = "auto";
1370
- textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
1371
- }
1372
- }, []);
1373
- useEffect5(() => {
1374
- adjustHeight();
1375
- }, [
1376
- adjustHeight
1377
- ]);
1378
- useEffect5(() => {
1379
- adjustHeight();
1380
- }, [
1381
- getValue(),
1382
- adjustHeight
1383
- ]);
1384
- const handleChange = useCallback6((event) => onValueChange(type, event.target.value), [
1385
- type,
1386
- onValueChange
1387
- ]);
1362
+ const isRef = Ref2.isRefType(type);
1388
1363
  const value3 = getValue();
1389
- if ((readonly || layout === "static") && !value3) {
1364
+ if ((readonly || layout === "static") && value3 == null) {
1390
1365
  return null;
1391
1366
  }
1367
+ const renderEditor = () => {
1368
+ if (isRef) {
1369
+ const reference = value3;
1370
+ if (reference) {
1371
+ return /* @__PURE__ */ React8.createElement(RefMarkdownEditor, {
1372
+ reference,
1373
+ placeholder
1374
+ });
1375
+ }
1376
+ if (readonly) {
1377
+ return null;
1378
+ }
1379
+ return /* @__PURE__ */ React8.createElement(CreateTextButton, {
1380
+ db,
1381
+ disabled: !db,
1382
+ onCreate: (ref) => onValueChange(type, ref)
1383
+ });
1384
+ }
1385
+ return /* @__PURE__ */ React8.createElement(StringMarkdownEditor, {
1386
+ value: value3 ?? "",
1387
+ placeholder,
1388
+ readonly: !!readonly,
1389
+ onChange: (next) => onValueChange(type, next)
1390
+ });
1391
+ };
1392
+ const renderStatic = () => {
1393
+ if (isRef) {
1394
+ const reference = value3;
1395
+ return reference ? /* @__PURE__ */ React8.createElement(RefStaticText, {
1396
+ reference
1397
+ }) : null;
1398
+ }
1399
+ return /* @__PURE__ */ React8.createElement("p", {
1400
+ className: "whitespace-pre-wrap"
1401
+ }, value3 ?? "");
1402
+ };
1392
1403
  return /* @__PURE__ */ React8.createElement(Input4.Root, {
1393
1404
  validationValence: status
1394
1405
  }, layout !== "inline" && /* @__PURE__ */ React8.createElement(FormFieldLabel, {
1395
1406
  error,
1396
1407
  readonly,
1397
1408
  label
1398
- }), layout === "static" ? /* @__PURE__ */ React8.createElement("p", null, value3) : /* @__PURE__ */ React8.createElement(Input4.TextArea, {
1399
- ref: textareaRef,
1400
- disabled: !!readonly,
1409
+ }), layout === "static" ? renderStatic() : renderEditor(), layout === "full" && /* @__PURE__ */ React8.createElement(Input4.Validation, null, error));
1410
+ };
1411
+ var RefStaticText = ({ reference }) => {
1412
+ const text = useAtomValue(useMemo6(() => AtomRef.make(reference), [
1413
+ reference
1414
+ ]));
1415
+ if (!text?.content) {
1416
+ return null;
1417
+ }
1418
+ return /* @__PURE__ */ React8.createElement("p", {
1419
+ className: "whitespace-pre-wrap"
1420
+ }, text.content);
1421
+ };
1422
+ var RefMarkdownEditor = ({ reference, placeholder }) => {
1423
+ const text = useAtomValue(useMemo6(() => AtomRef.make(reference), [
1424
+ reference
1425
+ ]));
1426
+ const dataExtensions = useMemo6(() => text ? [
1427
+ createDataExtensions({
1428
+ id: reference.dxn.toString(),
1429
+ text: createDocAccessor(text, [
1430
+ "content"
1431
+ ])
1432
+ })
1433
+ ] : [], [
1434
+ text,
1435
+ reference
1436
+ ]);
1437
+ const extensions = useBasicMarkdownExtensions({
1401
1438
  placeholder,
1402
- value: value3 ?? "",
1403
- classNames: "min-h-auto max-h-40 overflow-auto",
1404
- onChange: handleChange,
1405
- onBlur,
1406
- style: {
1407
- resize: "none"
1408
- },
1409
- spellCheck: false
1410
- }), layout === "full" && /* @__PURE__ */ React8.createElement(Input4.Validation, null, error));
1439
+ extensions: dataExtensions
1440
+ });
1441
+ if (!text) {
1442
+ return null;
1443
+ }
1444
+ return /* @__PURE__ */ React8.createElement(Editor.Root, null, /* @__PURE__ */ React8.createElement(Editor.View, {
1445
+ classNames: editorClassNames,
1446
+ extensions
1447
+ }));
1448
+ };
1449
+ var StringMarkdownEditor = ({ value: value3, placeholder, readonly, onChange }) => {
1450
+ const extensions = useBasicMarkdownExtensions({
1451
+ placeholder
1452
+ });
1453
+ const handleChange = useCallback6((next) => onChange(next), [
1454
+ onChange
1455
+ ]);
1456
+ return /* @__PURE__ */ React8.createElement(Editor.Root, null, /* @__PURE__ */ React8.createElement(Editor.View, {
1457
+ classNames: editorClassNames,
1458
+ extensions,
1459
+ value: value3,
1460
+ onChange: readonly ? void 0 : handleChange
1461
+ }));
1462
+ };
1463
+ var CreateTextButton = ({ db, disabled, onCreate }) => {
1464
+ const { t } = useTranslation5(translationKey5);
1465
+ const handleClick = useCallback6(() => {
1466
+ if (!db) {
1467
+ return;
1468
+ }
1469
+ const text = db.add(Obj.make(Text.Text, {
1470
+ content: ""
1471
+ }));
1472
+ onCreate(Ref2.make(text));
1473
+ }, [
1474
+ db,
1475
+ onCreate
1476
+ ]);
1477
+ return /* @__PURE__ */ React8.createElement(Button, {
1478
+ onClick: handleClick,
1479
+ disabled
1480
+ }, /* @__PURE__ */ React8.createElement(Icon2, {
1481
+ icon: "ph--plus--regular",
1482
+ size: 4
1483
+ }), /* @__PURE__ */ React8.createElement("span", null, t("create-text.label")));
1411
1484
  };
1412
1485
 
1413
1486
  // src/components/Form/fields/NumberField.tsx
@@ -1433,47 +1506,33 @@ var NumberField = ({ type, readonly, placeholder, onValueChange, onBlur, ...prop
1433
1506
  };
1434
1507
 
1435
1508
  // src/components/Form/fields/RefField.tsx
1509
+ import React11, { useCallback as useCallback9, useMemo as useMemo7, useState as useState4 } from "react";
1436
1510
  import "@dxos/lit-ui/dx-tag-picker.pcss";
1437
- import React11, { useCallback as useCallback9, useMemo as useMemo6 } from "react";
1438
- import { Entity, Filter, Obj, Ref as Ref2, Type } from "@dxos/echo";
1439
- import { ReferenceAnnotationId } from "@dxos/echo/internal";
1440
- import { useQuery, useSchema as useSchema$ } from "@dxos/echo-react";
1441
- import { findAnnotation } from "@dxos/effect";
1511
+ import { Entity, Filter, Obj as Obj2, Ref as Ref3, Type } from "@dxos/echo";
1512
+ import { useQuery, useSchema as defaultUseSchema } from "@dxos/echo-react";
1513
+ import { ReferenceAnnotationId as ReferenceAnnotationId2 } from "@dxos/echo/internal";
1514
+ import { findAnnotation as findAnnotation2 } from "@dxos/effect";
1442
1515
  import { DXN } from "@dxos/keys";
1443
1516
  import { DxAnchor } from "@dxos/lit-ui/react";
1444
- import { Button, Icon as Icon2, Input as Input6, useTranslation as useTranslation6 } from "@dxos/react-ui";
1445
- import { mx as mx3 } from "@dxos/ui-theme";
1517
+ import { Button as Button2, Icon as Icon3, Input as Input6, useTranslation as useTranslation7 } from "@dxos/react-ui";
1518
+ import { ParentLabelAnnotationId } from "@dxos/schema";
1519
+ import { translationKey as translationKey7 } from "#translations";
1446
1520
 
1447
1521
  // src/components/ObjectPicker/ObjectPicker.tsx
1448
- import React10, { forwardRef as forwardRef2, useCallback as useCallback8, useState as useState3 } from "react";
1449
- import { Popover, useTranslation as useTranslation5 } from "@dxos/react-ui";
1450
- import { Combobox, useSearchListInput, useSearchListResults } from "@dxos/react-ui-searchlist";
1451
- var CreateItem = ({ createOptionLabel, createOptionIcon, onCreateItemSelect }) => {
1452
- const { t } = useTranslation5(translationKey);
1453
- const { query } = useSearchListInput();
1454
- return /* @__PURE__ */ React10.createElement(Combobox.Item, {
1455
- value: "__create__",
1456
- label: t(createOptionLabel[0], {
1457
- ns: createOptionLabel[1].ns,
1458
- text: query
1459
- }),
1460
- icon: createOptionIcon,
1461
- classNames: "flex items-center gap-2",
1462
- closeOnSelect: false,
1463
- onSelect: () => {
1464
- onCreateItemSelect(query);
1465
- }
1466
- });
1467
- };
1468
- var ObjectPickerContent = /* @__PURE__ */ forwardRef2(({ options, selectedIds, createSchema, createOptionLabel, createOptionIcon, createInitialValuePath, onSelect, onCreate, ...props }, ref) => {
1469
- const { t } = useTranslation5(translationKey);
1522
+ import React10, { forwardRef, useCallback as useCallback8, useState as useState3 } from "react";
1523
+ import { Popover, useTranslation as useTranslation6 } from "@dxos/react-ui";
1524
+ import { Combobox } from "@dxos/react-ui-list";
1525
+ import { useSearchListResults } from "@dxos/react-ui-search";
1526
+ import { translationKey as translationKey6 } from "#translations";
1527
+ var ObjectPickerContent = /* @__PURE__ */ forwardRef(({ options, selectedIds, createSchema, createOptionLabel, createOptionIcon, createInitialValuePath, createFieldMap: createFieldMap3, onSelect, onCreate, ...props }, forwardedRef) => {
1528
+ const { t } = useTranslation6(translationKey6);
1470
1529
  const [showForm, setShowForm] = useState3(false);
1471
1530
  const [formInitialValue, setFormInitialValue] = useState3("");
1472
- const { results, handleSearch } = useSearchListResults({
1531
+ const { results, query, handleSearch } = useSearchListResults({
1473
1532
  items: options
1474
1533
  });
1475
- const handleFormSave = useCallback8((values) => {
1476
- onCreate?.(values);
1534
+ const handleFormSave = useCallback8(async (values) => {
1535
+ await onCreate?.(values);
1477
1536
  setShowForm(false);
1478
1537
  setFormInitialValue("");
1479
1538
  }, [
@@ -1495,22 +1554,31 @@ var ObjectPickerContent = /* @__PURE__ */ forwardRef2(({ options, selectedIds, c
1495
1554
  }, [
1496
1555
  createSchema
1497
1556
  ]);
1557
+ if (showForm && createSchema) {
1558
+ return /* @__PURE__ */ React10.createElement(Combobox.Content, {
1559
+ ...props,
1560
+ onKeyDownCapture: handleKeyDown,
1561
+ ref: forwardedRef
1562
+ }, /* @__PURE__ */ React10.createElement(Popover.Viewport, null, /* @__PURE__ */ React10.createElement(Form.Root, {
1563
+ testId: "create-referenced-object-form",
1564
+ schema: createSchema,
1565
+ defaultValues: createInitialValuePath ? {
1566
+ [createInitialValuePath]: formInitialValue
1567
+ } : {},
1568
+ fieldMap: createFieldMap3,
1569
+ onSave: handleFormSave,
1570
+ onCancel: handleFormCancel
1571
+ }, /* @__PURE__ */ React10.createElement(Form.Viewport, null, /* @__PURE__ */ React10.createElement(Form.Content, null, /* @__PURE__ */ React10.createElement(Form.FieldSet, null), /* @__PURE__ */ React10.createElement(Form.Actions, null))))), /* @__PURE__ */ React10.createElement(Combobox.Arrow, null));
1572
+ }
1498
1573
  return /* @__PURE__ */ React10.createElement(Combobox.Content, {
1499
1574
  ...props,
1500
- ref,
1501
- onSearch: handleSearch,
1502
- onKeyDownCapture: handleKeyDown
1503
- }, showForm && createSchema ? /* @__PURE__ */ React10.createElement(Popover.Viewport, null, /* @__PURE__ */ React10.createElement(Form.Root, {
1504
- testId: "create-referenced-object-form",
1505
- schema: createSchema,
1506
- values: createInitialValuePath ? {
1507
- [createInitialValuePath]: formInitialValue
1508
- } : {},
1509
- onSave: handleFormSave,
1510
- onCancel: handleFormCancel
1511
- }, /* @__PURE__ */ React10.createElement(Form.Viewport, null, /* @__PURE__ */ React10.createElement(Form.Content, null, /* @__PURE__ */ React10.createElement(Form.FieldSet, null), /* @__PURE__ */ React10.createElement(Form.Actions, null))))) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Combobox.Input, {
1512
- placeholder: t("ref field combobox input placeholder"),
1513
- autoFocus: true
1575
+ onKeyDownCapture: handleKeyDown,
1576
+ ref: forwardedRef
1577
+ }, /* @__PURE__ */ React10.createElement(Combobox.Input, {
1578
+ placeholder: t("ref-field-combobox-input.placeholder"),
1579
+ autoFocus: true,
1580
+ value: query,
1581
+ onValueChange: handleSearch
1514
1582
  }), /* @__PURE__ */ React10.createElement(Combobox.List, null, results.map((option) => /* @__PURE__ */ React10.createElement(Combobox.Item, {
1515
1583
  key: option.id,
1516
1584
  value: option.id,
@@ -1518,16 +1586,34 @@ var ObjectPickerContent = /* @__PURE__ */ forwardRef2(({ options, selectedIds, c
1518
1586
  checked: selectedIds?.includes(option.id),
1519
1587
  onSelect: () => onSelect(option.id),
1520
1588
  classNames: "flex items-center gap-2"
1521
- })), createOptionLabel && createOptionIcon && createSchema && onCreate && /* @__PURE__ */ React10.createElement(CreateItem, {
1589
+ })), createSchema && onCreate && /* @__PURE__ */ React10.createElement(CreateItem, {
1590
+ query,
1522
1591
  createOptionLabel,
1523
- createOptionIcon,
1524
- onCreateItemSelect: (query) => {
1525
- setFormInitialValue(query);
1592
+ createOptionIcon: createOptionIcon ?? "ph--plus--regular",
1593
+ onCreateItemSelect: (currentQuery) => {
1594
+ setFormInitialValue(currentQuery);
1526
1595
  setShowForm(true);
1527
1596
  }
1528
- }))), /* @__PURE__ */ React10.createElement(Combobox.Arrow, null));
1597
+ })), /* @__PURE__ */ React10.createElement(Combobox.Arrow, null));
1529
1598
  });
1530
- ObjectPickerContent.displayName = "ObjectPickerContent";
1599
+ var CreateItem = ({ query, createOptionLabel, createOptionIcon, onCreateItemSelect }) => {
1600
+ const { t } = useTranslation6(translationKey6);
1601
+ const label = createOptionLabel ? t(createOptionLabel[0], {
1602
+ ns: createOptionLabel[1].ns,
1603
+ text: query
1604
+ }) : t("create-option.label");
1605
+ return /* @__PURE__ */ React10.createElement(Combobox.Item, {
1606
+ value: "__create__",
1607
+ label,
1608
+ icon: createOptionIcon,
1609
+ classNames: "flex items-center gap-2",
1610
+ closeOnSelect: false,
1611
+ onSelect: () => {
1612
+ onCreateItemSelect(query);
1613
+ }
1614
+ });
1615
+ };
1616
+ ObjectPickerContent.displayName = "ObjectPicker.Content";
1531
1617
  var ObjectPicker = {
1532
1618
  Root: Combobox.Root,
1533
1619
  Portal: Combobox.Portal,
@@ -1540,34 +1626,43 @@ var ObjectPicker = {
1540
1626
  var isRefSnapshot = (val) => {
1541
1627
  return typeof val === "object" && typeof val?.["/"] === "string";
1542
1628
  };
1543
- var defaultGetOptions = (results) => results.map((result) => {
1629
+ var defaultGetOptions = (results, { parentLabel } = {}) => results.map((result) => {
1544
1630
  const id = Entity.getDXN(result).toString();
1545
- const label = Entity.getLabel(result);
1631
+ const parent = parentLabel ? Obj2.getParent(result) : void 0;
1632
+ const label = parent ? Entity.getLabel(parent) : Entity.getLabel(result);
1546
1633
  return {
1547
1634
  id,
1548
1635
  label: label ?? id
1549
1636
  };
1550
1637
  });
1551
- var defaultResultsHook = (db, typename) => useQuery(db, typename ? typename === Type.getTypename(Obj.Unknown) ? Filter.everything() : Filter.typename(typename) : Filter.nothing());
1638
+ var defaultUseResults = (db, typename) => useQuery(db, typename ? typename === Type.getTypename(Obj2.Unknown) ? Filter.everything() : Filter.typename(typename) : Filter.nothing());
1552
1639
  var RefField = (props) => {
1553
- const { type, readonly, label, placeholder, layout, getStatus, getValue, createOptionLabel, createOptionIcon, createInitialValuePath, db, resultsHook: useResults = defaultResultsHook, schemaHook: useSchema = useSchema$, getOptions: getOptions2 = defaultGetOptions, onCreate, onValueChange } = props;
1554
- const { t } = useTranslation6(translationKey);
1640
+ const { type, readonly, label, placeholder, layout, getStatus, getValue, createOptionLabel, createOptionIcon, createInitialValuePath, createFieldMap: createFieldMap3, db, useSchema = defaultUseSchema, useResults = defaultUseResults, getOptions = defaultGetOptions, onCreate, onValueChange } = props;
1641
+ const { t } = useTranslation7(translationKey7);
1555
1642
  const { status, error } = getStatus();
1556
- const typename = useMemo6(() => type ? findAnnotation(type, ReferenceAnnotationId)?.typename : void 0, [
1643
+ const typename = useMemo7(() => type ? findAnnotation2(type, ReferenceAnnotationId2)?.typename : void 0, [
1557
1644
  type
1558
1645
  ]);
1559
1646
  const results = useResults(db, typename);
1560
- const options = useMemo6(() => getOptions2(results), [
1647
+ const options = useMemo7(() => {
1648
+ const parentLabel = type ? findAnnotation2(type, ParentLabelAnnotationId) === true : false;
1649
+ return getOptions(results, {
1650
+ parentLabel
1651
+ });
1652
+ }, [
1561
1653
  results,
1562
- getOptions2
1654
+ getOptions,
1655
+ type
1563
1656
  ]);
1564
1657
  const handleGetValue = useCallback9(() => {
1565
1658
  const formValue = getValue();
1659
+ const dxnToObjectId = (dxn) => dxn.split(":").pop() ?? dxn;
1566
1660
  const unknownToRefOption = (value3) => {
1567
- const isRef = Ref2.isRef(value3);
1661
+ const isRef = Ref3.isRef(value3);
1568
1662
  if (isRef || isRefSnapshot(value3)) {
1569
1663
  const dxnString = isRef ? value3.dxn.toString() : value3["/"];
1570
- const matchingOption = options.find((option) => option.id === dxnString);
1664
+ const objectId = dxnToObjectId(dxnString);
1665
+ const matchingOption = options.find((option) => dxnToObjectId(option.id) === objectId);
1571
1666
  if (matchingOption) {
1572
1667
  return matchingOption;
1573
1668
  }
@@ -1579,29 +1674,37 @@ var RefField = (props) => {
1579
1674
  options,
1580
1675
  getValue
1581
1676
  ]);
1582
- const handleUpdate = useCallback9((id) => {
1583
- const item2 = options.find((option) => option.id === id);
1584
- const ref = item2 ? Ref2.fromDXN(DXN.parse(item2.id)) : void 0;
1585
- onValueChange(type, ref);
1586
- }, [
1587
- options,
1588
- type,
1589
- onValueChange
1590
- ]);
1591
1677
  const item = handleGetValue();
1592
- const selectedIds = useMemo6(() => item ? [
1678
+ const selectedIds = useMemo7(() => item ? [
1593
1679
  item.id
1594
1680
  ] : [], [
1595
1681
  item
1596
1682
  ]);
1597
1683
  const createSchema = useSchema(db, typename);
1598
- const handleCreate = useCallback9((values) => {
1599
- if (createSchema && onCreate) {
1600
- onCreate(createSchema, values);
1684
+ const [open, setOpen] = useState4(false);
1685
+ const handleCreate = useCallback9(async (values) => {
1686
+ if (!createSchema || !onCreate) {
1687
+ return;
1688
+ }
1689
+ const newObject = await onCreate(createSchema, values);
1690
+ if (newObject) {
1691
+ onValueChange(type, Ref3.make(newObject));
1601
1692
  }
1693
+ setOpen(false);
1602
1694
  }, [
1603
1695
  createSchema,
1604
- onCreate
1696
+ onCreate,
1697
+ type,
1698
+ onValueChange
1699
+ ]);
1700
+ const handleUpdate = useCallback9((id) => {
1701
+ const item2 = options.find((option) => option.id === id);
1702
+ const ref = item2 ? Ref3.fromDXN(DXN.parse(item2.id)) : void 0;
1703
+ onValueChange(type, ref);
1704
+ }, [
1705
+ options,
1706
+ type,
1707
+ onValueChange
1605
1708
  ]);
1606
1709
  const handleSelect = useCallback9((id) => {
1607
1710
  if (item?.id === id) {
@@ -1623,40 +1726,46 @@ var RefField = (props) => {
1623
1726
  readonly,
1624
1727
  label
1625
1728
  }), /* @__PURE__ */ React11.createElement("div", null, readonly ? !item ? /* @__PURE__ */ React11.createElement("p", {
1626
- className: mx3("text-description", "mb-2")
1627
- }, t("empty readonly ref field label")) : /* @__PURE__ */ React11.createElement(DxAnchor, {
1729
+ className: "text-description mb-2"
1730
+ }, t("empty-readonly-ref-field.label")) : /* @__PURE__ */ React11.createElement(DxAnchor, {
1628
1731
  key: item.id,
1629
1732
  dxn: item.id,
1630
1733
  rootclassname: "me-1"
1631
- }, item.label) : /* @__PURE__ */ React11.createElement(ObjectPicker.Root, null, /* @__PURE__ */ React11.createElement(ObjectPicker.Trigger, {
1734
+ }, item.label) : /* @__PURE__ */ React11.createElement(ObjectPicker.Root, {
1735
+ open,
1736
+ onOpenChange: setOpen
1737
+ }, /* @__PURE__ */ React11.createElement(ObjectPicker.Trigger, {
1632
1738
  asChild: true,
1633
1739
  classNames: "p-0"
1634
1740
  }, item ? /* @__PURE__ */ React11.createElement("div", {
1635
- className: "flex gap-2 w-full"
1741
+ className: "flex gap-form-gap w-full"
1636
1742
  }, /* @__PURE__ */ React11.createElement(Input6.Root, {
1637
1743
  key: item.id
1638
1744
  }, /* @__PURE__ */ React11.createElement(Input6.TextInput, {
1639
1745
  value: item.label,
1640
1746
  readOnly: true,
1641
1747
  classNames: "w-full"
1642
- }))) : /* @__PURE__ */ React11.createElement(Button, {
1643
- classNames: "w-full text-start gap-2"
1748
+ }))) : /* @__PURE__ */ React11.createElement(Button2, {
1749
+ classNames: "w-full text-start gap-form-gap"
1644
1750
  }, /* @__PURE__ */ React11.createElement("div", {
1645
- role: "none",
1646
1751
  className: "grow overflow-hidden"
1647
1752
  }, /* @__PURE__ */ React11.createElement("span", {
1648
- className: "flex truncate text-description"
1649
- }, placeholder ?? t("ref field placeholder"))), /* @__PURE__ */ React11.createElement(Icon2, {
1753
+ className: "truncate text-description"
1754
+ }, placeholder ?? t("ref-field.placeholder"))), /* @__PURE__ */ React11.createElement(Icon3, {
1650
1755
  size: 3,
1651
1756
  icon: "ph--caret-down--bold"
1652
1757
  }))), /* @__PURE__ */ React11.createElement(ObjectPicker.Portal, null, /* @__PURE__ */ React11.createElement(ObjectPicker.Content, {
1653
1758
  classNames: "dx-card-popover-width",
1654
1759
  options,
1655
1760
  selectedIds,
1656
- createSchema: createSchema && omitId(createSchema),
1761
+ // Strip hidden (`FormInputAnnotation.set(false)`) fields so the
1762
+ // form's validator doesn't reject required-but-hidden fields
1763
+ // such as backing-object refs supplied by a `FactoryAnnotation`.
1764
+ createSchema: createSchema && omitHiddenFormFields(omitId(createSchema)),
1657
1765
  createOptionLabel,
1658
1766
  createOptionIcon,
1659
1767
  createInitialValuePath,
1768
+ createFieldMap: createFieldMap3,
1660
1769
  onCreate: handleCreate,
1661
1770
  onSelect: handleSelect
1662
1771
  })))), layout === "full" && /* @__PURE__ */ React11.createElement(Input6.DescriptionAndValidation, null, error));
@@ -1698,20 +1807,21 @@ var SelectField = ({ type, readonly, label, layout, placeholder, options, getSta
1698
1807
  };
1699
1808
 
1700
1809
  // src/components/Form/fields/SelectOptionField.tsx
1701
- import React13, { useCallback as useCallback11, useEffect as useEffect6, useRef as useRef3, useState as useState4 } from "react";
1810
+ import React13, { useCallback as useCallback11, useEffect as useEffect4, useRef as useRef2, useState as useState5 } from "react";
1702
1811
  import { PublicKey } from "@dxos/keys";
1703
- import { IconButton as IconButton3, Input as Input8, Tag, useTranslation as useTranslation7 } from "@dxos/react-ui";
1812
+ import { IconButton as IconButton3, Input as Input8, Tag, useTranslation as useTranslation8 } from "@dxos/react-ui";
1704
1813
  import { List } from "@dxos/react-ui-list";
1705
1814
  import { HuePicker } from "@dxos/react-ui-pickers";
1706
- import { hues, osTranslations, subtleHover } from "@dxos/ui-theme";
1815
+ import { hues, osTranslations } from "@dxos/ui-theme";
1816
+ import { translationKey as translationKey8 } from "#translations";
1707
1817
  var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueChange }) => {
1708
- const { t } = useTranslation7(translationKey);
1818
+ const { t } = useTranslation8(translationKey8);
1709
1819
  const { status, error } = getStatus();
1710
- const [selected, setSelectedId] = useState4(null);
1711
- const [isNewOption, setIsNewOption] = useState4(false);
1712
- const inputRef = useRef3(null);
1820
+ const [selected, setSelectedId] = useState5(null);
1821
+ const [isNewOption, setIsNewOption] = useState5(false);
1822
+ const inputRef = useRef2(null);
1713
1823
  const options = getValue();
1714
- useEffect6(() => {
1824
+ useEffect4(() => {
1715
1825
  if (options === void 0) {
1716
1826
  onValueChange(type, []);
1717
1827
  }
@@ -1802,7 +1912,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1802
1912
  type,
1803
1913
  onValueChange
1804
1914
  ]);
1805
- useEffect6(() => {
1915
+ useEffect4(() => {
1806
1916
  if (selected && isNewOption && inputRef.current) {
1807
1917
  inputRef.current.focus();
1808
1918
  setIsNewOption(false);
@@ -1817,9 +1927,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1817
1927
  error,
1818
1928
  readonly,
1819
1929
  label
1820
- }), /* @__PURE__ */ React13.createElement("div", {
1821
- role: "none"
1822
- }, options && /* @__PURE__ */ React13.createElement(List.Root, {
1930
+ }), /* @__PURE__ */ React13.createElement("div", null, options && /* @__PURE__ */ React13.createElement(List.Root, {
1823
1931
  items: options,
1824
1932
  isItem: (_item) => true,
1825
1933
  onMove: readonly ? void 0 : handleMove,
@@ -1832,10 +1940,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1832
1940
  }, /* @__PURE__ */ React13.createElement(List.Item, {
1833
1941
  role: "button",
1834
1942
  item,
1835
- classNames: [
1836
- subtleHover,
1837
- "flex flex-col cursor-pointer rounded-xs"
1838
- ],
1943
+ classNames: "flex flex-col cursor-pointer rounded-xs dx-hover",
1839
1944
  "aria-expanded": selected === item.id
1840
1945
  }, /* @__PURE__ */ React13.createElement("div", {
1841
1946
  className: "flex items-center"
@@ -1849,20 +1954,20 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1849
1954
  }, item.title || "\u200B")), /* @__PURE__ */ React13.createElement(IconButton3, {
1850
1955
  iconOnly: true,
1851
1956
  variant: "ghost",
1852
- label: t(selected === item.id ? "collapse label" : "expand label", {
1957
+ label: t(selected === item.id ? "collapse.label" : "expand.label", {
1853
1958
  ns: osTranslations
1854
1959
  }),
1855
1960
  icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
1856
1961
  onClick: () => handleClick(item.id)
1857
1962
  })), selected === item.id && /* @__PURE__ */ React13.createElement("div", {
1858
- className: "flex flex-col p-form-padding gap-1 dx-density-fine"
1963
+ className: "flex flex-col p-form-padding gap-form-gap dx-density-fine"
1859
1964
  }, /* @__PURE__ */ React13.createElement(Input8.Label, {
1860
1965
  classNames: "text-xs"
1861
- }, t("select option label")), /* @__PURE__ */ React13.createElement("div", {
1862
- className: "grid grid-cols-[1fr_min-content_min-content] gap-1"
1966
+ }, t("select-option.label")), /* @__PURE__ */ React13.createElement("div", {
1967
+ className: "grid grid-cols-[1fr_min-content_min-content] gap-form-gap"
1863
1968
  }, /* @__PURE__ */ React13.createElement(Input8.TextInput, {
1864
1969
  disabled: !!readonly,
1865
- placeholder: t("select option label placeholder"),
1970
+ placeholder: t("select-option-label.placeholder"),
1866
1971
  ref: selected === item.id ? inputRef : void 0,
1867
1972
  value: item.title,
1868
1973
  onChange: handleTitleChange(item.id),
@@ -1876,12 +1981,12 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1876
1981
  disabled: !!readonly,
1877
1982
  icon: "ph--trash--fill",
1878
1983
  iconOnly: true,
1879
- label: t("select option delete"),
1984
+ label: t("select-option-delete.button"),
1880
1985
  onClick: () => handleDelete(item.id)
1881
1986
  })))))), /* @__PURE__ */ React13.createElement(IconButton3, {
1882
1987
  variant: "ghost",
1883
1988
  icon: "ph--plus--regular",
1884
- label: t("select option add"),
1989
+ label: t("select-option-add.button"),
1885
1990
  onClick: handleAdd,
1886
1991
  disabled: !!readonly,
1887
1992
  classNames: "w-full"
@@ -1891,7 +1996,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1891
1996
  // src/components/Form/fields/TextField.tsx
1892
1997
  import React14, { useCallback as useCallback12 } from "react";
1893
1998
  import { Input as Input9 } from "@dxos/react-ui";
1894
- var TextField = ({ type, readonly, placeholder, onValueChange, onBlur, ...props }) => {
1999
+ var TextField = ({ type, readonly, placeholder, onBlur, onValueChange, ...props }) => {
1895
2000
  const handleChange = useCallback12((event) => onValueChange(type, event.target.value), [
1896
2001
  type,
1897
2002
  onValueChange
@@ -1904,8 +2009,8 @@ var TextField = ({ type, readonly, placeholder, onValueChange, onBlur, ...props
1904
2009
  disabled: !!readonly,
1905
2010
  placeholder,
1906
2011
  value: value3,
1907
- onChange: handleChange,
1908
- onBlur
2012
+ onBlur,
2013
+ onChange: handleChange
1909
2014
  }));
1910
2015
  };
1911
2016
 
@@ -1933,7 +2038,7 @@ var TextAreaField = ({ type, readonly, placeholder, onValueChange, onBlur, ...pr
1933
2038
  // src/components/Form/fields/TupleField.tsx
1934
2039
  import React16 from "react";
1935
2040
  import { Input as Input11 } from "@dxos/react-ui";
1936
- import { mx as mx4 } from "@dxos/ui-theme";
2041
+ import { mx as mx2 } from "@dxos/ui-theme";
1937
2042
  import { safeParseFloat as safeParseFloat3 } from "@dxos/util";
1938
2043
  var gridCols = [
1939
2044
  "grid-cols-1",
@@ -1951,7 +2056,7 @@ var TupleField = ({ binding, type, readonly, label, getStatus, getValue, onValue
1951
2056
  readonly,
1952
2057
  label
1953
2058
  }), /* @__PURE__ */ React16.createElement("div", {
1954
- className: mx4("grid gap-2", gridCols[binding.length - 1])
2059
+ className: mx2("grid gap-form-gap", gridCols[binding.length - 1])
1955
2060
  }, binding.map((prop) => /* @__PURE__ */ React16.createElement(Input11.TextInput, {
1956
2061
  key: prop,
1957
2062
  type: "number",
@@ -1970,13 +2075,13 @@ var TupleField = ({ binding, type, readonly, label, getStatus, getValue, onValue
1970
2075
  // src/components/FieldEditor/FieldEditor.tsx
1971
2076
  var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
1972
2077
  var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCancel }) => {
1973
- const { t } = useTranslation8(translationKey);
1974
- const [props, setProps] = useState5(projection.getFieldProjection(field.id).props);
1975
- useEffect7(() => setProps(projection.getFieldProjection(field.id).props), [
2078
+ const { t } = useTranslation9(translationKey9);
2079
+ const [props, setProps] = useState6(projection.getFieldProjection(field.id).props);
2080
+ useEffect5(() => setProps(projection.getFieldProjection(field.id).props), [
1976
2081
  field,
1977
2082
  projection
1978
2083
  ]);
1979
- const [schemas, setSchemas] = useState5([]);
2084
+ const [schemas, setSchemas] = useState6([]);
1980
2085
  useAsyncEffect(async () => {
1981
2086
  if (!registry) {
1982
2087
  return;
@@ -1990,22 +2095,22 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
1990
2095
  }, [
1991
2096
  registry
1992
2097
  ]);
1993
- const [referenceSchema, setReferenceSchema] = useState5();
1994
- useEffect7(() => {
2098
+ const [referenceSchema, setReferenceSchema] = useState6();
2099
+ useEffect5(() => {
1995
2100
  setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
1996
2101
  }, [
1997
2102
  schemas,
1998
2103
  props?.referenceSchema
1999
2104
  ]);
2000
- const [{ fieldSchema }, setFieldSchema] = useState5({
2105
+ const [{ fieldSchema }, setFieldSchema] = useState6({
2001
2106
  fieldSchema: getFormatSchema(props?.format)
2002
2107
  });
2003
- const fieldMap = useMemo7(() => ({
2108
+ const fieldMap = useMemo8(() => ({
2004
2109
  ["format"]: (props2) => /* @__PURE__ */ React17.createElement(SelectField, {
2005
2110
  ...props2,
2006
2111
  options: FormatEnums.filter((value3) => value3 !== Format4.TypeFormat.None).map((value3) => ({
2007
2112
  value: value3,
2008
- label: t(`format ${value3}`)
2113
+ label: t(`format.${value3}.label`)
2009
2114
  }))
2010
2115
  }),
2011
2116
  ["referenceSchema"]: (props2) => /* @__PURE__ */ React17.createElement(SelectField, {
@@ -2079,7 +2184,7 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
2079
2184
  ]);
2080
2185
  const handleSave = useCallback14((props2) => {
2081
2186
  if (view) {
2082
- Obj2.change(view, () => {
2187
+ Obj3.update(view, () => {
2083
2188
  projection.setFieldProjection({
2084
2189
  field,
2085
2190
  props: props2
@@ -2107,12 +2212,7 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
2107
2212
  if (!fieldSchema) {
2108
2213
  log2.warn("invalid format", {
2109
2214
  props
2110
- }, {
2111
- F: __dxlog_file2,
2112
- L: 172,
2113
- S: void 0,
2114
- C: (f, a) => f(...a)
2115
- });
2215
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 156, S: void 0 });
2116
2216
  return null;
2117
2217
  }
2118
2218
  return /* @__PURE__ */ React17.createElement(Form.Root, {
@@ -2134,160 +2234,487 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
2134
2234
  }, /* @__PURE__ */ React17.createElement(Form.Content, null, /* @__PURE__ */ React17.createElement(Form.FieldSet, null), /* @__PURE__ */ React17.createElement(Form.Actions, null)));
2135
2235
  };
2136
2236
 
2137
- // src/components/Settings/Settings.tsx
2138
- import React18 from "react";
2139
- import { Button as Button2, Input as Input12, ScrollArea as ScrollArea2, toLocalizedString, useTranslation as useTranslation9 } from "@dxos/react-ui";
2140
- import { mx as mx5 } from "@dxos/ui-theme";
2141
- var SETTINGS_ROOT_NAME = "Settings.Root";
2142
- var SETTINGS_SECTION_NAME = "Settings.Section";
2143
- var SETTINGS_SECTION_HEADING_NAME = "Settings.SectionHeading";
2144
- var SETTINGS_GROUP_NAME = "Settings.Group";
2145
- var SETTINGS_GROUP_BUTTON_NAME = "Settings.GroupButton";
2146
- var SETTINGS_CONTAINER_NAME = "Settings.Container";
2147
- var SETTINGS_FRAME_NAME = "Settings.Frame";
2148
- var SETTINGS_FRAME_ITEM_NAME = "Settings.FrameItem";
2149
- var SETTINGS_ITEM_NAME = "Settings.Item";
2150
- var SETTINGS_ITEM_INPUT_NAME = "Settings.ItemInput";
2151
- var styles = {
2152
- title: "pb-trim-md text-base-surface-text text-lg",
2153
- description: "text-base text-description",
2154
- grid: "grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-x-trim-lg"
2155
- };
2156
- var SettingsRoot = ({ children }) => {
2157
- return /* @__PURE__ */ React18.createElement(ScrollArea2.Root, {
2158
- orientation: "vertical",
2159
- className: "dx-article"
2160
- }, /* @__PURE__ */ React18.createElement(ScrollArea2.Viewport, {
2161
- classNames: "p-trim-md"
2162
- }, children));
2163
- };
2164
- SettingsRoot.displayName = SETTINGS_ROOT_NAME;
2165
- var SettingsSection = ({ title, description, children }) => {
2166
- return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(SettingsSectionHeading, {
2167
- title,
2168
- description
2169
- }), /* @__PURE__ */ React18.createElement("div", {
2170
- className: "w-full pt-trim-md space-y-trim-md"
2171
- }, children));
2172
- };
2173
- SettingsSection.displayName = SETTINGS_SECTION_NAME;
2174
- var SettingsSectionHeading = ({ title, description }) => {
2175
- const { t } = useTranslation9(translationKey);
2176
- return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("h2", {
2177
- className: "px-trim-md mt-trim-md mb-trim-md text-xl"
2178
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React18.createElement("p", {
2179
- className: "px-trim-md my-trim-md text-description"
2180
- }, toLocalizedString(description, t)));
2237
+ // src/components/ObjectForm/ObjectForm.tsx
2238
+ import * as Schema3 from "effect/Schema";
2239
+ import React18, { useCallback as useCallback15, useMemo as useMemo9 } from "react";
2240
+ import { DXN as DXN2, Obj as Obj4, Ref as Ref4, Tag as Tag2, Type as Type2 } from "@dxos/echo";
2241
+ import { splitJsonPath } from "@dxos/echo/internal";
2242
+ import { invariant } from "@dxos/invariant";
2243
+ import { HuePicker as HuePicker2 } from "@dxos/react-ui-pickers";
2244
+ import { isNonNullable } from "@dxos/util";
2245
+ import { translationKey as translationKey10 } from "#translations";
2246
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ObjectForm/ObjectForm.tsx";
2247
+ var createFieldMap = {
2248
+ hue: ({ type, label, layout, getValue, onValueChange }) => {
2249
+ const handleChange = useCallback15((nextHue) => onValueChange(type, nextHue), [
2250
+ onValueChange,
2251
+ type
2252
+ ]);
2253
+ const handleReset = useCallback15(() => onValueChange(type, void 0), [
2254
+ onValueChange,
2255
+ type
2256
+ ]);
2257
+ return /* @__PURE__ */ React18.createElement(React18.Fragment, null, layout !== "inline" && /* @__PURE__ */ React18.createElement(Form.Label, {
2258
+ label
2259
+ }), /* @__PURE__ */ React18.createElement(HuePicker2, {
2260
+ value: getValue(),
2261
+ onChange: handleChange,
2262
+ onReset: handleReset
2263
+ }));
2264
+ }
2181
2265
  };
2182
- SettingsSectionHeading.displayName = SETTINGS_SECTION_HEADING_NAME;
2183
- var SettingsGroupButton = ({ classNames, ...props }) => {
2184
- return /* @__PURE__ */ React18.createElement(Button2, {
2185
- ...props,
2186
- classNames: [
2187
- "md:col-span-2",
2188
- classNames
2189
- ]
2190
- });
2266
+ var ObjectForm = ({ object, schema }) => {
2267
+ const db = Obj4.getDatabase(object);
2268
+ const meta = Obj4.getMeta(object);
2269
+ const tags = (meta.tags ?? []).map((tag) => db?.makeRef(DXN2.parse(tag))).filter(isNonNullable);
2270
+ const values = useMemo9(() => ({
2271
+ tags,
2272
+ ...object
2273
+ }), [
2274
+ object,
2275
+ tags
2276
+ ]);
2277
+ const formSchema = useMemo9(() => omitId(Schema3.Struct({
2278
+ tags: Schema3.Array(Ref4.Ref(Tag2.Tag)).pipe(Schema3.optional)
2279
+ }).pipe(Schema3.extend(schema))), [
2280
+ schema
2281
+ ]);
2282
+ const handleCreate = useCallback15((schema2, values2) => {
2283
+ invariant(db, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 49, S: void 0, A: ["db", ""] });
2284
+ invariant(Type2.isObjectSchema(schema2), void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 50, S: void 0, A: ["Type.isObjectSchema(schema)", ""] });
2285
+ const newObject = db.add(Obj4.make(schema2, values2));
2286
+ if (Obj4.instanceOf(Tag2.Tag, newObject)) {
2287
+ Obj4.update(object, (object2) => {
2288
+ Obj4.getMeta(object2).tags = [
2289
+ ...Obj4.getMeta(object2).tags ?? [],
2290
+ Obj4.getDXN(newObject).toString()
2291
+ ];
2292
+ });
2293
+ }
2294
+ }, []);
2295
+ const handleChange = useCallback15(({ tags: tags2, ...values2 }, { isValid, changed }) => {
2296
+ if (!isValid) {
2297
+ return;
2298
+ }
2299
+ const changedPaths = Object.keys(changed).filter((path) => changed[path]);
2300
+ const hasTagsChange = changedPaths.some((path) => splitJsonPath(path)[0] === "tags");
2301
+ if (hasTagsChange) {
2302
+ Obj4.update(object, (object2) => {
2303
+ Obj4.getMeta(object2).tags = tags2?.map((tag) => tag.dxn.toString()) ?? [];
2304
+ });
2305
+ }
2306
+ const nonTagPaths = changedPaths.filter((path) => splitJsonPath(path)[0] !== "tags");
2307
+ if (nonTagPaths.length > 0) {
2308
+ Obj4.update(object, () => {
2309
+ for (const path of nonTagPaths) {
2310
+ const parts = splitJsonPath(path);
2311
+ const value3 = Obj4.getValue(values2, parts);
2312
+ Obj4.setValue(object, parts, value3);
2313
+ }
2314
+ });
2315
+ }
2316
+ }, [
2317
+ object
2318
+ ]);
2319
+ return /* @__PURE__ */ React18.createElement(Form.Root, {
2320
+ schema: formSchema,
2321
+ defaultValues: values,
2322
+ createTypename: Type2.getTypename(Tag2.Tag),
2323
+ createOptionIcon: "ph--plus--regular",
2324
+ createOptionLabel: [
2325
+ "add-tag.label",
2326
+ {
2327
+ ns: translationKey10
2328
+ }
2329
+ ],
2330
+ createInitialValuePath: "label",
2331
+ createFieldMap,
2332
+ db,
2333
+ onValuesChanged: handleChange,
2334
+ onCreate: handleCreate
2335
+ }, /* @__PURE__ */ React18.createElement(Form.Viewport, null, /* @__PURE__ */ React18.createElement(Form.Content, null, /* @__PURE__ */ React18.createElement(Form.FieldSet, null))));
2191
2336
  };
2192
- SettingsGroupButton.displayName = SETTINGS_GROUP_BUTTON_NAME;
2193
- var SettingsGroup = ({ children, classNames }) => /* @__PURE__ */ React18.createElement("div", {
2194
- role: "none",
2195
- className: mx5("group space-y-trim-md", classNames)
2196
- }, children);
2197
- SettingsGroup.displayName = SETTINGS_GROUP_NAME;
2198
- var SettingsFrame = ({ children }) => /* @__PURE__ */ React18.createElement("div", {
2199
- role: "none",
2200
- className: "p-trim-md border border-separator rounded-md"
2201
- }, children);
2202
- SettingsFrame.displayName = SETTINGS_FRAME_NAME;
2203
- var SettingsFrameItem = ({ title, description, children }) => {
2204
- const { t } = useTranslation9(translationKey);
2205
- return /* @__PURE__ */ React18.createElement("div", {
2206
- role: "group",
2207
- className: "min-w-0"
2208
- }, /* @__PURE__ */ React18.createElement("h3", {
2209
- className: "text-lg mb-2"
2210
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React18.createElement("p", {
2211
- className: "my-trim-sm md:mb-0 text-description"
2212
- }, toLocalizedString(description, t)), children);
2337
+
2338
+ // src/components/ObjectProperties/ObjectProperties.tsx
2339
+ import * as Function from "effect/Function";
2340
+ import * as Option5 from "effect/Option";
2341
+ import * as Schema4 from "effect/Schema";
2342
+ import React19, { useCallback as useCallback16, useMemo as useMemo10 } from "react";
2343
+ import { DXN as DXN3, Obj as Obj5, Ref as Ref5, Tag as Tag3, Type as Type3 } from "@dxos/echo";
2344
+ import { splitJsonPath as splitJsonPath2 } from "@dxos/echo/internal";
2345
+ import { invariant as invariant2 } from "@dxos/invariant";
2346
+ import { HuePicker as HuePicker3 } from "@dxos/react-ui-pickers";
2347
+ import { FactoryAnnotation } from "@dxos/schema";
2348
+ import { composable as composable2, composableProps as composableProps2 } from "@dxos/ui-theme";
2349
+ import { isNonNullable as isNonNullable2 } from "@dxos/util";
2350
+ import { translationKey as translationKey11 } from "#translations";
2351
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ObjectProperties/ObjectProperties.tsx";
2352
+ var ObjectProperties = composable2(({ children, object, ...props }, forwardedRef) => {
2353
+ const db = Obj5.getDatabase(object);
2354
+ const meta = Obj5.getMeta(object);
2355
+ const tags = (meta.tags ?? []).map((tag) => db?.makeRef(DXN3.parse(tag))).filter(isNonNullable2);
2356
+ const values = useMemo10(() => ({
2357
+ tags,
2358
+ ...object
2359
+ }), [
2360
+ object,
2361
+ tags
2362
+ ]);
2363
+ const formSchema = useMemo10(() => {
2364
+ return Function.pipe(Obj5.getSchema(object), Option5.fromNullable, Option5.map((schema) => omitId(BaseSchema.pipe(Schema4.extend(schema)))), Option5.getOrUndefined);
2365
+ }, [
2366
+ object
2367
+ ]);
2368
+ const handleCreate = useCallback16((schema, values2) => {
2369
+ invariant2(db, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 45, S: void 0, A: ["db", ""] });
2370
+ invariant2(Type3.isObjectSchema(schema), void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 46, S: void 0, A: ["Type.isObjectSchema(schema)", ""] });
2371
+ const factory = Option5.getOrUndefined(FactoryAnnotation.get(schema));
2372
+ const newObject = factory ? factory(values2) : Obj5.make(schema, values2);
2373
+ return db.add(newObject);
2374
+ }, [
2375
+ db
2376
+ ]);
2377
+ const handleChange = useCallback16(({ tags: tags2, ...values2 }, { isValid, changed }) => {
2378
+ if (!isValid) {
2379
+ return;
2380
+ }
2381
+ const changedPaths = Object.keys(changed).filter((path) => changed[path]);
2382
+ const hasTagsChange = changedPaths.some((path) => splitJsonPath2(path)[0] === "tags");
2383
+ if (hasTagsChange) {
2384
+ Obj5.update(object, (object2) => {
2385
+ Obj5.getMeta(object2).tags = tags2?.map((tag) => tag.dxn.toString()) ?? [];
2386
+ });
2387
+ }
2388
+ const nonTagPaths = changedPaths.filter((path) => splitJsonPath2(path)[0] !== "tags");
2389
+ if (nonTagPaths.length > 0) {
2390
+ Obj5.update(object, () => {
2391
+ for (const path of nonTagPaths) {
2392
+ const parts = splitJsonPath2(path);
2393
+ const value3 = Obj5.getValue(values2, parts);
2394
+ Obj5.setValue(object, parts, value3);
2395
+ }
2396
+ });
2397
+ }
2398
+ }, [
2399
+ object
2400
+ ]);
2401
+ if (!formSchema) {
2402
+ return null;
2403
+ }
2404
+ return /* @__PURE__ */ React19.createElement(Form.Root, {
2405
+ schema: formSchema,
2406
+ defaultValues: values,
2407
+ createTypename: Type3.getTypename(Tag3.Tag),
2408
+ createOptionIcon: "ph--plus--regular",
2409
+ createOptionLabel: [
2410
+ "add-tag.label",
2411
+ {
2412
+ ns: translationKey11
2413
+ }
2414
+ ],
2415
+ createInitialValuePath: "label",
2416
+ createFieldMap: createFieldMap2,
2417
+ db,
2418
+ onValuesChanged: handleChange,
2419
+ onCreate: handleCreate
2420
+ }, /* @__PURE__ */ React19.createElement(Form.Viewport, {
2421
+ ...composableProps2(props),
2422
+ ref: forwardedRef
2423
+ }, /* @__PURE__ */ React19.createElement(Form.Content, null, /* @__PURE__ */ React19.createElement(Form.FieldSet, null), children)));
2424
+ });
2425
+ var createFieldMap2 = {
2426
+ hue: ({ type, label, layout, getValue, onValueChange }) => {
2427
+ const handleChange = useCallback16((nextHue) => onValueChange(type, nextHue), [
2428
+ onValueChange,
2429
+ type
2430
+ ]);
2431
+ const handleReset = useCallback16(() => onValueChange(type, void 0), [
2432
+ onValueChange,
2433
+ type
2434
+ ]);
2435
+ return /* @__PURE__ */ React19.createElement(React19.Fragment, null, layout !== "inline" && /* @__PURE__ */ React19.createElement(Form.Label, {
2436
+ label
2437
+ }), /* @__PURE__ */ React19.createElement(HuePicker3, {
2438
+ value: getValue(),
2439
+ onChange: handleChange,
2440
+ onReset: handleReset
2441
+ }));
2442
+ }
2213
2443
  };
2214
- SettingsFrameItem.displayName = SETTINGS_FRAME_ITEM_NAME;
2215
- var SettingsContainer = ({ classNames, children }) => {
2216
- return /* @__PURE__ */ React18.createElement("div", {
2217
- role: "none",
2218
- className: mx5([
2219
- "dx-article",
2220
- "*:first:mt-0! *:last:mb-0! px-trim-md py-trim-md",
2221
- "border border-separator rounded-md",
2222
- classNames
2223
- ])
2444
+ var BaseSchema = Schema4.Struct({
2445
+ tags: Schema4.Array(Ref5.Ref(Tag3.Tag)).pipe(Schema4.optional)
2446
+ });
2447
+
2448
+ // src/components/Settings/Settings.tsx
2449
+ import React22 from "react";
2450
+ import { ScrollArea as ScrollArea2, toLocalizedString as toLocalizedString2, useTranslation as useTranslation11 } from "@dxos/react-ui";
2451
+ import { composable as composable3, composableProps as composableProps3, mx as mx4 } from "@dxos/ui-theme";
2452
+ import { translationKey as translationKey13 } from "#translations";
2453
+
2454
+ // src/components/Settings/SettingsFieldSet.tsx
2455
+ import * as SchemaAST5 from "effect/SchemaAST";
2456
+ import * as String3 from "effect/String";
2457
+ import React21, { useCallback as useCallback17, useMemo as useMemo11 } from "react";
2458
+ import { getAnnotation as getAnnotation3 } from "@dxos/effect";
2459
+ import { Input as Input13, Select as Select2 } from "@dxos/react-ui";
2460
+
2461
+ // src/components/Settings/SettingsItem.tsx
2462
+ import React20 from "react";
2463
+ import { Input as Input12, toLocalizedString, useTranslation as useTranslation10 } from "@dxos/react-ui";
2464
+ import { mx as mx3 } from "@dxos/ui-theme";
2465
+ import { translationKey as translationKey12 } from "#translations";
2466
+ var SETTINGS_PANEL_NAME = "Settings.Panel";
2467
+ var SETTINGS_ITEM_NAME = "Settings.Item";
2468
+ var SettingsPanel = ({ classNames, children }) => {
2469
+ return /* @__PURE__ */ React20.createElement("div", {
2470
+ className: mx3("flex flex-col gap-3 p-trim-md border border-separator rounded-sm", classNames)
2224
2471
  }, children);
2225
2472
  };
2226
- SettingsContainer.displayName = SETTINGS_CONTAINER_NAME;
2473
+ SettingsPanel.displayName = SETTINGS_PANEL_NAME;
2227
2474
  var SettingsItem = ({ title, description = "", children }) => {
2228
- const { t } = useTranslation9(translationKey);
2229
- return /* @__PURE__ */ React18.createElement(SettingsContainer, {
2230
- classNames: styles.grid
2231
- }, /* @__PURE__ */ React18.createElement("h3", {
2232
- className: mx5(styles.title, "md:col-span-2")
2233
- }, toLocalizedString(title, t)), /* @__PURE__ */ React18.createElement("p", {
2234
- className: styles.description
2235
- }, toLocalizedString(description, t)), /* @__PURE__ */ React18.createElement("div", {
2236
- role: "none",
2237
- className: "overflow-hidden text-end py-1"
2238
- }, children));
2475
+ const { t } = useTranslation10(translationKey12);
2476
+ return /* @__PURE__ */ React20.createElement(Input12.Root, null, /* @__PURE__ */ React20.createElement(SettingsPanel, {
2477
+ classNames: "grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-x-trim-lg gap-y-0"
2478
+ }, /* @__PURE__ */ React20.createElement(Input12.Label, {
2479
+ classNames: "pb-trim-md text-base-foreground text-lg md:col-span-2"
2480
+ }, toLocalizedString(title, t)), /* @__PURE__ */ React20.createElement(Input12.DescriptionAndValidation, null, /* @__PURE__ */ React20.createElement(Input12.Description, {
2481
+ classNames: "text-base text-description"
2482
+ }, toLocalizedString(description, t))), /* @__PURE__ */ React20.createElement("div", {
2483
+ className: "text-end py-1"
2484
+ }, children)));
2239
2485
  };
2240
2486
  SettingsItem.displayName = SETTINGS_ITEM_NAME;
2241
- var SettingsItemInput = ({ title, description = "", children }) => {
2242
- const { t } = useTranslation9(translationKey);
2243
- return /* @__PURE__ */ React18.createElement(Input12.Root, null, /* @__PURE__ */ React18.createElement(SettingsContainer, {
2244
- classNames: styles.grid
2245
- }, /* @__PURE__ */ React18.createElement(Input12.Label, {
2246
- classNames: mx5(styles.title, "md:col-span-2")
2247
- }, toLocalizedString(title, t)), /* @__PURE__ */ React18.createElement(Input12.DescriptionAndValidation, null, /* @__PURE__ */ React18.createElement(Input12.Description, {
2248
- classNames: styles.description
2249
- }, toLocalizedString(description, t))), /* @__PURE__ */ React18.createElement("div", {
2250
- role: "none",
2251
- className: "text-end py-1"
2487
+
2488
+ // src/components/Settings/SettingsFieldSet.tsx
2489
+ var SettingsFieldSet = ({ schema, values, onValuesChanged, readonly, fieldMap, visible, sort, pathPrefix = "" }) => {
2490
+ const properties = useMemo11(() => {
2491
+ const props = getFormProperties(schema.ast);
2492
+ if (!sort) {
2493
+ return props;
2494
+ }
2495
+ const rank = (name) => {
2496
+ const idx = sort.indexOf(name);
2497
+ return idx === -1 ? Number.POSITIVE_INFINITY : idx;
2498
+ };
2499
+ return [
2500
+ ...props
2501
+ ].sort(({ name: a }, { name: b }) => rank(a.toString()) - rank(b.toString()));
2502
+ }, [
2503
+ schema,
2504
+ sort
2505
+ ]);
2506
+ const handleChange = useCallback17((name, value3) => {
2507
+ onValuesChanged?.({
2508
+ ...values,
2509
+ [name]: value3
2510
+ });
2511
+ }, [
2512
+ values,
2513
+ onValuesChanged
2514
+ ]);
2515
+ return /* @__PURE__ */ React21.createElement(React21.Fragment, null, properties.map((property) => {
2516
+ const name = property.name.toString();
2517
+ const path = pathPrefix ? `${pathPrefix}.${name}` : name;
2518
+ if (visible && !visible(path, values)) {
2519
+ return null;
2520
+ }
2521
+ const entry = fieldMap?.[name];
2522
+ return /* @__PURE__ */ React21.createElement(SettingsFieldItem, {
2523
+ key: name,
2524
+ path,
2525
+ property,
2526
+ value: values[name],
2527
+ onChange: (value3) => handleChange(name, value3),
2528
+ readonly,
2529
+ customField: typeof entry === "function" ? entry : void 0,
2530
+ nestedFieldMap: typeof entry === "object" ? entry : void 0,
2531
+ visible,
2532
+ sort
2533
+ });
2534
+ }));
2535
+ };
2536
+ SettingsFieldSet.displayName = "Settings.FieldSet";
2537
+ var SettingsFieldItem = ({ property, path, value: value3, onChange, readonly, customField, nestedFieldMap, visible, sort }) => {
2538
+ const { type } = property;
2539
+ const name = property.name.toString();
2540
+ const title = getAnnotation3(SchemaAST5.TitleAnnotationId)(type) ?? String3.capitalize(name);
2541
+ const description = getAnnotation3(SchemaAST5.DescriptionAnnotationId)(type);
2542
+ if (customField) {
2543
+ const CustomField = customField;
2544
+ return /* @__PURE__ */ React21.createElement(SettingsItem, {
2545
+ title,
2546
+ description
2547
+ }, /* @__PURE__ */ React21.createElement(CustomField, {
2548
+ value: value3,
2549
+ onChange,
2550
+ readonly
2551
+ }));
2552
+ }
2553
+ const fieldType = detectFieldType(type);
2554
+ switch (fieldType) {
2555
+ case "struct":
2556
+ return /* @__PURE__ */ React21.createElement(SettingsFieldSet, {
2557
+ schema: {
2558
+ ast: type
2559
+ },
2560
+ values: value3 ?? {},
2561
+ onValuesChanged: onChange,
2562
+ readonly,
2563
+ fieldMap: nestedFieldMap,
2564
+ visible,
2565
+ sort,
2566
+ pathPrefix: path
2567
+ });
2568
+ case "boolean":
2569
+ return /* @__PURE__ */ React21.createElement(SettingsItem, {
2570
+ title,
2571
+ description
2572
+ }, /* @__PURE__ */ React21.createElement(Input13.Switch, {
2573
+ disabled: readonly,
2574
+ checked: !!value3,
2575
+ onCheckedChange: (checked) => onChange(!!checked)
2576
+ }));
2577
+ case "select": {
2578
+ const options = getSelectOptionsFromAst(type) ?? [];
2579
+ return /* @__PURE__ */ React21.createElement(SettingsItem, {
2580
+ title,
2581
+ description
2582
+ }, /* @__PURE__ */ React21.createElement(Select2.Root, {
2583
+ disabled: readonly,
2584
+ value: value3 == null ? "" : globalThis.String(value3),
2585
+ onValueChange: (selected) => {
2586
+ const matched = options.find((option) => globalThis.String(option.value) === selected);
2587
+ onChange(matched?.value ?? selected);
2588
+ }
2589
+ }, /* @__PURE__ */ React21.createElement(Select2.TriggerButton, {
2590
+ disabled: readonly
2591
+ }), /* @__PURE__ */ React21.createElement(Select2.Portal, null, /* @__PURE__ */ React21.createElement(Select2.Content, null, /* @__PURE__ */ React21.createElement(Select2.Viewport, null, options.map((option) => /* @__PURE__ */ React21.createElement(Select2.Option, {
2592
+ key: globalThis.String(option.value),
2593
+ value: globalThis.String(option.value)
2594
+ }, option.label ?? globalThis.String(option.value)))), /* @__PURE__ */ React21.createElement(Select2.Arrow, null)))));
2595
+ }
2596
+ case "string":
2597
+ return /* @__PURE__ */ React21.createElement(SettingsItem, {
2598
+ title,
2599
+ description
2600
+ }, /* @__PURE__ */ React21.createElement(Input13.TextInput, {
2601
+ disabled: readonly,
2602
+ value: value3 ?? "",
2603
+ onChange: (event) => onChange(event.target.value)
2604
+ }));
2605
+ case "number":
2606
+ return /* @__PURE__ */ React21.createElement(SettingsItem, {
2607
+ title,
2608
+ description
2609
+ }, /* @__PURE__ */ React21.createElement(Input13.TextInput, {
2610
+ disabled: readonly,
2611
+ type: "number",
2612
+ value: value3 ?? "",
2613
+ onChange: (event) => {
2614
+ if (event.target.value === "") {
2615
+ onChange(void 0);
2616
+ return;
2617
+ }
2618
+ const parsed = Number(event.target.value);
2619
+ onChange(Number.isNaN(parsed) ? void 0 : parsed);
2620
+ }
2621
+ }));
2622
+ default:
2623
+ return null;
2624
+ }
2625
+ };
2626
+
2627
+ // src/components/Settings/Settings.tsx
2628
+ var SETTINGS_ROOT_NAME = "Settings.Root";
2629
+ var SETTINGS_VIEWPORT_NAME = "Settings.Viewport";
2630
+ var SETTINGS_SECTION_NAME = "Settings.Section";
2631
+ var SettingsRoot = ({ children, classNames }) => {
2632
+ return /* @__PURE__ */ React22.createElement("div", {
2633
+ className: mx4("flex flex-col gap-2", classNames)
2634
+ }, children);
2635
+ };
2636
+ SettingsRoot.displayName = SETTINGS_ROOT_NAME;
2637
+ var SettingsViewport = composable3(({ children, ...props }, forwardedRef) => {
2638
+ return /* @__PURE__ */ React22.createElement(ScrollArea2.Root, {
2639
+ ...composableProps3(props),
2640
+ orientation: "vertical",
2641
+ centered: true,
2642
+ thin: true,
2643
+ ref: forwardedRef
2644
+ }, /* @__PURE__ */ React22.createElement(ScrollArea2.Viewport, {
2645
+ classNames: "px-4 pointer-coarse:px-2"
2646
+ }, /* @__PURE__ */ React22.createElement("div", {
2647
+ className: "dx-document flex flex-col gap-2 py-4"
2252
2648
  }, children)));
2649
+ });
2650
+ SettingsViewport.displayName = SETTINGS_VIEWPORT_NAME;
2651
+ var SettingsSection = ({ title, description, children }) => {
2652
+ const { t } = useTranslation11(translationKey13);
2653
+ return /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement("h2", {
2654
+ className: "px-trim-md mt-trim-md text-xl"
2655
+ }, toLocalizedString2(title, t)), description && /* @__PURE__ */ React22.createElement("p", {
2656
+ className: "px-trim-md text-description"
2657
+ }, toLocalizedString2(description, t)), /* @__PURE__ */ React22.createElement("div", {
2658
+ className: "w-full pt-trim-md space-y-trim-md"
2659
+ }, children));
2253
2660
  };
2254
- SettingsItemInput.displayName = SETTINGS_ITEM_INPUT_NAME;
2661
+ SettingsSection.displayName = SETTINGS_SECTION_NAME;
2255
2662
  var Settings = {
2256
2663
  Root: SettingsRoot,
2664
+ Viewport: SettingsViewport,
2257
2665
  Section: SettingsSection,
2258
- SectionHeading: SettingsSectionHeading,
2259
- Group: SettingsGroup,
2260
- GroupButton: SettingsGroupButton,
2261
- Container: SettingsContainer,
2262
- Frame: SettingsFrame,
2263
- FrameItem: SettingsFrameItem,
2666
+ Panel: SettingsPanel,
2264
2667
  Item: SettingsItem,
2265
- ItemInput: SettingsItemInput
2668
+ FieldSet: SettingsFieldSet
2669
+ };
2670
+
2671
+ // src/components/Settings/SettingsSelectField.tsx
2672
+ import React23 from "react";
2673
+ import { Select as Select3 } from "@dxos/react-ui";
2674
+ var createSelectField = ({ options, defaultLabel = "Default" }) => {
2675
+ const normalized = options.map((option) => typeof option === "string" ? {
2676
+ value: option,
2677
+ label: option
2678
+ } : option);
2679
+ const hasDefault = defaultLabel !== null;
2680
+ const sentinel = hasDefault ? `__default__${Math.random().toString(36).slice(2)}` : "";
2681
+ return ({ value: value3, onChange, readonly }) => /* @__PURE__ */ React23.createElement(Select3.Root, {
2682
+ disabled: readonly,
2683
+ value: value3 ?? sentinel,
2684
+ onValueChange: (next) => onChange(hasDefault && next === sentinel ? void 0 : next)
2685
+ }, /* @__PURE__ */ React23.createElement(Select3.TriggerButton, {
2686
+ disabled: readonly
2687
+ }), /* @__PURE__ */ React23.createElement(Select3.Portal, null, /* @__PURE__ */ React23.createElement(Select3.Content, null, /* @__PURE__ */ React23.createElement(Select3.Viewport, null, hasDefault && /* @__PURE__ */ React23.createElement(Select3.Option, {
2688
+ value: sentinel
2689
+ }, defaultLabel), normalized.map((option) => /* @__PURE__ */ React23.createElement(Select3.Option, {
2690
+ key: option.value,
2691
+ value: option.value
2692
+ }, option.label ?? option.value))), /* @__PURE__ */ React23.createElement(Select3.Arrow, null))));
2266
2693
  };
2267
2694
 
2268
2695
  // src/components/ViewEditor/ViewEditor.tsx
2269
2696
  import { RegistryContext } from "@effect-atom/atom-react";
2270
- import * as Array2 from "effect/Array";
2697
+ import * as Array4 from "effect/Array";
2271
2698
  import * as Match2 from "effect/Match";
2272
- import * as Option4 from "effect/Option";
2273
- import * as Schema3 from "effect/Schema";
2274
- import React19, { forwardRef as forwardRef3, useCallback as useCallback15, useContext, useImperativeHandle, useMemo as useMemo8, useState as useState6 } from "react";
2275
- import { Entity as Entity2, Feed, Filter as Filter2, Format as Format5, Obj as Obj3, Query, QueryAST, Ref as Ref3 } from "@dxos/echo";
2276
- import { View } from "@dxos/echo";
2699
+ import * as Option6 from "effect/Option";
2700
+ import * as Schema5 from "effect/Schema";
2701
+ import React24, { forwardRef as forwardRef2, useCallback as useCallback18, useContext, useImperativeHandle, useMemo as useMemo12, useState as useState7 } from "react";
2702
+ import { Entity as Entity2, Feed, Filter as Filter2, Format as Format5, Obj as Obj6, Query, QueryAST, Ref as Ref6, View } from "@dxos/echo";
2277
2703
  import { EchoSchema, isMutable, toJsonSchema } from "@dxos/echo/internal";
2278
- import { invariant } from "@dxos/invariant";
2704
+ import { invariant as invariant3 } from "@dxos/invariant";
2279
2705
  import { useObject, useQuery as useQuery2 } from "@dxos/react-client/echo";
2280
- import { IconButton as IconButton4, Input as Input13, Message, useTranslation as useTranslation10 } from "@dxos/react-ui";
2706
+ import { IconButton as IconButton4, Input as Input14, Message, useTranslation as useTranslation12 } from "@dxos/react-ui";
2281
2707
  import { QueryForm } from "@dxos/react-ui-components";
2282
2708
  import { List as List2 } from "@dxos/react-ui-list";
2283
- import { ProjectionModel, VIEW_FIELD_LIMIT, createEchoChangeCallback, getTypenameFromQuery } from "@dxos/schema";
2284
- import { mx as mx6, osTranslations as osTranslations2, subtleHover as subtleHover2 } from "@dxos/ui-theme";
2285
- var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
2286
- var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode = "schema", registry, db, readonly, showHeading = false, types, tags, onQueryChanged, onDelete }, forwardedRef) => {
2709
+ import { ParentLabelAnnotation, ProjectionModel, VIEW_FIELD_LIMIT, createEchoChangeCallback, getTypenameFromQuery } from "@dxos/schema";
2710
+ import { mx as mx5, osTranslations as osTranslations2 } from "@dxos/ui-theme";
2711
+ import { translationKey as translationKey14 } from "#translations";
2712
+ var __dxlog_file5 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
2713
+ var ViewEditor = /* @__PURE__ */ forwardRef2(({ classNames, schema, view, mode = "schema", registry, db, readonly, showHeading = false, types, tags, onQueryChanged, onDelete }, forwardedRef) => {
2287
2714
  const atomRegistry = useContext(RegistryContext);
2288
2715
  const schemaReadonly = !isMutable(schema);
2289
- const { t } = useTranslation10(translationKey);
2290
- const projectionModel = useMemo8(() => {
2716
+ const { t } = useTranslation12(translationKey14);
2717
+ const projectionModel = useMemo12(() => {
2291
2718
  const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
2292
2719
  const change = createEchoChangeCallback(view, schema instanceof EchoSchema ? schema : void 0);
2293
2720
  const model = new ProjectionModel({
@@ -2311,21 +2738,21 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
2311
2738
  if (from._tag !== "scope") {
2312
2739
  return void 0;
2313
2740
  }
2314
- return Option4.fromNullable(from.scope.queues).pipe(Option4.flatMap((queues) => Array2.head(queues)), Option4.map(String), Option4.getOrUndefined);
2741
+ return Option6.fromNullable(from.scope.feeds).pipe(Option6.flatMap((feeds2) => Array4.head(feeds2)), Option6.map(String), Option6.getOrUndefined);
2315
2742
  }), Match2.orElse(() => void 0));
2316
2743
  const feeds = useQuery2(db, Filter2.type(Feed.Feed));
2317
- const targetRef = useMemo8(() => {
2744
+ const targetRef = useMemo12(() => {
2318
2745
  if (!queueTarget) {
2319
2746
  return void 0;
2320
2747
  }
2321
2748
  const feed = feeds.find((feed2) => Feed.getQueueDxn(feed2)?.toString() === queueTarget);
2322
- return feed ? Ref3.fromDXN(Entity2.getDXN(feed)) : void 0;
2749
+ return feed ? Ref6.fromDXN(Entity2.getDXN(feed)) : void 0;
2323
2750
  }, [
2324
2751
  queueTarget,
2325
2752
  feeds
2326
2753
  ]);
2327
- const viewSchema = useMemo8(() => {
2328
- const base = Schema3.Struct({
2754
+ const viewSchema = useMemo12(() => {
2755
+ const base = Schema5.Struct({
2329
2756
  query: mode === "schema" ? Format5.URL.annotations({
2330
2757
  title: "Record type"
2331
2758
  }) : QueryAST.Query.annotations({
@@ -2333,18 +2760,19 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
2333
2760
  })
2334
2761
  });
2335
2762
  if (mode === "tag") {
2336
- return Schema3.Struct({
2763
+ return Schema5.Struct({
2337
2764
  ...base.fields,
2338
- target: Schema3.optional(Ref3.Ref(Feed.Feed).annotations({
2765
+ // TODO(wittjosiah): Replace Type.Feed with Dataset.Dataset when Ref.Ref supports unions.
2766
+ target: Ref6.Ref(Feed.Feed).pipe(Schema5.annotations({
2339
2767
  title: "Target Feed"
2340
- }))
2341
- }).pipe(Schema3.mutable);
2768
+ }), ParentLabelAnnotation.set(true), Schema5.optional)
2769
+ }).pipe(Schema5.mutable);
2342
2770
  }
2343
- return base.pipe(Schema3.mutable);
2771
+ return base.pipe(Schema5.mutable);
2344
2772
  }, [
2345
2773
  mode
2346
2774
  ]);
2347
- const viewValues = useMemo8(() => ({
2775
+ const viewValues = useMemo12(() => ({
2348
2776
  query: mode === "schema" ? getTypenameFromQuery(view.query.ast) : view.query.ast,
2349
2777
  target: targetRef
2350
2778
  }), [
@@ -2352,7 +2780,7 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
2352
2780
  view.query.ast,
2353
2781
  targetRef
2354
2782
  ]);
2355
- const fieldMap = useMemo8(() => mode === "tag" ? customFields({
2783
+ const fieldMap = useMemo12(() => mode === "tag" ? customFields({
2356
2784
  types,
2357
2785
  tags
2358
2786
  }) : void 0, [
@@ -2360,54 +2788,45 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
2360
2788
  types,
2361
2789
  tags
2362
2790
  ]);
2363
- const handleUpdate = useCallback15((values) => {
2791
+ const handleUpdate = useCallback18((values) => {
2364
2792
  const targetValue = values.target;
2365
- let queueDxn;
2366
- if (Ref3.isRef(targetValue)) {
2367
- const feedDxn = targetValue.dxn.toString();
2368
- const feed = feeds.find((feed2) => Obj3.getDXN(feed2).toString() === feedDxn);
2793
+ let feedDXN;
2794
+ if (Ref6.isRef(targetValue)) {
2795
+ const targetDXN = targetValue.dxn.toString();
2796
+ const feed = feeds.find((feed2) => Obj6.getDXN(feed2).toString() === targetDXN);
2369
2797
  if (feed) {
2370
- queueDxn = Feed.getQueueDxn(feed)?.toString();
2798
+ feedDXN = Feed.getQueueDxn(feed)?.toString();
2371
2799
  }
2372
2800
  }
2373
2801
  const query = mode === "schema" ? Query.select(Filter2.typename(values.query)).ast : JSON.parse(JSON.stringify(values.query));
2374
- onQueryChanged?.(query, queueDxn);
2802
+ onQueryChanged?.(query, feedDXN);
2375
2803
  }, [
2376
2804
  onQueryChanged,
2377
2805
  mode,
2378
2806
  feeds
2379
2807
  ]);
2380
- const handleDelete = useCallback15((fieldId) => {
2381
- invariant(!readonly, void 0, {
2382
- F: __dxlog_file3,
2383
- L: 174,
2384
- S: void 0,
2385
- A: [
2386
- "!readonly",
2387
- ""
2388
- ]
2389
- });
2808
+ const handleDelete = useCallback18((fieldId) => {
2809
+ invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 126, S: void 0, A: ["!readonly", ""] });
2390
2810
  onDelete?.(fieldId);
2391
2811
  }, [
2392
2812
  onDelete,
2393
2813
  readonly
2394
2814
  ]);
2395
- return /* @__PURE__ */ React19.createElement("div", {
2396
- role: "none",
2397
- className: mx6(classNames)
2398
- }, schemaReadonly && !readonly && /* @__PURE__ */ React19.createElement(Message.Root, {
2815
+ return /* @__PURE__ */ React24.createElement("div", {
2816
+ className: mx5(classNames)
2817
+ }, schemaReadonly && !readonly && /* @__PURE__ */ React24.createElement(Message.Root, {
2399
2818
  valence: "info",
2400
2819
  classNames: "my-form-padding"
2401
- }, /* @__PURE__ */ React19.createElement(Message.Title, null, t("system schema description"))), /* @__PURE__ */ React19.createElement(Form.Root, {
2820
+ }, /* @__PURE__ */ React24.createElement(Message.Title, null, t("system-schema.description"))), /* @__PURE__ */ React24.createElement(Form.Root, {
2402
2821
  schema: viewSchema,
2403
2822
  values: viewValues,
2404
2823
  fieldMap,
2405
2824
  db,
2406
2825
  onValuesChanged: handleUpdate
2407
- }, /* @__PURE__ */ React19.createElement(Form.FieldSet, null), /* @__PURE__ */ React19.createElement(FormFieldLabel, {
2408
- label: t("fields label"),
2826
+ }, /* @__PURE__ */ React24.createElement(Form.FieldSet, null), /* @__PURE__ */ React24.createElement(FormFieldLabel, {
2827
+ label: t("fields.label"),
2409
2828
  asChild: true
2410
- }), /* @__PURE__ */ React19.createElement(FieldList, {
2829
+ }), /* @__PURE__ */ React24.createElement(FieldList, {
2411
2830
  schema,
2412
2831
  view,
2413
2832
  registry,
@@ -2419,9 +2838,9 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
2419
2838
  var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDelete }) => {
2420
2839
  const atomRegistry = useContext(RegistryContext);
2421
2840
  const schemaReadonly = !isMutable(schema);
2422
- const { t } = useTranslation10(translationKey);
2841
+ const { t } = useTranslation12(translationKey14);
2423
2842
  const [viewSnapshot] = useObject(view);
2424
- const projectionModel = useMemo8(() => {
2843
+ const projectionModel = useMemo12(() => {
2425
2844
  const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
2426
2845
  const change = createEchoChangeCallback(view, schema instanceof EchoSchema ? schema : void 0);
2427
2846
  const model = new ProjectionModel({
@@ -2436,38 +2855,22 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
2436
2855
  schema,
2437
2856
  view
2438
2857
  ]);
2439
- const [expandedField, setExpandedField] = useState6();
2440
- const handleAdd = useCallback15(() => {
2441
- invariant(!readonly, void 0, {
2442
- F: __dxlog_file3,
2443
- L: 239,
2444
- S: void 0,
2445
- A: [
2446
- "!readonly",
2447
- ""
2448
- ]
2449
- });
2858
+ const [expandedField, setExpandedField] = useState7();
2859
+ const handleAdd = useCallback18(() => {
2860
+ invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 181, S: void 0, A: ["!readonly", ""] });
2450
2861
  const field = projectionModel.createFieldProjection();
2451
2862
  setExpandedField(field.id);
2452
2863
  }, [
2453
2864
  projectionModel,
2454
2865
  readonly
2455
2866
  ]);
2456
- const handleToggleField = useCallback15((field) => {
2867
+ const handleToggleField = useCallback18((field) => {
2457
2868
  setExpandedField((prevExpandedFieldId) => prevExpandedFieldId === field.id ? void 0 : field.id);
2458
2869
  }, [
2459
2870
  readonly
2460
2871
  ]);
2461
- const handleDelete = useCallback15((fieldId) => {
2462
- invariant(!readonly, void 0, {
2463
- F: __dxlog_file3,
2464
- L: 253,
2465
- S: void 0,
2466
- A: [
2467
- "!readonly",
2468
- ""
2469
- ]
2470
- });
2872
+ const handleDelete = useCallback18((fieldId) => {
2873
+ invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 194, S: void 0, A: ["!readonly", ""] });
2471
2874
  if (fieldId === expandedField) {
2472
2875
  setExpandedField(void 0);
2473
2876
  }
@@ -2477,36 +2880,28 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
2477
2880
  onDelete,
2478
2881
  readonly
2479
2882
  ]);
2480
- const handleMove = useCallback15((fromIndex, toIndex) => {
2481
- invariant(!readonly, void 0, {
2482
- F: __dxlog_file3,
2483
- L: 265,
2484
- S: void 0,
2485
- A: [
2486
- "!readonly",
2487
- ""
2488
- ]
2489
- });
2490
- Obj3.change(view, (v) => {
2883
+ const handleMove = useCallback18((fromIndex, toIndex) => {
2884
+ invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 205, S: void 0, A: ["!readonly", ""] });
2885
+ Obj6.update(view, (view2) => {
2491
2886
  const fields = [
2492
- ...v.projection.fields
2887
+ ...view2.projection.fields
2493
2888
  ];
2494
2889
  const [moved] = fields.splice(fromIndex, 1);
2495
2890
  fields.splice(toIndex, 0, moved);
2496
- v.projection.fields = fields;
2891
+ view2.projection.fields = fields;
2497
2892
  });
2498
2893
  }, [
2499
2894
  view,
2500
2895
  readonly
2501
2896
  ]);
2502
- const handleClose = useCallback15(() => setExpandedField(void 0), []);
2503
- const handleHide = useCallback15((fieldId) => {
2897
+ const handleClose = useCallback18(() => setExpandedField(void 0), []);
2898
+ const handleHide = useCallback18((fieldId) => {
2504
2899
  setExpandedField(void 0);
2505
2900
  projectionModel.hideFieldProjection(fieldId);
2506
2901
  }, [
2507
2902
  projectionModel
2508
2903
  ]);
2509
- const handleShow = useCallback15((property) => {
2904
+ const handleShow = useCallback18((property) => {
2510
2905
  setExpandedField(void 0);
2511
2906
  projectionModel.showFieldProjection(property);
2512
2907
  }, [
@@ -2515,70 +2910,67 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
2515
2910
  if (!viewSnapshot) {
2516
2911
  return null;
2517
2912
  }
2518
- return /* @__PURE__ */ React19.createElement(List2.Root, {
2913
+ return /* @__PURE__ */ React24.createElement(List2.Root, {
2519
2914
  items: viewSnapshot.projection.fields,
2520
- isItem: Schema3.is(View.FieldSchema),
2915
+ isItem: Schema5.is(View.FieldSchema),
2521
2916
  getId: (field) => field.id,
2522
2917
  onMove: readonly ? void 0 : handleMove,
2523
2918
  readonly
2524
- }, ({ items: fields }) => /* @__PURE__ */ React19.createElement(React19.Fragment, null, showHeading && /* @__PURE__ */ React19.createElement("h3", {
2919
+ }, ({ items: fields }) => /* @__PURE__ */ React24.createElement(React24.Fragment, null, showHeading && /* @__PURE__ */ React24.createElement("h3", {
2525
2920
  className: "text-sm"
2526
- }, t("field path label")), /* @__PURE__ */ React19.createElement("div", {
2921
+ }, t("field-path.label")), /* @__PURE__ */ React24.createElement("div", {
2527
2922
  role: "list",
2528
2923
  className: "grid grid-cols-[min-content_1fr_min-content_min-content_min-content]"
2529
2924
  }, fields?.map((field) => {
2530
2925
  const hidden = field.visible === false;
2531
- return /* @__PURE__ */ React19.createElement(List2.Item, {
2926
+ return /* @__PURE__ */ React24.createElement(List2.Item, {
2532
2927
  key: field.id,
2533
2928
  item: field,
2534
2929
  classNames: "grid grid-cols-subgrid col-span-5",
2535
2930
  "aria-expanded": expandedField === field.id
2536
- }, /* @__PURE__ */ React19.createElement("div", {
2537
- role: "none",
2538
- className: mx6(subtleHover2, "grid grid-cols-subgrid col-span-5", "rounded-xs cursor-pointer min-h-10")
2539
- }, /* @__PURE__ */ React19.createElement(List2.ItemDragHandle, {
2931
+ }, /* @__PURE__ */ React24.createElement("div", {
2932
+ className: "grid grid-cols-subgrid col-span-5 rounded-xs cursor-pointer min-h-10 dx-hover"
2933
+ }, /* @__PURE__ */ React24.createElement(List2.ItemDragHandle, {
2540
2934
  disabled: readonly || schemaReadonly
2541
- }), /* @__PURE__ */ React19.createElement(List2.ItemTitle, {
2935
+ }), /* @__PURE__ */ React24.createElement(List2.ItemTitle, {
2542
2936
  classNames: hidden && "text-subdued",
2543
2937
  onClick: () => handleToggleField(field)
2544
- }, field.path), /* @__PURE__ */ React19.createElement(List2.ItemButton, {
2545
- label: t(hidden ? "show field label" : "hide field label"),
2938
+ }, field.path), /* @__PURE__ */ React24.createElement(List2.ItemIconButton, {
2939
+ label: t(hidden ? "show-field.label" : "hide-field.label"),
2546
2940
  "data-testid": hidden ? "show-field-button" : "hide-field-button",
2547
2941
  icon: hidden ? "ph--eye-closed--regular" : "ph--eye--regular",
2548
2942
  autoHide: false,
2549
2943
  disabled: readonly || !hidden && projectionModel.getFields().length <= 1,
2550
2944
  onClick: () => hidden ? handleShow(field.path) : handleHide(field.id)
2551
- }), !readonly && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(List2.ItemDeleteButton, {
2552
- label: t("delete field label"),
2945
+ }), !readonly && /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement(List2.ItemDeleteButton, {
2946
+ label: t("delete-field.label"),
2553
2947
  autoHide: false,
2554
2948
  disabled: readonly || schemaReadonly || viewSnapshot.projection.fields.length <= 1,
2555
2949
  onClick: () => handleDelete(field.id),
2556
2950
  "data-testid": "field.delete"
2557
- }), /* @__PURE__ */ React19.createElement(IconButton4, {
2951
+ }), /* @__PURE__ */ React24.createElement(List2.ItemIconButton, {
2558
2952
  iconOnly: true,
2559
2953
  variant: "ghost",
2560
- label: t("toggle expand label", {
2954
+ label: t("toggle-expand.label", {
2561
2955
  ns: osTranslations2
2562
2956
  }),
2563
2957
  icon: expandedField === field.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
2564
2958
  onClick: () => handleToggleField(field),
2565
2959
  "data-testid": "field.toggle"
2566
- }))), expandedField === field.id && !readonly && /* @__PURE__ */ React19.createElement("div", {
2567
- role: "none",
2568
- className: "col-span-5 mt-1 mb-1 border border-separator rounded-md"
2569
- }, /* @__PURE__ */ React19.createElement(FieldEditor, {
2960
+ }))), expandedField === field.id && !readonly && /* @__PURE__ */ React24.createElement("div", {
2961
+ className: "col-span-full mt-1 mb-1 border border-separator rounded-md"
2962
+ }, /* @__PURE__ */ React24.createElement(FieldEditor, {
2570
2963
  readonly: readonly || schemaReadonly,
2571
2964
  registry,
2572
2965
  projection: projectionModel,
2573
2966
  field,
2574
2967
  onSave: handleClose
2575
2968
  })));
2576
- })), !readonly && !expandedField && /* @__PURE__ */ React19.createElement("div", {
2577
- role: "none",
2969
+ })), !readonly && !expandedField && /* @__PURE__ */ React24.createElement("div", {
2578
2970
  className: "my-form-padding"
2579
- }, /* @__PURE__ */ React19.createElement(IconButton4, {
2971
+ }, /* @__PURE__ */ React24.createElement(IconButton4, {
2580
2972
  icon: "ph--plus--regular",
2581
- label: t("add property button label"),
2973
+ label: t("add-property-button.label"),
2582
2974
  onClick: handleAdd,
2583
2975
  disabled: viewSnapshot.projection.fields.length >= VIEW_FIELD_LIMIT,
2584
2976
  classNames: "w-full"
@@ -2586,13 +2978,13 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
2586
2978
  };
2587
2979
  var customFields = ({ types, tags }) => ({
2588
2980
  query: ({ type, readonly, label, getValue, onValueChange }) => {
2589
- const handleChange = useCallback15((query) => onValueChange(type, query.ast), [
2981
+ const handleChange = useCallback18((query) => onValueChange(type, query.ast), [
2590
2982
  onValueChange
2591
2983
  ]);
2592
- return /* @__PURE__ */ React19.createElement(Input13.Root, null, /* @__PURE__ */ React19.createElement(FormFieldLabel, {
2984
+ return /* @__PURE__ */ React24.createElement(Input14.Root, null, /* @__PURE__ */ React24.createElement(FormFieldLabel, {
2593
2985
  readonly,
2594
2986
  label
2595
- }), /* @__PURE__ */ React19.createElement(QueryForm, {
2987
+ }), /* @__PURE__ */ React24.createElement(QueryForm, {
2596
2988
  initialQuery: getValue(),
2597
2989
  types,
2598
2990
  tags,
@@ -2611,7 +3003,9 @@ export {
2611
3003
  GeoPointField,
2612
3004
  MarkdownField,
2613
3005
  NumberField,
3006
+ ObjectForm,
2614
3007
  ObjectPicker,
3008
+ ObjectProperties,
2615
3009
  RefField,
2616
3010
  SelectField,
2617
3011
  SelectOptionField,
@@ -2621,15 +3015,18 @@ export {
2621
3015
  TupleField,
2622
3016
  ViewEditor,
2623
3017
  cellClassesForFieldType,
3018
+ createSelectField,
3019
+ detectFieldType,
2624
3020
  formatForDisplay,
2625
3021
  formatForEditing,
2626
3022
  getDefaultValue,
2627
3023
  getFormProperties,
2628
3024
  getRefProps,
3025
+ getSelectOptionsFromAst,
3026
+ omitHiddenFormFields,
2629
3027
  omitId,
2630
3028
  parseValue,
2631
3029
  pathNotUniqueError,
2632
- translations,
2633
3030
  useFormContext,
2634
3031
  useFormFieldState,
2635
3032
  useFormHandler,