@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 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({ menuData, activePath, collapsed, mode, onSelect }: MenuAdapterProps) {
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={() => onSelect(item.path)}
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
- onSelect={onSelect}
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
- onSelect,
200
+ openKeys,
201
+ onMenuItemClick,
192
202
  depth = 0,
193
203
  }: {
194
204
  item: MenuItem;
195
205
  activePath: string;
196
206
  collapsed: boolean;
197
- onSelect: (path: string) => void;
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
- onSelect={onSelect}
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={() => onSelect(item.path)}
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()`, `onRefresh()`, `onSetFixed(path, fixed)` |
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 LayoutContextValue {
75
- adapters: LayoutAdapters;
76
- setMenuAdapter: (component: ComponentType<MenuAdapterProps>) => void;
77
- setTabAdapter: (component: ComponentType<TabAdapterProps>) => void;
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 useLayoutContext(): LayoutContextValue;
102
- declare function LayoutProvider({ children }: {
103
- children: ReactNode;
104
- }): react_jsx_runtime.JSX.Element;
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, useLayoutContext as useLayout };
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 LayoutContextValue {
75
- adapters: LayoutAdapters;
76
- setMenuAdapter: (component: ComponentType<MenuAdapterProps>) => void;
77
- setTabAdapter: (component: ComponentType<TabAdapterProps>) => void;
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 useLayoutContext(): LayoutContextValue;
102
- declare function LayoutProvider({ children }: {
103
- children: ReactNode;
104
- }): react_jsx_runtime.JSX.Element;
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, useLayoutContext as useLayout };
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 { createContext, useContext, useRef, useCallback, useState, useMemo, useEffect } from 'react';
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({ children }) {
134
+ function LayoutProvider({
135
+ children,
136
+ activePath = "",
137
+ activeFullPath
138
+ }) {
139
+ const config = consumeLayoutConfig();
71
140
  const navigateRef = useRef(null);
72
- const setNavigateAdapter = useCallback(
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 [adapters, setAdapters] = useState({});
85
- const setMenuAdapter = useCallback(
86
- (c) => setAdapters((prev) => prev.menu === c ? prev : { ...prev, menu: c }),
87
- []
88
- );
89
- const setTabAdapter = useCallback(
90
- (c) => setAdapters((prev) => prev.tab === c ? prev : { ...prev, tab: c }),
91
- []
92
- );
93
- const setBreadcrumbAdapter = useCallback(
94
- (c) => setAdapters((prev) => prev.breadcrumb === c ? prev : { ...prev, breadcrumb: c }),
95
- []
96
- );
97
- const setLogoAdapter = useCallback(
98
- (c) => setAdapters((prev) => prev.logo === c ? prev : { ...prev, logo: c }),
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(menuData);
125
- menuDataRef.current = menuData;
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(menuData, path);
235
+ const item = findMenuItemByPath(config.menus, path);
194
236
  return !item?.children || item.children.length === 0;
195
237
  },
196
- [menuData]
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
- setMenuAdapter,
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
- setMenus,
243
- setActivePath,
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
- setNavigateAdapter,
250
- navigate,
251
- homePath,
252
- setHomePath,
253
- maxTabs,
254
- setMaxTabs
269
+ navigate
255
270
  }),
256
271
  [
257
272
  adapters,
258
- setMenuAdapter,
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
- setMenus,
270
- setActivePath,
275
+ config.expandedWidth,
276
+ config.collapsedWidth,
277
+ config.layoutMode,
278
+ config.homePath,
279
+ config.maxTabs,
271
280
  isConcretePage,
272
281
  getFullPath,
273
- setNavigateAdapter,
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 }, refreshKey)
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: /* @__PURE__ */ new Set(),
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, useLayoutContext as useLayout };
604
+ export { Layout, LayoutProvider, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tker-react/layout",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "type": "module",