vue-stack-tabs 0.1.18 → 0.1.20

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.
@@ -1,93 +1,93 @@
1
- import { defu } from 'defu'
2
-
3
- import { getCurrentInstance } from 'vue'
4
- import type { ComponentInternalInstance } from 'vue'
5
- import { type RouteLocationPathRaw, useRoute, useRouter } from 'vue-router'
6
-
7
- import useTabpanel from '@/lib/hooks/useTabpanel'
8
- import { uriDecode } from '@/lib/utils/UriHelper'
9
- export default () => {
10
- const { attrs } = getCurrentInstance() as ComponentInternalInstance
11
- const { pageShown, getTab, markDeletableCache, removeComponent, getComponent } = useTabpanel()
12
- const route = useRoute()
13
- const router = useRouter()
14
- let currentId = ''
15
- // const currentPageId = ''
16
- let currentTab = ''
17
-
18
- currentId = attrs.tId as string
19
- // currentPageId = attrs.pId as string
20
- currentTab = route.query.__tab as string
21
- const forward = (to: RouteLocationPathRaw) => {
22
- pageShown.value = false
23
- const query = defu(
24
- {
25
- __tab: currentTab
26
- },
27
- to.query
28
- )
29
- router.push({
30
- path: to.path,
31
- query
32
- })
33
- }
34
- /**
35
- * 返回
36
- * @param to url or step
37
- * @param query 返回时要加截的数据
38
- */
39
- const backward = (to: number | string, query?: Object) => {
40
- pageShown.value = false
41
-
42
- const tab = getTab(currentId)
43
- if (!tab) {
44
- return
45
- }
46
- const tabStack = tab.pages
47
- let absTo = 0
48
- if (typeof to === 'number') {
49
- absTo = Math.abs(to)
50
- } else {
51
- let index = 1
52
- let hasPath = false
53
- const pageItems = tabStack.list()
54
- const url = uriDecode(to)
55
- query = defu(url.query, query)
56
- for (let i = tabStack.size() - 2; i >= 0; i--) {
57
- if (pageItems[i].path === url.path) {
58
- hasPath = true
59
- break
60
- }
61
- index += 1
62
- }
63
- if (hasPath) {
64
- absTo = index
65
- }
66
- }
67
-
68
- if (absTo === 0 || tabStack!.size() <= absTo) {
69
- return
70
- }
71
- // const removeCaches = new Set()
72
- for (let i = 0; i < absTo; i++) {
73
- const popRoute = tabStack.pop()
74
- removeComponent(popRoute!.id)
75
- markDeletableCache(popRoute!.id)
76
- }
77
- const pageRoute = tabStack?.peek()
78
- const component = getComponent(pageRoute!.id)
79
- if (component !== null && component !== undefined) {
80
- const sourceComponent = component.components.DynamicComponent
81
- sourceComponent.props = defu(query, sourceComponent.props)
82
- }
83
- router.push({
84
- path: pageRoute!.path,
85
- query: pageRoute!.query
86
- })
87
- }
88
-
89
- return {
90
- forward,
91
- backward
92
- }
93
- }
1
+ import { defu } from 'defu'
2
+
3
+ import { getCurrentInstance } from 'vue'
4
+ import type { ComponentInternalInstance } from 'vue'
5
+ import { type RouteLocationPathRaw, useRoute, useRouter } from 'vue-router'
6
+
7
+ import useTabpanel from '@/lib/hooks/useTabpanel'
8
+ import { uriDecode } from '@/lib/utils/UriHelper'
9
+ export default () => {
10
+ const { attrs } = getCurrentInstance() as ComponentInternalInstance
11
+ const { pageShown, getTab, markDeletableCache, removeComponent, getComponent } = useTabpanel()
12
+ const route = useRoute()
13
+ const router = useRouter()
14
+ let currentId = ''
15
+ // const currentPageId = ''
16
+ let currentTab = ''
17
+
18
+ currentId = attrs.tId as string
19
+ // currentPageId = attrs.pId as string
20
+ currentTab = route.query.__tab as string
21
+ const forward = (to: RouteLocationPathRaw) => {
22
+ pageShown.value = false
23
+ const query = defu(
24
+ {
25
+ __tab: currentTab
26
+ },
27
+ to.query
28
+ )
29
+ router.push({
30
+ path: to.path,
31
+ query
32
+ })
33
+ }
34
+ /**
35
+ * 返回
36
+ * @param to url or step
37
+ * @param query 返回时要加截的数据
38
+ */
39
+ const backward = (to: number | string, query?: Object) => {
40
+ pageShown.value = false
41
+
42
+ const tab = getTab(currentId)
43
+ if (!tab) {
44
+ return
45
+ }
46
+ const tabStack = tab.pages
47
+ let absTo = 0
48
+ if (typeof to === 'number') {
49
+ absTo = Math.abs(to)
50
+ } else {
51
+ let index = 1
52
+ let hasPath = false
53
+ const pageItems = tabStack.list()
54
+ const url = uriDecode(to)
55
+ query = defu(url.query, query)
56
+ for (let i = tabStack.size() - 2; i >= 0; i--) {
57
+ if (pageItems[i].path === url.path) {
58
+ hasPath = true
59
+ break
60
+ }
61
+ index += 1
62
+ }
63
+ if (hasPath) {
64
+ absTo = index
65
+ }
66
+ }
67
+
68
+ if (absTo === 0 || tabStack!.size() <= absTo) {
69
+ return
70
+ }
71
+ // const removeCaches = new Set()
72
+ for (let i = 0; i < absTo; i++) {
73
+ const popRoute = tabStack.pop()
74
+ removeComponent(popRoute!.id)
75
+ markDeletableCache(popRoute!.id)
76
+ }
77
+ const pageRoute = tabStack?.peek()
78
+ const component = getComponent(pageRoute!.id)
79
+ if (component !== null && component !== undefined) {
80
+ const sourceComponent = component.components.DynamicComponent
81
+ sourceComponent.props = defu(query, sourceComponent.props)
82
+ }
83
+ router.push({
84
+ path: pageRoute!.path,
85
+ query: pageRoute!.query
86
+ })
87
+ }
88
+
89
+ return {
90
+ forward,
91
+ backward
92
+ }
93
+ }
@@ -19,7 +19,7 @@ const components = new Map<string, any>()
19
19
  const deletableCache = new Set<String>()
20
20
  const pageShown = ref<boolean>(true)
21
21
  const SESSION_TAB_NAME = 'stacktab-active-tab'
22
-
22
+ let initialed = false
23
23
  let max = 0
24
24
  export default () => {
25
25
  const router = useRouter()
@@ -90,6 +90,7 @@ export default () => {
90
90
  tabs.value.push(temp)
91
91
  }
92
92
  }
93
+ initialed = true
93
94
  }
94
95
  const hasTab = (id: string) => {
95
96
  for (const tab of tabs.value) {
@@ -496,6 +497,7 @@ export default () => {
496
497
  tabs,
497
498
  caches,
498
499
  pageShown,
500
+ initialed,
499
501
  setMaxSize,
500
502
  canAddTab,
501
503
  initial,
@@ -1,5 +1,5 @@
1
- import { useI18n } from 'vue-i18n'
2
- import { inject } from 'vue'
1
+ import { createI18n } from 'vue-i18n-lite'
2
+
3
3
  export default () => {
4
4
  // 引入lang目录下文件
5
5
  // 此处使用了 VITE 的 import.meta.globEager。非 VITE 的 可以使用 require.context
@@ -57,14 +57,24 @@ export default () => {
57
57
  getLangFiles(modules, message)
58
58
  return message
59
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',
60
+ // const localeI18n = inject('locales') as { locale: string; messages: object }
61
+ const getI18n = (localeI18n?: any) => {
62
+ let combinateMessage = { ...allLangs() }
63
+ if (!localeI18n) {
64
+ combinateMessage = { ...allLangs(), ...localeI18n.messages }
65
+ }
66
+
67
+ return createI18n({
65
68
  locale: localeI18n.locale,
69
+ fallbackLocale: 'en',
66
70
  messages: combinateMessage
67
71
  })
72
+ // const combinateMessage = { ...allLangs(), ...localeI18n.messages }
73
+ // return useI18n({
74
+ // useScope: 'local',
75
+ // locale: localeI18n.locale,
76
+ // messages: combinateMessage
77
+ // })
68
78
  }
69
79
  return {
70
80
  getI18n
package/src/lib/index.ts CHANGED
@@ -1,33 +1,37 @@
1
- import type { App } from 'vue'
2
- import { createI18n } from 'vue-i18n'
3
- import StackTab from './StackTabs.vue'
4
- import tabVersion from './banner'
5
- import IFrame from './iframe.vue'
6
- import useTabLoading from './hooks/useTabLoading'
7
- import useTabRouter from './hooks/useTabRouter'
8
- import useStackTab from './hooks/useStackTab'
9
- import TabHeaderButton from '@/lib/components/TabHeader/TabHeaderButton.vue'
10
- import useTabMitt from '@/lib/hooks/useTabMitt'
11
- import './assets/style/index.scss'
12
-
13
- const i18n = createI18n({
14
- legacy: false,
15
- locale: 'zh-CN',
16
- fallbackLocale: 'en-US'
17
- })
18
-
19
- export * from './model/TabModel'
20
- // Cutsom type
21
- declare module '@vue/runtime-core' {
22
- export interface GlobalComponents {
23
- VueStackTabs: typeof StackTab
24
- }
25
- }
26
-
27
- export { IFrame, useTabLoading, useTabRouter, useStackTab, TabHeaderButton, StackTab }
28
- export default {
29
- install(Vue: App): void {
30
- tabVersion(import.meta.env.PACKAGE_VERSION)
31
- Vue.component('VueStackTabs', StackTab).use(useTabMitt).use(i18n)
32
- }
33
- }
1
+ import type { App } from 'vue'
2
+ // import { createI18n } from 'vue-i18n'
3
+ import i18n from './i18n'
4
+ import StackTab from './StackTabs.vue'
5
+ import tabVersion from './banner'
6
+ import IFrame from './iframe.vue'
7
+ import useTabLoading from './hooks/useTabLoading'
8
+ import useTabRouter from './hooks/useTabRouter'
9
+ import useStackTab from './hooks/useStackTab'
10
+ import TabHeaderButton from '@/lib/components/TabHeader/TabHeaderButton.vue'
11
+ import useTabMitt from '@/lib/hooks/useTabMitt'
12
+ import './assets/style/index.scss'
13
+ //
14
+ // const i18n = createI18n({
15
+ // legacy: false,
16
+ // locale: 'zh-CN',
17
+ // fallbackLocale: 'en-US'
18
+ // })
19
+
20
+ export * from './model/TabModel'
21
+ // Cutsom type
22
+ declare module '@vue/runtime-core' {
23
+ export interface GlobalComponents {
24
+ VueStackTabs: typeof StackTab
25
+ }
26
+ }
27
+
28
+ export { IFrame, useTabLoading, useTabRouter, useStackTab, TabHeaderButton, StackTab }
29
+ export default {
30
+ install(
31
+ Vue: App,
32
+ options: { locale: string; messages: any } = { locale: 'zh-CN', messages: {} }
33
+ ): void {
34
+ tabVersion(import.meta.env.PACKAGE_VERSION)
35
+ Vue.component('VueStackTabs', StackTab).use(useTabMitt).use(i18n().getI18n(options))
36
+ }
37
+ }
@@ -1,178 +1,178 @@
1
- // Tab的滚动方式
2
- export enum TabScrollMode {
3
- // 使用滚轮
4
- WHEEL = 'wheel',
5
- // 使用按钮
6
- BUTTON = 'button',
7
- // 两者都可以
8
- BOTH = 'both'
9
- }
10
-
11
- // export enum EventType {
12
- // I18N_LOCALES = 'I18N_LOCALES',
13
- // PANEL_MAXIMUM = 'PANEL_MAXIMUM',
14
- // TAB_ACTIVE = 'TAB_ACTIVE',
15
- // TAB_CLOSE = 'TAB_CLOSE',
16
- // TAB_CLOSE_ALL = 'TAB_CLOSE_ALL',
17
- // TAB_CLOSE_RIGHT = 'TAB_CLOSE_RIGHT',
18
- // TAB_CLOSE_LEFT = 'TAB_CLOSE_LEFT',
19
- // TAB_REFRESH = 'TAB_REFRESH',
20
- // TAB_REFRESH_ALL = 'TAB_REFRESH_ALL'
21
- // }
22
- // 拖拽数据接口
23
- export interface DragData {
24
- thumbLeft: number
25
- startScrollLeft: number
26
- startThumbLeft: number
27
- startPageX: number
28
- }
29
- // 滑块数据接口
30
- export interface ScrollData {
31
- clientWidth: number
32
- scrollWidth: number
33
- scrollLeft: number
34
- }
35
- // 滚动条事件类型
36
- export type ScrollEvents = {
37
- ScrollUpdate: void
38
- }
39
-
40
- /**
41
- * Tab data for open
42
- */
43
- export interface ITabData extends ITabBase {
44
- // tab name
45
- title: string
46
- path: string
47
- query?: Record<string, string>
48
- }
49
- export interface ITabBase {
50
- id?: string
51
- title: string
52
- closable?: boolean
53
- refreshable?: boolean
54
- iframe?: boolean
55
- }
56
- export interface ITabItem extends ITabBase {
57
- id: string
58
- closable: boolean
59
- refreshable: boolean
60
- iframe: boolean
61
- url?: string
62
- active: boolean
63
- pages: Stack<ITabPage>
64
- }
65
-
66
- export interface ITabPage {
67
- id: string
68
- tabId: string
69
- path: string
70
- query?: Record<string, string>
71
- }
72
- export interface IContextMenu {
73
- icon?: string
74
- title: string
75
- callback(id: string): void
76
- disabled: (tabData: ITabBase) => boolean
77
- }
78
- // export interface TabRouteLocationRaw {
79
- // path: string
80
- // query?: any
81
- // }
82
- // export interface PageRouteLocationRaw {
83
- // pId: string
84
- // path: string
85
- // query: any
86
- // }
87
- export class Stack<T> {
88
- // 存储的Map
89
- private items: Map<number, T>
90
-
91
- //
92
- constructor(items?:T[]) {
93
- this.items = new Map()
94
- if(items) {
95
- for (const item of items) {
96
- this.push(item)
97
- }
98
- }
99
- }
100
-
101
- /**
102
- * @description: 入栈
103
- * @param {T} element 要入栈的元素
104
- */
105
- push(element: T) {
106
- this.items.set(this.items.size, element)
107
- }
108
-
109
- /**
110
- * @description: 出栈
111
- * @return {T} 返回出栈的元素
112
- */
113
- pop(): T | undefined {
114
- if (this.isEmpty()) {
115
- return undefined
116
- }
117
- const result = this.items.get(this.items.size - 1)
118
- this.items.delete(this.items.size - 1)
119
- return result
120
- }
121
-
122
- /**
123
- * @description: 返回栈顶的元素
124
- * @return {T}
125
- */
126
- peek(): T | undefined {
127
- if (this.isEmpty()) {
128
- return undefined
129
- }
130
- return this.items.get(this.items.size - 1)
131
- }
132
-
133
- /**
134
- * @description: 返回栈是否为空
135
- * @return {Boolean}
136
- */
137
- isEmpty(): boolean {
138
- return this.items.size === 0
139
- }
140
-
141
- /**
142
- * @description: 返回栈里的元素个数
143
- * @return {Number}
144
- */
145
- size(): number {
146
- return this.items.size
147
- }
148
-
149
- /**
150
- * @description: 清空栈
151
- */
152
- clear() {
153
- this.items.clear()
154
- }
155
-
156
- list() {
157
- return Array.from(this.items.values())
158
- }
159
-
160
- /**
161
- * @description: 覆盖Object默认的toString
162
- * @return {String}
163
- */
164
- toString(): string {
165
- if (this.isEmpty()) {
166
- return ''
167
- }
168
- let result: string = ''
169
- this.items.forEach((value, key) => {
170
- result = `${result}${key === 0 ? '' : ', '}${value}`
171
- })
172
- return result
173
- }
174
- toJSON() {
175
- // return Object.fromEntries(this.items)
176
- return Array.from(this.items.values())
177
- }
178
- }
1
+ // Tab的滚动方式
2
+ export enum TabScrollMode {
3
+ // 使用滚轮
4
+ WHEEL = 'wheel',
5
+ // 使用按钮
6
+ BUTTON = 'button',
7
+ // 两者都可以
8
+ BOTH = 'both'
9
+ }
10
+
11
+ // export enum EventType {
12
+ // I18N_LOCALES = 'I18N_LOCALES',
13
+ // PANEL_MAXIMUM = 'PANEL_MAXIMUM',
14
+ // TAB_ACTIVE = 'TAB_ACTIVE',
15
+ // TAB_CLOSE = 'TAB_CLOSE',
16
+ // TAB_CLOSE_ALL = 'TAB_CLOSE_ALL',
17
+ // TAB_CLOSE_RIGHT = 'TAB_CLOSE_RIGHT',
18
+ // TAB_CLOSE_LEFT = 'TAB_CLOSE_LEFT',
19
+ // TAB_REFRESH = 'TAB_REFRESH',
20
+ // TAB_REFRESH_ALL = 'TAB_REFRESH_ALL'
21
+ // }
22
+ // 拖拽数据接口
23
+ export interface DragData {
24
+ thumbLeft: number
25
+ startScrollLeft: number
26
+ startThumbLeft: number
27
+ startPageX: number
28
+ }
29
+ // 滑块数据接口
30
+ export interface ScrollData {
31
+ clientWidth: number
32
+ scrollWidth: number
33
+ scrollLeft: number
34
+ }
35
+ // 滚动条事件类型
36
+ export type ScrollEvents = {
37
+ ScrollUpdate: void
38
+ }
39
+
40
+ /**
41
+ * Tab data for open
42
+ */
43
+ export interface ITabData extends ITabBase {
44
+ // tab name
45
+ title: string
46
+ path: string
47
+ query?: Record<string, string>
48
+ }
49
+ export interface ITabBase {
50
+ id?: string
51
+ title: string
52
+ closable?: boolean
53
+ refreshable?: boolean
54
+ iframe?: boolean
55
+ }
56
+ export interface ITabItem extends ITabBase {
57
+ id: string
58
+ closable: boolean
59
+ refreshable: boolean
60
+ iframe: boolean
61
+ url?: string
62
+ active: boolean
63
+ pages: Stack<ITabPage>
64
+ }
65
+
66
+ export interface ITabPage {
67
+ id: string
68
+ tabId: string
69
+ path: string
70
+ query?: Record<string, string>
71
+ }
72
+ export interface IContextMenu {
73
+ icon?: string
74
+ title: string
75
+ callback(id: string): void
76
+ disabled: (tabData: ITabBase) => boolean
77
+ }
78
+ // export interface TabRouteLocationRaw {
79
+ // path: string
80
+ // query?: any
81
+ // }
82
+ // export interface PageRouteLocationRaw {
83
+ // pId: string
84
+ // path: string
85
+ // query: any
86
+ // }
87
+ export class Stack<T> {
88
+ // 存储的Map
89
+ private items: Map<number, T>
90
+
91
+ //
92
+ constructor(items?: T[]) {
93
+ this.items = new Map()
94
+ if (items) {
95
+ for (const item of items) {
96
+ this.push(item)
97
+ }
98
+ }
99
+ }
100
+
101
+ /**
102
+ * @description: 入栈
103
+ * @param {T} element 要入栈的元素
104
+ */
105
+ push(element: T) {
106
+ this.items.set(this.items.size, element)
107
+ }
108
+
109
+ /**
110
+ * @description: 出栈
111
+ * @return {T} 返回出栈的元素
112
+ */
113
+ pop(): T | undefined {
114
+ if (this.isEmpty()) {
115
+ return undefined
116
+ }
117
+ const result = this.items.get(this.items.size - 1)
118
+ this.items.delete(this.items.size - 1)
119
+ return result
120
+ }
121
+
122
+ /**
123
+ * @description: 返回栈顶的元素
124
+ * @return {T}
125
+ */
126
+ peek(): T | undefined {
127
+ if (this.isEmpty()) {
128
+ return undefined
129
+ }
130
+ return this.items.get(this.items.size - 1)
131
+ }
132
+
133
+ /**
134
+ * @description: 返回栈是否为空
135
+ * @return {Boolean}
136
+ */
137
+ isEmpty(): boolean {
138
+ return this.items.size === 0
139
+ }
140
+
141
+ /**
142
+ * @description: 返回栈里的元素个数
143
+ * @return {Number}
144
+ */
145
+ size(): number {
146
+ return this.items.size
147
+ }
148
+
149
+ /**
150
+ * @description: 清空栈
151
+ */
152
+ clear() {
153
+ this.items.clear()
154
+ }
155
+
156
+ list() {
157
+ return Array.from(this.items.values())
158
+ }
159
+
160
+ /**
161
+ * @description: 覆盖Object默认的toString
162
+ * @return {String}
163
+ */
164
+ toString(): string {
165
+ if (this.isEmpty()) {
166
+ return ''
167
+ }
168
+ let result: string = ''
169
+ this.items.forEach((value, key) => {
170
+ result = `${result}${key === 0 ? '' : ', '}${value}`
171
+ })
172
+ return result
173
+ }
174
+ toJSON() {
175
+ // return Object.fromEntries(this.items)
176
+ return Array.from(this.items.values())
177
+ }
178
+ }