vue3-router-tab 1.0.9 → 1.1.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 +72 -49
- package/dist/vue3-router-tab.js +450 -574
- package/dist/vue3-router-tab.umd.cjs +1 -12
- package/lib/components/RouterTab.vue +54 -98
- package/lib/components/RouterTabs.vue +14 -0
- package/lib/constants.ts +2 -0
- package/lib/core/types.ts +12 -0
- package/lib/index.ts +9 -11
- package/lib/persistence.ts +171 -0
- package/package.json +11 -8
- package/index.d.ts +0 -134
- package/lib/components/RouterTabsPinia.vue +0 -13
- package/lib/pinia.ts +0 -149
package/index.d.ts
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import type { App, Plugin } from 'vue'
|
|
2
|
-
import type { RouteLocationRaw } from 'vue-router'
|
|
3
|
-
import type {
|
|
4
|
-
TabRecord,
|
|
5
|
-
TabInput,
|
|
6
|
-
RouterTabsOptions,
|
|
7
|
-
CloseTabOptions,
|
|
8
|
-
RouterTabsContext,
|
|
9
|
-
RouterTabsMenuConfig,
|
|
10
|
-
RouterTabsMenuItem,
|
|
11
|
-
RouterTabsMenuPreset,
|
|
12
|
-
RouterTabsSnapshot,
|
|
13
|
-
RouterTabsSnapshotTab
|
|
14
|
-
} from './lib/core/types'
|
|
15
|
-
|
|
16
|
-
export type {
|
|
17
|
-
TabRecord,
|
|
18
|
-
TabInput,
|
|
19
|
-
RouterTabsOptions,
|
|
20
|
-
CloseTabOptions,
|
|
21
|
-
RouterTabsContext,
|
|
22
|
-
RouterTabsMenuConfig,
|
|
23
|
-
RouterTabsMenuItem,
|
|
24
|
-
RouterTabsMenuPreset,
|
|
25
|
-
RouterTabsSnapshot,
|
|
26
|
-
RouterTabsSnapshotTab
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export declare const routerTabsKey: import('vue').InjectionKey<RouterTabsContext>
|
|
30
|
-
|
|
31
|
-
export declare function useRouterTabs(options?: { optional?: boolean }): RouterTabsContext | null
|
|
32
|
-
|
|
33
|
-
export interface RouterTabsPiniaOptions {
|
|
34
|
-
storeId?: string
|
|
35
|
-
storageKey?: string
|
|
36
|
-
storage?: Storage | null
|
|
37
|
-
fallbackRoute?: import('vue-router').RouteLocationRaw
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export declare function useRouterTabsPiniaPersistence(options?: RouterTabsPiniaOptions & { store?: import('pinia').StoreDefinition<any, any, any, any> }): import('pinia').Store<any, any, any, any>
|
|
41
|
-
|
|
42
|
-
export declare const RouterTabsPinia: import('vue').DefineComponent<RouterTabsPiniaOptions, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<RouterTabsPiniaOptions>, {}>
|
|
43
|
-
|
|
44
|
-
export declare const RouterTab: import('vue').DefineComponent<{
|
|
45
|
-
tabs: {
|
|
46
|
-
type: import('vue').PropType<TabInput[]>
|
|
47
|
-
default: () => TabInput[]
|
|
48
|
-
}
|
|
49
|
-
keepAlive: {
|
|
50
|
-
type: BooleanConstructor
|
|
51
|
-
default: boolean
|
|
52
|
-
}
|
|
53
|
-
maxAlive: {
|
|
54
|
-
type: NumberConstructor
|
|
55
|
-
default: number
|
|
56
|
-
}
|
|
57
|
-
keepLastTab: {
|
|
58
|
-
type: BooleanConstructor
|
|
59
|
-
default: boolean
|
|
60
|
-
}
|
|
61
|
-
append: {
|
|
62
|
-
type: import('vue').PropType<'last' | 'next'>
|
|
63
|
-
default: 'last' | 'next'
|
|
64
|
-
}
|
|
65
|
-
defaultPage: {
|
|
66
|
-
type: import('vue').PropType<RouteLocationRaw>
|
|
67
|
-
default: RouteLocationRaw
|
|
68
|
-
}
|
|
69
|
-
tabTransition: {
|
|
70
|
-
type: import('vue').PropType<import('./lib/core/types').TransitionLike>
|
|
71
|
-
default: string | import('./lib/core/types').TransitionLike
|
|
72
|
-
}
|
|
73
|
-
pageTransition: {
|
|
74
|
-
type: import('vue').PropType<import('./lib/core/types').TransitionLike>
|
|
75
|
-
default: () => import('./lib/core/types').TransitionLike
|
|
76
|
-
}
|
|
77
|
-
contextmenu: {
|
|
78
|
-
type: import('vue').PropType<boolean | RouterTabsMenuConfig[]>
|
|
79
|
-
default: true
|
|
80
|
-
}
|
|
81
|
-
storage: {
|
|
82
|
-
type: BooleanConstructor | StringConstructor
|
|
83
|
-
default: boolean
|
|
84
|
-
}
|
|
85
|
-
}, any, any, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, Record<string, any>, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<{
|
|
86
|
-
tabs?: TabInput[] | undefined
|
|
87
|
-
keepAlive?: boolean | undefined
|
|
88
|
-
maxAlive?: number | undefined
|
|
89
|
-
keepLastTab?: boolean | undefined
|
|
90
|
-
append?: 'last' | 'next' | undefined
|
|
91
|
-
defaultPage?: RouteLocationRaw | undefined
|
|
92
|
-
tabTransition?: import('./lib/core/types').TransitionLike | undefined
|
|
93
|
-
pageTransition?: import('./lib/core/types').TransitionLike | undefined
|
|
94
|
-
contextmenu?: boolean | RouterTabsMenuConfig[] | undefined
|
|
95
|
-
storage?: boolean | string | undefined
|
|
96
|
-
}> & {
|
|
97
|
-
tabs?: TabInput[] | undefined
|
|
98
|
-
keepAlive?: boolean | undefined
|
|
99
|
-
maxAlive?: number | undefined
|
|
100
|
-
keepLastTab?: boolean | undefined
|
|
101
|
-
append?: 'last' | 'next' | undefined
|
|
102
|
-
defaultPage?: RouteLocationRaw | undefined
|
|
103
|
-
tabTransition?: import('./lib/core/types').TransitionLike | undefined
|
|
104
|
-
pageTransition?: import('./lib/core/types').TransitionLike | undefined
|
|
105
|
-
contextmenu?: boolean | RouterTabsMenuConfig[] | undefined
|
|
106
|
-
storage?: boolean | string | undefined
|
|
107
|
-
}, {
|
|
108
|
-
tabs: TabInput[]
|
|
109
|
-
keepAlive: boolean
|
|
110
|
-
maxAlive: number
|
|
111
|
-
keepLastTab: boolean
|
|
112
|
-
append: 'last' | 'next'
|
|
113
|
-
defaultPage: RouteLocationRaw
|
|
114
|
-
tabTransition: import('./lib/core/types').TransitionLike
|
|
115
|
-
pageTransition: import('./lib/core/types').TransitionLike
|
|
116
|
-
contextmenu: true
|
|
117
|
-
storage: boolean
|
|
118
|
-
}>
|
|
119
|
-
|
|
120
|
-
export interface RouterTabPlugin extends Plugin {}
|
|
121
|
-
|
|
122
|
-
declare const plugin: RouterTabPlugin
|
|
123
|
-
|
|
124
|
-
export default plugin
|
|
125
|
-
|
|
126
|
-
declare module '@vue/runtime-core' {
|
|
127
|
-
interface ComponentCustomProperties {
|
|
128
|
-
$tabs: RouterTabsContext | null
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
declare module './constants' {
|
|
132
|
-
const value: any;
|
|
133
|
-
export = value;
|
|
134
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<span class="router-tabs" aria-hidden="true" />
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<script setup lang="ts">
|
|
6
|
-
import { useRouterTabsPiniaPersistence } from '../pinia'
|
|
7
|
-
defineOptions({ name: 'RouterTabs' })
|
|
8
|
-
import type { RouterTabsPiniaOptions } from '../pinia'
|
|
9
|
-
|
|
10
|
-
const props = defineProps<RouterTabsPiniaOptions>()
|
|
11
|
-
|
|
12
|
-
useRouterTabsPiniaPersistence(props as RouterTabsPiniaOptions)
|
|
13
|
-
</script>
|
package/lib/pinia.ts
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { defineStore, type StoreDefinition } from 'pinia'
|
|
2
|
-
import { onMounted, ref, watch } from 'vue'
|
|
3
|
-
import type { RouteLocationRaw } from 'vue-router'
|
|
4
|
-
import { useRouterTabs } from './useRouterTabs'
|
|
5
|
-
import type { RouterTabsSnapshot } from './core/types'
|
|
6
|
-
|
|
7
|
-
export interface RouterTabsPiniaOptions {
|
|
8
|
-
/** Pinia store id. Defaults to 'routerTabs'. */
|
|
9
|
-
storeId?: string
|
|
10
|
-
/** Storage key used when persisting snapshots. Defaults to 'router-tabs:persistent'. */
|
|
11
|
-
storageKey?: string
|
|
12
|
-
/** Custom storage implementation (e.g. localStorage, sessionStorage). Defaults to window.localStorage. */
|
|
13
|
-
storage?: Storage | null
|
|
14
|
-
/** Fallback route to open when no snapshot exists. Defaults to RouterTab's default route. */
|
|
15
|
-
fallbackRoute?: RouteLocationRaw
|
|
16
|
-
/** Provide a custom store definition if you want to control persistence yourself. */
|
|
17
|
-
store?: StoreDefinition<'routerTabs', { snapshot: RouterTabsSnapshot | null }, {}, { load(): void; setSnapshot(snapshot: RouterTabsSnapshot | null): void; clear(): void }>
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const defaultStorageKey = 'router-tabs:persistent'
|
|
21
|
-
|
|
22
|
-
function resolveStorage(storage?: Storage | null): Storage | null {
|
|
23
|
-
if (typeof window === 'undefined') return null
|
|
24
|
-
if (storage === undefined) return window.localStorage ?? null
|
|
25
|
-
return storage
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function createDefaultStore(options: RouterTabsPiniaOptions) {
|
|
29
|
-
const storage = resolveStorage(options.storage)
|
|
30
|
-
const key = options.storageKey ?? defaultStorageKey
|
|
31
|
-
|
|
32
|
-
return defineStore(options.storeId ?? 'routerTabs', {
|
|
33
|
-
state: () => ({
|
|
34
|
-
snapshot: null as RouterTabsSnapshot | null
|
|
35
|
-
}),
|
|
36
|
-
actions: {
|
|
37
|
-
load() {
|
|
38
|
-
if (!storage || this.snapshot) return
|
|
39
|
-
try {
|
|
40
|
-
const raw = storage.getItem(key)
|
|
41
|
-
if (raw) {
|
|
42
|
-
this.snapshot = JSON.parse(raw)
|
|
43
|
-
}
|
|
44
|
-
} catch (error) {
|
|
45
|
-
if (import.meta.env?.DEV) {
|
|
46
|
-
console.warn('[RouterTabs] Failed to load snapshot from storage', error)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
setSnapshot(snapshot: RouterTabsSnapshot | null) {
|
|
51
|
-
this.snapshot = snapshot
|
|
52
|
-
if (!storage) return
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
if (snapshot && snapshot.tabs.length) {
|
|
56
|
-
storage.setItem(key, JSON.stringify(snapshot))
|
|
57
|
-
} else {
|
|
58
|
-
storage.removeItem(key)
|
|
59
|
-
}
|
|
60
|
-
} catch (error) {
|
|
61
|
-
if (import.meta.env?.DEV) {
|
|
62
|
-
console.warn('[RouterTabs] Failed to persist snapshot to storage', error)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
clear() {
|
|
67
|
-
this.setSnapshot(null)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
})
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Synchronise RouterTab state with a Pinia store so tab snapshots persist across reloads.
|
|
75
|
-
*
|
|
76
|
-
* ```ts
|
|
77
|
-
* const store = useRouterTabsPiniaPersistence()
|
|
78
|
-
* ```
|
|
79
|
-
*/
|
|
80
|
-
export function useRouterTabsPiniaPersistence(options: RouterTabsPiniaOptions = {}) {
|
|
81
|
-
const Store = options.store ?? createDefaultStore(options)
|
|
82
|
-
const store = Store()
|
|
83
|
-
const hydrating = ref(false)
|
|
84
|
-
let initialized = false
|
|
85
|
-
|
|
86
|
-
const attemptSetup = (controller: NonNullable<ReturnType<typeof useRouterTabs>>) => {
|
|
87
|
-
if (!controller || initialized) return
|
|
88
|
-
initialized = true
|
|
89
|
-
|
|
90
|
-
onMounted(async () => {
|
|
91
|
-
store.load()
|
|
92
|
-
const snapshot = store.snapshot
|
|
93
|
-
|
|
94
|
-
if (snapshot && snapshot.tabs?.length) {
|
|
95
|
-
try {
|
|
96
|
-
hydrating.value = true
|
|
97
|
-
await controller.hydrate(snapshot)
|
|
98
|
-
} finally {
|
|
99
|
-
hydrating.value = false
|
|
100
|
-
}
|
|
101
|
-
} else {
|
|
102
|
-
try {
|
|
103
|
-
hydrating.value = true
|
|
104
|
-
const fallback = options.fallbackRoute ?? controller.options.defaultRoute
|
|
105
|
-
await controller.reset(fallback)
|
|
106
|
-
} finally {
|
|
107
|
-
hydrating.value = false
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
store.setSnapshot(controller.snapshot())
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
watch(
|
|
115
|
-
() => ({
|
|
116
|
-
tabs: controller.tabs.map(tab => ({
|
|
117
|
-
to: tab.to,
|
|
118
|
-
title: tab.title,
|
|
119
|
-
tips: tab.tips,
|
|
120
|
-
icon: tab.icon,
|
|
121
|
-
tabClass: tab.tabClass,
|
|
122
|
-
closable: tab.closable
|
|
123
|
-
})),
|
|
124
|
-
active: controller.activeId.value
|
|
125
|
-
}),
|
|
126
|
-
() => {
|
|
127
|
-
if (hydrating.value) return
|
|
128
|
-
store.setSnapshot(controller.snapshot())
|
|
129
|
-
},
|
|
130
|
-
{ deep: true }
|
|
131
|
-
)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const controller = useRouterTabs({ optional: true })
|
|
135
|
-
if (controller) {
|
|
136
|
-
attemptSetup(controller)
|
|
137
|
-
} else {
|
|
138
|
-
onMounted(() => {
|
|
139
|
-
const lateController = useRouterTabs({ optional: true })
|
|
140
|
-
if (lateController) {
|
|
141
|
-
attemptSetup(lateController)
|
|
142
|
-
} else if (import.meta.env?.DEV) {
|
|
143
|
-
console.warn('[RouterTabs] Pinia helper must be used inside <router-tab>.')
|
|
144
|
-
}
|
|
145
|
-
})
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return store
|
|
149
|
-
}
|