UNPKG

storybook-addon-theme-changer

Version:

A Storybook addon for switching different themes (ex. daisyUI etc.)

1 lines 8.62 kB
{"version":3,"sources":["../src/withGlobals.ts","../src/utils/index.ts","../src/preview.ts"],"names":["useEffect","useGlobals","getThemes","themesObj","defaultThemes","defaultMethod","themes","method","setColorMode","systemPreference","persistedPreference","colorMode","initialValue","withGlobals","StoryFn","context","theme","updateGlobals","isInDocs","chakraClassNames","savedTheme","preview","preview_default"],"mappings":"AAAA,OAAS,aAAAA,EAAW,cAAAC,MAAkB,yBCA/B,IAAMC,EACXC,GACG,CAEH,IAAIC,EAA0B,CAAC,QAAS,MAAM,EAC1CC,EAA8B,aAC9BC,EACAC,EAIJ,OAAI,MAAM,QAAQJ,CAAS,GAAKA,EAAU,OAAS,GACjDG,EAASH,EAETI,EAAS,cAGA,OAAOJ,GAAc,UAE1B,WAAYA,GACV,MAAM,QAAQA,EAAU,MAAM,GAAKA,EAAU,OAAO,OAAS,IAC/DG,EAASH,EAAU,QAQnB,WAAYA,EAEVA,EAAU,OAAO,YAAY,IAAM,aAAa,YAAY,EAC9DI,EAAS,aAEAJ,EAAU,OAAO,YAAY,IAAM,WAAW,YAAY,GACnEI,EAAS,WAETD,EAASF,GAGTG,EAASF,EAGXE,EAASF,IAMXC,EAAS,OACTC,EAAS,QAGJ,CAAE,OAAAD,EAAQ,OAAAC,CAAO,CAC1B,EAEaC,EAAe,IAAM,CAEhC,IAAMC,EADM,OAAO,WAAW,8BAA8B,EAC/B,QAAU,OAAS,QAE5CC,EACAC,EACAC,EAAe,QAEnB,GAAI,CACFF,EAAsB,aAAa,QAAQ,sBAAsB,CACnE,MAAgB,CACd,QAAQ,IACN,6FACF,CACF,CAEI,OAAOA,GAAwB,SACjCC,EAAYD,EAEZC,EAAYC,IAAiB,SAAWH,EAAmBG,EAGzDD,GACF,SAAS,gBAAgB,MAAM,YAC7B,yBACAA,CACF,CAEJ,ED3EO,IAAME,EAAc,CACzBC,EACAC,IACG,CACH,GAAM,CAAE,OAAQZ,CAAU,EAAIY,EAAQ,QAChC,CAAE,OAAAT,EAAQ,OAAAC,CAAO,EAAIL,EAAUC,CAAS,EACxC,CAAC,CAAE,MAAAa,CAAM,EAAGC,CAAa,EAAIhB,EAAW,EACxCiB,EAAWH,EAAQ,WAAa,OAChCI,EAAmB,CACvB,MAAO,kBACP,KAAM,gBACR,EAGA,OAAKD,IAECX,IAAW,cAEbP,EAAU,IAAM,CACd,IAAMoB,EAAa,OAAO,aAAa,QAAQ,YAAY,EACvDA,EAGFH,EAAc,CAAE,MAAOG,CAAW,CAAC,EAI/Bd,GAAUA,EAAO,OAAS,GAC5BW,EAAc,CAAE,MAAOX,EAAO,CAAC,CAAE,CAAC,CAGxC,EAAG,CAAC,CAAC,EAGLN,EAAU,IAAM,CACVgB,IACF,SAAS,gBAAgB,aAAa,aAAcA,CAAK,EACzD,OAAO,aAAa,QAAQ,aAAcA,CAAK,EAKnD,EAAG,CAACA,CAAK,CAAC,GACDT,IAAW,aAGpBP,EAAU,IAAM,CAEdQ,EAAa,CACf,EAAG,CAAC,CAAC,EAGLR,EAAU,IAAM,CACVgB,IAGF,SAAS,gBAAgB,QAAQ,MAAQA,EACzC,SAAS,gBAAgB,MAAM,YAAcA,EAC7C,SAAS,KAAK,UACX,IACCA,IAAU,QACNG,EAAiB,MACjBA,EAAiB,IACvB,EACF,SAAS,KAAK,UACX,OACCH,IAAU,QACNG,EAAiB,KACjBA,EAAiB,KACvB,EACF,aAAa,QAAQ,uBAAwBH,CAAK,EAItD,EAAG,CAACA,CAAK,CAAC,IAIPF,EAAQ,CACjB,EErEA,IAAMO,EAAwC,CAC5C,WAAY,CAACR,CAAW,EACxB,QAAS,CACP,MAAO,EACT,CACF,EAEOS,EAAQD","sourcesContent":["import { useEffect, useGlobals } from \"@storybook/preview-api\";\nimport { getThemes, setColorMode } from \"./utils\";\n\nimport type {\n Renderer,\n PartialStoryFn as StoryFunction,\n StoryContext,\n} from \"@storybook/types\";\n\nexport const withGlobals = (\n StoryFn: StoryFunction<Renderer>,\n context: StoryContext<Renderer>,\n) => {\n const { themes: themesObj } = context.globals;\n const { themes, method } = getThemes(themesObj);\n const [{ theme }, updateGlobals] = useGlobals();\n const isInDocs = context.viewMode === \"docs\";\n const chakraClassNames = {\n light: \"chakra-ui-light\",\n dark: \"chakra-ui-dark\",\n };\n\n // disable addon on doc\n if (!isInDocs) {\n // if method is \"data-theme\"\n if (method === \"data-theme\") {\n // only the first render\n useEffect(() => {\n const savedTheme = window.localStorage.getItem(\"data-theme\");\n if (savedTheme) {\n // this function triggers useEffect hook to update data-theme attribute\n // and save it to local storage\n updateGlobals({ theme: savedTheme });\n } else {\n // handle data-theme === undefined case\n // default set it to the first theme\n if (themes && themes.length > 0) {\n updateGlobals({ theme: themes[0] });\n }\n }\n }, []);\n\n // whenever theme changes\n useEffect(() => {\n if (theme) {\n document.documentElement.setAttribute(\"data-theme\", theme);\n window.localStorage.setItem(\"data-theme\", theme);\n\n // DEBUG: debug purpose message\n // console.log(\"theme changed to: \", theme);\n }\n }, [theme]);\n } else if (method === \"ChakraUI\") {\n // TODO: implement this\n // only the first render\n useEffect(() => {\n // set color mode from local storage\n setColorMode();\n }, []);\n\n // whenever theme changes\n useEffect(() => {\n if (theme) {\n // document.documentElement.setAttribute(\"data-theme\", theme);\n // document.documentElement.style.setProperty(\"color-scheme\", theme);\n document.documentElement.dataset.theme = theme;\n document.documentElement.style.colorScheme = theme;\n document.body.classList // .getElementsByClassName(\"sb-main-padded sb-show-main\")[0]\n .add(\n theme === \"light\"\n ? chakraClassNames.light\n : chakraClassNames.dark,\n );\n document.body.classList // .getElementsByClassName(\"sb-main-padded sb-show-main\")[0]\n .remove(\n theme === \"light\"\n ? chakraClassNames.dark\n : chakraClassNames.light,\n );\n localStorage.setItem(\"chakra-ui-color-mode\", theme);\n // DEBUG: debug purpose message\n // console.log(\"theme changed to: \", theme);\n }\n }, [theme]);\n }\n }\n\n return StoryFn()\n};\n","export const getThemes = (\n themesObj: { themes?: Array<string>; method?: string } | Array<string>,\n) => {\n // default values\n let defaultThemes: string[] = [\"light\", \"dark\"];\n let defaultMethod: \"data-theme\" = \"data-theme\";\n let themes: string[] | undefined = undefined;\n let method: \"data-theme\" | \"ChakraUI\" | undefined = undefined;\n\n // backward compatibility\n // handle themes is an array case\n if (Array.isArray(themesObj) && themesObj.length > 0) {\n themes = themesObj;\n // old behavior\n method = \"data-theme\";\n // expected case\n // handle themes is an object case\n } else if (typeof themesObj === \"object\") {\n // handle themes\n if (\"themes\" in themesObj) {\n if (Array.isArray(themesObj.themes) && themesObj.themes.length > 0) {\n themes = themesObj.themes;\n }\n // else {\n // themes = undefined;\n // }\n }\n\n // handle method\n if (\"method\" in themesObj) {\n // case insensitive comparison\n if (themesObj.method.toUpperCase() === \"data-theme\".toUpperCase()) {\n method = \"data-theme\";\n // case insensitive comparison\n } else if (themesObj.method.toUpperCase() === \"ChakraUI\".toUpperCase()) {\n method = \"ChakraUI\";\n // ChakraUI accpets only \"light\" and \"dark\" themes\n themes = defaultThemes;\n } else {\n // use \"data-theme\" method if not specified\n method = defaultMethod;\n }\n } else {\n method = defaultMethod;\n }\n }\n\n // otherwise undefined\n else {\n themes = undefined;\n method = undefined;\n }\n\n return { themes, method };\n};\n\nexport const setColorMode = () => {\n const mql = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const systemPreference = mql.matches ? \"dark\" : \"light\";\n\n let persistedPreference;\n let colorMode;\n let initialValue = \"light\";\n\n try {\n persistedPreference = localStorage.getItem(\"chakra-ui-color-mode\");\n } catch (error) {\n console.log(\n \"Chakra UI: localStorage is not available. Color mode persistence might not work as expected\",\n );\n }\n\n if (typeof persistedPreference === \"string\") {\n colorMode = persistedPreference;\n } else {\n colorMode = initialValue === \"system\" ? systemPreference : initialValue;\n }\n\n if (colorMode) {\n document.documentElement.style.setProperty(\n \"--chakra-ui-color-mode\",\n colorMode,\n );\n }\n};\n","/**\n * A decorator is a way to wrap a story in extra “rendering” functionality. Many addons define decorators\n * in order to augment stories:\n * - with extra rendering\n * - gather details about how a story is rendered\n *\n * When writing stories, decorators are typically used to wrap stories with extra markup or context mocking.\n *\n * https://storybook.js.org/docs/react/writing-stories/decorators\n */\nimport type { Renderer, ProjectAnnotations } from \"@storybook/types\";\nimport { withGlobals } from \"./withGlobals\";\nimport withChakra from \"./withChakra\";\n\n/**\n * Note: if you want to use JSX in this file, rename it to `preview.tsx`\n * and update the entry prop in tsup.config.ts to use \"src/preview.tsx\",\n */\n\nconst preview: ProjectAnnotations<Renderer> = {\n decorators: [withGlobals],\n globals: {\n theme: \"\",\n },\n};\n\nexport default preview;\n"]}