vue-stack-tabs 1.3.1 → 1.4.2
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 +119 -52
- package/README.md +103 -42
- package/README.ru.md +125 -54
- package/dist/{src/lib/StackTabs.vue.d.ts → StackTabs.vue.d.ts} +5 -5
- package/dist/{src/lib/components → components}/ContextMenu/index.vue.d.ts +1 -1
- package/dist/components/StackKeepAlive/emptyPlaceholder.d.ts +3 -0
- package/dist/{src/lib/components → components}/TabHeader/TabHeaderItem.vue.d.ts +9 -0
- package/dist/{src/lib/components → components}/TabHeader/index.vue.d.ts +3 -3
- package/dist/{src/lib/hooks → hooks}/stackTabsContext.d.ts +5 -2
- package/dist/hooks/tabPanel/pageComponentFactory.d.ts +23 -0
- package/dist/{src/lib/hooks → hooks}/tabPanel/refresh.d.ts +6 -3
- package/dist/{src/lib/hooks → hooks}/tabPanel/scroll.d.ts +2 -0
- package/dist/hooks/tabPanel/tabStore.d.ts +69 -0
- package/dist/hooks/useScrollShadow.d.ts +20 -0
- package/dist/{src/lib/hooks → hooks}/useTabActions.d.ts +7 -2
- package/dist/{src/lib/hooks → hooks}/useTabEventBus.d.ts +2 -1
- package/dist/{src/lib/hooks → hooks}/useTabPanel.d.ts +16 -4
- package/dist/iframe-bridge.mjs +1 -1
- package/dist/index.d.ts +22 -6
- package/dist/{src/lib/model → model}/TabModel.d.ts +21 -0
- package/dist/nuxt/module.mjs +10 -6
- package/dist/nuxt/runtime/plugin.mjs +1600 -4
- package/dist/style.css +1 -1
- package/dist/utils/iframeBridge.d.ts +7 -1
- package/dist/{src/lib/utils → utils}/scrollUtils.d.ts +7 -1
- package/dist/{src/lib/versionLogger.d.ts → versionLogger.d.ts} +1 -1
- package/dist/vue-stack-tabs.css +1 -1
- package/dist/vue-stack-tabs.es.js +1 -1
- package/package.json +64 -40
- package/src/lib/StackTabs.vue +16 -3
- package/src/lib/assets/style/common/var.scss +2 -0
- package/src/lib/assets/style/stackTab.scss +17 -3
- package/src/lib/components/ContextMenu/index.vue +12 -3
- package/src/lib/components/PageLoading.vue +10 -2
- package/src/lib/components/StackKeepAlive/StackCacheRenderer.vue +3 -9
- package/src/lib/components/StackKeepAlive/emptyPlaceholder.tsx +18 -0
- package/src/lib/components/TabHeader/index.vue +4 -3
- package/src/lib/hooks/stackTabsContext.ts +23 -18
- package/src/lib/hooks/tabPanel/pageComponentFactory.tsx +136 -0
- package/src/lib/hooks/tabPanel/refresh.ts +20 -13
- package/src/lib/hooks/tabPanel/scroll.ts +110 -7
- package/src/lib/hooks/tabPanel/session.ts +29 -3
- package/src/lib/hooks/tabPanel/tabStore.ts +595 -0
- package/src/lib/hooks/useContextMenu.ts +57 -11
- package/src/lib/hooks/useIframeManager.ts +18 -2
- package/src/lib/hooks/useScrollShadow.ts +124 -0
- package/src/lib/hooks/useTabActions.ts +18 -8
- package/src/lib/hooks/useTabEventBus.ts +5 -3
- package/src/lib/hooks/useTabPanel.tsx +183 -302
- package/src/lib/hooks/useTabRouter.ts +42 -38
- package/src/lib/i18n/index.ts +3 -3
- package/src/lib/model/TabModel.ts +40 -1
- package/src/lib/nuxt/module.ts +10 -3
- package/src/lib/nuxt/runtime/plugin.ts +13 -2
- package/src/lib/utils/iframeBridge.ts +9 -1
- package/src/lib/utils/scrollUtils.ts +35 -2
- package/src/lib/utils/tabInfoEncoder.ts +21 -8
- package/src/lib/utils/urlParser.ts +3 -1
- package/src/lib/versionLogger.ts +6 -2
- package/dist/favicon.svg +0 -10
- package/dist/iframe-bridge.html +0 -77
- package/dist/iframe-child.html +0 -88
- package/dist/nuxt/favicon.svg +0 -10
- package/dist/nuxt/iframe-bridge.html +0 -77
- package/dist/nuxt/iframe-child.html +0 -88
- package/dist/nuxt/plugin.mjs +0 -9
- package/dist/src/lib/iframe-bridge.d.ts +0 -8
- package/dist/src/lib/index.d.ts +0 -22
- package/dist/src/lib/nuxt/module.d.ts +0 -6
- package/dist/src/lib/nuxt/runtime/plugin.client.d.ts +0 -2
- package/dist/src/lib/nuxt/runtime/plugin.d.ts +0 -2
- package/dist/src/lib/utils/iframeBridge.d.ts +0 -39
- package/src/lib/nuxt/runtime/plugin.client.ts +0 -10
- /package/dist/{src/lib/components → components}/ContextMenu/ContextMenuItem.vue.d.ts +0 -0
- /package/dist/{src/lib/components → components}/PageLoading.vue.d.ts +0 -0
- /package/dist/{src/lib/components → components}/StackKeepAlive/StackCacheRenderer.vue.d.ts +0 -0
- /package/dist/{src/lib/components → components}/StackKeepAlive/StackKeepAlive.vue.d.ts +0 -0
- /package/dist/{src/lib/components → components}/TabHeader/TabHeaderButton.vue.d.ts +0 -0
- /package/dist/{src/lib/components → components}/TabHeader/TabHeaderScroll.vue.d.ts +0 -0
- /package/dist/{src/lib/hooks → hooks}/tabPanel/evict.d.ts +0 -0
- /package/dist/{src/lib/hooks → hooks}/tabPanel/navigationTransaction.d.ts +0 -0
- /package/dist/{src/lib/hooks → hooks}/tabPanel/session.d.ts +0 -0
- /package/dist/{src/lib/hooks → hooks}/tabPanel/state.d.ts +0 -0
- /package/dist/{src/lib/hooks → hooks}/useContextMenu.d.ts +0 -0
- /package/dist/{src/lib/hooks → hooks}/useIframeManager.d.ts +0 -0
- /package/dist/{src/lib/hooks → hooks}/useTabLoading.d.ts +0 -0
- /package/dist/{src/lib/hooks → hooks}/useTabRouter.d.ts +0 -0
- /package/dist/{src/lib/i18n → i18n}/index.d.ts +0 -0
- /package/dist/{src/lib/i18n → i18n}/lang/en.d.ts +0 -0
- /package/dist/{src/lib/i18n → i18n}/lang/zh-CN.d.ts +0 -0
- /package/dist/{src/lib/i18n → i18n}/stackTabsLocale.d.ts +0 -0
- /package/dist/{src/lib/iframe.vue.d.ts → iframe.vue.d.ts} +0 -0
- /package/dist/{src/lib/utils → utils}/stackTabsA11y.d.ts +0 -0
- /package/dist/{src/lib/utils → utils}/stackTabsMessage.d.ts +0 -0
- /package/dist/{src/lib/utils → utils}/tabInfoEncoder.d.ts +0 -0
- /package/dist/{src/lib/utils → utils}/typeGuards.d.ts +0 -0
- /package/dist/{src/lib/utils → utils}/urlParser.d.ts +0 -0
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="zh-CN">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Iframe Bridge 测试页面</title>
|
|
7
|
-
<style>
|
|
8
|
-
body {
|
|
9
|
-
font-family: system-ui, sans-serif;
|
|
10
|
-
padding: 20px;
|
|
11
|
-
background: #f0f2f5;
|
|
12
|
-
}
|
|
13
|
-
.card {
|
|
14
|
-
background: white;
|
|
15
|
-
padding: 20px;
|
|
16
|
-
border-radius: 8px;
|
|
17
|
-
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
18
|
-
}
|
|
19
|
-
button {
|
|
20
|
-
padding: 10px 20px;
|
|
21
|
-
background: #67c23a;
|
|
22
|
-
color: white;
|
|
23
|
-
border: none;
|
|
24
|
-
border-radius: 4px;
|
|
25
|
-
cursor: pointer;
|
|
26
|
-
}
|
|
27
|
-
.status {
|
|
28
|
-
margin-top: 10px;
|
|
29
|
-
color: #606266;
|
|
30
|
-
}
|
|
31
|
-
</style>
|
|
32
|
-
</head>
|
|
33
|
-
<body>
|
|
34
|
-
<div class="card">
|
|
35
|
-
<h2>此页面演示使用封装好的 Bridge 对接方式</h2>
|
|
36
|
-
<p>页面加载时间: <span id="time"></span></p>
|
|
37
|
-
<p>
|
|
38
|
-
使用 <code>iframeBridge.ts</code> 中提供的 <code>postOpenTab</code> 和
|
|
39
|
-
<code>onRefreshRequest</code>。
|
|
40
|
-
</p>
|
|
41
|
-
|
|
42
|
-
<div style="margin: 20px 0">
|
|
43
|
-
<button id="btnOpen">使用 Bridge 方法请求打开新 Tab</button>
|
|
44
|
-
</div>
|
|
45
|
-
<div class="status" id="status"></div>
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
<!-- 注意:在实际项目中,如果是原生 HTML 需要引入编译后的 Bridge 脚本,或者直接使用 type="module" -->
|
|
49
|
-
<script type="module">
|
|
50
|
-
// 这里的导入路径仅为本地调试示意,实际推荐将 Bridge 打包为公共库或 CDN 引用
|
|
51
|
-
import { postOpenTab, onRefreshRequest } from './src/lib/utils/iframeBridge.ts'
|
|
52
|
-
|
|
53
|
-
const timeEl = document.getElementById('time')
|
|
54
|
-
timeEl.innerText = new Date().toLocaleTimeString()
|
|
55
|
-
|
|
56
|
-
// 1. 使用 Bridge 封装的方法打开 Tab
|
|
57
|
-
document.getElementById('btnOpen').onclick = () => {
|
|
58
|
-
postOpenTab({
|
|
59
|
-
id: 'bridge_triggered_tab',
|
|
60
|
-
title: 'Bridge 弹出的新页签',
|
|
61
|
-
path: '/demo/page1',
|
|
62
|
-
closable: true
|
|
63
|
-
})
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// 2. 使用 Bridge 封装的方法监听刷新请求
|
|
67
|
-
onRefreshRequest(() => {
|
|
68
|
-
console.log('[Bridge Child] Received refresh request from parent')
|
|
69
|
-
const statusEl = document.getElementById('status')
|
|
70
|
-
statusEl.innerText = '正在执行刷新 logic...'
|
|
71
|
-
setTimeout(() => {
|
|
72
|
-
location.reload()
|
|
73
|
-
}, 500)
|
|
74
|
-
})
|
|
75
|
-
</script>
|
|
76
|
-
</body>
|
|
77
|
-
</html>
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="zh-CN">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>Iframe 子页面测试</title>
|
|
7
|
-
<style>
|
|
8
|
-
body {
|
|
9
|
-
font-family: system-ui, sans-serif;
|
|
10
|
-
padding: 20px;
|
|
11
|
-
background: #f0f9eb;
|
|
12
|
-
}
|
|
13
|
-
.card {
|
|
14
|
-
background: white;
|
|
15
|
-
padding: 20px;
|
|
16
|
-
border-radius: 8px;
|
|
17
|
-
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
18
|
-
}
|
|
19
|
-
button {
|
|
20
|
-
padding: 10px 20px;
|
|
21
|
-
background: #409eff;
|
|
22
|
-
color: white;
|
|
23
|
-
border: none;
|
|
24
|
-
border-radius: 4px;
|
|
25
|
-
cursor: pointer;
|
|
26
|
-
}
|
|
27
|
-
input {
|
|
28
|
-
padding: 8px;
|
|
29
|
-
width: 200px;
|
|
30
|
-
margin-right: 10px;
|
|
31
|
-
border: 1px solid #dcdfe6;
|
|
32
|
-
border-radius: 4px;
|
|
33
|
-
}
|
|
34
|
-
</style>
|
|
35
|
-
</head>
|
|
36
|
-
<body>
|
|
37
|
-
<div class="card">
|
|
38
|
-
<h2>此页面运行在隔离的 iframe 中</h2>
|
|
39
|
-
<p>页面加载时间: <span id="time"></span></p>
|
|
40
|
-
<p>
|
|
41
|
-
用于测试 iframe 页面的加载、刷新隔离,以及通过 `postMessage` 向外层通信请求打开新 Tab
|
|
42
|
-
的功能。
|
|
43
|
-
</p>
|
|
44
|
-
|
|
45
|
-
<div style="margin: 20px 0">
|
|
46
|
-
<label>隔离缓存测试输入框:</label>
|
|
47
|
-
<input type="text" id="ipt" placeholder="切走该页签是否会销毁内容?" />
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
<div style="margin: 20px 0">
|
|
51
|
-
<button onclick="requestNewTab()">向父级发送 postMessage 请求在外部打开新 Tab</button>
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
|
|
55
|
-
<script>
|
|
56
|
-
const timeEl = document.getElementById('time')
|
|
57
|
-
const updateTime = () => {
|
|
58
|
-
timeEl.innerText = new Date().toLocaleTimeString()
|
|
59
|
-
}
|
|
60
|
-
updateTime()
|
|
61
|
-
|
|
62
|
-
// 1. 原生对接:向父窗口请求打开新标签
|
|
63
|
-
function requestNewTab() {
|
|
64
|
-
window.parent.postMessage(
|
|
65
|
-
{
|
|
66
|
-
type: 'vue-stack-tabs:openTab', // 推荐使用该标准类型,StackTabs 已支持兼容 'openTab'
|
|
67
|
-
payload: {
|
|
68
|
-
id: 'native_triggered_tab',
|
|
69
|
-
title: '原生弹出的新页签',
|
|
70
|
-
path: '/demo/page2',
|
|
71
|
-
closable: true
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
'*'
|
|
75
|
-
)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// 2. 原生对接:监听父窗口发送的刷新请求
|
|
79
|
-
window.addEventListener('message', (ev) => {
|
|
80
|
-
if (ev.data?.type === 'vue-stack-tabs:refresh') {
|
|
81
|
-
console.log('[Native Child] Received refresh request from parent')
|
|
82
|
-
// 执行刷新逻辑(例如重新加载页面或局部数据更新)
|
|
83
|
-
location.reload()
|
|
84
|
-
}
|
|
85
|
-
})
|
|
86
|
-
</script>
|
|
87
|
-
</body>
|
|
88
|
-
</html>
|
package/dist/nuxt/plugin.mjs
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { defineNuxtPlugin as e, useRuntimeConfig as t } from "nuxt/app";
|
|
2
|
-
import n from "vue-stack-tabs";
|
|
3
|
-
//#region src/lib/nuxt/runtime/plugin.ts
|
|
4
|
-
var r = e((e) => {
|
|
5
|
-
let r = t().public.vueStackTabs;
|
|
6
|
-
e.vueApp.use(n, [{ locale: r?.locale ?? "zh-CN" }]);
|
|
7
|
-
});
|
|
8
|
-
//#endregion
|
|
9
|
-
export { r as default };
|
|
@@ -1,8 +0,0 @@
|
|
|
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';
|
package/dist/src/lib/index.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { App } from 'vue';
|
|
2
|
-
import { LocaleMessageOption } from './i18n';
|
|
3
|
-
import { default as StackTab } from './StackTabs.vue';
|
|
4
|
-
import { default as IFrame } from './iframe.vue';
|
|
5
|
-
import { default as useTabLoading } from './hooks/useTabLoading';
|
|
6
|
-
import { default as useTabRouter } from './hooks/useTabRouter';
|
|
7
|
-
import { default as useTabActions } from './hooks/useTabActions';
|
|
8
|
-
import { default as TabHeaderButton } from './components/TabHeader/TabHeaderButton.vue';
|
|
9
|
-
export type VueStackTabsPluginOptions = LocaleMessageOption[];
|
|
10
|
-
export * from './model/TabModel';
|
|
11
|
-
declare module '@vue/runtime-core' {
|
|
12
|
-
interface GlobalComponents {
|
|
13
|
-
VueStackTabs: typeof StackTab;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
export { IFrame, useTabActions, useTabLoading, useTabRouter, TabHeaderButton, StackTab, StackTab as VueStackTabs };
|
|
17
|
-
export { postOpenTab, onRefreshRequest, MSG_REFRESH, MSG_OPEN_TAB } from './utils/iframeBridge';
|
|
18
|
-
export type { IframeOpenTabPayload } from './utils/iframeBridge';
|
|
19
|
-
declare const _default: {
|
|
20
|
-
install(Vue: App, options?: VueStackTabsPluginOptions): void;
|
|
21
|
-
};
|
|
22
|
-
export default _default;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { LocationQueryRaw } from 'vue-router';
|
|
2
|
-
/**
|
|
3
|
-
* iframe 与父窗口的 postMessage 桥接
|
|
4
|
-
*
|
|
5
|
-
* 在 iframe 内的页面中引入,用于:
|
|
6
|
-
* - 接收父窗口的刷新指令并执行
|
|
7
|
-
* - 向父窗口发送打开新标签的请求
|
|
8
|
-
*/
|
|
9
|
-
/** 刷新消息:父 -> iframe,iframe 内页面需监听并执行 location.reload() 或自身刷新逻辑 */
|
|
10
|
-
export declare const MSG_REFRESH = "vue-stack-tabs:refresh";
|
|
11
|
-
/** 打开标签消息:iframe -> 父,payload 为 ITabData */
|
|
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
|
-
}
|
|
19
|
-
export interface IframeOpenTabPayload {
|
|
20
|
-
id?: string;
|
|
21
|
-
title: string;
|
|
22
|
-
path: string;
|
|
23
|
-
query?: LocationQueryRaw;
|
|
24
|
-
closable?: boolean;
|
|
25
|
-
refreshable?: boolean;
|
|
26
|
-
iframe?: boolean;
|
|
27
|
-
iframeRefreshMode?: 'postMessage' | 'reload';
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* 在 iframe 内调用:向父窗口请求打开新标签
|
|
31
|
-
* @param payload 标签数据,至少需 title、path
|
|
32
|
-
*/
|
|
33
|
-
export declare function postOpenTab(payload: IframeOpenTabPayload, options?: IframeBridgeOptions): void;
|
|
34
|
-
/**
|
|
35
|
-
* 在 iframe 内调用:注册刷新监听,收到父窗口刷新指令时执行 callback
|
|
36
|
-
* @param callback 默认 location.reload(),可自定义
|
|
37
|
-
* @returns 取消监听的函数
|
|
38
|
-
*/
|
|
39
|
-
export declare function onRefreshRequest(callback?: () => void, options?: RefreshRequestOptions): () => void;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { defineNuxtPlugin, useRuntimeConfig } from 'nuxt/app'
|
|
2
|
-
import VueStackTabs from 'vue-stack-tabs'
|
|
3
|
-
|
|
4
|
-
export default defineNuxtPlugin((nuxtApp) => {
|
|
5
|
-
const config = useRuntimeConfig().public.vueStackTabs as {
|
|
6
|
-
locale?: string
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
nuxtApp.vueApp.use(VueStackTabs, [{ locale: config?.locale ?? 'zh-CN' }])
|
|
10
|
-
})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|