{"version":3,"file":"zoom.v1.1563.min.js?t=898b33f5fe533ddbecca","mappings":"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","sources":["webpack://@hero-digital/zoom/./src/components/product-hub-components/service-cards/service-cards.js"],"sourcesContent":["class ServiceCards {\r\n static ACTIVE_BULLET_GAP = 20\r\n static ACTIVE_BULLET_GAP_MD = 20\r\n static DYNAMIC_BULLETS_QUERY = '(max-width: 1024px)'\r\n static DESKTOP_QUERY = '(min-width: 1025px)'\r\n\r\n constructor(el) {\r\n this.el = el\r\n this.$swiper = el.querySelector('.card-swiper-container.swiper')\r\n this.$cards = el.querySelectorAll('.service-card')\r\n this.currentFlippedCard = null\r\n this.isInitializing = true\r\n\r\n // Add loading classes to prevent FOUC\r\n this.el.classList.add('is-initializing')\r\n this.$swiper?.classList.add('swiper-initializing')\r\n\r\n this.mq = window.matchMedia(ServiceCards.DYNAMIC_BULLETS_QUERY)\r\n this.desktopMq = window.matchMedia(ServiceCards.DESKTOP_QUERY)\r\n\r\n this.onBreakpointChange = () => this.handleResize()\r\n this.onResize = this.debounce(() => this.handleResize(), 250)\r\n\r\n this.mq.addEventListener('change', this.onBreakpointChange)\r\n this.desktopMq.addEventListener('change', this.onBreakpointChange)\r\n window.addEventListener('resize', this.onResize)\r\n window.addEventListener('orientationchange', this.onResize)\r\n\r\n // Wait for images to load before initializing\r\n let initialized = false\r\n\r\n const initialize = () => {\r\n if (initialized) return\r\n initialized = true\r\n\r\n this.initSwiper()\r\n this.initFlipCards()\r\n this.hideSkeletons()\r\n }\r\n\r\n const initTimeout = setTimeout(() => {\r\n // Fallback: initialize after 3 seconds even if images haven't loaded\r\n if (this.isInitializing) {\r\n initialize()\r\n }\r\n }, 3000)\r\n\r\n this.waitForImages().then(() => {\r\n clearTimeout(initTimeout)\r\n initialize()\r\n })\r\n }\r\n\r\n waitForImages() {\r\n const images = Array.from(this.el.querySelectorAll('.service-card__image'))\r\n\r\n if (images.length === 0) {\r\n return Promise.resolve()\r\n }\r\n\r\n const imagePromises = images.map((img, index) => {\r\n return new Promise((resolve) => {\r\n if (img.complete && img.naturalHeight !== 0) {\r\n resolve()\r\n } else {\r\n const timeout = setTimeout(() => resolve(), 2000) // Per-image timeout\r\n img.addEventListener('load', () => {\r\n clearTimeout(timeout)\r\n resolve()\r\n }, { once: true })\r\n img.addEventListener('error', () => {\r\n clearTimeout(timeout)\r\n resolve()\r\n }, { once: true })\r\n }\r\n })\r\n })\r\n\r\n return Promise.all(imagePromises)\r\n }\r\n\r\n hideSkeletons() {\r\n // Small delay to ensure swiper has applied all styles\r\n setTimeout(() => {\r\n this.$cards.forEach((card) => {\r\n card.classList.add('is-loaded')\r\n })\r\n\r\n // Remove initializing class to allow overflow for flip animations\r\n this.el.classList.remove('is-initializing')\r\n this.isInitializing = false\r\n }, 150)\r\n }\r\n\r\n initSwiper() {\r\n this.swiper?.destroy(true, true)\r\n this.resetPagination()\r\n\r\n // Disable Swiper on desktop (>= 1025px)\r\n if (window.innerWidth >= 1025) {\r\n this.$swiper.classList.add('swiper-disabled')\r\n this.$swiper.classList.remove('swiper-initializing')\r\n this.el.classList.remove('is-initializing')\r\n return\r\n }\r\n\r\n this.$swiper.classList.remove('swiper-disabled')\r\n\r\n const hideArrows = this.$swiper.getAttribute('data-hide-arrows') === 'true'\r\n const slideCount = this.$swiper.querySelectorAll('.swiper-slide').length\r\n const useDynamicBullets = this.mq.matches\r\n ? slideCount >= 7\r\n : slideCount > 15\r\n\r\n const config = {\r\n slidesPerView: 1.2,\r\n spaceBetween: 16,\r\n centeredSlides: true,\r\n loop: false,\r\n watchOverflow: true,\r\n observer: true,\r\n observeParents: true,\r\n breakpoints: {\r\n 600: {\r\n slidesPerView: 1.5,\r\n spaceBetween: 20,\r\n centeredSlides: true,\r\n centeredSlidesBounds: true\r\n },\r\n 768: {\r\n slidesPerView: 3,\r\n centeredSlides: false,\r\n spaceBetween: 20\r\n }\r\n },\r\n pagination: {\r\n el: this.$swiper.querySelector('.swiper-pagination'),\r\n clickable: true,\r\n dynamicBullets: useDynamicBullets,\r\n dynamicMainBullets: 5\r\n },\r\n on: {\r\n paginationUpdate: (swiper, paginationEl) => {\r\n if (!swiper.params.pagination.dynamicBullets) return\r\n\r\n const gap =\r\n window.innerWidth >= 768\r\n ? ServiceCards.ACTIVE_BULLET_GAP_MD\r\n : ServiceCards.ACTIVE_BULLET_GAP\r\n\r\n let afterActive = false\r\n\r\n paginationEl\r\n .querySelectorAll('.swiper-pagination-bullet')\r\n .forEach((bullet) => {\r\n if (\r\n bullet.classList.contains('swiper-pagination-bullet-active')\r\n ) {\r\n afterActive = true\r\n return\r\n }\r\n\r\n const baseLeft = parseFloat(bullet.style.left) || 0\r\n const offset = afterActive ? gap : -gap\r\n bullet.style.left = `${baseLeft + offset}px`\r\n })\r\n }\r\n }\r\n }\r\n\r\n if (!hideArrows) {\r\n config.navigation = {\r\n nextEl: this.$swiper.querySelector('.swiper-button-forward'),\r\n prevEl: this.$swiper.querySelector('.swiper-button-previous')\r\n }\r\n }\r\n\r\n this.swiper = new Swiper(this.$swiper, config)\r\n\r\n // Remove initializing class and force update after initialization\r\n setTimeout(() => {\r\n this.$swiper?.classList.remove('swiper-initializing')\r\n this.$swiper?.classList.add('swiper-ready')\r\n this.swiper?.update()\r\n }, 100)\r\n }\r\n\r\n resetPagination() {\r\n const $pagination = this.$swiper.querySelector('.swiper-pagination')\r\n if (!$pagination) return\r\n $pagination.classList.remove('swiper-pagination-bullets-dynamic')\r\n $pagination.removeAttribute('style')\r\n $pagination.innerHTML = ''\r\n }\r\n\r\n initFlipCards() {\r\n this.$cards.forEach((card) => {\r\n const inner = card.querySelector('.service-card__inner')\r\n\r\n if (this.desktopMq.matches) {\r\n // Desktop: hover to flip\r\n card.addEventListener('mouseenter', () => {\r\n this.flipCard(inner, true)\r\n this.currentFlippedCard = inner\r\n })\r\n card.addEventListener('mouseleave', () => {\r\n this.flipCard(inner, false)\r\n if (this.currentFlippedCard === inner) {\r\n this.currentFlippedCard = null\r\n }\r\n })\r\n } else {\r\n // Mobile/Tablet: click to toggle (only one card at a time)\r\n card.addEventListener('click', () => this.handleCardClick(inner))\r\n }\r\n\r\n // Keyboard accessibility\r\n card.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter' || e.key === ' ') {\r\n e.preventDefault()\r\n this.handleCardClick(inner)\r\n }\r\n })\r\n\r\n // Make card focusable\r\n if (!card.hasAttribute('tabindex')) {\r\n card.setAttribute('tabindex', '0')\r\n }\r\n })\r\n }\r\n\r\n handleResize() {\r\n // Reinitialize both Swiper and card interactions\r\n // Don't show skeletons on resize, only on initial load\r\n this.initSwiper()\r\n this.updateCardInteractions()\r\n\r\n // Ensure cards remain visible during resize\r\n if (!this.isInitializing) {\r\n this.$cards.forEach((card) => {\r\n card.classList.add('is-loaded')\r\n })\r\n }\r\n }\r\n\r\n updateCardInteractions() {\r\n // Close any flipped cards before cloning (prevents orphaned flip state)\r\n if (this.currentFlippedCard) {\r\n this.flipCard(this.currentFlippedCard, false)\r\n }\r\n\r\n // Clear existing card event listeners by cloning and replacing\r\n this.$cards.forEach((card) => {\r\n const newCard = card.cloneNode(true)\r\n card.parentNode.replaceChild(newCard, card)\r\n })\r\n\r\n // Reset flipped card reference (now points to detached node)\r\n this.currentFlippedCard = null\r\n\r\n // Re-query cards and reinitialize\r\n this.$cards = this.el.querySelectorAll('.service-card')\r\n this.initFlipCards()\r\n }\r\n\r\n flipCard(inner, flip) {\r\n if (flip) {\r\n inner.classList.add('is-flipped')\r\n } else {\r\n inner.classList.remove('is-flipped')\r\n }\r\n }\r\n\r\n handleCardClick(inner) {\r\n // If clicking the same card, toggle it\r\n if (this.currentFlippedCard === inner) {\r\n this.flipCard(inner, false)\r\n this.currentFlippedCard = null\r\n } else {\r\n // Close the previously flipped card if exists\r\n if (this.currentFlippedCard) {\r\n this.flipCard(this.currentFlippedCard, false)\r\n }\r\n // Open the new card\r\n this.flipCard(inner, true)\r\n this.currentFlippedCard = inner\r\n }\r\n }\r\n\r\n debounce(func, wait) {\r\n let timeout\r\n return function executedFunction(...args) {\r\n const later = () => {\r\n clearTimeout(timeout)\r\n func(...args)\r\n }\r\n clearTimeout(timeout)\r\n timeout = setTimeout(later, wait)\r\n }\r\n }\r\n\r\n destroy() {\r\n this.mq?.removeEventListener('change', this.onBreakpointChange)\r\n this.desktopMq?.removeEventListener('change', this.onBreakpointChange)\r\n window.removeEventListener('resize', this.onResize)\r\n window.removeEventListener('orientationchange', this.onResize)\r\n this.swiper?.destroy()\r\n }\r\n}\r\n\r\nexport default ServiceCards\r\n"],"names":["ServiceCards","el","_this$$swiper","_this","this","_classCallCheck","$swiper","querySelector","$cards","querySelectorAll","currentFlippedCard","isInitializing","classList","add","mq","window","matchMedia","DYNAMIC_BULLETS_QUERY","desktopMq","DESKTOP_QUERY","onBreakpointChange","handleResize","onResize","debounce","addEventListener","initialized","initialize","initSwiper","initFlipCards","hideSkeletons","initTimeout","setTimeout","waitForImages","then","clearTimeout","key","value","images","Array","from","length","Promise","resolve","imagePromises","map","img","index","complete","naturalHeight","timeout","once","all","_this2","forEach","card","remove","_this$swiper","_this3","swiper","destroy","resetPagination","innerWidth","hideArrows","getAttribute","slideCount","useDynamicBullets","matches","config","slidesPerView","spaceBetween","centeredSlides","loop","watchOverflow","observer","observeParents","breakpoints","centeredSlidesBounds","pagination","clickable","dynamicBullets","dynamicMainBullets","on","paginationUpdate","paginationEl","params","gap","ACTIVE_BULLET_GAP_MD","ACTIVE_BULLET_GAP","afterActive","bullet","contains","baseLeft","parseFloat","style","left","offset","concat","navigation","nextEl","prevEl","Swiper","_this3$$swiper","_this3$$swiper2","_this3$swiper","update","$pagination","removeAttribute","innerHTML","_this4","inner","flipCard","handleCardClick","e","preventDefault","hasAttribute","setAttribute","updateCardInteractions","newCard","cloneNode","parentNode","replaceChild","flip","func","wait","_len","arguments","args","_key","apply","_this$mq","_this$desktopMq","_this$swiper2","removeEventListener","_defineProperty","service_cards"],"sourceRoot":""}