portal-vue
Advanced tools
Comparing version 1.2.2 to 1.3.0-beta.0
/* | ||
portal-vue | ||
Version: 1.2.2 | ||
Version: 1.3.0-beta.0 | ||
Licence: MIT | ||
@@ -32,25 +32,4 @@ (c) Thorsten Lünborg | ||
var classCallCheck = function (instance, Constructor) { | ||
if (!(instance instanceof Constructor)) { | ||
throw new TypeError("Cannot call a class as a function"); | ||
} | ||
}; | ||
var createClass = function () { | ||
function defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
return function (Constructor, protoProps, staticProps) { | ||
if (protoProps) defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) defineProperties(Constructor, staticProps); | ||
return Constructor; | ||
}; | ||
}(); | ||
@@ -63,2 +42,3 @@ | ||
var _extends = Object.assign || function (target) { | ||
@@ -157,4 +137,8 @@ for (var i = 1; i < arguments.length; i++) { | ||
function combinePassengers(transports) { | ||
var slotProps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
return transports.reduce(function (passengers, transport) { | ||
return passengers.concat(transport.passengers); | ||
var newPassengers = transport.passengers[0]; | ||
newPassengers = typeof newPassengers === 'function' ? newPassengers(slotProps) : transport.passengers; | ||
return passengers.concat(newPassengers); | ||
}, []); | ||
@@ -165,12 +149,8 @@ } | ||
var Wormhole = function () { | ||
function Wormhole(transports) { | ||
classCallCheck(this, Wormhole); | ||
this.transports = transports; | ||
} | ||
createClass(Wormhole, [{ | ||
key: 'open', | ||
value: function open(transport) { | ||
var Wormhole = Vue.extend({ | ||
data: function data() { | ||
return { transports: transports }; | ||
}, | ||
methods: { | ||
open: function open(transport) { | ||
var to = transport.to, | ||
@@ -201,6 +181,4 @@ from = transport.from, | ||
this.transports[to] = newTransports; | ||
} | ||
}, { | ||
key: 'close', | ||
value: function close(transport) { | ||
}, | ||
close: function close(transport) { | ||
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
@@ -226,11 +204,7 @@ var to = transport.to, | ||
} | ||
} | ||
}, { | ||
key: 'hasTarget', | ||
value: function hasTarget(to) { | ||
}, | ||
hasTarget: function hasTarget(to) { | ||
return this.transports.hasOwnProperty(to); | ||
} | ||
}, { | ||
key: 'hasContentFor', | ||
value: function hasContentFor(to) { | ||
}, | ||
hasContentFor: function hasContentFor(to) { | ||
if (!this.transports[to]) { | ||
@@ -240,11 +214,7 @@ return false; | ||
return this.getContentFor(to).length > 0; | ||
} | ||
}, { | ||
key: 'getSourceFor', | ||
value: function getSourceFor(to) { | ||
}, | ||
getSourceFor: function getSourceFor(to) { | ||
return this.transports[to] && this.transports[to][0].from; | ||
} | ||
}, { | ||
key: 'getContentFor', | ||
value: function getContentFor(to) { | ||
}, | ||
getContentFor: function getContentFor(to) { | ||
var transports = this.transports[to]; | ||
@@ -255,6 +225,4 @@ if (!transports) { | ||
return combinePassengers(transports); | ||
} | ||
}, { | ||
key: 'getTransportIndex', | ||
value: function getTransportIndex(_ref) { | ||
}, | ||
getTransportIndex: function getTransportIndex(_ref) { | ||
var to = _ref.to, | ||
@@ -270,5 +238,5 @@ from = _ref.from; | ||
} | ||
}]); | ||
return Wormhole; | ||
}(); | ||
} | ||
}); | ||
var wormhole = new Wormhole(transports); | ||
@@ -322,4 +290,4 @@ | ||
return function () { | ||
a.apply(this, arguments); | ||
b.apply(this, arguments); | ||
a && a.apply(this, arguments); | ||
b && b.apply(this, arguments); | ||
} | ||
@@ -330,3 +298,3 @@ } | ||
var Target = { | ||
abstract: true, | ||
abstract: false, | ||
name: 'portalTarget', | ||
@@ -340,2 +308,5 @@ props: { | ||
slim: { type: Boolean, default: false }, | ||
slotProps: { type: Object, default: function _default() { | ||
return {}; | ||
} }, | ||
tag: { type: String, default: 'div' }, | ||
@@ -368,3 +339,11 @@ transition: { type: [Boolean, String, Object], default: false }, | ||
}); | ||
if (this.$options.abstract) { | ||
this.$options.abstract = false; | ||
} | ||
}, | ||
updated: function updated() { | ||
if (this.$options.abstract) { | ||
this.$options.abstract = false; | ||
} | ||
}, | ||
beforeDestroy: function beforeDestroy() { | ||
@@ -396,3 +375,3 @@ this.unwatch(); | ||
passengers: function passengers() { | ||
return combinePassengers(this.ownTransports); | ||
return combinePassengers(this.ownTransports, this.slotProps); | ||
}, | ||
@@ -442,2 +421,3 @@ children: function children() { | ||
render: function render(h) { | ||
this.$options.abstract = true; | ||
var TransitionType = this.noWrapper ? 'transition' : 'transition-group'; | ||
@@ -470,3 +450,3 @@ var Tag = this.tag; | ||
var Portal = { | ||
abstract: true, | ||
abstract: false, | ||
name: 'portal', | ||
@@ -481,7 +461,13 @@ props: { | ||
slim: { type: Boolean, default: false }, | ||
slotProps: { type: Object, default: function _default() { | ||
return {}; | ||
} }, | ||
tag: { type: [String], default: 'DIV' }, | ||
targetEl: { type: inBrowser ? [String, HTMLElement] : String }, | ||
to: { type: String, default: function _default() { | ||
to: { | ||
type: String, | ||
default: function _default() { | ||
return String(Math.round(Math.random() * 10000000)); | ||
} } | ||
} | ||
} | ||
}, | ||
@@ -496,2 +482,7 @@ | ||
} | ||
// Reset hack to make child components skip the portal when defining their $parent | ||
// was set to true during render when we render something locally. | ||
if (this.$options.abstract) { | ||
this.$options.abstract = false; | ||
} | ||
}, | ||
@@ -504,2 +495,7 @@ updated: function updated() { | ||
} | ||
// Reset hack to make child components skip the portal when defining their $parent | ||
// was set to true during render when we render something locally. | ||
if (this.$options.abstract) { | ||
this.$options.abstract = false; | ||
} | ||
}, | ||
@@ -513,3 +509,2 @@ beforeDestroy: function beforeDestroy() { | ||
watch: { | ||
@@ -528,8 +523,12 @@ to: function to(newValue, oldValue) { | ||
methods: { | ||
normalizedSlots: function normalizedSlots() { | ||
return this.$scopedSlots.default ? [this.$scopedSlots.default] : this.$slots.default; | ||
}, | ||
sendUpdate: function sendUpdate() { | ||
if (this.$slots.default) { | ||
var slotContent = this.normalizedSlots(); | ||
if (slotContent) { | ||
wormhole.open({ | ||
from: this.name, | ||
to: this.to, | ||
passengers: [].concat(toConsumableArray(this.$slots.default)), | ||
passengers: [].concat(toConsumableArray(slotContent)), | ||
order: this.order | ||
@@ -574,2 +573,5 @@ }); | ||
} | ||
}, | ||
normalizeChildren: function normalizeChildren(children) { | ||
return typeof children === 'function' ? children(this.slotProps) : children; | ||
} | ||
@@ -579,9 +581,11 @@ }, | ||
render: function render(h) { | ||
var children = this.$slots.default || []; | ||
var children = this.$slots.default || this.$scopedSlots.default || []; | ||
var Tag = this.tag; | ||
if (children.length && this.disabled) { | ||
// hack to make child components skip the portal when defining their $parent | ||
this.$options.abstract = true; | ||
return children.length <= 1 && this.slim ? children[0] : h( | ||
Tag, | ||
null, | ||
[children] | ||
[this.normalizeChildren(children)] | ||
); | ||
@@ -591,3 +595,7 @@ } else { | ||
Tag, | ||
{ 'class': 'v-portal', style: 'display: none', key: 'v-portal-placeholder' }, | ||
{ | ||
'class': 'v-portal', | ||
style: 'display: none', | ||
key: 'v-portal-placeholder' | ||
}, | ||
[] | ||
@@ -604,3 +612,3 @@ ); | ||
Vue$$1.component(opts.portalName || 'portal', Portal); | ||
Vue$$1.component(opts.portalTargetName || 'portal-target', Target); | ||
Vue$$1.component(opts.portalTargetName || 'portalTarget', Target); | ||
} | ||
@@ -607,0 +615,0 @@ if (typeof window !== 'undefined' && window.Vue) { |
@@ -1,1 +0,1 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("vue")):"function"==typeof define&&define.amd?define(["vue"],e):t.PortalVue=e(t.Vue)}(this,function(t){"use strict";function e(t){for(var e=t.hasAttributes()?t.attributes:[],n={},r=0;r<e.length;r++){var o=e[r];o.value&&(n[o.name]=""===o.value||o.value)}var s=void 0,i=void 0;return n.class&&(s=n.class,delete n.class),n.style&&(i=n.style,delete n.style),{attrs:n,class:s,style:i}}function n(t){return Array.isArray(t)||"object"===(void 0===t?"undefined":i(t))?Object.freeze(t):t}function r(t){return t.reduce(function(t,e){return t.concat(e.passengers)},[])}function o(t,e){return function(){t.apply(this,arguments),e.apply(this,arguments)}}function s(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};t.component(e.portalName||"portal",b),t.component(e.portalTargetName||"portal-target",y)}t=t&&"default"in t?t.default:t;var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},a=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")},u=function(){function t(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(e,n,r){return n&&t(e.prototype,n),r&&t(e,r),e}}(),l=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},h=function(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e<t.length;e++)n[e]=t[e];return n}return Array.from(t)},f={},c=function(){function e(t){a(this,e),this.transports=t}return u(e,[{key:"open",value:function(e){var r=e.to,o=e.from,s=e.passengers;if(r&&o&&s){e.passengers=n(s);-1===Object.keys(this.transports).indexOf(r)&&t.set(this.transports,r,[]);var i=this.getTransportIndex(e),a=this.transports[r].slice(0);-1===i?a.push(e):a[i]=e,a.sort(function(t,e){return t.order-e.order}),this.transports[r]=a}}},{key:"close",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.to,r=t.from;if(n&&r&&this.transports[n])if(e)this.transports[n]=[];else{var o=this.getTransportIndex(t);if(o>=0){var s=this.transports[n].slice(0);s.splice(o,1),this.transports[n]=s}}}},{key:"hasTarget",value:function(t){return this.transports.hasOwnProperty(t)}},{key:"hasContentFor",value:function(t){return!!this.transports[t]&&this.getContentFor(t).length>0}},{key:"getSourceFor",value:function(t){return this.transports[t]&&this.transports[t][0].from}},{key:"getContentFor",value:function(t){var e=this.transports[t];if(e)return r(e)}},{key:"getTransportIndex",value:function(t){var e=t.to,n=t.from;for(var r in this.transports[e])if(this.transports[e][r].from===n)return r;return-1}}]),e}(),p=new c(f),d=/^(attrs|props|on|nativeOn|class|style|hook)$/,g=function(t){return t.reduce(function(t,e){var n,r,s,i,a;for(s in e)if(n=t[s],r=e[s],n&&d.test(s))if("class"===s&&("string"==typeof n&&(a=n,t[s]=n={},n[a]=!0),"string"==typeof r&&(a=r,e[s]=r={},r[a]=!0)),"on"===s||"nativeOn"===s||"hook"===s)for(i in r)n[i]=o(n[i],r[i]);else if(Array.isArray(n))t[s]=n.concat(r);else if(Array.isArray(r))t[s]=[n].concat(r);else for(i in r)n[i]=r[i];else t[s]=e[s];return t},{})},y={abstract:!0,name:"portalTarget",props:{attributes:{type:Object,default:function(){return{}}},multiple:{type:Boolean,default:!1},name:{type:String,required:!0},slim:{type:Boolean,default:!1},tag:{type:String,default:"div"},transition:{type:[Boolean,String,Object],default:!1},transitionEvents:{type:Object,default:function(){return{}}}},data:function(){return{transports:p.transports,firstRender:!0}},created:function(){this.transports[this.name]||this.$set(this.transports,this.name,[])},mounted:function(){var t=this;this.unwatch=this.$watch("ownTransports",this.emitChange),this.$nextTick(function(){t.transition&&(t.firstRender=!1)})},beforeDestroy:function(){this.unwatch(),this.$el.innerHTML=""},methods:{emitChange:function(t,e){if(this.multiple)this.$emit("change",[].concat(h(t)),[].concat(h(e)));else{var n=0===t.length?void 0:t[0],r=0===e.length?void 0:e[0];this.$emit("change",l({},n),l({},r))}}},computed:{ownTransports:function(){var t=this.transports[this.name]||[];return this.multiple?t:0===t.length?[]:[t[t.length-1]]},passengers:function(){return r(this.ownTransports)},children:function(){return 0!==this.passengers.length?this.passengers:this.$slots.default||[]},hasAttributes:function(){return Object.keys(this.attributes).length>0},noWrapper:function(){var t=!this.hasAttributes&&this.slim;return t&&this.children.length>1&&console.warn("[portal-vue]: PortalTarget with `slim` option received more than one child element."),t},withTransition:function(){return!!this.transition},transitionData:function(){var t=this.transition,e={};return this.firstRender&&"object"===i(this.transition)&&!this.transition.appear?(e.props={name:"__notranstition__portal-vue__"},e):("string"==typeof t?e.props={name:t}:"object"===(void 0===t?"undefined":i(t))&&(e.props=t),this.renderSlim&&(e.props.tag=this.tag),e.on=this.transitionEvents,e)}},render:function(t){var e=this.noWrapper?"transition":"transition-group",n=this.tag;if(this.withTransition)return t(e,g([this.transitionData,{class:"vue-portal-target"}]),[this.children]);var r=this.ownTransports.length;return this.noWrapper?this.children[0]:t(n,g([{class:"vue-portal-target"},this.attributes,{key:r}]),[this.children])}},m="undefined"!=typeof window,v=1,b={abstract:!0,name:"portal",props:{disabled:{type:Boolean,default:!1},name:{type:String,default:function(){return String(v++)}},order:{type:Number,default:0},slim:{type:Boolean,default:!1},tag:{type:[String],default:"DIV"},targetEl:{type:m?[String,HTMLElement]:String},to:{type:String,default:function(){return String(Math.round(1e7*Math.random()))}}},mounted:function(){this.targetEl&&this.mountToTarget(),this.disabled||this.sendUpdate()},updated:function(){this.disabled?this.clear():this.sendUpdate()},beforeDestroy:function(){this.clear(),this.mountedComp&&this.mountedComp.$destroy()},watch:{to:function(t,e){e&&this.clear(e),this.sendUpdate()},targetEl:function(t,e){t&&this.mountToTarget()}},methods:{sendUpdate:function(){this.$slots.default?p.open({from:this.name,to:this.to,passengers:[].concat(h(this.$slots.default)),order:this.order}):this.clear()},clear:function(t){p.close({from:this.name,to:t||this.to})},mountToTarget:function(){var n=void 0,r=this.targetEl;if("string"==typeof r)n=document.querySelector(r);else{if(!(r instanceof HTMLElement))return void console.warn("[vue-portal]: value of targetEl must be of type String or HTMLElement");n=r}if(n){var o=new t(l({},y,{parent:this,propsData:{name:this.to,tag:n.tagName,attributes:e(n)}}));o.$mount(n),this.mountedComp=o}else console.warn("[vue-portal]: The specified targetEl "+r+" was not found")}},render:function(t){var e=this.$slots.default||[],n=this.tag;return e.length&&this.disabled?e.length<=1&&this.slim?e[0]:t(n,null,[e]):t(n,{class:"v-portal",style:"display: none",key:"v-portal-placeholder"},[])}};return"undefined"!=typeof window&&window.Vue&&window.Vue.use({install:s}),{install:s,Portal:b,PortalTarget:y,Wormhole:p}}); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("vue")):"function"==typeof define&&define.amd?define(["vue"],e):t.PortalVue=e(t.Vue)}(this,function(t){"use strict";function e(t){for(var e=t.hasAttributes()?t.attributes:[],n={},r=0;r<e.length;r++){var s=e[r];s.value&&(n[s.name]=""===s.value||s.value)}var o=void 0,i=void 0;return n.class&&(o=n.class,delete n.class),n.style&&(i=n.style,delete n.style),{attrs:n,class:o,style:i}}function n(t){return Array.isArray(t)||"object"===(void 0===t?"undefined":i(t))?Object.freeze(t):t}function r(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return t.reduce(function(t,n){var r=n.passengers[0];return r="function"==typeof r?r(e):n.passengers,t.concat(r)},[])}function s(t,e){return function(){t&&t.apply(this,arguments),e&&e.apply(this,arguments)}}function o(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};t.component(e.portalName||"portal",y),t.component(e.portalTargetName||"portalTarget",d)}t=t&&"default"in t?t.default:t;var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},u=function(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e<t.length;e++)n[e]=t[e];return n}return Array.from(t)},l={},h=t.extend({data:function(){return{transports:l}},methods:{open:function(e){var r=e.to,s=e.from,o=e.passengers;if(r&&s&&o){e.passengers=n(o);-1===Object.keys(this.transports).indexOf(r)&&t.set(this.transports,r,[]);var i=this.getTransportIndex(e),a=this.transports[r].slice(0);-1===i?a.push(e):a[i]=e,a.sort(function(t,e){return t.order-e.order}),this.transports[r]=a}},close:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.to,r=t.from;if(n&&r&&this.transports[n])if(e)this.transports[n]=[];else{var s=this.getTransportIndex(t);if(s>=0){var o=this.transports[n].slice(0);o.splice(s,1),this.transports[n]=o}}},hasTarget:function(t){return this.transports.hasOwnProperty(t)},hasContentFor:function(t){return!!this.transports[t]&&this.getContentFor(t).length>0},getSourceFor:function(t){return this.transports[t]&&this.transports[t][0].from},getContentFor:function(t){var e=this.transports[t];if(e)return r(e)},getTransportIndex:function(t){var e=t.to,n=t.from;for(var r in this.transports[e])if(this.transports[e][r].from===n)return r;return-1}}}),p=new h(l),c=/^(attrs|props|on|nativeOn|class|style|hook)$/,f=function(t){return t.reduce(function(t,e){var n,r,o,i,a;for(o in e)if(n=t[o],r=e[o],n&&c.test(o))if("class"===o&&("string"==typeof n&&(a=n,t[o]=n={},n[a]=!0),"string"==typeof r&&(a=r,e[o]=r={},r[a]=!0)),"on"===o||"nativeOn"===o||"hook"===o)for(i in r)n[i]=s(n[i],r[i]);else if(Array.isArray(n))t[o]=n.concat(r);else if(Array.isArray(r))t[o]=[n].concat(r);else for(i in r)n[i]=r[i];else t[o]=e[o];return t},{})},d={abstract:!1,name:"portalTarget",props:{attributes:{type:Object,default:function(){return{}}},multiple:{type:Boolean,default:!1},name:{type:String,required:!0},slim:{type:Boolean,default:!1},slotProps:{type:Object,default:function(){return{}}},tag:{type:String,default:"div"},transition:{type:[Boolean,String,Object],default:!1},transitionEvents:{type:Object,default:function(){return{}}}},data:function(){return{transports:p.transports,firstRender:!0}},created:function(){this.transports[this.name]||this.$set(this.transports,this.name,[])},mounted:function(){var t=this;this.unwatch=this.$watch("ownTransports",this.emitChange),this.$nextTick(function(){t.transition&&(t.firstRender=!1)}),this.$options.abstract&&(this.$options.abstract=!1)},updated:function(){this.$options.abstract&&(this.$options.abstract=!1)},beforeDestroy:function(){this.unwatch(),this.$el.innerHTML=""},methods:{emitChange:function(t,e){if(this.multiple)this.$emit("change",[].concat(u(t)),[].concat(u(e)));else{var n=0===t.length?void 0:t[0],r=0===e.length?void 0:e[0];this.$emit("change",a({},n),a({},r))}}},computed:{ownTransports:function(){var t=this.transports[this.name]||[];return this.multiple?t:0===t.length?[]:[t[t.length-1]]},passengers:function(){return r(this.ownTransports,this.slotProps)},children:function(){return 0!==this.passengers.length?this.passengers:this.$slots.default||[]},hasAttributes:function(){return Object.keys(this.attributes).length>0},noWrapper:function(){var t=!this.hasAttributes&&this.slim;return t&&this.children.length>1&&console.warn("[portal-vue]: PortalTarget with `slim` option received more than one child element."),t},withTransition:function(){return!!this.transition},transitionData:function(){var t=this.transition,e={};return this.firstRender&&"object"===i(this.transition)&&!this.transition.appear?(e.props={name:"__notranstition__portal-vue__"},e):("string"==typeof t?e.props={name:t}:"object"===(void 0===t?"undefined":i(t))&&(e.props=t),this.renderSlim&&(e.props.tag=this.tag),e.on=this.transitionEvents,e)}},render:function(t){this.$options.abstract=!0;var e=this.noWrapper?"transition":"transition-group",n=this.tag;if(this.withTransition)return t(e,f([this.transitionData,{class:"vue-portal-target"}]),[this.children]);var r=this.ownTransports.length;return this.noWrapper?this.children[0]:t(n,f([{class:"vue-portal-target"},this.attributes,{key:r}]),[this.children])}},m="undefined"!=typeof window,g=1,y={abstract:!1,name:"portal",props:{disabled:{type:Boolean,default:!1},name:{type:String,default:function(){return String(g++)}},order:{type:Number,default:0},slim:{type:Boolean,default:!1},slotProps:{type:Object,default:function(){return{}}},tag:{type:[String],default:"DIV"},targetEl:{type:m?[String,HTMLElement]:String},to:{type:String,default:function(){return String(Math.round(1e7*Math.random()))}}},mounted:function(){this.targetEl&&this.mountToTarget(),this.disabled||this.sendUpdate(),this.$options.abstract&&(this.$options.abstract=!1)},updated:function(){this.disabled?this.clear():this.sendUpdate(),this.$options.abstract&&(this.$options.abstract=!1)},beforeDestroy:function(){this.clear(),this.mountedComp&&this.mountedComp.$destroy()},watch:{to:function(t,e){e&&this.clear(e),this.sendUpdate()},targetEl:function(t,e){t&&this.mountToTarget()}},methods:{normalizedSlots:function(){return this.$scopedSlots.default?[this.$scopedSlots.default]:this.$slots.default},sendUpdate:function(){var t=this.normalizedSlots();t?p.open({from:this.name,to:this.to,passengers:[].concat(u(t)),order:this.order}):this.clear()},clear:function(t){p.close({from:this.name,to:t||this.to})},mountToTarget:function(){var n=void 0,r=this.targetEl;if("string"==typeof r)n=document.querySelector(r);else{if(!(r instanceof HTMLElement))return void console.warn("[vue-portal]: value of targetEl must be of type String or HTMLElement");n=r}if(n){var s=new t(a({},d,{parent:this,propsData:{name:this.to,tag:n.tagName,attributes:e(n)}}));s.$mount(n),this.mountedComp=s}else console.warn("[vue-portal]: The specified targetEl "+r+" was not found")},normalizeChildren:function(t){return"function"==typeof t?t(this.slotProps):t}},render:function(t){var e=this.$slots.default||this.$scopedSlots.default||[],n=this.tag;return e.length&&this.disabled?(this.$options.abstract=!0,e.length<=1&&this.slim?e[0]:t(n,null,[this.normalizeChildren(e)])):t(n,{class:"v-portal",style:"display: none",key:"v-portal-placeholder"},[])}};return"undefined"!=typeof window&&window.Vue&&window.Vue.use({install:o}),{install:o,Portal:y,PortalTarget:d,Wormhole:p}}); |
{ | ||
"name": "portal-vue", | ||
"version": "1.2.2", | ||
"description": "A Vue component to render elements outside of a component's template, elsewhere in the DOM", | ||
"version": "1.3.0-beta.0", | ||
"description": | ||
"A Vue component to render elements outside of a component's template, elsewhere in the DOM", | ||
"main": "dist/portal-vue.js", | ||
@@ -18,6 +19,10 @@ "files": [ | ||
"lint:test": "eslint test/", | ||
"build": "npm run lint && cross-env NODE_ENV=production rollup -c build/rollup.conf.prod.js && uglifyjs dist/portal-vue.js -c -m > dist/portal-vue.min.js", | ||
"dev": "cross-env NODE_ENV=development webpack-dev-server --watch --config build/webpack.conf.js --inline --hot", | ||
"prod": "NODE_ENV=production webpack-dev-server --watch --config build/webpack.conf.js --inline --hot", | ||
"docs": "docute ./docs --watch", | ||
"build": | ||
"npm run lint && cross-env NODE_ENV=production rollup -c build/rollup.conf.prod.js && uglifyjs dist/portal-vue.js -c -m > dist/portal-vue.min.js", | ||
"dev": | ||
"cross-env NODE_ENV=development webpack-dev-server --watch --config build/webpack.conf.js --inline --hot", | ||
"prod": | ||
"NODE_ENV=production webpack-dev-server --watch --config build/webpack.conf.js --inline --hot", | ||
"docs:dev": "docute ./docs --watch", | ||
"docs:deploy": "gh-pages -d docs", | ||
"test": "jest --config test/unit/jest.conf.js --coverage", | ||
@@ -27,3 +32,7 @@ "test:watch": "jest --config test/unit/jest.conf.js --watch" | ||
"eslintConfig": { | ||
"parser": "babel-eslint", | ||
"parserOptions": { | ||
"parser": "babel-eslint", | ||
"ecmaVersion": 2017, | ||
"sourceType": "module" | ||
}, | ||
"env": { | ||
@@ -33,15 +42,7 @@ "mocha": true, | ||
}, | ||
"extends": [ | ||
"vue" | ||
], | ||
"plugins": [ | ||
"html", | ||
"vue" | ||
], | ||
"extends": ["plugin:vue/recommended"], | ||
"plugins": ["html", "vue"], | ||
"rules": { | ||
"vue/jsx-uses-vars": 2, | ||
"comma-dangle": [ | ||
"error", | ||
"always-multiline" | ||
] | ||
"comma-dangle": ["error", "always-multiline"] | ||
} | ||
@@ -59,5 +60,3 @@ }, | ||
], | ||
"plugins": [ | ||
"transform-vue-jsx" | ||
], | ||
"plugins": ["transform-vue-jsx"], | ||
"comments": true, | ||
@@ -67,6 +66,3 @@ "env": { | ||
"test": { | ||
"presets": [ | ||
"es2015", | ||
"stage-3" | ||
] | ||
"presets": ["es2015", "stage-3"] | ||
} | ||
@@ -78,4 +74,4 @@ } | ||
"babel-core": "^6.25.0", | ||
"babel-eslint": "^7.2.3", | ||
"babel-helper-vue-jsx-merge-props": "^2.0.2", | ||
"babel-eslint": "^8.0.3", | ||
"babel-helper-vue-jsx-merge-props": "^2.0.3", | ||
"babel-jest": "^21.0.2", | ||
@@ -90,26 +86,24 @@ "babel-loader": "^7.0.0", | ||
"babel-preset-stage-3": "^6.24.1", | ||
"chai": "^4.0.2", | ||
"cross-env": "^5.0.0", | ||
"css-loader": "^0.28.2", | ||
"docute": "^3.4.7", | ||
"chai": "^4.1.2", | ||
"cross-env": "^5.1.2", | ||
"css-loader": "^0.28.7", | ||
"docute": "^3.4.9", | ||
"docute-cli": "^0.6.0", | ||
"eslint": "^3.19.0", | ||
"eslint-config-vue": "^2.0.2", | ||
"eslint": "^4.13.1", | ||
"eslint-friendly-formatter": "^3.0.0", | ||
"eslint-loader": "^1.7.1", | ||
"eslint-plugin-html": "^2.0.3", | ||
"eslint-plugin-vue": "^2.0.1", | ||
"eslint-plugin-html": "^4.0.1", | ||
"eslint-plugin-vue": "^4.0.0-beta.3", | ||
"friendly-errors-webpack-plugin": "^1.6.1", | ||
"gh-pages": "^1.1.0", | ||
"inject-loader": "^3.0.0", | ||
"jest": "^21.2.0", | ||
"jest-serializer-vue": "^0.3.0", | ||
"karma": "^1.7.0", | ||
"karma-chrome-launcher": "^2.1.1", | ||
"karma-mocha": "^1.3.0", | ||
"karma-sourcemap-loader": "^0.3.7", | ||
"karma-spec-reporter": "^0.0.31", | ||
"karma-webpack": "^2.0.3", | ||
"mocha": "^3.4.2", | ||
"karma-webpack": "^2.0.9", | ||
"mocha": "^3.5.3", | ||
"mocha-css": "^1.0.1", | ||
"node-sass": "^4.5.3", | ||
"node-sass": "^4.7.2", | ||
"puppeteer": "^0.11.0", | ||
@@ -119,18 +113,17 @@ "rollup": "^0.43.0", | ||
"rollup-plugin-buble": "^0.15.0", | ||
"rollup-plugin-commonjs": "^8.0.2", | ||
"rollup-plugin-commonjs": "^8.2.6", | ||
"rollup-plugin-node-resolve": "^3.0.0", | ||
"sass-loader": "^6.0.5", | ||
"style-loader": "^0.18.2", | ||
"testdouble": "^2.1.2", | ||
"testdouble-chai": "^0.5.0", | ||
"vue": "^2.3.4", | ||
"vue-jest": "^1.0.2", | ||
"vue-loader": "^12.2.1", | ||
"vue-router": "^2.5.3", | ||
"vue-template-compiler": "^2.3.4", | ||
"vue-test-utils": "^1.0.0-beta.5", | ||
"webpack": "^2.6.1", | ||
"webpack-dev-server": "^2.4.5", | ||
"webpack-merge": "^4.1.0" | ||
"vue": "^2.5.13", | ||
"vue-jest": "^1.4.0", | ||
"vue-loader": "^13.6.0", | ||
"vue-router": "^3.0.1", | ||
"vue-template-compiler": "^2.5.13", | ||
"vue-test-utils": "^1.0.0-beta.8", | ||
"webpack": "^3.10.0", | ||
"webpack-dev-server": "^2.9.7", | ||
"webpack-merge": "^4.1.1" | ||
} | ||
} |
@@ -6,3 +6,3 @@ // import { transports } from './wormhole' | ||
export default { | ||
abstract: true, | ||
abstract: false, | ||
name: 'portalTarget', | ||
@@ -14,2 +14,3 @@ props: { | ||
slim: { type: Boolean, default: false }, | ||
slotProps: { type: Object, default: () => ({}) }, | ||
tag: { type: String, default: 'div' }, | ||
@@ -19,3 +20,3 @@ transition: { type: [Boolean, String, Object], default: false }, | ||
}, | ||
data () { | ||
data() { | ||
return { | ||
@@ -26,3 +27,3 @@ transports: wormhole.transports, | ||
}, | ||
created () { | ||
created() { | ||
if (!this.transports[this.name]) { | ||
@@ -32,11 +33,20 @@ this.$set(this.transports, this.name, []) | ||
}, | ||
mounted () { | ||
mounted() { | ||
this.unwatch = this.$watch('ownTransports', this.emitChange) | ||
this.$nextTick(() => { | ||
if (this.transition) { // only when we have a transition, because it causes a re-render | ||
if (this.transition) { | ||
// only when we have a transition, because it causes a re-render | ||
this.firstRender = false | ||
} | ||
}) | ||
if (this.$options.abstract) { | ||
this.$options.abstract = false | ||
} | ||
}, | ||
beforeDestroy () { | ||
updated() { | ||
if (this.$options.abstract) { | ||
this.$options.abstract = false | ||
} | ||
}, | ||
beforeDestroy() { | ||
this.unwatch() | ||
@@ -47,15 +57,11 @@ this.$el.innerHTML = '' | ||
methods: { | ||
emitChange (newTransports, oldTransports) { | ||
emitChange(newTransports, oldTransports) { | ||
if (this.multiple) { | ||
this.$emit('change', | ||
[...newTransports], | ||
[...oldTransports] | ||
) | ||
this.$emit('change', [...newTransports], [...oldTransports]) | ||
} else { | ||
const newTransport = newTransports.length === 0 ? undefined : newTransports[0] | ||
const oldTransport = oldTransports.length === 0 ? undefined : oldTransports[0] | ||
this.$emit('change', | ||
{ ...newTransport }, | ||
{ ...oldTransport } | ||
) | ||
const newTransport = | ||
newTransports.length === 0 ? undefined : newTransports[0] | ||
const oldTransport = | ||
oldTransports.length === 0 ? undefined : oldTransports[0] | ||
this.$emit('change', { ...newTransport }, { ...oldTransport }) | ||
} | ||
@@ -65,3 +71,3 @@ }, | ||
computed: { | ||
ownTransports () { | ||
ownTransports() { | ||
const transports = this.transports[this.name] || [] | ||
@@ -73,22 +79,26 @@ if (this.multiple) { | ||
}, | ||
passengers () { | ||
return combinePassengers(this.ownTransports) | ||
passengers() { | ||
return combinePassengers(this.ownTransports, this.slotProps) | ||
}, | ||
children () { | ||
return this.passengers.length !== 0 ? this.passengers : (this.$slots.default || []) | ||
children() { | ||
return this.passengers.length !== 0 | ||
? this.passengers | ||
: this.$slots.default || [] | ||
}, | ||
hasAttributes () { | ||
hasAttributes() { | ||
return Object.keys(this.attributes).length > 0 | ||
}, | ||
noWrapper () { | ||
noWrapper() { | ||
const noWrapper = !this.hasAttributes && this.slim | ||
if (noWrapper && this.children.length > 1) { | ||
console.warn('[portal-vue]: PortalTarget with `slim` option received more than one child element.') | ||
console.warn( | ||
'[portal-vue]: PortalTarget with `slim` option received more than one child element.' | ||
) | ||
} | ||
return noWrapper | ||
}, | ||
withTransition () { | ||
withTransition() { | ||
return !!this.transition | ||
}, | ||
transitionData () { | ||
transitionData() { | ||
const t = this.transition | ||
@@ -100,3 +110,6 @@ const data = {} | ||
// because in Portals, transitions can behave as if appear was defined under certain conditions. | ||
if (this.firstRender && (typeof this.transition === 'object' && !this.transition.appear)) { | ||
if ( | ||
this.firstRender && | ||
(typeof this.transition === 'object' && !this.transition.appear) | ||
) { | ||
data.props = { name: '__notranstition__portal-vue__' } | ||
@@ -120,3 +133,4 @@ return data | ||
render (h) { | ||
render(h) { | ||
this.$options.abstract = true | ||
const TransitionType = this.noWrapper ? 'transition' : 'transition-group' | ||
@@ -127,3 +141,3 @@ const Tag = this.tag | ||
return ( | ||
<TransitionType {...this.transitionData} class='vue-portal-target'> | ||
<TransitionType {...this.transitionData} class="vue-portal-target"> | ||
{this.children} | ||
@@ -137,6 +151,10 @@ </TransitionType> | ||
return this.noWrapper | ||
? this.children[0] | ||
: <Tag class='vue-portal-target' {...this.attributes} key={wrapperKey}>{this.children}</Tag> | ||
return this.noWrapper ? ( | ||
this.children[0] | ||
) : ( | ||
<Tag class="vue-portal-target" {...this.attributes} key={wrapperKey}> | ||
{this.children} | ||
</Tag> | ||
) | ||
}, | ||
} |
@@ -1,2 +0,1 @@ | ||
import Vue from 'vue' | ||
@@ -7,3 +6,3 @@ import wormhole from './wormhole' | ||
const inBrowser = (typeof window !== 'undefined') | ||
const inBrowser = typeof window !== 'undefined' | ||
@@ -13,3 +12,3 @@ let pid = 1 | ||
export default { | ||
abstract: true, | ||
abstract: false, | ||
name: 'portal', | ||
@@ -22,8 +21,12 @@ props: { | ||
slim: { type: Boolean, default: false }, | ||
slotProps: { type: Object, default: () => ({}) }, | ||
tag: { type: [String], default: 'DIV' }, | ||
targetEl: { type: inBrowser ? [String, HTMLElement] : String }, | ||
to: { type: String, default: () => String(Math.round(Math.random() * 10000000)) }, | ||
to: { | ||
type: String, | ||
default: () => String(Math.round(Math.random() * 10000000)), | ||
}, | ||
}, | ||
mounted () { | ||
mounted() { | ||
if (this.targetEl) { | ||
@@ -35,5 +38,10 @@ this.mountToTarget() | ||
} | ||
// Reset hack to make child components skip the portal when defining their $parent | ||
// was set to true during render when we render something locally. | ||
if (this.$options.abstract) { | ||
this.$options.abstract = false | ||
} | ||
}, | ||
updated () { | ||
updated() { | ||
if (this.disabled) { | ||
@@ -44,5 +52,10 @@ this.clear() | ||
} | ||
// Reset hack to make child components skip the portal when defining their $parent | ||
// was set to true during render when we render something locally. | ||
if (this.$options.abstract) { | ||
this.$options.abstract = false | ||
} | ||
}, | ||
beforeDestroy () { | ||
beforeDestroy() { | ||
this.clear() | ||
@@ -53,9 +66,8 @@ if (this.mountedComp) { | ||
}, | ||
watch: { | ||
to (newValue, oldValue) { | ||
to(newValue, oldValue) { | ||
oldValue && this.clear(oldValue) | ||
this.sendUpdate() | ||
}, | ||
targetEl (newValue, oldValue) { | ||
targetEl(newValue, oldValue) { | ||
if (newValue) { | ||
@@ -68,9 +80,14 @@ this.mountToTarget() | ||
methods: { | ||
sendUpdate () { | ||
if (this.$slots.default) { | ||
normalizedSlots() { | ||
return this.$scopedSlots.default | ||
? [this.$scopedSlots.default] | ||
: this.$slots.default | ||
}, | ||
sendUpdate() { | ||
const slotContent = this.normalizedSlots() | ||
if (slotContent) { | ||
wormhole.open({ | ||
from: this.name, | ||
to: this.to, | ||
passengers: [...this.$slots.default], | ||
passengers: [...slotContent], | ||
order: this.order, | ||
@@ -83,3 +100,3 @@ }) | ||
clear (target) { | ||
clear(target) { | ||
wormhole.close({ | ||
@@ -91,3 +108,3 @@ from: this.name, | ||
mountToTarget () { | ||
mountToTarget() { | ||
let el | ||
@@ -101,3 +118,5 @@ const target = this.targetEl | ||
} else { | ||
console.warn('[vue-portal]: value of targetEl must be of type String or HTMLElement') | ||
console.warn( | ||
'[vue-portal]: value of targetEl must be of type String or HTMLElement' | ||
) | ||
return | ||
@@ -119,16 +138,33 @@ } | ||
} else { | ||
console.warn('[vue-portal]: The specified targetEl ' + target + ' was not found') | ||
console.warn( | ||
'[vue-portal]: The specified targetEl ' + target + ' was not found' | ||
) | ||
} | ||
}, | ||
normalizeChildren(children) { | ||
return typeof children === 'function' | ||
? children(this.slotProps) | ||
: children | ||
}, | ||
}, | ||
render (h) { | ||
const children = this.$slots.default || [] | ||
render(h) { | ||
const children = this.$slots.default || this.$scopedSlots.default || [] | ||
const Tag = this.tag | ||
if (children.length && this.disabled) { | ||
return children.length <= 1 && this.slim | ||
? children[0] | ||
: (<Tag>{children}</Tag>) | ||
// hack to make child components skip the portal when defining their $parent | ||
this.$options.abstract = true | ||
return children.length <= 1 && this.slim ? ( | ||
children[0] | ||
) : ( | ||
<Tag>{this.normalizeChildren(children)}</Tag> | ||
) | ||
} else { | ||
return (<Tag class={'v-portal'} style={'display: none'} key={'v-portal-placeholder'}/>) | ||
return ( | ||
<Tag | ||
class={'v-portal'} | ||
style={'display: none'} | ||
key={'v-portal-placeholder'} | ||
/> | ||
) | ||
// h(this.tag, { class: { 'v-portal': true }, style: { display: 'none' }, key: 'v-portal-placeholder' }) | ||
@@ -135,0 +171,0 @@ } |
@@ -7,85 +7,85 @@ import Vue from 'vue' | ||
export class Wormhole { | ||
constructor (transports) { | ||
this.transports = transports | ||
} | ||
export const Wormhole = Vue.extend({ | ||
data: () => ({ transports }), | ||
methods: { | ||
open(transport) { | ||
const { to, from, passengers } = transport | ||
if (!to || !from || !passengers) return | ||
open (transport) { | ||
const { to, from, passengers } = transport | ||
if (!to || !from || !passengers) return | ||
transport.passengers = freeze(passengers) | ||
const keys = Object.keys(this.transports) | ||
if (keys.indexOf(to) === -1) { | ||
Vue.set(this.transports, to, []) | ||
} | ||
transport.passengers = freeze(passengers) | ||
const keys = Object.keys(this.transports) | ||
if (keys.indexOf(to) === -1) { | ||
Vue.set(this.transports, to, []) | ||
} | ||
const currentIndex = this.getTransportIndex(transport) | ||
// Copying the array here so that the PortalTarget change event will actually contain two distinct arrays | ||
const newTransports = this.transports[to].slice(0) | ||
if (currentIndex === -1) { | ||
newTransports.push(transport) | ||
} else { | ||
newTransports[currentIndex] = transport | ||
} | ||
newTransports.sort(function(a, b) { | ||
return a.order - b.order | ||
}) | ||
const currentIndex = this.getTransportIndex(transport) | ||
// Copying the array here so that the PortalTarget change event will actually contain two distinct arrays | ||
const newTransports = this.transports[to].slice(0) | ||
if (currentIndex === -1) { | ||
newTransports.push(transport) | ||
} else { | ||
newTransports[currentIndex] = transport | ||
} | ||
newTransports.sort(function (a, b) { | ||
return a.order - b.order | ||
}) | ||
this.transports[to] = newTransports | ||
}, | ||
this.transports[to] = newTransports | ||
} | ||
close(transport, force = false) { | ||
const { to, from } = transport | ||
if (!to || !from) return | ||
if (!this.transports[to]) { | ||
return | ||
} | ||
close (transport, force = false) { | ||
const { to, from } = transport | ||
if (!to || !from) return | ||
if (!this.transports[to]) { | ||
return | ||
} | ||
if (force) { | ||
this.transports[to] = [] | ||
} else { | ||
const index = this.getTransportIndex(transport) | ||
if (index >= 0) { | ||
// Copying the array here so that the PortalTarget change event will actually contain two distinct arrays | ||
const newTransports = this.transports[to].slice(0) | ||
newTransports.splice(index, 1) | ||
this.transports[to] = newTransports | ||
if (force) { | ||
this.transports[to] = [] | ||
} else { | ||
const index = this.getTransportIndex(transport) | ||
if (index >= 0) { | ||
// Copying the array here so that the PortalTarget change event will actually contain two distinct arrays | ||
const newTransports = this.transports[to].slice(0) | ||
newTransports.splice(index, 1) | ||
this.transports[to] = newTransports | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
hasTarget (to) { | ||
return this.transports.hasOwnProperty(to) | ||
} | ||
hasTarget(to) { | ||
return this.transports.hasOwnProperty(to) | ||
}, | ||
hasContentFor (to) { | ||
if (!this.transports[to]) { | ||
return false | ||
} | ||
return this.getContentFor(to).length > 0 | ||
} | ||
hasContentFor(to) { | ||
if (!this.transports[to]) { | ||
return false | ||
} | ||
return this.getContentFor(to).length > 0 | ||
}, | ||
getSourceFor (to) { | ||
return this.transports[to] && this.transports[to][0].from | ||
} | ||
getSourceFor(to) { | ||
return this.transports[to] && this.transports[to][0].from | ||
}, | ||
getContentFor (to) { | ||
const transports = this.transports[to] | ||
if (!transports) { | ||
return undefined | ||
} | ||
return combinePassengers(transports) | ||
} | ||
getContentFor(to) { | ||
const transports = this.transports[to] | ||
if (!transports) { | ||
return undefined | ||
} | ||
return combinePassengers(transports) | ||
}, | ||
getTransportIndex ({ to, from }) { | ||
for (const i in this.transports[to]) { | ||
if (this.transports[to][i].from === from) { | ||
return i | ||
getTransportIndex({ to, from }) { | ||
for (const i in this.transports[to]) { | ||
if (this.transports[to][i].from === from) { | ||
return i | ||
} | ||
} | ||
} | ||
return -1 | ||
} | ||
} | ||
return -1 | ||
}, | ||
}, | ||
}) | ||
const wormhole = new Wormhole(transports) | ||
export default wormhole |
@@ -5,5 +5,5 @@ import Portal from './components/portal.js' | ||
function install (Vue, opts = {}) { | ||
function install(Vue, opts = {}) { | ||
Vue.component(opts.portalName || 'portal', Portal) | ||
Vue.component(opts.portalTargetName || 'portal-target', PortalTarget) | ||
Vue.component(opts.portalTargetName || 'portalTarget', PortalTarget) | ||
} | ||
@@ -10,0 +10,0 @@ if (typeof window !== 'undefined' && window.Vue) { |
@@ -1,2 +0,2 @@ | ||
export function extractAttributes (el) { | ||
export function extractAttributes(el) { | ||
const map = el.hasAttributes() ? el.attributes : [] | ||
@@ -27,3 +27,3 @@ const attrs = {} | ||
export function freeze (item) { | ||
export function freeze(item) { | ||
if (Array.isArray(item) || typeof item === 'object') { | ||
@@ -35,6 +35,11 @@ return Object.freeze(item) | ||
export function combinePassengers (transports) { | ||
export function combinePassengers(transports, slotProps = {}) { | ||
return transports.reduce((passengers, transport) => { | ||
return passengers.concat(transport.passengers) | ||
let newPassengers = transport.passengers[0] | ||
newPassengers = | ||
typeof newPassengers === 'function' | ||
? newPassengers(slotProps) | ||
: transport.passengers | ||
return passengers.concat(newPassengers) | ||
}, []) | ||
} |
Sorry, the diff of this file is not supported yet
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
73625
53
967
3