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