@dxos/react-ui-form 0.8.4-main.3a94e84 → 0.8.4-main.406dc2a

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