// Light / Dark theme toggle (function () { const defaultTheme = 'system' const themeToggleButtons = document.querySelectorAll(".theme-toggle"); // Change the icons of the buttons based on previous settings or system theme if ( localStorage.getItem("color-theme") === "dark" || (!("color-theme" in localStorage) && ((window.matchMedia("(prefers-color-scheme: dark)").matches && defaultTheme === "system") || defaultTheme === "dark")) ) { themeToggleButtons.forEach((el) => el.dataset.theme = "dark"); } else { themeToggleButtons.forEach((el) => el.dataset.theme = "light"); } // Add click event handler to the buttons themeToggleButtons.forEach((el) => { el.addEventListener("click", function () { if (localStorage.getItem("color-theme")) { if (localStorage.getItem("color-theme") === "light") { setDarkTheme(); localStorage.setItem("color-theme", "dark"); } else { setLightTheme(); localStorage.setItem("color-theme", "light"); } } else { if (document.documentElement.classList.contains("dark")) { setLightTheme(); localStorage.setItem("color-theme", "light"); } else { setDarkTheme(); localStorage.setItem("color-theme", "dark"); } } el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light"; }); }); // Listen for system theme changes window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => { if (defaultTheme === "system" && !("color-theme" in localStorage)) { e.matches ? setDarkTheme() : setLightTheme(); themeToggleButtons.forEach((el) => el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light" ); } }); })(); ; // Hamburger menu for mobile navigation document.addEventListener('DOMContentLoaded', function () { const menu = document.querySelector('.hamburger-menu'); const overlay = document.querySelector('.mobile-menu-overlay'); const sidebarContainer = document.querySelector('.sidebar-container'); // Initialize the overlay const overlayClasses = ['hx-fixed', 'hx-inset-0', 'hx-z-10', 'hx-bg-black/80', 'dark:hx-bg-black/60']; overlay.classList.add('hx-bg-transparent'); overlay.classList.remove("hx-hidden", ...overlayClasses); function toggleMenu() { // Toggle the hamburger menu menu.querySelector('svg').classList.toggle('open'); // When the menu is open, we want to show the navigation sidebar sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,-100%,0)]'); sidebarContainer.classList.toggle('max-md:[transform:translate3d(0,0,0)]'); // When the menu is open, we want to prevent the body from scrolling document.body.classList.toggle('hx-overflow-hidden'); document.body.classList.toggle('md:hx-overflow-auto'); } menu.addEventListener('click', (e) => { e.preventDefault(); toggleMenu(); if (overlay.classList.contains('hx-bg-transparent')) { // Show the overlay overlay.classList.add(...overlayClasses); overlay.classList.remove('hx-bg-transparent'); } else { // Hide the overlay overlay.classList.remove(...overlayClasses); overlay.classList.add('hx-bg-transparent'); } }); overlay.addEventListener('click', (e) => { e.preventDefault(); toggleMenu(); // Hide the overlay overlay.classList.remove(...overlayClasses); overlay.classList.add('hx-bg-transparent'); }); }); ; // Copy button for code blocks document.addEventListener('DOMContentLoaded', function () { const getCopyIcon = () => { const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.innerHTML = ` `; svg.setAttribute('fill', 'none'); svg.setAttribute('viewBox', '0 0 24 24'); svg.setAttribute('stroke', 'currentColor'); svg.setAttribute('stroke-width', '2'); return svg; } const getSuccessIcon = () => { const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.innerHTML = ` `; svg.setAttribute('fill', 'none'); svg.setAttribute('viewBox', '0 0 24 24'); svg.setAttribute('stroke', 'currentColor'); svg.setAttribute('stroke-width', '2'); return svg; } document.querySelectorAll('.hextra-code-copy-btn').forEach(function (button) { // Add copy and success icons button.querySelector('.copy-icon')?.appendChild(getCopyIcon()); button.querySelector('.success-icon')?.appendChild(getSuccessIcon()); // Add click event listener for copy button button.addEventListener('click', function (e) { e.preventDefault(); // Get the code target const target = button.parentElement.previousElementSibling; let codeElement; if (target.tagName === 'CODE') { codeElement = target; } else { // Select the last code element in case line numbers are present const codeElements = target.querySelectorAll('code'); codeElement = codeElements[codeElements.length - 1]; } if (codeElement) { let code = codeElement.innerText; // Replace double newlines with single newlines in the innerText // as each line inside has trailing newline '\n' if ("lang" in codeElement.dataset) { code = code.replace(/\n\n/g, '\n'); } navigator.clipboard.writeText(code).then(function () { button.classList.add('copied'); setTimeout(function () { button.classList.remove('copied'); }, 1000); }).catch(function (err) { console.error('Failed to copy text: ', err); }); } else { console.error('Target element not found'); } }); }); }); ; document.querySelectorAll('.hextra-tabs-toggle').forEach(function (button) { button.addEventListener('click', function (e) { // set parent tabs to unselected const tabs = Array.from(e.target.parentElement.querySelectorAll('.hextra-tabs-toggle')); tabs.map(tab => tab.dataset.state = ''); // set current tab to selected e.target.dataset.state = 'selected'; // set all panels to unselected const panelsContainer = e.target.parentElement.parentElement.nextElementSibling; Array.from(panelsContainer.children).forEach(function (panel) { panel.dataset.state = ''; }); const panelId = e.target.getAttribute('aria-controls'); const panel = panelsContainer.querySelector(`#${panelId}`); panel.dataset.state = 'selected'; }); }); ; (function () { const languageSwitchers = document.querySelectorAll('.language-switcher'); languageSwitchers.forEach((switcher) => { switcher.addEventListener('click', (e) => { e.preventDefault(); switcher.dataset.state = switcher.dataset.state === 'open' ? 'closed' : 'open'; const optionsElement = switcher.nextElementSibling; optionsElement.classList.toggle('hx-hidden'); // Calculate position of language options element const switcherRect = switcher.getBoundingClientRect(); const translateY = switcherRect.top - window.innerHeight - 15; optionsElement.style.transform = `translate3d(${switcherRect.left}px, ${translateY}px, 0)`; optionsElement.style.minWidth = `${Math.max(switcherRect.width, 50)}px`; }); }); // Dismiss language switcher when clicking outside document.addEventListener('click', (e) => { if (e.target.closest('.language-switcher') === null) { languageSwitchers.forEach((switcher) => { switcher.dataset.state = 'closed'; const optionsElement = switcher.nextElementSibling; optionsElement.classList.add('hx-hidden'); }); } }); })(); ; // Script for filetree shortcode collapsing/expanding folders used in the theme // ====================================================================== document.addEventListener("DOMContentLoaded", function () { const folders = document.querySelectorAll(".hextra-filetree-folder"); folders.forEach(function (folder) { folder.addEventListener("click", function () { Array.from(folder.children).forEach(function (el) { el.dataset.state = el.dataset.state === "open" ? "closed" : "open"; }); folder.nextElementSibling.dataset.state = folder.nextElementSibling.dataset.state === "open" ? "closed" : "open"; }); }); }); ; document.addEventListener("DOMContentLoaded", function () { scrollToActiveItem(); enableCollapsibles(); }); function enableCollapsibles() { const buttons = document.querySelectorAll(".hextra-sidebar-collapsible-button"); buttons.forEach(function (button) { button.addEventListener("click", function (e) { e.preventDefault(); const list = button.parentElement.parentElement; if (list) { list.classList.toggle("open") } }); }); } function scrollToActiveItem() { const sidebarScrollbar = document.querySelector("aside.sidebar-container > .hextra-scrollbar"); const activeItems = document.querySelectorAll(".sidebar-active-item"); const visibleActiveItem = Array.from(activeItems).find(function (activeItem) { return activeItem.getBoundingClientRect().height > 0; }); if (!visibleActiveItem) { return; } const yOffset = visibleActiveItem.clientHeight; const yDistance = visibleActiveItem.getBoundingClientRect().top - sidebarScrollbar.getBoundingClientRect().top; sidebarScrollbar.scrollTo({ behavior: "instant", top: yDistance - yOffset }); } ; // Back to top button document.addEventListener("DOMContentLoaded", function () { const backToTop = document.querySelector("#backToTop"); if (backToTop) { document.addEventListener("scroll", (e) => { if (window.scrollY > 300) { backToTop.classList.remove("hx-opacity-0"); } else { backToTop.classList.add("hx-opacity-0"); } }); } }); function scrollUp() { window.scroll({ top: 0, left: 0, behavior: "smooth", }); }