@dxos/react-ui-form 0.7.5-labs.e27f9b9 → 0.7.5-labs.f400bbc

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 (65) hide show
  1. package/dist/lib/browser/index.mjs +546 -362
  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 +589 -401
  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 +546 -362
  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/FieldEditor/FieldEditor.d.ts +1 -2
  11. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  12. package/dist/types/src/components/Form/ArrayField.d.ts +1 -2
  13. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
  14. package/dist/types/src/components/Form/Defaults.d.ts +5 -5
  15. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Form.d.ts +2 -2
  17. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/FormActions.d.ts +1 -2
  19. package/dist/types/src/components/Form/FormActions.d.ts.map +1 -1
  20. package/dist/types/src/components/Form/FormContent.d.ts +2 -3
  21. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
  22. package/dist/types/src/components/Form/FormContext.d.ts +4 -1
  23. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
  24. package/dist/types/src/components/Form/Input.d.ts +2 -2
  25. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  26. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts +1 -2
  27. package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
  28. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts +1 -2
  29. package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -1
  30. package/dist/types/src/components/Form/custom/TupleInput.d.ts +1 -2
  31. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
  32. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  33. package/dist/types/src/components/Form/index.d.ts +2 -0
  34. package/dist/types/src/components/Form/index.d.ts.map +1 -1
  35. package/dist/types/src/components/ViewEditor/Test.stories.d.ts +1 -2
  36. package/dist/types/src/components/ViewEditor/Test.stories.d.ts.map +1 -1
  37. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +1 -2
  38. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  39. package/dist/types/src/components/deprecated/Form.d.ts +1 -2
  40. package/dist/types/src/components/deprecated/Form.d.ts.map +1 -1
  41. package/dist/types/src/components/deprecated/Form.stories.d.ts +1 -2
  42. package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
  43. package/dist/types/src/components/deprecated/FormInput.d.ts +2 -2
  44. package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
  45. package/dist/types/src/components/testing.d.ts +3 -3
  46. package/dist/types/src/components/testing.d.ts.map +1 -1
  47. package/dist/types/src/hooks/useForm.d.ts +1 -0
  48. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  49. package/dist/types/src/util/field.d.ts.map +1 -1
  50. package/dist/types/src/util/formatting.d.ts.map +1 -1
  51. package/package.json +25 -24
  52. package/src/components/Form/Defaults.tsx +61 -4
  53. package/src/components/Form/Form.tsx +9 -5
  54. package/src/components/Form/FormActions.tsx +1 -1
  55. package/src/components/Form/FormContent.tsx +10 -13
  56. package/src/components/Form/FormContext.tsx +58 -10
  57. package/src/components/Form/custom/GeoPointInput.tsx +42 -12
  58. package/src/components/Form/custom/SelectOptionsInput.tsx +7 -9
  59. package/src/components/Form/factory.tsx +4 -2
  60. package/src/components/Form/index.ts +3 -0
  61. package/src/components/ViewEditor/ViewEditor.tsx +2 -2
  62. package/src/hooks/useForm.ts +69 -40
  63. package/src/translations.ts +1 -1
  64. package/src/util/field.ts +19 -1
  65. package/src/util/formatting.ts +29 -1
@@ -29,7 +29,7 @@ var translations_default = [
29
29
  "format hostname": "Hostname",
30
30
  "format integer": "Integer",
31
31
  "format json": "JSON",
32
- "format latlng": "LatLng",
32
+ "format latlng": "Geopoint",
33
33
  "format markdown": "Markdown",
34
34
  "format percent": "Percent",
35
35
  "format ref": "Reference",
@@ -99,85 +99,394 @@ var DeprecatedFormInput = ({ label, description, secondary, children }) => {
99
99
  };
100
100
 
101
101
  // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
102
- import React12, { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo5, useState as useState3 } from "react";
102
+ import React12, { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo7, useState as useState4 } from "react";
103
103
  import { FormatEnum as FormatEnum2, FormatEnums, formatToType } from "@dxos/echo-schema";
104
104
  import { log as log2 } from "@dxos/log";
105
105
  import { useTranslation as useTranslation5 } from "@dxos/react-ui";
106
106
  import { getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
107
107
 
108
+ // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
109
+ import React2, { createContext, useContext, useEffect as useEffect2, useMemo as useMemo2 } from "react";
110
+ import { raise } from "@dxos/debug";
111
+ import { getValue as getValue2 } from "@dxos/echo-schema";
112
+ import { createJsonPath as createJsonPath2 } from "@dxos/effect";
113
+
114
+ // packages/ui/react-ui-form/src/hooks/useForm.ts
115
+ import { useCallback, useEffect, useMemo, useState } from "react";
116
+ import { getValue, setValue } from "@dxos/echo-schema";
117
+ import { AST, createJsonPath, fromEffectValidationPath } from "@dxos/effect";
118
+ import { invariant } from "@dxos/invariant";
119
+ import { log } from "@dxos/log";
120
+ import { validateSchema } from "@dxos/schema";
121
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
122
+ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
123
+ invariant(AST.isTypeLiteral(schema.ast), void 0, {
124
+ F: __dxlog_file,
125
+ L: 92,
126
+ S: void 0,
127
+ A: [
128
+ "AST.isTypeLiteral(schema.ast)",
129
+ ""
130
+ ]
131
+ });
132
+ const [values, setValues] = useState(initialValues);
133
+ useEffect(() => {
134
+ setValues(initialValues);
135
+ }, [
136
+ initialValues
137
+ ]);
138
+ const [touched, setTouched] = useState(createKeySet(initialValues, false));
139
+ const [changed, setChanged] = useState(createKeySet(initialValues, false));
140
+ const [errors, setErrors] = useState({});
141
+ const [saving, setSaving] = useState(false);
142
+ const validate = useCallback((values2) => {
143
+ let errors2 = validateSchema(schema, values2) ?? [];
144
+ if (errors2.length === 0 && onValidate) {
145
+ const validatedValues = values2;
146
+ errors2 = onValidate(validatedValues) ?? [];
147
+ }
148
+ setErrors(flatMap(errors2));
149
+ const valid = errors2.length === 0;
150
+ return valid;
151
+ }, [
152
+ schema,
153
+ onValidate
154
+ ]);
155
+ const [schemaDirty, setSchemaDirty] = useState(false);
156
+ useEffect(() => setSchemaDirty(true), [
157
+ schema
158
+ ]);
159
+ useEffect(() => {
160
+ if (schemaDirty) {
161
+ validate(values);
162
+ setSchemaDirty(false);
163
+ }
164
+ }, [
165
+ values,
166
+ schemaDirty
167
+ ]);
168
+ const formIsValid = useMemo(() => {
169
+ return Object.keys(errors).length === 0;
170
+ }, [
171
+ errors
172
+ ]);
173
+ const canSave = useMemo(() => !saving && // Check if any error paths that are touched have errors.
174
+ !Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
175
+ touched,
176
+ errors,
177
+ saving
178
+ ]);
179
+ const handleSave = useCallback(async () => {
180
+ if (validate(values)) {
181
+ setSaving(true);
182
+ try {
183
+ await onSave?.(values, {
184
+ changed
185
+ });
186
+ } finally {
187
+ setSaving(false);
188
+ }
189
+ }
190
+ }, [
191
+ values,
192
+ validate,
193
+ onSave,
194
+ changed
195
+ ]);
196
+ const getStatus = useCallback((path) => {
197
+ const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
198
+ const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
199
+ return {
200
+ status: matchingError ? "error" : void 0,
201
+ error: matchingError ? matchingError[1] : void 0
202
+ };
203
+ }, [
204
+ errors
205
+ ]);
206
+ const getFormValue = useCallback((path) => {
207
+ return getValue(values, createJsonPath(path));
208
+ }, [
209
+ values
210
+ ]);
211
+ const onValueChange = useCallback((path, type, value) => {
212
+ const jsonPath = createJsonPath(path);
213
+ let parsedValue = value;
214
+ try {
215
+ if (type === "number") {
216
+ parsedValue = parseFloat(value) || 0;
217
+ }
218
+ } catch (err) {
219
+ log.catch(err, void 0, {
220
+ F: __dxlog_file,
221
+ L: 202,
222
+ S: void 0,
223
+ C: (f, a) => f(...a)
224
+ });
225
+ parsedValue = void 0;
226
+ }
227
+ const newValues = {
228
+ ...setValue(values, jsonPath, parsedValue)
229
+ };
230
+ setValues(newValues);
231
+ setChanged((prev) => ({
232
+ ...prev,
233
+ [jsonPath]: true
234
+ }));
235
+ onValuesChanged?.(newValues);
236
+ const isValid = validate(newValues);
237
+ if (isValid && onValid) {
238
+ onValid(newValues, {
239
+ changed
240
+ });
241
+ }
242
+ }, [
243
+ values,
244
+ onValuesChanged,
245
+ validate,
246
+ onValid,
247
+ changed
248
+ ]);
249
+ const onTouched = useCallback((path) => {
250
+ const jsonPath = createJsonPath(path);
251
+ setTouched((touched2) => ({
252
+ ...touched2,
253
+ [jsonPath]: true
254
+ }));
255
+ validate(values);
256
+ }, [
257
+ validate,
258
+ values
259
+ ]);
260
+ return useMemo(() => ({
261
+ // State.
262
+ values,
263
+ errors,
264
+ touched,
265
+ changed,
266
+ canSave,
267
+ formIsValid,
268
+ // Actions.
269
+ handleSave,
270
+ // Field utils.
271
+ getStatus,
272
+ getValue: getFormValue,
273
+ onValueChange,
274
+ onTouched
275
+ }), [
276
+ values,
277
+ errors,
278
+ touched,
279
+ changed,
280
+ canSave,
281
+ formIsValid,
282
+ handleSave,
283
+ getStatus,
284
+ getFormValue,
285
+ onValueChange,
286
+ onTouched
287
+ ]);
288
+ };
289
+ var createKeySet = (obj, value) => {
290
+ invariant(obj, void 0, {
291
+ F: __dxlog_file,
292
+ L: 264,
293
+ S: void 0,
294
+ A: [
295
+ "obj",
296
+ ""
297
+ ]
298
+ });
299
+ return Object.keys(obj).reduce((acc, key) => ({
300
+ ...acc,
301
+ [key]: value
302
+ }), {});
303
+ };
304
+ var flatMap = (errors) => {
305
+ return errors.reduce((result, { path, message }) => {
306
+ const jsonPath = fromEffectValidationPath(path);
307
+ if (!(jsonPath in result)) {
308
+ result[jsonPath] = message;
309
+ }
310
+ return result;
311
+ }, {});
312
+ };
313
+
314
+ // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
315
+ var FormContext = /* @__PURE__ */ createContext(void 0);
316
+ var useFormContext = () => {
317
+ return useContext(FormContext) ?? raise(new Error("Missing FormContext"));
318
+ };
319
+ var useFormValues = (path = []) => {
320
+ const { values: formValues } = useFormContext();
321
+ const jsonPath = createJsonPath2(path);
322
+ return getValue2(formValues, jsonPath);
323
+ };
324
+ var useInputProps = (path = []) => {
325
+ const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
326
+ const stablePath = useMemo2(() => path, [
327
+ Array.isArray(path) ? path.join(".") : path
328
+ ]);
329
+ return useMemo2(() => ({
330
+ getStatus: () => getStatus(stablePath),
331
+ getValue: () => getFormValue(stablePath),
332
+ onValueChange: (type, value) => onValueChange(stablePath, type, value),
333
+ onBlur: () => onTouched(stablePath)
334
+ }), [
335
+ getStatus,
336
+ getFormValue,
337
+ onValueChange,
338
+ onTouched,
339
+ stablePath
340
+ ]);
341
+ };
342
+ var FormProvider = ({ children, formRef, autoSave, ...formOptions }) => {
343
+ const form = useForm(formOptions);
344
+ useEffect2(() => {
345
+ if (!formRef?.current) {
346
+ return;
347
+ }
348
+ const handleKeyDown = (event) => {
349
+ const keyIsEnter = event.key === "Enter";
350
+ const modifierUsed = event.ctrlKey || event.altKey || event.metaKey || event.shiftKey;
351
+ const inputIsTextarea = event.target.tagName.toLowerCase() === "textarea";
352
+ const inputOptOut = event.target.hasAttribute("data-no-submit");
353
+ const shouldSubmitRegularInput = !inputIsTextarea && keyIsEnter && !modifierUsed;
354
+ const shouldSubmitTextarea = inputIsTextarea && keyIsEnter && event.metaKey;
355
+ if ((shouldSubmitRegularInput || shouldSubmitTextarea) && !inputOptOut) {
356
+ if (!autoSave && form.canSave) {
357
+ form.handleSave();
358
+ }
359
+ if (autoSave && form.formIsValid) {
360
+ event.target.blur();
361
+ }
362
+ }
363
+ };
364
+ const formElement = formRef.current;
365
+ formElement.addEventListener("keydown", handleKeyDown);
366
+ return () => formElement.removeEventListener("keydown", handleKeyDown);
367
+ }, [
368
+ formRef,
369
+ form.canSave,
370
+ form.formIsValid,
371
+ form.handleSave,
372
+ autoSave
373
+ ]);
374
+ return /* @__PURE__ */ React2.createElement(FormContext.Provider, {
375
+ value: form
376
+ }, children);
377
+ };
378
+
108
379
  // packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
109
- import React3 from "react";
380
+ import React4, { useCallback as useCallback2, useState as useState2, useEffect as useEffect3, useMemo as useMemo3 } from "react";
381
+ import { GeoLocation } from "@dxos/echo-schema";
110
382
  import { Input as Input2, useTranslation } from "@dxos/react-ui";
111
383
  import { safeParseFloat } from "@dxos/util";
112
384
 
113
385
  // packages/ui/react-ui-form/src/components/Form/Input.tsx
114
- import React2 from "react";
386
+ import React3 from "react";
115
387
  import { Icon, Tooltip } from "@dxos/react-ui";
116
388
  import { errorText } from "@dxos/react-ui-theme";
117
389
  var InputHeader = ({ children, error }) => {
118
- return /* @__PURE__ */ React2.createElement("div", {
390
+ return /* @__PURE__ */ React3.createElement("div", {
119
391
  role: "none",
120
392
  className: "flex justify-between items-center mb-1"
121
- }, children, error && /* @__PURE__ */ React2.createElement(Tooltip.Root, null, /* @__PURE__ */ React2.createElement(Tooltip.Trigger, {
393
+ }, children, error && /* @__PURE__ */ React3.createElement(Tooltip.Root, null, /* @__PURE__ */ React3.createElement(Tooltip.Trigger, {
122
394
  asChild: true
123
- }, /* @__PURE__ */ React2.createElement(Icon, {
395
+ }, /* @__PURE__ */ React3.createElement(Icon, {
124
396
  icon: "ph--warning--regular",
125
397
  size: 4,
126
398
  classNames: errorText
127
- })), /* @__PURE__ */ React2.createElement(Tooltip.Content, {
399
+ })), /* @__PURE__ */ React3.createElement(Tooltip.Content, {
128
400
  side: "bottom"
129
- }, /* @__PURE__ */ React2.createElement(Tooltip.Arrow, null), error)));
401
+ }, /* @__PURE__ */ React3.createElement(Tooltip.Arrow, null), error)));
130
402
  };
131
403
 
132
404
  // packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
133
405
  var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
134
406
  const { t } = useTranslation(translationKey);
135
407
  const { status, error } = getStatus();
136
- const [lng = 0, lat = 0] = getValue3() ?? [];
137
- return /* @__PURE__ */ React3.createElement(Input2.Root, {
408
+ const geoPoint = useMemo3(() => getValue3() ?? [
409
+ 0,
410
+ 0
411
+ ], [
412
+ getValue3
413
+ ]);
414
+ const geoLocation = useMemo3(() => GeoLocation.fromGeoPoint(geoPoint), [
415
+ geoPoint
416
+ ]);
417
+ const [longitudeText, setLongitudeText] = useState2(geoLocation.longitude?.toString());
418
+ const [latitudeText, setLatitudeText] = useState2(geoLocation.latitude?.toString());
419
+ useEffect3(() => {
420
+ const location = GeoLocation.fromGeoPoint(geoPoint);
421
+ setLongitudeText(location.longitude.toString());
422
+ setLatitudeText(location.latitude.toString());
423
+ }, [
424
+ geoPoint
425
+ ]);
426
+ const handleCoordinateChange = useCallback2((coordinateType, setText) => (event) => {
427
+ const inputText = event.target.value;
428
+ setText(inputText);
429
+ if (inputText !== "" && inputText !== "-") {
430
+ const coord = safeParseFloat(inputText);
431
+ if (coord !== void 0 && !isNaN(coord)) {
432
+ const currentLocation = GeoLocation.fromGeoPoint(getValue3() ?? [
433
+ 0,
434
+ 0
435
+ ]);
436
+ const newLocation = {
437
+ ...currentLocation,
438
+ [coordinateType]: coord
439
+ };
440
+ const newValue = GeoLocation.toGeoPoint(newLocation);
441
+ onValueChange(type, newValue);
442
+ }
443
+ }
444
+ }, [
445
+ getValue3,
446
+ onValueChange,
447
+ type
448
+ ]);
449
+ return /* @__PURE__ */ React4.createElement(Input2.Root, {
138
450
  validationValence: status
139
- }, /* @__PURE__ */ React3.createElement(InputHeader, {
451
+ }, /* @__PURE__ */ React4.createElement(InputHeader, {
140
452
  error
141
- }, /* @__PURE__ */ React3.createElement(Input2.Label, null, label)), /* @__PURE__ */ React3.createElement("div", {
453
+ }, /* @__PURE__ */ React4.createElement(Input2.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
454
+ role: "none",
142
455
  className: "grid grid-cols-2 gap-2"
143
- }, /* @__PURE__ */ React3.createElement(Input2.TextInput, {
144
- type: "number",
456
+ }, /* @__PURE__ */ React4.createElement(Input2.TextInput, {
457
+ type: "text",
458
+ pattern: "^-?[0-9]*\\.?[0-9]*$",
145
459
  disabled,
146
- placeholder: t("placeholder longitude"),
147
- value: lng,
148
- onChange: (event) => onValueChange(type, [
149
- lat,
150
- safeParseFloat(event.target.value, 0)
151
- ]),
460
+ placeholder: t("placeholder latitude"),
461
+ value: latitudeText,
462
+ onChange: handleCoordinateChange("latitude", setLatitudeText),
152
463
  onBlur
153
- }), /* @__PURE__ */ React3.createElement(Input2.TextInput, {
154
- type: "number",
464
+ }), /* @__PURE__ */ React4.createElement(Input2.TextInput, {
465
+ type: "text",
466
+ pattern: "^-?[0-9]*\\.?[0-9]*$",
155
467
  disabled,
156
- placeholder: t("placeholder latitude"),
157
- value: lat,
158
- onChange: (event) => onValueChange(type, [
159
- safeParseFloat(event.target.value, 0),
160
- lng
161
- ]),
468
+ placeholder: t("placeholder longitude"),
469
+ value: longitudeText,
470
+ onChange: handleCoordinateChange("longitude", setLongitudeText),
162
471
  onBlur
163
472
  })));
164
473
  };
165
474
 
166
475
  // packages/ui/react-ui-form/src/components/Form/custom/SelectOptionsInput.tsx
167
- import React4, { useCallback, useEffect, useState, useRef } from "react";
476
+ import React5, { useCallback as useCallback3, useEffect as useEffect4, useState as useState3, useRef } from "react";
168
477
  import { PublicKey } from "@dxos/keys";
169
478
  import { Icon as Icon2, IconButton, Input as Input3, Tag, Toolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
170
479
  import { List } from "@dxos/react-ui-list";
171
- import { HuePickerToolbarButton } from "@dxos/react-ui-pickers";
172
- import { hueTokenThemes, mx as mx2 } from "@dxos/react-ui-theme";
480
+ import { HuePicker } from "@dxos/react-ui-pickers";
481
+ import { hues, mx as mx2 } from "@dxos/react-ui-theme";
173
482
  var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange }) => {
174
- const [selected, setSelectedId] = useState(null);
175
- const [isNewOption, setIsNewOption] = useState(false);
483
+ const [selected, setSelectedId] = useState3(null);
484
+ const [isNewOption, setIsNewOption] = useState3(false);
176
485
  const inputRef = useRef(null);
177
486
  const { t } = useTranslation2(translationKey);
178
487
  const { status, error } = getStatus();
179
488
  const options = getValue3();
180
- useEffect(() => {
489
+ useEffect4(() => {
181
490
  if (options === void 0) {
182
491
  onValueChange(type, []);
183
492
  }
@@ -188,16 +497,15 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
188
497
  ]);
189
498
  const randomHue = () => {
190
499
  const usedHues = new Set(options?.map((option) => option.color) ?? []);
191
- const hueKeys = Object.keys(hueTokenThemes);
192
- const unusedHues = hueKeys.filter((hue) => !usedHues.has(hue));
500
+ const unusedHues = hues.filter((hue) => !usedHues.has(hue));
193
501
  if (unusedHues.length > 0) {
194
502
  return unusedHues[Math.floor(Math.random() * unusedHues.length)];
195
503
  }
196
504
  const lastThree = new Set(options?.slice(-3).map((option) => option.color) ?? []);
197
- const availableHues = hueKeys.filter((hue) => !lastThree.has(hue));
198
- return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hueKeys[Math.floor(Math.random() * hueKeys.length)];
505
+ const availableHues = hues.filter((hue) => !lastThree.has(hue));
506
+ return availableHues[Math.floor(Math.random() * availableHues.length)] ?? hues[Math.floor(Math.random() * hues.length)];
199
507
  };
200
- const handleAdd = useCallback(() => {
508
+ const handleAdd = useCallback3(() => {
201
509
  const newId = PublicKey.random().truncate();
202
510
  const newOption = {
203
511
  id: newId,
@@ -215,7 +523,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
215
523
  type,
216
524
  onValueChange
217
525
  ]);
218
- const handleDelete = useCallback((id) => {
526
+ const handleDelete = useCallback3((id) => {
219
527
  const newOptions = options?.filter((option) => option.id !== id) ?? [];
220
528
  onValueChange(type, newOptions);
221
529
  setSelectedId(null);
@@ -224,7 +532,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
224
532
  type,
225
533
  onValueChange
226
534
  ]);
227
- const handleMove = useCallback((from, to) => {
535
+ const handleMove = useCallback3((from, to) => {
228
536
  if (!options) {
229
537
  return;
230
538
  }
@@ -239,10 +547,10 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
239
547
  type,
240
548
  onValueChange
241
549
  ]);
242
- const handleClick = useCallback((id) => {
550
+ const handleClick = useCallback3((id) => {
243
551
  setSelectedId((current) => current === id ? null : id);
244
552
  }, []);
245
- const handleTitleChange = useCallback((id) => (e) => {
553
+ const handleTitleChange = useCallback3((id) => (e) => {
246
554
  const newOptions = options?.map((o) => o.id === id ? {
247
555
  ...o,
248
556
  title: e.target.value
@@ -253,12 +561,12 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
253
561
  type,
254
562
  onValueChange
255
563
  ]);
256
- const handleKeyDown = useCallback((e) => {
564
+ const handleKeyDown = useCallback3((e) => {
257
565
  if (e.key === "Enter") {
258
566
  setSelectedId(null);
259
567
  }
260
568
  }, []);
261
- const handleColorChange = useCallback((id) => (hue) => {
569
+ const handleColorChange = useCallback3((id) => (hue) => {
262
570
  const newOptions = options?.map((o) => o.id === id ? {
263
571
  ...o,
264
572
  color: hue
@@ -269,7 +577,7 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
269
577
  type,
270
578
  onValueChange
271
579
  ]);
272
- useEffect(() => {
580
+ useEffect4(() => {
273
581
  if (selected && isNewOption && inputRef.current) {
274
582
  inputRef.current.focus();
275
583
  setIsNewOption(false);
@@ -278,76 +586,77 @@ var SelectOptionInput = ({ type, label, disabled, getStatus, getValue: getValue3
278
586
  selected,
279
587
  isNewOption
280
588
  ]);
281
- return /* @__PURE__ */ React4.createElement(Input3.Root, {
589
+ return /* @__PURE__ */ React5.createElement(Input3.Root, {
282
590
  validationValence: status
283
- }, /* @__PURE__ */ React4.createElement(InputHeader, {
591
+ }, /* @__PURE__ */ React5.createElement(InputHeader, {
284
592
  error
285
- }, /* @__PURE__ */ React4.createElement(Input3.Label, null, label)), /* @__PURE__ */ React4.createElement("div", {
593
+ }, /* @__PURE__ */ React5.createElement(Input3.Label, null, label)), /* @__PURE__ */ React5.createElement("div", {
286
594
  role: "none"
287
- }, options && /* @__PURE__ */ React4.createElement(List.Root, {
595
+ }, options && /* @__PURE__ */ React5.createElement(List.Root, {
288
596
  items: options,
289
597
  isItem: (item) => true,
290
598
  onMove: handleMove
291
- }, ({ items }) => /* @__PURE__ */ React4.createElement("div", {
599
+ }, ({ items }) => /* @__PURE__ */ React5.createElement("div", {
292
600
  role: "list",
293
601
  className: "w-full overflow-auto"
294
- }, items?.map((item) => /* @__PURE__ */ React4.createElement("div", {
602
+ }, items?.map((item) => /* @__PURE__ */ React5.createElement("div", {
295
603
  key: item.id
296
- }, /* @__PURE__ */ React4.createElement(List.Item, {
604
+ }, /* @__PURE__ */ React5.createElement(List.Item, {
297
605
  role: "button",
298
606
  item,
299
607
  classNames: mx2("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
300
608
  "aria-expanded": selected === item.id
301
- }, /* @__PURE__ */ React4.createElement("div", {
609
+ }, /* @__PURE__ */ React5.createElement("div", {
302
610
  className: "flex items-center"
303
- }, /* @__PURE__ */ React4.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React4.createElement(List.ItemTitle, {
611
+ }, /* @__PURE__ */ React5.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React5.createElement(List.ItemTitle, {
304
612
  onClick: () => handleClick(item.id),
305
613
  classNames: "flex-1"
306
- }, /* @__PURE__ */ React4.createElement(Tag, {
614
+ }, /* @__PURE__ */ React5.createElement(Tag, {
307
615
  palette: item.color
308
- }, item.title || "\u200B")), /* @__PURE__ */ React4.createElement(Icon2, {
616
+ }, item.title || "\u200B")), /* @__PURE__ */ React5.createElement(Icon2, {
309
617
  icon: selected === item.id ? "ph--caret-down--regular" : "ph--caret-right--regular",
310
618
  onClick: () => handleClick(item.id)
311
- })), selected === item.id && /* @__PURE__ */ React4.createElement("div", {
619
+ })), selected === item.id && /* @__PURE__ */ React5.createElement("div", {
312
620
  className: "mis-4 mbs-2 flex flex-col gap-1"
313
- }, /* @__PURE__ */ React4.createElement(Input3.Label, {
621
+ }, /* @__PURE__ */ React5.createElement(Input3.Label, {
314
622
  classNames: "text-xs"
315
- }, t("select option label")), /* @__PURE__ */ React4.createElement("div", {
623
+ }, t("select option label")), /* @__PURE__ */ React5.createElement("div", {
316
624
  className: "flex flex-row items-center gap-1"
317
- }, /* @__PURE__ */ React4.createElement(Input3.TextInput, {
625
+ }, /* @__PURE__ */ React5.createElement(Input3.TextInput, {
318
626
  placeholder: t("select option label placeholder"),
319
627
  ref: selected === item.id ? inputRef : void 0,
320
628
  value: item.title,
321
629
  onChange: handleTitleChange(item.id),
322
630
  onKeyDown: handleKeyDown,
323
- classNames: "flex-1"
324
- }), /* @__PURE__ */ React4.createElement(Toolbar.Root, {
631
+ classNames: "flex-1",
632
+ "data-no-submit": true
633
+ }), /* @__PURE__ */ React5.createElement(Toolbar.Root, {
325
634
  classNames: "p-0 m-0 !is-auto"
326
- }, /* @__PURE__ */ React4.createElement(HuePickerToolbarButton, {
327
- hue: item.color,
328
- onChangeHue: handleColorChange(item.id)
329
- })), /* @__PURE__ */ React4.createElement(IconButton, {
635
+ }, /* @__PURE__ */ React5.createElement(HuePicker, {
636
+ value: item.color,
637
+ onChange: handleColorChange(item.id)
638
+ })), /* @__PURE__ */ React5.createElement(IconButton, {
330
639
  icon: "ph--trash--fill",
331
640
  iconOnly: true,
332
641
  label: t("select option delete"),
333
642
  onClick: () => handleDelete(item.id)
334
- })))))), /* @__PURE__ */ React4.createElement("div", {
643
+ })))))), /* @__PURE__ */ React5.createElement("div", {
335
644
  role: "listitem"
336
- }, /* @__PURE__ */ React4.createElement("div", {
645
+ }, /* @__PURE__ */ React5.createElement("div", {
337
646
  role: "button",
338
647
  className: mx2("p-1 plb-2", "flex flex-col", "cursor-pointer", "hover:bg-hoverOverlay"),
339
648
  onClick: handleAdd
340
- }, /* @__PURE__ */ React4.createElement("div", {
649
+ }, /* @__PURE__ */ React5.createElement("div", {
341
650
  className: "flex items-center gap-1"
342
- }, /* @__PURE__ */ React4.createElement(Icon2, {
651
+ }, /* @__PURE__ */ React5.createElement(Icon2, {
343
652
  icon: "ph--plus--regular"
344
- }), /* @__PURE__ */ React4.createElement("span", {
653
+ }), /* @__PURE__ */ React5.createElement("span", {
345
654
  className: "text-sm"
346
655
  }, t("select option add")))))))));
347
656
  };
348
657
 
349
658
  // packages/ui/react-ui-form/src/components/Form/custom/TupleInput.tsx
350
- import React5 from "react";
659
+ import React6 from "react";
351
660
  import { Input as Input4 } from "@dxos/react-ui";
352
661
  import { mx as mx3 } from "@dxos/react-ui-theme";
353
662
  import { safeParseFloat as safeParseFloat2 } from "@dxos/util";
@@ -360,13 +669,13 @@ var gridCols = [
360
669
  var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
361
670
  const { status, error } = getStatus();
362
671
  const values = getValue3() ?? {};
363
- return /* @__PURE__ */ React5.createElement(Input4.Root, {
672
+ return /* @__PURE__ */ React6.createElement(Input4.Root, {
364
673
  validationValence: status
365
- }, /* @__PURE__ */ React5.createElement(InputHeader, {
674
+ }, /* @__PURE__ */ React6.createElement(InputHeader, {
366
675
  error
367
- }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement("div", {
676
+ }, /* @__PURE__ */ React6.createElement(Input4.Label, null, label)), /* @__PURE__ */ React6.createElement("div", {
368
677
  className: mx3("grid gap-2", gridCols[binding.length - 1])
369
- }, binding.map((prop) => /* @__PURE__ */ React5.createElement(Input4.TextInput, {
678
+ }, binding.map((prop) => /* @__PURE__ */ React6.createElement(Input4.TextInput, {
370
679
  key: prop,
371
680
  type: "number",
372
681
  disabled,
@@ -380,291 +689,124 @@ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValu
380
689
  };
381
690
 
382
691
  // packages/ui/react-ui-form/src/components/Form/Defaults.tsx
383
- import React6 from "react";
692
+ import React7, { useCallback as useCallback4, useEffect as useEffect5, useRef as useRef2 } from "react";
384
693
  import { Input as Input5, Select } from "@dxos/react-ui";
385
694
  var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
386
695
  const { status, error } = getStatus();
387
- return /* @__PURE__ */ React6.createElement(Input5.Root, {
696
+ return /* @__PURE__ */ React7.createElement(Input5.Root, {
388
697
  validationValence: status
389
- }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
698
+ }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
390
699
  error
391
- }, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement(Input5.TextInput, {
700
+ }, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.TextInput, {
392
701
  disabled,
393
702
  placeholder,
394
703
  value: getValue3() ?? "",
395
704
  onChange: (event) => onValueChange(type, event.target.value),
396
705
  onBlur
397
- }), inputOnly && /* @__PURE__ */ React6.createElement(Input5.Validation, null, error));
706
+ }), inputOnly && /* @__PURE__ */ React7.createElement(Input5.Validation, null, error));
398
707
  };
399
708
  var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
400
709
  const { status, error } = getStatus();
401
- return /* @__PURE__ */ React6.createElement(Input5.Root, {
710
+ return /* @__PURE__ */ React7.createElement(Input5.Root, {
402
711
  validationValence: status
403
- }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
712
+ }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
404
713
  error
405
- }, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement(Input5.TextInput, {
714
+ }, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.TextInput, {
406
715
  type: "number",
407
716
  disabled,
408
717
  placeholder,
409
718
  value: getValue3() ?? 0,
410
719
  onChange: (event) => onValueChange(type, event.target.value),
411
720
  onBlur
412
- }), inputOnly && /* @__PURE__ */ React6.createElement(Input5.DescriptionAndValidation, null, error));
721
+ }), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
413
722
  };
414
723
  var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
415
724
  const { status, error } = getStatus();
416
- return /* @__PURE__ */ React6.createElement(Input5.Root, {
725
+ const checked = Boolean(getValue3());
726
+ return /* @__PURE__ */ React7.createElement(Input5.Root, {
417
727
  validationValence: status
418
- }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
728
+ }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
419
729
  error
420
- }, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement(Input5.Switch, {
421
- checked: getValue3(),
730
+ }, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.Switch, {
731
+ checked,
422
732
  onCheckedChange: (value) => onValueChange(type, value)
423
- }), inputOnly && /* @__PURE__ */ React6.createElement(Input5.DescriptionAndValidation, null, error));
733
+ }), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
424
734
  };
425
735
  var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
426
736
  const { status, error } = getStatus();
427
- return /* @__PURE__ */ React6.createElement(Input5.Root, {
737
+ return /* @__PURE__ */ React7.createElement(Input5.Root, {
428
738
  validationValence: status
429
- }, !inputOnly && /* @__PURE__ */ React6.createElement(InputHeader, {
739
+ }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
430
740
  error
431
- }, /* @__PURE__ */ React6.createElement(Input5.Label, null, label)), /* @__PURE__ */ React6.createElement(Select.Root, {
741
+ }, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Select.Root, {
432
742
  value: getValue3(),
433
743
  onValueChange: (value) => onValueChange(type, value)
434
- }, /* @__PURE__ */ React6.createElement(Select.TriggerButton, {
744
+ }, /* @__PURE__ */ React7.createElement(Select.TriggerButton, {
435
745
  classNames: "is-full",
436
746
  disabled,
437
747
  placeholder
438
- }), /* @__PURE__ */ React6.createElement(Select.Portal, null, /* @__PURE__ */ React6.createElement(Select.Content, null, /* @__PURE__ */ React6.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
748
+ }), /* @__PURE__ */ React7.createElement(Select.Portal, null, /* @__PURE__ */ React7.createElement(Select.Content, null, /* @__PURE__ */ React7.createElement(Select.Viewport, null, options?.map(({ value, label: label2 }) => (
439
749
  // NOTE: Numeric values are converted to and from strings.
440
- /* @__PURE__ */ React6.createElement(Select.Option, {
750
+ /* @__PURE__ */ React7.createElement(Select.Option, {
441
751
  key: String(value),
442
752
  value: String(value)
443
753
  }, label2 ?? String(value))
444
- )))))), inputOnly && /* @__PURE__ */ React6.createElement(Input5.DescriptionAndValidation, null, error));
754
+ )))))), inputOnly && /* @__PURE__ */ React7.createElement(Input5.DescriptionAndValidation, null, error));
445
755
  };
446
-
447
- // packages/ui/react-ui-form/src/components/Form/Form.tsx
448
- import React11, { useEffect as useEffect3, useMemo as useMemo4 } from "react";
449
- import { mx as mx7 } from "@dxos/react-ui-theme";
450
-
451
- // packages/ui/react-ui-form/src/components/Form/FormActions.tsx
452
- import React8 from "react";
453
- import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
454
- import { mx as mx4 } from "@dxos/react-ui-theme";
455
-
456
- // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
457
- import React7, { createContext, useContext } from "react";
458
- import { raise } from "@dxos/debug";
459
- import { getValue as getValue2 } from "@dxos/echo-schema";
460
- import { createJsonPath as createJsonPath2 } from "@dxos/effect";
461
-
462
- // packages/ui/react-ui-form/src/hooks/useForm.ts
463
- import { useCallback as useCallback2, useEffect as useEffect2, useMemo, useState as useState2 } from "react";
464
- import { getValue, setValue } from "@dxos/echo-schema";
465
- import { AST, createJsonPath, fromEffectValidationPath } from "@dxos/effect";
466
- import { invariant } from "@dxos/invariant";
467
- import { log } from "@dxos/log";
468
- import { validateSchema } from "@dxos/schema";
469
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
470
- var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
471
- invariant(AST.isTypeLiteral(schema.ast), void 0, {
472
- F: __dxlog_file,
473
- L: 91,
474
- S: void 0,
475
- A: [
476
- "AST.isTypeLiteral(schema.ast)",
477
- ""
478
- ]
479
- });
480
- const [values, setValues] = useState2(initialValues);
481
- useEffect2(() => {
482
- setValues(initialValues);
483
- }, [
484
- initialValues
485
- ]);
486
- const [touched, setTouched] = useState2(createKeySet(initialValues, false));
487
- const [changed, setChanged] = useState2(createKeySet(initialValues, false));
488
- const [errors, setErrors] = useState2({});
489
- const [saving, setSaving] = useState2(false);
490
- const validate = useCallback2((values2) => {
491
- let errors2 = validateSchema(schema, values2) ?? [];
492
- if (errors2.length === 0 && onValidate) {
493
- const validatedValues = values2;
494
- errors2 = onValidate(validatedValues) ?? [];
495
- }
496
- setErrors(flatMap(errors2));
497
- const valid = errors2.length === 0;
498
- return valid;
499
- }, [
500
- schema,
501
- onValidate
502
- ]);
503
- const [schemaDirty, setSchemaDirty] = useState2(false);
504
- useEffect2(() => setSchemaDirty(true), [
505
- schema
506
- ]);
507
- useEffect2(() => {
508
- if (schemaDirty) {
509
- validate(values);
510
- setSchemaDirty(false);
511
- }
512
- }, [
513
- values,
514
- schemaDirty
515
- ]);
516
- const canSave = useMemo(() => !saving && // Check if any error paths that are touched have errors
517
- !Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
518
- touched,
519
- errors,
520
- saving
521
- ]);
522
- const handleSave = useCallback2(async () => {
523
- if (validate(values)) {
524
- setSaving(true);
525
- try {
526
- await onSave?.(values, {
527
- changed
528
- });
529
- } finally {
530
- setSaving(false);
531
- }
756
+ var MarkdownInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
757
+ const { status, error } = getStatus();
758
+ const textareaRef = useRef2(null);
759
+ const adjustHeight = useCallback4(() => {
760
+ const textarea = textareaRef.current;
761
+ if (textarea) {
762
+ textarea.style.blockSize = "auto";
763
+ textarea.style.blockSize = `${textarea.scrollHeight + 2}px`;
532
764
  }
765
+ }, []);
766
+ useEffect5(() => {
767
+ adjustHeight();
533
768
  }, [
534
- values,
535
- validate,
536
- onSave,
537
- changed
538
- ]);
539
- const getStatus = useCallback2((path) => {
540
- const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
541
- const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
542
- return {
543
- status: matchingError ? "error" : void 0,
544
- error: matchingError ? matchingError[1] : void 0
545
- };
546
- }, [
547
- errors
769
+ adjustHeight
548
770
  ]);
549
- const getFormValue = (path) => {
550
- return getValue(values, createJsonPath(path));
551
- };
552
- const onValueChange = (path, type, value) => {
553
- const jsonPath = createJsonPath(path);
554
- let parsedValue = value;
555
- try {
556
- if (type === "number") {
557
- parsedValue = parseFloat(value) || 0;
558
- }
559
- } catch (err) {
560
- log.catch(err, void 0, {
561
- F: __dxlog_file,
562
- L: 193,
563
- S: void 0,
564
- C: (f, a) => f(...a)
565
- });
566
- parsedValue = void 0;
567
- }
568
- const newValues = {
569
- ...setValue(values, jsonPath, parsedValue)
570
- };
571
- setValues(newValues);
572
- setChanged((prev) => ({
573
- ...prev,
574
- [jsonPath]: true
575
- }));
576
- onValuesChanged?.(newValues);
577
- const isValid = validate(newValues);
578
- if (isValid && onValid) {
579
- onValid(newValues, {
580
- changed
581
- });
582
- }
583
- };
584
- const onTouched = useCallback2((path) => {
585
- const jsonPath = createJsonPath(path);
586
- setTouched((touched2) => ({
587
- ...touched2,
588
- [jsonPath]: true
589
- }));
590
- validate(values);
771
+ useEffect5(() => {
772
+ adjustHeight();
591
773
  }, [
592
- validate,
593
- values
774
+ getValue3(),
775
+ adjustHeight
594
776
  ]);
595
- return {
596
- // State.
597
- values,
598
- errors,
599
- touched,
600
- changed,
601
- canSave,
602
- handleSave,
603
- // Field utils.
604
- getStatus,
605
- getValue: getFormValue,
606
- onValueChange,
607
- onTouched
608
- };
609
- };
610
- var createKeySet = (obj, value) => {
611
- invariant(obj, void 0, {
612
- F: __dxlog_file,
613
- L: 235,
614
- S: void 0,
615
- A: [
616
- "obj",
617
- ""
618
- ]
619
- });
620
- return Object.keys(obj).reduce((acc, key) => ({
621
- ...acc,
622
- [key]: value
623
- }), {});
624
- };
625
- var flatMap = (errors) => {
626
- return errors.reduce((result, { path, message }) => {
627
- const jsonPath = fromEffectValidationPath(path);
628
- if (!(jsonPath in result)) {
629
- result[jsonPath] = message;
630
- }
631
- return result;
632
- }, {});
777
+ return /* @__PURE__ */ React7.createElement(Input5.Root, {
778
+ validationValence: status
779
+ }, !inputOnly && /* @__PURE__ */ React7.createElement(InputHeader, {
780
+ error
781
+ }, /* @__PURE__ */ React7.createElement(Input5.Label, null, label)), /* @__PURE__ */ React7.createElement(Input5.TextArea, {
782
+ ref: textareaRef,
783
+ disabled,
784
+ placeholder,
785
+ value: getValue3() ?? "",
786
+ classNames: "min-bs-auto max-h-40 overflow-auto",
787
+ onChange: (event) => onValueChange(type, event.target.value),
788
+ onBlur,
789
+ style: {
790
+ resize: "none"
791
+ },
792
+ spellCheck: false
793
+ }), inputOnly && /* @__PURE__ */ React7.createElement(Input5.Validation, null, error));
633
794
  };
634
795
 
635
- // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
636
- var FormContext = /* @__PURE__ */ createContext(void 0);
637
- var useFormContext = () => {
638
- return useContext(FormContext) ?? raise(new Error("Missing FormContext"));
639
- };
640
- var useFormValues = (path = []) => {
641
- const { values: formValues } = useFormContext();
642
- const jsonPath = createJsonPath2(path);
643
- return getValue2(formValues, jsonPath);
644
- };
645
- var useInputProps = (path = []) => {
646
- const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
647
- return {
648
- getStatus: () => getStatus(path),
649
- getValue: () => getFormValue(path),
650
- onValueChange: (type, value) => onValueChange(path, type, value),
651
- onBlur: () => onTouched(path)
652
- };
653
- };
654
- var FormProvider = ({ children, ...formOptions }) => {
655
- const formHandler = useForm(formOptions);
656
- return /* @__PURE__ */ React7.createElement(FormContext.Provider, {
657
- value: formHandler
658
- }, children);
659
- };
796
+ // packages/ui/react-ui-form/src/components/Form/Form.tsx
797
+ import React11, { useEffect as useEffect6, useMemo as useMemo6, useRef as useRef3 } from "react";
798
+ import { mx as mx7 } from "@dxos/react-ui-theme";
660
799
 
661
800
  // packages/ui/react-ui-form/src/components/Form/FormActions.tsx
801
+ import React8 from "react";
802
+ import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
803
+ import { mx as mx4 } from "@dxos/react-ui-theme";
662
804
  var FormActions = ({ onCancel, readonly }) => {
663
805
  const { t } = useTranslation3(translationKey);
664
806
  const { canSave, handleSave } = useFormContext();
665
807
  return /* @__PURE__ */ React8.createElement("div", {
666
808
  role: "none",
667
- className: "flex justify-center"
809
+ className: "mt-2 flex justify-center"
668
810
  }, /* @__PURE__ */ React8.createElement("div", {
669
811
  role: "none",
670
812
  className: mx4(onCancel && !readonly && "grid grid-cols-2 gap-2")
@@ -686,7 +828,7 @@ var FormActions = ({ onCancel, readonly }) => {
686
828
  // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
687
829
  import { pipe as pipe2 } from "effect";
688
830
  import { capitalize as capitalize2 } from "effect/String";
689
- import React10, { useMemo as useMemo3 } from "react";
831
+ import React10, { useMemo as useMemo5 } from "react";
690
832
  import { AST as AST3, S } from "@dxos/echo-schema";
691
833
  import { createJsonPath as createJsonPath3, findNode as findNode2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
692
834
  import { mx as mx6 } from "@dxos/react-ui-theme";
@@ -696,7 +838,7 @@ import { isNotFalsy } from "@dxos/util";
696
838
  // packages/ui/react-ui-form/src/components/Form/ArrayField.tsx
697
839
  import { pipe } from "effect";
698
840
  import { capitalize } from "effect/String";
699
- import React9, { useCallback as useCallback3, useMemo as useMemo2 } from "react";
841
+ import React9, { useCallback as useCallback5, useMemo as useMemo4 } from "react";
700
842
  import { AST as AST2 } from "@dxos/echo-schema";
701
843
  import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
702
844
  import { invariant as invariant2 } from "@dxos/invariant";
@@ -732,7 +874,7 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
732
874
  prop.defaultValue
733
875
  ]));
734
876
  };
735
- const newValue = useMemo2(() => {
877
+ const newValue = useMemo4(() => {
736
878
  if (type === "object" && elementType) {
737
879
  return getDefaultObjectValue(elementType);
738
880
  } else {
@@ -742,7 +884,7 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
742
884
  type,
743
885
  elementType
744
886
  ]);
745
- const handleAdd = useCallback3(() => {
887
+ const handleAdd = useCallback5(() => {
746
888
  inputProps.onValueChange(type, [
747
889
  ...values,
748
890
  newValue
@@ -754,7 +896,7 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
754
896
  newValue,
755
897
  values
756
898
  ]);
757
- const handleRemove = useCallback3((index) => {
899
+ const handleRemove = useCallback5((index) => {
758
900
  const newValues = values.filter((_, i) => i !== index);
759
901
  inputProps.onValueChange(type, newValues);
760
902
  }, [
@@ -812,8 +954,10 @@ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponen
812
954
  import { FormatEnum } from "@dxos/echo-schema";
813
955
  var getInputComponent = (type, format) => {
814
956
  switch (format) {
815
- case FormatEnum.LatLng:
957
+ case FormatEnum.GeoPoint:
816
958
  return GeoPointInput;
959
+ case FormatEnum.Markdown:
960
+ return MarkdownInput;
817
961
  }
818
962
  switch (type) {
819
963
  case "string":
@@ -829,11 +973,11 @@ var getInputComponent = (type, format) => {
829
973
  var FormField = ({ property, path, readonly, inline, lookupComponent, Custom }) => {
830
974
  const inputProps = useInputProps(path);
831
975
  const { ast, name, type, format, title, description, options, examples, array } = property;
832
- const label = useMemo3(() => title ?? pipe2(name, capitalize2), [
976
+ const label = useMemo5(() => title ?? pipe2(name, capitalize2), [
833
977
  title,
834
978
  name
835
979
  ]);
836
- const placeholder = useMemo3(() => examples?.length ? `Example: "${examples[0]}"` : description, [
980
+ const placeholder = useMemo5(() => examples?.length ? `Example: "${examples[0]}"` : description, [
837
981
  examples,
838
982
  description
839
983
  ]);
@@ -857,20 +1001,15 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
857
1001
  const jsonPath = createJsonPath3(path ?? []);
858
1002
  const CustomComponent = Custom?.[jsonPath];
859
1003
  if (CustomComponent) {
860
- return (
861
- // TODO(ZaymonFC): We should try to remove this div wrapper.
862
- /* @__PURE__ */ React10.createElement("div", {
863
- role: "none"
864
- }, /* @__PURE__ */ React10.createElement(CustomComponent, {
865
- type,
866
- format,
867
- label,
868
- inputOnly: inline,
869
- placeholder,
870
- disabled: readonly,
871
- ...inputProps
872
- }))
873
- );
1004
+ return /* @__PURE__ */ React10.createElement(CustomComponent, {
1005
+ type,
1006
+ format,
1007
+ label,
1008
+ inputOnly: inline,
1009
+ placeholder,
1010
+ disabled: readonly,
1011
+ ...inputProps
1012
+ });
874
1013
  }
875
1014
  if (array) {
876
1015
  return /* @__PURE__ */ React10.createElement(ArrayField, {
@@ -930,7 +1069,7 @@ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom })
930
1069
  };
931
1070
  var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custom }) => {
932
1071
  const values = useFormValues(path);
933
- const properties = useMemo3(() => {
1072
+ const properties = useMemo5(() => {
934
1073
  const props = getSchemaProperties2(schema.ast, values);
935
1074
  const filtered = filter ? filter(props) : props;
936
1075
  return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
@@ -942,7 +1081,7 @@ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custo
942
1081
  ]);
943
1082
  return /* @__PURE__ */ React10.createElement("div", {
944
1083
  role: "form",
945
- className: mx6("flex flex-col w-full gap-2 py-2")
1084
+ className: mx6("flex flex-col w-full gap-2")
946
1085
  }, properties.map((property) => {
947
1086
  return /* @__PURE__ */ React10.createElement(FormField, {
948
1087
  key: property.name,
@@ -960,13 +1099,14 @@ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custo
960
1099
 
961
1100
  // packages/ui/react-ui-form/src/components/Form/Form.tsx
962
1101
  var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
963
- const onValid = useMemo4(() => autoSave ? onSave : void 0, [
1102
+ const formRef = useRef3(null);
1103
+ const onValid = useMemo6(() => autoSave ? onSave : void 0, [
964
1104
  autoSave,
965
1105
  onSave
966
1106
  ]);
967
- useEffect3(() => {
968
- if (autoFocus) {
969
- const input = document.querySelector("input");
1107
+ useEffect6(() => {
1108
+ if (autoFocus && formRef.current) {
1109
+ const input = formRef.current.querySelector("input");
970
1110
  if (input) {
971
1111
  input.focus();
972
1112
  }
@@ -975,13 +1115,16 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
975
1115
  autoFocus
976
1116
  ]);
977
1117
  return /* @__PURE__ */ React11.createElement(FormProvider, {
1118
+ formRef,
978
1119
  schema,
1120
+ autoSave,
979
1121
  initialValues,
980
1122
  onValuesChanged,
981
1123
  onValidate,
982
1124
  onValid,
983
1125
  onSave
984
1126
  }, /* @__PURE__ */ React11.createElement("div", {
1127
+ ref: formRef,
985
1128
  role: "none",
986
1129
  className: mx7("p-2", classNames),
987
1130
  "data-testid": testId
@@ -1003,13 +1146,13 @@ var Form = ({ classNames, schema, values: initialValues, path = [], autoFocus, r
1003
1146
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
1004
1147
  var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1005
1148
  const { t } = useTranslation5(translationKey);
1006
- const [props, setProps] = useState3(projection.getFieldProjection(field.id).props);
1007
- useEffect4(() => setProps(projection.getFieldProjection(field.id).props), [
1149
+ const [props, setProps] = useState4(projection.getFieldProjection(field.id).props);
1150
+ useEffect7(() => setProps(projection.getFieldProjection(field.id).props), [
1008
1151
  field,
1009
1152
  projection
1010
1153
  ]);
1011
- const [schemas, setSchemas] = useState3([]);
1012
- useEffect4(() => {
1154
+ const [schemas, setSchemas] = useState4([]);
1155
+ useEffect7(() => {
1013
1156
  if (!registry) {
1014
1157
  return;
1015
1158
  }
@@ -1027,17 +1170,17 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1027
1170
  }, [
1028
1171
  registry
1029
1172
  ]);
1030
- const [referenceSchema, setReferenceSchema] = useState3();
1031
- useEffect4(() => {
1173
+ const [referenceSchema, setReferenceSchema] = useState4();
1174
+ useEffect7(() => {
1032
1175
  setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
1033
1176
  }, [
1034
1177
  schemas,
1035
1178
  props?.referenceSchema
1036
1179
  ]);
1037
- const [{ fieldSchema }, setFieldSchema] = useState3({
1180
+ const [{ fieldSchema }, setFieldSchema] = useState4({
1038
1181
  fieldSchema: getFormatSchema(props?.format)
1039
1182
  });
1040
- const handleValuesChanged = useCallback4((_props) => {
1183
+ const handleValuesChanged = useCallback6((_props) => {
1041
1184
  setFieldSchema((prev) => {
1042
1185
  const fieldSchema2 = getFormatSchema(_props.format);
1043
1186
  if (prev.fieldSchema === fieldSchema2) {
@@ -1072,7 +1215,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1072
1215
  props.format,
1073
1216
  props.referenceSchema
1074
1217
  ]);
1075
- const handleValidate = useCallback4(({ property }) => {
1218
+ const handleValidate = useCallback6(({ property }) => {
1076
1219
  if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
1077
1220
  return [
1078
1221
  {
@@ -1085,7 +1228,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1085
1228
  view.fields,
1086
1229
  field
1087
1230
  ]);
1088
- const handleSave = useCallback4((props2) => {
1231
+ const handleSave = useCallback6((props2) => {
1089
1232
  projection.setFieldProjection({
1090
1233
  field,
1091
1234
  props: props2
@@ -1096,13 +1239,13 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1096
1239
  field,
1097
1240
  onSave
1098
1241
  ]);
1099
- const handleCancel = useCallback4(() => {
1242
+ const handleCancel = useCallback6(() => {
1100
1243
  requestAnimationFrame(() => onCancel?.());
1101
1244
  onSave();
1102
1245
  }, [
1103
1246
  onSave
1104
1247
  ]);
1105
- const Custom = useMemo5(() => ({
1248
+ const Custom = useMemo7(() => ({
1106
1249
  ["format"]: (props2) => /* @__PURE__ */ React12.createElement(SelectInput, {
1107
1250
  ...props2,
1108
1251
  options: FormatEnums.filter((value) => value !== FormatEnum2.None).map((value) => ({
@@ -1128,7 +1271,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1128
1271
  schemas,
1129
1272
  referenceSchema
1130
1273
  ]);
1131
- const propIsNotType = useCallback4((props2) => props2.filter((p) => p.name !== "type"), []);
1274
+ const propIsNotType = useCallback6((props2) => props2.filter((p) => p.name !== "type"), []);
1132
1275
  if (!fieldSchema) {
1133
1276
  log2.warn("invalid format", {
1134
1277
  props
@@ -1159,7 +1302,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
1159
1302
  };
1160
1303
 
1161
1304
  // packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
1162
- import React13, { useCallback as useCallback5, useMemo as useMemo6, useState as useState4 } from "react";
1305
+ import React13, { useCallback as useCallback7, useMemo as useMemo8, useState as useState5 } from "react";
1163
1306
  import { AST as AST4, Format, S as S2 } from "@dxos/echo-schema";
1164
1307
  import { IconButton as IconButton4, useTranslation as useTranslation6 } from "@dxos/react-ui";
1165
1308
  import { List as List2 } from "@dxos/react-ui-list";
@@ -1170,18 +1313,18 @@ var ViewMetaSchema = S2.Struct({
1170
1313
  name: S2.String.annotations({
1171
1314
  [AST4.TitleAnnotationId]: "View"
1172
1315
  }),
1173
- typename: Format.DXN.annotations({
1316
+ typename: Format.URL.annotations({
1174
1317
  [AST4.TitleAnnotationId]: "Typename"
1175
1318
  })
1176
1319
  }).pipe(S2.mutable);
1177
1320
  var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
1178
1321
  const { t } = useTranslation6(translationKey);
1179
- const projection = useMemo6(() => new ViewProjection(schema, view), [
1322
+ const projection = useMemo8(() => new ViewProjection(schema, view), [
1180
1323
  schema,
1181
1324
  view
1182
1325
  ]);
1183
- const [field, setField] = useState4();
1184
- const viewValues = useMemo6(() => {
1326
+ const [field, setField] = useState5();
1327
+ const viewValues = useMemo8(() => {
1185
1328
  return {
1186
1329
  name: view.name,
1187
1330
  // TODO(burdon): Need to warn user of possible consequences of editing.
@@ -1191,7 +1334,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1191
1334
  }, [
1192
1335
  view
1193
1336
  ]);
1194
- const handleViewUpdate = useCallback5(({ name, typename }) => {
1337
+ const handleViewUpdate = useCallback7(({ name, typename }) => {
1195
1338
  requestAnimationFrame(() => {
1196
1339
  if (view.name !== name) {
1197
1340
  view.name = name;
@@ -1205,16 +1348,16 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1205
1348
  schema,
1206
1349
  onTypenameChanged
1207
1350
  ]);
1208
- const handleSelect = useCallback5((field2) => {
1351
+ const handleSelect = useCallback7((field2) => {
1209
1352
  setField((f) => f === field2 ? void 0 : field2);
1210
1353
  }, []);
1211
- const handleAdd = useCallback5(() => {
1354
+ const handleAdd = useCallback7(() => {
1212
1355
  const field2 = projection.createFieldProjection();
1213
1356
  setField(field2);
1214
1357
  }, [
1215
1358
  view
1216
1359
  ]);
1217
- const handleMove = useCallback5((fromIndex, toIndex) => {
1360
+ const handleMove = useCallback7((fromIndex, toIndex) => {
1218
1361
  const fields = [
1219
1362
  ...view.fields
1220
1363
  ];
@@ -1224,12 +1367,11 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1224
1367
  }, [
1225
1368
  view.fields
1226
1369
  ]);
1227
- const handleClose = useCallback5(() => setField(void 0), []);
1370
+ const handleClose = useCallback7(() => setField(void 0), []);
1228
1371
  return /* @__PURE__ */ React13.createElement("div", {
1229
1372
  role: "none",
1230
1373
  className: mx8("flex flex-col w-full divide-y divide-separator", classNames)
1231
1374
  }, /* @__PURE__ */ React13.createElement(Form, {
1232
- autoFocus: true,
1233
1375
  autoSave: true,
1234
1376
  schema: ViewMetaSchema,
1235
1377
  values: viewValues,
@@ -1280,7 +1422,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
1280
1422
  };
1281
1423
 
1282
1424
  // packages/ui/react-ui-form/src/util/field.ts
1283
- import { FormatEnum as FormatEnum3, TypeEnum } from "@dxos/echo-schema";
1425
+ import { FormatEnum as FormatEnum3, GeoLocation as GeoLocation2, TypeEnum } from "@dxos/echo-schema";
1284
1426
  var parseValue = ({ type, format, value }) => {
1285
1427
  if (value === void 0 || value === null || value === "") {
1286
1428
  return void 0;
@@ -1334,6 +1476,26 @@ var parseValue = ({ type, format, value }) => {
1334
1476
  const date = new Date(value);
1335
1477
  return isNaN(date.getTime()) ? null : date;
1336
1478
  }
1479
+ case FormatEnum3.GeoPoint: {
1480
+ if (typeof value === "string") {
1481
+ const cleaned = value.replace(/[^0-9.,-]+/g, "");
1482
+ const parts = cleaned.split(",");
1483
+ if (parts.length === 2) {
1484
+ const lat = parseFloat(parts[0]);
1485
+ const long = parseFloat(parts[1]);
1486
+ if (!isNaN(lat) && !isNaN(long)) {
1487
+ return GeoLocation2.toGeoPoint({
1488
+ latitude: lat,
1489
+ longitude: long
1490
+ });
1491
+ }
1492
+ }
1493
+ }
1494
+ return [
1495
+ 0,
1496
+ 0
1497
+ ];
1498
+ }
1337
1499
  default: {
1338
1500
  return value;
1339
1501
  }
@@ -1392,7 +1554,7 @@ var pathNotUniqueError = (path) => ({
1392
1554
  });
1393
1555
 
1394
1556
  // packages/ui/react-ui-form/src/util/formatting.ts
1395
- import { FormatEnum as FormatEnum4, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
1557
+ import { FormatEnum as FormatEnum4, GeoLocation as GeoLocation3, TypeEnum as TypeEnum2 } from "@dxos/echo-schema";
1396
1558
  var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1397
1559
  const formatScalar = (type2) => {
1398
1560
  switch (type2) {
@@ -1445,6 +1607,16 @@ var formatForDisplay = ({ type, format, value, locale = void 0 }) => {
1445
1607
  return date.toLocaleTimeString(locale);
1446
1608
  }
1447
1609
  }
1610
+ case FormatEnum4.GeoPoint: {
1611
+ if (value === null || value === void 0) {
1612
+ return "";
1613
+ }
1614
+ if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1615
+ const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
1616
+ return `${latitude},${longitude}`;
1617
+ }
1618
+ return String(value);
1619
+ }
1448
1620
  default: {
1449
1621
  if (value === null || value === "undefined") {
1450
1622
  return "";
@@ -1493,6 +1665,16 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1493
1665
  const date = new Date(value);
1494
1666
  return date.toISOString().split("T")[1].split(".")[0];
1495
1667
  }
1668
+ case FormatEnum4.GeoPoint: {
1669
+ if (value === null || value === void 0) {
1670
+ return "";
1671
+ }
1672
+ if (Array.isArray(value) && value.length >= 2 && value.every(Number.isFinite)) {
1673
+ const { latitude, longitude } = GeoLocation3.fromGeoPoint(value);
1674
+ return `${latitude},${longitude}`;
1675
+ }
1676
+ return String(value);
1677
+ }
1496
1678
  default: {
1497
1679
  return String(value);
1498
1680
  }
@@ -1506,6 +1688,7 @@ export {
1506
1688
  Form,
1507
1689
  GeoPointInput,
1508
1690
  InputHeader,
1691
+ MarkdownInput,
1509
1692
  NumberInput,
1510
1693
  SelectInput,
1511
1694
  SelectOptionInput,
@@ -1519,6 +1702,7 @@ export {
1519
1702
  parseValue,
1520
1703
  pathNotUniqueError,
1521
1704
  translations_default as translations,
1522
- useForm
1705
+ useForm,
1706
+ useFormValues
1523
1707
  };
1524
1708
  //# sourceMappingURL=index.mjs.map