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