@wise/components-theming 1.7.1 → 1.9.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.
- package/dist/ThemeProvider.d.ts +2 -3
- package/dist/ThemeProvider.d.ts.map +1 -1
- package/dist/ThemeProvider.js +8 -4
- package/dist/ThemeProvider.js.map +1 -1
- package/dist/ThemeProvider.mjs +10 -6
- package/dist/ThemeProvider.mjs.map +1 -1
- package/dist/ThemeProviderContext.d.ts +2 -0
- package/dist/ThemeProviderContext.d.ts.map +1 -1
- package/dist/ThemeProviderContext.js.map +1 -1
- package/dist/ThemeProviderContext.mjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/useTheme.d.ts +2 -0
- package/dist/useTheme.d.ts.map +1 -1
- package/dist/useTheme.js +10 -4
- package/dist/useTheme.js.map +1 -1
- package/dist/useTheme.mjs +11 -5
- package/dist/useTheme.mjs.map +1 -1
- package/package.json +1 -1
- package/src/ThemeProvider.tsx +10 -5
- package/src/ThemeProviderContext.tsx +2 -0
- package/src/index.ts +1 -1
- package/src/useTheme.spec.tsx +61 -12
- package/src/useTheme.ts +13 -2
package/dist/ThemeProvider.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
2
|
import type { Theming } from './const';
|
|
3
|
-
type ThemeProviderProps = PropsWithChildren<Theming> & {
|
|
3
|
+
export 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;
|
|
7
|
-
export {};
|
|
6
|
+
export declare const ThemeProvider: ({ theme: initialTheme, screenMode: initialScreenMode, isNotRootProvider, children, className, }: ThemeProviderProps) => import("react").JSX.Element;
|
|
8
7
|
//# 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,
|
|
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,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAKrF,eAAO,MAAM,aAAa,GAAI,iGAM3B,kBAAkB,gCA8BpB,CAAC"}
|
package/dist/ThemeProvider.js
CHANGED
|
@@ -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
|
-
|
|
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\
|
|
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\nexport type 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;;;;"}
|
package/dist/ThemeProvider.mjs
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import { useContext, useEffect, useMemo } from 'react';
|
|
1
|
+
import { useContext, useState, useEffect, useMemo } from 'react';
|
|
2
2
|
import { ThemedChildren } from './ThemedChildren.mjs';
|
|
3
|
-
import {
|
|
3
|
+
import { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const.mjs';
|
|
4
4
|
import { getThemeClassName } from './helpers.mjs';
|
|
5
5
|
import { ThemeContext } from './ThemeProviderContext.mjs';
|
|
6
6
|
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
|
-
|
|
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\
|
|
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\nexport type 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;
|
|
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,
|
|
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,
|
|
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;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type { ComponentTheme, BaseTheme, ExtraTheme, ScreenMode, Theming } from './const';
|
|
2
2
|
export { isThemeModern, isExtraTheme, isForestGreenTheme, isScreenModeDark, getThemeClassName, } from './helpers';
|
|
3
|
-
export { ThemeProvider } from './ThemeProvider';
|
|
3
|
+
export { ThemeProvider, type ThemeProviderProps } from './ThemeProvider';
|
|
4
4
|
export { useTheme } from './useTheme';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EACL,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EACL,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/useTheme.d.ts
CHANGED
|
@@ -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 {};
|
package/dist/useTheme.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
-
|
|
40
|
+
className: helpers.getThemeClassName(theme, screenMode),
|
|
41
|
+
setTheme,
|
|
42
|
+
setScreenMode
|
|
43
|
+
}), [theme, screenMode, setTheme, setScreenMode]);
|
|
38
44
|
};
|
|
39
45
|
|
|
40
46
|
exports.useTheme = useTheme;
|
package/dist/useTheme.js.map
CHANGED
|
@@ -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 {
|
|
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 {
|
|
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
|
-
|
|
38
|
+
className: getThemeClassName(theme, screenMode),
|
|
39
|
+
setTheme,
|
|
40
|
+
setScreenMode
|
|
41
|
+
}), [theme, screenMode, setTheme, setScreenMode]);
|
|
36
42
|
};
|
|
37
43
|
|
|
38
44
|
export { useTheme };
|
package/dist/useTheme.mjs.map
CHANGED
|
@@ -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 {
|
|
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
package/src/ThemeProvider.tsx
CHANGED
|
@@ -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';
|
|
@@ -6,19 +6,21 @@ import { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';
|
|
|
6
6
|
import { getThemeClassName } from './helpers';
|
|
7
7
|
import { ThemeContext } from './ThemeProviderContext';
|
|
8
8
|
|
|
9
|
-
type ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };
|
|
9
|
+
export type ThemeProviderProps = PropsWithChildren<Theming> & { className?: string };
|
|
10
10
|
|
|
11
11
|
// RegEx to check for `np-theme-` class name
|
|
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(
|
|
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}>
|
package/src/index.ts
CHANGED
package/src/useTheme.spec.tsx
CHANGED
|
@@ -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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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).
|
|
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 {
|
|
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
|
};
|