@dxos/react-ui-form 0.7.3-staging.cc8dd3e → 0.7.3

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.
@@ -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);
@@ -355,7 +356,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
355
356
  errors
356
357
  ]);
357
358
  const getValue = (property) => {
358
- return values[property];
359
+ return getByPath(values, property);
359
360
  };
360
361
  const onValueChange = (property, type, value) => {
361
362
  let parsedValue = value;
@@ -366,16 +367,13 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
366
367
  } catch (err) {
367
368
  import_log3.log.catch(err, void 0, {
368
369
  F: __dxlog_file,
369
- L: 180,
370
+ L: 183,
370
371
  S: void 0,
371
372
  C: (f, a) => f(...a)
372
373
  });
373
374
  parsedValue = void 0;
374
375
  }
375
- const newValues = {
376
- ...values,
377
- [property]: parsedValue
378
- };
376
+ const newValues = setByPath(values, property, parsedValue);
379
377
  setValues(newValues);
380
378
  setChanged((prev) => ({
381
379
  ...prev,
@@ -421,7 +419,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
421
419
  var createKeySet = (obj, value) => {
422
420
  (0, import_invariant.invariant)(obj, void 0, {
423
421
  F: __dxlog_file,
424
- L: 231,
422
+ L: 234,
425
423
  S: void 0,
426
424
  A: [
427
425
  "obj",
@@ -441,10 +439,23 @@ var flatMap = (errors) => {
441
439
  return result;
442
440
  }, {});
443
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
+ };
444
456
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/Form.tsx";
445
457
  var padding = "px-2";
446
458
  var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, Custom }) => {
447
- const { t } = (0, import_react_ui3.useTranslation)(translationKey);
448
459
  const onValid = (0, import_react3.useMemo)(() => autoSave ? onSave : void 0, [
449
460
  autoSave,
450
461
  onSave
@@ -476,7 +487,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
476
487
  errors
477
488
  }, {
478
489
  F: __dxlog_file2,
479
- L: 101,
490
+ L: 100,
480
491
  S: void 0,
481
492
  C: (f, a) => f(...a)
482
493
  });
@@ -489,7 +500,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
489
500
  className: (0, import_react_ui_theme.mx)("flex flex-col w-full gap-2 py-2", classNames),
490
501
  "data-testid": testId
491
502
  }, properties.map((property) => {
492
- const { ast, name, type, format, title, description, examples, options } = property;
503
+ const { ast, name, type, format, title, description, examples, options, array } = property;
493
504
  const key = [
494
505
  ...path,
495
506
  name
@@ -518,6 +529,22 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
518
529
  }));
519
530
  }
520
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
+ }
521
548
  }
522
549
  if (!InputComponent) {
523
550
  if (type === "object") {
@@ -546,7 +573,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
546
573
  type
547
574
  }, {
548
575
  F: __dxlog_file2,
549
- L: 165,
576
+ L: 185,
550
577
  S: void 0,
551
578
  C: (f, a) => f(...a)
552
579
  });
@@ -565,7 +592,140 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
565
592
  placeholder,
566
593
  ...inputProps
567
594
  }));
568
- }).filter(import_util.isNotFalsy), (onCancel || onSave) && !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", {
569
729
  role: "none",
570
730
  className: "flex justify-center"
571
731
  }, /* @__PURE__ */ import_react3.default.createElement("div", {
@@ -576,14 +736,14 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
576
736
  icon: "ph--x--regular",
577
737
  label: t("button cancel"),
578
738
  onClick: onCancel
579
- }), onSave && /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.IconButton, {
739
+ }), onSubmit && /* @__PURE__ */ import_react3.default.createElement(import_react_ui3.IconButton, {
580
740
  type: "submit",
581
741
  "data-testid": "save-button",
582
- disabled: !canSave,
742
+ disabled: !canSubmit,
583
743
  icon: "ph--check--regular",
584
744
  label: t("button save"),
585
- onClick: handleSave
586
- }))));
745
+ onClick: onSubmit
746
+ })));
587
747
  };
588
748
  var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
589
749
  var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
@@ -743,7 +903,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
743
903
  name: view.name,
744
904
  // TODO(burdon): Need to warn user of possible consequences of editing.
745
905
  // TODO(burdon): Settings should have domain name owned by user.
746
- typename: view.query.typename
906
+ typename: view.query.type
747
907
  };
748
908
  }, [
749
909
  view
@@ -751,7 +911,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
751
911
  const handleViewUpdate = (0, import_react8.useCallback)(({ name, typename }) => {
752
912
  requestAnimationFrame(() => {
753
913
  view.name = name;
754
- view.query.typename = typename;
914
+ view.query.type = typename;
755
915
  schema.updateTypename(typename);
756
916
  });
757
917
  }, [
@@ -1046,6 +1206,7 @@ var formatForEditing = ({ type, format, value, locale = void 0 }) => {
1046
1206
  DeprecatedFormInput,
1047
1207
  FieldEditor,
1048
1208
  Form,
1209
+ FormActions,
1049
1210
  GeiPointInput,
1050
1211
  InputHeader,
1051
1212
  NumberInput,