// Custom touch handling for gallery carousel let touchStartX = 0; let touchStartY = 0; let touchStartTime = 0; let isSwiping = false; let activeTooltip = null; function handleTouchStart(e) { touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; touchStartTime = Date.now(); isSwiping = false; } function handleTouchMove(e) { if (!touchStartX || !touchStartY) { return; } const touchX = e.touches[0].clientX; const touchY = e.touches[0].clientY; const diffX = Math.abs(touchX - touchStartX); const diffY = Math.abs(touchY - touchStartY); // If horizontal movement is greater than vertical, it's a swipe if (diffX > diffY && diffX > 30) { isSwiping = true; // Prevent default to avoid any unwanted behaviors e.preventDefault(); } } function handleTouchEnd(e) { if (!touchStartX || !touchStartY) { return; } const touchEndX = e.changedTouches[0].clientX; const touchEndTime = Date.now(); const touchDuration = touchEndTime - touchStartTime; // Reset values const startX = touchStartX; touchStartX = 0; touchStartY = 0; touchStartTime = 0; // If it was a swipe, handle navigation if (isSwiping) { const diff = startX - touchEndX; // Find the carousel controls const leftBtn = document.querySelector('[data-landingsite-carousel-controls-left]'); const rightBtn = document.querySelector('[data-landingsite-carousel-controls-right]'); if (Math.abs(diff) > 50) { // Minimum swipe distance if (diff > 0 && rightBtn) { // Swipe left = next rightBtn.click(); } else if (diff < 0 && leftBtn) { // Swipe right = previous leftBtn.click(); } } } else if (touchDuration < 500) { // Short tap - toggle tooltip const carouselItem = e.target.closest('[data-landingsite-carousel-item]'); if (carouselItem) { const tooltip = carouselItem.querySelector('.absolute.bottom-4'); // Hide any other active tooltips if (activeTooltip && activeTooltip !== tooltip) { activeTooltip.classList.remove('translate-y-0'); activeTooltip.classList.add('translate-y-8'); activeTooltip.parentElement.classList.remove('opacity-100'); activeTooltip.parentElement.classList.add('opacity-0'); } if (tooltip) { const overlay = tooltip.parentElement; const isVisible = !overlay.classList.contains('opacity-0'); if (isVisible) { // Hide tooltip tooltip.classList.remove('translate-y-0'); tooltip.classList.add('translate-y-8'); overlay.classList.remove('opacity-100'); overlay.classList.add('opacity-0'); activeTooltip = null; } else { // Show tooltip tooltip.classList.remove('translate-y-8'); tooltip.classList.add('translate-y-0'); overlay.classList.remove('opacity-0'); overlay.classList.add('opacity-100'); activeTooltip = tooltip; } } } } isSwiping = false; } // Hide tooltip when clicking outside function handleDocumentClick(e) { const carouselItem = e.target.closest('[data-landingsite-carousel-item]'); if (!carouselItem && activeTooltip) { activeTooltip.classList.remove('translate-y-0'); activeTooltip.classList.add('translate-y-8'); activeTooltip.parentElement.classList.remove('opacity-100'); activeTooltip.parentElement.classList.add('opacity-0'); activeTooltip = null; } } export function init() { const carousel = document.querySelector('[data-landingsite-carousel]'); if (carousel) { // Add touch event listeners to the carousel carousel.addEventListener('touchstart', handleTouchStart, { passive: false }); carousel.addEventListener('touchmove', handleTouchMove, { passive: false }); carousel.addEventListener('touchend', handleTouchEnd, { passive: false }); // Add click listener to document for hiding tooltips document.addEventListener('click', handleDocumentClick); } } export function teardown() { const carousel = document.querySelector('[data-landingsite-carousel]'); if (carousel) { carousel.removeEventListener('touchstart', handleTouchStart); carousel.removeEventListener('touchmove', handleTouchMove); carousel.removeEventListener('touchend', handleTouchEnd); } document.removeEventListener('click', handleDocumentClick); // Reset globals activeTooltip = null; }