vue-stack-tabs 0.1.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 (61) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +3 -0
  3. package/dist/favicon.svg +10 -0
  4. package/dist/style.css +1 -0
  5. package/dist/vue-stack-tabs.es.js +6386 -0
  6. package/dist/vue-stack-tabs.umd.js +46 -0
  7. package/package.json +92 -0
  8. package/src/lib/StackTabs.vue +136 -0
  9. package/src/lib/assets/image/close.svg +6 -0
  10. package/src/lib/assets/image/close_all.svg +9 -0
  11. package/src/lib/assets/image/close_fill.svg +1 -0
  12. package/src/lib/assets/image/close_lefts.svg +1 -0
  13. package/src/lib/assets/image/close_other.svg +1 -0
  14. package/src/lib/assets/image/close_rights.svg +1 -0
  15. package/src/lib/assets/image/disable.svg +11 -0
  16. package/src/lib/assets/image/fullscreen.svg +1 -0
  17. package/src/lib/assets/image/left_arrow.svg +1 -0
  18. package/src/lib/assets/image/loading.svg +15 -0
  19. package/src/lib/assets/image/mask.svg +7 -0
  20. package/src/lib/assets/image/move.svg +6 -0
  21. package/src/lib/assets/image/reload.svg +3 -0
  22. package/src/lib/assets/image/reload_all.svg +6 -0
  23. package/src/lib/assets/image/reload_lefts.svg +15 -0
  24. package/src/lib/assets/image/reload_rights.svg +15 -0
  25. package/src/lib/assets/image/restore.svg +1 -0
  26. package/src/lib/assets/image/right_arrow.svg +1 -0
  27. package/src/lib/assets/image/scroll_pointer.svg +13 -0
  28. package/src/lib/assets/style/common/mixins.scss +45 -0
  29. package/src/lib/assets/style/common/var.scss +65 -0
  30. package/src/lib/assets/style/icon.scss +93 -0
  31. package/src/lib/assets/style/index.scss +3 -0
  32. package/src/lib/assets/style/stackTab.scss +395 -0
  33. package/src/lib/assets/style/transition.scss +40 -0
  34. package/src/lib/banner.ts +51 -0
  35. package/src/lib/components/ContextMenu/ContextMenuItem.vue +15 -0
  36. package/src/lib/components/ContextMenu/index.vue +128 -0
  37. package/src/lib/components/TabHeader/TabHeaderButton.vue +35 -0
  38. package/src/lib/components/TabHeader/TabHeaderItem.vue +63 -0
  39. package/src/lib/components/TabHeader/TabHeaderScroll.vue +240 -0
  40. package/src/lib/components/TabHeader/index.vue +134 -0
  41. package/src/lib/hooks/useContextMenu.ts +50 -0
  42. package/src/lib/hooks/useStackTab.ts +65 -0
  43. package/src/lib/hooks/useTabLoading.ts +48 -0
  44. package/src/lib/hooks/useTabRouter.ts +95 -0
  45. package/src/lib/hooks/useTabpanel.tsx +489 -0
  46. package/src/lib/i18n/index.ts +72 -0
  47. package/src/lib/i18n/lang/en.ts +15 -0
  48. package/src/lib/i18n/lang/zh-CN.ts +15 -0
  49. package/src/lib/iframe.vue +7 -0
  50. package/src/lib/index.ts +25 -0
  51. package/src/lib/model/TabModel.ts +182 -0
  52. package/src/lib/utils/TabIdHelper.ts +76 -0
  53. package/src/lib/utils/TabScrollHelper.ts +104 -0
  54. package/src/lib/utils/UriHelper.ts +22 -0
  55. package/types/banner.d.ts +2 -0
  56. package/types/hooks/useStackTab.d.ts +8 -0
  57. package/types/hooks/useTabLoading.d.ts +5 -0
  58. package/types/hooks/useTabRouter.d.ts +5 -0
  59. package/types/iframe.vue.d.ts +2 -0
  60. package/types/index.d.ts +10 -0
  61. package/types/model/TabModel.d.ts +114 -0
@@ -0,0 +1,489 @@
1
+ import type { ITabData, ITabItem, ITabPage } from '@/lib/model/TabModel'
2
+ import { defineComponent, onActivated, onUnmounted, ref, unref } from 'vue'
3
+ import type { DefineComponent, VNode } from 'vue'
4
+ import { useRouter } from 'vue-router'
5
+ import type { RouteLocationNormalizedLoaded } from 'vue-router'
6
+ import { ulid } from 'ulidx'
7
+ import { encodeTabInfo, createPageId, decodeTabInfo } from '@/lib/utils/TabIdHelper'
8
+ import { defu } from 'defu'
9
+ import { Stack } from '@/lib/model/TabModel'
10
+ import { uriDecode } from '@/lib/utils/UriHelper'
11
+
12
+ const tabs = ref<ITabItem[]>([])
13
+ const defaultTabs: ITabItem[] = []
14
+ // cache
15
+ const caches = ref<string[]>([])
16
+ // Dynamic components
17
+ const components = new Map<string, any>()
18
+ const deletableCache = new Set<String>()
19
+ const pageShown = ref<boolean>(true)
20
+ const SESSION_TAB_NAME = 'stacktab-active-tab'
21
+ export default () => {
22
+ const router = useRouter()
23
+ const size = (): number => {
24
+ return tabs.value.length
25
+ }
26
+ /**
27
+ * Init the Tab list
28
+ */
29
+ const initial = (staticTabs: ITabData[]) => {
30
+ // add default tabs
31
+ defaultTabs.splice(0)
32
+ for (const item of staticTabs) {
33
+ const id = ulid()
34
+ const __tab = encodeTabInfo(defu(item, { id }))
35
+ const uri = uriDecode(item.path)
36
+ const config = defu(item, {
37
+ closable: true,
38
+ refreshable: true,
39
+ iframe: false
40
+ })
41
+ const cacheName = createPageId(id, uri.path, uri.query)
42
+ const page: ITabPage = {
43
+ id: cacheName,
44
+ tabId: id,
45
+ path: uri.path,
46
+ query: defu(uri.query, { __tab })
47
+ }
48
+ const pages = new Stack<ITabPage>()
49
+ pages.push(page)
50
+ const tab: ITabItem = {
51
+ id,
52
+ title: config.title,
53
+ closable: config.closable,
54
+ refreshable: config.refreshable,
55
+ iframe: config.iframe,
56
+ active: false,
57
+ pages
58
+ }
59
+
60
+ defaultTabs.push(tab)
61
+ tabs.value.push(tab)
62
+ caches.value.push(cacheName)
63
+ }
64
+
65
+ // add temp tab from session
66
+ const tempTab = window.sessionStorage.getItem(SESSION_TAB_NAME)
67
+ if (tempTab !== null && tempTab !== undefined) {
68
+ // const tempItems = JSON.parse(window.sessionStorage.getItem('tabItems')!)
69
+ const temp = defu({ pages: new Stack<ITabPage>() }, JSON.parse(tempTab)) as ITabItem
70
+ let hasTab = false
71
+ for (const tab of tabs.value) {
72
+ if (tab.id === temp.id) {
73
+ hasTab = true
74
+ break
75
+ }
76
+ }
77
+ if (!hasTab) {
78
+ tabs.value.push(temp)
79
+ }
80
+ }
81
+ }
82
+ const hasTab = (id: string) => {
83
+ for (const tab of tabs.value) {
84
+ if (tab.id === id) {
85
+ return true
86
+ }
87
+ }
88
+ return false
89
+ }
90
+ const addTab = (tab: ITabItem) => {
91
+ tabs.value.push(tab)
92
+ }
93
+ const getTab = (id: string) => {
94
+ for (const tab of tabs.value) {
95
+ if (tab.id === id) {
96
+ return tab
97
+ }
98
+ }
99
+ return null
100
+ }
101
+ const addPage = (route: RouteLocationNormalizedLoaded, component: VNode): DefineComponent => {
102
+ let cacheComponent: DefineComponent
103
+ const tabInfo = decodeTabInfo(route.query.__tab as string)
104
+ const cacheName = createPageId(tabInfo.id!, route.path, route.query.valueOf())
105
+ const src = route.query.__src
106
+ // const cacheSet = new Set(caches.value)
107
+ if (components.has(cacheName)) {
108
+ cacheComponent = components.get(cacheName)!
109
+ } else {
110
+ // 增加控件
111
+ cacheComponent = defineComponent({
112
+ name: cacheName!,
113
+ components: {
114
+ DynamicComponent: component
115
+ },
116
+ setup() {
117
+ // onMounted(() => {
118
+ // addCache(cacheName)
119
+ // })
120
+ onActivated(() => {
121
+ removeDeletableCache()
122
+ component.props = null
123
+ })
124
+ onUnmounted(() => {
125
+ console.log('on unMounted', cacheName)
126
+ // setTimeout(() => {
127
+ // 刷新时重置路由
128
+ // pageShown.value = true
129
+ // }, 500)
130
+ })
131
+ return () => (
132
+ <div class="cache-page-wrapper" id={tabInfo.id}>
133
+ <dynamic-component tId={tabInfo.id} pId={cacheName} />
134
+ </div>
135
+ )
136
+ }
137
+ })
138
+ components.set(cacheName, cacheComponent)
139
+
140
+ // 增加tab
141
+ let activeTab: ITabItem | null = null
142
+ for (const tab of unref(tabs)) {
143
+ tab.active = false
144
+ if (tab.id === tabInfo.id) {
145
+ activeTab = tab as ITabItem
146
+ }
147
+ }
148
+ const page: ITabPage = {
149
+ id: cacheName,
150
+ tabId: tabInfo.id!,
151
+ path: route.path,
152
+ query: route.query as Record<string, string>
153
+ }
154
+
155
+ if (activeTab === null) {
156
+ const pages = new Stack<ITabPage>()
157
+ pages.push(page)
158
+ activeTab = {
159
+ id: tabInfo.id!,
160
+ title: tabInfo.title,
161
+ closable: tabInfo.closable!,
162
+ refreshable: tabInfo.refreshable!,
163
+ iframe: tabInfo.iframe!,
164
+ url: decodeURIComponent(src as string),
165
+ active: true,
166
+ pages
167
+ }
168
+ tabs.value.push(activeTab!)
169
+ } else {
170
+ activeTab.active = true
171
+ if (activeTab.pages.isEmpty() || activeTab.pages.peek()!.id !== page.id) {
172
+ activeTab.pages.push(page)
173
+ }
174
+ }
175
+ updateSession(activeTab)
176
+ //
177
+ }
178
+
179
+ // 加入缓存
180
+ // const cacheSet = new Set(caches.value)
181
+ // if (routerAlive.value) {
182
+ // if (!cacheSet.has(cacheName)) {
183
+ // caches.value.push(cacheName)
184
+ // }
185
+ // }
186
+ addCache(cacheName)
187
+ return cacheComponent
188
+ }
189
+ /**
190
+ * if id is null , then remove all tab that deleted is true
191
+ * @param id
192
+ */
193
+ const removeTab = (id: string): string => {
194
+ let activeTabId = ''
195
+ for (let i = tabs.value.length - 1; i >= 0; i--) {
196
+ if (id === unref(tabs)[i].id) {
197
+ if (!unref(tabs)[i].closable) {
198
+ break
199
+ }
200
+ for (const item of unref(tabs)[i].pages.list()) {
201
+ removeComponent(item.id)
202
+ markDeletableCache(item.id)
203
+ }
204
+ unref(tabs)[i].pages.clear()
205
+ if (tabs.value.length > 1) {
206
+ if (i === 0) {
207
+ activeTabId = unref(tabs)[1].id
208
+ } else {
209
+ activeTabId = unref(tabs)[i - 1].id
210
+ }
211
+ }
212
+ unref(tabs).splice(i, 1)
213
+
214
+ break
215
+ }
216
+ }
217
+ active(activeTabId)
218
+ // if remove inactive tab,then we need remove the cache manually.
219
+ if (activeTabId !== id) {
220
+ removeDeletableCache()
221
+ }
222
+ return activeTabId
223
+ }
224
+
225
+ const removeAllTabs = () => {
226
+ const uTabs = unref(tabs)
227
+ for (let i = uTabs.length - 1; i >= 0; i--) {
228
+ if (uTabs[i].closable) {
229
+ for (const item of uTabs[i].pages.list()) {
230
+ removeComponent(item.id)
231
+ markDeletableCache(item.id)
232
+ }
233
+ unref(tabs)[i].pages.clear()
234
+ unref(tabs).splice(i, 1)
235
+ }
236
+ }
237
+ for (const stay of uTabs) {
238
+ if (stay.active) {
239
+ removeDeletableCache()
240
+ return
241
+ }
242
+ }
243
+ // 如果都是非Active状态,就把最后一个active
244
+ active(uTabs[uTabs.length - 1].id)
245
+ }
246
+ const removeOtherTabs = (id: string) => {
247
+ const uTabs = unref(tabs)
248
+ let activeTab
249
+ for (let i = uTabs.length - 1; i >= 0; i--) {
250
+ if (uTabs[i].id === id) {
251
+ activeTab = uTabs[i]
252
+ } else if (uTabs[i].closable && uTabs[i].id !== id) {
253
+ for (const item of uTabs[i].pages.list()) {
254
+ removeComponent(item.id)
255
+ markDeletableCache(item.id)
256
+ }
257
+ unref(tabs)[i].pages.clear()
258
+ unref(tabs).splice(i, 1)
259
+ }
260
+ }
261
+ if (!activeTab!.active) {
262
+ active(id)
263
+ } else {
264
+ removeDeletableCache()
265
+ }
266
+ }
267
+ /**
268
+ * 关闭左边
269
+ * @param id
270
+ */
271
+ const removeLeftTabs = (id: string) => {
272
+ let startIndex = -1
273
+ const uTabs = unref(tabs)
274
+ for (let i = 0; i < uTabs.length; i++) {
275
+ if (uTabs[i].id === id) {
276
+ startIndex = i - 1
277
+ break
278
+ }
279
+ }
280
+ for (let i = startIndex; i >= 0; i--) {
281
+ if (uTabs[i].closable) {
282
+ for (const item of uTabs[i].pages.list()) {
283
+ removeComponent(item.id)
284
+ markDeletableCache(item.id)
285
+ }
286
+ unref(tabs)[i].pages.clear()
287
+ unref(tabs).splice(i, 1)
288
+ }
289
+ }
290
+ for (const stay of uTabs) {
291
+ if (stay.active) {
292
+ removeDeletableCache()
293
+ return
294
+ }
295
+ }
296
+ // 如果都是非Active状态,就把最后一个active
297
+ active(uTabs[0].id)
298
+ }
299
+
300
+ /**
301
+ * 关闭右边
302
+ * @param id
303
+ */
304
+ const removeRightTabs = (id: string) => {
305
+ const uTabs = unref(tabs)
306
+ let startIndex = uTabs.length
307
+ for (let i = 0; i < uTabs.length; i++) {
308
+ if (uTabs[i].id === id) {
309
+ startIndex = i + 1
310
+ break
311
+ }
312
+ }
313
+ for (let i = uTabs.length - 1; i >= startIndex; i--) {
314
+ if (uTabs[i].closable) {
315
+ for (const item of uTabs[i].pages.list()) {
316
+ removeComponent(item.id)
317
+ markDeletableCache(item.id)
318
+ }
319
+ unref(tabs)[i].pages.clear()
320
+ unref(tabs).splice(i, 1)
321
+ }
322
+ }
323
+ for (const stay of uTabs) {
324
+ if (stay.active) {
325
+ removeDeletableCache()
326
+ return
327
+ }
328
+ }
329
+ active(uTabs[uTabs.length - 1].id)
330
+ }
331
+
332
+ /**
333
+ * 刷新
334
+ */
335
+ const refreshTab = (id: string) => {
336
+ // const uTabs = unref(tabs)
337
+ for (const uTabs of unref(tabs)) {
338
+ if (uTabs.id === id) {
339
+ const currentPageId = uTabs.pages.peek()?.id
340
+ for (let i = caches.value.length - 1; i >= 0; i--) {
341
+ const cacheId = caches.value[i]
342
+ if (cacheId === currentPageId) {
343
+ caches.value.splice(i, 1)
344
+ // 如果要刷新的是显示的TAB
345
+ if (uTabs.active) {
346
+ pageShown.value = false
347
+ }
348
+ break
349
+ }
350
+ }
351
+ break
352
+ }
353
+ }
354
+ }
355
+ /**
356
+ * 全部刷新
357
+ */
358
+ const refreshAllTabs = () => {
359
+ const refreshPage = new Set<string>()
360
+ tabs.value.forEach((value) => {
361
+ refreshPage.add(value.pages.peek()!.id)
362
+ })
363
+ for (let i = caches.value.length - 1; i >= 0; i--) {
364
+ const cacheId = caches.value[i]
365
+ if (refreshPage.has(cacheId)) {
366
+ caches.value.splice(i, 1)
367
+ }
368
+ }
369
+ pageShown.value = false
370
+ }
371
+
372
+ const addComponent = (id: string, comp: DefineComponent) => {
373
+ components.set(id, comp)
374
+ }
375
+ const getComponent = (id: string) => {
376
+ return components.get(id)
377
+ }
378
+ const removeComponent = (id: string) => {
379
+ components.delete(id)
380
+ }
381
+
382
+ /**
383
+ * Delete the cache after new Page loaded.
384
+ * @param cacheName
385
+ */
386
+ const markDeletableCache = (cacheName: string) => {
387
+ deletableCache.add(cacheName)
388
+ }
389
+ const removeDeletableCache = () => {
390
+ for (let i = caches.value.length - 1; i >= 0; i--) {
391
+ if (deletableCache.has(caches.value[i])) {
392
+ unref(caches).splice(i, 1)
393
+ }
394
+ }
395
+ deletableCache.clear()
396
+ }
397
+ const removeCache = (cacheName: string) => {
398
+ for (let i = caches.value.length - 1; i >= 0; i--) {
399
+ if (cacheName === caches.value[i]) {
400
+ unref(caches).splice(i, 1)
401
+ }
402
+ }
403
+ }
404
+ const addCache = (cacheName: string) => {
405
+ const cacheSet = new Set(caches.value)
406
+ if (!cacheSet.has(cacheName)) {
407
+ caches.value.push(cacheName)
408
+ }
409
+ }
410
+
411
+ /**
412
+ * active the tab,
413
+ * @param id
414
+ * @param route
415
+ * @return true if already actived
416
+ */
417
+ const active = (id: string, route = true) => {
418
+ for (let i = tabs.value.length - 1; i >= 0; i--) {
419
+ const tab = tabs.value[i] as ITabItem
420
+ if (tab.id === id) {
421
+ if (tab.active) {
422
+ break
423
+ } else {
424
+ tab.active = true
425
+ pageShown.value = false
426
+ updateSession(tab)
427
+ if (route) {
428
+ const top = tab.pages.peek()
429
+ router.push({
430
+ path: top!.path,
431
+ query: top!.query
432
+ })
433
+ }
434
+ }
435
+ } else {
436
+ tabs.value[i].active = false
437
+ }
438
+ }
439
+ }
440
+ /**
441
+ * save current tab info into Browser's session
442
+ * @param id
443
+ */
444
+ const updateSession = (tab: ITabItem) => {
445
+ // window.sessionStorage.setItem('tabItems', JSON.stringify(currentItems?.values()))
446
+ window.sessionStorage.setItem(SESSION_TAB_NAME, JSON.stringify(tab))
447
+ }
448
+ const reset = () => {
449
+ destroy()
450
+ unref(tabs).push(...defaultTabs)
451
+ active(defaultTabs[0].id)
452
+ }
453
+ const destroy = () => {
454
+ unref(tabs).splice(0)
455
+ components.clear()
456
+ deletableCache.clear()
457
+ unref(caches).splice(0)
458
+ pageShown.value = true
459
+ }
460
+
461
+ return {
462
+ tabs,
463
+ caches,
464
+ pageShown,
465
+ initial,
466
+ size,
467
+ active,
468
+ destroy,
469
+ reset,
470
+ addCache,
471
+ removeCache,
472
+ getTab,
473
+ addTab,
474
+ removeTab,
475
+ removeAllTabs,
476
+ removeLeftTabs,
477
+ removeRightTabs,
478
+ removeOtherTabs,
479
+ hasTab,
480
+ addPage,
481
+ addComponent,
482
+ getComponent,
483
+ removeComponent,
484
+ markDeletableCache,
485
+ removeDeletableCache,
486
+ refreshTab,
487
+ refreshAllTabs
488
+ }
489
+ }
@@ -0,0 +1,72 @@
1
+ import { useI18n } from 'vue-i18n'
2
+ import { inject } from 'vue'
3
+ export default () => {
4
+ // 引入lang目录下文件
5
+ // 此处使用了 VITE 的 import.meta.globEager。非 VITE 的 可以使用 require.context
6
+ const modules = import.meta.glob('./lang/*', { eager: true })
7
+
8
+ /**
9
+ * 获取所有语言文件
10
+ * @param {Object} mList
11
+ */
12
+ function getLangFiles(mList: any, msg: any) {
13
+ for (const path in mList) {
14
+ if (mList[path].default) {
15
+ // 获取文件名
16
+ const pathName = path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.'))
17
+
18
+ if (msg[pathName]) {
19
+ msg[pathName] = {
20
+ ...mList[pathName],
21
+ ...mList[path].default
22
+ }
23
+ } else {
24
+ msg[pathName] = mList[path].default
25
+ }
26
+ }
27
+ }
28
+ }
29
+
30
+ /**
31
+ * 注册i18n实例并引入语言文件
32
+ */
33
+ // const i18n = createI18n({
34
+ // fallbackLocale: 'zh-CN',
35
+ // // 定义默认语言为中文
36
+ // locale: 'zh-CN',
37
+ // legacy: false,
38
+ // // 挂载到全局,不然会报错
39
+ // // globalInjection: true,
40
+ // messages: getAllLang(),
41
+ // })
42
+ /**
43
+ * 局部使用i18n
44
+ */
45
+ // const i18n = useI18n({
46
+ // useScope: 'local',
47
+ // locale: 'zh-CN',
48
+ // messages: getAllLang(),
49
+ // })
50
+
51
+ // 假设你还有其他目录下的语言文件 它的路径是 src/views/home/locales/en-US.ts
52
+ // 那么你就可以 使用 :lower:(小写) :upper:(大写) 来引入文件
53
+ // const viewModules = import.meta.globEager('../views/**/locales/[[:lower:]][[:lower:]]-[[:upper:]][[:upper:]].ts')
54
+
55
+ const allLangs: any = () => {
56
+ const message: any = {}
57
+ getLangFiles(modules, message)
58
+ return message
59
+ }
60
+ const localeI18n = inject('locales') as { locale: string; messages: object }
61
+ const getI18n = () => {
62
+ const combinateMessage = { ...allLangs(), ...localeI18n.messages }
63
+ return useI18n({
64
+ useScope: 'local',
65
+ locale: localeI18n.locale,
66
+ messages: combinateMessage
67
+ })
68
+ }
69
+ return {
70
+ getI18n
71
+ }
72
+ }
@@ -0,0 +1,15 @@
1
+ export default {
2
+ VueStackTab: {
3
+ close: 'close',
4
+ closeLefts: 'close lefts',
5
+ closeRights: 'close rights',
6
+ closeOthers: 'close others',
7
+ closeAll: 'close all',
8
+ reload: 'reload',
9
+ reloadAll: 'reload all',
10
+ maximum: 'maximum',
11
+ restore: 'restore',
12
+ undefined: 'undefined',
13
+ loading: 'loading'
14
+ }
15
+ }
@@ -0,0 +1,15 @@
1
+ export default {
2
+ VueStackTab: {
3
+ close: '关闭',
4
+ closeLefts: '关闭左侧',
5
+ closeRights: '关闭右侧',
6
+ closeOthers: '关闭其他',
7
+ closeAll: '关闭所有',
8
+ reload: '刷新',
9
+ reloadAll: '刷新所有',
10
+ maximum: '最大化',
11
+ restore: '还原',
12
+ undefined: '未命名',
13
+ loading: '加载中'
14
+ }
15
+ }
@@ -0,0 +1,7 @@
1
+ <script setup lang="ts">
2
+ import useTabRouter from '@/lib/hooks/useTabRouter'
3
+ useTabRouter()
4
+ </script>
5
+ <template>
6
+ <div></div>
7
+ </template>
@@ -0,0 +1,25 @@
1
+ import type { App } from 'vue'
2
+ import { createI18n } from 'vue-i18n'
3
+ import StackTab from './StackTabs.vue'
4
+ // import VueEmttier from './hooks/useMitt'
5
+ import tabVersion from './banner'
6
+ // import './assets/style/index.scss'
7
+ // import 'vue-loading-overlay/dist/css/index.css'
8
+ import IFrame from './iframe.vue'
9
+ import useTabLoading from './hooks/useTabLoading'
10
+ import useTabRouter from './hooks/useTabRouter'
11
+ import useStackTab from './hooks/useStackTab'
12
+
13
+ const i18n = createI18n({
14
+ legacy: false,
15
+ locale: 'zh-CN',
16
+ fallbackLocale: 'en-US'
17
+ })
18
+ export { IFrame, useTabLoading, useTabRouter, useStackTab }
19
+ export * from './model/TabModel'
20
+ export default {
21
+ install(app: App): void {
22
+ tabVersion(import.meta.env.PACKAGE_VERSION)
23
+ app.component('VueStackTabs', StackTab).use(i18n)
24
+ }
25
+ }