vue-stack-tabs 1.1.0 → 1.3.1

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.
Files changed (115) hide show
  1. package/README.en.md +526 -0
  2. package/README.md +141 -39
  3. package/README.ru.md +526 -0
  4. package/dist/iframe-bridge.d.ts +8 -0
  5. package/dist/iframe-bridge.html +77 -0
  6. package/dist/iframe-bridge.mjs +20 -0
  7. package/dist/iframe-child.html +19 -6
  8. package/dist/nuxt/favicon.svg +10 -0
  9. package/dist/nuxt/iframe-bridge.html +77 -0
  10. package/dist/nuxt/iframe-child.html +88 -0
  11. package/dist/nuxt/module.d.ts +6 -0
  12. package/dist/nuxt/module.mjs +28 -0
  13. package/dist/nuxt/plugin.mjs +9 -0
  14. package/dist/nuxt/runtime/plugin.d.ts +2 -0
  15. package/dist/nuxt/runtime/plugin.mjs +9 -0
  16. package/dist/src/lib/StackTabs.vue.d.ts +30 -16
  17. package/dist/src/lib/components/ContextMenu/ContextMenuItem.vue.d.ts +7 -1
  18. package/dist/src/lib/components/ContextMenu/index.vue.d.ts +5 -4
  19. package/dist/src/lib/components/PageLoading.vue.d.ts +2 -1
  20. package/dist/src/lib/components/StackKeepAlive/StackCacheRenderer.vue.d.ts +25 -0
  21. package/dist/src/lib/components/StackKeepAlive/StackKeepAlive.vue.d.ts +12 -0
  22. package/dist/src/lib/components/TabHeader/TabHeaderButton.vue.d.ts +11 -12
  23. package/dist/src/lib/components/TabHeader/TabHeaderItem.vue.d.ts +5 -4
  24. package/dist/src/lib/components/TabHeader/TabHeaderScroll.vue.d.ts +8 -22
  25. package/dist/src/lib/components/TabHeader/index.vue.d.ts +11 -164
  26. package/dist/src/lib/hooks/stackTabsContext.d.ts +49 -0
  27. package/dist/src/lib/hooks/tabPanel/evict.d.ts +21 -61
  28. package/dist/src/lib/hooks/tabPanel/navigationTransaction.d.ts +35 -0
  29. package/dist/src/lib/hooks/tabPanel/refresh.d.ts +17 -0
  30. package/dist/src/lib/hooks/tabPanel/scroll.d.ts +8 -8
  31. package/dist/src/lib/hooks/tabPanel/session.d.ts +9 -8
  32. package/dist/src/lib/hooks/tabPanel/state.d.ts +20 -72
  33. package/dist/src/lib/hooks/useIframeManager.d.ts +35 -0
  34. package/dist/src/lib/hooks/useTabActions.d.ts +5 -46
  35. package/dist/src/lib/hooks/useTabEventBus.d.ts +22 -9
  36. package/dist/src/lib/hooks/useTabPanel.d.ts +14 -73
  37. package/dist/src/lib/i18n/index.d.ts +6 -4
  38. package/dist/src/lib/i18n/lang/en.d.ts +5 -0
  39. package/dist/src/lib/i18n/lang/zh-CN.d.ts +5 -0
  40. package/dist/src/lib/i18n/stackTabsLocale.d.ts +2 -0
  41. package/dist/src/lib/iframe-bridge.d.ts +8 -0
  42. package/dist/src/lib/iframe.vue.d.ts +2 -1
  43. package/dist/src/lib/index.d.ts +4 -5
  44. package/dist/src/lib/model/TabModel.d.ts +11 -40
  45. package/dist/src/lib/nuxt/module.d.ts +6 -0
  46. package/dist/src/lib/nuxt/runtime/plugin.client.d.ts +2 -0
  47. package/dist/src/lib/nuxt/runtime/plugin.d.ts +2 -0
  48. package/dist/src/lib/utils/iframeBridge.d.ts +11 -3
  49. package/dist/src/lib/utils/stackTabsA11y.d.ts +8 -0
  50. package/dist/src/lib/utils/stackTabsMessage.d.ts +7 -0
  51. package/dist/src/lib/utils/tabInfoEncoder.d.ts +0 -15
  52. package/dist/src/lib/utils/typeGuards.d.ts +2 -0
  53. package/dist/src/lib/utils/urlParser.d.ts +24 -3
  54. package/dist/src/lib/versionLogger.d.ts +1 -0
  55. package/dist/style.css +2 -1
  56. package/dist/utils/iframeBridge.d.ts +39 -0
  57. package/dist/vue-stack-tabs.css +2 -1
  58. package/dist/vue-stack-tabs.es.js +1 -2220
  59. package/package.json +71 -50
  60. package/src/lib/StackTabs.vue +223 -196
  61. package/src/lib/assets/style/stackTab.scss +110 -13
  62. package/src/lib/components/ContextMenu/ContextMenuItem.vue +23 -11
  63. package/src/lib/components/ContextMenu/index.vue +94 -10
  64. package/src/lib/components/PageLoading.vue +9 -7
  65. package/src/lib/components/StackKeepAlive/StackCacheRenderer.vue +70 -0
  66. package/src/lib/components/StackKeepAlive/StackKeepAlive.vue +57 -0
  67. package/src/lib/components/TabHeader/TabHeaderButton.vue +19 -8
  68. package/src/lib/components/TabHeader/TabHeaderItem.vue +74 -17
  69. package/src/lib/components/TabHeader/TabHeaderScroll.vue +47 -25
  70. package/src/lib/components/TabHeader/index.vue +181 -13
  71. package/src/lib/hooks/stackTabsContext.ts +135 -0
  72. package/src/lib/hooks/tabPanel/evict.ts +122 -87
  73. package/src/lib/hooks/tabPanel/navigationTransaction.ts +61 -0
  74. package/src/lib/hooks/tabPanel/refresh.ts +109 -0
  75. package/src/lib/hooks/tabPanel/scroll.ts +57 -40
  76. package/src/lib/hooks/tabPanel/session.ts +84 -22
  77. package/src/lib/hooks/tabPanel/state.ts +41 -44
  78. package/src/lib/hooks/useIframeManager.ts +253 -0
  79. package/src/lib/hooks/useTabActions.ts +64 -30
  80. package/src/lib/hooks/useTabEventBus.ts +29 -19
  81. package/src/lib/hooks/useTabLoading.ts +3 -2
  82. package/src/lib/hooks/useTabPanel.tsx +290 -313
  83. package/src/lib/hooks/useTabRouter.ts +111 -97
  84. package/src/lib/i18n/index.ts +53 -45
  85. package/src/lib/i18n/lang/en.ts +6 -1
  86. package/src/lib/i18n/lang/zh-CN.ts +6 -1
  87. package/src/lib/i18n/stackTabsLocale.ts +8 -0
  88. package/src/lib/iframe-bridge.ts +12 -0
  89. package/src/lib/index.ts +14 -19
  90. package/src/lib/model/TabModel.ts +27 -82
  91. package/src/lib/nuxt/module.d.ts +4 -0
  92. package/src/lib/nuxt/module.ts +8 -3
  93. package/src/lib/nuxt/runtime/plugin.client.ts +1 -0
  94. package/src/lib/nuxt/runtime/plugin.ts +11 -0
  95. package/src/lib/utils/iframeBridge.ts +29 -5
  96. package/src/lib/utils/scrollUtils.ts +9 -4
  97. package/src/lib/utils/stackTabsA11y.ts +12 -0
  98. package/src/lib/utils/stackTabsMessage.ts +99 -0
  99. package/src/lib/utils/tabInfoEncoder.ts +70 -21
  100. package/src/lib/utils/typeGuards.ts +3 -0
  101. package/src/lib/utils/urlParser.ts +144 -14
  102. package/src/lib/versionLogger.ts +7 -19
  103. package/dist/src/lib/hooks/tabPanel/evict.spec.d.ts +0 -1
  104. package/dist/src/lib/hooks/useTabPanel.spec.d.ts +0 -1
  105. package/dist/src/lib/model/TabModel.spec.d.ts +0 -1
  106. package/dist/src/lib/utils/iframeBridge.spec.d.ts +0 -1
  107. package/dist/src/lib/utils/tabInfoEncoder.spec.d.ts +0 -1
  108. package/dist/src/lib/utils/urlParser.spec.d.ts +0 -1
  109. package/dist/vue-stack-tabs.umd.js +0 -1
  110. package/src/lib/hooks/tabPanel/evict.spec.ts +0 -85
  111. package/src/lib/hooks/useTabPanel.spec.ts +0 -34
  112. package/src/lib/model/TabModel.spec.ts +0 -40
  113. package/src/lib/utils/iframeBridge.spec.ts +0 -37
  114. package/src/lib/utils/tabInfoEncoder.spec.ts +0 -32
  115. package/src/lib/utils/urlParser.spec.ts +0 -45
@@ -1,18 +1,31 @@
1
+ import { InjectionKey } from 'vue';
1
2
  import { Emitter, EventType } from 'mitt';
2
- import { App } from 'vue';
3
3
  declare module '@vue/runtime-core' {
4
4
  interface ComponentCustomProperties {
5
- $layerEmitter: Emitter<Record<EventType, unknown>>;
5
+ $layerEmitter: Emitter<TabEventPayloadMap>;
6
6
  }
7
7
  }
8
- declare const plugin: {
9
- install(app: App): void;
10
- };
11
- /** 获取标签事件总线,用于组件间通信 */
12
- export declare const useTabEmitter: <T extends Record<EventType, unknown>>() => Emitter<T>;
13
8
  /** 标签相关事件类型 */
14
9
  export declare enum TabEventType {
15
10
  PAGE_LOADING = "PAGE_LOADING",
16
- TAB_ACTIVE = "TAB_ACTIVE"
11
+ TAB_ACTIVE = "TAB_ACTIVE",
12
+ FORWARD = "FORWARD",
13
+ BACKWARD = "BACKWARD",
14
+ REFRESH_IFRAME_POSTMESSAGE = "REFRESH_IFRAME_POSTMESSAGE"
15
+ }
16
+ export interface TabEventPayloadMap extends Record<EventType, unknown> {
17
+ [TabEventType.PAGE_LOADING]: {
18
+ tId: string;
19
+ value: boolean;
20
+ };
21
+ [TabEventType.TAB_ACTIVE]: {
22
+ id: string;
23
+ isRoute?: boolean;
24
+ };
25
+ [TabEventType.FORWARD]: void;
26
+ [TabEventType.BACKWARD]: void;
27
+ [TabEventType.REFRESH_IFRAME_POSTMESSAGE]: string;
17
28
  }
18
- export default plugin;
29
+ export declare const tabEmitterKey: InjectionKey<Emitter<TabEventPayloadMap>>;
30
+ /** 获取标签事件总线,用于组件间通信 */
31
+ export declare const useTabEmitter: () => Emitter<TabEventPayloadMap>;
@@ -1,96 +1,37 @@
1
- import { ITabData, ITabItem, ITabPage } from '../model/TabModel';
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
- id: string;
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
- toJSON: () => ITabPage[];
24
- toString: () => string;
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
- toJSON: () => ITabPage[];
44
- toString: () => string;
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: (n: number) => void;
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>;
57
18
  getCacheName: () => string;
58
19
  destroy: () => void;
59
20
  reset: () => void;
60
21
  addCache: (cacheName: string) => void;
61
22
  removeCache: (cacheName: string) => void;
62
- getTab: (id: string) => {
63
- id: string;
64
- closable: boolean;
65
- refreshable: boolean;
66
- iframe: boolean;
67
- iframeRefreshMode?: import('..').IframeRefreshMode | undefined;
68
- url?: string | undefined;
69
- active: boolean;
70
- pages: {
71
- push: (element: ITabPage) => void;
72
- pop: () => ITabPage | undefined;
73
- peek: () => ITabPage | undefined;
74
- isEmpty: () => boolean;
75
- size: () => number;
76
- clear: () => void;
77
- list: () => ITabPage[];
78
- toJSON: () => ITabPage[];
79
- toString: () => string;
80
- };
81
- title: string;
82
- } | null;
83
- addTab: (tab: ITabItem) => Promise<boolean>;
23
+ getTab: (id: string) => ITabItem | null;
24
+ addTab: (tab: ITabItem) => void;
84
25
  removeTab: (id: string) => string;
85
26
  removeAllTabs: () => void;
86
27
  removeLeftTabs: (id: string) => void;
87
28
  removeRightTabs: (id: string) => void;
88
29
  removeOtherTabs: (id: string) => void;
89
30
  hasTab: (id: string) => boolean;
90
- renewTab: (tab: ITabData) => void;
91
- addPage: (route: RouteLocationNormalizedLoaded, component: VNode) => DefineComponent;
92
- addComponent: (id: string, comp: DefineComponent) => Map<string, DefineComponent<{}, {}, {}, import('vue').ComputedOptions, import('vue').MethodOptions, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>>;
93
- getComponent: (id: string) => DefineComponent<{}, {}, {}, import('vue').ComputedOptions, import('vue').MethodOptions, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{}>>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any> | undefined;
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;
94
35
  removeComponent: (id: string) => boolean;
95
36
  markCacheForEviction: (cacheName: string) => void;
96
37
  evictMarkedCaches: () => void;
@@ -99,8 +40,8 @@ declare const _default: () => {
99
40
  refreshAllTabs: () => void;
100
41
  iframeRefreshKeys: import('vue').Ref<Record<string, number>, Record<string, number>>;
101
42
  addPageScroller: (pageCacheId: string, ...selectorIds: string[]) => void;
102
- setGlobalScroll: (v: boolean) => void;
43
+ setGlobalScroll: (value: boolean) => void;
103
44
  clearSession: () => void;
104
- setSessionPrefix: (p: string) => void;
45
+ setSessionPrefix: (value: string) => void;
105
46
  };
106
47
  export default _default;
@@ -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,2 @@
1
+ /** 将指定的 locale 应用到 vue-stack-tabs 内部 i18n 实例 */
2
+ export declare const applyStackTabsLocale: (changeLocale: (locale: string) => void, locale?: string) => void;
@@ -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 _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
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;
@@ -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?: Record<string, string>;
34
+ query?: LocationQueryRaw;
34
35
  }
35
36
  /** iframe 刷新方式:postMessage 由 iframe 内页自行刷新(不重建 DOM,动画正常);reload 强制重载 iframe */
36
37
  export type IframeRefreshMode = 'postMessage' | 'reload';
@@ -60,63 +61,33 @@ export interface ITabPage {
60
61
  id: string;
61
62
  tabId: string;
62
63
  path: string;
63
- query?: Record<string, string>;
64
+ query?: LocationQueryRaw;
65
+ /** 页面级刷新版本;仅影响当前页面的 keep-alive 缓存 key */
66
+ refreshVersion?: number;
64
67
  /** 该页面从别的页面被后退唤醒时附带的临时闭包参数,不污染 URL */
65
68
  _backParams?: Record<string, unknown>;
66
69
  }
67
- /** 右键菜单项:图标、标题、回调、禁用条件 */
70
+ /** 右键菜单项:重复或动态菜单应提供稳定 key,避免 fallback 标题/图标重复 */
68
71
  export interface IContextMenu {
72
+ key?: string;
69
73
  icon?: string;
70
74
  title: string;
71
75
  callback(id: string): void;
72
76
  disabled: (tabData: ITabBase) => boolean;
73
77
  }
74
- /** 使用 Map 实现的栈结构,用于标签内的 pages 页面栈 */
78
+ /** 数组实现的栈结构,用于标签内的 pages 页面栈 */
75
79
  export declare class Stack<T> {
76
- protected items: Map<number, T>;
80
+ protected items: T[];
77
81
  constructor(items?: T[]);
78
- /**
79
- * @description: 入栈
80
- * @param {T} element 要入栈的元素
81
- */
82
82
  push(element: T): void;
83
- /**
84
- * @description: 出栈
85
- * @return {T} 返回出栈的元素
86
- */
87
83
  pop(): T | undefined;
88
- /**
89
- * @description: 返回栈顶的元素
90
- * @return {T}
91
- */
92
84
  peek(): T | undefined;
93
- /**
94
- * @description: 返回栈是否为空
95
- * @return {Boolean}
96
- */
85
+ at(index: number): T | undefined;
97
86
  isEmpty(): boolean;
98
- /**
99
- * @description: 返回栈里的元素个数
100
- * @return {Number}
101
- */
102
87
  size(): number;
103
- /**
104
- * @description: 清空栈内存
105
- */
106
88
  clear(): void;
107
- /**
108
- * @description: 将栈中的元素转换为数组
109
- * @return {T[]}
110
- */
111
89
  list(): T[];
112
- /**
113
- * @description: 用于控制 JSON.stringify 时的序列化输出
114
- * @return {T[]}
115
- */
90
+ readonlyList(): readonly T[];
116
91
  toJSON(): T[];
117
- /**
118
- * @description: 覆盖Object默认的toString
119
- * @return {String}
120
- */
121
92
  toString(): string;
122
93
  }
@@ -0,0 +1,6 @@
1
+ export interface ModuleOptions {
2
+ /** 默认语言 */
3
+ locale?: string;
4
+ }
5
+ declare const _default: import('nuxt/schema').NuxtModule<ModuleOptions, ModuleOptions, false>;
6
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import('nuxt/app').Plugin<Record<string, unknown>> & import('nuxt/app').ObjectPlugin<Record<string, unknown>>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import('nuxt/app').Plugin<Record<string, unknown>> & import('nuxt/app').ObjectPlugin<Record<string, unknown>>;
2
+ export default _default;
@@ -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?: Record<string, string>;
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
- * 生成页面缓存 ID (CacheName)
17
- * 采用全局唯一的 ULID 确保同一个路由在栈内打开多少次都是绝对隔离的不同实例。
18
- */
19
4
  export declare const createPageId: () => string;
@@ -0,0 +1,2 @@
1
+ /** 类型守卫:判断值是否为非数组的普通对象 */
2
+ export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
@@ -1,9 +1,18 @@
1
+ import { LocationQueryRaw } from 'vue-router';
1
2
  /**
2
- * 判断是否为不可嵌入 iframe 的协议
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 javascript:、data: 等返回 true
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: Record<string, string>;
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;
@@ -1,2 +1,3 @@
1
+ /** 在浏览器控制台输出带样式的库版本标识 */
1
2
  declare const logVersion: (version: string) => void;
2
3
  export default logVersion;