UNPKG

igniteui-webcomponents

Version:

Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.

136 lines 4.03 kB
import { isServer } from 'lit'; import { isDocument, isElement } from '../util.js'; const ID_REF_EMITTERS = new WeakMap(); const ID_REF_EVENT = 'id-refs-change'; function getEmitter(root) { let emitter = ID_REF_EMITTERS.get(root); if (!emitter) { emitter = new IdRefChangeEmitter(root); ID_REF_EMITTERS.set(root, emitter); } return emitter; } function refObserverCallback(mutations, emitter) { const affected = new Set(); for (const mutation of mutations) { if (mutation.type === 'attributes') { if (!isElement(mutation.target)) continue; const oldId = mutation.oldValue; const newId = mutation.target.id; if (oldId) affected.add(oldId); if (newId) affected.add(newId); } else { for (const node of mutation.addedNodes) { if (!isElement(node)) continue; if (node.id) affected.add(node.id); for (const child of node.querySelectorAll('[id]')) { if (child.id) affected.add(child.id); } } for (const node of mutation.removedNodes) { if (!isElement(node)) continue; if (node.id) affected.add(node.id); for (const child of node.querySelectorAll('[id]')) { if (child.id) affected.add(child.id); } } } } if (affected.size > 0) { emitter.dispatchEvent(new CustomEvent(ID_REF_EVENT, { detail: affected })); } } class IdRefChangeEmitter extends EventTarget { constructor(root) { super(); this._refCount = 0; this._root = root; if (!isServer) { this._observer = new MutationObserver((mutations) => refObserverCallback(mutations, this)); } } retain() { if (this._refCount++ === 0) { const root = isDocument(this._root) ? this._root.body : this._root; this._observer?.observe(root, { attributeFilter: ['id'], attributeOldValue: true, subtree: true, childList: true, }); } } release() { if (this._refCount > 0 && --this._refCount === 0) { this._observer?.disconnect(); } } } class IdRefResolverController { constructor(host, callback) { this._active = false; this._connected = false; this._emitter = null; this._host = host; this._host.addController(this); this._callback = callback; } _observe() { const root = this._host.getRootNode(); this._emitter = getEmitter(root); this._emitter.retain(); this._emitter.addEventListener(ID_REF_EVENT, this); } _unobserve() { if (this._emitter) { this._emitter.removeEventListener(ID_REF_EVENT, this); this._emitter.release(); this._emitter = null; } } handleEvent(event) { this._callback.call(this._host, event.detail); } hostConnected() { this._connected = true; if (this._active) { this._observe(); } } hostDisconnected() { if (this._active) { this._unobserve(); } this._connected = false; } observe() { if (this._active) return; this._active = true; if (this._connected) { this._observe(); } } unobserve() { if (!this._active) return; this._active = false; if (this._connected) { this._unobserve(); } } } export function addIdRefResolver(host, callback) { return new IdRefResolverController(host, callback); } //# sourceMappingURL=id-resolver.js.map