@tker-react/layout 0.2.11 → 0.2.13

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 CHANGED
@@ -1,12 +1,11 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { ReactNode, ComponentType } from 'react';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
4
 
4
5
  interface LayoutProps {
5
6
  children?: ReactNode;
6
- activePath?: string;
7
- activeFullPath?: string;
8
7
  }
9
- declare function Layout({ children, ...props }: LayoutProps): react_jsx_runtime.JSX.Element;
8
+ declare const Layout: react.MemoExoticComponent<({ children }: LayoutProps) => react_jsx_runtime.JSX.Element>;
10
9
 
11
10
  interface BreadcrumbItem {
12
11
  path: string;
@@ -74,10 +73,8 @@ interface LayoutAdapters {
74
73
 
75
74
  interface LayoutProviderProps {
76
75
  children?: ReactNode;
77
- activePath?: string;
78
- activeFullPath?: string;
79
76
  }
80
- declare function LayoutProvider({ children, activePath, activeFullPath, }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
77
+ declare function LayoutProvider({ children }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
81
78
 
82
79
  declare function setMenus(data: MenuItem[]): void;
83
80
  declare function setMenuAdapter(c: ComponentType<MenuAdapterProps>): void;
@@ -92,6 +89,7 @@ declare function setLayoutMode(mode: "side-menu" | "top-menu"): void;
92
89
  declare function setExpandedWidth(width: string): void;
93
90
  declare function setCollapsedWidth(width: string): void;
94
91
  declare function setNavigateAdapter(fn: (path: string) => void): void;
92
+ declare function setActivePath(path: string, fullPath?: string): void;
95
93
 
96
- export { Layout, LayoutProvider, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
94
+ export { Layout, LayoutProvider, setActivePath, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
97
95
  export type { BreadcrumbAdapterProps, BreadcrumbItem, LayoutAdapters, LogoAdapterProps, MenuAdapterProps, MenuItem, TabAdapterProps, TabItem, UserAvatarAdapterProps };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,11 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ import * as react from 'react';
2
2
  import { ReactNode, ComponentType } from 'react';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
4
 
4
5
  interface LayoutProps {
5
6
  children?: ReactNode;
6
- activePath?: string;
7
- activeFullPath?: string;
8
7
  }
9
- declare function Layout({ children, ...props }: LayoutProps): react_jsx_runtime.JSX.Element;
8
+ declare const Layout: react.MemoExoticComponent<({ children }: LayoutProps) => react_jsx_runtime.JSX.Element>;
10
9
 
11
10
  interface BreadcrumbItem {
12
11
  path: string;
@@ -74,10 +73,8 @@ interface LayoutAdapters {
74
73
 
75
74
  interface LayoutProviderProps {
76
75
  children?: ReactNode;
77
- activePath?: string;
78
- activeFullPath?: string;
79
76
  }
80
- declare function LayoutProvider({ children, activePath, activeFullPath, }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
77
+ declare function LayoutProvider({ children }: LayoutProviderProps): react_jsx_runtime.JSX.Element;
81
78
 
82
79
  declare function setMenus(data: MenuItem[]): void;
83
80
  declare function setMenuAdapter(c: ComponentType<MenuAdapterProps>): void;
@@ -92,6 +89,7 @@ declare function setLayoutMode(mode: "side-menu" | "top-menu"): void;
92
89
  declare function setExpandedWidth(width: string): void;
93
90
  declare function setCollapsedWidth(width: string): void;
94
91
  declare function setNavigateAdapter(fn: (path: string) => void): void;
92
+ declare function setActivePath(path: string, fullPath?: string): void;
95
93
 
96
- export { Layout, LayoutProvider, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
94
+ export { Layout, LayoutProvider, setActivePath, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
97
95
  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, useEffect, createContext, useContext } from 'react';
3
+ import { useRef, useCallback, useMemo, useState, useSyncExternalStore, createContext, useContext, memo, useEffect } from 'react';
4
4
 
5
5
  function findMenuItemByPath(menuData, path) {
6
6
  for (const item of menuData) {
@@ -112,6 +112,28 @@ 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
+ }
115
137
 
116
138
  const LayoutContext = createContext(null);
117
139
  const LayoutInteractionContext = createContext(null);
@@ -131,11 +153,11 @@ function useLayoutContext() {
131
153
  if (!ctx) throw new Error("useLayoutContext \u5FC5\u987B\u5728 <Layout> \u5185\u90E8\u4F7F\u7528");
132
154
  return ctx;
133
155
  }
134
- function LayoutProvider({
135
- children,
136
- activePath = "",
137
- activeFullPath
138
- }) {
156
+ const ActivePathContext = createContext("");
157
+ function useActivePathContext() {
158
+ return useContext(ActivePathContext);
159
+ }
160
+ function LayoutProvider({ children }) {
139
161
  const config = consumeLayoutConfig();
140
162
  const navigateRef = useRef(null);
141
163
  navigateRef.current = config.navigateAdapter;
@@ -174,12 +196,7 @@ function LayoutProvider({
174
196
  menuDataRef.current = config.menus;
175
197
  const layoutModeRef = useRef(config.layoutMode);
176
198
  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]);
199
+ const activePath = useSyncExternalStore(subscribeActivePath, getActivePathSnapshot);
183
200
  const toggleMenuOpen = useCallback((path, forceOpen) => {
184
201
  setOpenKeys((prev) => {
185
202
  const next = new Set(prev);
@@ -210,7 +227,7 @@ function LayoutProvider({
210
227
  toggleMenuOpen(path);
211
228
  }
212
229
  } else {
213
- const fullPath = pathParamsMap.current.get(path) || path;
230
+ const fullPath = getFullPathByActivePath(path);
214
231
  if (window.location.pathname + window.location.search !== fullPath) {
215
232
  navigateRef.current?.(fullPath);
216
233
  }
@@ -227,7 +244,7 @@ function LayoutProvider({
227
244
  setCollapsedState(nextCollapsed);
228
245
  }, []);
229
246
  const getFullPath = useCallback(
230
- (path) => pathParamsMap.current.get(path) || path,
247
+ (path) => getFullPathByActivePath(path),
231
248
  []
232
249
  );
233
250
  const isConcretePage = useCallback(
@@ -258,7 +275,6 @@ function LayoutProvider({
258
275
  () => ({
259
276
  adapters,
260
277
  menuData: config.menus,
261
- activePath,
262
278
  expandedWidth: config.expandedWidth,
263
279
  collapsedWidth: config.collapsedWidth,
264
280
  layoutMode: config.layoutMode,
@@ -271,7 +287,6 @@ function LayoutProvider({
271
287
  [
272
288
  adapters,
273
289
  config.menus,
274
- activePath,
275
290
  config.expandedWidth,
276
291
  config.collapsedWidth,
277
292
  config.layoutMode,
@@ -282,7 +297,7 @@ function LayoutProvider({
282
297
  navigate
283
298
  ]
284
299
  );
285
- return /* @__PURE__ */ jsx(LayoutContext.Provider, { value, children: /* @__PURE__ */ jsx(LayoutInteractionContext.Provider, { value: interactionValue, children: /* @__PURE__ */ jsx(LayoutOpenKeysContext.Provider, { value: openKeysValue, children }) }) });
300
+ return /* @__PURE__ */ jsx(LayoutContext.Provider, { value, children: /* @__PURE__ */ jsx(LayoutInteractionContext.Provider, { value: interactionValue, children: /* @__PURE__ */ jsx(LayoutOpenKeysContext.Provider, { value: openKeysValue, children: /* @__PURE__ */ jsx(ActivePathContext.Provider, { value: activePath, children }) }) }) });
286
301
  }
287
302
 
288
303
  function LayoutAside() {
@@ -291,11 +306,11 @@ function LayoutAside() {
291
306
  expandedWidth,
292
307
  collapsedWidth,
293
308
  menuData,
294
- activePath,
295
309
  layoutMode,
296
310
  getFullPath,
297
311
  navigate
298
312
  } = useLayoutContext();
313
+ const activePath = useActivePathContext();
299
314
  const { collapsed, toggleCollapse, menuItemClick } = useLayoutInteractionContext();
300
315
  const { openKeys } = useLayoutOpenKeysContext();
301
316
  const menuMode = layoutMode === "top-menu" ? "top" : "side";
@@ -347,18 +362,24 @@ function LayoutAside() {
347
362
  ] });
348
363
  }
349
364
 
350
- function LayoutContent({ children }) {
365
+ const LayoutContent = memo(function LayoutContent2({ children }) {
366
+ const { layoutMode } = useLayoutContext();
367
+ const isTopMenu = layoutMode === "top-menu";
368
+ return /* @__PURE__ */ jsxs("main", { className: "tker-layout-content", children: [
369
+ /* @__PURE__ */ jsx(LayoutTabs, { isTopMenu }),
370
+ /* @__PURE__ */ jsx("div", { className: "tker-layout-content__body", children })
371
+ ] });
372
+ });
373
+ function LayoutTabs({ isTopMenu }) {
351
374
  const {
352
375
  adapters,
353
376
  menuData,
354
- activePath,
355
- layoutMode,
356
377
  homePath,
357
378
  maxTabs,
358
379
  getFullPath,
359
380
  navigate
360
381
  } = useLayoutContext();
361
- const isTopMenu = layoutMode === "top-menu";
382
+ const activePath = useActivePathContext();
362
383
  const menuDataRef = useRef(menuData);
363
384
  menuDataRef.current = menuData;
364
385
  const initialTab = activePath && activePath !== "/" ? openTabInData([], activePath, { homePath, maxTabs, menuData }) : [];
@@ -451,21 +472,19 @@ function LayoutContent({ children }) {
451
472
  );
452
473
  }, []);
453
474
  const TabAdapter = adapters.tab;
454
- return /* @__PURE__ */ jsxs("main", { className: "tker-layout-content", children: [
455
- !isTopMenu && TabAdapter && /* @__PURE__ */ jsx(
456
- TabAdapter,
457
- {
458
- tabData,
459
- activeTab,
460
- onSelect: handleTabSelect,
461
- onClose: handleTabClose,
462
- onCloseOther: handleCloseOtherTabs,
463
- onCloseAll: handleCloseAllTabs,
464
- onSetFixed: handleSetFixed
465
- }
466
- ),
467
- /* @__PURE__ */ jsx("div", { className: "tker-layout-content__body", children })
468
- ] });
475
+ if (isTopMenu || !TabAdapter) return null;
476
+ return /* @__PURE__ */ jsx(
477
+ TabAdapter,
478
+ {
479
+ tabData,
480
+ activeTab,
481
+ onSelect: handleTabSelect,
482
+ onClose: handleTabClose,
483
+ onCloseOther: handleCloseOtherTabs,
484
+ onCloseAll: handleCloseAllTabs,
485
+ onSetFixed: handleSetFixed
486
+ }
487
+ );
469
488
  }
470
489
  function openTabInData(tabData, path, config) {
471
490
  const { homePath, maxTabs, menuData } = config;
@@ -516,12 +535,12 @@ function LayoutHeader() {
516
535
  expandedWidth,
517
536
  collapsedWidth,
518
537
  menuData,
519
- activePath,
520
538
  layoutMode,
521
539
  getFullPath,
522
540
  isConcretePage,
523
541
  navigate
524
542
  } = useLayoutContext();
543
+ const activePath = useActivePathContext();
525
544
  const { collapsed, menuItemClick } = useLayoutInteractionContext();
526
545
  const isTopMenu = layoutMode === "top-menu";
527
546
  const isSideMenu = layoutMode === "side-menu";
@@ -592,7 +611,7 @@ function LayoutHeader() {
592
611
  ] });
593
612
  }
594
613
 
595
- function LayoutInner({ children }) {
614
+ const LayoutInner = memo(function LayoutInner2({ children }) {
596
615
  const { layoutMode } = useLayoutContext();
597
616
  const isSideMenu = layoutMode === "side-menu";
598
617
  return /* @__PURE__ */ jsxs("div", { className: "tker-layout", children: [
@@ -602,9 +621,9 @@ function LayoutInner({ children }) {
602
621
  /* @__PURE__ */ jsx(LayoutContent, { children })
603
622
  ] })
604
623
  ] });
605
- }
606
- function Layout({ children, ...props }) {
607
- return /* @__PURE__ */ jsx(LayoutProvider, { ...props, children: /* @__PURE__ */ jsx(LayoutInner, { children }) });
608
- }
624
+ });
625
+ const Layout = memo(function Layout2({ children }) {
626
+ return /* @__PURE__ */ jsx(LayoutProvider, { children: /* @__PURE__ */ jsx(LayoutInner, { children }) });
627
+ });
609
628
 
610
- export { Layout, LayoutProvider, setBreadcrumbAdapter, setCollapsedWidth, setExpandedWidth, setHomePath, setLayoutMode, setLogoAdapter, setMaxTabs, setMenuAdapter, setMenus, setNavigateAdapter, setTabAdapter, setToolbarAdapter, setUserAvatarAdapter };
629
+ export { Layout, LayoutProvider, setActivePath, 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.11",
3
+ "version": "0.2.13",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "type": "module",