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