1function generateThemeVariables( 2 theme = "default", 3 brand = "blue", 4 target = document.querySelector("head"), 5 styleId = "#hs-brand-variables", 6 id = "hs-brand-variables" 7) { 8 let style = null; 9 10 if (!target.querySelector(styleId)) { 11 style = document.createElement("style"); 12 style.id = id; 13 14 target.append(style); 15 } else { 16 style = target.querySelector(styleId); 17 } 18 19 style.textContent = ` 20 :root[data-theme="theme-${theme}"], 21 [data-theme="theme-${theme}"] { 22 --primary-50: var(--color-${brand}-50); 23 --primary-100: var(--color-${brand}-100); 24 --primary-200: var(--color-${brand}-200); 25 --primary-300: var(--color-${brand}-300); 26 --primary-400: var(--color-${brand}-400); 27 --primary-500: var(--color-${brand}-500); 28 --primary-600: var(--color-${brand}-600); 29 --primary-700: var(--color-${brand}-700); 30 --primary-800: var(--color-${brand}-800); 31 --primary-900: var(--color-${brand}-900); 32 --primary-950: var(--color-${brand}-950); 33 } 34 `; 35} 36 37document.addEventListener('DOMContentLoaded', function () { 38 const themeSwitcher = document.querySelector('#hs-themes'); 39 const brandSwitcher = document.querySelector('#hs-brands'); 40 const fontSwitcher = document.querySelector('#hs-fonts'); 41 const appearanceSwitcher = document.querySelector('#hs-appearance'); 42 const iframeEl = document.querySelector('#hs-theme-main-demo-iframe'); 43 44 if ( 45 !themeSwitcher || 46 !brandSwitcher || 47 !fontSwitcher || 48 !appearanceSwitcher || 49 !iframeEl 50 ) { 51 return; 52 } 53 54 let currentTheme = themeSwitcher.value || 'default'; 55 let currentBrand = brandSwitcher.value || 'blue'; 56 let currentFont = fontSwitcher.value || 'sans'; 57 let currentAppearance = 'light'; 58 59 const themesDefaults = { 60 "default": "blue", 61 "harvest": "amber", 62 "retro": "fuchsia", 63 "ocean": "cyan", 64 "autumn": "yellow", 65 "moon": "gray", 66 "bubblegum": "pink", 67 "cashmere": "preline-mauve", 68 "olive": "preline-avocado", 69 }; 70 71 const dispatchToIframe = (type, value) => { 72 if (!iframeEl.contentWindow) return false; 73 74 iframeEl.contentWindow.postMessage({ type, value }, "*"); 75 }; 76 const withIframe = (callback) => { 77 if (!iframeEl || !iframeEl.contentWindow || !iframeEl.contentWindow.document) return false; 78 const iframeDoc = iframeEl.contentWindow.document; 79 80 if (iframeDoc.readyState !== 'complete') return false; 81 82 callback(iframeDoc); 83 return true; 84 }; 85 86 const applyAppearance = (appearance) => { 87 currentAppearance = appearance; 88 89 withIframe((iframeDoc) => { 90 const html = iframeDoc.documentElement; 91 const head = iframeDoc.head; 92 93 html.classList.remove("light", "dark", "auto"); 94 html.classList.add(currentAppearance); 95 generateThemeVariables(currentTheme, currentBrand, head); 96 dispatchToIframe("hs:appearance-change", currentAppearance); 97 }); 98 }; 99 100 const syncTheme = () => { 101 withIframe((iframeDoc) => { 102 const html = iframeDoc.documentElement; 103 const head = iframeDoc.head; 104 105 html.setAttribute('data-theme', `theme-${currentTheme}`); 106 html.setAttribute('data-brand', currentBrand); 107 html.setAttribute('data-font', currentFont); 108 generateThemeVariables(currentTheme, currentBrand, head); 109 dispatchToIframe("hs:color-theme-change", currentTheme); 110 dispatchToIframe("hs:brand-change", currentBrand); 111 dispatchToIframe("hs:font-change", currentFont); 112 }); 113 }; 114 115 themeSwitcher.addEventListener('change', function () { 116 const brandSwitcherInstance = HSSelect.getInstance(brandSwitcher, true); 117 currentTheme = this.value; 118 currentBrand = themesDefaults[currentTheme]; 119 120 brandSwitcherInstance.element.setValue(currentBrand); 121 syncTheme(); 122 }); 123 124 brandSwitcher.addEventListener('change', function () { 125 currentBrand = this.value; 126 127 syncTheme(); 128 }); 129 130 fontSwitcher.addEventListener('change', function () { 131 currentFont = this.value; 132 133 syncTheme(); 134 }); 135 136 appearanceSwitcher.addEventListener('change', function () { 137 applyAppearance(this.checked ? "dark" : "light"); 138 }); 139 140 window.addEventListener('on-hs-appearance-change', (evt) => { 141 const nextAppearance = evt.detail; 142 143 appearanceSwitcher.checked = nextAppearance === "dark"; 144 appearanceSwitcher.disabled = nextAppearance === "dark"; 145 146 applyAppearance(nextAppearance); 147 }); 148 149 if (iframeEl) { 150 const initSync = () => { 151 const isReady = withIframe(() => { 152 syncTheme(); 153 applyAppearance(currentAppearance); 154 }); 155 156 if (!isReady) { 157 setTimeout(initSync, 50); 158 } 159 }; 160 161 iframeEl.addEventListener('load', initSync); 162 initSync(); 163 } 164});
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.