const LOCAL_STORAGE_KEY = 'nightowl-color-scheme' const LIGHT = 'light' const DARK = 'dark' let store: Storage | null = null const persistPreference = true let mode = LIGHT let automaticInitialization = true let toggleButtonMode = 'currentState' interface NightowlOptions { defaultMode?: 'light' | 'dark' toggleButtonMode?: 'currentState' | 'newState' } try { store = localStorage } catch (err) { // Do nothing. The user probably blocks cookies. } function loadCss() { // fix css loading via vite // https://github.com/vitejs/vite/issues/8976 const css = document.createElement('style') css.innerHTML = ` /* Prevent inconsistencies for positioning */ .nightowl-light body{ filter: invert(0%); } .nightowl-dark { /* Firefox fallback. */ background-color: #111; } .nightowl-dark body { filter: invert(100%) hue-rotate(180deg); } /* Do not invert media (revert the invert). */ .nightowl-dark img, .nightowl-dark video, .nightowl-dark iframe, .nightowl-dark .nightowl-daylight { filter: invert(100%) hue-rotate(180deg); } /* Improve contrast on icons. */ .nightowl-dark .icon { filter: invert(15%) hue-rotate(180deg); } /* Re-enable code block backgrounds. */ .nightowl-dark pre { filter: invert(6%); } /* Improve contrast on list item markers. */ .nightowl-dark li::marker { color: #666; } ` document.head.appendChild(css) } export function createNightowl(options: NightowlOptions) { automaticInitialization = false if (options.defaultMode === 'dark') { mode = DARK } if (options.toggleButtonMode) { toggleButtonMode = options.toggleButtonMode } if (document.readyState === 'complete') { loadCss() initializeNightowl() initializeSwitcher() } else { window.addEventListener('load', () => { loadCss() initializeNightowl() initializeSwitcher() }) } } window.addEventListener('load', () => { if (automaticInitialization) { loadCss() initializeNightowl() initializeSwitcher() } }) function enableDarkMode() { mode = DARK const htmlElement = document.querySelector('html') if (htmlElement) { htmlElement.classList.remove('nightowl-light') htmlElement.classList.add('nightowl-dark') } } function enableLightMode() { mode = LIGHT const htmlElement = document.querySelector('html') if (htmlElement) { htmlElement.classList.remove('nightowl-dark') htmlElement.classList.add('nightowl-light') } } function toggleMode() { mode = mode === DARK ? LIGHT : DARK updateMode() } function updateMode() { if (mode === DARK) { enableDarkMode() } else { enableLightMode() } setSwitcherIcon() } function setSwitcherIcon() { const switcher = document.getElementById('nightowl-switcher-default') if (switcher) { const lightIcon = '\n' + ' \n' + '' const darkIcon = '\n' + ' \n' + '' if (toggleButtonMode === 'newState') { switcher.innerHTML = mode === DARK ? lightIcon : darkIcon } else if (toggleButtonMode === 'currentState') { switcher.innerHTML = mode === DARK ? darkIcon : lightIcon } } } function initializeSwitcher() { const switcher = document.createElement('div') console.log(window.innerWidth) switcher.id = 'nightowl-switcher-default' switcher.style.position = 'fixed' switcher.style.left = 'calc(100vw - 100px)' switcher.style.top = 'calc(10px)' switcher.style.width = '50px' switcher.style.height = '50px' switcher.style.borderRadius = '50%' switcher.style.backgroundColor = toggleButtonMode === 'newState' ? 'black' : 'white' switcher.style.display = 'flex' switcher.style.justifyContent = 'center' switcher.style.alignItems = 'center' switcher.style.cursor = 'pointer' switcher.style.zIndex = '9999' switcher.style.boxShadow = '0 0 10px rgba(0,0,0,0.2)' switcher.style.transition = 'all 0.3s ease-in-out' switcher.style.overflow = 'hidden' switcher.style.color = toggleButtonMode === 'newState' ? 'white' : 'black' switcher.addEventListener('click', () => { toggleMode() storeModeInLocalStorage() }) document.body.appendChild(switcher) setSwitcherIcon() } function initializeColorSchemeChangeListener() { // window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { // const newColorScheme = e.matches ? "dark" : "light"; // }); } function checkForRememberedValue() { let rememberedValue = null try { if (store) { rememberedValue = store.getItem(LOCAL_STORAGE_KEY) } } catch (err) { // Do nothing. The user probably blocks cookies. } if (rememberedValue && [DARK, LIGHT].includes(rememberedValue)) { mode = rememberedValue } else if (hasNativeDarkPrefersColorScheme()) { mode = DARK } } function initializeNightowl() { initializeColorSchemeChangeListener() checkForRememberedValue() updateMode() } function storeModeInLocalStorage() { if (persistPreference && mode !== null) { try { if (store) { store.setItem(LOCAL_STORAGE_KEY, mode) } } catch (err) { // Do nothing. The user probably blocks cookies. } } } function hasNativeDarkPrefersColorScheme() { return ( window.matchMedia && (window.matchMedia('(prefers-color-scheme: dark)').matches || window.matchMedia('(prefers-color-scheme:dark)').matches) ) }