@firecms/core 3.0.0-canary.282 → 3.0.0-canary.284
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/core/EntityEditView.d.ts +2 -2
- package/dist/form/EntityForm.d.ts +3 -1
- package/dist/form/index.d.ts +2 -1
- package/dist/index.es.js +166 -113
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +164 -111
- package/dist/index.umd.js.map +1 -1
- package/dist/preview/components/UserPreview.d.ts +1 -1
- package/dist/types/collections.d.ts +7 -0
- package/package.json +5 -5
- package/src/components/PropertyConfigBadge.tsx +2 -2
- package/src/components/UserDisplay.tsx +2 -1
- package/src/core/EntityEditView.tsx +13 -10
- package/src/core/EntityEditViewFormActions.tsx +33 -18
- package/src/form/EntityForm.tsx +49 -25
- package/src/form/EntityFormActions.tsx +30 -15
- package/src/form/PropertyFieldBinding.tsx +4 -0
- package/src/form/components/ErrorFocus.tsx +22 -29
- package/src/form/index.tsx +5 -1
- package/src/hooks/useBuildNavigationController.tsx +3 -2
- package/src/preview/components/UserPreview.tsx +7 -2
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +1 -1
- package/src/types/collections.ts +8 -0
- package/src/util/entity_cache.ts +0 -1
|
@@ -1,51 +1,44 @@
|
|
|
1
|
-
import React, { useEffect } from "react";
|
|
1
|
+
import React, { useEffect, useRef } from "react";
|
|
2
2
|
import { useFormex } from "@firecms/formex";
|
|
3
3
|
|
|
4
4
|
export const ErrorFocus = ({ containerRef }:
|
|
5
5
|
{
|
|
6
6
|
containerRef?: React.RefObject<HTMLDivElement>
|
|
7
7
|
}) => {
|
|
8
|
-
const {
|
|
8
|
+
const {
|
|
9
|
+
isValidating,
|
|
10
|
+
errors,
|
|
11
|
+
version
|
|
12
|
+
} = useFormex();
|
|
13
|
+
|
|
14
|
+
const prevVersion = useRef(version);
|
|
9
15
|
|
|
10
16
|
useEffect(() => {
|
|
17
|
+
|
|
18
|
+
if (version === prevVersion.current) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
11
22
|
const keys = Object.keys(errors);
|
|
12
23
|
|
|
13
|
-
// Whenever there are errors and the form
|
|
14
|
-
if (keys.length > 0
|
|
24
|
+
// Whenever there are errors and the form has been submitted and is not validating
|
|
25
|
+
if (!isValidating && keys.length > 0) {
|
|
15
26
|
const errorElement = containerRef?.current?.querySelector<HTMLDivElement>(
|
|
16
27
|
`#form_field_${keys[0]}`
|
|
17
28
|
);
|
|
18
29
|
|
|
19
|
-
if (errorElement
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
top: scrollableParent.scrollTop + top - 196,
|
|
25
|
-
behavior: "smooth"
|
|
26
|
-
});
|
|
27
|
-
}
|
|
30
|
+
if (errorElement) {
|
|
31
|
+
errorElement.scrollIntoView({
|
|
32
|
+
behavior: "smooth",
|
|
33
|
+
block: "center"
|
|
34
|
+
});
|
|
28
35
|
const input = errorElement.querySelector("input");
|
|
29
36
|
if (input) input.focus();
|
|
30
37
|
}
|
|
38
|
+
prevVersion.current = version;
|
|
31
39
|
}
|
|
32
|
-
}, [
|
|
40
|
+
}, [isValidating, errors, containerRef, version]);
|
|
33
41
|
|
|
34
42
|
// This component does not render anything by itself.
|
|
35
43
|
return null;
|
|
36
44
|
};
|
|
37
|
-
|
|
38
|
-
const isScrollable = (ele: HTMLElement | null) => {
|
|
39
|
-
const hasScrollableContent = ele && ele.scrollHeight > ele.clientHeight;
|
|
40
|
-
|
|
41
|
-
const overflowYStyle = ele ? window.getComputedStyle(ele).overflowY : null;
|
|
42
|
-
const isOverflowHidden = overflowYStyle && overflowYStyle.indexOf("hidden") !== -1;
|
|
43
|
-
|
|
44
|
-
return hasScrollableContent && !isOverflowHidden;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const getScrollableParent = (ele: HTMLElement | null): HTMLElement | null => {
|
|
48
|
-
return (!ele || ele === document.body)
|
|
49
|
-
? document.body
|
|
50
|
-
: (isScrollable(ele) ? ele : getScrollableParent(ele.parentNode as HTMLElement));
|
|
51
|
-
};
|
package/src/form/index.tsx
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
export
|
|
1
|
+
export {
|
|
2
|
+
EntityForm,
|
|
3
|
+
yupToFormErrors,
|
|
4
|
+
} from "./EntityForm";
|
|
5
|
+
export type { EntityFormProps } from "./EntityForm";
|
|
2
6
|
|
|
3
7
|
export { SelectFieldBinding } from "./field_bindings/SelectFieldBinding";
|
|
4
8
|
export { MultiSelectFieldBinding } from "./field_bindings/MultiSelectFieldBinding";
|
|
@@ -457,8 +457,9 @@ export function useBuildNavigationController<EC extends EntityCollection, USER e
|
|
|
457
457
|
[fullCollectionPath]);
|
|
458
458
|
|
|
459
459
|
const urlPathToDataPath = useCallback((path: string): string => {
|
|
460
|
-
|
|
461
|
-
|
|
460
|
+
const decodedPath = decodeURIComponent(path);
|
|
461
|
+
if (decodedPath.startsWith(fullCollectionPath))
|
|
462
|
+
return decodedPath.replace(fullCollectionPath, "");
|
|
462
463
|
throw Error("Expected path starting with " + fullCollectionPath);
|
|
463
464
|
}, [fullCollectionPath]);
|
|
464
465
|
|
|
@@ -2,6 +2,8 @@ import React from "react";
|
|
|
2
2
|
import { PropertyPreviewProps } from "../PropertyPreviewProps";
|
|
3
3
|
import { useInternalUserManagementController } from "../../hooks";
|
|
4
4
|
import { UserDisplay } from "../../components/UserDisplay";
|
|
5
|
+
import { EmptyValue } from "./EmptyValue";
|
|
6
|
+
import { Typography } from "@firecms/ui";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Preview component for displaying user information.
|
|
@@ -13,10 +15,13 @@ export function UserPreview({ value }: PropertyPreviewProps<string>) {
|
|
|
13
15
|
const { getUser } = useInternalUserManagementController();
|
|
14
16
|
|
|
15
17
|
if (!value) {
|
|
16
|
-
return
|
|
18
|
+
return <EmptyValue/>;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
const user = getUser(value);
|
|
22
|
+
if (!user) {
|
|
23
|
+
return <Typography variant={"caption"} color={"secondary"}>User not found: {value}</Typography>;
|
|
24
|
+
}
|
|
20
25
|
|
|
21
|
-
return <UserDisplay user={user}
|
|
26
|
+
return <UserDisplay user={user}/>;
|
|
22
27
|
}
|
|
@@ -42,7 +42,7 @@ export function ArrayPropertyPreview({
|
|
|
42
42
|
const childSize: PreviewSize = size === "medium" ? "medium" : "small";
|
|
43
43
|
|
|
44
44
|
return (
|
|
45
|
-
<div className="flex flex-col gap-2">
|
|
45
|
+
<div className="w-full flex flex-col gap-2">
|
|
46
46
|
{values &&
|
|
47
47
|
values.map((value, index) => {
|
|
48
48
|
const of: ResolvedProperty = property.resolvedProperties[index] ??
|
package/src/types/collections.ts
CHANGED
|
@@ -352,6 +352,14 @@ export interface EntityCollection<M extends Record<string, any> = any, USER exte
|
|
|
352
352
|
* This prop has no effect if the history plugin is not enabled
|
|
353
353
|
*/
|
|
354
354
|
history?: boolean;
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* If set to true, local changes to entities in this collection will be backed up
|
|
358
|
+
* in the browser's local storage. This allows users to recover unsaved changes
|
|
359
|
+
* in case of accidental navigation or browser crashes.
|
|
360
|
+
* Defaults to `true`.
|
|
361
|
+
*/
|
|
362
|
+
enableLocalChangesBackup?: boolean;
|
|
355
363
|
}
|
|
356
364
|
|
|
357
365
|
/**
|
package/src/util/entity_cache.ts
CHANGED