@wise/components-theming 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,6 @@ import type { Theming } from './const';
3
3
  type ThemeProviderProps = PropsWithChildren<Theming> & {
4
4
  className?: string;
5
5
  };
6
- export declare const ThemeProvider: ({ theme, screenMode, isNotRootProvider, children, className, }: ThemeProviderProps) => import("react").JSX.Element;
6
+ export declare const ThemeProvider: ({ theme: initialTheme, screenMode: initialScreenMode, isNotRootProvider, children, className, }: ThemeProviderProps) => import("react").JSX.Element;
7
7
  export {};
8
8
  //# sourceMappingURL=ThemeProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../src/ThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAkC,MAAM,OAAO,CAAC;AAG1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAKvC,KAAK,kBAAkB,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAK9E,eAAO,MAAM,aAAa,GAAI,gEAM3B,kBAAkB,gCAyBpB,CAAC"}
1
+ {"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../src/ThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA4C,MAAM,OAAO,CAAC;AAGpF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAKvC,KAAK,kBAAkB,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAK9E,eAAO,MAAM,aAAa,GAAI,iGAM3B,kBAAkB,gCA8BpB,CAAC"}
@@ -9,13 +9,15 @@ var jsxRuntime = require('react/jsx-runtime');
9
9
 
10
10
  const themeClass = /\bnp-theme-[a-z-]+\b/g;
11
11
  const ThemeProvider = ({
12
- theme = _const.DEFAULT_BASE_THEME,
13
- screenMode = _const.DEFAULT_SCREEN_MODE,
12
+ theme: initialTheme = _const.DEFAULT_BASE_THEME,
13
+ screenMode: initialScreenMode = _const.DEFAULT_SCREEN_MODE,
14
14
  isNotRootProvider = false,
15
15
  children,
16
16
  className = undefined
17
17
  }) => {
18
18
  const isContextRoot = react.useContext(ThemeProviderContext.ThemeContext) === undefined;
19
+ const [theme, setTheme] = react.useState(initialTheme);
20
+ const [screenMode, setScreenMode] = react.useState(initialScreenMode);
19
21
  // useEffect hook used to apply the theme class to the HTML element
20
22
  react.useEffect(() => {
21
23
  if (!isNotRootProvider && isContextRoot) {
@@ -30,8 +32,10 @@ const ThemeProvider = ({
30
32
  }, [isNotRootProvider, isContextRoot, theme, screenMode]);
31
33
  const contextValue = react.useMemo(() => ({
32
34
  theme,
33
- screenMode
34
- }), [screenMode, theme]);
35
+ screenMode,
36
+ setTheme,
37
+ setScreenMode
38
+ }), [theme, screenMode, setTheme, setScreenMode]);
35
39
  return /*#__PURE__*/jsxRuntime.jsx(ThemeProviderContext.ThemeContext.Provider, {
36
40
  value: contextValue,
37
41
  children: /*#__PURE__*/jsxRuntime.jsx(ThemedChildren.ThemedChildren, {
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.js","sources":["../src/ThemeProvider.tsx"],"sourcesContent":["import { PropsWithChildren, useContext, useEffect, useMemo } from 'react';\n\nimport { ThemedChildren } from './ThemedChildren';\nimport type { Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { getThemeClassName } from './helpers';\nimport { ThemeContext } from './ThemeProviderContext';\n\ntype ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };\n\n// RegEx to check for `np-theme-` class name\nconst themeClass = /\\bnp-theme-[a-z-]+\\b/g;\n\nexport const ThemeProvider = ({\n theme = DEFAULT_BASE_THEME,\n screenMode = DEFAULT_SCREEN_MODE,\n isNotRootProvider = false,\n children,\n className = undefined,\n}: ThemeProviderProps) => {\n const isContextRoot = useContext(ThemeContext) === undefined;\n\n // useEffect hook used to apply the theme class to the HTML element\n useEffect(() => {\n if (!isNotRootProvider && isContextRoot) {\n // Remove all the theme classes from the documentElement\n document.documentElement.className.match(themeClass)?.forEach((item) => {\n document.documentElement.classList.remove(item);\n });\n getThemeClassName(theme, screenMode)\n .split(' ')\n .forEach((item) => {\n document.documentElement.classList.add(item);\n });\n }\n }, [isNotRootProvider, isContextRoot, theme, screenMode]);\n\n const contextValue = useMemo(() => ({ theme, screenMode }), [screenMode, theme]);\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemedChildren className={className}>{children}</ThemedChildren>\n </ThemeContext.Provider>\n );\n};\n"],"names":["themeClass","ThemeProvider","theme","DEFAULT_BASE_THEME","screenMode","DEFAULT_SCREEN_MODE","isNotRootProvider","children","className","undefined","isContextRoot","useContext","ThemeContext","useEffect","document","documentElement","match","forEach","item","classList","remove","getThemeClassName","split","add","contextValue","useMemo","_jsx","Provider","value","ThemedChildren"],"mappings":";;;;;;;;;AAWA,MAAMA,UAAU,GAAG,uBAAuB;AAEnC,MAAMC,aAAa,GAAGA,CAAC;AAC5BC,EAAAA,KAAK,GAAGC,yBAAkB;AAC1BC,EAAAA,UAAU,GAAGC,0BAAmB;AAChCC,EAAAA,iBAAiB,GAAG,KAAK;EACzBC,QAAQ;AACRC,EAAAA,SAAS,GAAGC;AAAS,CACF,KAAI;AACvB,EAAA,MAAMC,aAAa,GAAGC,gBAAU,CAACC,iCAAY,CAAC,KAAKH,SAAS;AAE5D;AACAI,EAAAA,eAAS,CAAC,MAAK;AACb,IAAA,IAAI,CAACP,iBAAiB,IAAII,aAAa,EAAE;AACvC;AACAI,MAAAA,QAAQ,CAACC,eAAe,CAACP,SAAS,CAACQ,KAAK,CAAChB,UAAU,CAAC,EAAEiB,OAAO,CAAEC,IAAI,IAAI;QACrEJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACC,MAAM,CAACF,IAAI,CAAC;AACjD,MAAA,CAAC,CAAC;AACFG,MAAAA,yBAAiB,CAACnB,KAAK,EAAEE,UAAU,CAAC,CACjCkB,KAAK,CAAC,GAAG,CAAC,CACVL,OAAO,CAAEC,IAAI,IAAI;QAChBJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACI,GAAG,CAACL,IAAI,CAAC;AAC9C,MAAA,CAAC,CAAC;AACN,IAAA;EACF,CAAC,EAAE,CAACZ,iBAAiB,EAAEI,aAAa,EAAER,KAAK,EAAEE,UAAU,CAAC,CAAC;AAEzD,EAAA,MAAMoB,YAAY,GAAGC,aAAO,CAAC,OAAO;IAAEvB,KAAK;AAAEE,IAAAA;AAAU,GAAE,CAAC,EAAE,CAACA,UAAU,EAAEF,KAAK,CAAC,CAAC;AAEhF,EAAA,oBACEwB,cAAA,CAACd,iCAAY,CAACe,QAAQ,EAAA;AAACC,IAAAA,KAAK,EAAEJ,YAAa;IAAAjB,QAAA,eACzCmB,cAAA,CAACG,6BAAc,EAAA;AAACrB,MAAAA,SAAS,EAAEA,SAAU;AAAAD,MAAAA,QAAA,EAAEA;KAAyB;AAClE,GAAuB,CAAC;AAE5B;;;;"}
1
+ {"version":3,"file":"ThemeProvider.js","sources":["../src/ThemeProvider.tsx"],"sourcesContent":["import { PropsWithChildren, useContext, useEffect, useMemo, useState } from 'react';\n\nimport { ThemedChildren } from './ThemedChildren';\nimport type { Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { getThemeClassName } from './helpers';\nimport { ThemeContext } from './ThemeProviderContext';\n\ntype ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };\n\n// RegEx to check for `np-theme-` class name\nconst themeClass = /\\bnp-theme-[a-z-]+\\b/g;\n\nexport const ThemeProvider = ({\n theme: initialTheme = DEFAULT_BASE_THEME,\n screenMode: initialScreenMode = DEFAULT_SCREEN_MODE,\n isNotRootProvider = false,\n children,\n className = undefined,\n}: ThemeProviderProps) => {\n const isContextRoot = useContext(ThemeContext) === undefined;\n const [theme, setTheme] = useState(initialTheme);\n const [screenMode, setScreenMode] = useState(initialScreenMode);\n\n // useEffect hook used to apply the theme class to the HTML element\n useEffect(() => {\n if (!isNotRootProvider && isContextRoot) {\n // Remove all the theme classes from the documentElement\n document.documentElement.className.match(themeClass)?.forEach((item) => {\n document.documentElement.classList.remove(item);\n });\n getThemeClassName(theme, screenMode)\n .split(' ')\n .forEach((item) => {\n document.documentElement.classList.add(item);\n });\n }\n }, [isNotRootProvider, isContextRoot, theme, screenMode]);\n\n const contextValue = useMemo(\n () => ({ theme, screenMode, setTheme, setScreenMode }),\n [theme, screenMode, setTheme, setScreenMode],\n );\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemedChildren className={className}>{children}</ThemedChildren>\n </ThemeContext.Provider>\n );\n};\n"],"names":["themeClass","ThemeProvider","theme","initialTheme","DEFAULT_BASE_THEME","screenMode","initialScreenMode","DEFAULT_SCREEN_MODE","isNotRootProvider","children","className","undefined","isContextRoot","useContext","ThemeContext","setTheme","useState","setScreenMode","useEffect","document","documentElement","match","forEach","item","classList","remove","getThemeClassName","split","add","contextValue","useMemo","_jsx","Provider","value","ThemedChildren"],"mappings":";;;;;;;;;AAWA,MAAMA,UAAU,GAAG,uBAAuB;AAEnC,MAAMC,aAAa,GAAGA,CAAC;EAC5BC,KAAK,EAAEC,YAAY,GAAGC,yBAAkB;EACxCC,UAAU,EAAEC,iBAAiB,GAAGC,0BAAmB;AACnDC,EAAAA,iBAAiB,GAAG,KAAK;EACzBC,QAAQ;AACRC,EAAAA,SAAS,GAAGC;AAAS,CACF,KAAI;AACvB,EAAA,MAAMC,aAAa,GAAGC,gBAAU,CAACC,iCAAY,CAAC,KAAKH,SAAS;EAC5D,MAAM,CAACT,KAAK,EAAEa,QAAQ,CAAC,GAAGC,cAAQ,CAACb,YAAY,CAAC;EAChD,MAAM,CAACE,UAAU,EAAEY,aAAa,CAAC,GAAGD,cAAQ,CAACV,iBAAiB,CAAC;AAE/D;AACAY,EAAAA,eAAS,CAAC,MAAK;AACb,IAAA,IAAI,CAACV,iBAAiB,IAAII,aAAa,EAAE;AACvC;AACAO,MAAAA,QAAQ,CAACC,eAAe,CAACV,SAAS,CAACW,KAAK,CAACrB,UAAU,CAAC,EAAEsB,OAAO,CAAEC,IAAI,IAAI;QACrEJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACC,MAAM,CAACF,IAAI,CAAC;AACjD,MAAA,CAAC,CAAC;AACFG,MAAAA,yBAAiB,CAACxB,KAAK,EAAEG,UAAU,CAAC,CACjCsB,KAAK,CAAC,GAAG,CAAC,CACVL,OAAO,CAAEC,IAAI,IAAI;QAChBJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACI,GAAG,CAACL,IAAI,CAAC;AAC9C,MAAA,CAAC,CAAC;AACN,IAAA;EACF,CAAC,EAAE,CAACf,iBAAiB,EAAEI,aAAa,EAAEV,KAAK,EAAEG,UAAU,CAAC,CAAC;AAEzD,EAAA,MAAMwB,YAAY,GAAGC,aAAO,CAC1B,OAAO;IAAE5B,KAAK;IAAEG,UAAU;IAAEU,QAAQ;AAAEE,IAAAA;GAAe,CAAC,EACtD,CAACf,KAAK,EAAEG,UAAU,EAAEU,QAAQ,EAAEE,aAAa,CAAC,CAC7C;AAED,EAAA,oBACEc,cAAA,CAACjB,iCAAY,CAACkB,QAAQ,EAAA;AAACC,IAAAA,KAAK,EAAEJ,YAAa;IAAApB,QAAA,eACzCsB,cAAA,CAACG,6BAAc,EAAA;AAACxB,MAAAA,SAAS,EAAEA,SAAU;AAAAD,MAAAA,QAAA,EAAEA;KAAyB;AAClE,GAAuB,CAAC;AAE5B;;;;"}
@@ -1,4 +1,4 @@
1
- import { useContext, useEffect, useMemo } from 'react';
1
+ import { useContext, useState, useEffect, useMemo } from 'react';
2
2
  import { ThemedChildren } from './ThemedChildren.mjs';
3
3
  import { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const.mjs';
4
4
  import { getThemeClassName } from './helpers.mjs';
@@ -7,13 +7,15 @@ import { jsx } from 'react/jsx-runtime';
7
7
 
8
8
  const themeClass = /\bnp-theme-[a-z-]+\b/g;
9
9
  const ThemeProvider = ({
10
- theme = DEFAULT_BASE_THEME,
11
- screenMode = DEFAULT_SCREEN_MODE,
10
+ theme: initialTheme = DEFAULT_BASE_THEME,
11
+ screenMode: initialScreenMode = DEFAULT_SCREEN_MODE,
12
12
  isNotRootProvider = false,
13
13
  children,
14
14
  className = undefined
15
15
  }) => {
16
16
  const isContextRoot = useContext(ThemeContext) === undefined;
17
+ const [theme, setTheme] = useState(initialTheme);
18
+ const [screenMode, setScreenMode] = useState(initialScreenMode);
17
19
  // useEffect hook used to apply the theme class to the HTML element
18
20
  useEffect(() => {
19
21
  if (!isNotRootProvider && isContextRoot) {
@@ -28,8 +30,10 @@ const ThemeProvider = ({
28
30
  }, [isNotRootProvider, isContextRoot, theme, screenMode]);
29
31
  const contextValue = useMemo(() => ({
30
32
  theme,
31
- screenMode
32
- }), [screenMode, theme]);
33
+ screenMode,
34
+ setTheme,
35
+ setScreenMode
36
+ }), [theme, screenMode, setTheme, setScreenMode]);
33
37
  return /*#__PURE__*/jsx(ThemeContext.Provider, {
34
38
  value: contextValue,
35
39
  children: /*#__PURE__*/jsx(ThemedChildren, {
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.mjs","sources":["../src/ThemeProvider.tsx"],"sourcesContent":["import { PropsWithChildren, useContext, useEffect, useMemo } from 'react';\n\nimport { ThemedChildren } from './ThemedChildren';\nimport type { Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { getThemeClassName } from './helpers';\nimport { ThemeContext } from './ThemeProviderContext';\n\ntype ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };\n\n// RegEx to check for `np-theme-` class name\nconst themeClass = /\\bnp-theme-[a-z-]+\\b/g;\n\nexport const ThemeProvider = ({\n theme = DEFAULT_BASE_THEME,\n screenMode = DEFAULT_SCREEN_MODE,\n isNotRootProvider = false,\n children,\n className = undefined,\n}: ThemeProviderProps) => {\n const isContextRoot = useContext(ThemeContext) === undefined;\n\n // useEffect hook used to apply the theme class to the HTML element\n useEffect(() => {\n if (!isNotRootProvider && isContextRoot) {\n // Remove all the theme classes from the documentElement\n document.documentElement.className.match(themeClass)?.forEach((item) => {\n document.documentElement.classList.remove(item);\n });\n getThemeClassName(theme, screenMode)\n .split(' ')\n .forEach((item) => {\n document.documentElement.classList.add(item);\n });\n }\n }, [isNotRootProvider, isContextRoot, theme, screenMode]);\n\n const contextValue = useMemo(() => ({ theme, screenMode }), [screenMode, theme]);\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemedChildren className={className}>{children}</ThemedChildren>\n </ThemeContext.Provider>\n );\n};\n"],"names":["themeClass","ThemeProvider","theme","DEFAULT_BASE_THEME","screenMode","DEFAULT_SCREEN_MODE","isNotRootProvider","children","className","undefined","isContextRoot","useContext","ThemeContext","useEffect","document","documentElement","match","forEach","item","classList","remove","getThemeClassName","split","add","contextValue","useMemo","_jsx","Provider","value","ThemedChildren"],"mappings":";;;;;;;AAWA,MAAMA,UAAU,GAAG,uBAAuB;AAEnC,MAAMC,aAAa,GAAGA,CAAC;AAC5BC,EAAAA,KAAK,GAAGC,kBAAkB;AAC1BC,EAAAA,UAAU,GAAGC,mBAAmB;AAChCC,EAAAA,iBAAiB,GAAG,KAAK;EACzBC,QAAQ;AACRC,EAAAA,SAAS,GAAGC;AAAS,CACF,KAAI;AACvB,EAAA,MAAMC,aAAa,GAAGC,UAAU,CAACC,YAAY,CAAC,KAAKH,SAAS;AAE5D;AACAI,EAAAA,SAAS,CAAC,MAAK;AACb,IAAA,IAAI,CAACP,iBAAiB,IAAII,aAAa,EAAE;AACvC;AACAI,MAAAA,QAAQ,CAACC,eAAe,CAACP,SAAS,CAACQ,KAAK,CAAChB,UAAU,CAAC,EAAEiB,OAAO,CAAEC,IAAI,IAAI;QACrEJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACC,MAAM,CAACF,IAAI,CAAC;AACjD,MAAA,CAAC,CAAC;AACFG,MAAAA,iBAAiB,CAACnB,KAAK,EAAEE,UAAU,CAAC,CACjCkB,KAAK,CAAC,GAAG,CAAC,CACVL,OAAO,CAAEC,IAAI,IAAI;QAChBJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACI,GAAG,CAACL,IAAI,CAAC;AAC9C,MAAA,CAAC,CAAC;AACN,IAAA;EACF,CAAC,EAAE,CAACZ,iBAAiB,EAAEI,aAAa,EAAER,KAAK,EAAEE,UAAU,CAAC,CAAC;AAEzD,EAAA,MAAMoB,YAAY,GAAGC,OAAO,CAAC,OAAO;IAAEvB,KAAK;AAAEE,IAAAA;AAAU,GAAE,CAAC,EAAE,CAACA,UAAU,EAAEF,KAAK,CAAC,CAAC;AAEhF,EAAA,oBACEwB,GAAA,CAACd,YAAY,CAACe,QAAQ,EAAA;AAACC,IAAAA,KAAK,EAAEJ,YAAa;IAAAjB,QAAA,eACzCmB,GAAA,CAACG,cAAc,EAAA;AAACrB,MAAAA,SAAS,EAAEA,SAAU;AAAAD,MAAAA,QAAA,EAAEA;KAAyB;AAClE,GAAuB,CAAC;AAE5B;;;;"}
1
+ {"version":3,"file":"ThemeProvider.mjs","sources":["../src/ThemeProvider.tsx"],"sourcesContent":["import { PropsWithChildren, useContext, useEffect, useMemo, useState } from 'react';\n\nimport { ThemedChildren } from './ThemedChildren';\nimport type { Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { getThemeClassName } from './helpers';\nimport { ThemeContext } from './ThemeProviderContext';\n\ntype ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };\n\n// RegEx to check for `np-theme-` class name\nconst themeClass = /\\bnp-theme-[a-z-]+\\b/g;\n\nexport const ThemeProvider = ({\n theme: initialTheme = DEFAULT_BASE_THEME,\n screenMode: initialScreenMode = DEFAULT_SCREEN_MODE,\n isNotRootProvider = false,\n children,\n className = undefined,\n}: ThemeProviderProps) => {\n const isContextRoot = useContext(ThemeContext) === undefined;\n const [theme, setTheme] = useState(initialTheme);\n const [screenMode, setScreenMode] = useState(initialScreenMode);\n\n // useEffect hook used to apply the theme class to the HTML element\n useEffect(() => {\n if (!isNotRootProvider && isContextRoot) {\n // Remove all the theme classes from the documentElement\n document.documentElement.className.match(themeClass)?.forEach((item) => {\n document.documentElement.classList.remove(item);\n });\n getThemeClassName(theme, screenMode)\n .split(' ')\n .forEach((item) => {\n document.documentElement.classList.add(item);\n });\n }\n }, [isNotRootProvider, isContextRoot, theme, screenMode]);\n\n const contextValue = useMemo(\n () => ({ theme, screenMode, setTheme, setScreenMode }),\n [theme, screenMode, setTheme, setScreenMode],\n );\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemedChildren className={className}>{children}</ThemedChildren>\n </ThemeContext.Provider>\n );\n};\n"],"names":["themeClass","ThemeProvider","theme","initialTheme","DEFAULT_BASE_THEME","screenMode","initialScreenMode","DEFAULT_SCREEN_MODE","isNotRootProvider","children","className","undefined","isContextRoot","useContext","ThemeContext","setTheme","useState","setScreenMode","useEffect","document","documentElement","match","forEach","item","classList","remove","getThemeClassName","split","add","contextValue","useMemo","_jsx","Provider","value","ThemedChildren"],"mappings":";;;;;;;AAWA,MAAMA,UAAU,GAAG,uBAAuB;AAEnC,MAAMC,aAAa,GAAGA,CAAC;EAC5BC,KAAK,EAAEC,YAAY,GAAGC,kBAAkB;EACxCC,UAAU,EAAEC,iBAAiB,GAAGC,mBAAmB;AACnDC,EAAAA,iBAAiB,GAAG,KAAK;EACzBC,QAAQ;AACRC,EAAAA,SAAS,GAAGC;AAAS,CACF,KAAI;AACvB,EAAA,MAAMC,aAAa,GAAGC,UAAU,CAACC,YAAY,CAAC,KAAKH,SAAS;EAC5D,MAAM,CAACT,KAAK,EAAEa,QAAQ,CAAC,GAAGC,QAAQ,CAACb,YAAY,CAAC;EAChD,MAAM,CAACE,UAAU,EAAEY,aAAa,CAAC,GAAGD,QAAQ,CAACV,iBAAiB,CAAC;AAE/D;AACAY,EAAAA,SAAS,CAAC,MAAK;AACb,IAAA,IAAI,CAACV,iBAAiB,IAAII,aAAa,EAAE;AACvC;AACAO,MAAAA,QAAQ,CAACC,eAAe,CAACV,SAAS,CAACW,KAAK,CAACrB,UAAU,CAAC,EAAEsB,OAAO,CAAEC,IAAI,IAAI;QACrEJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACC,MAAM,CAACF,IAAI,CAAC;AACjD,MAAA,CAAC,CAAC;AACFG,MAAAA,iBAAiB,CAACxB,KAAK,EAAEG,UAAU,CAAC,CACjCsB,KAAK,CAAC,GAAG,CAAC,CACVL,OAAO,CAAEC,IAAI,IAAI;QAChBJ,QAAQ,CAACC,eAAe,CAACI,SAAS,CAACI,GAAG,CAACL,IAAI,CAAC;AAC9C,MAAA,CAAC,CAAC;AACN,IAAA;EACF,CAAC,EAAE,CAACf,iBAAiB,EAAEI,aAAa,EAAEV,KAAK,EAAEG,UAAU,CAAC,CAAC;AAEzD,EAAA,MAAMwB,YAAY,GAAGC,OAAO,CAC1B,OAAO;IAAE5B,KAAK;IAAEG,UAAU;IAAEU,QAAQ;AAAEE,IAAAA;GAAe,CAAC,EACtD,CAACf,KAAK,EAAEG,UAAU,EAAEU,QAAQ,EAAEE,aAAa,CAAC,CAC7C;AAED,EAAA,oBACEc,GAAA,CAACjB,YAAY,CAACkB,QAAQ,EAAA;AAACC,IAAAA,KAAK,EAAEJ,YAAa;IAAApB,QAAA,eACzCsB,GAAA,CAACG,cAAc,EAAA;AAACxB,MAAAA,SAAS,EAAEA,SAAU;AAAAD,MAAAA,QAAA,EAAEA;KAAyB;AAClE,GAAuB,CAAC;AAE5B;;;;"}
@@ -2,5 +2,7 @@ import type { ScreenMode, Theming } from './const';
2
2
  export declare const ThemeContext: import("react").Context<{
3
3
  theme: NonNullable<Theming["theme"]>;
4
4
  screenMode: ScreenMode;
5
+ setTheme: (theme: NonNullable<Theming["theme"]>) => void;
6
+ setScreenMode: (screenMode: ScreenMode) => void;
5
7
  } | undefined>;
6
8
  //# sourceMappingURL=ThemeProviderContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProviderContext.d.ts","sourceRoot":"","sources":["../src/ThemeProviderContext.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEnD,eAAO,MAAM,YAAY;WAEZ,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACxB,UAAU;cAGhB,CAAC"}
1
+ {"version":3,"file":"ThemeProviderContext.d.ts","sourceRoot":"","sources":["../src/ThemeProviderContext.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEnD,eAAO,MAAM,YAAY;WAEZ,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACxB,UAAU;cACZ,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI;mBACzC,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI;cAGzC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProviderContext.js","sources":["../src/ThemeProviderContext.tsx"],"sourcesContent":["import { createContext } from 'react';\nimport type { ScreenMode, Theming } from './const';\n\nexport const ThemeContext = createContext<\n | {\n theme: NonNullable<Theming['theme']>;\n screenMode: ScreenMode;\n }\n | undefined\n>(undefined);\n"],"names":["ThemeContext","createContext","undefined"],"mappings":";;;;MAGaA,YAAY,gBAAGC,mBAAa,CAMvCC,SAAS;;;;"}
1
+ {"version":3,"file":"ThemeProviderContext.js","sources":["../src/ThemeProviderContext.tsx"],"sourcesContent":["import { createContext } from 'react';\nimport type { ScreenMode, Theming } from './const';\n\nexport const ThemeContext = createContext<\n | {\n theme: NonNullable<Theming['theme']>;\n screenMode: ScreenMode;\n setTheme: (theme: NonNullable<Theming['theme']>) => void;\n setScreenMode: (screenMode: ScreenMode) => void;\n }\n | undefined\n>(undefined);\n"],"names":["ThemeContext","createContext","undefined"],"mappings":";;;;MAGaA,YAAY,gBAAGC,mBAAa,CAQvCC,SAAS;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProviderContext.mjs","sources":["../src/ThemeProviderContext.tsx"],"sourcesContent":["import { createContext } from 'react';\nimport type { ScreenMode, Theming } from './const';\n\nexport const ThemeContext = createContext<\n | {\n theme: NonNullable<Theming['theme']>;\n screenMode: ScreenMode;\n }\n | undefined\n>(undefined);\n"],"names":["ThemeContext","createContext","undefined"],"mappings":";;MAGaA,YAAY,gBAAGC,aAAa,CAMvCC,SAAS;;;;"}
1
+ {"version":3,"file":"ThemeProviderContext.mjs","sources":["../src/ThemeProviderContext.tsx"],"sourcesContent":["import { createContext } from 'react';\nimport type { ScreenMode, Theming } from './const';\n\nexport const ThemeContext = createContext<\n | {\n theme: NonNullable<Theming['theme']>;\n screenMode: ScreenMode;\n setTheme: (theme: NonNullable<Theming['theme']>) => void;\n setScreenMode: (screenMode: ScreenMode) => void;\n }\n | undefined\n>(undefined);\n"],"names":["ThemeContext","createContext","undefined"],"mappings":";;MAGaA,YAAY,gBAAGC,aAAa,CAQvCC,SAAS;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,OAAO,EACR,MAAM,SAAS,CAAC;AAGjB,eAAO,MAAM,aAAa,GAAI,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAG,KAAK,IAAI,WACjC,CAAC;AAE9C,eAAO,MAAM,YAAY,GAAI,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAG,KAAK,IAAI,UAClC,CAAC;AAE5C,eAAO,MAAM,kBAAkB,GAC7B,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KACnC,KAAK,IAAI,gBAA4C,CAAC;AAEzD,eAAO,MAAM,gBAAgB,GAC3B,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EACpC,YAAY,UAAU,KACrB,UAAU,IAAI,cACqD,CAAC;AAEvE,eAAO,MAAM,iBAAiB,GAAI,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,YAAY,UAAU,WAc7F,CAAC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,OAAO,EACR,MAAM,SAAS,CAAC;AAGjB,eAAO,MAAM,aAAa,GAAI,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAG,KAAK,IAAI,WACjC,CAAC;AAE9C,eAAO,MAAM,YAAY,GAAI,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAG,KAAK,IAAI,UAClC,CAAC;AAE5C,eAAO,MAAM,kBAAkB,GAC7B,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KACnC,KAAK,IAAI,gBAA4C,CAAC;AAEzD,eAAO,MAAM,gBAAgB,GAC3B,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EACpC,YAAY,UAAU,KACrB,UAAU,IAAI,cACqD,CAAC;AAEvE,eAAO,MAAM,iBAAiB,GAAI,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,YAAY,UAAU,WAuC7F,CAAC"}
package/dist/helpers.js CHANGED
@@ -7,16 +7,38 @@ const isExtraTheme = theme => _const.extraThemes.includes(theme);
7
7
  const isForestGreenTheme = theme => theme === _const.extraThemes[0];
8
8
  const isScreenModeDark = (theme, screenMode) => isThemeModern(theme) && _const.screenModes[1] === screenMode;
9
9
  const getThemeClassName = (theme, screenMode) => {
10
- if (!isThemeModern(theme)) {
11
- return `np-theme-${theme || 'personal'}`;
10
+ if (['light'].includes(theme)) {
11
+ return `np-theme-${theme}`;
12
12
  }
13
- let classes = `np-theme-${theme === 'business' ? 'business' : 'personal'}`;
14
- if (isExtraTheme(theme)) {
15
- classes += ` ${classes}--${theme}`;
16
- } else if (_const.screenModes[1] === screenMode) {
17
- classes += ` ${classes}--${screenMode}`;
13
+ // Personal light is always there by default
14
+ const themeClasses = ['np-theme-personal'];
15
+ /* eslint-disable functional/immutable-data */
16
+ // Personal dark theme
17
+ if (theme === 'personal' && screenMode === 'dark') {
18
+ themeClasses.push(`np-theme-personal--${screenMode}`);
18
19
  }
19
- return classes;
20
+ // Personal forest-green and bright-green themes
21
+ else if (['forest-green', 'bright-green'].includes(theme)) {
22
+ themeClasses.push(`np-theme-personal--${theme}`);
23
+ }
24
+ // Business light
25
+ else if (theme === 'business') {
26
+ themeClasses.push(`np-theme-business`);
27
+ // Business dark theme
28
+ if (screenMode === 'dark') {
29
+ themeClasses.push(`np-theme-business--${screenMode}`);
30
+ }
31
+ }
32
+ // Business forest-green and bright-green themes
33
+ else if (['business--forest-green', 'business--bright-green'].includes(theme)) {
34
+ themeClasses.push(`np-theme-${theme}`);
35
+ }
36
+ // Platform themes
37
+ else if (theme.startsWith('platform')) {
38
+ themeClasses.push(`np-theme-${theme}`);
39
+ }
40
+ /* eslint-enable functional/immutable-data */
41
+ return themeClasses.join(' ');
20
42
  };
21
43
 
22
44
  exports.getThemeClassName = getThemeClassName;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sources":["../src/helpers.ts"],"sourcesContent":["import type {\n ModernTheme,\n ExtraTheme,\n ForestGreenTheme,\n ScreenMode,\n ScreenModeDark,\n Theming,\n} from './const';\nimport { extraThemes, screenModes, modernThemes } from './const';\n\nexport const isThemeModern = (theme: NonNullable<Theming['theme']>): theme is ModernTheme =>\n modernThemes.includes(theme as ModernTheme);\n\nexport const isExtraTheme = (theme: NonNullable<Theming['theme']>): theme is ExtraTheme =>\n extraThemes.includes(theme as ExtraTheme);\n\nexport const isForestGreenTheme = (\n theme: NonNullable<Theming['theme']>,\n): theme is ForestGreenTheme => theme === extraThemes[0];\n\nexport const isScreenModeDark = (\n theme: NonNullable<Theming['theme']>,\n screenMode: ScreenMode,\n): screenMode is ScreenModeDark =>\n isThemeModern(theme as ModernTheme) && screenModes[1] === screenMode;\n\nexport const getThemeClassName = (theme: NonNullable<Theming['theme']>, screenMode: ScreenMode) => {\n if (!isThemeModern(theme)) {\n return `np-theme-${theme || 'personal'}`;\n }\n\n let classes = `np-theme-${theme === 'business' ? 'business' : 'personal'}`;\n\n if (isExtraTheme(theme)) {\n classes += ` ${classes}--${theme}`;\n } else if (screenModes[1] === screenMode) {\n classes += ` ${classes}--${screenMode}`;\n }\n\n return classes;\n};\n"],"names":["isThemeModern","theme","modernThemes","includes","isExtraTheme","extraThemes","isForestGreenTheme","isScreenModeDark","screenMode","screenModes","getThemeClassName","classes"],"mappings":";;;;AAUO,MAAMA,aAAa,GAAIC,KAAoC,IAChEC,mBAAY,CAACC,QAAQ,CAACF,KAAoB;AAErC,MAAMG,YAAY,GAAIH,KAAoC,IAC/DI,kBAAW,CAACF,QAAQ,CAACF,KAAmB;AAEnC,MAAMK,kBAAkB,GAC7BL,KAAoC,IACNA,KAAK,KAAKI,kBAAW,CAAC,CAAC;MAE1CE,gBAAgB,GAAGA,CAC9BN,KAAoC,EACpCO,UAAsB,KAEtBR,aAAa,CAACC,KAAoB,CAAC,IAAIQ,kBAAW,CAAC,CAAC,CAAC,KAAKD;MAE/CE,iBAAiB,GAAGA,CAACT,KAAoC,EAAEO,UAAsB,KAAI;AAChG,EAAA,IAAI,CAACR,aAAa,CAACC,KAAK,CAAC,EAAE;AACzB,IAAA,OAAO,CAAA,SAAA,EAAYA,KAAK,IAAI,UAAU,CAAA,CAAE;AAC1C,EAAA;EAEA,IAAIU,OAAO,GAAG,CAAA,SAAA,EAAYV,KAAK,KAAK,UAAU,GAAG,UAAU,GAAG,UAAU,CAAA,CAAE;AAE1E,EAAA,IAAIG,YAAY,CAACH,KAAK,CAAC,EAAE;AACvBU,IAAAA,OAAO,IAAI,CAAA,CAAA,EAAIA,OAAO,CAAA,EAAA,EAAKV,KAAK,CAAA,CAAE;EACpC,CAAC,MAAM,IAAIQ,kBAAW,CAAC,CAAC,CAAC,KAAKD,UAAU,EAAE;AACxCG,IAAAA,OAAO,IAAI,CAAA,CAAA,EAAIA,OAAO,CAAA,EAAA,EAAKH,UAAU,CAAA,CAAE;AACzC,EAAA;AAEA,EAAA,OAAOG,OAAO;AAChB;;;;;;;;"}
1
+ {"version":3,"file":"helpers.js","sources":["../src/helpers.ts"],"sourcesContent":["import type {\n ModernTheme,\n ExtraTheme,\n ForestGreenTheme,\n ScreenMode,\n ScreenModeDark,\n Theming,\n} from './const';\nimport { extraThemes, screenModes, modernThemes } from './const';\n\nexport const isThemeModern = (theme: NonNullable<Theming['theme']>): theme is ModernTheme =>\n modernThemes.includes(theme as ModernTheme);\n\nexport const isExtraTheme = (theme: NonNullable<Theming['theme']>): theme is ExtraTheme =>\n extraThemes.includes(theme as ExtraTheme);\n\nexport const isForestGreenTheme = (\n theme: NonNullable<Theming['theme']>,\n): theme is ForestGreenTheme => theme === extraThemes[0];\n\nexport const isScreenModeDark = (\n theme: NonNullable<Theming['theme']>,\n screenMode: ScreenMode,\n): screenMode is ScreenModeDark =>\n isThemeModern(theme as ModernTheme) && screenModes[1] === screenMode;\n\nexport const getThemeClassName = (theme: NonNullable<Theming['theme']>, screenMode: ScreenMode) => {\n if (['light'].includes(theme)) {\n return `np-theme-${theme}`;\n }\n\n // Personal light is always there by default\n const themeClasses = ['np-theme-personal'];\n\n /* eslint-disable functional/immutable-data */\n // Personal dark theme\n if (theme === 'personal' && screenMode === 'dark') {\n themeClasses.push(`np-theme-personal--${screenMode}`);\n }\n\n // Personal forest-green and bright-green themes\n else if (['forest-green', 'bright-green'].includes(theme)) {\n themeClasses.push(`np-theme-personal--${theme}`);\n }\n\n // Business light\n else if (theme === 'business') {\n themeClasses.push(`np-theme-business`);\n // Business dark theme\n if (screenMode === 'dark') {\n themeClasses.push(`np-theme-business--${screenMode}`);\n }\n }\n\n // Business forest-green and bright-green themes\n else if (['business--forest-green', 'business--bright-green'].includes(theme)) {\n themeClasses.push(`np-theme-${theme}`);\n }\n\n // Platform themes\n else if (theme.startsWith('platform')) {\n themeClasses.push(`np-theme-${theme}`);\n }\n /* eslint-enable functional/immutable-data */\n return themeClasses.join(' ');\n};\n"],"names":["isThemeModern","theme","modernThemes","includes","isExtraTheme","extraThemes","isForestGreenTheme","isScreenModeDark","screenMode","screenModes","getThemeClassName","themeClasses","push","startsWith","join"],"mappings":";;;;AAUO,MAAMA,aAAa,GAAIC,KAAoC,IAChEC,mBAAY,CAACC,QAAQ,CAACF,KAAoB;AAErC,MAAMG,YAAY,GAAIH,KAAoC,IAC/DI,kBAAW,CAACF,QAAQ,CAACF,KAAmB;AAEnC,MAAMK,kBAAkB,GAC7BL,KAAoC,IACNA,KAAK,KAAKI,kBAAW,CAAC,CAAC;MAE1CE,gBAAgB,GAAGA,CAC9BN,KAAoC,EACpCO,UAAsB,KAEtBR,aAAa,CAACC,KAAoB,CAAC,IAAIQ,kBAAW,CAAC,CAAC,CAAC,KAAKD;MAE/CE,iBAAiB,GAAGA,CAACT,KAAoC,EAAEO,UAAsB,KAAI;EAChG,IAAI,CAAC,OAAO,CAAC,CAACL,QAAQ,CAACF,KAAK,CAAC,EAAE;IAC7B,OAAO,CAAA,SAAA,EAAYA,KAAK,CAAA,CAAE;AAC5B,EAAA;AAEA;AACA,EAAA,MAAMU,YAAY,GAAG,CAAC,mBAAmB,CAAC;AAE1C;AACA;AACA,EAAA,IAAIV,KAAK,KAAK,UAAU,IAAIO,UAAU,KAAK,MAAM,EAAE;AACjDG,IAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,mBAAA,EAAsBJ,UAAU,EAAE,CAAC;AACvD,EAAA;AAEA;OACK,IAAI,CAAC,cAAc,EAAE,cAAc,CAAC,CAACL,QAAQ,CAACF,KAAK,CAAC,EAAE;AACzDU,IAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,mBAAA,EAAsBX,KAAK,EAAE,CAAC;AAClD,EAAA;AAEA;AAAA,OACK,IAAIA,KAAK,KAAK,UAAU,EAAE;AAC7BU,IAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,iBAAA,CAAmB,CAAC;AACtC;IACA,IAAIJ,UAAU,KAAK,MAAM,EAAE;AACzBG,MAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,mBAAA,EAAsBJ,UAAU,EAAE,CAAC;AACvD,IAAA;AACF,EAAA;AAEA;OACK,IAAI,CAAC,wBAAwB,EAAE,wBAAwB,CAAC,CAACL,QAAQ,CAACF,KAAK,CAAC,EAAE;AAC7EU,IAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,SAAA,EAAYX,KAAK,EAAE,CAAC;AACxC,EAAA;AAEA;AAAA,OACK,IAAIA,KAAK,CAACY,UAAU,CAAC,UAAU,CAAC,EAAE;AACrCF,IAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,SAAA,EAAYX,KAAK,EAAE,CAAC;AACxC,EAAA;AACA;AACA,EAAA,OAAOU,YAAY,CAACG,IAAI,CAAC,GAAG,CAAC;AAC/B;;;;;;;;"}
package/dist/helpers.mjs CHANGED
@@ -5,16 +5,38 @@ const isExtraTheme = theme => extraThemes.includes(theme);
5
5
  const isForestGreenTheme = theme => theme === extraThemes[0];
6
6
  const isScreenModeDark = (theme, screenMode) => isThemeModern(theme) && screenModes[1] === screenMode;
7
7
  const getThemeClassName = (theme, screenMode) => {
8
- if (!isThemeModern(theme)) {
9
- return `np-theme-${theme || 'personal'}`;
8
+ if (['light'].includes(theme)) {
9
+ return `np-theme-${theme}`;
10
10
  }
11
- let classes = `np-theme-${theme === 'business' ? 'business' : 'personal'}`;
12
- if (isExtraTheme(theme)) {
13
- classes += ` ${classes}--${theme}`;
14
- } else if (screenModes[1] === screenMode) {
15
- classes += ` ${classes}--${screenMode}`;
11
+ // Personal light is always there by default
12
+ const themeClasses = ['np-theme-personal'];
13
+ /* eslint-disable functional/immutable-data */
14
+ // Personal dark theme
15
+ if (theme === 'personal' && screenMode === 'dark') {
16
+ themeClasses.push(`np-theme-personal--${screenMode}`);
16
17
  }
17
- return classes;
18
+ // Personal forest-green and bright-green themes
19
+ else if (['forest-green', 'bright-green'].includes(theme)) {
20
+ themeClasses.push(`np-theme-personal--${theme}`);
21
+ }
22
+ // Business light
23
+ else if (theme === 'business') {
24
+ themeClasses.push(`np-theme-business`);
25
+ // Business dark theme
26
+ if (screenMode === 'dark') {
27
+ themeClasses.push(`np-theme-business--${screenMode}`);
28
+ }
29
+ }
30
+ // Business forest-green and bright-green themes
31
+ else if (['business--forest-green', 'business--bright-green'].includes(theme)) {
32
+ themeClasses.push(`np-theme-${theme}`);
33
+ }
34
+ // Platform themes
35
+ else if (theme.startsWith('platform')) {
36
+ themeClasses.push(`np-theme-${theme}`);
37
+ }
38
+ /* eslint-enable functional/immutable-data */
39
+ return themeClasses.join(' ');
18
40
  };
19
41
 
20
42
  export { getThemeClassName, isExtraTheme, isForestGreenTheme, isScreenModeDark, isThemeModern };
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.mjs","sources":["../src/helpers.ts"],"sourcesContent":["import type {\n ModernTheme,\n ExtraTheme,\n ForestGreenTheme,\n ScreenMode,\n ScreenModeDark,\n Theming,\n} from './const';\nimport { extraThemes, screenModes, modernThemes } from './const';\n\nexport const isThemeModern = (theme: NonNullable<Theming['theme']>): theme is ModernTheme =>\n modernThemes.includes(theme as ModernTheme);\n\nexport const isExtraTheme = (theme: NonNullable<Theming['theme']>): theme is ExtraTheme =>\n extraThemes.includes(theme as ExtraTheme);\n\nexport const isForestGreenTheme = (\n theme: NonNullable<Theming['theme']>,\n): theme is ForestGreenTheme => theme === extraThemes[0];\n\nexport const isScreenModeDark = (\n theme: NonNullable<Theming['theme']>,\n screenMode: ScreenMode,\n): screenMode is ScreenModeDark =>\n isThemeModern(theme as ModernTheme) && screenModes[1] === screenMode;\n\nexport const getThemeClassName = (theme: NonNullable<Theming['theme']>, screenMode: ScreenMode) => {\n if (!isThemeModern(theme)) {\n return `np-theme-${theme || 'personal'}`;\n }\n\n let classes = `np-theme-${theme === 'business' ? 'business' : 'personal'}`;\n\n if (isExtraTheme(theme)) {\n classes += ` ${classes}--${theme}`;\n } else if (screenModes[1] === screenMode) {\n classes += ` ${classes}--${screenMode}`;\n }\n\n return classes;\n};\n"],"names":["isThemeModern","theme","modernThemes","includes","isExtraTheme","extraThemes","isForestGreenTheme","isScreenModeDark","screenMode","screenModes","getThemeClassName","classes"],"mappings":";;AAUO,MAAMA,aAAa,GAAIC,KAAoC,IAChEC,YAAY,CAACC,QAAQ,CAACF,KAAoB;AAErC,MAAMG,YAAY,GAAIH,KAAoC,IAC/DI,WAAW,CAACF,QAAQ,CAACF,KAAmB;AAEnC,MAAMK,kBAAkB,GAC7BL,KAAoC,IACNA,KAAK,KAAKI,WAAW,CAAC,CAAC;MAE1CE,gBAAgB,GAAGA,CAC9BN,KAAoC,EACpCO,UAAsB,KAEtBR,aAAa,CAACC,KAAoB,CAAC,IAAIQ,WAAW,CAAC,CAAC,CAAC,KAAKD;MAE/CE,iBAAiB,GAAGA,CAACT,KAAoC,EAAEO,UAAsB,KAAI;AAChG,EAAA,IAAI,CAACR,aAAa,CAACC,KAAK,CAAC,EAAE;AACzB,IAAA,OAAO,CAAA,SAAA,EAAYA,KAAK,IAAI,UAAU,CAAA,CAAE;AAC1C,EAAA;EAEA,IAAIU,OAAO,GAAG,CAAA,SAAA,EAAYV,KAAK,KAAK,UAAU,GAAG,UAAU,GAAG,UAAU,CAAA,CAAE;AAE1E,EAAA,IAAIG,YAAY,CAACH,KAAK,CAAC,EAAE;AACvBU,IAAAA,OAAO,IAAI,CAAA,CAAA,EAAIA,OAAO,CAAA,EAAA,EAAKV,KAAK,CAAA,CAAE;EACpC,CAAC,MAAM,IAAIQ,WAAW,CAAC,CAAC,CAAC,KAAKD,UAAU,EAAE;AACxCG,IAAAA,OAAO,IAAI,CAAA,CAAA,EAAIA,OAAO,CAAA,EAAA,EAAKH,UAAU,CAAA,CAAE;AACzC,EAAA;AAEA,EAAA,OAAOG,OAAO;AAChB;;;;"}
1
+ {"version":3,"file":"helpers.mjs","sources":["../src/helpers.ts"],"sourcesContent":["import type {\n ModernTheme,\n ExtraTheme,\n ForestGreenTheme,\n ScreenMode,\n ScreenModeDark,\n Theming,\n} from './const';\nimport { extraThemes, screenModes, modernThemes } from './const';\n\nexport const isThemeModern = (theme: NonNullable<Theming['theme']>): theme is ModernTheme =>\n modernThemes.includes(theme as ModernTheme);\n\nexport const isExtraTheme = (theme: NonNullable<Theming['theme']>): theme is ExtraTheme =>\n extraThemes.includes(theme as ExtraTheme);\n\nexport const isForestGreenTheme = (\n theme: NonNullable<Theming['theme']>,\n): theme is ForestGreenTheme => theme === extraThemes[0];\n\nexport const isScreenModeDark = (\n theme: NonNullable<Theming['theme']>,\n screenMode: ScreenMode,\n): screenMode is ScreenModeDark =>\n isThemeModern(theme as ModernTheme) && screenModes[1] === screenMode;\n\nexport const getThemeClassName = (theme: NonNullable<Theming['theme']>, screenMode: ScreenMode) => {\n if (['light'].includes(theme)) {\n return `np-theme-${theme}`;\n }\n\n // Personal light is always there by default\n const themeClasses = ['np-theme-personal'];\n\n /* eslint-disable functional/immutable-data */\n // Personal dark theme\n if (theme === 'personal' && screenMode === 'dark') {\n themeClasses.push(`np-theme-personal--${screenMode}`);\n }\n\n // Personal forest-green and bright-green themes\n else if (['forest-green', 'bright-green'].includes(theme)) {\n themeClasses.push(`np-theme-personal--${theme}`);\n }\n\n // Business light\n else if (theme === 'business') {\n themeClasses.push(`np-theme-business`);\n // Business dark theme\n if (screenMode === 'dark') {\n themeClasses.push(`np-theme-business--${screenMode}`);\n }\n }\n\n // Business forest-green and bright-green themes\n else if (['business--forest-green', 'business--bright-green'].includes(theme)) {\n themeClasses.push(`np-theme-${theme}`);\n }\n\n // Platform themes\n else if (theme.startsWith('platform')) {\n themeClasses.push(`np-theme-${theme}`);\n }\n /* eslint-enable functional/immutable-data */\n return themeClasses.join(' ');\n};\n"],"names":["isThemeModern","theme","modernThemes","includes","isExtraTheme","extraThemes","isForestGreenTheme","isScreenModeDark","screenMode","screenModes","getThemeClassName","themeClasses","push","startsWith","join"],"mappings":";;AAUO,MAAMA,aAAa,GAAIC,KAAoC,IAChEC,YAAY,CAACC,QAAQ,CAACF,KAAoB;AAErC,MAAMG,YAAY,GAAIH,KAAoC,IAC/DI,WAAW,CAACF,QAAQ,CAACF,KAAmB;AAEnC,MAAMK,kBAAkB,GAC7BL,KAAoC,IACNA,KAAK,KAAKI,WAAW,CAAC,CAAC;MAE1CE,gBAAgB,GAAGA,CAC9BN,KAAoC,EACpCO,UAAsB,KAEtBR,aAAa,CAACC,KAAoB,CAAC,IAAIQ,WAAW,CAAC,CAAC,CAAC,KAAKD;MAE/CE,iBAAiB,GAAGA,CAACT,KAAoC,EAAEO,UAAsB,KAAI;EAChG,IAAI,CAAC,OAAO,CAAC,CAACL,QAAQ,CAACF,KAAK,CAAC,EAAE;IAC7B,OAAO,CAAA,SAAA,EAAYA,KAAK,CAAA,CAAE;AAC5B,EAAA;AAEA;AACA,EAAA,MAAMU,YAAY,GAAG,CAAC,mBAAmB,CAAC;AAE1C;AACA;AACA,EAAA,IAAIV,KAAK,KAAK,UAAU,IAAIO,UAAU,KAAK,MAAM,EAAE;AACjDG,IAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,mBAAA,EAAsBJ,UAAU,EAAE,CAAC;AACvD,EAAA;AAEA;OACK,IAAI,CAAC,cAAc,EAAE,cAAc,CAAC,CAACL,QAAQ,CAACF,KAAK,CAAC,EAAE;AACzDU,IAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,mBAAA,EAAsBX,KAAK,EAAE,CAAC;AAClD,EAAA;AAEA;AAAA,OACK,IAAIA,KAAK,KAAK,UAAU,EAAE;AAC7BU,IAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,iBAAA,CAAmB,CAAC;AACtC;IACA,IAAIJ,UAAU,KAAK,MAAM,EAAE;AACzBG,MAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,mBAAA,EAAsBJ,UAAU,EAAE,CAAC;AACvD,IAAA;AACF,EAAA;AAEA;OACK,IAAI,CAAC,wBAAwB,EAAE,wBAAwB,CAAC,CAACL,QAAQ,CAACF,KAAK,CAAC,EAAE;AAC7EU,IAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,SAAA,EAAYX,KAAK,EAAE,CAAC;AACxC,EAAA;AAEA;AAAA,OACK,IAAIA,KAAK,CAACY,UAAU,CAAC,UAAU,CAAC,EAAE;AACrCF,IAAAA,YAAY,CAACC,IAAI,CAAC,CAAA,SAAA,EAAYX,KAAK,EAAE,CAAC;AACxC,EAAA;AACA;AACA,EAAA,OAAOU,YAAY,CAACG,IAAI,CAAC,GAAG,CAAC;AAC/B;;;;"}
@@ -6,6 +6,8 @@ interface ThemeHookValue {
6
6
  isForestGreenTheme: boolean;
7
7
  isScreenModeDark: boolean;
8
8
  className: string;
9
+ setTheme: (theme: NonNullable<Theming['theme']>) => void;
10
+ setScreenMode: (screenMode: ScreenMode) => void;
9
11
  }
10
12
  export declare const useTheme: () => ThemeHookValue;
11
13
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../src/useTheme.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAInD,UAAU,cAAc;IACtB,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAeD,eAAO,MAAM,QAAQ,QAAO,cAuB3B,CAAC"}
1
+ {"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../src/useTheme.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAInD,UAAU,cAAc;IACtB,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACrC,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC;IACzD,aAAa,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;CACjD;AAiBD,eAAO,MAAM,QAAQ,QAAO,cA8B3B,CAAC"}
package/dist/useTheme.js CHANGED
@@ -7,7 +7,9 @@ var helpers = require('./helpers.js');
7
7
 
8
8
  const FALLBACK_VALUES = {
9
9
  theme: _const.DEFAULT_BASE_THEME,
10
- screenMode: _const.DEFAULT_SCREEN_MODE
10
+ screenMode: _const.DEFAULT_SCREEN_MODE,
11
+ setTheme: () => {},
12
+ setScreenMode: () => {}
11
13
  };
12
14
  const isNotProduction = () => {
13
15
  try {
@@ -24,7 +26,9 @@ const useTheme = () => {
24
26
  }
25
27
  const {
26
28
  theme,
27
- screenMode: contextScreenMode
29
+ screenMode: contextScreenMode,
30
+ setTheme,
31
+ setScreenMode
28
32
  } = theming ?? FALLBACK_VALUES;
29
33
  const screenMode = theme === _const.DEFAULT_BASE_THEME ? _const.DEFAULT_SCREEN_MODE : contextScreenMode;
30
34
  return react.useMemo(() => ({
@@ -33,8 +37,10 @@ const useTheme = () => {
33
37
  isModern: helpers.isThemeModern(theme),
34
38
  isForestGreenTheme: helpers.isForestGreenTheme(theme),
35
39
  isScreenModeDark: helpers.isScreenModeDark(theme, screenMode),
36
- className: helpers.getThemeClassName(theme, screenMode)
37
- }), [theme, screenMode]);
40
+ className: helpers.getThemeClassName(theme, screenMode),
41
+ setTheme,
42
+ setScreenMode
43
+ }), [theme, screenMode, setTheme, setScreenMode]);
38
44
  };
39
45
 
40
46
  exports.useTheme = useTheme;
@@ -1 +1 @@
1
- {"version":3,"file":"useTheme.js","sources":["../src/useTheme.ts"],"sourcesContent":["import { useContext, useMemo } from 'react';\n\nimport { ThemeContext } from './ThemeProviderContext';\nimport type { ScreenMode, Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { isThemeModern, isForestGreenTheme, isScreenModeDark, getThemeClassName } from './helpers';\n\ninterface ThemeHookValue {\n theme: NonNullable<Theming['theme']>;\n screenMode: ScreenMode;\n isModern: boolean;\n isForestGreenTheme: boolean;\n isScreenModeDark: boolean;\n className: string;\n}\n\nconst FALLBACK_VALUES = {\n theme: DEFAULT_BASE_THEME,\n screenMode: DEFAULT_SCREEN_MODE,\n} as const;\n\nconst isNotProduction = () => {\n try {\n return ['localhost', 'dev-wi.se'].includes(window.location.hostname);\n } catch {\n return false;\n }\n};\n\nexport const useTheme = (): ThemeHookValue => {\n const theming = useContext(ThemeContext);\n\n if (!theming && isNotProduction()) {\n // eslint-disable-next-line no-console\n console.warn('Call to useTheme outside a ThemeProvider');\n }\n\n const { theme, screenMode: contextScreenMode } = theming ?? FALLBACK_VALUES;\n\n const screenMode = theme === DEFAULT_BASE_THEME ? DEFAULT_SCREEN_MODE : contextScreenMode;\n\n return useMemo(\n () => ({\n theme,\n screenMode,\n isModern: isThemeModern(theme),\n isForestGreenTheme: isForestGreenTheme(theme),\n isScreenModeDark: isScreenModeDark(theme, screenMode),\n className: getThemeClassName(theme, screenMode),\n }),\n [theme, screenMode],\n );\n};\n"],"names":["FALLBACK_VALUES","theme","DEFAULT_BASE_THEME","screenMode","DEFAULT_SCREEN_MODE","isNotProduction","includes","window","location","hostname","useTheme","theming","useContext","ThemeContext","console","warn","contextScreenMode","useMemo","isModern","isThemeModern","isForestGreenTheme","isScreenModeDark","className","getThemeClassName"],"mappings":";;;;;;;AAgBA,MAAMA,eAAe,GAAG;AACtBC,EAAAA,KAAK,EAAEC,yBAAkB;AACzBC,EAAAA,UAAU,EAAEC;CACJ;AAEV,MAAMC,eAAe,GAAGA,MAAK;EAC3B,IAAI;AACF,IAAA,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAACC,QAAQ,CAACC,MAAM,CAACC,QAAQ,CAACC,QAAQ,CAAC;AACtE,EAAA,CAAC,CAAC,MAAM;AACN,IAAA,OAAO,KAAK;AACd,EAAA;AACF,CAAC;AAEM,MAAMC,QAAQ,GAAGA,MAAqB;AAC3C,EAAA,MAAMC,OAAO,GAAGC,gBAAU,CAACC,iCAAY,CAAC;AAExC,EAAA,IAAI,CAACF,OAAO,IAAIN,eAAe,EAAE,EAAE;AACjC;AACAS,IAAAA,OAAO,CAACC,IAAI,CAAC,0CAA0C,CAAC;AAC1D,EAAA;EAEA,MAAM;IAAEd,KAAK;AAAEE,IAAAA,UAAU,EAAEa;GAAmB,GAAGL,OAAO,IAAIX,eAAe;EAE3E,MAAMG,UAAU,GAAGF,KAAK,KAAKC,yBAAkB,GAAGE,0BAAmB,GAAGY,iBAAiB;EAEzF,OAAOC,aAAO,CACZ,OAAO;IACLhB,KAAK;IACLE,UAAU;AACVe,IAAAA,QAAQ,EAAEC,qBAAa,CAAClB,KAAK,CAAC;AAC9BmB,IAAAA,kBAAkB,EAAEA,0BAAkB,CAACnB,KAAK,CAAC;AAC7CoB,IAAAA,gBAAgB,EAAEA,wBAAgB,CAACpB,KAAK,EAAEE,UAAU,CAAC;AACrDmB,IAAAA,SAAS,EAAEC,yBAAiB,CAACtB,KAAK,EAAEE,UAAU;AAC/C,GAAA,CAAC,EACF,CAACF,KAAK,EAAEE,UAAU,CAAC,CACpB;AACH;;;;"}
1
+ {"version":3,"file":"useTheme.js","sources":["../src/useTheme.ts"],"sourcesContent":["import { useContext, useMemo } from 'react';\n\nimport { ThemeContext } from './ThemeProviderContext';\nimport type { ScreenMode, Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { isThemeModern, isForestGreenTheme, isScreenModeDark, getThemeClassName } from './helpers';\n\ninterface ThemeHookValue {\n theme: NonNullable<Theming['theme']>;\n screenMode: ScreenMode;\n isModern: boolean;\n isForestGreenTheme: boolean;\n isScreenModeDark: boolean;\n className: string;\n setTheme: (theme: NonNullable<Theming['theme']>) => void;\n setScreenMode: (screenMode: ScreenMode) => void;\n}\n\nconst FALLBACK_VALUES = {\n theme: DEFAULT_BASE_THEME,\n screenMode: DEFAULT_SCREEN_MODE,\n setTheme: () => {},\n setScreenMode: () => {},\n} as const;\n\nconst isNotProduction = () => {\n try {\n return ['localhost', 'dev-wi.se'].includes(window.location.hostname);\n } catch {\n return false;\n }\n};\n\nexport const useTheme = (): ThemeHookValue => {\n const theming = useContext(ThemeContext);\n\n if (!theming && isNotProduction()) {\n // eslint-disable-next-line no-console\n console.warn('Call to useTheme outside a ThemeProvider');\n }\n\n const {\n theme,\n screenMode: contextScreenMode,\n setTheme,\n setScreenMode,\n } = theming ?? FALLBACK_VALUES;\n\n const screenMode = theme === DEFAULT_BASE_THEME ? DEFAULT_SCREEN_MODE : contextScreenMode;\n\n return useMemo(\n () => ({\n theme,\n screenMode,\n isModern: isThemeModern(theme),\n isForestGreenTheme: isForestGreenTheme(theme),\n isScreenModeDark: isScreenModeDark(theme, screenMode),\n className: getThemeClassName(theme, screenMode),\n setTheme,\n setScreenMode,\n }),\n [theme, screenMode, setTheme, setScreenMode],\n );\n};\n"],"names":["FALLBACK_VALUES","theme","DEFAULT_BASE_THEME","screenMode","DEFAULT_SCREEN_MODE","setTheme","setScreenMode","isNotProduction","includes","window","location","hostname","useTheme","theming","useContext","ThemeContext","console","warn","contextScreenMode","useMemo","isModern","isThemeModern","isForestGreenTheme","isScreenModeDark","className","getThemeClassName"],"mappings":";;;;;;;AAkBA,MAAMA,eAAe,GAAG;AACtBC,EAAAA,KAAK,EAAEC,yBAAkB;AACzBC,EAAAA,UAAU,EAAEC,0BAAmB;AAC/BC,EAAAA,QAAQ,EAAEA,MAAK,CAAE,CAAC;EAClBC,aAAa,EAAEA,MAAK,CAAE;CACd;AAEV,MAAMC,eAAe,GAAGA,MAAK;EAC3B,IAAI;AACF,IAAA,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAACC,QAAQ,CAACC,MAAM,CAACC,QAAQ,CAACC,QAAQ,CAAC;AACtE,EAAA,CAAC,CAAC,MAAM;AACN,IAAA,OAAO,KAAK;AACd,EAAA;AACF,CAAC;AAEM,MAAMC,QAAQ,GAAGA,MAAqB;AAC3C,EAAA,MAAMC,OAAO,GAAGC,gBAAU,CAACC,iCAAY,CAAC;AAExC,EAAA,IAAI,CAACF,OAAO,IAAIN,eAAe,EAAE,EAAE;AACjC;AACAS,IAAAA,OAAO,CAACC,IAAI,CAAC,0CAA0C,CAAC;AAC1D,EAAA;EAEA,MAAM;IACJhB,KAAK;AACLE,IAAAA,UAAU,EAAEe,iBAAiB;IAC7Bb,QAAQ;AACRC,IAAAA;GACD,GAAGO,OAAO,IAAIb,eAAe;EAE9B,MAAMG,UAAU,GAAGF,KAAK,KAAKC,yBAAkB,GAAGE,0BAAmB,GAAGc,iBAAiB;EAEzF,OAAOC,aAAO,CACZ,OAAO;IACLlB,KAAK;IACLE,UAAU;AACViB,IAAAA,QAAQ,EAAEC,qBAAa,CAACpB,KAAK,CAAC;AAC9BqB,IAAAA,kBAAkB,EAAEA,0BAAkB,CAACrB,KAAK,CAAC;AAC7CsB,IAAAA,gBAAgB,EAAEA,wBAAgB,CAACtB,KAAK,EAAEE,UAAU,CAAC;AACrDqB,IAAAA,SAAS,EAAEC,yBAAiB,CAACxB,KAAK,EAAEE,UAAU,CAAC;IAC/CE,QAAQ;AACRC,IAAAA;GACD,CAAC,EACF,CAACL,KAAK,EAAEE,UAAU,EAAEE,QAAQ,EAAEC,aAAa,CAAC,CAC7C;AACH;;;;"}
package/dist/useTheme.mjs CHANGED
@@ -1,11 +1,13 @@
1
1
  import { useContext, useMemo } from 'react';
2
2
  import { ThemeContext } from './ThemeProviderContext.mjs';
3
- import { DEFAULT_SCREEN_MODE, DEFAULT_BASE_THEME } from './const.mjs';
3
+ import { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const.mjs';
4
4
  import { getThemeClassName, isScreenModeDark, isForestGreenTheme, isThemeModern } from './helpers.mjs';
5
5
 
6
6
  const FALLBACK_VALUES = {
7
7
  theme: DEFAULT_BASE_THEME,
8
- screenMode: DEFAULT_SCREEN_MODE
8
+ screenMode: DEFAULT_SCREEN_MODE,
9
+ setTheme: () => {},
10
+ setScreenMode: () => {}
9
11
  };
10
12
  const isNotProduction = () => {
11
13
  try {
@@ -22,7 +24,9 @@ const useTheme = () => {
22
24
  }
23
25
  const {
24
26
  theme,
25
- screenMode: contextScreenMode
27
+ screenMode: contextScreenMode,
28
+ setTheme,
29
+ setScreenMode
26
30
  } = theming ?? FALLBACK_VALUES;
27
31
  const screenMode = theme === DEFAULT_BASE_THEME ? DEFAULT_SCREEN_MODE : contextScreenMode;
28
32
  return useMemo(() => ({
@@ -31,8 +35,10 @@ const useTheme = () => {
31
35
  isModern: isThemeModern(theme),
32
36
  isForestGreenTheme: isForestGreenTheme(theme),
33
37
  isScreenModeDark: isScreenModeDark(theme, screenMode),
34
- className: getThemeClassName(theme, screenMode)
35
- }), [theme, screenMode]);
38
+ className: getThemeClassName(theme, screenMode),
39
+ setTheme,
40
+ setScreenMode
41
+ }), [theme, screenMode, setTheme, setScreenMode]);
36
42
  };
37
43
 
38
44
  export { useTheme };
@@ -1 +1 @@
1
- {"version":3,"file":"useTheme.mjs","sources":["../src/useTheme.ts"],"sourcesContent":["import { useContext, useMemo } from 'react';\n\nimport { ThemeContext } from './ThemeProviderContext';\nimport type { ScreenMode, Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { isThemeModern, isForestGreenTheme, isScreenModeDark, getThemeClassName } from './helpers';\n\ninterface ThemeHookValue {\n theme: NonNullable<Theming['theme']>;\n screenMode: ScreenMode;\n isModern: boolean;\n isForestGreenTheme: boolean;\n isScreenModeDark: boolean;\n className: string;\n}\n\nconst FALLBACK_VALUES = {\n theme: DEFAULT_BASE_THEME,\n screenMode: DEFAULT_SCREEN_MODE,\n} as const;\n\nconst isNotProduction = () => {\n try {\n return ['localhost', 'dev-wi.se'].includes(window.location.hostname);\n } catch {\n return false;\n }\n};\n\nexport const useTheme = (): ThemeHookValue => {\n const theming = useContext(ThemeContext);\n\n if (!theming && isNotProduction()) {\n // eslint-disable-next-line no-console\n console.warn('Call to useTheme outside a ThemeProvider');\n }\n\n const { theme, screenMode: contextScreenMode } = theming ?? FALLBACK_VALUES;\n\n const screenMode = theme === DEFAULT_BASE_THEME ? DEFAULT_SCREEN_MODE : contextScreenMode;\n\n return useMemo(\n () => ({\n theme,\n screenMode,\n isModern: isThemeModern(theme),\n isForestGreenTheme: isForestGreenTheme(theme),\n isScreenModeDark: isScreenModeDark(theme, screenMode),\n className: getThemeClassName(theme, screenMode),\n }),\n [theme, screenMode],\n );\n};\n"],"names":["FALLBACK_VALUES","theme","DEFAULT_BASE_THEME","screenMode","DEFAULT_SCREEN_MODE","isNotProduction","includes","window","location","hostname","useTheme","theming","useContext","ThemeContext","console","warn","contextScreenMode","useMemo","isModern","isThemeModern","isForestGreenTheme","isScreenModeDark","className","getThemeClassName"],"mappings":";;;;;AAgBA,MAAMA,eAAe,GAAG;AACtBC,EAAAA,KAAK,EAAEC,kBAAkB;AACzBC,EAAAA,UAAU,EAAEC;CACJ;AAEV,MAAMC,eAAe,GAAGA,MAAK;EAC3B,IAAI;AACF,IAAA,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAACC,QAAQ,CAACC,MAAM,CAACC,QAAQ,CAACC,QAAQ,CAAC;AACtE,EAAA,CAAC,CAAC,MAAM;AACN,IAAA,OAAO,KAAK;AACd,EAAA;AACF,CAAC;AAEM,MAAMC,QAAQ,GAAGA,MAAqB;AAC3C,EAAA,MAAMC,OAAO,GAAGC,UAAU,CAACC,YAAY,CAAC;AAExC,EAAA,IAAI,CAACF,OAAO,IAAIN,eAAe,EAAE,EAAE;AACjC;AACAS,IAAAA,OAAO,CAACC,IAAI,CAAC,0CAA0C,CAAC;AAC1D,EAAA;EAEA,MAAM;IAAEd,KAAK;AAAEE,IAAAA,UAAU,EAAEa;GAAmB,GAAGL,OAAO,IAAIX,eAAe;EAE3E,MAAMG,UAAU,GAAGF,KAAK,KAAKC,kBAAkB,GAAGE,mBAAmB,GAAGY,iBAAiB;EAEzF,OAAOC,OAAO,CACZ,OAAO;IACLhB,KAAK;IACLE,UAAU;AACVe,IAAAA,QAAQ,EAAEC,aAAa,CAAClB,KAAK,CAAC;AAC9BmB,IAAAA,kBAAkB,EAAEA,kBAAkB,CAACnB,KAAK,CAAC;AAC7CoB,IAAAA,gBAAgB,EAAEA,gBAAgB,CAACpB,KAAK,EAAEE,UAAU,CAAC;AACrDmB,IAAAA,SAAS,EAAEC,iBAAiB,CAACtB,KAAK,EAAEE,UAAU;AAC/C,GAAA,CAAC,EACF,CAACF,KAAK,EAAEE,UAAU,CAAC,CACpB;AACH;;;;"}
1
+ {"version":3,"file":"useTheme.mjs","sources":["../src/useTheme.ts"],"sourcesContent":["import { useContext, useMemo } from 'react';\n\nimport { ThemeContext } from './ThemeProviderContext';\nimport type { ScreenMode, Theming } from './const';\nimport { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { isThemeModern, isForestGreenTheme, isScreenModeDark, getThemeClassName } from './helpers';\n\ninterface ThemeHookValue {\n theme: NonNullable<Theming['theme']>;\n screenMode: ScreenMode;\n isModern: boolean;\n isForestGreenTheme: boolean;\n isScreenModeDark: boolean;\n className: string;\n setTheme: (theme: NonNullable<Theming['theme']>) => void;\n setScreenMode: (screenMode: ScreenMode) => void;\n}\n\nconst FALLBACK_VALUES = {\n theme: DEFAULT_BASE_THEME,\n screenMode: DEFAULT_SCREEN_MODE,\n setTheme: () => {},\n setScreenMode: () => {},\n} as const;\n\nconst isNotProduction = () => {\n try {\n return ['localhost', 'dev-wi.se'].includes(window.location.hostname);\n } catch {\n return false;\n }\n};\n\nexport const useTheme = (): ThemeHookValue => {\n const theming = useContext(ThemeContext);\n\n if (!theming && isNotProduction()) {\n // eslint-disable-next-line no-console\n console.warn('Call to useTheme outside a ThemeProvider');\n }\n\n const {\n theme,\n screenMode: contextScreenMode,\n setTheme,\n setScreenMode,\n } = theming ?? FALLBACK_VALUES;\n\n const screenMode = theme === DEFAULT_BASE_THEME ? DEFAULT_SCREEN_MODE : contextScreenMode;\n\n return useMemo(\n () => ({\n theme,\n screenMode,\n isModern: isThemeModern(theme),\n isForestGreenTheme: isForestGreenTheme(theme),\n isScreenModeDark: isScreenModeDark(theme, screenMode),\n className: getThemeClassName(theme, screenMode),\n setTheme,\n setScreenMode,\n }),\n [theme, screenMode, setTheme, setScreenMode],\n );\n};\n"],"names":["FALLBACK_VALUES","theme","DEFAULT_BASE_THEME","screenMode","DEFAULT_SCREEN_MODE","setTheme","setScreenMode","isNotProduction","includes","window","location","hostname","useTheme","theming","useContext","ThemeContext","console","warn","contextScreenMode","useMemo","isModern","isThemeModern","isForestGreenTheme","isScreenModeDark","className","getThemeClassName"],"mappings":";;;;;AAkBA,MAAMA,eAAe,GAAG;AACtBC,EAAAA,KAAK,EAAEC,kBAAkB;AACzBC,EAAAA,UAAU,EAAEC,mBAAmB;AAC/BC,EAAAA,QAAQ,EAAEA,MAAK,CAAE,CAAC;EAClBC,aAAa,EAAEA,MAAK,CAAE;CACd;AAEV,MAAMC,eAAe,GAAGA,MAAK;EAC3B,IAAI;AACF,IAAA,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAACC,QAAQ,CAACC,MAAM,CAACC,QAAQ,CAACC,QAAQ,CAAC;AACtE,EAAA,CAAC,CAAC,MAAM;AACN,IAAA,OAAO,KAAK;AACd,EAAA;AACF,CAAC;AAEM,MAAMC,QAAQ,GAAGA,MAAqB;AAC3C,EAAA,MAAMC,OAAO,GAAGC,UAAU,CAACC,YAAY,CAAC;AAExC,EAAA,IAAI,CAACF,OAAO,IAAIN,eAAe,EAAE,EAAE;AACjC;AACAS,IAAAA,OAAO,CAACC,IAAI,CAAC,0CAA0C,CAAC;AAC1D,EAAA;EAEA,MAAM;IACJhB,KAAK;AACLE,IAAAA,UAAU,EAAEe,iBAAiB;IAC7Bb,QAAQ;AACRC,IAAAA;GACD,GAAGO,OAAO,IAAIb,eAAe;EAE9B,MAAMG,UAAU,GAAGF,KAAK,KAAKC,kBAAkB,GAAGE,mBAAmB,GAAGc,iBAAiB;EAEzF,OAAOC,OAAO,CACZ,OAAO;IACLlB,KAAK;IACLE,UAAU;AACViB,IAAAA,QAAQ,EAAEC,aAAa,CAACpB,KAAK,CAAC;AAC9BqB,IAAAA,kBAAkB,EAAEA,kBAAkB,CAACrB,KAAK,CAAC;AAC7CsB,IAAAA,gBAAgB,EAAEA,gBAAgB,CAACtB,KAAK,EAAEE,UAAU,CAAC;AACrDqB,IAAAA,SAAS,EAAEC,iBAAiB,CAACxB,KAAK,EAAEE,UAAU,CAAC;IAC/CE,QAAQ;AACRC,IAAAA;GACD,CAAC,EACF,CAACL,KAAK,EAAEE,UAAU,EAAEE,QAAQ,EAAEC,aAAa,CAAC,CAC7C;AACH;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wise/components-theming",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Provides theming support for the Wise Design system components",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -40,9 +40,13 @@ describe('ThemeProvider', () => {
40
40
  // eslint-disable-next-line testing-library/no-node-access
41
41
  expect(screen.getByText('personal').parentElement).toHaveClass('np-theme-personal');
42
42
  // eslint-disable-next-line testing-library/no-node-access
43
- expect(screen.getByText('platform').parentElement).toHaveClass('np-theme-platform');
43
+ expect(screen.getByText('platform').parentElement).toHaveClass(
44
+ 'np-theme-personal',
45
+ 'np-theme-platform',
46
+ );
44
47
  // eslint-disable-next-line testing-library/no-node-access
45
48
  expect(screen.getByText('platform--forest-green').parentElement).toHaveClass(
49
+ 'np-theme-personal',
46
50
  'np-theme-platform--forest-green',
47
51
  );
48
52
  });
@@ -64,15 +68,24 @@ describe('ThemeProvider', () => {
64
68
  );
65
69
 
66
70
  // eslint-disable-next-line testing-library/no-node-access
67
- expect(screen.getByText('business').parentElement).toHaveClass('np-theme-business');
71
+ expect(screen.getByText('business').parentElement).toHaveClass(
72
+ 'np-theme-personal',
73
+ 'np-theme-business',
74
+ );
68
75
  // eslint-disable-next-line testing-library/no-node-access
69
- expect(screen.getByText('business-dark').parentElement).toHaveClass('np-theme-business--dark');
76
+ expect(screen.getByText('business-dark').parentElement).toHaveClass(
77
+ 'np-theme-personal',
78
+ 'np-theme-business',
79
+ 'np-theme-business--dark',
80
+ );
70
81
  // eslint-disable-next-line testing-library/no-node-access
71
82
  expect(screen.getByText('business--bright-green').parentElement).toHaveClass(
83
+ 'np-theme-personal',
72
84
  'np-theme-business--bright-green',
73
85
  );
74
86
  // eslint-disable-next-line testing-library/no-node-access
75
87
  expect(screen.getByText('business--forest-green').parentElement).toHaveClass(
88
+ 'np-theme-personal',
76
89
  'np-theme-business--forest-green',
77
90
  );
78
91
  });
@@ -1,4 +1,4 @@
1
- import { PropsWithChildren, useContext, useEffect, useMemo } from 'react';
1
+ import { PropsWithChildren, useContext, useEffect, useMemo, useState } from 'react';
2
2
 
3
3
  import { ThemedChildren } from './ThemedChildren';
4
4
  import type { Theming } from './const';
@@ -12,13 +12,15 @@ type ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };
12
12
  const themeClass = /\bnp-theme-[a-z-]+\b/g;
13
13
 
14
14
  export const ThemeProvider = ({
15
- theme = DEFAULT_BASE_THEME,
16
- screenMode = DEFAULT_SCREEN_MODE,
15
+ theme: initialTheme = DEFAULT_BASE_THEME,
16
+ screenMode: initialScreenMode = DEFAULT_SCREEN_MODE,
17
17
  isNotRootProvider = false,
18
18
  children,
19
19
  className = undefined,
20
20
  }: ThemeProviderProps) => {
21
21
  const isContextRoot = useContext(ThemeContext) === undefined;
22
+ const [theme, setTheme] = useState(initialTheme);
23
+ const [screenMode, setScreenMode] = useState(initialScreenMode);
22
24
 
23
25
  // useEffect hook used to apply the theme class to the HTML element
24
26
  useEffect(() => {
@@ -35,7 +37,10 @@ export const ThemeProvider = ({
35
37
  }
36
38
  }, [isNotRootProvider, isContextRoot, theme, screenMode]);
37
39
 
38
- const contextValue = useMemo(() => ({ theme, screenMode }), [screenMode, theme]);
40
+ const contextValue = useMemo(
41
+ () => ({ theme, screenMode, setTheme, setScreenMode }),
42
+ [theme, screenMode, setTheme, setScreenMode],
43
+ );
39
44
 
40
45
  return (
41
46
  <ThemeContext.Provider value={contextValue}>
@@ -5,6 +5,8 @@ export const ThemeContext = createContext<
5
5
  | {
6
6
  theme: NonNullable<Theming['theme']>;
7
7
  screenMode: ScreenMode;
8
+ setTheme: (theme: NonNullable<Theming['theme']>) => void;
9
+ setScreenMode: (screenMode: ScreenMode) => void;
8
10
  }
9
11
  | undefined
10
12
  >(undefined);
package/src/helpers.ts CHANGED
@@ -25,17 +25,42 @@ export const isScreenModeDark = (
25
25
  isThemeModern(theme as ModernTheme) && screenModes[1] === screenMode;
26
26
 
27
27
  export const getThemeClassName = (theme: NonNullable<Theming['theme']>, screenMode: ScreenMode) => {
28
- if (!isThemeModern(theme)) {
29
- return `np-theme-${theme || 'personal'}`;
28
+ if (['light'].includes(theme)) {
29
+ return `np-theme-${theme}`;
30
30
  }
31
31
 
32
- let classes = `np-theme-${theme === 'business' ? 'business' : 'personal'}`;
32
+ // Personal light is always there by default
33
+ const themeClasses = ['np-theme-personal'];
33
34
 
34
- if (isExtraTheme(theme)) {
35
- classes += ` ${classes}--${theme}`;
36
- } else if (screenModes[1] === screenMode) {
37
- classes += ` ${classes}--${screenMode}`;
35
+ /* eslint-disable functional/immutable-data */
36
+ // Personal dark theme
37
+ if (theme === 'personal' && screenMode === 'dark') {
38
+ themeClasses.push(`np-theme-personal--${screenMode}`);
38
39
  }
39
40
 
40
- return classes;
41
+ // Personal forest-green and bright-green themes
42
+ else if (['forest-green', 'bright-green'].includes(theme)) {
43
+ themeClasses.push(`np-theme-personal--${theme}`);
44
+ }
45
+
46
+ // Business light
47
+ else if (theme === 'business') {
48
+ themeClasses.push(`np-theme-business`);
49
+ // Business dark theme
50
+ if (screenMode === 'dark') {
51
+ themeClasses.push(`np-theme-business--${screenMode}`);
52
+ }
53
+ }
54
+
55
+ // Business forest-green and bright-green themes
56
+ else if (['business--forest-green', 'business--bright-green'].includes(theme)) {
57
+ themeClasses.push(`np-theme-${theme}`);
58
+ }
59
+
60
+ // Platform themes
61
+ else if (theme.startsWith('platform')) {
62
+ themeClasses.push(`np-theme-${theme}`);
63
+ }
64
+ /* eslint-enable functional/immutable-data */
65
+ return themeClasses.join(' ');
41
66
  };
@@ -1,4 +1,4 @@
1
- import { renderHook } from '@testing-library/react';
1
+ import { renderHook, act } from '@testing-library/react';
2
2
 
3
3
  import { ThemeProvider } from './ThemeProvider';
4
4
  import { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';
@@ -12,7 +12,7 @@ describe('useTheme', () => {
12
12
  result: { current },
13
13
  } = renderHook(() => useTheme());
14
14
 
15
- expect(current).toStrictEqual({
15
+ expect(current).toMatchObject({
16
16
  theme: DEFAULT_BASE_THEME,
17
17
  screenMode: DEFAULT_SCREEN_MODE,
18
18
  isModern: false,
@@ -20,6 +20,8 @@ describe('useTheme', () => {
20
20
  isScreenModeDark: false,
21
21
  className: 'np-theme-light',
22
22
  });
23
+ expect(current.setTheme).toBeInstanceOf(Function);
24
+ expect(current.setScreenMode).toBeInstanceOf(Function);
23
25
 
24
26
  jest.clearAllMocks();
25
27
  });
@@ -31,7 +33,7 @@ describe('useTheme', () => {
31
33
  wrapper: (props) => <ThemeProvider theme="personal" {...props} />,
32
34
  });
33
35
 
34
- expect(current).toStrictEqual({
36
+ expect(current).toMatchObject({
35
37
  theme: 'personal',
36
38
  screenMode: DEFAULT_SCREEN_MODE,
37
39
  isModern: true,
@@ -39,6 +41,8 @@ describe('useTheme', () => {
39
41
  isScreenModeDark: false,
40
42
  className: 'np-theme-personal',
41
43
  });
44
+ expect(current.setTheme).toBeInstanceOf(Function);
45
+ expect(current.setScreenMode).toBeInstanceOf(Function);
42
46
  });
43
47
 
44
48
  it('returns forest-green theme', () => {
@@ -48,7 +52,7 @@ describe('useTheme', () => {
48
52
  wrapper: (props) => <ThemeProvider theme="forest-green" {...props} />,
49
53
  });
50
54
 
51
- expect(current).toStrictEqual({
55
+ expect(current).toMatchObject({
52
56
  theme: 'forest-green',
53
57
  screenMode: DEFAULT_SCREEN_MODE,
54
58
  isModern: true,
@@ -56,6 +60,8 @@ describe('useTheme', () => {
56
60
  isScreenModeDark: false,
57
61
  className: 'np-theme-personal np-theme-personal--forest-green',
58
62
  });
63
+ expect(current.setTheme).toBeInstanceOf(Function);
64
+ expect(current.setScreenMode).toBeInstanceOf(Function);
59
65
  });
60
66
 
61
67
  it('returns bright-green theme', () => {
@@ -65,7 +71,7 @@ describe('useTheme', () => {
65
71
  wrapper: (props) => <ThemeProvider theme="bright-green" {...props} />,
66
72
  });
67
73
 
68
- expect(current).toStrictEqual({
74
+ expect(current).toMatchObject({
69
75
  theme: 'bright-green',
70
76
  screenMode: DEFAULT_SCREEN_MODE,
71
77
  isModern: true,
@@ -73,6 +79,8 @@ describe('useTheme', () => {
73
79
  isScreenModeDark: false,
74
80
  className: 'np-theme-personal np-theme-personal--bright-green',
75
81
  });
82
+ expect(current.setTheme).toBeInstanceOf(Function);
83
+ expect(current.setScreenMode).toBeInstanceOf(Function);
76
84
  });
77
85
 
78
86
  it('returns default screen mode if used default light theme', () => {
@@ -82,7 +90,7 @@ describe('useTheme', () => {
82
90
  wrapper: (props) => <ThemeProvider theme={DEFAULT_BASE_THEME} screenMode="dark" {...props} />,
83
91
  });
84
92
 
85
- expect(current).toStrictEqual({
93
+ expect(current).toMatchObject({
86
94
  theme: DEFAULT_BASE_THEME,
87
95
  screenMode: DEFAULT_SCREEN_MODE,
88
96
  isModern: false,
@@ -90,6 +98,8 @@ describe('useTheme', () => {
90
98
  isScreenModeDark: false,
91
99
  className: 'np-theme-light',
92
100
  });
101
+ expect(current.setTheme).toBeInstanceOf(Function);
102
+ expect(current.setScreenMode).toBeInstanceOf(Function);
93
103
  });
94
104
 
95
105
  it('returns dark screen mode', () => {
@@ -99,7 +109,7 @@ describe('useTheme', () => {
99
109
  wrapper: (props) => <ThemeProvider theme="personal" screenMode="dark" {...props} />,
100
110
  });
101
111
 
102
- expect(current).toStrictEqual({
112
+ expect(current).toMatchObject({
103
113
  theme: 'personal',
104
114
  screenMode: 'dark',
105
115
  isModern: true,
@@ -107,8 +117,9 @@ describe('useTheme', () => {
107
117
  isScreenModeDark: true,
108
118
  className: 'np-theme-personal np-theme-personal--dark',
109
119
  });
120
+ expect(current.setTheme).toBeInstanceOf(Function);
121
+ expect(current.setScreenMode).toBeInstanceOf(Function);
110
122
  });
111
-
112
123
  it('warns when used outside a theme provider on staging or localhost', () => {
113
124
  jest.spyOn(console, 'warn').mockImplementation();
114
125
 
@@ -123,7 +134,7 @@ describe('useTheme', () => {
123
134
  result: { current: productionValue },
124
135
  } = renderHook(() => useTheme());
125
136
 
126
- expect(productionValue).toStrictEqual({
137
+ expect(productionValue).toMatchObject({
127
138
  theme: DEFAULT_BASE_THEME,
128
139
  screenMode: DEFAULT_SCREEN_MODE,
129
140
  isModern: false,
@@ -131,6 +142,8 @@ describe('useTheme', () => {
131
142
  isScreenModeDark: false,
132
143
  className: 'np-theme-light',
133
144
  });
145
+ expect(productionValue.setTheme).toBeInstanceOf(Function);
146
+ expect(productionValue.setScreenMode).toBeInstanceOf(Function);
134
147
 
135
148
  // eslint-disable-next-line no-console
136
149
  expect(console.warn).not.toHaveBeenCalled();
@@ -146,7 +159,7 @@ describe('useTheme', () => {
146
159
  result: { current: stagingValue },
147
160
  } = renderHook(() => useTheme());
148
161
 
149
- expect(stagingValue).toStrictEqual({
162
+ expect(stagingValue).toMatchObject({
150
163
  theme: DEFAULT_BASE_THEME,
151
164
  screenMode: DEFAULT_SCREEN_MODE,
152
165
  isModern: false,
@@ -154,6 +167,8 @@ describe('useTheme', () => {
154
167
  isScreenModeDark: false,
155
168
  className: 'np-theme-light',
156
169
  });
170
+ expect(stagingValue.setTheme).toBeInstanceOf(Function);
171
+ expect(stagingValue.setScreenMode).toBeInstanceOf(Function);
157
172
 
158
173
  // eslint-disable-next-line no-console
159
174
  expect(console.warn).toHaveBeenCalledTimes(1);
@@ -169,7 +184,7 @@ describe('useTheme', () => {
169
184
  result: { current: localhostValue },
170
185
  } = renderHook(() => useTheme());
171
186
 
172
- expect(localhostValue).toStrictEqual({
187
+ expect(localhostValue).toMatchObject({
173
188
  theme: DEFAULT_BASE_THEME,
174
189
  screenMode: DEFAULT_SCREEN_MODE,
175
190
  isModern: false,
@@ -177,6 +192,8 @@ describe('useTheme', () => {
177
192
  isScreenModeDark: false,
178
193
  className: 'np-theme-light',
179
194
  });
195
+ expect(localhostValue.setTheme).toBeInstanceOf(Function);
196
+ expect(localhostValue.setScreenMode).toBeInstanceOf(Function);
180
197
 
181
198
  // eslint-disable-next-line no-console
182
199
  expect(console.warn).toHaveBeenCalledTimes(2);
@@ -190,7 +207,7 @@ describe('useTheme', () => {
190
207
  result: { current: noHostnameValue },
191
208
  } = renderHook(() => useTheme());
192
209
 
193
- expect(noHostnameValue).toStrictEqual({
210
+ expect(noHostnameValue).toMatchObject({
194
211
  theme: DEFAULT_BASE_THEME,
195
212
  screenMode: DEFAULT_SCREEN_MODE,
196
213
  isModern: false,
@@ -198,10 +215,42 @@ describe('useTheme', () => {
198
215
  isScreenModeDark: false,
199
216
  className: 'np-theme-light',
200
217
  });
218
+ expect(noHostnameValue.setTheme).toBeInstanceOf(Function);
219
+ expect(noHostnameValue.setScreenMode).toBeInstanceOf(Function);
201
220
 
202
221
  // eslint-disable-next-line no-console
203
222
  expect(console.warn).toHaveBeenCalledTimes(2);
204
223
 
205
224
  jest.clearAllMocks();
206
225
  });
226
+
227
+ it('allows theme changes from child components via setTheme', async () => {
228
+ const { result } = renderHook(() => useTheme(), {
229
+ wrapper: (props) => <ThemeProvider theme="personal" {...props} />,
230
+ });
231
+
232
+ expect(result.current.theme).toBe('personal');
233
+
234
+ // Change theme using setTheme
235
+ await act(async () => {
236
+ result.current.setTheme('business');
237
+ });
238
+
239
+ expect(result.current.theme).toBe('business');
240
+ });
241
+
242
+ it('allows screen mode changes from child components via setScreenMode', async () => {
243
+ const { result } = renderHook(() => useTheme(), {
244
+ wrapper: (props) => <ThemeProvider theme="personal" screenMode="light" {...props} />,
245
+ });
246
+
247
+ expect(result.current.screenMode).toBe('light');
248
+
249
+ // Change screen mode using setScreenMode
250
+ await act(async () => {
251
+ result.current.setScreenMode('dark');
252
+ });
253
+
254
+ expect(result.current.screenMode).toBe('dark');
255
+ });
207
256
  });
package/src/useTheme.ts CHANGED
@@ -12,11 +12,15 @@ interface ThemeHookValue {
12
12
  isForestGreenTheme: boolean;
13
13
  isScreenModeDark: boolean;
14
14
  className: string;
15
+ setTheme: (theme: NonNullable<Theming['theme']>) => void;
16
+ setScreenMode: (screenMode: ScreenMode) => void;
15
17
  }
16
18
 
17
19
  const FALLBACK_VALUES = {
18
20
  theme: DEFAULT_BASE_THEME,
19
21
  screenMode: DEFAULT_SCREEN_MODE,
22
+ setTheme: () => {},
23
+ setScreenMode: () => {},
20
24
  } as const;
21
25
 
22
26
  const isNotProduction = () => {
@@ -35,7 +39,12 @@ export const useTheme = (): ThemeHookValue => {
35
39
  console.warn('Call to useTheme outside a ThemeProvider');
36
40
  }
37
41
 
38
- const { theme, screenMode: contextScreenMode } = theming ?? FALLBACK_VALUES;
42
+ const {
43
+ theme,
44
+ screenMode: contextScreenMode,
45
+ setTheme,
46
+ setScreenMode,
47
+ } = theming ?? FALLBACK_VALUES;
39
48
 
40
49
  const screenMode = theme === DEFAULT_BASE_THEME ? DEFAULT_SCREEN_MODE : contextScreenMode;
41
50
 
@@ -47,7 +56,9 @@ export const useTheme = (): ThemeHookValue => {
47
56
  isForestGreenTheme: isForestGreenTheme(theme),
48
57
  isScreenModeDark: isScreenModeDark(theme, screenMode),
49
58
  className: getThemeClassName(theme, screenMode),
59
+ setTheme,
60
+ setScreenMode,
50
61
  }),
51
- [theme, screenMode],
62
+ [theme, screenMode, setTheme, setScreenMode],
52
63
  );
53
64
  };