@dxos/react-ui-form 0.8.2-main.f11618f → 0.8.2-staging.42af850

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 (98) hide show
  1. package/dist/lib/browser/index.mjs +1732 -1374
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +1715 -1365
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +1732 -1374
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/ControlSection/ControlSection.d.ts +1 -1
  11. package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +1 -1
  12. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  13. package/dist/types/src/components/FieldEditor/FieldEditor.test.d.ts +2 -0
  14. package/dist/types/src/components/FieldEditor/FieldEditor.test.d.ts.map +1 -0
  15. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Defaults.d.ts +4 -4
  17. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/Form.d.ts +4 -4
  19. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  20. package/dist/types/src/components/Form/Form.stories.d.ts +34 -34
  21. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  22. package/dist/types/src/components/Form/FormActions.d.ts +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 +9 -8
  25. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
  26. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
  27. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  28. package/dist/types/src/components/Form/RefField.d.ts +7 -18
  29. package/dist/types/src/components/Form/RefField.d.ts.map +1 -1
  30. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
  31. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -1
  32. package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -1
  33. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
  34. package/dist/types/src/components/Form/factory.d.ts +1 -1
  35. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  36. package/dist/types/src/components/Form/index.d.ts.map +1 -1
  37. package/dist/types/src/components/ViewEditor/Test.stories.d.ts.map +1 -1
  38. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +2 -2
  39. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  40. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +5 -3
  41. package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
  42. package/dist/types/src/components/deprecated/Form.d.ts +2 -2
  43. package/dist/types/src/components/deprecated/Form.d.ts.map +1 -1
  44. package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
  45. package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
  46. package/dist/types/src/components/testing.d.ts.map +1 -1
  47. package/dist/types/src/hooks/index.d.ts +2 -0
  48. package/dist/types/src/hooks/index.d.ts.map +1 -1
  49. package/dist/types/src/hooks/useForm.d.ts +2 -2
  50. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  51. package/dist/types/src/hooks/useQueryRefOptions.d.ts +23 -0
  52. package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +1 -0
  53. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts +8 -0
  54. package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +1 -0
  55. package/dist/types/src/translations.d.ts +5 -0
  56. package/dist/types/src/translations.d.ts.map +1 -1
  57. package/dist/types/src/util/field.d.ts.map +1 -1
  58. package/dist/types/src/util/formatting.d.ts.map +1 -1
  59. package/dist/types/src/util/index.d.ts +2 -0
  60. package/dist/types/src/util/index.d.ts.map +1 -1
  61. package/dist/types/src/util/refs.d.ts +9 -0
  62. package/dist/types/src/util/refs.d.ts.map +1 -0
  63. package/dist/types/src/util/schema.d.ts +3 -0
  64. package/dist/types/src/util/schema.d.ts.map +1 -0
  65. package/dist/types/src/vitest-setup.d.ts +2 -0
  66. package/dist/types/src/vitest-setup.d.ts.map +1 -0
  67. package/dist/types/tsconfig.tsbuildinfo +1 -1
  68. package/package.json +28 -25
  69. package/src/components/ControlSection/ControlSection.stories.tsx +1 -1
  70. package/src/components/ControlSection/ControlSection.tsx +2 -2
  71. package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
  72. package/src/components/FieldEditor/FieldEditor.test.tsx +49 -0
  73. package/src/components/FieldEditor/FieldEditor.tsx +3 -2
  74. package/src/components/Form/ArrayField.tsx +60 -49
  75. package/src/components/Form/Defaults.tsx +77 -48
  76. package/src/components/Form/Form.stories.tsx +104 -122
  77. package/src/components/Form/Form.tsx +5 -6
  78. package/src/components/Form/FormActions.tsx +15 -18
  79. package/src/components/Form/FormContent.tsx +80 -54
  80. package/src/components/Form/FormContext.tsx +14 -8
  81. package/src/components/Form/Input.tsx +4 -10
  82. package/src/components/Form/RefField.tsx +167 -101
  83. package/src/components/Form/custom/SelectOptionsInput.stories.tsx +6 -5
  84. package/src/components/Form/factory.tsx +1 -1
  85. package/src/components/Form/index.ts +0 -1
  86. package/src/components/ViewEditor/ViewEditor.stories.tsx +19 -9
  87. package/src/components/ViewEditor/ViewEditor.tsx +65 -35
  88. package/src/components/deprecated/Form.tsx +6 -6
  89. package/src/components/testing.tsx +5 -9
  90. package/src/hooks/index.ts +3 -1
  91. package/src/hooks/useForm.ts +4 -3
  92. package/src/hooks/useQueryRefOptions.ts +53 -0
  93. package/src/hooks/useRefQueryLookupHandler.ts +39 -0
  94. package/src/translations.ts +9 -2
  95. package/src/util/index.ts +3 -1
  96. package/src/util/refs.ts +38 -0
  97. package/src/util/schema.ts +14 -0
  98. package/src/vitest-setup.ts +11 -0
@@ -8,6 +8,7 @@ var translations_default = [
8
8
  [translationKey]: {
9
9
  "fields label": "Fields",
10
10
  "hidden fields label": "Hidden Fields",
11
+ "empty readonly ref field label": "(none)",
11
12
  // TODO(burdon): Standardize field/property.
12
13
  "button add property": "Add property",
13
14
  "field property label": "Property",
@@ -17,6 +18,8 @@ var translations_default = [
17
18
  "add field": "Add field",
18
19
  "delete field": "Delete field",
19
20
  "field limit reached": "Maximum number of fields reached",
21
+ "boolean input true value": "Yes",
22
+ "boolean input false value": "No",
20
23
  // TODO(burdon): Factor out?
21
24
  "button cancel": "Cancel",
22
25
  "button save": "Save",
@@ -46,246 +49,324 @@ var translations_default = [
46
49
  "format number": "Number",
47
50
  "format uri": "URI",
48
51
  "format uuid": "UUID",
49
- // Placeholders
52
+ // Placeholders.
50
53
  "placeholder latitude": "Latitude",
51
54
  "placeholder longitude": "Longitude",
52
- // SelectOptionsInput
55
+ // SelectOptionsInput.
53
56
  "select option label": "Label",
54
57
  "select option label placeholder": "Option label",
55
58
  "select option color": "Color",
56
59
  "select option delete": "Delete",
57
- "select option add": "Add option"
60
+ "select option add": "Add option",
61
+ // System schema message.
62
+ "system schema title": "System Schema",
63
+ "system schema description": "This schema is managed by the system and cannot be modified."
58
64
  }
59
65
  }
60
66
  }
61
67
  ];
62
68
 
63
69
  // packages/ui/react-ui-form/src/components/deprecated/FormInput.tsx
70
+ import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
64
71
  import React from "react";
65
72
  import { Input } from "@dxos/react-ui";
66
73
  import { mx, textBlockWidth } from "@dxos/react-ui-theme";
67
74
  var DeprecatedFormContainer = ({ children, classNames }) => {
68
- return /* @__PURE__ */ React.createElement("div", {
69
- role: "none",
70
- className: "container-max-width p-4 justify-center overflow-x-hidden overflow-y-auto"
71
- }, /* @__PURE__ */ React.createElement("div", {
72
- role: "form",
73
- className: mx("flex flex-col", textBlockWidth, classNames)
74
- }, children));
75
+ var _effect = _useSignals();
76
+ try {
77
+ return /* @__PURE__ */ React.createElement("div", {
78
+ role: "none",
79
+ className: "container-max-width p-4 justify-center overflow-x-hidden overflow-y-auto"
80
+ }, /* @__PURE__ */ React.createElement("div", {
81
+ role: "form",
82
+ className: mx("flex flex-col", textBlockWidth, classNames)
83
+ }, children));
84
+ } finally {
85
+ _effect.f();
86
+ }
75
87
  };
76
88
  var DeprecatedFormInput = ({ label, description, secondary, children }) => {
77
- const primary = /* @__PURE__ */ React.createElement("div", {
78
- role: "none",
79
- className: "flex w-full gap-4 py-1"
80
- }, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement("div", {
81
- role: "none",
82
- className: "flex flex-col w-full"
83
- }, /* @__PURE__ */ React.createElement(Input.Label, {
84
- classNames: "flex min-bs-[--rail-action] items-center",
85
- style: {
86
- fontSize: "unset"
87
- }
88
- }, label), description && /* @__PURE__ */ React.createElement(Input.DescriptionAndValidation, {
89
- classNames: "mbs-0.5"
90
- }, /* @__PURE__ */ React.createElement(Input.Description, null, description))), /* @__PURE__ */ React.createElement("div", {
91
- role: "none"
92
- }, /* @__PURE__ */ React.createElement("div", {
93
- role: "none",
94
- className: "flex min-bs-[--rail-action] items-center"
95
- }, children))));
96
- if (secondary) {
97
- return /* @__PURE__ */ React.createElement("div", {
89
+ var _effect = _useSignals();
90
+ try {
91
+ const primary = /* @__PURE__ */ React.createElement("div", {
92
+ role: "none",
93
+ className: "flex w-full gap-4 py-1"
94
+ }, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement("div", {
95
+ role: "none",
96
+ className: "flex flex-col w-full"
97
+ }, /* @__PURE__ */ React.createElement(Input.Label, {
98
+ classNames: "flex min-bs-[--rail-action] items-center",
99
+ style: {
100
+ fontSize: "unset"
101
+ }
102
+ }, label), description && /* @__PURE__ */ React.createElement(Input.DescriptionAndValidation, {
103
+ classNames: "mbs-0.5"
104
+ }, /* @__PURE__ */ React.createElement(Input.Description, null, description))), /* @__PURE__ */ React.createElement("div", {
98
105
  role: "none"
99
- }, primary, secondary);
106
+ }, /* @__PURE__ */ React.createElement("div", {
107
+ role: "none",
108
+ className: "flex min-bs-[--rail-action] items-center"
109
+ }, children))));
110
+ if (secondary) {
111
+ return /* @__PURE__ */ React.createElement("div", {
112
+ role: "none"
113
+ }, primary, secondary);
114
+ }
115
+ return primary;
116
+ } finally {
117
+ _effect.f();
100
118
  }
101
- return primary;
102
119
  };
103
120
 
104
121
  // packages/ui/react-ui-form/src/components/ControlSection/ControlSection.tsx
122
+ import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
105
123
  import React2 from "react";
106
124
  import { Button, Input as Input2, toLocalizedString, useTranslation } from "@dxos/react-ui";
107
125
  import { mx as mx2 } from "@dxos/react-ui-theme";
108
126
  var ControlPage = ({ children, classNames, ...props }) => {
109
- return /* @__PURE__ */ React2.createElement("div", {
110
- role: "none",
111
- className: mx2("pli-2", classNames),
112
- ...props
113
- }, children);
127
+ var _effect = _useSignals2();
128
+ try {
129
+ return /* @__PURE__ */ React2.createElement("div", {
130
+ role: "none",
131
+ className: mx2("pli-2", classNames),
132
+ ...props
133
+ }, children);
134
+ } finally {
135
+ _effect.f();
136
+ }
114
137
  };
115
138
  var ControlSection = ({ title, description, children }) => {
116
- return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(ControlSectionHeading, {
117
- title,
118
- description
119
- }), children);
139
+ var _effect = _useSignals2();
140
+ try {
141
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement(ControlSectionHeading, {
142
+ title,
143
+ description
144
+ }), children);
145
+ } finally {
146
+ _effect.f();
147
+ }
120
148
  };
121
149
  var ControlSectionHeading = ({ title, description }) => {
122
- const { t } = useTranslation(translationKey);
123
- return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("h2", {
124
- className: "pli-4 container-max-width text-xl mbs-6 mbe-4"
125
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
126
- className: "pli-4 mlb-4 container-max-width text-description"
127
- }, toLocalizedString(description, t)));
150
+ var _effect = _useSignals2();
151
+ try {
152
+ const { t } = useTranslation(translationKey);
153
+ return /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("h2", {
154
+ className: "pli-4 container-max-width text-xl mbs-6 mbe-4"
155
+ }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
156
+ className: "pli-4 mlb-4 container-max-width text-description"
157
+ }, toLocalizedString(description, t)));
158
+ } finally {
159
+ _effect.f();
160
+ }
128
161
  };
129
162
  var ControlGroupButton = ({ classNames, ...props }) => {
130
- return /* @__PURE__ */ React2.createElement(Button, {
131
- ...props,
132
- classNames: [
133
- "md:col-span-2",
134
- classNames
135
- ]
136
- });
163
+ var _effect = _useSignals2();
164
+ try {
165
+ return /* @__PURE__ */ React2.createElement(Button, {
166
+ ...props,
167
+ classNames: [
168
+ "md:col-span-2",
169
+ classNames
170
+ ]
171
+ });
172
+ } finally {
173
+ _effect.f();
174
+ }
175
+ };
176
+ var ControlGroup = ({ children, classNames }) => {
177
+ var _effect = _useSignals2();
178
+ try {
179
+ return /* @__PURE__ */ React2.createElement("div", {
180
+ role: "none",
181
+ className: mx2("group container-max-width grid grid-cols-1 md:grid-cols-[1fr_min-content] gap-4", classNames)
182
+ }, children);
183
+ } finally {
184
+ _effect.f();
185
+ }
186
+ };
187
+ var ControlFrame = ({ children }) => {
188
+ var _effect = _useSignals2();
189
+ try {
190
+ return /* @__PURE__ */ React2.createElement("div", {
191
+ role: "none",
192
+ className: "p-4 border border-separator rounded-lg container-max-width grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-2 md:gap-8"
193
+ }, children);
194
+ } finally {
195
+ _effect.f();
196
+ }
137
197
  };
138
- var ControlGroup = ({ children, classNames }) => /* @__PURE__ */ React2.createElement("div", {
139
- role: "none",
140
- className: mx2("group container-max-width grid grid-cols-1 md:grid-cols-[1fr_min-content] gap-4", classNames)
141
- }, children);
142
- var ControlFrame = ({ children }) => /* @__PURE__ */ React2.createElement("div", {
143
- role: "none",
144
- className: "p-4 border border-separator rounded-lg container-max-width grid grid-cols-1 md:grid-cols-[1fr_1fr] gap-2 md:gap-8"
145
- }, children);
146
- var controlItemClasses = "p-4 border border-separator rounded-lg container-max-width grid md:col-span-2 grid-cols-subgrid items-center";
147
- var controlItemTitleClasses = "text-lg font-normal mbe-2";
198
+ var controlItemClasses = "p-4 border border-separator rounded-lg container-max-width grid md:col-span-2 grid-cols-subgrid items-center gap-2";
199
+ var controlItemTitleClasses = "text-lg font-normal";
148
200
  var controlItemDescriptionClasses = "text-base mlb-2 md:mbe-0 text-description";
149
201
  var ControlItem = ({ title, description, children }) => {
150
- const { t } = useTranslation(translationKey);
151
- return /* @__PURE__ */ React2.createElement("div", {
152
- className: controlItemClasses
153
- }, /* @__PURE__ */ React2.createElement("div", {
154
- role: "none"
155
- }, /* @__PURE__ */ React2.createElement("h3", {
156
- className: controlItemTitleClasses
157
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
158
- className: controlItemDescriptionClasses
159
- }, toLocalizedString(description, t))), children);
202
+ var _effect = _useSignals2();
203
+ try {
204
+ const { t } = useTranslation(translationKey);
205
+ return /* @__PURE__ */ React2.createElement("div", {
206
+ className: controlItemClasses
207
+ }, /* @__PURE__ */ React2.createElement("div", {
208
+ role: "none"
209
+ }, /* @__PURE__ */ React2.createElement("h3", {
210
+ className: controlItemTitleClasses
211
+ }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
212
+ className: controlItemDescriptionClasses
213
+ }, toLocalizedString(description, t))), children);
214
+ } finally {
215
+ _effect.f();
216
+ }
160
217
  };
161
218
  var ControlItemInput = ({ title, description, children }) => {
162
- const { t } = useTranslation(translationKey);
163
- return /* @__PURE__ */ React2.createElement(Input2.Root, null, /* @__PURE__ */ React2.createElement("div", {
164
- className: controlItemClasses
165
- }, /* @__PURE__ */ React2.createElement("div", {
166
- role: "none"
167
- }, /* @__PURE__ */ React2.createElement(Input2.Label, {
168
- classNames: controlItemTitleClasses
169
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement(Input2.DescriptionAndValidation, null, /* @__PURE__ */ React2.createElement(Input2.Description, {
170
- classNames: controlItemDescriptionClasses
171
- }, toLocalizedString(description, t)))), children));
219
+ var _effect = _useSignals2();
220
+ try {
221
+ const { t } = useTranslation(translationKey);
222
+ return /* @__PURE__ */ React2.createElement(Input2.Root, null, /* @__PURE__ */ React2.createElement("div", {
223
+ className: controlItemClasses
224
+ }, /* @__PURE__ */ React2.createElement("div", {
225
+ role: "none"
226
+ }, /* @__PURE__ */ React2.createElement(Input2.Label, {
227
+ classNames: controlItemTitleClasses
228
+ }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement(Input2.DescriptionAndValidation, null, /* @__PURE__ */ React2.createElement(Input2.Description, {
229
+ classNames: controlItemDescriptionClasses
230
+ }, toLocalizedString(description, t)))), children));
231
+ } finally {
232
+ _effect.f();
233
+ }
172
234
  };
173
235
  var ControlFrameItem = ({ title, description, children }) => {
174
- const { t } = useTranslation(translationKey);
175
- return /* @__PURE__ */ React2.createElement("div", {
176
- role: "group",
177
- className: "min-is-0"
178
- }, /* @__PURE__ */ React2.createElement("h3", {
179
- className: "text-lg mbe-2"
180
- }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
181
- className: "mlb-2 md:mbe-0 text-description"
182
- }, toLocalizedString(description, t)), children);
236
+ var _effect = _useSignals2();
237
+ try {
238
+ const { t } = useTranslation(translationKey);
239
+ return /* @__PURE__ */ React2.createElement("div", {
240
+ role: "group",
241
+ className: "min-is-0"
242
+ }, /* @__PURE__ */ React2.createElement("h3", {
243
+ className: "text-lg mbe-2"
244
+ }, toLocalizedString(title, t)), description && /* @__PURE__ */ React2.createElement("p", {
245
+ className: "mlb-2 md:mbe-0 text-description"
246
+ }, toLocalizedString(description, t)), children);
247
+ } finally {
248
+ _effect.f();
249
+ }
183
250
  };
184
251
 
185
252
  // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
186
- import React14, { useCallback as useCallback6, useEffect as useEffect8, useMemo as useMemo7, useState as useState5 } from "react";
187
- import { FormatEnum as FormatEnum2, FormatEnums, formatToType } from "@dxos/echo-schema";
253
+ import { useSignals as _useSignals14 } from "@preact-signals/safe-react/tracking";
254
+ import React14, { useCallback as useCallback9, useEffect as useEffect8, useMemo as useMemo7, useState as useState5 } from "react";
255
+ import { FormatEnum as FormatEnum5, FormatEnums, formatToType } from "@dxos/echo-schema";
188
256
  import { log as log3 } from "@dxos/log";
189
- import { useTranslation as useTranslation6 } from "@dxos/react-ui";
257
+ import { useTranslation as useTranslation8 } from "@dxos/react-ui";
190
258
  import { getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
191
259
 
192
260
  // packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
261
+ import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
193
262
  import React4, { useCallback, useState, useEffect, useMemo } from "react";
194
263
  import { GeoLocation } from "@dxos/echo-schema";
195
264
  import { Input as Input3, useTranslation as useTranslation2 } from "@dxos/react-ui";
196
265
  import { safeParseFloat } from "@dxos/util";
197
266
 
198
267
  // packages/ui/react-ui-form/src/components/Form/Input.tsx
268
+ import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
199
269
  import React3 from "react";
200
270
  import { Icon, Tooltip } from "@dxos/react-ui";
201
271
  import { errorText } from "@dxos/react-ui-theme";
202
272
  var InputHeader = ({ children, error }) => {
203
- return /* @__PURE__ */ React3.createElement("div", {
204
- role: "none",
205
- className: "flex justify-between items-center mb-1"
206
- }, children, error && /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
207
- asChild: true
208
- }, /* @__PURE__ */ React3.createElement(Icon, {
209
- icon: "ph--warning--regular",
210
- size: 4,
211
- classNames: errorText
212
- })), /* @__PURE__ */ React3.createElement(Tooltip.Content, {
213
- side: "bottom"
214
- }, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null), error)));
273
+ var _effect = _useSignals3();
274
+ try {
275
+ return /* @__PURE__ */ React3.createElement("div", {
276
+ role: "none",
277
+ className: "flex justify-between items-center mbs-2 mbe-1 first:mbs-0"
278
+ }, children, error && /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
279
+ asChild: true,
280
+ content: error,
281
+ side: "bottom"
282
+ }, /* @__PURE__ */ React3.createElement(Icon, {
283
+ icon: "ph--warning--regular",
284
+ size: 4,
285
+ classNames: errorText
286
+ })));
287
+ } finally {
288
+ _effect.f();
289
+ }
215
290
  };
216
291
 
217
292
  // packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
218
293
  var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
219
- const { t } = useTranslation2(translationKey);
220
- const { status, error } = getStatus();
221
- const geoPoint = useMemo(() => getValue3() ?? [
222
- 0,
223
- 0
224
- ], [
225
- getValue3
226
- ]);
227
- const geoLocation = useMemo(() => GeoLocation.fromGeoPoint(geoPoint), [
228
- geoPoint
229
- ]);
230
- const [longitudeText, setLongitudeText] = useState(geoLocation.longitude?.toString());
231
- const [latitudeText, setLatitudeText] = useState(geoLocation.latitude?.toString());
232
- useEffect(() => {
233
- const location = GeoLocation.fromGeoPoint(geoPoint);
234
- setLongitudeText(location.longitude.toString());
235
- setLatitudeText(location.latitude.toString());
236
- }, [
237
- geoPoint
238
- ]);
239
- const handleCoordinateChange = useCallback((coordinateType, setText) => (event) => {
240
- const inputText = event.target.value;
241
- setText(inputText);
242
- if (inputText !== "" && inputText !== "-") {
243
- const coord = safeParseFloat(inputText);
244
- if (coord !== void 0 && !isNaN(coord)) {
245
- const currentLocation = GeoLocation.fromGeoPoint(getValue3() ?? [
246
- 0,
247
- 0
248
- ]);
249
- const newLocation = {
250
- ...currentLocation,
251
- [coordinateType]: coord
252
- };
253
- const newValue = GeoLocation.toGeoPoint(newLocation);
254
- onValueChange(type, newValue);
294
+ var _effect = _useSignals4();
295
+ try {
296
+ const { t } = useTranslation2(translationKey);
297
+ const { status, error } = getStatus();
298
+ const geoPoint = useMemo(() => getValue3() ?? [
299
+ 0,
300
+ 0
301
+ ], [
302
+ getValue3
303
+ ]);
304
+ const geoLocation = useMemo(() => GeoLocation.fromGeoPoint(geoPoint), [
305
+ geoPoint
306
+ ]);
307
+ const [longitudeText, setLongitudeText] = useState(geoLocation.longitude?.toString());
308
+ const [latitudeText, setLatitudeText] = useState(geoLocation.latitude?.toString());
309
+ useEffect(() => {
310
+ const location = GeoLocation.fromGeoPoint(geoPoint);
311
+ setLongitudeText(location.longitude.toString());
312
+ setLatitudeText(location.latitude.toString());
313
+ }, [
314
+ geoPoint
315
+ ]);
316
+ const handleCoordinateChange = useCallback((coordinateType, setText) => (event) => {
317
+ const inputText = event.target.value;
318
+ setText(inputText);
319
+ if (inputText !== "" && inputText !== "-") {
320
+ const coord = safeParseFloat(inputText);
321
+ if (coord !== void 0 && !isNaN(coord)) {
322
+ const currentLocation = GeoLocation.fromGeoPoint(getValue3() ?? [
323
+ 0,
324
+ 0
325
+ ]);
326
+ const newLocation = {
327
+ ...currentLocation,
328
+ [coordinateType]: coord
329
+ };
330
+ const newValue = GeoLocation.toGeoPoint(newLocation);
331
+ onValueChange(type, newValue);
332
+ }
255
333
  }
256
- }
257
- }, [
258
- getValue3,
259
- onValueChange,
260
- type
261
- ]);
262
- return /* @__PURE__ */ React4.createElement(Input3.Root, {
263
- validationValence: status
264
- }, /* @__PURE__ */ React4.createElement(InputHeader, {
265
- error
266
- }, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
267
- role: "none",
268
- className: "grid grid-cols-2 gap-2"
269
- }, /* @__PURE__ */ React4.createElement(Input3.TextInput, {
270
- type: "text",
271
- pattern: "^-?[0-9]*\\.?[0-9]*$",
272
- disabled,
273
- placeholder: t("placeholder latitude"),
274
- value: latitudeText,
275
- onChange: handleCoordinateChange("latitude", setLatitudeText),
276
- onBlur
277
- }), /* @__PURE__ */ React4.createElement(Input3.TextInput, {
278
- type: "text",
279
- pattern: "^-?[0-9]*\\.?[0-9]*$",
280
- disabled,
281
- placeholder: t("placeholder longitude"),
282
- value: longitudeText,
283
- onChange: handleCoordinateChange("longitude", setLongitudeText),
284
- onBlur
285
- })));
334
+ }, [
335
+ getValue3,
336
+ onValueChange,
337
+ type
338
+ ]);
339
+ return /* @__PURE__ */ React4.createElement(Input3.Root, {
340
+ validationValence: status
341
+ }, /* @__PURE__ */ React4.createElement(InputHeader, {
342
+ error
343
+ }, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
344
+ role: "none",
345
+ className: "grid grid-cols-2 gap-2"
346
+ }, /* @__PURE__ */ React4.createElement(Input3.TextInput, {
347
+ type: "text",
348
+ pattern: "^-?[0-9]*\\.?[0-9]*$",
349
+ disabled,
350
+ placeholder: t("placeholder latitude"),
351
+ value: latitudeText,
352
+ onChange: handleCoordinateChange("latitude", setLatitudeText),
353
+ onBlur
354
+ }), /* @__PURE__ */ React4.createElement(Input3.TextInput, {
355
+ type: "text",
356
+ pattern: "^-?[0-9]*\\.?[0-9]*$",
357
+ disabled,
358
+ placeholder: t("placeholder longitude"),
359
+ value: longitudeText,
360
+ onChange: handleCoordinateChange("longitude", setLongitudeText),
361
+ onBlur
362
+ })));
363
+ } finally {
364
+ _effect.f();
365
+ }
286
366
  };
287
367
 
288
368
  // packages/ui/react-ui-form/src/components/Form/custom/SelectOptionsInput.tsx
369
+ import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
289
370
  import React5, { useCallback as useCallback2, useEffect as useEffect2, useState as useState2, useRef } from "react";
290
371
  import { PublicKey } from "@dxos/keys";
291
372
  import { Icon as Icon2, IconButton, Input as Input4, Tag, Toolbar, useTranslation as useTranslation3 } from "@dxos/react-ui";
@@ -293,183 +374,189 @@ import { List } from "@dxos/react-ui-list";
293
374
  import { HuePicker } from "@dxos/react-ui-pickers";
294
375
  import { hues, mx as mx3 } from "@dxos/react-ui-theme";
295
376
  var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
296
- const [selected, setSelectedId] = useState2(null);
297
- const [isNewOption, setIsNewOption] = useState2(false);
298
- const inputRef = useRef(null);
299
- const { t } = useTranslation3(translationKey);
300
- const { status, error } = getStatus();
301
- const options = getValue3();
302
- useEffect2(() => {
303
- if (options === void 0) {
304
- onValueChange(type, []);
305
- }
306
- }, [
307
- options,
308
- onValueChange,
309
- type
310
- ]);
311
- const randomHue = () => {
312
- const usedHues = new Set(options?.map((option) => option.color) ?? []);
313
- const unusedHues = hues.filter((hue) => !usedHues.has(hue));
314
- if (unusedHues.length > 0) {
315
- return unusedHues[Math.floor(Math.random() * unusedHues.length)];
316
- }
317
- const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
318
- const availableHues = hues.filter((hue) => !lastThree.has(hue));
319
- return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hues[Math.floor(Math.random() * hues.length)];
320
- };
321
- const handleAdd = useCallback2(() => {
322
- const newId = PublicKey.random().truncate();
323
- const newOption = {
324
- id: newId,
325
- title: "",
326
- color: randomHue()
377
+ var _effect = _useSignals5();
378
+ try {
379
+ const [selected, setSelectedId] = useState2(null);
380
+ const [isNewOption, setIsNewOption] = useState2(false);
381
+ const inputRef = useRef(null);
382
+ const { t } = useTranslation3(translationKey);
383
+ const { status, error } = getStatus();
384
+ const options = getValue3();
385
+ useEffect2(() => {
386
+ if (options === void 0) {
387
+ onValueChange(type, []);
388
+ }
389
+ }, [
390
+ options,
391
+ onValueChange,
392
+ type
393
+ ]);
394
+ const randomHue = () => {
395
+ const usedHues = new Set(options?.map((option) => option.color) ?? []);
396
+ const unusedHues = hues.filter((hue) => !usedHues.has(hue));
397
+ if (unusedHues.length > 0) {
398
+ return unusedHues[Math.floor(Math.random() * unusedHues.length)];
399
+ }
400
+ const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
401
+ const availableHues = hues.filter((hue) => !lastThree.has(hue));
402
+ return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hues[Math.floor(Math.random() * hues.length)];
327
403
  };
328
- onValueChange(type, [
329
- ...options ?? [],
330
- newOption
404
+ const handleAdd = useCallback2(() => {
405
+ const newId = PublicKey.random().truncate();
406
+ const newOption = {
407
+ id: newId,
408
+ title: "",
409
+ color: randomHue()
410
+ };
411
+ onValueChange(type, [
412
+ ...options ?? [],
413
+ newOption
414
+ ]);
415
+ setSelectedId(newId);
416
+ setIsNewOption(true);
417
+ }, [
418
+ options,
419
+ type,
420
+ onValueChange
331
421
  ]);
332
- setSelectedId(newId);
333
- setIsNewOption(true);
334
- }, [
335
- options,
336
- type,
337
- onValueChange
338
- ]);
339
- const handleDelete = useCallback2((id) => {
340
- const newOptions = options?.filter((option) => option.id !== id) ?? [];
341
- onValueChange(type, newOptions);
342
- setSelectedId(null);
343
- }, [
344
- options,
345
- type,
346
- onValueChange
347
- ]);
348
- const handleMove = useCallback2((from, to) => {
349
- if (!options) {
350
- return;
351
- }
352
- const newOptions = [
353
- ...options
354
- ];
355
- const [removed] = newOptions.splice(from, 1);
356
- newOptions.splice(to, 0, removed);
357
- onValueChange(type, newOptions);
358
- }, [
359
- options,
360
- type,
361
- onValueChange
362
- ]);
363
- const handleClick = useCallback2((id) => {
364
- setSelectedId((current) => current === id ? null : id);
365
- }, []);
366
- const handleTitleChange = useCallback2((id) => (e) => {
367
- const newOptions = options?.map((o) => o.id === id ? {
368
- ...o,
369
- title: e.target.value
370
- } : o);
371
- onValueChange(type, newOptions ?? []);
372
- }, [
373
- options,
374
- type,
375
- onValueChange
376
- ]);
377
- const handleKeyDown = useCallback2((e) => {
378
- if (e.key === "Enter") {
422
+ const handleDelete = useCallback2((id) => {
423
+ const newOptions = options?.filter((option) => option.id !== id) ?? [];
424
+ onValueChange(type, newOptions);
379
425
  setSelectedId(null);
380
- }
381
- }, []);
382
- const handleColorChange = useCallback2((id) => (hue) => {
383
- const newOptions = options?.map((o) => o.id === id ? {
384
- ...o,
385
- color: hue
386
- } : o);
387
- onValueChange(type, newOptions ?? []);
388
- }, [
389
- options,
390
- type,
391
- onValueChange
392
- ]);
393
- useEffect2(() => {
394
- if (selected && isNewOption && inputRef.current) {
395
- inputRef.current.focus();
396
- setIsNewOption(false);
397
- }
398
- }, [
399
- selected,
400
- isNewOption
401
- ]);
402
- return /* @__PURE__ */ React5.createElement(Input4.Root, {
403
- validationValence: status
404
- }, /* @__PURE__ */ React5.createElement(InputHeader, {
405
- error
406
- }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement("div", {
407
- role: "none"
408
- }, options && /* @__PURE__ */ React5.createElement(List.Root, {
409
- items: options,
410
- isItem: (item) => true,
411
- onMove: handleMove
412
- }, ({ items }) => /* @__PURE__ */ React5.createElement("div", {
413
- role: "list",
414
- className: "w-full overflow-auto"
415
- }, items?.map((item) => /* @__PURE__ */ React5.createElement("div", {
416
- key: item.id
417
- }, /* @__PURE__ */ React5.createElement(List.Item, {
418
- role: "button",
419
- item,
420
- classNames: mx3("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
421
- "aria-expanded": selected === item.id
422
- }, /* @__PURE__ */ React5.createElement("div", {
423
- className: "flex items-center"
424
- }, /* @__PURE__ */ React5.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React5.createElement(List.ItemTitle, {
425
- onClick: () => handleClick(item.id),
426
- classNames: "flex-1"
427
- }, /* @__PURE__ */ React5.createElement(Tag, {
428
- palette: item.color
429
- }, item.title || "\u200B")), /* @__PURE__ */ React5.createElement(Icon2, {
430
- icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
431
- onClick: () => handleClick(item.id)
432
- })), selected === item.id && /* @__PURE__ */ React5.createElement("div", {
433
- className: "mis-4 mbs-2 flex flex-col gap-1"
434
- }, /* @__PURE__ */ React5.createElement(Input4.Label, {
435
- classNames: "text-xs"
436
- }, t("select option label")), /* @__PURE__ */ React5.createElement("div", {
437
- className: "flex flex-row items-center gap-1"
438
- }, /* @__PURE__ */ React5.createElement(Input4.TextInput, {
439
- placeholder: t("select option label placeholder"),
440
- ref: selected === item.id ? inputRef : void 0,
441
- value: item.title,
442
- onChange: handleTitleChange(item.id),
443
- onKeyDown: handleKeyDown,
444
- classNames: "flex-1",
445
- "data-no-submit": true
446
- }), /* @__PURE__ */ React5.createElement(Toolbar.Root, {
447
- classNames: "p-0 m-0 !is-auto"
448
- }, /* @__PURE__ */ React5.createElement(HuePicker, {
449
- value: item.color,
450
- onChange: handleColorChange(item.id),
451
- rootVariant: "toolbar-button"
452
- })), /* @__PURE__ */ React5.createElement(IconButton, {
453
- icon: "ph--trash--fill",
454
- iconOnly: true,
455
- label: t("select option delete"),
456
- onClick: () => handleDelete(item.id)
457
- })))))), /* @__PURE__ */ React5.createElement("div", {
458
- role: "listitem"
459
- }, /* @__PURE__ */ React5.createElement("div", {
460
- role: "button",
461
- className: mx3("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
462
- onClick: handleAdd
463
- }, /* @__PURE__ */ React5.createElement("div", {
464
- className: "flex items-center gap-1"
465
- }, /* @__PURE__ */ React5.createElement(Icon2, {
466
- icon: "ph--plus--regular"
467
- }), /* @__PURE__ */ React5.createElement("span", {
468
- className: "text-sm"
469
- }, t("select option add")))))))));
426
+ }, [
427
+ options,
428
+ type,
429
+ onValueChange
430
+ ]);
431
+ const handleMove = useCallback2((from, to) => {
432
+ if (!options) {
433
+ return;
434
+ }
435
+ const newOptions = [
436
+ ...options
437
+ ];
438
+ const [removed] = newOptions.splice(from, 1);
439
+ newOptions.splice(to, 0, removed);
440
+ onValueChange(type, newOptions);
441
+ }, [
442
+ options,
443
+ type,
444
+ onValueChange
445
+ ]);
446
+ const handleClick = useCallback2((id) => {
447
+ setSelectedId((current) => current === id ? null : id);
448
+ }, []);
449
+ const handleTitleChange = useCallback2((id) => (e) => {
450
+ const newOptions = options?.map((o) => o.id === id ? {
451
+ ...o,
452
+ title: e.target.value
453
+ } : o);
454
+ onValueChange(type, newOptions ?? []);
455
+ }, [
456
+ options,
457
+ type,
458
+ onValueChange
459
+ ]);
460
+ const handleKeyDown = useCallback2((e) => {
461
+ if (e.key === "Enter") {
462
+ setSelectedId(null);
463
+ }
464
+ }, []);
465
+ const handleColorChange = useCallback2((id) => (hue) => {
466
+ const newOptions = options?.map((o) => o.id === id ? {
467
+ ...o,
468
+ color: hue
469
+ } : o);
470
+ onValueChange(type, newOptions ?? []);
471
+ }, [
472
+ options,
473
+ type,
474
+ onValueChange
475
+ ]);
476
+ useEffect2(() => {
477
+ if (selected && isNewOption && inputRef.current) {
478
+ inputRef.current.focus();
479
+ setIsNewOption(false);
480
+ }
481
+ }, [
482
+ selected,
483
+ isNewOption
484
+ ]);
485
+ return /* @__PURE__ */ React5.createElement(Input4.Root, {
486
+ validationValence: status
487
+ }, /* @__PURE__ */ React5.createElement(InputHeader, {
488
+ error
489
+ }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement("div", {
490
+ role: "none"
491
+ }, options && /* @__PURE__ */ React5.createElement(List.Root, {
492
+ items: options,
493
+ isItem: (item) => true,
494
+ onMove: handleMove
495
+ }, ({ items }) => /* @__PURE__ */ React5.createElement("div", {
496
+ role: "list",
497
+ className: "w-full overflow-auto"
498
+ }, items?.map((item) => /* @__PURE__ */ React5.createElement("div", {
499
+ key: item.id
500
+ }, /* @__PURE__ */ React5.createElement(List.Item, {
501
+ role: "button",
502
+ item,
503
+ classNames: mx3("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
504
+ "aria-expanded": selected === item.id
505
+ }, /* @__PURE__ */ React5.createElement("div", {
506
+ className: "flex items-center"
507
+ }, /* @__PURE__ */ React5.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React5.createElement(List.ItemTitle, {
508
+ onClick: () => handleClick(item.id),
509
+ classNames: "flex-1"
510
+ }, /* @__PURE__ */ React5.createElement(Tag, {
511
+ palette: item.color
512
+ }, item.title || "\u200B")), /* @__PURE__ */ React5.createElement(Icon2, {
513
+ icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
514
+ onClick: () => handleClick(item.id)
515
+ })), selected === item.id && /* @__PURE__ */ React5.createElement("div", {
516
+ className: "mis-4 mbs-2 flex flex-col gap-1"
517
+ }, /* @__PURE__ */ React5.createElement(Input4.Label, {
518
+ classNames: "text-xs"
519
+ }, t("select option label")), /* @__PURE__ */ React5.createElement("div", {
520
+ className: "flex flex-row items-center gap-1"
521
+ }, /* @__PURE__ */ React5.createElement(Input4.TextInput, {
522
+ placeholder: t("select option label placeholder"),
523
+ ref: selected === item.id ? inputRef : void 0,
524
+ value: item.title,
525
+ onChange: handleTitleChange(item.id),
526
+ onKeyDown: handleKeyDown,
527
+ classNames: "flex-1",
528
+ "data-no-submit": true
529
+ }), /* @__PURE__ */ React5.createElement(Toolbar.Root, {
530
+ classNames: "p-0 m-0 !is-auto"
531
+ }, /* @__PURE__ */ React5.createElement(HuePicker, {
532
+ value: item.color,
533
+ onChange: handleColorChange(item.id),
534
+ rootVariant: "toolbar-button"
535
+ })), /* @__PURE__ */ React5.createElement(IconButton, {
536
+ icon: "ph--trash--fill",
537
+ iconOnly: true,
538
+ label: t("select option delete"),
539
+ onClick: () => handleDelete(item.id)
540
+ })))))), /* @__PURE__ */ React5.createElement("div", {
541
+ role: "listitem"
542
+ }, /* @__PURE__ */ React5.createElement("div", {
543
+ role: "button",
544
+ className: mx3("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
545
+ onClick: handleAdd
546
+ }, /* @__PURE__ */ React5.createElement("div", {
547
+ className: "flex items-center gap-1"
548
+ }, /* @__PURE__ */ React5.createElement(Icon2, {
549
+ icon: "ph--plus--regular"
550
+ }), /* @__PURE__ */ React5.createElement("span", {
551
+ className: "text-sm"
552
+ }, t("select option add")))))))));
553
+ } finally {
554
+ _effect.f();
555
+ }
470
556
  };
471
557
 
472
558
  // packages/ui/react-ui-form/src/components/Form/custom/TupleInput.tsx
559
+ import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
473
560
  import React6 from "react";
474
561
  import { Input as Input5 } from "@dxos/react-ui";
475
562
  import { mx as mx4 } from "@dxos/react-ui-theme";
@@ -481,149 +568,188 @@ var gridCols = [
481
568
  "grid-cols-4"
482
569
  ];
483
570
  var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
484
- const { status, error } = getStatus();
485
- const values = getValue3() ?? {};
486
- return /* @__PURE__ */ React6.createElement(Input5.Root, {
487
- validationValence: status
488
- }, /* @__PURE__ */ React6.createElement(InputHeader, {
489
- error
490
- }, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement("div", {
491
- className: mx4("grid gap-2", gridCols[binding.length - 1])
492
- }, binding.map((prop) => /* @__PURE__ */ React6.createElement(Input5.TextInput, {
493
- key: prop,
494
- type: "number",
495
- disabled,
496
- value: values[prop],
497
- onChange: (event) => onValueChange(type, {
498
- ...values,
499
- [prop]: safeParseFloat2(event.target.value, 0)
500
- }),
501
- onBlur
502
- }))));
571
+ var _effect = _useSignals6();
572
+ try {
573
+ const { status, error } = getStatus();
574
+ const values = getValue3() ?? {};
575
+ return /* @__PURE__ */ React6.createElement(Input5.Root, {
576
+ validationValence: status
577
+ }, /* @__PURE__ */ React6.createElement(InputHeader, {
578
+ error
579
+ }, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement("div", {
580
+ className: mx4("grid gap-2", gridCols[binding.length - 1])
581
+ }, binding.map((prop) => /* @__PURE__ */ React6.createElement(Input5.TextInput, {
582
+ key: prop,
583
+ type: "number",
584
+ disabled,
585
+ value: values[prop],
586
+ onChange: (event) => onValueChange(type, {
587
+ ...values,
588
+ [prop]: safeParseFloat2(event.target.value, 0)
589
+ }),
590
+ onBlur
591
+ }))));
592
+ } finally {
593
+ _effect.f();
594
+ }
503
595
  };
504
596
 
505
597
  // packages/ui/react-ui-form/src/components/Form/Defaults.tsx
598
+ import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
506
599
  import React7, { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef2 } from "react";
507
- import { Input as Input6, Select } from "@dxos/react-ui";
600
+ import { Input as Input6, Select, useTranslation as useTranslation4 } from "@dxos/react-ui";
508
601
  var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
509
- const { status, error } = getStatus();
510
- return /* @__PURE__ */ React7.createElement(Input6.Root, {
511
- validationValence: status
512
- }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
513
- error
514
- }, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), /* @__PURE__ */ React7.createElement(Input6.TextInput, {
515
- disabled,
516
- placeholder,
517
- value: getValue3() ?? "",
518
- onChange: (event) => onValueChange(type, event.target.value),
519
- onBlur
520
- }), inputOnly && /* @__PURE__ */ React7.createElement(Input6.Validation, null, error));
602
+ var _effect = _useSignals7();
603
+ try {
604
+ const { status, error } = getStatus();
605
+ return disabled && !getValue3() ? null : disabled && inputOnly ? /* @__PURE__ */ React7.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React7.createElement(Input6.Root, {
606
+ validationValence: status
607
+ }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
608
+ error
609
+ }, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), disabled ? /* @__PURE__ */ React7.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React7.createElement(Input6.TextInput, {
610
+ disabled,
611
+ placeholder,
612
+ value: getValue3() ?? "",
613
+ onChange: (event) => onValueChange(type, event.target.value),
614
+ onBlur
615
+ }), inputOnly && /* @__PURE__ */ React7.createElement(Input6.Validation, null, error));
616
+ } finally {
617
+ _effect.f();
618
+ }
521
619
  };
522
620
  var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
523
- const { status, error } = getStatus();
524
- return /* @__PURE__ */ React7.createElement(Input6.Root, {
525
- validationValence: status
526
- }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
527
- error
528
- }, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), /* @__PURE__ */ React7.createElement(Input6.TextInput, {
529
- type: "number",
530
- disabled,
531
- placeholder,
532
- value: getValue3() ?? 0,
533
- onChange: (event) => onValueChange(type, event.target.value),
534
- onBlur
535
- }), inputOnly && /* @__PURE__ */ React7.createElement(Input6.DescriptionAndValidation, null, error));
621
+ var _effect = _useSignals7();
622
+ try {
623
+ const { status, error } = getStatus();
624
+ return disabled && !getValue3() ? null : disabled && inputOnly ? /* @__PURE__ */ React7.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React7.createElement(Input6.Root, {
625
+ validationValence: status
626
+ }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
627
+ error
628
+ }, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), disabled ? /* @__PURE__ */ React7.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React7.createElement(Input6.TextInput, {
629
+ type: "number",
630
+ disabled,
631
+ placeholder,
632
+ value: getValue3() ?? 0,
633
+ onChange: (event) => onValueChange(type, event.target.value),
634
+ onBlur
635
+ }), inputOnly && /* @__PURE__ */ React7.createElement(Input6.DescriptionAndValidation, null, error));
636
+ } finally {
637
+ _effect.f();
638
+ }
536
639
  };
537
- var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
538
- const { status, error } = getStatus();
539
- const checked = Boolean(getValue3());
540
- return /* @__PURE__ */ React7.createElement(Input6.Root, {
541
- validationValence: status
542
- }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
543
- error
544
- }, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), /* @__PURE__ */ React7.createElement(Input6.Switch, {
545
- checked,
546
- onCheckedChange: (value) => onValueChange(type, value)
547
- }), inputOnly && /* @__PURE__ */ React7.createElement(Input6.DescriptionAndValidation, null, error));
640
+ var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange, disabled }) => {
641
+ var _effect = _useSignals7();
642
+ try {
643
+ const { status, error } = getStatus();
644
+ const checked = Boolean(getValue3());
645
+ const { t } = useTranslation4(translationKey);
646
+ return /* @__PURE__ */ React7.createElement(Input6.Root, {
647
+ validationValence: status
648
+ }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
649
+ error
650
+ }, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), disabled ? /* @__PURE__ */ React7.createElement("p", null, t(checked ? "boolean input true value" : "boolean input false value")) : /* @__PURE__ */ React7.createElement(Input6.Switch, {
651
+ checked,
652
+ onCheckedChange: (value) => onValueChange(type, value)
653
+ }), inputOnly && /* @__PURE__ */ React7.createElement(Input6.DescriptionAndValidation, null, error));
654
+ } finally {
655
+ _effect.f();
656
+ }
548
657
  };
549
658
  var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
550
- const { status, error } = getStatus();
551
- return /* @__PURE__ */ React7.createElement(Input6.Root, {
552
- validationValence: status
553
- }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
554
- error
555
- }, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), /* @__PURE__ */ React7.createElement(Select.Root, {
556
- value: getValue3(),
557
- onValueChange: (value) => onValueChange(type, value)
558
- }, /* @__PURE__ */ React7.createElement(Select.TriggerButton, {
559
- classNames: "is-full",
560
- disabled,
561
- placeholder
562
- }), /* @__PURE__ */ React7.createElement(Select.Portal, null, /* @__PURE__ */ React7.createElement(Select.Content, null, /* @__PURE__ */ React7.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
563
- // NOTE: Numeric values are converted to and from strings.
564
- /* @__PURE__ */ React7.createElement(Select.Option, {
565
- key: String(value),
566
- value: String(value)
567
- }, label2 ?? String(value))
568
- )))))), inputOnly && /* @__PURE__ */ React7.createElement(Input6.DescriptionAndValidation, null, error));
659
+ var _effect = _useSignals7();
660
+ try {
661
+ const { status, error } = getStatus();
662
+ const value = getValue3();
663
+ const handleValueChange = useCallback3((value2) => onValueChange(type, value2), [
664
+ type,
665
+ onValueChange
666
+ ]);
667
+ return disabled && !value ? null : /* @__PURE__ */ React7.createElement(Input6.Root, {
668
+ validationValence: status
669
+ }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
670
+ error
671
+ }, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), disabled ? /* @__PURE__ */ React7.createElement("p", null, options?.find(({ value: optionValue }) => optionValue === value)?.label ?? String(value)) : /* @__PURE__ */ React7.createElement(Select.Root, {
672
+ value,
673
+ onValueChange: handleValueChange
674
+ }, /* @__PURE__ */ React7.createElement(Select.TriggerButton, {
675
+ classNames: "is-full",
676
+ disabled,
677
+ placeholder
678
+ }), /* @__PURE__ */ React7.createElement(Select.Portal, null, /* @__PURE__ */ React7.createElement(Select.Content, null, /* @__PURE__ */ React7.createElement(Select.Viewport, null, options?.map(({ value: value2, label: label2 }) => (
679
+ // NOTE: Numeric values are converted to and from strings.
680
+ /* @__PURE__ */ React7.createElement(Select.Option, {
681
+ key: String(value2),
682
+ value: String(value2)
683
+ }, label2 ?? String(value2))
684
+ )))))), inputOnly && /* @__PURE__ */ React7.createElement(Input6.DescriptionAndValidation, null, error));
685
+ } finally {
686
+ _effect.f();
687
+ }
569
688
  };
570
689
  var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
571
- const { status, error } = getStatus();
572
- const textareaRef = useRef2(null);
573
- const adjustHeight = useCallback3(() => {
574
- const textarea = textareaRef.current;
575
- if (textarea) {
576
- textarea.style.blockSize = "auto";
577
- textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
578
- }
579
- }, []);
580
- useEffect3(() => {
581
- adjustHeight();
582
- }, [
583
- adjustHeight
584
- ]);
585
- useEffect3(() => {
586
- adjustHeight();
587
- }, [
588
- getValue3(),
589
- adjustHeight
590
- ]);
591
- return /* @__PURE__ */ React7.createElement(Input6.Root, {
592
- validationValence: status
593
- }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
594
- error
595
- }, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), /* @__PURE__ */ React7.createElement(Input6.TextArea, {
596
- ref: textareaRef,
597
- disabled,
598
- placeholder,
599
- value: getValue3() ?? "",
600
- classNames: "min-bs-auto max-h-40 overflow-auto",
601
- onChange: (event) => onValueChange(type, event.target.value),
602
- onBlur,
603
- style: {
604
- resize: "none"
605
- },
606
- spellCheck: false
607
- }), inputOnly && /* @__PURE__ */ React7.createElement(Input6.Validation, null, error));
690
+ var _effect = _useSignals7();
691
+ try {
692
+ const { status, error } = getStatus();
693
+ const textareaRef = useRef2(null);
694
+ const adjustHeight = useCallback3(() => {
695
+ const textarea = textareaRef.current;
696
+ if (textarea) {
697
+ textarea.style.blockSize = "auto";
698
+ textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
699
+ }
700
+ }, []);
701
+ useEffect3(() => {
702
+ adjustHeight();
703
+ }, [
704
+ adjustHeight
705
+ ]);
706
+ useEffect3(() => {
707
+ adjustHeight();
708
+ }, [
709
+ getValue3(),
710
+ adjustHeight
711
+ ]);
712
+ return /* @__PURE__ */ React7.createElement(Input6.Root, {
713
+ validationValence: status
714
+ }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
715
+ error
716
+ }, /* @__PURE__ */ React7.createElement(Input6.Label, null, label)), disabled ? /* @__PURE__ */ React7.createElement("p", null, getValue3() ?? "") : /* @__PURE__ */ React7.createElement(Input6.TextArea, {
717
+ ref: textareaRef,
718
+ disabled,
719
+ placeholder,
720
+ value: getValue3() ?? "",
721
+ classNames: "min-bs-auto max-h-40 overflow-auto",
722
+ onChange: (event) => onValueChange(type, event.target.value),
723
+ onBlur,
724
+ style: {
725
+ resize: "none"
726
+ },
727
+ spellCheck: false
728
+ }), inputOnly && /* @__PURE__ */ React7.createElement(Input6.Validation, null, error));
729
+ } finally {
730
+ _effect.f();
731
+ }
608
732
  };
609
733
 
610
734
  // packages/ui/react-ui-form/src/components/Form/Form.tsx
735
+ import { useSignals as _useSignals13 } from "@preact-signals/safe-react/tracking";
611
736
  import React13, { useEffect as useEffect7, useMemo as useMemo6, useRef as useRef3 } from "react";
612
- import { mx as mx8 } from "@dxos/react-ui-theme";
737
+ import { mx as mx7 } from "@dxos/react-ui-theme";
613
738
 
614
739
  // packages/ui/react-ui-form/src/components/Form/FormActions.tsx
740
+ import { useSignals as _useSignals9 } from "@preact-signals/safe-react/tracking";
615
741
  import React9 from "react";
616
- import { IconButton as IconButton2, useTranslation as useTranslation4 } from "@dxos/react-ui";
617
- import { mx as mx5 } from "@dxos/react-ui-theme";
742
+ import { IconButton as IconButton2, useTranslation as useTranslation5 } from "@dxos/react-ui";
618
743
 
619
744
  // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
620
- import React8, { createContext, useContext, useEffect as useEffect5, useMemo as useMemo3 } from "react";
745
+ import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
746
+ import React8, { createContext, useContext, useEffect as useEffect6, useMemo as useMemo3, useCallback as useCallback6 } from "react";
621
747
  import { raise } from "@dxos/debug";
622
748
  import { getValue as getValue2 } from "@dxos/echo-schema";
623
749
  import { createJsonPath as createJsonPath2 } from "@dxos/effect";
624
750
 
625
751
  // packages/ui/react-ui-form/src/hooks/useForm.ts
626
- import { SchemaAST as AST } from "effect";
752
+ import { SchemaAST } from "effect";
627
753
  import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo2, useState as useState3 } from "react";
628
754
  import { getValue, setValue } from "@dxos/echo-schema";
629
755
  import { createJsonPath, fromEffectValidationPath } from "@dxos/effect";
@@ -632,12 +758,12 @@ import { log } from "@dxos/log";
632
758
  import { validateSchema } from "@dxos/schema";
633
759
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
634
760
  var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
635
- invariant(AST.isTypeLiteral(schema.ast), void 0, {
761
+ invariant(SchemaAST.isTypeLiteral(schema.ast), void 0, {
636
762
  F: __dxlog_file,
637
763
  L: 93,
638
764
  S: void 0,
639
765
  A: [
640
- "AST.isTypeLiteral(schema.ast)",
766
+ "SchemaAST.isTypeLiteral(schema.ast)",
641
767
  ""
642
768
  ]
643
769
  });
@@ -738,7 +864,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
738
864
  } catch (err) {
739
865
  log.catch(err, void 0, {
740
866
  F: __dxlog_file,
741
- L: 212,
867
+ L: 213,
742
868
  S: void 0,
743
869
  C: (f, a) => f(...a)
744
870
  });
@@ -809,7 +935,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
809
935
  var createKeySet = (obj, value) => {
810
936
  invariant(obj, void 0, {
811
937
  F: __dxlog_file,
812
- L: 274,
938
+ L: 275,
813
939
  S: void 0,
814
940
  A: [
815
941
  "obj",
@@ -831,6 +957,80 @@ var flatMap = (errors) => {
831
957
  }, {});
832
958
  };
833
959
 
960
+ // packages/ui/react-ui-form/src/hooks/useRefQueryLookupHandler.ts
961
+ import { useCallback as useCallback5 } from "react";
962
+ import { getDXN } from "@dxos/echo-schema";
963
+ import { Filter } from "@dxos/react-client/echo";
964
+ import { isNonNullable } from "@dxos/util";
965
+ var useRefQueryLookupHandler = ({ space }) => {
966
+ return useCallback5(async (typeInfo) => {
967
+ if (!space) {
968
+ return [];
969
+ }
970
+ const query = space.db.query(Filter.typename(typeInfo.typename));
971
+ const { objects } = await query.run();
972
+ return objects.map((object) => {
973
+ const dxn = getDXN(object);
974
+ if (!dxn) {
975
+ return void 0;
976
+ }
977
+ const item = {
978
+ dxn,
979
+ label: object?.name ?? object?.id ?? ""
980
+ };
981
+ return item;
982
+ }).filter(isNonNullable);
983
+ }, [
984
+ space
985
+ ]);
986
+ };
987
+
988
+ // packages/ui/react-ui-form/src/hooks/useQueryRefOptions.ts
989
+ import { useEffect as useEffect5, useState as useState4 } from "react";
990
+ import { log as log2 } from "@dxos/log";
991
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useQueryRefOptions.ts";
992
+ var useQueryRefOptions = ({ refTypeInfo, onQueryRefOptions }) => {
993
+ const [options, setOptions] = useState4([]);
994
+ const [loading, setLoading] = useState4(false);
995
+ useEffect5(() => {
996
+ if (!refTypeInfo || !onQueryRefOptions) {
997
+ return;
998
+ }
999
+ const fetchOptions = async () => {
1000
+ setLoading(true);
1001
+ try {
1002
+ const fetchedOptions = await onQueryRefOptions(refTypeInfo);
1003
+ setOptions(fetchedOptions.map((option) => {
1004
+ const dxn = option.dxn.toString();
1005
+ return {
1006
+ id: dxn,
1007
+ label: option.label ?? dxn,
1008
+ hue: "neutral"
1009
+ };
1010
+ }));
1011
+ } catch (error) {
1012
+ log2.error("Failed to fetch ref options:", error, {
1013
+ F: __dxlog_file2,
1014
+ L: 42,
1015
+ S: void 0,
1016
+ C: (f, a) => f(...a)
1017
+ });
1018
+ setOptions([]);
1019
+ } finally {
1020
+ setLoading(false);
1021
+ }
1022
+ };
1023
+ void fetchOptions();
1024
+ }, [
1025
+ refTypeInfo,
1026
+ onQueryRefOptions
1027
+ ]);
1028
+ return {
1029
+ options,
1030
+ loading
1031
+ };
1032
+ };
1033
+
834
1034
  // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
835
1035
  var FormContext = /* @__PURE__ */ createContext(void 0);
836
1036
  var useFormContext = () => {
@@ -860,16 +1060,14 @@ var useInputProps = (path = []) => {
860
1060
  ]);
861
1061
  };
862
1062
  var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
863
- const form = useForm(formOptions);
864
- useEffect5(() => {
865
- if (!formRef?.current) {
866
- return;
867
- }
868
- const handleKeyDown = (event) => {
1063
+ var _effect = _useSignals8();
1064
+ try {
1065
+ const form = useForm(formOptions);
1066
+ const handleKeyDown = useCallback6((event) => {
869
1067
  const keyIsEnter = event.key === "Enter";
870
1068
  const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
871
1069
  const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
872
- const inputOptOut = event.target.hasAttribute("data-no-submit");
1070
+ const inputOptOut = event.target.hasAttribute("data-no-submit") || event.target.closest("[data-no-submit]") !== null;
873
1071
  const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
874
1072
  const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
875
1073
  if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
@@ -880,881 +1078,108 @@ var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
880
1078
  event.target.blur();
881
1079
  }
882
1080
  }
883
- };
884
- const formElement = formRef.current;
885
- formElement.addEventListener("keydown", handleKeyDown);
886
- return () => formElement.removeEventListener("keydown", handleKeyDown);
887
- }, [
888
- formRef,
889
- form.canSave,
890
- form.formIsValid,
891
- form.handleSave,
892
- autoSave
893
- ]);
894
- return /* @__PURE__ */ React8.createElement(FormContext.Provider, {
895
- value: form
896
- }, children);
1081
+ }, [
1082
+ form,
1083
+ autoSave
1084
+ ]);
1085
+ useEffect6(() => {
1086
+ if (!formRef?.current) {
1087
+ return;
1088
+ }
1089
+ const formElement = formRef.current;
1090
+ formElement.addEventListener("keydown", handleKeyDown);
1091
+ return () => formElement.removeEventListener("keydown", handleKeyDown);
1092
+ }, [
1093
+ formRef,
1094
+ form.canSave,
1095
+ form.formIsValid,
1096
+ form.handleSave,
1097
+ autoSave
1098
+ ]);
1099
+ return /* @__PURE__ */ React8.createElement(FormContext.Provider, {
1100
+ value: form
1101
+ }, children);
1102
+ } finally {
1103
+ _effect.f();
1104
+ }
897
1105
  };
898
1106
 
899
1107
  // packages/ui/react-ui-form/src/components/Form/FormActions.tsx
900
- var FormActions = ({ onCancel, readonly }) => {
901
- const { t } = useTranslation4(translationKey);
902
- const { canSave, handleSave } = useFormContext();
903
- return /* @__PURE__ */ React9.createElement("div", {
904
- role: "none",
905
- className: "mt-2 flex justify-center"
906
- }, /* @__PURE__ */ React9.createElement("div", {
907
- role: "none",
908
- className: mx5(onCancel && !readonly && "grid grid-cols-2 gap-2")
909
- }, onCancel && !readonly && /* @__PURE__ */ React9.createElement(IconButton2, {
910
- "data-testid": "cancel-button",
911
- icon: "ph--x--regular",
912
- label: t("button cancel"),
913
- onClick: onCancel
914
- }), handleSave && /* @__PURE__ */ React9.createElement(IconButton2, {
915
- type: "submit",
916
- "data-testid": "save-button",
917
- disabled: !canSave,
918
- icon: "ph--check--regular",
919
- label: t("button save"),
920
- onClick: handleSave
921
- })));
1108
+ var FormActions = ({ readonly, onCancel }) => {
1109
+ var _effect = _useSignals9();
1110
+ try {
1111
+ const { t } = useTranslation5(translationKey);
1112
+ const { canSave, handleSave } = useFormContext();
1113
+ return /* @__PURE__ */ React9.createElement("div", {
1114
+ role: "none",
1115
+ className: "flex [&_button]:grow gap-1"
1116
+ }, onCancel && !readonly && /* @__PURE__ */ React9.createElement(IconButton2, {
1117
+ "data-testid": "cancel-button",
1118
+ icon: "ph--x--regular",
1119
+ label: t("button cancel"),
1120
+ onClick: onCancel
1121
+ }), handleSave && /* @__PURE__ */ React9.createElement(IconButton2, {
1122
+ type: "submit",
1123
+ "data-testid": "save-button",
1124
+ disabled: !canSave,
1125
+ icon: "ph--check--regular",
1126
+ label: t("button save"),
1127
+ onClick: handleSave
1128
+ }));
1129
+ } finally {
1130
+ _effect.f();
1131
+ }
922
1132
  };
923
1133
 
924
1134
  // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
925
- import { pipe as pipe2 } from "effect";
1135
+ import { useSignals as _useSignals12 } from "@preact-signals/safe-react/tracking";
1136
+ import { Schema, SchemaAST as SchemaAST4, pipe as pipe2 } from "effect";
926
1137
  import { capitalize as capitalize2 } from "effect/String";
927
1138
  import React12, { useMemo as useMemo5 } from "react";
928
- import { AST as AST3, S } from "@dxos/echo-schema";
929
- import { createJsonPath as createJsonPath3, findNode as findNode2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
930
- import { mx as mx7 } from "@dxos/react-ui-theme";
1139
+ import { createJsonPath as createJsonPath3, findNode as findNode3, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
1140
+ import { mx as mx6 } from "@dxos/react-ui-theme";
931
1141
  import { getSchemaProperties as getSchemaProperties2 } from "@dxos/schema";
932
1142
  import { isNotFalsy } from "@dxos/util";
933
1143
 
934
1144
  // packages/ui/react-ui-form/src/components/Form/ArrayField.tsx
935
- import { pipe } from "effect";
1145
+ import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
1146
+ import { SchemaAST as SchemaAST3, pipe } from "effect";
936
1147
  import { capitalize } from "effect/String";
937
- import React10, { useCallback as useCallback5, useMemo as useMemo4 } from "react";
938
- import { AST as AST2 } from "@dxos/echo-schema";
939
- import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
1148
+ import React10, { Fragment, useCallback as useCallback7 } from "react";
1149
+ import { findNode as findNode2, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
940
1150
  import { invariant as invariant2 } from "@dxos/invariant";
941
- import { IconButton as IconButton3, useTranslation as useTranslation5 } from "@dxos/react-ui";
942
- import { mx as mx6 } from "@dxos/react-ui-theme";
1151
+ import { IconButton as IconButton3, useTranslation as useTranslation6 } from "@dxos/react-ui";
943
1152
  import { getSchemaProperties } from "@dxos/schema";
944
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
945
- var padding = "px-2";
946
- var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
947
- const { t } = useTranslation5(translationKey);
948
- const { ast, name, type, title } = property;
949
- const values = useFormValues(path ?? []) ?? [];
950
- invariant2(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
951
- F: __dxlog_file2,
952
- L: 39,
953
- S: void 0,
954
- A: [
955
- "Array.isArray(values)",
956
- "`Values at path ${path?.join('.')} must be an array.`"
957
- ]
958
- });
959
- const label = title ?? pipe(name, capitalize);
960
- const tupleType = findNode(ast, AST2.isTupleType);
961
- const elementType = tupleType?.rest[0]?.type;
962
- const getDefaultObjectValue = (typeNode) => {
963
- const baseNode = findNode(typeNode, isDiscriminatedUnion);
964
- const typeLiteral = baseNode ? getDiscriminatedType(baseNode, {}) : findNode(typeNode, AST2.isTypeLiteral);
965
- if (!typeLiteral) {
966
- return {};
967
- }
968
- return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [
969
- prop.name,
970
- prop.defaultValue
971
- ]));
972
- };
973
- const newValue = useMemo4(() => {
974
- if (type === "object" && elementType) {
975
- return getDefaultObjectValue(elementType);
976
- } else {
977
- return SimpleType.getDefaultValue(type);
978
- }
979
- }, [
980
- type,
981
- elementType
982
- ]);
983
- const handleAdd = useCallback5(() => {
984
- inputProps.onValueChange(type, [
985
- ...values,
986
- newValue
987
- ]);
988
- }, [
989
- type,
990
- elementType,
991
- inputProps,
992
- newValue,
993
- values
994
- ]);
995
- const handleRemove = useCallback5((index) => {
996
- const newValues = values.filter((_, i) => i !== index);
997
- inputProps.onValueChange(type, newValues);
998
- }, [
999
- type,
1000
- inputProps,
1001
- values
1002
- ]);
1003
- if (!elementType) {
1004
- return null;
1005
- }
1006
- return /* @__PURE__ */ React10.createElement("div", {
1007
- role: "none",
1008
- className: mx6(padding)
1009
- }, /* @__PURE__ */ React10.createElement(InputHeader, null, label), /* @__PURE__ */ React10.createElement("div", {
1010
- role: "none",
1011
- className: "flex flex-col gap-1"
1012
- }, values.map((_value, index) => /* @__PURE__ */ React10.createElement("div", {
1013
- key: index,
1014
- role: "none",
1015
- className: "flex items-center gap-1"
1016
- }, /* @__PURE__ */ React10.createElement("div", {
1017
- role: "none",
1018
- className: "flex-1"
1019
- }, /* @__PURE__ */ React10.createElement(FormField, {
1020
- property: {
1021
- ...property,
1022
- array: false,
1023
- ast: elementType
1024
- },
1025
- path: [
1026
- ...path ?? [],
1027
- index
1028
- ],
1029
- readonly,
1030
- inline: true,
1031
- Custom,
1032
- lookupComponent
1033
- })), /* @__PURE__ */ React10.createElement(IconButton3, {
1034
- icon: "ph--trash--regular",
1035
- iconOnly: true,
1036
- label: t("button remove"),
1037
- onClick: () => handleRemove(index)
1038
- })))), /* @__PURE__ */ React10.createElement("div", {
1039
- role: "none",
1040
- className: "flex justify-between items-center plb-1"
1041
- }, /* @__PURE__ */ React10.createElement(IconButton3, {
1042
- icon: "ph--plus--regular",
1043
- iconOnly: true,
1044
- label: t("button add"),
1045
- onClick: handleAdd
1046
- })));
1047
- };
1048
1153
 
1049
- // packages/ui/react-ui-form/src/components/Form/RefField.tsx
1050
- import React11, { useEffect as useEffect6, useState as useState4 } from "react";
1051
- import { Expando, getTypeAnnotation, ReferenceAnnotationId } from "@dxos/echo-schema";
1052
- import { findAnnotation } from "@dxos/effect";
1053
- import { DXN } from "@dxos/keys";
1054
- import { refFromDXN, RefImpl } from "@dxos/live-object";
1055
- import { log as log2 } from "@dxos/log";
1056
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/RefField.tsx";
1057
- var RefField = ({ ast, type, label, readonly, placeholder, inline, onQueryRefOptions, inputProps }) => {
1058
- const { getValue: getValue3, onValueChange, ...restInputProps } = inputProps;
1059
- const refTypeInfo = findAnnotation(ast, ReferenceAnnotationId);
1060
- const [refOptions, setRefOptions] = useState4([]);
1061
- const [loading, setLoading] = useState4(false);
1062
- useEffect6(() => {
1063
- if (!refTypeInfo || !onQueryRefOptions) {
1064
- return;
1065
- }
1066
- const fetchOptions = async () => {
1067
- setLoading(true);
1068
- try {
1069
- const options = await onQueryRefOptions(refTypeInfo);
1070
- setRefOptions(options.map((option) => ({
1071
- label: option.label,
1072
- value: option.dxn.toString()
1073
- })));
1074
- } catch (error) {
1075
- log2.error("Failed to fetch ref options:", error, {
1076
- F: __dxlog_file3,
1077
- L: 68,
1078
- S: void 0,
1079
- C: (f, a) => f(...a)
1080
- });
1081
- setRefOptions([]);
1082
- } finally {
1083
- setLoading(false);
1084
- }
1085
- };
1086
- void fetchOptions();
1087
- }, [
1088
- refTypeInfo,
1089
- onQueryRefOptions
1090
- ]);
1091
- if (!refTypeInfo) {
1092
- return null;
1154
+ // packages/ui/react-ui-form/src/util/field.ts
1155
+ import { FormatEnum, GeoLocation as GeoLocation2, TypeEnum } from "@dxos/echo-schema";
1156
+ var parseValue = ({ type, format, value }) => {
1157
+ if (value === void 0 || value === null || value === "") {
1158
+ return void 0;
1093
1159
  }
1094
- if (refTypeInfo.typename === getTypeAnnotation(Expando)?.typename || !onQueryRefOptions) {
1095
- const handleOnValueChange = (_type, dxnString) => {
1096
- const dxn = DXN.tryParse(dxnString);
1097
- if (dxn) {
1098
- onValueChange?.("object", refFromDXN(dxn));
1099
- } else if (dxnString === "") {
1100
- onValueChange?.("object", void 0);
1101
- } else {
1102
- onValueChange?.("string", dxnString);
1160
+ const parseScalar = (type2) => {
1161
+ switch (type2) {
1162
+ case TypeEnum.Boolean: {
1163
+ if (typeof value === "string") {
1164
+ const lowercaseValue = value.toLowerCase();
1165
+ if (lowercaseValue === "0" || lowercaseValue === "false") {
1166
+ return false;
1167
+ } else if (lowercaseValue === "1" || lowercaseValue === "true") {
1168
+ return true;
1169
+ }
1170
+ }
1171
+ return Boolean(value);
1103
1172
  }
1104
- };
1105
- const handleGetValue2 = () => {
1106
- const formValue = getValue3();
1107
- if (typeof formValue === "string") {
1108
- return formValue;
1173
+ case TypeEnum.Number: {
1174
+ const cleaned = typeof value === "string" ? value.replace(/[^0-9.-]+/g, "") : value;
1175
+ const num = Number(cleaned);
1176
+ return Number.isNaN(num) ? null : num;
1109
1177
  }
1110
- if (formValue instanceof RefImpl) {
1111
- return formValue.dxn.toString();
1112
- }
1113
- return void 0;
1114
- };
1115
- return /* @__PURE__ */ React11.createElement(TextInput, {
1116
- type,
1117
- label,
1118
- disabled: readonly,
1119
- placeholder,
1120
- inputOnly: inline,
1121
- getValue: handleGetValue2,
1122
- onValueChange: handleOnValueChange,
1123
- ...restInputProps
1124
- });
1125
- }
1126
- const handleGetValue = () => {
1127
- const formValue = getValue3();
1128
- if (formValue instanceof RefImpl) {
1129
- return formValue.dxn.toString();
1130
- }
1131
- return void 0;
1132
- };
1133
- const handleValueChanged = (_type, dxnString) => {
1134
- const dxn = DXN.parse(dxnString);
1135
- const ref = refFromDXN(dxn);
1136
- onValueChange("object", ref);
1137
- };
1138
- return /* @__PURE__ */ React11.createElement(SelectInput, {
1139
- type,
1140
- label,
1141
- disabled: readonly || loading,
1142
- placeholder: loading ? "Loading options..." : placeholder,
1143
- inputOnly: inline,
1144
- getValue: handleGetValue,
1145
- onValueChange: handleValueChanged,
1146
- options: refOptions,
1147
- ...restInputProps
1148
- });
1149
- };
1150
-
1151
- // packages/ui/react-ui-form/src/components/Form/factory.tsx
1152
- import { FormatEnum } from "@dxos/echo-schema";
1153
- var getInputComponent = (type, format) => {
1154
- switch (format) {
1155
- case FormatEnum.GeoPoint:
1156
- return GeoPointInput;
1157
- case FormatEnum.Markdown:
1158
- return MarkdownInput;
1159
- }
1160
- switch (type) {
1161
- case "string":
1162
- return TextInput;
1163
- case "number":
1164
- return NumberInput;
1165
- case "boolean":
1166
- return BooleanInput;
1167
- }
1168
- };
1169
-
1170
- // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
1171
- var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupComponent, Custom }) => {
1172
- const inputProps = useInputProps(path);
1173
- const { ast, name, type, format, title, description, options, examples, array } = property;
1174
- const label = useMemo5(() => title ?? pipe2(name, capitalize2), [
1175
- title,
1176
- name
1177
- ]);
1178
- const placeholder = useMemo5(() => examples?.length ? `Example: "${examples[0]}"` : description, [
1179
- examples,
1180
- description
1181
- ]);
1182
- const FoundComponent = lookupComponent?.({
1183
- prop: name,
1184
- schema: S.make(ast),
1185
- inputProps: {
1186
- type,
1187
- format,
1188
- label,
1189
- disabled: readonly,
1190
- placeholder,
1191
- ...inputProps
1192
- }
1193
- });
1194
- if (FoundComponent) {
1195
- return /* @__PURE__ */ React12.createElement("div", {
1196
- role: "none"
1197
- }, FoundComponent);
1198
- }
1199
- const jsonPath = createJsonPath3(path ?? []);
1200
- const CustomComponent = Custom?.[jsonPath];
1201
- if (CustomComponent) {
1202
- return /* @__PURE__ */ React12.createElement(CustomComponent, {
1203
- type,
1204
- format,
1205
- label,
1206
- inputOnly: inline,
1207
- placeholder,
1208
- disabled: readonly,
1209
- ...inputProps
1210
- });
1211
- }
1212
- if (array) {
1213
- return /* @__PURE__ */ React12.createElement(ArrayField, {
1214
- property,
1215
- path,
1216
- inputProps,
1217
- readonly,
1218
- Custom
1219
- });
1220
- }
1221
- const InputComponent = getInputComponent(type, format);
1222
- if (InputComponent) {
1223
- return /* @__PURE__ */ React12.createElement("div", {
1224
- role: "none"
1225
- }, /* @__PURE__ */ React12.createElement(InputComponent, {
1226
- type,
1227
- format,
1228
- label,
1229
- inputOnly: inline,
1230
- placeholder,
1231
- disabled: readonly,
1232
- ...inputProps
1233
- }));
1234
- }
1235
- if (options) {
1236
- return /* @__PURE__ */ React12.createElement("div", {
1237
- role: "none"
1238
- }, /* @__PURE__ */ React12.createElement(SelectInput, {
1239
- type,
1240
- format,
1241
- disabled: readonly,
1242
- inputOnly: inline,
1243
- label,
1244
- options: options.map((option) => ({
1245
- value: option,
1246
- label: String(option)
1247
- })),
1248
- placeholder,
1249
- ...inputProps
1250
- }));
1251
- }
1252
- if (format === "ref") {
1253
- return /* @__PURE__ */ React12.createElement(RefField, {
1254
- ast,
1255
- type,
1256
- label,
1257
- readonly,
1258
- placeholder,
1259
- inline,
1260
- onQueryRefOptions,
1261
- inputProps
1262
- });
1263
- }
1264
- if (type === "object") {
1265
- const baseNode = findNode2(ast, isDiscriminatedUnion2);
1266
- const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode2(ast, AST3.isTypeLiteral);
1267
- if (typeLiteral) {
1268
- return /* @__PURE__ */ React12.createElement("div", {
1269
- role: "none"
1270
- }, !inline && /* @__PURE__ */ React12.createElement("h3", {
1271
- className: "text-lg mbs-2 mbe-1"
1272
- }, label), /* @__PURE__ */ React12.createElement(FormFields, {
1273
- schema: S.make(typeLiteral),
1274
- path,
1275
- readonly,
1276
- onQueryRefOptions,
1277
- Custom,
1278
- lookupComponent
1279
- }));
1280
- }
1281
- }
1282
- return null;
1283
- };
1284
- var FormFields = ({ schema, path, filter, sort, readonly, onQueryRefOptions, lookupComponent, Custom }) => {
1285
- const values = useFormValues(path);
1286
- const properties = useMemo5(() => {
1287
- const props = getSchemaProperties2(schema.ast, values);
1288
- const filtered = filter ? filter(props) : props;
1289
- return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
1290
- }, [
1291
- schema,
1292
- values,
1293
- filter,
1294
- sort
1295
- ]);
1296
- return /* @__PURE__ */ React12.createElement("div", {
1297
- role: "form",
1298
- className: mx7("flex flex-col w-full gap-2")
1299
- }, properties.map((property) => {
1300
- return /* @__PURE__ */ React12.createElement(FormField, {
1301
- key: property.name,
1302
- property,
1303
- path: [
1304
- ...path ?? [],
1305
- property.name
1306
- ],
1307
- readonly,
1308
- onQueryRefOptions,
1309
- lookupComponent,
1310
- Custom
1311
- });
1312
- }).filter(isNotFalsy));
1313
- };
1314
-
1315
- // packages/ui/react-ui-form/src/components/Form/Form.tsx
1316
- var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, onQueryRefOptions, lookupComponent, Custom }) => {
1317
- const formRef = useRef3(null);
1318
- const onValid = useMemo6(() => autoSave ? onSave : void 0, [
1319
- autoSave,
1320
- onSave
1321
- ]);
1322
- useEffect7(() => {
1323
- if (autoFocus && formRef.current) {
1324
- const input = formRef.current.querySelector("input");
1325
- if (input) {
1326
- input.focus();
1327
- }
1328
- }
1329
- }, [
1330
- autoFocus
1331
- ]);
1332
- return /* @__PURE__ */ React13.createElement(FormProvider, {
1333
- formRef,
1334
- schema,
1335
- autoSave,
1336
- initialValues,
1337
- onValuesChanged,
1338
- onValidate,
1339
- onValid,
1340
- onSave
1341
- }, /* @__PURE__ */ React13.createElement("div", {
1342
- ref: formRef,
1343
- role: "none",
1344
- className: mx8("p-2", classNames),
1345
- "data-testid": testId
1346
- }, /* @__PURE__ */ React13.createElement(FormFields, {
1347
- schema,
1348
- path,
1349
- readonly,
1350
- filter,
1351
- sort,
1352
- onQueryRefOptions,
1353
- lookupComponent,
1354
- Custom
1355
- }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React13.createElement(FormActions, {
1356
- onCancel,
1357
- readonly
1358
- })));
1359
- };
1360
-
1361
- // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
1362
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
1363
- var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1364
- const { t } = useTranslation6(translationKey);
1365
- const [props, setProps] = useState5(projection.getFieldProjection(field.id).props);
1366
- useEffect8(() => setProps(projection.getFieldProjection(field.id).props), [
1367
- field,
1368
- projection
1369
- ]);
1370
- const [schemas, setSchemas] = useState5([]);
1371
- useEffect8(() => {
1372
- if (!registry) {
1373
- return;
1374
- }
1375
- const subscription = registry.query().subscribe((query) => setSchemas(query.results), {
1376
- fire: true
1377
- });
1378
- const t2 = setTimeout(async () => {
1379
- const schemas2 = await registry.query().run();
1380
- setSchemas(schemas2);
1381
- });
1382
- return () => {
1383
- clearTimeout(t2);
1384
- subscription?.();
1385
- };
1386
- }, [
1387
- registry
1388
- ]);
1389
- const [referenceSchema, setReferenceSchema] = useState5();
1390
- useEffect8(() => {
1391
- setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
1392
- }, [
1393
- schemas,
1394
- props?.referenceSchema
1395
- ]);
1396
- const [{ fieldSchema }, setFieldSchema] = useState5({
1397
- fieldSchema: getFormatSchema(props?.format)
1398
- });
1399
- const handleValuesChanged = useCallback6((_props) => {
1400
- setFieldSchema((prev) => {
1401
- const fieldSchema2 = getFormatSchema(_props.format);
1402
- if (prev.fieldSchema === fieldSchema2) {
1403
- return prev;
1404
- }
1405
- return {
1406
- fieldSchema: fieldSchema2
1407
- };
1408
- });
1409
- setReferenceSchema((prev) => {
1410
- if (_props.referenceSchema !== prev?.typename) {
1411
- const newSchema = schemas.find((schema) => schema.typename === _props.referenceSchema);
1412
- if (newSchema) {
1413
- return newSchema;
1414
- }
1415
- }
1416
- return prev;
1417
- });
1418
- setProps((props2) => {
1419
- const type = formatToType[_props.format];
1420
- if (props2.type !== type) {
1421
- return {
1422
- ...props2,
1423
- ..._props,
1424
- type
1425
- };
1426
- }
1427
- return _props;
1428
- });
1429
- }, [
1430
- schemas,
1431
- props.format,
1432
- props.referenceSchema
1433
- ]);
1434
- const handleValidate = useCallback6(({ property }) => {
1435
- if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
1436
- return [
1437
- {
1438
- path: "property",
1439
- message: `property is not unique: '${property}'`
1440
- }
1441
- ];
1442
- }
1443
- }, [
1444
- view.fields,
1445
- field
1446
- ]);
1447
- const handleSave = useCallback6((props2) => {
1448
- projection.setFieldProjection({
1449
- field,
1450
- props: props2
1451
- });
1452
- onSave();
1453
- }, [
1454
- projection,
1455
- field,
1456
- onSave
1457
- ]);
1458
- const handleCancel = useCallback6(() => {
1459
- requestAnimationFrame(() => onCancel?.());
1460
- onSave();
1461
- }, [
1462
- onSave
1463
- ]);
1464
- const Custom = useMemo7(() => ({
1465
- ["format"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
1466
- ...props2,
1467
- options: FormatEnums.filter((value) => value !== FormatEnum2.None).map((value) => ({
1468
- value,
1469
- label: t(`format ${value}`)
1470
- }))
1471
- }),
1472
- ["referenceSchema"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
1473
- ...props2,
1474
- options: schemas.map((schema) => ({
1475
- value: schema.typename
1476
- }))
1477
- }),
1478
- ["referencePath"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
1479
- ...props2,
1480
- options: referenceSchema ? getSchemaProperties3(referenceSchema.ast).sort(sortProperties).map((p) => ({
1481
- value: p.name
1482
- })) : []
1483
- }),
1484
- ["options"]: (props2) => /* @__PURE__ */ React14.createElement(SelectOptionInput, props2)
1485
- }), [
1486
- t,
1487
- schemas,
1488
- referenceSchema
1489
- ]);
1490
- const propIsNotType = useCallback6((props2) => props2.filter((p) => p.name !== "type"), []);
1491
- if (!fieldSchema) {
1492
- log3.warn("invalid format", {
1493
- props
1494
- }, {
1495
- F: __dxlog_file4,
1496
- L: 174,
1497
- S: void 0,
1498
- C: (f, a) => f(...a)
1499
- });
1500
- return null;
1501
- }
1502
- return /* @__PURE__ */ React14.createElement(Form, {
1503
- key: field.id,
1504
- autoFocus: true,
1505
- values: props,
1506
- schema: fieldSchema,
1507
- filter: propIsNotType,
1508
- sort: [
1509
- "property",
1510
- "format"
1511
- ],
1512
- onValuesChanged: handleValuesChanged,
1513
- onValidate: handleValidate,
1514
- onSave: handleSave,
1515
- onCancel: handleCancel,
1516
- Custom
1517
- });
1518
- };
1519
-
1520
- // packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
1521
- import React15, { useCallback as useCallback7, useMemo as useMemo8, useState as useState6 } from "react";
1522
- import { AST as AST4, Format, S as S2 } from "@dxos/echo-schema";
1523
- import { invariant as invariant3 } from "@dxos/invariant";
1524
- import { IconButton as IconButton4, useTranslation as useTranslation7 } from "@dxos/react-ui";
1525
- import { List as List2 } from "@dxos/react-ui-list";
1526
- import { ghostHover, inputTextLabel, mx as mx9 } from "@dxos/react-ui-theme";
1527
- import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
1528
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
1529
- var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
1530
- var ViewMetaSchema = S2.Struct({
1531
- name: S2.String.annotations({
1532
- [AST4.TitleAnnotationId]: "View"
1533
- }),
1534
- typename: Format.URL.annotations({
1535
- [AST4.TitleAnnotationId]: "Typename"
1536
- })
1537
- }).pipe(S2.mutable);
1538
- var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
1539
- const { t } = useTranslation7(translationKey);
1540
- const projection = useMemo8(() => new ViewProjection(schema.jsonSchema, view), [
1541
- schema,
1542
- view
1543
- ]);
1544
- const [field, setField] = useState6();
1545
- const viewValues = useMemo8(() => {
1546
- return {
1547
- name: view.name,
1548
- // TODO(burdon): Need to warn user of possible consequences of editing.
1549
- // TODO(burdon): Settings should have domain name owned by user.
1550
- typename: view.query.typename
1551
- };
1552
- }, [
1553
- view
1554
- ]);
1555
- const handleSelect = useCallback7((field2) => {
1556
- setField((f) => f === field2 ? void 0 : field2);
1557
- }, []);
1558
- const handleAdd = useCallback7(() => {
1559
- invariant3(!schema.readonly, void 0, {
1560
- F: __dxlog_file5,
1561
- L: 76,
1562
- S: void 0,
1563
- A: [
1564
- "!schema.readonly",
1565
- ""
1566
- ]
1567
- });
1568
- const field2 = projection.createFieldProjection();
1569
- setField(field2);
1570
- }, [
1571
- schema,
1572
- view
1573
- ]);
1574
- const handleUpdate = useCallback7(({ name, typename }) => {
1575
- invariant3(!schema.readonly, void 0, {
1576
- F: __dxlog_file5,
1577
- L: 83,
1578
- S: void 0,
1579
- A: [
1580
- "!schema.readonly",
1581
- ""
1582
- ]
1583
- });
1584
- requestAnimationFrame(() => {
1585
- if (view.name !== name) {
1586
- view.name = name;
1587
- }
1588
- if (view.query.typename !== typename) {
1589
- onTypenameChanged?.(typename);
1590
- }
1591
- });
1592
- }, [
1593
- schema,
1594
- view,
1595
- onTypenameChanged
1596
- ]);
1597
- const handleDelete = useCallback7((fieldId) => {
1598
- invariant3(!schema.readonly, void 0, {
1599
- F: __dxlog_file5,
1600
- L: 99,
1601
- S: void 0,
1602
- A: [
1603
- "!schema.readonly",
1604
- ""
1605
- ]
1606
- });
1607
- if (fieldId === field?.id) {
1608
- setField(void 0);
1609
- }
1610
- onDelete?.(fieldId);
1611
- }, [
1612
- schema,
1613
- field,
1614
- onDelete
1615
- ]);
1616
- const handleMove = useCallback7((fromIndex, toIndex) => {
1617
- invariant3(!schema.readonly, void 0, {
1618
- F: __dxlog_file5,
1619
- L: 111,
1620
- S: void 0,
1621
- A: [
1622
- "!schema.readonly",
1623
- ""
1624
- ]
1625
- });
1626
- const fields = [
1627
- ...view.fields
1628
- ];
1629
- const [moved] = fields.splice(fromIndex, 1);
1630
- fields.splice(toIndex, 0, moved);
1631
- view.fields = fields;
1632
- }, [
1633
- schema,
1634
- view.fields
1635
- ]);
1636
- const handleClose = useCallback7(() => setField(void 0), []);
1637
- const hiddenProperties = projection.getHiddenProperties();
1638
- const handleHide = useCallback7((fieldId) => {
1639
- setField(void 0);
1640
- projection.hideFieldProjection(fieldId);
1641
- }, [
1642
- projection
1643
- ]);
1644
- const handleShow = useCallback7((property) => {
1645
- setField(void 0);
1646
- projection.showFieldProjection(property);
1647
- }, [
1648
- projection
1649
- ]);
1650
- return /* @__PURE__ */ React15.createElement("div", {
1651
- role: "none",
1652
- className: mx9("flex flex-col w-full divide-y divide-separator", classNames)
1653
- }, /* @__PURE__ */ React15.createElement(Form, {
1654
- autoSave: true,
1655
- schema: ViewMetaSchema,
1656
- values: viewValues,
1657
- onSave: schema.readonly ? void 0 : handleUpdate
1658
- }), /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("div", {
1659
- role: "none",
1660
- className: "p-2"
1661
- }, /* @__PURE__ */ React15.createElement("label", {
1662
- className: mx9(inputTextLabel)
1663
- }, t("fields label"))), /* @__PURE__ */ React15.createElement(List2.Root, {
1664
- items: view.fields,
1665
- isItem: S2.is(FieldSchema),
1666
- getId: (field2) => field2.id,
1667
- onMove: schema.readonly ? void 0 : handleMove
1668
- }, ({ items: fields }) => /* @__PURE__ */ React15.createElement(React15.Fragment, null, showHeading && /* @__PURE__ */ React15.createElement("div", {
1669
- role: "heading",
1670
- className: grid
1671
- }, /* @__PURE__ */ React15.createElement("div", null), /* @__PURE__ */ React15.createElement("div", {
1672
- className: "flex items-center text-sm"
1673
- }, t("field path label"))), /* @__PURE__ */ React15.createElement("div", {
1674
- role: "list",
1675
- className: "flex flex-col w-full"
1676
- }, fields?.map((field2) => /* @__PURE__ */ React15.createElement(List2.Item, {
1677
- key: field2.id,
1678
- item: field2,
1679
- classNames: mx9(grid, ghostHover, "cursor-pointer")
1680
- }, /* @__PURE__ */ React15.createElement(List2.ItemDragHandle, null), /* @__PURE__ */ React15.createElement(List2.ItemTitle, {
1681
- onClick: () => handleSelect(field2)
1682
- }, field2.path), /* @__PURE__ */ React15.createElement("div", {
1683
- className: "flex items-center gap-2 -ml-4"
1684
- }, /* @__PURE__ */ React15.createElement(List2.ItemButton, {
1685
- icon: "ph--eye-slash--regular",
1686
- disabled: view.fields.length <= 1,
1687
- onClick: () => handleHide(field2.id)
1688
- }), !schema.readonly && /* @__PURE__ */ React15.createElement(List2.ItemDeleteButton, {
1689
- icon: "ph--trash--regular",
1690
- disabled: view.fields.length <= 1,
1691
- onClick: () => handleDelete(field2.id)
1692
- }))))))), hiddenProperties.length > 0 && /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("div", {
1693
- role: "none",
1694
- className: "p-2"
1695
- }, /* @__PURE__ */ React15.createElement("label", {
1696
- className: mx9(inputTextLabel)
1697
- }, t("hidden fields label"))), /* @__PURE__ */ React15.createElement(List2.Root, {
1698
- items: hiddenProperties,
1699
- isItem: (item) => typeof item === "string",
1700
- getId: (property) => property
1701
- }, ({ items: properties }) => /* @__PURE__ */ React15.createElement("div", {
1702
- role: "list",
1703
- className: "flex flex-col w-full"
1704
- }, properties?.map((property) => /* @__PURE__ */ React15.createElement(List2.Item, {
1705
- key: property,
1706
- item: property,
1707
- classNames: mx9(grid, ghostHover, "cursor-pointer")
1708
- }, /* @__PURE__ */ React15.createElement("div", null), /* @__PURE__ */ React15.createElement(List2.ItemTitle, null, property), /* @__PURE__ */ React15.createElement(List2.ItemButton, {
1709
- icon: "ph--eye--regular",
1710
- onClick: () => handleShow(property)
1711
- }))))))), field && /* @__PURE__ */ React15.createElement(FieldEditor, {
1712
- key: field.id,
1713
- view,
1714
- projection,
1715
- field,
1716
- registry,
1717
- onSave: handleClose
1718
- }), !readonly && !field && /* @__PURE__ */ React15.createElement("div", {
1719
- className: "flex p-2 justify-center"
1720
- }, /* @__PURE__ */ React15.createElement(IconButton4, {
1721
- icon: "ph--plus--regular",
1722
- label: t("button add property"),
1723
- onClick: schema.readonly ? void 0 : handleAdd,
1724
- // TODO(burdon): Show field limit in ux (not tooltip).
1725
- disabled: view.fields.length >= VIEW_FIELD_LIMIT
1726
- })));
1727
- };
1728
-
1729
- // packages/ui/react-ui-form/src/util/field.ts
1730
- import { FormatEnum as FormatEnum3, GeoLocation as GeoLocation2, TypeEnum } from "@dxos/echo-schema";
1731
- var parseValue = ({ type, format, value }) => {
1732
- if (value === void 0 || value === null || value === "") {
1733
- return void 0;
1734
- }
1735
- const parseScalar = (type2) => {
1736
- switch (type2) {
1737
- case TypeEnum.Boolean: {
1738
- if (typeof value === "string") {
1739
- const lowercaseValue = value.toLowerCase();
1740
- if (lowercaseValue === "0" || lowercaseValue === "false") {
1741
- return false;
1742
- } else if (lowercaseValue === "1" || lowercaseValue === "true") {
1743
- return true;
1744
- }
1745
- }
1746
- return Boolean(value);
1747
- }
1748
- case TypeEnum.Number: {
1749
- const cleaned = typeof value === "string" ? value.replace(/[^0-9.-]+/g, "") : value;
1750
- const num = Number(cleaned);
1751
- return Number.isNaN(num) ? null : num;
1752
- }
1753
- case TypeEnum.String:
1754
- case TypeEnum.Ref:
1755
- return String(value);
1756
- default: {
1757
- return value;
1178
+ case TypeEnum.String:
1179
+ case TypeEnum.Ref:
1180
+ return String(value);
1181
+ default: {
1182
+ return value;
1758
1183
  }
1759
1184
  }
1760
1185
  };
@@ -1762,26 +1187,26 @@ var parseValue = ({ type, format, value }) => {
1762
1187
  return parseScalar(type);
1763
1188
  }
1764
1189
  switch (format) {
1765
- case FormatEnum3.Boolean:
1190
+ case FormatEnum.Boolean:
1766
1191
  return parseScalar(TypeEnum.Boolean);
1767
- case FormatEnum3.Number:
1768
- case FormatEnum3.Percent:
1769
- case FormatEnum3.Currency:
1192
+ case FormatEnum.Number:
1193
+ case FormatEnum.Percent:
1194
+ case FormatEnum.Currency:
1770
1195
  return parseScalar(TypeEnum.Number);
1771
- case FormatEnum3.String:
1772
- case FormatEnum3.Markdown: {
1196
+ case FormatEnum.String:
1197
+ case FormatEnum.Markdown: {
1773
1198
  return parseScalar(TypeEnum.String);
1774
1199
  }
1775
- case FormatEnum3.Ref:
1776
- throw new Error(`unexpected format: ${FormatEnum3.Ref}`);
1777
- case FormatEnum3.DateTime:
1778
- case FormatEnum3.Date:
1779
- case FormatEnum3.Time:
1780
- case FormatEnum3.Timestamp: {
1200
+ case FormatEnum.Ref:
1201
+ throw new Error(`unexpected format: ${FormatEnum.Ref}`);
1202
+ case FormatEnum.DateTime:
1203
+ case FormatEnum.Date:
1204
+ case FormatEnum.Time:
1205
+ case FormatEnum.Timestamp: {
1781
1206
  const date = new Date(value);
1782
1207
  return isNaN(date.getTime()) ? null : date;
1783
1208
  }
1784
- case FormatEnum3.GeoPoint: {
1209
+ case FormatEnum.GeoPoint: {
1785
1210
  if (typeof value === "string") {
1786
1211
  const cleaned = value.replace(/[^0-9.,-]+/g, "");
1787
1212
  const parts = cleaned.split(",");
@@ -1829,23 +1254,23 @@ var cellClassesForFieldType = ({ type, format }) => {
1829
1254
  }
1830
1255
  }
1831
1256
  switch (format) {
1832
- case FormatEnum3.Markdown:
1257
+ case FormatEnum.Markdown:
1833
1258
  return void 0;
1834
- case FormatEnum3.Time:
1835
- case FormatEnum3.Timestamp:
1836
- case FormatEnum3.DateTime:
1837
- case FormatEnum3.Date:
1838
- case FormatEnum3.Duration:
1259
+ case FormatEnum.Time:
1260
+ case FormatEnum.Timestamp:
1261
+ case FormatEnum.DateTime:
1262
+ case FormatEnum.Date:
1263
+ case FormatEnum.Duration:
1839
1264
  return [
1840
1265
  "font-mono",
1841
1266
  "text-right"
1842
1267
  ];
1843
- case FormatEnum3.Currency:
1268
+ case FormatEnum.Currency:
1844
1269
  return [
1845
1270
  "text-right"
1846
1271
  ];
1847
- case FormatEnum3.JSON:
1848
- case FormatEnum3.DID:
1272
+ case FormatEnum.JSON:
1273
+ case FormatEnum.DID:
1849
1274
  return [
1850
1275
  "font-mono"
1851
1276
  ];
@@ -1860,7 +1285,7 @@ var pathNotUniqueError = (path) => ({
1860
1285
 
1861
1286
  // packages/ui/react-ui-form/src/util/formatting.ts
1862
1287
  import { format as formatDate } from "date-fns/format";
1863
- import { FormatEnum as FormatEnum4, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
1288
+ import { FormatEnum as FormatEnum2, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
1864
1289
  var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1865
1290
  const formatScalar = (type2) => {
1866
1291
  switch (type2) {
@@ -1880,20 +1305,20 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1880
1305
  return formatScalar(type);
1881
1306
  }
1882
1307
  switch (format) {
1883
- case FormatEnum4.Boolean: {
1308
+ case FormatEnum2.Boolean: {
1884
1309
  return formatScalar(TypeEnum2.Boolean);
1885
1310
  }
1886
- case FormatEnum4.Number: {
1311
+ case FormatEnum2.Number: {
1887
1312
  return formatScalar(TypeEnum2.Number);
1888
1313
  }
1889
- case FormatEnum4.String:
1890
- case FormatEnum4.Ref: {
1314
+ case FormatEnum2.String:
1315
+ case FormatEnum2.Ref: {
1891
1316
  return formatScalar(TypeEnum2.String);
1892
1317
  }
1893
- case FormatEnum4.Percent: {
1318
+ case FormatEnum2.Percent: {
1894
1319
  return `${value * 100}%`;
1895
1320
  }
1896
- case FormatEnum4.Currency: {
1321
+ case FormatEnum2.Currency: {
1897
1322
  return value.toLocaleString(locale, {
1898
1323
  style: "currency",
1899
1324
  currency: "USD",
@@ -1901,28 +1326,28 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1901
1326
  maximumFractionDigits: 2
1902
1327
  });
1903
1328
  }
1904
- case FormatEnum4.Date: {
1329
+ case FormatEnum2.Date: {
1905
1330
  try {
1906
1331
  return formatDate(new Date(value), "yyyy-MM-dd");
1907
1332
  } catch (error) {
1908
1333
  return "Invalid Date";
1909
1334
  }
1910
1335
  }
1911
- case FormatEnum4.Time: {
1336
+ case FormatEnum2.Time: {
1912
1337
  try {
1913
1338
  return formatDate(new Date(value), "HH:mm:ss");
1914
1339
  } catch (error) {
1915
1340
  return "Invalid Time";
1916
1341
  }
1917
1342
  }
1918
- case FormatEnum4.DateTime: {
1343
+ case FormatEnum2.DateTime: {
1919
1344
  try {
1920
1345
  return formatDate(new Date(value), "yyyy-MM-dd HH:mm:ss");
1921
1346
  } catch (error) {
1922
1347
  return "Invalid DateTime";
1923
1348
  }
1924
1349
  }
1925
- case FormatEnum4.GeoPoint: {
1350
+ case FormatEnum2.GeoPoint: {
1926
1351
  if (value === null || value === void 0) {
1927
1352
  return "";
1928
1353
  }
@@ -1956,31 +1381,31 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1956
1381
  return formatScalar(type);
1957
1382
  }
1958
1383
  switch (format) {
1959
- case FormatEnum4.Boolean:
1960
- case FormatEnum4.Number:
1961
- case FormatEnum4.String:
1962
- case FormatEnum4.Ref: {
1384
+ case FormatEnum2.Boolean:
1385
+ case FormatEnum2.Number:
1386
+ case FormatEnum2.String:
1387
+ case FormatEnum2.Ref: {
1963
1388
  return formatScalar(type);
1964
1389
  }
1965
- case FormatEnum4.Percent: {
1390
+ case FormatEnum2.Percent: {
1966
1391
  return String(value * 100);
1967
1392
  }
1968
- case FormatEnum4.Currency: {
1393
+ case FormatEnum2.Currency: {
1969
1394
  return String(value);
1970
1395
  }
1971
- case FormatEnum4.DateTime: {
1396
+ case FormatEnum2.DateTime: {
1972
1397
  const date = new Date(value);
1973
1398
  return date.toISOString();
1974
1399
  }
1975
- case FormatEnum4.Date: {
1400
+ case FormatEnum2.Date: {
1976
1401
  const date = new Date(value);
1977
1402
  return date.toISOString().split("T")[0];
1978
1403
  }
1979
- case FormatEnum4.Time: {
1404
+ case FormatEnum2.Time: {
1980
1405
  const date = new Date(value);
1981
1406
  return date.toISOString().split("T")[1].split(".")[0];
1982
1407
  }
1983
- case FormatEnum4.GeoPoint: {
1408
+ case FormatEnum2.GeoPoint: {
1984
1409
  if (value === null || value === void 0) {
1985
1410
  return "";
1986
1411
  }
@@ -1995,6 +1420,935 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1995
1420
  }
1996
1421
  }
1997
1422
  };
1423
+
1424
+ // packages/ui/react-ui-form/src/util/refs.ts
1425
+ import { FormatEnum as FormatEnum3, ReferenceAnnotationId } from "@dxos/echo-schema";
1426
+ import { findAnnotation } from "@dxos/effect";
1427
+
1428
+ // packages/ui/react-ui-form/src/util/schema.ts
1429
+ import { SchemaAST as SchemaAST2 } from "effect";
1430
+ import { findNode } from "@dxos/effect";
1431
+ var findArrayElementType = (ast) => {
1432
+ const tupleType = findNode(ast, SchemaAST2.isTupleType);
1433
+ const elementType = tupleType?.rest[0]?.type;
1434
+ return elementType;
1435
+ };
1436
+
1437
+ // packages/ui/react-ui-form/src/util/refs.ts
1438
+ var getRefProps = (property) => {
1439
+ const { ast, format, array } = property;
1440
+ if (format === FormatEnum3.Ref) {
1441
+ return {
1442
+ ast,
1443
+ isArray: false
1444
+ };
1445
+ }
1446
+ if (array) {
1447
+ const elementType = findArrayElementType(ast);
1448
+ if (elementType) {
1449
+ const annotation = findAnnotation(elementType, ReferenceAnnotationId);
1450
+ if (annotation) {
1451
+ return {
1452
+ ast: elementType,
1453
+ isArray: true
1454
+ };
1455
+ }
1456
+ }
1457
+ }
1458
+ return void 0;
1459
+ };
1460
+
1461
+ // packages/ui/react-ui-form/src/components/Form/ArrayField.tsx
1462
+ var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
1463
+ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
1464
+ var _effect = _useSignals10();
1465
+ try {
1466
+ const { t } = useTranslation6(translationKey);
1467
+ const { ast, name, type, title } = property;
1468
+ const values = useFormValues(path ?? []) ?? [];
1469
+ invariant2(Array.isArray(values), `Values at path ${path?.join(".")} must be an array.`, {
1470
+ F: __dxlog_file3,
1471
+ L: 36,
1472
+ S: void 0,
1473
+ A: [
1474
+ "Array.isArray(values)",
1475
+ "`Values at path ${path?.join('.')} must be an array.`"
1476
+ ]
1477
+ });
1478
+ const label = title ?? pipe(name, capitalize);
1479
+ const elementType = findArrayElementType(ast);
1480
+ const getDefaultObjectValue = (typeNode) => {
1481
+ const baseNode = findNode2(typeNode, isDiscriminatedUnion);
1482
+ const typeLiteral = baseNode ? getDiscriminatedType(baseNode, {}) : findNode2(typeNode, SchemaAST3.isTypeLiteral);
1483
+ if (!typeLiteral) {
1484
+ return {};
1485
+ }
1486
+ return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [
1487
+ prop.name,
1488
+ prop.defaultValue
1489
+ ]));
1490
+ };
1491
+ const getDefaultValue = () => type === "object" && elementType ? getDefaultObjectValue(elementType) : SimpleType.getDefaultValue(type);
1492
+ const handleAdd = useCallback7(() => {
1493
+ inputProps.onValueChange(type, [
1494
+ ...values,
1495
+ getDefaultValue()
1496
+ ]);
1497
+ }, [
1498
+ type,
1499
+ elementType,
1500
+ inputProps,
1501
+ values
1502
+ ]);
1503
+ const handleRemove = useCallback7((index) => {
1504
+ const newValues = values.filter((_, i) => i !== index);
1505
+ inputProps.onValueChange(type, newValues);
1506
+ }, [
1507
+ type,
1508
+ inputProps,
1509
+ values
1510
+ ]);
1511
+ if (!elementType) {
1512
+ return null;
1513
+ }
1514
+ return readonly && values.length < 1 ? null : /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(InputHeader, null, label), /* @__PURE__ */ React10.createElement("div", {
1515
+ role: "none",
1516
+ className: readonly ? "flex flex-wrap gap-1 mlb-1" : values.length > 0 ? "grid gap-1 grid-cols-[1fr_min-content] mlb-1" : "hidden"
1517
+ }, values.map((_value, index) => {
1518
+ const field = /* @__PURE__ */ React10.createElement(FormField, {
1519
+ property: {
1520
+ ...property,
1521
+ array: false,
1522
+ ast: elementType
1523
+ },
1524
+ path: [
1525
+ ...path ?? [],
1526
+ index
1527
+ ],
1528
+ readonly,
1529
+ inline: true,
1530
+ Custom,
1531
+ lookupComponent
1532
+ });
1533
+ return readonly ? field : /* @__PURE__ */ React10.createElement(Fragment, {
1534
+ key: index
1535
+ }, /* @__PURE__ */ React10.createElement("div", {
1536
+ role: "none"
1537
+ }, field), /* @__PURE__ */ React10.createElement(IconButton3, {
1538
+ icon: "ph--trash--regular",
1539
+ iconOnly: true,
1540
+ label: t("button remove"),
1541
+ onClick: () => handleRemove(index),
1542
+ classNames: "self-center"
1543
+ }));
1544
+ })), !readonly && /* @__PURE__ */ React10.createElement(IconButton3, {
1545
+ classNames: "is-full mlb-1 flex",
1546
+ icon: "ph--plus--regular",
1547
+ label: t("add field"),
1548
+ onClick: handleAdd
1549
+ }));
1550
+ } finally {
1551
+ _effect.f();
1552
+ }
1553
+ };
1554
+
1555
+ // packages/ui/react-ui-form/src/components/Form/RefField.tsx
1556
+ import { useSignals as _useSignals11 } from "@preact-signals/safe-react/tracking";
1557
+ import React11, { useCallback as useCallback8, useMemo as useMemo4 } from "react";
1558
+ import { Expando, getTypeAnnotation, Ref, ReferenceAnnotationId as ReferenceAnnotationId2 } from "@dxos/echo-schema";
1559
+ import { findAnnotation as findAnnotation2 } from "@dxos/effect";
1560
+ import { DXN } from "@dxos/keys";
1561
+ import { DxRefTag } from "@dxos/lit-ui/react";
1562
+ import { Input as Input7, useTranslation as useTranslation7 } from "@dxos/react-ui";
1563
+ import { TagPicker } from "@dxos/react-ui-tag-picker";
1564
+ import { descriptionText, mx as mx5 } from "@dxos/react-ui-theme";
1565
+ import { isNonNullable as isNonNullable2 } from "@dxos/util";
1566
+ var RefField = ({ type, label, disabled, placeholder, inputOnly, array, ast, getValue: getValue3, onBlur, onQueryRefOptions, onValueChange, ...restInputProps }) => {
1567
+ var _effect = _useSignals11();
1568
+ try {
1569
+ const { t } = useTranslation7(translationKey);
1570
+ const refTypeInfo = useMemo4(() => ast ? findAnnotation2(ast, ReferenceAnnotationId2) : void 0, [
1571
+ ast
1572
+ ]);
1573
+ const { options: availableOptions, loading: _loading } = useQueryRefOptions({
1574
+ refTypeInfo,
1575
+ onQueryRefOptions
1576
+ });
1577
+ if (refTypeInfo && refTypeInfo?.typename === getTypeAnnotation(Expando)?.typename || !onQueryRefOptions) {
1578
+ return /* @__PURE__ */ React11.createElement(RefFieldFallback, {
1579
+ type,
1580
+ label,
1581
+ placeholder,
1582
+ disabled,
1583
+ inputOnly,
1584
+ getValue: getValue3,
1585
+ onBlur,
1586
+ onValueChange,
1587
+ ...restInputProps
1588
+ });
1589
+ }
1590
+ const handleGetValue = useCallback8(() => {
1591
+ const formValue = getValue3();
1592
+ const unknownToRefOption = (val) => {
1593
+ if (Ref.isRef(val)) {
1594
+ const dxnString = val.dxn.toString();
1595
+ const matchingOption = availableOptions.find((option2) => option2.id === dxnString);
1596
+ if (matchingOption) {
1597
+ return matchingOption;
1598
+ }
1599
+ }
1600
+ return void 0;
1601
+ };
1602
+ if (array && Array.isArray(formValue)) {
1603
+ return formValue.map(unknownToRefOption).filter(isNonNullable2) ?? [];
1604
+ }
1605
+ const option = unknownToRefOption(formValue);
1606
+ if (option) {
1607
+ return [
1608
+ option
1609
+ ];
1610
+ }
1611
+ return [];
1612
+ }, [
1613
+ getValue3,
1614
+ availableOptions,
1615
+ array
1616
+ ]);
1617
+ const handleSearch = useCallback8((text, ids) => availableOptions.filter((option) => !ids.includes(option.id)).filter((option) => option.label.toLowerCase().includes(text.toLowerCase())).map((option) => ({
1618
+ id: option.id,
1619
+ label: option.label,
1620
+ hue: option.hue
1621
+ })), [
1622
+ availableOptions
1623
+ ]);
1624
+ const handleUpdate = useCallback8((ids) => {
1625
+ if (ids.length === 0) {
1626
+ onValueChange("object", void 0);
1627
+ return;
1628
+ }
1629
+ const refs = ids.map((id) => {
1630
+ const item = availableOptions.find((option) => option.id === id);
1631
+ if (item) {
1632
+ const dxn = DXN.parse(item.id);
1633
+ return Ref.fromDXN(dxn);
1634
+ }
1635
+ return null;
1636
+ }).filter(isNonNullable2);
1637
+ if (array) {
1638
+ onValueChange("object", refs);
1639
+ } else {
1640
+ onValueChange("object", refs[0]);
1641
+ }
1642
+ }, [
1643
+ availableOptions,
1644
+ array,
1645
+ onValueChange
1646
+ ]);
1647
+ const tagPickerMode = useMemo4(() => array ? "multi-select" : "single-select", [
1648
+ array
1649
+ ]);
1650
+ if (!refTypeInfo) {
1651
+ return null;
1652
+ }
1653
+ const { status, error } = restInputProps.getStatus();
1654
+ const items = handleGetValue();
1655
+ return disabled && items.length < 1 ? null : /* @__PURE__ */ React11.createElement(Input7.Root, {
1656
+ validationValence: status
1657
+ }, !inputOnly && /* @__PURE__ */ React11.createElement(InputHeader, {
1658
+ error
1659
+ }, /* @__PURE__ */ React11.createElement(Input7.Label, null, label)), /* @__PURE__ */ React11.createElement("div", {
1660
+ "data-no-submit": true
1661
+ }, disabled ? items.length < 1 ? /* @__PURE__ */ React11.createElement("p", {
1662
+ className: mx5(descriptionText, "mbe-2")
1663
+ }, t("empty readonly ref field label")) : items.map((item) => /* @__PURE__ */ React11.createElement(DxRefTag, {
1664
+ key: item.id,
1665
+ refid: item.id,
1666
+ rootclassname: "mie-1",
1667
+ style: {
1668
+ marginInlineEnd: ".25rem"
1669
+ }
1670
+ }, item.label)) : /* @__PURE__ */ React11.createElement(TagPicker, {
1671
+ readonly: disabled,
1672
+ items,
1673
+ mode: tagPickerMode,
1674
+ onBlur: (event) => onBlur(event),
1675
+ onUpdate: handleUpdate,
1676
+ onSearch: handleSearch,
1677
+ classNames: "rounded-sm bg-inputSurface p-1.5"
1678
+ })), inputOnly && /* @__PURE__ */ React11.createElement(Input7.DescriptionAndValidation, null, error));
1679
+ } finally {
1680
+ _effect.f();
1681
+ }
1682
+ };
1683
+ var RefFieldFallback = ({ type, label, disabled, placeholder, inputOnly, getValue: getValue3, onValueChange, ...restInputProps }) => {
1684
+ var _effect = _useSignals11();
1685
+ try {
1686
+ const handleOnValueChange = (_type, dxnString) => {
1687
+ const dxn = DXN.tryParse(dxnString);
1688
+ if (dxn) {
1689
+ onValueChange?.("object", Ref.fromDXN(dxn));
1690
+ } else if (dxnString === "") {
1691
+ onValueChange?.("object", void 0);
1692
+ } else {
1693
+ onValueChange?.("string", dxnString);
1694
+ }
1695
+ };
1696
+ const handleGetValue = () => {
1697
+ const formValue = getValue3();
1698
+ if (typeof formValue === "string") {
1699
+ return formValue;
1700
+ }
1701
+ if (Ref.isRef(formValue)) {
1702
+ return formValue.dxn.toString();
1703
+ }
1704
+ return void 0;
1705
+ };
1706
+ return /* @__PURE__ */ React11.createElement(TextInput, {
1707
+ type,
1708
+ label,
1709
+ disabled,
1710
+ placeholder,
1711
+ inputOnly,
1712
+ getValue: handleGetValue,
1713
+ onValueChange: handleOnValueChange,
1714
+ ...restInputProps
1715
+ });
1716
+ } finally {
1717
+ _effect.f();
1718
+ }
1719
+ };
1720
+
1721
+ // packages/ui/react-ui-form/src/components/Form/factory.tsx
1722
+ import { FormatEnum as FormatEnum4 } from "@dxos/echo-schema";
1723
+ var getInputComponent = (type, format) => {
1724
+ switch (format) {
1725
+ case FormatEnum4.GeoPoint:
1726
+ return GeoPointInput;
1727
+ case FormatEnum4.Markdown:
1728
+ return MarkdownInput;
1729
+ }
1730
+ switch (type) {
1731
+ case "string":
1732
+ return TextInput;
1733
+ case "number":
1734
+ return NumberInput;
1735
+ case "boolean":
1736
+ return BooleanInput;
1737
+ }
1738
+ };
1739
+
1740
+ // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
1741
+ var FormField = ({ property, path, readonly, inline, onQueryRefOptions, lookupComponent, Custom }) => {
1742
+ var _effect = _useSignals12();
1743
+ try {
1744
+ const inputProps = useInputProps(path);
1745
+ const { ast, name, type, format, title, description, options, examples, array } = property;
1746
+ const label = useMemo5(() => title ?? pipe2(name, capitalize2), [
1747
+ title,
1748
+ name
1749
+ ]);
1750
+ const placeholder = useMemo5(() => examples?.length ? `Example: "${examples[0]}"` : description, [
1751
+ examples,
1752
+ description
1753
+ ]);
1754
+ const FoundComponent = lookupComponent?.({
1755
+ prop: name,
1756
+ schema: Schema.make(ast),
1757
+ inputProps: {
1758
+ type,
1759
+ format,
1760
+ label,
1761
+ disabled: readonly,
1762
+ placeholder,
1763
+ ...inputProps
1764
+ }
1765
+ });
1766
+ if (FoundComponent) {
1767
+ return FoundComponent;
1768
+ }
1769
+ const jsonPath = createJsonPath3(path ?? []);
1770
+ const CustomComponent = Custom?.[jsonPath];
1771
+ if (CustomComponent) {
1772
+ return /* @__PURE__ */ React12.createElement(CustomComponent, {
1773
+ type,
1774
+ format,
1775
+ label,
1776
+ inputOnly: inline,
1777
+ placeholder,
1778
+ disabled: readonly,
1779
+ ...inputProps
1780
+ });
1781
+ }
1782
+ const refProps = getRefProps(property);
1783
+ if (refProps) {
1784
+ return /* @__PURE__ */ React12.createElement(RefField, {
1785
+ ast: refProps.ast,
1786
+ array: refProps.isArray,
1787
+ type,
1788
+ format,
1789
+ label,
1790
+ placeholder,
1791
+ disabled: readonly,
1792
+ inputOnly: inline,
1793
+ onQueryRefOptions,
1794
+ ...inputProps
1795
+ });
1796
+ }
1797
+ if (array) {
1798
+ return /* @__PURE__ */ React12.createElement(ArrayField, {
1799
+ property,
1800
+ path,
1801
+ inputProps,
1802
+ readonly,
1803
+ Custom
1804
+ });
1805
+ }
1806
+ const InputComponent = getInputComponent(type, format);
1807
+ if (InputComponent) {
1808
+ return /* @__PURE__ */ React12.createElement(InputComponent, {
1809
+ type,
1810
+ format,
1811
+ label,
1812
+ inputOnly: inline,
1813
+ placeholder,
1814
+ disabled: readonly,
1815
+ ...inputProps
1816
+ });
1817
+ }
1818
+ if (options) {
1819
+ return /* @__PURE__ */ React12.createElement(SelectInput, {
1820
+ type,
1821
+ format,
1822
+ disabled: readonly,
1823
+ inputOnly: inline,
1824
+ label,
1825
+ options: options.map((option) => ({
1826
+ value: option,
1827
+ label: String(option)
1828
+ })),
1829
+ placeholder,
1830
+ ...inputProps
1831
+ });
1832
+ }
1833
+ if (type === "object") {
1834
+ const baseNode = findNode3(ast, isDiscriminatedUnion2);
1835
+ const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode3(ast, SchemaAST4.isTypeLiteral);
1836
+ if (typeLiteral) {
1837
+ return /* @__PURE__ */ React12.createElement(React12.Fragment, null, !inline && /* @__PURE__ */ React12.createElement("h3", {
1838
+ className: "text-lg mbs-2 mbe-1 first:mbs-0"
1839
+ }, label), /* @__PURE__ */ React12.createElement(FormFields, {
1840
+ schema: Schema.make(typeLiteral),
1841
+ path,
1842
+ readonly,
1843
+ onQueryRefOptions,
1844
+ Custom,
1845
+ lookupComponent
1846
+ }));
1847
+ }
1848
+ }
1849
+ return null;
1850
+ } finally {
1851
+ _effect.f();
1852
+ }
1853
+ };
1854
+ var FormFields = ({ classNames, Custom, schema, path, filter, sort, readonly, lookupComponent, onQueryRefOptions }) => {
1855
+ var _effect = _useSignals12();
1856
+ try {
1857
+ const values = useFormValues(path);
1858
+ const properties = useMemo5(() => {
1859
+ const props = getSchemaProperties2(schema.ast, values);
1860
+ const filtered = filter ? filter(props) : props;
1861
+ return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
1862
+ }, [
1863
+ schema,
1864
+ values,
1865
+ filter,
1866
+ sort
1867
+ ]);
1868
+ return (
1869
+ // TODO(burdon): Consistent padding (with composite forms).
1870
+ /* @__PURE__ */ React12.createElement("div", {
1871
+ role: "form",
1872
+ className: mx6("p-2 is-full", classNames)
1873
+ }, properties.map((property) => {
1874
+ return /* @__PURE__ */ React12.createElement(FormField, {
1875
+ key: property.name,
1876
+ property,
1877
+ path: [
1878
+ ...path ?? [],
1879
+ property.name
1880
+ ],
1881
+ readonly,
1882
+ onQueryRefOptions,
1883
+ lookupComponent,
1884
+ Custom
1885
+ });
1886
+ }).filter(isNotFalsy))
1887
+ );
1888
+ } finally {
1889
+ _effect.f();
1890
+ }
1891
+ };
1892
+
1893
+ // packages/ui/react-ui-form/src/components/Form/Form.tsx
1894
+ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, onQueryRefOptions, lookupComponent, Custom }) => {
1895
+ var _effect = _useSignals13();
1896
+ try {
1897
+ const formRef = useRef3(null);
1898
+ const onValid = useMemo6(() => autoSave ? onSave : void 0, [
1899
+ autoSave,
1900
+ onSave
1901
+ ]);
1902
+ useEffect7(() => {
1903
+ if (autoFocus && formRef.current) {
1904
+ const input = formRef.current.querySelector("input");
1905
+ if (input) {
1906
+ input.focus();
1907
+ }
1908
+ }
1909
+ }, [
1910
+ autoFocus
1911
+ ]);
1912
+ return /* @__PURE__ */ React13.createElement(FormProvider, {
1913
+ formRef,
1914
+ schema,
1915
+ autoSave,
1916
+ initialValues,
1917
+ onValuesChanged,
1918
+ onValidate,
1919
+ onValid,
1920
+ onSave
1921
+ }, /* @__PURE__ */ React13.createElement("div", {
1922
+ ref: formRef,
1923
+ role: "none",
1924
+ className: mx7("flex flex-col gap-4", classNames),
1925
+ "data-testid": testId
1926
+ }, /* @__PURE__ */ React13.createElement(FormFields, {
1927
+ schema,
1928
+ path,
1929
+ readonly,
1930
+ filter,
1931
+ sort,
1932
+ onQueryRefOptions,
1933
+ lookupComponent,
1934
+ Custom
1935
+ }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React13.createElement(FormActions, {
1936
+ onCancel,
1937
+ readonly
1938
+ })));
1939
+ } finally {
1940
+ _effect.f();
1941
+ }
1942
+ };
1943
+
1944
+ // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
1945
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
1946
+ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1947
+ var _effect = _useSignals14();
1948
+ try {
1949
+ const { t } = useTranslation8(translationKey);
1950
+ const [props, setProps] = useState5(projection.getFieldProjection(field.id).props);
1951
+ useEffect8(() => setProps(projection.getFieldProjection(field.id).props), [
1952
+ field,
1953
+ projection
1954
+ ]);
1955
+ const [schemas, setSchemas] = useState5([]);
1956
+ useEffect8(() => {
1957
+ if (!registry) {
1958
+ return;
1959
+ }
1960
+ const subscription = registry.query().subscribe((query) => setSchemas(query.results), {
1961
+ fire: true
1962
+ });
1963
+ const t2 = setTimeout(async () => {
1964
+ const schemas2 = await registry.query().run();
1965
+ setSchemas(schemas2);
1966
+ });
1967
+ return () => {
1968
+ clearTimeout(t2);
1969
+ subscription?.();
1970
+ };
1971
+ }, [
1972
+ registry
1973
+ ]);
1974
+ const [referenceSchema, setReferenceSchema] = useState5();
1975
+ useEffect8(() => {
1976
+ setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
1977
+ }, [
1978
+ schemas,
1979
+ props?.referenceSchema
1980
+ ]);
1981
+ const [{ fieldSchema }, setFieldSchema] = useState5({
1982
+ fieldSchema: getFormatSchema(props?.format)
1983
+ });
1984
+ const handleValuesChanged = useCallback9((_props) => {
1985
+ setFieldSchema((prev) => {
1986
+ const fieldSchema2 = getFormatSchema(_props.format);
1987
+ if (prev.fieldSchema === fieldSchema2) {
1988
+ return prev;
1989
+ }
1990
+ return {
1991
+ fieldSchema: fieldSchema2
1992
+ };
1993
+ });
1994
+ setReferenceSchema((prev) => {
1995
+ if (_props.referenceSchema !== prev?.typename) {
1996
+ const newSchema = schemas.find((schema) => schema.typename === _props.referenceSchema);
1997
+ if (newSchema) {
1998
+ return newSchema;
1999
+ }
2000
+ }
2001
+ return prev;
2002
+ });
2003
+ setProps((props2) => {
2004
+ const type = formatToType[_props.format];
2005
+ if (props2.type !== type) {
2006
+ return {
2007
+ ...props2,
2008
+ ..._props,
2009
+ type
2010
+ };
2011
+ }
2012
+ return _props;
2013
+ });
2014
+ }, [
2015
+ schemas,
2016
+ props.format,
2017
+ props.referenceSchema
2018
+ ]);
2019
+ const handleValidate = useCallback9(({ property }) => {
2020
+ if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
2021
+ return [
2022
+ {
2023
+ path: "property",
2024
+ message: `property is not unique: '${property}'`
2025
+ }
2026
+ ];
2027
+ }
2028
+ }, [
2029
+ view.fields,
2030
+ field
2031
+ ]);
2032
+ const handleSave = useCallback9((props2) => {
2033
+ projection.setFieldProjection({
2034
+ field,
2035
+ props: props2
2036
+ });
2037
+ onSave();
2038
+ }, [
2039
+ projection,
2040
+ field,
2041
+ onSave
2042
+ ]);
2043
+ const handleCancel = useCallback9(() => {
2044
+ requestAnimationFrame(() => onCancel?.());
2045
+ onSave();
2046
+ }, [
2047
+ onSave
2048
+ ]);
2049
+ const custom = useMemo7(() => ({
2050
+ ["format"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
2051
+ ...props2,
2052
+ options: FormatEnums.filter((value) => value !== FormatEnum5.None).map((value) => ({
2053
+ value,
2054
+ label: t(`format ${value}`)
2055
+ }))
2056
+ }),
2057
+ ["referenceSchema"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
2058
+ ...props2,
2059
+ options: schemas.map((schema) => ({
2060
+ value: schema.typename
2061
+ }))
2062
+ }),
2063
+ ["referencePath"]: (props2) => /* @__PURE__ */ React14.createElement(SelectInput, {
2064
+ ...props2,
2065
+ options: referenceSchema ? getSchemaProperties3(referenceSchema.ast).sort(sortProperties).map((p) => ({
2066
+ value: p.name
2067
+ })) : []
2068
+ }),
2069
+ ["options"]: (props2) => /* @__PURE__ */ React14.createElement(SelectOptionInput, props2)
2070
+ }), [
2071
+ t,
2072
+ schemas,
2073
+ referenceSchema
2074
+ ]);
2075
+ const propIsNotType = useCallback9((props2) => props2.filter((p) => p.name !== "type"), []);
2076
+ if (!fieldSchema) {
2077
+ log3.warn("invalid format", {
2078
+ props
2079
+ }, {
2080
+ F: __dxlog_file4,
2081
+ L: 175,
2082
+ S: void 0,
2083
+ C: (f, a) => f(...a)
2084
+ });
2085
+ return null;
2086
+ }
2087
+ return /* @__PURE__ */ React14.createElement(Form, {
2088
+ key: field.id,
2089
+ autoFocus: true,
2090
+ values: props,
2091
+ schema: fieldSchema,
2092
+ filter: propIsNotType,
2093
+ sort: [
2094
+ "property",
2095
+ "format"
2096
+ ],
2097
+ onValuesChanged: handleValuesChanged,
2098
+ onValidate: handleValidate,
2099
+ onSave: handleSave,
2100
+ onCancel: handleCancel,
2101
+ Custom: custom
2102
+ });
2103
+ } finally {
2104
+ _effect.f();
2105
+ }
2106
+ };
2107
+
2108
+ // packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
2109
+ import { useSignals as _useSignals15 } from "@preact-signals/safe-react/tracking";
2110
+ import { Schema as Schema2 } from "effect";
2111
+ import React15, { useCallback as useCallback10, useMemo as useMemo8, useState as useState6 } from "react";
2112
+ import { EchoSchema, Format, isMutable, toJsonSchema } from "@dxos/echo-schema";
2113
+ import { invariant as invariant3 } from "@dxos/invariant";
2114
+ import { Icon as Icon3, IconButton as IconButton4, Message, useTranslation as useTranslation9 } from "@dxos/react-ui";
2115
+ import { List as List2 } from "@dxos/react-ui-list";
2116
+ import { ghostHover, inputTextLabel, mx as mx8 } from "@dxos/react-ui-theme";
2117
+ import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
2118
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx";
2119
+ var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
2120
+ var ViewMetaSchema = Schema2.Struct({
2121
+ name: Schema2.String.annotations({
2122
+ title: "View"
2123
+ }),
2124
+ typename: Format.URL.annotations({
2125
+ title: "Typename"
2126
+ })
2127
+ }).pipe(Schema2.mutable);
2128
+ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
2129
+ var _effect = _useSignals15();
2130
+ try {
2131
+ const { t } = useTranslation9(translationKey);
2132
+ const projection = useMemo8(() => {
2133
+ const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : toJsonSchema(schema);
2134
+ return new ViewProjection(jsonSchema, view);
2135
+ }, [
2136
+ schema,
2137
+ view
2138
+ ]);
2139
+ const [field, setField] = useState6();
2140
+ const immutable = readonly || !isMutable(schema);
2141
+ const viewValues = useMemo8(() => {
2142
+ return {
2143
+ name: view.name,
2144
+ // TODO(burdon): Need to warn user of possible consequences of editing.
2145
+ // TODO(burdon): Settings should have domain name owned by user.
2146
+ typename: view.query.typename
2147
+ };
2148
+ }, [
2149
+ view
2150
+ ]);
2151
+ const handleSelect = useCallback10((field2) => {
2152
+ if (immutable) {
2153
+ return;
2154
+ }
2155
+ setField((f) => f === field2 ? void 0 : field2);
2156
+ }, [
2157
+ immutable
2158
+ ]);
2159
+ const handleAdd = useCallback10(() => {
2160
+ invariant3(!immutable, void 0, {
2161
+ F: __dxlog_file5,
2162
+ L: 88,
2163
+ S: void 0,
2164
+ A: [
2165
+ "!immutable",
2166
+ ""
2167
+ ]
2168
+ });
2169
+ const field2 = projection.createFieldProjection();
2170
+ setField(field2);
2171
+ }, [
2172
+ schema,
2173
+ view
2174
+ ]);
2175
+ const handleUpdate = useCallback10(({ name, typename }) => {
2176
+ invariant3(!immutable, void 0, {
2177
+ F: __dxlog_file5,
2178
+ L: 95,
2179
+ S: void 0,
2180
+ A: [
2181
+ "!immutable",
2182
+ ""
2183
+ ]
2184
+ });
2185
+ requestAnimationFrame(() => {
2186
+ if (view.name !== name) {
2187
+ view.name = name;
2188
+ }
2189
+ if (view.query.typename !== typename && !immutable) {
2190
+ onTypenameChanged?.(typename);
2191
+ }
2192
+ });
2193
+ }, [
2194
+ schema,
2195
+ view,
2196
+ onTypenameChanged,
2197
+ immutable
2198
+ ]);
2199
+ const handleDelete = useCallback10((fieldId) => {
2200
+ invariant3(!immutable, void 0, {
2201
+ F: __dxlog_file5,
2202
+ L: 111,
2203
+ S: void 0,
2204
+ A: [
2205
+ "!immutable",
2206
+ ""
2207
+ ]
2208
+ });
2209
+ if (fieldId === field?.id) {
2210
+ setField(void 0);
2211
+ }
2212
+ onDelete?.(fieldId);
2213
+ }, [
2214
+ schema,
2215
+ field,
2216
+ onDelete
2217
+ ]);
2218
+ const handleMove = useCallback10((fromIndex, toIndex) => {
2219
+ invariant3(!immutable, void 0, {
2220
+ F: __dxlog_file5,
2221
+ L: 123,
2222
+ S: void 0,
2223
+ A: [
2224
+ "!immutable",
2225
+ ""
2226
+ ]
2227
+ });
2228
+ const fields = [
2229
+ ...view.fields
2230
+ ];
2231
+ const [moved] = fields.splice(fromIndex, 1);
2232
+ fields.splice(toIndex, 0, moved);
2233
+ view.fields = fields;
2234
+ }, [
2235
+ schema,
2236
+ view.fields
2237
+ ]);
2238
+ const handleClose = useCallback10(() => setField(void 0), []);
2239
+ const hiddenProperties = projection.getHiddenProperties();
2240
+ const handleHide = useCallback10((fieldId) => {
2241
+ setField(void 0);
2242
+ projection.hideFieldProjection(fieldId);
2243
+ }, [
2244
+ projection
2245
+ ]);
2246
+ const handleShow = useCallback10((property) => {
2247
+ setField(void 0);
2248
+ projection.showFieldProjection(property);
2249
+ }, [
2250
+ projection
2251
+ ]);
2252
+ return /* @__PURE__ */ React15.createElement("div", {
2253
+ role: "none",
2254
+ className: mx8("overflow-y-auto", classNames)
2255
+ }, /* @__PURE__ */ React15.createElement("div", {
2256
+ role: "none",
2257
+ className: "p-2"
2258
+ }, /* @__PURE__ */ React15.createElement("div", {
2259
+ role: "none",
2260
+ className: "mbe-2"
2261
+ }, immutable && /* @__PURE__ */ React15.createElement(Message.Root, {
2262
+ valence: "neutral",
2263
+ className: "rounded"
2264
+ }, /* @__PURE__ */ React15.createElement(Message.Title, null, /* @__PURE__ */ React15.createElement(Icon3, {
2265
+ icon: "ph--info--regular",
2266
+ size: 5,
2267
+ classNames: "inline"
2268
+ }), " ", t("system schema title")), /* @__PURE__ */ React15.createElement(Message.Body, null, t("system schema description")))), /* @__PURE__ */ React15.createElement(Form, {
2269
+ autoSave: true,
2270
+ schema: ViewMetaSchema,
2271
+ values: viewValues,
2272
+ onSave: handleUpdate,
2273
+ classNames: "min-bs-0 overflow-y-auto"
2274
+ })), /* @__PURE__ */ React15.createElement("div", {
2275
+ role: "none",
2276
+ className: "min-bs-0 overflow-y-auto"
2277
+ }, /* @__PURE__ */ React15.createElement("div", {
2278
+ role: "none",
2279
+ className: "p-2"
2280
+ }, /* @__PURE__ */ React15.createElement("label", {
2281
+ className: mx8(inputTextLabel)
2282
+ }, t("fields label"))), /* @__PURE__ */ React15.createElement(List2.Root, {
2283
+ items: view.fields,
2284
+ isItem: Schema2.is(FieldSchema),
2285
+ getId: (field2) => field2.id,
2286
+ onMove: immutable ? void 0 : handleMove
2287
+ }, ({ items: fields }) => /* @__PURE__ */ React15.createElement(React15.Fragment, null, showHeading && /* @__PURE__ */ React15.createElement("div", {
2288
+ role: "heading",
2289
+ className: grid
2290
+ }, /* @__PURE__ */ React15.createElement("div", null), /* @__PURE__ */ React15.createElement("div", {
2291
+ className: "flex items-center text-sm"
2292
+ }, t("field path label"))), /* @__PURE__ */ React15.createElement("div", {
2293
+ role: "list",
2294
+ className: "flex flex-col w-full"
2295
+ }, fields?.map((field2) => /* @__PURE__ */ React15.createElement(List2.Item, {
2296
+ key: field2.id,
2297
+ item: field2,
2298
+ classNames: mx8(grid, ghostHover, !immutable && "cursor-pointer")
2299
+ }, /* @__PURE__ */ React15.createElement(List2.ItemDragHandle, null), /* @__PURE__ */ React15.createElement(List2.ItemTitle, {
2300
+ onClick: () => handleSelect(field2)
2301
+ }, field2.path), /* @__PURE__ */ React15.createElement("div", {
2302
+ className: "flex items-center gap-2 -ml-4"
2303
+ }, /* @__PURE__ */ React15.createElement(List2.ItemButton, {
2304
+ icon: "ph--eye-slash--regular",
2305
+ disabled: view.fields.length <= 1,
2306
+ onClick: () => handleHide(field2.id)
2307
+ }), !immutable && /* @__PURE__ */ React15.createElement(List2.ItemDeleteButton, {
2308
+ icon: "ph--trash--regular",
2309
+ disabled: view.fields.length <= 1,
2310
+ onClick: () => handleDelete(field2.id)
2311
+ }))))))), hiddenProperties.length > 0 && /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("div", {
2312
+ role: "none",
2313
+ className: "p-2"
2314
+ }, /* @__PURE__ */ React15.createElement("label", {
2315
+ className: mx8(inputTextLabel)
2316
+ }, t("hidden fields label"))), /* @__PURE__ */ React15.createElement(List2.Root, {
2317
+ items: hiddenProperties,
2318
+ isItem: (item) => typeof item === "string",
2319
+ getId: (property) => property
2320
+ }, ({ items: properties }) => /* @__PURE__ */ React15.createElement("div", {
2321
+ role: "list",
2322
+ className: "flex flex-col w-full"
2323
+ }, properties?.map((property) => /* @__PURE__ */ React15.createElement(List2.Item, {
2324
+ key: property,
2325
+ item: property,
2326
+ classNames: mx8(grid, ghostHover, !immutable && "cursor-pointer")
2327
+ }, /* @__PURE__ */ React15.createElement("div", null), /* @__PURE__ */ React15.createElement(List2.ItemTitle, null, property), /* @__PURE__ */ React15.createElement(List2.ItemButton, {
2328
+ icon: "ph--eye--regular",
2329
+ onClick: () => handleShow(property)
2330
+ }))))))), field && /* @__PURE__ */ React15.createElement(FieldEditor, {
2331
+ key: field.id,
2332
+ view,
2333
+ projection,
2334
+ field,
2335
+ registry,
2336
+ onSave: handleClose
2337
+ }), !readonly && !field && /* @__PURE__ */ React15.createElement("div", {
2338
+ role: "none",
2339
+ className: "p-2"
2340
+ }, /* @__PURE__ */ React15.createElement(IconButton4, {
2341
+ icon: "ph--plus--regular",
2342
+ label: t("button add property"),
2343
+ onClick: immutable ? void 0 : handleAdd,
2344
+ // TODO(burdon): Show field limit in ux (not tooltip).
2345
+ disabled: view.fields.length >= VIEW_FIELD_LIMIT,
2346
+ classNames: "flex is-full"
2347
+ })));
2348
+ } finally {
2349
+ _effect.f();
2350
+ }
2351
+ };
1998
2352
  export {
1999
2353
  BooleanInput,
2000
2354
  ControlFrame,
@@ -2022,14 +2376,18 @@ export {
2022
2376
  ViewEditor,
2023
2377
  cellClassesForFieldType,
2024
2378
  controlItemClasses,
2379
+ findArrayElementType,
2025
2380
  formatForDisplay,
2026
2381
  formatForEditing,
2382
+ getRefProps,
2027
2383
  parseValue,
2028
2384
  pathNotUniqueError,
2029
2385
  translations_default as translations,
2030
2386
  useForm,
2031
2387
  useFormContext,
2032
2388
  useFormValues,
2033
- useInputProps
2389
+ useInputProps,
2390
+ useQueryRefOptions,
2391
+ useRefQueryLookupHandler
2034
2392
  };
2035
2393
  //# sourceMappingURL=index.mjs.map