vue3-portal
Version:
Portal for Vue 3
2 lines (1 loc) • 3.69 kB
JavaScript
(function(c,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],r):(c=typeof globalThis<"u"?globalThis:c||self,r(c.index={},c.Vue))})(this,function(c,r){"use strict";let P=1;const p=r.defineComponent({name:"Portal",props:{disabled:{type:Boolean},name:{type:String,default:()=>String(P++)},order:{type:Number,default:0},slotProps:{type:Object,default:()=>({})},tag:{type:String,default:"DIV"},to:{type:String,default:()=>String(Math.round(Math.random()*1e7))}},setup(t){const e=r.inject("wormhole"),n=r.useSlots(),s=o=>{const a={from:t.name,to:o||t.to};e==null||e.close(a)},l=()=>n.default(),i=o=>typeof o=="function"?o(t.slotProps):o,d=()=>{const o=l();if(o){const a={from:t.name,to:t.to,passengers:o,order:t.order};e==null||e.open(a)}else s()};return r.onMounted(()=>{t.disabled||d()}),r.onUpdated(()=>{t.disabled||d()}),r.onBeforeUnmount(()=>{s()}),r.watch(()=>t.to,(o,a)=>{a&&a!==o&&s(a),d()}),()=>{const o=n.default()||[],a=t.tag;return o&&t.disabled?o.length<=1?i(o)[0]:r.h(a,null,i(o)):r.h(a,{class:{"v-portal":!0},style:{display:"none"},key:"v-portal-placeholder"})}}}),h=typeof window<"u";function T(t){return Array.isArray(t)||typeof t=="object"?Object.freeze(t):t}function w(t,e={}){return t.reduce((n,s)=>{const l=s.passengers[0],i=typeof l=="function"?l(e):s.passengers;return n.concat(i)},[])}function b(t,e){return t.map((n,s)=>[s,n]).sort(function(n,s){return e(n[1],s[1])||n[0]-s[0]}).map(n=>n[1])}const g=r.defineComponent({name:"PortalTarget",props:{multiple:{type:Boolean,default:!1},name:{type:String,required:!0},slim:{type:Boolean,default:!1},slotProps:{type:Object,default:()=>({})},tag:{type:String,default:"div"},transition:{type:[String,Object,Function]}},setup(t,{emit:e}){const n=r.inject("wormhole"),s=r.useSlots(),l=r.ref(n.transports),i=r.ref(!0),d=()=>{var y;const f=((y=l.value)==null?void 0:y[t.name])||[];return t.multiple?f:f.length===0?[]:[f[f.length-1]]},o=()=>w(d(),t.slotProps),a=()=>o().length?o():s.default||[],u=()=>{const f=t.slim&&!t.transition;return f&&a().length>1&&console.warn("[portal-vue]: PortalTarget with `slim` option received more than one child element."),f};return r.onMounted(()=>{t.transition&&r.nextTick(()=>{i.value=!1})}),r.watch(d,()=>{e("change",a().length>0)}),{transports:l,firstRender:i,ownTransports:d,passengers:o,children:a,noWrapper:u}},render(){const t=this.noWrapper(),e=this.children(),n=this.transition||this.tag;return t?e[0]:this.slim&&!n?r.h():r.h(n,{props:{tag:this.transition&&this.tag?this.tag:void 0},class:{"vue-portal-target":!0}},e)}}),m={...{transports:{},trackInstances:h,open(t){if(!h)return;const{to:e,from:n,passengers:s,order:l=1/0}=t;if(!e||!n||!s)return;const i={to:e,from:n,passengers:T(s),order:l};Object.keys(this.transports).indexOf(e)===-1&&(this.transports[e]=[]);const o=this.getTransportIndex(i),a=this.transports[e].slice(0);o===-1?a.push(i):a[o]=i,this.transports[e]=b(a,(u,f)=>u.order-f.order)},close(t,e=!1){const{to:n,from:s}=t;if(!(!n||!s&&e===!1)&&this.transports[n])if(e)this.transports[n]=[];else{const l=this.getTransportIndex(t);if(l>=0){const i=this.transports[n].slice(0);i.splice(l,1),this.transports[n]=i}}},getTransportIndex(t){const{to:e,from:n}=t;for(const s in this.transports[e])if(this.transports[e][s].from===n)return+s;return-1}},install:(t,e={})=>{t.component(e.portalName||"Portal",p),t.component(e.portalTargetName||"PortalTarget",g),t.config.globalProperties.$wormhole=r.reactive(m),t.provide("wormhole",t.config.globalProperties.$wormhole)}};c.Portal=p,c.PortalTarget=g,c.default=m,Object.defineProperties(c,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});