@etsoo/toolpad 1.0.29 → 1.0.30
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/build/cjs/AppProvider/AppProvider.d.ts +1 -0
- package/build/cjs/PageContainer/PageContainer.d.ts +1 -6
- package/build/cjs/PageContainer/PageContainer.js +27 -27
- package/build/cjs/useActivePage/useActivePage.d.ts +2 -0
- package/build/cjs/useActivePage/useActivePage.js +13 -21
- package/build/mjs/AppProvider/AppProvider.d.ts +1 -0
- package/build/mjs/PageContainer/PageContainer.d.ts +1 -6
- package/build/mjs/PageContainer/PageContainer.js +27 -27
- package/build/mjs/useActivePage/useActivePage.d.ts +2 -0
- package/build/mjs/useActivePage/useActivePage.js +13 -21
- package/package.json +1 -1
- package/src/AppProvider/AppProvider.tsx +1 -0
- package/src/PageContainer/PageContainer.tsx +46 -57
- package/src/useActivePage/useActivePage.ts +15 -25
|
@@ -25,8 +25,7 @@ export type PageData = {
|
|
|
25
25
|
title?: string;
|
|
26
26
|
page?: string;
|
|
27
27
|
breadcrumbs?: Breadcrumb[];
|
|
28
|
-
|
|
29
|
-
noPageHeader?: boolean;
|
|
28
|
+
pageHeader?: React.ReactNode;
|
|
30
29
|
};
|
|
31
30
|
type PageDataAction = PageData;
|
|
32
31
|
export declare const PageDataContext: React.Context<{
|
|
@@ -35,10 +34,6 @@ export declare const PageDataContext: React.Context<{
|
|
|
35
34
|
}>;
|
|
36
35
|
export declare function PageDataContextProvider(props: React.PropsWithChildren<PageData>): import("react/jsx-runtime").JSX.Element;
|
|
37
36
|
type PageContainerBarProps = {
|
|
38
|
-
/**
|
|
39
|
-
* The default title of the page.
|
|
40
|
-
*/
|
|
41
|
-
defaultTitle?: string;
|
|
42
37
|
/**
|
|
43
38
|
* The components used for each slot inside.
|
|
44
39
|
*/
|
|
@@ -64,7 +64,7 @@ function reducer(state, action) {
|
|
|
64
64
|
let key;
|
|
65
65
|
let isSame = true;
|
|
66
66
|
for (key in action) {
|
|
67
|
-
if (action[key]
|
|
67
|
+
if (action[key] != state[key]) {
|
|
68
68
|
isSame = false;
|
|
69
69
|
break;
|
|
70
70
|
}
|
|
@@ -76,38 +76,30 @@ function reducer(state, action) {
|
|
|
76
76
|
}
|
|
77
77
|
function PageDataContextProvider(props) {
|
|
78
78
|
// Destruct
|
|
79
|
-
const { title, page, breadcrumbs,
|
|
79
|
+
const { title, page, breadcrumbs, pageHeader, ...rest } = props;
|
|
80
80
|
// useReducer hook to manage state with our reducer function and initial state
|
|
81
81
|
const [state, dispatch] = React.useReducer(reducer, {
|
|
82
82
|
title,
|
|
83
83
|
page,
|
|
84
84
|
breadcrumbs,
|
|
85
|
-
|
|
86
|
-
noPageHeader
|
|
85
|
+
pageHeader
|
|
87
86
|
});
|
|
88
87
|
// Provide the state and dispatch function to the context value
|
|
89
88
|
return (0, jsx_runtime_1.jsx)(exports.PageDataContext.Provider, { value: { state, dispatch }, ...rest });
|
|
90
89
|
}
|
|
91
90
|
function PageContainerBar(props) {
|
|
92
|
-
const {
|
|
91
|
+
const { slots, slotProps } = props;
|
|
93
92
|
const { state } = React.useContext(exports.PageDataContext);
|
|
94
93
|
const activePage = (0, useActivePage_1.useActivePage)();
|
|
95
|
-
React.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
React.useEffect(() => {
|
|
95
|
+
return () => {
|
|
96
|
+
// Reset the state when the component unmounts
|
|
97
|
+
state.breadcrumbs = undefined;
|
|
98
|
+
state.page = undefined;
|
|
99
|
+
state.pageHeader = undefined;
|
|
100
|
+
state.title = undefined;
|
|
101
|
+
};
|
|
102
102
|
}, [activePage?.sourcePath]);
|
|
103
|
-
let resolvedBreadcrumbs = state.breadcrumbs ?? activePage?.breadcrumbs ?? [];
|
|
104
|
-
const title = state.title ?? defaultTitle ?? activePage?.title ?? "";
|
|
105
|
-
if (state.page) {
|
|
106
|
-
resolvedBreadcrumbs = [
|
|
107
|
-
...resolvedBreadcrumbs,
|
|
108
|
-
{ title: state.page, path: "#" }
|
|
109
|
-
];
|
|
110
|
-
}
|
|
111
103
|
const ToolbarComponent = slots?.toolbar ?? PageContainerToolbar_1.PageContainerToolbar;
|
|
112
104
|
const toolbarSlotProps = (0, useSlotProps_1.default)({
|
|
113
105
|
elementType: ToolbarComponent,
|
|
@@ -115,11 +107,19 @@ function PageContainerBar(props) {
|
|
|
115
107
|
externalSlotProps: slotProps?.toolbar,
|
|
116
108
|
additionalProps: {}
|
|
117
109
|
});
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
110
|
+
const breadcrumbs = state.breadcrumbs ?? activePage?.breadcrumbs ?? [];
|
|
111
|
+
const title = state.title ?? activePage?.title ?? "";
|
|
112
|
+
const pageHeader = state.pageHeader ?? activePage?.pageHeader ?? null;
|
|
113
|
+
if (pageHeader === false)
|
|
114
|
+
return undefined;
|
|
115
|
+
if (pageHeader != null)
|
|
116
|
+
return pageHeader;
|
|
117
|
+
if (state.page) {
|
|
118
|
+
breadcrumbs.push({ title: state.page, path: "#" });
|
|
119
|
+
}
|
|
120
|
+
return ((0, jsx_runtime_1.jsxs)(Stack_1.default, { children: [breadcrumbs && ((0, jsx_runtime_1.jsx)(Breadcrumbs_1.default, { "aria-label": "breadcrumb", children: breadcrumbs.map((item, index) => {
|
|
121
|
+
return index < breadcrumbs.length - 1 ? ((0, jsx_runtime_1.jsx)(Link_1.default, { component: Link_2.Link, underline: "hover", color: "inherit", href: item.path, children: (0, navigation_1.getItemTitle)(item) }, item.path)) : ((0, jsx_runtime_1.jsx)(Typography_1.default, { color: "text.primary", children: (0, navigation_1.getItemTitle)(item) }, item.path));
|
|
122
|
+
}) })), (0, jsx_runtime_1.jsxs)(PageContentHeader, { children: [title ? (0, jsx_runtime_1.jsx)(Typography_1.default, { variant: "h4", children: title }) : null, (0, jsx_runtime_1.jsx)(ToolbarComponent, { ...toolbarSlotProps })] })] }));
|
|
123
123
|
}
|
|
124
124
|
/**
|
|
125
125
|
* A container component to provide a title and breadcrumbs for your pages.
|
|
@@ -133,6 +133,6 @@ function PageContainerBar(props) {
|
|
|
133
133
|
* - [PageContainer API](https://mui.com/toolpad/core/api/page-container)
|
|
134
134
|
*/
|
|
135
135
|
function PageContainer(props) {
|
|
136
|
-
const { children,
|
|
137
|
-
return ((0, jsx_runtime_1.jsxs)(Stack_1.default, { sx: { mx: 3, my: 2 }, spacing: 2, ...rest, children: [(0, jsx_runtime_1.jsx)(PageContainerBar, {
|
|
136
|
+
const { children, slots, slotProps, ...rest } = props;
|
|
137
|
+
return ((0, jsx_runtime_1.jsxs)(Stack_1.default, { sx: { mx: 3, my: 2 }, spacing: 2, ...rest, children: [(0, jsx_runtime_1.jsx)(PageContainerBar, { slots: slots, slotProps: slotProps }), children] }));
|
|
138
138
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import * as React from "react";
|
|
1
2
|
import type { Breadcrumb } from "../PageContainer";
|
|
2
3
|
export interface ActivePage {
|
|
3
4
|
title: string;
|
|
4
5
|
path: string;
|
|
5
6
|
sourcePath: string;
|
|
6
7
|
breadcrumbs: Breadcrumb[];
|
|
8
|
+
pageHeader?: React.ReactNode;
|
|
7
9
|
}
|
|
8
10
|
export declare function useActivePage(): ActivePage | null;
|
|
@@ -41,14 +41,13 @@ const navigation_1 = require("../shared/navigation");
|
|
|
41
41
|
function useActivePage() {
|
|
42
42
|
const navigationContext = React.useContext(context_1.NavigationContext);
|
|
43
43
|
const routerContext = React.useContext(context_1.RouterContext);
|
|
44
|
-
const
|
|
45
|
-
let pathname = routerContext?.pathname ?? "/";
|
|
44
|
+
const pathname = routerContext?.pathname ?? "/";
|
|
46
45
|
const activeItem = (0, navigation_1.matchPath)(navigationContext, pathname);
|
|
47
46
|
const rootItem = (0, navigation_1.matchPath)(navigationContext, "/");
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
return React.useMemo(() => {
|
|
48
|
+
if (!activeItem) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
52
51
|
const breadcrumbs = [];
|
|
53
52
|
if (rootItem) {
|
|
54
53
|
breadcrumbs.push({
|
|
@@ -74,19 +73,12 @@ function useActivePage() {
|
|
|
74
73
|
});
|
|
75
74
|
}
|
|
76
75
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
path,
|
|
86
|
-
sourcePath: pathname,
|
|
87
|
-
breadcrumbs
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return pageRef.current;
|
|
76
|
+
return {
|
|
77
|
+
title: (0, navigation_1.getItemTitle)(activeItem),
|
|
78
|
+
path: (0, navigation_1.getItemPath)(navigationContext, activeItem),
|
|
79
|
+
sourcePath: pathname,
|
|
80
|
+
breadcrumbs,
|
|
81
|
+
pageHeader: activeItem.pageHeader
|
|
82
|
+
};
|
|
83
|
+
}, [activeItem, rootItem, pathname, navigationContext]);
|
|
92
84
|
}
|
|
@@ -25,8 +25,7 @@ export type PageData = {
|
|
|
25
25
|
title?: string;
|
|
26
26
|
page?: string;
|
|
27
27
|
breadcrumbs?: Breadcrumb[];
|
|
28
|
-
|
|
29
|
-
noPageHeader?: boolean;
|
|
28
|
+
pageHeader?: React.ReactNode;
|
|
30
29
|
};
|
|
31
30
|
type PageDataAction = PageData;
|
|
32
31
|
export declare const PageDataContext: React.Context<{
|
|
@@ -35,10 +34,6 @@ export declare const PageDataContext: React.Context<{
|
|
|
35
34
|
}>;
|
|
36
35
|
export declare function PageDataContextProvider(props: React.PropsWithChildren<PageData>): import("react/jsx-runtime").JSX.Element;
|
|
37
36
|
type PageContainerBarProps = {
|
|
38
|
-
/**
|
|
39
|
-
* The default title of the page.
|
|
40
|
-
*/
|
|
41
|
-
defaultTitle?: string;
|
|
42
37
|
/**
|
|
43
38
|
* The components used for each slot inside.
|
|
44
39
|
*/
|
|
@@ -23,7 +23,7 @@ function reducer(state, action) {
|
|
|
23
23
|
let key;
|
|
24
24
|
let isSame = true;
|
|
25
25
|
for (key in action) {
|
|
26
|
-
if (action[key]
|
|
26
|
+
if (action[key] != state[key]) {
|
|
27
27
|
isSame = false;
|
|
28
28
|
break;
|
|
29
29
|
}
|
|
@@ -35,38 +35,30 @@ function reducer(state, action) {
|
|
|
35
35
|
}
|
|
36
36
|
export function PageDataContextProvider(props) {
|
|
37
37
|
// Destruct
|
|
38
|
-
const { title, page, breadcrumbs,
|
|
38
|
+
const { title, page, breadcrumbs, pageHeader, ...rest } = props;
|
|
39
39
|
// useReducer hook to manage state with our reducer function and initial state
|
|
40
40
|
const [state, dispatch] = React.useReducer(reducer, {
|
|
41
41
|
title,
|
|
42
42
|
page,
|
|
43
43
|
breadcrumbs,
|
|
44
|
-
|
|
45
|
-
noPageHeader
|
|
44
|
+
pageHeader
|
|
46
45
|
});
|
|
47
46
|
// Provide the state and dispatch function to the context value
|
|
48
47
|
return _jsx(PageDataContext.Provider, { value: { state, dispatch }, ...rest });
|
|
49
48
|
}
|
|
50
49
|
function PageContainerBar(props) {
|
|
51
|
-
const {
|
|
50
|
+
const { slots, slotProps } = props;
|
|
52
51
|
const { state } = React.useContext(PageDataContext);
|
|
53
52
|
const activePage = useActivePage();
|
|
54
|
-
React.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
React.useEffect(() => {
|
|
54
|
+
return () => {
|
|
55
|
+
// Reset the state when the component unmounts
|
|
56
|
+
state.breadcrumbs = undefined;
|
|
57
|
+
state.page = undefined;
|
|
58
|
+
state.pageHeader = undefined;
|
|
59
|
+
state.title = undefined;
|
|
60
|
+
};
|
|
61
61
|
}, [activePage?.sourcePath]);
|
|
62
|
-
let resolvedBreadcrumbs = state.breadcrumbs ?? activePage?.breadcrumbs ?? [];
|
|
63
|
-
const title = state.title ?? defaultTitle ?? activePage?.title ?? "";
|
|
64
|
-
if (state.page) {
|
|
65
|
-
resolvedBreadcrumbs = [
|
|
66
|
-
...resolvedBreadcrumbs,
|
|
67
|
-
{ title: state.page, path: "#" }
|
|
68
|
-
];
|
|
69
|
-
}
|
|
70
62
|
const ToolbarComponent = slots?.toolbar ?? PageContainerToolbar;
|
|
71
63
|
const toolbarSlotProps = useSlotProps({
|
|
72
64
|
elementType: ToolbarComponent,
|
|
@@ -74,11 +66,19 @@ function PageContainerBar(props) {
|
|
|
74
66
|
externalSlotProps: slotProps?.toolbar,
|
|
75
67
|
additionalProps: {}
|
|
76
68
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
69
|
+
const breadcrumbs = state.breadcrumbs ?? activePage?.breadcrumbs ?? [];
|
|
70
|
+
const title = state.title ?? activePage?.title ?? "";
|
|
71
|
+
const pageHeader = state.pageHeader ?? activePage?.pageHeader ?? null;
|
|
72
|
+
if (pageHeader === false)
|
|
73
|
+
return undefined;
|
|
74
|
+
if (pageHeader != null)
|
|
75
|
+
return pageHeader;
|
|
76
|
+
if (state.page) {
|
|
77
|
+
breadcrumbs.push({ title: state.page, path: "#" });
|
|
78
|
+
}
|
|
79
|
+
return (_jsxs(Stack, { children: [breadcrumbs && (_jsx(Breadcrumbs, { "aria-label": "breadcrumb", children: breadcrumbs.map((item, index) => {
|
|
80
|
+
return index < breadcrumbs.length - 1 ? (_jsx(Link, { component: ToolpadLink, underline: "hover", color: "inherit", href: item.path, children: getItemTitle(item) }, item.path)) : (_jsx(Typography, { color: "text.primary", children: getItemTitle(item) }, item.path));
|
|
81
|
+
}) })), _jsxs(PageContentHeader, { children: [title ? _jsx(Typography, { variant: "h4", children: title }) : null, _jsx(ToolbarComponent, { ...toolbarSlotProps })] })] }));
|
|
82
82
|
}
|
|
83
83
|
/**
|
|
84
84
|
* A container component to provide a title and breadcrumbs for your pages.
|
|
@@ -92,7 +92,7 @@ function PageContainerBar(props) {
|
|
|
92
92
|
* - [PageContainer API](https://mui.com/toolpad/core/api/page-container)
|
|
93
93
|
*/
|
|
94
94
|
function PageContainer(props) {
|
|
95
|
-
const { children,
|
|
96
|
-
return (_jsxs(Stack, { sx: { mx: 3, my: 2 }, spacing: 2, ...rest, children: [_jsx(PageContainerBar, {
|
|
95
|
+
const { children, slots, slotProps, ...rest } = props;
|
|
96
|
+
return (_jsxs(Stack, { sx: { mx: 3, my: 2 }, spacing: 2, ...rest, children: [_jsx(PageContainerBar, { slots: slots, slotProps: slotProps }), children] }));
|
|
97
97
|
}
|
|
98
98
|
export { PageContainer };
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import * as React from "react";
|
|
1
2
|
import type { Breadcrumb } from "../PageContainer";
|
|
2
3
|
export interface ActivePage {
|
|
3
4
|
title: string;
|
|
4
5
|
path: string;
|
|
5
6
|
sourcePath: string;
|
|
6
7
|
breadcrumbs: Breadcrumb[];
|
|
8
|
+
pageHeader?: React.ReactNode;
|
|
7
9
|
}
|
|
8
10
|
export declare function useActivePage(): ActivePage | null;
|
|
@@ -5,14 +5,13 @@ import { getItemPath, getItemTitle, matchPath } from "../shared/navigation";
|
|
|
5
5
|
export function useActivePage() {
|
|
6
6
|
const navigationContext = React.useContext(NavigationContext);
|
|
7
7
|
const routerContext = React.useContext(RouterContext);
|
|
8
|
-
const
|
|
9
|
-
let pathname = routerContext?.pathname ?? "/";
|
|
8
|
+
const pathname = routerContext?.pathname ?? "/";
|
|
10
9
|
const activeItem = matchPath(navigationContext, pathname);
|
|
11
10
|
const rootItem = matchPath(navigationContext, "/");
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
return React.useMemo(() => {
|
|
12
|
+
if (!activeItem) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
16
15
|
const breadcrumbs = [];
|
|
17
16
|
if (rootItem) {
|
|
18
17
|
breadcrumbs.push({
|
|
@@ -38,19 +37,12 @@ export function useActivePage() {
|
|
|
38
37
|
});
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
path,
|
|
50
|
-
sourcePath: pathname,
|
|
51
|
-
breadcrumbs
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return pageRef.current;
|
|
40
|
+
return {
|
|
41
|
+
title: getItemTitle(activeItem),
|
|
42
|
+
path: getItemPath(navigationContext, activeItem),
|
|
43
|
+
sourcePath: pathname,
|
|
44
|
+
breadcrumbs,
|
|
45
|
+
pageHeader: activeItem.pageHeader
|
|
46
|
+
};
|
|
47
|
+
}, [activeItem, rootItem, pathname, navigationContext]);
|
|
56
48
|
}
|
package/package.json
CHANGED
|
@@ -48,8 +48,7 @@ export type PageData = {
|
|
|
48
48
|
title?: string;
|
|
49
49
|
page?: string;
|
|
50
50
|
breadcrumbs?: Breadcrumb[];
|
|
51
|
-
|
|
52
|
-
noPageHeader?: boolean;
|
|
51
|
+
pageHeader?: React.ReactNode;
|
|
53
52
|
};
|
|
54
53
|
|
|
55
54
|
type PageDataAction = PageData;
|
|
@@ -64,7 +63,7 @@ function reducer(state: PageData, action: PageDataAction) {
|
|
|
64
63
|
let key: keyof PageDataAction;
|
|
65
64
|
let isSame = true;
|
|
66
65
|
for (key in action) {
|
|
67
|
-
if (action[key]
|
|
66
|
+
if (action[key] != state[key]) {
|
|
68
67
|
isSame = false;
|
|
69
68
|
break;
|
|
70
69
|
}
|
|
@@ -81,16 +80,14 @@ export function PageDataContextProvider(
|
|
|
81
80
|
props: React.PropsWithChildren<PageData>
|
|
82
81
|
) {
|
|
83
82
|
// Destruct
|
|
84
|
-
const { title, page, breadcrumbs,
|
|
85
|
-
props;
|
|
83
|
+
const { title, page, breadcrumbs, pageHeader, ...rest } = props;
|
|
86
84
|
|
|
87
85
|
// useReducer hook to manage state with our reducer function and initial state
|
|
88
86
|
const [state, dispatch] = React.useReducer(reducer, {
|
|
89
87
|
title,
|
|
90
88
|
page,
|
|
91
89
|
breadcrumbs,
|
|
92
|
-
|
|
93
|
-
noPageHeader
|
|
90
|
+
pageHeader
|
|
94
91
|
});
|
|
95
92
|
|
|
96
93
|
// Provide the state and dispatch function to the context value
|
|
@@ -98,10 +95,6 @@ export function PageDataContextProvider(
|
|
|
98
95
|
}
|
|
99
96
|
|
|
100
97
|
type PageContainerBarProps = {
|
|
101
|
-
/**
|
|
102
|
-
* The default title of the page.
|
|
103
|
-
*/
|
|
104
|
-
defaultTitle?: string;
|
|
105
98
|
/**
|
|
106
99
|
* The components used for each slot inside.
|
|
107
100
|
*/
|
|
@@ -113,31 +106,22 @@ type PageContainerBarProps = {
|
|
|
113
106
|
};
|
|
114
107
|
|
|
115
108
|
function PageContainerBar(props: PageContainerBarProps) {
|
|
116
|
-
const {
|
|
109
|
+
const { slots, slotProps } = props;
|
|
117
110
|
|
|
118
111
|
const { state } = React.useContext(PageDataContext);
|
|
119
112
|
|
|
120
113
|
const activePage = useActivePage();
|
|
121
114
|
|
|
122
|
-
React.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
115
|
+
React.useEffect(() => {
|
|
116
|
+
return () => {
|
|
117
|
+
// Reset the state when the component unmounts
|
|
118
|
+
state.breadcrumbs = undefined;
|
|
119
|
+
state.page = undefined;
|
|
120
|
+
state.pageHeader = undefined;
|
|
121
|
+
state.title = undefined;
|
|
122
|
+
};
|
|
129
123
|
}, [activePage?.sourcePath]);
|
|
130
124
|
|
|
131
|
-
let resolvedBreadcrumbs = state.breadcrumbs ?? activePage?.breadcrumbs ?? [];
|
|
132
|
-
const title = state.title ?? defaultTitle ?? activePage?.title ?? "";
|
|
133
|
-
|
|
134
|
-
if (state.page) {
|
|
135
|
-
resolvedBreadcrumbs = [
|
|
136
|
-
...resolvedBreadcrumbs,
|
|
137
|
-
{ title: state.page, path: "#" }
|
|
138
|
-
];
|
|
139
|
-
}
|
|
140
|
-
|
|
141
125
|
const ToolbarComponent = slots?.toolbar ?? PageContainerToolbar;
|
|
142
126
|
const toolbarSlotProps = useSlotProps({
|
|
143
127
|
elementType: ToolbarComponent,
|
|
@@ -146,29 +130,38 @@ function PageContainerBar(props: PageContainerBarProps) {
|
|
|
146
130
|
additionalProps: {}
|
|
147
131
|
});
|
|
148
132
|
|
|
149
|
-
|
|
133
|
+
const breadcrumbs = state.breadcrumbs ?? activePage?.breadcrumbs ?? [];
|
|
134
|
+
const title = state.title ?? activePage?.title ?? "";
|
|
135
|
+
const pageHeader = state.pageHeader ?? activePage?.pageHeader ?? null;
|
|
136
|
+
|
|
137
|
+
if (pageHeader === false) return undefined;
|
|
138
|
+
if (pageHeader != null) return pageHeader;
|
|
139
|
+
|
|
140
|
+
if (state.page) {
|
|
141
|
+
breadcrumbs.push({ title: state.page, path: "#" });
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return (
|
|
150
145
|
<Stack>
|
|
151
|
-
{
|
|
146
|
+
{breadcrumbs && (
|
|
152
147
|
<Breadcrumbs aria-label="breadcrumb">
|
|
153
|
-
{
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
})
|
|
171
|
-
: null}
|
|
148
|
+
{breadcrumbs.map((item, index) => {
|
|
149
|
+
return index < breadcrumbs.length - 1 ? (
|
|
150
|
+
<Link
|
|
151
|
+
key={item.path}
|
|
152
|
+
component={ToolpadLink}
|
|
153
|
+
underline="hover"
|
|
154
|
+
color="inherit"
|
|
155
|
+
href={item.path}
|
|
156
|
+
>
|
|
157
|
+
{getItemTitle(item)}
|
|
158
|
+
</Link>
|
|
159
|
+
) : (
|
|
160
|
+
<Typography key={item.path} color="text.primary">
|
|
161
|
+
{getItemTitle(item)}
|
|
162
|
+
</Typography>
|
|
163
|
+
);
|
|
164
|
+
})}
|
|
172
165
|
</Breadcrumbs>
|
|
173
166
|
)}
|
|
174
167
|
<PageContentHeader>
|
|
@@ -176,7 +169,7 @@ function PageContainerBar(props: PageContainerBarProps) {
|
|
|
176
169
|
<ToolbarComponent {...toolbarSlotProps} />
|
|
177
170
|
</PageContentHeader>
|
|
178
171
|
</Stack>
|
|
179
|
-
)
|
|
172
|
+
);
|
|
180
173
|
}
|
|
181
174
|
|
|
182
175
|
export type PageContainerProps = React.PropsWithChildren<
|
|
@@ -195,15 +188,11 @@ export type PageContainerProps = React.PropsWithChildren<
|
|
|
195
188
|
* - [PageContainer API](https://mui.com/toolpad/core/api/page-container)
|
|
196
189
|
*/
|
|
197
190
|
function PageContainer(props: PageContainerProps) {
|
|
198
|
-
const { children,
|
|
191
|
+
const { children, slots, slotProps, ...rest } = props;
|
|
199
192
|
|
|
200
193
|
return (
|
|
201
194
|
<Stack sx={{ mx: 3, my: 2 }} spacing={2} {...rest}>
|
|
202
|
-
<PageContainerBar
|
|
203
|
-
defaultTitle={defaultTitle}
|
|
204
|
-
slots={slots}
|
|
205
|
-
slotProps={slotProps}
|
|
206
|
-
/>
|
|
195
|
+
<PageContainerBar slots={slots} slotProps={slotProps} />
|
|
207
196
|
{children}
|
|
208
197
|
</Stack>
|
|
209
198
|
);
|
|
@@ -9,22 +9,23 @@ export interface ActivePage {
|
|
|
9
9
|
path: string;
|
|
10
10
|
sourcePath: string;
|
|
11
11
|
breadcrumbs: Breadcrumb[];
|
|
12
|
+
pageHeader?: React.ReactNode;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export function useActivePage(): ActivePage | null {
|
|
15
16
|
const navigationContext = React.useContext(NavigationContext);
|
|
16
17
|
const routerContext = React.useContext(RouterContext);
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
let pathname = routerContext?.pathname ?? "/";
|
|
19
|
+
const pathname = routerContext?.pathname ?? "/";
|
|
21
20
|
const activeItem = matchPath(navigationContext, pathname);
|
|
22
21
|
|
|
23
22
|
const rootItem = matchPath(navigationContext, "/");
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
return React.useMemo(() => {
|
|
25
|
+
if (!activeItem) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
28
29
|
const breadcrumbs: Breadcrumb[] = [];
|
|
29
30
|
|
|
30
31
|
if (rootItem) {
|
|
@@ -53,23 +54,12 @@ export function useActivePage(): ActivePage | null {
|
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
) {
|
|
65
|
-
pageRef.current = {
|
|
66
|
-
title,
|
|
67
|
-
path,
|
|
68
|
-
sourcePath: pathname,
|
|
69
|
-
breadcrumbs
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return pageRef.current;
|
|
57
|
+
return {
|
|
58
|
+
title: getItemTitle(activeItem),
|
|
59
|
+
path: getItemPath(navigationContext, activeItem),
|
|
60
|
+
sourcePath: pathname,
|
|
61
|
+
breadcrumbs,
|
|
62
|
+
pageHeader: activeItem.pageHeader
|
|
63
|
+
};
|
|
64
|
+
}, [activeItem, rootItem, pathname, navigationContext]);
|
|
75
65
|
}
|