@dxos/react-ui-form 0.8.4-main.c85a9c8dae → 0.8.4-main.d05539e30a

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