@dxos/react-ui-form 0.8.4-main.3f58842 → 0.8.4-main.548089c

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