@dxos/react-ui-form 0.8.4-main.84f28bd → 0.8.4-main.ae835ea

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