@dxos/react-ui-form 0.8.4-main.3eb6e50203 → 0.8.4-main.3fbcb4aa9b

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