vue-stack-tabs 1.0.1 → 1.3.0
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.en.md +526 -0
- package/README.md +337 -520
- package/README.ru.md +526 -0
- package/dist/iframe-bridge.d.ts +8 -0
- package/dist/iframe-bridge.html +77 -0
- package/dist/iframe-bridge.mjs +20 -0
- package/dist/iframe-child.html +88 -0
- package/dist/nuxt/favicon.svg +10 -0
- package/dist/nuxt/iframe-bridge.html +77 -0
- package/dist/nuxt/iframe-child.html +88 -0
- package/dist/nuxt/module.d.ts +6 -0
- package/dist/nuxt/module.mjs +28 -0
- package/dist/nuxt/plugin.mjs +9 -0
- package/dist/nuxt/runtime/plugin.d.ts +2 -0
- package/dist/nuxt/runtime/plugin.mjs +9 -0
- package/dist/src/lib/StackTabs.vue.d.ts +30 -16
- package/dist/src/lib/components/ContextMenu/ContextMenuItem.vue.d.ts +7 -1
- package/dist/src/lib/components/ContextMenu/index.vue.d.ts +5 -4
- package/dist/src/lib/components/PageLoading.vue.d.ts +2 -1
- package/dist/src/lib/components/StackKeepAlive/StackCacheRenderer.vue.d.ts +25 -0
- package/dist/src/lib/components/StackKeepAlive/StackKeepAlive.vue.d.ts +12 -0
- package/dist/src/lib/components/TabHeader/TabHeaderButton.vue.d.ts +11 -12
- package/dist/src/lib/components/TabHeader/TabHeaderItem.vue.d.ts +5 -4
- package/dist/src/lib/components/TabHeader/TabHeaderScroll.vue.d.ts +8 -22
- package/dist/src/lib/components/TabHeader/index.vue.d.ts +11 -164
- package/dist/src/lib/hooks/stackTabsContext.d.ts +49 -0
- package/dist/src/lib/hooks/tabPanel/evict.d.ts +21 -23
- package/dist/src/lib/hooks/tabPanel/navigationTransaction.d.ts +35 -0
- package/dist/src/lib/hooks/tabPanel/refresh.d.ts +17 -0
- package/dist/src/lib/hooks/tabPanel/scroll.d.ts +8 -8
- package/dist/src/lib/hooks/tabPanel/session.d.ts +9 -8
- package/dist/src/lib/hooks/tabPanel/state.d.ts +20 -73
- package/dist/src/lib/hooks/useIframeManager.d.ts +35 -0
- package/dist/src/lib/hooks/useTabActions.d.ts +5 -46
- package/dist/src/lib/hooks/useTabEventBus.d.ts +22 -9
- package/dist/src/lib/hooks/useTabPanel.d.ts +17 -74
- package/dist/src/lib/hooks/useTabRouter.d.ts +5 -5
- package/dist/src/lib/i18n/index.d.ts +6 -4
- package/dist/src/lib/i18n/lang/en.d.ts +5 -0
- package/dist/src/lib/i18n/lang/zh-CN.d.ts +5 -0
- package/dist/src/lib/i18n/stackTabsLocale.d.ts +2 -0
- package/dist/src/lib/iframe-bridge.d.ts +8 -0
- package/dist/src/lib/iframe.vue.d.ts +2 -1
- package/dist/src/lib/index.d.ts +4 -5
- package/dist/src/lib/model/TabModel.d.ts +14 -33
- package/dist/src/lib/nuxt/module.d.ts +6 -0
- package/dist/src/lib/nuxt/runtime/plugin.client.d.ts +2 -0
- package/dist/src/lib/nuxt/runtime/plugin.d.ts +2 -0
- package/dist/src/lib/utils/iframeBridge.d.ts +11 -3
- package/dist/src/lib/utils/stackTabsA11y.d.ts +8 -0
- package/dist/src/lib/utils/stackTabsMessage.d.ts +7 -0
- package/dist/src/lib/utils/tabInfoEncoder.d.ts +1 -16
- package/dist/src/lib/utils/typeGuards.d.ts +2 -0
- package/dist/src/lib/utils/urlParser.d.ts +24 -3
- package/dist/src/lib/versionLogger.d.ts +1 -0
- package/dist/style.css +2 -1
- package/dist/utils/iframeBridge.d.ts +39 -0
- package/dist/vue-stack-tabs.css +2 -1
- package/dist/vue-stack-tabs.es.js +1 -2411
- package/package.json +68 -47
- package/src/lib/StackTabs.vue +216 -192
- package/src/lib/assets/style/stackTab.scss +84 -12
- package/src/lib/components/ContextMenu/ContextMenuItem.vue +23 -11
- package/src/lib/components/ContextMenu/index.vue +94 -10
- package/src/lib/components/PageLoading.vue +9 -7
- package/src/lib/components/StackKeepAlive/StackCacheRenderer.vue +70 -0
- package/src/lib/components/StackKeepAlive/StackKeepAlive.vue +57 -0
- package/src/lib/components/TabHeader/TabHeaderButton.vue +19 -8
- package/src/lib/components/TabHeader/TabHeaderItem.vue +45 -16
- package/src/lib/components/TabHeader/TabHeaderScroll.vue +47 -25
- package/src/lib/components/TabHeader/index.vue +109 -12
- package/src/lib/hooks/stackTabsContext.ts +135 -0
- package/src/lib/hooks/tabPanel/evict.ts +123 -41
- package/src/lib/hooks/tabPanel/navigationTransaction.ts +61 -0
- package/src/lib/hooks/tabPanel/refresh.ts +109 -0
- package/src/lib/hooks/tabPanel/scroll.ts +57 -36
- package/src/lib/hooks/tabPanel/session.ts +84 -22
- package/src/lib/hooks/tabPanel/state.ts +41 -44
- package/src/lib/hooks/useIframeManager.ts +253 -0
- package/src/lib/hooks/useTabActions.ts +62 -30
- package/src/lib/hooks/useTabEventBus.ts +29 -19
- package/src/lib/hooks/useTabLoading.ts +3 -2
- package/src/lib/hooks/useTabPanel.tsx +415 -213
- package/src/lib/hooks/useTabRouter.ts +172 -43
- package/src/lib/i18n/index.ts +53 -45
- package/src/lib/i18n/lang/en.ts +6 -1
- package/src/lib/i18n/lang/zh-CN.ts +6 -1
- package/src/lib/i18n/stackTabsLocale.ts +8 -0
- package/src/lib/iframe-bridge.ts +12 -0
- package/src/lib/index.ts +14 -19
- package/src/lib/model/TabModel.ts +34 -86
- package/src/lib/nuxt/module.d.ts +4 -0
- package/src/lib/nuxt/module.ts +8 -3
- package/src/lib/nuxt/runtime/plugin.client.ts +2 -3
- package/src/lib/nuxt/runtime/plugin.ts +11 -0
- package/src/lib/utils/iframeBridge.ts +29 -5
- package/src/lib/utils/scrollUtils.ts +9 -4
- package/src/lib/utils/stackTabsA11y.ts +12 -0
- package/src/lib/utils/stackTabsMessage.ts +99 -0
- package/src/lib/utils/tabInfoEncoder.ts +69 -42
- package/src/lib/utils/typeGuards.ts +3 -0
- package/src/lib/utils/urlParser.ts +144 -14
- package/src/lib/versionLogger.ts +7 -19
- package/dist/src/lib/hooks/tabPanel/evict.spec.d.ts +0 -1
- package/dist/src/lib/hooks/useTabPanel.spec.d.ts +0 -1
- package/dist/src/lib/model/TabModel.spec.d.ts +0 -1
- package/dist/src/lib/utils/iframeBridge.spec.d.ts +0 -1
- package/dist/src/lib/utils/tabInfoEncoder.spec.d.ts +0 -1
- package/dist/src/lib/utils/urlParser.spec.d.ts +0 -1
- package/dist/vue-stack-tabs.umd.js +0 -1
- package/src/lib/hooks/tabPanel/evict.spec.ts +0 -85
- package/src/lib/hooks/useTabPanel.spec.ts +0 -34
- package/src/lib/model/TabModel.spec.ts +0 -40
- package/src/lib/utils/iframeBridge.spec.ts +0 -37
- package/src/lib/utils/tabInfoEncoder.spec.ts +0 -42
- package/src/lib/utils/urlParser.spec.ts +0 -45
|
@@ -1,104 +1,47 @@
|
|
|
1
|
-
import { ITabData, ITabItem
|
|
1
|
+
import { ITabData, ITabItem } from '../model/TabModel';
|
|
2
2
|
import { DefineComponent, VNode } from 'vue';
|
|
3
3
|
import { RouteLocationNormalizedLoaded } from 'vue-router';
|
|
4
4
|
/** 规范化路径(nginx 等可能加尾部斜杠) */
|
|
5
5
|
export declare const normalizePathForCache: (route: RouteLocationNormalizedLoaded) => string;
|
|
6
6
|
declare const _default: () => {
|
|
7
|
-
tabs: import('vue').Ref<
|
|
8
|
-
|
|
9
|
-
closable: boolean;
|
|
10
|
-
refreshable: boolean;
|
|
11
|
-
iframe: boolean;
|
|
12
|
-
iframeRefreshMode?: import('..').IframeRefreshMode | undefined;
|
|
13
|
-
url?: string | undefined;
|
|
14
|
-
active: boolean;
|
|
15
|
-
pages: {
|
|
16
|
-
push: (element: ITabPage) => void;
|
|
17
|
-
pop: () => ITabPage | undefined;
|
|
18
|
-
peek: () => ITabPage | undefined;
|
|
19
|
-
isEmpty: () => boolean;
|
|
20
|
-
size: () => number;
|
|
21
|
-
clear: () => void;
|
|
22
|
-
list: () => ITabPage[];
|
|
23
|
-
toString: () => string;
|
|
24
|
-
toJSON: () => ITabPage[];
|
|
25
|
-
};
|
|
26
|
-
title: string;
|
|
27
|
-
}[], ITabItem[] | {
|
|
28
|
-
id: string;
|
|
29
|
-
closable: boolean;
|
|
30
|
-
refreshable: boolean;
|
|
31
|
-
iframe: boolean;
|
|
32
|
-
iframeRefreshMode?: import('..').IframeRefreshMode | undefined;
|
|
33
|
-
url?: string | undefined;
|
|
34
|
-
active: boolean;
|
|
35
|
-
pages: {
|
|
36
|
-
push: (element: ITabPage) => void;
|
|
37
|
-
pop: () => ITabPage | undefined;
|
|
38
|
-
peek: () => ITabPage | undefined;
|
|
39
|
-
isEmpty: () => boolean;
|
|
40
|
-
size: () => number;
|
|
41
|
-
clear: () => void;
|
|
42
|
-
list: () => ITabPage[];
|
|
43
|
-
toString: () => string;
|
|
44
|
-
toJSON: () => ITabPage[];
|
|
45
|
-
};
|
|
46
|
-
title: string;
|
|
47
|
-
}[]>;
|
|
48
|
-
caches: import('vue').Ref<string[], string[]>;
|
|
7
|
+
tabs: import('vue').Ref<ITabItem[], ITabItem[]>;
|
|
8
|
+
caches: import('vue').ShallowRef<string[]>;
|
|
49
9
|
refreshKey: import('vue').Ref<number, number>;
|
|
50
|
-
|
|
10
|
+
activeCacheKey: import('vue').Ref<string, string>;
|
|
11
|
+
activePageRefreshVersion: import('vue').ComputedRef<number>;
|
|
51
12
|
isInitialized: import('vue').Ref<boolean, boolean>;
|
|
52
|
-
setMaxSize: (
|
|
13
|
+
setMaxSize: (value: number) => void;
|
|
53
14
|
canAddTab: () => boolean;
|
|
54
15
|
initialize: (staticTabs: ITabData[]) => void;
|
|
55
16
|
size: () => number;
|
|
56
|
-
active: (id: string, route?: boolean) => void
|
|
17
|
+
active: (id: string, route?: boolean) => Promise<void | import('vue-router').NavigationFailure | undefined>;
|
|
18
|
+
getCacheName: () => string;
|
|
57
19
|
destroy: () => void;
|
|
58
20
|
reset: () => void;
|
|
59
21
|
addCache: (cacheName: string) => void;
|
|
60
22
|
removeCache: (cacheName: string) => void;
|
|
61
|
-
getTab: (id: string) =>
|
|
62
|
-
|
|
63
|
-
closable: boolean;
|
|
64
|
-
refreshable: boolean;
|
|
65
|
-
iframe: boolean;
|
|
66
|
-
iframeRefreshMode?: import('..').IframeRefreshMode | undefined;
|
|
67
|
-
url?: string | undefined;
|
|
68
|
-
active: boolean;
|
|
69
|
-
pages: {
|
|
70
|
-
push: (element: ITabPage) => void;
|
|
71
|
-
pop: () => ITabPage | undefined;
|
|
72
|
-
peek: () => ITabPage | undefined;
|
|
73
|
-
isEmpty: () => boolean;
|
|
74
|
-
size: () => number;
|
|
75
|
-
clear: () => void;
|
|
76
|
-
list: () => ITabPage[];
|
|
77
|
-
toString: () => string;
|
|
78
|
-
toJSON: () => ITabPage[];
|
|
79
|
-
};
|
|
80
|
-
title: string;
|
|
81
|
-
} | null;
|
|
82
|
-
addTab: (tab: ITabItem) => Promise<boolean>;
|
|
23
|
+
getTab: (id: string) => ITabItem | null;
|
|
24
|
+
addTab: (tab: ITabItem) => void;
|
|
83
25
|
removeTab: (id: string) => string;
|
|
84
26
|
removeAllTabs: () => void;
|
|
85
27
|
removeLeftTabs: (id: string) => void;
|
|
86
28
|
removeRightTabs: (id: string) => void;
|
|
87
29
|
removeOtherTabs: (id: string) => void;
|
|
88
30
|
hasTab: (id: string) => boolean;
|
|
89
|
-
renewTab: (tab: ITabData) => void;
|
|
90
|
-
addPage: (route: RouteLocationNormalizedLoaded, component
|
|
91
|
-
addComponent: (id: string, comp: DefineComponent) => Map<string, DefineComponent
|
|
92
|
-
getComponent: (id: string) => DefineComponent
|
|
31
|
+
renewTab: (tab: ITabData) => (() => void) | undefined;
|
|
32
|
+
addPage: (route: RouteLocationNormalizedLoaded, component?: VNode | null) => DefineComponent;
|
|
33
|
+
addComponent: (id: string, comp: DefineComponent) => Map<string, DefineComponent>;
|
|
34
|
+
getComponent: (id: string) => DefineComponent | undefined;
|
|
93
35
|
removeComponent: (id: string) => boolean;
|
|
94
36
|
markCacheForEviction: (cacheName: string) => void;
|
|
95
37
|
evictMarkedCaches: () => void;
|
|
38
|
+
evictPageCache: (cacheName: string) => void;
|
|
96
39
|
refreshTab: (id: string) => void;
|
|
97
40
|
refreshAllTabs: () => void;
|
|
98
41
|
iframeRefreshKeys: import('vue').Ref<Record<string, number>, Record<string, number>>;
|
|
99
42
|
addPageScroller: (pageCacheId: string, ...selectorIds: string[]) => void;
|
|
100
|
-
setGlobalScroll: (
|
|
43
|
+
setGlobalScroll: (value: boolean) => void;
|
|
101
44
|
clearSession: () => void;
|
|
102
|
-
setSessionPrefix: (
|
|
45
|
+
setSessionPrefix: (value: string) => void;
|
|
103
46
|
};
|
|
104
47
|
export default _default;
|
|
@@ -3,15 +3,15 @@ import { RouteLocationPathRaw } from 'vue-router';
|
|
|
3
3
|
* useTabRouter - 标签内路由 Hook
|
|
4
4
|
*
|
|
5
5
|
* 职责:在单个标签内实现「前进/后退」栈式导航,以及滚动位置的记录与恢复
|
|
6
|
-
* 使用范围:仅在标签内的页面组件中使用,依赖
|
|
6
|
+
* 使用范围:仅在标签内的页面组件中使用,依赖 StackTabs 通过 cloneVNode 注入的 tId / pId
|
|
7
7
|
*
|
|
8
8
|
* 主要 API:
|
|
9
|
-
* - forward(to)
|
|
10
|
-
* - backward(to, backQuery
|
|
11
|
-
* - addScrollTarget(...
|
|
9
|
+
* - forward(to) 前进:push 新页面到该标签的 pages 栈
|
|
10
|
+
* - backward(to, backQuery) 后退:pop 栈顶、驱逐缓存,跳转到新栈顶
|
|
11
|
+
* - addScrollTarget(...) 注册需要记录滚动位置的选择器
|
|
12
12
|
*/
|
|
13
13
|
export default function useTabRouter(): {
|
|
14
14
|
forward: (to: RouteLocationPathRaw) => void;
|
|
15
|
-
backward: (to: number | string, backQuery?:
|
|
15
|
+
backward: (to: number | string, backQuery?: Record<string, unknown>) => boolean;
|
|
16
16
|
addScrollTarget: (...selectors: string[]) => void;
|
|
17
17
|
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
export interface LocaleMessageOption {
|
|
2
|
+
locale: string;
|
|
3
|
+
messages?: Record<string, unknown>;
|
|
4
|
+
}
|
|
5
|
+
export declare const mergeLocaleMessages: (baseMessages: Record<string, Record<string, unknown>>, localeI18n?: LocaleMessageOption[]) => Record<string, Record<string, unknown>>;
|
|
1
6
|
declare const _default: () => {
|
|
2
|
-
getI18n: (localeI18n?:
|
|
3
|
-
locale: string;
|
|
4
|
-
messages: Record<string, unknown>;
|
|
5
|
-
}[]) => import('vue-i18n-lite').I18n;
|
|
7
|
+
getI18n: (localeI18n?: LocaleMessageOption[]) => import('vue-i18n-lite').I18n;
|
|
6
8
|
};
|
|
7
9
|
export default _default;
|
|
@@ -11,7 +11,12 @@ declare const _default: {
|
|
|
11
11
|
restore: string;
|
|
12
12
|
undefined: string;
|
|
13
13
|
loading: string;
|
|
14
|
+
iframeTitle: string;
|
|
15
|
+
iframeLoadTimeout: string;
|
|
16
|
+
retry: string;
|
|
14
17
|
openInNewWindow: string;
|
|
18
|
+
scrollLeft: string;
|
|
19
|
+
scrollRight: string;
|
|
15
20
|
};
|
|
16
21
|
};
|
|
17
22
|
export default _default;
|
|
@@ -11,7 +11,12 @@ declare const _default: {
|
|
|
11
11
|
restore: string;
|
|
12
12
|
undefined: string;
|
|
13
13
|
loading: string;
|
|
14
|
+
iframeTitle: string;
|
|
15
|
+
iframeLoadTimeout: string;
|
|
16
|
+
retry: string;
|
|
14
17
|
openInNewWindow: string;
|
|
18
|
+
scrollLeft: string;
|
|
19
|
+
scrollRight: string;
|
|
15
20
|
};
|
|
16
21
|
};
|
|
17
22
|
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* iframe-bridge 子入口(vue-stack-tabs/iframe-bridge)。
|
|
3
|
+
*
|
|
4
|
+
* 供 iframe 内部页面引用,不包含 Vue 组件和样式等副作用,
|
|
5
|
+
* 仅导出 postMessage 通信工具。
|
|
6
|
+
*/
|
|
7
|
+
export { MSG_OPEN_TAB, MSG_REFRESH, onRefreshRequest, postOpenTab } from './utils/iframeBridge';
|
|
8
|
+
export type { IframeBridgeOptions, IframeOpenTabPayload, RefreshRequestOptions } from './utils/iframeBridge';
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
declare const
|
|
1
|
+
declare const __VLS_export: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
2
|
+
declare const _default: typeof __VLS_export;
|
|
2
3
|
export default _default;
|
package/dist/src/lib/index.d.ts
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { App } from 'vue';
|
|
2
|
+
import { LocaleMessageOption } from './i18n';
|
|
2
3
|
import { default as StackTab } from './StackTabs.vue';
|
|
3
4
|
import { default as IFrame } from './iframe.vue';
|
|
4
5
|
import { default as useTabLoading } from './hooks/useTabLoading';
|
|
5
6
|
import { default as useTabRouter } from './hooks/useTabRouter';
|
|
6
7
|
import { default as useTabActions } from './hooks/useTabActions';
|
|
7
8
|
import { default as TabHeaderButton } from './components/TabHeader/TabHeaderButton.vue';
|
|
9
|
+
export type VueStackTabsPluginOptions = LocaleMessageOption[];
|
|
8
10
|
export * from './model/TabModel';
|
|
9
11
|
declare module '@vue/runtime-core' {
|
|
10
12
|
interface GlobalComponents {
|
|
11
13
|
VueStackTabs: typeof StackTab;
|
|
12
14
|
}
|
|
13
15
|
}
|
|
14
|
-
export { IFrame, useTabActions, useTabLoading, useTabRouter, TabHeaderButton, StackTab };
|
|
16
|
+
export { IFrame, useTabActions, useTabLoading, useTabRouter, TabHeaderButton, StackTab, StackTab as VueStackTabs };
|
|
15
17
|
export { postOpenTab, onRefreshRequest, MSG_REFRESH, MSG_OPEN_TAB } from './utils/iframeBridge';
|
|
16
18
|
export type { IframeOpenTabPayload } from './utils/iframeBridge';
|
|
17
19
|
declare const _default: {
|
|
18
|
-
install(Vue: App, options?:
|
|
19
|
-
locale: string;
|
|
20
|
-
messages: Record<string, unknown>;
|
|
21
|
-
}[]): void;
|
|
20
|
+
install(Vue: App, options?: VueStackTabsPluginOptions): void;
|
|
22
21
|
};
|
|
23
22
|
export default _default;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LocationQueryRaw } from 'vue-router';
|
|
1
2
|
/**
|
|
2
3
|
* TabModel - 标签页数据模型
|
|
3
4
|
*
|
|
@@ -30,7 +31,7 @@ export type ScrollEvents = {
|
|
|
30
31
|
export interface ITabData extends ITabBase {
|
|
31
32
|
title: string;
|
|
32
33
|
path: string;
|
|
33
|
-
query?:
|
|
34
|
+
query?: LocationQueryRaw;
|
|
34
35
|
}
|
|
35
36
|
/** iframe 刷新方式:postMessage 由 iframe 内页自行刷新(不重建 DOM,动画正常);reload 强制重载 iframe */
|
|
36
37
|
export type IframeRefreshMode = 'postMessage' | 'reload';
|
|
@@ -60,53 +61,33 @@ export interface ITabPage {
|
|
|
60
61
|
id: string;
|
|
61
62
|
tabId: string;
|
|
62
63
|
path: string;
|
|
63
|
-
query?:
|
|
64
|
+
query?: LocationQueryRaw;
|
|
65
|
+
/** 页面级刷新版本;仅影响当前页面的 keep-alive 缓存 key */
|
|
66
|
+
refreshVersion?: number;
|
|
67
|
+
/** 该页面从别的页面被后退唤醒时附带的临时闭包参数,不污染 URL */
|
|
68
|
+
_backParams?: Record<string, unknown>;
|
|
64
69
|
}
|
|
65
|
-
/**
|
|
70
|
+
/** 右键菜单项:重复或动态菜单应提供稳定 key,避免 fallback 标题/图标重复 */
|
|
66
71
|
export interface IContextMenu {
|
|
72
|
+
key?: string;
|
|
67
73
|
icon?: string;
|
|
68
74
|
title: string;
|
|
69
75
|
callback(id: string): void;
|
|
70
76
|
disabled: (tabData: ITabBase) => boolean;
|
|
71
77
|
}
|
|
72
|
-
/**
|
|
78
|
+
/** 数组实现的栈结构,用于标签内的 pages 页面栈 */
|
|
73
79
|
export declare class Stack<T> {
|
|
74
|
-
|
|
80
|
+
protected items: T[];
|
|
75
81
|
constructor(items?: T[]);
|
|
76
|
-
/**
|
|
77
|
-
* @description: 入栈
|
|
78
|
-
* @param {T} element 要入栈的元素
|
|
79
|
-
*/
|
|
80
82
|
push(element: T): void;
|
|
81
|
-
/**
|
|
82
|
-
* @description: 出栈
|
|
83
|
-
* @return {T} 返回出栈的元素
|
|
84
|
-
*/
|
|
85
83
|
pop(): T | undefined;
|
|
86
|
-
/**
|
|
87
|
-
* @description: 返回栈顶的元素
|
|
88
|
-
* @return {T}
|
|
89
|
-
*/
|
|
90
84
|
peek(): T | undefined;
|
|
91
|
-
|
|
92
|
-
* @description: 返回栈是否为空
|
|
93
|
-
* @return {Boolean}
|
|
94
|
-
*/
|
|
85
|
+
at(index: number): T | undefined;
|
|
95
86
|
isEmpty(): boolean;
|
|
96
|
-
/**
|
|
97
|
-
* @description: 返回栈里的元素个数
|
|
98
|
-
* @return {Number}
|
|
99
|
-
*/
|
|
100
87
|
size(): number;
|
|
101
|
-
/**
|
|
102
|
-
* @description: 清空栈
|
|
103
|
-
*/
|
|
104
88
|
clear(): void;
|
|
105
89
|
list(): T[];
|
|
106
|
-
|
|
107
|
-
* @description: 覆盖Object默认的toString
|
|
108
|
-
* @return {String}
|
|
109
|
-
*/
|
|
110
|
-
toString(): string;
|
|
90
|
+
readonlyList(): readonly T[];
|
|
111
91
|
toJSON(): T[];
|
|
92
|
+
toString(): string;
|
|
112
93
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LocationQueryRaw } from 'vue-router';
|
|
1
2
|
/**
|
|
2
3
|
* iframe 与父窗口的 postMessage 桥接
|
|
3
4
|
*
|
|
@@ -9,23 +10,30 @@
|
|
|
9
10
|
export declare const MSG_REFRESH = "vue-stack-tabs:refresh";
|
|
10
11
|
/** 打开标签消息:iframe -> 父,payload 为 ITabData */
|
|
11
12
|
export declare const MSG_OPEN_TAB = "vue-stack-tabs:openTab";
|
|
13
|
+
export interface IframeBridgeOptions {
|
|
14
|
+
targetOrigin?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface RefreshRequestOptions {
|
|
17
|
+
allowedOrigins?: string[];
|
|
18
|
+
}
|
|
12
19
|
export interface IframeOpenTabPayload {
|
|
13
20
|
id?: string;
|
|
14
21
|
title: string;
|
|
15
22
|
path: string;
|
|
16
|
-
query?:
|
|
23
|
+
query?: LocationQueryRaw;
|
|
17
24
|
closable?: boolean;
|
|
18
25
|
refreshable?: boolean;
|
|
19
26
|
iframe?: boolean;
|
|
27
|
+
iframeRefreshMode?: 'postMessage' | 'reload';
|
|
20
28
|
}
|
|
21
29
|
/**
|
|
22
30
|
* 在 iframe 内调用:向父窗口请求打开新标签
|
|
23
31
|
* @param payload 标签数据,至少需 title、path
|
|
24
32
|
*/
|
|
25
|
-
export declare function postOpenTab(payload: IframeOpenTabPayload): void;
|
|
33
|
+
export declare function postOpenTab(payload: IframeOpenTabPayload, options?: IframeBridgeOptions): void;
|
|
26
34
|
/**
|
|
27
35
|
* 在 iframe 内调用:注册刷新监听,收到父窗口刷新指令时执行 callback
|
|
28
36
|
* @param callback 默认 location.reload(),可自定义
|
|
29
37
|
* @returns 取消监听的函数
|
|
30
38
|
*/
|
|
31
|
-
export declare function onRefreshRequest(callback?: () => void): () => void;
|
|
39
|
+
export declare function onRefreshRequest(callback?: () => void, options?: RefreshRequestOptions): () => void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAI-ARIA 无障碍 ID 生成工具。
|
|
3
|
+
* 为 tab/panel 元素生成符合 ARIA tablist 模式的关联 ID。
|
|
4
|
+
*/
|
|
5
|
+
/** 生成 tab 触发器的 DOM id,用于 aria-controls 关联 */
|
|
6
|
+
export declare const getStackTabTabId: (tabId: string) => string;
|
|
7
|
+
/** 生成 tab 面板的 DOM id,用于 aria-labelledby 关联 */
|
|
8
|
+
export declare const getStackTabPanelId: (tabId: string) => string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ITabData } from '../model/TabModel';
|
|
2
|
+
type ManagedSourceChecker = (source: MessageEventSource | null) => boolean;
|
|
3
|
+
/** 校验 MessageEvent 是否为合法的 openTab 请求,返回解析后的 ITabData 或 null */
|
|
4
|
+
export declare const isStackTabsOpenTabMessage: (event: MessageEvent, isManagedSource: ManagedSourceChecker) => ITabData | null;
|
|
5
|
+
/** 根据 iframe URL 计算安全的 postMessage targetOrigin,非法 URL 返回 null */
|
|
6
|
+
export declare const getPostMessageTargetOrigin: (url: string, fallbackOrigin?: string) => string | null;
|
|
7
|
+
export {};
|
|
@@ -1,19 +1,4 @@
|
|
|
1
1
|
import { ITabBase } from '../model/TabModel';
|
|
2
|
-
/**
|
|
3
|
-
* 标签信息编解码器
|
|
4
|
-
*
|
|
5
|
-
* 职责:将标签元数据压缩为 URL query 可用的短字符串,用于 __tab 参数
|
|
6
|
-
* 格式: id|title|iframe|closable|refreshable,压缩后写入 query.__tab
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* 编码标签基础信息为压缩字符串(用于 query.__tab)
|
|
10
|
-
* @param tabData 标签基础数据
|
|
11
|
-
*/
|
|
12
2
|
export declare const encodeTabInfo: (tabData: ITabBase) => string;
|
|
13
|
-
/** 从 query.__tab 解压并解析为 ITabBase */
|
|
14
3
|
export declare const decodeTabInfo: (encoded: string) => ITabBase;
|
|
15
|
-
|
|
16
|
-
* 根据 tabId + path + query 生成页面缓存 ID
|
|
17
|
-
* 用于 keep-alive 的 include 和 exclude,需稳定且唯一
|
|
18
|
-
*/
|
|
19
|
-
export declare const createPageId: (tabId: string, path: string, query: object) => string;
|
|
4
|
+
export declare const createPageId: () => string;
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
import { LocationQueryRaw } from 'vue-router';
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
+
* 判断标签 URL 是否允许进入 iframe/window.open/router 等 URL sink。
|
|
4
|
+
* 允许相对路径、http(s) URL 与 about:blank;拒绝其它 scheme。
|
|
5
|
+
*/
|
|
6
|
+
export declare function isAllowedTabUrl(url: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* 判断是否为不允许嵌入 iframe 的 URL
|
|
3
9
|
* @param url - 待检查的 URL 字符串
|
|
4
|
-
* @returns
|
|
10
|
+
* @returns 非 allowlist URL 返回 true
|
|
5
11
|
*/
|
|
6
12
|
export declare function isInvalidIframeUrl(url: string): boolean;
|
|
13
|
+
/** 非法 URL 降级为 about:blank,避免进入 iframe/window.open 等 URL sink */
|
|
14
|
+
export declare function toSafeTabUrl(url: string): string;
|
|
15
|
+
export declare function decodeSafeTabUrl(encodedUrl: unknown): string;
|
|
7
16
|
/**
|
|
8
17
|
* 判断 URL 是否为跨域(相对路径或同源视为同域)
|
|
9
18
|
* @param url - 待检查的 URL
|
|
@@ -15,5 +24,17 @@ export declare function isCrossOriginUrl(url: string): boolean;
|
|
|
15
24
|
*/
|
|
16
25
|
export declare function parseUrl(uri: string): {
|
|
17
26
|
path: string;
|
|
18
|
-
query:
|
|
27
|
+
query: LocationQueryRaw;
|
|
19
28
|
};
|
|
29
|
+
/** 浅克隆 LocationQueryRaw,避免引用共享导致的副作用 */
|
|
30
|
+
export declare function cloneLocationQuery(query?: LocationQueryRaw): LocationQueryRaw;
|
|
31
|
+
export interface CloneablePage {
|
|
32
|
+
query?: LocationQueryRaw;
|
|
33
|
+
_backParams?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
/** 深克隆页面对象的 query 和 _backParams,防止跨页面引用污染 */
|
|
36
|
+
export declare function clonePage<T extends CloneablePage>(page: T): T;
|
|
37
|
+
/** 忽略 __tab/__src/_back 等内部保留 key 后比较两个 query 是否等价 */
|
|
38
|
+
export declare function isSameQueryIgnoringReserved(a?: LocationQueryRaw, b?: LocationQueryRaw): boolean;
|
|
39
|
+
/** 移除 query 中的 vue-stack-tabs 保留参数(__tab、__src),返回干净的 query */
|
|
40
|
+
export declare function omitStackTabsReservedQuery(query?: LocationQueryRaw): LocationQueryRaw;
|