@tker-react/layout 0.2.13 → 0.2.15
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 +99 -76
- package/dist/index.d.mts +8 -6
- package/dist/index.d.ts +8 -6
- package/dist/index.mjs +18 -31
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
React 后台管理布局框架,提供菜单、面包屑、标签页、侧边栏等布局能力。
|
|
4
4
|
|
|
5
5
|
- **无内置 adapter**:不依赖特定 UI 库,所有 UI 渲染由使用者通过 adapter 组件控制
|
|
6
|
-
- **React Context 共享状态**:`<Layout>` 内置 Provider
|
|
7
|
-
- **路由解耦**:不直接依赖路由库,通过 `setNavigateAdapter` 和 `
|
|
6
|
+
- **React Context 共享状态**:`<Layout>` 内置 Provider
|
|
7
|
+
- **路由解耦**:不直接依赖路由库,通过 `setNavigateAdapter` 和 `<Layout>` 的 `activePath`/`activeFullPath` props 与路由层对接
|
|
8
|
+
- **细粒度重渲染**:`activePath` 通过独立 context 传播,路由变化时仅菜单、面包屑、标签页重渲染,`<Outlet />` 不受影响
|
|
8
9
|
|
|
9
10
|
## 安装
|
|
10
11
|
|
|
@@ -26,59 +27,66 @@ import "@tker-react/layout/layout.css";
|
|
|
26
27
|
|
|
27
28
|
```tsx
|
|
28
29
|
// layouts/AppLayout.tsx
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
import {
|
|
31
|
+
Layout,
|
|
32
|
+
setMenus,
|
|
33
|
+
setMenuAdapter,
|
|
34
|
+
setTabAdapter,
|
|
35
|
+
setBreadcrumbAdapter,
|
|
36
|
+
setLogoAdapter,
|
|
37
|
+
setToolbarAdapter,
|
|
38
|
+
setUserAvatarAdapter,
|
|
39
|
+
setHomePath,
|
|
40
|
+
setNavigateAdapter,
|
|
41
|
+
} from "@tker-react/layout";
|
|
42
|
+
import { Outlet, useRouterState } from "@tanstack/react-router";
|
|
43
|
+
import { useMemo } from "react";
|
|
44
|
+
|
|
45
|
+
// adapter 组件和菜单数据
|
|
46
|
+
import MenuAdapter from "../adapters/MenuAdapter";
|
|
47
|
+
import TabAdapter from "../adapters/TabAdapter";
|
|
48
|
+
import BreadcrumbAdapter from "../adapters/BreadcrumbAdapter";
|
|
49
|
+
import LogoAdapter from "../adapters/LogoAdapter";
|
|
50
|
+
import ToolbarAdapter from "../adapters/ToolbarAdapter";
|
|
51
|
+
import UserAvatarAdapter from "../adapters/UserAvatarAdapter";
|
|
52
|
+
import { router } from "../router";
|
|
53
|
+
|
|
54
|
+
// -- 静态配置:模块顶层调用即可 --
|
|
55
|
+
setMenuAdapter(MenuAdapter);
|
|
56
|
+
setTabAdapter(TabAdapter);
|
|
57
|
+
setBreadcrumbAdapter(BreadcrumbAdapter);
|
|
58
|
+
setLogoAdapter(LogoAdapter);
|
|
59
|
+
setToolbarAdapter(ToolbarAdapter);
|
|
60
|
+
setUserAvatarAdapter(UserAvatarAdapter);
|
|
61
|
+
setHomePath("/dashboard");
|
|
62
|
+
setNavigateAdapter((path) => router.navigate({ to: path }));
|
|
63
|
+
setMenus([
|
|
64
|
+
{ path: "/dashboard", title: "仪表盘" },
|
|
65
|
+
{
|
|
66
|
+
path: "/users",
|
|
67
|
+
title: "用户管理",
|
|
68
|
+
children: [
|
|
69
|
+
{ path: "/users/list", title: "用户列表" },
|
|
70
|
+
{ path: "/users/detail", title: "用户详情" },
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
]);
|
|
32
74
|
|
|
33
75
|
export function AppLayout() {
|
|
34
|
-
return (
|
|
35
|
-
<Layout>
|
|
36
|
-
<SetupLayout />
|
|
37
|
-
<Outlet />
|
|
38
|
-
</Layout>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function SetupLayout() {
|
|
43
|
-
const layout = useLayout();
|
|
44
|
-
const router = useRouter();
|
|
45
76
|
const pathname = useRouterState({ select: (s) => s.location.pathname });
|
|
46
77
|
const search = useRouterState({ select: (s) => s.location.searchStr });
|
|
47
78
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
layout.setUserAvatarAdapter(UserAvatarAdapter);
|
|
56
|
-
layout.setMenus([
|
|
57
|
-
{ path: "/dashboard", title: "仪表盘" },
|
|
58
|
-
{
|
|
59
|
-
path: "/users",
|
|
60
|
-
title: "用户管理",
|
|
61
|
-
children: [
|
|
62
|
-
{ path: "/users", title: "用户列表" },
|
|
63
|
-
{ path: "/users/detail", title: "用户详情" },
|
|
64
|
-
],
|
|
65
|
-
},
|
|
66
|
-
]);
|
|
67
|
-
layout.setHomePath("/dashboard");
|
|
68
|
-
}, []);
|
|
69
|
-
|
|
70
|
-
// setNavigateAdapter 存储 ref,可以直接在 render 中调用
|
|
71
|
-
layout.setNavigateAdapter((path) => router.navigate({ to: path }));
|
|
72
|
-
|
|
73
|
-
useLayoutEffect(() => {
|
|
74
|
-
layout.setActivePath(pathname, pathname + search);
|
|
75
|
-
}, [pathname, search]);
|
|
76
|
-
|
|
77
|
-
return null;
|
|
79
|
+
const outlet = useMemo(() => <Outlet />, []);
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<Layout activeFullPath={pathname + search} activePath={pathname}>
|
|
83
|
+
{outlet}
|
|
84
|
+
</Layout>
|
|
85
|
+
);
|
|
78
86
|
}
|
|
79
87
|
```
|
|
80
88
|
|
|
81
|
-
>
|
|
89
|
+
> **注意**:adapter、菜单等静态配置在模块顶层调用一次即可(只写 module 变量)。`activePath`/`activeFullPath` 通过 props 传入 `<Layout>`。`<Outlet />` 用 `useMemo` 稳定引用,配合 `LayoutInner` 的 `React.memo` 避免路由变化时 `Outlet` 被 Layout 层牵连重渲染。
|
|
82
90
|
|
|
83
91
|
### 2. 定义路由并挂载
|
|
84
92
|
|
|
@@ -429,62 +437,65 @@ function UserAvatarAdapter({ onSettings, onLogout }: UserAvatarAdapterProps) {
|
|
|
429
437
|
|
|
430
438
|
## 使用不同路由库
|
|
431
439
|
|
|
432
|
-
|
|
440
|
+
静态配置(adapter、菜单)在模块顶层调用不变。以下展示各路由器 `activePath` 的对接方式。
|
|
433
441
|
|
|
434
442
|
### TanStack Router
|
|
435
443
|
|
|
436
444
|
```tsx
|
|
437
|
-
//
|
|
438
|
-
|
|
445
|
+
// AppLayout 中的路由同步部分
|
|
446
|
+
setNavigateAdapter((path) => router.navigate({ to: path }));
|
|
447
|
+
|
|
439
448
|
const pathname = useRouterState({ select: (s) => s.location.pathname });
|
|
440
449
|
const search = useRouterState({ select: (s) => s.location.searchStr });
|
|
441
450
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
451
|
+
return (
|
|
452
|
+
<Layout activeFullPath={pathname + search} activePath={pathname}>
|
|
453
|
+
{outlet}
|
|
454
|
+
</Layout>
|
|
455
|
+
);
|
|
447
456
|
```
|
|
448
457
|
|
|
449
458
|
### React Router v6+
|
|
450
459
|
|
|
451
460
|
```tsx
|
|
452
|
-
//
|
|
453
|
-
|
|
454
|
-
const navigate = useNavigate();
|
|
461
|
+
// AppLayout 中的路由同步部分
|
|
462
|
+
setNavigateAdapter((path) => navigate(path));
|
|
455
463
|
|
|
456
|
-
|
|
464
|
+
const location = useLocation();
|
|
457
465
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}
|
|
466
|
+
return (
|
|
467
|
+
<Layout activeFullPath={location.pathname + location.search} activePath={location.pathname}>
|
|
468
|
+
{outlet}
|
|
469
|
+
</Layout>
|
|
470
|
+
);
|
|
461
471
|
```
|
|
462
472
|
|
|
463
473
|
### Next.js App Router
|
|
464
474
|
|
|
465
475
|
```tsx
|
|
466
|
-
//
|
|
476
|
+
// AppLayout 中的路由同步部分
|
|
477
|
+
setNavigateAdapter((path) => router.push(path));
|
|
478
|
+
|
|
467
479
|
const pathname = usePathname();
|
|
468
480
|
const searchParams = useSearchParams();
|
|
469
|
-
const router = useRouter();
|
|
470
|
-
|
|
471
|
-
layout.setNavigateAdapter((path) => router.push(path));
|
|
472
|
-
|
|
473
481
|
const fullPath = pathname + (searchParams.toString() ? `?${searchParams}` : "");
|
|
474
482
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
}
|
|
483
|
+
return (
|
|
484
|
+
<Layout activeFullPath={fullPath} activePath={pathname}>
|
|
485
|
+
{outlet}
|
|
486
|
+
</Layout>
|
|
487
|
+
);
|
|
478
488
|
```
|
|
479
489
|
|
|
480
490
|
## API
|
|
481
491
|
|
|
482
|
-
###
|
|
492
|
+
### 模块级 setter
|
|
493
|
+
|
|
494
|
+
所有配置通过模块级 setter 设置,在 import 阶段调用即可(不需要 hook),内部存储为 module 变量。
|
|
483
495
|
|
|
484
|
-
|
|
|
496
|
+
| 函数 | 说明 |
|
|
485
497
|
|------|------|
|
|
486
498
|
| `setMenus(data)` | 设置菜单数据 |
|
|
487
|
-
| `setActivePath(path, fullPath?)` | 设置当前激活路径,自动触发面包屑更新和标签页打开 |
|
|
488
499
|
| `setMenuAdapter(component)` | 注册菜单适配器组件 |
|
|
489
500
|
| `setTabAdapter(component)` | 注册标签页适配器组件 |
|
|
490
501
|
| `setBreadcrumbAdapter(component)` | 注册面包屑适配器组件 |
|
|
@@ -492,11 +503,23 @@ useLayoutEffect(() => {
|
|
|
492
503
|
| `setToolbarAdapter(component)` | 注册工具栏适配器组件 |
|
|
493
504
|
| `setUserAvatarAdapter(component)` | 注册用户头像适配器组件 |
|
|
494
505
|
| `setNavigateAdapter(fn)` | 设置导航回调,Layout 内部点击菜单/tab/面包屑时调用 |
|
|
495
|
-
| `
|
|
496
|
-
| `setLayoutMode(mode)` | 设置布局模式:`"side-menu"` 或 `"top-menu"` |
|
|
506
|
+
| `setLayoutMode(mode)` | 设置布局模式:`"side-menu"` 或 `"top-menu"`,默认 `"side-menu"` |
|
|
497
507
|
| `setHomePath(path)` | 设置首页路径,首页 tab 固定在最左侧 |
|
|
498
508
|
| `setMaxTabs(n)` | 设置最大标签页数量,超出后关闭最早的 |
|
|
499
|
-
| `
|
|
509
|
+
| `setExpandedWidth(width)` | 侧边栏展开宽度,默认 `"200px"` |
|
|
510
|
+
| `setCollapsedWidth(width)` | 侧边栏折叠宽度,默认 `"64px"` |
|
|
511
|
+
|
|
512
|
+
### 组件
|
|
513
|
+
|
|
514
|
+
| 组件 | Props | 说明 |
|
|
515
|
+
|------|-------|------|
|
|
516
|
+
| `<Layout>` | `children`, `activePath?`, `activeFullPath?` | 布局容器,内置所有 Provider。`activePath` 为当前路由路径,`activeFullPath` 为含 query string 的完整路径 |
|
|
517
|
+
|
|
518
|
+
### Hook
|
|
519
|
+
|
|
520
|
+
| Hook | 说明 |
|
|
521
|
+
|------|------|
|
|
522
|
+
| `useActivePathContext()` | 获取当前 activePath,通常仅在自定义 adapter 时使用 |
|
|
500
523
|
|
|
501
524
|
### Adapter 组件 Props
|
|
502
525
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import * as react from 'react';
|
|
2
|
-
import { ReactNode, ComponentType } from 'react';
|
|
3
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode, ComponentType } from 'react';
|
|
4
3
|
|
|
5
4
|
interface LayoutProps {
|
|
6
5
|
children?: ReactNode;
|
|
6
|
+
activePath?: string;
|
|
7
|
+
activeFullPath?: string;
|
|
7
8
|
}
|
|
8
|
-
declare
|
|
9
|
+
declare function Layout({ children, ...props }: LayoutProps): react_jsx_runtime.JSX.Element;
|
|
9
10
|
|
|
10
11
|
interface BreadcrumbItem {
|
|
11
12
|
path: string;
|
|
@@ -73,8 +74,10 @@ interface LayoutAdapters {
|
|
|
73
74
|
|
|
74
75
|
interface LayoutProviderProps {
|
|
75
76
|
children?: ReactNode;
|
|
77
|
+
activePath?: string;
|
|
78
|
+
activeFullPath?: string;
|
|
76
79
|
}
|
|
77
|
-
declare function LayoutProvider({ children }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
|
|
80
|
+
declare function LayoutProvider({ children, activePath, activeFullPath, }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
|
|
78
81
|
|
|
79
82
|
declare function setMenus(data: MenuItem[]): void;
|
|
80
83
|
declare function setMenuAdapter(c: ComponentType<MenuAdapterProps>): void;
|
|
@@ -89,7 +92,6 @@ declare function setLayoutMode(mode: "side-menu" | "top-menu"): void;
|
|
|
89
92
|
declare function setExpandedWidth(width: string): void;
|
|
90
93
|
declare function setCollapsedWidth(width: string): void;
|
|
91
94
|
declare function setNavigateAdapter(fn: (path: string) => void): void;
|
|
92
|
-
declare function setActivePath(path: string, fullPath?: string): void;
|
|
93
95
|
|
|
94
|
-
export { Layout, LayoutProvider,
|
|
96
|
+
export { Layout, LayoutProvider, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
|
|
95
97
|
export type { BreadcrumbAdapterProps, BreadcrumbItem, LayoutAdapters, LogoAdapterProps, MenuAdapterProps, MenuItem, TabAdapterProps, TabItem, UserAvatarAdapterProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import * as react from 'react';
|
|
2
|
-
import { ReactNode, ComponentType } from 'react';
|
|
3
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode, ComponentType } from 'react';
|
|
4
3
|
|
|
5
4
|
interface LayoutProps {
|
|
6
5
|
children?: ReactNode;
|
|
6
|
+
activePath?: string;
|
|
7
|
+
activeFullPath?: string;
|
|
7
8
|
}
|
|
8
|
-
declare
|
|
9
|
+
declare function Layout({ children, ...props }: LayoutProps): react_jsx_runtime.JSX.Element;
|
|
9
10
|
|
|
10
11
|
interface BreadcrumbItem {
|
|
11
12
|
path: string;
|
|
@@ -73,8 +74,10 @@ interface LayoutAdapters {
|
|
|
73
74
|
|
|
74
75
|
interface LayoutProviderProps {
|
|
75
76
|
children?: ReactNode;
|
|
77
|
+
activePath?: string;
|
|
78
|
+
activeFullPath?: string;
|
|
76
79
|
}
|
|
77
|
-
declare function LayoutProvider({ children }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
|
|
80
|
+
declare function LayoutProvider({ children, activePath, activeFullPath, }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
|
|
78
81
|
|
|
79
82
|
declare function setMenus(data: MenuItem[]): void;
|
|
80
83
|
declare function setMenuAdapter(c: ComponentType<MenuAdapterProps>): void;
|
|
@@ -89,7 +92,6 @@ declare function setLayoutMode(mode: "side-menu" | "top-menu"): void;
|
|
|
89
92
|
declare function setExpandedWidth(width: string): void;
|
|
90
93
|
declare function setCollapsedWidth(width: string): void;
|
|
91
94
|
declare function setNavigateAdapter(fn: (path: string) => void): void;
|
|
92
|
-
declare function setActivePath(path: string, fullPath?: string): void;
|
|
93
95
|
|
|
94
|
-
export { Layout, LayoutProvider,
|
|
96
|
+
export { Layout, LayoutProvider, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
|
|
95
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 { useRef, useCallback, useMemo, useState,
|
|
3
|
+
import { useRef, useCallback, useMemo, useState, useEffect, createContext, useContext, memo } from 'react';
|
|
4
4
|
|
|
5
5
|
function findMenuItemByPath(menuData, path) {
|
|
6
6
|
for (const item of menuData) {
|
|
@@ -112,28 +112,6 @@ function consumeLayoutConfig() {
|
|
|
112
112
|
navigateAdapter: _navigateAdapter
|
|
113
113
|
};
|
|
114
114
|
}
|
|
115
|
-
let _activePath = "";
|
|
116
|
-
const _pathParamsMap = /* @__PURE__ */ new Map();
|
|
117
|
-
let _activePathListeners = [];
|
|
118
|
-
function setActivePath(path, fullPath) {
|
|
119
|
-
_activePath = path;
|
|
120
|
-
if (fullPath && fullPath !== path) {
|
|
121
|
-
_pathParamsMap.set(path, fullPath);
|
|
122
|
-
}
|
|
123
|
-
_activePathListeners.forEach((l) => l());
|
|
124
|
-
}
|
|
125
|
-
function subscribeActivePath(listener) {
|
|
126
|
-
_activePathListeners.push(listener);
|
|
127
|
-
return () => {
|
|
128
|
-
_activePathListeners = _activePathListeners.filter((l) => l !== listener);
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
function getActivePathSnapshot() {
|
|
132
|
-
return _activePath;
|
|
133
|
-
}
|
|
134
|
-
function getFullPathByActivePath(path) {
|
|
135
|
-
return _pathParamsMap.get(path) || path;
|
|
136
|
-
}
|
|
137
115
|
|
|
138
116
|
const LayoutContext = createContext(null);
|
|
139
117
|
const LayoutInteractionContext = createContext(null);
|
|
@@ -157,7 +135,11 @@ const ActivePathContext = createContext("");
|
|
|
157
135
|
function useActivePathContext() {
|
|
158
136
|
return useContext(ActivePathContext);
|
|
159
137
|
}
|
|
160
|
-
function LayoutProvider({
|
|
138
|
+
function LayoutProvider({
|
|
139
|
+
children,
|
|
140
|
+
activePath = "",
|
|
141
|
+
activeFullPath
|
|
142
|
+
}) {
|
|
161
143
|
const config = consumeLayoutConfig();
|
|
162
144
|
const navigateRef = useRef(null);
|
|
163
145
|
navigateRef.current = config.navigateAdapter;
|
|
@@ -196,7 +178,12 @@ function LayoutProvider({ children }) {
|
|
|
196
178
|
menuDataRef.current = config.menus;
|
|
197
179
|
const layoutModeRef = useRef(config.layoutMode);
|
|
198
180
|
layoutModeRef.current = config.layoutMode;
|
|
199
|
-
const
|
|
181
|
+
const pathParamsMap = useRef(/* @__PURE__ */ new Map());
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
if (activeFullPath && activeFullPath !== activePath) {
|
|
184
|
+
pathParamsMap.current.set(activePath, activeFullPath);
|
|
185
|
+
}
|
|
186
|
+
}, [activePath, activeFullPath]);
|
|
200
187
|
const toggleMenuOpen = useCallback((path, forceOpen) => {
|
|
201
188
|
setOpenKeys((prev) => {
|
|
202
189
|
const next = new Set(prev);
|
|
@@ -227,7 +214,7 @@ function LayoutProvider({ children }) {
|
|
|
227
214
|
toggleMenuOpen(path);
|
|
228
215
|
}
|
|
229
216
|
} else {
|
|
230
|
-
const fullPath =
|
|
217
|
+
const fullPath = pathParamsMap.current.get(path) || path;
|
|
231
218
|
if (window.location.pathname + window.location.search !== fullPath) {
|
|
232
219
|
navigateRef.current?.(fullPath);
|
|
233
220
|
}
|
|
@@ -244,7 +231,7 @@ function LayoutProvider({ children }) {
|
|
|
244
231
|
setCollapsedState(nextCollapsed);
|
|
245
232
|
}, []);
|
|
246
233
|
const getFullPath = useCallback(
|
|
247
|
-
(path) =>
|
|
234
|
+
(path) => pathParamsMap.current.get(path) || path,
|
|
248
235
|
[]
|
|
249
236
|
);
|
|
250
237
|
const isConcretePage = useCallback(
|
|
@@ -622,8 +609,8 @@ const LayoutInner = memo(function LayoutInner2({ children }) {
|
|
|
622
609
|
] })
|
|
623
610
|
] });
|
|
624
611
|
});
|
|
625
|
-
|
|
626
|
-
return /* @__PURE__ */ jsx(LayoutProvider, { children: /* @__PURE__ */ jsx(LayoutInner, { children }) });
|
|
627
|
-
}
|
|
612
|
+
function Layout({ children, ...props }) {
|
|
613
|
+
return /* @__PURE__ */ jsx(LayoutProvider, { ...props, children: /* @__PURE__ */ jsx(LayoutInner, { children }) });
|
|
614
|
+
}
|
|
628
615
|
|
|
629
|
-
export { Layout, LayoutProvider,
|
|
616
|
+
export { Layout, LayoutProvider, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
|