vue3-router-tab 1.1.0 → 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 +26 -0
- package/dist/vue3-router-tab.js +387 -490
- package/dist/vue3-router-tab.umd.cjs +1 -12
- package/lib/components/RouterTab.vue +35 -27
- package/package.json +7 -7
- package/index.d.ts +0 -146
|
@@ -1,12 +1 @@
|
|
|
1
|
-
(function(C,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],t):(C=typeof globalThis<"u"?globalThis:C||self,t(C["vue3-router-tab"]={},C.Vue))})(this,(function(C,t){"use strict";/*!
|
|
2
|
-
* vue-router v4.5.1
|
|
3
|
-
* (c) 2025 Eduardo San Martin Morote
|
|
4
|
-
* @license MIT
|
|
5
|
-
*/const ae=typeof document<"u",ie=Object.assign,se=Array.isArray;function re(e){const n=Array.from(arguments).slice(1);console.warn.apply(console,["[Vue Router warn]: "+e].concat(n))}function le(e,n){return(e.aliasOf||e)===(n.aliasOf||n)}var q;(function(e){e.pop="pop",e.push="push"})(q||(q={}));var H;(function(e){e.back="back",e.forward="forward",e.unknown=""})(H||(H={})),Symbol(process.env.NODE_ENV!=="production"?"navigation failure":"");var Y;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(Y||(Y={}));const ce=Symbol(process.env.NODE_ENV!=="production"?"router view location matched":""),F=Symbol(process.env.NODE_ENV!=="production"?"router view depth":"");Symbol(process.env.NODE_ENV!=="production"?"router":""),Symbol(process.env.NODE_ENV!=="production"?"route location":"");const W=Symbol(process.env.NODE_ENV!=="production"?"router view location":""),ue=t.defineComponent({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:n,slots:a}){process.env.NODE_ENV!=="production"&&de();const o=t.inject(W),r=t.computed(()=>e.route||o.value),b=t.inject(F,0),p=t.computed(()=>{let m=t.unref(b);const{matched:h}=r.value;let y;for(;(y=h[m])&&!y.components;)m++;return m}),l=t.computed(()=>r.value.matched[p.value]);t.provide(F,t.computed(()=>p.value+1)),t.provide(ce,l),t.provide(W,r);const c=t.ref();return t.watch(()=>[c.value,l.value,e.name],([m,h,y],[R,g,w])=>{h&&(h.instances[y]=m,g&&g!==h&&m&&m===R&&(h.leaveGuards.size||(h.leaveGuards=g.leaveGuards),h.updateGuards.size||(h.updateGuards=g.updateGuards))),m&&h&&(!g||!le(h,g)||!R)&&(h.enterCallbacks[y]||[]).forEach(v=>v(m))},{flush:"post"}),()=>{const m=r.value,h=e.name,y=l.value,R=y&&y.components[h];if(!R)return X(a.default,{Component:R,route:m});const g=y.props[h],w=g?g===!0?m.params:typeof g=="function"?g(m):g:null,v=E=>{E.component.isUnmounted&&(y.instances[h]=null)},_=t.h(R,ie({},w,n,{onVnodeUnmounted:v,ref:c}));if(process.env.NODE_ENV!=="production"&&ae&&_.ref){const E={depth:p.value,name:y.name,path:y.path,meta:y.meta};(se(_.ref)?_.ref.map(P=>P.i):[_.ref.i]).forEach(P=>{P.__vrv_devtools=E})}return X(a.default,{Component:_,route:m})||_}}});function X(e,n){if(!e)return null;const a=e(n);return a.length===1?a[0]:a}const fe=ue;function de(){const e=t.getCurrentInstance(),n=e.parent&&e.parent.type.name,a=e.parent&&e.parent.subTree&&e.parent.subTree.type;if(n&&(n==="KeepAlive"||n.includes("Transition"))&&typeof a=="object"&&a.name==="RouterView"){const o=n==="KeepAlive"?"keep-alive":"transition";re(`<router-view> can no longer be used directly inside <transition> or <keep-alive>.
|
|
6
|
-
Use slot props instead:
|
|
7
|
-
|
|
8
|
-
<router-view v-slot="{ Component }">
|
|
9
|
-
<${o}>
|
|
10
|
-
<component :is="Component" />
|
|
11
|
-
</${o}>
|
|
12
|
-
</router-view>`)}}function pe(e={}){return{initialTabs:e.initialTabs??[],keepAlive:e.keepAlive??!0,maxAlive:e.maxAlive??0,keepLastTab:e.keepLastTab??!0,appendPosition:e.appendPosition??"last",defaultRoute:e.defaultRoute??"/"}}function S(e,n){const a=e.resolve(n);if(!a||!a.matched.length)throw new Error(`[RouterTabs] Unable to resolve route: ${String(n)}`);return a}const be={path:e=>e.path,fullpath:e=>e.fullPath,fullname:e=>e.fullPath,full:e=>e.fullPath,name:e=>e.name?String(e.name):e.fullPath};function V(e){const n=e.meta?.key;if(typeof n=="function"){const a=n(e);if(typeof a=="string"&&a.length)return a}else if(typeof n=="string"&&n.length){const a=be[n.toLowerCase()];return a?a(e):n}return e.fullPath}function I(e,n){const a=e.meta?.keepAlive;return typeof a=="boolean"?a:n}function O(e,n){const a=e.meta?.reuse;return typeof a=="boolean"?a:n}function Q(e){const n=e.meta??{},a={};return"title"in n&&(a.title=n.title),"tips"in n&&(a.tips=n.tips),"icon"in n&&(a.icon=n.icon),"closable"in n&&(a.closable=n.closable),"tabClass"in n&&(a.tabClass=n.tabClass),"target"in n&&(a.target=n.target),"href"in n&&(a.href=n.href),a}function K(e,n,a){const o=Q(e);return{id:V(e),to:e.fullPath,fullPath:e.fullPath,matched:e,alive:I(e,a),reusable:O(e,!1),closable:o.closable??!0,...o,...n}}function D(e,n,a,o){if(!e.find(b=>b.id===n.id)){if(a==="next"&&o){const b=e.findIndex(p=>p.id===o);if(b>-1){e.splice(b+1,0,n);return}}e.push(n)}}function Z(e,n,a){if(!n||n<=0)return;const o=e.filter(r=>r.alive);for(;o.length>n;){const r=o.shift();if(!r||r.id===a)continue;const b=e.findIndex(p=>p.id===r.id);b>-1&&(e[b].alive=!1)}}function me(e){return{to:e.to,title:e.title,tips:e.tips,icon:e.icon,tabClass:e.tabClass,closable:e.closable}}function he(e){const n={};return"title"in e&&(n.title=e.title),"tips"in e&&(n.tips=e.tips),"icon"in e&&(n.icon=e.icon),"tabClass"in e&&(n.tabClass=e.tabClass),"closable"in e&&(n.closable=e.closable),n}function ye(e,n={}){const a=pe(n),o=t.reactive([]),r=t.ref(null),b=t.shallowRef(),p=t.ref(null),l=t.computed(()=>o.filter(s=>s.alive).map(s=>s.id));let c=!1;function m(s){const u=typeof s.matched=="object"?s:S(e,s);return{key:V(u),fullPath:u.fullPath,alive:I(u,a.keepAlive),reusable:O(u,!1),matched:u}}function h(s){const u=V(s);let f=o.find(k=>k.id===u);return f?(f.fullPath=s.fullPath,f.to=s.fullPath,f.matched=s,f.alive=I(s,a.keepAlive),f.reusable=O(s,f.reusable),Object.assign(f,Q(s)),f):(f=K(s,{},a.keepAlive),D(o,f,a.appendPosition,r.value),Z(o,a.maxAlive,r.value),f)}async function y(s,u=!1,f=!0){const k=S(e,s),i=V(k),d=r.value===i;f==="sameTab"&&(f=d),f&&await v(i,!0),await e[u?"replace":"push"](k),d&&await N()}function R(s){const u=o.findIndex(k=>k.id===s),f=o[u]||o[u-1]||o[0];return f?f.to:a.defaultRoute}async function g(s=r.value,u={}){if(s){if(!u.force&&a.keepLastTab&&o.length===1)throw new Error("[RouterTabs] Unable to close the final tab when keepLastTab is true.");if(await w(s,{force:u.force}),u.redirect!==null)if(r.value===s){const f=u.redirect??R(s);f&&await e.replace(f)}else u.redirect&&await e.replace(u.redirect)}}async function w(s,u={}){const f=o.findIndex(k=>k.id===s);f!==-1&&(o.splice(f,1),p.value===s&&(p.value=null),r.value===s&&(r.value=null,b.value=void 0))}async function v(s=r.value??void 0,u=!1){s&&(p.value=s,await t.nextTick(),u||await t.nextTick(),p.value=null)}async function _(s=!1){for(const u of o)await v(u.id,s)}async function E(s=a.defaultRoute){o.splice(0,o.length),r.value=null,b.value=void 0;for(const u of a.initialTabs){const f=S(e,u.to),k=K(f,u,a.keepAlive);o.push(k)}await e.replace(s)}async function N(){const s=r.value;s&&await v(s,!0)}function P(s){return typeof s.matched=="object"?V(s):V(S(e,s))}function $(){const s=o.find(u=>u.id===r.value);return{tabs:o.map(me),active:s?s.to:null}}async function U(s){c=!0,o.splice(0,o.length),r.value=null,b.value=void 0;const u=s?.tabs??[];for(const k of u)try{const i=S(e,k.to),d=he(k),T=K(i,d,a.keepAlive);D(o,T,"last",null)}catch{}c=!1;const f=s?.active??u[u.length-1]?.to??a.defaultRoute;if(f)try{await e.replace(f)}catch{}}return t.watch(()=>e.currentRoute.value,s=>{if(c)return;const u=h(s);r.value=u.id,b.value=u,Z(o,a.maxAlive,r.value)},{immediate:!0}),a.initialTabs.length&&a.initialTabs.forEach(s=>{const u=S(e,s.to),f=K(u,s,a.keepAlive);D(o,f,"last",null)}),{options:a,tabs:o,activeId:r,current:b,includeKeys:l,refreshingKey:p,openTab:y,closeTab:g,removeTab:w,refreshTab:v,refreshAll:_,reset:E,reload:N,getRouteKey:P,matchRoute:m,snapshot:$,hydrate:U}}function ee(e){return e?typeof e=="string"?{name:e}:e:{}}const x=Symbol("RouterTabsContext"),ge="router-tabs:snapshot";function M(e={}){const{optional:n=!1}=e,a=t.inject(x,null);if(a)return a;const o=t.inject("$tabs",null);if(o)return o;const b=t.getCurrentInstance()?.appContext.config.globalProperties.$tabs;if(b)return b;if(!n)throw new Error("[RouterTabs] useRouterTabs must be used within <router-tab>.");return null}const ke=864e5;function Te(e){if(typeof document>"u")return null;const n=`${encodeURIComponent(e)}=`,a=document.cookie?document.cookie.split("; "):[];for(const o of a)if(o.startsWith(n))return decodeURIComponent(o.slice(n.length));return null}function te(e,n,a){if(typeof document>"u")return;const{expiresInDays:o=7,path:r="/",domain:b,secure:p,sameSite:l="lax"}=a,c=[`${encodeURIComponent(e)}=${encodeURIComponent(n)}`];if(o!==1/0){const m=new Date(Date.now()+o*ke).toUTCString();c.push(`Expires=${m}`)}r&&c.push(`Path=${r}`),b&&c.push(`Domain=${b}`),p&&c.push("Secure"),l&&c.push(`SameSite=${l.charAt(0).toUpperCase()}${l.slice(1)}`),document.cookie=c.join("; ")}function ne(e,n){if(typeof document>"u")return;const{path:a="/",domain:o}=n,r=[`${encodeURIComponent(e)}=`];r.push("Expires=Thu, 01 Jan 1970 00:00:01 GMT"),a&&r.push(`Path=${a}`),o&&r.push(`Domain=${o}`),document.cookie=r.join("; ")}const we=e=>JSON.stringify(e??null),Ce=e=>{if(!e)return null;try{return JSON.parse(e)}catch{return null}};function j(e={}){const{cookieKey:n=ge,serialize:a=we,deserialize:o=Ce}=e,r=M({optional:!0}),b=t.ref(!1),p=l=>{t.onMounted(async()=>{const c=o(Te(n));if(c&&c.tabs?.length)try{b.value=!0,await l.hydrate(c)}finally{b.value=!1}else try{b.value=!0;const h=e.fallbackRoute??l.options.defaultRoute;await l.reset(h)}finally{b.value=!1}const m=l.snapshot();m.tabs.length?te(n,a(m),e):ne(n,e)}),t.watch(()=>({tabs:l.tabs.map(c=>({to:c.to,title:c.title,tips:c.tips,icon:c.icon,tabClass:c.tabClass,closable:c.closable})),active:l.activeId.value}),()=>{if(b.value)return;const c=l.snapshot();c.tabs.length?te(n,a(c),e):ne(n,e)},{deep:!0})};r?p(r):t.onMounted(()=>{const l=M({optional:!0});l&&p(l)})}const Re=t.defineComponent({name:"RouterTab",components:{RouterView:fe},props:{tabs:{type:Array,default:()=>[]},keepAlive:{type:Boolean,default:!0},maxAlive:{type:Number,default:0},keepLastTab:{type:Boolean,default:!0},append:{type:String,default:"last"},defaultPage:{type:[String,Object],default:"/"},tabTransition:{type:[String,Object],default:"router-tab-zoom"},pageTransition:{type:[String,Object],default:()=>({name:"router-tab-swap",mode:"out-in"})},contextmenu:{type:[Boolean,Array],default:!0},cookieKey:{type:String,default:null},persistence:{type:Object,default:null}},setup(e){const n=t.getCurrentInstance();if(!n)throw new Error("[RouterTab] component must be used within a Vue application context.");const a=n.appContext.app.config.globalProperties.$router;if(!a)throw new Error("[RouterTab] Vue Router is required. Make sure to call app.use(router) before RouterTab.");const o=ye(a,{initialTabs:e.tabs,keepAlive:e.keepAlive,maxAlive:e.maxAlive,keepLastTab:e.keepLastTab,appendPosition:e.append,defaultRoute:e.defaultPage});if(t.provide(x,o),n.appContext.config.globalProperties.$tabs=o,e.cookieKey||e.persistence){const i={...e.persistence??{}};e.cookieKey&&(i.cookieKey=e.cookieKey),j(i)}const r=t.computed(()=>ee(e.tabTransition)),b=t.computed(()=>ee(e.pageTransition)),p=t.reactive({visible:!1,target:null,position:{x:0,y:0}}),l=["refresh","refreshAll","close","closeLefts","closeRights","closeOthers"];function c(i){return o.tabs.findIndex(d=>d.id===i)}function m(i){const d=c(i.id);return d>0?o.tabs.slice(0,d):[]}function h(i){const d=c(i.id);return d>-1?o.tabs.slice(d+1):[]}function y(i){return o.tabs.filter(d=>d.id!==i.id)}async function R(i,d){const T=i.filter(A=>A.closable!==!1);if(T.length){for(const A of T)o.activeId.value===A.id?await o.closeTab(A.id,{redirect:d.to,force:!0}):await o.removeTab(A.id,{force:!0});o.activeId.value!==d.id&&await o.openTab(d.to,!0,!1)}}const g={refresh:{label:"Refresh",handler:async({target:i})=>{await o.refreshTab(i.id,!0)}},refreshAll:{label:"Refresh All",handler:async()=>{await o.refreshAll(!0)}},close:{label:"Close",handler:async({target:i})=>{await o.closeTab(i.id)},enable:({target:i})=>$(i)},closeLefts:{label:"Close to the Left",handler:async({target:i})=>{await R(m(i),i)},enable:({target:i})=>m(i).some(d=>d.closable!==!1)},closeRights:{label:"Close to the Right",handler:async({target:i})=>{await R(h(i),i)},enable:({target:i})=>h(i).some(d=>d.closable!==!1)},closeOthers:{label:"Close Others",handler:async({target:i})=>{await R(y(i),i)},enable:({target:i})=>y(i).some(d=>d.closable!==!1)}};function w(){p.visible=!1,p.target=null}function v(i,d){e.contextmenu&&(p.visible=!0,p.target=i,p.position.x=d.clientX,p.position.y=d.clientY,document.addEventListener("click",w,{once:!0}))}function _(i,d){const T=typeof i=="string"?{id:i}:i,A=g[T.id],Oe=T.label??A?.label??String(T.id),G=T.visible??A?.visible??!0;if(!(typeof G=="function"?G(d):G!==!1))return null;const J=T.enable??A?.enable??!0,De=typeof J=="function"?J(d):J!==!1,oe=T.handler??A?.handler;if(!oe)return null;const Me=async()=>{await Promise.resolve(oe(d))};return{id:String(T.id),label:Oe,disabled:!De,action:Me}}const E=t.computed(()=>{if(!p.visible||!p.target||e.contextmenu===!1)return[];const i=Array.isArray(e.contextmenu)?e.contextmenu:l,d={target:p.target,controller:o};return i.map(T=>_(T,d)).filter(T=>!!T)});async function N(i){i.disabled||(w(),await i.action())}function P(i){return typeof i.title=="string"?i.title:Array.isArray(i.title)&&i.title.length?String(i.title[0]):i.fullPath}function $(i){return!(i.closable===!1||o.options.keepLastTab&&o.tabs.length<=1)}async function U(i){await o.closeTab(i.id)}function s(i){o.activeId.value!==i.id&&o.openTab(i.to,!1)}function u(i){return["router-tab__item",{"is-active":o.activeId.value===i.id,"is-closable":$(i)},i.tabClass]}function f(i){return o.refreshingKey.value===o.getRouteKey(i)}t.onMounted(()=>{document.addEventListener("keydown",w)}),t.onBeforeUnmount(()=>{document.removeEventListener("keydown",w),n.appContext.config.globalProperties.$tabs=null}),t.watch(()=>e.keepAlive,i=>{o.options.keepAlive=i}),t.watch(()=>o.activeId.value,()=>w()),t.watch(()=>e.contextmenu,i=>{i||w()}),t.watch(()=>E.value.length,i=>{p.visible&&i===0&&w()});const k=o.includeKeys;return{controller:o,tabs:o.tabs,includeKeys:k,tabTransitionProps:r,pageTransitionProps:b,buildTabClass:u,activate:s,close:U,context:p,menuItems:E,handleMenuAction:N,showContextMenu:v,hideContextMenu:w,tabTitle:P,isClosable:$,isRefreshing:f}}}),ve=(e,n)=>{const a=e.__vccOpts||e;for(const[o,r]of n)a[o]=r;return a},_e={class:"router-tab"},Ae={class:"router-tab__header"},Ee={class:"router-tab__slot-start"},Pe={class:"router-tab__scroll"},Se=["onClick","onAuxclick","onContextmenu"],Ve=["title"],xe=["onClick"],Ne={class:"router-tab__slot-end"},$e={class:"router-tab__container"},Ke=["aria-disabled","onClick"];function Be(e,n,a,o,r,b){const p=t.resolveComponent("RouterView");return t.openBlock(),t.createElementBlock("div",_e,[t.createElementVNode("header",Ae,[t.createElementVNode("div",Ee,[t.renderSlot(e.$slots,"start")]),t.createElementVNode("div",Pe,[t.createVNode(t.TransitionGroup,t.mergeProps({tag:"ul",class:"router-tab__nav"},e.tabTransitionProps),{default:t.withCtx(()=>[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(e.tabs,l=>(t.openBlock(),t.createElementBlock("li",{key:l.id,class:t.normalizeClass(e.buildTabClass(l)),onClick:c=>e.activate(l),onAuxclick:t.withModifiers(c=>e.close(l),["middle","prevent"]),onContextmenu:t.withModifiers(c=>e.showContextMenu(l,c),["prevent"])},[t.createElementVNode("span",{class:"router-tab__item-title",title:e.tabTitle(l)},[l.icon?(t.openBlock(),t.createElementBlock("i",{key:0,class:t.normalizeClass(["router-tab__item-icon",l.icon])},null,2)):t.createCommentVNode("",!0),t.createTextVNode(" "+t.toDisplayString(e.tabTitle(l)),1)],8,Ve),e.isClosable(l)?(t.openBlock(),t.createElementBlock("a",{key:0,class:"router-tab__item-close",type:"button",onClick:t.withModifiers(c=>e.close(l),["stop"])},null,8,xe)):t.createCommentVNode("",!0)],42,Se))),128))]),_:1},16)]),t.createElementVNode("div",Ne,[t.renderSlot(e.$slots,"end")])]),t.createElementVNode("div",$e,[t.createVNode(p,null,{default:t.withCtx(({Component:l,route:c})=>[t.createVNode(t.Transition,t.mergeProps(e.pageTransitionProps,{appear:""}),{default:t.withCtx(()=>[e.controller.options.keepAlive?(t.openBlock(),t.createBlock(t.KeepAlive,{key:0,include:e.includeKeys,max:e.controller.options.maxAlive||void 0},[e.isRefreshing(c)?t.createCommentVNode("",!0):(t.openBlock(),t.createBlock(t.resolveDynamicComponent(l),{key:e.controller.getRouteKey(c),class:"router-tab-page"}))],1032,["include","max"])):t.createCommentVNode("",!0)]),_:2},1040),t.createVNode(t.Transition,t.mergeProps(e.pageTransitionProps,{appear:""}),{default:t.withCtx(()=>[!e.controller.options.keepAlive||e.isRefreshing(c)?(t.openBlock(),t.createBlock(t.resolveDynamicComponent(l),{key:e.controller.getRouteKey(c)+(e.isRefreshing(c)?"-refresh":""),class:"router-tab-page"})):t.createCommentVNode("",!0)]),_:2},1040)]),_:1})]),e.context.visible&&e.context.target?(t.openBlock(),t.createElementBlock("div",{key:0,class:"router-tab__contextmenu",style:t.normalizeStyle({left:e.context.position.x+"px",top:e.context.position.y+"px"})},[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(e.menuItems,l=>(t.openBlock(),t.createElementBlock("a",{key:l.id,class:"router-tab__contextmenu-item","aria-disabled":l.disabled,onClick:t.withModifiers(c=>e.handleMenuAction(l),["prevent"])},t.toDisplayString(l.label),9,Ke))),128))],4)):t.createCommentVNode("",!0)])}const L=ve(Re,[["render",Be]]),Ie={class:"router-tabs","aria-hidden":"true"},B=t.defineComponent({name:"RouterTabs",__name:"RouterTabs",props:{cookieKey:{},expiresInDays:{},path:{},domain:{},secure:{type:Boolean},sameSite:{},serialize:{type:Function},deserialize:{type:Function},fallbackRoute:{}},setup(e){return j(e),(a,o)=>(t.openBlock(),t.createElementBlock("span",Ie))}}),z={install(e){if(z._installed)return;z._installed=!0;const n=L.name||"RouterTab",a=B.name||"RouterTabs";e.component(n,L),e.component(a,B),a!=="router-tabs"&&e.component("router-tabs",B),Object.defineProperty(e.config.globalProperties,"$tabs",{configurable:!0,enumerable:!1,get(){return e._context.provides[x]},set(o){o&&e.provide(x,o)}})}};C.RouterTab=L,C.RouterTabs=B,C.default=z,C.routerTabsKey=x,C.useRouterTabs=M,C.useRouterTabsPersistence=j,Object.defineProperties(C,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|
|
1
|
+
(function(y,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("vue"),require("vue-router")):typeof define=="function"&&define.amd?define(["exports","vue","vue-router"],t):(y=typeof globalThis<"u"?globalThis:y||self,t(y["vue3-router-tab"]={},y.Vue,y.VueRouter))})(this,(function(y,t,Z){"use strict";function ee(e={}){return{initialTabs:e.initialTabs??[],keepAlive:e.keepAlive??!0,maxAlive:e.maxAlive??0,keepLastTab:e.keepLastTab??!0,appendPosition:e.appendPosition??"last",defaultRoute:e.defaultRoute??"/"}}function w(e,o){const a=e.resolve(o);if(!a||!a.matched.length)throw new Error(`[RouterTabs] Unable to resolve route: ${String(o)}`);return a}const te={path:e=>e.path,fullpath:e=>e.fullPath,fullname:e=>e.fullPath,full:e=>e.fullPath,name:e=>e.name?String(e.name):e.fullPath};function R(e){const o=e.meta?.key;if(typeof o=="function"){const a=o(e);if(typeof a=="string"&&a.length)return a}else if(typeof o=="string"&&o.length){const a=te[o.toLowerCase()];return a?a(e):o}return e.fullPath}function I(e,o){const a=e.meta?.keepAlive;return typeof a=="boolean"?a:o}function K(e,o){const a=e.meta?.reuse;return typeof a=="boolean"?a:o}function J(e){const o=e.meta??{},a={};return"title"in o&&(a.title=o.title),"tips"in o&&(a.tips=o.tips),"icon"in o&&(a.icon=o.icon),"closable"in o&&(a.closable=o.closable),"tabClass"in o&&(a.tabClass=o.tabClass),"target"in o&&(a.target=o.target),"href"in o&&(a.href=o.href),a}function B(e,o,a){const n=J(e);return{id:R(e),to:e.fullPath,fullPath:e.fullPath,matched:e,alive:I(e,a),reusable:K(e,!1),closable:n.closable??!0,...n,...o}}function N(e,o,a,n){if(!e.find(b=>b.id===o.id)){if(a==="next"&&n){const b=e.findIndex(p=>p.id===n);if(b>-1){e.splice(b+1,0,o);return}}e.push(o)}}function H(e,o,a){if(!o||o<=0)return;const n=e.filter(c=>c.alive);for(;n.length>o;){const c=n.shift();if(!c||c.id===a)continue;const b=e.findIndex(p=>p.id===c.id);b>-1&&(e[b].alive=!1)}}function ne(e){return{to:e.to,title:e.title,tips:e.tips,icon:e.icon,tabClass:e.tabClass,closable:e.closable}}function oe(e){const o={};return"title"in e&&(o.title=e.title),"tips"in e&&(o.tips=e.tips),"icon"in e&&(o.icon=e.icon),"tabClass"in e&&(o.tabClass=e.tabClass),"closable"in e&&(o.closable=e.closable),o}function ie(e,o={}){const a=ee(o),n=t.reactive([]),c=t.ref(null),b=t.shallowRef(),p=t.ref(null),s=t.computed(()=>n.filter(l=>l.alive).map(l=>l.id));let f=!1;function T(l){const r=typeof l.matched=="object"?l:w(e,l);return{key:R(r),fullPath:r.fullPath,alive:I(r,a.keepAlive),reusable:K(r,!1),matched:r}}function A(l){const r=R(l);let u=n.find(m=>m.id===r);return u?(u.fullPath=l.fullPath,u.to=l.fullPath,u.matched=l,u.alive=I(l,a.keepAlive),u.reusable=K(l,u.reusable),Object.assign(u,J(l)),u):(u=B(l,{},a.keepAlive),N(n,u,a.appendPosition,c.value),H(n,a.maxAlive,c.value),u)}async function E(l,r=!1,u=!0){const m=w(e,l),C=R(m),i=c.value===C;u==="sameTab"&&(u=i),u&&await g(C,!0),await e[r?"replace":"push"](m),i&&await v()}function S(l){const r=n.findIndex(m=>m.id===l),u=n[r]||n[r-1]||n[0];return u?u.to:a.defaultRoute}async function P(l=c.value,r={}){if(l){if(!r.force&&a.keepLastTab&&n.length===1)throw new Error("[RouterTabs] Unable to close the final tab when keepLastTab is true.");if(await V(l,{force:r.force}),r.redirect!==null)if(c.value===l){const u=r.redirect??S(l);u&&await e.replace(u)}else r.redirect&&await e.replace(r.redirect)}}async function V(l,r={}){const u=n.findIndex(m=>m.id===l);u!==-1&&(n.splice(u,1),p.value===l&&(p.value=null),c.value===l&&(c.value=null,b.value=void 0))}async function g(l=c.value??void 0,r=!1){l&&(p.value=l,await t.nextTick(),r||await t.nextTick(),p.value=null)}async function D(l=!1){for(const r of n)await g(r.id,l)}async function O(l=a.defaultRoute){n.splice(0,n.length),c.value=null,b.value=void 0;for(const r of a.initialTabs){const u=w(e,r.to),m=B(u,r,a.keepAlive);n.push(m)}await e.replace(l)}async function v(){const l=c.value;l&&await g(l,!0)}function U(l){return typeof l.matched=="object"?R(l):R(w(e,l))}function F(){const l=n.find(r=>r.id===c.value);return{tabs:n.map(ne),active:l?l.to:null}}async function x(l){f=!0,n.splice(0,n.length),c.value=null,b.value=void 0;const r=l?.tabs??[];for(const m of r)try{const C=w(e,m.to),i=oe(m),d=B(C,i,a.keepAlive);N(n,d,"last",null)}catch{}f=!1;const u=l?.active??r[r.length-1]?.to??a.defaultRoute;if(u)try{await e.replace(u)}catch{}}return t.watch(()=>e.currentRoute.value,l=>{if(f)return;const r=A(l);c.value=r.id,b.value=r,H(n,a.maxAlive,c.value)},{immediate:!0}),a.initialTabs.length&&a.initialTabs.forEach(l=>{const r=w(e,l.to),u=B(r,l,a.keepAlive);N(n,u,"last",null)}),{options:a,tabs:n,activeId:c,current:b,includeKeys:s,refreshingKey:p,openTab:E,closeTab:P,removeTab:V,refreshTab:g,refreshAll:D,reset:O,reload:v,getRouteKey:U,matchRoute:T,snapshot:F,hydrate:x}}function Y(e){return e?typeof e=="string"?{name:e}:e:{}}const _=Symbol("RouterTabsContext"),ae="router-tabs:snapshot";function M(e={}){const{optional:o=!1}=e,a=t.inject(_,null);if(a)return a;const n=t.inject("$tabs",null);if(n)return n;const b=t.getCurrentInstance()?.appContext.config.globalProperties.$tabs;if(b)return b;if(!o)throw new Error("[RouterTabs] useRouterTabs must be used within <router-tab>.");return null}const le=864e5;function se(e){if(typeof document>"u")return null;const o=`${encodeURIComponent(e)}=`,a=document.cookie?document.cookie.split("; "):[];for(const n of a)if(n.startsWith(o))return decodeURIComponent(n.slice(o.length));return null}function W(e,o,a){if(typeof document>"u")return;const{expiresInDays:n=7,path:c="/",domain:b,secure:p,sameSite:s="lax"}=a,f=[`${encodeURIComponent(e)}=${encodeURIComponent(o)}`];if(n!==1/0){const T=new Date(Date.now()+n*le).toUTCString();f.push(`Expires=${T}`)}c&&f.push(`Path=${c}`),b&&f.push(`Domain=${b}`),p&&f.push("Secure"),s&&f.push(`SameSite=${s.charAt(0).toUpperCase()}${s.slice(1)}`),document.cookie=f.join("; ")}function X(e,o){if(typeof document>"u")return;const{path:a="/",domain:n}=o,c=[`${encodeURIComponent(e)}=`];c.push("Expires=Thu, 01 Jan 1970 00:00:01 GMT"),a&&c.push(`Path=${a}`),n&&c.push(`Domain=${n}`),document.cookie=c.join("; ")}const re=e=>JSON.stringify(e??null),ce=e=>{if(!e)return null;try{return JSON.parse(e)}catch{return null}};function L(e={}){const{cookieKey:o=ae,serialize:a=re,deserialize:n=ce}=e,c=M({optional:!0}),b=t.ref(!1),p=s=>{t.onMounted(async()=>{const f=n(se(o));if(f&&f.tabs?.length)try{b.value=!0,await s.hydrate(f)}finally{b.value=!1}else try{b.value=!0;const A=e.fallbackRoute??s.options.defaultRoute;await s.reset(A)}finally{b.value=!1}const T=s.snapshot();T.tabs.length?W(o,a(T),e):X(o,e)}),t.watch(()=>({tabs:s.tabs.map(f=>({to:f.to,title:f.title,tips:f.tips,icon:f.icon,tabClass:f.tabClass,closable:f.closable})),active:s.activeId.value}),()=>{if(b.value)return;const f=s.snapshot();f.tabs.length?W(o,a(f),e):X(o,e)},{deep:!0})};c?p(c):t.onMounted(()=>{const s=M({optional:!0});s&&p(s)})}const ue=t.defineComponent({name:"RouterTab",components:{RouterView:Z.RouterView},props:{tabs:{type:Array,default:()=>[]},keepAlive:{type:Boolean,default:!0},maxAlive:{type:Number,default:0},keepLastTab:{type:Boolean,default:!0},append:{type:String,default:"last"},defaultPage:{type:[String,Object],default:"/"},tabTransition:{type:[String,Object],default:"router-tab-zoom"},pageTransition:{type:[String,Object],default:()=>({name:"router-tab-swap",mode:"out-in"})},contextmenu:{type:[Boolean,Array],default:!0},cookieKey:{type:String,default:null},persistence:{type:Object,default:null}},setup(e){const o=t.getCurrentInstance();if(!o)throw new Error("[RouterTab] component must be used within a Vue application context.");const a=o.appContext.app.config.globalProperties.$router;if(!a)throw new Error("[RouterTab] Vue Router is required. Make sure to call app.use(router) before RouterTab.");const n=ie(a,{initialTabs:e.tabs,keepAlive:e.keepAlive,maxAlive:e.maxAlive,keepLastTab:e.keepLastTab,appendPosition:e.append,defaultRoute:e.defaultPage});t.provide(_,n),o.appContext.config.globalProperties.$tabs=n;const c=t.computed(()=>!!o?.slots?.default);if(e.cookieKey||e.persistence){const i={...e.persistence??{}};e.cookieKey&&(i.cookieKey=e.cookieKey),L(i)}const b=t.computed(()=>Y(e.tabTransition)),p=t.computed(()=>Y(e.pageTransition)),s=t.reactive({visible:!1,target:null,position:{x:0,y:0}}),f=["refresh","refreshAll","close","closeLefts","closeRights","closeOthers"];function T(i){return n.tabs.findIndex(d=>d.id===i)}function A(i){const d=T(i.id);return d>0?n.tabs.slice(0,d):[]}function E(i){const d=T(i.id);return d>-1?n.tabs.slice(d+1):[]}function S(i){return n.tabs.filter(d=>d.id!==i.id)}async function P(i,d){const h=i.filter(k=>k.closable!==!1);if(h.length){for(const k of h)n.activeId.value===k.id?await n.closeTab(k.id,{redirect:d.to,force:!0}):await n.removeTab(k.id,{force:!0});n.activeId.value!==d.id&&await n.openTab(d.to,!0,!1)}}const V={refresh:{label:"Refresh",handler:async({target:i})=>{await n.refreshTab(i.id,!0)}},refreshAll:{label:"Refresh All",handler:async()=>{await n.refreshAll(!0)}},close:{label:"Close",handler:async({target:i})=>{await n.closeTab(i.id)},enable:({target:i})=>x(i)},closeLefts:{label:"Close to the Left",handler:async({target:i})=>{await P(A(i),i)},enable:({target:i})=>A(i).some(d=>d.closable!==!1)},closeRights:{label:"Close to the Right",handler:async({target:i})=>{await P(E(i),i)},enable:({target:i})=>E(i).some(d=>d.closable!==!1)},closeOthers:{label:"Close Others",handler:async({target:i})=>{await P(S(i),i)},enable:({target:i})=>S(i).some(d=>d.closable!==!1)}};function g(){s.visible=!1,s.target=null}function D(i,d){e.contextmenu&&(s.visible=!0,s.target=i,s.position.x=d.clientX,s.position.y=d.clientY,document.addEventListener("click",g,{once:!0}))}function O(i,d){const h=typeof i=="string"?{id:i}:i,k=V[h.id],Ae=h.label??k?.label??String(h.id),q=h.visible??k?.visible??!0;if(!(typeof q=="function"?q(d):q!==!1))return null;const G=h.enable??k?.enable??!0,_e=typeof G=="function"?G(d):G!==!1,Q=h.handler??k?.handler;if(!Q)return null;const Pe=async()=>{await Promise.resolve(Q(d))};return{id:String(h.id),label:Ae,disabled:!_e,action:Pe}}const v=t.computed(()=>{if(!s.visible||!s.target||e.contextmenu===!1)return[];const i=Array.isArray(e.contextmenu)?e.contextmenu:f,d={target:s.target,controller:n};return i.map(h=>O(h,d)).filter(h=>!!h)});async function U(i){i.disabled||(g(),await i.action())}function F(i){return typeof i.title=="string"?i.title:Array.isArray(i.title)&&i.title.length?String(i.title[0]):i.fullPath}function x(i){return!(i.closable===!1||n.options.keepLastTab&&n.tabs.length<=1)}async function l(i){await n.closeTab(i.id)}function r(i){n.activeId.value!==i.id&&n.openTab(i.to,!1)}function u(i){return["router-tab__item",{"is-active":n.activeId.value===i.id,"is-closable":x(i)},i.tabClass]}function m(i){return n.refreshingKey.value===n.getRouteKey(i)}t.onMounted(()=>{document.addEventListener("keydown",g)}),t.onBeforeUnmount(()=>{document.removeEventListener("keydown",g),o.appContext.config.globalProperties.$tabs=null}),t.watch(()=>e.keepAlive,i=>{n.options.keepAlive=i}),t.watch(()=>n.activeId.value,()=>g()),t.watch(()=>e.contextmenu,i=>{i||g()}),t.watch(()=>v.value.length,i=>{s.visible&&i===0&&g()});const C=n.includeKeys;return{controller:n,tabs:n.tabs,includeKeys:C,tabTransitionProps:b,pageTransitionProps:p,buildTabClass:u,activate:r,close:l,context:s,menuItems:v,handleMenuAction:U,showContextMenu:D,hideContextMenu:g,tabTitle:F,isClosable:x,isRefreshing:m,hasCustomSlot:c}}}),fe=(e,o)=>{const a=e.__vccOpts||e;for(const[n,c]of o)a[n]=c;return a},de={class:"router-tab"},be={class:"router-tab__header"},pe={class:"router-tab__slot-start"},me={class:"router-tab__scroll"},he=["onClick","onAuxclick","onContextmenu"],ye=["title"],ge=["onClick"],ke={class:"router-tab__slot-end"},Te={class:"router-tab__container"},Ce=["aria-disabled","onClick"];function we(e,o,a,n,c,b){const p=t.resolveComponent("RouterView");return t.openBlock(),t.createElementBlock("div",de,[t.createElementVNode("header",be,[t.createElementVNode("div",pe,[t.renderSlot(e.$slots,"start")]),t.createElementVNode("div",me,[t.createVNode(t.TransitionGroup,t.mergeProps({tag:"ul",class:"router-tab__nav"},e.tabTransitionProps),{default:t.withCtx(()=>[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(e.tabs,s=>(t.openBlock(),t.createElementBlock("li",{key:s.id,class:t.normalizeClass(e.buildTabClass(s)),onClick:f=>e.activate(s),onAuxclick:t.withModifiers(f=>e.close(s),["middle","prevent"]),onContextmenu:t.withModifiers(f=>e.showContextMenu(s,f),["prevent"])},[t.createElementVNode("span",{class:"router-tab__item-title",title:e.tabTitle(s)},[s.icon?(t.openBlock(),t.createElementBlock("i",{key:0,class:t.normalizeClass(["router-tab__item-icon",s.icon])},null,2)):t.createCommentVNode("",!0),t.createTextVNode(" "+t.toDisplayString(e.tabTitle(s)),1)],8,ye),e.isClosable(s)?(t.openBlock(),t.createElementBlock("a",{key:0,class:"router-tab__item-close",type:"button",onClick:t.withModifiers(f=>e.close(s),["stop"])},null,8,ge)):t.createCommentVNode("",!0)],42,he))),128))]),_:1},16)]),t.createElementVNode("div",ke,[t.renderSlot(e.$slots,"end")])]),t.createElementVNode("div",Te,[t.createVNode(p,null,{default:t.withCtx(s=>[e.hasCustomSlot?t.renderSlot(e.$slots,"default",t.normalizeProps(t.mergeProps({key:0},{...s,controller:e.controller}))):(t.openBlock(),t.createElementBlock(t.Fragment,{key:1},[t.createVNode(t.Transition,t.mergeProps(e.pageTransitionProps,{appear:""}),{default:t.withCtx(()=>[e.controller.options.keepAlive?(t.openBlock(),t.createBlock(t.KeepAlive,{key:0,include:e.includeKeys,max:e.controller.options.maxAlive||void 0},[e.isRefreshing(s.route)?t.createCommentVNode("",!0):(t.openBlock(),t.createBlock(t.resolveDynamicComponent(s.Component),{key:e.controller.getRouteKey(s.route),class:"router-tab-page"}))],1032,["include","max"])):t.createCommentVNode("",!0)]),_:2},1040),t.createVNode(t.Transition,t.mergeProps(e.pageTransitionProps,{appear:""}),{default:t.withCtx(()=>[!e.controller.options.keepAlive||e.isRefreshing(s.route)?(t.openBlock(),t.createBlock(t.resolveDynamicComponent(s.Component),{key:e.controller.getRouteKey(s.route)+(e.isRefreshing(s.route)?"-refresh":""),class:"router-tab-page"})):t.createCommentVNode("",!0)]),_:2},1040)],64))]),_:3})]),e.context.visible&&e.context.target?(t.openBlock(),t.createElementBlock("div",{key:0,class:"router-tab__contextmenu",style:t.normalizeStyle({left:e.context.position.x+"px",top:e.context.position.y+"px"})},[(t.openBlock(!0),t.createElementBlock(t.Fragment,null,t.renderList(e.menuItems,s=>(t.openBlock(),t.createElementBlock("a",{key:s.id,class:"router-tab__contextmenu-item","aria-disabled":s.disabled,onClick:t.withModifiers(f=>e.handleMenuAction(s),["prevent"])},t.toDisplayString(s.label),9,Ce))),128))],4)):t.createCommentVNode("",!0)])}const j=fe(ue,[["render",we]]),Re={class:"router-tabs","aria-hidden":"true"},$=t.defineComponent({name:"RouterTabs",__name:"RouterTabs",props:{cookieKey:{},expiresInDays:{},path:{},domain:{},secure:{type:Boolean},sameSite:{},serialize:{type:Function},deserialize:{type:Function},fallbackRoute:{}},setup(e){return L(e),(a,n)=>(t.openBlock(),t.createElementBlock("span",Re))}}),z={install(e){if(z._installed)return;z._installed=!0;const o=j.name||"RouterTab",a=$.name||"RouterTabs";e.component(o,j),e.component(a,$),a!=="router-tabs"&&e.component("router-tabs",$),Object.defineProperty(e.config.globalProperties,"$tabs",{configurable:!0,enumerable:!1,get(){return e._context.provides[_]},set(n){n&&e.provide(_,n)}})}};y.RouterTab=j,y.RouterTabs=$,y.default=z,y.routerTabsKey=_,y.useRouterTabs=M,y.useRouterTabsPersistence=L,Object.defineProperties(y,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|
|
@@ -39,36 +39,41 @@
|
|
|
39
39
|
</header>
|
|
40
40
|
|
|
41
41
|
<div class="router-tab__container">
|
|
42
|
-
<RouterView v-slot="
|
|
43
|
-
<
|
|
44
|
-
v-bind="
|
|
45
|
-
|
|
46
|
-
>
|
|
47
|
-
<
|
|
48
|
-
v-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
<RouterView v-slot="routerSlot">
|
|
43
|
+
<template v-if="hasCustomSlot">
|
|
44
|
+
<slot v-bind="{ ...routerSlot, controller }" />
|
|
45
|
+
</template>
|
|
46
|
+
<template v-else>
|
|
47
|
+
<transition
|
|
48
|
+
v-bind="pageTransitionProps"
|
|
49
|
+
appear
|
|
50
|
+
>
|
|
51
|
+
<KeepAlive
|
|
52
|
+
v-if="controller.options.keepAlive"
|
|
53
|
+
:include="includeKeys"
|
|
54
|
+
:max="controller.options.maxAlive || undefined"
|
|
55
|
+
>
|
|
56
|
+
<component
|
|
57
|
+
v-if="!isRefreshing(routerSlot.route)"
|
|
58
|
+
:is="routerSlot.Component"
|
|
59
|
+
:key="controller.getRouteKey(routerSlot.route)"
|
|
60
|
+
class="router-tab-page"
|
|
61
|
+
/>
|
|
62
|
+
</KeepAlive>
|
|
63
|
+
</transition>
|
|
64
|
+
|
|
65
|
+
<transition
|
|
66
|
+
v-bind="pageTransitionProps"
|
|
67
|
+
appear
|
|
51
68
|
>
|
|
52
69
|
<component
|
|
53
|
-
v-if="!isRefreshing(route)"
|
|
54
|
-
:is="Component"
|
|
55
|
-
:key="controller.getRouteKey(route)"
|
|
70
|
+
v-if="!controller.options.keepAlive || isRefreshing(routerSlot.route)"
|
|
71
|
+
:is="routerSlot.Component"
|
|
72
|
+
:key="controller.getRouteKey(routerSlot.route) + (isRefreshing(routerSlot.route) ? '-refresh' : '')"
|
|
56
73
|
class="router-tab-page"
|
|
57
74
|
/>
|
|
58
|
-
</
|
|
59
|
-
</
|
|
60
|
-
|
|
61
|
-
<transition
|
|
62
|
-
v-bind="pageTransitionProps"
|
|
63
|
-
appear
|
|
64
|
-
>
|
|
65
|
-
<component
|
|
66
|
-
v-if="!controller.options.keepAlive || isRefreshing(route)"
|
|
67
|
-
:is="Component"
|
|
68
|
-
:key="controller.getRouteKey(route) + (isRefreshing(route) ? '-refresh' : '')"
|
|
69
|
-
class="router-tab-page"
|
|
70
|
-
/>
|
|
71
|
-
</transition>
|
|
75
|
+
</transition>
|
|
76
|
+
</template>
|
|
72
77
|
</RouterView>
|
|
73
78
|
</div>
|
|
74
79
|
|
|
@@ -199,6 +204,8 @@ export default defineComponent({
|
|
|
199
204
|
provide(routerTabsKey, controller)
|
|
200
205
|
instance.appContext.config.globalProperties.$tabs = controller
|
|
201
206
|
|
|
207
|
+
const hasCustomSlot = computed(() => Boolean(instance?.slots?.default))
|
|
208
|
+
|
|
202
209
|
if (props.cookieKey || props.persistence) {
|
|
203
210
|
const options: RouterTabsPersistenceOptions = {
|
|
204
211
|
...(props.persistence ?? {})
|
|
@@ -464,7 +471,8 @@ export default defineComponent({
|
|
|
464
471
|
hideContextMenu,
|
|
465
472
|
tabTitle,
|
|
466
473
|
isClosable,
|
|
467
|
-
isRefreshing
|
|
474
|
+
isRefreshing,
|
|
475
|
+
hasCustomSlot
|
|
468
476
|
}
|
|
469
477
|
}
|
|
470
478
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vue3-router-tab",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -22,10 +22,6 @@
|
|
|
22
22
|
"scripts": {
|
|
23
23
|
"build": "vite build"
|
|
24
24
|
},
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"vue": "^3.5.22",
|
|
27
|
-
"vue-router": "^4.5.1"
|
|
28
|
-
},
|
|
29
25
|
"devDependencies": {
|
|
30
26
|
"@vitejs/plugin-vue": "^6.0.1",
|
|
31
27
|
"pinia": "^3.0.3",
|
|
@@ -34,7 +30,9 @@
|
|
|
34
30
|
"typescript": "^5.9.2",
|
|
35
31
|
"vite": "^7.1.7",
|
|
36
32
|
"vite-plugin-dts": "^4.5.4",
|
|
37
|
-
"vite-plugin-libcss": "^1.1.2"
|
|
33
|
+
"vite-plugin-libcss": "^1.1.2",
|
|
34
|
+
"vue": "^3.5.22",
|
|
35
|
+
"vue-router": "^4.5.1"
|
|
38
36
|
},
|
|
39
37
|
"keywords": [
|
|
40
38
|
"vue3-router-tab",
|
|
@@ -67,6 +65,8 @@
|
|
|
67
65
|
]
|
|
68
66
|
},
|
|
69
67
|
"peerDependencies": {
|
|
70
|
-
"pinia": "^2.1.7"
|
|
68
|
+
"pinia": "^2.1.7",
|
|
69
|
+
"vue": "^3.3.0",
|
|
70
|
+
"vue-router": "^4.2.0"
|
|
71
71
|
}
|
|
72
72
|
}
|
package/index.d.ts
DELETED
|
@@ -1,146 +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 RouterTabsPersistenceOptions {
|
|
34
|
-
cookieKey?: string
|
|
35
|
-
expiresInDays?: number
|
|
36
|
-
path?: string
|
|
37
|
-
domain?: string
|
|
38
|
-
secure?: boolean
|
|
39
|
-
sameSite?: 'lax' | 'strict' | 'none'
|
|
40
|
-
serialize?: (snapshot: RouterTabsSnapshot | null) => string
|
|
41
|
-
deserialize?: (value: string | null) => RouterTabsSnapshot | null
|
|
42
|
-
fallbackRoute?: import('vue-router').RouteLocationRaw
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export declare function useRouterTabsPersistence(options?: RouterTabsPersistenceOptions): void
|
|
46
|
-
|
|
47
|
-
export declare const RouterTabs: import('vue').DefineComponent<RouterTabsPersistenceOptions, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<RouterTabsPersistenceOptions>, {}>
|
|
48
|
-
|
|
49
|
-
export declare const RouterTab: import('vue').DefineComponent<{
|
|
50
|
-
tabs: {
|
|
51
|
-
type: import('vue').PropType<TabInput[]>
|
|
52
|
-
default: () => TabInput[]
|
|
53
|
-
}
|
|
54
|
-
keepAlive: {
|
|
55
|
-
type: BooleanConstructor
|
|
56
|
-
default: boolean
|
|
57
|
-
}
|
|
58
|
-
maxAlive: {
|
|
59
|
-
type: NumberConstructor
|
|
60
|
-
default: number
|
|
61
|
-
}
|
|
62
|
-
keepLastTab: {
|
|
63
|
-
type: BooleanConstructor
|
|
64
|
-
default: boolean
|
|
65
|
-
}
|
|
66
|
-
append: {
|
|
67
|
-
type: import('vue').PropType<'last' | 'next'>
|
|
68
|
-
default: 'last' | 'next'
|
|
69
|
-
}
|
|
70
|
-
defaultPage: {
|
|
71
|
-
type: import('vue').PropType<RouteLocationRaw>
|
|
72
|
-
default: RouteLocationRaw
|
|
73
|
-
}
|
|
74
|
-
tabTransition: {
|
|
75
|
-
type: import('vue').PropType<import('./lib/core/types').TransitionLike>
|
|
76
|
-
default: string | import('./lib/core/types').TransitionLike
|
|
77
|
-
}
|
|
78
|
-
pageTransition: {
|
|
79
|
-
type: import('vue').PropType<import('./lib/core/types').TransitionLike>
|
|
80
|
-
default: () => import('./lib/core/types').TransitionLike
|
|
81
|
-
}
|
|
82
|
-
contextmenu: {
|
|
83
|
-
type: import('vue').PropType<boolean | RouterTabsMenuConfig[]>
|
|
84
|
-
default: true
|
|
85
|
-
}
|
|
86
|
-
cookieKey: {
|
|
87
|
-
type: StringConstructor
|
|
88
|
-
default: string | null
|
|
89
|
-
}
|
|
90
|
-
persistence: {
|
|
91
|
-
type: import('vue').PropType<RouterTabsPersistenceOptions | null>
|
|
92
|
-
default: RouterTabsPersistenceOptions | null
|
|
93
|
-
}
|
|
94
|
-
}, any, any, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, Record<string, any>, string, import('vue').VNodeProps & import('vue').AllowedComponentProps & import('vue').ComponentCustomProps, Readonly<{
|
|
95
|
-
tabs?: TabInput[] | undefined
|
|
96
|
-
keepAlive?: boolean | undefined
|
|
97
|
-
maxAlive?: number | undefined
|
|
98
|
-
keepLastTab?: boolean | undefined
|
|
99
|
-
append?: 'last' | 'next' | undefined
|
|
100
|
-
defaultPage?: RouteLocationRaw | undefined
|
|
101
|
-
tabTransition?: import('./lib/core/types').TransitionLike | undefined
|
|
102
|
-
pageTransition?: import('./lib/core/types').TransitionLike | undefined
|
|
103
|
-
contextmenu?: boolean | RouterTabsMenuConfig[] | undefined
|
|
104
|
-
cookieKey?: string | undefined
|
|
105
|
-
persistence?: RouterTabsPersistenceOptions | null | undefined
|
|
106
|
-
}> & {
|
|
107
|
-
tabs?: TabInput[] | undefined
|
|
108
|
-
keepAlive?: boolean | undefined
|
|
109
|
-
maxAlive?: number | undefined
|
|
110
|
-
keepLastTab?: boolean | undefined
|
|
111
|
-
append?: 'last' | 'next' | undefined
|
|
112
|
-
defaultPage?: RouteLocationRaw | undefined
|
|
113
|
-
tabTransition?: import('./lib/core/types').TransitionLike | undefined
|
|
114
|
-
pageTransition?: import('./lib/core/types').TransitionLike | undefined
|
|
115
|
-
contextmenu?: boolean | RouterTabsMenuConfig[] | undefined
|
|
116
|
-
cookieKey?: string | undefined
|
|
117
|
-
persistence?: RouterTabsPersistenceOptions | null | undefined
|
|
118
|
-
}, {
|
|
119
|
-
tabs: TabInput[]
|
|
120
|
-
keepAlive: boolean
|
|
121
|
-
maxAlive: number
|
|
122
|
-
keepLastTab: boolean
|
|
123
|
-
append: 'last' | 'next'
|
|
124
|
-
defaultPage: RouteLocationRaw
|
|
125
|
-
tabTransition: import('./lib/core/types').TransitionLike
|
|
126
|
-
pageTransition: import('./lib/core/types').TransitionLike
|
|
127
|
-
contextmenu: true
|
|
128
|
-
cookieKey: string | null
|
|
129
|
-
persistence: RouterTabsPersistenceOptions | null
|
|
130
|
-
}>
|
|
131
|
-
|
|
132
|
-
export interface RouterTabPlugin extends Plugin {}
|
|
133
|
-
|
|
134
|
-
declare const plugin: RouterTabPlugin
|
|
135
|
-
|
|
136
|
-
export default plugin
|
|
137
|
-
|
|
138
|
-
declare module '@vue/runtime-core' {
|
|
139
|
-
interface ComponentCustomProperties {
|
|
140
|
-
$tabs: RouterTabsContext | null
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
declare module './constants' {
|
|
144
|
-
const value: any;
|
|
145
|
-
export = value;
|
|
146
|
-
}
|