@tker-react/layout 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +5 -7
- package/dist/index.d.ts +5 -7
- package/dist/index.mjs +43 -28
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -39,6 +39,10 @@ interface MenuAdapterProps {
|
|
|
39
39
|
mode: "side" | "top";
|
|
40
40
|
width: string;
|
|
41
41
|
onSelect: (path: string) => void;
|
|
42
|
+
/** 当前展开的子菜单路径集合(side-menu 模式使用) */
|
|
43
|
+
openKeys: Set<string>;
|
|
44
|
+
/** 统一菜单点击入口,自动处理展开/折叠/导航,替代 onSelect 时 adapter 无需自行判断菜单类型 */
|
|
45
|
+
onMenuItemClick: (path: string) => void;
|
|
42
46
|
}
|
|
43
47
|
interface BreadcrumbAdapterProps {
|
|
44
48
|
breadcrumbData: BreadcrumbItem[];
|
|
@@ -77,17 +81,11 @@ interface LayoutContextValue {
|
|
|
77
81
|
setUserAvatarAdapter: (component: ComponentType<UserAvatarAdapterProps>) => void;
|
|
78
82
|
menuData: MenuItem[];
|
|
79
83
|
activePath: string;
|
|
80
|
-
collapsed: boolean;
|
|
81
84
|
expandedWidth: string;
|
|
82
85
|
collapsedWidth: string;
|
|
83
86
|
layoutMode: "side-menu" | "top-menu";
|
|
84
87
|
setMenus: (data: MenuItem[]) => void;
|
|
85
88
|
setActivePath: (path: string, fullPath?: string) => void;
|
|
86
|
-
toggleCollapse: () => void;
|
|
87
|
-
setCollapsed: (collapsed: boolean) => void;
|
|
88
|
-
openKeys: Set<string>;
|
|
89
|
-
toggleMenuOpen: (path: string, forceOpen?: boolean) => void;
|
|
90
|
-
menuItemClick: (path: string) => void;
|
|
91
89
|
setExpandedWidth: (width: string) => void;
|
|
92
90
|
setCollapsedWidth: (width: string) => void;
|
|
93
91
|
setLayoutMode: (mode: "side-menu" | "top-menu") => void;
|
|
@@ -105,5 +103,5 @@ declare function LayoutProvider({ children }: {
|
|
|
105
103
|
children: ReactNode;
|
|
106
104
|
}): react_jsx_runtime.JSX.Element;
|
|
107
105
|
|
|
108
|
-
export { Layout, LayoutProvider, useLayoutContext as useLayout
|
|
106
|
+
export { Layout, LayoutProvider, useLayoutContext as useLayout };
|
|
109
107
|
export type { BreadcrumbAdapterProps, BreadcrumbItem, LayoutAdapters, LogoAdapterProps, MenuAdapterProps, MenuItem, TabAdapterProps, TabItem, UserAvatarAdapterProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -39,6 +39,10 @@ interface MenuAdapterProps {
|
|
|
39
39
|
mode: "side" | "top";
|
|
40
40
|
width: string;
|
|
41
41
|
onSelect: (path: string) => void;
|
|
42
|
+
/** 当前展开的子菜单路径集合(side-menu 模式使用) */
|
|
43
|
+
openKeys: Set<string>;
|
|
44
|
+
/** 统一菜单点击入口,自动处理展开/折叠/导航,替代 onSelect 时 adapter 无需自行判断菜单类型 */
|
|
45
|
+
onMenuItemClick: (path: string) => void;
|
|
42
46
|
}
|
|
43
47
|
interface BreadcrumbAdapterProps {
|
|
44
48
|
breadcrumbData: BreadcrumbItem[];
|
|
@@ -77,17 +81,11 @@ interface LayoutContextValue {
|
|
|
77
81
|
setUserAvatarAdapter: (component: ComponentType<UserAvatarAdapterProps>) => void;
|
|
78
82
|
menuData: MenuItem[];
|
|
79
83
|
activePath: string;
|
|
80
|
-
collapsed: boolean;
|
|
81
84
|
expandedWidth: string;
|
|
82
85
|
collapsedWidth: string;
|
|
83
86
|
layoutMode: "side-menu" | "top-menu";
|
|
84
87
|
setMenus: (data: MenuItem[]) => void;
|
|
85
88
|
setActivePath: (path: string, fullPath?: string) => void;
|
|
86
|
-
toggleCollapse: () => void;
|
|
87
|
-
setCollapsed: (collapsed: boolean) => void;
|
|
88
|
-
openKeys: Set<string>;
|
|
89
|
-
toggleMenuOpen: (path: string, forceOpen?: boolean) => void;
|
|
90
|
-
menuItemClick: (path: string) => void;
|
|
91
89
|
setExpandedWidth: (width: string) => void;
|
|
92
90
|
setCollapsedWidth: (width: string) => void;
|
|
93
91
|
setLayoutMode: (mode: "side-menu" | "top-menu") => void;
|
|
@@ -105,5 +103,5 @@ declare function LayoutProvider({ children }: {
|
|
|
105
103
|
children: ReactNode;
|
|
106
104
|
}): react_jsx_runtime.JSX.Element;
|
|
107
105
|
|
|
108
|
-
export { Layout, LayoutProvider, useLayoutContext as useLayout
|
|
106
|
+
export { Layout, LayoutProvider, useLayoutContext as useLayout };
|
|
109
107
|
export type { BreadcrumbAdapterProps, BreadcrumbItem, LayoutAdapters, LogoAdapterProps, MenuAdapterProps, MenuItem, TabAdapterProps, TabItem, UserAvatarAdapterProps };
|
package/dist/index.mjs
CHANGED
|
@@ -44,6 +44,14 @@ function generateBreadcrumb(menuData, activePath) {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
const LayoutContext = createContext(null);
|
|
47
|
+
const LayoutInteractionContext = createContext(null);
|
|
48
|
+
function useLayoutInteractionContext() {
|
|
49
|
+
const ctx = useContext(LayoutInteractionContext);
|
|
50
|
+
if (!ctx) {
|
|
51
|
+
throw new Error("useLayoutInteractionContext \u5FC5\u987B\u5728 <Layout> \u5185\u90E8\u4F7F\u7528");
|
|
52
|
+
}
|
|
53
|
+
return ctx;
|
|
54
|
+
}
|
|
47
55
|
function useLayoutContext() {
|
|
48
56
|
const ctx = useContext(LayoutContext);
|
|
49
57
|
if (!ctx) {
|
|
@@ -107,6 +115,8 @@ function LayoutProvider({ children }) {
|
|
|
107
115
|
collapsedRef.current = collapsed;
|
|
108
116
|
const menuDataRef = useRef(menuData);
|
|
109
117
|
menuDataRef.current = menuData;
|
|
118
|
+
const layoutModeRef = useRef(layoutMode);
|
|
119
|
+
layoutModeRef.current = layoutMode;
|
|
110
120
|
const toggleMenuOpen = useCallback((path, forceOpen) => {
|
|
111
121
|
setOpenKeys((prev) => {
|
|
112
122
|
const next = new Set(prev);
|
|
@@ -125,7 +135,9 @@ function LayoutProvider({ children }) {
|
|
|
125
135
|
const menuItemClick = useCallback((path) => {
|
|
126
136
|
const item = findMenuItemByPath(menuDataRef.current, path);
|
|
127
137
|
const hasChildren = !!(item?.children && item.children.length > 0);
|
|
138
|
+
const isSide = layoutModeRef.current === "side-menu";
|
|
128
139
|
if (hasChildren) {
|
|
140
|
+
if (!isSide) return;
|
|
129
141
|
if (collapsedRef.current) {
|
|
130
142
|
setCollapsedState(false);
|
|
131
143
|
const restored = new Set(savedOpenKeysRef.current);
|
|
@@ -183,6 +195,26 @@ function LayoutProvider({ children }) {
|
|
|
183
195
|
const setMaxTabs = useCallback((max) => {
|
|
184
196
|
setMaxTabsState(max);
|
|
185
197
|
}, []);
|
|
198
|
+
const setCollapsed = useCallback((val) => {
|
|
199
|
+
if (val) {
|
|
200
|
+
savedOpenKeysRef.current = new Set(openKeysRef.current);
|
|
201
|
+
setOpenKeys(/* @__PURE__ */ new Set());
|
|
202
|
+
} else {
|
|
203
|
+
setOpenKeys(new Set(savedOpenKeysRef.current));
|
|
204
|
+
}
|
|
205
|
+
setCollapsedState(val);
|
|
206
|
+
}, []);
|
|
207
|
+
const interactionValue = useMemo(
|
|
208
|
+
() => ({
|
|
209
|
+
collapsed,
|
|
210
|
+
toggleCollapse,
|
|
211
|
+
setCollapsed,
|
|
212
|
+
openKeys,
|
|
213
|
+
toggleMenuOpen,
|
|
214
|
+
menuItemClick
|
|
215
|
+
}),
|
|
216
|
+
[collapsed, toggleCollapse, setCollapsed, openKeys, toggleMenuOpen, menuItemClick]
|
|
217
|
+
);
|
|
186
218
|
const value = useMemo(
|
|
187
219
|
() => ({
|
|
188
220
|
adapters,
|
|
@@ -194,26 +226,11 @@ function LayoutProvider({ children }) {
|
|
|
194
226
|
setUserAvatarAdapter,
|
|
195
227
|
menuData,
|
|
196
228
|
activePath,
|
|
197
|
-
collapsed,
|
|
198
229
|
expandedWidth,
|
|
199
230
|
collapsedWidth,
|
|
200
231
|
layoutMode,
|
|
201
232
|
setMenus,
|
|
202
233
|
setActivePath,
|
|
203
|
-
toggleCollapse,
|
|
204
|
-
// setCollapsed 同样处理 openKeys 保存/恢复,与 toggleCollapse 逻辑一致
|
|
205
|
-
setCollapsed: (val) => {
|
|
206
|
-
if (val) {
|
|
207
|
-
savedOpenKeysRef.current = new Set(openKeysRef.current);
|
|
208
|
-
setOpenKeys(/* @__PURE__ */ new Set());
|
|
209
|
-
} else {
|
|
210
|
-
setOpenKeys(new Set(savedOpenKeysRef.current));
|
|
211
|
-
}
|
|
212
|
-
setCollapsedState(val);
|
|
213
|
-
},
|
|
214
|
-
openKeys,
|
|
215
|
-
toggleMenuOpen,
|
|
216
|
-
menuItemClick,
|
|
217
234
|
setExpandedWidth,
|
|
218
235
|
setCollapsedWidth,
|
|
219
236
|
setLayoutMode,
|
|
@@ -236,16 +253,11 @@ function LayoutProvider({ children }) {
|
|
|
236
253
|
setUserAvatarAdapter,
|
|
237
254
|
menuData,
|
|
238
255
|
activePath,
|
|
239
|
-
collapsed,
|
|
240
256
|
expandedWidth,
|
|
241
257
|
collapsedWidth,
|
|
242
258
|
layoutMode,
|
|
243
259
|
setMenus,
|
|
244
260
|
setActivePath,
|
|
245
|
-
toggleCollapse,
|
|
246
|
-
openKeys,
|
|
247
|
-
toggleMenuOpen,
|
|
248
|
-
menuItemClick,
|
|
249
261
|
isConcretePage,
|
|
250
262
|
getFullPath,
|
|
251
263
|
setNavigateAdapter,
|
|
@@ -256,22 +268,21 @@ function LayoutProvider({ children }) {
|
|
|
256
268
|
setMaxTabs
|
|
257
269
|
]
|
|
258
270
|
);
|
|
259
|
-
return /* @__PURE__ */ jsx(LayoutContext.Provider, { value, children });
|
|
271
|
+
return /* @__PURE__ */ jsx(LayoutContext.Provider, { value, children: /* @__PURE__ */ jsx(LayoutInteractionContext.Provider, { value: interactionValue, children }) });
|
|
260
272
|
}
|
|
261
273
|
|
|
262
274
|
function LayoutAside() {
|
|
263
275
|
const {
|
|
264
276
|
adapters,
|
|
265
|
-
collapsed,
|
|
266
277
|
expandedWidth,
|
|
267
278
|
collapsedWidth,
|
|
268
279
|
menuData,
|
|
269
280
|
activePath,
|
|
270
281
|
layoutMode,
|
|
271
282
|
getFullPath,
|
|
272
|
-
navigate
|
|
273
|
-
toggleCollapse
|
|
283
|
+
navigate
|
|
274
284
|
} = useLayoutContext();
|
|
285
|
+
const { collapsed, toggleCollapse, openKeys, menuItemClick } = useLayoutInteractionContext();
|
|
275
286
|
const menuMode = layoutMode === "top-menu" ? "top" : "side";
|
|
276
287
|
const handleMenuSelect = useCallback(
|
|
277
288
|
(path) => {
|
|
@@ -293,7 +304,9 @@ function LayoutAside() {
|
|
|
293
304
|
collapsed,
|
|
294
305
|
mode: menuMode,
|
|
295
306
|
width: asideWidth,
|
|
296
|
-
|
|
307
|
+
openKeys,
|
|
308
|
+
onSelect: handleMenuSelect,
|
|
309
|
+
onMenuItemClick: menuItemClick
|
|
297
310
|
}
|
|
298
311
|
),
|
|
299
312
|
/* @__PURE__ */ jsx(
|
|
@@ -484,7 +497,6 @@ function openTabInData(tabData, path, config) {
|
|
|
484
497
|
function LayoutHeader() {
|
|
485
498
|
const {
|
|
486
499
|
adapters,
|
|
487
|
-
collapsed,
|
|
488
500
|
expandedWidth,
|
|
489
501
|
collapsedWidth,
|
|
490
502
|
menuData,
|
|
@@ -494,6 +506,7 @@ function LayoutHeader() {
|
|
|
494
506
|
isConcretePage,
|
|
495
507
|
navigate
|
|
496
508
|
} = useLayoutContext();
|
|
509
|
+
const { collapsed, menuItemClick } = useLayoutInteractionContext();
|
|
497
510
|
const isTopMenu = layoutMode === "top-menu";
|
|
498
511
|
const isSideMenu = layoutMode === "side-menu";
|
|
499
512
|
const breadcrumbData = useMemo(
|
|
@@ -542,7 +555,9 @@ function LayoutHeader() {
|
|
|
542
555
|
collapsed: false,
|
|
543
556
|
mode: "top",
|
|
544
557
|
width: logoWidth,
|
|
545
|
-
|
|
558
|
+
openKeys: /* @__PURE__ */ new Set(),
|
|
559
|
+
onSelect: handleMenuSelect,
|
|
560
|
+
onMenuItemClick: menuItemClick
|
|
546
561
|
}
|
|
547
562
|
),
|
|
548
563
|
BreadcrumbAdapter && isSideMenu && /* @__PURE__ */ jsx(
|
|
@@ -575,4 +590,4 @@ function Layout({ children }) {
|
|
|
575
590
|
return /* @__PURE__ */ jsx(LayoutProvider, { children: /* @__PURE__ */ jsx(LayoutInner, { children }) });
|
|
576
591
|
}
|
|
577
592
|
|
|
578
|
-
export { Layout, LayoutProvider, useLayoutContext as useLayout
|
|
593
|
+
export { Layout, LayoutProvider, useLayoutContext as useLayout };
|