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