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,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TransitionProps } from 'vue';
|
|
2
2
|
import { TabScrollMode } from '../../model/TabModel';
|
|
3
3
|
type __VLS_Props = {
|
|
4
4
|
space: number;
|
|
@@ -7,92 +7,13 @@ type __VLS_Props = {
|
|
|
7
7
|
contextmenu?: boolean | object;
|
|
8
8
|
max?: number;
|
|
9
9
|
};
|
|
10
|
-
declare
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
};
|
|
16
|
-
refs: {
|
|
17
|
-
scrollContainerRef: ({
|
|
18
|
-
$: import('vue').ComponentInternalInstance;
|
|
19
|
-
$data: {};
|
|
20
|
-
$props: {
|
|
21
|
-
readonly space?: number | undefined;
|
|
22
|
-
readonly isScrollWheel?: boolean | undefined;
|
|
23
|
-
readonly isScrollButton?: boolean | undefined;
|
|
24
|
-
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps;
|
|
25
|
-
$attrs: {
|
|
26
|
-
[x: string]: unknown;
|
|
27
|
-
};
|
|
28
|
-
$refs: {
|
|
29
|
-
[x: string]: unknown;
|
|
30
|
-
} & {
|
|
31
|
-
headerScroll: HTMLDivElement;
|
|
32
|
-
container: HTMLDivElement;
|
|
33
|
-
bar: HTMLDivElement;
|
|
34
|
-
thumb: HTMLDivElement;
|
|
35
|
-
};
|
|
36
|
-
$slots: Readonly<{
|
|
37
|
-
[name: string]: import('vue').Slot<any> | undefined;
|
|
38
|
-
}>;
|
|
39
|
-
$root: import('vue').ComponentPublicInstance | null;
|
|
40
|
-
$parent: import('vue').ComponentPublicInstance | null;
|
|
41
|
-
$host: Element | null;
|
|
42
|
-
$emit: (event: string, ...args: any[]) => void;
|
|
43
|
-
$el: any;
|
|
44
|
-
$options: import('vue').ComponentOptionsBase<Readonly<{
|
|
45
|
-
space?: number;
|
|
46
|
-
isScrollWheel?: boolean;
|
|
47
|
-
isScrollButton?: boolean;
|
|
48
|
-
}> & Readonly<{}>, {
|
|
49
|
-
scrollIntoView: (el: HTMLElement) => void;
|
|
50
|
-
isInView: (el: HTMLElement) => boolean;
|
|
51
|
-
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, {
|
|
52
|
-
space: number;
|
|
53
|
-
isScrollWheel: boolean;
|
|
54
|
-
isScrollButton: boolean;
|
|
55
|
-
}, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & {
|
|
56
|
-
beforeCreate?: (() => void) | (() => void)[];
|
|
57
|
-
created?: (() => void) | (() => void)[];
|
|
58
|
-
beforeMount?: (() => void) | (() => void)[];
|
|
59
|
-
mounted?: (() => void) | (() => void)[];
|
|
60
|
-
beforeUpdate?: (() => void) | (() => void)[];
|
|
61
|
-
updated?: (() => void) | (() => void)[];
|
|
62
|
-
activated?: (() => void) | (() => void)[];
|
|
63
|
-
deactivated?: (() => void) | (() => void)[];
|
|
64
|
-
beforeDestroy?: (() => void) | (() => void)[];
|
|
65
|
-
beforeUnmount?: (() => void) | (() => void)[];
|
|
66
|
-
destroyed?: (() => void) | (() => void)[];
|
|
67
|
-
unmounted?: (() => void) | (() => void)[];
|
|
68
|
-
renderTracked?: ((e: import('vue').DebuggerEvent) => void) | ((e: import('vue').DebuggerEvent) => void)[];
|
|
69
|
-
renderTriggered?: ((e: import('vue').DebuggerEvent) => void) | ((e: import('vue').DebuggerEvent) => void)[];
|
|
70
|
-
errorCaptured?: ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void) | ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void)[];
|
|
71
|
-
};
|
|
72
|
-
$forceUpdate: () => void;
|
|
73
|
-
$nextTick: typeof nextTick;
|
|
74
|
-
$watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (...args: [R, R, import('@vue/reactivity').OnCleanup]) => any : (...args: [any, any, import('@vue/reactivity').OnCleanup]) => any, options?: import('vue').WatchOptions): import('vue').WatchStopHandle;
|
|
75
|
-
} & Readonly<{
|
|
76
|
-
space: number;
|
|
77
|
-
isScrollWheel: boolean;
|
|
78
|
-
isScrollButton: boolean;
|
|
79
|
-
}> & Omit<Readonly<{
|
|
80
|
-
space?: number;
|
|
81
|
-
isScrollWheel?: boolean;
|
|
82
|
-
isScrollButton?: boolean;
|
|
83
|
-
}> & Readonly<{}>, "scrollIntoView" | "isInView" | ("space" | "isScrollWheel" | "isScrollButton")> & import('vue').ShallowUnwrapRef<{
|
|
84
|
-
scrollIntoView: (el: HTMLElement) => void;
|
|
85
|
-
isInView: (el: HTMLElement) => boolean;
|
|
86
|
-
}> & {} & import('vue').ComponentCustomProperties & {} & {
|
|
87
|
-
$slots: {
|
|
88
|
-
default?(_: {}): any;
|
|
89
|
-
};
|
|
90
|
-
}) | null;
|
|
91
|
-
};
|
|
92
|
-
rootEl: HTMLDivElement;
|
|
10
|
+
declare var __VLS_1: {}, __VLS_30: {};
|
|
11
|
+
type __VLS_Slots = {} & {
|
|
12
|
+
leftButton?: (props: typeof __VLS_1) => any;
|
|
13
|
+
} & {
|
|
14
|
+
rightButton?: (props: typeof __VLS_30) => any;
|
|
93
15
|
};
|
|
94
|
-
|
|
95
|
-
declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
16
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
96
17
|
active: (...args: any[]) => void;
|
|
97
18
|
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
98
19
|
onActive?: ((...args: any[]) => any) | undefined;
|
|
@@ -101,85 +22,11 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
|
|
|
101
22
|
contextmenu: boolean | object;
|
|
102
23
|
tabScrollMode: TabScrollMode;
|
|
103
24
|
tabTransition: string | TransitionProps;
|
|
104
|
-
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
$data: {};
|
|
108
|
-
$props: {
|
|
109
|
-
readonly space?: number | undefined;
|
|
110
|
-
readonly isScrollWheel?: boolean | undefined;
|
|
111
|
-
readonly isScrollButton?: boolean | undefined;
|
|
112
|
-
} & import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps;
|
|
113
|
-
$attrs: {
|
|
114
|
-
[x: string]: unknown;
|
|
115
|
-
};
|
|
116
|
-
$refs: {
|
|
117
|
-
[x: string]: unknown;
|
|
118
|
-
} & {
|
|
119
|
-
headerScroll: HTMLDivElement;
|
|
120
|
-
container: HTMLDivElement;
|
|
121
|
-
bar: HTMLDivElement;
|
|
122
|
-
thumb: HTMLDivElement;
|
|
123
|
-
};
|
|
124
|
-
$slots: Readonly<{
|
|
125
|
-
[name: string]: import('vue').Slot<any> | undefined;
|
|
126
|
-
}>;
|
|
127
|
-
$root: import('vue').ComponentPublicInstance | null;
|
|
128
|
-
$parent: import('vue').ComponentPublicInstance | null;
|
|
129
|
-
$host: Element | null;
|
|
130
|
-
$emit: (event: string, ...args: any[]) => void;
|
|
131
|
-
$el: any;
|
|
132
|
-
$options: import('vue').ComponentOptionsBase<Readonly<{
|
|
133
|
-
space?: number;
|
|
134
|
-
isScrollWheel?: boolean;
|
|
135
|
-
isScrollButton?: boolean;
|
|
136
|
-
}> & Readonly<{}>, {
|
|
137
|
-
scrollIntoView: (el: HTMLElement) => void;
|
|
138
|
-
isInView: (el: HTMLElement) => boolean;
|
|
139
|
-
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, {
|
|
140
|
-
space: number;
|
|
141
|
-
isScrollWheel: boolean;
|
|
142
|
-
isScrollButton: boolean;
|
|
143
|
-
}, {}, string, {}, import('vue').GlobalComponents, import('vue').GlobalDirectives, string, import('vue').ComponentProvideOptions> & {
|
|
144
|
-
beforeCreate?: (() => void) | (() => void)[];
|
|
145
|
-
created?: (() => void) | (() => void)[];
|
|
146
|
-
beforeMount?: (() => void) | (() => void)[];
|
|
147
|
-
mounted?: (() => void) | (() => void)[];
|
|
148
|
-
beforeUpdate?: (() => void) | (() => void)[];
|
|
149
|
-
updated?: (() => void) | (() => void)[];
|
|
150
|
-
activated?: (() => void) | (() => void)[];
|
|
151
|
-
deactivated?: (() => void) | (() => void)[];
|
|
152
|
-
beforeDestroy?: (() => void) | (() => void)[];
|
|
153
|
-
beforeUnmount?: (() => void) | (() => void)[];
|
|
154
|
-
destroyed?: (() => void) | (() => void)[];
|
|
155
|
-
unmounted?: (() => void) | (() => void)[];
|
|
156
|
-
renderTracked?: ((e: import('vue').DebuggerEvent) => void) | ((e: import('vue').DebuggerEvent) => void)[];
|
|
157
|
-
renderTriggered?: ((e: import('vue').DebuggerEvent) => void) | ((e: import('vue').DebuggerEvent) => void)[];
|
|
158
|
-
errorCaptured?: ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void) | ((err: unknown, instance: import('vue').ComponentPublicInstance | null, info: string) => boolean | void)[];
|
|
159
|
-
};
|
|
160
|
-
$forceUpdate: () => void;
|
|
161
|
-
$nextTick: typeof nextTick;
|
|
162
|
-
$watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (...args: [R, R, import('@vue/reactivity').OnCleanup]) => any : (...args: [any, any, import('@vue/reactivity').OnCleanup]) => any, options?: import('vue').WatchOptions): import('vue').WatchStopHandle;
|
|
163
|
-
} & Readonly<{
|
|
164
|
-
space: number;
|
|
165
|
-
isScrollWheel: boolean;
|
|
166
|
-
isScrollButton: boolean;
|
|
167
|
-
}> & Omit<Readonly<{
|
|
168
|
-
space?: number;
|
|
169
|
-
isScrollWheel?: boolean;
|
|
170
|
-
isScrollButton?: boolean;
|
|
171
|
-
}> & Readonly<{}>, "scrollIntoView" | "isInView" | ("space" | "isScrollWheel" | "isScrollButton")> & import('vue').ShallowUnwrapRef<{
|
|
172
|
-
scrollIntoView: (el: HTMLElement) => void;
|
|
173
|
-
isInView: (el: HTMLElement) => boolean;
|
|
174
|
-
}> & {} & import('vue').ComponentCustomProperties & {} & {
|
|
175
|
-
$slots: {
|
|
176
|
-
default?(_: {}): any;
|
|
177
|
-
};
|
|
178
|
-
}) | null;
|
|
179
|
-
}, HTMLDivElement>;
|
|
180
|
-
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
25
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
26
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
27
|
+
declare const _default: typeof __VLS_export;
|
|
181
28
|
export default _default;
|
|
182
|
-
type
|
|
29
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
183
30
|
new (): {
|
|
184
31
|
$slots: S;
|
|
185
32
|
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { App, DefineComponent, InjectionKey, Ref, ShallowRef } from 'vue';
|
|
2
|
+
import { Emitter } from 'mitt';
|
|
3
|
+
import { ITabItem } from '../model/TabModel';
|
|
4
|
+
import { TabEventPayloadMap } from './useTabEventBus';
|
|
5
|
+
import { ScrollPosition } from './tabPanel/state';
|
|
6
|
+
export declare const STACK_TABS_CONTEXT_UNAVAILABLE_MESSAGE = "VueStackTabs runtime context is not available. Render <VueStackTabs> before using vue-stack-tabs composables.";
|
|
7
|
+
export declare const STACK_TABS_DUPLICATE_INSTANCE_MESSAGE = "VueStackTabs only supports one <VueStackTabs> instance per Vue app.";
|
|
8
|
+
export interface StackTabsRuntimeContext {
|
|
9
|
+
tabs: Ref<ITabItem[]>;
|
|
10
|
+
defaultTabs: Ref<ITabItem[]>;
|
|
11
|
+
caches: ShallowRef<string[]>;
|
|
12
|
+
components: Map<string, DefineComponent>;
|
|
13
|
+
cacheIdsToEvict: Set<string>;
|
|
14
|
+
tabIdsToEvict: Set<string>;
|
|
15
|
+
refreshKey: Ref<number>;
|
|
16
|
+
scrollPositionsByPageId: Map<string, Map<string, ScrollPosition>>;
|
|
17
|
+
isInitialized: Ref<boolean>;
|
|
18
|
+
iframeRefreshKeys: Ref<Record<string, number>>;
|
|
19
|
+
maxTabCount: Ref<number>;
|
|
20
|
+
useGlobalScroll: Ref<boolean>;
|
|
21
|
+
sessionPrefix: Ref<string>;
|
|
22
|
+
iframePath: Ref<string>;
|
|
23
|
+
eventBus: Emitter<TabEventPayloadMap>;
|
|
24
|
+
}
|
|
25
|
+
export interface CreateStackTabsRuntimeContextOptions {
|
|
26
|
+
iframePath?: string;
|
|
27
|
+
maxTabCount?: number;
|
|
28
|
+
useGlobalScroll?: boolean;
|
|
29
|
+
sessionPrefix?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface RegisterStackTabsRuntimeContextOptions {
|
|
32
|
+
app?: App;
|
|
33
|
+
isProduction?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface UnregisterStackTabsRuntimeContextOptions {
|
|
36
|
+
app?: App;
|
|
37
|
+
}
|
|
38
|
+
export declare const stackTabsContextKey: InjectionKey<StackTabsRuntimeContext>;
|
|
39
|
+
export declare const maximumKey: InjectionKey<Ref<boolean>>;
|
|
40
|
+
/** 创建一个新的运行时上下文实例 */
|
|
41
|
+
export declare const createStackTabsRuntimeContext: (options?: CreateStackTabsRuntimeContextOptions) => StackTabsRuntimeContext;
|
|
42
|
+
/** 获取当前活跃的运行时上下文(模块级单例) */
|
|
43
|
+
export declare const getActiveStackTabsRuntimeContext: () => StackTabsRuntimeContext | null;
|
|
44
|
+
/** 注册运行时上下文,重复注册会在开发环境抛出错误 */
|
|
45
|
+
export declare const registerStackTabsRuntimeContext: (context: StackTabsRuntimeContext, options?: RegisterStackTabsRuntimeContextOptions) => boolean;
|
|
46
|
+
/** 注销运行时上下文,组件卸载时调用 */
|
|
47
|
+
export declare const unregisterStackTabsRuntimeContext: (context: StackTabsRuntimeContext, options?: UnregisterStackTabsRuntimeContextOptions) => void;
|
|
48
|
+
/** 解析当前可用的运行时上下文,优先使用 inject,回退到模块单例 */
|
|
49
|
+
export declare const resolveStackTabsRuntimeContext: () => StackTabsRuntimeContext;
|
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
import { ITabPage } from '../../model/TabModel';
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}) => void;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
export declare const
|
|
23
|
-
/** 执行所有待驱逐缓存的驱逐 */
|
|
24
|
-
export declare const evictMarkedCaches: () => void;
|
|
2
|
+
import { StackTabsRuntimeContext } from '../stackTabsContext';
|
|
3
|
+
export interface TabPanelEvictionApi {
|
|
4
|
+
markCacheForEviction: (cacheName: string) => void;
|
|
5
|
+
markTabPagesForEviction: (tab: {
|
|
6
|
+
id: string;
|
|
7
|
+
pages: {
|
|
8
|
+
list(): ITabPage[];
|
|
9
|
+
};
|
|
10
|
+
}) => void;
|
|
11
|
+
markTabPagesForEvictionOnly: (tab: {
|
|
12
|
+
pages: {
|
|
13
|
+
list(): ITabPage[];
|
|
14
|
+
};
|
|
15
|
+
}) => void;
|
|
16
|
+
addCache: (cacheName: string) => void;
|
|
17
|
+
removeCache: (cacheName: string) => void;
|
|
18
|
+
evictPageCache: (cacheName: string) => void;
|
|
19
|
+
replacePageCaches: (cacheNamesToEvict: Iterable<string>, cacheNamesToAdd: Iterable<string>) => void;
|
|
20
|
+
evictMarkedCaches: () => void;
|
|
21
|
+
}
|
|
22
|
+
export declare const createTabPanelEviction: (context: StackTabsRuntimeContext) => TabPanelEvictionApi;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 导航事务管理器。
|
|
3
|
+
*
|
|
4
|
+
* 将「乐观 UI 更新 → 路由导航 → 确认/回滚」包装为原子事务:
|
|
5
|
+
* 1. apply() — 先对 UI 状态做乐观修改,返回快照
|
|
6
|
+
* 2. navigate() — 执行 router.push 等异步导航
|
|
7
|
+
* 3. 成功 → commit();失败/异常 → rollback(snapshot) 恢复快照
|
|
8
|
+
*
|
|
9
|
+
* 当连续快速操作导致事务过期时(isCurrent 返回 false),
|
|
10
|
+
* 不回滚而是调用 cleanupStale() 清理残留状态,避免覆盖新事务的结果。
|
|
11
|
+
*/
|
|
12
|
+
interface NavigationTransactionOptions<TSnapshot, TResult> {
|
|
13
|
+
/** 乐观应用 UI 变更,返回可用于 rollback 的快照 */
|
|
14
|
+
apply: () => TSnapshot;
|
|
15
|
+
/** 执行异步路由导航 */
|
|
16
|
+
navigate: () => Promise<TResult>;
|
|
17
|
+
/** 导航失败时回滚到快照状态 */
|
|
18
|
+
rollback: (snapshot: TSnapshot) => void;
|
|
19
|
+
/** 导航成功后的确认回调(如驱逐旧缓存) */
|
|
20
|
+
commit?: () => void;
|
|
21
|
+
/** 判断导航结果是否为失败(如 vue-router 返回的 NavigationFailure) */
|
|
22
|
+
isFailureResult?: (result: TResult) => boolean;
|
|
23
|
+
/** 若为失败结果,是否将其作为异常抛出 */
|
|
24
|
+
rejectFailureResult?: boolean;
|
|
25
|
+
/** 检查当前事务是否仍然有效(防止过期事务覆盖新状态) */
|
|
26
|
+
isCurrent?: () => boolean;
|
|
27
|
+
/** 事务已过期时的清理回调(替代 rollback) */
|
|
28
|
+
cleanupStale?: () => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 执行一次导航事务:apply → navigate → commit/rollback。
|
|
32
|
+
* 保证乐观更新在导航失败时能安全回滚。
|
|
33
|
+
*/
|
|
34
|
+
export declare const runNavigationTransaction: <TSnapshot, TResult>(options: NavigationTransactionOptions<TSnapshot, TResult>) => Promise<TResult>;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Ref } from 'vue';
|
|
2
|
+
import { ITabItem } from '../../model/TabModel';
|
|
3
|
+
export interface TabPanelRefreshApi {
|
|
4
|
+
refreshTab: (id: string) => void;
|
|
5
|
+
refreshAllTabs: () => void;
|
|
6
|
+
}
|
|
7
|
+
export interface CreateTabPanelRefreshOptions {
|
|
8
|
+
tabs: Ref<ITabItem[]>;
|
|
9
|
+
iframeRefreshKeys: Ref<Record<string, number>>;
|
|
10
|
+
getTab: (id: string) => ITabItem | null;
|
|
11
|
+
createPageId: () => string;
|
|
12
|
+
addCache: (cacheName: string) => void;
|
|
13
|
+
evictPageCache: (cacheName: string) => void;
|
|
14
|
+
replacePageCaches: (cacheNamesToEvict: Iterable<string>, cacheNamesToAdd: Iterable<string>) => void;
|
|
15
|
+
refreshIframeByPostMessage: (tabId: string) => void;
|
|
16
|
+
}
|
|
17
|
+
export declare const createTabPanelRefresh: (options: CreateTabPanelRefreshOptions) => TabPanelRefreshApi;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export declare const
|
|
1
|
+
import { StackTabsRuntimeContext } from '../stackTabsContext';
|
|
2
|
+
export interface TabPanelScrollApi {
|
|
3
|
+
restoreScroller: (pageCacheId: string) => void;
|
|
4
|
+
saveScroller: (pageCacheId: string) => void;
|
|
5
|
+
removeScroller: (pageCacheId: string) => void;
|
|
6
|
+
addPageScroller: (pageCacheId: string, ...selectorIds: string[]) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare const createTabPanelScroll: (context: StackTabsRuntimeContext) => TabPanelScrollApi;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ITabItem } from '../../model/TabModel';
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
import { StackTabsRuntimeContext } from '../stackTabsContext';
|
|
3
|
+
export interface TabPanelSessionApi {
|
|
4
|
+
getSessionKey: () => string;
|
|
5
|
+
saveActiveTabToSession: (tab: ITabItem) => void;
|
|
6
|
+
clearSession: () => void;
|
|
7
|
+
restoreActiveTabSession: (storedJson: string | null) => void;
|
|
8
|
+
restoreTabFromSession: (storedJson: string | null) => ITabItem | null;
|
|
9
|
+
}
|
|
10
|
+
export declare const createTabPanelSession: (context: StackTabsRuntimeContext) => TabPanelSessionApi;
|
|
@@ -1,77 +1,24 @@
|
|
|
1
|
+
import { DefineComponent, Ref, ShallowRef } from 'vue';
|
|
1
2
|
import { ITabItem } from '../../model/TabModel';
|
|
2
|
-
|
|
3
|
-
export declare const tabs: import('vue').Ref<{
|
|
4
|
-
id: string;
|
|
5
|
-
closable: boolean;
|
|
6
|
-
refreshable: boolean;
|
|
7
|
-
iframe: boolean;
|
|
8
|
-
iframeRefreshMode?: import('../..').IframeRefreshMode | undefined;
|
|
9
|
-
url?: string | undefined;
|
|
10
|
-
active: boolean;
|
|
11
|
-
pages: {
|
|
12
|
-
push: (element: import('../..').ITabPage) => void;
|
|
13
|
-
pop: () => import('../..').ITabPage | undefined;
|
|
14
|
-
peek: () => import('../..').ITabPage | undefined;
|
|
15
|
-
isEmpty: () => boolean;
|
|
16
|
-
size: () => number;
|
|
17
|
-
clear: () => void;
|
|
18
|
-
list: () => import('../..').ITabPage[];
|
|
19
|
-
toString: () => string;
|
|
20
|
-
toJSON: () => import('../..').ITabPage[];
|
|
21
|
-
};
|
|
22
|
-
title: string;
|
|
23
|
-
}[], ITabItem[] | {
|
|
24
|
-
id: string;
|
|
25
|
-
closable: boolean;
|
|
26
|
-
refreshable: boolean;
|
|
27
|
-
iframe: boolean;
|
|
28
|
-
iframeRefreshMode?: import('../..').IframeRefreshMode | undefined;
|
|
29
|
-
url?: string | undefined;
|
|
30
|
-
active: boolean;
|
|
31
|
-
pages: {
|
|
32
|
-
push: (element: import('../..').ITabPage) => void;
|
|
33
|
-
pop: () => import('../..').ITabPage | undefined;
|
|
34
|
-
peek: () => import('../..').ITabPage | undefined;
|
|
35
|
-
isEmpty: () => boolean;
|
|
36
|
-
size: () => number;
|
|
37
|
-
clear: () => void;
|
|
38
|
-
list: () => import('../..').ITabPage[];
|
|
39
|
-
toString: () => string;
|
|
40
|
-
toJSON: () => import('../..').ITabPage[];
|
|
41
|
-
};
|
|
42
|
-
title: string;
|
|
43
|
-
}[]>;
|
|
44
|
-
/** 初始化时传入的默认标签(用于对比 session 恢复) */
|
|
45
|
-
export declare const defaultTabs: ITabItem[];
|
|
46
|
-
/** keep-alive include 数组,与 Vue 的 keep-alive :include 绑定 */
|
|
47
|
-
export declare const caches: import('vue').Ref<string[], string[]>;
|
|
48
|
-
/** 页面缓存 ID -> 包装后的 DefineComponent */
|
|
49
|
-
export declare const components: Map<string, import('vue').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>>;
|
|
50
|
-
/** 待驱逐的页面缓存 ID 集合 */
|
|
51
|
-
export declare const cacheIdsToEvict: Set<string>;
|
|
52
|
-
/** 待驱逐的标签 ID 集合 */
|
|
53
|
-
export declare const tabIdsToEvict: Set<string>;
|
|
54
|
-
/** 刷新计数器,变更时触发 component :key 变化 */
|
|
55
|
-
export declare const refreshKey: import('vue').Ref<number, number>;
|
|
56
|
-
/** 刷新时临时加入 keep-alive exclude 的缓存 ID */
|
|
57
|
-
export declare const excludedCacheIdsForRefresh: import('vue').Ref<string[], string[]>;
|
|
58
|
-
/** pageCacheId -> Map<selector, { top, left }> 滚动位置存储 */
|
|
59
|
-
export declare const scrollPositionsByPageId: Map<string, Map<string, {
|
|
3
|
+
export interface ScrollPosition {
|
|
60
4
|
top: number;
|
|
61
5
|
left: number;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
6
|
+
}
|
|
7
|
+
export interface TabPanelRuntimeState {
|
|
8
|
+
tabs: Ref<ITabItem[]>;
|
|
9
|
+
defaultTabs: Ref<ITabItem[]>;
|
|
10
|
+
caches: ShallowRef<string[]>;
|
|
11
|
+
components: Map<string, DefineComponent>;
|
|
12
|
+
cacheIdsToEvict: Set<string>;
|
|
13
|
+
tabIdsToEvict: Set<string>;
|
|
14
|
+
refreshKey: Ref<number>;
|
|
15
|
+
scrollPositionsByPageId: Map<string, Map<string, ScrollPosition>>;
|
|
16
|
+
isInitialized: Ref<boolean>;
|
|
17
|
+
iframeRefreshKeys: Ref<Record<string, number>>;
|
|
18
|
+
maxTabCount: Ref<number>;
|
|
19
|
+
useGlobalScroll: Ref<boolean>;
|
|
20
|
+
sessionPrefix: Ref<string>;
|
|
21
|
+
}
|
|
22
|
+
/** sessionStorage 中存储当前激活标签的 key 后缀 */
|
|
66
23
|
export declare const SESSION_TAB_NAME = "stacktab-active-tab";
|
|
67
|
-
|
|
68
|
-
export declare const iframeRefreshKeys: import('vue').Ref<Record<string, number>, Record<string, number>>;
|
|
69
|
-
/** 最大标签数量,0 表示不限制 */
|
|
70
|
-
export declare let maxTabCount: number;
|
|
71
|
-
/** 是否使用页面级滚动 */
|
|
72
|
-
export declare let useGlobalScroll: boolean;
|
|
73
|
-
/** sessionStorage key 前缀 */
|
|
74
|
-
export declare let sessionPrefix: string;
|
|
75
|
-
export declare const setMaxTabCount: (n: number) => void;
|
|
76
|
-
export declare const setUseGlobalScroll: (v: boolean) => void;
|
|
77
|
-
export declare const setSessionPrefix: (p: string) => void;
|
|
24
|
+
export declare const createTabPanelRuntimeState: () => TabPanelRuntimeState;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Ref } from 'vue';
|
|
2
|
+
import { ITabData, ITabItem } from '../model/TabModel';
|
|
3
|
+
type IframeLoadStatus = 'idle' | 'loading' | 'loaded' | 'timeout';
|
|
4
|
+
interface IframeLoadState {
|
|
5
|
+
status: IframeLoadStatus;
|
|
6
|
+
message?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface UseIframeManagerOptions {
|
|
9
|
+
tabs: Ref<ITabItem[]>;
|
|
10
|
+
iframeRefreshKeys: Ref<Record<string, number>>;
|
|
11
|
+
iframeLoadTimeout: number;
|
|
12
|
+
t: (key: string) => string;
|
|
13
|
+
}
|
|
14
|
+
export declare function useIframeManager(options: UseIframeManagerOptions): {
|
|
15
|
+
iframeTabs: import('vue').ComputedRef<ITabItem[]>;
|
|
16
|
+
activeNonIframeTab: import('vue').ComputedRef<ITabItem | undefined>;
|
|
17
|
+
hasActiveNonIframeTab: import('vue').ComputedRef<boolean>;
|
|
18
|
+
iframeSrcMap: import('vue').ComputedRef<Record<string, string>>;
|
|
19
|
+
getIframeRefreshKey: (frameId: string) => number;
|
|
20
|
+
getIframeKey: (frame: {
|
|
21
|
+
id: string;
|
|
22
|
+
}) => string;
|
|
23
|
+
getIframeLoadState: (frameId: string) => IframeLoadState;
|
|
24
|
+
shouldShowIframeLoading: (frameId: string) => boolean;
|
|
25
|
+
shouldShowIframeError: (frameId: string) => boolean;
|
|
26
|
+
retryIframe: (frameId: string) => void;
|
|
27
|
+
setIframeRef: (id: string, el: HTMLIFrameElement | null) => void;
|
|
28
|
+
handleIframeLoad: (frame: {
|
|
29
|
+
id: string;
|
|
30
|
+
url?: string;
|
|
31
|
+
}, event: Event) => void;
|
|
32
|
+
handleRefreshIframePostMessage: (tabId: string) => void;
|
|
33
|
+
createMessageHandler: (allowedOrigins: Ref<string[]>, openTab: (tab: ITabData) => Promise<string | undefined>) => (ev: MessageEvent) => void;
|
|
34
|
+
};
|
|
35
|
+
export {};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ITabData, IframeRefreshMode } from '../model/TabModel';
|
|
1
|
+
import { ITabData } from '../model/TabModel';
|
|
3
2
|
/**
|
|
4
3
|
* useTabActions - 标签操作对外 Hook
|
|
5
4
|
*
|
|
@@ -14,55 +13,15 @@ import { ITabData, IframeRefreshMode } from '../model/TabModel';
|
|
|
14
13
|
* - reset() 重置(关闭所有)
|
|
15
14
|
*/
|
|
16
15
|
export default function useTabActions(): {
|
|
17
|
-
openTab:
|
|
16
|
+
openTab: (tab: ITabData, renew?: boolean) => Promise<string | undefined>;
|
|
18
17
|
closeTab: (id: string) => string;
|
|
19
18
|
closeAllTabs: () => void;
|
|
20
19
|
refreshTab: (id: string) => void;
|
|
21
20
|
refreshAllTabs: () => void;
|
|
22
|
-
activeTab: (id: string, route?: boolean) => void
|
|
21
|
+
activeTab: (id: string, route?: boolean) => Promise<void | import('vue-router').NavigationFailure | undefined>;
|
|
23
22
|
reset: () => void;
|
|
24
|
-
tabs: import('vue').Ref<
|
|
25
|
-
id: string;
|
|
26
|
-
closable: boolean;
|
|
27
|
-
refreshable: boolean;
|
|
28
|
-
iframe: boolean;
|
|
29
|
-
iframeRefreshMode?: IframeRefreshMode | undefined;
|
|
30
|
-
url?: string | undefined;
|
|
31
|
-
active: boolean;
|
|
32
|
-
pages: {
|
|
33
|
-
push: (element: import('..').ITabPage) => void;
|
|
34
|
-
pop: () => import('..').ITabPage | undefined;
|
|
35
|
-
peek: () => import('..').ITabPage | undefined;
|
|
36
|
-
isEmpty: () => boolean;
|
|
37
|
-
size: () => number;
|
|
38
|
-
clear: () => void;
|
|
39
|
-
list: () => import('..').ITabPage[];
|
|
40
|
-
toString: () => string;
|
|
41
|
-
toJSON: () => import('..').ITabPage[];
|
|
42
|
-
};
|
|
43
|
-
title: string;
|
|
44
|
-
}[], import('..').ITabItem[] | {
|
|
45
|
-
id: string;
|
|
46
|
-
closable: boolean;
|
|
47
|
-
refreshable: boolean;
|
|
48
|
-
iframe: boolean;
|
|
49
|
-
iframeRefreshMode?: IframeRefreshMode | undefined;
|
|
50
|
-
url?: string | undefined;
|
|
51
|
-
active: boolean;
|
|
52
|
-
pages: {
|
|
53
|
-
push: (element: import('..').ITabPage) => void;
|
|
54
|
-
pop: () => import('..').ITabPage | undefined;
|
|
55
|
-
peek: () => import('..').ITabPage | undefined;
|
|
56
|
-
isEmpty: () => boolean;
|
|
57
|
-
size: () => number;
|
|
58
|
-
clear: () => void;
|
|
59
|
-
list: () => import('..').ITabPage[];
|
|
60
|
-
toString: () => string;
|
|
61
|
-
toJSON: () => import('..').ITabPage[];
|
|
62
|
-
};
|
|
63
|
-
title: string;
|
|
64
|
-
}[]>;
|
|
23
|
+
tabs: import('vue').Ref<import('..').ITabItem[], import('..').ITabItem[]>;
|
|
65
24
|
setIFramePath: (path: string) => void;
|
|
66
|
-
getWrapper: () => Element
|
|
25
|
+
getWrapper: () => Element;
|
|
67
26
|
openInNewWindow: (id: string) => void;
|
|
68
27
|
};
|
|
@@ -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<
|
|
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
|
|
29
|
+
export declare const tabEmitterKey: InjectionKey<Emitter<TabEventPayloadMap>>;
|
|
30
|
+
/** 获取标签事件总线,用于组件间通信 */
|
|
31
|
+
export declare const useTabEmitter: () => Emitter<TabEventPayloadMap>;
|