UNPKG

vue-events-backbone

Version:

This plugin is an Event Bus that, by default, simulates DOM events propagation through vue components.

6 lines (5 loc) 16.7 kB
(function(c,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],u):(c=typeof globalThis<"u"?globalThis:c||self,u(c.VueEventsBackbone={},c.Vue))})(this,function(c,u){"use strict";var U=Object.defineProperty;var D=(c,u,y)=>u in c?U(c,u,{enumerable:!0,configurable:!0,writable:!0,value:y}):c[u]=y;var l=(c,u,y)=>D(c,typeof u!="symbol"?u+"":u,y);function y(o){return o.watchedIsUnmounted!==void 0}const v=function(o){return y(o)?o:(o=Object.defineProperties(o,{watchedIsUnmounted:{enumerable:!0,writable:!0,value:o.isUnmounted},isUnmountedCallbacks:{enumerable:!0,writable:!0,value:[]}}),Object.defineProperty(o,"isUnmounted",{get(){return this.watchedIsUnmounted},set(e){if(e!==this.watchedIsUnmounted)try{for(const n of this.isUnmountedCallbacks)n();this.isUnmountedCallbacks.length=0}catch(n){console.error(n)}this.watchedIsUnmounted=e}}))};class w{constructor(){l(this,"evntsTree");l(this,"lstnrsRegistry");l(this,"compsRegistry");l(this,"listenAllSymbol",Symbol("*"));l(this,"emptyMap",new Map);this.evntsTree=new Map,this.lstnrsRegistry=new Map,this.compsRegistry=new Map}_getComponentFromUid(e){for(const n of this.compsRegistry.entries())if(n[0].uid===e)return n[0]}_callHandler(e,n,t){var a,d,h,f;const r=this._rebuildEventNameFromSymbol(t),s=((d=(a=n.handlerCallerComponentInstance)==null?void 0:a.type)==null?void 0:d.__name)||((f=(h=n.handlerCallerComponentInstance)==null?void 0:h.type)==null?void 0:f.name);n.once=()=>{this.off(n.handlerCallerComponentInstance.uid,r||"-",e)};let i;try{i=e(n)}catch(x){return console.error(`Error in handler function: ${e==null?void 0:e.name} - event: ${r} - handler caller: ${s}`),console.error(x),x}return i}async _callHandlers(e,n){const t=[];e.branchSymbols.forEach(r=>{for(const s of(this.lstnrsRegistry.get(r)||this.emptyMap).entries()){const i=n?n.uid===s[0].uid?n:void 0:s[0];if(i){e.handlerCallerComponentInstance=i;for(const a of s[1]){let d=this._callHandler(a,e,r);!e.eager&&d instanceof Promise&&t.push(d)}}}}),await Promise.allSettled(t)}async _internalEmitEvent(e,n){e.handlerCallerComponentInstance=n||e.emitterComponentInstance,this.compsRegistry.has(e.handlerCallerComponentInstance)&&await this._callHandlers(e,e.handlerCallerComponentInstance),!e.propagationStopped&&e.handlerCallerComponentInstance.parent&&await this._internalEmitEvent(e,e.handlerCallerComponentInstance.parent)}_getBranchSymbols(e){const n=e.split(":"),t=[this.listenAllSymbol];let r;for(;n.length>0;){r=r?r+`:${n.splice(0,1)[0]}`:`${n.splice(0,1)[0]}`;const s=this._getEventEntry(r.split(":"));if(s)t.unshift(s.symbol);else break}return t}emitEvent(e,n,t,r){const s=this,i={emitterComponentInstance:e,handlerCallerComponentInstance:e,eventName:n,branchSymbols:this._getBranchSymbols(n),eventData:t,global:(r==null?void 0:r.global)||!1,propagationStopped:null,eager:Object.is(r==null?void 0:r.eager,void 0)||Object.is(r==null?void 0:r.eager,null)?!0:!!(r!=null&&r.eager)||!1,stopPropagation:function(){if(!this.global){this.propagationStopped=!this.global;return}console.warn(`${this.eventName} - can not stop the propagation of an event emitted globally.`)},once:()=>{},transformEvent:function(a,d){if(this.global){console.warn(`Cannot transform event ${this.eventName} into ${a} as ${this.eventName} has been emitted globally.`);return}try{s._checkEventNameValidity(a),this.eventName=a,this.eventData=d||this.eventData,this.branchSymbols=s._getBranchSymbols(a)}catch(h){console.error(`Error trying to transform event ${this.eventName} into ${a}`),console.error(h)}},emitEvent:function(a,d,h,f){return s.emitEvent(this.handlerCallerComponentInstance,a,d,{global:h,eager:f})}};return i.transformEvent=i.transformEvent.bind(i),r!=null&&r.global?this._callHandlers(i):this._internalEmitEvent(i)}_addEventEntry(e,n){return n&&e!=="*"?n.children.set(e,{symbol:Symbol(e),parent:n,children:new Map}).get(e):this.evntsTree.set(e,{symbol:e==="*"?this.listenAllSymbol:Symbol(e),parent:n,children:new Map}).get(e)}_checkEventEntryValidity(e){const n=!!this.lstnrsRegistry.get(e.symbol);if(n||e.children.size===0)return n;for(const t of e.children.entries())if(this._checkEventEntryValidity(t[1]))return!0;return n}_removeEventEntry(e){let n=e.parent;if(!n){this.evntsTree.delete(e.symbol.description);return}for(e.parent=void 0,n.children.delete(e.symbol.description);n&&!this._checkEventEntryValidity(n);){const t=n.parent;t?(n.parent=void 0,t.children.delete(n.symbol.description)):this.evntsTree.delete(n.symbol.description),n=t}}_rebuildEventNameFromSymbol(e){const n=this._findEventEntryFromNodeName(e.description);if(n)return this._rebuildEventNameFromEventEntry(n)}_rebuildEventNameFromEventEntry(e){let n=e.symbol.description;for(;e.parent;)n=`${e.parent.symbol.description}:`+n,e=e.parent;return n}_findEventEntryFromNodeName(e,n){if(n){for(const t of n.children.entries()){if(t[0]===e)return t[1];const r=this._findEventEntryFromNodeName(e,t[1]);if(r)return r}return}for(const t of this.evntsTree.entries()){if(t[0]===e)return t[1];const r=this._findEventEntryFromNodeName(e,t[1]);if(r)return r}}_getEventEntry(e,n,t){const r=e.splice(0,1)[0];let s=n?n.children.get(r):this.evntsTree.get(r);if(!s){if(!t)return s;s=this._addEventEntry(r,n)}return e.length===0?s:this._getEventEntry(e,s,t)}_checkEventNameValidity(e){var r,s,i,a,d,h;const t=/(?<listenallerror>.*\*.+)|(?<consequentcolons>:{2,})|(?<spacescolons>:\s+:)|(?<finalcolon>^.*:$)|(?<startingcolon>^:.*$)|(?<spacesfound>^[a-zA-Z:]*\s+[a-zA-Z:]*$)/gi.exec(e);if((r=t==null?void 0:t.groups)!=null&&r.listenallerror)throw new Error(`${e} - Invalid event name. Listen All event listeners must be registered with a lone '*'.`);if((s=t==null?void 0:t.groups)!=null&&s.consequentcolons)throw new Error(`${e} - Invalid event name. The name cannot have consequent colons.`);if((i=t==null?void 0:t.groups)!=null&&i.finalcolon)throw new Error(`${e} - Invalid event name. The name cannot end with a colon.`);if((a=t==null?void 0:t.groups)!=null&&a.startingcolon)throw new Error(`${e} - Invalid event name. The name cannot start with a colon.`);if((d=t==null?void 0:t.groups)!=null&&d.spacescolons)throw new Error(`${e} - Invalid event name. The name cannot have two colons separated by spaces.`);if((h=t==null?void 0:t.groups)!=null&&h.spacesfound)throw new Error(`${e} - Invalid event name. The name cannot have spaces inside.`)}_addListener(e,n,t){const r=this._getEventEntry(n.split(":"),void 0,!0);r&&(this._addListenerEntry(e,r.symbol,t),this._addCompEntrySymbol(e,r.symbol))}_addListenerEntry(e,n,t){const r=this.lstnrsRegistry.get(n);if(!r)this.lstnrsRegistry.set(n,new Map([[e,new Set([t])]]));else{const s=r.get(e);if(s){s.has(t)||s.add(t);return}r.set(e,new Set([t]))}}_addCompEntrySymbol(e,n){var t;if(this.compsRegistry.has(e)){(t=this.compsRegistry.get(e))==null||t.add(n);return}this.compsRegistry.set(e,new Set([n]))}_removeCompEntry(e){this.compsRegistry.delete(e)}_removeCompEntrySymbol(e,n){const t=this.compsRegistry.get(e);t&&(t.delete(n),t.size===0&&this._removeCompEntry(e))}_removeListenerEntry(e,n,t){const r=this.lstnrsRegistry.get(n);if(!r)return;const s=r.get(e);s&&(s.delete(t),s.size===0&&(r.delete(e),this._removeCompEntrySymbol(e,n)))}_removeListener(e,n,t){const r=this._getEventEntry(n.split(":"));if(r){this._removeListenerEntry(e,r.symbol,t);const s=this.lstnrsRegistry.get(r.symbol);s&&s.size===0&&this.lstnrsRegistry.delete(r.symbol),this._checkEventEntryValidity(r)||this._removeEventEntry(r)}}on(e,n,t){try{if(n=n.trim(),n.length===0){console.error("Event name can not be an empty string");return}let r=v(e);r.isUnmountedCallbacks.push(()=>{this.offAll(r)}),this._checkEventNameValidity(n),this._addListener(r,n,t)}catch(r){console.error(r)}}off(e,n,t){const r=this._getComponentFromUid(e);r&&t?this._removeListener(r,n,t):r&&!t&&this.offAll(r)}offAll(e){const n=this.compsRegistry.get(e);n&&(n.forEach(t=>{const r=this.lstnrsRegistry.get(t);r&&r.has(e)&&r.delete(e)}),this.compsRegistry.delete(e))}}const m=function(o){return new o}(w);function g(o){o&&m.offAll(o)}function b(o,e){if(e)for(const n in o)if(!Array.isArray(o[n]))console.warn(`${e.type.__name||e.type.name} - eventKey value for ${n} must be an array`);else for(const t of o[n])m.off(e.uid,n,t)}function p(o,e,n){if(g(n&&e?e:void 0),e)for(const t in o)if(Array.isArray(o[t]))for(const r of o[t])m.on(e,t,r);else console.warn(`${e.type.__name||e.type.name} - eventKey value for ${t} must be an array`)}const R={beforeMount(o,e,n){var t;p(e.value,(t=e.instance)==null?void 0:t.$)},beforeUpdate(o,e,n,t){var r;p(e.value,e.arg==="update"&&((r=e.instance)==null?void 0:r.$),e.arg==="update")},beforeUnmount(o,e,n){var t;g((t=e.instance)==null?void 0:t.$)}};class C{constructor(e,n,t){l(this,"neuronFrom");l(this,"neuronTo");l(this,"axonKey");this.neuronFrom=n,this.axonKey=e,this.neuronTo=t}async transmitSignal(e,n){return this.neuronTo?await this.neuronTo.deliverSignal(e,n):(console.log("No neuron linked to axon with key: "+this.axonKey),[])}getNeuronFrom(){return this.neuronFrom}getAxonKey(){return this.axonKey}destroy(e,n){this.neuronFrom&&this.neuronTo&&(e&&this.neuronFrom&&this.neuronFrom.notifyCutAxonFromReceiverNeuron(this.axonKey,this.neuronTo.getNeuronKey(),!!n),this.neuronTo&&this.neuronTo.notifyCutAxonFromSenderNeuron(this.axonKey)),this.neuronTo=void 0,this.neuronFrom=void 0}}class k{constructor(e,n,t){l(this,"dendriteComponent");l(this,"neuron");l(this,"callbacks");this.callbacks=new Map,this.neuron=n,this.dendriteComponent=e,t&&this.setNeurotransmitterCallbacks(t),e.isUnmountedCallbacks.push(this.destroy.bind(this))}getComponentInstance(){return this.dendriteComponent}setNeurotransmitterCallbacks(e){for(const n in e)this.callbacks.set(n,e[n])}removeNeurotransmitterCallbacks(e){for(const n of e)this.callbacks.delete(n)}getNeuron(){return this.neuron}deliverSignalToDendrite(e,n){const t=this.callbacks.get(e);if(t)try{return t(n)}catch(r){console.error(r)}}sendSignalFromDendrite(e,n,t){return this.getNeuron().sendSignal(e,n,t)}deleteAxonFromDendrite(e,n){var t;console.log("deleteAxonFromDendrite"),console.log(e),console.log(n),(t=this.neuron)==null||t.deleteAxon(e,n)}destroy(){var e;this.dendriteComponent=void 0,this.callbacks.clear(),(e=this.neuron)==null||e.deleteDendrite(this),this.neuron=void 0}}class _{constructor(e,n,...t){l(this,"dendrites");l(this,"brain");l(this,"neuronKey");l(this,"senderAxons");l(this,"receiverAxons");l(this,"pendingAxonRequests");this.brain=e,this.neuronKey=n,this.dendrites=new Set(t),this.senderAxons=new Map,this.receiverAxons=new Map,this.pendingAxonRequests=new Set}addDendrite(e){return this.dendrites.add(e),e}getDendrites(){return this.dendrites}deleteDendrite(e){this.dendrites.delete(e),this.size===0&&this.destroy()}hasDendrite(e){return this.dendrites.has(e)}getNeuronKey(){return this.neuronKey}getAxons(){return this.senderAxons}getAxon(e){return this.senderAxons.get(e)}deleteAxon(e,n){console.warn("deleteAxon"),console.log(e),console.log(n);const t=this.getAxon(e);if(console.log("a",t),t){t.destroy(!1,n),this.senderAxons.delete(e);return}else if(this.pendingAxonRequests.has(e)){this.stopPendingAxonRequest(e);return}console.warn(`No axon with key ${e} has been found on neuron ${this.neuronKey}`)}async notifyCutAxonFromReceiverNeuron(e,n,t){const r=this.senderAxons.delete(e);t||!r||await this.requestAxon(e,n)}async notifyCutAxonFromSenderNeuron(e){this.receiverAxons.delete(e)}addAxonRequest(e){this.pendingAxonRequests.add(e)}removeAxonRequest(e){this.pendingAxonRequests.delete(e)}stopPendingAxonRequest(e){this.brain&&(this.brain.stopPendingAxonRequest(this.neuronKey,e),this.removeAxonRequest(e))}async requestAxon(e,n){if(!this.brain)throw new Error("Unable to request axon creation. Brain is not set.");this.addAxonRequest(n);try{const t=await this.brain.requestNeuronForAxon(this.neuronKey,n);if(this.removeAxonRequest(n),!t){console.warn("Axon request from "+this.neuronKey+" to "+n+" stopped.");return}const r=new C(e,this,t);return t.receiveAxon(r),this.senderAxons.set(e,r),r}catch(t){console.error("Error trying to request axon from neuron "+this.neuronKey+" to neuron "+n),console.error(t),this.removeAxonRequest(n)}}receiveAxon(e){e&&!this.receiverAxons.has(e.getAxonKey())&&this.receiverAxons.set(e.getAxonKey(),e)}async sendSignal(e,n,t){const r=this.senderAxons.get(e);if(r)return await r.transmitSignal(n,t);console.log("No axon with key: "+e+" in neuron with key: "+this.neuronKey)}async deliverSignal(e,n){const t=[];for(const r of this.dendrites){const s=r.deliverSignalToDendrite(e,n);s&&s instanceof Promise?t.push(s):t.push(Promise.resolve(s))}return await Promise.allSettled(t)}get size(){return this.dendrites.size}get length(){return this.size}destroy(){var e;for(const n of this.pendingAxonRequests)this.stopPendingAxonRequest(n);this.pendingAxonRequests.clear(),(e=this.brain)==null||e.deleteNeuron(this.neuronKey),this.brain=void 0;for(const n of this.senderAxons.entries())n[1].destroy(!1);this.senderAxons.clear();for(const n of this.receiverAxons.entries())n[1].destroy(!0);this.receiverAxons.clear()}}class q{constructor(){l(this,"neurons");l(this,"pendingAxonRequests");l(this,"closePendingAxonRequests");this.neurons=new Map,this.pendingAxonRequests=new Map,this.closePendingAxonRequests=new Map}generateNeuron(e,n,t){const r=v(n);let s=this.neurons.get(e);if(!s){s=new _(this,e),this.neurons.set(e,s);const i=this.pendingAxonRequests.get(e);if(i)for(const a of i.entries())a[1]()}return s.addDendrite(new k(r,s,t))}cleanupPendingAxonRequestsCallbacks(e,n){const t=this.pendingAxonRequests.get(n),r=this.closePendingAxonRequests.get(e);t&&(t.delete(e),t.size===0&&this.pendingAxonRequests.delete(n)),r&&(r.delete(n),r.size===0&&this.closePendingAxonRequests.delete(e))}requestNeuronForAxon(e,n){const t=this.neurons.get(n);return t?Promise.resolve(t):new Promise((r,s)=>{const i=this.pendingAxonRequests.get(n),a=this.closePendingAxonRequests.get(e),d=()=>{try{this.cleanupPendingAxonRequestsCallbacks(e,n),r(this.neurons.get(n))}catch(f){this.cleanupPendingAxonRequestsCallbacks(e,n),console.error(f),s("unable to retrieve requested neuron")}},h=()=>{this.cleanupPendingAxonRequestsCallbacks(e,n),r()};if(i)i.set(e,d);else{const f=new Map([[e,d]]);this.pendingAxonRequests.set(n,f)}if(a)a.set(n,h);else{const f=new Map([[n,d]]);this.closePendingAxonRequests.set(e,f)}})}stopPendingAxonRequest(e,n){const t=this.closePendingAxonRequests.get(e);if(t){const r=t.get(n);if(r)try{r()}catch{console.error("Error stopping axon request from neuron "+e+" to neuron "+n)}}}deleteNeuron(e){this.neurons.delete(e),this.pendingAxonRequests.delete(e)}}const E=function(o){return new o}(q);function A(){return E}function S(o,e){const n=u.getCurrentInstance();if(!n)throw new Error("Cannot get current component instance. Please call createNeuron inside a lifecycle hook");return E.generateNeuron(o,n,e)}function B(o){const e=o||u.getCurrentInstance();return e?function(n){b(n,e)}:n=>{const t=u.getCurrentInstance();if(t){b(n,t);return}console.warn(`Unable to retrieve component instance. Probably defineRemoveEventListeners has been called outside from a lifecycle hook, this means that at least this returned function must be called inside a lifecycle hook`)}}function N(o){const e=o||u.getCurrentInstance();return e?function(n,t){p(n,e,t)}:(n,t)=>{const r=u.getCurrentInstance();if(r){p(n,r,t);return}console.warn(`Unable to retrieve component instance. Probably defineAddEventListeners has been called outside from a lifecycle hook, this means that at least this returned function must be called inside a lifecycle hook`)}}function I(o,e){const n=e||u.getCurrentInstance();if(n){if(o){const t=new Map(o.map(r=>[r,function(s,i,a){return m.emitEvent(n,r,s,{global:i,eager:a})}]));return function(r,s,i,a){const d=t.get(r);return d?d(s,i,a):(console.warn(`Event ${r} not defined as backbone emitter.`),Promise.resolve())}}return function(t,r,s,i){return m.emitEvent(n,t,r,{global:s,eager:i})}}return console.warn("No current component instance. defineBackboneEmits has to be called inside a lifecycle hook."),(t,r,s,i)=>(console.warn(`Default backbone emitter called. Event ${t} NOT emitted through the backbone.`),Promise.resolve())}const P=R,$=A,F=S,M={install:o=>{if(!o){console.warn("No app parameter provided, returning...");return}o.config.globalProperties.$EventsBackBone=m,o.config.globalProperties.$EventsBackboneBrain=A()}};function L(){return m}c.EventsBackBoneDirective=P,c.createNeuron=F,c.default=M,c.defineAddEventListeners=N,c.defineBackboneEmits=I,c.defineRemoveEventListeners=B,c.useBackbone=L,c.useBackboneBrain=$,Object.defineProperties(c,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});