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.
Files changed (116) hide show
  1. package/README.en.md +526 -0
  2. package/README.md +337 -520
  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 +88 -0
  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 -23
  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 -73
  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 +17 -74
  37. package/dist/src/lib/hooks/useTabRouter.d.ts +5 -5
  38. package/dist/src/lib/i18n/index.d.ts +6 -4
  39. package/dist/src/lib/i18n/lang/en.d.ts +5 -0
  40. package/dist/src/lib/i18n/lang/zh-CN.d.ts +5 -0
  41. package/dist/src/lib/i18n/stackTabsLocale.d.ts +2 -0
  42. package/dist/src/lib/iframe-bridge.d.ts +8 -0
  43. package/dist/src/lib/iframe.vue.d.ts +2 -1
  44. package/dist/src/lib/index.d.ts +4 -5
  45. package/dist/src/lib/model/TabModel.d.ts +14 -33
  46. package/dist/src/lib/nuxt/module.d.ts +6 -0
  47. package/dist/src/lib/nuxt/runtime/plugin.client.d.ts +2 -0
  48. package/dist/src/lib/nuxt/runtime/plugin.d.ts +2 -0
  49. package/dist/src/lib/utils/iframeBridge.d.ts +11 -3
  50. package/dist/src/lib/utils/stackTabsA11y.d.ts +8 -0
  51. package/dist/src/lib/utils/stackTabsMessage.d.ts +7 -0
  52. package/dist/src/lib/utils/tabInfoEncoder.d.ts +1 -16
  53. package/dist/src/lib/utils/typeGuards.d.ts +2 -0
  54. package/dist/src/lib/utils/urlParser.d.ts +24 -3
  55. package/dist/src/lib/versionLogger.d.ts +1 -0
  56. package/dist/style.css +2 -1
  57. package/dist/utils/iframeBridge.d.ts +39 -0
  58. package/dist/vue-stack-tabs.css +2 -1
  59. package/dist/vue-stack-tabs.es.js +1 -2411
  60. package/package.json +68 -47
  61. package/src/lib/StackTabs.vue +216 -192
  62. package/src/lib/assets/style/stackTab.scss +84 -12
  63. package/src/lib/components/ContextMenu/ContextMenuItem.vue +23 -11
  64. package/src/lib/components/ContextMenu/index.vue +94 -10
  65. package/src/lib/components/PageLoading.vue +9 -7
  66. package/src/lib/components/StackKeepAlive/StackCacheRenderer.vue +70 -0
  67. package/src/lib/components/StackKeepAlive/StackKeepAlive.vue +57 -0
  68. package/src/lib/components/TabHeader/TabHeaderButton.vue +19 -8
  69. package/src/lib/components/TabHeader/TabHeaderItem.vue +45 -16
  70. package/src/lib/components/TabHeader/TabHeaderScroll.vue +47 -25
  71. package/src/lib/components/TabHeader/index.vue +109 -12
  72. package/src/lib/hooks/stackTabsContext.ts +135 -0
  73. package/src/lib/hooks/tabPanel/evict.ts +123 -41
  74. package/src/lib/hooks/tabPanel/navigationTransaction.ts +61 -0
  75. package/src/lib/hooks/tabPanel/refresh.ts +109 -0
  76. package/src/lib/hooks/tabPanel/scroll.ts +57 -36
  77. package/src/lib/hooks/tabPanel/session.ts +84 -22
  78. package/src/lib/hooks/tabPanel/state.ts +41 -44
  79. package/src/lib/hooks/useIframeManager.ts +253 -0
  80. package/src/lib/hooks/useTabActions.ts +62 -30
  81. package/src/lib/hooks/useTabEventBus.ts +29 -19
  82. package/src/lib/hooks/useTabLoading.ts +3 -2
  83. package/src/lib/hooks/useTabPanel.tsx +415 -213
  84. package/src/lib/hooks/useTabRouter.ts +172 -43
  85. package/src/lib/i18n/index.ts +53 -45
  86. package/src/lib/i18n/lang/en.ts +6 -1
  87. package/src/lib/i18n/lang/zh-CN.ts +6 -1
  88. package/src/lib/i18n/stackTabsLocale.ts +8 -0
  89. package/src/lib/iframe-bridge.ts +12 -0
  90. package/src/lib/index.ts +14 -19
  91. package/src/lib/model/TabModel.ts +34 -86
  92. package/src/lib/nuxt/module.d.ts +4 -0
  93. package/src/lib/nuxt/module.ts +8 -3
  94. package/src/lib/nuxt/runtime/plugin.client.ts +2 -3
  95. package/src/lib/nuxt/runtime/plugin.ts +11 -0
  96. package/src/lib/utils/iframeBridge.ts +29 -5
  97. package/src/lib/utils/scrollUtils.ts +9 -4
  98. package/src/lib/utils/stackTabsA11y.ts +12 -0
  99. package/src/lib/utils/stackTabsMessage.ts +99 -0
  100. package/src/lib/utils/tabInfoEncoder.ts +69 -42
  101. package/src/lib/utils/typeGuards.ts +3 -0
  102. package/src/lib/utils/urlParser.ts +144 -14
  103. package/src/lib/versionLogger.ts +7 -19
  104. package/dist/src/lib/hooks/tabPanel/evict.spec.d.ts +0 -1
  105. package/dist/src/lib/hooks/useTabPanel.spec.d.ts +0 -1
  106. package/dist/src/lib/model/TabModel.spec.d.ts +0 -1
  107. package/dist/src/lib/utils/iframeBridge.spec.d.ts +0 -1
  108. package/dist/src/lib/utils/tabInfoEncoder.spec.d.ts +0 -1
  109. package/dist/src/lib/utils/urlParser.spec.d.ts +0 -1
  110. package/dist/vue-stack-tabs.umd.js +0 -1
  111. package/src/lib/hooks/tabPanel/evict.spec.ts +0 -85
  112. package/src/lib/hooks/useTabPanel.spec.ts +0 -34
  113. package/src/lib/model/TabModel.spec.ts +0 -40
  114. package/src/lib/utils/iframeBridge.spec.ts +0 -37
  115. package/src/lib/utils/tabInfoEncoder.spec.ts +0 -42
  116. 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
- })