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