1/** 2 * wyzard blog chrome.js â AUTO-GENERATED 3 * Handles theme toggle, scroll-bg, mega-menu, and mobile menu. 4 * localStorage key 'wyz-theme' is shared with the marketing Next.js site 5 * (ThemeProvider.tsx) so toggling on either surface persists across both. 6 * 7 * Sets window.__wyzChromeActive = true so theme.js (fallback) can bail early 8 * and avoid double-registering the same event handlers. 9 */ 10(function () { 11 'use strict'; 12 13 // Signal to theme.js that chrome.js is handling all interactions. 14 window.__wyzChromeActive = true; 15 16 var STORAGE_KEY = 'wyz-theme'; 17 var root = document.documentElement; 18 19 /* ââ Theme helpers ââ */ 20 function readTheme() { 21 try { return localStorage.getItem(STORAGE_KEY) === 'light' ? 'light' : 'dark'; } 22 catch (_) { return root.dataset.theme === 'light' ? 'light' : 'dark'; } 23 } 24 25 function applyTheme(theme) { 26 root.dataset.theme = theme; 27 root.classList.toggle('light', theme === 'light'); 28 root.classList.toggle('dark', theme === 'dark'); 29 try { localStorage.setItem(STORAGE_KEY, theme); } catch (_) { /* private mode */ } 30 document.querySelectorAll('[data-wyz-theme-toggle]').forEach(function (btn) { 31 var next = theme === 'dark' ? 'light' : 'dark'; 32 btn.setAttribute('aria-pressed', theme === 'light' ? 'true' : 'false'); 33 btn.setAttribute('aria-label', 'Switch to ' + next + ' mode'); 34 }); 35 } 36 37 /* Apply ASAP â before paint â to avoid FOUC */ 38 applyTheme(readTheme()); 39 40 /* ââ Capture-phase delegates â registered immediately, before any tracker ââ */ 41 document.addEventListener('click', function (e) { 42 var btn = e.target && e.target.closest && e.target.closest('[data-wyz-theme-toggle]'); 43 if (!btn) return; 44 e.preventDefault(); 45 e.stopPropagation(); 46 e.stopImmediatePropagation(); 47 applyTheme(root.dataset.theme === 'light' ? 'dark' : 'light'); 48 }, true); 49 50 document.addEventListener('click', function (e) { 51 var btn = e.target && e.target.closest && e.target.closest('[data-wyz-menu-toggle]'); 52 if (!btn) return; 53 e.preventDefault(); 54 e.stopPropagation(); 55 e.stopImmediatePropagation(); 56 var mobileMenu = document.getElementById('wyz-mobile-menu'); 57 var isOpen = btn.getAttribute('aria-expanded') === 'true'; 58 btn.setAttribute('aria-expanded', isOpen ? 'false' : 'true'); 59 btn.setAttribute('aria-label', isOpen ? 'Open menu' : 'Close menu'); 60 if (mobileMenu) mobileMenu.hidden = isOpen; 61 document.body.style.overflow = isOpen ? '' : 'hidden'; 62 btn.classList.toggle('is-open', !isOpen); 63 }, true); 64 65 document.addEventListener('DOMContentLoaded', function () { 66 var header = document.getElementById('wyz-header'); 67 var mobileMenu = document.getElementById('wyz-mobile-menu'); 68 var menuToggle = document.querySelector('[data-wyz-menu-toggle]'); 69 70 /* ââ Scroll-bg ââ */ 71 function syncHeaderScroll() { 72 if (header) header.classList.toggle('is-scrolled', window.scrollY > 12); 73 } 74 syncHeaderScroll(); 75 window.addEventListener('scroll', syncHeaderScroll, { passive: true }); 76 77 /* ââ Mobile menu link â close on nav ââ */ 78 if (menuToggle && mobileMenu) { 79 mobileMenu.querySelectorAll('a').forEach(function (link) { 80 link.addEventListener('click', function () { 81 menuToggle.setAttribute('aria-expanded', 'false'); 82 menuToggle.setAttribute('aria-label', 'Open menu'); 83 mobileMenu.hidden = true; 84 document.body.style.overflow = ''; 85 menuToggle.classList.remove('is-open'); 86 }); 87 }); 88 } 89 90 /* ââ Mega-menus (desktop) ââ */ 91 document.querySelectorAll('[data-wyz-mega]').forEach(function (item) { 92 var trigger = item.querySelector('.wyz-nav__trigger'); 93 var panel = item.querySelector('.wyz-mega'); 94 if (!trigger || !panel) return; 95 96 var closeTimer; 97 98 function openMenu() { 99 clearTimeout(closeTimer); 100 panel.hidden = false; 101 trigger.setAttribute('aria-expanded', 'true'); 102 trigger.querySelector('.wyz-nav__chevron').style.transform = 'rotate(180deg)'; 103 } 104 function closeMenu() { 105 closeTimer = setTimeout(function () { 106 panel.hidden = true; 107 trigger.setAttribute('aria-expanded', 'false'); 108 trigger.querySelector('.wyz-nav__chevron').style.transform = ''; 109 }, 80); 110 } 111 112 item.addEventListener('mouseenter', openMenu); 113 item.addEventListener('mouseleave', closeMenu); 114 trigger.addEventListener('click', function () { 115 panel.hidden ? openMenu() : closeMenu(); 116 }); 117 /* Keep open when mouse re-enters the panel */ 118 panel.addEventListener('mouseenter', function () { clearTimeout(closeTimer); }); 119 panel.addEventListener('mouseleave', closeMenu); 120 }); 121 }); 122})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.