diff --git a/src/visualBuilder/eventManager/useRecalculateVariantDataCSLPValues.ts b/src/visualBuilder/eventManager/useRecalculateVariantDataCSLPValues.ts index 4a277ca8..a577da4a 100644 --- a/src/visualBuilder/eventManager/useRecalculateVariantDataCSLPValues.ts +++ b/src/visualBuilder/eventManager/useRecalculateVariantDataCSLPValues.ts @@ -35,15 +35,17 @@ function updateVariantClasses({ const updateElementClasses = ( element: HTMLElement, dataCslp: string, - observer: MutationObserver + observer?: MutationObserver ) => { if (!dataCslp) return; if ( dataCslp.startsWith("v2:") && - element.classList.contains("visual-builder__base-field") + !element.classList.contains("visual-builder__variant-field") ) { - element.classList.remove("visual-builder__base-field"); + if (element.classList.contains("visual-builder__base-field")) { + element.classList.remove("visual-builder__base-field"); + } if (highlightVariantFields) { element.classList.add( visualBuilderStyles()["visual-builder__variant-field"], @@ -73,7 +75,7 @@ function updateVariantClasses({ ); element.classList.add("visual-builder__disabled-variant-field"); } - + if (!observer) return; // Disconnect this observer after processing observer.disconnect(); const index = observers.indexOf(observer); @@ -82,20 +84,79 @@ function updateVariantClasses({ } }; + const addElementClasses = (element: HTMLElement) => { + const dataCslp = element.getAttribute(DATA_CSLP_ATTR_SELECTOR); + + if (!dataCslp) { + //recursive call for child nodes + element.childNodes.forEach((child) => { + if (child instanceof HTMLElement) { + addElementClasses(child); + } + }); + return; + } + //if element might have been updated by another observer + if ( + dataCslp.startsWith("v2:") && + element.classList.contains("visual-builder__variant-field") + ) { + return; + } + // if element has not given variant/base class + if ( + dataCslp.startsWith("v2:") && + !element.classList.contains("visual-builder__variant-field") + ) { + if (element.classList.contains("visual-builder__base-field")) { + element.classList.remove("visual-builder__base-field"); + } + if (highlightVariantFields) { + element.classList.add( + visualBuilderStyles()["visual-builder__variant-field"], + "visual-builder__variant-field" + ); + } else { + element.classList.add("visual-builder__variant-field"); + } + } else if (!dataCslp.startsWith("v2:")) { + if (element.classList.contains("visual-builder__variant-field")) { + element.classList.remove( + visualBuilderStyles()["visual-builder__variant-field"], + "visual-builder__variant-field" + ); + } + element.classList.add("visual-builder__base-field"); + } + + //recursive call for child nodes + element.childNodes.forEach((child) => { + if (child instanceof HTMLElement) { + addElementClasses(child); + } + }); + }; + // Create a separate observer for each element const elementsWithCslp = document.querySelectorAll( `[${DATA_CSLP_ATTR_SELECTOR}]` ); - elementsWithCslp.forEach((elementNode) => { const element = elementNode as HTMLElement; - const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if ( - mutation.type === "attributes" && - mutation.attributeName === DATA_CSLP_ATTR_SELECTOR + (mutation.type === "attributes" && + mutation.attributeName === DATA_CSLP_ATTR_SELECTOR) || + mutation.type === "childList" ) { + if (mutation.addedNodes.length > 0) { + mutation.addedNodes.forEach((node) => { + if (node instanceof HTMLElement) { + addElementClasses(node); + } + }); + } const dataCslp = element.getAttribute( DATA_CSLP_ATTR_SELECTOR ); @@ -105,7 +166,11 @@ function updateVariantClasses({ }); observers.push(observer); - observer.observe(element, { attributes: true }); + observer.observe(element, { + attributes: true, + childList: true, // Observe direct children + subtree: true, + }); }); setTimeout(() => {