UNPKG

vue-events-backbone

Version:

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

674 lines (673 loc) 22.7 kB
var x = Object.defineProperty; var A = (o, e, n) => e in o ? x(o, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : o[e] = n; var l = (o, e, n) => A(o, typeof e != "symbol" ? e + "" : e, n); import { getCurrentInstance as m } from "vue"; function w(o) { return o.watchedIsUnmounted !== void 0; } const v = function(o) { return w(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 R { constructor() { l(this, "evntsTree"); l(this, "lstnrsRegistry"); l(this, "compsRegistry"); l(this, "listenAllSymbol", Symbol("*")); l(this, "emptyMap", /* @__PURE__ */ new Map()); this.evntsTree = /* @__PURE__ */ new Map(), this.lstnrsRegistry = /* @__PURE__ */ new Map(), this.compsRegistry = /* @__PURE__ */ 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, c, d, u; const r = this._rebuildEventNameFromSymbol(t), s = ((c = (a = n.handlerCallerComponentInstance) == null ? void 0 : a.type) == null ? void 0 : c.__name) || ((u = (d = n.handlerCallerComponentInstance) == null ? void 0 : d.type) == null ? void 0 : u.name); n.once = () => { this.off(n.handlerCallerComponentInstance.uid, r || "-", e); }; let i; try { i = e(n); } catch (p) { return console.error(`Error in handler function: ${e == null ? void 0 : e.name} - event: ${r} - handler caller: ${s}`), console.error(p), p; } 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 c = this._callHandler( a, e, r ); !e.eager && c instanceof Promise && t.push(c); } } } }), 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); } // get the reversed branch of event symbols a:b:c -> [c, b, a] _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; } // main function to handle emitted event 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, // placeholders to avoid the optional parameters in type definition 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, c) { 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 = c || this.eventData, this.branchSymbols = s._getBranchSymbols(a); } catch (d) { console.error(`Error trying to transform event ${this.eventName} into ${a}`), console.error(d); } }, emitEvent: function(a, c, d, u) { return s.emitEvent(this.handlerCallerComponentInstance, a, c, { global: d, eager: u }); } }; 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: /* @__PURE__ */ new Map() }).get(e) : this.evntsTree.set(e, { symbol: e === "*" ? this.listenAllSymbol : Symbol(e), parent: n, children: /* @__PURE__ */ 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, c, d; 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 ((c = t == null ? void 0 : t.groups) != null && c.spacescolons) throw new Error(`${e} - Invalid event name. The name cannot have two colons separated by spaces.`); if ((d = t == null ? void 0 : t.groups) != null && d.spacesfound) throw new Error(`${e} - Invalid event name. The name cannot have spaces inside.`); } // da chiamare nell' ON _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, /* @__PURE__ */ new Map([[e, /* @__PURE__ */ new Set([t])]])); else { const s = r.get(e); if (s) { s.has(t) || s.add(t); return; } r.set(e, /* @__PURE__ */ 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, /* @__PURE__ */ new Set([n])); } // remove functions _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))); } // da chiamare nell' OFF _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); } } // removes specific component instance handler for specific event // if no handler is passed to the function, it removes all handlers for specific events 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 C = function(o) { return new o(); }, h = C(R); function g(o) { o && h.offAll(o); } function y(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]) h.off(e.uid, n, t); } function f(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]) h.on(e, t, r); else console.warn(`${e.type.__name || e.type.name} - eventKey value for ${t} must be an array`); } const _ = { beforeMount(o, e, n) { var t; f(e.value, (t = e.instance) == null ? void 0 : t.$); }, beforeUpdate(o, e, n, t) { var r; f(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 q { 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 = /* @__PURE__ */ 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 N { // private readonly signalsQueue: Map<EventsBackboneAxonKey, [EventsBackboneNeurotransmitterKey, any]> 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 = /* @__PURE__ */ new Map(), this.receiverAxons = /* @__PURE__ */ new Map(), this.pendingAxonRequests = /* @__PURE__ */ 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}`); } // quando il neurone ricevente viene distrutto, notifica il neurone trasmettitore // che occorre ricreare l'assone (attendendo per quando verrà rimontato eventualmente // il neurone ricevente) 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 q(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); } // emette il segnale tramite l'axon verso il neuron target 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); } // funzione per consegnare il segnale e i dati inviati dal neuron transmitter attraverso l'axon // ritorna tutti i risultati delle funzioni chiamate per ogni dendrite 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 S { constructor() { l(this, "neurons"); l(this, "pendingAxonRequests"); l(this, "closePendingAxonRequests"); this.neurons = /* @__PURE__ */ new Map(), this.pendingAxonRequests = /* @__PURE__ */ new Map(), this.closePendingAxonRequests = /* @__PURE__ */ new Map(); } // crea il neurone risolvendo allo stesso tempo le richieste pending di axon connection // provenienti da altri neurons generateNeuron(e, n, t) { const r = v(n); let s = this.neurons.get(e); if (!s) { s = new N(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), c = () => { try { this.cleanupPendingAxonRequestsCallbacks(e, n), r(this.neurons.get(n)); } catch (u) { this.cleanupPendingAxonRequestsCallbacks(e, n), console.error(u), s("unable to retrieve requested neuron"); } }, d = () => { this.cleanupPendingAxonRequestsCallbacks(e, n), r(); }; if (i) i.set(e, c); else { const u = /* @__PURE__ */ new Map([ [e, c] ]); this.pendingAxonRequests.set(n, u); } if (a) a.set(n, d); else { const u = /* @__PURE__ */ new Map([ [n, c] ]); this.closePendingAxonRequests.set(e, u); } }); } 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 $ = function(o) { return new o(); }, b = $(S); function E() { return b; } function P(o, e) { const n = m(); if (!n) throw new Error("Cannot get current component instance. Please call createNeuron inside a lifecycle hook"); return b.generateNeuron(o, n, e); } function F(o) { const e = o || m(); return e ? function(n) { y(n, e); } : (n) => { const t = m(); if (t) { y(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 M(o) { const e = o || m(); return e ? function(n, t) { f(n, e, t); } : (n, t) => { const r = m(); if (r) { f(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 U(o, e) { const n = e || m(); if (n) { if (o) { const t = new Map( o.map( (r) => [ r, function(s, i, a) { return h.emitEvent(n, r, s, { global: i, eager: a }); } ] ) ); return function(r, s, i, a) { const c = t.get(r); return c ? c(s, i, a) : (console.warn(`Event ${r} not defined as backbone emitter.`), Promise.resolve()); }; } return function(t, r, s, i) { return h.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 L = _, D = E, T = P, z = { install: (o) => { if (!o) { console.warn("No app parameter provided, returning..."); return; } o.config.globalProperties.$EventsBackBone = h, o.config.globalProperties.$EventsBackboneBrain = E(); } }; function V() { return h; } export { L as EventsBackBoneDirective, T as createNeuron, z as default, M as defineAddEventListeners, U as defineBackboneEmits, F as defineRemoveEventListeners, V as useBackbone, D as useBackboneBrain };