@dxos/react-ui-form 0.7.5-feature-compute.4d9d99a → 0.7.5-labs.a279d8c

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 (47) hide show
  1. package/dist/lib/browser/index.mjs +416 -409
  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 +461 -469
  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 +416 -409
  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/Form/ArrayField.d.ts +16 -0
  11. package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -0
  12. package/dist/types/src/components/Form/Defaults.d.ts +5 -6
  13. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  14. package/dist/types/src/components/Form/Form.d.ts +10 -20
  15. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Form.stories.d.ts +2 -1
  17. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/FormActions.d.ts +7 -0
  19. package/dist/types/src/components/Form/FormActions.d.ts.map +1 -0
  20. package/dist/types/src/components/Form/FormContent.d.ts +26 -0
  21. package/dist/types/src/components/Form/FormContent.d.ts.map +1 -0
  22. package/dist/types/src/components/Form/FormContext.d.ts +20 -0
  23. package/dist/types/src/components/Form/FormContext.d.ts.map +1 -0
  24. package/dist/types/src/components/Form/Input.d.ts +5 -6
  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/TupleInput.d.ts +1 -2
  29. package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
  30. package/dist/types/src/components/Form/factory.d.ts +2 -2
  31. package/dist/types/src/components/Form/factory.d.ts.map +1 -1
  32. package/dist/types/src/hooks/useForm.d.ts +9 -10
  33. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  34. package/package.json +23 -23
  35. package/src/components/FieldEditor/FieldEditor.tsx +4 -4
  36. package/src/components/Form/ArrayField.tsx +111 -0
  37. package/src/components/Form/Defaults.tsx +18 -33
  38. package/src/components/Form/Form.stories.tsx +15 -5
  39. package/src/components/Form/Form.tsx +37 -359
  40. package/src/components/Form/FormActions.tsx +41 -0
  41. package/src/components/Form/FormContent.tsx +155 -0
  42. package/src/components/Form/FormContext.tsx +48 -0
  43. package/src/components/Form/Input.tsx +5 -6
  44. package/src/components/Form/custom/GeoPointInput.tsx +6 -15
  45. package/src/components/Form/custom/TupleInput.tsx +5 -9
  46. package/src/components/Form/factory.tsx +2 -5
  47. package/src/hooks/useForm.ts +54 -46
@@ -80,11 +80,11 @@ var DeprecatedFormInput = ({ label, description, secondary, children }) => {
80
80
  };
81
81
 
82
82
  // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
83
- import React7, { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo3, useState as useState2 } from "react";
83
+ import React11, { useCallback as useCallback3, useEffect as useEffect2, useMemo as useMemo5, useState as useState2 } from "react";
84
84
  import { FormatEnum as FormatEnum2, FormatEnums, formatToType } from "@dxos/echo-schema";
85
- import { log as log3 } from "@dxos/log";
86
- import { useTranslation as useTranslation3 } from "@dxos/react-ui";
87
- import { getFormatSchema, getSchemaProperties as getSchemaProperties2, sortProperties } from "@dxos/schema";
85
+ import { log as log2 } from "@dxos/log";
86
+ import { useTranslation as useTranslation4 } from "@dxos/react-ui";
87
+ import { getFormatSchema, getSchemaProperties as getSchemaProperties3, sortProperties } from "@dxos/schema";
88
88
 
89
89
  // packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
90
90
  import React3 from "react";
@@ -111,10 +111,10 @@ var InputHeader = ({ children, error }) => {
111
111
  };
112
112
 
113
113
  // packages/ui/react-ui-form/src/components/Form/custom/GeoPointInput.tsx
114
- var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
114
+ var GeoPointInput = ({ type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
115
115
  const { t } = useTranslation(translationKey);
116
- const { status, error } = getStatus?.(property);
117
- const [lng = 0, lat = 0] = getValue2(property) ?? [];
116
+ const { status, error } = getStatus();
117
+ const [lng = 0, lat = 0] = getValue3() ?? [];
118
118
  return /* @__PURE__ */ React3.createElement(Input2.Root, {
119
119
  validationValence: status
120
120
  }, /* @__PURE__ */ React3.createElement(InputHeader, {
@@ -126,7 +126,7 @@ var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: get
126
126
  disabled,
127
127
  placeholder: t("placeholder longitude"),
128
128
  value: lng,
129
- onChange: (event) => onValueChange(property, type, [
129
+ onChange: (event) => onValueChange(type, [
130
130
  lat,
131
131
  safeParseFloat(event.target.value, 0)
132
132
  ]),
@@ -136,7 +136,7 @@ var GeoPointInput = ({ property, type, label, disabled, getStatus, getValue: get
136
136
  disabled,
137
137
  placeholder: t("placeholder latitude"),
138
138
  value: lat,
139
- onChange: (event) => onValueChange(property, type, [
139
+ onChange: (event) => onValueChange(type, [
140
140
  safeParseFloat(event.target.value, 0),
141
141
  lng
142
142
  ]),
@@ -155,9 +155,9 @@ var gridCols = [
155
155
  "grid-cols-3",
156
156
  "grid-cols-4"
157
157
  ];
158
- var TupleInput = ({ binding, property, type, label, disabled, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
159
- const { status, error } = getStatus?.(property);
160
- const values = getValue2(property) ?? {};
158
+ var TupleInput = ({ binding, type, label, disabled, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
159
+ const { status, error } = getStatus();
160
+ const values = getValue3() ?? {};
161
161
  return /* @__PURE__ */ React4.createElement(Input3.Root, {
162
162
  validationValence: status
163
163
  }, /* @__PURE__ */ React4.createElement(InputHeader, {
@@ -169,7 +169,7 @@ var TupleInput = ({ binding, property, type, label, disabled, getStatus, getValu
169
169
  type: "number",
170
170
  disabled,
171
171
  value: values[prop],
172
- onChange: (event) => onValueChange(property, type, {
172
+ onChange: (event) => onValueChange(type, {
173
173
  ...values,
174
174
  [prop]: safeParseFloat2(event.target.value, 0)
175
175
  }),
@@ -180,8 +180,8 @@ var TupleInput = ({ binding, property, type, label, disabled, getStatus, getValu
180
180
  // packages/ui/react-ui-form/src/components/Form/Defaults.tsx
181
181
  import React5 from "react";
182
182
  import { Input as Input4, Select } from "@dxos/react-ui";
183
- var TextInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
184
- const { status, error } = getStatus?.(property);
183
+ var TextInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
184
+ const { status, error } = getStatus();
185
185
  return /* @__PURE__ */ React5.createElement(Input4.Root, {
186
186
  validationValence: status
187
187
  }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
@@ -189,13 +189,13 @@ var TextInput = ({ property, type, label, inputOnly, disabled, placeholder, getS
189
189
  }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Input4.TextInput, {
190
190
  disabled,
191
191
  placeholder,
192
- value: getValue2(property) ?? "",
193
- onChange: (event) => onValueChange(property, type, event.target.value),
192
+ value: getValue3() ?? "",
193
+ onChange: (event) => onValueChange(type, event.target.value),
194
194
  onBlur
195
195
  }), inputOnly && /* @__PURE__ */ React5.createElement(Input4.Validation, null, error));
196
196
  };
197
- var NumberInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue2, onValueChange, onBlur }) => {
198
- const { status, error } = getStatus?.(property);
197
+ var NumberInput = ({ type, label, inputOnly, disabled, placeholder, getStatus, getValue: getValue3, onValueChange, onBlur }) => {
198
+ const { status, error } = getStatus();
199
199
  return /* @__PURE__ */ React5.createElement(Input4.Root, {
200
200
  validationValence: status
201
201
  }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
@@ -204,31 +204,31 @@ var NumberInput = ({ property, type, label, inputOnly, disabled, placeholder, ge
204
204
  type: "number",
205
205
  disabled,
206
206
  placeholder,
207
- value: getValue2(property) ?? 0,
208
- onChange: (event) => onValueChange(property, type, event.target.value),
207
+ value: getValue3() ?? 0,
208
+ onChange: (event) => onValueChange(type, event.target.value),
209
209
  onBlur
210
210
  }), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
211
211
  };
212
- var BooleanInput = ({ property, type, label, inputOnly, getStatus, getValue: getValue2, onValueChange }) => {
213
- const { status, error } = getStatus?.(property);
212
+ var BooleanInput = ({ type, label, inputOnly, getStatus, getValue: getValue3, onValueChange }) => {
213
+ const { status, error } = getStatus();
214
214
  return /* @__PURE__ */ React5.createElement(Input4.Root, {
215
215
  validationValence: status
216
216
  }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
217
217
  error
218
218
  }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Input4.Switch, {
219
- checked: getValue2(property),
220
- onCheckedChange: (value) => onValueChange(property, type, value)
219
+ checked: getValue3(),
220
+ onCheckedChange: (value) => onValueChange(type, value)
221
221
  }), inputOnly && /* @__PURE__ */ React5.createElement(Input4.DescriptionAndValidation, null, error));
222
222
  };
223
- var SelectInput = ({ property, type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue2, onValueChange }) => {
224
- const { status, error } = getStatus?.(property);
223
+ var SelectInput = ({ type, label, inputOnly, disabled, placeholder, options, getStatus, getValue: getValue3, onValueChange }) => {
224
+ const { status, error } = getStatus();
225
225
  return /* @__PURE__ */ React5.createElement(Input4.Root, {
226
226
  validationValence: status
227
227
  }, !inputOnly && /* @__PURE__ */ React5.createElement(InputHeader, {
228
228
  error
229
229
  }, /* @__PURE__ */ React5.createElement(Input4.Label, null, label)), /* @__PURE__ */ React5.createElement(Select.Root, {
230
- value: getValue2(property),
231
- onValueChange: (value) => onValueChange(property, type, value)
230
+ value: getValue3(),
231
+ onValueChange: (value) => onValueChange(type, value)
232
232
  }, /* @__PURE__ */ React5.createElement(Select.TriggerButton, {
233
233
  classNames: "is-full",
234
234
  disabled,
@@ -243,38 +243,24 @@ var SelectInput = ({ property, type, label, inputOnly, disabled, placeholder, op
243
243
  };
244
244
 
245
245
  // packages/ui/react-ui-form/src/components/Form/Form.tsx
246
- import { pipe } from "effect";
247
- import { capitalize } from "effect/String";
248
- import React6, { useEffect as useEffect2, useMemo as useMemo2 } from "react";
249
- import { AST as AST2, S } from "@dxos/echo-schema";
250
- import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
251
- import { log as log2 } from "@dxos/log";
246
+ import React10, { useMemo as useMemo4 } from "react";
247
+ import { mx as mx5 } from "@dxos/react-ui-theme";
248
+
249
+ // packages/ui/react-ui-form/src/components/Form/FormActions.tsx
250
+ import React7 from "react";
252
251
  import { IconButton, useTranslation as useTranslation2 } from "@dxos/react-ui";
253
252
  import { mx as mx2 } from "@dxos/react-ui-theme";
254
- import { getSchemaProperties } from "@dxos/schema";
255
- import { isNotFalsy } from "@dxos/util";
256
253
 
257
- // packages/ui/react-ui-form/src/components/Form/factory.tsx
258
- import { FormatEnum } from "@dxos/echo-schema";
259
- var getInputComponent = (type, format) => {
260
- switch (format) {
261
- case FormatEnum.LatLng:
262
- return GeoPointInput;
263
- }
264
- switch (type) {
265
- case "string":
266
- return TextInput;
267
- case "number":
268
- return NumberInput;
269
- case "boolean":
270
- return BooleanInput;
271
- }
272
- };
254
+ // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
255
+ import React6, { createContext, useContext } from "react";
256
+ import { raise } from "@dxos/debug";
257
+ import { getValue as getValue2 } from "@dxos/echo-schema";
258
+ import { createJsonPath as createJsonPath2 } from "@dxos/effect";
273
259
 
274
260
  // packages/ui/react-ui-form/src/hooks/useForm.ts
275
261
  import { useCallback, useEffect, useMemo, useState } from "react";
276
262
  import { getValue, setValue } from "@dxos/echo-schema";
277
- import { AST } from "@dxos/effect";
263
+ import { AST, createJsonPath, fromEffectValidationPath } from "@dxos/effect";
278
264
  import { invariant } from "@dxos/invariant";
279
265
  import { log } from "@dxos/log";
280
266
  import { validateSchema } from "@dxos/schema";
@@ -325,8 +311,8 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
325
311
  values,
326
312
  schemaDirty
327
313
  ]);
328
- const canSave = useMemo(() => !saving && Object.keys(values).every((property) => touched[property] === false || !errors[property]), [
329
- values,
314
+ const canSave = useMemo(() => !saving && // Check if any error paths that are touched have errors
315
+ !Object.entries(touched).some(([path, isTouched]) => isTouched && Object.keys(errors).some((errorPath) => errorPath === path || errorPath.startsWith(`${path}.`) || errorPath.startsWith(`${path}[`))), [
330
316
  touched,
331
317
  errors,
332
318
  saving
@@ -348,17 +334,21 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
348
334
  onSave,
349
335
  changed
350
336
  ]);
351
- const getStatus = useCallback((property) => ({
352
- status: errors[property] ? "error" : void 0,
353
- error: errors[property] ? errors[property] : void 0
354
- }), [
355
- touched,
337
+ const getStatus = useCallback((path) => {
338
+ const jsonPath = Array.isArray(path) ? createJsonPath(path) : path;
339
+ const matchingError = Object.entries(errors).find(([errorPath]) => errorPath === jsonPath || errorPath.startsWith(`${jsonPath}.`) || errorPath.startsWith(`${jsonPath}[`));
340
+ return {
341
+ status: matchingError ? "error" : void 0,
342
+ error: matchingError ? matchingError[1] : void 0
343
+ };
344
+ }, [
356
345
  errors
357
346
  ]);
358
- const getFormValue = (property) => {
359
- return getValue(values, property);
347
+ const getFormValue = (path) => {
348
+ return getValue(values, createJsonPath(path));
360
349
  };
361
- const onValueChange = (property, type, value) => {
350
+ const onValueChange = (path, type, value) => {
351
+ const jsonPath = createJsonPath(path);
362
352
  let parsedValue = value;
363
353
  try {
364
354
  if (type === "number") {
@@ -367,19 +357,19 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
367
357
  } catch (err) {
368
358
  log.catch(err, void 0, {
369
359
  F: __dxlog_file,
370
- L: 179,
360
+ L: 194,
371
361
  S: void 0,
372
362
  C: (f, a) => f(...a)
373
363
  });
374
364
  parsedValue = void 0;
375
365
  }
376
366
  const newValues = {
377
- ...setValue(values, property, parsedValue)
367
+ ...setValue(values, jsonPath, parsedValue)
378
368
  };
379
369
  setValues(newValues);
380
370
  setChanged((prev) => ({
381
371
  ...prev,
382
- [property]: true
372
+ [jsonPath]: true
383
373
  }));
384
374
  onValuesChanged?.(newValues);
385
375
  const isValid = validate(newValues);
@@ -389,15 +379,12 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
389
379
  });
390
380
  }
391
381
  };
392
- const onBlur = useCallback((event) => {
393
- const { name } = event.target;
382
+ const onTouched = useCallback((path) => {
383
+ const jsonPath = createJsonPath(path);
394
384
  setTouched((touched2) => ({
395
385
  ...touched2,
396
- [name]: true
386
+ [jsonPath]: true
397
387
  }));
398
- if (event.relatedTarget?.getAttribute("type") === "submit") {
399
- setTouched(createKeySet(values, true));
400
- }
401
388
  validate(values);
402
389
  }, [
403
390
  validate,
@@ -415,13 +402,13 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
415
402
  getStatus,
416
403
  getValue: getFormValue,
417
404
  onValueChange,
418
- onBlur
405
+ onTouched
419
406
  };
420
407
  };
421
408
  var createKeySet = (obj, value) => {
422
409
  invariant(obj, void 0, {
423
410
  F: __dxlog_file,
424
- L: 230,
411
+ L: 236,
425
412
  S: void 0,
426
413
  A: [
427
414
  "obj",
@@ -435,338 +422,359 @@ var createKeySet = (obj, value) => {
435
422
  };
436
423
  var flatMap = (errors) => {
437
424
  return errors.reduce((result, { path, message }) => {
438
- if (!(path in result)) {
439
- result[path] = message;
425
+ const jsonPath = fromEffectValidationPath(path);
426
+ if (!(jsonPath in result)) {
427
+ result[jsonPath] = message;
440
428
  }
441
429
  return result;
442
430
  }, {});
443
431
  };
444
432
 
445
- // packages/ui/react-ui-form/src/components/Form/Form.tsx
446
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/Form.tsx";
433
+ // packages/ui/react-ui-form/src/components/Form/FormContext.tsx
434
+ var FormContext = /* @__PURE__ */ createContext(void 0);
435
+ var useFormContext = () => {
436
+ return useContext(FormContext) ?? raise(new Error("Missing FormContext"));
437
+ };
438
+ var useFormValues = (path = []) => {
439
+ const { values: formValues } = useFormContext();
440
+ const jsonPath = createJsonPath2(path);
441
+ return getValue2(formValues, jsonPath);
442
+ };
443
+ var useInputProps = (path = []) => {
444
+ const { getStatus, getValue: getFormValue, onValueChange, onTouched } = useFormContext();
445
+ return {
446
+ getStatus: () => getStatus(path),
447
+ getValue: () => getFormValue(path),
448
+ onValueChange: (type, value) => onValueChange(path, type, value),
449
+ onBlur: () => onTouched(path)
450
+ };
451
+ };
452
+ var FormProvider = ({ children, ...formOptions }) => {
453
+ const formHandler = useForm(formOptions);
454
+ return /* @__PURE__ */ React6.createElement(FormContext.Provider, {
455
+ value: formHandler
456
+ }, children);
457
+ };
458
+
459
+ // packages/ui/react-ui-form/src/components/Form/FormActions.tsx
460
+ var FormActions = ({ onCancel, readonly }) => {
461
+ const { t } = useTranslation2(translationKey);
462
+ const { canSave, handleSave } = useFormContext();
463
+ return /* @__PURE__ */ React7.createElement("div", {
464
+ role: "none",
465
+ className: "flex justify-center"
466
+ }, /* @__PURE__ */ React7.createElement("div", {
467
+ role: "none",
468
+ className: mx2(onCancel && !readonly && "grid grid-cols-2 gap-2")
469
+ }, onCancel && !readonly && /* @__PURE__ */ React7.createElement(IconButton, {
470
+ "data-testid": "cancel-button",
471
+ icon: "ph--x--regular",
472
+ label: t("button cancel"),
473
+ onClick: onCancel
474
+ }), handleSave && /* @__PURE__ */ React7.createElement(IconButton, {
475
+ type: "submit",
476
+ "data-testid": "save-button",
477
+ disabled: !canSave,
478
+ icon: "ph--check--regular",
479
+ label: t("button save"),
480
+ onClick: handleSave
481
+ })));
482
+ };
483
+
484
+ // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
485
+ import { pipe as pipe2 } from "effect";
486
+ import { capitalize as capitalize2 } from "effect/String";
487
+ import React9, { useMemo as useMemo3 } from "react";
488
+ import { AST as AST3, S } from "@dxos/echo-schema";
489
+ import { createJsonPath as createJsonPath3, findNode as findNode2, getDiscriminatedType as getDiscriminatedType2, isDiscriminatedUnion as isDiscriminatedUnion2 } from "@dxos/effect";
490
+ import { mx as mx4 } from "@dxos/react-ui-theme";
491
+ import { getSchemaProperties as getSchemaProperties2 } from "@dxos/schema";
492
+ import { isNotFalsy } from "@dxos/util";
493
+
494
+ // packages/ui/react-ui-form/src/components/Form/ArrayField.tsx
495
+ import { pipe } from "effect";
496
+ import { capitalize } from "effect/String";
497
+ import React8, { useCallback as useCallback2, useMemo as useMemo2 } from "react";
498
+ import { AST as AST2 } from "@dxos/echo-schema";
499
+ import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from "@dxos/effect";
500
+ import { invariant as invariant2 } from "@dxos/invariant";
501
+ import { IconButton as IconButton2, useTranslation as useTranslation3 } from "@dxos/react-ui";
502
+ import { mx as mx3 } from "@dxos/react-ui-theme";
503
+ import { getSchemaProperties } from "@dxos/schema";
504
+ var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/ArrayField.tsx";
447
505
  var padding = "px-2";
448
- var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
449
- const onValid = useMemo2(() => autoSave ? onSave : void 0, [
450
- autoSave,
451
- onSave
452
- ]);
453
- const { canSave, values, errors, handleSave, ...inputProps } = useForm({
454
- schema,
455
- initialValues,
456
- onValuesChanged,
457
- onValidate,
458
- onValid,
459
- onSave
506
+ var ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }) => {
507
+ const { t } = useTranslation3(translationKey);
508
+ const { ast, name, type, title } = property;
509
+ const values = useFormValues(path ?? []);
510
+ invariant2(Array.isArray(values), void 0, {
511
+ F: __dxlog_file2,
512
+ L: 37,
513
+ S: void 0,
514
+ A: [
515
+ "Array.isArray(values)",
516
+ ""
517
+ ]
460
518
  });
461
- const properties = useMemo2(() => {
462
- const props = getSchemaProperties(schema.ast, values);
463
- const filtered = filter ? filter(props) : props;
464
- const findIndex = (props2, prop) => {
465
- const idx = props2.findIndex((p) => p === prop);
466
- return idx === -1 ? Infinity : idx;
467
- };
468
- return sort ? filtered.sort(({ name: a }, { name: b }) => findIndex(sort, a) - findIndex(sort, b)) : filtered;
519
+ const label = title ?? pipe(name, capitalize);
520
+ const tupleType = findNode(ast, AST2.isTupleType);
521
+ const elementType = tupleType?.rest[0]?.type;
522
+ const getDefaultObjectValue = (typeNode) => {
523
+ const baseNode = findNode(typeNode, isDiscriminatedUnion);
524
+ const typeLiteral = baseNode ? getDiscriminatedType(baseNode, {}) : findNode(typeNode, AST2.isTypeLiteral);
525
+ if (!typeLiteral) {
526
+ return {};
527
+ }
528
+ return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [
529
+ prop.name,
530
+ prop.defaultValue
531
+ ]));
532
+ };
533
+ const newValue = useMemo2(() => {
534
+ if (type === "object" && elementType) {
535
+ return getDefaultObjectValue(elementType);
536
+ } else {
537
+ return SimpleType.getDefaultValue(type);
538
+ }
469
539
  }, [
470
- schema,
471
- filter,
540
+ type,
541
+ elementType
542
+ ]);
543
+ const handleAdd = useCallback2(() => {
544
+ inputProps.onValueChange(type, [
545
+ ...values,
546
+ newValue
547
+ ]);
548
+ }, [
549
+ type,
550
+ elementType,
551
+ inputProps,
552
+ newValue,
472
553
  values
473
554
  ]);
474
- useEffect2(() => {
475
- if (errors && Object.keys(errors).length) {
476
- log2.warn("validation", {
477
- errors
478
- }, {
479
- F: __dxlog_file2,
480
- L: 106,
481
- S: void 0,
482
- C: (f, a) => f(...a)
483
- });
484
- }
555
+ const handleRemove = useCallback2((index) => {
556
+ const newValues = values.filter((_, i) => i !== index);
557
+ inputProps.onValueChange(type, newValues);
485
558
  }, [
486
- errors
559
+ type,
560
+ inputProps,
561
+ values
487
562
  ]);
488
- return /* @__PURE__ */ React6.createElement("div", {
489
- role: "form",
490
- className: mx2("flex flex-col w-full gap-2 py-2", classNames),
491
- "data-testid": testId
492
- }, properties.map((property) => {
493
- const { ast, name, type, format, title, description, examples, options, array } = property;
494
- const key = [
495
- ...path,
496
- name
497
- ];
498
- const label = title ?? pipe(name, capitalize);
499
- const placeholder = examples?.length ? `Example: "${examples[0]}"` : description;
500
- const FoundComponent = lookupComponent?.({
501
- prop: name,
502
- schema: S.make(ast),
503
- inputProps: {
504
- property: name,
505
- type,
506
- format,
507
- label,
508
- disabled: readonly,
509
- placeholder,
510
- ...inputProps
511
- }
512
- });
513
- if (FoundComponent) {
514
- return /* @__PURE__ */ React6.createElement("div", {
515
- key: name,
516
- role: "none",
517
- className: padding
518
- }, FoundComponent);
519
- }
520
- let InputComponent = Custom?.[key.join(".")];
521
- if (!InputComponent) {
522
- if (options) {
523
- return /* @__PURE__ */ React6.createElement("div", {
524
- key: name,
525
- role: "none",
526
- className: padding
527
- }, /* @__PURE__ */ React6.createElement(SelectInput, {
528
- type,
529
- format,
530
- property: name,
531
- disabled: readonly,
532
- label,
533
- options: options.map((option) => ({
534
- value: option,
535
- label: String(option)
536
- })),
537
- placeholder,
538
- ...inputProps
539
- }));
540
- }
541
- InputComponent = getInputComponent(type, format);
542
- if (array) {
543
- return /* @__PURE__ */ React6.createElement(ArrayField, {
544
- key: name,
545
- name,
546
- type,
547
- array: true,
548
- label,
549
- ast,
550
- values,
551
- format,
552
- readonly,
553
- placeholder,
554
- inputProps,
555
- Custom
556
- });
557
- }
558
- }
559
- if (!InputComponent) {
560
- if (type === "object") {
561
- const baseNode = findNode(ast, isDiscriminatedUnion);
562
- const typeLiteral = baseNode ? getDiscriminatedType(baseNode, values[name]) : findNode(ast, AST2.isTypeLiteral);
563
- if (typeLiteral) {
564
- const schema2 = S.make(typeLiteral);
565
- return /* @__PURE__ */ React6.createElement("div", {
566
- key: name,
567
- role: "none"
568
- }, /* @__PURE__ */ React6.createElement("div", {
569
- className: padding
570
- }, label), /* @__PURE__ */ React6.createElement(Form, {
571
- schema: schema2,
572
- path: key,
573
- values: values[name] ?? {},
574
- onValuesChanged: (childValues) => {
575
- inputProps.onValueChange(name, "object", childValues);
576
- },
577
- Custom
578
- }));
579
- }
580
- }
581
- log2("no renderer for property", {
582
- name,
583
- type
584
- }, {
585
- F: __dxlog_file2,
586
- L: 213,
587
- S: void 0,
588
- C: (f, a) => f(...a)
589
- });
590
- return null;
591
- }
592
- return /* @__PURE__ */ React6.createElement("div", {
593
- key: name,
594
- role: "none",
595
- className: padding
596
- }, /* @__PURE__ */ React6.createElement(InputComponent, {
597
- type,
598
- format,
599
- property: name,
600
- disabled: readonly,
601
- label,
602
- placeholder,
603
- ...inputProps
604
- }));
605
- }).filter(isNotFalsy), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React6.createElement(FormActions, {
606
- onCancel,
607
- onSubmit: handleSave,
608
- canSubmit: canSave,
609
- readonly
610
- }));
611
- };
612
- var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholder, inputProps, Custom }) => {
613
- const { t } = useTranslation2(translationKey);
614
- const arrayValues = values[name] ?? [];
615
- const key = [
616
- name
617
- ];
618
- const tupleType = findNode(ast, AST2.isTupleType);
619
- const elementType = tupleType?.rest[0]?.type;
620
- if (type === "object" && elementType) {
621
- const baseNode = findNode(elementType, isDiscriminatedUnion);
622
- const typeLiteral = baseNode ? getDiscriminatedType(baseNode, values[name]) : findNode(elementType, AST2.isTypeLiteral);
623
- if (typeLiteral) {
624
- const schema = S.make(typeLiteral);
625
- return /* @__PURE__ */ React6.createElement("div", {
626
- key: name,
627
- role: "none",
628
- className: mx2(padding)
629
- }, /* @__PURE__ */ React6.createElement(InputHeader, null, label), /* @__PURE__ */ React6.createElement("div", {
630
- role: "none",
631
- className: "flex flex-col gap-1"
632
- }, arrayValues.map((value, index) => {
633
- return /* @__PURE__ */ React6.createElement("div", {
634
- key: index,
635
- role: "none",
636
- className: "flex items-center gap-1"
637
- }, /* @__PURE__ */ React6.createElement("div", {
638
- role: "none",
639
- className: "flex-1"
640
- }, /* @__PURE__ */ React6.createElement(Form, {
641
- schema,
642
- path: [
643
- ...key,
644
- `[${index}]`
645
- ],
646
- values: value,
647
- onValuesChanged: (childValues) => {
648
- const newValues = [
649
- ...arrayValues
650
- ];
651
- newValues[index] = childValues;
652
- inputProps.onValueChange(name, "object", newValues);
653
- },
654
- Custom
655
- })), /* @__PURE__ */ React6.createElement(IconButton, {
656
- icon: "ph--trash--regular",
657
- iconOnly: true,
658
- label: t("button remove"),
659
- onClick: () => {
660
- const newValues = arrayValues.filter((_, i) => i !== index);
661
- inputProps.onValueChange(name, type, newValues);
662
- }
663
- }));
664
- })), /* @__PURE__ */ React6.createElement("div", {
665
- role: "none",
666
- className: "flex justify-between items-center plb-1"
667
- }, /* @__PURE__ */ React6.createElement(IconButton, {
668
- icon: "ph--plus--regular",
669
- iconOnly: true,
670
- label: t("button add"),
671
- onClick: () => {
672
- const newValues = [
673
- ...arrayValues,
674
- {}
675
- ];
676
- inputProps.onValueChange(name, type, newValues);
677
- }
678
- })));
679
- }
680
- return /* @__PURE__ */ React6.createElement("div", {
681
- key: name,
682
- role: "none"
683
- }, "Nested form not supported in arrays, yet.");
684
- }
685
- const InputComponent = getInputComponent(type, format);
686
- if (!InputComponent) {
563
+ if (!elementType) {
687
564
  return null;
688
565
  }
689
- return /* @__PURE__ */ React6.createElement("div", {
566
+ return /* @__PURE__ */ React8.createElement("div", {
690
567
  role: "none",
691
- key: "meta-input",
692
- className: mx2(padding)
693
- }, /* @__PURE__ */ React6.createElement(InputHeader, null, label), /* @__PURE__ */ React6.createElement("div", {
568
+ className: mx3(padding)
569
+ }, /* @__PURE__ */ React8.createElement(InputHeader, null, label), /* @__PURE__ */ React8.createElement("div", {
694
570
  role: "none",
695
571
  className: "flex flex-col gap-1"
696
- }, arrayValues.map((_, index) => /* @__PURE__ */ React6.createElement("div", {
572
+ }, values.map((_value, index) => /* @__PURE__ */ React8.createElement("div", {
697
573
  key: index,
698
574
  role: "none",
699
- className: "flex items-start gap-1"
700
- }, /* @__PURE__ */ React6.createElement("div", {
575
+ className: "flex items-center gap-1"
576
+ }, /* @__PURE__ */ React8.createElement("div", {
701
577
  role: "none",
702
578
  className: "flex-1"
703
- }, /* @__PURE__ */ React6.createElement(InputComponent, {
704
- type,
705
- format,
706
- label,
707
- inputOnly: true,
708
- property: `${name}[${index}]`,
709
- disabled: readonly,
710
- placeholder,
711
- ...inputProps
712
- })), /* @__PURE__ */ React6.createElement(IconButton, {
579
+ }, /* @__PURE__ */ React8.createElement(FormField, {
580
+ property: {
581
+ ...property,
582
+ array: false,
583
+ ast: elementType
584
+ },
585
+ path: [
586
+ ...path ?? [],
587
+ index
588
+ ],
589
+ readonly,
590
+ inline: true,
591
+ Custom,
592
+ lookupComponent
593
+ })), /* @__PURE__ */ React8.createElement(IconButton2, {
713
594
  icon: "ph--trash--regular",
714
595
  iconOnly: true,
715
596
  label: t("button remove"),
716
- onClick: () => {
717
- const newValues = arrayValues.filter((_2, i) => i !== index);
718
- inputProps.onValueChange(name, type, newValues);
719
- }
720
- })))), /* @__PURE__ */ React6.createElement("div", {
597
+ onClick: () => handleRemove(index)
598
+ })))), /* @__PURE__ */ React8.createElement("div", {
721
599
  role: "none",
722
600
  className: "flex justify-between items-center plb-1"
723
- }, /* @__PURE__ */ React6.createElement(IconButton, {
601
+ }, /* @__PURE__ */ React8.createElement(IconButton2, {
724
602
  icon: "ph--plus--regular",
725
603
  iconOnly: true,
726
604
  label: t("button add"),
727
- onClick: () => {
728
- const newValues = [
729
- ...arrayValues,
730
- SimpleType.getDefaultValue(type)
731
- ];
732
- inputProps.onValueChange(name, type, newValues);
733
- }
605
+ onClick: handleAdd
734
606
  })));
735
607
  };
736
- var FormActions = ({ onCancel, onSubmit, canSubmit, readonly }) => {
737
- const { t } = useTranslation2(translationKey);
738
- return /* @__PURE__ */ React6.createElement("div", {
739
- role: "none",
740
- className: "flex justify-center"
741
- }, /* @__PURE__ */ React6.createElement("div", {
608
+
609
+ // packages/ui/react-ui-form/src/components/Form/factory.tsx
610
+ import { FormatEnum } from "@dxos/echo-schema";
611
+ var getInputComponent = (type, format) => {
612
+ switch (format) {
613
+ case FormatEnum.LatLng:
614
+ return GeoPointInput;
615
+ }
616
+ switch (type) {
617
+ case "string":
618
+ return TextInput;
619
+ case "number":
620
+ return NumberInput;
621
+ case "boolean":
622
+ return BooleanInput;
623
+ }
624
+ };
625
+
626
+ // packages/ui/react-ui-form/src/components/Form/FormContent.tsx
627
+ var FormField = ({ property, path, readonly, inline, lookupComponent, Custom }) => {
628
+ const inputProps = useInputProps(path);
629
+ const { ast, name, type, format, title, description, options, examples, array } = property;
630
+ const label = useMemo3(() => title ?? pipe2(name, capitalize2), [
631
+ title,
632
+ name
633
+ ]);
634
+ const placeholder = useMemo3(() => examples?.length ? `Example: "${examples[0]}"` : description, [
635
+ examples,
636
+ description
637
+ ]);
638
+ if (array) {
639
+ return /* @__PURE__ */ React9.createElement(ArrayField, {
640
+ property,
641
+ path,
642
+ inputProps,
643
+ readonly,
644
+ Custom
645
+ });
646
+ }
647
+ const FoundComponent = lookupComponent?.({
648
+ prop: name,
649
+ schema: S.make(ast),
650
+ inputProps: {
651
+ type,
652
+ format,
653
+ label,
654
+ disabled: readonly,
655
+ placeholder,
656
+ ...inputProps
657
+ }
658
+ });
659
+ if (FoundComponent) {
660
+ return /* @__PURE__ */ React9.createElement("div", null, FoundComponent);
661
+ }
662
+ const jsonPath = createJsonPath3(path ?? []);
663
+ const InputComponent = Custom?.[jsonPath] || getInputComponent(type, format);
664
+ if (InputComponent) {
665
+ return /* @__PURE__ */ React9.createElement("div", null, /* @__PURE__ */ React9.createElement(InputComponent, {
666
+ type,
667
+ format,
668
+ label,
669
+ inputOnly: inline,
670
+ placeholder,
671
+ disabled: readonly,
672
+ ...inputProps
673
+ }));
674
+ }
675
+ if (options) {
676
+ return /* @__PURE__ */ React9.createElement("div", {
677
+ role: "none"
678
+ }, /* @__PURE__ */ React9.createElement(SelectInput, {
679
+ type,
680
+ format,
681
+ disabled: readonly,
682
+ inputOnly: inline,
683
+ label,
684
+ options: options.map((option) => ({
685
+ value: option,
686
+ label: String(option)
687
+ })),
688
+ placeholder,
689
+ ...inputProps
690
+ }));
691
+ }
692
+ if (type === "object") {
693
+ const baseNode = findNode2(ast, isDiscriminatedUnion2);
694
+ const typeLiteral = baseNode ? getDiscriminatedType2(baseNode, inputProps.getValue()) : findNode2(ast, AST3.isTypeLiteral);
695
+ if (typeLiteral) {
696
+ return /* @__PURE__ */ React9.createElement("div", null, !inline && /* @__PURE__ */ React9.createElement("div", null, label), /* @__PURE__ */ React9.createElement(FormFields, {
697
+ schema: S.make(typeLiteral),
698
+ path,
699
+ readonly,
700
+ Custom
701
+ }));
702
+ }
703
+ }
704
+ return null;
705
+ };
706
+ var FormFields = ({ schema, path, filter, sort, readonly, lookupComponent, Custom }) => {
707
+ const values = useFormValues(path);
708
+ const properties = useMemo3(() => {
709
+ const props = getSchemaProperties2(schema.ast, values);
710
+ const filtered = filter ? filter(props) : props;
711
+ return sort ? filtered.sort((a, b) => sort.indexOf(a.name) - sort.indexOf(b.name)) : filtered;
712
+ }, [
713
+ schema,
714
+ values,
715
+ filter,
716
+ sort
717
+ ]);
718
+ return /* @__PURE__ */ React9.createElement("div", {
719
+ role: "form",
720
+ className: mx4("flex flex-col w-full gap-2 py-2")
721
+ }, properties.map((property) => {
722
+ return /* @__PURE__ */ React9.createElement(FormField, {
723
+ key: property.name,
724
+ property,
725
+ path: [
726
+ ...path ?? [],
727
+ property.name
728
+ ],
729
+ readonly,
730
+ lookupComponent,
731
+ Custom
732
+ });
733
+ }).filter(isNotFalsy));
734
+ };
735
+
736
+ // packages/ui/react-ui-form/src/components/Form/Form.tsx
737
+ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, lookupComponent, Custom }) => {
738
+ const onValid = useMemo4(() => autoSave ? onSave : void 0, [
739
+ autoSave,
740
+ onSave
741
+ ]);
742
+ return /* @__PURE__ */ React10.createElement(FormProvider, {
743
+ schema,
744
+ initialValues,
745
+ onValuesChanged,
746
+ onValidate,
747
+ onValid,
748
+ onSave
749
+ }, /* @__PURE__ */ React10.createElement("div", {
742
750
  role: "none",
743
- className: mx2(onCancel && !readonly && "grid grid-cols-2 gap-2")
744
- }, onCancel && !readonly && /* @__PURE__ */ React6.createElement(IconButton, {
745
- "data-testid": "cancel-button",
746
- icon: "ph--x--regular",
747
- label: t("button cancel"),
748
- onClick: onCancel
749
- }), onSubmit && /* @__PURE__ */ React6.createElement(IconButton, {
750
- type: "submit",
751
- "data-testid": "save-button",
752
- disabled: !canSubmit,
753
- icon: "ph--check--regular",
754
- label: t("button save"),
755
- onClick: onSubmit
751
+ className: mx5("p-2", classNames),
752
+ "data-testid": testId
753
+ }, /* @__PURE__ */ React10.createElement(FormFields, {
754
+ schema,
755
+ path,
756
+ readonly,
757
+ filter,
758
+ sort,
759
+ lookupComponent,
760
+ Custom
761
+ }), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React10.createElement(FormActions, {
762
+ onCancel,
763
+ readonly
756
764
  })));
757
765
  };
758
766
 
759
767
  // packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
760
768
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
761
769
  var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
762
- const { t } = useTranslation3(translationKey);
770
+ const { t } = useTranslation4(translationKey);
763
771
  const [props, setProps] = useState2(projection.getFieldProjection(field.id).props);
764
- useEffect3(() => setProps(projection.getFieldProjection(field.id).props), [
772
+ useEffect2(() => setProps(projection.getFieldProjection(field.id).props), [
765
773
  field,
766
774
  projection
767
775
  ]);
768
776
  const [schemas, setSchemas] = useState2([]);
769
- useEffect3(() => {
777
+ useEffect2(() => {
770
778
  if (!registry) {
771
779
  return;
772
780
  }
@@ -785,7 +793,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
785
793
  registry
786
794
  ]);
787
795
  const [referenceSchema, setReferenceSchema] = useState2();
788
- useEffect3(() => {
796
+ useEffect2(() => {
789
797
  setReferenceSchema(schemas.find((schema) => schema.typename === props?.referenceSchema));
790
798
  }, [
791
799
  schemas,
@@ -794,7 +802,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
794
802
  const [{ fieldSchema }, setFieldSchema] = useState2({
795
803
  fieldSchema: getFormatSchema(props?.format)
796
804
  });
797
- const handleValuesChanged = useCallback2((_props) => {
805
+ const handleValuesChanged = useCallback3((_props) => {
798
806
  setFieldSchema((prev) => {
799
807
  const fieldSchema2 = getFormatSchema(_props.format);
800
808
  if (prev.fieldSchema === fieldSchema2) {
@@ -829,7 +837,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
829
837
  props.format,
830
838
  props.referenceSchema
831
839
  ]);
832
- const handleValidate = useCallback2(({ property }) => {
840
+ const handleValidate = useCallback3(({ property }) => {
833
841
  if (property && view.fields.find((f) => f.path === property && f.path !== field.path)) {
834
842
  return [
835
843
  {
@@ -842,7 +850,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
842
850
  view.fields,
843
851
  field
844
852
  ]);
845
- const handleSave = useCallback2((props2) => {
853
+ const handleSave = useCallback3((props2) => {
846
854
  projection.setFieldProjection({
847
855
  field,
848
856
  props: props2
@@ -853,29 +861,29 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
853
861
  field,
854
862
  onSave
855
863
  ]);
856
- const handleCancel = useCallback2(() => {
864
+ const handleCancel = useCallback3(() => {
857
865
  requestAnimationFrame(() => onCancel?.());
858
866
  onSave();
859
867
  }, [
860
868
  onSave
861
869
  ]);
862
- const Custom = useMemo3(() => ({
863
- ["format"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
870
+ const Custom = useMemo5(() => ({
871
+ ["format"]: (props2) => /* @__PURE__ */ React11.createElement(SelectInput, {
864
872
  ...props2,
865
873
  options: FormatEnums.filter((value) => value !== FormatEnum2.None).map((value) => ({
866
874
  value,
867
875
  label: t(`format ${value}`)
868
876
  }))
869
877
  }),
870
- ["referenceSchema"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
878
+ ["referenceSchema"]: (props2) => /* @__PURE__ */ React11.createElement(SelectInput, {
871
879
  ...props2,
872
880
  options: schemas.map((schema) => ({
873
881
  value: schema.typename
874
882
  }))
875
883
  }),
876
- ["referencePath"]: (props2) => /* @__PURE__ */ React7.createElement(SelectInput, {
884
+ ["referencePath"]: (props2) => /* @__PURE__ */ React11.createElement(SelectInput, {
877
885
  ...props2,
878
- options: referenceSchema ? getSchemaProperties2(referenceSchema.ast).sort(sortProperties).map((p) => ({
886
+ options: referenceSchema ? getSchemaProperties3(referenceSchema.ast).sort(sortProperties).map((p) => ({
879
887
  value: p.name
880
888
  })) : []
881
889
  })
@@ -884,9 +892,9 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
884
892
  schemas,
885
893
  referenceSchema
886
894
  ]);
887
- const propIsNotType = useCallback2((props2) => props2.filter((p) => p.name !== "type"), []);
895
+ const propIsNotType = useCallback3((props2) => props2.filter((p) => p.name !== "type"), []);
888
896
  if (!fieldSchema) {
889
- log3.warn("invalid format", {
897
+ log2.warn("invalid format", {
890
898
  props
891
899
  }, {
892
900
  F: __dxlog_file3,
@@ -896,7 +904,7 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
896
904
  });
897
905
  return null;
898
906
  }
899
- return /* @__PURE__ */ React7.createElement(Form, {
907
+ return /* @__PURE__ */ React11.createElement(Form, {
900
908
  key: field.id,
901
909
  autoFocus: true,
902
910
  values: props,
@@ -915,30 +923,30 @@ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
915
923
  };
916
924
 
917
925
  // packages/ui/react-ui-form/src/components/ViewEditor/ViewEditor.tsx
918
- import React8, { useCallback as useCallback3, useMemo as useMemo4, useState as useState3 } from "react";
919
- import { AST as AST3, Format, S as S2 } from "@dxos/echo-schema";
920
- import { IconButton as IconButton2, useTranslation as useTranslation4 } from "@dxos/react-ui";
926
+ import React12, { useCallback as useCallback4, useMemo as useMemo6, useState as useState3 } from "react";
927
+ import { AST as AST4, Format, S as S2 } from "@dxos/echo-schema";
928
+ import { IconButton as IconButton3, useTranslation as useTranslation5 } from "@dxos/react-ui";
921
929
  import { List } from "@dxos/react-ui-list";
922
- import { ghostHover, inputTextLabel, mx as mx3 } from "@dxos/react-ui-theme";
930
+ import { ghostHover, inputTextLabel, mx as mx6 } from "@dxos/react-ui-theme";
923
931
  import { FieldSchema, ViewProjection, VIEW_FIELD_LIMIT } from "@dxos/schema";
924
932
  import { arrayMove } from "@dxos/util";
925
933
  var grid = "grid grid-cols-[32px_1fr_32px] min-bs-[2.5rem]";
926
934
  var ViewMetaSchema = S2.Struct({
927
935
  name: S2.String.annotations({
928
- [AST3.TitleAnnotationId]: "View"
936
+ [AST4.TitleAnnotationId]: "View"
929
937
  }),
930
938
  typename: Format.DXN.annotations({
931
- [AST3.TitleAnnotationId]: "Typename"
939
+ [AST4.TitleAnnotationId]: "Typename"
932
940
  })
933
941
  }).pipe(S2.mutable);
934
942
  var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading = false, onTypenameChanged, onDelete }) => {
935
- const { t } = useTranslation4(translationKey);
936
- const projection = useMemo4(() => new ViewProjection(schema, view), [
943
+ const { t } = useTranslation5(translationKey);
944
+ const projection = useMemo6(() => new ViewProjection(schema, view), [
937
945
  schema,
938
946
  view
939
947
  ]);
940
948
  const [field, setField] = useState3();
941
- const viewValues = useMemo4(() => {
949
+ const viewValues = useMemo6(() => {
942
950
  return {
943
951
  name: view.name,
944
952
  // TODO(burdon): Need to warn user of possible consequences of editing.
@@ -948,7 +956,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
948
956
  }, [
949
957
  view
950
958
  ]);
951
- const handleViewUpdate = useCallback3(({ name, typename }) => {
959
+ const handleViewUpdate = useCallback4(({ name, typename }) => {
952
960
  requestAnimationFrame(() => {
953
961
  if (view.name !== name) {
954
962
  view.name = name;
@@ -962,67 +970,67 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
962
970
  schema,
963
971
  onTypenameChanged
964
972
  ]);
965
- const handleSelect = useCallback3((field2) => {
973
+ const handleSelect = useCallback4((field2) => {
966
974
  setField((f) => f === field2 ? void 0 : field2);
967
975
  }, []);
968
- const handleAdd = useCallback3(() => {
976
+ const handleAdd = useCallback4(() => {
969
977
  const field2 = projection.createFieldProjection();
970
978
  setField(field2);
971
979
  }, [
972
980
  view
973
981
  ]);
974
- const handleMove = useCallback3((fromIndex, toIndex) => {
982
+ const handleMove = useCallback4((fromIndex, toIndex) => {
975
983
  arrayMove(view.fields, fromIndex, toIndex);
976
984
  }, [
977
985
  view.fields
978
986
  ]);
979
- const handleClose = useCallback3(() => setField(void 0), []);
980
- return /* @__PURE__ */ React8.createElement("div", {
987
+ const handleClose = useCallback4(() => setField(void 0), []);
988
+ return /* @__PURE__ */ React12.createElement("div", {
981
989
  role: "none",
982
- className: mx3("flex flex-col w-full divide-y divide-separator", classNames)
983
- }, /* @__PURE__ */ React8.createElement(Form, {
990
+ className: mx6("flex flex-col w-full divide-y divide-separator", classNames)
991
+ }, /* @__PURE__ */ React12.createElement(Form, {
984
992
  autoFocus: true,
985
993
  autoSave: true,
986
994
  schema: ViewMetaSchema,
987
995
  values: viewValues,
988
996
  onSave: handleViewUpdate
989
- }), /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("div", {
997
+ }), /* @__PURE__ */ React12.createElement("div", null, /* @__PURE__ */ React12.createElement("div", {
990
998
  role: "none",
991
999
  className: "p-2"
992
- }, /* @__PURE__ */ React8.createElement("label", {
993
- className: mx3(inputTextLabel)
994
- }, t("fields label"))), /* @__PURE__ */ React8.createElement(List.Root, {
1000
+ }, /* @__PURE__ */ React12.createElement("label", {
1001
+ className: mx6(inputTextLabel)
1002
+ }, t("fields label"))), /* @__PURE__ */ React12.createElement(List.Root, {
995
1003
  items: view.fields,
996
1004
  isItem: S2.is(FieldSchema),
997
1005
  getId: (field2) => field2.id,
998
1006
  onMove: handleMove
999
- }, ({ items: fields }) => /* @__PURE__ */ React8.createElement(React8.Fragment, null, showHeading && /* @__PURE__ */ React8.createElement("div", {
1007
+ }, ({ items: fields }) => /* @__PURE__ */ React12.createElement(React12.Fragment, null, showHeading && /* @__PURE__ */ React12.createElement("div", {
1000
1008
  role: "heading",
1001
1009
  className: grid
1002
- }, /* @__PURE__ */ React8.createElement("div", null), /* @__PURE__ */ React8.createElement("div", {
1010
+ }, /* @__PURE__ */ React12.createElement("div", null), /* @__PURE__ */ React12.createElement("div", {
1003
1011
  className: "flex items-center text-sm"
1004
- }, t("field path label"))), /* @__PURE__ */ React8.createElement("div", {
1012
+ }, t("field path label"))), /* @__PURE__ */ React12.createElement("div", {
1005
1013
  role: "list",
1006
1014
  className: "flex flex-col w-full"
1007
- }, fields?.map((field2) => /* @__PURE__ */ React8.createElement(List.Item, {
1015
+ }, fields?.map((field2) => /* @__PURE__ */ React12.createElement(List.Item, {
1008
1016
  key: field2.id,
1009
1017
  item: field2,
1010
- classNames: mx3(grid, ghostHover, "cursor-pointer")
1011
- }, /* @__PURE__ */ React8.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React8.createElement(List.ItemTitle, {
1018
+ classNames: mx6(grid, ghostHover, "cursor-pointer")
1019
+ }, /* @__PURE__ */ React12.createElement(List.ItemDragHandle, null), /* @__PURE__ */ React12.createElement(List.ItemTitle, {
1012
1020
  onClick: () => handleSelect(field2)
1013
- }, field2.path), /* @__PURE__ */ React8.createElement(List.ItemDeleteButton, {
1021
+ }, field2.path), /* @__PURE__ */ React12.createElement(List.ItemDeleteButton, {
1014
1022
  disabled: view.fields.length <= 1,
1015
1023
  onClick: () => onDelete(field2.id)
1016
- }))))))), field && /* @__PURE__ */ React8.createElement(FieldEditor, {
1024
+ }))))))), field && /* @__PURE__ */ React12.createElement(FieldEditor, {
1017
1025
  key: field.id,
1018
1026
  view,
1019
1027
  projection,
1020
1028
  field,
1021
1029
  registry,
1022
1030
  onSave: handleClose
1023
- }), !readonly && !field && /* @__PURE__ */ React8.createElement("div", {
1031
+ }), !readonly && !field && /* @__PURE__ */ React12.createElement("div", {
1024
1032
  className: "flex p-2 justify-center"
1025
- }, /* @__PURE__ */ React8.createElement(IconButton2, {
1033
+ }, /* @__PURE__ */ React12.createElement(IconButton3, {
1026
1034
  icon: "ph--plus--regular",
1027
1035
  label: t("button add property"),
1028
1036
  onClick: handleAdd,
@@ -1255,7 +1263,6 @@ export {
1255
1263
  DeprecatedFormInput,
1256
1264
  FieldEditor,
1257
1265
  Form,
1258
- FormActions,
1259
1266
  GeoPointInput,
1260
1267
  InputHeader,
1261
1268
  NumberInput,