@dxos/react-ui-form 0.7.2 → 0.7.3-staging.971cd8d
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.
- package/dist/lib/browser/index.mjs +49 -39
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +49 -39
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +49 -39
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts +2 -2
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +3 -2
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +9 -5
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/useForm.d.ts +12 -5
- package/dist/types/src/hooks/useForm.d.ts.map +1 -1
- package/package.json +23 -22
- package/src/components/FieldEditor/FieldEditor.stories.tsx +3 -3
- package/src/components/FieldEditor/FieldEditor.tsx +8 -8
- package/src/components/Form/Form.stories.tsx +41 -11
- package/src/components/Form/Form.tsx +23 -12
- package/src/components/ViewEditor/ViewEditor.tsx +8 -7
- package/src/components/deprecated/Form.stories.tsx +4 -4
- package/src/hooks/useForm.ts +29 -14
|
@@ -252,7 +252,7 @@ import { invariant } from "@dxos/invariant";
|
|
|
252
252
|
import { log } from "@dxos/log";
|
|
253
253
|
import { validateSchema } from "@dxos/schema";
|
|
254
254
|
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/hooks/useForm.ts";
|
|
255
|
-
var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid,
|
|
255
|
+
var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, onSave }) => {
|
|
256
256
|
const [values, setValues] = useState(initialValues);
|
|
257
257
|
useEffect(() => {
|
|
258
258
|
setValues(initialValues);
|
|
@@ -262,6 +262,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
262
262
|
const [touched, setTouched] = useState(createKeySet(initialValues, false));
|
|
263
263
|
const [changed, setChanged] = useState(createKeySet(initialValues, false));
|
|
264
264
|
const [errors, setErrors] = useState({});
|
|
265
|
+
const [saving, setSaving] = useState(false);
|
|
265
266
|
const validate = useCallback((values2) => {
|
|
266
267
|
let errors2 = validateSchema(schema, values2) ?? [];
|
|
267
268
|
if (errors2.length === 0 && onValidate) {
|
|
@@ -286,21 +287,27 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
286
287
|
values,
|
|
287
288
|
schemaDirty
|
|
288
289
|
]);
|
|
289
|
-
const
|
|
290
|
+
const canSave = useMemo(() => !saving && Object.keys(values).every((property) => touched[property] === false || !errors[property]), [
|
|
290
291
|
values,
|
|
291
292
|
touched,
|
|
292
|
-
errors
|
|
293
|
+
errors,
|
|
294
|
+
saving
|
|
293
295
|
]);
|
|
294
|
-
const
|
|
296
|
+
const handleSave = useCallback(async () => {
|
|
295
297
|
if (validate(values)) {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
298
|
+
setSaving(true);
|
|
299
|
+
try {
|
|
300
|
+
await onSave?.(values, {
|
|
301
|
+
changed
|
|
302
|
+
});
|
|
303
|
+
} finally {
|
|
304
|
+
setSaving(false);
|
|
305
|
+
}
|
|
299
306
|
}
|
|
300
307
|
}, [
|
|
301
308
|
values,
|
|
302
309
|
validate,
|
|
303
|
-
|
|
310
|
+
onSave
|
|
304
311
|
]);
|
|
305
312
|
const getStatus = useCallback((property) => ({
|
|
306
313
|
status: errors[property] ? "error" : void 0,
|
|
@@ -321,7 +328,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
321
328
|
} catch (err) {
|
|
322
329
|
log.catch(err, void 0, {
|
|
323
330
|
F: __dxlog_file,
|
|
324
|
-
L:
|
|
331
|
+
L: 180,
|
|
325
332
|
S: void 0,
|
|
326
333
|
C: (f, a) => f(...a)
|
|
327
334
|
});
|
|
@@ -364,8 +371,8 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
364
371
|
errors,
|
|
365
372
|
touched,
|
|
366
373
|
changed,
|
|
367
|
-
|
|
368
|
-
|
|
374
|
+
canSave,
|
|
375
|
+
handleSave,
|
|
369
376
|
// Field utils.
|
|
370
377
|
getStatus,
|
|
371
378
|
getValue,
|
|
@@ -376,7 +383,7 @@ var useForm = ({ schema, initialValues, onValuesChanged, onValidate, onValid, on
|
|
|
376
383
|
var createKeySet = (obj, value) => {
|
|
377
384
|
invariant(obj, void 0, {
|
|
378
385
|
F: __dxlog_file,
|
|
379
|
-
L:
|
|
386
|
+
L: 231,
|
|
380
387
|
S: void 0,
|
|
381
388
|
A: [
|
|
382
389
|
"obj",
|
|
@@ -400,19 +407,19 @@ var flatMap = (errors) => {
|
|
|
400
407
|
// packages/ui/react-ui-form/src/components/Form/Form.tsx
|
|
401
408
|
var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/Form/Form.tsx";
|
|
402
409
|
var padding = "px-2";
|
|
403
|
-
var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, onValuesChanged, onValidate,
|
|
410
|
+
var Form = ({ classNames, schema, values: initialValues, path = [], readonly, filter, sort, autoSave, testId, onValuesChanged, onValidate, onSave, onCancel, Custom }) => {
|
|
404
411
|
const { t } = useTranslation2(translationKey);
|
|
405
|
-
const onValid = useMemo2(() => autoSave ?
|
|
412
|
+
const onValid = useMemo2(() => autoSave ? onSave : void 0, [
|
|
406
413
|
autoSave,
|
|
407
|
-
|
|
414
|
+
onSave
|
|
408
415
|
]);
|
|
409
|
-
const {
|
|
416
|
+
const { canSave, values, errors, handleSave, ...inputProps } = useForm({
|
|
410
417
|
schema,
|
|
411
418
|
initialValues,
|
|
412
419
|
onValuesChanged,
|
|
413
420
|
onValidate,
|
|
414
421
|
onValid,
|
|
415
|
-
|
|
422
|
+
onSave
|
|
416
423
|
});
|
|
417
424
|
const properties = useMemo2(() => {
|
|
418
425
|
const props = getSchemaProperties(schema.ast, values);
|
|
@@ -433,7 +440,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
|
|
|
433
440
|
errors
|
|
434
441
|
}, {
|
|
435
442
|
F: __dxlog_file2,
|
|
436
|
-
L:
|
|
443
|
+
L: 101,
|
|
437
444
|
S: void 0,
|
|
438
445
|
C: (f, a) => f(...a)
|
|
439
446
|
});
|
|
@@ -443,14 +450,15 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
|
|
|
443
450
|
]);
|
|
444
451
|
return /* @__PURE__ */ React5.createElement("div", {
|
|
445
452
|
role: "form",
|
|
446
|
-
className: mx("flex flex-col w-full gap-2 py-2", classNames)
|
|
453
|
+
className: mx("flex flex-col w-full gap-2 py-2", classNames),
|
|
454
|
+
"data-testid": testId
|
|
447
455
|
}, properties.map((property) => {
|
|
448
456
|
const { ast, name, type, format, title, description, examples, options } = property;
|
|
449
457
|
const key = [
|
|
450
458
|
...path,
|
|
451
459
|
name
|
|
452
460
|
];
|
|
453
|
-
const label =
|
|
461
|
+
const label = title ?? pipe(name, capitalize);
|
|
454
462
|
const placeholder = examples?.length ? `Example: "${examples[0]}"` : description;
|
|
455
463
|
let InputComponent = Custom?.[key.join(".")];
|
|
456
464
|
if (!InputComponent) {
|
|
@@ -502,7 +510,7 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
|
|
|
502
510
|
type
|
|
503
511
|
}, {
|
|
504
512
|
F: __dxlog_file2,
|
|
505
|
-
L:
|
|
513
|
+
L: 165,
|
|
506
514
|
S: void 0,
|
|
507
515
|
C: (f, a) => f(...a)
|
|
508
516
|
});
|
|
@@ -521,28 +529,30 @@ var Form = ({ classNames, schema, values: initialValues, path = [], readonly, fi
|
|
|
521
529
|
placeholder,
|
|
522
530
|
...inputProps
|
|
523
531
|
}));
|
|
524
|
-
}).filter(isNotFalsy), (onCancel ||
|
|
532
|
+
}).filter(isNotFalsy), (onCancel || onSave) && !autoSave && /* @__PURE__ */ React5.createElement("div", {
|
|
525
533
|
role: "none",
|
|
526
534
|
className: "flex justify-center"
|
|
527
535
|
}, /* @__PURE__ */ React5.createElement("div", {
|
|
528
536
|
role: "none",
|
|
529
537
|
className: mx(onCancel && !readonly && "grid grid-cols-2 gap-2")
|
|
530
538
|
}, onCancel && !readonly && /* @__PURE__ */ React5.createElement(IconButton, {
|
|
539
|
+
"data-testid": "cancel-button",
|
|
531
540
|
icon: "ph--x--regular",
|
|
532
541
|
label: t("button cancel"),
|
|
533
542
|
onClick: onCancel
|
|
534
|
-
}),
|
|
543
|
+
}), onSave && /* @__PURE__ */ React5.createElement(IconButton, {
|
|
535
544
|
type: "submit",
|
|
536
|
-
|
|
545
|
+
"data-testid": "save-button",
|
|
546
|
+
disabled: !canSave,
|
|
537
547
|
icon: "ph--check--regular",
|
|
538
548
|
label: t("button save"),
|
|
539
|
-
onClick:
|
|
549
|
+
onClick: handleSave
|
|
540
550
|
}))));
|
|
541
551
|
};
|
|
542
552
|
|
|
543
553
|
// packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx
|
|
544
554
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-form/src/components/FieldEditor/FieldEditor.tsx";
|
|
545
|
-
var FieldEditor = ({ view, projection, field, registry,
|
|
555
|
+
var FieldEditor = ({ view, projection, field, registry, onSave, onCancel }) => {
|
|
546
556
|
const { t } = useTranslation3(translationKey);
|
|
547
557
|
const [props, setProps] = useState2(projection.getFieldProjection(field.id).props);
|
|
548
558
|
useEffect3(() => setProps(projection.getFieldProjection(field.id).props), [
|
|
@@ -613,22 +623,22 @@ var FieldEditor = ({ view, projection, field, registry, onClose, onCancel }) =>
|
|
|
613
623
|
view.fields,
|
|
614
624
|
field
|
|
615
625
|
]);
|
|
616
|
-
const
|
|
626
|
+
const handleSave = useCallback2((props2) => {
|
|
617
627
|
projection.setFieldProjection({
|
|
618
628
|
field,
|
|
619
629
|
props: props2
|
|
620
630
|
});
|
|
621
|
-
|
|
631
|
+
onSave();
|
|
622
632
|
}, [
|
|
623
633
|
projection,
|
|
624
634
|
field,
|
|
625
|
-
|
|
635
|
+
onSave
|
|
626
636
|
]);
|
|
627
637
|
const handleCancel = useCallback2(() => {
|
|
628
638
|
requestAnimationFrame(() => onCancel?.());
|
|
629
|
-
|
|
639
|
+
onSave();
|
|
630
640
|
}, [
|
|
631
|
-
|
|
641
|
+
onSave
|
|
632
642
|
]);
|
|
633
643
|
if (!fieldSchema) {
|
|
634
644
|
log3.warn("invalid format", {
|
|
@@ -653,7 +663,7 @@ var FieldEditor = ({ view, projection, field, registry, onClose, onCancel }) =>
|
|
|
653
663
|
],
|
|
654
664
|
onValuesChanged: handleValuesChanged,
|
|
655
665
|
onValidate: handleValidate,
|
|
656
|
-
|
|
666
|
+
onSave: handleSave,
|
|
657
667
|
onCancel: handleCancel,
|
|
658
668
|
Custom: {
|
|
659
669
|
["format"]: (props2) => /* @__PURE__ */ React6.createElement(SelectInput, {
|
|
@@ -692,7 +702,7 @@ var ViewMetaSchema = S2.Struct({
|
|
|
692
702
|
name: S2.String.annotations({
|
|
693
703
|
[AST2.TitleAnnotationId]: "View"
|
|
694
704
|
}),
|
|
695
|
-
|
|
705
|
+
typename: Format.DXN.annotations({
|
|
696
706
|
[AST2.TitleAnnotationId]: "Typename"
|
|
697
707
|
})
|
|
698
708
|
}).pipe(S2.mutable);
|
|
@@ -708,16 +718,16 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
708
718
|
name: view.name,
|
|
709
719
|
// TODO(burdon): Need to warn user of possible consequences of editing.
|
|
710
720
|
// TODO(burdon): Settings should have domain name owned by user.
|
|
711
|
-
|
|
721
|
+
typename: view.query.typename
|
|
712
722
|
};
|
|
713
723
|
}, [
|
|
714
724
|
view
|
|
715
725
|
]);
|
|
716
|
-
const handleViewUpdate = useCallback3(({ name,
|
|
726
|
+
const handleViewUpdate = useCallback3(({ name, typename }) => {
|
|
717
727
|
requestAnimationFrame(() => {
|
|
718
728
|
view.name = name;
|
|
719
|
-
view.query.
|
|
720
|
-
schema.updateTypename(
|
|
729
|
+
view.query.typename = typename;
|
|
730
|
+
schema.updateTypename(typename);
|
|
721
731
|
});
|
|
722
732
|
}, [
|
|
723
733
|
view,
|
|
@@ -746,7 +756,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
746
756
|
autoSave: true,
|
|
747
757
|
schema: ViewMetaSchema,
|
|
748
758
|
values: viewValues,
|
|
749
|
-
|
|
759
|
+
onSave: handleViewUpdate
|
|
750
760
|
}), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement("div", {
|
|
751
761
|
role: "none",
|
|
752
762
|
className: "p-2"
|
|
@@ -780,7 +790,7 @@ var ViewEditor = ({ classNames, schema, view, registry, readonly, showHeading =
|
|
|
780
790
|
projection,
|
|
781
791
|
field,
|
|
782
792
|
registry,
|
|
783
|
-
|
|
793
|
+
onSave: handleClose
|
|
784
794
|
}), !readonly && !field && /* @__PURE__ */ React7.createElement("div", {
|
|
785
795
|
className: "flex p-2 justify-center"
|
|
786
796
|
}, /* @__PURE__ */ React7.createElement(IconButton2, {
|