vue-stack-tabs 0.1.51 → 1.0.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.
- package/README.md +717 -3
- package/dist/index.d.ts +3 -0
- package/dist/src/lib/StackTabs.vue.d.ts +33 -161
- package/dist/src/lib/components/ContextMenu/ContextMenuItem.vue.d.ts +6 -6
- package/dist/src/lib/components/ContextMenu/index.vue.d.ts +14 -14
- package/dist/src/lib/components/PageLoading.vue.d.ts +5 -5
- package/dist/src/lib/components/TabHeader/TabHeaderButton.vue.d.ts +24 -15
- package/dist/src/lib/components/TabHeader/TabHeaderItem.vue.d.ts +10 -8
- package/dist/src/lib/components/TabHeader/TabHeaderScroll.vue.d.ts +31 -13
- package/dist/src/lib/components/TabHeader/index.vue.d.ts +172 -20
- package/dist/src/lib/hooks/tabPanel/evict.d.ts +24 -0
- package/dist/src/lib/hooks/tabPanel/evict.spec.d.ts +1 -0
- package/dist/src/lib/hooks/tabPanel/scroll.d.ts +8 -0
- package/dist/src/lib/hooks/tabPanel/session.d.ts +9 -0
- package/dist/src/lib/hooks/tabPanel/state.d.ts +77 -0
- package/dist/src/lib/hooks/useContextMenu.d.ts +6 -1
- package/dist/src/lib/hooks/useTabActions.d.ts +68 -0
- package/dist/src/lib/hooks/{useTabMitt.d.ts → useTabEventBus.d.ts} +4 -3
- package/dist/src/lib/hooks/useTabLoading.d.ts +6 -0
- package/dist/src/lib/hooks/{useTabpanel.d.ts → useTabPanel.d.ts} +20 -14
- package/dist/src/lib/hooks/useTabPanel.spec.d.ts +1 -0
- package/dist/src/lib/hooks/useTabRouter.d.ts +14 -5
- package/dist/src/lib/i18n/index.d.ts +1 -1
- package/dist/src/lib/i18n/lang/en.d.ts +1 -0
- package/dist/src/lib/i18n/lang/zh-CN.d.ts +1 -0
- package/dist/src/lib/index.d.ts +5 -4
- package/dist/src/lib/model/TabModel.d.ts +20 -3
- package/dist/src/lib/model/TabModel.spec.d.ts +1 -0
- package/dist/src/lib/utils/iframeBridge.d.ts +31 -0
- package/dist/src/lib/utils/iframeBridge.spec.d.ts +1 -0
- package/dist/src/lib/utils/scrollUtils.d.ts +28 -0
- package/dist/src/lib/utils/tabInfoEncoder.d.ts +19 -0
- package/dist/src/lib/utils/tabInfoEncoder.spec.d.ts +1 -0
- package/dist/src/lib/utils/urlParser.d.ts +19 -0
- package/dist/src/lib/utils/urlParser.spec.d.ts +1 -0
- package/dist/src/lib/versionLogger.d.ts +2 -0
- package/dist/style.css +1 -1
- package/dist/vue-stack-tabs.css +1 -0
- package/dist/vue-stack-tabs.es.js +1795 -1679
- package/dist/vue-stack-tabs.umd.js +1 -5
- package/package.json +76 -39
- package/src/lib/StackTabs.vue +222 -47
- package/src/lib/assets/image/open.svg +1 -0
- package/src/lib/assets/style/common/var.scss +1 -1
- package/src/lib/assets/style/icon.scss +6 -0
- package/src/lib/assets/style/stackTab.scss +46 -3
- package/src/lib/assets/style/transition.scss +63 -62
- package/src/lib/components/ContextMenu/ContextMenuItem.vue +7 -0
- package/src/lib/components/ContextMenu/index.vue +50 -38
- package/src/lib/components/PageLoading.vue +30 -10
- package/src/lib/components/TabHeader/TabHeaderButton.vue +12 -3
- package/src/lib/components/TabHeader/TabHeaderItem.vue +31 -27
- package/src/lib/components/TabHeader/TabHeaderScroll.vue +83 -77
- package/src/lib/components/TabHeader/index.vue +45 -40
- package/src/lib/hooks/tabPanel/evict.spec.ts +85 -0
- package/src/lib/hooks/tabPanel/evict.ts +57 -0
- package/src/lib/hooks/tabPanel/scroll.ts +52 -0
- package/src/lib/hooks/tabPanel/session.ts +33 -0
- package/src/lib/hooks/tabPanel/state.ts +52 -0
- package/src/lib/hooks/useContextMenu.ts +22 -20
- package/src/lib/hooks/useTabActions.ts +148 -0
- package/src/lib/hooks/useTabEventBus.ts +31 -0
- package/src/lib/hooks/useTabLoading.ts +12 -4
- package/src/lib/hooks/useTabPanel.spec.ts +34 -0
- package/src/lib/hooks/useTabPanel.tsx +546 -0
- package/src/lib/hooks/useTabRouter.ts +114 -103
- package/src/lib/i18n/index.ts +14 -18
- package/src/lib/i18n/lang/en.ts +2 -1
- package/src/lib/i18n/lang/zh-CN.ts +2 -1
- package/src/lib/iframe.vue +6 -0
- package/src/lib/index.ts +27 -8
- package/src/lib/model/TabModel.spec.ts +40 -0
- package/src/lib/model/TabModel.ts +22 -9
- package/src/lib/nuxt/module.d.ts +19 -0
- package/src/lib/nuxt/module.ts +34 -0
- package/src/lib/nuxt/runtime/plugin.client.ts +11 -0
- package/src/lib/utils/iframeBridge.spec.ts +37 -0
- package/src/lib/utils/iframeBridge.ts +52 -0
- package/src/lib/utils/{TabScrollHelper.ts → scrollUtils.ts} +23 -29
- package/src/lib/utils/tabInfoEncoder.spec.ts +42 -0
- package/src/lib/utils/tabInfoEncoder.ts +65 -0
- package/src/lib/utils/urlParser.spec.ts +45 -0
- package/src/lib/utils/urlParser.ts +42 -0
- package/src/lib/{banner.ts → versionLogger.ts} +4 -5
- package/dist/src/lib/banner.d.ts +0 -2
- package/dist/src/lib/hooks/useStackTab.d.ts +0 -11
- package/dist/src/lib/utils/TabIdHelper.d.ts +0 -11
- package/dist/src/lib/utils/TabScrollHelper.d.ts +0 -33
- package/dist/src/lib/utils/UriHelper.d.ts +0 -4
- package/src/lib/hooks/useStackTab.ts +0 -119
- package/src/lib/hooks/useTabMitt.ts +0 -30
- package/src/lib/hooks/useTabpanel.tsx +0 -708
- package/src/lib/utils/TabIdHelper.ts +0 -70
- package/src/lib/utils/UriHelper.ts +0 -22
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* @param {number} [top=0]
|
|
2
|
+
* 滚动工具函数
|
|
3
|
+
*
|
|
4
|
+
* 职责:页面/标签切换时保存与恢复滚动位置,以及 z-index 计算
|
|
5
|
+
* 使用:useTabPanel 的 scrollPositionsByPageId、TabHeader 滚动条
|
|
7
6
|
*/
|
|
8
|
-
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 将指定容器滚动到 (left, top),支持 smooth
|
|
10
|
+
*/
|
|
11
|
+
export const scrollTo = ({
|
|
9
12
|
wrap,
|
|
10
13
|
left = 0,
|
|
11
14
|
top = 0,
|
|
@@ -30,50 +33,45 @@ export const _scrollTo = ({
|
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
* @export
|
|
36
|
-
* @param {Element} el 目标元素
|
|
37
|
-
* @param {Element} wrap 滚动区域
|
|
38
|
-
* @param {String} block 垂直方向的对齐,可选:'start', 'center', 'end', 或 'nearest'
|
|
39
|
-
* @param {String} inline 水平方向的对齐,可选值同上
|
|
40
|
-
*/
|
|
41
|
-
export function _scrollIntoView({
|
|
36
|
+
/** 将指定元素滚动到容器可视区域内,支持 block/inline 对齐方式 */
|
|
37
|
+
export function scrollIntoView({
|
|
42
38
|
el,
|
|
43
39
|
wrap,
|
|
44
40
|
block = 'start',
|
|
45
41
|
inline = 'nearest'
|
|
46
42
|
}: {
|
|
47
43
|
el: HTMLElement
|
|
48
|
-
wrap:
|
|
49
|
-
block?:
|
|
50
|
-
inline?:
|
|
44
|
+
wrap: HTMLElement | { value: HTMLElement | null } | null
|
|
45
|
+
block?: ScrollLogicalPosition
|
|
46
|
+
inline?: ScrollLogicalPosition
|
|
51
47
|
}) {
|
|
52
|
-
|
|
48
|
+
const wrapEl = wrap && typeof wrap === 'object' && 'value' in wrap ? wrap.value : wrap
|
|
49
|
+
if (!el || !wrapEl) return
|
|
53
50
|
|
|
54
51
|
if (el.scrollIntoView) {
|
|
55
52
|
el.scrollIntoView({ behavior: 'smooth', block, inline })
|
|
56
53
|
} else {
|
|
57
54
|
const { offsetLeft, offsetTop } = el
|
|
58
|
-
let left
|
|
55
|
+
let left: number
|
|
56
|
+
let top: number
|
|
59
57
|
|
|
60
58
|
if (block === 'center') {
|
|
61
|
-
top = offsetTop + (el.clientHeight -
|
|
59
|
+
top = offsetTop + (el.clientHeight - wrapEl.clientHeight) / 2
|
|
62
60
|
} else {
|
|
63
61
|
top = offsetTop
|
|
64
62
|
}
|
|
65
63
|
|
|
66
64
|
if (inline === 'center') {
|
|
67
|
-
left = offsetLeft + (el.clientWidth -
|
|
65
|
+
left = offsetLeft + (el.clientWidth - wrapEl.clientWidth) / 2
|
|
68
66
|
} else {
|
|
69
67
|
left = offsetLeft
|
|
70
68
|
}
|
|
71
69
|
|
|
72
|
-
|
|
70
|
+
scrollTo({ wrap: wrapEl, left, top })
|
|
73
71
|
}
|
|
74
72
|
}
|
|
75
73
|
|
|
76
|
-
|
|
74
|
+
/** 获取系统滚动条宽度(用于布局计算) */
|
|
77
75
|
export const getScrollbarWidth = (function () {
|
|
78
76
|
let width: number | null = null
|
|
79
77
|
|
|
@@ -91,14 +89,10 @@ export const getScrollbarWidth = (function () {
|
|
|
91
89
|
}
|
|
92
90
|
})()
|
|
93
91
|
|
|
94
|
-
/**
|
|
95
|
-
* 获取最大z-index
|
|
96
|
-
* @returns 最大z-index的值
|
|
97
|
-
*/
|
|
92
|
+
/** 获取指定选择器下元素的最大 z-index + 1,用于最大化时置顶 */
|
|
98
93
|
export const getMaxZIndex = (key = '.stack-tab__container *'): number => {
|
|
99
94
|
const allZIndex = Array.from(document.querySelectorAll(key)).map(
|
|
100
95
|
(e) => +window.getComputedStyle(e).zIndex || 0
|
|
101
96
|
)
|
|
102
|
-
// 特殊处理,不高于90000的才行
|
|
103
97
|
return allZIndex.length ? Math.max(...allZIndex.filter((item) => item < 90000)) + 1 : 1
|
|
104
98
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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
|
+
})
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ITabBase } from '../model/TabModel'
|
|
2
|
+
import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from 'lz-string'
|
|
3
|
+
import Hex from 'hex-encoding'
|
|
4
|
+
import { blake3 } from '@noble/hashes/blake3.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 标签信息编解码器
|
|
8
|
+
*
|
|
9
|
+
* 职责:将标签元数据压缩为 URL query 可用的短字符串,用于 __tab 参数
|
|
10
|
+
* 格式: id|title|iframe|closable|refreshable,压缩后写入 query.__tab
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 编码标签基础信息为压缩字符串(用于 query.__tab)
|
|
15
|
+
* @param tabData 标签基础数据
|
|
16
|
+
*/
|
|
17
|
+
export const encodeTabInfo = (tabData: ITabBase): string => {
|
|
18
|
+
const mode = (tabData as { iframeRefreshMode?: string }).iframeRefreshMode === 'reload' ? 'R' : 'P'
|
|
19
|
+
const info = `${tabData.id}|${tabData.title}|${tabData.iframe ? 'Y' : 'N'}|${tabData.closable ? 'Y' : 'N'}|${tabData.refreshable ? 'Y' : 'N'}|${mode}`
|
|
20
|
+
return compressToEncodedURIComponent(info)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** 从 query.__tab 解压并解析为 ITabBase */
|
|
24
|
+
export const decodeTabInfo = (encoded: string): ITabBase => {
|
|
25
|
+
const tabString = decompressFromEncodedURIComponent(encoded)
|
|
26
|
+
const tabValues: string[] = tabString.split('|')
|
|
27
|
+
const refreshMode = tabValues[5] === 'R' ? ('reload' as const) : ('postMessage' as const)
|
|
28
|
+
return {
|
|
29
|
+
id: tabValues[0] ?? '',
|
|
30
|
+
title: tabValues[1] ?? '',
|
|
31
|
+
iframe: tabValues[2] === 'Y',
|
|
32
|
+
closable: tabValues[3] === 'Y',
|
|
33
|
+
refreshable: tabValues[4] === 'Y',
|
|
34
|
+
iframeRefreshMode: refreshMode
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 根据 tabId + path + query 生成页面缓存 ID
|
|
40
|
+
* 用于 keep-alive 的 include 和 exclude,需稳定且唯一
|
|
41
|
+
*/
|
|
42
|
+
export const createPageId = (tabId: string, path: string, query: object): string => {
|
|
43
|
+
const queryEntries: { key: string; value: string }[] = []
|
|
44
|
+
type ObjectKey = keyof typeof query
|
|
45
|
+
for (const key in query) {
|
|
46
|
+
if (!key.startsWith('__')) {
|
|
47
|
+
queryEntries.push({
|
|
48
|
+
key,
|
|
49
|
+
value: query[key as ObjectKey]
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
queryEntries.sort((a, b) => {
|
|
54
|
+
let result = 0
|
|
55
|
+
if (a.key > b.key) {
|
|
56
|
+
result = 1
|
|
57
|
+
} else if (a.key < b.key) {
|
|
58
|
+
result = -1
|
|
59
|
+
}
|
|
60
|
+
return result
|
|
61
|
+
})
|
|
62
|
+
const msg = new TextEncoder().encode(`${tabId}|${path}|${JSON.stringify(queryEntries)}`)
|
|
63
|
+
const hash = blake3(msg)
|
|
64
|
+
return Hex.encode(hash)
|
|
65
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
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
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 判断是否为不可嵌入 iframe 的协议
|
|
3
|
+
* @param url - 待检查的 URL 字符串
|
|
4
|
+
* @returns javascript:、data: 等返回 true
|
|
5
|
+
*/
|
|
6
|
+
export function isInvalidIframeUrl(url: string): boolean {
|
|
7
|
+
return !!(url && /^(javascript|data):/i.test(url))
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 判断 URL 是否为跨域(相对路径或同源视为同域)
|
|
12
|
+
* @param url - 待检查的 URL
|
|
13
|
+
*/
|
|
14
|
+
export function isCrossOriginUrl(url: string): boolean {
|
|
15
|
+
if (!url || !/^https?:\/\//i.test(url)) return false
|
|
16
|
+
try {
|
|
17
|
+
const cur = typeof window !== 'undefined' ? window.location : { origin: 'http://localhost' }
|
|
18
|
+
const u = new URL(url, cur.origin)
|
|
19
|
+
return u.origin !== cur.origin
|
|
20
|
+
} catch {
|
|
21
|
+
return true
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 解析 URL 字符串为 path 和 query
|
|
27
|
+
* @param uri 完整 URL 或 path?query 字符串
|
|
28
|
+
*/
|
|
29
|
+
export function parseUrl(uri: string): { path: string; query: Record<string, string> } {
|
|
30
|
+
const [pathPart, queryPart] = uri.split('?')
|
|
31
|
+
if (!queryPart) {
|
|
32
|
+
return { path: pathPart ?? '', query: {} }
|
|
33
|
+
}
|
|
34
|
+
const query: Record<string, string> = {}
|
|
35
|
+
for (const pair of queryPart.split('&')) {
|
|
36
|
+
const [key, val] = pair.split('=')
|
|
37
|
+
if (key != null && val != null && val !== '') {
|
|
38
|
+
query[key] = val
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { path: pathPart ?? '', query }
|
|
42
|
+
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { encode } from 'js-base64'
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
const logVersion = (version: string) => {
|
|
3
4
|
const height = 100
|
|
4
5
|
const width = 580
|
|
5
6
|
const xml = `<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1167.06 237.75"><path d="M79.24,19.73h108.91v29.7h-108.91v-29.7Z" style="fill:#79a7ff; stroke-width:0px;"/><path d="M179.24,199.67H20.26c-11.21-.07-20.26-9.17-20.26-20.38V20.39C0,9.18,9.05.07,20.26,0h59.49c3.51.07,6.34,2.9,6.41,6.42v44.36c0,3.54-2.87,6.41-6.41,6.41s-6.41-2.86-6.42-6.4V12.36H20.25c-4.13.07-7.44,3.44-7.44,7.56v159.41c0,4.13,3.31,7.49,7.44,7.56h158.98c4.13-.07,7.44-3.44,7.44-7.56V51.84c0-3.54,2.87-6.41,6.41-6.42,3.55,0,6.42,2.87,6.42,6.42v127.45c0,11.21-9.05,20.32-20.26,20.39h0Z" style="fill:#377dff; stroke-width:0px;"/><path d="M192.8,60.77c-3.66-.07-6.61-3.02-6.68-6.68v-18.23c.09-4.29-3.32-7.83-7.6-7.92h-96.43c-3.69,0-6.69-2.99-6.69-6.69s2.99-6.69,6.69-6.69h96.27c11.69.08,21.13,9.58,21.13,21.27v18.25c0,3.69-2.99,6.68-6.68,6.68h0Z" style="fill:#377dff; stroke-width:0px;"/><path d="M193.08,58.67H10.15c-3.61-.08-6.48-3.07-6.41-6.68-.08-3.62,2.79-6.61,6.4-6.69,0,0,0,0,0,0h182.93c3.62.08,6.48,3.08,6.41,6.69.07,3.61-2.79,6.6-6.41,6.68h0Z" style="fill:#377dff; stroke-width:0px;"/><path d="M137.2,58.67c-3.42.24-6.4-2.32-6.68-5.74v-28.15c.55-3.69,4-6.24,7.69-5.69,2.94.44,5.24,2.75,5.69,5.69v28.15c-.28,3.42-3.26,5.98-6.68,5.74h-.02Z" style="fill:#377dff; stroke-width:0px;"/><path d="M99.78,100.48l-12.83-22.22h-18.39l31.22,54.05,31.22-54.05h-18.39l-12.83,22.22Z" style="fill:#00d797; stroke-width:0px;"/><path d="M135.28,78.26l-35.49,61.43-35.44-61.43h-20.11l55.55,96.2,55.55-96.2s-20.06,0-20.06,0ZM313.33,59.95c0,.52-.67,1.84-2,3.95s-3.3,5.2-5.9,9.28-5.75,9.28-9.46,15.61c-3.7,6.33-7.52,13.34-11.45,21.04-4.51,8.85-7.76,15.8-9.76,20.86s-2.99,9.41-2.99,13.05c0,2.89,1.53,5.44,4.6,7.63,3.7-2.89,7.34-6.33,10.93-10.32,3.58-3.99,7.13-8.44,10.63-13.36s7.55-11.13,12.14-18.65c4.6-7.52,8.69-14.43,12.27-20.73-.17-.52-.36-1.04-.56-1.56s-.3-.95-.3-1.3c0-2.72.55-5.26,1.65-7.63,1.1-2.37,2.47-4.68,4.12-6.94s4.12-5.44,7.42-9.54c.87-1.1,1.94-1.65,3.21-1.65,2.08,0,3.12,1.33,3.12,3.99s-1.08,6.84-3.25,12.53c-2.17,5.7-5.37,12.39-9.59,20.08s-9.47,16.29-15.74,25.81c-6.28,9.51-13.37,19.45-21.3,29.8-8.04,10.47-13.79,15.7-17.26,15.7-1.97,0-4.19-1.08-6.68-3.25s-4.63-5.13-6.42-8.89-2.69-7.78-2.69-12.06c0-2.54.53-5.81,1.6-9.8s2.75-8.78,5.03-14.36,4.87-11.09,7.76-16.53c3.01-5.72,5.65-10.47,7.94-14.23,2.28-3.76,4.87-7.94,7.76-12.53,2.89-4.6,4.34-7.1,4.34-7.5,0-.87-.58-1.3-1.73-1.3-3.35,0-7.82,1.71-13.4,5.12s-12.85,8.59-21.82,15.53c-3.41,2.66-5.57,4.38-6.46,5.16s-1.34,1.43-1.34,1.95c0,.69.55,1.04,1.65,1.04.46,0,2.02-.17,4.68-.52s4.77-.52,6.33-.52c2.6,0,3.9.46,3.9,1.39,0,.81-.54,1.45-1.61,1.91-1.07.46-2.54.93-4.42,1.39s-4.44,1.1-7.68,1.91c-3.47.93-7.16,2.25-11.06,3.99-3.9,1.73-6.14,2.6-6.72,2.6-1.1,0-1.78-.4-2.04-1.21s-.39-2.14-.39-3.99c0-8.21,1.36-14.56,4.08-19.04s7.58-9.15,14.57-14.01c7.98-5.55,15.61-10.16,22.9-13.84,7.29-3.67,13.58-6.36,18.87-8.07s9.18-2.56,11.67-2.56,4.84,1.56,7.24,4.68,3.6,6.42,3.6,9.89h0ZM366.34,124.75c-8.39,11.1-14.76,19-19.13,23.68s-7.94,7.03-10.71,7.03c-2.2,0-4.22-.91-6.07-2.73-1.85-1.82-3.28-4.28-4.29-7.37s-1.52-6.4-1.52-9.93c0-2.31.22-4.39.65-6.25.43-1.85,1.26-3.89,2.47-6.12s2.82-4.64,4.81-7.24c2-2.6,4.44-5.55,7.33-8.85,1.73-2.02,3.19-3.73,4.38-5.12,1.18-1.39,2.34-2.33,3.47-2.82s2.96-.74,5.51-.74c1.85,0,3.61.25,5.29.74,1.68.49,2.52,1,2.52,1.52,0,1.04-.85,2.92-2.56,5.64s-4.45,6.03-8.24,9.93c-3.79,3.9-8.17,7.74-13.14,11.49-1.1,3.41-1.65,6.01-1.65,7.81,0,2.49.95,3.73,2.86,3.73.69,0,1.85-.59,3.47-1.78,1.62-1.18,4.35-3.47,8.2-6.85,3.84-3.38,7.3-6.38,10.37-8.98,2.25-1.97,4.87-4.9,7.85-8.8s5.39-6.84,7.24-8.8c4.28-4.51,7.2-7.44,8.76-8.8s3.06-2.04,4.51-2.04,2.33.43,2.82,1.3c.49.87.74,2.63.74,5.29,0,1.21-.12,2.2-.35,2.95s-.71,1.72-1.43,2.91-2.18,3.37-4.38,6.55-4.8,6.94-7.81,11.28c-1.66,2.38-3.09,4.93-4.25,7.59-1.21,2.75-1.82,4.81-1.82,6.2,0,3.01,1.18,4.51,3.56,4.51,1.96,0,4.25-.81,6.85-2.43s6.59-4.54,11.97-8.76v5.81c-6.77,6.25-11.77,10.79-15.01,13.62s-6.04,4.97-8.41,6.42-4.63,2.17-6.77,2.17c-4.86,0-7.29-2.89-7.29-8.67,0-2.2.72-5.16,2.17-8.89,1.44-3.73,3.79-9.12,7.03-16.18v-.02Z" style="fill:#306fff; stroke-width:0px;"/><path d="M407.71,133.77v2.17c0,3.41.84,6.07,2.52,7.98,1.68,1.91,3.87,2.86,6.59,2.86s5.77-.66,8.8-2c3.04-1.33,6.06-3.09,9.07-5.29s6.68-5.15,11.02-8.85v5.29c-6.54,7.87-12.67,13.89-18.39,18.09-5.72,4.19-11.54,6.29-17.44,6.29-5.15,0-9.22-2-12.23-5.99s-4.51-9.46-4.51-16.39c0-6.07,1.42-11.58,4.25-16.52s7.46-10.16,13.88-15.66c4.39-3.76,8.76-6.59,13.1-8.5s8.21-2.86,11.62-2.86c2.72,0,4.87.62,6.46,1.86s2.39,3.11,2.39,5.59c0,3.64-1.36,7.27-4.08,10.89s-6.87,7.2-12.45,10.76c-5.58,3.56-12.45,6.98-20.6,10.28h0ZM408.58,128.13c5.2-2.02,9.66-4.54,13.36-7.55,3.7-3.01,6.43-5.88,8.2-8.63,1.76-2.75,2.65-4.76,2.65-6.03s-.61-2-1.82-2c-1.04,0-2.73.67-5.07,2s-4.71,3.07-7.11,5.21-4.55,4.66-6.46,7.55c-1.9,2.86-3.17,6.08-3.73,9.46h-.02ZM585.37,132.9c-1.45-2.66-3.61-5.06-6.51-7.2-2.89-2.14-6.15-3.86-9.76-5.16s-7.39-2.27-11.32-2.91c-11.68-1.74-22.58-5.52-32.7-11.36-.87-.46-1.79-1.44-2.78-2.95-.98-1.5-1.47-2.95-1.47-4.34,0-5.09.85-10.19,2.56-15.31,1.71-5.12,3.89-9.12,6.55-12.01,4.28-4.8,11.98-8.99,23.12-12.58,11.13-3.58,23.67-5.38,37.6-5.38,8.33,0,14.76.64,19.3,1.91s6.81,3.24,6.81,5.9c0,4.34-.59,7.69-1.78,10.06s-2.46,3.95-3.82,4.73c-1.36.78-3.75,1.84-7.16,3.17-3.64,1.27-6.81,2.6-9.5,3.99s-4.99,2.72-6.9,3.99c-1.91,1.27-3.09,1.91-3.56,1.91-.58,0-.87-.23-.87-.69,0-.98,1.03-2.47,3.08-4.47s4.58-3.74,7.59-5.25c3.18-1.68,4.77-2.75,4.77-3.21,0-.75-1.76-1.13-5.29-1.13-10.7,0-20.59.95-29.67,2.86s-16.24,4.42-21.47,7.55c-5.23,3.12-7.85,6.3-7.85,9.54,0,2.02,1.08,3.46,3.25,4.29,2.17.84,6.95,2.24,14.36,4.21,7.4,1.97,14.02,4.22,19.86,6.77,8.38,3.59,14.6,7.32,18.65,11.19,4.05,3.88,6.07,8.21,6.07,13.01,0,3.3-.8,6.61-2.39,9.93-1.59,3.33-3.92,6.38-6.98,9.15-3.07,2.78-6.59,5.06-10.58,6.85-3.41,1.45-7.71,2.8-12.88,4.08-5.18,1.27-10.79,2.27-16.83,2.99-6.04.72-11.81,1.08-17.31,1.08-10.12,0-18.26-.95-24.42-2.86s-9.24-4.8-9.24-8.67c0-1.74,1.04-4.44,3.12-8.11s4.54-6.14,7.37-7.42c2.49-.98,4.89-1.55,7.2-1.69,2.31-.14,3.47.13,3.47.82,0,.17-.09.35-.26.52s-.38.32-.61.43c-.23.12-.46.23-.69.35-1.16.46-2.1.82-2.82,1.08-.72.26-1.3.52-1.74.78-.43.26-.65.62-.65,1.08,0,1.21,5.99,1.82,17.96,1.82,10.41,0,18.94-.38,25.59-1.13s12.52-2.11,17.61-4.08c5.09-1.97,9.71-4.68,13.88-8.15l.04.02ZM640.8,85.63h3.73c3.06-5.49,5.84-9.38,8.33-11.67,2.49-2.28,5.32-3.43,8.5-3.43s4.77.72,4.77,2.17c0,.69-1.24,2.57-3.73,5.64s-4.37,5.64-5.64,7.72c1.96.23,3.71.43,5.25.61,1.53.17,2.73.32,3.6.43-3.3,6.13-7.43,12.4-12.4,18.82l-4.08-.3c-1.1-.09-2.21-.17-3.34-.26s-2.5-.19-4.12-.3c-3.12,5.03-5.74,9.53-7.85,13.49s-3.73,7.59-4.86,10.89-1.69,6.42-1.69,9.37c0,3.99,1.59,5.99,4.77,5.99,2.2,0,5.07-1.17,8.63-3.51s8.31-5.94,14.27-10.8v5.81c-15.61,16.95-27.15,25.42-34.61,25.42-2.6,0-4.7-1.01-6.29-3.04-1.59-2.02-2.38-4.63-2.38-7.81,0-2.14.45-4.68,1.34-7.63.9-2.95,2.5-7.4,4.81-13.36-.81.69-1.58,1.37-2.3,2.04s-1.39,1.27-2,1.82-1.26,1.13-1.95,1.73c-.69.61-1.39,1.23-2.08,1.87v-5.99c6.07-5.09,13.42-14.02,22.03-26.8-.87-.06-1.68-.1-2.43-.13s-1.65-.04-2.69-.04c-3.41,0-5.96.23-7.63.69-.69.17-1.34.36-1.95.56s-1.03.3-1.26.3-.35-.17-.35-.52c0-1.91,1.18-4.77,3.56-8.59,1.91-3.24,3.72-5.64,5.42-7.2,1.71-1.56,3.79-2.62,6.25-3.17,2.46-.55,5.91-.82,10.37-.82h0Z" style="fill:#306fff; stroke-width:0px;"/><path d="M664.91,115.12c8.79-7.98,17.32-13.91,25.59-17.78s14.66-5.81,19.17-5.81c1.21,0,2.34.51,3.38,1.52,1.04,1,1.88,2.19,2.47,3.51.61,1.33.91,2.31.91,2.95,0,1.04-.41,1.81-1.21,2.3-.81.49-2.23,1.08-4.25,1.78.4.93.92,2.11,1.56,3.56s1.13,2.62,1.47,3.51c.35.9.52,1.69.52,2.39,0,1.39-1.4,3.98-4.21,7.76-2.81,3.79-4.77,6.58-5.9,8.37-1.13,1.79-1.69,3.99-1.69,6.59,0,4.28,1.96,6.42,5.9,6.42s10.38-3.79,19-11.36v5.29c-14.63,16.25-25.1,24.38-31.4,24.38-2.26,0-3.86-.74-4.81-2.21s-1.43-3.66-1.43-6.55c0-4.57,1.65-11.19,4.94-19.86-8.44,9.37-14.72,16.03-18.82,20-4.11,3.96-7.49,5.94-10.15,5.94-1.27,0-2.86-1.1-4.77-3.3-1.91-2.2-3.6-5.04-5.07-8.54-1.47-3.5-2.21-7.13-2.21-10.89,0-2.72.26-4.99.78-6.81s1.53-3.69,3.04-5.59c1.5-1.91,3.9-4.42,7.2-7.55v-.02ZM706.46,105.58c-15.04,6.88-25.75,12.72-32.14,17.52s-9.59,9.75-9.59,14.83c0,1.85.32,3.37.95,4.55.64,1.19,1.5,1.78,2.6,1.78.64,0,1.76-.4,3.38-1.21,6.07-3.58,11.62-8.25,16.66-14.01,5.03-5.75,11.07-13.58,18.13-23.46h.01Z" style="fill:#306fff; stroke-width:0px;"/><path d="M779.07,130.82v5.81c-6.19,6.07-11.23,10.79-15.14,14.14-3.9,3.35-7.55,5.96-10.93,7.81-3.38,1.85-6.69,2.78-9.93,2.78s-6.1-1.26-8.76-3.77c-2.66-2.52-4.74-5.81-6.25-9.89-1.5-4.08-2.26-8.4-2.26-12.97,0-3.93.87-7.43,2.6-10.5,1.74-3.07,5.09-7.03,10.06-11.88,5.9-5.78,11.38-10.25,16.44-13.4s9.04-4.73,11.93-4.73c2.08,0,3.85.72,5.29,2.17s2.17,3.27,2.17,5.46c0,1.85-.95,4.48-2.86,7.89-1.91,3.41-4.05,6.38-6.42,8.89-2.37,2.52-4.25,3.77-5.64,3.77-1.5,0-2.25-.81-2.25-2.43.06-.46.1-.9.13-1.3s.04-.81.04-1.21c0-.69-.25-1.08-.74-1.17s-1.08.13-1.78.65c-5.78,4.05-9.75,6.9-11.88,8.54-2.14,1.65-3.83,3.31-5.07,4.99s-1.87,3.44-1.87,5.29c0,3.41,1.1,6.19,3.3,8.33s5.06,3.21,8.59,3.21,8.02-1.4,13.14-4.21c5.12-2.8,11.15-6.9,18.09-12.27h0Z" style="fill:#306fff; stroke-width:0px;"/><path d="M844.13,130.65v5.81c-6.48,7.58-11.91,13.32-16.31,17.22s-8.07,5.86-11.02,5.86-5.39-.84-7.68-2.52c-2.29-1.68-4.34-3.99-6.16-6.94-1.82-2.95-3.98-7.05-6.46-12.32-2.95,3.64-5.61,7.04-7.98,10.19-2.37,3.15-4.02,5.25-4.94,6.29-.93,1.04-1.77,1.56-2.52,1.56-1.56,0-2.69-1-3.38-2.99-.69-2-1.04-4.9-1.04-8.72,0-5.21.62-10.22,1.87-15.05,1.24-4.83,3.04-9.53,5.38-14.1s5.35-9.5,9.02-14.79c3.67-5.29,7.79-10.83,12.36-16.61,6.3-7.98,11.74-14.5,16.31-19.56,4.57-5.06,8.54-8.88,11.93-11.45,3.38-2.57,6.2-3.86,8.46-3.86,2.78,0,4.16,1.24,4.16,3.73,0,2.14-5.12,9.85-15.35,23.12-10.24,13.27-25.16,31.39-44.76,54.35v7.46c13.13-14.05,23.69-24.49,31.71-31.31,8.01-6.82,14.21-10.24,18.61-10.24,1.79,0,3.18,1.06,4.16,3.17s1.47,4.55,1.47,7.33c0,5.67-2.43,10.92-7.29,15.74-4.86,4.83-12.32,10.37-22.38,16.61,1.74,2.6,3.27,4.5,4.6,5.68,1.33,1.19,3.01,1.78,5.03,1.78,1.79,0,3.73-.61,5.81-1.82s4.21-2.75,6.38-4.6,5.51-4.86,10.02-9.02h-.01ZM809.86,135.07c2.2-1.45,4.93-3.69,8.2-6.72,3.27-3.04,6.06-6.19,8.37-9.46s3.47-6,3.47-8.2c0-.92-.41-1.39-1.21-1.39-2.2,0-5.97,2.11-11.32,6.33-5.35,4.22-10.57,9.63-15.66,16.22,2.2,0,4.92,1.07,8.15,3.21h0ZM951.78,140.71l2.86,2.17c-.75,1.62-1.47,3.04-2.17,4.25-.69,1.21-1.53,2.69-2.52,4.42-.98,1.73-1.73,3.04-2.25,3.9-4.34,7.58-8.41,11.36-12.23,11.36-1.62,0-3.01-.64-4.16-1.91-1.16-1.27-1.73-3.01-1.73-5.2,0-3.12,1.11-7.4,3.34-12.84,2.23-5.43,5.67-12.13,10.32-20.08s10.51-16.96,17.57-27.02c7.05-10.06,15.01-20.67,23.85-31.84-5.09-.75-11.13-1.13-18.13-1.13-8.04,0-16.99.9-26.85,2.69s-18.45,3.86-25.76,6.2c-7.32,2.34-10.97,4.06-10.97,5.16,0,.41.14.68.43.82.29.15.77.26,1.43.35s1.52.19,2.56.3c6.77.93,10.15,1.97,10.15,3.12,0,.58-1.47.85-4.42.82s-6.51-.04-10.67-.04c-3.3,0-5.68-.13-7.16-.39s-2.46-.75-2.95-1.47-.74-1.84-.74-3.34c0-.98.29-3.12.87-6.42,1.1-6.13,2.79-11.04,5.07-14.75,2.28-3.7,5.78-6.72,10.5-9.06,4.71-2.34,11.2-4.21,19.47-5.59,13.88-2.37,25.36-3.56,34.44-3.56,6.71,0,12,.27,15.88.82,3.87.55,6.72,1.34,8.54,2.39,1.82,1.04,2.98,2.07,3.47,3.08s1.14,2.76,1.95,5.25l2.69,7.98c.17.52.32.94.43,1.26.12.32.22.65.3,1,.09.35.13.67.13.95,0,2.26-.51,4.28-1.52,6.07s-2.86,4.48-5.55,8.07-4.67,6.39-5.94,8.41c-14.92,24.23-25.1,42.16-30.53,53.78v.02ZM991.94,115.12c8.79-7.98,17.32-13.91,25.59-17.78s14.66-5.81,19.17-5.81c1.21,0,2.34.51,3.38,1.52,1.04,1,1.88,2.19,2.47,3.51.61,1.33.91,2.31.91,2.95,0,1.04-.41,1.81-1.21,2.3-.81.49-2.23,1.08-4.25,1.78.4.93.92,2.11,1.56,3.56s1.13,2.62,1.47,3.51c.35.9.52,1.69.52,2.39,0,1.39-1.4,3.98-4.21,7.76-2.81,3.79-4.77,6.58-5.9,8.37-1.13,1.79-1.69,3.99-1.69,6.59,0,4.28,1.96,6.42,5.9,6.42s10.38-3.79,19-11.36v5.29c-14.63,16.25-25.1,24.38-31.4,24.38-2.26,0-3.86-.74-4.81-2.21s-1.43-3.66-1.43-6.55c0-4.57,1.65-11.19,4.94-19.86-8.44,9.37-14.72,16.03-18.82,20-4.11,3.96-7.49,5.94-10.15,5.94-1.27,0-2.86-1.1-4.77-3.3-1.91-2.2-3.6-5.04-5.07-8.54-1.47-3.5-2.21-7.13-2.21-10.89,0-2.72.26-4.99.78-6.81s1.53-3.69,3.04-5.59c1.5-1.91,3.9-4.42,7.2-7.55v-.02ZM1033.49,105.58c-15.04,6.88-25.75,12.72-32.14,17.52s-9.59,9.75-9.59,14.83c0,1.85.32,3.37.95,4.55.64,1.19,1.5,1.78,2.6,1.78.64,0,1.76-.4,3.38-1.21,6.07-3.58,11.62-8.25,16.66-14.01,5.03-5.75,11.07-13.58,18.13-23.46h.01Z" style="fill:#306fff; stroke-width:0px;"/><path d="M1111.3,130.82v5.64c-6.02,3.82-10.76,5.72-14.23,5.72-1.91,0-3.93-.32-6.07-.95-5.2,6.59-9.67,11.42-13.4,14.49s-7.47,4.6-11.23,4.6c-4.34,0-7.68-2.29-10.02-6.85-2.34-4.57-3.51-10.24-3.51-17,0-9.2,2.78-19.21,8.33-30.06,5.56-10.85,12.29-21.07,20.08-30.45,7.84-9.46,15.43-17.28,22.77-23.46,7.34-6.19,12.32-9.28,14.92-9.28s3.73,1.71,3.73,5.12c0,15.15-19.43,41.58-58.29,79.29-.12,1.04-.17,3.09-.17,6.16,0,7.98,2.14,11.97,6.42,11.97,1.68,0,3.37-.68,5.07-2.04,1.71-1.36,4.32-3.95,7.85-7.76-1.39-3.12-2.08-5.44-2.08-6.94,0-3.18,1.3-6.62,3.9-10.32s5.57-6.9,8.89-9.59c3.33-2.69,5.74-4.03,7.24-4.03,2.37,0,3.56,1.71,3.56,5.12,0,2.6-.68,5.72-2.04,9.37-1.36,3.64-3.34,7.81-5.94,12.49.98.81,1.76,1.4,2.34,1.78s1.45.56,2.6.56c2.66,0,5.75-1.18,9.28-3.56v-.02ZM1067.24,117.81c3.01-2.6,6.03-5.68,9.06-9.24s7.47-9.01,13.32-16.35c5.61-7.05,10.02-12.94,13.23-17.65s5.62-8.63,7.24-11.75c1.62-3.12,2.43-5.26,2.43-6.42,0-.87-.23-1.3-.69-1.3-1.27,0-3.92,2.1-7.94,6.29-4.02,4.19-8.6,9.93-13.75,17.22-7.11,10.06-12.26,17.64-15.44,22.73-3.18,5.09-5.67,10.58-7.46,16.48h0Z" style="fill:#306fff; stroke-width:0px;"/><path d="M1110.96,133.08v-2.08c14.92-15.73,25.18-26.75,30.79-33.05,1.27-7.11,4.34-10.67,9.19-10.67,1.21,0,2.52.35,3.9,1.04l.52,1.65c-.23.69-.35,1.68-.35,2.95,0,1.1.42,3.14,1.26,6.12s1.49,5.48,1.95,7.5.69,4.31.69,6.85c0,3.82-.87,7.48-2.6,10.97-1.73,3.5-4.25,6.85-7.55,10.06-3.3,3.21-7.55,6.49-12.75,9.85,2.08.35,3.73.52,4.94.52,2.37,0,4.93-.59,7.68-1.78,2.75-1.18,5.55-2.78,8.41-4.77,2.86-2,6.2-4.58,10.02-7.76v5.81c-7.4,7.23-14.02,12.71-19.86,16.44s-10.87,5.59-15.09,5.59c-5.44,0-10.47-2.31-15.09-6.94-2.72-2.78-4.41-5.43-5.08-7.98-.67-2.54-1-5.99-1-10.32h.02ZM1143.31,119.8l-1.56-12.66c-3.59,4.05-11.25,11.83-22.99,23.33,3.47.75,5.84,1.76,7.11,3.04,1.27,1.27,3.06,3.73,5.38,7.37,3.93-1.62,6.95-3.83,9.07-6.64,2.11-2.8,3.17-6.64,3.17-11.49,0-.58-.01-1.1-.04-1.56s-.07-.92-.13-1.39h0Z" style="fill:#306fff; stroke-width:0px;"/><g style="isolation:isolate;"><text transform="translate(943.45 229.96)" style="fill:#00d797; font-family:ArialMT, Arial; font-size:24px; isolation:isolate;"><tspan x="0" y="0">version: ${version}</tspan></text></g></svg>`
|
|
6
|
-
// Make it base64
|
|
7
7
|
const svg64 = encode(xml)
|
|
8
8
|
const b64Start = 'data:image/svg+xml;base64,'
|
|
9
|
-
// Prepend a "header"
|
|
10
9
|
const image64 = b64Start + svg64
|
|
11
10
|
const style =
|
|
12
11
|
'font-size: 1px; padding: ' +
|
|
@@ -16,11 +15,11 @@ const printVersion = (version: string) => {
|
|
|
16
15
|
'px; line-height: ' +
|
|
17
16
|
Math.floor(height / 2) +
|
|
18
17
|
'px;'
|
|
19
|
-
// Logging part
|
|
20
18
|
window.console.log(
|
|
21
19
|
'%c' + '+',
|
|
22
20
|
style +
|
|
23
21
|
`background-image: url(${image64});background-size: ${width}px ${height}px;background-repeat: norepeat; color: transparent;`
|
|
24
22
|
)
|
|
25
23
|
}
|
|
26
|
-
|
|
24
|
+
|
|
25
|
+
export default logVersion
|
package/dist/src/lib/banner.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { throttle } from 'throttle-debounce';
|
|
2
|
-
import { ITabData } from '../model/TabModel';
|
|
3
|
-
|
|
4
|
-
declare const _default: () => {
|
|
5
|
-
openNewTab: throttle<(tab: ITabData, renew?: any) => Promise<unknown>>;
|
|
6
|
-
setIFramePath: (path: string) => void;
|
|
7
|
-
active: (id: string, route?: boolean) => void;
|
|
8
|
-
reset: () => void;
|
|
9
|
-
getWrapper: () => Element;
|
|
10
|
-
};
|
|
11
|
-
export default _default;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { ITabBase } from '../model/TabModel';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* compress tab info to string
|
|
5
|
-
* format:
|
|
6
|
-
* {tab id}{current timestamp}{tab name}{tab closable}
|
|
7
|
-
* @param tabData
|
|
8
|
-
*/
|
|
9
|
-
export declare const encodeTabInfo: (tabData: ITabBase) => string;
|
|
10
|
-
export declare const decodeTabInfo: (tab: string) => ITabBase;
|
|
11
|
-
export declare const createPageId: (tabId: string, path: string, query: Object) => string;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 滚动到指定位置
|
|
3
|
-
* @export
|
|
4
|
-
* @param {Element} wrap 滚动区域
|
|
5
|
-
* @param {number} [left=0]
|
|
6
|
-
* @param {number} [top=0]
|
|
7
|
-
*/
|
|
8
|
-
export declare const _scrollTo: ({ wrap, left, top, smooth }: {
|
|
9
|
-
wrap: HTMLElement | null;
|
|
10
|
-
left?: number;
|
|
11
|
-
top?: number;
|
|
12
|
-
smooth?: boolean;
|
|
13
|
-
}) => void;
|
|
14
|
-
/**
|
|
15
|
-
* 指定元素滚动到可视区域
|
|
16
|
-
* @export
|
|
17
|
-
* @param {Element} el 目标元素
|
|
18
|
-
* @param {Element} wrap 滚动区域
|
|
19
|
-
* @param {String} block 垂直方向的对齐,可选:'start', 'center', 'end', 或 'nearest'
|
|
20
|
-
* @param {String} inline 水平方向的对齐,可选值同上
|
|
21
|
-
*/
|
|
22
|
-
export declare function _scrollIntoView({ el, wrap, block, inline }: {
|
|
23
|
-
el: HTMLElement;
|
|
24
|
-
wrap: any;
|
|
25
|
-
block?: any;
|
|
26
|
-
inline?: any;
|
|
27
|
-
}): void;
|
|
28
|
-
export declare const getScrollbarWidth: () => number;
|
|
29
|
-
/**
|
|
30
|
-
* 获取最大z-index
|
|
31
|
-
* @returns 最大z-index的值
|
|
32
|
-
*/
|
|
33
|
-
export declare const getMaxZIndex: (key?: string) => number;
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { useRouter } from 'vue-router'
|
|
2
|
-
import useTabpanel from '../hooks/useTabpanel'
|
|
3
|
-
import { throttle } from 'throttle-debounce'
|
|
4
|
-
import type { ITabData } from '../model/TabModel'
|
|
5
|
-
import { defu } from 'defu'
|
|
6
|
-
|
|
7
|
-
import { encodeTabInfo } from '../utils/TabIdHelper'
|
|
8
|
-
import { uriDecode } from '../utils/UriHelper'
|
|
9
|
-
import { ulid } from 'ulid'
|
|
10
|
-
import { MittType, useEmitter } from './useTabMitt'
|
|
11
|
-
import { nextTick } from 'vue'
|
|
12
|
-
|
|
13
|
-
let iframePath: string
|
|
14
|
-
export default () => {
|
|
15
|
-
const router = useRouter()
|
|
16
|
-
const { active, hasTab, pageShown, reset, canAddTab, renewTab, getTab } = useTabpanel()
|
|
17
|
-
const emitter = useEmitter()
|
|
18
|
-
/**
|
|
19
|
-
* 打开新的TAB页面
|
|
20
|
-
* @param tab
|
|
21
|
-
* @param to
|
|
22
|
-
*/
|
|
23
|
-
const openNewTab = throttle(500, (tab: ITabData, renew = false) => {
|
|
24
|
-
return new Promise((resolve, reject) => {
|
|
25
|
-
if (!pageShown.value) {
|
|
26
|
-
reject()
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
const tabInfo = defu(tab, {
|
|
30
|
-
refreshable: true,
|
|
31
|
-
closable: true,
|
|
32
|
-
iframe: false
|
|
33
|
-
})
|
|
34
|
-
if (tabInfo.id && renew && hasTab(tabInfo.id!)) {
|
|
35
|
-
renewTab(tab)
|
|
36
|
-
const currentTab = getTab(tab.id!)
|
|
37
|
-
// if current tab is active, then must reload the component of router view for complete remove the cache!!!
|
|
38
|
-
if (currentTab?.active) {
|
|
39
|
-
pageShown.value = false
|
|
40
|
-
nextTick(() => {
|
|
41
|
-
pageShown.value = true
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* In the function of openNewTab, if the tab already 'ACTIVE' then do nothing.
|
|
47
|
-
*/
|
|
48
|
-
if (hasTab(tabInfo.id!) && !renew) {
|
|
49
|
-
emitter.emit(MittType.TAB_ACTIVE, { id: tabInfo.id! })
|
|
50
|
-
// active(tabInfo.id!)
|
|
51
|
-
resolve(tabInfo.id)
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
if (!tabInfo.id) {
|
|
55
|
-
tabInfo.id = ulid()
|
|
56
|
-
}
|
|
57
|
-
if (!canAddTab()) {
|
|
58
|
-
reject('Max Size')
|
|
59
|
-
return
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// if (initialed) {
|
|
63
|
-
// // 增加tab
|
|
64
|
-
// let activeTab: ITabItem | null = null
|
|
65
|
-
// for (const tab of unref(tabs)) {
|
|
66
|
-
// tab.active = false
|
|
67
|
-
// }
|
|
68
|
-
// activeTab = {
|
|
69
|
-
// id: tabInfo.id!,
|
|
70
|
-
// title: tabInfo.title,
|
|
71
|
-
// closable: tabInfo.closable!,
|
|
72
|
-
// refreshable: tabInfo.refreshable!,
|
|
73
|
-
// iframe: tabInfo.iframe!,
|
|
74
|
-
// url: tabInfo.iframe ? tab.path : null,
|
|
75
|
-
// active: true,
|
|
76
|
-
// pages: new Stack<ITabPage>()
|
|
77
|
-
// } as ITabItem
|
|
78
|
-
// addTab(activeTab).finally(() => {
|
|
79
|
-
// toPage(tab, tabInfo)
|
|
80
|
-
// resolve(tabInfo.id)
|
|
81
|
-
// })
|
|
82
|
-
// } else {
|
|
83
|
-
toPage(tab, tabInfo)
|
|
84
|
-
resolve(tabInfo.id)
|
|
85
|
-
// }
|
|
86
|
-
})
|
|
87
|
-
})
|
|
88
|
-
const toPage = (tab: ITabData, tabInfo: any) => {
|
|
89
|
-
const __tab = encodeTabInfo(tabInfo)
|
|
90
|
-
let query = defu(
|
|
91
|
-
{
|
|
92
|
-
__tab
|
|
93
|
-
},
|
|
94
|
-
tab.query
|
|
95
|
-
) as Record<string, string>
|
|
96
|
-
let path
|
|
97
|
-
if (!tab.iframe) {
|
|
98
|
-
const url = uriDecode(tab.path)
|
|
99
|
-
path = url.path
|
|
100
|
-
query = defu(url.query, query)
|
|
101
|
-
} else {
|
|
102
|
-
const __src = encodeURIComponent(tab.path as string)
|
|
103
|
-
path = iframePath
|
|
104
|
-
query['__src'] = __src
|
|
105
|
-
}
|
|
106
|
-
router.push({
|
|
107
|
-
path,
|
|
108
|
-
query
|
|
109
|
-
})
|
|
110
|
-
}
|
|
111
|
-
const setIFramePath = (path: string) => {
|
|
112
|
-
iframePath = path
|
|
113
|
-
}
|
|
114
|
-
const getWrapper = () =>{
|
|
115
|
-
return document.getElementsByClassName('cache-page-wrapper')[0]
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return { openNewTab, setIFramePath, active, reset,getWrapper }
|
|
119
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { Emitter, EventType } from 'mitt'
|
|
2
|
-
import mitt from 'mitt'
|
|
3
|
-
import { type App, inject } from 'vue'
|
|
4
|
-
// const emitter = mitt()
|
|
5
|
-
// Cutsom type
|
|
6
|
-
declare module '@vue/runtime-core' {
|
|
7
|
-
export interface ComponentCustomProperties {
|
|
8
|
-
$layerEmitter: Emitter<Record<EventType, unknown>>
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
const emitter: Emitter<Record<EventType, unknown>> = mitt()
|
|
12
|
-
|
|
13
|
-
const plugin = {
|
|
14
|
-
install(app: App) {
|
|
15
|
-
// const emitter = mitt()
|
|
16
|
-
app.provide('tabEmitter', emitter)
|
|
17
|
-
// app.config.globalProperties.$emitter = emitter
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
// export const setEmitter = (mitter: Emitter<Record<EventType, unknown>>) => {
|
|
21
|
-
// emitter = mitter
|
|
22
|
-
// }
|
|
23
|
-
export const useEmitter = <T extends Record<EventType, unknown>>(): Emitter<T> => {
|
|
24
|
-
return inject('tabEmitter')!
|
|
25
|
-
}
|
|
26
|
-
export enum MittType {
|
|
27
|
-
PAGE_LOADING = 'PAGE_LOADING',
|
|
28
|
-
TAB_ACTIVE = 'TAB_ACTIVE'
|
|
29
|
-
}
|
|
30
|
-
export default plugin
|