@dxos/react-ui-form 0.7.2 → 0.7.3-staging.0905f03

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 (33) hide show
  1. package/dist/lib/browser/index.mjs +228 -58
  2. package/dist/lib/browser/index.mjs.map +3 -3
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +228 -57
  5. package/dist/lib/node/index.cjs.map +3 -3
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +228 -58
  8. package/dist/lib/node-esm/index.mjs.map +3 -3
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +2 -2
  11. package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
  12. package/dist/types/src/components/Form/Defaults.d.ts +4 -4
  13. package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
  14. package/dist/types/src/components/Form/Form.d.ts +11 -2
  15. package/dist/types/src/components/Form/Form.d.ts.map +1 -1
  16. package/dist/types/src/components/Form/Form.stories.d.ts +20 -5
  17. package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
  18. package/dist/types/src/components/Form/Input.d.ts +5 -4
  19. package/dist/types/src/components/Form/Input.d.ts.map +1 -1
  20. package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
  21. package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
  22. package/dist/types/src/hooks/useForm.d.ts +19 -11
  23. package/dist/types/src/hooks/useForm.d.ts.map +1 -1
  24. package/package.json +23 -22
  25. package/src/components/FieldEditor/FieldEditor.stories.tsx +3 -3
  26. package/src/components/FieldEditor/FieldEditor.tsx +8 -8
  27. package/src/components/Form/Defaults.tsx +28 -13
  28. package/src/components/Form/Form.stories.tsx +81 -19
  29. package/src/components/Form/Form.tsx +216 -29
  30. package/src/components/Form/Input.tsx +5 -4
  31. package/src/components/ViewEditor/ViewEditor.tsx +8 -7
  32. package/src/components/deprecated/Form.stories.tsx +4 -4
  33. package/src/hooks/useForm.ts +65 -32
@@ -32,6 +32,7 @@ __export(node_exports, {
32
32
  DeprecatedFormInput: () => DeprecatedFormInput,
33
33
  FieldEditor: () => FieldEditor,
34
34
  Form: () => Form,
35
+ FormActions: () => FormActions,
35
36
  GeiPointInput: () => GeiPointInput,
36
37
  InputHeader: () => InputHeader,
37
38
  NumberInput: () => NumberInput,
@@ -175,11 +176,11 @@ var InputHeader = ({ children, error }) => {
175
176
  side: "bottom"
176
177
  }, /* @__PURE__ */ import_react5.default.createElement(import_react_ui5.Tooltip.Arrow, null), error)));
177
178
  };
178
- var TextInput = ({ property, type, label, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
179
+ var TextInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
179
180
  const { status, error } = getStatus?.(property);
180
181
  return /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.Root, {
181
182
  validationValence: status
182
- }, /* @__PURE__ */ import_react4.default.createElement(InputHeader, {
183
+ }, !inputOnly && /* @__PURE__ */ import_react4.default.createElement(InputHeader, {
183
184
  error
184
185
  }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.Label, null, label)), /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.TextInput, {
185
186
  disabled,
@@ -187,13 +188,13 @@ var TextInput = ({ property, type, label, disabled, placeholder, getStatus, getV
187
188
  value: getValue(property) ?? "",
188
189
  onChange: (event) => onValueChange(property, type, event.target.value),
189
190
  onBlur
190
- }));
191
+ }), inputOnly && /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.Validation, null, error));
191
192
  };
192
- var NumberInput = ({ property, type, label, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
193
+ var NumberInput = ({ property, type, label, inputOnly, disabled, placeholder, getStatus, getValue, onValueChange, onBlur }) => {
193
194
  const { status, error } = getStatus?.(property);
194
195
  return /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.Root, {
195
196
  validationValence: status
196
- }, /* @__PURE__ */ import_react4.default.createElement(InputHeader, {
197
+ }, !inputOnly && /* @__PURE__ */ import_react4.default.createElement(InputHeader, {
197
198
  error
198
199
  }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.Label, null, label)), /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.TextInput, {
199
200
  type: "number",
@@ -202,24 +203,24 @@ var NumberInput = ({ property, type, label, disabled, placeholder, getStatus, ge
202
203
  value: getValue(property) ?? 0,
203
204
  onChange: (event) => onValueChange(property, type, event.target.value),
204
205
  onBlur
205
- }));
206
+ }), inputOnly && /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.DescriptionAndValidation, null, error));
206
207
  };
207
- var BooleanInput = ({ property, type, label, getStatus, getValue, onValueChange }) => {
208
+ var BooleanInput = ({ property, type, label, inputOnly, getStatus, getValue, onValueChange }) => {
208
209
  const { status, error } = getStatus?.(property);
209
210
  return /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.Root, {
210
211
  validationValence: status
211
- }, /* @__PURE__ */ import_react4.default.createElement(InputHeader, {
212
+ }, !inputOnly && /* @__PURE__ */ import_react4.default.createElement(InputHeader, {
212
213
  error
213
214
  }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.Label, null, label)), /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.Switch, {
214
215
  checked: getValue(property),
215
216
  onCheckedChange: (value) => onValueChange(property, type, value)
216
- }));
217
+ }), inputOnly && /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.DescriptionAndValidation, null, error));
217
218
  };
218
- var SelectInput = ({ property, type, label, disabled, placeholder, options, getStatus, getValue, onValueChange }) => {
219
+ var SelectInput = ({ property, type, label, inputOnly, disabled, placeholder, options, getStatus, getValue, onValueChange }) => {
219
220
  const { status, error } = getStatus?.(property);
220
221
  return /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.Root, {
221
222
  validationValence: status
222
- }, /* @__PURE__ */ import_react4.default.createElement(InputHeader, {
223
+ }, !inputOnly && /* @__PURE__ */ import_react4.default.createElement(InputHeader, {
223
224
  error
224
225
  }, /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.Label, null, label)), /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Select.Root, {
225
226
  value: getValue(property),
@@ -234,7 +235,7 @@ var SelectInput = ({ property, type, label, disabled, placeholder, options, getS
234
235
  key: String(value),
235
236
  value: String(value)
236
237
  }, label2 ?? String(value))
237
- )))))));
238
+ )))))), inputOnly && /* @__PURE__ */ import_react4.default.createElement(import_react_ui4.Input.DescriptionAndValidation, null, error));
238
239
  };
239
240
  var GeiPointInput = ({ property, type, label, disabled, getStatus, getValue, onValueChange, onBlur }) => {
240
241
  const { t } = (0, import_react_ui6.useTranslation)(translationKey);
@@ -290,7 +291,7 @@ var getInputComponent = (type, format) => {
290
291
  }
291
292
  };
292
293
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
293
- var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSubmit }) => {
294
+ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
294
295
  const [values, setValues] = (0, import_react7.useState)(initialValues);
295
296
  (0, import_react7.useEffect)(() => {
296
297
  setValues(initialValues);
@@ -300,6 +301,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
300
301
  const [touched, setTouched] = (0, import_react7.useState)(createKeySet(initialValues, false));
301
302
  const [changed, setChanged] = (0, import_react7.useState)(createKeySet(initialValues, false));
302
303
  const [errors, setErrors] = (0, import_react7.useState)({});
304
+ const [saving, setSaving] = (0, import_react7.useState)(false);
303
305
  const validate = (0, import_react7.useCallback)((values2) => {
304
306
  let errors2 = (0, import_schema3.validateSchema)(schema, values2) ?? [];
305
307
  if (errors2.length === 0 && onValidate) {
@@ -324,21 +326,27 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
324
326
  values,
325
327
  schemaDirty
326
328
  ]);
327
- const canSubmit = (0, import_react7.useMemo)(() => Object.keys(values).every((property) => touched[property] === false || !errors[property]), [
329
+ const canSave = (0, import_react7.useMemo)(() => !saving && Object.keys(values).every((property) => touched[property] === false || !errors[property]), [
328
330
  values,
329
331
  touched,
330
- errors
332
+ errors,
333
+ saving
331
334
  ]);
332
- const handleSubmit = (0, import_react7.useCallback)(() => {
335
+ const handleSave = (0, import_react7.useCallback)(async () => {
333
336
  if (validate(values)) {
334
- onSubmit?.(values, {
335
- changed
336
- });
337
+ setSaving(true);
338
+ try {
339
+ await onSave?.(values, {
340
+ changed
341
+ });
342
+ } finally {
343
+ setSaving(false);
344
+ }
337
345
  }
338
346
  }, [
339
347
  values,
340
348
  validate,
341
- onSubmit
349
+ onSave
342
350
  ]);
343
351
  const getStatus = (0, import_react7.useCallback)((property) => ({
344
352
  status: errors[property] ? "error" : void 0,
@@ -348,7 +356,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
348
356
  errors
349
357
  ]);
350
358
  const getValue = (property) => {
351
- return values[property];
359
+ return getByPath(values, property);
352
360
  };
353
361
  const onValueChange = (property, type, value) => {
354
362
  let parsedValue = value;
@@ -359,16 +367,13 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
359
367
  } catch (err) {
360
368
  import_log3.log.catch(err, void 0, {
361
369
  F: __dxlog_file,
362
- L: 165,
370
+ L: 183,
363
371
  S: void 0,
364
372
  C: (f, a) => f(...a)
365
373
  });
366
374
  parsedValue = void 0;
367
375
  }
368
- const newValues = {
369
- ...values,
370
- [property]: parsedValue
371
- };
376
+ const newValues = setByPath(values, property, parsedValue);
372
377
  setValues(newValues);
373
378
  setChanged((prev) => ({
374
379
  ...prev,
@@ -402,8 +407,8 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
402
407
  errors,
403
408
  touched,
404
409
  changed,
405
- canSubmit,
406
- handleSubmit,
410
+ canSave,
411
+ handleSave,
407
412
  // Field utils.
408
413
  getStatus,
409
414
  getValue,
@@ -414,7 +419,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
414
419
  var createKeySet = (obj, value) => {
415
420
  (0, import_invariant.invariant)(obj, void 0, {
416
421
  F: __dxlog_file,
417
- L: 216,
422
+ L: 234,
418
423
  S: void 0,
419
424
  A: [
420
425
  "obj",
@@ -434,21 +439,34 @@ var flatMap = (errors) => {
434
439
  return result;
435
440
  }, {});
436
441
  };
442
+ var getByPath = (obj, path) => {
443
+ const [key, index] = path.split(".");
444
+ return index === void 0 ? obj[key] : obj[key][parseInt(index)];
445
+ };
446
+ var setByPath = (obj, path, value) => {
447
+ const [key, index] = path.split(".");
448
+ const newValue = index === void 0 ? value : [
449
+ ...obj[key]
450
+ ].map((v, i) => i === parseInt(index) ? value : v);
451
+ return {
452
+ ...obj,
453
+ [key]: newValue
454
+ };
455
+ };
437
456
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/Form.tsx";
438
457
  var padding = "px-2";
439
- var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, onValuesChanged, onValidate, onSubmit, onCancel, Custom }) => {
440
- const { t } = (0, import_react_ui3.useTranslation)(translationKey);
441
- const onValid = (0, import_react3.useMemo)(() => autoSave ? onSubmit : void 0, [
458
+ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, Custom }) => {
459
+ const onValid = (0, import_react3.useMemo)(() => autoSave ? onSave : void 0, [
442
460
  autoSave,
443
- onSubmit
461
+ onSave
444
462
  ]);
445
- const { canSubmit, values, errors, handleSubmit, ...inputProps } = useForm({
463
+ const { canSave, values, errors, handleSave, ...inputProps } = useForm({
446
464
  schema,
447
465
  initialValues,
448
466
  onValuesChanged,
449
467
  onValidate,
450
468
  onValid,
451
- onSubmit
469
+ onSave
452
470
  });
453
471
  const properties = (0, import_react3.useMemo)(() => {
454
472
  const props = (0, import_schema2.getSchemaProperties)(schema.ast, values);
@@ -469,7 +487,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
469
487
  errors
470
488
  }, {
471
489
  F: __dxlog_file2,
472
- L: 96,
490
+ L: 100,
473
491
  S: void 0,
474
492
  C: (f, a) => f(...a)
475
493
  });
@@ -479,14 +497,15 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
479
497
  ]);
480
498
  return /* @__PURE__ */ import_react3.default.createElement("div", {
481
499
  role: "form",
482
- className: (0, import_react_ui_theme.mx)("flex flex-col w-full gap-2 py-2", classNames)
500
+ className: (0, import_react_ui_theme.mx)("flex flex-col w-full gap-2 py-2", classNames),
501
+ "data-testid": testId
483
502
  }, properties.map((property) => {
484
- const { ast, name, type, format, title, description, examples, options } = property;
503
+ const { ast, name, type, format, title, description, examples, options, array } = property;
485
504
  const key = [
486
505
  ...path,
487
506
  name
488
507
  ];
489
- const label = (0, import_effect.pipe)(title ?? name, import_String.capitalize);
508
+ const label = title ?? (0, import_effect.pipe)(name, import_String.capitalize);
490
509
  const placeholder = examples?.length ? `Example: "${examples[0]}"` : description;
491
510
  let InputComponent = Custom?.[key.join(".")];
492
511
  if (!InputComponent) {
@@ -510,6 +529,22 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
510
529
  }));
511
530
  }
512
531
  InputComponent = getInputComponent(type, format);
532
+ if (array) {
533
+ return /* @__PURE__ */ import_react3.default.createElement(ArrayField, {
534
+ key: name,
535
+ name,
536
+ type,
537
+ array: true,
538
+ label,
539
+ ast,
540
+ values,
541
+ format,
542
+ readonly,
543
+ placeholder,
544
+ inputProps,
545
+ Custom
546
+ });
547
+ }
513
548
  }
514
549
  if (!InputComponent) {
515
550
  if (type === "object") {
@@ -538,7 +573,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
538
573
  type
539
574
  }, {
540
575
  F: __dxlog_file2,
541
- L: 160,
576
+ L: 185,
542
577
  S: void 0,
543
578
  C: (f, a) => f(...a)
544
579
  });
@@ -557,26 +592,161 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
557
592
  placeholder,
558
593
  ...inputProps
559
594
  }));
560
- }).filter(import_util.isNotFalsy), (onCancel || onSubmit) && !autoSave && /* @__PURE__ */ import_react3.default.createElement("div", {
595
+ }).filter(import_util.isNotFalsy), (onCancel || onSave) && !autoSave && /* @__PURE__ */ import_react3.default.createElement(FormActions, {
596
+ onCancel,
597
+ onSubmit: handleSave,
598
+ canSubmit: canSave,
599
+ readonly
600
+ }));
601
+ };
602
+ var ArrayField = ({ name, type, label, ast, values, format, readonly, placeholder, inputProps, Custom }) => {
603
+ const { t } = (0, import_react_ui3.useTranslation)(translationKey);
604
+ const arrayValues = values[name] ?? [];
605
+ const key = [
606
+ name
607
+ ];
608
+ const tupleType = (0, import_effect2.findNode)(ast, import_echo_schema2.AST.isTupleType);
609
+ const elementType = tupleType?.rest[0]?.type;
610
+ if (type === "object" && elementType) {
611
+ const baseNode = (0, import_effect2.findNode)(elementType, import_effect2.isDiscriminatedUnion);
612
+ const typeLiteral = baseNode ? (0, import_effect2.getDiscriminatedType)(baseNode, values[name]) : (0, import_effect2.findNode)(elementType, import_echo_schema2.AST.isTypeLiteral);
613
+ if (typeLiteral) {
614
+ const schema = import_echo_schema2.S.make(typeLiteral);
615
+ return /* @__PURE__ */ import_react3.default.createElement("div", {
616
+ key: name,
617
+ role: "none",
618
+ className: (0, import_react_ui_theme.mx)(padding)
619
+ }, /* @__PURE__ */ import_react3.default.createElement(InputHeader, null, label), /* @__PURE__ */ import_react3.default.createElement("div", {
620
+ role: "none",
621
+ className: "flex flex-col gap-1"
622
+ }, arrayValues.map((value, index) => {
623
+ return /* @__PURE__ */ import_react3.default.createElement("div", {
624
+ key: index,
625
+ role: "none",
626
+ className: "flex items-center gap-1"
627
+ }, /* @__PURE__ */ import_react3.default.createElement("div", {
628
+ role: "none",
629
+ className: "flex-1"
630
+ }, /* @__PURE__ */ import_react3.default.createElement(Form, {
631
+ schema,
632
+ path: [
633
+ ...key,
634
+ index.toString()
635
+ ],
636
+ values: value,
637
+ onValuesChanged: (childValues) => {
638
+ const newValues = [
639
+ ...arrayValues
640
+ ];
641
+ newValues[index] = childValues;
642
+ inputProps.onValueChange(name, "object", newValues);
643
+ },
644
+ Custom
645
+ })), /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.IconButton, {
646
+ icon: "ph--trash--regular",
647
+ iconOnly: true,
648
+ label: t("button remove"),
649
+ onClick: () => {
650
+ const newValues = arrayValues.filter((_, i) => i !== index);
651
+ inputProps.onValueChange(name, type, newValues);
652
+ }
653
+ }));
654
+ })), /* @__PURE__ */ import_react3.default.createElement("div", {
655
+ role: "none",
656
+ className: "flex justify-between items-center plb-1"
657
+ }, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.IconButton, {
658
+ icon: "ph--plus--regular",
659
+ iconOnly: true,
660
+ label: t("button add"),
661
+ onClick: () => {
662
+ const newValues = [
663
+ ...arrayValues,
664
+ {}
665
+ ];
666
+ inputProps.onValueChange(name, type, newValues);
667
+ }
668
+ })));
669
+ }
670
+ return /* @__PURE__ */ import_react3.default.createElement("div", {
671
+ key: name,
672
+ role: "none"
673
+ }, "Nested form not supported in arrays, yet.");
674
+ }
675
+ const InputComponent = getInputComponent(type, format);
676
+ if (!InputComponent) {
677
+ return null;
678
+ }
679
+ return /* @__PURE__ */ import_react3.default.createElement("div", {
680
+ role: "none",
681
+ key: "meta-input",
682
+ className: (0, import_react_ui_theme.mx)(padding)
683
+ }, /* @__PURE__ */ import_react3.default.createElement(InputHeader, null, label), /* @__PURE__ */ import_react3.default.createElement("div", {
684
+ role: "none",
685
+ className: "flex flex-col gap-1"
686
+ }, arrayValues.map((_, index) => /* @__PURE__ */ import_react3.default.createElement("div", {
687
+ key: index,
688
+ role: "none",
689
+ className: "flex items-start gap-1"
690
+ }, /* @__PURE__ */ import_react3.default.createElement("div", {
691
+ role: "none",
692
+ className: "flex-1"
693
+ }, /* @__PURE__ */ import_react3.default.createElement(InputComponent, {
694
+ type,
695
+ format,
696
+ label,
697
+ inputOnly: true,
698
+ property: `${name}.${index}`,
699
+ disabled: readonly,
700
+ placeholder,
701
+ ...inputProps
702
+ })), /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.IconButton, {
703
+ icon: "ph--trash--regular",
704
+ iconOnly: true,
705
+ label: t("button remove"),
706
+ onClick: () => {
707
+ const newValues = arrayValues.filter((_2, i) => i !== index);
708
+ inputProps.onValueChange(name, type, newValues);
709
+ }
710
+ })))), /* @__PURE__ */ import_react3.default.createElement("div", {
711
+ role: "none",
712
+ className: "flex justify-between items-center plb-1"
713
+ }, /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.IconButton, {
714
+ icon: "ph--plus--regular",
715
+ iconOnly: true,
716
+ label: t("button add"),
717
+ onClick: () => {
718
+ const newValues = [
719
+ ...arrayValues,
720
+ import_effect2.SimpleType.getDefaultValue(type)
721
+ ];
722
+ inputProps.onValueChange(name, type, newValues);
723
+ }
724
+ })));
725
+ };
726
+ var FormActions = ({ onCancel, onSubmit, canSubmit, readonly }) => {
727
+ const { t } = (0, import_react_ui3.useTranslation)(translationKey);
728
+ return /* @__PURE__ */ import_react3.default.createElement("div", {
561
729
  role: "none",
562
730
  className: "flex justify-center"
563
731
  }, /* @__PURE__ */ import_react3.default.createElement("div", {
564
732
  role: "none",
565
733
  className: (0, import_react_ui_theme.mx)(onCancel && !readonly && "grid grid-cols-2 gap-2")
566
734
  }, onCancel && !readonly && /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.IconButton, {
735
+ "data-testid": "cancel-button",
567
736
  icon: "ph--x--regular",
568
737
  label: t("button cancel"),
569
738
  onClick: onCancel
570
739
  }), onSubmit && /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.IconButton, {
571
740
  type: "submit",
741
+ "data-testid": "save-button",
572
742
  disabled: !canSubmit,
573
743
  icon: "ph--check--regular",
574
744
  label: t("button save"),
575
- onClick: handleSubmit
576
- }))));
745
+ onClick: onSubmit
746
+ })));
577
747
  };
578
748
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
579
- var FieldEditor = ({ view, projection, field, registry, onClose, onCancel }) => {
749
+ var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
580
750
  const { t } = (0, import_react_ui2.useTranslation)(translationKey);
581
751
  const [props, setProps] = (0, import_react2.useState)(projection.getFieldProjection(field.id).props);
582
752
  (0, import_react2.useEffect)(() => setProps(projection.getFieldProjection(field.id).props), [
@@ -647,22 +817,22 @@ var FieldEditor = ({ view, projection, field, registry, onClose, onCancel }) =>
647
817
  view.fields,
648
818
  field
649
819
  ]);
650
- const handleSubmit = (0, import_react2.useCallback)((props2) => {
820
+ const handleSave = (0, import_react2.useCallback)((props2) => {
651
821
  projection.setFieldProjection({
652
822
  field,
653
823
  props: props2
654
824
  });
655
- onClose();
825
+ onSave();
656
826
  }, [
657
827
  projection,
658
828
  field,
659
- onClose
829
+ onSave
660
830
  ]);
661
831
  const handleCancel = (0, import_react2.useCallback)(() => {
662
832
  requestAnimationFrame(() => onCancel?.());
663
- onClose();
833
+ onSave();
664
834
  }, [
665
- onClose
835
+ onSave
666
836
  ]);
667
837
  if (!fieldSchema) {
668
838
  import_log.log.warn("invalid format", {
@@ -687,7 +857,7 @@ var FieldEditor = ({ view, projection, field, registry, onClose, onCancel }) =>
687
857
  ],
688
858
  onValuesChanged: handleValuesChanged,
689
859
  onValidate: handleValidate,
690
- onSubmit: handleSubmit,
860
+ onSave: handleSave,
691
861
  onCancel: handleCancel,
692
862
  Custom: {
693
863
  ["format"]: (props2) => /* @__PURE__ */ import_react2.default.createElement(SelectInput, {
@@ -717,7 +887,7 @@ var ViewMetaSchema = import_echo_schema4.S.Struct({
717
887
  name: import_echo_schema4.S.String.annotations({
718
888
  [import_echo_schema4.AST.TitleAnnotationId]: "View"
719
889
  }),
720
- type: import_echo_schema4.Format.DXN.annotations({
890
+ typename: import_echo_schema4.Format.DXN.annotations({
721
891
  [import_echo_schema4.AST.TitleAnnotationId]: "Typename"
722
892
  })
723
893
  }).pipe(import_echo_schema4.S.mutable);
@@ -733,16 +903,16 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
733
903
  name: view.name,
734
904
  // TODO(burdon): Need to warn user of possible consequences of editing.
735
905
  // TODO(burdon): Settings should have domain name owned by user.
736
- type: view.query.type
906
+ typename: view.query.type
737
907
  };
738
908
  }, [
739
909
  view
740
910
  ]);
741
- const handleViewUpdate = (0, import_react8.useCallback)(({ name, type }) => {
911
+ const handleViewUpdate = (0, import_react8.useCallback)(({ name, typename }) => {
742
912
  requestAnimationFrame(() => {
743
913
  view.name = name;
744
- view.query.type = type;
745
- schema.updateTypename(type);
914
+ view.query.type = typename;
915
+ schema.updateTypename(typename);
746
916
  });
747
917
  }, [
748
918
  view,
@@ -771,7 +941,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
771
941
  autoSave: true,
772
942
  schema: ViewMetaSchema,
773
943
  values: viewValues,
774
- onSubmit: handleViewUpdate
944
+ onSave: handleViewUpdate
775
945
  }), /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("div", {
776
946
  role: "none",
777
947
  className: "p-2"
@@ -805,7 +975,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
805
975
  projection,
806
976
  field,
807
977
  registry,
808
- onClose: handleClose
978
+ onSave: handleClose
809
979
  }), !readonly && !field && /* @__PURE__ */ import_react8.default.createElement("div", {
810
980
  className: "flex p-2 justify-center"
811
981
  }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui7.IconButton, {
@@ -1036,6 +1206,7 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1036
1206
  DeprecatedFormInput,
1037
1207
  FieldEditor,
1038
1208
  Form,
1209
+ FormActions,
1039
1210
  GeiPointInput,
1040
1211
  InputHeader,
1041
1212
  NumberInput,