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,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @vitest-environment happy-dom
|
|
3
|
-
*/
|
|
4
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
5
|
-
import { MSG_REFRESH, MSG_OPEN_TAB, postOpenTab, onRefreshRequest } from './iframeBridge'
|
|
6
|
-
|
|
7
|
-
describe('iframeBridge', () => {
|
|
8
|
-
it('MSG_REFRESH 和 MSG_OPEN_TAB 为预期常量', () => {
|
|
9
|
-
expect(MSG_REFRESH).toBe('vue-stack-tabs:refresh')
|
|
10
|
-
expect(MSG_OPEN_TAB).toBe('vue-stack-tabs:openTab')
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
describe('postOpenTab', () => {
|
|
14
|
-
it('有 window.parent 时调用 postMessage', () => {
|
|
15
|
-
const spy = vi.spyOn(window.parent, 'postMessage')
|
|
16
|
-
postOpenTab({ title: 't', path: '/p' })
|
|
17
|
-
expect(spy).toHaveBeenCalledWith(
|
|
18
|
-
{ type: MSG_OPEN_TAB, payload: { title: 't', path: '/p' } },
|
|
19
|
-
'*'
|
|
20
|
-
)
|
|
21
|
-
spy.mockRestore()
|
|
22
|
-
})
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
describe('onRefreshRequest', () => {
|
|
26
|
-
it('注册监听并返回取消函数', () => {
|
|
27
|
-
const cb = vi.fn()
|
|
28
|
-
const off = onRefreshRequest(cb)
|
|
29
|
-
expect(typeof off).toBe('function')
|
|
30
|
-
window.dispatchEvent(new MessageEvent('message', { data: { type: MSG_REFRESH } }))
|
|
31
|
-
expect(cb).toHaveBeenCalled()
|
|
32
|
-
off()
|
|
33
|
-
window.dispatchEvent(new MessageEvent('message', { data: { type: MSG_REFRESH } }))
|
|
34
|
-
expect(cb).toHaveBeenCalledTimes(1)
|
|
35
|
-
})
|
|
36
|
-
})
|
|
37
|
-
})
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest'
|
|
2
|
-
import { encodeTabInfo, decodeTabInfo, createPageId } from './tabInfoEncoder'
|
|
3
|
-
import type { ITabBase } from '../model/TabModel'
|
|
4
|
-
|
|
5
|
-
describe('tabInfoEncoder', () => {
|
|
6
|
-
const tabData: ITabBase = {
|
|
7
|
-
id: 'tab-1',
|
|
8
|
-
title: '测试',
|
|
9
|
-
iframe: false,
|
|
10
|
-
closable: true,
|
|
11
|
-
refreshable: true
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
it('encodeTabInfo 与 decodeTabInfo 往返一致', () => {
|
|
15
|
-
const encoded = encodeTabInfo(tabData)
|
|
16
|
-
expect(encoded).toBeTruthy()
|
|
17
|
-
const decoded = decodeTabInfo(encoded)
|
|
18
|
-
expect(decoded.id).toBe(tabData.id)
|
|
19
|
-
expect(decoded.title).toBe(tabData.title)
|
|
20
|
-
expect(decoded.iframe).toBe(false)
|
|
21
|
-
expect(decoded.closable).toBe(true)
|
|
22
|
-
expect(decoded.refreshable).toBe(true)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('createPageId 相同输入产生相同输出', () => {
|
|
26
|
-
const id1 = createPageId('t1', '/path', { a: '1', b: '2' })
|
|
27
|
-
const id2 = createPageId('t1', '/path', { b: '2', a: '1' })
|
|
28
|
-
expect(id1).toBe(id2)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it('createPageId 不同 tabId 产生不同输出', () => {
|
|
32
|
-
const id1 = createPageId('t1', '/path', {})
|
|
33
|
-
const id2 = createPageId('t2', '/path', {})
|
|
34
|
-
expect(id1).not.toBe(id2)
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it('createPageId 排除 __ 前缀的 query', () => {
|
|
38
|
-
const withTab = createPageId('t1', '/path', { __tab: 'x', a: '1' })
|
|
39
|
-
const withoutTab = createPageId('t1', '/path', { a: '1' })
|
|
40
|
-
expect(withTab).toBe(withoutTab)
|
|
41
|
-
})
|
|
42
|
-
})
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest'
|
|
2
|
-
import { parseUrl, isCrossOriginUrl, isInvalidIframeUrl } from './urlParser'
|
|
3
|
-
|
|
4
|
-
describe('isInvalidIframeUrl', () => {
|
|
5
|
-
it('javascript: 和 data: 协议返回 true', () => {
|
|
6
|
-
expect(isInvalidIframeUrl('javascript:void(0)')).toBe(true)
|
|
7
|
-
expect(isInvalidIframeUrl('data:text/html,test')).toBe(true)
|
|
8
|
-
})
|
|
9
|
-
it('http/https 或相对路径返回 false', () => {
|
|
10
|
-
expect(isInvalidIframeUrl('http://example.com')).toBe(false)
|
|
11
|
-
expect(isInvalidIframeUrl('/path')).toBe(false)
|
|
12
|
-
expect(isInvalidIframeUrl('')).toBe(false)
|
|
13
|
-
})
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
describe('isCrossOriginUrl', () => {
|
|
17
|
-
it('相对路径返回 false', () => {
|
|
18
|
-
expect(isCrossOriginUrl('/demo')).toBe(false)
|
|
19
|
-
})
|
|
20
|
-
it('空或非 http(s) 返回 false', () => {
|
|
21
|
-
expect(isCrossOriginUrl('')).toBe(false)
|
|
22
|
-
expect(isCrossOriginUrl('javascript:void(0)')).toBe(false)
|
|
23
|
-
})
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
describe('parseUrl', () => {
|
|
27
|
-
it('解析纯 path', () => {
|
|
28
|
-
expect(parseUrl('/dashboard')).toEqual({ path: '/dashboard', query: {} })
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it('解析 path 带 query', () => {
|
|
32
|
-
expect(parseUrl('/page?a=1&b=2')).toEqual({
|
|
33
|
-
path: '/page',
|
|
34
|
-
query: { a: '1', b: '2' }
|
|
35
|
-
})
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('解析单个 query 参数', () => {
|
|
39
|
-
expect(parseUrl('/x?id=123')).toEqual({ path: '/x', query: { id: '123' } })
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('空 query 或空 value 不加入结果', () => {
|
|
43
|
-
expect(parseUrl('/p?key=')).toEqual({ path: '/p', query: {} })
|
|
44
|
-
})
|
|
45
|
-
})
|