@dxos/react-ui-form 0.8.4-main.f9ba587 → 0.8.4-main.fffef41

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 (118) hide show
  1. package/dist/lib/browser/index.mjs +884 -637
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +884 -637
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/components/ControlSection/ControlSection.d.ts +2 -2
  8. package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +1 -1
  9. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts +80 -5
  10. package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts.map +1 -1
  11. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +4 -5
  12. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  13. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +77 -7
  14. package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts.map +1 -1
  15. package/dist/types/src/components/Form/ArrayField.d.ts +2 -2
  16. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
  17. package/dist/types/src/components/Form/Defaults.d.ts +5 -5
  18. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  19. package/dist/types/src/components/Form/Form.d.ts +8 -6
  20. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  21. package/dist/types/src/components/Form/Form.stories.d.ts +128 -32
  22. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  23. package/dist/types/src/components/Form/FormActions.d.ts.map +1 -1
  24. package/dist/types/src/components/Form/FormContent.d.ts +17 -11
  25. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
  26. package/dist/types/src/components/Form/FormContext.d.ts +3 -3
  27. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
  28. package/dist/types/src/components/Form/Input.d.ts +5 -2
  29. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  30. package/dist/types/src/components/Form/RefField.d.ts +15 -5
  31. package/dist/types/src/components/Form/RefField.d.ts.map +1 -1
  32. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +1 -1
  33. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
  34. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +1 -1
  35. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -1
  36. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +75 -4
  37. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -1
  38. package/dist/types/src/components/Form/custom/TupleInput.d.ts +1 -1
  39. package/dist/types/src/components/Form/factory.d.ts +1 -1
  40. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  41. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +41 -0
  42. package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -0
  43. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +81 -0
  44. package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -0
  45. package/dist/types/src/components/ObjectPicker/index.d.ts +2 -0
  46. package/dist/types/src/components/ObjectPicker/index.d.ts.map +1 -0
  47. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +20 -6
  48. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  49. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +80 -9
  50. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  51. package/dist/types/src/components/index.d.ts +1 -1
  52. package/dist/types/src/components/index.d.ts.map +1 -1
  53. package/dist/types/src/components/testing.d.ts +6 -3
  54. package/dist/types/src/components/testing.d.ts.map +1 -1
  55. package/dist/types/src/hooks/useForm.d.ts +3 -3
  56. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  57. package/dist/types/src/hooks/useQueryRefOptions.d.ts +9 -3
  58. package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +1 -1
  59. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +1 -1
  60. package/dist/types/src/translations.d.ts +13 -8
  61. package/dist/types/src/translations.d.ts.map +1 -1
  62. package/dist/types/src/util/field.d.ts +1 -1
  63. package/dist/types/src/util/field.d.ts.map +1 -1
  64. package/dist/types/src/util/formatting.d.ts +1 -1
  65. package/dist/types/src/util/formatting.d.ts.map +1 -1
  66. package/dist/types/src/util/refs.d.ts +1 -1
  67. package/dist/types/src/util/refs.d.ts.map +1 -1
  68. package/dist/types/src/util/schema.d.ts +1 -1
  69. package/dist/types/src/util/schema.d.ts.map +1 -1
  70. package/dist/types/tsconfig.tsbuildinfo +1 -1
  71. package/package.json +42 -36
  72. package/src/components/ControlSection/ControlSection.stories.tsx +11 -14
  73. package/src/components/ControlSection/ControlSection.tsx +26 -12
  74. package/src/components/FieldEditor/FieldEditor.stories.tsx +26 -24
  75. package/src/components/FieldEditor/FieldEditor.test.tsx +14 -13
  76. package/src/components/FieldEditor/FieldEditor.tsx +21 -23
  77. package/src/components/Form/ArrayField.tsx +13 -12
  78. package/src/components/Form/Defaults.tsx +23 -21
  79. package/src/components/Form/Form.stories.tsx +135 -99
  80. package/src/components/Form/Form.tsx +30 -16
  81. package/src/components/Form/FormActions.tsx +4 -3
  82. package/src/components/Form/FormContent.tsx +171 -49
  83. package/src/components/Form/FormContext.tsx +8 -8
  84. package/src/components/Form/Input.tsx +5 -2
  85. package/src/components/Form/RefField.tsx +111 -41
  86. package/src/components/Form/custom/GeoPointInput.tsx +29 -21
  87. package/src/components/Form/custom/SelectOptionsInput.stories.tsx +11 -11
  88. package/src/components/Form/custom/SelectOptionsInput.tsx +31 -32
  89. package/src/components/Form/custom/TupleInput.tsx +2 -2
  90. package/src/components/Form/factory.tsx +2 -2
  91. package/src/components/ObjectPicker/ObjectPicker.stories.tsx +207 -0
  92. package/src/components/ObjectPicker/ObjectPicker.tsx +161 -0
  93. package/src/components/ObjectPicker/index.ts +5 -0
  94. package/src/components/ViewEditor/ViewEditor.stories.tsx +130 -49
  95. package/src/components/ViewEditor/ViewEditor.test.tsx +19 -19
  96. package/src/components/ViewEditor/ViewEditor.tsx +281 -233
  97. package/src/components/index.ts +1 -2
  98. package/src/components/testing.tsx +15 -9
  99. package/src/hooks/useForm.ts +11 -6
  100. package/src/hooks/useQueryRefOptions.ts +15 -6
  101. package/src/hooks/useRefQueryLookupHandler.ts +3 -3
  102. package/src/translations.ts +15 -9
  103. package/src/util/field.ts +9 -19
  104. package/src/util/formatting.ts +1 -1
  105. package/src/util/refs.ts +7 -7
  106. package/src/util/schema.ts +2 -4
  107. package/dist/types/src/components/deprecated/Form.d.ts +0 -15
  108. package/dist/types/src/components/deprecated/Form.d.ts.map +0 -1
  109. package/dist/types/src/components/deprecated/Form.stories.d.ts +0 -13
  110. package/dist/types/src/components/deprecated/Form.stories.d.ts.map +0 -1
  111. package/dist/types/src/components/deprecated/FormInput.d.ts +0 -16
  112. package/dist/types/src/components/deprecated/FormInput.d.ts.map +0 -1
  113. package/dist/types/src/components/deprecated/index.d.ts +0 -2
  114. package/dist/types/src/components/deprecated/index.d.ts.map +0 -1
  115. package/src/components/deprecated/Form.stories.tsx +0 -62
  116. package/src/components/deprecated/Form.tsx +0 -119
  117. package/src/components/deprecated/FormInput.tsx +0 -71
  118. package/src/components/deprecated/index.ts +0 -5
@@ -10,7 +10,7 @@ var translations = [
10
10
  "hidden fields label": "Hidden Fields",
11
11
  "empty readonly ref field label": "(none)",
12
12
  // TODO(burdon): Standardize field/property.
13
- "button add property": "Add property",
13
+ "add property button": "Add property",
14
14
  "field property label": "Property",
15
15
  "field property placeholder": "Property name",
16
16
  "field format label": "Type",
@@ -20,9 +20,14 @@ var translations = [
20
20
  "field limit reached": "Maximum number of fields reached",
21
21
  "boolean input true value": "Yes",
22
22
  "boolean input false value": "No",
23
+ "show field label": "Show field",
24
+ "hide field label": "Hide field",
25
+ "delete field label": "Delete field",
26
+ "ref field combobox input placeholder": "Search\u2026",
27
+ "ref field placeholder_one": "Select\u2026",
28
+ "ref field placeholder_other": "Select items\u2026",
23
29
  // TODO(burdon): Factor out?
24
- "button cancel": "Cancel",
25
- "button save": "Save",
30
+ "save button": "Save",
26
31
  // FormatEnum
27
32
  "format boolean": "Boolean",
28
33
  "format currency": "Currency",
@@ -36,7 +41,7 @@ var translations = [
36
41
  "format hostname": "Hostname",
37
42
  "format integer": "Integer",
38
43
  "format json": "JSON",
39
- "format latlng": "Geopoint",
44
+ "format lnglat": "Geopoint",
40
45
  "format markdown": "Markdown",
41
46
  "format percent": "Percent",
42
47
  "format ref": "Reference",
@@ -52,9 +57,9 @@ var translations = [
52
57
  "format uri": "URI",
53
58
  "format url": "URL",
54
59
  "format uuid": "UUID",
55
- // Placeholders.
56
- "placeholder latitude": "Latitude",
57
- "placeholder longitude": "Longitude",
60
+ // GeoPointInput.
61
+ "latitude label": "Latitude",
62
+ "longitude label": "Longitude",
58
63
  // SelectOptionsInput.
59
64
  "select option label": "Label",
60
65
  "select option label placeholder": "Option label",
@@ -62,86 +67,38 @@ var translations = [
62
67
  "select option delete": "Delete",
63
68
  "select option add": "Add option",
64
69
  // System schema message.
65
- "system schema title": "System Schema",
66
- "system schema description": "This is a system schema and cannot be modified."
70
+ "system schema title": "System record type",
71
+ "system schema description": "This is a system record type and cannot be modified, though the view can still be configured."
67
72
  }
68
73
  }
69
74
  }
70
75
  ];
71
76
 
72
- // src/components/deprecated/FormInput.tsx
77
+ // src/components/ControlSection/ControlSection.tsx
73
78
  import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
74
79
  import React from "react";
75
- import { Input } from "@dxos/react-ui";
76
- import { mx, textBlockWidth } from "@dxos/react-ui-theme";
77
- var DeprecatedFormContainer = ({ children, classNames }) => {
78
- var _effect = _useSignals();
79
- try {
80
- return /* @__PURE__ */ React.createElement("div", {
81
- role: "none",
82
- className: "container-max-width p-4 justify-center overflow-x-hidden overflow-y-auto"
83
- }, /* @__PURE__ */ React.createElement("div", {
84
- role: "form",
85
- className: mx("flex flex-col", textBlockWidth, classNames)
86
- }, children));
87
- } finally {
88
- _effect.f();
89
- }
90
- };
91
- var DeprecatedFormInput = ({ label, description, secondary, children }) => {
80
+ import { Button, Input, toLocalizedString, useTranslation } from "@dxos/react-ui";
81
+ import { StackItem } from "@dxos/react-ui-stack";
82
+ import { mx } from "@dxos/react-ui-theme";
83
+ var ControlPage = ({ children, classNames, ...props }) => {
92
84
  var _effect = _useSignals();
93
85
  try {
94
- const primary = /* @__PURE__ */ React.createElement("div", {
95
- role: "none",
96
- className: "flex w-full gap-4 py-1"
97
- }, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement("div", {
98
- role: "none",
99
- className: "flex flex-col w-full"
100
- }, /* @__PURE__ */ React.createElement(Input.Label, {
101
- classNames: "flex min-bs-[--rail-action] items-center",
102
- style: {
103
- fontSize: "unset"
104
- }
105
- }, label), description && /* @__PURE__ */ React.createElement(Input.DescriptionAndValidation, {
106
- classNames: "mbs-0.5"
107
- }, /* @__PURE__ */ React.createElement(Input.Description, null, description))), /* @__PURE__ */ React.createElement("div", {
108
- role: "none"
86
+ return /* @__PURE__ */ React.createElement(StackItem.Content, {
87
+ scrollable: true,
88
+ classNames: "[--control-spacing:var(--dx-trimMd)]"
109
89
  }, /* @__PURE__ */ React.createElement("div", {
110
90
  role: "none",
111
- className: "flex min-bs-[--rail-action] items-center"
112
- }, children))));
113
- if (secondary) {
114
- return /* @__PURE__ */ React.createElement("div", {
115
- role: "none"
116
- }, primary, secondary);
117
- }
118
- return primary;
119
- } finally {
120
- _effect.f();
121
- }
122
- };
123
-
124
- // src/components/ControlSection/ControlSection.tsx
125
- import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
126
- import React2 from "react";
127
- import { Button, Input as Input2, toLocalizedString, useTranslation } from "@dxos/react-ui";
128
- import { mx as mx2 } from "@dxos/react-ui-theme";
129
- var ControlPage = ({ children, classNames, ...props }) => {
130
- var _effect = _useSignals2();
131
- try {
132
- return /* @__PURE__ */ React2.createElement("div", {
133
- role: "none",
134
- className: mx2("pli-cardSpacingInline", classNames),
91
+ className: mx("pli-cardSpacingInline pbe-trimLg", classNames),
135
92
  ...props
136
- }, children);
93
+ }, children));
137
94
  } finally {
138
95
  _effect.f();
139
96
  }
140
97
  };
141
98
  var ControlSection = ({ title, description, children }) => {
142
- var _effect = _useSignals2();
99
+ var _effect = _useSignals();
143
100
  try {
144
- return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(ControlSectionHeading, {
101
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ControlSectionHeading, {
145
102
  title,
146
103
  description
147
104
  }), children);
@@ -150,12 +107,12 @@ var ControlSection = ({ title, description, children }) => {
150
107
  }
151
108
  };
152
109
  var ControlSectionHeading = ({ title, description }) => {
153
- var _effect = _useSignals2();
110
+ var _effect = _useSignals();
154
111
  try {
155
112
  const { t } = useTranslation(translationKey);
156
- return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("h2", {
113
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("h2", {
157
114
  className: "pli-trimMd container-max-width text-xl mbs-trimLg mbe-trimMd"
158
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
115
+ }, toLocalizedString(title, t)), description && /* @__PURE__ */ React.createElement("p", {
159
116
  className: "pli-trimMd mlb-trimMd container-max-width text-description"
160
117
  }, toLocalizedString(description, t)));
161
118
  } finally {
@@ -163,9 +120,9 @@ var ControlSectionHeading = ({ title, description }) => {
163
120
  }
164
121
  };
165
122
  var ControlGroupButton = ({ classNames, ...props }) => {
166
- var _effect = _useSignals2();
123
+ var _effect = _useSignals();
167
124
  try {
168
- return /* @__PURE__ */ React2.createElement(Button, {
125
+ return /* @__PURE__ */ React.createElement(Button, {
169
126
  ...props,
170
127
  classNames: [
171
128
  "md:col-span-2",
@@ -177,41 +134,46 @@ var ControlGroupButton = ({ classNames, ...props }) => {
177
134
  }
178
135
  };
179
136
  var ControlGroup = ({ children, classNames }) => {
180
- var _effect = _useSignals2();
137
+ var _effect = _useSignals();
181
138
  try {
182
- return /* @__PURE__ */ React2.createElement("div", {
139
+ return /* @__PURE__ */ React.createElement("div", {
183
140
  role: "none",
184
- className: mx2("group container-max-width grid grid-cols-1 md:grid-cols-[1fr_min-content] gap-trimMd", classNames)
141
+ className: mx("group container-max-width grid grid-cols-1 md:grid-cols-[1fr_min-content] gap-trimMd", "[--control-spacing:0px] [&_input]:justify-self-end [&_button]:justify-self-end", classNames)
185
142
  }, children);
186
143
  } finally {
187
144
  _effect.f();
188
145
  }
189
146
  };
190
147
  var ControlFrame = ({ children }) => {
191
- var _effect = _useSignals2();
148
+ var _effect = _useSignals();
192
149
  try {
193
- return /* @__PURE__ */ React2.createElement("div", {
150
+ return /* @__PURE__ */ React.createElement("div", {
194
151
  role: "none",
195
- className: "p-trimMd container-max-width grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-trimSm md:gap-trimMd border border-separator rounded-md"
152
+ className: mx("container-max-width grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-trimSm md:gap-trimMd p-trimMd", "border border-separator rounded-md")
196
153
  }, children);
197
154
  } finally {
198
155
  _effect.f();
199
156
  }
200
157
  };
201
- var controlItemClasses = "pli-trimMd plb-trimMd container-max-width grid md:col-span-2 grid-cols-subgrid items-center gap-trimSm border border-separator rounded-md *:first:!mbs-0 *:last:!mbe-0";
202
- var controlItemTitleClasses = "text-lg font-normal";
203
- var controlItemDescriptionClasses = "text-base mlb-trimSm md:mbe-0 text-description";
158
+ var controlItemClasses = mx([
159
+ "container-max-width grid md:col-span-2 grid-cols-subgrid gap-trimSm items-center",
160
+ // TODO(burdon): Use grid gap consistently or apply margins consistently?
161
+ "mlb-[--control-spacing] *:first:!mbs-0 *:last:!mbe-0 pli-trimMd plb-trimMd",
162
+ "border border-separator rounded-md"
163
+ ]);
164
+ var controlItemTitleClasses = "mbe-0 text-lg text-baseText font-normal";
165
+ var controlItemDescriptionClasses = "mlb-trimSm md:mbe-0 text-base text-description";
204
166
  var ControlItem = ({ title, description, children }) => {
205
- var _effect = _useSignals2();
167
+ var _effect = _useSignals();
206
168
  try {
207
169
  const { t } = useTranslation(translationKey);
208
- return /* @__PURE__ */ React2.createElement("div", {
170
+ return /* @__PURE__ */ React.createElement("div", {
209
171
  className: controlItemClasses
210
- }, /* @__PURE__ */ React2.createElement("div", {
172
+ }, /* @__PURE__ */ React.createElement("div", {
211
173
  role: "none"
212
- }, /* @__PURE__ */ React2.createElement("h3", {
174
+ }, /* @__PURE__ */ React.createElement("h3", {
213
175
  className: controlItemTitleClasses
214
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
176
+ }, toLocalizedString(title, t)), description && /* @__PURE__ */ React.createElement("p", {
215
177
  className: controlItemDescriptionClasses
216
178
  }, toLocalizedString(description, t))), children);
217
179
  } finally {
@@ -219,16 +181,16 @@ var ControlItem = ({ title, description, children }) => {
219
181
  }
220
182
  };
221
183
  var ControlItemInput = ({ title, description, children }) => {
222
- var _effect = _useSignals2();
184
+ var _effect = _useSignals();
223
185
  try {
224
186
  const { t } = useTranslation(translationKey);
225
- return /* @__PURE__ */ React2.createElement(Input2.Root, null, /* @__PURE__ */ React2.createElement("div", {
187
+ return /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement("div", {
226
188
  className: controlItemClasses
227
- }, /* @__PURE__ */ React2.createElement("div", {
189
+ }, /* @__PURE__ */ React.createElement("div", {
228
190
  role: "none"
229
- }, /* @__PURE__ */ React2.createElement(Input2.Label, {
191
+ }, /* @__PURE__ */ React.createElement(Input.Label, {
230
192
  classNames: controlItemTitleClasses
231
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement(Input2.DescriptionAndValidation, null, /* @__PURE__ */ React2.createElement(Input2.Description, {
193
+ }, toLocalizedString(title, t)), description && /* @__PURE__ */ React.createElement(Input.DescriptionAndValidation, null, /* @__PURE__ */ React.createElement(Input.Description, {
232
194
  classNames: controlItemDescriptionClasses
233
195
  }, toLocalizedString(description, t)))), children));
234
196
  } finally {
@@ -236,15 +198,15 @@ var ControlItemInput = ({ title, description, children }) => {
236
198
  }
237
199
  };
238
200
  var ControlFrameItem = ({ title, description, children }) => {
239
- var _effect = _useSignals2();
201
+ var _effect = _useSignals();
240
202
  try {
241
203
  const { t } = useTranslation(translationKey);
242
- return /* @__PURE__ */ React2.createElement("div", {
204
+ return /* @__PURE__ */ React.createElement("div", {
243
205
  role: "group",
244
206
  className: "min-is-0"
245
- }, /* @__PURE__ */ React2.createElement("h3", {
207
+ }, /* @__PURE__ */ React.createElement("h3", {
246
208
  className: "text-lg mbe-2"
247
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
209
+ }, toLocalizedString(title, t)), description && /* @__PURE__ */ React.createElement("p", {
248
210
  className: "mlb-trimSm md:mbe-0 text-description"
249
211
  }, toLocalizedString(description, t)), children);
250
212
  } finally {
@@ -254,40 +216,40 @@ var ControlFrameItem = ({ title, description, children }) => {
254
216
 
255
217
  // src/components/FieldEditor/FieldEditor.tsx
256
218
  import { useSignals as _useSignals14 } from "@preact-signals/safe-react/tracking";
257
- import React14, { useCallback as useCallback9, useEffect as useEffect8, useMemo as useMemo7, useState as useState5 } from "react";
258
- import { FormatEnum as FormatEnum5, FormatEnums, formatToType } from "@dxos/echo-schema";
219
+ import React14, { useCallback as useCallback12, useEffect as useEffect8, useMemo as useMemo7, useState as useState6 } from "react";
220
+ import { FormatEnum as FormatEnum5, FormatEnums, formatToType } from "@dxos/echo/internal";
259
221
  import { log as log3 } from "@dxos/log";
260
- import { useTranslation as useTranslation8 } from "@dxos/react-ui";
261
- import { getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
222
+ import { useAsyncEffect, useTranslation as useTranslation9 } from "@dxos/react-ui";
223
+ import { formatToAdditionalPropertyAttributes, getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
262
224
 
263
225
  // src/components/Form/custom/GeoPointInput.tsx
264
- import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
265
- import React4, { useCallback, useState, useEffect, useMemo } from "react";
266
- import { GeoLocation } from "@dxos/echo-schema";
267
- import { Input as Input4, useTranslation as useTranslation2 } from "@dxos/react-ui";
226
+ import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
227
+ import React3, { useCallback, useEffect, useMemo, useState } from "react";
228
+ import { GeoLocation } from "@dxos/echo/internal";
229
+ import { Input as Input3, useTranslation as useTranslation2 } from "@dxos/react-ui";
268
230
  import { safeParseFloat } from "@dxos/util";
269
231
 
270
232
  // src/components/Form/Input.tsx
271
- import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
272
- import React3 from "react";
273
- import { Icon, Input as Input3, Tooltip } from "@dxos/react-ui";
233
+ import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
234
+ import React2 from "react";
235
+ import { Icon, Input as Input2, Tooltip } from "@dxos/react-ui";
274
236
  import { labelSpacing } from "@dxos/react-ui-stack";
275
- import { errorText, mx as mx3 } from "@dxos/react-ui-theme";
237
+ import { errorText, mx as mx2 } from "@dxos/react-ui-theme";
276
238
  var InputHeader = ({ error, label, readonly }) => {
277
- var _effect = _useSignals3();
239
+ var _effect = _useSignals2();
278
240
  try {
279
- const Label = readonly ? "span" : Input3.Label;
241
+ const Label = readonly ? "span" : Input2.Label;
280
242
  const labelProps = readonly ? {} : {
281
243
  classNames: "!mlb-0"
282
244
  };
283
- return /* @__PURE__ */ React3.createElement("div", {
245
+ return /* @__PURE__ */ React2.createElement("div", {
284
246
  role: "none",
285
- className: mx3("flex justify-between items-center", labelSpacing)
286
- }, /* @__PURE__ */ React3.createElement(Label, labelProps, label), error && /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
247
+ className: mx2("flex justify-between items-center", labelSpacing)
248
+ }, /* @__PURE__ */ React2.createElement(Label, labelProps, label), error && /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
287
249
  asChild: true,
288
250
  content: error,
289
251
  side: "bottom"
290
- }, /* @__PURE__ */ React3.createElement(Icon, {
252
+ }, /* @__PURE__ */ React2.createElement(Icon, {
291
253
  icon: "ph--warning--regular",
292
254
  size: 4,
293
255
  classNames: errorText
@@ -298,8 +260,8 @@ var InputHeader = ({ error, label, readonly }) => {
298
260
  };
299
261
 
300
262
  // src/components/Form/custom/GeoPointInput.tsx
301
- var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
302
- var _effect = _useSignals4();
263
+ var GeoPointInput = ({ type, label, readonly, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
264
+ var _effect = _useSignals3();
303
265
  try {
304
266
  const { t } = useTranslation2(translationKey);
305
267
  const { status, error } = getStatus();
@@ -344,46 +306,52 @@ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, on
344
306
  onValueChange,
345
307
  type
346
308
  ]);
347
- return /* @__PURE__ */ React4.createElement(Input4.Root, {
309
+ return /* @__PURE__ */ React3.createElement(Input3.Root, {
348
310
  validationValence: status
349
- }, /* @__PURE__ */ React4.createElement(InputHeader, {
311
+ }, /* @__PURE__ */ React3.createElement(InputHeader, {
350
312
  error,
351
313
  label
352
- }), /* @__PURE__ */ React4.createElement("div", {
314
+ }), /* @__PURE__ */ React3.createElement("div", {
353
315
  role: "none",
354
316
  className: "grid grid-cols-2 gap-2"
355
- }, /* @__PURE__ */ React4.createElement(Input4.TextInput, {
356
- type: "text",
357
- pattern: "^-?[0-9]*\\.?[0-9]*$",
358
- disabled,
359
- placeholder: t("placeholder latitude"),
317
+ }, /* @__PURE__ */ React3.createElement("div", {
318
+ role: "none"
319
+ }, /* @__PURE__ */ React3.createElement(Input3.Label, null, t("latitude label")), /* @__PURE__ */ React3.createElement(Input3.TextInput, {
320
+ type: "number",
321
+ step: "0.00001",
322
+ min: "-90",
323
+ max: "90",
324
+ disabled: !!readonly,
360
325
  value: latitudeText,
361
326
  onChange: handleCoordinateChange("latitude", setLatitudeText),
362
327
  onBlur
363
- }), /* @__PURE__ */ React4.createElement(Input4.TextInput, {
364
- type: "text",
365
- pattern: "^-?[0-9]*\\.?[0-9]*$",
366
- disabled,
367
- placeholder: t("placeholder longitude"),
328
+ })), /* @__PURE__ */ React3.createElement("div", {
329
+ role: "none"
330
+ }, /* @__PURE__ */ React3.createElement(Input3.Label, null, t("longitude label")), /* @__PURE__ */ React3.createElement(Input3.TextInput, {
331
+ type: "number",
332
+ step: "0.00001",
333
+ min: "-180",
334
+ max: "180",
335
+ disabled: !!readonly,
368
336
  value: longitudeText,
369
337
  onChange: handleCoordinateChange("longitude", setLongitudeText),
370
338
  onBlur
371
- })));
339
+ }))));
372
340
  } finally {
373
341
  _effect.f();
374
342
  }
375
343
  };
376
344
 
377
345
  // src/components/Form/custom/SelectOptionsInput.tsx
378
- import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
379
- import React5, { useCallback as useCallback2, useEffect as useEffect2, useState as useState2, useRef } from "react";
346
+ import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
347
+ import React4, { useCallback as useCallback2, useEffect as useEffect2, useRef, useState as useState2 } from "react";
380
348
  import { PublicKey } from "@dxos/keys";
381
- import { Icon as Icon2, IconButton, Input as Input5, Tag, Toolbar, useTranslation as useTranslation3 } from "@dxos/react-ui";
349
+ import { IconButton, Input as Input4, Tag, useTranslation as useTranslation3 } from "@dxos/react-ui";
382
350
  import { List } from "@dxos/react-ui-list";
383
351
  import { HuePicker } from "@dxos/react-ui-pickers";
384
- import { hues, mx as mx4 } from "@dxos/react-ui-theme";
385
- var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
386
- var _effect = _useSignals5();
352
+ import { hues, subtleHover } from "@dxos/react-ui-theme";
353
+ var SelectOptionInput = ({ type, label, readonly, getStatus, getValue: getValue3, onValueChange }) => {
354
+ var _effect = _useSignals4();
387
355
  try {
388
356
  const [selected, setSelectedId] = useState2(null);
389
357
  const [isNewOption, setIsNewOption] = useState2(false);
@@ -491,44 +459,56 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
491
459
  selected,
492
460
  isNewOption
493
461
  ]);
494
- return /* @__PURE__ */ React5.createElement(Input5.Root, {
462
+ return /* @__PURE__ */ React4.createElement(Input4.Root, {
495
463
  validationValence: status
496
- }, /* @__PURE__ */ React5.createElement(InputHeader, {
464
+ }, /* @__PURE__ */ React4.createElement(InputHeader, {
497
465
  error,
498
466
  label
499
- }), /* @__PURE__ */ React5.createElement("div", {
467
+ }), /* @__PURE__ */ React4.createElement("div", {
500
468
  role: "none"
501
- }, options && /* @__PURE__ */ React5.createElement(List.Root, {
469
+ }, options && /* @__PURE__ */ React4.createElement(List.Root, {
502
470
  items: options,
503
471
  isItem: (item) => true,
504
- onMove: handleMove
505
- }, ({ items }) => /* @__PURE__ */ React5.createElement("div", {
472
+ onMove: readonly ? void 0 : handleMove,
473
+ readonly: !!readonly
474
+ }, ({ items }) => /* @__PURE__ */ React4.createElement("div", {
506
475
  role: "list",
507
- className: "w-full overflow-auto"
508
- }, items?.map((item) => /* @__PURE__ */ React5.createElement("div", {
476
+ className: "is-full overflow-auto"
477
+ }, items?.map((item) => /* @__PURE__ */ React4.createElement("div", {
509
478
  key: item.id
510
- }, /* @__PURE__ */ React5.createElement(List.Item, {
479
+ }, /* @__PURE__ */ React4.createElement(List.Item, {
511
480
  role: "button",
512
481
  item,
513
- classNames: mx4("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
482
+ classNames: [
483
+ subtleHover,
484
+ "flex flex-col cursor-pointer rounded-sm"
485
+ ],
514
486
  "aria-expanded": selected === item.id
515
- }, /* @__PURE__ */ React5.createElement("div", {
487
+ }, /* @__PURE__ */ React4.createElement("div", {
516
488
  className: "flex items-center"
517
- }, /* @__PURE__ */ React5.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React5.createElement(List.ItemTitle, {
489
+ }, /* @__PURE__ */ React4.createElement(List.ItemDragHandle, {
490
+ disabled: !!readonly
491
+ }), /* @__PURE__ */ React4.createElement(List.ItemTitle, {
518
492
  onClick: () => handleClick(item.id),
519
493
  classNames: "flex-1"
520
- }, /* @__PURE__ */ React5.createElement(Tag, {
494
+ }, /* @__PURE__ */ React4.createElement(Tag, {
521
495
  palette: item.color
522
- }, item.title || "\u200B")), /* @__PURE__ */ React5.createElement(Icon2, {
496
+ }, item.title || "\u200B")), /* @__PURE__ */ React4.createElement(IconButton, {
497
+ iconOnly: true,
498
+ variant: "ghost",
499
+ label: t(selected === item.id ? "collapse label" : "expand label", {
500
+ ns: "os"
501
+ }),
523
502
  icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
524
503
  onClick: () => handleClick(item.id)
525
- })), selected === item.id && /* @__PURE__ */ React5.createElement("div", {
526
- className: "mis-4 mbs-2 flex flex-col gap-1"
527
- }, /* @__PURE__ */ React5.createElement(Input5.Label, {
504
+ })), selected === item.id && /* @__PURE__ */ React4.createElement("div", {
505
+ className: "pli-cardSpacingInline plb-cardSpacingBlock flex flex-col gap-1 density-fine"
506
+ }, /* @__PURE__ */ React4.createElement(Input4.Label, {
528
507
  classNames: "text-xs"
529
- }, t("select option label")), /* @__PURE__ */ React5.createElement("div", {
530
- className: "flex flex-row items-center gap-1"
531
- }, /* @__PURE__ */ React5.createElement(Input5.TextInput, {
508
+ }, t("select option label")), /* @__PURE__ */ React4.createElement("div", {
509
+ className: "grid grid-cols-[1fr_min-content_min-content] gap-1"
510
+ }, /* @__PURE__ */ React4.createElement(Input4.TextInput, {
511
+ disabled: !!readonly,
532
512
  placeholder: t("select option label placeholder"),
533
513
  ref: selected === item.id ? inputRef : void 0,
534
514
  value: item.title,
@@ -536,40 +516,34 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
536
516
  onKeyDown: handleKeyDown,
537
517
  classNames: "flex-1",
538
518
  "data-no-submit": true
539
- }), /* @__PURE__ */ React5.createElement(Toolbar.Root, {
540
- classNames: "p-0 m-0 !is-auto"
541
- }, /* @__PURE__ */ React5.createElement(HuePicker, {
519
+ }), /* @__PURE__ */ React4.createElement(HuePicker, {
520
+ disabled: !!readonly,
542
521
  value: item.color,
543
- onChange: handleColorChange(item.id),
544
- rootVariant: "toolbar-button"
545
- })), /* @__PURE__ */ React5.createElement(IconButton, {
522
+ onChange: handleColorChange(item.id)
523
+ }), /* @__PURE__ */ React4.createElement(IconButton, {
524
+ disabled: !!readonly,
546
525
  icon: "ph--trash--fill",
547
526
  iconOnly: true,
548
527
  label: t("select option delete"),
549
528
  onClick: () => handleDelete(item.id)
550
- })))))), /* @__PURE__ */ React5.createElement("div", {
551
- role: "listitem"
552
- }, /* @__PURE__ */ React5.createElement("div", {
553
- role: "button",
554
- className: mx4("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
555
- onClick: handleAdd
556
- }, /* @__PURE__ */ React5.createElement("div", {
557
- className: "flex items-center gap-1"
558
- }, /* @__PURE__ */ React5.createElement(Icon2, {
559
- icon: "ph--plus--regular"
560
- }), /* @__PURE__ */ React5.createElement("span", {
561
- className: "text-sm"
562
- }, t("select option add")))))))));
529
+ })))))), /* @__PURE__ */ React4.createElement(IconButton, {
530
+ variant: "ghost",
531
+ icon: "ph--plus--regular",
532
+ label: t("select option add"),
533
+ onClick: handleAdd,
534
+ disabled: !!readonly,
535
+ classNames: "is-full"
536
+ })))));
563
537
  } finally {
564
538
  _effect.f();
565
539
  }
566
540
  };
567
541
 
568
542
  // src/components/Form/custom/TupleInput.tsx
569
- import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
570
- import React6 from "react";
571
- import { Input as Input6 } from "@dxos/react-ui";
572
- import { mx as mx5 } from "@dxos/react-ui-theme";
543
+ import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
544
+ import React5 from "react";
545
+ import { Input as Input5 } from "@dxos/react-ui";
546
+ import { mx as mx3 } from "@dxos/react-ui-theme";
573
547
  import { safeParseFloat as safeParseFloat2 } from "@dxos/util";
574
548
  var gridCols = [
575
549
  "grid-cols-1",
@@ -577,22 +551,22 @@ var gridCols = [
577
551
  "grid-cols-3",
578
552
  "grid-cols-4"
579
553
  ];
580
- var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
581
- var _effect = _useSignals6();
554
+ var TupleInput = ({ binding, type, label, readonly, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
555
+ var _effect = _useSignals5();
582
556
  try {
583
557
  const { status, error } = getStatus();
584
558
  const values = getValue3() ?? {};
585
- return /* @__PURE__ */ React6.createElement(Input6.Root, {
559
+ return /* @__PURE__ */ React5.createElement(Input5.Root, {
586
560
  validationValence: status
587
- }, /* @__PURE__ */ React6.createElement(InputHeader, {
561
+ }, /* @__PURE__ */ React5.createElement(InputHeader, {
588
562
  error,
589
563
  label
590
- }), /* @__PURE__ */ React6.createElement("div", {
591
- className: mx5("grid gap-2", gridCols[binding.length - 1])
592
- }, binding.map((prop) => /* @__PURE__ */ React6.createElement(Input6.TextInput, {
564
+ }), /* @__PURE__ */ React5.createElement("div", {
565
+ className: mx3("grid gap-2", gridCols[binding.length - 1])
566
+ }, binding.map((prop) => /* @__PURE__ */ React5.createElement(Input5.TextInput, {
593
567
  key: prop,
594
568
  type: "number",
595
- disabled,
569
+ disabled: !!readonly,
596
570
  value: values[prop],
597
571
  onChange: (event) => onValueChange(type, {
598
572
  ...values,
@@ -606,103 +580,104 @@ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValu
606
580
  };
607
581
 
608
582
  // src/components/Form/Defaults.tsx
609
- import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
610
- import React7, { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef2 } from "react";
611
- import { Input as Input7, Select, useTranslation as useTranslation4 } from "@dxos/react-ui";
612
- var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
613
- var _effect = _useSignals7();
583
+ import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
584
+ import React6, { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef2 } from "react";
585
+ import { Input as Input6, Select, useTranslation as useTranslation4 } from "@dxos/react-ui";
586
+ var TextInput = ({ type, label, inputOnly, readonly, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
587
+ var _effect = _useSignals6();
614
588
  try {
615
589
  const { status, error } = getStatus();
616
- return disabled && !getValue3() ? null : disabled && inputOnly ? /* @__PURE__ */ React7.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React7.createElement(Input7.Root, {
590
+ return readonly && !getValue3() ? null : readonly === "static" && inputOnly ? /* @__PURE__ */ React6.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React6.createElement(Input6.Root, {
617
591
  validationValence: status
618
- }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
592
+ }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
619
593
  error,
620
594
  label
621
- }), disabled ? /* @__PURE__ */ React7.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React7.createElement(Input7.TextInput, {
622
- disabled,
595
+ }), readonly === "static" ? /* @__PURE__ */ React6.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React6.createElement(Input6.TextInput, {
596
+ disabled: !!readonly,
623
597
  placeholder,
624
598
  value: getValue3() ?? "",
625
599
  onChange: (event) => onValueChange(type, event.target.value),
626
600
  onBlur
627
- }), inputOnly && /* @__PURE__ */ React7.createElement(Input7.Validation, null, error));
601
+ }), inputOnly && /* @__PURE__ */ React6.createElement(Input6.Validation, null, error));
628
602
  } finally {
629
603
  _effect.f();
630
604
  }
631
605
  };
632
- var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
633
- var _effect = _useSignals7();
606
+ var NumberInput = ({ type, label, inputOnly, readonly, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
607
+ var _effect = _useSignals6();
634
608
  try {
635
609
  const { status, error } = getStatus();
636
- return disabled && !getValue3() ? null : disabled && inputOnly ? /* @__PURE__ */ React7.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React7.createElement(Input7.Root, {
610
+ return readonly && !getValue3() ? null : readonly === "static" && inputOnly ? /* @__PURE__ */ React6.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React6.createElement(Input6.Root, {
637
611
  validationValence: status
638
- }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
612
+ }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
639
613
  error,
640
614
  label
641
- }), disabled ? /* @__PURE__ */ React7.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React7.createElement(Input7.TextInput, {
615
+ }), readonly === "static" ? /* @__PURE__ */ React6.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React6.createElement(Input6.TextInput, {
642
616
  type: "number",
643
- disabled,
617
+ disabled: !!readonly,
644
618
  placeholder,
645
- value: getValue3() ?? 0,
619
+ value: getValue3(),
646
620
  onChange: (event) => onValueChange(type, event.target.value),
647
621
  onBlur
648
- }), inputOnly && /* @__PURE__ */ React7.createElement(Input7.DescriptionAndValidation, null, error));
622
+ }), inputOnly && /* @__PURE__ */ React6.createElement(Input6.DescriptionAndValidation, null, error));
649
623
  } finally {
650
624
  _effect.f();
651
625
  }
652
626
  };
653
- var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange, disabled }) => {
654
- var _effect = _useSignals7();
627
+ var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange, readonly }) => {
628
+ var _effect = _useSignals6();
655
629
  try {
656
630
  const { status, error } = getStatus();
657
631
  const checked = Boolean(getValue3());
658
632
  const { t } = useTranslation4(translationKey);
659
- return /* @__PURE__ */ React7.createElement(Input7.Root, {
633
+ return /* @__PURE__ */ React6.createElement(Input6.Root, {
660
634
  validationValence: status
661
- }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
635
+ }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
662
636
  error,
663
637
  label
664
- }), disabled ? /* @__PURE__ */ React7.createElement("p", null, t(checked ? "boolean input true value" : "boolean input false value")) : /* @__PURE__ */ React7.createElement(Input7.Switch, {
638
+ }), readonly === "static" ? /* @__PURE__ */ React6.createElement("p", null, t(checked ? "boolean input true value" : "boolean input false value")) : /* @__PURE__ */ React6.createElement(Input6.Switch, {
639
+ disabled: !!readonly,
665
640
  checked,
666
- onCheckedChange: (value) => onValueChange(type, value)
667
- }), inputOnly && /* @__PURE__ */ React7.createElement(Input7.DescriptionAndValidation, null, error));
641
+ onCheckedChange: (value2) => onValueChange(type, value2)
642
+ }), inputOnly && /* @__PURE__ */ React6.createElement(Input6.DescriptionAndValidation, null, error));
668
643
  } finally {
669
644
  _effect.f();
670
645
  }
671
646
  };
672
- var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
673
- var _effect = _useSignals7();
647
+ var SelectInput = ({ type, label, inputOnly, readonly, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
648
+ var _effect = _useSignals6();
674
649
  try {
675
650
  const { status, error } = getStatus();
676
- const value = getValue3();
677
- const handleValueChange = useCallback3((value2) => onValueChange(type, value2), [
651
+ const value2 = getValue3();
652
+ const handleValueChange = useCallback3((value3) => onValueChange(type, value3), [
678
653
  type,
679
654
  onValueChange
680
655
  ]);
681
- return disabled && !value ? null : /* @__PURE__ */ React7.createElement(Input7.Root, {
656
+ return readonly && !value2 ? null : /* @__PURE__ */ React6.createElement(Input6.Root, {
682
657
  validationValence: status
683
- }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
658
+ }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
684
659
  error,
685
660
  label
686
- }), disabled ? /* @__PURE__ */ React7.createElement("p", null, options?.find(({ value: optionValue }) => optionValue === value)?.label ?? String(value)) : /* @__PURE__ */ React7.createElement(Select.Root, {
687
- value,
661
+ }), readonly === "static" ? /* @__PURE__ */ React6.createElement("p", null, options?.find(({ value: optionValue }) => optionValue === value2)?.label ?? String(value2)) : /* @__PURE__ */ React6.createElement(Select.Root, {
662
+ value: value2,
688
663
  onValueChange: handleValueChange
689
- }, /* @__PURE__ */ React7.createElement(Select.TriggerButton, {
664
+ }, /* @__PURE__ */ React6.createElement(Select.TriggerButton, {
690
665
  classNames: "is-full",
691
- disabled,
666
+ disabled: !!readonly,
692
667
  placeholder
693
- }), /* @__PURE__ */ React7.createElement(Select.Portal, null, /* @__PURE__ */ React7.createElement(Select.Content, null, /* @__PURE__ */ React7.createElement(Select.Viewport, null, options?.map(({ value: value2, label: label2 }) => (
668
+ }), /* @__PURE__ */ React6.createElement(Select.Portal, null, /* @__PURE__ */ React6.createElement(Select.Content, null, /* @__PURE__ */ React6.createElement(Select.Viewport, null, options?.map(({ value: value3, label: label2 }) => (
694
669
  // NOTE: Numeric values are converted to and from strings.
695
- /* @__PURE__ */ React7.createElement(Select.Option, {
696
- key: String(value2),
697
- value: String(value2)
698
- }, label2 ?? String(value2))
699
- )))))), inputOnly && /* @__PURE__ */ React7.createElement(Input7.DescriptionAndValidation, null, error));
670
+ /* @__PURE__ */ React6.createElement(Select.Option, {
671
+ key: String(value3),
672
+ value: String(value3)
673
+ }, label2 ?? String(value3))
674
+ ))), /* @__PURE__ */ React6.createElement(Select.Arrow, null)))), inputOnly && /* @__PURE__ */ React6.createElement(Input6.DescriptionAndValidation, null, error));
700
675
  } finally {
701
676
  _effect.f();
702
677
  }
703
678
  };
704
- var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
705
- var _effect = _useSignals7();
679
+ var MarkdownInput = ({ type, label, inputOnly, readonly, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
680
+ var _effect = _useSignals6();
706
681
  try {
707
682
  const { status, error } = getStatus();
708
683
  const textareaRef = useRef2(null);
@@ -724,24 +699,24 @@ var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus,
724
699
  getValue3(),
725
700
  adjustHeight
726
701
  ]);
727
- return /* @__PURE__ */ React7.createElement(Input7.Root, {
702
+ return /* @__PURE__ */ React6.createElement(Input6.Root, {
728
703
  validationValence: status
729
- }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
704
+ }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
730
705
  error,
731
706
  label
732
- }), disabled ? /* @__PURE__ */ React7.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React7.createElement(Input7.TextArea, {
707
+ }), readonly === "static" ? /* @__PURE__ */ React6.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React6.createElement(Input6.TextArea, {
733
708
  ref: textareaRef,
734
- disabled,
709
+ disabled: !!readonly,
735
710
  placeholder,
736
711
  value: getValue3() ?? "",
737
- classNames: "min-bs-auto max-h-40 overflow-auto",
712
+ classNames: "min-bs-auto max-bs-40 overflow-auto",
738
713
  onChange: (event) => onValueChange(type, event.target.value),
739
714
  onBlur,
740
715
  style: {
741
716
  resize: "none"
742
717
  },
743
718
  spellCheck: false
744
- }), inputOnly && /* @__PURE__ */ React7.createElement(Input7.Validation, null, error));
719
+ }), inputOnly && /* @__PURE__ */ React6.createElement(Input6.Validation, null, error));
745
720
  } finally {
746
721
  _effect.f();
747
722
  }
@@ -749,27 +724,28 @@ var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus,
749
724
 
750
725
  // src/components/Form/Form.tsx
751
726
  import { useSignals as _useSignals13 } from "@preact-signals/safe-react/tracking";
752
- import React13, { useEffect as useEffect7, useMemo as useMemo6, useRef as useRef3 } from "react";
727
+ import { useFocusFinders } from "@fluentui/react-tabster";
728
+ import React13, { useCallback as useCallback11, useEffect as useEffect7, useRef as useRef3 } from "react";
753
729
  import { cardDialogOverflow, cardSpacing as cardSpacing2 } from "@dxos/react-ui-stack";
754
730
 
755
731
  // src/components/Form/FormActions.tsx
756
- import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
757
- import React9 from "react";
732
+ import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
733
+ import React8 from "react";
758
734
  import { IconButton as IconButton2, useTranslation as useTranslation5 } from "@dxos/react-ui";
759
735
  import { cardSpacing } from "@dxos/react-ui-stack";
760
- import { mx as mx6 } from "@dxos/react-ui-theme";
736
+ import { mx as mx4 } from "@dxos/react-ui-theme";
761
737
 
762
738
  // src/components/Form/FormContext.tsx
763
- import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
764
- import React8, { createContext, useContext, useEffect as useEffect6, useMemo as useMemo3, useCallback as useCallback6 } from "react";
739
+ import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
740
+ import React7, { createContext, useCallback as useCallback7, useContext, useEffect as useEffect6, useMemo as useMemo3 } from "react";
765
741
  import { raise } from "@dxos/debug";
766
- import { getValue as getValue2 } from "@dxos/echo-schema";
742
+ import { getValue as getValue2 } from "@dxos/echo/internal";
767
743
  import { createJsonPath as createJsonPath2 } from "@dxos/effect";
768
744
 
769
745
  // src/hooks/useForm.ts
770
- import { SchemaAST } from "effect";
746
+ import * as SchemaAST from "effect/SchemaAST";
771
747
  import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo2, useState as useState3 } from "react";
772
- import { getValue, setValue } from "@dxos/echo-schema";
748
+ import { getValue, setValue } from "@dxos/echo/internal";
773
749
  import { createJsonPath, fromEffectValidationPath } from "@dxos/effect";
774
750
  import { invariant } from "@dxos/invariant";
775
751
  import { log } from "@dxos/log";
@@ -778,7 +754,7 @@ var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.t
778
754
  var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
779
755
  invariant(SchemaAST.isTypeLiteral(schema.ast), void 0, {
780
756
  F: __dxlog_file,
781
- L: 93,
757
+ L: 96,
782
758
  S: void 0,
783
759
  A: [
784
760
  "SchemaAST.isTypeLiteral(schema.ast)",
@@ -872,17 +848,17 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
872
848
  }, [
873
849
  values
874
850
  ]);
875
- const onValueChange = useCallback4((path, type, value) => {
851
+ const onValueChange = useCallback4((path, type, value2) => {
876
852
  const jsonPath = createJsonPath(path);
877
- let parsedValue = value;
853
+ let parsedValue = value2;
878
854
  try {
879
855
  if (type === "number") {
880
- parsedValue = parseFloat(value) || 0;
856
+ parsedValue = parseFloat(value2) || 0;
881
857
  }
882
858
  } catch (err) {
883
859
  log.catch(err, void 0, {
884
860
  F: __dxlog_file,
885
- L: 213,
861
+ L: 217,
886
862
  S: void 0,
887
863
  C: (f, a) => f(...a)
888
864
  });
@@ -892,15 +868,16 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
892
868
  ...setValue(values, jsonPath, parsedValue)
893
869
  };
894
870
  setValues(newValues);
895
- setChanged((prev) => ({
896
- ...prev,
871
+ const newChanged = {
872
+ ...changed,
897
873
  [jsonPath]: true
898
- }));
874
+ };
875
+ setChanged(newChanged);
899
876
  onValuesChanged?.(newValues);
900
877
  const isValid = validate(newValues);
901
878
  if (isValid && onValid) {
902
879
  onValid(newValues, {
903
- changed
880
+ changed: newChanged
904
881
  });
905
882
  }
906
883
  }, [
@@ -950,10 +927,10 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
950
927
  onTouched
951
928
  ]);
952
929
  };
953
- var createKeySet = (obj, value) => {
930
+ var createKeySet = (obj, value2) => {
954
931
  invariant(obj, void 0, {
955
932
  F: __dxlog_file,
956
- L: 275,
933
+ L: 280,
957
934
  S: void 0,
958
935
  A: [
959
936
  "obj",
@@ -962,7 +939,7 @@ var createKeySet = (obj, value) => {
962
939
  });
963
940
  return Object.keys(obj).reduce((acc, key) => ({
964
941
  ...acc,
965
- [key]: value
942
+ [key]: value2
966
943
  }), {});
967
944
  };
968
945
  var flatMap = (errors) => {
@@ -977,7 +954,8 @@ var flatMap = (errors) => {
977
954
 
978
955
  // src/hooks/useRefQueryLookupHandler.ts
979
956
  import { useCallback as useCallback5 } from "react";
980
- import { getObjectDXN } from "@dxos/echo-schema";
957
+ import { Obj } from "@dxos/echo";
958
+ import { getObjectDXN } from "@dxos/echo/internal";
981
959
  import { Filter } from "@dxos/react-client/echo";
982
960
  import { isNonNullable } from "@dxos/util";
983
961
  var useRefQueryLookupHandler = ({ space }) => {
@@ -994,7 +972,7 @@ var useRefQueryLookupHandler = ({ space }) => {
994
972
  }
995
973
  const item = {
996
974
  dxn,
997
- label: object?.name ?? object?.id ?? ""
975
+ label: Obj.getLabel(object) ?? object?.id ?? ""
998
976
  };
999
977
  return item;
1000
978
  }).filter(isNonNullable);
@@ -1004,12 +982,14 @@ var useRefQueryLookupHandler = ({ space }) => {
1004
982
  };
1005
983
 
1006
984
  // src/hooks/useQueryRefOptions.ts
1007
- import { useEffect as useEffect5, useState as useState4 } from "react";
985
+ import { useCallback as useCallback6, useEffect as useEffect5, useState as useState4 } from "react";
1008
986
  import { log as log2 } from "@dxos/log";
1009
987
  var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/hooks/useQueryRefOptions.ts";
1010
988
  var useQueryRefOptions = ({ refTypeInfo, onQueryRefOptions }) => {
1011
989
  const [options, setOptions] = useState4([]);
1012
990
  const [loading, setLoading] = useState4(false);
991
+ const [state, setState] = useState4({});
992
+ const update = useCallback6(() => setState({}), []);
1013
993
  useEffect5(() => {
1014
994
  if (!refTypeInfo || !onQueryRefOptions) {
1015
995
  return;
@@ -1029,7 +1009,7 @@ var useQueryRefOptions = ({ refTypeInfo, onQueryRefOptions }) => {
1029
1009
  } catch (error) {
1030
1010
  log2.error("Failed to fetch ref options:", error, {
1031
1011
  F: __dxlog_file2,
1032
- L: 42,
1012
+ L: 51,
1033
1013
  S: void 0,
1034
1014
  C: (f, a) => f(...a)
1035
1015
  });
@@ -1041,10 +1021,12 @@ var useQueryRefOptions = ({ refTypeInfo, onQueryRefOptions }) => {
1041
1021
  void fetchOptions();
1042
1022
  }, [
1043
1023
  refTypeInfo,
1044
- onQueryRefOptions
1024
+ onQueryRefOptions,
1025
+ state
1045
1026
  ]);
1046
1027
  return {
1047
1028
  options,
1029
+ update,
1048
1030
  loading
1049
1031
  };
1050
1032
  };
@@ -1067,7 +1049,7 @@ var useInputProps = (path = []) => {
1067
1049
  return useMemo3(() => ({
1068
1050
  getStatus: () => getStatus(stablePath),
1069
1051
  getValue: () => getFormValue(stablePath),
1070
- onValueChange: (type, value) => onValueChange(stablePath, type, value),
1052
+ onValueChange: (type, value2) => onValueChange(stablePath, type, value2),
1071
1053
  onBlur: () => onTouched(stablePath)
1072
1054
  }), [
1073
1055
  getStatus,
@@ -1078,10 +1060,10 @@ var useInputProps = (path = []) => {
1078
1060
  ]);
1079
1061
  };
1080
1062
  var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
1081
- var _effect = _useSignals8();
1063
+ var _effect = _useSignals7();
1082
1064
  try {
1083
1065
  const form = useForm(formOptions);
1084
- const handleKeyDown = useCallback6((event) => {
1066
+ const handleKeyDown = useCallback7((event) => {
1085
1067
  const keyIsEnter = event.key === "Enter";
1086
1068
  const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
1087
1069
  const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
@@ -1097,7 +1079,9 @@ var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
1097
1079
  }
1098
1080
  }
1099
1081
  }, [
1100
- form,
1082
+ form.canSave,
1083
+ form.formIsValid,
1084
+ form.handleSave,
1101
1085
  autoSave
1102
1086
  ]);
1103
1087
  useEffect6(() => {
@@ -1114,7 +1098,7 @@ var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
1114
1098
  form.handleSave,
1115
1099
  autoSave
1116
1100
  ]);
1117
- return /* @__PURE__ */ React8.createElement(FormContext.Provider, {
1101
+ return /* @__PURE__ */ React7.createElement(FormContext.Provider, {
1118
1102
  value: form
1119
1103
  }, children);
1120
1104
  } finally {
@@ -1124,24 +1108,24 @@ var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
1124
1108
 
1125
1109
  // src/components/Form/FormActions.tsx
1126
1110
  var FormActions = ({ readonly, onCancel, outerSpacing = true }) => {
1127
- var _effect = _useSignals9();
1111
+ var _effect = _useSignals8();
1128
1112
  try {
1129
1113
  const { t } = useTranslation5(translationKey);
1130
1114
  const { canSave, handleSave } = useFormContext();
1131
- return /* @__PURE__ */ React9.createElement("div", {
1115
+ return /* @__PURE__ */ React8.createElement("div", {
1132
1116
  role: "none",
1133
- className: mx6(outerSpacing === "scroll-fields" ? "pli-cardSpacingInline mbe-cardSpacingBlock" : outerSpacing ? cardSpacing : "mbs-cardSpacingBlock", "flex [&_button]:grow gap-1 first:mbs-0")
1134
- }, onCancel && !readonly && /* @__PURE__ */ React9.createElement(IconButton2, {
1117
+ className: mx4(outerSpacing === "scroll-fields" ? "pli-cardSpacingInline mbe-cardSpacingBlock" : outerSpacing ? cardSpacing : "mbs-cardSpacingBlock", "flex [&_button]:grow gap-1 first:mbs-0")
1118
+ }, onCancel && !readonly && /* @__PURE__ */ React8.createElement(IconButton2, {
1135
1119
  "data-testid": "cancel-button",
1136
1120
  icon: "ph--x--regular",
1137
- label: t("button cancel"),
1121
+ label: t("cancel button"),
1138
1122
  onClick: onCancel
1139
- }), handleSave && /* @__PURE__ */ React9.createElement(IconButton2, {
1123
+ }), handleSave && /* @__PURE__ */ React8.createElement(IconButton2, {
1140
1124
  type: "submit",
1141
1125
  "data-testid": "save-button",
1142
1126
  disabled: !canSave,
1143
1127
  icon: "ph--check--regular",
1144
- label: t("button save"),
1128
+ label: t("save button"),
1145
1129
  onClick: handleSave
1146
1130
  }));
1147
1131
  } finally {
@@ -1151,53 +1135,45 @@ var FormActions = ({ readonly, onCancel, outerSpacing = true }) => {
1151
1135
 
1152
1136
  // src/components/Form/FormContent.tsx
1153
1137
  import { useSignals as _useSignals12 } from "@preact-signals/safe-react/tracking";
1154
- import { Schema, SchemaAST as SchemaAST4, pipe as pipe2 } from "effect";
1155
- import { capitalize as capitalize2 } from "effect/String";
1156
- import React12, { forwardRef, useMemo as useMemo5 } from "react";
1138
+ import * as Function2 from "effect/Function";
1139
+ import * as Schema from "effect/Schema";
1140
+ import * as SchemaAST4 from "effect/SchemaAST";
1141
+ import * as StringEffect from "effect/String";
1142
+ import React12, { Component, forwardRef as forwardRef2, useMemo as useMemo6 } from "react";
1157
1143
  import { createJsonPath as createJsonPath3, findNode as findNode3, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
1158
- import { mx as mx8 } from "@dxos/react-ui-theme";
1144
+ import { mx as mx6 } from "@dxos/react-ui-theme";
1159
1145
  import { getSchemaProperties as getSchemaProperties2 } from "@dxos/schema";
1160
- import { isNotFalsy } from "@dxos/util";
1161
-
1162
- // src/components/Form/ArrayField.tsx
1163
- import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
1164
- import { SchemaAST as SchemaAST3, pipe } from "effect";
1165
- import { capitalize } from "effect/String";
1166
- import React10, { Fragment, useCallback as useCallback7 } from "react";
1167
- import { findNode as findNode2, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
1168
- import { invariant as invariant2 } from "@dxos/invariant";
1169
- import { IconButton as IconButton3, useTranslation as useTranslation6 } from "@dxos/react-ui";
1170
- import { getSchemaProperties } from "@dxos/schema";
1146
+ import { isTruthy } from "@dxos/util";
1171
1147
 
1172
1148
  // src/util/field.ts
1173
- import { FormatEnum, GeoLocation as GeoLocation2, TypeEnum } from "@dxos/echo-schema";
1174
- var parseValue = ({ type, format, value }) => {
1175
- if (value === void 0 || value === null || value === "") {
1149
+ import { FormatEnum, GeoLocation as GeoLocation2, TypeEnum } from "@dxos/echo/internal";
1150
+ var parseValue = ({ type, format, value: value2 }) => {
1151
+ if (value2 === void 0 || value2 === null || value2 === "") {
1176
1152
  return void 0;
1177
1153
  }
1178
1154
  const parseScalar = (type2) => {
1179
1155
  switch (type2) {
1180
1156
  case TypeEnum.Boolean: {
1181
- if (typeof value === "string") {
1182
- const lowercaseValue = value.toLowerCase();
1157
+ if (typeof value2 === "string") {
1158
+ const lowercaseValue = value2.toLowerCase();
1183
1159
  if (lowercaseValue === "0" || lowercaseValue === "false") {
1184
1160
  return false;
1185
1161
  } else if (lowercaseValue === "1" || lowercaseValue === "true") {
1186
1162
  return true;
1187
1163
  }
1188
1164
  }
1189
- return Boolean(value);
1165
+ return Boolean(value2);
1190
1166
  }
1191
1167
  case TypeEnum.Number: {
1192
- const cleaned = typeof value === "string" ? value.replace(/[^0-9.-]+/g, "") : value;
1168
+ const cleaned = typeof value2 === "string" ? value2.replace(/[^0-9.-]+/g, "") : value2;
1193
1169
  const num = Number(cleaned);
1194
1170
  return Number.isNaN(num) ? null : num;
1195
1171
  }
1196
1172
  case TypeEnum.String:
1197
1173
  case TypeEnum.Ref:
1198
- return String(value);
1174
+ return String(value2);
1199
1175
  default: {
1200
- return value;
1176
+ return value2;
1201
1177
  }
1202
1178
  }
1203
1179
  };
@@ -1221,12 +1197,12 @@ var parseValue = ({ type, format, value }) => {
1221
1197
  case FormatEnum.Date:
1222
1198
  case FormatEnum.Time:
1223
1199
  case FormatEnum.Timestamp: {
1224
- const date = new Date(value);
1200
+ const date = new Date(value2);
1225
1201
  return isNaN(date.getTime()) ? null : date;
1226
1202
  }
1227
1203
  case FormatEnum.GeoPoint: {
1228
- if (typeof value === "string") {
1229
- const cleaned = value.replace(/[^0-9.,-]+/g, "");
1204
+ if (typeof value2 === "string") {
1205
+ const cleaned = value2.replace(/[^0-9.,-]+/g, "");
1230
1206
  const parts = cleaned.split(",");
1231
1207
  if (parts.length === 2) {
1232
1208
  const lat = parseFloat(parts[0]);
@@ -1245,33 +1221,12 @@ var parseValue = ({ type, format, value }) => {
1245
1221
  ];
1246
1222
  }
1247
1223
  default: {
1248
- return value;
1224
+ return value2;
1249
1225
  }
1250
1226
  }
1251
1227
  };
1252
1228
  var cellClassesForFieldType = ({ type, format }) => {
1253
- if (!format) {
1254
- switch (type) {
1255
- case TypeEnum.Number:
1256
- return [
1257
- "text-right",
1258
- "font-mono"
1259
- ];
1260
- case TypeEnum.Boolean:
1261
- return [
1262
- "text-right",
1263
- "font-mono"
1264
- ];
1265
- case TypeEnum.String:
1266
- return void 0;
1267
- case TypeEnum.Ref:
1268
- return void 0;
1269
- default: {
1270
- return void 0;
1271
- }
1272
- }
1273
- }
1274
- switch (format) {
1229
+ switch (format || type) {
1275
1230
  case FormatEnum.Markdown:
1276
1231
  return void 0;
1277
1232
  case FormatEnum.Time:
@@ -1292,6 +1247,16 @@ var cellClassesForFieldType = ({ type, format }) => {
1292
1247
  return [
1293
1248
  "font-mono"
1294
1249
  ];
1250
+ case TypeEnum.Number:
1251
+ case TypeEnum.Boolean:
1252
+ return [
1253
+ "text-right",
1254
+ "font-mono"
1255
+ ];
1256
+ case TypeEnum.String:
1257
+ return void 0;
1258
+ case TypeEnum.Ref:
1259
+ return void 0;
1295
1260
  default:
1296
1261
  return void 0;
1297
1262
  }
@@ -1303,19 +1268,19 @@ var pathNotUniqueError = (path) => ({
1303
1268
 
1304
1269
  // src/util/formatting.ts
1305
1270
  import { format as formatDate } from "date-fns/format";
1306
- import { FormatEnum as FormatEnum2, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
1307
- var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1271
+ import { FormatEnum as FormatEnum2, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo/internal";
1272
+ var formatForDisplay = ({ type, format, value: value2, locale = void 0 }) => {
1308
1273
  const formatScalar = (type2) => {
1309
1274
  switch (type2) {
1310
1275
  case TypeEnum2.Boolean:
1311
- return value.toLocaleString().toUpperCase();
1276
+ return value2.toLocaleString().toUpperCase();
1312
1277
  case TypeEnum2.Number:
1313
- return value.toLocaleString(locale);
1278
+ return value2.toLocaleString(locale);
1314
1279
  case TypeEnum2.String:
1315
1280
  case TypeEnum2.Ref:
1316
- return String(value);
1281
+ return String(value2);
1317
1282
  default: {
1318
- return String(value);
1283
+ return String(value2);
1319
1284
  }
1320
1285
  }
1321
1286
  };
@@ -1334,10 +1299,10 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1334
1299
  return formatScalar(TypeEnum2.String);
1335
1300
  }
1336
1301
  case FormatEnum2.Percent: {
1337
- return `${value * 100}%`;
1302
+ return `${value2 * 100}%`;
1338
1303
  }
1339
1304
  case FormatEnum2.Currency: {
1340
- return value.toLocaleString(locale, {
1305
+ return value2.toLocaleString(locale, {
1341
1306
  style: "currency",
1342
1307
  currency: "USD",
1343
1308
  minimumFractionDigits: 2,
@@ -1346,53 +1311,53 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1346
1311
  }
1347
1312
  case FormatEnum2.Date: {
1348
1313
  try {
1349
- return formatDate(new Date(value), "yyyy-MM-dd");
1314
+ return formatDate(new Date(value2), "yyyy-MM-dd");
1350
1315
  } catch (error) {
1351
1316
  return "Invalid Date";
1352
1317
  }
1353
1318
  }
1354
1319
  case FormatEnum2.Time: {
1355
1320
  try {
1356
- return formatDate(new Date(value), "HH:mm:ss");
1321
+ return formatDate(new Date(value2), "HH:mm:ss");
1357
1322
  } catch (error) {
1358
1323
  return "Invalid Time";
1359
1324
  }
1360
1325
  }
1361
1326
  case FormatEnum2.DateTime: {
1362
1327
  try {
1363
- return formatDate(new Date(value), "yyyy-MM-dd HH:mm:ss");
1328
+ return formatDate(new Date(value2), "yyyy-MM-dd HH:mm:ss");
1364
1329
  } catch (error) {
1365
1330
  return "Invalid DateTime";
1366
1331
  }
1367
1332
  }
1368
1333
  case FormatEnum2.GeoPoint: {
1369
- if (value === null || value === void 0) {
1334
+ if (value2 === null || value2 === void 0) {
1370
1335
  return "";
1371
1336
  }
1372
- if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1373
- const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
1337
+ if (Array.isArray(value2) && value2.length >= 2 && value2.every(Number.isFinite)) {
1338
+ const { latitude, longitude } = GeoLocation3.fromGeoPoint(value2);
1374
1339
  return `${latitude},${longitude}`;
1375
1340
  }
1376
- return String(value);
1341
+ return String(value2);
1377
1342
  }
1378
1343
  default: {
1379
- if (value === null || value === "undefined") {
1344
+ if (value2 === null || value2 === "undefined") {
1380
1345
  return "";
1381
1346
  }
1382
- return String(value);
1347
+ return String(value2);
1383
1348
  }
1384
1349
  }
1385
1350
  };
1386
- var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1351
+ var formatForEditing = ({ type, format, value: value2, locale = void 0 }) => {
1387
1352
  const formatScalar = (type2) => {
1388
1353
  switch (type2) {
1389
1354
  case TypeEnum2.Boolean:
1390
1355
  case TypeEnum2.Number:
1391
1356
  case TypeEnum2.String:
1392
1357
  case TypeEnum2.Ref:
1393
- return String(value);
1358
+ return String(value2);
1394
1359
  default:
1395
- return String(value);
1360
+ return String(value2);
1396
1361
  }
1397
1362
  };
1398
1363
  if (!format) {
@@ -1406,61 +1371,54 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1406
1371
  return formatScalar(type);
1407
1372
  }
1408
1373
  case FormatEnum2.Percent: {
1409
- return String(value * 100);
1374
+ return String(value2 * 100);
1410
1375
  }
1411
1376
  case FormatEnum2.Currency: {
1412
- return String(value);
1377
+ return String(value2);
1413
1378
  }
1414
1379
  case FormatEnum2.DateTime: {
1415
- const date = new Date(value);
1380
+ const date = new Date(value2);
1416
1381
  return date.toISOString();
1417
1382
  }
1418
1383
  case FormatEnum2.Date: {
1419
- const date = new Date(value);
1384
+ const date = new Date(value2);
1420
1385
  return date.toISOString().split("T")[0];
1421
1386
  }
1422
1387
  case FormatEnum2.Time: {
1423
- const date = new Date(value);
1388
+ const date = new Date(value2);
1424
1389
  return date.toISOString().split("T")[1].split(".")[0];
1425
1390
  }
1426
1391
  case FormatEnum2.GeoPoint: {
1427
- if (value === null || value === void 0) {
1392
+ if (value2 === null || value2 === void 0) {
1428
1393
  return "";
1429
1394
  }
1430
- if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1431
- const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
1395
+ if (Array.isArray(value2) && value2.length >= 2 && value2.every(Number.isFinite)) {
1396
+ const { latitude, longitude } = GeoLocation3.fromGeoPoint(value2);
1432
1397
  return `${latitude},${longitude}`;
1433
1398
  }
1434
- return String(value);
1399
+ return String(value2);
1435
1400
  }
1436
1401
  default: {
1437
- return String(value);
1402
+ return String(value2);
1438
1403
  }
1439
1404
  }
1440
1405
  };
1441
1406
 
1442
1407
  // src/util/refs.ts
1443
- import { FormatEnum as FormatEnum3, ReferenceAnnotationId } from "@dxos/echo-schema";
1408
+ import { FormatEnum as FormatEnum3, ReferenceAnnotationId } from "@dxos/echo/internal";
1444
1409
  import { findAnnotation } from "@dxos/effect";
1445
1410
 
1446
1411
  // src/util/schema.ts
1447
- import { SchemaAST as SchemaAST2 } from "effect";
1412
+ import * as SchemaAST2 from "effect/SchemaAST";
1448
1413
  import { findNode } from "@dxos/effect";
1449
1414
  var findArrayElementType = (ast) => {
1450
1415
  const tupleType = findNode(ast, SchemaAST2.isTupleType);
1451
- const elementType = tupleType?.rest[0]?.type;
1452
- return elementType;
1416
+ return tupleType?.rest[0]?.type;
1453
1417
  };
1454
1418
 
1455
1419
  // src/util/refs.ts
1456
1420
  var getRefProps = (property) => {
1457
1421
  const { ast, format, array } = property;
1458
- if (format === FormatEnum3.Ref) {
1459
- return {
1460
- ast,
1461
- isArray: false
1462
- };
1463
- }
1464
1422
  if (array) {
1465
1423
  const elementType = findArrayElementType(ast);
1466
1424
  if (elementType) {
@@ -1473,27 +1431,42 @@ var getRefProps = (property) => {
1473
1431
  }
1474
1432
  }
1475
1433
  }
1434
+ if (format === FormatEnum3.Ref) {
1435
+ return {
1436
+ ast,
1437
+ isArray: false
1438
+ };
1439
+ }
1476
1440
  return void 0;
1477
1441
  };
1478
1442
 
1479
1443
  // src/components/Form/ArrayField.tsx
1444
+ import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
1445
+ import * as Function from "effect/Function";
1446
+ import * as SchemaAST3 from "effect/SchemaAST";
1447
+ import * as String2 from "effect/String";
1448
+ import React9, { Fragment, useCallback as useCallback8 } from "react";
1449
+ import { SimpleType, findNode as findNode2, getDiscriminatedType, isDiscriminatedUnion } from "@dxos/effect";
1450
+ import { invariant as invariant2 } from "@dxos/invariant";
1451
+ import { IconButton as IconButton3, useTranslation as useTranslation6 } from "@dxos/react-ui";
1452
+ import { getSchemaProperties } from "@dxos/schema";
1480
1453
  var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
1481
1454
  var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
1482
- var _effect = _useSignals10();
1455
+ var _effect = _useSignals9();
1483
1456
  try {
1484
1457
  const { t } = useTranslation6(translationKey);
1485
1458
  const { ast, name, type, title } = property;
1486
1459
  const values = useFormValues(path ?? []) ?? [];
1487
1460
  invariant2(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
1488
1461
  F: __dxlog_file3,
1489
- L: 36,
1462
+ L: 37,
1490
1463
  S: void 0,
1491
1464
  A: [
1492
1465
  "Array.isArray(values)",
1493
1466
  "`Values at path ${path?.join('.')} must be an array.`"
1494
1467
  ]
1495
1468
  });
1496
- const label = title ?? pipe(name, capitalize);
1469
+ const label = title ?? Function.pipe(name, String2.capitalize);
1497
1470
  const elementType = findArrayElementType(ast);
1498
1471
  const getDefaultObjectValue = (typeNode) => {
1499
1472
  const baseNode = findNode2(typeNode, isDiscriminatedUnion);
@@ -1507,7 +1480,7 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
1507
1480
  ]));
1508
1481
  };
1509
1482
  const getDefaultValue = () => type === "object" && elementType ? getDefaultObjectValue(elementType) : SimpleType.getDefaultValue(type);
1510
- const handleAdd = useCallback7(() => {
1483
+ const handleAdd = useCallback8(() => {
1511
1484
  inputProps.onValueChange(type, [
1512
1485
  ...values,
1513
1486
  getDefaultValue()
@@ -1518,7 +1491,7 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
1518
1491
  inputProps,
1519
1492
  values
1520
1493
  ]);
1521
- const handleRemove = useCallback7((index) => {
1494
+ const handleRemove = useCallback8((index) => {
1522
1495
  const newValues = values.filter((_, i) => i !== index);
1523
1496
  inputProps.onValueChange(type, newValues);
1524
1497
  }, [
@@ -1529,14 +1502,14 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
1529
1502
  if (!elementType) {
1530
1503
  return null;
1531
1504
  }
1532
- return readonly && values.length < 1 ? null : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(InputHeader, {
1505
+ return readonly && values.length < 1 ? null : /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(InputHeader, {
1533
1506
  readonly: true,
1534
1507
  label
1535
- }), /* @__PURE__ */ React10.createElement("div", {
1508
+ }), /* @__PURE__ */ React9.createElement("div", {
1536
1509
  role: "none",
1537
1510
  className: readonly ? "flex flex-wrap gap-1 mlb-1" : values.length > 0 ? "grid gap-1 grid-cols-[1fr_min-content] mlb-1" : "hidden"
1538
1511
  }, values.map((_value, index) => {
1539
- const field = /* @__PURE__ */ React10.createElement(FormField, {
1512
+ const field = /* @__PURE__ */ React9.createElement(FormField, {
1540
1513
  property: {
1541
1514
  ...property,
1542
1515
  array: false,
@@ -1551,19 +1524,19 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
1551
1524
  Custom,
1552
1525
  lookupComponent
1553
1526
  });
1554
- return readonly ? field : /* @__PURE__ */ React10.createElement(Fragment, {
1527
+ return readonly ? field : /* @__PURE__ */ React9.createElement(Fragment, {
1555
1528
  key: index
1556
- }, /* @__PURE__ */ React10.createElement("div", {
1529
+ }, /* @__PURE__ */ React9.createElement("div", {
1557
1530
  role: "none"
1558
- }, field), /* @__PURE__ */ React10.createElement(IconButton3, {
1531
+ }, field), /* @__PURE__ */ React9.createElement(IconButton3, {
1559
1532
  icon: "ph--trash--regular",
1560
1533
  iconOnly: true,
1561
1534
  label: t("button remove"),
1562
1535
  onClick: () => handleRemove(index),
1563
1536
  classNames: "self-center"
1564
1537
  }));
1565
- })), !readonly && /* @__PURE__ */ React10.createElement(IconButton3, {
1566
- classNames: "is-full mlb-1 flex",
1538
+ })), !readonly && /* @__PURE__ */ React9.createElement(IconButton3, {
1539
+ classNames: "is-full mlb-cardSpacingBlock flex",
1567
1540
  icon: "ph--plus--regular",
1568
1541
  label: t("add field"),
1569
1542
  onClick: handleAdd
@@ -1573,25 +1546,144 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
1573
1546
  }
1574
1547
  };
1575
1548
 
1549
+ // src/components/Form/factory.tsx
1550
+ import { FormatEnum as FormatEnum4 } from "@dxos/echo/internal";
1551
+ var getInputComponent = (type, format) => {
1552
+ switch (format) {
1553
+ case FormatEnum4.GeoPoint:
1554
+ return GeoPointInput;
1555
+ case FormatEnum4.Markdown:
1556
+ return MarkdownInput;
1557
+ }
1558
+ switch (type) {
1559
+ case "string":
1560
+ return TextInput;
1561
+ case "number":
1562
+ return NumberInput;
1563
+ case "boolean":
1564
+ return BooleanInput;
1565
+ }
1566
+ };
1567
+
1576
1568
  // src/components/Form/RefField.tsx
1577
1569
  import { useSignals as _useSignals11 } from "@preact-signals/safe-react/tracking";
1578
- import React11, { useCallback as useCallback8, useMemo as useMemo4 } from "react";
1579
- import { Expando, getTypeAnnotation, Ref, ReferenceAnnotationId as ReferenceAnnotationId2 } from "@dxos/echo-schema";
1570
+ import "@dxos/lit-ui/dx-tag-picker.pcss";
1571
+ import React11, { useCallback as useCallback10, useMemo as useMemo5 } from "react";
1572
+ import { Expando, Ref, ReferenceAnnotationId as ReferenceAnnotationId2, getTypeAnnotation } from "@dxos/echo/internal";
1580
1573
  import { findAnnotation as findAnnotation2 } from "@dxos/effect";
1581
1574
  import { DXN } from "@dxos/keys";
1582
- import { DxRefTag } from "@dxos/lit-ui/react";
1583
- import { Input as Input8, useTranslation as useTranslation7 } from "@dxos/react-ui";
1584
- import { TagPicker } from "@dxos/react-ui-tag-picker";
1585
- import { descriptionText, mx as mx7 } from "@dxos/react-ui-theme";
1575
+ import { DxAnchor, DxTagPickerItem } from "@dxos/lit-ui/react";
1576
+ import { Button as Button2, Icon as Icon3, Input as Input7, useTranslation as useTranslation8 } from "@dxos/react-ui";
1577
+ import { descriptionText, mx as mx5 } from "@dxos/react-ui-theme";
1586
1578
  import { isNonNullable as isNonNullable2 } from "@dxos/util";
1587
- var RefField = ({ type, label, disabled, placeholder, inputOnly, array, ast, getValue: getValue3, onBlur, onQueryRefOptions, onValueChange, ...restInputProps }) => {
1588
- var _effect = _useSignals11();
1579
+
1580
+ // src/components/ObjectPicker/ObjectPicker.tsx
1581
+ import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
1582
+ import React10, { forwardRef, useCallback as useCallback9, useMemo as useMemo4, useState as useState5 } from "react";
1583
+ import { Icon as Icon2, Popover, useTranslation as useTranslation7 } from "@dxos/react-ui";
1584
+ import { Combobox } from "@dxos/react-ui-searchlist";
1585
+ var ObjectPickerContent = /* @__PURE__ */ forwardRef(({ options, selectedIds, createSchema, createOptionLabel, createOptionIcon, createInitialValuePath, onSelect, onCreate, ...props }, ref) => {
1586
+ var _effect = _useSignals10();
1589
1587
  try {
1590
1588
  const { t } = useTranslation7(translationKey);
1591
- const refTypeInfo = useMemo4(() => ast ? findAnnotation2(ast, ReferenceAnnotationId2) : void 0, [
1589
+ const [searchString, setSearchString] = useState5("");
1590
+ const [showForm, setShowForm] = useState5(false);
1591
+ const handleFormSave = useCallback9((values) => {
1592
+ onCreate?.(values);
1593
+ setShowForm(false);
1594
+ setSearchString("");
1595
+ }, [
1596
+ onCreate
1597
+ ]);
1598
+ const handleFormCancel = useCallback9(() => {
1599
+ setShowForm(false);
1600
+ setSearchString("");
1601
+ }, []);
1602
+ const handleClick = useCallback9((event) => {
1603
+ if (createSchema && event.target.closest('[data-value="__create__"]')) {
1604
+ event.stopPropagation();
1605
+ event.preventDefault();
1606
+ setShowForm(true);
1607
+ }
1608
+ }, [
1609
+ createSchema
1610
+ ]);
1611
+ const handleKeyDown = useCallback9((event) => {
1612
+ if (event.key === "Enter" && createSchema && event.currentTarget.querySelector('[role="option"][aria-selected="true"][data-value="__create__"]')) {
1613
+ event.stopPropagation();
1614
+ event.preventDefault();
1615
+ setShowForm(true);
1616
+ }
1617
+ }, [
1618
+ createSchema
1619
+ ]);
1620
+ const labelById = useMemo4(() => options.reduce((acc, option) => {
1621
+ acc[option.id.toLowerCase()] = option.label.toLowerCase();
1622
+ return acc;
1623
+ }, {}), [
1624
+ options
1625
+ ]);
1626
+ return /* @__PURE__ */ React10.createElement(Combobox.Content, {
1627
+ ...props,
1628
+ ref,
1629
+ filter: (value2, search) => value2 === "__create__" || labelById[value2]?.includes(search.toLowerCase()) ? 1 : 0,
1630
+ onClickCapture: handleClick,
1631
+ onKeyDownCapture: handleKeyDown
1632
+ }, showForm && createSchema ? /* @__PURE__ */ React10.createElement(Popover.Viewport, null, /* @__PURE__ */ React10.createElement(Form, {
1633
+ schema: createSchema,
1634
+ values: createInitialValuePath ? {
1635
+ [createInitialValuePath]: searchString
1636
+ } : {},
1637
+ onSave: handleFormSave,
1638
+ onCancel: handleFormCancel,
1639
+ testId: "create-referenced-object-form"
1640
+ })) : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Combobox.Input, {
1641
+ placeholder: t("ref field combobox input placeholder"),
1642
+ value: searchString,
1643
+ onValueChange: setSearchString,
1644
+ autoFocus: true
1645
+ }), /* @__PURE__ */ React10.createElement(Combobox.List, null, options.map((option) => /* @__PURE__ */ React10.createElement(Combobox.Item, {
1646
+ key: option.id,
1647
+ value: option.id,
1648
+ onSelect: () => onSelect(option.id),
1649
+ classNames: "flex items-center gap-2"
1650
+ }, /* @__PURE__ */ React10.createElement("span", {
1651
+ className: "grow"
1652
+ }, option.label), selectedIds?.includes(option.id) && /* @__PURE__ */ React10.createElement(Icon2, {
1653
+ icon: "ph--check--regular"
1654
+ }))), searchString.length > 0 && createOptionLabel && createOptionIcon && createSchema && onCreate && /* @__PURE__ */ React10.createElement(Combobox.Item, {
1655
+ value: "__create__",
1656
+ classNames: "flex items-center gap-2"
1657
+ }, /* @__PURE__ */ React10.createElement(Icon2, {
1658
+ icon: createOptionIcon
1659
+ }), t(createOptionLabel[0], {
1660
+ ns: createOptionLabel[1].ns,
1661
+ text: searchString
1662
+ })))), /* @__PURE__ */ React10.createElement(Combobox.Arrow, null));
1663
+ } finally {
1664
+ _effect.f();
1665
+ }
1666
+ });
1667
+ ObjectPickerContent.displayName = "ObjectPickerContent";
1668
+ var ObjectPicker = {
1669
+ Root: Combobox.Root,
1670
+ Trigger: Combobox.Trigger,
1671
+ VirtualTrigger: Combobox.VirtualTrigger,
1672
+ Content: ObjectPickerContent
1673
+ };
1674
+
1675
+ // src/components/Form/RefField.tsx
1676
+ var isRefSnapShot = (val) => {
1677
+ return typeof val === "object" && typeof val?.["/"] === "string";
1678
+ };
1679
+ var RefField = ({ type, label, readonly, placeholder, inputOnly, array, ast, getValue: getValue3, createOptionLabel, createOptionIcon, onBlur, onCreate, createSchema, createInitialValuePath, onQueryRefOptions, onValueChange, ...restInputProps }) => {
1680
+ var _effect = _useSignals11();
1681
+ try {
1682
+ const { t } = useTranslation8(translationKey);
1683
+ const refTypeInfo = useMemo5(() => ast ? findAnnotation2(ast, ReferenceAnnotationId2) : void 0, [
1592
1684
  ast
1593
1685
  ]);
1594
- const { options: availableOptions, loading: _loading } = useQueryRefOptions({
1686
+ const { options: availableOptions, update: updateOptions, loading: _loading } = useQueryRefOptions({
1595
1687
  refTypeInfo,
1596
1688
  onQueryRefOptions
1597
1689
  });
@@ -1600,7 +1692,7 @@ var RefField = ({ type, label, disabled, placeholder, inputOnly, array, ast, get
1600
1692
  type,
1601
1693
  label,
1602
1694
  placeholder,
1603
- disabled,
1695
+ readonly,
1604
1696
  inputOnly,
1605
1697
  getValue: getValue3,
1606
1698
  onBlur,
@@ -1608,11 +1700,12 @@ var RefField = ({ type, label, disabled, placeholder, inputOnly, array, ast, get
1608
1700
  ...restInputProps
1609
1701
  });
1610
1702
  }
1611
- const handleGetValue = useCallback8(() => {
1703
+ const handleGetValue = useCallback10(() => {
1612
1704
  const formValue = getValue3();
1613
1705
  const unknownToRefOption = (val) => {
1614
- if (Ref.isRef(val)) {
1615
- const dxnString = val.dxn.toString();
1706
+ const isRef = Ref.isRef(val);
1707
+ if (isRef || isRefSnapShot(val)) {
1708
+ const dxnString = isRef ? val.dxn.toString() : val["/"];
1616
1709
  const matchingOption = availableOptions.find((option2) => option2.id === dxnString);
1617
1710
  if (matchingOption) {
1618
1711
  return matchingOption;
@@ -1635,14 +1728,7 @@ var RefField = ({ type, label, disabled, placeholder, inputOnly, array, ast, get
1635
1728
  availableOptions,
1636
1729
  array
1637
1730
  ]);
1638
- const handleSearch = useCallback8((text, ids) => availableOptions.filter((option) => !ids.includes(option.id)).filter((option) => option.label.toLowerCase().includes(text.toLowerCase())).map((option) => ({
1639
- id: option.id,
1640
- label: option.label,
1641
- hue: option.hue
1642
- })), [
1643
- availableOptions
1644
- ]);
1645
- const handleUpdate = useCallback8((ids) => {
1731
+ const handleUpdate = useCallback10((ids) => {
1646
1732
  if (ids.length === 0) {
1647
1733
  onValueChange("object", void 0);
1648
1734
  return;
@@ -1665,44 +1751,98 @@ var RefField = ({ type, label, disabled, placeholder, inputOnly, array, ast, get
1665
1751
  array,
1666
1752
  onValueChange
1667
1753
  ]);
1668
- const tagPickerMode = useMemo4(() => array ? "multi-select" : "single-select", [
1669
- array
1754
+ const handleCreate = useCallback10((values) => {
1755
+ onCreate?.(values);
1756
+ updateOptions();
1757
+ }, [
1758
+ onCreate,
1759
+ updateOptions
1670
1760
  ]);
1671
1761
  if (!refTypeInfo) {
1672
1762
  return null;
1673
1763
  }
1674
1764
  const { status, error } = restInputProps.getStatus();
1675
1765
  const items = handleGetValue();
1676
- return disabled && items.length < 1 ? null : /* @__PURE__ */ React11.createElement(Input8.Root, {
1766
+ const selectedIds = useMemo5(() => items.map((i) => i.id), [
1767
+ items
1768
+ ]);
1769
+ const toggleSelect = useCallback10((id) => {
1770
+ if (array) {
1771
+ const nextIds = selectedIds.includes(id) ? selectedIds.filter((x) => x !== id) : [
1772
+ ...selectedIds,
1773
+ id
1774
+ ];
1775
+ handleUpdate(nextIds);
1776
+ } else {
1777
+ if (selectedIds[0] === id) {
1778
+ handleUpdate([]);
1779
+ } else {
1780
+ handleUpdate([
1781
+ id
1782
+ ]);
1783
+ }
1784
+ }
1785
+ }, [
1786
+ array,
1787
+ selectedIds,
1788
+ handleUpdate
1789
+ ]);
1790
+ return readonly && items.length < 1 ? null : /* @__PURE__ */ React11.createElement(Input7.Root, {
1677
1791
  validationValence: status
1678
1792
  }, !inputOnly && /* @__PURE__ */ React11.createElement(InputHeader, {
1679
1793
  error,
1680
1794
  label
1681
1795
  }), /* @__PURE__ */ React11.createElement("div", {
1682
1796
  "data-no-submit": true
1683
- }, disabled ? items.length < 1 ? /* @__PURE__ */ React11.createElement("p", {
1684
- className: mx7(descriptionText, "mbe-2")
1685
- }, t("empty readonly ref field label")) : items.map((item) => /* @__PURE__ */ React11.createElement(DxRefTag, {
1797
+ }, readonly ? items.length < 1 ? /* @__PURE__ */ React11.createElement("p", {
1798
+ className: mx5(descriptionText, "mbe-2")
1799
+ }, t("empty readonly ref field label")) : items.map((item) => /* @__PURE__ */ React11.createElement(DxAnchor, {
1686
1800
  key: item.id,
1687
1801
  refid: item.id,
1688
- rootclassname: "mie-1",
1689
- style: {
1690
- marginInlineEnd: ".25rem"
1802
+ rootclassname: "mie-1"
1803
+ }, item.label)) : /* @__PURE__ */ React11.createElement(ObjectPicker.Root, null, /* @__PURE__ */ React11.createElement(ObjectPicker.Trigger, {
1804
+ asChild: true
1805
+ }, /* @__PURE__ */ React11.createElement(Button2, {
1806
+ variant: "ghost",
1807
+ classNames: "is-full text-start gap-2"
1808
+ }, /* @__PURE__ */ React11.createElement("div", {
1809
+ role: "none",
1810
+ className: "grow"
1811
+ }, items?.length ? items?.map((item) => /* @__PURE__ */ React11.createElement(DxTagPickerItem, {
1812
+ key: item.id,
1813
+ itemId: item.id,
1814
+ label: item.label,
1815
+ ...item.hue ? {
1816
+ hue: item.hue
1817
+ } : {},
1818
+ removeLabel: t("remove item label"),
1819
+ onItemClick: (event) => {
1820
+ if (event.action === "remove") {
1821
+ toggleSelect(item.id);
1822
+ }
1691
1823
  }
1692
- }, item.label)) : /* @__PURE__ */ React11.createElement(TagPicker, {
1693
- readonly: disabled,
1694
- items,
1695
- mode: tagPickerMode,
1696
- onBlur: (event) => onBlur(event),
1697
- onUpdate: handleUpdate,
1698
- onSearch: handleSearch,
1699
- classNames: "bg-inputSurface p-1.5 rounded-sm"
1700
- })), inputOnly && /* @__PURE__ */ React11.createElement(Input8.DescriptionAndValidation, null, error));
1824
+ })) : /* @__PURE__ */ React11.createElement("span", {
1825
+ className: "text-description"
1826
+ }, placeholder ?? t("ref field placeholder", {
1827
+ count: array ? 99 : 1
1828
+ }))), /* @__PURE__ */ React11.createElement(Icon3, {
1829
+ size: 3,
1830
+ icon: "ph--caret-down--bold"
1831
+ }))), /* @__PURE__ */ React11.createElement(ObjectPicker.Content, {
1832
+ options: availableOptions,
1833
+ selectedIds,
1834
+ onSelect: toggleSelect,
1835
+ createSchema,
1836
+ createOptionLabel,
1837
+ createOptionIcon,
1838
+ createInitialValuePath,
1839
+ onCreate: handleCreate
1840
+ }))), inputOnly && /* @__PURE__ */ React11.createElement(Input7.DescriptionAndValidation, null, error));
1701
1841
  } finally {
1702
1842
  _effect.f();
1703
1843
  }
1704
1844
  };
1705
- var RefFieldFallback = ({ type, label, disabled, placeholder, inputOnly, getValue: getValue3, onValueChange, ...restInputProps }) => {
1845
+ var RefFieldFallback = ({ type, label, readonly, placeholder, inputOnly, getValue: getValue3, onValueChange, ...restInputProps }) => {
1706
1846
  var _effect = _useSignals11();
1707
1847
  try {
1708
1848
  const handleOnValueChange = (_type, dxnString) => {
@@ -1728,7 +1868,7 @@ var RefFieldFallback = ({ type, label, disabled, placeholder, inputOnly, getValu
1728
1868
  return /* @__PURE__ */ React11.createElement(TextInput, {
1729
1869
  type,
1730
1870
  label,
1731
- disabled,
1871
+ readonly,
1732
1872
  placeholder,
1733
1873
  inputOnly,
1734
1874
  getValue: handleGetValue,
@@ -1740,36 +1880,17 @@ var RefFieldFallback = ({ type, label, disabled, placeholder, inputOnly, getValu
1740
1880
  }
1741
1881
  };
1742
1882
 
1743
- // src/components/Form/factory.tsx
1744
- import { FormatEnum as FormatEnum4 } from "@dxos/echo-schema";
1745
- var getInputComponent = (type, format) => {
1746
- switch (format) {
1747
- case FormatEnum4.GeoPoint:
1748
- return GeoPointInput;
1749
- case FormatEnum4.Markdown:
1750
- return MarkdownInput;
1751
- }
1752
- switch (type) {
1753
- case "string":
1754
- return TextInput;
1755
- case "number":
1756
- return NumberInput;
1757
- case "boolean":
1758
- return BooleanInput;
1759
- }
1760
- };
1761
-
1762
1883
  // src/components/Form/FormContent.tsx
1763
- var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupComponent, Custom }) => {
1884
+ var FormField = ({ property, path, readonly, inline, projection, onQueryRefOptions, createOptionLabel, createOptionIcon, onCreate, createSchema, createInitialValuePath, lookupComponent, Custom }) => {
1764
1885
  var _effect = _useSignals12();
1765
1886
  try {
1766
1887
  const { ast, name, type, format, title, description, options, examples, array } = property;
1767
1888
  const inputProps = useInputProps(path);
1768
- const label = useMemo5(() => title ?? pipe2(name, capitalize2), [
1889
+ const label = useMemo6(() => title ?? Function2.pipe(name, StringEffect.capitalize), [
1769
1890
  title,
1770
1891
  name
1771
1892
  ]);
1772
- const placeholder = useMemo5(() => examples?.length ? `Example: "${examples[0]}"` : description, [
1893
+ const placeholder = useMemo6(() => examples?.length ? `Example: "${examples[0]}"` : description, [
1773
1894
  examples,
1774
1895
  description
1775
1896
  ]);
@@ -1780,7 +1901,7 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
1780
1901
  type,
1781
1902
  format,
1782
1903
  label,
1783
- disabled: readonly,
1904
+ readonly,
1784
1905
  placeholder,
1785
1906
  ...inputProps
1786
1907
  }
@@ -1797,7 +1918,7 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
1797
1918
  label,
1798
1919
  inputOnly: inline,
1799
1920
  placeholder,
1800
- disabled: readonly,
1921
+ readonly,
1801
1922
  ...inputProps
1802
1923
  });
1803
1924
  }
@@ -1810,9 +1931,14 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
1810
1931
  format,
1811
1932
  label,
1812
1933
  placeholder,
1813
- disabled: readonly,
1934
+ readonly,
1814
1935
  inputOnly: inline,
1815
1936
  onQueryRefOptions,
1937
+ createOptionLabel,
1938
+ createOptionIcon,
1939
+ onCreate,
1940
+ createSchema,
1941
+ createInitialValuePath,
1816
1942
  ...inputProps
1817
1943
  });
1818
1944
  }
@@ -1833,7 +1959,7 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
1833
1959
  label,
1834
1960
  inputOnly: inline,
1835
1961
  placeholder,
1836
- disabled: readonly,
1962
+ readonly,
1837
1963
  ...inputProps
1838
1964
  });
1839
1965
  }
@@ -1841,7 +1967,7 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
1841
1967
  return /* @__PURE__ */ React12.createElement(SelectInput, {
1842
1968
  type,
1843
1969
  format,
1844
- disabled: readonly,
1970
+ readonly,
1845
1971
  inputOnly: inline,
1846
1972
  label,
1847
1973
  options: options.map((option) => ({
@@ -1857,12 +1983,16 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
1857
1983
  const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode3(ast, SchemaAST4.isTypeLiteral);
1858
1984
  if (typeLiteral) {
1859
1985
  return /* @__PURE__ */ React12.createElement(React12.Fragment, null, !inline && /* @__PURE__ */ React12.createElement("h3", {
1860
- className: mx8("text-lg mlb-inputSpacingBlock first:mbs-0")
1986
+ className: mx6("text-lg mlb-inputSpacingBlock first:mbs-0")
1861
1987
  }, label), /* @__PURE__ */ React12.createElement(FormFields, {
1862
1988
  schema: Schema.make(typeLiteral),
1863
1989
  path,
1864
1990
  readonly,
1991
+ projection,
1865
1992
  onQueryRefOptions,
1993
+ createOptionLabel,
1994
+ createOptionIcon,
1995
+ onCreate,
1866
1996
  Custom,
1867
1997
  lookupComponent
1868
1998
  }));
@@ -1873,62 +2003,122 @@ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupCo
1873
2003
  _effect.f();
1874
2004
  }
1875
2005
  };
1876
- var FormFields = /* @__PURE__ */ forwardRef(({ classNames, testId, schema, path, filter, sort, readonly, lookupComponent, Custom, onQueryRefOptions }, forwardRef2) => {
2006
+ var FormFields = /* @__PURE__ */ forwardRef2(({ classNames, schema, path, filter, sort, projection, readonly, lookupComponent, Custom, onQueryRefOptions, ...props }, forwardRef4) => {
1877
2007
  var _effect = _useSignals12();
1878
2008
  try {
1879
2009
  const values = useFormValues(path);
1880
- const properties = useMemo5(() => {
1881
- const props = getSchemaProperties2(schema.ast, values);
1882
- const filtered = filter ? filter(props) : props;
2010
+ const properties = useMemo6(() => {
2011
+ const props2 = getSchemaProperties2(schema.ast, values);
2012
+ if (projection) {
2013
+ const fieldProjections = projection.getFieldProjections();
2014
+ const hiddenProperties = new Set(projection.getHiddenProperties());
2015
+ const visibleProps = props2.filter((prop) => !hiddenProperties.has(prop.name));
2016
+ const orderedProps = [];
2017
+ for (const fieldProjection of fieldProjections) {
2018
+ const fieldPath = String(fieldProjection.field.path);
2019
+ const prop = visibleProps.find((p) => p.name === fieldPath);
2020
+ if (prop) {
2021
+ orderedProps.push(prop);
2022
+ }
2023
+ }
2024
+ const projectionPaths = new Set(fieldProjections.map((fp) => String(fp.field.path)));
2025
+ const remainingProps = visibleProps.filter((prop) => !projectionPaths.has(prop.name));
2026
+ orderedProps.push(...remainingProps);
2027
+ return orderedProps;
2028
+ }
2029
+ const filtered = filter ? filter(props2) : props2;
1883
2030
  return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
1884
2031
  }, [
1885
2032
  schema,
1886
2033
  values,
1887
2034
  filter,
1888
- sort
2035
+ sort,
2036
+ projection?.fields
1889
2037
  ]);
1890
2038
  return /* @__PURE__ */ React12.createElement("div", {
1891
2039
  role: "form",
1892
- className: mx8("is-full", classNames),
1893
- ref: forwardRef2
2040
+ className: mx6("is-full", classNames),
2041
+ ref: forwardRef4
1894
2042
  }, properties.map((property) => {
1895
- return /* @__PURE__ */ React12.createElement(FormField, {
2043
+ return /* @__PURE__ */ React12.createElement(ErrorBoundary, {
1896
2044
  key: property.name,
2045
+ path: [
2046
+ ...path ?? [],
2047
+ property.name
2048
+ ]
2049
+ }, /* @__PURE__ */ React12.createElement(FormField, {
1897
2050
  property,
1898
2051
  path: [
1899
2052
  ...path ?? [],
1900
2053
  property.name
1901
2054
  ],
1902
2055
  readonly,
2056
+ projection,
1903
2057
  onQueryRefOptions,
1904
2058
  lookupComponent,
1905
- Custom
1906
- });
1907
- }).filter(isNotFalsy));
2059
+ Custom,
2060
+ ...props
2061
+ }));
2062
+ }).filter(isTruthy));
1908
2063
  } finally {
1909
2064
  _effect.f();
1910
2065
  }
1911
2066
  });
2067
+ var ErrorBoundary = class extends Component {
2068
+ static getDerivedStateFromError(error) {
2069
+ return {
2070
+ error
2071
+ };
2072
+ }
2073
+ state = {
2074
+ error: void 0
2075
+ };
2076
+ componentDidUpdate(prevProps) {
2077
+ if (prevProps.path !== this.props.path) {
2078
+ this.resetError();
2079
+ }
2080
+ }
2081
+ render() {
2082
+ if (this.state.error) {
2083
+ return /* @__PURE__ */ React12.createElement("div", {
2084
+ className: "flex gap-2 border border-roseFill font-mono text-sm"
2085
+ }, /* @__PURE__ */ React12.createElement("span", {
2086
+ className: "bg-roseFill text-surfaceText pli-1 font-thin"
2087
+ }, "ERROR"), String(this.props.path?.join(".")));
2088
+ }
2089
+ return this.props.children;
2090
+ }
2091
+ resetError() {
2092
+ this.setState({
2093
+ error: void 0
2094
+ });
2095
+ }
2096
+ };
1912
2097
 
1913
2098
  // src/components/Form/Form.tsx
1914
- var Form = ({ classNames, testId, values: initialValues, autoFocus, readonly, autoSave, outerSpacing = true, onCancel, schema, onValuesChanged, onValidate, onSave, ...props }) => {
2099
+ var Form = ({ classNames, id, testId, values: initialValues, autoFocus, readonly, autoSave, outerSpacing = true, schema, onCancel, onValuesChanged, onValidate, onSave, ...props }) => {
1915
2100
  var _effect = _useSignals13();
1916
2101
  try {
1917
2102
  const formRef = useRef3(null);
1918
- const handleValid = useMemo6(() => autoSave ? onSave : void 0, [
1919
- autoSave,
1920
- onSave
1921
- ]);
2103
+ const { findFirstFocusable } = useFocusFinders();
1922
2104
  useEffect7(() => {
1923
2105
  if (autoFocus && formRef.current) {
1924
- const input = formRef.current.querySelector("input");
1925
- if (input) {
1926
- input.focus();
2106
+ const firstFocusable = findFirstFocusable(formRef.current);
2107
+ if (firstFocusable) {
2108
+ firstFocusable.focus();
1927
2109
  }
1928
2110
  }
1929
2111
  }, [
1930
2112
  autoFocus
1931
2113
  ]);
2114
+ const handleValid = useCallback11(async (values, meta) => {
2115
+ if (autoSave) {
2116
+ await onSave?.(values, meta);
2117
+ }
2118
+ }, [
2119
+ autoSave,
2120
+ onSave
2121
+ ]);
1932
2122
  return /* @__PURE__ */ React13.createElement(FormProvider, {
1933
2123
  formRef,
1934
2124
  schema,
@@ -1941,6 +2131,9 @@ var Form = ({ classNames, testId, values: initialValues, autoFocus, readonly, au
1941
2131
  }, /* @__PURE__ */ React13.createElement("div", {
1942
2132
  role: "none",
1943
2133
  className: "contents",
2134
+ ...id && {
2135
+ "data-object-id": id
2136
+ },
1944
2137
  "data-testid": testId
1945
2138
  }, /* @__PURE__ */ React13.createElement(FormFields, {
1946
2139
  ...props,
@@ -1952,7 +2145,7 @@ var Form = ({ classNames, testId, values: initialValues, autoFocus, readonly, au
1952
2145
  ],
1953
2146
  readonly,
1954
2147
  schema
1955
- }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React13.createElement(FormActions, {
2148
+ }), (onCancel || onSave) && !autoSave && !readonly && /* @__PURE__ */ React13.createElement(FormActions, {
1956
2149
  readonly,
1957
2150
  onCancel,
1958
2151
  outerSpacing
@@ -1964,45 +2157,40 @@ var Form = ({ classNames, testId, values: initialValues, autoFocus, readonly, au
1964
2157
 
1965
2158
  // src/components/FieldEditor/FieldEditor.tsx
1966
2159
  var __dxlog_file4 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
1967
- var FieldEditor = ({ view, projection, field, registry, onSave, onCancel, outerSpacing }) => {
2160
+ var FieldEditor = ({ readonly, projection, field, registry, onSave, onCancel, outerSpacing }) => {
1968
2161
  var _effect = _useSignals14();
1969
2162
  try {
1970
- const { t } = useTranslation8(translationKey);
1971
- const [props, setProps] = useState5(projection.getFieldProjection(field.id).props);
2163
+ const { t } = useTranslation9(translationKey);
2164
+ const [props, setProps] = useState6(projection.getFieldProjection(field.id).props);
1972
2165
  useEffect8(() => setProps(projection.getFieldProjection(field.id).props), [
1973
2166
  field,
1974
2167
  projection
1975
2168
  ]);
1976
- const [schemas, setSchemas] = useState5([]);
1977
- useEffect8(() => {
2169
+ const [schemas, setSchemas] = useState6([]);
2170
+ useAsyncEffect(async () => {
1978
2171
  if (!registry) {
1979
2172
  return;
1980
2173
  }
1981
2174
  const subscription = registry.query().subscribe((query) => setSchemas(query.results), {
1982
2175
  fire: true
1983
2176
  });
1984
- const t2 = setTimeout(async () => {
1985
- const schemas2 = await registry.query().run();
1986
- setSchemas(schemas2);
1987
- });
1988
- return () => {
1989
- clearTimeout(t2);
1990
- subscription?.();
1991
- };
2177
+ const schemas2 = await registry.query().run();
2178
+ setSchemas(schemas2);
2179
+ return () => subscription?.();
1992
2180
  }, [
1993
2181
  registry
1994
2182
  ]);
1995
- const [referenceSchema, setReferenceSchema] = useState5();
2183
+ const [referenceSchema, setReferenceSchema] = useState6();
1996
2184
  useEffect8(() => {
1997
2185
  setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
1998
2186
  }, [
1999
2187
  schemas,
2000
2188
  props?.referenceSchema
2001
2189
  ]);
2002
- const [{ fieldSchema }, setFieldSchema] = useState5({
2190
+ const [{ fieldSchema }, setFieldSchema] = useState6({
2003
2191
  fieldSchema: getFormatSchema(props?.format)
2004
2192
  });
2005
- const handleValuesChanged = useCallback9((_props) => {
2193
+ const handleValuesChanged = useCallback12((_props) => {
2006
2194
  setFieldSchema((prev) => {
2007
2195
  const fieldSchema2 = getFormatSchema(_props.format);
2008
2196
  if (prev.fieldSchema === fieldSchema2) {
@@ -2023,10 +2211,12 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel, outerS
2023
2211
  });
2024
2212
  setProps((props2) => {
2025
2213
  const type = formatToType[_props.format];
2214
+ const additionalProps = formatToAdditionalPropertyAttributes[_props.format];
2026
2215
  if (props2.type !== type) {
2027
2216
  return {
2028
2217
  ...props2,
2029
2218
  ..._props,
2219
+ ...additionalProps,
2030
2220
  type
2031
2221
  };
2032
2222
  }
@@ -2037,8 +2227,8 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel, outerS
2037
2227
  props.format,
2038
2228
  props.referenceSchema
2039
2229
  ]);
2040
- const handleValidate = useCallback9(({ property }) => {
2041
- if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
2230
+ const handleValidate = useCallback12(({ property }) => {
2231
+ if (property && projection.fields.find((f) => f.path === property && f.path !== field.path)) {
2042
2232
  return [
2043
2233
  {
2044
2234
  path: "property",
@@ -2047,10 +2237,10 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel, outerS
2047
2237
  ];
2048
2238
  }
2049
2239
  }, [
2050
- view.fields,
2240
+ projection.fields,
2051
2241
  field
2052
2242
  ]);
2053
- const handleSave = useCallback9((props2) => {
2243
+ const handleSave = useCallback12((props2) => {
2054
2244
  projection.setFieldProjection({
2055
2245
  field,
2056
2246
  props: props2
@@ -2061,7 +2251,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel, outerS
2061
2251
  field,
2062
2252
  onSave
2063
2253
  ]);
2064
- const handleCancel = useCallback9(() => {
2254
+ const handleCancel = useCallback12(() => {
2065
2255
  requestAnimationFrame(() => onCancel?.());
2066
2256
  onSave();
2067
2257
  }, [
@@ -2070,9 +2260,9 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel, outerS
2070
2260
  const custom = useMemo7(() => ({
2071
2261
  ["format"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
2072
2262
  ...props2,
2073
- options: FormatEnums.filter((value) => value !== FormatEnum5.None).map((value) => ({
2074
- value,
2075
- label: t(`format ${value}`)
2263
+ options: FormatEnums.filter((value2) => value2 !== FormatEnum5.None).map((value2) => ({
2264
+ value: value2,
2265
+ label: t(`format ${value2}`)
2076
2266
  }))
2077
2267
  }),
2078
2268
  ["referenceSchema"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
@@ -2093,13 +2283,13 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel, outerS
2093
2283
  schemas,
2094
2284
  referenceSchema
2095
2285
  ]);
2096
- const propIsNotType = useCallback9((props2) => props2.filter((p) => p.name !== "type"), []);
2286
+ const propIsNotType = useCallback12((props2) => props2.filter((p) => p.name !== "type"), []);
2097
2287
  if (!fieldSchema) {
2098
2288
  log3.warn("invalid format", {
2099
2289
  props
2100
2290
  }, {
2101
2291
  F: __dxlog_file4,
2102
- L: 183,
2292
+ L: 180,
2103
2293
  S: void 0,
2104
2294
  C: (f, a) => f(...a)
2105
2295
  });
@@ -2108,6 +2298,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel, outerS
2108
2298
  return /* @__PURE__ */ React14.createElement(Form, {
2109
2299
  key: field.id,
2110
2300
  autoFocus: true,
2301
+ readonly,
2111
2302
  values: props,
2112
2303
  schema: fieldSchema,
2113
2304
  filter: propIsNotType,
@@ -2129,77 +2320,109 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel, outerS
2129
2320
 
2130
2321
  // src/components/ViewEditor/ViewEditor.tsx
2131
2322
  import { useSignals as _useSignals15 } from "@preact-signals/safe-react/tracking";
2132
- import { Schema as Schema2 } from "effect";
2133
- import React15, { useCallback as useCallback10, useMemo as useMemo8, useState as useState6 } from "react";
2134
- import { EchoSchema, Format, isMutable, toJsonSchema } from "@dxos/echo-schema";
2323
+ import * as Array2 from "effect/Array";
2324
+ import * as Match from "effect/Match";
2325
+ import * as Option from "effect/Option";
2326
+ import * as Schema2 from "effect/Schema";
2327
+ import React15, { forwardRef as forwardRef3, useCallback as useCallback13, useImperativeHandle, useMemo as useMemo8, useState as useState7 } from "react";
2328
+ import { QueryAST } from "@dxos/echo";
2329
+ import { EchoSchema, Format, isMutable, toJsonSchema } from "@dxos/echo/internal";
2330
+ import { Filter as Filter2, Query } from "@dxos/echo-db";
2135
2331
  import { invariant as invariant3 } from "@dxos/invariant";
2136
- import { Callout, IconButton as IconButton4, useTranslation as useTranslation9 } from "@dxos/react-ui";
2332
+ import { Callout, IconButton as IconButton4, Input as Input8, useTranslation as useTranslation10 } from "@dxos/react-ui";
2333
+ import { QueryForm } from "@dxos/react-ui-components";
2137
2334
  import { List as List2 } from "@dxos/react-ui-list";
2138
2335
  import { cardSpacing as cardSpacing3 } from "@dxos/react-ui-stack";
2139
- import { ghostHover, inputTextLabel, mx as mx9 } from "@dxos/react-ui-theme";
2140
- import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
2336
+ import { inputTextLabel, mx as mx7, subtleHover as subtleHover2 } from "@dxos/react-ui-theme";
2337
+ import { FieldSchema, ProjectionModel, VIEW_FIELD_LIMIT, getTypenameFromQuery } from "@dxos/schema";
2141
2338
  var __dxlog_file5 = "/__w/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
2142
- var grid = "grid grid-cols-[32px_1fr_32px_32px] min-bs-[2.5rem]";
2143
- var ViewMetaSchema = Schema2.Struct({
2144
- name: Schema2.String.annotations({
2145
- title: "View"
2146
- }),
2147
- typename: Format.URL.annotations({
2148
- title: "Typename"
2149
- })
2150
- }).pipe(Schema2.mutable);
2151
- var ViewEditor = ({ classNames, schema, view, registry, readonly: _readonly, showHeading = false, onTypenameChanged, onDelete, outerSpacing = true }) => {
2339
+ var listGrid = "grid grid-cols-[min-content_1fr_min-content_min-content_min-content]";
2340
+ var listItemGrid = "grid grid-cols-subgrid col-span-5";
2341
+ var ViewEditor = /* @__PURE__ */ forwardRef3(({ classNames, schema, view, mode = "schema", registry, readonly, showHeading = false, types, tags, onQueryChanged, onDelete, outerSpacing = true }, forwardedRef) => {
2152
2342
  var _effect = _useSignals15();
2153
2343
  try {
2154
- const { t } = useTranslation9(translationKey);
2155
- const projection = useMemo8(() => {
2344
+ const schemaReadonly = !isMutable(schema);
2345
+ const { t } = useTranslation10(translationKey);
2346
+ const projectionModel = useMemo8(() => {
2156
2347
  const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
2157
- return new ViewProjection(jsonSchema, view);
2348
+ return new ProjectionModel(jsonSchema, view.projection);
2158
2349
  }, [
2159
2350
  schema,
2160
- view
2351
+ JSON.stringify(view.projection)
2161
2352
  ]);
2162
- const [field, setField] = useState6();
2163
- const readonly = _readonly || !isMutable(schema);
2164
- const viewValues = useMemo8(() => {
2165
- return {
2166
- name: view.name,
2167
- // TODO(burdon): Need to warn user of possible consequences of editing.
2168
- // TODO(burdon): Settings should have domain name owned by user.
2169
- typename: view.query.typename
2170
- };
2171
- }, [
2172
- view
2353
+ useImperativeHandle(forwardedRef, () => projectionModel, [
2354
+ projectionModel
2173
2355
  ]);
2174
- const handleSelect = useCallback10((field2) => {
2175
- if (readonly) {
2176
- return;
2356
+ const [expandedField, setExpandedField] = useState7();
2357
+ const queueTarget = Match.value(view.query.ast).pipe(Match.when({
2358
+ type: "options"
2359
+ }, ({ options }) => {
2360
+ return Option.fromNullable(options.queues).pipe(Option.flatMap((queues) => Array2.head(queues)), Option.getOrUndefined);
2361
+ }), Match.orElse(() => void 0));
2362
+ const viewSchema = useMemo8(() => {
2363
+ const base = Schema2.Struct({
2364
+ query: mode === "schema" ? Format.URL.annotations({
2365
+ title: "Record type"
2366
+ }) : QueryAST.Query.annotations({
2367
+ title: "Query"
2368
+ })
2369
+ });
2370
+ if (mode === "query" || mode === "named-query") {
2371
+ const name = Schema2.Struct({
2372
+ name: Schema2.optional(Schema2.String.annotations({
2373
+ title: "Name"
2374
+ }))
2375
+ });
2376
+ return Schema2.Struct({
2377
+ ...mode === "named-query" ? {
2378
+ ...name.fields,
2379
+ ...base.fields
2380
+ } : base.fields,
2381
+ target: Schema2.optional(Schema2.String.annotations({
2382
+ title: "Target Queue"
2383
+ }))
2384
+ }).pipe(Schema2.mutable);
2177
2385
  }
2178
- setField((f) => f === field2 ? void 0 : field2);
2386
+ return base.pipe(Schema2.mutable);
2387
+ }, [
2388
+ mode
2389
+ ]);
2390
+ const viewValues = useMemo8(() => ({
2391
+ name: view.name,
2392
+ query: mode === "schema" ? getTypenameFromQuery(view.query.ast) : view.query.ast,
2393
+ target: queueTarget
2394
+ }), [
2395
+ view.name,
2396
+ mode,
2397
+ view.query.ast,
2398
+ queueTarget
2399
+ ]);
2400
+ const handleToggleField = useCallback13((field) => {
2401
+ setExpandedField((prevExpandedFieldId) => prevExpandedFieldId === field.id ? void 0 : field.id);
2179
2402
  }, [
2180
2403
  readonly
2181
2404
  ]);
2182
- const handleAdd = useCallback10(() => {
2405
+ const handleAdd = useCallback13(() => {
2183
2406
  invariant3(!readonly, void 0, {
2184
2407
  F: __dxlog_file5,
2185
- L: 92,
2408
+ L: 134,
2186
2409
  S: void 0,
2187
2410
  A: [
2188
2411
  "!readonly",
2189
2412
  ""
2190
2413
  ]
2191
2414
  });
2192
- const field2 = projection.createFieldProjection();
2193
- setField(field2);
2415
+ const field = projectionModel.createFieldProjection();
2416
+ setExpandedField(field.id);
2194
2417
  }, [
2195
2418
  schema,
2196
- view,
2419
+ projectionModel,
2197
2420
  readonly
2198
2421
  ]);
2199
- const handleUpdate = useCallback10(({ name, typename }) => {
2422
+ const handleUpdate = useCallback13((values) => {
2200
2423
  invariant3(!readonly, void 0, {
2201
2424
  F: __dxlog_file5,
2202
- L: 99,
2425
+ L: 141,
2203
2426
  S: void 0,
2204
2427
  A: [
2205
2428
  "!readonly",
@@ -2207,43 +2430,43 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly: _readonly, sho
2207
2430
  ]
2208
2431
  });
2209
2432
  requestAnimationFrame(() => {
2210
- if (view.name !== name) {
2211
- view.name = name;
2212
- }
2213
- if (view.query.typename !== typename && !readonly) {
2214
- onTypenameChanged?.(typename);
2433
+ if ("name" in values && view.name !== values.name) {
2434
+ view.name = values.name;
2435
+ return;
2215
2436
  }
2437
+ const query = mode === "schema" ? Query.select(Filter2.typename(values.query)).ast : values.query;
2438
+ onQueryChanged?.(query, values.target);
2216
2439
  });
2217
2440
  }, [
2218
- schema,
2441
+ onQueryChanged,
2442
+ readonly,
2219
2443
  view,
2220
- onTypenameChanged,
2221
- readonly
2444
+ queueTarget,
2445
+ mode
2222
2446
  ]);
2223
- const handleDelete = useCallback10((fieldId) => {
2447
+ const handleDelete = useCallback13((fieldId) => {
2224
2448
  invariant3(!readonly, void 0, {
2225
2449
  F: __dxlog_file5,
2226
- L: 115,
2450
+ L: 157,
2227
2451
  S: void 0,
2228
2452
  A: [
2229
2453
  "!readonly",
2230
2454
  ""
2231
2455
  ]
2232
2456
  });
2233
- if (fieldId === field?.id) {
2234
- setField(void 0);
2457
+ if (fieldId === expandedField) {
2458
+ setExpandedField(void 0);
2235
2459
  }
2236
2460
  onDelete?.(fieldId);
2237
2461
  }, [
2238
- schema,
2239
- field,
2462
+ expandedField,
2240
2463
  onDelete,
2241
2464
  readonly
2242
2465
  ]);
2243
- const handleMove = useCallback10((fromIndex, toIndex) => {
2466
+ const handleMove = useCallback13((fromIndex, toIndex) => {
2244
2467
  invariant3(!readonly, void 0, {
2245
2468
  F: __dxlog_file5,
2246
- L: 127,
2469
+ L: 169,
2247
2470
  S: void 0,
2248
2471
  A: [
2249
2472
  "!readonly",
@@ -2251,120 +2474,145 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly: _readonly, sho
2251
2474
  ]
2252
2475
  });
2253
2476
  const fields = [
2254
- ...view.fields
2477
+ ...view.projection.fields
2255
2478
  ];
2256
2479
  const [moved] = fields.splice(fromIndex, 1);
2257
2480
  fields.splice(toIndex, 0, moved);
2258
- view.fields = fields;
2481
+ view.projection.fields = fields;
2259
2482
  }, [
2260
- schema,
2261
- view.fields,
2483
+ view.projection.fields,
2262
2484
  readonly
2263
2485
  ]);
2264
- const handleClose = useCallback10(() => setField(void 0), []);
2265
- const hiddenProperties = projection.getHiddenProperties();
2266
- const handleHide = useCallback10((fieldId) => {
2267
- setField(void 0);
2268
- projection.hideFieldProjection(fieldId);
2486
+ const handleClose = useCallback13(() => setExpandedField(void 0), []);
2487
+ const handleHide = useCallback13((fieldId) => {
2488
+ setExpandedField(void 0);
2489
+ projectionModel.hideFieldProjection(fieldId);
2269
2490
  }, [
2270
- projection
2491
+ projectionModel
2271
2492
  ]);
2272
- const handleShow = useCallback10((property) => {
2273
- setField(void 0);
2274
- projection.showFieldProjection(property);
2493
+ const handleShow = useCallback13((property) => {
2494
+ setExpandedField(void 0);
2495
+ projectionModel.showFieldProjection(property);
2275
2496
  }, [
2276
- projection
2497
+ projectionModel
2498
+ ]);
2499
+ const custom = useMemo8(() => mode === "query" ? customFields({
2500
+ types,
2501
+ tags
2502
+ }) : void 0, [
2503
+ types,
2504
+ tags,
2505
+ mode
2277
2506
  ]);
2278
2507
  return /* @__PURE__ */ React15.createElement("div", {
2279
2508
  role: "none",
2280
- className: mx9(classNames)
2281
- }, readonly && /* @__PURE__ */ React15.createElement("div", {
2282
- role: "none",
2283
- className: mx9("is-full", outerSpacing && "plb-cardSpacingBlock pli-cardSpacingInline")
2284
- }, /* @__PURE__ */ React15.createElement(Callout.Root, {
2285
- valence: "info"
2286
- }, /* @__PURE__ */ React15.createElement(Callout.Title, null, t("system schema description")))), /* @__PURE__ */ React15.createElement(Form, {
2509
+ className: mx7(classNames)
2510
+ }, schemaReadonly && mode === "schema" && /* @__PURE__ */ React15.createElement(Callout.Root, {
2511
+ valence: "info",
2512
+ classNames: [
2513
+ "mlb-cardSpacingBlock",
2514
+ outerSpacing && "mli-cardSpacingInline"
2515
+ ]
2516
+ }, /* @__PURE__ */ React15.createElement(Callout.Title, null, t("system schema description"))), /* @__PURE__ */ React15.createElement(Form, {
2287
2517
  autoSave: true,
2288
- schema: ViewMetaSchema,
2518
+ schema: viewSchema,
2289
2519
  values: viewValues,
2290
- readonly,
2520
+ readonly: readonly ? "disabled-input" : false,
2291
2521
  onSave: handleUpdate,
2292
- outerSpacing
2522
+ outerSpacing,
2523
+ Custom: custom
2293
2524
  }), /* @__PURE__ */ React15.createElement("div", {
2294
2525
  role: "none",
2295
2526
  className: outerSpacing ? cardSpacing3 : "mlb-cardSpacingBlock"
2296
- }, /* @__PURE__ */ React15.createElement("label", {
2297
- className: mx9(inputTextLabel)
2527
+ }, /* @__PURE__ */ React15.createElement("h2", {
2528
+ className: mx7(inputTextLabel)
2298
2529
  }, t("fields label")), /* @__PURE__ */ React15.createElement(List2.Root, {
2299
- items: view.fields,
2530
+ items: view.projection.fields,
2300
2531
  isItem: Schema2.is(FieldSchema),
2301
- getId: (field2) => field2.id,
2302
- readonly,
2303
- onMove: readonly ? void 0 : handleMove
2304
- }, ({ items: fields }) => /* @__PURE__ */ React15.createElement(React15.Fragment, null, showHeading && /* @__PURE__ */ React15.createElement("div", {
2305
- role: "heading",
2306
- className: grid
2307
- }, /* @__PURE__ */ React15.createElement("div", null), /* @__PURE__ */ React15.createElement("div", {
2308
- className: "flex items-center text-sm"
2309
- }, t("field path label"))), /* @__PURE__ */ React15.createElement("div", {
2310
- role: "list",
2311
- className: "flex flex-col is-full"
2312
- }, fields?.map((field2) => /* @__PURE__ */ React15.createElement(List2.Item, {
2313
- key: field2.id,
2314
- item: field2,
2315
- classNames: mx9(grid, ghostHover, "overflow-hidden", !readonly && "cursor-pointer")
2316
- }, /* @__PURE__ */ React15.createElement(List2.ItemDragHandle, null), /* @__PURE__ */ React15.createElement(List2.ItemTitle, {
2317
- onClick: () => handleSelect(field2)
2318
- }, field2.path), /* @__PURE__ */ React15.createElement(List2.ItemButton, {
2319
- "data-testid": "hide-field-button",
2320
- icon: "ph--eye-slash--regular",
2321
- // TDOO(burdon): Is this the correct test?
2322
- disabled: view.fields.length <= 1,
2323
- onClick: () => handleHide(field2.id)
2324
- }), !readonly && /* @__PURE__ */ React15.createElement(List2.ItemDeleteButton, {
2325
- disabled: view.fields.length <= 1,
2326
- onClick: () => handleDelete(field2.id)
2327
- })))))), hiddenProperties.length > 0 && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("label", {
2328
- className: mx9(inputTextLabel)
2329
- }, t("hidden fields label")), /* @__PURE__ */ React15.createElement(List2.Root, {
2330
- items: hiddenProperties,
2331
- isItem: (item) => typeof item === "string",
2332
- getId: (property) => property
2333
- }, ({ items: properties }) => /* @__PURE__ */ React15.createElement("div", {
2532
+ getId: (field) => field.id,
2533
+ onMove: readonly ? void 0 : handleMove,
2534
+ readonly
2535
+ }, ({ items: fields }) => /* @__PURE__ */ React15.createElement(React15.Fragment, null, showHeading && /* @__PURE__ */ React15.createElement("h3", {
2536
+ className: "text-sm"
2537
+ }, t("field path label")), /* @__PURE__ */ React15.createElement("div", {
2334
2538
  role: "list",
2335
- className: "flex flex-col is-full"
2336
- }, properties?.map((property) => /* @__PURE__ */ React15.createElement(List2.Item, {
2337
- key: property,
2338
- item: property,
2339
- classNames: mx9(grid, ghostHover, !readonly && "cursor-pointer")
2340
- }, /* @__PURE__ */ React15.createElement(List2.ItemDragHandle, {
2341
- disabled: true
2342
- }), /* @__PURE__ */ React15.createElement(List2.ItemTitle, null, property), /* @__PURE__ */ React15.createElement(List2.ItemButton, {
2343
- icon: "ph--eye--regular",
2344
- onClick: () => handleShow(property),
2345
- "data-testid": "show-field-button"
2346
- }))))))), field && /* @__PURE__ */ React15.createElement(FieldEditor, {
2347
- key: field.id,
2348
- view,
2349
- projection,
2350
- field,
2351
- registry,
2352
- onSave: handleClose
2353
- }), !readonly && !field && /* @__PURE__ */ React15.createElement("div", {
2539
+ className: listGrid
2540
+ }, fields?.map((field) => {
2541
+ const hidden = field.visible === false;
2542
+ return /* @__PURE__ */ React15.createElement(List2.Item, {
2543
+ key: field.id,
2544
+ item: field,
2545
+ classNames: listItemGrid,
2546
+ "aria-expanded": expandedField === field.id
2547
+ }, /* @__PURE__ */ React15.createElement("div", {
2548
+ role: "none",
2549
+ className: mx7(subtleHover2, listItemGrid, "rounded-sm cursor-pointer min-bs-10")
2550
+ }, /* @__PURE__ */ React15.createElement(List2.ItemDragHandle, {
2551
+ disabled: readonly
2552
+ }), /* @__PURE__ */ React15.createElement(List2.ItemTitle, {
2553
+ classNames: hidden && "text-subdued",
2554
+ onClick: () => handleToggleField(field)
2555
+ }, field.path), /* @__PURE__ */ React15.createElement(List2.ItemButton, {
2556
+ label: t(hidden ? "show field label" : "hide field label"),
2557
+ "data-testid": hidden ? "show-field-button" : "hide-field-button",
2558
+ icon: hidden ? "ph--eye-closed--regular" : "ph--eye--regular",
2559
+ autoHide: false,
2560
+ disabled: readonly || !hidden && projectionModel.fields.length <= 1,
2561
+ onClick: () => hidden ? handleShow(field.path) : handleHide(field.id)
2562
+ }), mode === "schema" && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(List2.ItemDeleteButton, {
2563
+ label: t("delete field label"),
2564
+ autoHide: false,
2565
+ disabled: readonly || schemaReadonly || view.projection.fields.length <= 1,
2566
+ onClick: () => handleDelete(field.id),
2567
+ "data-testid": "field.delete"
2568
+ }), /* @__PURE__ */ React15.createElement(IconButton4, {
2569
+ iconOnly: true,
2570
+ variant: "ghost",
2571
+ label: t("toggle expand label", {
2572
+ ns: "os"
2573
+ }),
2574
+ icon: expandedField === field.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
2575
+ onClick: () => handleToggleField(field)
2576
+ }))), expandedField === field.id && mode === "schema" && /* @__PURE__ */ React15.createElement("div", {
2577
+ role: "none",
2578
+ className: "col-span-5 mbs-1 mbe-1 border border-separator rounded-md"
2579
+ }, /* @__PURE__ */ React15.createElement(FieldEditor, {
2580
+ readonly: readonly || schemaReadonly ? "disabled-input" : false,
2581
+ projection: projectionModel,
2582
+ field,
2583
+ registry,
2584
+ onSave: handleClose
2585
+ })));
2586
+ }))))), !readonly && !expandedField && mode === "schema" && /* @__PURE__ */ React15.createElement("div", {
2354
2587
  role: "none",
2355
2588
  className: outerSpacing ? cardSpacing3 : "mlb-cardSpacingBlock"
2356
2589
  }, /* @__PURE__ */ React15.createElement(IconButton4, {
2357
2590
  icon: "ph--plus--regular",
2358
- label: t("button add property"),
2591
+ label: t("add property button"),
2359
2592
  onClick: readonly ? void 0 : handleAdd,
2360
2593
  // TODO(burdon): Show field limit in ux (not tooltip).
2361
- disabled: view.fields.length >= VIEW_FIELD_LIMIT,
2362
- classNames: "flex is-full"
2594
+ disabled: view.projection.fields.length >= VIEW_FIELD_LIMIT,
2595
+ classNames: "is-full"
2363
2596
  })));
2364
2597
  } finally {
2365
2598
  _effect.f();
2366
2599
  }
2367
- };
2600
+ });
2601
+ var customFields = ({ types, tags }) => ({
2602
+ query: (props) => {
2603
+ const handleChange = useCallback13((query) => props.onValueChange("object", query.ast), [
2604
+ props.onValueChange
2605
+ ]);
2606
+ return /* @__PURE__ */ React15.createElement(Input8.Root, null, /* @__PURE__ */ React15.createElement(InputHeader, {
2607
+ label: props.label
2608
+ }), /* @__PURE__ */ React15.createElement(QueryForm, {
2609
+ initialQuery: props.getValue(),
2610
+ types,
2611
+ tags,
2612
+ onChange: handleChange
2613
+ }));
2614
+ }
2615
+ });
2368
2616
  export {
2369
2617
  BooleanInput,
2370
2618
  ControlFrame,
@@ -2376,8 +2624,6 @@ export {
2376
2624
  ControlPage,
2377
2625
  ControlSection,
2378
2626
  ControlSectionHeading,
2379
- DeprecatedFormContainer,
2380
- DeprecatedFormInput,
2381
2627
  FieldEditor,
2382
2628
  Form,
2383
2629
  FormProvider,
@@ -2385,6 +2631,7 @@ export {
2385
2631
  InputHeader,
2386
2632
  MarkdownInput,
2387
2633
  NumberInput,
2634
+ ObjectPicker,
2388
2635
  SelectInput,
2389
2636
  SelectOptionInput,
2390
2637
  TextInput,