@dxos/react-ui-form 0.8.4-main.d05673bc65 → 0.8.4-main.d9fc60f731

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 (209) hide show
  1. package/LICENSE +102 -5
  2. package/dist/lib/browser/index.mjs +2008 -840
  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 +83 -0
  6. package/dist/lib/browser/translations.mjs.map +7 -0
  7. package/dist/lib/node-esm/index.mjs +2008 -840
  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 +85 -0
  11. package/dist/lib/node-esm/translations.mjs.map +7 -0
  12. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +2 -2
  13. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  14. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +64 -61
  15. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Form.d.ts +71 -17
  17. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/Form.stories.d.ts +148 -86
  19. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  20. package/dist/types/src/components/Form/FormField.d.ts +24 -8
  21. package/dist/types/src/components/Form/FormField.d.ts.map +1 -1
  22. package/dist/types/src/components/Form/FormFieldComponent.d.ts +26 -13
  23. package/dist/types/src/components/Form/FormFieldComponent.d.ts.map +1 -1
  24. package/dist/types/src/components/Form/FormFieldComponent.stories.d.ts.map +1 -1
  25. package/dist/types/src/components/Form/FormFieldSet.d.ts +11 -9
  26. package/dist/types/src/components/Form/FormFieldSet.d.ts.map +1 -1
  27. package/dist/types/src/components/Form/FormTooltipsContext.d.ts +19 -0
  28. package/dist/types/src/components/Form/FormTooltipsContext.d.ts.map +1 -0
  29. package/dist/types/src/components/Form/Layout/FormLayout.d.ts +50 -0
  30. package/dist/types/src/components/Form/Layout/FormLayout.d.ts.map +1 -0
  31. package/dist/types/src/components/Form/Layout/FormLayout.stories.d.ts +119 -0
  32. package/dist/types/src/components/Form/Layout/FormLayout.stories.d.ts.map +1 -0
  33. package/dist/types/src/components/Form/Layout/FormLayout.stories.test.d.ts +2 -0
  34. package/dist/types/src/components/Form/Layout/FormLayout.stories.test.d.ts.map +1 -0
  35. package/dist/types/src/components/Form/Layout/FormLayout.test.d.ts +2 -0
  36. package/dist/types/src/components/Form/Layout/FormLayout.test.d.ts.map +1 -0
  37. package/dist/types/src/components/Form/Layout/annotation.d.ts +30 -0
  38. package/dist/types/src/components/Form/Layout/annotation.d.ts.map +1 -0
  39. package/dist/types/src/components/Form/Layout/index.d.ts +4 -0
  40. package/dist/types/src/components/Form/Layout/index.d.ts.map +1 -0
  41. package/dist/types/src/components/Form/Layout/parser.d.ts +31 -0
  42. package/dist/types/src/components/Form/Layout/parser.d.ts.map +1 -0
  43. package/dist/types/src/components/Form/Layout/parser.test.d.ts +2 -0
  44. package/dist/types/src/components/Form/Layout/parser.test.d.ts.map +1 -0
  45. package/dist/types/src/components/Form/fields/ArrayField.d.ts +4 -4
  46. package/dist/types/src/components/Form/fields/ArrayField.d.ts.map +1 -1
  47. package/dist/types/src/components/Form/fields/BooleanField.d.ts.map +1 -1
  48. package/dist/types/src/components/Form/fields/DateField.d.ts +4 -0
  49. package/dist/types/src/components/Form/fields/DateField.d.ts.map +1 -0
  50. package/dist/types/src/components/Form/fields/GeoPointField.d.ts +1 -1
  51. package/dist/types/src/components/Form/fields/GeoPointField.d.ts.map +1 -1
  52. package/dist/types/src/components/Form/fields/InlineRefField.d.ts +13 -0
  53. package/dist/types/src/components/Form/fields/InlineRefField.d.ts.map +1 -0
  54. package/dist/types/src/components/Form/fields/MarkdownField.d.ts +8 -1
  55. package/dist/types/src/components/Form/fields/MarkdownField.d.ts.map +1 -1
  56. package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts +85 -0
  57. package/dist/types/src/components/Form/fields/MarkdownField.stories.d.ts.map +1 -0
  58. package/dist/types/src/components/Form/fields/NumberField.d.ts.map +1 -1
  59. package/dist/types/src/components/Form/fields/RefField.d.ts +12 -6
  60. package/dist/types/src/components/Form/fields/RefField.d.ts.map +1 -1
  61. package/dist/types/src/components/Form/fields/SelectField.d.ts +4 -1
  62. package/dist/types/src/components/Form/fields/SelectField.d.ts.map +1 -1
  63. package/dist/types/src/components/Form/fields/SelectOptionField.d.ts +1 -1
  64. package/dist/types/src/components/Form/fields/SelectOptionField.d.ts.map +1 -1
  65. package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts +64 -61
  66. package/dist/types/src/components/Form/fields/SelectOptionField.stories.d.ts.map +1 -1
  67. package/dist/types/src/components/Form/fields/TextAreaField.d.ts.map +1 -1
  68. package/dist/types/src/components/Form/fields/TextField.d.ts +1 -1
  69. package/dist/types/src/components/Form/fields/TextField.d.ts.map +1 -1
  70. package/dist/types/src/components/Form/fields/TupleField.d.ts +1 -1
  71. package/dist/types/src/components/Form/fields/TupleField.d.ts.map +1 -1
  72. package/dist/types/src/components/Form/fields/index.d.ts +2 -0
  73. package/dist/types/src/components/Form/fields/index.d.ts.map +1 -1
  74. package/dist/types/src/components/Form/index.d.ts +3 -0
  75. package/dist/types/src/components/Form/index.d.ts.map +1 -1
  76. package/dist/types/src/components/Form/meta-tags.d.ts +30 -0
  77. package/dist/types/src/components/Form/meta-tags.d.ts.map +1 -0
  78. package/dist/types/src/components/Form/meta-tags.test.d.ts +2 -0
  79. package/dist/types/src/components/Form/meta-tags.test.d.ts.map +1 -0
  80. package/dist/types/src/components/ObjectForm/ObjectForm.d.ts +8 -0
  81. package/dist/types/src/components/ObjectForm/ObjectForm.d.ts.map +1 -0
  82. package/dist/types/src/components/ObjectForm/index.d.ts +2 -0
  83. package/dist/types/src/components/ObjectForm/index.d.ts.map +1 -0
  84. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +28 -6
  85. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -1
  86. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +64 -61
  87. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -1
  88. package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts +9 -0
  89. package/dist/types/src/components/ObjectProperties/ObjectProperties.d.ts.map +1 -0
  90. package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts +128 -0
  91. package/dist/types/src/components/ObjectProperties/ObjectProperties.stories.d.ts.map +1 -0
  92. package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts +2 -0
  93. package/dist/types/src/components/ObjectProperties/ObjectProperties.test.d.ts.map +1 -0
  94. package/dist/types/src/components/ObjectProperties/index.d.ts +2 -0
  95. package/dist/types/src/components/ObjectProperties/index.d.ts.map +1 -0
  96. package/dist/types/src/components/ObjectTree/ObjectTree.d.ts +9 -0
  97. package/dist/types/src/components/ObjectTree/ObjectTree.d.ts.map +1 -0
  98. package/dist/types/src/components/ObjectTree/ObjectTree.stories.d.ts +87 -0
  99. package/dist/types/src/components/ObjectTree/ObjectTree.stories.d.ts.map +1 -0
  100. package/dist/types/src/components/ObjectTree/index.d.ts +2 -0
  101. package/dist/types/src/components/ObjectTree/index.d.ts.map +1 -0
  102. package/dist/types/src/components/Settings/Settings.d.ts +28 -33
  103. package/dist/types/src/components/Settings/Settings.d.ts.map +1 -1
  104. package/dist/types/src/components/Settings/Settings.stories.d.ts +65 -61
  105. package/dist/types/src/components/Settings/Settings.stories.d.ts.map +1 -1
  106. package/dist/types/src/components/Settings/SettingsFieldSet.d.ts +43 -0
  107. package/dist/types/src/components/Settings/SettingsFieldSet.d.ts.map +1 -0
  108. package/dist/types/src/components/Settings/SettingsItem.d.ts +16 -0
  109. package/dist/types/src/components/Settings/SettingsItem.d.ts.map +1 -0
  110. package/dist/types/src/components/Settings/SettingsSelectField.d.ts +18 -0
  111. package/dist/types/src/components/Settings/SettingsSelectField.d.ts.map +1 -0
  112. package/dist/types/src/components/Settings/index.d.ts +2 -0
  113. package/dist/types/src/components/Settings/index.d.ts.map +1 -1
  114. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +9 -11
  115. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  116. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +68 -66
  117. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  118. package/dist/types/src/components/index.d.ts +3 -0
  119. package/dist/types/src/components/index.d.ts.map +1 -1
  120. package/dist/types/src/components/testing.d.ts +13 -4
  121. package/dist/types/src/components/testing.d.ts.map +1 -1
  122. package/dist/types/src/hooks/useFormHandler.d.ts.map +1 -1
  123. package/dist/types/src/hooks/useKeyHandler.d.ts +2 -1
  124. package/dist/types/src/hooks/useKeyHandler.d.ts.map +1 -1
  125. package/dist/types/src/index.d.ts +0 -2
  126. package/dist/types/src/index.d.ts.map +1 -1
  127. package/dist/types/src/translations.d.ts +64 -61
  128. package/dist/types/src/translations.d.ts.map +1 -1
  129. package/dist/types/src/util/field-type.d.ts +19 -0
  130. package/dist/types/src/util/field-type.d.ts.map +1 -0
  131. package/dist/types/src/util/field.d.ts.map +1 -1
  132. package/dist/types/src/util/formatting.d.ts.map +1 -1
  133. package/dist/types/src/util/index.d.ts +1 -0
  134. package/dist/types/src/util/index.d.ts.map +1 -1
  135. package/dist/types/src/util/properties.d.ts +18 -1
  136. package/dist/types/src/util/properties.d.ts.map +1 -1
  137. package/dist/types/src/util/properties.test.d.ts +2 -0
  138. package/dist/types/src/util/properties.test.d.ts.map +1 -0
  139. package/dist/types/src/util/refs.d.ts +1 -0
  140. package/dist/types/src/util/refs.d.ts.map +1 -1
  141. package/dist/types/tsconfig.tsbuildinfo +1 -1
  142. package/package.json +48 -41
  143. package/src/components/FieldEditor/FieldEditor.stories.tsx +4 -4
  144. package/src/components/FieldEditor/FieldEditor.test.tsx +4 -2
  145. package/src/components/FieldEditor/FieldEditor.tsx +23 -17
  146. package/src/components/Form/AUDIT.md +17 -0
  147. package/src/components/Form/Form.stories.tsx +46 -65
  148. package/src/components/Form/Form.tsx +176 -60
  149. package/src/components/Form/FormField.tsx +107 -38
  150. package/src/components/Form/FormFieldComponent.tsx +77 -20
  151. package/src/components/Form/FormFieldSet.tsx +128 -78
  152. package/src/components/Form/FormTooltipsContext.ts +25 -0
  153. package/src/components/Form/Layout/FormLayout.stories.test.tsx +51 -0
  154. package/src/components/Form/Layout/FormLayout.stories.tsx +422 -0
  155. package/src/components/Form/Layout/FormLayout.test.ts +59 -0
  156. package/src/components/Form/Layout/FormLayout.tsx +251 -0
  157. package/src/components/Form/Layout/annotation.ts +38 -0
  158. package/src/components/Form/Layout/index.ts +7 -0
  159. package/src/components/Form/Layout/parser.test.ts +120 -0
  160. package/src/components/Form/Layout/parser.ts +167 -0
  161. package/src/components/Form/fields/ArrayField.tsx +64 -35
  162. package/src/components/Form/fields/DateField.tsx +101 -0
  163. package/src/components/Form/fields/GeoPointField.tsx +12 -8
  164. package/src/components/Form/fields/InlineRefField.tsx +146 -0
  165. package/src/components/Form/fields/MarkdownField.stories.tsx +206 -0
  166. package/src/components/Form/fields/MarkdownField.tsx +135 -45
  167. package/src/components/Form/fields/RefField.tsx +83 -42
  168. package/src/components/Form/fields/SelectField.tsx +17 -5
  169. package/src/components/Form/fields/SelectOptionField.stories.tsx +8 -6
  170. package/src/components/Form/fields/SelectOptionField.tsx +14 -13
  171. package/src/components/Form/fields/TextAreaField.tsx +1 -1
  172. package/src/components/Form/fields/TextField.tsx +2 -2
  173. package/src/components/Form/fields/TupleField.tsx +3 -2
  174. package/src/components/Form/fields/index.ts +2 -0
  175. package/src/components/Form/index.ts +3 -0
  176. package/src/components/Form/meta-tags.test.ts +47 -0
  177. package/src/components/Form/meta-tags.ts +33 -0
  178. package/src/components/ObjectForm/ObjectForm.tsx +109 -0
  179. package/src/components/ObjectForm/index.ts +5 -0
  180. package/src/components/ObjectPicker/ObjectPicker.stories.tsx +13 -11
  181. package/src/components/ObjectPicker/ObjectPicker.tsx +93 -66
  182. package/src/components/ObjectProperties/ObjectProperties.stories.tsx +350 -0
  183. package/src/components/ObjectProperties/ObjectProperties.test.tsx +111 -0
  184. package/src/components/ObjectProperties/ObjectProperties.tsx +144 -0
  185. package/src/components/ObjectProperties/index.ts +5 -0
  186. package/src/components/ObjectTree/ObjectTree.stories.tsx +134 -0
  187. package/src/components/ObjectTree/ObjectTree.tsx +190 -0
  188. package/src/components/ObjectTree/index.ts +5 -0
  189. package/src/components/Settings/AUDIT.md +51 -0
  190. package/src/components/Settings/Settings.stories.tsx +69 -21
  191. package/src/components/Settings/Settings.tsx +32 -181
  192. package/src/components/Settings/SettingsFieldSet.tsx +257 -0
  193. package/src/components/Settings/SettingsItem.tsx +58 -0
  194. package/src/components/Settings/SettingsSelectField.tsx +59 -0
  195. package/src/components/Settings/index.ts +2 -0
  196. package/src/components/ViewEditor/ViewEditor.stories.tsx +45 -51
  197. package/src/components/ViewEditor/ViewEditor.test.tsx +11 -9
  198. package/src/components/ViewEditor/ViewEditor.tsx +45 -55
  199. package/src/components/index.ts +3 -0
  200. package/src/components/testing.tsx +19 -11
  201. package/src/hooks/useKeyHandler.tsx +7 -7
  202. package/src/index.ts +0 -4
  203. package/src/translations.ts +67 -63
  204. package/src/util/field-type.ts +60 -0
  205. package/src/util/index.ts +1 -0
  206. package/src/util/properties.test.ts +121 -0
  207. package/src/util/properties.ts +47 -4
  208. package/src/util/refs.ts +7 -3
  209. package/src/vite-env.d.ts +10 -0
@@ -1,89 +1,13 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
2
 
3
- // src/translations.ts
4
- var translationKey = "@dxos/react-ui-form";
5
- var translations = [
6
- {
7
- "en-US": {
8
- [translationKey]: {
9
- "fields label": "Fields",
10
- "hidden fields label": "Hidden Fields",
11
- "empty readonly ref field label": "(none)",
12
- // TODO(burdon): Standardize field/property.
13
- "add property button label": "Add property",
14
- "field property label": "Property",
15
- "field property placeholder": "Property name",
16
- "field format label": "Type",
17
- "field path label": "Field path",
18
- "add field": "Add field",
19
- "delete field": "Delete field",
20
- "field limit reached": "Maximum number of fields reached",
21
- "boolean input true value": "Yes",
22
- "boolean input false value": "No",
23
- "show field label": "Show field",
24
- "hide field label": "Hide field",
25
- "delete field label": "Delete field",
26
- "ref field combobox input placeholder": "Search\u2026",
27
- "ref field placeholder_one": "Select\u2026",
28
- "ref field placeholder_other": "Select items\u2026",
29
- "example placeholder": "Example",
30
- "latitude placeholder": "Latitude (e.g., 40.7128)",
31
- "longitude placeholder": "Longitude (e.g., -74.0060)",
32
- "cancel button label": "Cancel",
33
- "save button label": "Save",
34
- // FormatEnum
35
- "format boolean": "Boolean",
36
- "format currency": "Currency",
37
- "format date": "Date",
38
- "format date-time": "DateTime",
39
- "format did": "DID",
40
- "format duration": "Duration",
41
- "format dxn": "DXN",
42
- "format email": "Email",
43
- "format formula": "Formula",
44
- "format hostname": "Hostname",
45
- "format integer": "Integer",
46
- "format json": "JSON",
47
- "format lnglat": "Geopoint",
48
- "format markdown": "Markdown",
49
- "format percent": "Percent",
50
- "format ref": "Reference",
51
- "format regex": "RegExp",
52
- "format string": "String",
53
- "format single-select": "Select",
54
- "format multi-select": "Multi-select",
55
- "format text": "Long text",
56
- "format time": "Time",
57
- "format timestamp": "Timestamp",
58
- "format user": "User",
59
- "format number": "Number",
60
- "format uri": "URI",
61
- "format url": "URL",
62
- "format uuid": "UUID",
63
- // GeoPointField.
64
- "latitude label": "Latitude",
65
- "longitude label": "Longitude",
66
- // SelectOptionsField.
67
- "select option label": "Label",
68
- "select option label placeholder": "Option label",
69
- "select option color": "Color",
70
- "select option delete": "Delete",
71
- "select option add": "Add option",
72
- // System schema message.
73
- "system schema title": "System type",
74
- "system schema description": "System type: cannot add or remove fields."
75
- }
76
- }
77
- }
78
- ];
79
-
80
3
  // src/components/FieldEditor/FieldEditor.tsx
81
- import React17, { useCallback as useCallback14, useEffect as useEffect7, useMemo as useMemo7, useState as useState5 } from "react";
82
- import { Obj as Obj2 } from "@dxos/echo";
83
- import { Format as Format4, FormatEnums, formatToType } from "@dxos/echo/internal";
4
+ import React20, { useCallback as useCallback16, useEffect as useEffect5, useMemo as useMemo10, useState as useState6 } from "react";
5
+ import { Filter as Filter2, Obj as Obj4, Type as Type4 } from "@dxos/echo";
6
+ import { Format as Format6, FormatEnums, formatToType } from "@dxos/echo/internal";
84
7
  import { log as log2 } from "@dxos/log";
85
- import { useAsyncEffect, useTranslation as useTranslation8 } from "@dxos/react-ui";
8
+ import { useAsyncEffect, useTranslation as useTranslation10 } from "@dxos/react-ui";
86
9
  import { formatToAdditionalPropertyAttributes, getFormatSchema } from "@dxos/schema";
10
+ import { translationKey as translationKey10 } from "#translations";
87
11
 
88
12
  // src/util/field.ts
89
13
  import { Format, GeoLocation, TypeEnum } from "@dxos/echo/internal";
@@ -206,6 +130,46 @@ var pathNotUniqueError = (path) => ({
206
130
  message: `'${path}' is already present`
207
131
  });
208
132
 
133
+ // src/util/field-type.ts
134
+ import * as SchemaAST from "effect/SchemaAST";
135
+ import { getAnnotation, isLiteralUnion } from "@dxos/effect";
136
+ var detectFieldType = (ast) => {
137
+ if (isLiteralUnion(ast)) {
138
+ return "select";
139
+ }
140
+ if (SchemaAST.isTypeLiteral(ast)) {
141
+ return "struct";
142
+ }
143
+ switch (ast._tag) {
144
+ case "BooleanKeyword":
145
+ return "boolean";
146
+ case "StringKeyword":
147
+ return "string";
148
+ case "NumberKeyword":
149
+ return "number";
150
+ }
151
+ return void 0;
152
+ };
153
+ var getSelectOptionsFromAst = (ast) => {
154
+ if (!isLiteralUnion(ast)) {
155
+ return void 0;
156
+ }
157
+ return ast.types.flatMap((literalNode) => {
158
+ const value3 = literalNode.literal;
159
+ if (typeof value3 !== "string" && typeof value3 !== "number") {
160
+ return [];
161
+ }
162
+ const title = getAnnotation(SchemaAST.TitleAnnotationId, false)(literalNode);
163
+ const label = title ?? (typeof value3 === "string" ? value3.charAt(0).toUpperCase() + value3.slice(1) : String(value3));
164
+ return [
165
+ {
166
+ value: value3,
167
+ label
168
+ }
169
+ ];
170
+ });
171
+ };
172
+
209
173
  // src/util/formatting.ts
210
174
  import { format as formatDate } from "date-fns/format";
211
175
  import { Format as Format2, GeoLocation as GeoLocation2, TypeEnum as TypeEnum2 } from "@dxos/echo/internal";
@@ -346,51 +310,85 @@ var formatForEditing = ({ type, format, value: value3, locale = void 0 }) => {
346
310
 
347
311
  // src/util/properties.ts
348
312
  import * as Option from "effect/Option";
313
+ import * as SchemaAST2 from "effect/SchemaAST";
349
314
  import { Annotation } from "@dxos/echo";
350
- import { getProperties } from "@dxos/effect";
315
+ import { getProperties, isArrayType, isNestedType } from "@dxos/effect";
316
+ var unwrapOptional = (prop) => {
317
+ if (!prop.isOptional || !SchemaAST2.isUnion(prop.type)) {
318
+ return prop.type;
319
+ }
320
+ const defined = prop.type.types.filter((type) => type._tag !== "UndefinedKeyword");
321
+ if (defined.length === 0) {
322
+ return prop.type;
323
+ }
324
+ return defined.length === 1 ? defined[0] : SchemaAST2.Union.make(defined, prop.type.annotations);
325
+ };
351
326
  var getFormProperties = (ast) => {
352
- return getProperties(ast).filter((prop) => Annotation.FormInputAnnotation.getFromAst(prop.type).pipe(Option.getOrElse(() => true)));
327
+ const signatures = SchemaAST2.getPropertySignatures(ast);
328
+ const rawByName = new Map(signatures.map((prop) => [
329
+ prop.name,
330
+ unwrapOptional(prop)
331
+ ]));
332
+ const hidden = new Set(signatures.filter((prop) => Annotation.FormInputAnnotation.getFromAst(unwrapOptional(prop)).pipe(Option.getOrElse(() => true)) === false).map((prop) => prop.name));
333
+ return getProperties(ast).filter((prop) => !hidden.has(prop.name)).map((prop) => {
334
+ const raw = rawByName.get(prop.name);
335
+ return raw && (isNestedType(raw) || isArrayType(raw)) ? {
336
+ ...prop,
337
+ type: raw
338
+ } : prop;
339
+ });
353
340
  };
354
341
 
355
342
  // src/util/refs.ts
356
343
  import { Ref } from "@dxos/echo";
357
- import { getArrayElementType, isArrayType } from "@dxos/effect";
344
+ import { ReferenceAnnotationId } from "@dxos/echo/internal";
345
+ import { findAnnotation, getArrayElementType, isArrayType as isArrayType2 } from "@dxos/effect";
358
346
  var getRefProps = (ast) => {
359
- if (isArrayType(ast)) {
347
+ if (isArrayType2(ast)) {
360
348
  const elementType = getArrayElementType(ast);
361
349
  if (elementType) {
362
350
  if (Ref.isRefType(elementType)) {
351
+ const typename = findAnnotation(elementType, ReferenceAnnotationId)?.typename;
363
352
  return {
364
353
  ast: elementType,
365
- isArray: true
354
+ isArray: true,
355
+ typename
366
356
  };
367
357
  }
368
358
  }
369
359
  }
370
360
  if (Ref.isRefType(ast)) {
361
+ const typename = findAnnotation(ast, ReferenceAnnotationId)?.typename;
371
362
  return {
372
363
  ast,
373
- isArray: false
364
+ isArray: false,
365
+ typename
374
366
  };
375
367
  }
376
368
  return void 0;
377
369
  };
378
370
 
379
371
  // src/components/Form/fields/ArrayField.tsx
380
- import * as Option3 from "effect/Option";
381
- import * as SchemaAST3 from "effect/SchemaAST";
382
- import React5, { useCallback as useCallback3 } from "react";
383
- import { findNode as findNode2, getArrayElementType as getArrayElementType2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2, isNestedType as isNestedType2 } from "@dxos/effect";
384
- import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
372
+ import * as Option6 from "effect/Option";
373
+ import * as SchemaAST6 from "effect/SchemaAST";
374
+ import React6, { useCallback as useCallback3 } from "react";
375
+ import { Ref as Ref2 } from "@dxos/echo";
376
+ import { createJsonPath as createJsonPath6, findNode as findNode3, getArrayElementType as getArrayElementType2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2, isNestedType as isNestedType3 } from "@dxos/effect";
377
+ import { useTranslation as useTranslation3 } from "@dxos/react-ui";
378
+ import { translationKey as translationKey3 } from "#translations";
385
379
 
386
380
  // src/components/Form/Form.tsx
387
- import { createContext } from "@radix-ui/react-context";
388
- import * as Schema2 from "effect/Schema";
389
- import * as SchemaAST2 from "effect/SchemaAST";
390
- import React4, { useEffect as useEffect3, useMemo as useMemo4, useRef } from "react";
391
- import { createJsonPath as createJsonPath3, getValue as getValue$2 } from "@dxos/effect";
392
- import { IconButton, ScrollArea, useTranslation as useTranslation2 } from "@dxos/react-ui";
393
- import { mx as mx2 } from "@dxos/ui-theme";
381
+ import { createContext as createContext2 } from "@radix-ui/react-context";
382
+ import * as Option5 from "effect/Option";
383
+ import * as Schema3 from "effect/Schema";
384
+ import * as SchemaAST5 from "effect/SchemaAST";
385
+ import React5, { useEffect as useEffect2, useMemo as useMemo5, useRef } from "react";
386
+ import { Annotation as EchoAnnotation, Type } from "@dxos/echo";
387
+ import { createJsonPath as createJsonPath5, getValue as getValue$2 } from "@dxos/effect";
388
+ import { Column, IconButton as IconButton2, Input as Input3, ScrollArea, useMergeRefs, useTranslation as useTranslation2 } from "@dxos/react-ui";
389
+ import { composable, composableProps, withColumn } from "@dxos/react-ui";
390
+ import { mx as mx3 } from "@dxos/ui-theme";
391
+ import { translationKey as translationKey2 } from "#translations";
394
392
 
395
393
  // src/hooks/useFormHandler.ts
396
394
  import { useControllableState } from "@radix-ui/react-use-controllable-state";
@@ -428,12 +426,7 @@ var useFormHandler = ({ schema, autoSave, values: valuesProp, defaultValues: def
428
426
  log("validate", {
429
427
  values: values2,
430
428
  errors: errors2
431
- }, {
432
- F: __dxlog_file,
433
- L: 155,
434
- S: void 0,
435
- C: (f, a) => f(...a)
436
- });
429
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 42, S: void 0 });
437
430
  if (errors2.length === 0 && onValidate) {
438
431
  const validatedValues = values2;
439
432
  errors2 = onValidate(validatedValues) ?? [];
@@ -521,12 +514,7 @@ var useFormHandler = ({ schema, autoSave, values: valuesProp, defaultValues: def
521
514
  log("onValueChange", {
522
515
  path,
523
516
  value: value3
524
- }, {
525
- F: __dxlog_file,
526
- L: 254,
527
- S: void 0,
528
- C: (f, a) => f(...a)
529
- });
517
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 138, S: void 0 });
530
518
  const jsonPath = createJsonPath(path);
531
519
  const pathArray = path;
532
520
  let parsedValue = value3;
@@ -535,12 +523,7 @@ var useFormHandler = ({ schema, autoSave, values: valuesProp, defaultValues: def
535
523
  parsedValue = parseFloat(value3) || 0;
536
524
  }
537
525
  } catch (err) {
538
- log.catch(err, void 0, {
539
- F: __dxlog_file,
540
- L: 264,
541
- S: void 0,
542
- C: (f, a) => f(...a)
543
- });
526
+ log.catch(err, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 150, S: void 0 });
544
527
  parsedValue = void 0;
545
528
  }
546
529
  const newValues = mergeAtPath(values, pathArray, parsedValue);
@@ -624,18 +607,18 @@ var mergeAtPath = (obj, path, value3) => {
624
607
  if (path.length === 0) {
625
608
  return value3;
626
609
  }
627
- const [head2, ...rest] = path;
628
- const child = rest.length === 0 ? value3 : mergeAtPath(obj?.[head2], rest, value3);
610
+ const [head, ...rest] = path;
611
+ const child = rest.length === 0 ? value3 : mergeAtPath(obj?.[head], rest, value3);
629
612
  if (Array.isArray(obj)) {
630
613
  const copy = [
631
614
  ...obj
632
615
  ];
633
- copy[head2] = child;
616
+ copy[head] = child;
634
617
  return copy;
635
618
  }
636
619
  return {
637
620
  ...obj,
638
- [head2]: child
621
+ [head]: child
639
622
  };
640
623
  };
641
624
  var flatMap = (errors) => {
@@ -649,9 +632,9 @@ var flatMap = (errors) => {
649
632
  };
650
633
 
651
634
  // src/hooks/useKeyHandler.tsx
652
- import { useCallback as useCallback2, useEffect as useEffect2 } from "react";
635
+ import { useCallback as useCallback2, useLayoutEffect } from "react";
653
636
  import { addEventListener } from "@dxos/async";
654
- var useKeyHandler = (formElement, form) => {
637
+ var useKeyHandler = (elRef, form) => {
655
638
  const handleKeyDown = useCallback2((event) => {
656
639
  switch (event.key) {
657
640
  case "Enter": {
@@ -667,29 +650,45 @@ var useKeyHandler = (formElement, form) => {
667
650
  form.onSave,
668
651
  form.autoSave
669
652
  ]);
670
- useEffect2(() => {
671
- if (!formElement) {
653
+ useLayoutEffect(() => {
654
+ const el = elRef.current;
655
+ if (!el) {
672
656
  return;
673
657
  }
674
- return addEventListener(formElement, "keydown", handleKeyDown);
658
+ return addEventListener(el, "keydown", handleKeyDown);
675
659
  }, [
676
- formElement,
660
+ elRef,
677
661
  handleKeyDown
678
662
  ]);
679
663
  };
680
664
 
681
665
  // src/components/Form/FormFieldComponent.tsx
666
+ import { format as formatDate2 } from "date-fns";
682
667
  import React, { Component } from "react";
668
+ import { Format as Format3 } from "@dxos/echo";
683
669
  import { Icon, Input, Tooltip } from "@dxos/react-ui";
684
- import { inputTextLabel } from "@dxos/ui-theme";
685
- var FormFieldLabel = ({ label, error, readonly, asChild }) => {
670
+ import { inputTextLabel } from "@dxos/react-ui";
671
+ import { mx } from "@dxos/ui-theme";
672
+
673
+ // src/components/Form/FormTooltipsContext.ts
674
+ import { createContext, useContext } from "react";
675
+ var FormTooltipsContext = createContext(true);
676
+ var useFormTooltips = () => useContext(FormTooltipsContext);
677
+
678
+ // src/components/Form/FormFieldComponent.tsx
679
+ var FormFieldLabel = ({ label, error, readonly, asChild, path }) => {
680
+ const tooltips = useFormTooltips();
686
681
  const Label = readonly || asChild ? "span" : Input.Label;
682
+ const labelNode = /* @__PURE__ */ React.createElement(Label, {
683
+ className: mx(inputTextLabel, "text-sm")
684
+ }, label);
687
685
  return /* @__PURE__ */ React.createElement("div", {
688
- role: "none",
689
686
  className: "flex items-center justify-between"
690
- }, /* @__PURE__ */ React.createElement(Label, {
691
- className: inputTextLabel
692
- }, label), error && /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
687
+ }, tooltips && path ? /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
688
+ asChild: true,
689
+ content: path,
690
+ side: "bottom"
691
+ }, labelNode) : labelNode, error && /* @__PURE__ */ React.createElement(Tooltip.Trigger, {
693
692
  asChild: true,
694
693
  content: error,
695
694
  side: "bottom"
@@ -700,26 +699,48 @@ var FormFieldLabel = ({ label, error, readonly, asChild }) => {
700
699
  })));
701
700
  };
702
701
  FormFieldLabel.displayName = "Form.FieldLabel";
702
+ var formatStaticValue = (value3, format) => {
703
+ if (value3 == null) {
704
+ return "";
705
+ }
706
+ switch (format) {
707
+ case Format3.TypeFormat.DateTime:
708
+ case Format3.TypeFormat.Date:
709
+ case Format3.TypeFormat.Time: {
710
+ const date = new Date(value3);
711
+ if (Number.isNaN(date.getTime())) {
712
+ return String(value3);
713
+ }
714
+ const pattern = format === Format3.TypeFormat.DateTime ? "PPp" : format === Format3.TypeFormat.Date ? "PP" : "p";
715
+ return formatDate2(date, pattern);
716
+ }
717
+ default:
718
+ return String(value3);
719
+ }
720
+ };
703
721
  var FormFieldWrapper = (props) => {
704
- const { children, readonly, layout, label, getStatus, getValue } = props;
722
+ const { children, readonly, layout, label, jsonPath, format, getStatus, getValue } = props;
705
723
  const { status, error } = getStatus();
706
724
  const value3 = getValue();
707
725
  if (layout === "static" && value3 == null) {
708
726
  return null;
709
727
  }
710
- const str = String(value3 ?? "");
728
+ const str = formatStaticValue(value3, format);
711
729
  return /* @__PURE__ */ React.createElement("div", {
712
- role: "none",
713
730
  className: "contents"
714
731
  }, /* @__PURE__ */ React.createElement(Input.Root, {
715
732
  validationValence: status
716
733
  }, layout !== "inline" && /* @__PURE__ */ React.createElement(FormFieldLabel, {
717
734
  error,
718
735
  readonly,
719
- label
720
- }), layout === "static" ? /* @__PURE__ */ React.createElement("p", null, str) : children ? children({
736
+ label,
737
+ path: jsonPath
738
+ }), layout === "static" ? /* @__PURE__ */ React.createElement("p", {
739
+ className: "truncate min-w-0",
740
+ title: str
741
+ }, str) : children ? children({
721
742
  value: value3
722
- }) : null, layout === "full" && /* @__PURE__ */ React.createElement(Input.DescriptionAndValidation, null, /* @__PURE__ */ React.createElement(Input.Validation, null, error))));
743
+ }) : null, layout === "full" && error && /* @__PURE__ */ React.createElement(Input.DescriptionAndValidation, null, /* @__PURE__ */ React.createElement(Input.Validation, null, error))));
723
744
  };
724
745
  var FormFieldErrorBoundary = class extends Component {
725
746
  static getDerivedStateFromError(error) {
@@ -738,9 +759,9 @@ var FormFieldErrorBoundary = class extends Component {
738
759
  render() {
739
760
  if (this.state.error) {
740
761
  return /* @__PURE__ */ React.createElement("div", {
741
- className: "flex gap-2 border border-rose-fill font-mono text-sm"
762
+ className: "flex gap-2 border border-rose-bg font-mono text-sm"
742
763
  }, /* @__PURE__ */ React.createElement("span", {
743
- className: "bg-rose-fill text-surface-text px-1 font-thin"
764
+ className: "bg-rose-bg text-base-fg px-1 font-thin"
744
765
  }, "ERROR"), String(this.props.path?.join(".")));
745
766
  }
746
767
  return this.props.children;
@@ -753,20 +774,22 @@ var FormFieldErrorBoundary = class extends Component {
753
774
  };
754
775
 
755
776
  // src/components/Form/FormFieldSet.tsx
756
- import React3, { forwardRef, useMemo as useMemo3 } from "react";
757
- import { mx } from "@dxos/ui-theme";
758
- import { isTruthy } from "@dxos/util";
777
+ import * as Option4 from "effect/Option";
778
+ import React4, { useMemo as useMemo4 } from "react";
779
+ import { createJsonPath as createJsonPath4 } from "@dxos/effect";
759
780
 
760
781
  // src/components/Form/FormField.tsx
761
782
  import * as Match from "effect/Match";
762
783
  import * as Option2 from "effect/Option";
763
784
  import * as Schema from "effect/Schema";
764
- import * as SchemaAST from "effect/SchemaAST";
785
+ import * as SchemaAST3 from "effect/SchemaAST";
765
786
  import * as String2 from "effect/String";
766
787
  import React2, { useMemo as useMemo2 } from "react";
767
- import { Format as Format3 } from "@dxos/echo";
768
- import { createJsonPath as createJsonPath2, findNode, getAnnotation, getDiscriminatedType, isArrayType as isArrayType2, isDiscriminatedUnion, isLiteralUnion, isNestedType } from "@dxos/effect";
769
- import { useTranslation } from "@dxos/react-ui";
788
+ import { Annotation as Annotation2, Format as Format4 } from "@dxos/echo";
789
+ import { createJsonPath as createJsonPath2, findNode, getAnnotation as getAnnotation2, getDiscriminatedType, isArrayType as isArrayType3, isDiscriminatedUnion, isLiteralUnion as isLiteralUnion2, isNestedType as isNestedType2 } from "@dxos/effect";
790
+ import { IconButton, useTranslation } from "@dxos/react-ui";
791
+ import { mx as mx2 } from "@dxos/ui-theme";
792
+ import { translationKey } from "#translations";
770
793
  var FormField = (props) => {
771
794
  const {
772
795
  type,
@@ -778,51 +801,58 @@ var FormField = (props) => {
778
801
  readonly,
779
802
  layout,
780
803
  // RefFieldProps
804
+ createTypename,
781
805
  createOptionLabel,
782
806
  createOptionIcon,
783
807
  createInitialValuePath,
808
+ createFieldMap: createFieldMap3,
784
809
  db,
785
- schemaHook,
786
- getOptions: getRefOptions,
810
+ useType: schemaHook,
811
+ getOptions,
787
812
  onCreate
788
813
  } = props;
789
814
  const { t } = useTranslation(translationKey);
790
- const title = getAnnotation(SchemaAST.TitleAnnotationId)(type);
791
- const description = getAnnotation(SchemaAST.DescriptionAnnotationId)(type);
792
- const examples = getAnnotation(SchemaAST.ExamplesAnnotationId)(type);
793
- const label = useMemo2(() => title ?? String2.capitalize(name), [
815
+ const title = getAnnotation2(SchemaAST3.TitleAnnotationId)(type);
816
+ const description = getAnnotation2(SchemaAST3.DescriptionAnnotationId)(type);
817
+ const examples = getAnnotation2(SchemaAST3.ExamplesAnnotationId)(type);
818
+ const label = useMemo2(() => title ?? (name == null ? "" : String2.capitalize(name)), [
794
819
  title,
795
820
  name
796
821
  ]);
797
- const placeholder = useMemo2(() => examples?.length ? `${t("example placeholder")}: ${examples[0]}` : description ?? label, [
822
+ const placeholder = useMemo2(() => examples?.length ? `${t("example.placeholder")}: ${examples[0]}` : description ?? label, [
798
823
  examples,
799
824
  description,
800
825
  label
801
826
  ]);
802
827
  const fieldState = useFormFieldState(FormField.displayName, path);
828
+ const jsonPath = createJsonPath2(path ?? []);
803
829
  const fieldProps = {
804
830
  type,
805
- format: Format3.FormatAnnotation.getFromAst(type).pipe((annotation) => Option2.getOrUndefined(annotation)),
831
+ format: Format4.FormatAnnotation.getFromAst(type).pipe((annotation) => Option2.getOrUndefined(annotation)),
806
832
  readonly,
807
833
  label,
834
+ jsonPath,
808
835
  placeholder,
809
836
  layout,
837
+ db,
810
838
  ...fieldState
811
839
  };
812
- const jsonPath = createJsonPath2(path ?? []);
840
+ if (readonly && fieldState.getValue() == null) {
841
+ return null;
842
+ }
813
843
  const CustomField = fieldMap?.[jsonPath];
814
844
  if (CustomField) {
815
845
  return /* @__PURE__ */ React2.createElement(CustomField, fieldProps);
816
846
  }
817
847
  const component = fieldProvider?.({
818
848
  schema: Schema.make(type),
819
- prop: name,
849
+ prop: name ?? "",
820
850
  fieldProps
821
851
  });
822
852
  if (component) {
823
853
  return component;
824
854
  }
825
- if (isArrayType2(type)) {
855
+ if (isArrayType3(type)) {
826
856
  return /* @__PURE__ */ React2.createElement(ArrayField, {
827
857
  fieldProps: fieldState,
828
858
  label,
@@ -833,7 +863,7 @@ var FormField = (props) => {
833
863
  if (Field) {
834
864
  return /* @__PURE__ */ React2.createElement(Field, fieldProps);
835
865
  }
836
- const options = getOptions(type);
866
+ const options = getSelectOptions(type);
837
867
  if (options) {
838
868
  const fieldProjections = projection?.getFieldProjections();
839
869
  const fieldProjection = fieldProjections?.find((fp) => fp.field.path === name);
@@ -851,24 +881,36 @@ var FormField = (props) => {
851
881
  }
852
882
  const refProps = getRefProps(type);
853
883
  if (refProps) {
884
+ const inline = Annotation2.FormInlineAnnotation.getFromAst(refProps.ast).pipe(Option2.getOrElse(() => false));
885
+ if (inline && !refProps.isArray) {
886
+ return /* @__PURE__ */ React2.createElement(InlineRefField, {
887
+ ...fieldProps,
888
+ ...refProps,
889
+ db,
890
+ useType: schemaHook,
891
+ onCreate
892
+ });
893
+ }
894
+ const isCreateTarget = !createTypename || refProps.typename === createTypename;
854
895
  return /* @__PURE__ */ React2.createElement(RefField, {
855
896
  ...fieldProps,
856
897
  ...refProps,
857
- createOptionLabel,
858
- createOptionIcon,
859
- createInitialValuePath,
898
+ createOptionLabel: isCreateTarget ? createOptionLabel : void 0,
899
+ createOptionIcon: isCreateTarget ? createOptionIcon : void 0,
900
+ createInitialValuePath: isCreateTarget ? createInitialValuePath : void 0,
901
+ createFieldMap: isCreateTarget ? createFieldMap3 : void 0,
860
902
  db,
861
- schemaHook,
862
- getOptions: getRefOptions,
903
+ useType: schemaHook,
904
+ getOptions,
863
905
  onCreate
864
906
  });
865
907
  }
866
- if (isNestedType(type)) {
908
+ if (isNestedType2(type)) {
867
909
  const baseNode = findNode(type, isDiscriminatedUnion);
868
- const typeLiteral = baseNode ? getDiscriminatedType(baseNode, fieldState.getValue()) : findNode(type, SchemaAST.isTypeLiteral);
910
+ const typeLiteral = baseNode ? getDiscriminatedType(baseNode, fieldState.getValue()) : findNode(type, SchemaAST3.isTypeLiteral);
869
911
  if (typeLiteral) {
870
912
  const schema = Schema.make(typeLiteral);
871
- return /* @__PURE__ */ React2.createElement(FormFieldSet, {
913
+ return /* @__PURE__ */ React2.createElement(Nesting, null, /* @__PURE__ */ React2.createElement(FormFieldSet, {
872
914
  schema,
873
915
  path,
874
916
  readonly,
@@ -881,17 +923,33 @@ var FormField = (props) => {
881
923
  createOptionIcon,
882
924
  createInitialValuePath,
883
925
  db,
884
- schemaHook,
885
- getOptions: getRefOptions,
926
+ useType: schemaHook,
927
+ getOptions,
886
928
  onCreate
887
- });
929
+ }));
888
930
  }
889
931
  }
890
932
  return null;
891
933
  };
892
934
  FormField.displayName = "Form.FormField";
935
+ var Nesting = ({ children }) => /* @__PURE__ */ React2.createElement("div", {
936
+ className: "px-2 border border-subdued-separator rounded-sm mt-2"
937
+ }, /* @__PURE__ */ React2.createElement("div", {
938
+ className: "pb-2"
939
+ }, children));
940
+ var IconBlock = ({ inline, ...props }) => {
941
+ return /* @__PURE__ */ React2.createElement("div", {
942
+ className: mx2("h-full flex px-1", inline ? "items-center" : "flex-col pt-2.5")
943
+ }, /* @__PURE__ */ React2.createElement(IconButton, {
944
+ variant: "ghost",
945
+ density: "xs",
946
+ square: true,
947
+ iconOnly: true,
948
+ ...props
949
+ }));
950
+ };
893
951
  var getFormField = ({ type, format }) => {
894
- const formatField = Match.value(format).pipe(Match.withReturnType(), Match.when(Format3.TypeFormat.GeoPoint, () => GeoPointField), Match.when(Format3.TypeFormat.Markdown, () => MarkdownField), Match.when(Format3.TypeFormat.Text, () => TextAreaField), Match.orElse(() => void 0));
952
+ const formatField = Match.value(format).pipe(Match.withReturnType(), Match.when(Format4.TypeFormat.Date, () => DateField), Match.when(Format4.TypeFormat.DateTime, () => DateField), Match.when(Format4.TypeFormat.GeoPoint, () => GeoPointField), Match.when(Format4.TypeFormat.Markdown, () => MarkdownField), Match.when(Format4.TypeFormat.Text, () => TextAreaField), Match.when(Format4.TypeFormat.Time, () => DateField), Match.orElse(() => void 0));
895
953
  if (formatField) {
896
954
  return formatField;
897
955
  }
@@ -906,67 +964,327 @@ var getFormField = ({ type, format }) => {
906
964
  return BooleanField;
907
965
  }
908
966
  };
909
- var getOptions = (ast) => {
910
- if (isLiteralUnion(ast)) {
967
+ var getSelectOptions = (ast) => {
968
+ if (isLiteralUnion2(ast)) {
911
969
  return ast.types.map((type) => type.literal).filter((v) => v !== null);
912
970
  }
913
- return Format3.OptionsAnnotation.getFromAst(ast).pipe((annotation) => Option2.getOrUndefined(annotation));
971
+ return Format4.OptionsAnnotation.getFromAst(ast).pipe((annotation) => Option2.getOrUndefined(annotation));
914
972
  };
915
973
 
916
- // src/components/Form/FormFieldSet.tsx
917
- var FORM_FIELDSET_NAME = "Form.FieldSet";
918
- var FormFieldSet = /* @__PURE__ */ forwardRef(({ label, schema, readonly, path, exclude, sort, projection, layout, ...props }, forwardRef4) => {
919
- const values = useFormValues(FORM_FIELDSET_NAME, path);
920
- const properties = useMemo3(() => {
921
- if (!schema) {
922
- return [];
974
+ // src/components/Form/Layout/annotation.ts
975
+ import { createAnnotationHelper } from "@dxos/echo/internal";
976
+ var FormLayoutAnnotationId = /* @__PURE__ */ Symbol.for("@dxos/react-ui-form/annotation/Layout");
977
+ var FormLayoutAnnotation = createAnnotationHelper(FormLayoutAnnotationId);
978
+ var DEFAULT_LAYOUT_NAME = "default";
979
+
980
+ // src/components/Form/Layout/FormLayout.tsx
981
+ import * as Option3 from "effect/Option";
982
+ import * as Schema2 from "effect/Schema";
983
+ import * as SchemaAST4 from "effect/SchemaAST";
984
+ import * as String3 from "effect/String";
985
+ import React3, { Fragment, useMemo as useMemo3 } from "react";
986
+ import { Annotation as Annotation3 } from "@dxos/echo";
987
+ import { createJsonPath as createJsonPath3, findNode as findNode2, getAnnotation as getAnnotation3, getBaseType } from "@dxos/effect";
988
+ import { Input as Input2 } from "@dxos/react-ui";
989
+
990
+ // src/components/Form/Layout/parser.ts
991
+ var LayoutParseError = class extends Error {
992
+ position;
993
+ _tag = "LayoutParseError";
994
+ constructor(message, position) {
995
+ super(position !== void 0 ? `${message} (at position ${position})` : message), this.position = position;
996
+ }
997
+ };
998
+ var TAG_RE = /<\s*(\/?)\s*(\w+)([^>]*?)(\/?)\s*>/g;
999
+ var ATTR_RE = /([\w-]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|(\d+))/g;
1000
+ var parseAttrs = (raw) => {
1001
+ const attrs = {};
1002
+ ATTR_RE.lastIndex = 0;
1003
+ let match;
1004
+ while ((match = ATTR_RE.exec(raw)) !== null) {
1005
+ const [, key, doubleQuoted, singleQuoted, bare] = match;
1006
+ attrs[key] = doubleQuoted ?? singleQuoted ?? bare;
1007
+ }
1008
+ return attrs;
1009
+ };
1010
+ var tokenize = (input) => {
1011
+ const tokens = [];
1012
+ TAG_RE.lastIndex = 0;
1013
+ let match;
1014
+ let cursor = 0;
1015
+ while ((match = TAG_RE.exec(input)) !== null) {
1016
+ const between = input.slice(cursor, match.index);
1017
+ if (between.trim().length > 0) {
1018
+ throw new LayoutParseError(`unexpected text content: ${JSON.stringify(between.trim())}`, cursor);
1019
+ }
1020
+ const [, slash, name, attrsRaw, selfSlash] = match;
1021
+ if (slash) {
1022
+ tokens.push({
1023
+ type: "close",
1024
+ name,
1025
+ position: match.index
1026
+ });
1027
+ } else {
1028
+ tokens.push({
1029
+ type: "open",
1030
+ name,
1031
+ attrs: parseAttrs(attrsRaw),
1032
+ selfClosing: selfSlash === "/",
1033
+ position: match.index
1034
+ });
923
1035
  }
924
- const props2 = getFormProperties(schema.ast);
925
- if (projection) {
926
- const fieldProjections = projection.getFieldProjections();
927
- const hiddenProperties = new Set(projection.getHiddenProperties());
928
- const visibleProps = props2.filter((prop) => !hiddenProperties.has(prop.name.toString()));
929
- const orderedProps = [];
930
- for (const fieldProjection of fieldProjections) {
931
- const fieldPath = String(fieldProjection.field.path);
932
- const prop = visibleProps.find((p) => p.name === fieldPath);
933
- if (prop) {
934
- orderedProps.push(prop);
935
- }
1036
+ cursor = match.index + match[0].length;
1037
+ }
1038
+ const trailing = input.slice(cursor);
1039
+ if (trailing.trim().length > 0) {
1040
+ throw new LayoutParseError(`unexpected text content: ${JSON.stringify(trailing.trim())}`, cursor);
1041
+ }
1042
+ return tokens;
1043
+ };
1044
+ var requireAttr = (attrs, key, tag, position) => {
1045
+ const value3 = attrs[key];
1046
+ if (value3 === void 0) {
1047
+ throw new LayoutParseError(`<${tag}> missing required attribute "${key}"`, position);
1048
+ }
1049
+ return value3;
1050
+ };
1051
+ var parseInteger = (value3, attr, tag, position) => {
1052
+ if (!/^\d+$/.test(value3)) {
1053
+ throw new LayoutParseError(`<${tag}> attribute "${attr}" expects an integer, got ${JSON.stringify(value3)}`, position);
1054
+ }
1055
+ return Number.parseInt(value3, 10);
1056
+ };
1057
+ var parseLayout = (template) => {
1058
+ const tokens = tokenize(template);
1059
+ if (tokens.length === 0) {
1060
+ throw new LayoutParseError("empty template");
1061
+ }
1062
+ let index = 0;
1063
+ const parseNode = () => {
1064
+ const token = tokens[index];
1065
+ if (!token || token.type !== "open") {
1066
+ throw new LayoutParseError(`expected an opening tag, got ${JSON.stringify(token)}`, token?.position);
1067
+ }
1068
+ if (token.name === "field") {
1069
+ if (!token.selfClosing) {
1070
+ throw new LayoutParseError('<field> must be self-closing (e.g. <field name="x"/>)', token.position);
936
1071
  }
937
- const projectionPaths = new Set(fieldProjections.map((projection2) => String(projection2.field.path)));
938
- const remainingProps = visibleProps.filter((prop) => !projectionPaths.has(prop.name.toString()));
939
- orderedProps.push(...remainingProps);
940
- return orderedProps;
1072
+ const name = requireAttr(token.attrs, "name", "field", token.position);
1073
+ const spanRaw = token.attrs.span;
1074
+ const span = spanRaw !== void 0 ? parseInteger(spanRaw, "span", "field", token.position) : void 0;
1075
+ index += 1;
1076
+ return {
1077
+ kind: "field",
1078
+ name,
1079
+ span
1080
+ };
941
1081
  }
942
- const filtered = exclude ? exclude(props2) : props2;
943
- return sort ? filtered.sort(({ name: a }, { name: b }) => sort.indexOf(a.toString()) - sort.indexOf(b.toString())) : filtered;
944
- }, [
1082
+ if (token.name === "grid") {
1083
+ if (token.selfClosing) {
1084
+ throw new LayoutParseError("<grid> must wrap children (cannot self-close)", token.position);
1085
+ }
1086
+ const cols = parseInteger(requireAttr(token.attrs, "cols", "grid", token.position), "cols", "grid", token.position);
1087
+ index += 1;
1088
+ const children = [];
1089
+ while (index < tokens.length && !(tokens[index].type === "close" && tokens[index].name === "grid")) {
1090
+ children.push(parseNode());
1091
+ }
1092
+ const closing = tokens[index];
1093
+ if (!closing || closing.type !== "close" || closing.name !== "grid") {
1094
+ throw new LayoutParseError("<grid> not closed", token.position);
1095
+ }
1096
+ index += 1;
1097
+ return {
1098
+ kind: "grid",
1099
+ cols,
1100
+ children
1101
+ };
1102
+ }
1103
+ throw new LayoutParseError(`unknown element <${token.name}>`, token.position);
1104
+ };
1105
+ const root = parseNode();
1106
+ if (index !== tokens.length) {
1107
+ const trailing = tokens[index];
1108
+ throw new LayoutParseError(`unexpected trailing tag <${trailing.type === "open" ? "" : "/"}${trailing.name}>`, trailing.position);
1109
+ }
1110
+ if (root.kind !== "grid") {
1111
+ throw new LayoutParseError("root element must be <grid>");
1112
+ }
1113
+ return root;
1114
+ };
1115
+
1116
+ // src/components/Form/Layout/FormLayout.tsx
1117
+ var FORM_LAYOUT_NAME = "Form.Layout";
1118
+ var FormLayout = ({ schema, template, name = DEFAULT_LAYOUT_NAME, path, readonly, layout, projection, ...props }) => {
1119
+ const annotated = Option3.getOrUndefined(FormLayoutAnnotation.get(schema));
1120
+ const source = template ?? annotated?.[name];
1121
+ if (source === void 0) {
1122
+ throw new LayoutParseError(annotated ? `no layout named "${name}" on schema (available: ${Object.keys(annotated).join(", ") || "\u2205"})` : `no template provided and schema has no FormLayoutAnnotation`);
1123
+ }
1124
+ const tree = useMemo3(() => parseLayout(source), [
1125
+ source
1126
+ ]);
1127
+ return /* @__PURE__ */ React3.createElement(RenderNode, {
1128
+ node: tree,
1129
+ schema,
1130
+ basePath: path ?? [],
1131
+ readonly,
1132
+ layout,
1133
+ projection,
1134
+ ...props
1135
+ });
1136
+ };
1137
+ FormLayout.displayName = FORM_LAYOUT_NAME;
1138
+ var RenderNode = ({ node, schema, basePath, ...props }) => {
1139
+ if (node.kind === "grid") {
1140
+ return /* @__PURE__ */ React3.createElement("div", {
1141
+ className: "grid gap-x-form-gap",
1142
+ style: {
1143
+ gridTemplateColumns: `repeat(${node.cols}, minmax(0, 1fr))`
1144
+ }
1145
+ }, node.children.map((child, index) => /* @__PURE__ */ React3.createElement(Fragment, {
1146
+ key: index
1147
+ }, /* @__PURE__ */ React3.createElement(RenderNode, {
1148
+ node: child,
1149
+ schema,
1150
+ basePath,
1151
+ ...props
1152
+ }))));
1153
+ }
1154
+ const resolved = resolveLayoutField(schema, node.name);
1155
+ if (!resolved) {
1156
+ throw new LayoutParseError(`field "${node.name}" not found on schema`);
1157
+ }
1158
+ const { type, segments, leafName, title, labelType } = resolved;
1159
+ const path = [
1160
+ ...basePath,
1161
+ ...segments
1162
+ ];
1163
+ const span = node.span ? {
1164
+ gridColumn: `span ${node.span} / span ${node.span}`
1165
+ } : void 0;
1166
+ return /* @__PURE__ */ React3.createElement("div", {
1167
+ className: "min-w-0",
1168
+ style: span
1169
+ }, /* @__PURE__ */ React3.createElement(FormFieldErrorBoundary, {
1170
+ path
1171
+ }, labelType ? /* @__PURE__ */ React3.createElement(LabelField, {
1172
+ schema: Schema2.make(labelType),
1173
+ label: title ?? String3.capitalize(leafName),
1174
+ path,
1175
+ layout: props.layout
1176
+ }) : /* @__PURE__ */ React3.createElement(FormField, {
1177
+ type,
1178
+ name: leafName,
1179
+ path,
1180
+ ...props
1181
+ })));
1182
+ };
1183
+ var resolvePropertySignature = (ast, segments) => {
1184
+ let node = ast;
1185
+ for (let index = 0; index < segments.length; index++) {
1186
+ const typeLiteral = findNode2(node, SchemaAST4.isTypeLiteral);
1187
+ if (!typeLiteral) {
1188
+ return void 0;
1189
+ }
1190
+ const prop = SchemaAST4.getPropertySignatures(typeLiteral).find((p) => globalThis.String(p.name) === segments[index]);
1191
+ if (!prop) {
1192
+ return void 0;
1193
+ }
1194
+ if (index === segments.length - 1) {
1195
+ return prop;
1196
+ }
1197
+ node = prop.type;
1198
+ }
1199
+ return void 0;
1200
+ };
1201
+ var resolveLayoutField = (schema, name) => {
1202
+ const segments = name.split(".");
1203
+ const prop = resolvePropertySignature(schema.ast, segments);
1204
+ if (!prop) {
1205
+ return void 0;
1206
+ }
1207
+ const { type: baseType } = getBaseType(prop);
1208
+ const type = prop.annotations && Reflect.ownKeys(prop.annotations).length > 0 ? {
1209
+ ...baseType,
1210
+ annotations: {
1211
+ ...baseType.annotations,
1212
+ ...prop.annotations
1213
+ }
1214
+ } : baseType;
1215
+ const title = getAnnotation3(SchemaAST4.TitleAnnotationId)(type);
1216
+ const labelType = findNode2(prop.type, SchemaAST4.isTypeLiteral);
1217
+ const labelled = labelType != null && Option3.isSome(Annotation3.LabelAnnotation.getFromAst(labelType));
1218
+ return {
1219
+ type,
1220
+ segments,
1221
+ leafName: segments[segments.length - 1],
1222
+ title,
1223
+ labelType: labelled ? labelType : void 0
1224
+ };
1225
+ };
1226
+ var LabelField = ({ schema, label, path, layout }) => {
1227
+ const { getValue } = useFormFieldState(FORM_LAYOUT_NAME, path);
1228
+ const value3 = getValue();
1229
+ const text = value3 == null ? void 0 : Annotation3.getLabelWithSchema(schema, value3);
1230
+ if (text == null || text.trim().length === 0) {
1231
+ return null;
1232
+ }
1233
+ return /* @__PURE__ */ React3.createElement("div", {
1234
+ className: "contents"
1235
+ }, /* @__PURE__ */ React3.createElement(Input2.Root, null, layout !== "inline" && /* @__PURE__ */ React3.createElement(FormFieldLabel, {
1236
+ readonly: true,
1237
+ label,
1238
+ path: createJsonPath3(path)
1239
+ }), /* @__PURE__ */ React3.createElement("p", {
1240
+ className: "truncate min-w-0",
1241
+ title: text
1242
+ }, text)));
1243
+ };
1244
+
1245
+ // src/components/Form/FormFieldSet.tsx
1246
+ var FORM_FIELDSET_NAME = "Form.FieldSet";
1247
+ var FormFieldSet = ({ label, schema, readonly, path, sort, exclude, projection, layout, layoutName = DEFAULT_LAYOUT_NAME, ...props }) => {
1248
+ const values = useFormValues(FORM_FIELDSET_NAME, path);
1249
+ const properties = useFormFieldSetProperties({
945
1250
  schema,
946
1251
  values,
947
1252
  exclude,
948
1253
  sort,
949
- projection?.fields
950
- ]);
1254
+ projection
1255
+ });
951
1256
  if ((readonly || layout === "static") && values == null) {
952
1257
  return null;
953
1258
  }
954
- return /* @__PURE__ */ React3.createElement("div", {
955
- role: "form",
956
- className: mx("w-full", layout === "inline" && "flex flex-col gap-2"),
957
- ref: forwardRef4
958
- }, layout !== "inline" && label && /* @__PURE__ */ React3.createElement(FormFieldLabel, {
1259
+ const layouts = schema ? Option4.getOrUndefined(FormLayoutAnnotation.get(schema)) : void 0;
1260
+ if (layouts?.[layoutName] !== void 0 && schema) {
1261
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, layout !== "inline" && label && /* @__PURE__ */ React4.createElement(FormFieldLabel, {
1262
+ label,
1263
+ path: createJsonPath4(path ?? []),
1264
+ asChild: true
1265
+ }), /* @__PURE__ */ React4.createElement(FormLayout, {
1266
+ schema,
1267
+ name: layoutName,
1268
+ path,
1269
+ readonly,
1270
+ layout,
1271
+ projection,
1272
+ ...props
1273
+ }));
1274
+ }
1275
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, layout !== "inline" && label && /* @__PURE__ */ React4.createElement(FormFieldLabel, {
959
1276
  label,
1277
+ path: createJsonPath4(path ?? []),
960
1278
  asChild: true
961
1279
  }), properties.map((property) => {
962
1280
  const name = property.name.toString();
963
- return /* @__PURE__ */ React3.createElement(FormFieldErrorBoundary, {
1281
+ return /* @__PURE__ */ React4.createElement(FormFieldErrorBoundary, {
964
1282
  key: name,
965
1283
  path: [
966
1284
  ...path ?? [],
967
1285
  name
968
1286
  ]
969
- }, /* @__PURE__ */ React3.createElement(FormField, {
1287
+ }, /* @__PURE__ */ React4.createElement(FormField, {
970
1288
  type: property.type,
971
1289
  name,
972
1290
  path: [
@@ -978,25 +1296,68 @@ var FormFieldSet = /* @__PURE__ */ forwardRef(({ label, schema, readonly, path,
978
1296
  projection,
979
1297
  ...props
980
1298
  }));
981
- }).filter(isTruthy));
982
- });
1299
+ }));
1300
+ };
983
1301
  FormFieldSet.displayName = FORM_FIELDSET_NAME;
1302
+ var useFormFieldSetProperties = ({ schema, exclude, projection, values, sort }) => {
1303
+ return useMemo4(() => {
1304
+ if (!schema) {
1305
+ return [];
1306
+ }
1307
+ const schemaProps = getFormProperties(schema.ast);
1308
+ const filteredProps = exclude ? exclude(schemaProps) : schemaProps;
1309
+ if (projection) {
1310
+ const fieldProjections = projection.getFieldProjections();
1311
+ const hiddenProperties = new Set(projection.getHiddenProperties());
1312
+ const visibleProps = filteredProps.filter((prop) => !hiddenProperties.has(prop.name.toString()));
1313
+ const orderedProps = [];
1314
+ for (const fieldProjection of fieldProjections) {
1315
+ const fieldPath = String(fieldProjection.field.path);
1316
+ const prop = visibleProps.find((prop2) => prop2.name === fieldPath);
1317
+ if (prop) {
1318
+ orderedProps.push(prop);
1319
+ }
1320
+ }
1321
+ const projectionPaths = new Set(fieldProjections.map((projection2) => String(projection2.field.path)));
1322
+ const remainingProps = visibleProps.filter((prop) => !projectionPaths.has(prop.name.toString()));
1323
+ orderedProps.push(...remainingProps);
1324
+ return orderedProps;
1325
+ }
1326
+ return sort ? [
1327
+ ...filteredProps
1328
+ ].sort(({ name: a }, { name: b }) => sort.indexOf(a.toString()) - sort.indexOf(b.toString())) : filteredProps;
1329
+ }, [
1330
+ schema,
1331
+ values,
1332
+ exclude,
1333
+ sort,
1334
+ projection
1335
+ ]);
1336
+ };
984
1337
 
985
1338
  // src/components/Form/Form.tsx
986
- var omitId = (schema) => schema.pipe(Schema2.omit("id"));
987
- var [FormContextProvider, useFormContext] = createContext("Form");
1339
+ var omitId = (schemaOrType) => {
1340
+ const schema = Type.isType(schemaOrType) ? Type.getSchema(schemaOrType) : schemaOrType;
1341
+ return schema.pipe(Schema3.omit("id"));
1342
+ };
1343
+ var omitHiddenFormFields = (schema) => {
1344
+ const properties = SchemaAST5.getPropertySignatures(schema.ast);
1345
+ const hidden = properties.filter((prop) => Option5.getOrElse(EchoAnnotation.FormInputAnnotation.getFromAst(prop.type), () => true) === false).map((prop) => prop.name);
1346
+ return hidden.length === 0 ? schema : schema.pipe(Schema3.omit(...hidden));
1347
+ };
1348
+ var [FormContextProvider, useFormContext] = createContext2("Form");
988
1349
  var useFormValues = (componentName, path, defaultValue) => {
989
- const stablePath = useMemo4(() => path ?? [], [
1350
+ const stablePath = useMemo5(() => path ?? [], [
990
1351
  path ? path.join(".") : void 0
991
1352
  ]);
992
- const jsonPath = createJsonPath3(stablePath);
1353
+ const jsonPath = createJsonPath5(stablePath);
993
1354
  const { form: { values, onValueChange } } = useFormContext(componentName);
994
1355
  const value3 = getValue$2(values, jsonPath);
995
1356
  const lastAppliedPathRef = useRef(null);
996
- useEffect3(() => {
1357
+ useEffect2(() => {
997
1358
  if (value3 == null && defaultValue && lastAppliedPathRef.current !== jsonPath) {
998
1359
  lastAppliedPathRef.current = jsonPath;
999
- onValueChange(stablePath, SchemaAST2.stringKeyword, defaultValue());
1360
+ onValueChange(stablePath, SchemaAST5.stringKeyword, defaultValue());
1000
1361
  }
1001
1362
  }, [
1002
1363
  value3,
@@ -1008,11 +1369,11 @@ var useFormValues = (componentName, path, defaultValue) => {
1008
1369
  return value3;
1009
1370
  };
1010
1371
  var useFormFieldState = (componentName, path = []) => {
1011
- const stablePath = useMemo4(() => path, [
1372
+ const stablePath = useMemo5(() => path, [
1012
1373
  Array.isArray(path) ? path.join(".") : path
1013
1374
  ]);
1014
1375
  const { form: { getStatus, getValue, onBlur, onValueChange } } = useFormContext(componentName);
1015
- return useMemo4(() => ({
1376
+ return useMemo5(() => ({
1016
1377
  getStatus: () => getStatus(stablePath),
1017
1378
  getValue: () => getValue(stablePath),
1018
1379
  onBlur: () => onBlur(stablePath),
@@ -1033,121 +1394,188 @@ var FormRoot = ({ children, schema, values, onSave, onCancel, ...props }) => {
1033
1394
  onCancel,
1034
1395
  ...props
1035
1396
  });
1036
- return /* @__PURE__ */ React4.createElement(FormContextProvider, {
1397
+ return /* @__PURE__ */ React5.createElement(FormTooltipsContext.Provider, {
1398
+ value: props.tooltips ?? true
1399
+ }, /* @__PURE__ */ React5.createElement(FormContextProvider, {
1037
1400
  form,
1038
1401
  ...props
1039
- }, children);
1402
+ }, children));
1040
1403
  };
1041
1404
  FormRoot.displayName = "Form.Root";
1042
1405
  var FORM_VIEWPORT_NAME = "Form.Viewport";
1043
- var FormViewport = ({ children, classNames, margin = true, padding = true, thin = true, ...props }) => {
1044
- return /* @__PURE__ */ React4.createElement(ScrollArea.Root, {
1045
- orientation: "vertical",
1046
- classNames,
1047
- margin,
1048
- padding,
1049
- thin,
1050
- ...props
1051
- }, /* @__PURE__ */ React4.createElement(ScrollArea.Viewport, null, children));
1052
- };
1406
+ var FormViewport = composable(({ children, scroll, gutter = "sm", ...props }, forwardedRef) => {
1407
+ const span = "[.dx-column-root_&]:col-span-full";
1408
+ if (scroll) {
1409
+ return /* @__PURE__ */ React5.createElement(Column.Root, {
1410
+ gutter,
1411
+ classNames: [
1412
+ "dx-expander",
1413
+ span
1414
+ ]
1415
+ }, /* @__PURE__ */ React5.createElement(ScrollArea.Root, {
1416
+ ...composableProps(props),
1417
+ orientation: "vertical",
1418
+ centered: true,
1419
+ padding: true,
1420
+ thin: true,
1421
+ ref: forwardedRef
1422
+ }, /* @__PURE__ */ React5.createElement(ScrollArea.Viewport, null, children)));
1423
+ }
1424
+ return /* @__PURE__ */ React5.createElement(Column.Root, {
1425
+ ...composableProps(props),
1426
+ gutter,
1427
+ classNames: [
1428
+ "w-full min-w-0",
1429
+ span
1430
+ ],
1431
+ ref: forwardedRef
1432
+ }, children);
1433
+ });
1053
1434
  FormViewport.displayName = FORM_VIEWPORT_NAME;
1054
1435
  var FORM_CONTENT_NAME = "Form.Content";
1055
- var FormContent = ({ classNames, children }) => {
1436
+ var FormContent = composable(({ children, ...props }, forwardedRef) => {
1056
1437
  const { form, testId } = useFormContext(FORM_CONTENT_NAME);
1057
- const ref = useRef(null);
1058
- useKeyHandler(ref.current, form);
1059
- return /* @__PURE__ */ React4.createElement("div", {
1060
- ref,
1061
- role: "form",
1062
- className: mx2("w-full flex flex-col gap-form-padding", classNames),
1063
- "data-testid": testId
1438
+ const localRef = useRef(null);
1439
+ const mergedRef = useMergeRefs([
1440
+ forwardedRef,
1441
+ localRef
1442
+ ]);
1443
+ useKeyHandler(localRef, form);
1444
+ return /* @__PURE__ */ React5.createElement("div", {
1445
+ ...composableProps(props, {
1446
+ role: "form",
1447
+ classNames: mx3(withColumn.center(), "flex flex-col w-full")
1448
+ }),
1449
+ "data-testid": testId,
1450
+ ref: mergedRef
1064
1451
  }, children);
1065
- };
1452
+ });
1066
1453
  FormContent.displayName = FORM_CONTENT_NAME;
1067
1454
  var FORM_FIELDSET_NAME2 = "Form.FieldSet";
1068
1455
  var FormFieldSet2 = (props) => {
1069
1456
  const { form, ...contextProps } = useFormContext(FORM_FIELDSET_NAME2);
1070
- return /* @__PURE__ */ React4.createElement(FormFieldSet, {
1457
+ return /* @__PURE__ */ React5.createElement(FormFieldSet, {
1071
1458
  schema: form.schema,
1072
1459
  ...contextProps,
1073
1460
  ...props
1074
1461
  });
1075
1462
  };
1076
1463
  FormFieldSet2.displayName = FORM_FIELDSET_NAME2;
1464
+ var FORM_LAYOUT_NAME2 = "Form.Layout";
1465
+ var FormLayout2 = ({ schema, ...props }) => {
1466
+ const { form, ...contextProps } = useFormContext(FORM_LAYOUT_NAME2);
1467
+ const resolvedSchema = schema ?? form.schema;
1468
+ if (!resolvedSchema) {
1469
+ return null;
1470
+ }
1471
+ return /* @__PURE__ */ React5.createElement(FormLayout, {
1472
+ schema: resolvedSchema,
1473
+ ...contextProps,
1474
+ ...props
1475
+ });
1476
+ };
1477
+ FormLayout2.displayName = FORM_LAYOUT_NAME2;
1077
1478
  var FORM_ACTIONS_NAME = "Form.Actions";
1078
1479
  var FormActions = ({ classNames }) => {
1079
- const { t } = useTranslation2(translationKey);
1480
+ const { t } = useTranslation2(translationKey2);
1080
1481
  const { form: { canSave, onSave, onCancel }, readonly, layout } = useFormContext(FORM_ACTIONS_NAME);
1081
1482
  if (readonly || layout === "static") {
1082
1483
  return null;
1083
1484
  }
1084
- return /* @__PURE__ */ React4.createElement("div", {
1085
- role: "none",
1086
- className: mx2("grid grid-flow-col gap-2 auto-cols-fr py-form-padding", classNames)
1087
- }, onCancel && /* @__PURE__ */ React4.createElement(IconButton, {
1485
+ return /* @__PURE__ */ React5.createElement("div", {
1486
+ className: mx3(withColumn.center(), "grid grid-flow-col gap-form-gap auto-cols-fr py-form-padding", classNames)
1487
+ }, onCancel && /* @__PURE__ */ React5.createElement(IconButton2, {
1088
1488
  icon: "ph--x--regular",
1089
1489
  iconEnd: true,
1090
- label: t("cancel button label"),
1490
+ label: t("cancel-button.label"),
1091
1491
  onClick: onCancel,
1092
1492
  "data-testid": "cancel-button"
1093
- }), onSave && /* @__PURE__ */ React4.createElement(IconButton, {
1493
+ }), onSave && /* @__PURE__ */ React5.createElement(IconButton2, {
1094
1494
  type: "submit",
1095
1495
  variant: "primary",
1096
1496
  disabled: !canSave,
1097
1497
  icon: "ph--check--regular",
1098
1498
  iconEnd: true,
1099
- label: t("save button label"),
1499
+ label: t("save-button.label"),
1100
1500
  onClick: onSave,
1101
1501
  "data-testid": "save-button"
1102
1502
  }));
1103
1503
  };
1104
1504
  FormActions.displayName = FORM_ACTIONS_NAME;
1505
+ var FORM_SECTION_NAME = "Form.Section";
1506
+ var FormSection = composable(({ children, label, description, ...props }, forwardedRef) => {
1507
+ return /* @__PURE__ */ React5.createElement("div", {
1508
+ ...composableProps(props, {
1509
+ classNames: "flex flex-col pt-form-section-gap first:pt-0"
1510
+ }),
1511
+ ref: forwardedRef
1512
+ }, label && /* @__PURE__ */ React5.createElement("h2", {
1513
+ className: "text-lg"
1514
+ }, label), description && /* @__PURE__ */ React5.createElement("p", {
1515
+ className: "text-description"
1516
+ }, description), children);
1517
+ });
1518
+ FormSection.displayName = FORM_SECTION_NAME;
1105
1519
  var FORM_SUBMIT_NAME = "Form.Submit";
1106
1520
  var FormSubmit = ({ classNames, label, icon, disabled }) => {
1107
- const { t } = useTranslation2(translationKey);
1521
+ const { t } = useTranslation2(translationKey2);
1108
1522
  const { form: { canSave, onSave }, readonly, layout } = useFormContext(FORM_SUBMIT_NAME);
1109
1523
  if (readonly || layout === "static") {
1110
1524
  return null;
1111
1525
  }
1112
- return /* @__PURE__ */ React4.createElement("div", {
1113
- role: "none",
1114
- className: mx2("flex w-full pt-form-padding", classNames)
1115
- }, /* @__PURE__ */ React4.createElement(IconButton, {
1526
+ return /* @__PURE__ */ React5.createElement("div", {
1527
+ className: mx3("flex w-full pt-form-padding", classNames)
1528
+ }, /* @__PURE__ */ React5.createElement(IconButton2, {
1116
1529
  classNames: "w-full",
1117
1530
  type: "submit",
1118
1531
  variant: "primary",
1119
1532
  disabled: disabled ?? !canSave,
1120
1533
  icon: icon ?? "ph--check--regular",
1121
- label: label ?? t("save button label"),
1534
+ label: label ?? t("save-button.label"),
1122
1535
  onClick: onSave,
1123
1536
  "data-testid": "save-button"
1124
1537
  }));
1125
1538
  };
1126
1539
  FormSubmit.displayName = FORM_SUBMIT_NAME;
1540
+ var FORM_ERROR_NAME = "Form.Error";
1541
+ var FormError = ({ children, classNames }) => {
1542
+ if (!children) {
1543
+ return null;
1544
+ }
1545
+ return /* @__PURE__ */ React5.createElement(Input3.Root, {
1546
+ validationValence: "error"
1547
+ }, /* @__PURE__ */ React5.createElement(Input3.Validation, {
1548
+ classNames
1549
+ }, children));
1550
+ };
1551
+ FormError.displayName = FORM_ERROR_NAME;
1127
1552
  var Form = {
1128
1553
  Root: FormRoot,
1129
1554
  Viewport: FormViewport,
1130
1555
  Content: FormContent,
1556
+ Section: FormSection,
1131
1557
  FieldSet: FormFieldSet2,
1558
+ Layout: FormLayout2,
1132
1559
  Label: FormFieldLabel,
1133
1560
  Actions: FormActions,
1134
- Submit: FormSubmit
1561
+ Submit: FormSubmit,
1562
+ Error: FormError
1135
1563
  };
1136
1564
 
1137
1565
  // src/components/Form/fields/ArrayField.tsx
1138
1566
  var ArrayField = ({ type, path, label, readonly, layout, fieldProps: inputProps, ...props }) => {
1139
- const { t } = useTranslation3(translationKey);
1567
+ const { t } = useTranslation3(translationKey3);
1140
1568
  const elementType = getArrayElementType2(type);
1141
1569
  const { onValueChange } = inputProps;
1142
1570
  const values = useFormValues(ArrayField.displayName, path, () => []);
1143
1571
  const getDefaultObjectValue = (typeNode) => {
1144
- const baseNode = findNode2(typeNode, isDiscriminatedUnion2);
1145
- const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, {}) : findNode2(typeNode, SchemaAST3.isTypeLiteral);
1572
+ const baseNode = findNode3(typeNode, isDiscriminatedUnion2);
1573
+ const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, {}) : findNode3(typeNode, SchemaAST6.isTypeLiteral);
1146
1574
  if (!typeLiteral) {
1147
1575
  return {};
1148
1576
  }
1149
1577
  return Object.fromEntries(getFormProperties(typeLiteral).map((prop) => {
1150
- const defaultValue = SchemaAST3.getDefaultAnnotation(prop.type).pipe((annotation) => Option3.getOrUndefined(annotation));
1578
+ const defaultValue = SchemaAST6.getDefaultAnnotation(prop.type).pipe((annotation) => Option6.getOrUndefined(annotation));
1151
1579
  return [
1152
1580
  prop.name,
1153
1581
  defaultValue
@@ -1155,9 +1583,9 @@ var ArrayField = ({ type, path, label, readonly, layout, fieldProps: inputProps,
1155
1583
  }));
1156
1584
  };
1157
1585
  const handleAdd = useCallback3(() => {
1158
- const defaultValue = isNestedType2(type) && elementType ? getDefaultObjectValue(elementType) : getDefaultValue(elementType);
1159
- values && onValueChange(type, [
1160
- ...values,
1586
+ const defaultValue = isNestedType3(type) && elementType ? getDefaultObjectValue(elementType) : getDefaultValue(elementType);
1587
+ onValueChange(type, [
1588
+ ...values ?? [],
1161
1589
  defaultValue
1162
1590
  ]);
1163
1591
  }, [
@@ -1176,47 +1604,49 @@ var ArrayField = ({ type, path, label, readonly, layout, fieldProps: inputProps,
1176
1604
  if (!elementType || (readonly || layout === "static") && values && values.length < 1) {
1177
1605
  return null;
1178
1606
  }
1179
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, (layout !== "static" || values && values.length > 0) && /* @__PURE__ */ React5.createElement(FormFieldLabel, {
1607
+ const renderItemAsObject = elementType && isNestedType3(elementType) && !Ref2.isRefType(elementType);
1608
+ return /* @__PURE__ */ React6.createElement(React6.Fragment, null, (layout !== "static" || values && values.length > 0) && /* @__PURE__ */ React6.createElement("div", {
1609
+ className: "flex items-center gap-2"
1610
+ }, /* @__PURE__ */ React6.createElement("div", {
1611
+ className: "flex-1 min-w-0"
1612
+ }, /* @__PURE__ */ React6.createElement(FormFieldLabel, {
1180
1613
  readonly,
1181
1614
  label,
1615
+ path: createJsonPath6(path ?? []),
1182
1616
  asChild: true
1183
- }), /* @__PURE__ */ React5.createElement("div", {
1184
- role: "none",
1185
- className: "flex flex-col gap-2"
1617
+ })), !readonly && layout !== "static" && /* @__PURE__ */ React6.createElement(IconBlock, {
1618
+ inline: true,
1619
+ icon: "ph--plus--regular",
1620
+ label: t("add-item.button"),
1621
+ onClick: handleAdd
1622
+ })), /* @__PURE__ */ React6.createElement("div", {
1623
+ className: "flex flex-col"
1186
1624
  }, values?.map((_, index) => {
1187
- return /* @__PURE__ */ React5.createElement("div", {
1188
- role: "none",
1189
- key: index,
1190
- className: "grid grid-cols-[1fr_min-content] gap-2 last:mb-3"
1191
- }, /* @__PURE__ */ React5.createElement(FormField, {
1192
- autoFocus: index === values.length - 1,
1625
+ const isLast = index === values.length - 1;
1626
+ const fieldField = /* @__PURE__ */ React6.createElement(FormField, {
1627
+ ...props,
1628
+ autoFocus: isLast,
1193
1629
  type: elementType,
1630
+ ...renderItemAsObject && {
1631
+ name: null
1632
+ },
1194
1633
  path: [
1195
1634
  ...path ?? [],
1196
1635
  index
1197
1636
  ],
1198
1637
  readonly: readonly || layout === "static",
1199
- layout: "inline",
1200
- ...props
1201
- }), !readonly && layout !== "static" && /* @__PURE__ */ React5.createElement("div", {
1202
- role: "none",
1203
- className: "flex flex-col h-full justify-end"
1204
- }, /* @__PURE__ */ React5.createElement("div", {
1205
- role: "none",
1206
- className: "flex items-center h-[2rem]"
1207
- }, /* @__PURE__ */ React5.createElement(IconButton2, {
1638
+ layout: renderItemAsObject ? layout === "static" ? "static" : void 0 : "inline"
1639
+ });
1640
+ return /* @__PURE__ */ React6.createElement("div", {
1641
+ key: index,
1642
+ className: "grid grid-cols-[1fr_min-content] items-center mb-1 last:mb-form-gap"
1643
+ }, fieldField, !readonly && layout !== "static" && /* @__PURE__ */ React6.createElement(IconBlock, {
1644
+ inline: !renderItemAsObject,
1208
1645
  icon: "ph--x--regular",
1209
- iconOnly: true,
1210
- label: t("button remove"),
1211
- onClick: () => handleDelete(index),
1212
- classNames: "self-center"
1213
- }))));
1214
- })), !readonly && layout !== "static" && /* @__PURE__ */ React5.createElement(IconButton2, {
1215
- classNames: "flex w-full",
1216
- icon: "ph--plus--regular",
1217
- label: t("add field"),
1218
- onClick: handleAdd
1219
- }));
1646
+ label: t("remove-item.button"),
1647
+ onClick: () => handleDelete(index)
1648
+ }));
1649
+ })));
1220
1650
  };
1221
1651
  ArrayField.displayName = "Form.ArrayField";
1222
1652
  var getDefaultValue = (ast) => {
@@ -1234,7 +1664,7 @@ var getDefaultValue = (ast) => {
1234
1664
  return getDefaultValue(ast.f());
1235
1665
  }
1236
1666
  default: {
1237
- if (ast && isNestedType2(ast)) {
1667
+ if (ast && isNestedType3(ast)) {
1238
1668
  return {};
1239
1669
  } else {
1240
1670
  throw new Error(`Unsupported type: ${ast?._tag}`);
@@ -1244,50 +1674,124 @@ var getDefaultValue = (ast) => {
1244
1674
  };
1245
1675
 
1246
1676
  // src/components/Form/fields/BooleanField.tsx
1247
- import React6, { useCallback as useCallback4 } from "react";
1248
- import { Input as Input2 } from "@dxos/react-ui";
1677
+ import React7, { useCallback as useCallback4 } from "react";
1678
+ import { Input as Input4 } from "@dxos/react-ui";
1249
1679
  var BooleanField = ({ type, readonly, onValueChange, ...props }) => {
1250
1680
  const handleChange = useCallback4((value3) => onValueChange?.(type, value3), [
1251
1681
  type,
1252
1682
  onValueChange
1253
1683
  ]);
1254
- return /* @__PURE__ */ React6.createElement(FormFieldWrapper, {
1684
+ return /* @__PURE__ */ React7.createElement(FormFieldWrapper, {
1255
1685
  readonly,
1256
1686
  ...props
1257
- }, ({ value: value3 }) => /* @__PURE__ */ React6.createElement(Input2.Switch, {
1687
+ }, ({ value: value3 }) => /* @__PURE__ */ React7.createElement(Input4.Switch, {
1258
1688
  disabled: !!readonly,
1259
1689
  checked: value3,
1260
1690
  onCheckedChange: handleChange
1261
1691
  }));
1262
1692
  };
1263
1693
 
1694
+ // src/components/Form/fields/DateField.tsx
1695
+ import { format as formatDate3 } from "date-fns";
1696
+ import React8, { useCallback as useCallback5 } from "react";
1697
+ import { Format as Format5 } from "@dxos/echo";
1698
+ import { Input as Input5 } from "@dxos/react-ui";
1699
+ var isoToLocalDateTime = (value3) => {
1700
+ if (!value3) {
1701
+ return "";
1702
+ }
1703
+ const date = new Date(value3);
1704
+ if (Number.isNaN(date.getTime())) {
1705
+ return "";
1706
+ }
1707
+ return formatDate3(date, "yyyy-MM-dd'T'HH:mm");
1708
+ };
1709
+ var localDateTimeToIso = (value3) => {
1710
+ if (!value3) {
1711
+ return void 0;
1712
+ }
1713
+ const date = new Date(value3);
1714
+ return Number.isNaN(date.getTime()) ? void 0 : date.toISOString();
1715
+ };
1716
+ var DateField = ({ type, format, readonly, placeholder: _placeholder, onValueChange, onBlur: _onBlur, ...props }) => {
1717
+ const handleSimpleChange = useCallback5((next) => onValueChange(type, next), [
1718
+ type,
1719
+ onValueChange
1720
+ ]);
1721
+ const handleDateTimeChange = useCallback5((next) => {
1722
+ const iso = localDateTimeToIso(next);
1723
+ onValueChange(type, iso);
1724
+ }, [
1725
+ type,
1726
+ onValueChange
1727
+ ]);
1728
+ return /* @__PURE__ */ React8.createElement(FormFieldWrapper, {
1729
+ readonly,
1730
+ format,
1731
+ ...props
1732
+ }, ({ value: value3 }) => {
1733
+ switch (format) {
1734
+ case Format5.TypeFormat.Date:
1735
+ return /* @__PURE__ */ React8.createElement("div", {
1736
+ className: "grid grid-cols-[minmax(0,1fr)_min-content] items-stretch gap-1"
1737
+ }, /* @__PURE__ */ React8.createElement(Input5.Date, {
1738
+ classNames: "min-w-0 overflow-hidden",
1739
+ disabled: !!readonly,
1740
+ value: value3 ?? "",
1741
+ onValueChange: handleSimpleChange
1742
+ }), /* @__PURE__ */ React8.createElement(Input5.TriggerIcon, {
1743
+ classNames: "h-full"
1744
+ }));
1745
+ case Format5.TypeFormat.Time:
1746
+ return /* @__PURE__ */ React8.createElement(Input5.Time, {
1747
+ disabled: !!readonly,
1748
+ value: value3 ?? "",
1749
+ onValueChange: handleSimpleChange
1750
+ });
1751
+ case Format5.TypeFormat.DateTime:
1752
+ default:
1753
+ return /* @__PURE__ */ React8.createElement("div", {
1754
+ className: "grid grid-cols-[minmax(0,1fr)_min-content] items-stretch gap-1"
1755
+ }, /* @__PURE__ */ React8.createElement(Input5.DateTime, {
1756
+ classNames: "min-w-0 overflow-hidden",
1757
+ disabled: !!readonly,
1758
+ value: isoToLocalDateTime(value3),
1759
+ onValueChange: handleDateTimeChange
1760
+ }), /* @__PURE__ */ React8.createElement(Input5.TriggerIcon, {
1761
+ classNames: "h-full"
1762
+ }));
1763
+ }
1764
+ });
1765
+ };
1766
+
1264
1767
  // src/components/Form/fields/GeoPointField.tsx
1265
- import React7, { useCallback as useCallback5, useEffect as useEffect4, useMemo as useMemo5, useState as useState2 } from "react";
1768
+ import React9, { useCallback as useCallback6, useEffect as useEffect3, useMemo as useMemo6, useState as useState2 } from "react";
1266
1769
  import { GeoLocation as GeoLocation3 } from "@dxos/echo/internal";
1267
- import { Input as Input3, useTranslation as useTranslation4 } from "@dxos/react-ui";
1770
+ import { Input as Input6, useTranslation as useTranslation4 } from "@dxos/react-ui";
1268
1771
  import { safeParseFloat } from "@dxos/util";
1269
- var GeoPointField = ({ type, label, readonly, layout, getStatus, getValue, onValueChange, onBlur }) => {
1270
- const { t } = useTranslation4(translationKey);
1772
+ import { translationKey as translationKey4 } from "#translations";
1773
+ var GeoPointField = ({ type, label, jsonPath, readonly, layout, getStatus, getValue, onValueChange, onBlur }) => {
1774
+ const { t } = useTranslation4(translationKey4);
1271
1775
  const { status, error } = getStatus();
1272
- const geoPoint = useMemo5(() => getValue() ?? [
1776
+ const geoPoint = useMemo6(() => getValue() ?? [
1273
1777
  0,
1274
1778
  0
1275
1779
  ], [
1276
1780
  getValue
1277
1781
  ]);
1278
- const value3 = useMemo5(() => GeoLocation3.fromGeoPoint(geoPoint), [
1782
+ const value3 = useMemo6(() => GeoLocation3.fromGeoPoint(geoPoint), [
1279
1783
  geoPoint
1280
1784
  ]);
1281
1785
  const [longitudeText, setLongitudeText] = useState2(value3.longitude?.toString());
1282
1786
  const [latitudeText, setLatitudeText] = useState2(value3.latitude?.toString());
1283
- useEffect4(() => {
1787
+ useEffect3(() => {
1284
1788
  const location = GeoLocation3.fromGeoPoint(geoPoint);
1285
1789
  setLongitudeText(location.longitude?.toString());
1286
1790
  setLatitudeText(location.latitude?.toString());
1287
1791
  }, [
1288
1792
  geoPoint
1289
1793
  ]);
1290
- const handleChange = useCallback5((coordinateType, setText) => (event) => {
1794
+ const handleChange = useCallback6((coordinateType, setText) => (event) => {
1291
1795
  const inputText = event.target.value;
1292
1796
  setText(inputText);
1293
1797
  if (inputText !== "" && inputText !== "-") {
@@ -1313,33 +1817,33 @@ var GeoPointField = ({ type, label, readonly, layout, getStatus, getValue, onVal
1313
1817
  if ((readonly || layout === "static") && !value3?.latitude && !value3?.longitude) {
1314
1818
  return null;
1315
1819
  }
1316
- return /* @__PURE__ */ React7.createElement(Input3.Root, {
1820
+ return /* @__PURE__ */ React9.createElement(Input6.Root, {
1317
1821
  validationValence: status
1318
- }, layout !== "inline" && /* @__PURE__ */ React7.createElement(FormFieldLabel, {
1822
+ }, layout !== "inline" && /* @__PURE__ */ React9.createElement(FormFieldLabel, {
1319
1823
  error,
1320
1824
  readonly,
1321
1825
  label,
1826
+ path: jsonPath,
1322
1827
  asChild: true
1323
- }), layout === "static" ? /* @__PURE__ */ React7.createElement(LatLng, value3) : /* @__PURE__ */ React7.createElement("div", {
1324
- role: "none",
1325
- className: "grid grid-cols-2 gap-2"
1326
- }, /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("latitude label")), /* @__PURE__ */ React7.createElement(Input3.TextInput, {
1828
+ }), layout === "static" ? /* @__PURE__ */ React9.createElement(LatLng, value3) : /* @__PURE__ */ React9.createElement("div", {
1829
+ className: "grid grid-cols-2 gap-form-gap"
1830
+ }, /* @__PURE__ */ React9.createElement("div", null, /* @__PURE__ */ React9.createElement(Input6.Root, null, layout !== "inline" && /* @__PURE__ */ React9.createElement(Input6.Label, null, t("latitude.label")), /* @__PURE__ */ React9.createElement(Input6.TextInput, {
1327
1831
  type: "number",
1328
1832
  step: "0.00001",
1329
1833
  min: "-90",
1330
1834
  max: "90",
1331
1835
  disabled: !!readonly,
1332
- placeholder: t("latitude placeholder"),
1836
+ placeholder: t("latitude.placeholder"),
1333
1837
  value: latitudeText ?? "",
1334
1838
  onChange: handleChange("latitude", setLatitudeText),
1335
1839
  onBlur
1336
- }))), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement(Input3.Root, null, layout !== "inline" && /* @__PURE__ */ React7.createElement(Input3.Label, null, t("longitude label")), /* @__PURE__ */ React7.createElement(Input3.TextInput, {
1840
+ }))), /* @__PURE__ */ React9.createElement("div", null, /* @__PURE__ */ React9.createElement(Input6.Root, null, layout !== "inline" && /* @__PURE__ */ React9.createElement(Input6.Label, null, t("longitude.label")), /* @__PURE__ */ React9.createElement(Input6.TextInput, {
1337
1841
  type: "number",
1338
1842
  step: "0.00001",
1339
1843
  min: "-180",
1340
1844
  max: "180",
1341
1845
  disabled: !!readonly,
1342
- placeholder: t("longitude placeholder"),
1846
+ placeholder: t("longitude.placeholder"),
1343
1847
  value: longitudeText ?? "",
1344
1848
  onChange: handleChange("longitude", setLongitudeText),
1345
1849
  onBlur
@@ -1348,81 +1852,265 @@ var GeoPointField = ({ type, label, readonly, layout, getStatus, getValue, onVal
1348
1852
  var LatLng = ({ latitude = 0, longitude = 0 }) => {
1349
1853
  const latHem = latitude >= 0 ? "N" : "S";
1350
1854
  const lngHem = longitude >= 0 ? "E" : "W";
1351
- return /* @__PURE__ */ React7.createElement("span", {
1352
- className: "inline-flex items-center gap-1"
1353
- }, /* @__PURE__ */ React7.createElement("span", null, /* @__PURE__ */ React7.createElement("span", null, Math.abs(latitude).toFixed(5)), /* @__PURE__ */ React7.createElement("span", {
1855
+ return /* @__PURE__ */ React9.createElement("span", {
1856
+ className: "inline-flex items-center gap-form-gap"
1857
+ }, /* @__PURE__ */ React9.createElement("span", null, /* @__PURE__ */ React9.createElement("span", null, Math.abs(latitude).toFixed(5)), /* @__PURE__ */ React9.createElement("span", {
1354
1858
  className: "text-subdued"
1355
- }, "\xB0", latHem)), /* @__PURE__ */ React7.createElement("span", null, /* @__PURE__ */ React7.createElement("span", null, Math.abs(longitude).toFixed(5)), /* @__PURE__ */ React7.createElement("span", {
1859
+ }, "\xB0", latHem)), /* @__PURE__ */ React9.createElement("span", null, /* @__PURE__ */ React9.createElement("span", null, Math.abs(longitude).toFixed(5)), /* @__PURE__ */ React9.createElement("span", {
1356
1860
  className: "text-subdued"
1357
1861
  }, "\xB0", lngHem)));
1358
1862
  };
1359
1863
 
1360
- // src/components/Form/fields/MarkdownField.tsx
1361
- import React8, { useCallback as useCallback6, useEffect as useEffect5, useRef as useRef2 } from "react";
1362
- import { Input as Input4 } from "@dxos/react-ui";
1363
- var MarkdownField = ({ type, readonly, label, placeholder, layout, getStatus, getValue, onValueChange, onBlur }) => {
1364
- const { status, error } = getStatus();
1365
- const textareaRef = useRef2(null);
1366
- const adjustHeight = useCallback6(() => {
1367
- const textarea = textareaRef.current;
1368
- if (textarea) {
1369
- textarea.style.blockSize = "auto";
1370
- textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
1371
- }
1372
- }, []);
1373
- useEffect5(() => {
1374
- adjustHeight();
1375
- }, [
1376
- adjustHeight
1864
+ // src/components/Form/fields/InlineRefField.tsx
1865
+ import { useAtomValue } from "@effect-atom/atom-react";
1866
+ import React10, { useCallback as useCallback7, useMemo as useMemo7 } from "react";
1867
+ import { Obj, Ref as Ref3, Type as Type2 } from "@dxos/echo";
1868
+ import { AtomRef } from "@dxos/echo-atom";
1869
+ import { useType as defaultUseType } from "@dxos/echo-react";
1870
+ import { ReferenceAnnotationId as ReferenceAnnotationId2, splitJsonPath } from "@dxos/echo/internal";
1871
+ import { findAnnotation as findAnnotation2 } from "@dxos/effect";
1872
+ import { Button, Icon as Icon2, Input as Input7, useTranslation as useTranslation5 } from "@dxos/react-ui";
1873
+ import { translationKey as translationKey5 } from "#translations";
1874
+ var InlineRefField = (props) => {
1875
+ const { type, readonly, label, jsonPath, layout, db, getValue, onValueChange, onCreate, useType: useType2 = defaultUseType } = props;
1876
+ const { t } = useTranslation5(translationKey5);
1877
+ const reference = getValue();
1878
+ const typename = useMemo7(() => type ? findAnnotation2(type, ReferenceAnnotationId2)?.typename : void 0, [
1879
+ type
1377
1880
  ]);
1378
- useEffect5(() => {
1379
- adjustHeight();
1881
+ const createType = useType2(db, typename);
1882
+ const handleCreate = useCallback7(async () => {
1883
+ if (!createType || !onCreate) {
1884
+ return;
1885
+ }
1886
+ const newObject = await onCreate(createType, {});
1887
+ if (newObject) {
1888
+ onValueChange(type, Ref3.make(newObject));
1889
+ }
1380
1890
  }, [
1381
- getValue(),
1382
- adjustHeight
1383
- ]);
1384
- const handleChange = useCallback6((event) => onValueChange(type, event.target.value), [
1891
+ createType,
1892
+ onCreate,
1385
1893
  type,
1386
1894
  onValueChange
1387
1895
  ]);
1896
+ if (readonly && !reference) {
1897
+ return null;
1898
+ }
1899
+ return /* @__PURE__ */ React10.createElement(Input7.Root, null, layout !== "inline" && /* @__PURE__ */ React10.createElement(FormFieldLabel, {
1900
+ readonly,
1901
+ label,
1902
+ path: jsonPath
1903
+ }), reference ? /* @__PURE__ */ React10.createElement(InlineForm, {
1904
+ reference,
1905
+ db,
1906
+ readonly,
1907
+ useType: useType2
1908
+ }) : !readonly && onCreate && /* @__PURE__ */ React10.createElement(Button, {
1909
+ classNames: "w-full gap-form-gap",
1910
+ disabled: !createType || !db,
1911
+ onClick: () => void handleCreate()
1912
+ }, /* @__PURE__ */ React10.createElement(Icon2, {
1913
+ icon: "ph--plus--regular",
1914
+ size: 4
1915
+ }), /* @__PURE__ */ React10.createElement("span", null, label || t("ref-field.placeholder"))));
1916
+ };
1917
+ var InlineForm = ({ reference, db, readonly, useType: useType2 = defaultUseType }) => {
1918
+ const target = useAtomValue(useMemo7(() => AtomRef.make(reference), [
1919
+ reference
1920
+ ]));
1921
+ const typename = target ? Obj.getTypename(target) ?? void 0 : void 0;
1922
+ const typeFromRegistry = useType2(db, typename);
1923
+ const targetType = target && Obj.getType(target) || typeFromRegistry;
1924
+ const formSchema = useMemo7(() => targetType ? omitId(Type2.getSchema(targetType)) : void 0, [
1925
+ targetType
1926
+ ]);
1927
+ const defaultValues = useMemo7(() => target ? {
1928
+ ...target
1929
+ } : {}, [
1930
+ target
1931
+ ]);
1932
+ const handleChange = useCallback7((values, { isValid, changed }) => {
1933
+ if (!isValid || !target) {
1934
+ return;
1935
+ }
1936
+ const changedPaths = Object.keys(changed).filter((path) => changed[path]);
1937
+ if (changedPaths.length === 0) {
1938
+ return;
1939
+ }
1940
+ Obj.update(target, () => {
1941
+ for (const path of changedPaths) {
1942
+ const parts = splitJsonPath(path);
1943
+ Obj.setValue(target, parts, Obj.getValue(values, parts));
1944
+ }
1945
+ });
1946
+ }, [
1947
+ target
1948
+ ]);
1949
+ if (!target || !formSchema) {
1950
+ return null;
1951
+ }
1952
+ return /* @__PURE__ */ React10.createElement(Nesting, null, /* @__PURE__ */ React10.createElement(Form.Root, {
1953
+ schema: formSchema,
1954
+ defaultValues,
1955
+ db,
1956
+ onValuesChanged: handleChange
1957
+ }, /* @__PURE__ */ React10.createElement(Form.Content, null, /* @__PURE__ */ React10.createElement(Form.FieldSet, {
1958
+ readonly
1959
+ }))));
1960
+ };
1961
+
1962
+ // src/components/Form/fields/MarkdownField.tsx
1963
+ import { useAtomValue as useAtomValue2 } from "@effect-atom/atom-react";
1964
+ import React11, { useCallback as useCallback8, useMemo as useMemo8 } from "react";
1965
+ import { Obj as Obj2, Ref as Ref4 } from "@dxos/echo";
1966
+ import { AtomRef as AtomRef2 } from "@dxos/echo-atom";
1967
+ import { createDocAccessor } from "@dxos/echo-db";
1968
+ import { Button as Button2, Icon as Icon3, Input as Input8, useTranslation as useTranslation6 } from "@dxos/react-ui";
1969
+ import { Editor, useBasicMarkdownExtensions } from "@dxos/react-ui-editor";
1970
+ import { Text } from "@dxos/schema";
1971
+ import { createDataExtensions } from "@dxos/ui-editor";
1972
+ import { translationKey as translationKey6 } from "#translations";
1973
+ var editorClassNames = "transition-colors bg-input-surface focus-within:bg-focus-surface border border-separator rounded-xs p-1 px-2";
1974
+ var MarkdownField = ({ type, readonly, label, jsonPath, placeholder, layout, db, getStatus, getValue, onValueChange }) => {
1975
+ const { status, error } = getStatus();
1976
+ const isRef = Ref4.isRefType(type);
1388
1977
  const value3 = getValue();
1389
- if ((readonly || layout === "static") && !value3) {
1978
+ if ((readonly || layout === "static") && value3 == null) {
1390
1979
  return null;
1391
1980
  }
1392
- return /* @__PURE__ */ React8.createElement(Input4.Root, {
1981
+ const renderEditor = () => {
1982
+ if (isRef) {
1983
+ const reference = value3;
1984
+ if (reference) {
1985
+ return /* @__PURE__ */ React11.createElement(RefMarkdownEditor, {
1986
+ reference,
1987
+ placeholder
1988
+ });
1989
+ }
1990
+ if (readonly) {
1991
+ return null;
1992
+ }
1993
+ return /* @__PURE__ */ React11.createElement(CreateTextButton, {
1994
+ db,
1995
+ disabled: !db,
1996
+ onCreate: (ref) => onValueChange(type, ref)
1997
+ });
1998
+ }
1999
+ return /* @__PURE__ */ React11.createElement(StringMarkdownEditor, {
2000
+ value: value3 ?? "",
2001
+ placeholder,
2002
+ readonly: !!readonly,
2003
+ onChange: (next) => onValueChange(type, next)
2004
+ });
2005
+ };
2006
+ const renderStatic = () => {
2007
+ if (isRef) {
2008
+ const reference = value3;
2009
+ return reference ? /* @__PURE__ */ React11.createElement(RefStaticText, {
2010
+ reference
2011
+ }) : null;
2012
+ }
2013
+ return /* @__PURE__ */ React11.createElement("p", {
2014
+ className: "whitespace-pre-wrap"
2015
+ }, value3 ?? "");
2016
+ };
2017
+ return /* @__PURE__ */ React11.createElement(Input8.Root, {
1393
2018
  validationValence: status
1394
- }, layout !== "inline" && /* @__PURE__ */ React8.createElement(FormFieldLabel, {
2019
+ }, layout !== "inline" && /* @__PURE__ */ React11.createElement(FormFieldLabel, {
1395
2020
  error,
1396
2021
  readonly,
1397
- label
1398
- }), layout === "static" ? /* @__PURE__ */ React8.createElement("p", null, value3) : /* @__PURE__ */ React8.createElement(Input4.TextArea, {
1399
- ref: textareaRef,
1400
- disabled: !!readonly,
2022
+ label,
2023
+ path: jsonPath
2024
+ }), layout === "static" ? renderStatic() : renderEditor(), layout === "full" && /* @__PURE__ */ React11.createElement(Input8.Validation, null, error));
2025
+ };
2026
+ var RefStaticText = ({ reference }) => {
2027
+ const text = useAtomValue2(useMemo8(() => AtomRef2.make(reference), [
2028
+ reference
2029
+ ]));
2030
+ if (!text?.content) {
2031
+ return null;
2032
+ }
2033
+ return /* @__PURE__ */ React11.createElement("p", {
2034
+ className: "whitespace-pre-wrap"
2035
+ }, text.content);
2036
+ };
2037
+ var RefMarkdownEditor = ({ reference, placeholder }) => {
2038
+ const text = useAtomValue2(useMemo8(() => AtomRef2.make(reference), [
2039
+ reference
2040
+ ]));
2041
+ const dataExtensions = useMemo8(() => text ? [
2042
+ createDataExtensions({
2043
+ id: reference.uri,
2044
+ text: createDocAccessor(text, [
2045
+ "content"
2046
+ ])
2047
+ })
2048
+ ] : [], [
2049
+ text,
2050
+ reference
2051
+ ]);
2052
+ const extensions = useBasicMarkdownExtensions({
1401
2053
  placeholder,
1402
- value: value3 ?? "",
1403
- classNames: "min-h-auto max-h-40 overflow-auto",
1404
- onChange: handleChange,
1405
- onBlur,
1406
- style: {
1407
- resize: "none"
1408
- },
1409
- spellCheck: false
1410
- }), layout === "full" && /* @__PURE__ */ React8.createElement(Input4.Validation, null, error));
2054
+ extensions: dataExtensions
2055
+ });
2056
+ if (!text) {
2057
+ return null;
2058
+ }
2059
+ return /* @__PURE__ */ React11.createElement(Editor.Root, null, /* @__PURE__ */ React11.createElement(Editor.View, {
2060
+ classNames: editorClassNames,
2061
+ extensions
2062
+ }));
2063
+ };
2064
+ var StringMarkdownEditor = ({ value: value3, placeholder, readonly, onChange }) => {
2065
+ const extensions = useBasicMarkdownExtensions({
2066
+ placeholder
2067
+ });
2068
+ const handleChange = useCallback8((next) => onChange(next), [
2069
+ onChange
2070
+ ]);
2071
+ return /* @__PURE__ */ React11.createElement(Editor.Root, null, /* @__PURE__ */ React11.createElement(Editor.View, {
2072
+ classNames: editorClassNames,
2073
+ extensions,
2074
+ value: value3,
2075
+ onChange: readonly ? void 0 : handleChange
2076
+ }));
2077
+ };
2078
+ var CreateTextButton = ({ db, disabled, onCreate }) => {
2079
+ const { t } = useTranslation6(translationKey6);
2080
+ const handleClick = useCallback8(() => {
2081
+ if (!db) {
2082
+ return;
2083
+ }
2084
+ const text = db.add(Obj2.make(Text.Text, {
2085
+ content: ""
2086
+ }));
2087
+ onCreate(Ref4.make(text));
2088
+ }, [
2089
+ db,
2090
+ onCreate
2091
+ ]);
2092
+ return /* @__PURE__ */ React11.createElement(Button2, {
2093
+ onClick: handleClick,
2094
+ disabled
2095
+ }, /* @__PURE__ */ React11.createElement(Icon3, {
2096
+ icon: "ph--plus--regular",
2097
+ size: 4
2098
+ }), /* @__PURE__ */ React11.createElement("span", null, t("create-text.label")));
1411
2099
  };
1412
2100
 
1413
2101
  // src/components/Form/fields/NumberField.tsx
1414
- import React9, { useCallback as useCallback7 } from "react";
1415
- import { Input as Input5 } from "@dxos/react-ui";
2102
+ import React12, { useCallback as useCallback9 } from "react";
2103
+ import { Input as Input9 } from "@dxos/react-ui";
1416
2104
  import { safeParseFloat as safeParseFloat2 } from "@dxos/util";
1417
2105
  var NumberField = ({ type, readonly, placeholder, onValueChange, onBlur, ...props }) => {
1418
- const handleChange = useCallback7((event) => onValueChange(type, safeParseFloat2(event.target.value) || 0), [
2106
+ const handleChange = useCallback9((event) => onValueChange(type, safeParseFloat2(event.target.value) || 0), [
1419
2107
  type,
1420
2108
  onValueChange
1421
2109
  ]);
1422
- return /* @__PURE__ */ React9.createElement(FormFieldWrapper, {
2110
+ return /* @__PURE__ */ React12.createElement(FormFieldWrapper, {
1423
2111
  readonly,
1424
2112
  ...props
1425
- }, ({ value: value3 = "" }) => /* @__PURE__ */ React9.createElement(Input5.TextInput, {
2113
+ }, ({ value: value3 = "" }) => /* @__PURE__ */ React12.createElement(Input9.TextInput, {
1426
2114
  type: "number",
1427
2115
  disabled: !!readonly,
1428
2116
  placeholder,
@@ -1433,58 +2121,43 @@ var NumberField = ({ type, readonly, placeholder, onValueChange, onBlur, ...prop
1433
2121
  };
1434
2122
 
1435
2123
  // src/components/Form/fields/RefField.tsx
2124
+ import React14, { useCallback as useCallback11, useMemo as useMemo9, useState as useState4 } from "react";
1436
2125
  import "@dxos/lit-ui/dx-tag-picker.pcss";
1437
- import React11, { useCallback as useCallback9, useMemo as useMemo6 } from "react";
1438
- import { Entity, Filter, Obj, Ref as Ref2, Type } from "@dxos/echo";
1439
- import { ReferenceAnnotationId } from "@dxos/echo/internal";
1440
- import { useQuery, useSchema as useSchema$ } from "@dxos/echo-react";
1441
- import { findAnnotation } from "@dxos/effect";
1442
- import { DXN } from "@dxos/keys";
2126
+ import { Entity, Filter, Obj as Obj3, Ref as Ref5, Type as Type3 } from "@dxos/echo";
2127
+ import { useQuery, useType as defaultUseType2 } from "@dxos/echo-react";
2128
+ import { ANY_OBJECT_TYPENAME, ReferenceAnnotationId as ReferenceAnnotationId3 } from "@dxos/echo/internal";
2129
+ import { findAnnotation as findAnnotation3 } from "@dxos/effect";
2130
+ import { URI } from "@dxos/keys";
1443
2131
  import { DxAnchor } from "@dxos/lit-ui/react";
1444
- import { Button, Icon as Icon2, Input as Input6, useTranslation as useTranslation6 } from "@dxos/react-ui";
2132
+ import { Button as Button3, Icon as Icon4, Input as Input10, useTranslation as useTranslation8 } from "@dxos/react-ui";
1445
2133
  import { ParentLabelAnnotationId } from "@dxos/schema";
1446
- import { mx as mx3 } from "@dxos/ui-theme";
2134
+ import { translationKey as translationKey8 } from "#translations";
1447
2135
 
1448
2136
  // src/components/ObjectPicker/ObjectPicker.tsx
1449
- import React10, { forwardRef as forwardRef2, useCallback as useCallback8, useState as useState3 } from "react";
1450
- import { Popover, useTranslation as useTranslation5 } from "@dxos/react-ui";
1451
- import { Combobox, useSearchListInput, useSearchListResults } from "@dxos/react-ui-searchlist";
1452
- var CreateItem = ({ createOptionLabel, createOptionIcon, onCreateItemSelect }) => {
1453
- const { t } = useTranslation5(translationKey);
1454
- const { query } = useSearchListInput();
1455
- return /* @__PURE__ */ React10.createElement(Combobox.Item, {
1456
- value: "__create__",
1457
- label: t(createOptionLabel[0], {
1458
- ns: createOptionLabel[1].ns,
1459
- text: query
1460
- }),
1461
- icon: createOptionIcon,
1462
- classNames: "flex items-center gap-2",
1463
- closeOnSelect: false,
1464
- onSelect: () => {
1465
- onCreateItemSelect(query);
1466
- }
1467
- });
1468
- };
1469
- var ObjectPickerContent = /* @__PURE__ */ forwardRef2(({ options, selectedIds, createSchema, createOptionLabel, createOptionIcon, createInitialValuePath, onSelect, onCreate, ...props }, ref) => {
1470
- const { t } = useTranslation5(translationKey);
2137
+ import React13, { forwardRef, useCallback as useCallback10, useState as useState3 } from "react";
2138
+ import { Popover, useTranslation as useTranslation7 } from "@dxos/react-ui";
2139
+ import { Combobox } from "@dxos/react-ui-list";
2140
+ import { useSearchListResults } from "@dxos/react-ui-search";
2141
+ import { translationKey as translationKey7 } from "#translations";
2142
+ var ObjectPickerContent = /* @__PURE__ */ forwardRef(({ options, selectedIds, createSchema, createOptionLabel, createOptionIcon, createInitialValuePath, createFieldMap: createFieldMap3, onSelect, onCreate, ...props }, forwardedRef) => {
2143
+ const { t } = useTranslation7(translationKey7);
1471
2144
  const [showForm, setShowForm] = useState3(false);
1472
2145
  const [formInitialValue, setFormInitialValue] = useState3("");
1473
- const { results, handleSearch } = useSearchListResults({
2146
+ const { results, query, handleSearch } = useSearchListResults({
1474
2147
  items: options
1475
2148
  });
1476
- const handleFormSave = useCallback8((values) => {
1477
- onCreate?.(values);
2149
+ const handleFormSave = useCallback10(async (values) => {
2150
+ await onCreate?.(values);
1478
2151
  setShowForm(false);
1479
2152
  setFormInitialValue("");
1480
2153
  }, [
1481
2154
  onCreate
1482
2155
  ]);
1483
- const handleFormCancel = useCallback8(() => {
2156
+ const handleFormCancel = useCallback10(() => {
1484
2157
  setShowForm(false);
1485
2158
  setFormInitialValue("");
1486
2159
  }, []);
1487
- const handleKeyDown = useCallback8((event) => {
2160
+ const handleKeyDown = useCallback10((event) => {
1488
2161
  if (event.key === "Enter" && createSchema && event.currentTarget.querySelector('[role="option"][aria-selected="true"][data-value="__create__"]')) {
1489
2162
  event.stopPropagation();
1490
2163
  event.preventDefault();
@@ -1496,39 +2169,66 @@ var ObjectPickerContent = /* @__PURE__ */ forwardRef2(({ options, selectedIds, c
1496
2169
  }, [
1497
2170
  createSchema
1498
2171
  ]);
1499
- return /* @__PURE__ */ React10.createElement(Combobox.Content, {
2172
+ if (showForm && createSchema) {
2173
+ return /* @__PURE__ */ React13.createElement(Combobox.Content, {
2174
+ ...props,
2175
+ onKeyDownCapture: handleKeyDown,
2176
+ ref: forwardedRef
2177
+ }, /* @__PURE__ */ React13.createElement(Popover.Viewport, null, /* @__PURE__ */ React13.createElement(Form.Root, {
2178
+ testId: "create-referenced-object-form",
2179
+ schema: createSchema,
2180
+ defaultValues: createInitialValuePath ? {
2181
+ [createInitialValuePath]: formInitialValue
2182
+ } : {},
2183
+ fieldMap: createFieldMap3,
2184
+ onSave: handleFormSave,
2185
+ onCancel: handleFormCancel
2186
+ }, /* @__PURE__ */ React13.createElement(Form.Viewport, null, /* @__PURE__ */ React13.createElement(Form.Content, null, /* @__PURE__ */ React13.createElement(Form.FieldSet, null), /* @__PURE__ */ React13.createElement(Form.Actions, null))))), /* @__PURE__ */ React13.createElement(Combobox.Arrow, null));
2187
+ }
2188
+ return /* @__PURE__ */ React13.createElement(Combobox.Content, {
1500
2189
  ...props,
1501
- ref,
1502
- onSearch: handleSearch,
1503
- onKeyDownCapture: handleKeyDown
1504
- }, showForm && createSchema ? /* @__PURE__ */ React10.createElement(Popover.Viewport, null, /* @__PURE__ */ React10.createElement(Form.Root, {
1505
- testId: "create-referenced-object-form",
1506
- schema: createSchema,
1507
- values: createInitialValuePath ? {
1508
- [createInitialValuePath]: formInitialValue
1509
- } : {},
1510
- onSave: handleFormSave,
1511
- onCancel: handleFormCancel
1512
- }, /* @__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, {
1513
- placeholder: t("ref field combobox input placeholder"),
1514
- autoFocus: true
1515
- }), /* @__PURE__ */ React10.createElement(Combobox.List, null, results.map((option) => /* @__PURE__ */ React10.createElement(Combobox.Item, {
2190
+ onKeyDownCapture: handleKeyDown,
2191
+ ref: forwardedRef
2192
+ }, /* @__PURE__ */ React13.createElement(Combobox.Input, {
2193
+ placeholder: t("ref-field-combobox-input.placeholder"),
2194
+ autoFocus: true,
2195
+ value: query,
2196
+ onValueChange: handleSearch
2197
+ }), /* @__PURE__ */ React13.createElement(Combobox.List, null, results.map((option) => /* @__PURE__ */ React13.createElement(Combobox.Item, {
1516
2198
  key: option.id,
1517
2199
  value: option.id,
1518
2200
  label: option.label,
1519
2201
  checked: selectedIds?.includes(option.id),
1520
2202
  onSelect: () => onSelect(option.id),
1521
2203
  classNames: "flex items-center gap-2"
1522
- })), createOptionLabel && createOptionIcon && createSchema && onCreate && /* @__PURE__ */ React10.createElement(CreateItem, {
2204
+ })), createSchema && onCreate && /* @__PURE__ */ React13.createElement(CreateItem, {
2205
+ query,
1523
2206
  createOptionLabel,
1524
- createOptionIcon,
1525
- onCreateItemSelect: (query) => {
1526
- setFormInitialValue(query);
2207
+ createOptionIcon: createOptionIcon ?? "ph--plus--regular",
2208
+ onCreateItemSelect: (currentQuery) => {
2209
+ setFormInitialValue(currentQuery);
1527
2210
  setShowForm(true);
1528
2211
  }
1529
- }))), /* @__PURE__ */ React10.createElement(Combobox.Arrow, null));
2212
+ })), /* @__PURE__ */ React13.createElement(Combobox.Arrow, null));
1530
2213
  });
1531
- ObjectPickerContent.displayName = "ObjectPickerContent";
2214
+ var CreateItem = ({ query, createOptionLabel, createOptionIcon, onCreateItemSelect }) => {
2215
+ const { t } = useTranslation7(translationKey7);
2216
+ const label = createOptionLabel ? t(createOptionLabel[0], {
2217
+ ns: createOptionLabel[1].ns,
2218
+ text: query
2219
+ }) : t("create-option.label");
2220
+ return /* @__PURE__ */ React13.createElement(Combobox.Item, {
2221
+ value: "__create__",
2222
+ label,
2223
+ icon: createOptionIcon,
2224
+ classNames: "flex items-center gap-2",
2225
+ closeOnSelect: false,
2226
+ onSelect: () => {
2227
+ onCreateItemSelect(query);
2228
+ }
2229
+ });
2230
+ };
2231
+ ObjectPickerContent.displayName = "ObjectPicker.Content";
1532
2232
  var ObjectPicker = {
1533
2233
  Root: Combobox.Root,
1534
2234
  Portal: Combobox.Portal,
@@ -1542,40 +2242,42 @@ var isRefSnapshot = (val) => {
1542
2242
  return typeof val === "object" && typeof val?.["/"] === "string";
1543
2243
  };
1544
2244
  var defaultGetOptions = (results, { parentLabel } = {}) => results.map((result) => {
1545
- const id = Entity.getDXN(result).toString();
1546
- const parent = parentLabel ? Obj.getParent(result) : void 0;
2245
+ const id = Entity.getURI(result);
2246
+ const parent = parentLabel ? Obj3.getParent(result) : void 0;
1547
2247
  const label = parent ? Entity.getLabel(parent) : Entity.getLabel(result);
1548
2248
  return {
1549
2249
  id,
1550
2250
  label: label ?? id
1551
2251
  };
1552
2252
  });
1553
- var defaultResultsHook = (db, typename) => useQuery(db, typename ? typename === Type.getTypename(Obj.Unknown) ? Filter.everything() : Filter.typename(typename) : Filter.nothing());
2253
+ var defaultUseResults = (db, typename) => useQuery(db, typename ? typename === ANY_OBJECT_TYPENAME ? Filter.everything() : Filter.typename(typename) : Filter.nothing());
1554
2254
  var RefField = (props) => {
1555
- const { type, readonly, label, placeholder, layout, getStatus, getValue, createOptionLabel, createOptionIcon, createInitialValuePath, db, resultsHook: useResults = defaultResultsHook, schemaHook: useSchema = useSchema$, getOptions: getOptions2 = defaultGetOptions, onCreate, onValueChange } = props;
1556
- const { t } = useTranslation6(translationKey);
2255
+ const { type, readonly, label, jsonPath, placeholder, layout, getStatus, getValue, createOptionLabel, createOptionIcon, createInitialValuePath, createFieldMap: createFieldMap3, db, useType: useType2 = defaultUseType2, useResults = defaultUseResults, getOptions = defaultGetOptions, onCreate, onValueChange } = props;
2256
+ const { t } = useTranslation8(translationKey8);
1557
2257
  const { status, error } = getStatus();
1558
- const typename = useMemo6(() => type ? findAnnotation(type, ReferenceAnnotationId)?.typename : void 0, [
2258
+ const typename = useMemo9(() => type ? findAnnotation3(type, ReferenceAnnotationId3)?.typename : void 0, [
1559
2259
  type
1560
2260
  ]);
1561
2261
  const results = useResults(db, typename);
1562
- const options = useMemo6(() => {
1563
- const parentLabel = type ? findAnnotation(type, ParentLabelAnnotationId) === true : false;
1564
- return getOptions2(results, {
2262
+ const options = useMemo9(() => {
2263
+ const parentLabel = type ? findAnnotation3(type, ParentLabelAnnotationId) === true : false;
2264
+ return getOptions(results, {
1565
2265
  parentLabel
1566
2266
  });
1567
2267
  }, [
1568
2268
  results,
1569
- getOptions2,
2269
+ getOptions,
1570
2270
  type
1571
2271
  ]);
1572
- const handleGetValue = useCallback9(() => {
2272
+ const handleGetValue = useCallback11(() => {
1573
2273
  const formValue = getValue();
2274
+ const dxnToEntityId = (dxn) => dxn.split(/[:/]/).filter(Boolean).pop() ?? dxn;
1574
2275
  const unknownToRefOption = (value3) => {
1575
- const isRef = Ref2.isRef(value3);
2276
+ const isRef = Ref5.isRef(value3);
1576
2277
  if (isRef || isRefSnapshot(value3)) {
1577
- const dxnString = isRef ? value3.dxn.toString() : value3["/"];
1578
- const matchingOption = options.find((option) => option.id === dxnString);
2278
+ const dxnString = isRef ? value3.uri : value3["/"];
2279
+ const objectId = dxnToEntityId(dxnString);
2280
+ const matchingOption = options.find((option) => dxnToEntityId(option.id) === objectId);
1579
2281
  if (matchingOption) {
1580
2282
  return matchingOption;
1581
2283
  }
@@ -1587,31 +2289,39 @@ var RefField = (props) => {
1587
2289
  options,
1588
2290
  getValue
1589
2291
  ]);
1590
- const handleUpdate = useCallback9((id) => {
1591
- const item2 = options.find((option) => option.id === id);
1592
- const ref = item2 ? Ref2.fromDXN(DXN.parse(item2.id)) : void 0;
1593
- onValueChange(type, ref);
1594
- }, [
1595
- options,
1596
- type,
1597
- onValueChange
1598
- ]);
1599
2292
  const item = handleGetValue();
1600
- const selectedIds = useMemo6(() => item ? [
2293
+ const selectedIds = useMemo9(() => item ? [
1601
2294
  item.id
1602
2295
  ] : [], [
1603
2296
  item
1604
2297
  ]);
1605
- const createSchema = useSchema(db, typename);
1606
- const handleCreate = useCallback9((values) => {
1607
- if (createSchema && onCreate) {
1608
- onCreate(createSchema, values);
2298
+ const createSchema = useType2(db, typename);
2299
+ const [open, setOpen] = useState4(false);
2300
+ const handleCreate = useCallback11(async (values) => {
2301
+ if (!createSchema || !onCreate) {
2302
+ return;
2303
+ }
2304
+ const newObject = await onCreate(createSchema, values);
2305
+ if (newObject) {
2306
+ onValueChange(type, Ref5.make(newObject));
1609
2307
  }
2308
+ setOpen(false);
1610
2309
  }, [
1611
2310
  createSchema,
1612
- onCreate
2311
+ onCreate,
2312
+ type,
2313
+ onValueChange
2314
+ ]);
2315
+ const handleUpdate = useCallback11((id) => {
2316
+ const item2 = options.find((option) => option.id === id);
2317
+ const ref = item2 ? Ref5.fromURI(URI.make(item2.id)) : void 0;
2318
+ onValueChange(type, ref);
2319
+ }, [
2320
+ options,
2321
+ type,
2322
+ onValueChange
1613
2323
  ]);
1614
- const handleSelect = useCallback9((id) => {
2324
+ const handleSelect = useCallback11((id) => {
1615
2325
  if (item?.id === id) {
1616
2326
  handleUpdate(void 0);
1617
2327
  } else {
@@ -1624,102 +2334,123 @@ var RefField = (props) => {
1624
2334
  if (!typename || (readonly || layout === "static") && !item) {
1625
2335
  return null;
1626
2336
  }
1627
- return /* @__PURE__ */ React11.createElement(Input6.Root, {
2337
+ return /* @__PURE__ */ React14.createElement(Input10.Root, {
1628
2338
  validationValence: status
1629
- }, layout !== "inline" && /* @__PURE__ */ React11.createElement(FormFieldLabel, {
2339
+ }, layout !== "inline" && /* @__PURE__ */ React14.createElement(FormFieldLabel, {
1630
2340
  error,
1631
2341
  readonly,
1632
- label
1633
- }), /* @__PURE__ */ React11.createElement("div", null, readonly ? !item ? /* @__PURE__ */ React11.createElement("p", {
1634
- className: mx3("text-description", "mb-2")
1635
- }, t("empty readonly ref field label")) : /* @__PURE__ */ React11.createElement(DxAnchor, {
2342
+ label,
2343
+ path: jsonPath
2344
+ }), /* @__PURE__ */ React14.createElement("div", null, readonly ? !item ? /* @__PURE__ */ React14.createElement("p", {
2345
+ className: "text-description mb-2"
2346
+ }, t("empty-readonly-ref-field.label")) : /* @__PURE__ */ React14.createElement(DxAnchor, {
1636
2347
  key: item.id,
1637
2348
  dxn: item.id,
1638
2349
  rootclassname: "me-1"
1639
- }, item.label) : /* @__PURE__ */ React11.createElement(ObjectPicker.Root, null, /* @__PURE__ */ React11.createElement(ObjectPicker.Trigger, {
2350
+ }, item.label) : /* @__PURE__ */ React14.createElement(ObjectPicker.Root, {
2351
+ open,
2352
+ onOpenChange: setOpen
2353
+ }, /* @__PURE__ */ React14.createElement(ObjectPicker.Trigger, {
1640
2354
  asChild: true,
1641
2355
  classNames: "p-0"
1642
- }, item ? /* @__PURE__ */ React11.createElement("div", {
1643
- className: "flex gap-2 w-full"
1644
- }, /* @__PURE__ */ React11.createElement(Input6.Root, {
2356
+ }, item ? /* @__PURE__ */ React14.createElement("div", {
2357
+ className: "flex gap-form-gap w-full"
2358
+ }, /* @__PURE__ */ React14.createElement(Input10.Root, {
1645
2359
  key: item.id
1646
- }, /* @__PURE__ */ React11.createElement(Input6.TextInput, {
2360
+ }, /* @__PURE__ */ React14.createElement(Input10.TextInput, {
1647
2361
  value: item.label,
1648
2362
  readOnly: true,
1649
2363
  classNames: "w-full"
1650
- }))) : /* @__PURE__ */ React11.createElement(Button, {
1651
- classNames: "w-full text-start gap-2"
1652
- }, /* @__PURE__ */ React11.createElement("div", {
1653
- role: "none",
2364
+ }))) : /* @__PURE__ */ React14.createElement(Button3, {
2365
+ classNames: "w-full text-start gap-form-gap"
2366
+ }, /* @__PURE__ */ React14.createElement("div", {
1654
2367
  className: "grow overflow-hidden"
1655
- }, /* @__PURE__ */ React11.createElement("span", {
1656
- className: "flex truncate text-description"
1657
- }, placeholder ?? t("ref field placeholder"))), /* @__PURE__ */ React11.createElement(Icon2, {
2368
+ }, /* @__PURE__ */ React14.createElement("span", {
2369
+ className: "truncate text-description"
2370
+ }, placeholder || label || t("ref-field.placeholder"))), /* @__PURE__ */ React14.createElement(Icon4, {
1658
2371
  size: 3,
1659
2372
  icon: "ph--caret-down--bold"
1660
- }))), /* @__PURE__ */ React11.createElement(ObjectPicker.Portal, null, /* @__PURE__ */ React11.createElement(ObjectPicker.Content, {
2373
+ }))), /* @__PURE__ */ React14.createElement(ObjectPicker.Portal, null, /* @__PURE__ */ React14.createElement(ObjectPicker.Content, {
1661
2374
  classNames: "dx-card-popover-width",
1662
2375
  options,
1663
2376
  selectedIds,
1664
- createSchema: createSchema && omitId(createSchema),
2377
+ // Strip hidden (`FormInputAnnotation.set(false)`) fields so the
2378
+ // form's validator doesn't reject required-but-hidden fields
2379
+ // such as backing-object refs supplied by a `FactoryAnnotation`.
2380
+ createSchema: createSchema && omitHiddenFormFields(omitId(Type3.getSchema(createSchema))),
1665
2381
  createOptionLabel,
1666
2382
  createOptionIcon,
1667
2383
  createInitialValuePath,
2384
+ createFieldMap: createFieldMap3,
1668
2385
  onCreate: handleCreate,
1669
2386
  onSelect: handleSelect
1670
- })))), layout === "full" && /* @__PURE__ */ React11.createElement(Input6.DescriptionAndValidation, null, error));
2387
+ })))), layout === "full" && /* @__PURE__ */ React14.createElement(Input10.DescriptionAndValidation, null, error));
1671
2388
  };
1672
2389
 
1673
2390
  // src/components/Form/fields/SelectField.tsx
1674
- import React12, { useCallback as useCallback10 } from "react";
1675
- import { Input as Input7, Select } from "@dxos/react-ui";
1676
- var SelectField = ({ type, readonly, label, layout, placeholder, options, getStatus, getValue, onValueChange }) => {
2391
+ import React15, { useCallback as useCallback12 } from "react";
2392
+ import { Icon as Icon5, Input as Input11, Select } from "@dxos/react-ui";
2393
+ import { getStyles } from "@dxos/ui-theme";
2394
+ var SelectField = ({ type, readonly, label, jsonPath, layout, placeholder, options, getStatus, getValue, onValueChange }) => {
1677
2395
  const { status, error } = getStatus();
1678
2396
  const value3 = getValue();
1679
- const handleValueChange = useCallback10((value4) => onValueChange(type, value4), [
2397
+ const handleValueChange = useCallback12((value4) => onValueChange(type, value4), [
1680
2398
  type,
1681
2399
  onValueChange
1682
2400
  ]);
1683
2401
  if ((readonly || layout === "static") && value3 == null) {
1684
2402
  return null;
1685
2403
  }
1686
- return /* @__PURE__ */ React12.createElement(Input7.Root, {
2404
+ return /* @__PURE__ */ React15.createElement(Input11.Root, {
1687
2405
  validationValence: status
1688
- }, layout !== "inline" && /* @__PURE__ */ React12.createElement(FormFieldLabel, {
2406
+ }, layout !== "inline" && /* @__PURE__ */ React15.createElement(FormFieldLabel, {
1689
2407
  error,
1690
2408
  readonly,
1691
- label
1692
- }), layout === "static" ? /* @__PURE__ */ React12.createElement("p", null, options?.find(({ value: optionValue }) => optionValue === value3)?.label ?? String(value3)) : /* @__PURE__ */ React12.createElement(Select.Root, {
2409
+ label,
2410
+ path: jsonPath
2411
+ }), layout === "static" ? /* @__PURE__ */ React15.createElement("p", null, options?.find(({ value: optionValue }) => optionValue === value3)?.label ?? String(value3)) : /* @__PURE__ */ React15.createElement(Select.Root, {
1693
2412
  value: value3,
1694
2413
  onValueChange: handleValueChange
1695
- }, /* @__PURE__ */ React12.createElement(Select.TriggerButton, {
2414
+ }, /* @__PURE__ */ React15.createElement(Select.TriggerButton, {
1696
2415
  classNames: "w-full",
1697
2416
  disabled: !!readonly,
1698
2417
  placeholder
1699
- }), /* @__PURE__ */ React12.createElement(Select.Portal, null, /* @__PURE__ */ React12.createElement(Select.Content, null, /* @__PURE__ */ React12.createElement(Select.Viewport, null, options?.map(({ value: value4, label: label2 }) => (
2418
+ }), /* @__PURE__ */ React15.createElement(Select.Portal, null, /* @__PURE__ */ React15.createElement(Select.Content, null, /* @__PURE__ */ React15.createElement(Select.Viewport, null, options?.map(({ value: value4, label: label2, secondaryLabel, icon, iconHue }) => (
1700
2419
  // NOTE: Numeric values are converted to and from strings.
1701
- /* @__PURE__ */ React12.createElement(Select.Option, {
2420
+ /* @__PURE__ */ React15.createElement(Select.Option, {
1702
2421
  key: String(value4),
1703
2422
  value: String(value4)
1704
- }, label2 ?? String(value4))
1705
- ))), /* @__PURE__ */ React12.createElement(Select.Arrow, null)))), layout === "full" && /* @__PURE__ */ React12.createElement(Input7.DescriptionAndValidation, null, error));
2423
+ }, /* @__PURE__ */ React15.createElement("span", {
2424
+ className: "flex items-center flex-row gap-2"
2425
+ }, icon && /* @__PURE__ */ React15.createElement(Icon5, {
2426
+ icon,
2427
+ classNames: getIconHueStyles(iconHue)
2428
+ }), label2 ?? String(value4), secondaryLabel && /* @__PURE__ */ React15.createElement("span", {
2429
+ className: "text-subdued text-xs"
2430
+ }, secondaryLabel)))
2431
+ ))), /* @__PURE__ */ React15.createElement(Select.Arrow, null)))), layout === "full" && /* @__PURE__ */ React15.createElement(Input11.DescriptionAndValidation, null, error));
2432
+ };
2433
+ var getIconHueStyles = (iconHue) => {
2434
+ const styles = iconHue ? getStyles(iconHue) : void 0;
2435
+ return styles?.fg;
1706
2436
  };
1707
2437
 
1708
2438
  // src/components/Form/fields/SelectOptionField.tsx
1709
- import React13, { useCallback as useCallback11, useEffect as useEffect6, useRef as useRef3, useState as useState4 } from "react";
2439
+ import React16, { useCallback as useCallback13, useEffect as useEffect4, useRef as useRef2, useState as useState5 } from "react";
1710
2440
  import { PublicKey } from "@dxos/keys";
1711
- import { IconButton as IconButton3, Input as Input8, Tag, useTranslation as useTranslation7 } from "@dxos/react-ui";
2441
+ import { IconButton as IconButton3, Input as Input12, Tag, useTranslation as useTranslation9 } from "@dxos/react-ui";
1712
2442
  import { List } from "@dxos/react-ui-list";
1713
2443
  import { HuePicker } from "@dxos/react-ui-pickers";
1714
- import { hues, osTranslations, subtleHover } from "@dxos/ui-theme";
1715
- var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueChange }) => {
1716
- const { t } = useTranslation7(translationKey);
2444
+ import { hues, osTranslations } from "@dxos/ui-theme";
2445
+ import { translationKey as translationKey9 } from "#translations";
2446
+ var SelectOptionField = ({ type, readonly, label, jsonPath, getStatus, getValue, onValueChange }) => {
2447
+ const { t } = useTranslation9(translationKey9);
1717
2448
  const { status, error } = getStatus();
1718
- const [selected, setSelectedId] = useState4(null);
1719
- const [isNewOption, setIsNewOption] = useState4(false);
1720
- const inputRef = useRef3(null);
2449
+ const [selected, setSelectedId] = useState5(null);
2450
+ const [isNewOption, setIsNewOption] = useState5(false);
2451
+ const inputRef = useRef2(null);
1721
2452
  const options = getValue();
1722
- useEffect6(() => {
2453
+ useEffect4(() => {
1723
2454
  if (options === void 0) {
1724
2455
  onValueChange(type, []);
1725
2456
  }
@@ -1738,7 +2469,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1738
2469
  const availableHues = hues.filter((hue) => !lastThree.has(hue));
1739
2470
  return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hues[Math.floor(Math.random() * hues.length)];
1740
2471
  };
1741
- const handleAdd = useCallback11(() => {
2472
+ const handleAdd = useCallback13(() => {
1742
2473
  const newId = PublicKey.random().truncate();
1743
2474
  const newOption = {
1744
2475
  id: newId,
@@ -1756,7 +2487,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1756
2487
  type,
1757
2488
  onValueChange
1758
2489
  ]);
1759
- const handleDelete = useCallback11((id) => {
2490
+ const handleDelete = useCallback13((id) => {
1760
2491
  const newOptions = options?.filter((option) => option.id !== id) ?? [];
1761
2492
  onValueChange(type, newOptions);
1762
2493
  setSelectedId(null);
@@ -1765,7 +2496,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1765
2496
  type,
1766
2497
  onValueChange
1767
2498
  ]);
1768
- const handleMove = useCallback11((from, to) => {
2499
+ const handleMove = useCallback13((from, to) => {
1769
2500
  if (!options) {
1770
2501
  return;
1771
2502
  }
@@ -1780,10 +2511,10 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1780
2511
  type,
1781
2512
  onValueChange
1782
2513
  ]);
1783
- const handleClick = useCallback11((id) => {
2514
+ const handleClick = useCallback13((id) => {
1784
2515
  setSelectedId((current) => current === id ? null : id);
1785
2516
  }, []);
1786
- const handleTitleChange = useCallback11((id) => (e) => {
2517
+ const handleTitleChange = useCallback13((id) => (e) => {
1787
2518
  const newOptions = options?.map((o) => o.id === id ? {
1788
2519
  ...o,
1789
2520
  title: e.target.value
@@ -1794,12 +2525,12 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1794
2525
  type,
1795
2526
  onValueChange
1796
2527
  ]);
1797
- const handleKeyDown = useCallback11((ev) => {
2528
+ const handleKeyDown = useCallback13((ev) => {
1798
2529
  if (ev.key === "Enter") {
1799
2530
  setSelectedId(null);
1800
2531
  }
1801
2532
  }, []);
1802
- const handleColorChange = useCallback11((id) => (hue) => {
2533
+ const handleColorChange = useCallback13((id) => (hue) => {
1803
2534
  const newOptions = options?.map((o) => o.id === id ? {
1804
2535
  ...o,
1805
2536
  color: hue
@@ -1810,7 +2541,7 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1810
2541
  type,
1811
2542
  onValueChange
1812
2543
  ]);
1813
- useEffect6(() => {
2544
+ useEffect4(() => {
1814
2545
  if (selected && isNewOption && inputRef.current) {
1815
2546
  inputRef.current.focus();
1816
2547
  setIsNewOption(false);
@@ -1819,77 +2550,73 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1819
2550
  selected,
1820
2551
  isNewOption
1821
2552
  ]);
1822
- return /* @__PURE__ */ React13.createElement(Input8.Root, {
2553
+ return /* @__PURE__ */ React16.createElement(Input12.Root, {
1823
2554
  validationValence: status
1824
- }, /* @__PURE__ */ React13.createElement(FormFieldLabel, {
2555
+ }, /* @__PURE__ */ React16.createElement(FormFieldLabel, {
1825
2556
  error,
1826
2557
  readonly,
1827
- label
1828
- }), /* @__PURE__ */ React13.createElement("div", {
1829
- role: "none"
1830
- }, options && /* @__PURE__ */ React13.createElement(List.Root, {
2558
+ label,
2559
+ path: jsonPath
2560
+ }), /* @__PURE__ */ React16.createElement("div", null, options && /* @__PURE__ */ React16.createElement(List.Root, {
1831
2561
  items: options,
1832
2562
  isItem: (_item) => true,
1833
2563
  onMove: readonly ? void 0 : handleMove,
1834
2564
  readonly: !!readonly
1835
- }, ({ items }) => /* @__PURE__ */ React13.createElement("div", {
2565
+ }, ({ items }) => /* @__PURE__ */ React16.createElement("div", {
1836
2566
  role: "list",
1837
2567
  className: "w-full overflow-auto"
1838
- }, items?.map((item) => /* @__PURE__ */ React13.createElement("div", {
2568
+ }, items?.map((item) => /* @__PURE__ */ React16.createElement("div", {
1839
2569
  key: item.id
1840
- }, /* @__PURE__ */ React13.createElement(List.Item, {
2570
+ }, /* @__PURE__ */ React16.createElement(List.Item, {
1841
2571
  role: "button",
1842
2572
  item,
1843
- classNames: [
1844
- subtleHover,
1845
- "flex flex-col cursor-pointer rounded-xs"
1846
- ],
2573
+ classNames: "flex flex-col cursor-pointer rounded-xs dx-hover",
1847
2574
  "aria-expanded": selected === item.id
1848
- }, /* @__PURE__ */ React13.createElement("div", {
2575
+ }, /* @__PURE__ */ React16.createElement("div", {
1849
2576
  className: "flex items-center"
1850
- }, /* @__PURE__ */ React13.createElement(List.ItemDragHandle, {
2577
+ }, /* @__PURE__ */ React16.createElement(List.ItemDragHandle, {
1851
2578
  disabled: !!readonly
1852
- }), /* @__PURE__ */ React13.createElement(List.ItemTitle, {
2579
+ }), /* @__PURE__ */ React16.createElement(List.ItemTitle, {
1853
2580
  onClick: () => handleClick(item.id),
1854
2581
  classNames: "flex-1"
1855
- }, /* @__PURE__ */ React13.createElement(Tag, {
2582
+ }, /* @__PURE__ */ React16.createElement(Tag, {
1856
2583
  palette: item.color
1857
- }, item.title || "\u200B")), /* @__PURE__ */ React13.createElement(IconButton3, {
2584
+ }, item.title || "\u200B")), /* @__PURE__ */ React16.createElement(IconButton3, {
1858
2585
  iconOnly: true,
1859
2586
  variant: "ghost",
1860
- label: t(selected === item.id ? "collapse label" : "expand label", {
2587
+ label: t(selected === item.id ? "collapse.label" : "expand.label", {
1861
2588
  ns: osTranslations
1862
2589
  }),
1863
2590
  icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
1864
2591
  onClick: () => handleClick(item.id)
1865
- })), selected === item.id && /* @__PURE__ */ React13.createElement("div", {
1866
- className: "flex flex-col p-form-padding gap-1 dx-density-fine"
1867
- }, /* @__PURE__ */ React13.createElement(Input8.Label, {
1868
- classNames: "text-xs"
1869
- }, t("select option label")), /* @__PURE__ */ React13.createElement("div", {
1870
- className: "grid grid-cols-[1fr_min-content_min-content] gap-1"
1871
- }, /* @__PURE__ */ React13.createElement(Input8.TextInput, {
2592
+ })), selected === item.id && /* @__PURE__ */ React16.createElement("div", {
2593
+ className: "flex flex-col p-form-padding gap-form-gap dx-density-md"
2594
+ }, /* @__PURE__ */ React16.createElement(Input12.Label, {
2595
+ classNames: "text-sm"
2596
+ }, t("select-option.label")), /* @__PURE__ */ React16.createElement("div", {
2597
+ className: "grid grid-cols-[1fr_min-content_min-content] gap-form-gap"
2598
+ }, /* @__PURE__ */ React16.createElement(Input12.TextInput, {
1872
2599
  disabled: !!readonly,
1873
- placeholder: t("select option label placeholder"),
2600
+ placeholder: t("select-option-label.placeholder"),
1874
2601
  ref: selected === item.id ? inputRef : void 0,
1875
2602
  value: item.title,
1876
2603
  onChange: handleTitleChange(item.id),
1877
2604
  onKeyDown: handleKeyDown,
1878
2605
  classNames: "flex-1"
1879
- }), /* @__PURE__ */ React13.createElement(HuePicker, {
2606
+ }), /* @__PURE__ */ React16.createElement(HuePicker, {
1880
2607
  disabled: !!readonly,
1881
2608
  value: item.color,
1882
2609
  onChange: handleColorChange(item.id)
1883
- }), /* @__PURE__ */ React13.createElement(IconButton3, {
2610
+ }), /* @__PURE__ */ React16.createElement(IconButton3, {
1884
2611
  disabled: !!readonly,
1885
2612
  icon: "ph--trash--fill",
1886
2613
  iconOnly: true,
1887
- label: t("select option delete"),
2614
+ label: t("select-option-delete.button"),
1888
2615
  onClick: () => handleDelete(item.id)
1889
- })))))), /* @__PURE__ */ React13.createElement(IconButton3, {
2616
+ })))))), /* @__PURE__ */ React16.createElement(IconButton3, {
1890
2617
  variant: "ghost",
1891
2618
  icon: "ph--plus--regular",
1892
- label: t("select option add"),
2619
+ label: t("select-option-add.button"),
1893
2620
  onClick: handleAdd,
1894
2621
  disabled: !!readonly,
1895
2622
  classNames: "w-full"
@@ -1897,39 +2624,39 @@ var SelectOptionField = ({ type, readonly, label, getStatus, getValue, onValueCh
1897
2624
  };
1898
2625
 
1899
2626
  // src/components/Form/fields/TextField.tsx
1900
- import React14, { useCallback as useCallback12 } from "react";
1901
- import { Input as Input9 } from "@dxos/react-ui";
1902
- var TextField = ({ type, readonly, placeholder, onValueChange, onBlur, ...props }) => {
1903
- const handleChange = useCallback12((event) => onValueChange(type, event.target.value), [
2627
+ import React17, { useCallback as useCallback14 } from "react";
2628
+ import { Input as Input13 } from "@dxos/react-ui";
2629
+ var TextField = ({ type, readonly, placeholder, onBlur, onValueChange, ...props }) => {
2630
+ const handleChange = useCallback14((event) => onValueChange(type, event.target.value), [
1904
2631
  type,
1905
2632
  onValueChange
1906
2633
  ]);
1907
- return /* @__PURE__ */ React14.createElement(FormFieldWrapper, {
2634
+ return /* @__PURE__ */ React17.createElement(FormFieldWrapper, {
1908
2635
  readonly,
1909
2636
  ...props
1910
- }, ({ value: value3 = "" }) => /* @__PURE__ */ React14.createElement(Input9.TextInput, {
2637
+ }, ({ value: value3 = "" }) => /* @__PURE__ */ React17.createElement(Input13.TextInput, {
1911
2638
  noAutoFill: true,
1912
2639
  disabled: !!readonly,
1913
2640
  placeholder,
1914
2641
  value: value3,
1915
- onChange: handleChange,
1916
- onBlur
2642
+ onBlur,
2643
+ onChange: handleChange
1917
2644
  }));
1918
2645
  };
1919
2646
 
1920
2647
  // src/components/Form/fields/TextAreaField.tsx
1921
- import React15, { useCallback as useCallback13 } from "react";
1922
- import { Input as Input10 } from "@dxos/react-ui";
2648
+ import React18, { useCallback as useCallback15 } from "react";
2649
+ import { Input as Input14 } from "@dxos/react-ui";
1923
2650
  var TextAreaField = ({ type, readonly, placeholder, onValueChange, onBlur, ...props }) => {
1924
- const handleChange = useCallback13((event) => onValueChange(type, event.target.value), [
2651
+ const handleChange = useCallback15((event) => onValueChange(type, event.target.value), [
1925
2652
  type,
1926
2653
  onValueChange
1927
2654
  ]);
1928
- return /* @__PURE__ */ React15.createElement(FormFieldWrapper, {
2655
+ return /* @__PURE__ */ React18.createElement(FormFieldWrapper, {
1929
2656
  readonly,
1930
2657
  ...props
1931
- }, ({ value: value3 = "" }) => /* @__PURE__ */ React15.createElement(Input10.TextArea, {
1932
- rows: 3,
2658
+ }, ({ value: value3 = "" }) => /* @__PURE__ */ React18.createElement(Input14.TextArea, {
2659
+ rows: 5,
1933
2660
  disabled: !!readonly,
1934
2661
  placeholder,
1935
2662
  value: value3,
@@ -1939,8 +2666,8 @@ var TextAreaField = ({ type, readonly, placeholder, onValueChange, onBlur, ...pr
1939
2666
  };
1940
2667
 
1941
2668
  // src/components/Form/fields/TupleField.tsx
1942
- import React16 from "react";
1943
- import { Input as Input11 } from "@dxos/react-ui";
2669
+ import React19 from "react";
2670
+ import { Input as Input15 } from "@dxos/react-ui";
1944
2671
  import { mx as mx4 } from "@dxos/ui-theme";
1945
2672
  import { safeParseFloat as safeParseFloat3 } from "@dxos/util";
1946
2673
  var gridCols = [
@@ -1949,18 +2676,19 @@ var gridCols = [
1949
2676
  "grid-cols-3",
1950
2677
  "grid-cols-4"
1951
2678
  ];
1952
- var TupleField = ({ binding, type, readonly, label, getStatus, getValue, onValueChange, onBlur }) => {
2679
+ var TupleField = ({ binding, type, readonly, label, jsonPath, getStatus, getValue, onValueChange, onBlur }) => {
1953
2680
  const { status, error } = getStatus();
1954
2681
  const values = getValue() ?? {};
1955
- return /* @__PURE__ */ React16.createElement(Input11.Root, {
2682
+ return /* @__PURE__ */ React19.createElement(Input15.Root, {
1956
2683
  validationValence: status
1957
- }, /* @__PURE__ */ React16.createElement(FormFieldLabel, {
2684
+ }, /* @__PURE__ */ React19.createElement(FormFieldLabel, {
1958
2685
  error,
1959
2686
  readonly,
1960
- label
1961
- }), /* @__PURE__ */ React16.createElement("div", {
1962
- className: mx4("grid gap-2", gridCols[binding.length - 1])
1963
- }, binding.map((prop) => /* @__PURE__ */ React16.createElement(Input11.TextInput, {
2687
+ label,
2688
+ path: jsonPath
2689
+ }), /* @__PURE__ */ React19.createElement("div", {
2690
+ className: mx4("grid gap-form-gap", gridCols[binding.length - 1])
2691
+ }, binding.map((prop) => /* @__PURE__ */ React19.createElement(Input15.TextInput, {
1964
2692
  key: prop,
1965
2693
  type: "number",
1966
2694
  disabled: !!readonly,
@@ -1975,67 +2703,77 @@ var TupleField = ({ binding, type, readonly, label, getStatus, getValue, onValue
1975
2703
  }))));
1976
2704
  };
1977
2705
 
2706
+ // src/components/Form/meta-tags.ts
2707
+ import * as Schema4 from "effect/Schema";
2708
+ import { Ref as Ref6, Tag as Tag2 } from "@dxos/echo";
2709
+ var META_TAGS_KEY = "_tags";
2710
+ var withMetaTags = (schema) => omitId(Schema4.Struct({
2711
+ [META_TAGS_KEY]: Schema4.Array(Ref6.Ref(Tag2.Tag)).pipe(Schema4.annotations({
2712
+ title: "Tags"
2713
+ }), Schema4.optional)
2714
+ }).pipe(Schema4.extend(schema)));
2715
+
1978
2716
  // src/components/FieldEditor/FieldEditor.tsx
1979
2717
  var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
1980
2718
  var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCancel }) => {
1981
- const { t } = useTranslation8(translationKey);
1982
- const [props, setProps] = useState5(projection.getFieldProjection(field.id).props);
1983
- useEffect7(() => setProps(projection.getFieldProjection(field.id).props), [
2719
+ const { t } = useTranslation10(translationKey10);
2720
+ const [props, setProps] = useState6(projection.getFieldProjection(field.id).props);
2721
+ useEffect5(() => setProps(projection.getFieldProjection(field.id).props), [
1984
2722
  field,
1985
2723
  projection
1986
2724
  ]);
1987
- const [schemas, setSchemas] = useState5([]);
2725
+ const [schemas, setSchemas] = useState6([]);
1988
2726
  useAsyncEffect(async () => {
1989
2727
  if (!registry) {
1990
2728
  return;
1991
2729
  }
1992
- const subscription = registry.query().subscribe((query) => setSchemas(query.results), {
2730
+ const subscription = registry.query(Filter2.type(Type4.Type)).subscribe((query) => setSchemas(query.results), {
1993
2731
  fire: true
1994
2732
  });
1995
- const schemas2 = await registry.query().run();
2733
+ const schemas2 = await registry.query(Filter2.type(Type4.Type)).run();
1996
2734
  setSchemas(schemas2);
1997
2735
  return () => subscription?.();
1998
2736
  }, [
1999
2737
  registry
2000
2738
  ]);
2001
- const [referenceSchema, setReferenceSchema] = useState5();
2002
- useEffect7(() => {
2003
- setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
2739
+ const [referenceSchema, setReferenceSchema] = useState6();
2740
+ useEffect5(() => {
2741
+ setReferenceSchema(schemas.find((schema) => Type4.getTypename(schema) === props?.referenceSchema));
2004
2742
  }, [
2005
2743
  schemas,
2006
2744
  props?.referenceSchema
2007
2745
  ]);
2008
- const [{ fieldSchema }, setFieldSchema] = useState5({
2746
+ const [{ fieldSchema }, setFieldSchema] = useState6({
2009
2747
  fieldSchema: getFormatSchema(props?.format)
2010
2748
  });
2011
- const fieldMap = useMemo7(() => ({
2012
- ["format"]: (props2) => /* @__PURE__ */ React17.createElement(SelectField, {
2749
+ const fieldMap = useMemo10(() => ({
2750
+ ["format"]: (props2) => /* @__PURE__ */ React20.createElement(SelectField, {
2013
2751
  ...props2,
2014
- options: FormatEnums.filter((value3) => value3 !== Format4.TypeFormat.None).map((value3) => ({
2752
+ options: FormatEnums.filter((value3) => value3 !== Format6.TypeFormat.None).map((value3) => ({
2015
2753
  value: value3,
2016
- label: t(`format ${value3}`)
2754
+ label: t(`format.${value3}.label`)
2017
2755
  }))
2018
2756
  }),
2019
- ["referenceSchema"]: (props2) => /* @__PURE__ */ React17.createElement(SelectField, {
2757
+ ["referenceSchema"]: (props2) => /* @__PURE__ */ React20.createElement(SelectField, {
2020
2758
  ...props2,
2021
- options: schemas.map((schema) => ({
2022
- value: schema.typename
2759
+ options: schemas.map((schema) => Type4.getTypename(schema)).filter((typename) => typename != null).map((typename) => ({
2760
+ value: typename
2023
2761
  }))
2024
2762
  }),
2025
- ["referencePath"]: (props2) => /* @__PURE__ */ React17.createElement(SelectField, {
2763
+ ["referencePath"]: (props2) => /* @__PURE__ */ React20.createElement(SelectField, {
2026
2764
  ...props2,
2027
- options: referenceSchema ? getFormProperties(referenceSchema.ast).sort((a, b) => a.name.toString().localeCompare(b.name.toString())).map((p) => ({
2765
+ options: referenceSchema ? getFormProperties(Type4.getSchema(referenceSchema).ast).sort((a, b) => a.name.toString().localeCompare(b.name.toString())).map((p) => ({
2028
2766
  value: p.name.toString()
2029
2767
  })) : []
2030
2768
  }),
2031
- ["options"]: (props2) => /* @__PURE__ */ React17.createElement(SelectOptionField, props2)
2769
+ ["options"]: (props2) => /* @__PURE__ */ React20.createElement(SelectOptionField, props2)
2032
2770
  }), [
2033
2771
  t,
2034
2772
  schemas,
2035
2773
  referenceSchema
2036
2774
  ]);
2037
- const propIsNotType = useCallback14((props2) => props2.filter((prop) => prop.name !== "type"), []);
2038
- const handleValuesChanged = useCallback14((_props) => {
2775
+ const propIsNotType = useCallback16((props2) => props2.filter((prop) => prop.name !== "type"), []);
2776
+ const handleValuesChanged = useCallback16((_props) => {
2039
2777
  setFieldSchema((prev) => {
2040
2778
  const fieldSchema2 = getFormatSchema(_props.format);
2041
2779
  if (prev.fieldSchema === fieldSchema2) {
@@ -2046,8 +2784,8 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
2046
2784
  };
2047
2785
  });
2048
2786
  setReferenceSchema((prev) => {
2049
- if (_props.referenceSchema !== prev?.typename) {
2050
- const newSchema = schemas.find((schema) => schema.typename === _props.referenceSchema);
2787
+ if (_props.referenceSchema !== (prev ? Type4.getTypename(prev) : void 0)) {
2788
+ const newSchema = schemas.find((schema) => Type4.getTypename(schema) === _props.referenceSchema);
2051
2789
  if (newSchema) {
2052
2790
  return newSchema;
2053
2791
  }
@@ -2072,7 +2810,7 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
2072
2810
  props.format,
2073
2811
  props.referenceSchema
2074
2812
  ]);
2075
- const handleValidate = useCallback14(({ property }) => {
2813
+ const handleValidate = useCallback16(({ property }) => {
2076
2814
  if (property && projection.getFields().find((f) => f.path === property && f.path !== field.path)) {
2077
2815
  return [
2078
2816
  {
@@ -2085,9 +2823,9 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
2085
2823
  projection.getFields(),
2086
2824
  field
2087
2825
  ]);
2088
- const handleSave = useCallback14((props2) => {
2826
+ const handleSave = useCallback16((props2) => {
2089
2827
  if (view) {
2090
- Obj2.change(view, () => {
2828
+ Obj4.update(view, () => {
2091
2829
  projection.setFieldProjection({
2092
2830
  field,
2093
2831
  props: props2
@@ -2106,7 +2844,7 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
2106
2844
  view,
2107
2845
  onSave
2108
2846
  ]);
2109
- const handleCancel = useCallback14(() => {
2847
+ const handleCancel = useCallback16(() => {
2110
2848
  onSave();
2111
2849
  requestAnimationFrame(() => onCancel?.());
2112
2850
  }, [
@@ -2115,15 +2853,10 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
2115
2853
  if (!fieldSchema) {
2116
2854
  log2.warn("invalid format", {
2117
2855
  props
2118
- }, {
2119
- F: __dxlog_file2,
2120
- L: 172,
2121
- S: void 0,
2122
- C: (f, a) => f(...a)
2123
- });
2856
+ }, { "~LogMeta": "~LogMeta", F: __dxlog_file2, L: 156, S: void 0 });
2124
2857
  return null;
2125
2858
  }
2126
- return /* @__PURE__ */ React17.createElement(Form.Root, {
2859
+ return /* @__PURE__ */ React20.createElement(Form.Root, {
2127
2860
  key: field.id,
2128
2861
  fieldMap,
2129
2862
  autoFocus: true,
@@ -2139,165 +2872,617 @@ var FieldEditor = ({ readonly, projection, field, registry, view, onSave, onCanc
2139
2872
  onValidate: handleValidate,
2140
2873
  onSave: handleSave,
2141
2874
  onCancel: handleCancel
2142
- }, /* @__PURE__ */ React17.createElement(Form.Content, null, /* @__PURE__ */ React17.createElement(Form.FieldSet, null), /* @__PURE__ */ React17.createElement(Form.Actions, null)));
2875
+ }, /* @__PURE__ */ React20.createElement(Form.Content, null, /* @__PURE__ */ React20.createElement(Form.FieldSet, null), /* @__PURE__ */ React20.createElement(Form.Actions, null)));
2143
2876
  };
2144
2877
 
2145
- // src/components/Settings/Settings.tsx
2146
- import React18 from "react";
2147
- import { Button as Button2, Input as Input12, ScrollArea as ScrollArea2, toLocalizedString, useTranslation as useTranslation9 } from "@dxos/react-ui";
2878
+ // src/components/ObjectForm/ObjectForm.tsx
2879
+ import React21, { useCallback as useCallback17, useMemo as useMemo11 } from "react";
2880
+ import { Obj as Obj5, Ref as Ref7, Tag as Tag3, Type as Type5 } from "@dxos/echo";
2881
+ import { splitJsonPath as splitJsonPath2 } from "@dxos/echo/internal";
2882
+ import { invariant } from "@dxos/invariant";
2883
+ import { HuePicker as HuePicker2 } from "@dxos/react-ui-pickers";
2884
+ import { translationKey as translationKey11 } from "#translations";
2885
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ObjectForm/ObjectForm.tsx";
2886
+ var createFieldMap = {
2887
+ hue: ({ type, label, layout, getValue, onValueChange }) => {
2888
+ const handleChange = useCallback17((nextHue) => onValueChange(type, nextHue), [
2889
+ onValueChange,
2890
+ type
2891
+ ]);
2892
+ const handleReset = useCallback17(() => onValueChange(type, void 0), [
2893
+ onValueChange,
2894
+ type
2895
+ ]);
2896
+ return /* @__PURE__ */ React21.createElement(React21.Fragment, null, layout !== "inline" && /* @__PURE__ */ React21.createElement(Form.Label, {
2897
+ label
2898
+ }), /* @__PURE__ */ React21.createElement(HuePicker2, {
2899
+ value: getValue(),
2900
+ onChange: handleChange,
2901
+ onReset: handleReset
2902
+ }));
2903
+ }
2904
+ };
2905
+ var ObjectForm = ({ object, type }) => {
2906
+ const db = Obj5.getDatabase(object);
2907
+ const meta = Obj5.getMeta(object);
2908
+ const tags = [
2909
+ ...meta.tags
2910
+ ];
2911
+ const values = useMemo11(() => ({
2912
+ [META_TAGS_KEY]: tags,
2913
+ ...object
2914
+ }), [
2915
+ object,
2916
+ tags
2917
+ ]);
2918
+ const formSchema = useMemo11(() => withMetaTags(Type5.getSchema(type)), [
2919
+ type
2920
+ ]);
2921
+ const handleCreate = useCallback17((type2, values2) => {
2922
+ invariant(db, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 48, S: void 0, A: ["db", ""] });
2923
+ invariant(Type5.isObject(type2), void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file3, L: 49, S: void 0, A: ["Type.isObject(type)", ""] });
2924
+ const newObject = db.add(Obj5.make(type2, values2));
2925
+ if (Obj5.instanceOf(Tag3.Tag, newObject)) {
2926
+ Obj5.update(object, (object2) => {
2927
+ Obj5.getMeta(object2).tags = [
2928
+ ...Obj5.getMeta(object2).tags,
2929
+ Ref7.make(newObject)
2930
+ ];
2931
+ });
2932
+ }
2933
+ }, []);
2934
+ const handleChange = useCallback17(({ [META_TAGS_KEY]: metaTags, ...values2 }, { isValid, changed }) => {
2935
+ if (!isValid) {
2936
+ return;
2937
+ }
2938
+ const changedPaths = Object.keys(changed).filter((path) => changed[path]);
2939
+ const hasTagsChange = changedPaths.some((path) => splitJsonPath2(path)[0] === META_TAGS_KEY);
2940
+ if (hasTagsChange) {
2941
+ Obj5.update(object, (object2) => {
2942
+ Obj5.getMeta(object2).tags = Array.isArray(metaTags) ? [
2943
+ ...metaTags
2944
+ ] : [];
2945
+ });
2946
+ }
2947
+ const nonTagPaths = changedPaths.filter((path) => splitJsonPath2(path)[0] !== META_TAGS_KEY);
2948
+ if (nonTagPaths.length > 0) {
2949
+ Obj5.update(object, () => {
2950
+ for (const path of nonTagPaths) {
2951
+ const parts = splitJsonPath2(path);
2952
+ const value3 = Obj5.getValue(values2, parts);
2953
+ Obj5.setValue(object, parts, value3);
2954
+ }
2955
+ });
2956
+ }
2957
+ }, [
2958
+ object
2959
+ ]);
2960
+ return /* @__PURE__ */ React21.createElement(Form.Root, {
2961
+ schema: formSchema,
2962
+ defaultValues: values,
2963
+ createTypename: Type5.getTypename(Tag3.Tag),
2964
+ createOptionIcon: "ph--plus--regular",
2965
+ createOptionLabel: [
2966
+ "add-tag.label",
2967
+ {
2968
+ ns: translationKey11
2969
+ }
2970
+ ],
2971
+ createInitialValuePath: "label",
2972
+ createFieldMap,
2973
+ db,
2974
+ onValuesChanged: handleChange,
2975
+ onCreate: handleCreate
2976
+ }, /* @__PURE__ */ React21.createElement(Form.Viewport, null, /* @__PURE__ */ React21.createElement(Form.Content, null, /* @__PURE__ */ React21.createElement(Form.FieldSet, null))));
2977
+ };
2978
+
2979
+ // src/components/ObjectProperties/ObjectProperties.tsx
2980
+ import * as Function from "effect/Function";
2981
+ import * as Option7 from "effect/Option";
2982
+ import React22, { useCallback as useCallback18, useMemo as useMemo12 } from "react";
2983
+ import { Obj as Obj6, Tag as Tag4, Type as Type6 } from "@dxos/echo";
2984
+ import { useType } from "@dxos/echo-react";
2985
+ import { splitJsonPath as splitJsonPath3 } from "@dxos/echo/internal";
2986
+ import { invariant as invariant2 } from "@dxos/invariant";
2987
+ import { composable as composable2, composableProps as composableProps2 } from "@dxos/react-ui";
2988
+ import { HuePicker as HuePicker3 } from "@dxos/react-ui-pickers";
2989
+ import { FactoryAnnotation } from "@dxos/schema";
2990
+ import { translationKey as translationKey12 } from "#translations";
2991
+ var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ObjectProperties/ObjectProperties.tsx";
2992
+ var ObjectProperties = composable2(({ children, object, ...props }, forwardedRef) => {
2993
+ const db = Obj6.getDatabase(object);
2994
+ const meta = Obj6.getMeta(object);
2995
+ const tags = [
2996
+ ...meta.tags
2997
+ ];
2998
+ const values = useMemo12(() => ({
2999
+ [META_TAGS_KEY]: tags,
3000
+ ...object
3001
+ }), [
3002
+ object,
3003
+ tags
3004
+ ]);
3005
+ const typename = Obj6.getTypename(object) ?? void 0;
3006
+ const typeFromRegistry = useType(db, typename);
3007
+ const type = Obj6.getType(object) ?? typeFromRegistry;
3008
+ const formSchema = useMemo12(() => {
3009
+ return Function.pipe(type, Option7.fromNullable, Option7.map((type2) => Type6.getSchema(type2)), Option7.map((schema) => withMetaTags(schema)), Option7.getOrUndefined);
3010
+ }, [
3011
+ type
3012
+ ]);
3013
+ const handleCreate = useCallback18((type2, values2) => {
3014
+ invariant2(db, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 52, S: void 0, A: ["db", ""] });
3015
+ invariant2(Type6.isObject(type2), void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file4, L: 53, S: void 0, A: ["Type.isObject(type)", ""] });
3016
+ const factory = Option7.getOrUndefined(FactoryAnnotation.get(Type6.getSchema(type2)));
3017
+ const newObject = factory ? factory(values2) : Obj6.make(type2, values2);
3018
+ return db.add(newObject);
3019
+ }, [
3020
+ db
3021
+ ]);
3022
+ const handleChange = useCallback18(({ [META_TAGS_KEY]: metaTags, ...values2 }, { isValid, changed }) => {
3023
+ if (!isValid) {
3024
+ return;
3025
+ }
3026
+ const changedPaths = Object.keys(changed).filter((path) => changed[path]);
3027
+ const hasTagsChange = changedPaths.some((path) => splitJsonPath3(path)[0] === META_TAGS_KEY);
3028
+ if (hasTagsChange) {
3029
+ Obj6.update(object, (object2) => {
3030
+ Obj6.getMeta(object2).tags = Array.isArray(metaTags) ? [
3031
+ ...metaTags
3032
+ ] : [];
3033
+ });
3034
+ }
3035
+ const nonTagPaths = changedPaths.filter((path) => splitJsonPath3(path)[0] !== META_TAGS_KEY);
3036
+ if (nonTagPaths.length > 0) {
3037
+ Obj6.update(object, () => {
3038
+ for (const path of nonTagPaths) {
3039
+ const parts = splitJsonPath3(path);
3040
+ const value3 = Obj6.getValue(values2, parts);
3041
+ Obj6.setValue(object, parts, value3);
3042
+ }
3043
+ });
3044
+ }
3045
+ }, [
3046
+ object
3047
+ ]);
3048
+ if (!formSchema) {
3049
+ return null;
3050
+ }
3051
+ return /* @__PURE__ */ React22.createElement(Form.Root, {
3052
+ schema: formSchema,
3053
+ defaultValues: values,
3054
+ createTypename: Type6.getTypename(Tag4.Tag),
3055
+ createOptionIcon: "ph--plus--regular",
3056
+ createOptionLabel: [
3057
+ "add-tag.label",
3058
+ {
3059
+ ns: translationKey12
3060
+ }
3061
+ ],
3062
+ createInitialValuePath: "label",
3063
+ createFieldMap: createFieldMap2,
3064
+ db,
3065
+ onValuesChanged: handleChange,
3066
+ onCreate: handleCreate
3067
+ }, /* @__PURE__ */ React22.createElement(Form.Viewport, {
3068
+ ...composableProps2(props),
3069
+ ref: forwardedRef
3070
+ }, /* @__PURE__ */ React22.createElement(Form.Content, null, /* @__PURE__ */ React22.createElement(Form.FieldSet, null), children)));
3071
+ });
3072
+ var createFieldMap2 = {
3073
+ hue: ({ type, label, layout, getValue, onValueChange }) => {
3074
+ const handleChange = useCallback18((nextHue) => onValueChange(type, nextHue), [
3075
+ onValueChange,
3076
+ type
3077
+ ]);
3078
+ const handleReset = useCallback18(() => onValueChange(type, void 0), [
3079
+ onValueChange,
3080
+ type
3081
+ ]);
3082
+ return /* @__PURE__ */ React22.createElement(React22.Fragment, null, layout !== "inline" && /* @__PURE__ */ React22.createElement(Form.Label, {
3083
+ label
3084
+ }), /* @__PURE__ */ React22.createElement(HuePicker3, {
3085
+ value: getValue(),
3086
+ onChange: handleChange,
3087
+ onReset: handleReset
3088
+ }));
3089
+ }
3090
+ };
3091
+
3092
+ // src/components/ObjectTree/ObjectTree.tsx
3093
+ import * as SchemaAST7 from "effect/SchemaAST";
3094
+ import React23 from "react";
3095
+ import { composable as composable3, composableProps as composableProps3 } from "@dxos/react-ui";
2148
3096
  import { mx as mx5 } from "@dxos/ui-theme";
2149
- var SETTINGS_ROOT_NAME = "Settings.Root";
2150
- var SETTINGS_SECTION_NAME = "Settings.Section";
2151
- var SETTINGS_SECTION_HEADING_NAME = "Settings.SectionHeading";
2152
- var SETTINGS_GROUP_NAME = "Settings.Group";
2153
- var SETTINGS_GROUP_BUTTON_NAME = "Settings.GroupButton";
2154
- var SETTINGS_CONTAINER_NAME = "Settings.Container";
2155
- var SETTINGS_FRAME_NAME = "Settings.Frame";
2156
- var SETTINGS_FRAME_ITEM_NAME = "Settings.FrameItem";
2157
- var SETTINGS_ITEM_NAME = "Settings.Item";
2158
- var SETTINGS_ITEM_INPUT_NAME = "Settings.ItemInput";
2159
- var styles = {
2160
- title: "pb-trim-md text-base-surface-text text-lg",
2161
- description: "text-base text-description",
2162
- grid: "grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-x-trim-lg"
2163
- };
2164
- var SettingsRoot = ({ children }) => {
2165
- return /* @__PURE__ */ React18.createElement(ScrollArea2.Root, {
2166
- orientation: "vertical",
2167
- className: "dx-article"
2168
- }, /* @__PURE__ */ React18.createElement(ScrollArea2.Viewport, {
2169
- classNames: "p-trim-md"
2170
- }, children));
3097
+ var ObjectTreeImpl = composable3(({ schema, value: value3, ...props }, forwardedRef) => /* @__PURE__ */ React23.createElement("div", {
3098
+ ...composableProps3(props, {
3099
+ role: "table",
3100
+ classNames: "font-mono text-sm w-full"
3101
+ }),
3102
+ ref: forwardedRef
3103
+ }, /* @__PURE__ */ React23.createElement(Node, {
3104
+ ast: schema.ast,
3105
+ value: value3,
3106
+ label: null,
3107
+ depth: 0
3108
+ })));
3109
+ ObjectTreeImpl.displayName = "ObjectTree";
3110
+ var ObjectTree = ObjectTreeImpl;
3111
+ var unwrap = (ast) => {
3112
+ if (SchemaAST7.isRefinement(ast)) {
3113
+ return unwrap(ast.from);
3114
+ }
3115
+ if (SchemaAST7.isSuspend(ast)) {
3116
+ return unwrap(ast.f());
3117
+ }
3118
+ if (SchemaAST7.isTransformation(ast)) {
3119
+ return unwrap(ast.from);
3120
+ }
3121
+ return ast;
2171
3122
  };
2172
- SettingsRoot.displayName = SETTINGS_ROOT_NAME;
2173
- var SettingsSection = ({ title, description, children }) => {
2174
- return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(SettingsSectionHeading, {
2175
- title,
2176
- description
2177
- }), /* @__PURE__ */ React18.createElement("div", {
2178
- className: "w-full pt-trim-md space-y-trim-md"
2179
- }, children));
3123
+ var stripOptional = (ast) => {
3124
+ if (!SchemaAST7.isUnion(ast)) {
3125
+ return ast;
3126
+ }
3127
+ const nonUndef = ast.types.filter((t) => !SchemaAST7.isUndefinedKeyword(t));
3128
+ return nonUndef.length === 1 ? nonUndef[0] : ast;
2180
3129
  };
2181
- SettingsSection.displayName = SETTINGS_SECTION_NAME;
2182
- var SettingsSectionHeading = ({ title, description }) => {
2183
- const { t } = useTranslation9(translationKey);
2184
- return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("h2", {
2185
- className: "px-trim-md mt-trim-md mb-trim-md text-xl"
2186
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React18.createElement("p", {
2187
- className: "px-trim-md my-trim-md text-description"
2188
- }, toLocalizedString(description, t)));
2189
- };
2190
- SettingsSectionHeading.displayName = SETTINGS_SECTION_HEADING_NAME;
2191
- var SettingsGroupButton = ({ classNames, ...props }) => {
2192
- return /* @__PURE__ */ React18.createElement(Button2, {
2193
- ...props,
2194
- classNames: [
2195
- "md:col-span-2",
2196
- classNames
2197
- ]
3130
+ var Node = ({ ast, value: value3, label, depth }) => {
3131
+ const inner = unwrap(stripOptional(ast));
3132
+ if (SchemaAST7.isTypeLiteral(inner) && isPlainObject(value3)) {
3133
+ const childDepth = label === null ? depth : depth + 1;
3134
+ return /* @__PURE__ */ React23.createElement(React23.Fragment, null, label !== null && /* @__PURE__ */ React23.createElement(Row, {
3135
+ label,
3136
+ value: null,
3137
+ depth,
3138
+ kind: "group"
3139
+ }), inner.propertySignatures.map((prop) => /* @__PURE__ */ React23.createElement(Node, {
3140
+ key: String(prop.name),
3141
+ ast: prop.type,
3142
+ value: value3[String(prop.name)],
3143
+ label: String(prop.name),
3144
+ depth: childDepth
3145
+ })));
3146
+ }
3147
+ if (SchemaAST7.isTupleType(inner) && Array.isArray(value3)) {
3148
+ const elemType = inner.rest[0]?.type;
3149
+ return /* @__PURE__ */ React23.createElement(React23.Fragment, null, label !== null && /* @__PURE__ */ React23.createElement(Row, {
3150
+ label,
3151
+ value: `Array(${value3.length})`,
3152
+ depth,
3153
+ kind: "group"
3154
+ }), value3.map((item, index) => /* @__PURE__ */ React23.createElement(Node, {
3155
+ key: index,
3156
+ ast: elemType ?? SchemaAST7.unknownKeyword,
3157
+ value: item,
3158
+ label: `[${index}]`,
3159
+ depth: depth + 1
3160
+ })));
3161
+ }
3162
+ return /* @__PURE__ */ React23.createElement(Row, {
3163
+ label: label ?? "",
3164
+ value: formatLeaf(value3),
3165
+ depth,
3166
+ kind: "leaf"
2198
3167
  });
2199
3168
  };
2200
- SettingsGroupButton.displayName = SETTINGS_GROUP_BUTTON_NAME;
2201
- var SettingsGroup = ({ children, classNames }) => /* @__PURE__ */ React18.createElement("div", {
2202
- role: "none",
2203
- className: mx5("group space-y-trim-md", classNames)
2204
- }, children);
2205
- SettingsGroup.displayName = SETTINGS_GROUP_NAME;
2206
- var SettingsFrame = ({ children }) => /* @__PURE__ */ React18.createElement("div", {
2207
- role: "none",
2208
- className: "p-trim-md border border-separator rounded-md"
2209
- }, children);
2210
- SettingsFrame.displayName = SETTINGS_FRAME_NAME;
2211
- var SettingsFrameItem = ({ title, description, children }) => {
2212
- const { t } = useTranslation9(translationKey);
2213
- return /* @__PURE__ */ React18.createElement("div", {
2214
- role: "group",
2215
- className: "min-w-0"
2216
- }, /* @__PURE__ */ React18.createElement("h3", {
2217
- className: "text-lg mb-2"
2218
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React18.createElement("p", {
2219
- className: "my-trim-sm md:mb-0 text-description"
2220
- }, toLocalizedString(description, t)), children);
2221
- };
2222
- SettingsFrameItem.displayName = SETTINGS_FRAME_ITEM_NAME;
2223
- var SettingsContainer = ({ classNames, children }) => {
2224
- return /* @__PURE__ */ React18.createElement("div", {
2225
- role: "none",
2226
- className: mx5([
2227
- "dx-article",
2228
- "*:first:mt-0! *:last:mb-0! px-trim-md py-trim-md",
2229
- "border border-separator rounded-md",
2230
- classNames
2231
- ])
3169
+ var Row = ({ label, value: value3, depth }) => /* @__PURE__ */ React23.createElement("div", {
3170
+ role: "row",
3171
+ className: mx5("flex items-baseline gap-3 py-1"),
3172
+ style: {
3173
+ paddingInlineStart: 8 + depth * 16
3174
+ }
3175
+ }, /* @__PURE__ */ React23.createElement("div", {
3176
+ role: "cell",
3177
+ className: "text-subdued"
3178
+ }, label), /* @__PURE__ */ React23.createElement("div", {
3179
+ role: "cell",
3180
+ className: mx5("break-all text-base-fg")
3181
+ }, value3));
3182
+ var isPlainObject = (value3) => typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
3183
+ var formatLeaf = (value3) => {
3184
+ if (value3 === void 0) {
3185
+ return null;
3186
+ }
3187
+ if (value3 === null) {
3188
+ return /* @__PURE__ */ React23.createElement("span", {
3189
+ className: "text-description"
3190
+ }, "null");
3191
+ }
3192
+ switch (typeof value3) {
3193
+ case "string":
3194
+ return /* @__PURE__ */ React23.createElement("span", {
3195
+ className: "text-blue-text"
3196
+ }, JSON.stringify(value3));
3197
+ case "number":
3198
+ case "bigint":
3199
+ return /* @__PURE__ */ React23.createElement("span", {
3200
+ className: "text-green-text"
3201
+ }, String(value3));
3202
+ case "boolean":
3203
+ return /* @__PURE__ */ React23.createElement("span", {
3204
+ className: "text-purple-text"
3205
+ }, String(value3));
3206
+ default:
3207
+ try {
3208
+ return JSON.stringify(value3);
3209
+ } catch {
3210
+ return String(value3);
3211
+ }
3212
+ }
3213
+ };
3214
+
3215
+ // src/components/Settings/Settings.tsx
3216
+ import React26 from "react";
3217
+ import { ScrollArea as ScrollArea2, toLocalizedString as toLocalizedString2, useTranslation as useTranslation12 } from "@dxos/react-ui";
3218
+ import { composable as composable4, composableProps as composableProps4 } from "@dxos/react-ui";
3219
+ import { mx as mx7 } from "@dxos/ui-theme";
3220
+ import { translationKey as translationKey14 } from "#translations";
3221
+
3222
+ // src/components/Settings/SettingsFieldSet.tsx
3223
+ import * as SchemaAST8 from "effect/SchemaAST";
3224
+ import * as String4 from "effect/String";
3225
+ import React25, { useCallback as useCallback19, useMemo as useMemo13 } from "react";
3226
+ import { getAnnotation as getAnnotation4 } from "@dxos/effect";
3227
+ import { Input as Input17, Select as Select2 } from "@dxos/react-ui";
3228
+
3229
+ // src/components/Settings/SettingsItem.tsx
3230
+ import React24 from "react";
3231
+ import { Input as Input16, toLocalizedString, useTranslation as useTranslation11 } from "@dxos/react-ui";
3232
+ import { mx as mx6 } from "@dxos/ui-theme";
3233
+ import { translationKey as translationKey13 } from "#translations";
3234
+ var SETTINGS_PANEL_NAME = "Settings.Panel";
3235
+ var SETTINGS_ITEM_NAME = "Settings.Item";
3236
+ var SettingsPanel = ({ classNames, children }) => {
3237
+ return /* @__PURE__ */ React24.createElement("div", {
3238
+ className: mx6("flex flex-col gap-3 p-trim-md border border-separator rounded-sm", classNames)
2232
3239
  }, children);
2233
3240
  };
2234
- SettingsContainer.displayName = SETTINGS_CONTAINER_NAME;
3241
+ SettingsPanel.displayName = SETTINGS_PANEL_NAME;
2235
3242
  var SettingsItem = ({ title, description = "", children }) => {
2236
- const { t } = useTranslation9(translationKey);
2237
- return /* @__PURE__ */ React18.createElement(SettingsContainer, {
2238
- classNames: styles.grid
2239
- }, /* @__PURE__ */ React18.createElement("h3", {
2240
- className: mx5(styles.title, "md:col-span-2")
2241
- }, toLocalizedString(title, t)), /* @__PURE__ */ React18.createElement("p", {
2242
- className: styles.description
2243
- }, toLocalizedString(description, t)), /* @__PURE__ */ React18.createElement("div", {
2244
- role: "none",
2245
- className: "overflow-hidden text-end py-1"
2246
- }, children));
3243
+ const { t } = useTranslation11(translationKey13);
3244
+ return /* @__PURE__ */ React24.createElement(Input16.Root, null, /* @__PURE__ */ React24.createElement(SettingsPanel, {
3245
+ classNames: "grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-x-trim-lg gap-y-0"
3246
+ }, /* @__PURE__ */ React24.createElement(Input16.Label, {
3247
+ classNames: "pb-trim-md text-base-fg text-lg md:col-span-2"
3248
+ }, toLocalizedString(title, t)), /* @__PURE__ */ React24.createElement(Input16.DescriptionAndValidation, null, /* @__PURE__ */ React24.createElement(Input16.Description, {
3249
+ classNames: "text-base text-description"
3250
+ }, toLocalizedString(description, t))), /* @__PURE__ */ React24.createElement("div", {
3251
+ className: "text-end py-1"
3252
+ }, children)));
2247
3253
  };
2248
3254
  SettingsItem.displayName = SETTINGS_ITEM_NAME;
2249
- var SettingsItemInput = ({ title, description = "", children }) => {
2250
- const { t } = useTranslation9(translationKey);
2251
- return /* @__PURE__ */ React18.createElement(Input12.Root, null, /* @__PURE__ */ React18.createElement(SettingsContainer, {
2252
- classNames: styles.grid
2253
- }, /* @__PURE__ */ React18.createElement(Input12.Label, {
2254
- classNames: mx5(styles.title, "md:col-span-2")
2255
- }, toLocalizedString(title, t)), /* @__PURE__ */ React18.createElement(Input12.DescriptionAndValidation, null, /* @__PURE__ */ React18.createElement(Input12.Description, {
2256
- classNames: styles.description
2257
- }, toLocalizedString(description, t))), /* @__PURE__ */ React18.createElement("div", {
2258
- role: "none",
2259
- className: "text-end py-1"
3255
+
3256
+ // src/components/Settings/SettingsFieldSet.tsx
3257
+ var SettingsFieldSet = ({ schema, values, onValuesChanged, readonly, fieldMap, visible, sort, pathPrefix = "" }) => {
3258
+ const properties = useMemo13(() => {
3259
+ const props = getFormProperties(schema.ast);
3260
+ if (!sort) {
3261
+ return props;
3262
+ }
3263
+ const rank = (name) => {
3264
+ const idx = sort.indexOf(name);
3265
+ return idx === -1 ? Number.POSITIVE_INFINITY : idx;
3266
+ };
3267
+ return [
3268
+ ...props
3269
+ ].sort(({ name: a }, { name: b }) => rank(a.toString()) - rank(b.toString()));
3270
+ }, [
3271
+ schema,
3272
+ sort
3273
+ ]);
3274
+ const handleChange = useCallback19((name, value3) => {
3275
+ onValuesChanged?.({
3276
+ ...values,
3277
+ [name]: value3
3278
+ });
3279
+ }, [
3280
+ values,
3281
+ onValuesChanged
3282
+ ]);
3283
+ return /* @__PURE__ */ React25.createElement(React25.Fragment, null, properties.map((property) => {
3284
+ const name = property.name.toString();
3285
+ const path = pathPrefix ? `${pathPrefix}.${name}` : name;
3286
+ if (visible && !visible(path, values)) {
3287
+ return null;
3288
+ }
3289
+ const entry = fieldMap?.[name];
3290
+ return /* @__PURE__ */ React25.createElement(SettingsFieldItem, {
3291
+ key: name,
3292
+ path,
3293
+ property,
3294
+ value: values[name],
3295
+ onChange: (value3) => handleChange(name, value3),
3296
+ readonly,
3297
+ customField: typeof entry === "function" ? entry : void 0,
3298
+ nestedFieldMap: typeof entry === "object" ? entry : void 0,
3299
+ visible,
3300
+ sort
3301
+ });
3302
+ }));
3303
+ };
3304
+ SettingsFieldSet.displayName = "Settings.FieldSet";
3305
+ var SettingsFieldItem = ({ property, path, value: value3, onChange, readonly, customField, nestedFieldMap, visible, sort }) => {
3306
+ const { type } = property;
3307
+ const name = property.name.toString();
3308
+ const title = getAnnotation4(SchemaAST8.TitleAnnotationId)(type) ?? String4.capitalize(name);
3309
+ const description = getAnnotation4(SchemaAST8.DescriptionAnnotationId)(type);
3310
+ if (customField) {
3311
+ const CustomField = customField;
3312
+ return /* @__PURE__ */ React25.createElement(SettingsItem, {
3313
+ title,
3314
+ description
3315
+ }, /* @__PURE__ */ React25.createElement(CustomField, {
3316
+ value: value3,
3317
+ onChange,
3318
+ readonly
3319
+ }));
3320
+ }
3321
+ const fieldType = detectFieldType(type);
3322
+ switch (fieldType) {
3323
+ case "struct":
3324
+ return /* @__PURE__ */ React25.createElement(SettingsFieldSet, {
3325
+ schema: {
3326
+ ast: type
3327
+ },
3328
+ values: value3 ?? {},
3329
+ onValuesChanged: onChange,
3330
+ readonly,
3331
+ fieldMap: nestedFieldMap,
3332
+ visible,
3333
+ sort,
3334
+ pathPrefix: path
3335
+ });
3336
+ case "boolean":
3337
+ return /* @__PURE__ */ React25.createElement(SettingsItem, {
3338
+ title,
3339
+ description
3340
+ }, /* @__PURE__ */ React25.createElement(Input17.Switch, {
3341
+ disabled: readonly,
3342
+ checked: !!value3,
3343
+ onCheckedChange: (checked) => onChange(!!checked)
3344
+ }));
3345
+ case "select": {
3346
+ const options = getSelectOptionsFromAst(type) ?? [];
3347
+ return /* @__PURE__ */ React25.createElement(SettingsItem, {
3348
+ title,
3349
+ description
3350
+ }, /* @__PURE__ */ React25.createElement(Select2.Root, {
3351
+ disabled: readonly,
3352
+ value: value3 == null ? "" : globalThis.String(value3),
3353
+ onValueChange: (selected) => {
3354
+ const matched = options.find((option) => globalThis.String(option.value) === selected);
3355
+ onChange(matched?.value ?? selected);
3356
+ }
3357
+ }, /* @__PURE__ */ React25.createElement(Select2.TriggerButton, {
3358
+ disabled: readonly
3359
+ }), /* @__PURE__ */ React25.createElement(Select2.Portal, null, /* @__PURE__ */ React25.createElement(Select2.Content, null, /* @__PURE__ */ React25.createElement(Select2.Viewport, null, options.map((option) => /* @__PURE__ */ React25.createElement(Select2.Option, {
3360
+ key: globalThis.String(option.value),
3361
+ value: globalThis.String(option.value)
3362
+ }, option.label ?? globalThis.String(option.value)))), /* @__PURE__ */ React25.createElement(Select2.Arrow, null)))));
3363
+ }
3364
+ case "string":
3365
+ return /* @__PURE__ */ React25.createElement(SettingsItem, {
3366
+ title,
3367
+ description
3368
+ }, /* @__PURE__ */ React25.createElement(Input17.TextInput, {
3369
+ disabled: readonly,
3370
+ value: value3 ?? "",
3371
+ onChange: (event) => onChange(event.target.value)
3372
+ }));
3373
+ case "number":
3374
+ return /* @__PURE__ */ React25.createElement(SettingsItem, {
3375
+ title,
3376
+ description
3377
+ }, /* @__PURE__ */ React25.createElement(Input17.TextInput, {
3378
+ disabled: readonly,
3379
+ type: "number",
3380
+ value: value3 ?? "",
3381
+ onChange: (event) => {
3382
+ if (event.target.value === "") {
3383
+ onChange(void 0);
3384
+ return;
3385
+ }
3386
+ const parsed = Number(event.target.value);
3387
+ onChange(Number.isNaN(parsed) ? void 0 : parsed);
3388
+ }
3389
+ }));
3390
+ default:
3391
+ return null;
3392
+ }
3393
+ };
3394
+
3395
+ // src/components/Settings/Settings.tsx
3396
+ var SETTINGS_ROOT_NAME = "Settings.Root";
3397
+ var SETTINGS_VIEWPORT_NAME = "Settings.Viewport";
3398
+ var SETTINGS_SECTION_NAME = "Settings.Section";
3399
+ var SettingsRoot = ({ children, classNames }) => {
3400
+ return /* @__PURE__ */ React26.createElement("div", {
3401
+ className: mx7("flex flex-col gap-2", classNames)
3402
+ }, children);
3403
+ };
3404
+ SettingsRoot.displayName = SETTINGS_ROOT_NAME;
3405
+ var SettingsViewport = composable4(({ children, ...props }, forwardedRef) => {
3406
+ return /* @__PURE__ */ React26.createElement(ScrollArea2.Root, {
3407
+ ...composableProps4(props),
3408
+ orientation: "vertical",
3409
+ centered: true,
3410
+ thin: true,
3411
+ ref: forwardedRef
3412
+ }, /* @__PURE__ */ React26.createElement(ScrollArea2.Viewport, {
3413
+ classNames: "px-4 pointer-coarse:px-2"
3414
+ }, /* @__PURE__ */ React26.createElement("div", {
3415
+ className: "dx-document flex flex-col gap-2 py-4"
2260
3416
  }, children)));
3417
+ });
3418
+ SettingsViewport.displayName = SETTINGS_VIEWPORT_NAME;
3419
+ var SettingsSection = ({ title, description, children }) => {
3420
+ const { t } = useTranslation12(translationKey14);
3421
+ return /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement("h2", {
3422
+ className: "px-trim-md mt-trim-md text-xl"
3423
+ }, toLocalizedString2(title, t)), description && /* @__PURE__ */ React26.createElement("p", {
3424
+ className: "px-trim-md text-description"
3425
+ }, toLocalizedString2(description, t)), /* @__PURE__ */ React26.createElement("div", {
3426
+ className: "w-full pt-trim-md space-y-trim-md"
3427
+ }, children));
2261
3428
  };
2262
- SettingsItemInput.displayName = SETTINGS_ITEM_INPUT_NAME;
3429
+ SettingsSection.displayName = SETTINGS_SECTION_NAME;
2263
3430
  var Settings = {
2264
3431
  Root: SettingsRoot,
3432
+ Viewport: SettingsViewport,
2265
3433
  Section: SettingsSection,
2266
- SectionHeading: SettingsSectionHeading,
2267
- Group: SettingsGroup,
2268
- GroupButton: SettingsGroupButton,
2269
- Container: SettingsContainer,
2270
- Frame: SettingsFrame,
2271
- FrameItem: SettingsFrameItem,
3434
+ Panel: SettingsPanel,
2272
3435
  Item: SettingsItem,
2273
- ItemInput: SettingsItemInput
3436
+ FieldSet: SettingsFieldSet
3437
+ };
3438
+
3439
+ // src/components/Settings/SettingsSelectField.tsx
3440
+ import React27 from "react";
3441
+ import { Select as Select3 } from "@dxos/react-ui";
3442
+ var createSelectField = ({ options, defaultLabel = "Default" }) => {
3443
+ const normalized = options.map((option) => typeof option === "string" ? {
3444
+ value: option,
3445
+ label: option
3446
+ } : option);
3447
+ const hasDefault = defaultLabel !== null;
3448
+ const sentinel = hasDefault ? `__default__${Math.random().toString(36).slice(2)}` : "";
3449
+ return ({ value: value3, onChange, readonly }) => /* @__PURE__ */ React27.createElement(Select3.Root, {
3450
+ disabled: readonly,
3451
+ value: value3 ?? sentinel,
3452
+ onValueChange: (next) => onChange(hasDefault && next === sentinel ? void 0 : next)
3453
+ }, /* @__PURE__ */ React27.createElement(Select3.TriggerButton, {
3454
+ disabled: readonly
3455
+ }), /* @__PURE__ */ React27.createElement(Select3.Portal, null, /* @__PURE__ */ React27.createElement(Select3.Content, null, /* @__PURE__ */ React27.createElement(Select3.Viewport, null, hasDefault && /* @__PURE__ */ React27.createElement(Select3.Option, {
3456
+ value: sentinel
3457
+ }, defaultLabel), normalized.map((option) => /* @__PURE__ */ React27.createElement(Select3.Option, {
3458
+ key: option.value,
3459
+ value: option.value
3460
+ }, option.label ?? option.value))), /* @__PURE__ */ React27.createElement(Select3.Arrow, null))));
2274
3461
  };
2275
3462
 
2276
3463
  // src/components/ViewEditor/ViewEditor.tsx
2277
3464
  import { RegistryContext } from "@effect-atom/atom-react";
2278
- import * as Array2 from "effect/Array";
2279
3465
  import * as Match2 from "effect/Match";
2280
- import * as Option4 from "effect/Option";
2281
- import * as Schema3 from "effect/Schema";
2282
- import React19, { forwardRef as forwardRef3, useCallback as useCallback15, useContext, useImperativeHandle, useMemo as useMemo8, useState as useState6 } from "react";
2283
- import { Entity as Entity2, Feed, Filter as Filter2, Format as Format5, Obj as Obj3, Query, QueryAST, Ref as Ref3 } from "@dxos/echo";
2284
- import { View } from "@dxos/echo";
2285
- import { EchoSchema, isMutable, toJsonSchema } from "@dxos/echo/internal";
2286
- import { invariant } from "@dxos/invariant";
3466
+ import * as Option8 from "effect/Option";
3467
+ import * as Schema5 from "effect/Schema";
3468
+ import React28, { forwardRef as forwardRef2, useCallback as useCallback20, useContext as useContext2, useImperativeHandle, useMemo as useMemo14, useState as useState7 } from "react";
3469
+ import { Entity as Entity2, Feed, Filter as Filter3, Format as Format7, Obj as Obj7, Query, QueryAST, Ref as Ref8, Type as Type7, View } from "@dxos/echo";
3470
+ import { invariant as invariant3 } from "@dxos/invariant";
2287
3471
  import { useObject, useQuery as useQuery2 } from "@dxos/react-client/echo";
2288
- import { IconButton as IconButton4, Input as Input13, Message, useTranslation as useTranslation10 } from "@dxos/react-ui";
3472
+ import { IconButton as IconButton4, Input as Input18, Message, useTranslation as useTranslation13 } from "@dxos/react-ui";
2289
3473
  import { QueryForm } from "@dxos/react-ui-components";
2290
3474
  import { List as List2 } from "@dxos/react-ui-list";
2291
3475
  import { ParentLabelAnnotation, ProjectionModel, VIEW_FIELD_LIMIT, createEchoChangeCallback, getTypenameFromQuery } from "@dxos/schema";
2292
- import { mx as mx6, osTranslations as osTranslations2, subtleHover as subtleHover2 } from "@dxos/ui-theme";
2293
- var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
2294
- var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode = "schema", registry, db, readonly, showHeading = false, types, tags, onQueryChanged, onDelete }, forwardedRef) => {
2295
- const atomRegistry = useContext(RegistryContext);
2296
- const schemaReadonly = !isMutable(schema);
2297
- const { t } = useTranslation10(translationKey);
2298
- const projectionModel = useMemo8(() => {
2299
- const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
2300
- const change = createEchoChangeCallback(view, schema instanceof EchoSchema ? schema : void 0);
3476
+ import { mx as mx8, osTranslations as osTranslations2 } from "@dxos/ui-theme";
3477
+ import { translationKey as translationKey15 } from "#translations";
3478
+ var __dxlog_file5 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
3479
+ var ViewEditor = /* @__PURE__ */ forwardRef2(({ classNames, type, view, mode = "schema", registry, db, readonly, showHeading = false, types, tags, onQueryChanged, onDelete }, forwardedRef) => {
3480
+ const atomRegistry = useContext2(RegistryContext);
3481
+ const schemaReadonly = Type7.getDatabase(type) == null;
3482
+ const { t } = useTranslation13(translationKey15);
3483
+ const projectionModel = useMemo14(() => {
3484
+ const jsonSchema = type.jsonSchema;
3485
+ const change = createEchoChangeCallback(view, Type7.getDatabase(type) != null ? type : void 0);
2301
3486
  const model = new ProjectionModel({
2302
3487
  registry: atomRegistry,
2303
3488
  view,
@@ -2307,7 +3492,7 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
2307
3492
  return model;
2308
3493
  }, [
2309
3494
  atomRegistry,
2310
- schema,
3495
+ type,
2311
3496
  view
2312
3497
  ]);
2313
3498
  useImperativeHandle(forwardedRef, () => projectionModel, [
@@ -2319,41 +3504,42 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
2319
3504
  if (from._tag !== "scope") {
2320
3505
  return void 0;
2321
3506
  }
2322
- return Option4.fromNullable(from.scope.queues).pipe(Option4.flatMap((queues) => Array2.head(queues)), Option4.map(String), Option4.getOrUndefined);
3507
+ const feedScope = from.scopes.find((s) => s._tag === "feed");
3508
+ return Option8.fromNullable(feedScope).pipe(Option8.map((s) => s.feedUri), Option8.getOrUndefined);
2323
3509
  }), Match2.orElse(() => void 0));
2324
- const feeds = useQuery2(db, Filter2.type(Feed.Feed));
2325
- const targetRef = useMemo8(() => {
3510
+ const feeds = useQuery2(db, Filter3.type(Feed.Feed));
3511
+ const targetRef = useMemo14(() => {
2326
3512
  if (!queueTarget) {
2327
3513
  return void 0;
2328
3514
  }
2329
- const feed = feeds.find((feed2) => Feed.getQueueDxn(feed2)?.toString() === queueTarget);
2330
- return feed ? Ref3.fromDXN(Entity2.getDXN(feed)) : void 0;
3515
+ const feed = feeds.find((feed2) => Feed.getQueueUri(feed2)?.toString() === queueTarget);
3516
+ return feed ? Ref8.fromURI(Entity2.getURI(feed)) : void 0;
2331
3517
  }, [
2332
3518
  queueTarget,
2333
3519
  feeds
2334
3520
  ]);
2335
- const viewSchema = useMemo8(() => {
2336
- const base = Schema3.Struct({
2337
- query: mode === "schema" ? Format5.URL.annotations({
3521
+ const viewSchema = useMemo14(() => {
3522
+ const base = Schema5.Struct({
3523
+ query: mode === "schema" ? Format7.URL.annotations({
2338
3524
  title: "Record type"
2339
3525
  }) : QueryAST.Query.annotations({
2340
3526
  title: "Query"
2341
3527
  })
2342
3528
  });
2343
3529
  if (mode === "tag") {
2344
- return Schema3.Struct({
3530
+ return Schema5.Struct({
2345
3531
  ...base.fields,
2346
3532
  // TODO(wittjosiah): Replace Type.Feed with Dataset.Dataset when Ref.Ref supports unions.
2347
- target: Ref3.Ref(Feed.Feed).pipe(Schema3.annotations({
3533
+ target: Ref8.Ref(Feed.Feed).pipe(Schema5.annotations({
2348
3534
  title: "Target Feed"
2349
- }), ParentLabelAnnotation.set(true), Schema3.optional)
2350
- }).pipe(Schema3.mutable);
3535
+ }), ParentLabelAnnotation.set(true), Schema5.optional)
3536
+ }).pipe(Schema5.mutable);
2351
3537
  }
2352
- return base.pipe(Schema3.mutable);
3538
+ return base.pipe(Schema5.mutable);
2353
3539
  }, [
2354
3540
  mode
2355
3541
  ]);
2356
- const viewValues = useMemo8(() => ({
3542
+ const viewValues = useMemo14(() => ({
2357
3543
  query: mode === "schema" ? getTypenameFromQuery(view.query.ast) : view.query.ast,
2358
3544
  target: targetRef
2359
3545
  }), [
@@ -2361,7 +3547,7 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
2361
3547
  view.query.ast,
2362
3548
  targetRef
2363
3549
  ]);
2364
- const fieldMap = useMemo8(() => mode === "tag" ? customFields({
3550
+ const fieldMap = useMemo14(() => mode === "tag" ? customFields({
2365
3551
  types,
2366
3552
  tags
2367
3553
  }) : void 0, [
@@ -2369,55 +3555,46 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
2369
3555
  types,
2370
3556
  tags
2371
3557
  ]);
2372
- const handleUpdate = useCallback15((values) => {
3558
+ const handleUpdate = useCallback20((values) => {
2373
3559
  const targetValue = values.target;
2374
3560
  let queueDxn;
2375
- if (Ref3.isRef(targetValue)) {
2376
- const feedDxn = targetValue.dxn.toString();
2377
- const feed = feeds.find((feed2) => Obj3.getDXN(feed2).toString() === feedDxn);
3561
+ if (Ref8.isRef(targetValue)) {
3562
+ const feedUri = targetValue.uri;
3563
+ const feed = feeds.find((feed2) => Obj7.getURI(feed2) === feedUri);
2378
3564
  if (feed) {
2379
- queueDxn = Feed.getQueueDxn(feed)?.toString();
3565
+ queueDxn = Feed.getQueueUri(feed);
2380
3566
  }
2381
3567
  }
2382
- const query = mode === "schema" ? Query.select(Filter2.typename(values.query)).ast : JSON.parse(JSON.stringify(values.query));
3568
+ const query = mode === "schema" ? Query.select(Filter3.typename(values.query)).ast : JSON.parse(JSON.stringify(values.query));
2383
3569
  onQueryChanged?.(query, queueDxn);
2384
3570
  }, [
2385
3571
  onQueryChanged,
2386
3572
  mode,
2387
3573
  feeds
2388
3574
  ]);
2389
- const handleDelete = useCallback15((fieldId) => {
2390
- invariant(!readonly, void 0, {
2391
- F: __dxlog_file3,
2392
- L: 185,
2393
- S: void 0,
2394
- A: [
2395
- "!readonly",
2396
- ""
2397
- ]
2398
- });
3575
+ const handleDelete = useCallback20((fieldId) => {
3576
+ invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 124, S: void 0, A: ["!readonly", ""] });
2399
3577
  onDelete?.(fieldId);
2400
3578
  }, [
2401
3579
  onDelete,
2402
3580
  readonly
2403
3581
  ]);
2404
- return /* @__PURE__ */ React19.createElement("div", {
2405
- role: "none",
2406
- className: mx6(classNames)
2407
- }, schemaReadonly && !readonly && /* @__PURE__ */ React19.createElement(Message.Root, {
3582
+ return /* @__PURE__ */ React28.createElement("div", {
3583
+ className: mx8(classNames)
3584
+ }, schemaReadonly && !readonly && /* @__PURE__ */ React28.createElement(Message.Root, {
2408
3585
  valence: "info",
2409
3586
  classNames: "my-form-padding"
2410
- }, /* @__PURE__ */ React19.createElement(Message.Title, null, t("system schema description"))), /* @__PURE__ */ React19.createElement(Form.Root, {
3587
+ }, /* @__PURE__ */ React28.createElement(Message.Title, null, t("system-schema.description"))), /* @__PURE__ */ React28.createElement(Form.Root, {
2411
3588
  schema: viewSchema,
2412
3589
  values: viewValues,
2413
3590
  fieldMap,
2414
3591
  db,
2415
3592
  onValuesChanged: handleUpdate
2416
- }, /* @__PURE__ */ React19.createElement(Form.FieldSet, null), /* @__PURE__ */ React19.createElement(FormFieldLabel, {
2417
- label: t("fields label"),
3593
+ }, /* @__PURE__ */ React28.createElement(Form.FieldSet, null), /* @__PURE__ */ React28.createElement(FormFieldLabel, {
3594
+ label: t("fields.label"),
2418
3595
  asChild: true
2419
- }), /* @__PURE__ */ React19.createElement(FieldList, {
2420
- schema,
3596
+ }), /* @__PURE__ */ React28.createElement(FieldList, {
3597
+ type,
2421
3598
  view,
2422
3599
  registry,
2423
3600
  readonly,
@@ -2425,14 +3602,14 @@ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode =
2425
3602
  onDelete: handleDelete
2426
3603
  })));
2427
3604
  });
2428
- var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDelete }) => {
2429
- const atomRegistry = useContext(RegistryContext);
2430
- const schemaReadonly = !isMutable(schema);
2431
- const { t } = useTranslation10(translationKey);
3605
+ var FieldList = ({ type, view, registry, readonly, showHeading = false, onDelete }) => {
3606
+ const atomRegistry = useContext2(RegistryContext);
3607
+ const schemaReadonly = Type7.getDatabase(type) == null;
3608
+ const { t } = useTranslation13(translationKey15);
2432
3609
  const [viewSnapshot] = useObject(view);
2433
- const projectionModel = useMemo8(() => {
2434
- const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
2435
- const change = createEchoChangeCallback(view, schema instanceof EchoSchema ? schema : void 0);
3610
+ const projectionModel = useMemo14(() => {
3611
+ const jsonSchema = type.jsonSchema;
3612
+ const change = createEchoChangeCallback(view, Type7.getDatabase(type) != null ? type : void 0);
2436
3613
  const model = new ProjectionModel({
2437
3614
  registry: atomRegistry,
2438
3615
  view,
@@ -2442,41 +3619,25 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
2442
3619
  return model;
2443
3620
  }, [
2444
3621
  atomRegistry,
2445
- schema,
3622
+ type,
2446
3623
  view
2447
3624
  ]);
2448
- const [expandedField, setExpandedField] = useState6();
2449
- const handleAdd = useCallback15(() => {
2450
- invariant(!readonly, void 0, {
2451
- F: __dxlog_file3,
2452
- L: 250,
2453
- S: void 0,
2454
- A: [
2455
- "!readonly",
2456
- ""
2457
- ]
2458
- });
3625
+ const [expandedField, setExpandedField] = useState7();
3626
+ const handleAdd = useCallback20(() => {
3627
+ invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 178, S: void 0, A: ["!readonly", ""] });
2459
3628
  const field = projectionModel.createFieldProjection();
2460
3629
  setExpandedField(field.id);
2461
3630
  }, [
2462
3631
  projectionModel,
2463
3632
  readonly
2464
3633
  ]);
2465
- const handleToggleField = useCallback15((field) => {
3634
+ const handleToggleField = useCallback20((field) => {
2466
3635
  setExpandedField((prevExpandedFieldId) => prevExpandedFieldId === field.id ? void 0 : field.id);
2467
3636
  }, [
2468
3637
  readonly
2469
3638
  ]);
2470
- const handleDelete = useCallback15((fieldId) => {
2471
- invariant(!readonly, void 0, {
2472
- F: __dxlog_file3,
2473
- L: 264,
2474
- S: void 0,
2475
- A: [
2476
- "!readonly",
2477
- ""
2478
- ]
2479
- });
3639
+ const handleDelete = useCallback20((fieldId) => {
3640
+ invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 191, S: void 0, A: ["!readonly", ""] });
2480
3641
  if (fieldId === expandedField) {
2481
3642
  setExpandedField(void 0);
2482
3643
  }
@@ -2486,36 +3647,28 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
2486
3647
  onDelete,
2487
3648
  readonly
2488
3649
  ]);
2489
- const handleMove = useCallback15((fromIndex, toIndex) => {
2490
- invariant(!readonly, void 0, {
2491
- F: __dxlog_file3,
2492
- L: 276,
2493
- S: void 0,
2494
- A: [
2495
- "!readonly",
2496
- ""
2497
- ]
2498
- });
2499
- Obj3.change(view, (v) => {
3650
+ const handleMove = useCallback20((fromIndex, toIndex) => {
3651
+ invariant3(!readonly, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file5, L: 202, S: void 0, A: ["!readonly", ""] });
3652
+ Obj7.update(view, (view2) => {
2500
3653
  const fields = [
2501
- ...v.projection.fields
3654
+ ...view2.projection.fields
2502
3655
  ];
2503
3656
  const [moved] = fields.splice(fromIndex, 1);
2504
3657
  fields.splice(toIndex, 0, moved);
2505
- v.projection.fields = fields;
3658
+ view2.projection.fields = fields;
2506
3659
  });
2507
3660
  }, [
2508
3661
  view,
2509
3662
  readonly
2510
3663
  ]);
2511
- const handleClose = useCallback15(() => setExpandedField(void 0), []);
2512
- const handleHide = useCallback15((fieldId) => {
3664
+ const handleClose = useCallback20(() => setExpandedField(void 0), []);
3665
+ const handleHide = useCallback20((fieldId) => {
2513
3666
  setExpandedField(void 0);
2514
3667
  projectionModel.hideFieldProjection(fieldId);
2515
3668
  }, [
2516
3669
  projectionModel
2517
3670
  ]);
2518
- const handleShow = useCallback15((property) => {
3671
+ const handleShow = useCallback20((property) => {
2519
3672
  setExpandedField(void 0);
2520
3673
  projectionModel.showFieldProjection(property);
2521
3674
  }, [
@@ -2524,70 +3677,67 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
2524
3677
  if (!viewSnapshot) {
2525
3678
  return null;
2526
3679
  }
2527
- return /* @__PURE__ */ React19.createElement(List2.Root, {
3680
+ return /* @__PURE__ */ React28.createElement(List2.Root, {
2528
3681
  items: viewSnapshot.projection.fields,
2529
- isItem: Schema3.is(View.FieldSchema),
3682
+ isItem: Schema5.is(View.FieldSchema),
2530
3683
  getId: (field) => field.id,
2531
3684
  onMove: readonly ? void 0 : handleMove,
2532
3685
  readonly
2533
- }, ({ items: fields }) => /* @__PURE__ */ React19.createElement(React19.Fragment, null, showHeading && /* @__PURE__ */ React19.createElement("h3", {
3686
+ }, ({ items: fields }) => /* @__PURE__ */ React28.createElement(React28.Fragment, null, showHeading && /* @__PURE__ */ React28.createElement("h3", {
2534
3687
  className: "text-sm"
2535
- }, t("field path label")), /* @__PURE__ */ React19.createElement("div", {
3688
+ }, t("field-path.label")), /* @__PURE__ */ React28.createElement("div", {
2536
3689
  role: "list",
2537
3690
  className: "grid grid-cols-[min-content_1fr_min-content_min-content_min-content]"
2538
3691
  }, fields?.map((field) => {
2539
3692
  const hidden = field.visible === false;
2540
- return /* @__PURE__ */ React19.createElement(List2.Item, {
3693
+ return /* @__PURE__ */ React28.createElement(List2.Item, {
2541
3694
  key: field.id,
2542
3695
  item: field,
2543
3696
  classNames: "grid grid-cols-subgrid col-span-5",
2544
3697
  "aria-expanded": expandedField === field.id
2545
- }, /* @__PURE__ */ React19.createElement("div", {
2546
- role: "none",
2547
- className: mx6(subtleHover2, "grid grid-cols-subgrid col-span-5", "rounded-xs cursor-pointer min-h-10")
2548
- }, /* @__PURE__ */ React19.createElement(List2.ItemDragHandle, {
3698
+ }, /* @__PURE__ */ React28.createElement("div", {
3699
+ className: "grid grid-cols-subgrid col-span-5 rounded-xs cursor-pointer min-h-10 dx-hover"
3700
+ }, /* @__PURE__ */ React28.createElement(List2.ItemDragHandle, {
2549
3701
  disabled: readonly || schemaReadonly
2550
- }), /* @__PURE__ */ React19.createElement(List2.ItemTitle, {
3702
+ }), /* @__PURE__ */ React28.createElement(List2.ItemTitle, {
2551
3703
  classNames: hidden && "text-subdued",
2552
3704
  onClick: () => handleToggleField(field)
2553
- }, field.path), /* @__PURE__ */ React19.createElement(List2.ItemIconButton, {
2554
- label: t(hidden ? "show field label" : "hide field label"),
3705
+ }, field.path), /* @__PURE__ */ React28.createElement(List2.ItemIconButton, {
3706
+ label: t(hidden ? "show-field.label" : "hide-field.label"),
2555
3707
  "data-testid": hidden ? "show-field-button" : "hide-field-button",
2556
3708
  icon: hidden ? "ph--eye-closed--regular" : "ph--eye--regular",
2557
3709
  autoHide: false,
2558
3710
  disabled: readonly || !hidden && projectionModel.getFields().length <= 1,
2559
3711
  onClick: () => hidden ? handleShow(field.path) : handleHide(field.id)
2560
- }), !readonly && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(List2.ItemDeleteButton, {
2561
- label: t("delete field label"),
3712
+ }), !readonly && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(List2.ItemDeleteButton, {
3713
+ label: t("delete-field.label"),
2562
3714
  autoHide: false,
2563
3715
  disabled: readonly || schemaReadonly || viewSnapshot.projection.fields.length <= 1,
2564
3716
  onClick: () => handleDelete(field.id),
2565
3717
  "data-testid": "field.delete"
2566
- }), /* @__PURE__ */ React19.createElement(List2.ItemIconButton, {
3718
+ }), /* @__PURE__ */ React28.createElement(List2.ItemIconButton, {
2567
3719
  iconOnly: true,
2568
3720
  variant: "ghost",
2569
- label: t("toggle expand label", {
3721
+ label: t("toggle-expand.label", {
2570
3722
  ns: osTranslations2
2571
3723
  }),
2572
3724
  icon: expandedField === field.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
2573
3725
  onClick: () => handleToggleField(field),
2574
3726
  "data-testid": "field.toggle"
2575
- }))), expandedField === field.id && !readonly && /* @__PURE__ */ React19.createElement("div", {
2576
- role: "none",
2577
- className: "col-span-5 mt-1 mb-1 border border-separator rounded-md"
2578
- }, /* @__PURE__ */ React19.createElement(FieldEditor, {
3727
+ }))), expandedField === field.id && !readonly && /* @__PURE__ */ React28.createElement("div", {
3728
+ className: "col-span-full mt-1 mb-1 border border-separator rounded-md"
3729
+ }, /* @__PURE__ */ React28.createElement(FieldEditor, {
2579
3730
  readonly: readonly || schemaReadonly,
2580
3731
  registry,
2581
3732
  projection: projectionModel,
2582
3733
  field,
2583
3734
  onSave: handleClose
2584
3735
  })));
2585
- })), !readonly && !expandedField && /* @__PURE__ */ React19.createElement("div", {
2586
- role: "none",
3736
+ })), !readonly && !expandedField && /* @__PURE__ */ React28.createElement("div", {
2587
3737
  className: "my-form-padding"
2588
- }, /* @__PURE__ */ React19.createElement(IconButton4, {
3738
+ }, /* @__PURE__ */ React28.createElement(IconButton4, {
2589
3739
  icon: "ph--plus--regular",
2590
- label: t("add property button label"),
3740
+ label: t("add-property-button.label"),
2591
3741
  onClick: handleAdd,
2592
3742
  disabled: viewSnapshot.projection.fields.length >= VIEW_FIELD_LIMIT,
2593
3743
  classNames: "w-full"
@@ -2595,13 +3745,13 @@ var FieldList = ({ schema, view, registry, readonly, showHeading = false, onDele
2595
3745
  };
2596
3746
  var customFields = ({ types, tags }) => ({
2597
3747
  query: ({ type, readonly, label, getValue, onValueChange }) => {
2598
- const handleChange = useCallback15((query) => onValueChange(type, query.ast), [
3748
+ const handleChange = useCallback20((query) => onValueChange(type, query.ast), [
2599
3749
  onValueChange
2600
3750
  ]);
2601
- return /* @__PURE__ */ React19.createElement(Input13.Root, null, /* @__PURE__ */ React19.createElement(FormFieldLabel, {
3751
+ return /* @__PURE__ */ React28.createElement(Input18.Root, null, /* @__PURE__ */ React28.createElement(FormFieldLabel, {
2602
3752
  readonly,
2603
3753
  label
2604
- }), /* @__PURE__ */ React19.createElement(QueryForm, {
3754
+ }), /* @__PURE__ */ React28.createElement(QueryForm, {
2605
3755
  initialQuery: getValue(),
2606
3756
  types,
2607
3757
  tags,
@@ -2612,15 +3762,27 @@ var customFields = ({ types, tags }) => ({
2612
3762
  export {
2613
3763
  ArrayField,
2614
3764
  BooleanField,
3765
+ DEFAULT_LAYOUT_NAME,
3766
+ DateField,
2615
3767
  FieldEditor,
2616
3768
  Form,
2617
3769
  FormFieldErrorBoundary,
2618
3770
  FormFieldLabel,
2619
3771
  FormFieldWrapper,
3772
+ FormLayout,
3773
+ FormLayoutAnnotation,
3774
+ FormLayoutAnnotationId,
3775
+ FormTooltipsContext,
2620
3776
  GeoPointField,
3777
+ InlineRefField,
3778
+ LayoutParseError,
3779
+ META_TAGS_KEY,
2621
3780
  MarkdownField,
2622
3781
  NumberField,
3782
+ ObjectForm,
2623
3783
  ObjectPicker,
3784
+ ObjectProperties,
3785
+ ObjectTree,
2624
3786
  RefField,
2625
3787
  SelectField,
2626
3788
  SelectOptionField,
@@ -2630,19 +3792,25 @@ export {
2630
3792
  TupleField,
2631
3793
  ViewEditor,
2632
3794
  cellClassesForFieldType,
3795
+ createSelectField,
3796
+ detectFieldType,
2633
3797
  formatForDisplay,
2634
3798
  formatForEditing,
2635
3799
  getDefaultValue,
2636
3800
  getFormProperties,
2637
3801
  getRefProps,
3802
+ getSelectOptionsFromAst,
3803
+ omitHiddenFormFields,
2638
3804
  omitId,
3805
+ parseLayout,
2639
3806
  parseValue,
2640
3807
  pathNotUniqueError,
2641
- translations,
2642
3808
  useFormContext,
2643
3809
  useFormFieldState,
2644
3810
  useFormHandler,
3811
+ useFormTooltips,
2645
3812
  useFormValues,
2646
- useKeyHandler
3813
+ useKeyHandler,
3814
+ withMetaTags
2647
3815
  };
2648
3816
  //# sourceMappingURL=index.mjs.map