@tker-react/layout 0.2.8 → 0.2.10
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/README.md +23 -14
- package/dist/index.d.mts +23 -33
- package/dist/index.d.ts +23 -33
- package/dist/index.mjs +131 -131
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -148,14 +148,22 @@ import type { MenuAdapterProps, MenuItem } from "@tker-react/layout";
|
|
|
148
148
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
|
149
149
|
import { cn } from "@/lib/utils";
|
|
150
150
|
|
|
151
|
-
function MenuAdapter({
|
|
151
|
+
function MenuAdapter({
|
|
152
|
+
menuData,
|
|
153
|
+
activePath,
|
|
154
|
+
collapsed,
|
|
155
|
+
mode,
|
|
156
|
+
openKeys,
|
|
157
|
+
onSelect,
|
|
158
|
+
onMenuItemClick,
|
|
159
|
+
}: MenuAdapterProps) {
|
|
152
160
|
if (mode === "top") {
|
|
153
161
|
return (
|
|
154
162
|
<nav className="flex items-center gap-1 h-full">
|
|
155
163
|
{menuData.map((item) => (
|
|
156
164
|
<button
|
|
157
165
|
key={item.path}
|
|
158
|
-
onClick={() =>
|
|
166
|
+
onClick={() => onMenuItemClick(item.path)}
|
|
159
167
|
className={cn(
|
|
160
168
|
"px-3 py-1 text-sm rounded-md",
|
|
161
169
|
activePath === item.path ? "bg-accent text-accent-foreground" : "hover:bg-muted"
|
|
@@ -177,7 +185,8 @@ function MenuAdapter({ menuData, activePath, collapsed, mode, onSelect }: MenuAd
|
|
|
177
185
|
item={item}
|
|
178
186
|
activePath={activePath}
|
|
179
187
|
collapsed={collapsed}
|
|
180
|
-
|
|
188
|
+
openKeys={openKeys}
|
|
189
|
+
onMenuItemClick={onMenuItemClick}
|
|
181
190
|
/>
|
|
182
191
|
))}
|
|
183
192
|
</nav>
|
|
@@ -188,20 +197,23 @@ function MenuItemRenderer({
|
|
|
188
197
|
item,
|
|
189
198
|
activePath,
|
|
190
199
|
collapsed,
|
|
191
|
-
|
|
200
|
+
openKeys,
|
|
201
|
+
onMenuItemClick,
|
|
192
202
|
depth = 0,
|
|
193
203
|
}: {
|
|
194
204
|
item: MenuItem;
|
|
195
205
|
activePath: string;
|
|
196
206
|
collapsed: boolean;
|
|
197
|
-
|
|
207
|
+
openKeys: Set<string>;
|
|
208
|
+
onMenuItemClick: (path: string) => void;
|
|
198
209
|
depth?: number;
|
|
199
210
|
}) {
|
|
200
211
|
const hasChildren = item.children && item.children.length > 0;
|
|
212
|
+
const isOpen = openKeys.has(item.path);
|
|
201
213
|
|
|
202
214
|
if (hasChildren) {
|
|
203
215
|
return (
|
|
204
|
-
<Collapsible>
|
|
216
|
+
<Collapsible open={isOpen} onOpenChange={() => onMenuItemClick(item.path)}>
|
|
205
217
|
<CollapsibleTrigger
|
|
206
218
|
className={cn(
|
|
207
219
|
"flex items-center w-full rounded-md text-sm hover:bg-muted px-2 py-1.5",
|
|
@@ -224,7 +236,8 @@ function MenuItemRenderer({
|
|
|
224
236
|
item={child}
|
|
225
237
|
activePath={activePath}
|
|
226
238
|
collapsed={collapsed}
|
|
227
|
-
|
|
239
|
+
openKeys={openKeys}
|
|
240
|
+
onMenuItemClick={onMenuItemClick}
|
|
228
241
|
depth={depth + 1}
|
|
229
242
|
/>
|
|
230
243
|
))}
|
|
@@ -235,7 +248,7 @@ function MenuItemRenderer({
|
|
|
235
248
|
|
|
236
249
|
return (
|
|
237
250
|
<button
|
|
238
|
-
onClick={() =>
|
|
251
|
+
onClick={() => onMenuItemClick(item.path)}
|
|
239
252
|
className={cn(
|
|
240
253
|
"flex items-center rounded-md text-sm px-2 py-1.5",
|
|
241
254
|
activePath === item.path
|
|
@@ -308,7 +321,6 @@ function TabAdapter({
|
|
|
308
321
|
onClose,
|
|
309
322
|
onCloseOther,
|
|
310
323
|
onCloseAll,
|
|
311
|
-
onRefresh,
|
|
312
324
|
}: TabAdapterProps) {
|
|
313
325
|
return (
|
|
314
326
|
<div className="flex items-center h-9 bg-muted border-b">
|
|
@@ -337,9 +349,6 @@ function TabAdapter({
|
|
|
337
349
|
</div>
|
|
338
350
|
))}
|
|
339
351
|
</div>
|
|
340
|
-
<button onClick={onRefresh} className="p-2 hover:bg-muted shrink-0">
|
|
341
|
-
<RotateCw className="w-3.5 h-3.5" />
|
|
342
|
-
</button>
|
|
343
352
|
<DropdownMenu>
|
|
344
353
|
<DropdownMenuTrigger className="p-2 hover:bg-muted shrink-0">
|
|
345
354
|
<ChevronDown className="w-3.5 h-3.5" />
|
|
@@ -493,8 +502,8 @@ useLayoutEffect(() => {
|
|
|
493
502
|
|
|
494
503
|
| Adapter | Props |
|
|
495
504
|
|---------|-------|
|
|
496
|
-
| `menu` | `menuData`, `activePath`, `collapsed`, `mode` (`"side"|"top"`), `width`, `onSelect(path)` |
|
|
497
|
-
| `tab` | `tabData`, `activeTab`, `onSelect(path)`, `onClose(path)`, `onCloseOther(path?)`, `onCloseAll()`, `
|
|
505
|
+
| `menu` | `menuData`, `activePath`, `collapsed`, `mode` (`"side"|"top"`), `width`, `openKeys`, `onSelect(path)`, `onMenuItemClick(path)` |
|
|
506
|
+
| `tab` | `tabData`, `activeTab`, `onSelect(path)`, `onClose(path)`, `onCloseOther(path?)`, `onCloseAll()`, `onSetFixed(path, fixed)` |
|
|
498
507
|
| `breadcrumb` | `breadcrumbData`, `onSelect(path)` |
|
|
499
508
|
| `logo` | `collapsed`, `width` |
|
|
500
509
|
| `toolbar` | 无 props |
|
package/dist/index.d.mts
CHANGED
|
@@ -3,8 +3,10 @@ import { ReactNode, ComponentType } from 'react';
|
|
|
3
3
|
|
|
4
4
|
interface LayoutProps {
|
|
5
5
|
children?: ReactNode;
|
|
6
|
+
activePath?: string;
|
|
7
|
+
activeFullPath?: string;
|
|
6
8
|
}
|
|
7
|
-
declare function Layout({ children }: LayoutProps): react_jsx_runtime.JSX.Element;
|
|
9
|
+
declare function Layout({ children, ...props }: LayoutProps): react_jsx_runtime.JSX.Element;
|
|
8
10
|
|
|
9
11
|
interface BreadcrumbItem {
|
|
10
12
|
path: string;
|
|
@@ -55,7 +57,6 @@ interface TabAdapterProps {
|
|
|
55
57
|
onClose: (path: string) => void;
|
|
56
58
|
onCloseOther: (path?: string) => void;
|
|
57
59
|
onCloseAll: () => void;
|
|
58
|
-
onRefresh: () => void;
|
|
59
60
|
onSetFixed: (path: string, fixed: boolean) => void;
|
|
60
61
|
}
|
|
61
62
|
interface UserAvatarAdapterProps {
|
|
@@ -71,37 +72,26 @@ interface LayoutAdapters {
|
|
|
71
72
|
userAvatar?: ComponentType<UserAvatarAdapterProps>;
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
interface
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
setBreadcrumbAdapter: (component: ComponentType<BreadcrumbAdapterProps>) => void;
|
|
79
|
-
setLogoAdapter: (component: ComponentType<LogoAdapterProps>) => void;
|
|
80
|
-
setToolbarAdapter: (component: ComponentType) => void;
|
|
81
|
-
setUserAvatarAdapter: (component: ComponentType<UserAvatarAdapterProps>) => void;
|
|
82
|
-
menuData: MenuItem[];
|
|
83
|
-
activePath: string;
|
|
84
|
-
expandedWidth: string;
|
|
85
|
-
collapsedWidth: string;
|
|
86
|
-
layoutMode: "side-menu" | "top-menu";
|
|
87
|
-
setMenus: (data: MenuItem[]) => void;
|
|
88
|
-
setActivePath: (path: string, fullPath?: string) => void;
|
|
89
|
-
setExpandedWidth: (width: string) => void;
|
|
90
|
-
setCollapsedWidth: (width: string) => void;
|
|
91
|
-
setLayoutMode: (mode: "side-menu" | "top-menu") => void;
|
|
92
|
-
isConcretePage: (path: string) => boolean;
|
|
93
|
-
getFullPath: (path: string) => string;
|
|
94
|
-
setNavigateAdapter: (fn: (path: string) => void) => void;
|
|
95
|
-
navigate: (path: string) => void;
|
|
96
|
-
homePath: string;
|
|
97
|
-
setHomePath: (path: string) => void;
|
|
98
|
-
maxTabs: number;
|
|
99
|
-
setMaxTabs: (max: number) => void;
|
|
75
|
+
interface LayoutProviderProps {
|
|
76
|
+
children?: ReactNode;
|
|
77
|
+
activePath?: string;
|
|
78
|
+
activeFullPath?: string;
|
|
100
79
|
}
|
|
101
|
-
declare function
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
80
|
+
declare function LayoutProvider({ children, activePath, activeFullPath, }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
|
|
81
|
+
|
|
82
|
+
declare function setMenus(data: MenuItem[]): void;
|
|
83
|
+
declare function setMenuAdapter(c: ComponentType<MenuAdapterProps>): void;
|
|
84
|
+
declare function setTabAdapter(c: ComponentType<TabAdapterProps>): void;
|
|
85
|
+
declare function setBreadcrumbAdapter(c: ComponentType<BreadcrumbAdapterProps>): void;
|
|
86
|
+
declare function setLogoAdapter(c: ComponentType<LogoAdapterProps>): void;
|
|
87
|
+
declare function setToolbarAdapter(c: ComponentType): void;
|
|
88
|
+
declare function setUserAvatarAdapter(c: ComponentType<UserAvatarAdapterProps>): void;
|
|
89
|
+
declare function setHomePath(path: string): void;
|
|
90
|
+
declare function setMaxTabs(max: number): void;
|
|
91
|
+
declare function setLayoutMode(mode: "side-menu" | "top-menu"): void;
|
|
92
|
+
declare function setExpandedWidth(width: string): void;
|
|
93
|
+
declare function setCollapsedWidth(width: string): void;
|
|
94
|
+
declare function setNavigateAdapter(fn: (path: string) => void): void;
|
|
105
95
|
|
|
106
|
-
export { Layout, LayoutProvider,
|
|
96
|
+
export { Layout, LayoutProvider, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
|
|
107
97
|
export type { BreadcrumbAdapterProps, BreadcrumbItem, LayoutAdapters, LogoAdapterProps, MenuAdapterProps, MenuItem, TabAdapterProps, TabItem, UserAvatarAdapterProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,10 @@ import { ReactNode, ComponentType } from 'react';
|
|
|
3
3
|
|
|
4
4
|
interface LayoutProps {
|
|
5
5
|
children?: ReactNode;
|
|
6
|
+
activePath?: string;
|
|
7
|
+
activeFullPath?: string;
|
|
6
8
|
}
|
|
7
|
-
declare function Layout({ children }: LayoutProps): react_jsx_runtime.JSX.Element;
|
|
9
|
+
declare function Layout({ children, ...props }: LayoutProps): react_jsx_runtime.JSX.Element;
|
|
8
10
|
|
|
9
11
|
interface BreadcrumbItem {
|
|
10
12
|
path: string;
|
|
@@ -55,7 +57,6 @@ interface TabAdapterProps {
|
|
|
55
57
|
onClose: (path: string) => void;
|
|
56
58
|
onCloseOther: (path?: string) => void;
|
|
57
59
|
onCloseAll: () => void;
|
|
58
|
-
onRefresh: () => void;
|
|
59
60
|
onSetFixed: (path: string, fixed: boolean) => void;
|
|
60
61
|
}
|
|
61
62
|
interface UserAvatarAdapterProps {
|
|
@@ -71,37 +72,26 @@ interface LayoutAdapters {
|
|
|
71
72
|
userAvatar?: ComponentType<UserAvatarAdapterProps>;
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
interface
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
setBreadcrumbAdapter: (component: ComponentType<BreadcrumbAdapterProps>) => void;
|
|
79
|
-
setLogoAdapter: (component: ComponentType<LogoAdapterProps>) => void;
|
|
80
|
-
setToolbarAdapter: (component: ComponentType) => void;
|
|
81
|
-
setUserAvatarAdapter: (component: ComponentType<UserAvatarAdapterProps>) => void;
|
|
82
|
-
menuData: MenuItem[];
|
|
83
|
-
activePath: string;
|
|
84
|
-
expandedWidth: string;
|
|
85
|
-
collapsedWidth: string;
|
|
86
|
-
layoutMode: "side-menu" | "top-menu";
|
|
87
|
-
setMenus: (data: MenuItem[]) => void;
|
|
88
|
-
setActivePath: (path: string, fullPath?: string) => void;
|
|
89
|
-
setExpandedWidth: (width: string) => void;
|
|
90
|
-
setCollapsedWidth: (width: string) => void;
|
|
91
|
-
setLayoutMode: (mode: "side-menu" | "top-menu") => void;
|
|
92
|
-
isConcretePage: (path: string) => boolean;
|
|
93
|
-
getFullPath: (path: string) => string;
|
|
94
|
-
setNavigateAdapter: (fn: (path: string) => void) => void;
|
|
95
|
-
navigate: (path: string) => void;
|
|
96
|
-
homePath: string;
|
|
97
|
-
setHomePath: (path: string) => void;
|
|
98
|
-
maxTabs: number;
|
|
99
|
-
setMaxTabs: (max: number) => void;
|
|
75
|
+
interface LayoutProviderProps {
|
|
76
|
+
children?: ReactNode;
|
|
77
|
+
activePath?: string;
|
|
78
|
+
activeFullPath?: string;
|
|
100
79
|
}
|
|
101
|
-
declare function
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
80
|
+
declare function LayoutProvider({ children, activePath, activeFullPath, }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
|
|
81
|
+
|
|
82
|
+
declare function setMenus(data: MenuItem[]): void;
|
|
83
|
+
declare function setMenuAdapter(c: ComponentType<MenuAdapterProps>): void;
|
|
84
|
+
declare function setTabAdapter(c: ComponentType<TabAdapterProps>): void;
|
|
85
|
+
declare function setBreadcrumbAdapter(c: ComponentType<BreadcrumbAdapterProps>): void;
|
|
86
|
+
declare function setLogoAdapter(c: ComponentType<LogoAdapterProps>): void;
|
|
87
|
+
declare function setToolbarAdapter(c: ComponentType): void;
|
|
88
|
+
declare function setUserAvatarAdapter(c: ComponentType<UserAvatarAdapterProps>): void;
|
|
89
|
+
declare function setHomePath(path: string): void;
|
|
90
|
+
declare function setMaxTabs(max: number): void;
|
|
91
|
+
declare function setLayoutMode(mode: "side-menu" | "top-menu"): void;
|
|
92
|
+
declare function setExpandedWidth(width: string): void;
|
|
93
|
+
declare function setCollapsedWidth(width: string): void;
|
|
94
|
+
declare function setNavigateAdapter(fn: (path: string) => void): void;
|
|
105
95
|
|
|
106
|
-
export { Layout, LayoutProvider,
|
|
96
|
+
export { Layout, LayoutProvider, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
|
|
107
97
|
export type { BreadcrumbAdapterProps, BreadcrumbItem, LayoutAdapters, LogoAdapterProps, MenuAdapterProps, MenuItem, TabAdapterProps, TabItem, UserAvatarAdapterProps };
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./layout.css";
|
|
2
2
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
-
import {
|
|
3
|
+
import { useRef, useCallback, useMemo, useState, useEffect, createContext, useContext } from 'react';
|
|
4
4
|
|
|
5
5
|
function findMenuItemByPath(menuData, path) {
|
|
6
6
|
for (const item of menuData) {
|
|
@@ -43,88 +43,143 @@ function generateBreadcrumb(menuData, activePath) {
|
|
|
43
43
|
}));
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
let _menus = [];
|
|
47
|
+
let _menuAdapter;
|
|
48
|
+
let _tabAdapter;
|
|
49
|
+
let _breadcrumbAdapter;
|
|
50
|
+
let _logoAdapter;
|
|
51
|
+
let _toolbarAdapter;
|
|
52
|
+
let _userAvatarAdapter;
|
|
53
|
+
let _homePath = "";
|
|
54
|
+
let _maxTabs = 10;
|
|
55
|
+
let _layoutMode = "side-menu";
|
|
56
|
+
let _expandedWidth = "200px";
|
|
57
|
+
let _collapsedWidth = "64px";
|
|
58
|
+
let _navigateAdapter = null;
|
|
59
|
+
function setMenus(data) {
|
|
60
|
+
_menus = data;
|
|
61
|
+
}
|
|
62
|
+
function setMenuAdapter(c) {
|
|
63
|
+
_menuAdapter = c;
|
|
64
|
+
}
|
|
65
|
+
function setTabAdapter(c) {
|
|
66
|
+
_tabAdapter = c;
|
|
67
|
+
}
|
|
68
|
+
function setBreadcrumbAdapter(c) {
|
|
69
|
+
_breadcrumbAdapter = c;
|
|
70
|
+
}
|
|
71
|
+
function setLogoAdapter(c) {
|
|
72
|
+
_logoAdapter = c;
|
|
73
|
+
}
|
|
74
|
+
function setToolbarAdapter(c) {
|
|
75
|
+
_toolbarAdapter = c;
|
|
76
|
+
}
|
|
77
|
+
function setUserAvatarAdapter(c) {
|
|
78
|
+
_userAvatarAdapter = c;
|
|
79
|
+
}
|
|
80
|
+
function setHomePath(path) {
|
|
81
|
+
_homePath = path;
|
|
82
|
+
}
|
|
83
|
+
function setMaxTabs(max) {
|
|
84
|
+
_maxTabs = max;
|
|
85
|
+
}
|
|
86
|
+
function setLayoutMode(mode) {
|
|
87
|
+
_layoutMode = mode;
|
|
88
|
+
}
|
|
89
|
+
function setExpandedWidth(width) {
|
|
90
|
+
_expandedWidth = width;
|
|
91
|
+
}
|
|
92
|
+
function setCollapsedWidth(width) {
|
|
93
|
+
_collapsedWidth = width;
|
|
94
|
+
}
|
|
95
|
+
function setNavigateAdapter(fn) {
|
|
96
|
+
_navigateAdapter = fn;
|
|
97
|
+
}
|
|
98
|
+
function consumeLayoutConfig() {
|
|
99
|
+
return {
|
|
100
|
+
menus: _menus,
|
|
101
|
+
menuAdapter: _menuAdapter,
|
|
102
|
+
tabAdapter: _tabAdapter,
|
|
103
|
+
breadcrumbAdapter: _breadcrumbAdapter,
|
|
104
|
+
logoAdapter: _logoAdapter,
|
|
105
|
+
toolbarAdapter: _toolbarAdapter,
|
|
106
|
+
userAvatarAdapter: _userAvatarAdapter,
|
|
107
|
+
homePath: _homePath,
|
|
108
|
+
maxTabs: _maxTabs,
|
|
109
|
+
layoutMode: _layoutMode,
|
|
110
|
+
expandedWidth: _expandedWidth,
|
|
111
|
+
collapsedWidth: _collapsedWidth,
|
|
112
|
+
navigateAdapter: _navigateAdapter
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
46
116
|
const LayoutContext = createContext(null);
|
|
47
117
|
const LayoutInteractionContext = createContext(null);
|
|
48
118
|
function useLayoutInteractionContext() {
|
|
49
119
|
const ctx = useContext(LayoutInteractionContext);
|
|
50
|
-
if (!ctx)
|
|
51
|
-
throw new Error("useLayoutInteractionContext \u5FC5\u987B\u5728 <Layout> \u5185\u90E8\u4F7F\u7528");
|
|
52
|
-
}
|
|
120
|
+
if (!ctx) throw new Error("useLayoutInteractionContext \u5FC5\u987B\u5728 <Layout> \u5185\u90E8\u4F7F\u7528");
|
|
53
121
|
return ctx;
|
|
54
122
|
}
|
|
55
123
|
const LayoutOpenKeysContext = createContext(null);
|
|
56
124
|
function useLayoutOpenKeysContext() {
|
|
57
125
|
const ctx = useContext(LayoutOpenKeysContext);
|
|
58
|
-
if (!ctx)
|
|
59
|
-
throw new Error("useLayoutOpenKeysContext \u5FC5\u987B\u5728 <Layout> \u5185\u90E8\u4F7F\u7528");
|
|
60
|
-
}
|
|
126
|
+
if (!ctx) throw new Error("useLayoutOpenKeysContext \u5FC5\u987B\u5728 <Layout> \u5185\u90E8\u4F7F\u7528");
|
|
61
127
|
return ctx;
|
|
62
128
|
}
|
|
63
129
|
function useLayoutContext() {
|
|
64
130
|
const ctx = useContext(LayoutContext);
|
|
65
|
-
if (!ctx)
|
|
66
|
-
throw new Error("useLayoutContext \u5FC5\u987B\u5728 <Layout> \u5185\u90E8\u4F7F\u7528");
|
|
67
|
-
}
|
|
131
|
+
if (!ctx) throw new Error("useLayoutContext \u5FC5\u987B\u5728 <Layout> \u5185\u90E8\u4F7F\u7528");
|
|
68
132
|
return ctx;
|
|
69
133
|
}
|
|
70
|
-
function LayoutProvider({
|
|
134
|
+
function LayoutProvider({
|
|
135
|
+
children,
|
|
136
|
+
activePath = "",
|
|
137
|
+
activeFullPath
|
|
138
|
+
}) {
|
|
139
|
+
const config = consumeLayoutConfig();
|
|
71
140
|
const navigateRef = useRef(null);
|
|
72
|
-
|
|
73
|
-
(fn) => {
|
|
74
|
-
navigateRef.current = fn;
|
|
75
|
-
},
|
|
76
|
-
[]
|
|
77
|
-
);
|
|
141
|
+
navigateRef.current = config.navigateAdapter;
|
|
78
142
|
const navigate = useCallback(
|
|
79
143
|
(path) => {
|
|
80
144
|
navigateRef.current?.(path);
|
|
81
145
|
},
|
|
82
146
|
[]
|
|
83
147
|
);
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const setToolbarAdapter = useCallback(
|
|
102
|
-
(c) => setAdapters((prev) => prev.toolbar === c ? prev : { ...prev, toolbar: c }),
|
|
103
|
-
[]
|
|
104
|
-
);
|
|
105
|
-
const setUserAvatarAdapter = useCallback(
|
|
106
|
-
(c) => setAdapters((prev) => prev.userAvatar === c ? prev : { ...prev, userAvatar: c }),
|
|
107
|
-
[]
|
|
148
|
+
const adapters = useMemo(
|
|
149
|
+
() => ({
|
|
150
|
+
menu: config.menuAdapter,
|
|
151
|
+
tab: config.tabAdapter,
|
|
152
|
+
breadcrumb: config.breadcrumbAdapter,
|
|
153
|
+
logo: config.logoAdapter,
|
|
154
|
+
toolbar: config.toolbarAdapter,
|
|
155
|
+
userAvatar: config.userAvatarAdapter
|
|
156
|
+
}),
|
|
157
|
+
[
|
|
158
|
+
config.menuAdapter,
|
|
159
|
+
config.tabAdapter,
|
|
160
|
+
config.breadcrumbAdapter,
|
|
161
|
+
config.logoAdapter,
|
|
162
|
+
config.toolbarAdapter,
|
|
163
|
+
config.userAvatarAdapter
|
|
164
|
+
]
|
|
108
165
|
);
|
|
109
|
-
const [menuData, setMenuData] = useState([]);
|
|
110
|
-
const [activePath, setActivePathState] = useState("");
|
|
111
166
|
const [collapsed, setCollapsedState] = useState(false);
|
|
112
|
-
const [expandedWidth, setExpandedWidth] = useState("200px");
|
|
113
|
-
const [collapsedWidth, setCollapsedWidth] = useState("64px");
|
|
114
|
-
const [layoutMode, setLayoutMode] = useState(
|
|
115
|
-
"side-menu"
|
|
116
|
-
);
|
|
117
|
-
const setMenus = useCallback((data) => setMenuData(data), []);
|
|
118
167
|
const [openKeys, setOpenKeys] = useState(/* @__PURE__ */ new Set());
|
|
119
168
|
const savedOpenKeysRef = useRef(/* @__PURE__ */ new Set());
|
|
120
169
|
const openKeysRef = useRef(openKeys);
|
|
121
170
|
openKeysRef.current = openKeys;
|
|
122
171
|
const collapsedRef = useRef(collapsed);
|
|
123
172
|
collapsedRef.current = collapsed;
|
|
124
|
-
const menuDataRef = useRef(
|
|
125
|
-
menuDataRef.current =
|
|
126
|
-
const layoutModeRef = useRef(layoutMode);
|
|
127
|
-
layoutModeRef.current = layoutMode;
|
|
173
|
+
const menuDataRef = useRef(config.menus);
|
|
174
|
+
menuDataRef.current = config.menus;
|
|
175
|
+
const layoutModeRef = useRef(config.layoutMode);
|
|
176
|
+
layoutModeRef.current = config.layoutMode;
|
|
177
|
+
const pathParamsMap = useRef(/* @__PURE__ */ new Map());
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
if (activeFullPath && activeFullPath !== activePath) {
|
|
180
|
+
pathParamsMap.current.set(activePath, activeFullPath);
|
|
181
|
+
}
|
|
182
|
+
}, [activePath, activeFullPath]);
|
|
128
183
|
const toggleMenuOpen = useCallback((path, forceOpen) => {
|
|
129
184
|
setOpenKeys((prev) => {
|
|
130
185
|
const next = new Set(prev);
|
|
@@ -171,38 +226,17 @@ function LayoutProvider({ children }) {
|
|
|
171
226
|
}
|
|
172
227
|
setCollapsedState(nextCollapsed);
|
|
173
228
|
}, []);
|
|
174
|
-
const pathParamsMap = useRef(/* @__PURE__ */ new Map());
|
|
175
|
-
const storePathParams = useCallback((path, fullPath) => {
|
|
176
|
-
if (fullPath && fullPath !== path) {
|
|
177
|
-
pathParamsMap.current.set(path, fullPath);
|
|
178
|
-
}
|
|
179
|
-
}, []);
|
|
180
229
|
const getFullPath = useCallback(
|
|
181
230
|
(path) => pathParamsMap.current.get(path) || path,
|
|
182
231
|
[]
|
|
183
232
|
);
|
|
184
|
-
const setActivePath = useCallback(
|
|
185
|
-
(path, fullPath) => {
|
|
186
|
-
setActivePathState(path);
|
|
187
|
-
if (fullPath) storePathParams(path, fullPath);
|
|
188
|
-
},
|
|
189
|
-
[storePathParams]
|
|
190
|
-
);
|
|
191
233
|
const isConcretePage = useCallback(
|
|
192
234
|
(path) => {
|
|
193
|
-
const item = findMenuItemByPath(
|
|
235
|
+
const item = findMenuItemByPath(config.menus, path);
|
|
194
236
|
return !item?.children || item.children.length === 0;
|
|
195
237
|
},
|
|
196
|
-
[
|
|
238
|
+
[config.menus]
|
|
197
239
|
);
|
|
198
|
-
const [homePath, setHomePathState] = useState("");
|
|
199
|
-
const [maxTabs, setMaxTabsState] = useState(10);
|
|
200
|
-
const setHomePath = useCallback((path) => {
|
|
201
|
-
setHomePathState(path);
|
|
202
|
-
}, []);
|
|
203
|
-
const setMaxTabs = useCallback((max) => {
|
|
204
|
-
setMaxTabsState(max);
|
|
205
|
-
}, []);
|
|
206
240
|
const setCollapsed = useCallback((val) => {
|
|
207
241
|
if (val) {
|
|
208
242
|
savedOpenKeysRef.current = new Set(openKeysRef.current);
|
|
@@ -213,12 +247,7 @@ function LayoutProvider({ children }) {
|
|
|
213
247
|
setCollapsedState(val);
|
|
214
248
|
}, []);
|
|
215
249
|
const interactionValue = useMemo(
|
|
216
|
-
() => ({
|
|
217
|
-
collapsed,
|
|
218
|
-
toggleCollapse,
|
|
219
|
-
setCollapsed,
|
|
220
|
-
menuItemClick
|
|
221
|
-
}),
|
|
250
|
+
() => ({ collapsed, toggleCollapse, setCollapsed, menuItemClick }),
|
|
222
251
|
[collapsed, toggleCollapse, setCollapsed, menuItemClick]
|
|
223
252
|
);
|
|
224
253
|
const openKeysValue = useMemo(
|
|
@@ -228,54 +257,29 @@ function LayoutProvider({ children }) {
|
|
|
228
257
|
const value = useMemo(
|
|
229
258
|
() => ({
|
|
230
259
|
adapters,
|
|
231
|
-
|
|
232
|
-
setTabAdapter,
|
|
233
|
-
setBreadcrumbAdapter,
|
|
234
|
-
setLogoAdapter,
|
|
235
|
-
setToolbarAdapter,
|
|
236
|
-
setUserAvatarAdapter,
|
|
237
|
-
menuData,
|
|
260
|
+
menuData: config.menus,
|
|
238
261
|
activePath,
|
|
239
|
-
expandedWidth,
|
|
240
|
-
collapsedWidth,
|
|
241
|
-
layoutMode,
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
setExpandedWidth,
|
|
245
|
-
setCollapsedWidth,
|
|
246
|
-
setLayoutMode,
|
|
262
|
+
expandedWidth: config.expandedWidth,
|
|
263
|
+
collapsedWidth: config.collapsedWidth,
|
|
264
|
+
layoutMode: config.layoutMode,
|
|
265
|
+
homePath: config.homePath,
|
|
266
|
+
maxTabs: config.maxTabs,
|
|
247
267
|
isConcretePage,
|
|
248
268
|
getFullPath,
|
|
249
|
-
|
|
250
|
-
navigate,
|
|
251
|
-
homePath,
|
|
252
|
-
setHomePath,
|
|
253
|
-
maxTabs,
|
|
254
|
-
setMaxTabs
|
|
269
|
+
navigate
|
|
255
270
|
}),
|
|
256
271
|
[
|
|
257
272
|
adapters,
|
|
258
|
-
|
|
259
|
-
setTabAdapter,
|
|
260
|
-
setBreadcrumbAdapter,
|
|
261
|
-
setLogoAdapter,
|
|
262
|
-
setToolbarAdapter,
|
|
263
|
-
setUserAvatarAdapter,
|
|
264
|
-
menuData,
|
|
273
|
+
config.menus,
|
|
265
274
|
activePath,
|
|
266
|
-
expandedWidth,
|
|
267
|
-
collapsedWidth,
|
|
268
|
-
layoutMode,
|
|
269
|
-
|
|
270
|
-
|
|
275
|
+
config.expandedWidth,
|
|
276
|
+
config.collapsedWidth,
|
|
277
|
+
config.layoutMode,
|
|
278
|
+
config.homePath,
|
|
279
|
+
config.maxTabs,
|
|
271
280
|
isConcretePage,
|
|
272
281
|
getFullPath,
|
|
273
|
-
|
|
274
|
-
navigate,
|
|
275
|
-
homePath,
|
|
276
|
-
setHomePath,
|
|
277
|
-
maxTabs,
|
|
278
|
-
setMaxTabs
|
|
282
|
+
navigate
|
|
279
283
|
]
|
|
280
284
|
);
|
|
281
285
|
return /* @__PURE__ */ jsx(LayoutContext.Provider, { value, children: /* @__PURE__ */ jsx(LayoutInteractionContext.Provider, { value: interactionValue, children: /* @__PURE__ */ jsx(LayoutOpenKeysContext.Provider, { value: openKeysValue, children }) }) });
|
|
@@ -357,7 +361,6 @@ function LayoutContent({ children }) {
|
|
|
357
361
|
const isTopMenu = layoutMode === "top-menu";
|
|
358
362
|
const [tabData, setTabData] = useState([]);
|
|
359
363
|
const [activeTab, setActiveTab] = useState("");
|
|
360
|
-
const [refreshKey, setRefreshKey] = useState(0);
|
|
361
364
|
const menuDataRef = useRef(menuData);
|
|
362
365
|
menuDataRef.current = menuData;
|
|
363
366
|
const activeTabRef = useRef(activeTab);
|
|
@@ -441,9 +444,6 @@ function LayoutContent({ children }) {
|
|
|
441
444
|
(prev) => prev.map((t) => t.path === path ? { ...t, fixed } : t)
|
|
442
445
|
);
|
|
443
446
|
}, []);
|
|
444
|
-
const handleRefresh = useCallback(() => {
|
|
445
|
-
setRefreshKey((k) => k + 1);
|
|
446
|
-
}, []);
|
|
447
447
|
const TabAdapter = adapters.tab;
|
|
448
448
|
return /* @__PURE__ */ jsxs("main", { className: "tker-layout-content", children: [
|
|
449
449
|
!isTopMenu && TabAdapter && /* @__PURE__ */ jsx(
|
|
@@ -455,11 +455,10 @@ function LayoutContent({ children }) {
|
|
|
455
455
|
onClose: handleTabClose,
|
|
456
456
|
onCloseOther: handleCloseOtherTabs,
|
|
457
457
|
onCloseAll: handleCloseAllTabs,
|
|
458
|
-
onRefresh: handleRefresh,
|
|
459
458
|
onSetFixed: handleSetFixed
|
|
460
459
|
}
|
|
461
460
|
),
|
|
462
|
-
/* @__PURE__ */ jsx("div", { className: "tker-layout-content__body", children }
|
|
461
|
+
/* @__PURE__ */ jsx("div", { className: "tker-layout-content__body", children })
|
|
463
462
|
] });
|
|
464
463
|
}
|
|
465
464
|
function openTabInData(tabData, path, config) {
|
|
@@ -541,6 +540,7 @@ function LayoutHeader() {
|
|
|
541
540
|
},
|
|
542
541
|
[getFullPath, navigate, isConcretePage]
|
|
543
542
|
);
|
|
543
|
+
const emptyOpenKeysRef = useRef(/* @__PURE__ */ new Set());
|
|
544
544
|
const leftContent = isTopMenu ? ["logo", "menu"] : ["logo", "breadcrumb"];
|
|
545
545
|
const logoWidth = isSideMenu ? collapsed ? collapsedWidth : expandedWidth : expandedWidth;
|
|
546
546
|
const LogoAdapter = adapters.logo;
|
|
@@ -566,7 +566,7 @@ function LayoutHeader() {
|
|
|
566
566
|
collapsed: false,
|
|
567
567
|
mode: "top",
|
|
568
568
|
width: logoWidth,
|
|
569
|
-
openKeys:
|
|
569
|
+
openKeys: emptyOpenKeysRef.current,
|
|
570
570
|
onSelect: handleMenuSelect,
|
|
571
571
|
onMenuItemClick: menuItemClick
|
|
572
572
|
}
|
|
@@ -597,8 +597,8 @@ function LayoutInner({ children }) {
|
|
|
597
597
|
] })
|
|
598
598
|
] });
|
|
599
599
|
}
|
|
600
|
-
function Layout({ children }) {
|
|
601
|
-
return /* @__PURE__ */ jsx(LayoutProvider, { children: /* @__PURE__ */ jsx(LayoutInner, { children }) });
|
|
600
|
+
function Layout({ children, ...props }) {
|
|
601
|
+
return /* @__PURE__ */ jsx(LayoutProvider, { ...props, children: /* @__PURE__ */ jsx(LayoutInner, { children }) });
|
|
602
602
|
}
|
|
603
603
|
|
|
604
|
-
export { Layout, LayoutProvider,
|
|
604
|
+
export { Layout, LayoutProvider, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
|