UNPKG

dark-mode-switcheroo

Version:

🌓 Simple CSS theme switching with saved preferences and automatic OS setting detection

1 lines • 4.93 kB
{"version":3,"file":"dark-mode.cjs","sources":["../src/dark-mode.ts"],"sourcesContent":["export function init(options: {\n toggle?: Element | null;\n classes?: { dark: string, light: string };\n default?: string;\n storageKey?: string;\n onInit?: (toggle?: Element | null) => unknown;\n onUserToggle?: (toggle?: Element | null) => unknown;\n onChange?: (theme: string, toggle?: Element | null) => unknown;\n}): void {\n options = options || {};\n\n // use a specified element(s) to trigger swap when clicked\n const toggle = options.toggle || null;\n\n // check for preset `dark_mode_pref` preference in local storage\n const storageKey = options.storageKey || \"dark_mode_pref\";\n const pref = localStorage.getItem(storageKey);\n\n // change CSS via these <body> classes:\n const dark = options.classes ? options.classes.dark : \"dark\";\n const light = options.classes ? options.classes.light : \"light\";\n\n // which class is <body> set to initially?\n const defaultTheme = options.default || \"light\";\n\n // keep track of current state no matter how we got there\n let active = defaultTheme === dark;\n\n // receives a class name and switches <body> to it\n const activateTheme = function (theme: string, remember?: boolean) {\n // optional onChange callback function passed as option\n if (typeof options.onChange === \"function\") {\n options.onChange(theme, toggle);\n }\n\n document.body.classList.remove(dark, light);\n document.body.classList.add(theme);\n active = theme === dark;\n\n if (remember) {\n localStorage.setItem(storageKey, theme);\n }\n };\n\n // optional onInit callback function passed as option\n if (typeof options.onInit === \"function\") {\n options.onInit(toggle);\n }\n\n // user has never clicked the button, so go by their OS preference until/if they do so\n if (!pref) {\n // returns media query selector syntax\n const prefers = function (colorScheme: \"dark\" | \"light\") {\n // https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme\n return `(prefers-color-scheme: ${colorScheme})`;\n };\n\n // check for OS dark/light mode preference and switch accordingly\n // default to `defaultTheme` set above if unsupported\n if (window.matchMedia(prefers(\"dark\")).matches) {\n activateTheme(dark);\n } else if (window.matchMedia(prefers(\"light\")).matches) {\n activateTheme(light);\n } else {\n activateTheme(defaultTheme);\n }\n\n // real-time switching if supported by OS/browser\n window.matchMedia(prefers(\"dark\")).addEventListener(\"change\", function (e) {\n if (e.matches) {\n activateTheme(dark);\n }\n });\n window.matchMedia(prefers(\"light\")).addEventListener(\"change\", function (e) {\n if (e.matches) {\n activateTheme(light);\n }\n });\n } else if (pref === dark || pref === light) {\n // if user already explicitly toggled in the past, restore their preference\n activateTheme(pref);\n } else {\n // fallback to default theme (this shouldn't happen)\n activateTheme(defaultTheme);\n }\n\n // don't freak out if page happens not to have a toggle\n if (toggle !== null) {\n // handle toggle click\n toggle.addEventListener(\"click\", function () {\n // optional onUserToggle callback function passed as option\n if (typeof options.onUserToggle === \"function\") {\n options.onUserToggle(toggle);\n }\n\n // switch to the opposite theme & save preference in local storage\n if (active) {\n activateTheme(light, true);\n } else {\n activateTheme(dark, true);\n }\n });\n }\n}\n"],"names":["options","toggle","storageKey","pref","localStorage","getItem","dark","classes","light","defaultTheme","active","activateTheme","theme","remember","onChange","document","body","classList","remove","add","setItem","onInit","prefers","colorScheme","window","matchMedia","matches","addEventListener","e","onUserToggle"],"mappings":"sBAAqBA,GAYnB,IAAMC,GAHND,EAAUA,GAAW,IAGEC,QAAU,KAG3BC,EAAaF,EAAQE,YAAc,iBACnCC,EAAOC,aAAaC,QAAQH,GAG5BI,EAAON,EAAQO,QAAUP,EAAQO,QAAQD,KAAO,OAChDE,EAAQR,EAAQO,QAAUP,EAAQO,QAAQC,MAAQ,QAGlDC,EAAeT,WAAmB,QAGpCU,EAASD,IAAiBH,EAGxBK,EAAgB,SAAUC,EAAeC,GAEb,mBAArBb,EAAQc,UACjBd,EAAQc,SAASF,EAAOX,GAG1Bc,SAASC,KAAKC,UAAUC,OAAOZ,EAAME,GACrCO,SAASC,KAAKC,UAAUE,IAAIP,GAC5BF,EAASE,IAAUN,EAEfO,GACFT,aAAagB,QAAQlB,EAAYU,IAUrC,GAL8B,mBAAnBZ,EAAQqB,QACjBrB,EAAQqB,OAAOpB,GAIZE,EA8BHQ,EAFSR,IAASG,GAAQH,IAASK,EAErBL,EAGAM,OAjCL,CAET,IAAMa,EAAU,SAAUC,GAExB,gCAAiCA,OAK/BC,OAAOC,WAAWH,EAAQ,SAASI,QACrCf,EAAcL,GACLkB,OAAOC,WAAWH,EAAQ,UAAUI,QAC7Cf,EAAcH,GAEdG,EAAcF,GAIhBe,OAAOC,WAAWH,EAAQ,SAASK,iBAAiB,SAAU,SAAUC,GAClEA,EAAEF,SACJf,EAAcL,KAGlBkB,OAAOC,WAAWH,EAAQ,UAAUK,iBAAiB,SAAU,SAAUC,GACnEA,EAAEF,SACJf,EAAcH,KAYL,OAAXP,GAEFA,EAAO0B,iBAAiB,QAAS,WAEK,mBAAzB3B,EAAQ6B,cACjB7B,EAAQ6B,aAAa5B,GAKrBU,EADED,EACYF,EAEAF,GAFO"}