@dxos/react-ui-form 0.8.4-main.67995b8 → 0.8.4-main.72ec0f3

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