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