const ignoredAttributes = ["class", "style"]; export default function withAttrObserver(props = {}) { return function (component) { const oldDestroy = component.destroy; const toIgnore = props.ignore || ignoredAttributes; const attrObserver = Alpine.reactive({ observer: null, handler(attrName, newValue, oldValue, target) { if (component.onAttrChange) { component.onAttrChange(attrName, newValue, oldValue, target); } }, }); attrObserver.observer = new MutationObserver((mutationsList) => { for (const mutation of mutationsList) { if ( mutation.type !== "attributes" || toIgnore.includes(mutation.attributeName) ) { return; } const { target } = mutation; attrObserver.handler( mutation.attributeName, target.getAttribute(mutation.attributeName), mutation.oldValue, target ); } }); Object.assign(component, { destroy() { attrObserver.observer.disconnect(); attrObserver.observer = null; if (oldDestroy) { oldDestroy.call(this); } }, }); attrObserver.observer.observe(component.$root, { attributes: true }); return component; }; } export { ignoredAttributes };