@wise/components-theming 0.5.0 → 0.5.1
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/cjs/index.d.ts +14 -12
- package/dist/cjs/index.js +48 -25
- package/dist/cjs/index.js.map +1 -1
- package/dist/es/index.d.ts +14 -12
- package/dist/es/index.js +48 -25
- package/dist/es/index.js.map +1 -1
- package/package.json +2 -2
- package/src/ThemeProvider.tsx +14 -12
- package/src/const.ts +11 -8
- package/src/helpers.ts +26 -6
- package/src/index.ts +1 -1
- package/src/useTheme.spec.tsx +67 -5
- package/src/useTheme.ts +13 -8
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { PropsWithChildren } from "react";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
];
|
|
9
|
-
type
|
|
3
|
+
// TODO: Change 'light' with 'legacy' in future
|
|
4
|
+
declare const baseThemes: string[];
|
|
5
|
+
declare const extraThemes: string[];
|
|
6
|
+
declare const screenModes: string[];
|
|
7
|
+
type BaseTheme = (typeof baseThemes)[number];
|
|
8
|
+
type ExtraTheme = (typeof extraThemes)[number];
|
|
9
|
+
type ScreenMode = (typeof screenModes)[number];
|
|
10
10
|
type Theming = {
|
|
11
|
-
theme?:
|
|
11
|
+
theme?: BaseTheme | ExtraTheme;
|
|
12
|
+
screenMode?: ScreenMode;
|
|
12
13
|
};
|
|
13
14
|
type ThemeProviderProps = PropsWithChildren<Theming>;
|
|
14
|
-
declare const ThemeProvider: ({ theme, children }: ThemeProviderProps) => JSX.Element;
|
|
15
|
+
declare const ThemeProvider: ({ theme, screenMode, children }: ThemeProviderProps) => JSX.Element;
|
|
15
16
|
interface ThemeHookValue {
|
|
16
|
-
theme:
|
|
17
|
+
theme: BaseTheme | ExtraTheme;
|
|
18
|
+
screenMode: ScreenMode;
|
|
17
19
|
isModern: boolean;
|
|
18
|
-
|
|
20
|
+
isScreenModeDark: boolean;
|
|
19
21
|
className: string;
|
|
20
22
|
}
|
|
21
23
|
declare const useTheme: () => ThemeHookValue;
|
|
22
|
-
export type {
|
|
24
|
+
export type { BaseTheme, ExtraTheme, ScreenMode, Theming };
|
|
23
25
|
export { ThemeProvider, useTheme };
|
package/dist/cjs/index.js
CHANGED
|
@@ -3,32 +3,50 @@
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var react = require('react');
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
var
|
|
8
|
-
var
|
|
6
|
+
// TODO: Change 'light' with 'legacy' in future
|
|
7
|
+
var extraThemes = ['forest-green'];
|
|
8
|
+
var DEFAULT_BASE_THEME = 'light';
|
|
9
|
+
var DEFAULT_SCREEN_MODE = 'light';
|
|
9
10
|
|
|
10
11
|
var isThemeModern = function isThemeModern(theme) {
|
|
11
|
-
return
|
|
12
|
+
return extraThemes.includes(theme) || theme === 'personal';
|
|
12
13
|
};
|
|
13
|
-
var
|
|
14
|
-
return
|
|
14
|
+
var isExtraTheme = function isExtraTheme(theme) {
|
|
15
|
+
return extraThemes.includes(theme);
|
|
15
16
|
};
|
|
16
|
-
var
|
|
17
|
-
return
|
|
17
|
+
var isScreenModeDark = function isScreenModeDark(theme, screenMode) {
|
|
18
|
+
return theme !== DEFAULT_BASE_THEME && screenMode === 'dark';
|
|
19
|
+
};
|
|
20
|
+
var getThemeClassName = function getThemeClassName(theme, screenMode) {
|
|
21
|
+
if (!isThemeModern(theme)) {
|
|
22
|
+
return "np-theme-".concat(theme);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var classes = "np-theme-personal";
|
|
26
|
+
|
|
27
|
+
if (isExtraTheme(theme)) {
|
|
28
|
+
classes += " ".concat(classes, "--").concat(theme);
|
|
29
|
+
} else if (screenMode === 'dark') {
|
|
30
|
+
classes += " ".concat(classes, "--").concat(screenMode);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return classes;
|
|
18
34
|
};
|
|
19
35
|
|
|
20
36
|
var useTheme = function useTheme() {
|
|
21
|
-
var _useContext;
|
|
37
|
+
var _useContext$theme, _useContext$screenMod;
|
|
22
38
|
|
|
23
|
-
var theme = (_useContext = react.useContext(ThemeContext)) !== null && _useContext !== void 0 ? _useContext :
|
|
39
|
+
var theme = (_useContext$theme = react.useContext(ThemeContext).theme) !== null && _useContext$theme !== void 0 ? _useContext$theme : DEFAULT_BASE_THEME;
|
|
40
|
+
var screenMode = theme !== DEFAULT_BASE_THEME ? (_useContext$screenMod = react.useContext(ThemeContext).screenMode) !== null && _useContext$screenMod !== void 0 ? _useContext$screenMod : DEFAULT_SCREEN_MODE : DEFAULT_SCREEN_MODE;
|
|
24
41
|
return react.useMemo(function () {
|
|
25
42
|
return {
|
|
26
43
|
theme: theme,
|
|
44
|
+
screenMode: screenMode,
|
|
27
45
|
isModern: isThemeModern(theme),
|
|
28
|
-
|
|
29
|
-
className: getThemeClassName(theme)
|
|
46
|
+
isScreenModeDark: isScreenModeDark(theme, screenMode),
|
|
47
|
+
className: getThemeClassName(theme, screenMode)
|
|
30
48
|
};
|
|
31
|
-
}, [theme]);
|
|
49
|
+
}, [theme, screenMode]);
|
|
32
50
|
};
|
|
33
51
|
|
|
34
52
|
var ThemedChildren = function ThemedChildren(_ref) {
|
|
@@ -43,12 +61,17 @@ var ThemedChildren = function ThemedChildren(_ref) {
|
|
|
43
61
|
});
|
|
44
62
|
};
|
|
45
63
|
|
|
46
|
-
var ThemeContext = /*#__PURE__*/react.createContext(
|
|
64
|
+
var ThemeContext = /*#__PURE__*/react.createContext({
|
|
65
|
+
theme: undefined,
|
|
66
|
+
screenMode: undefined
|
|
67
|
+
});
|
|
47
68
|
var ThemeProvider = function ThemeProvider(_ref) {
|
|
48
69
|
var _ref$theme = _ref.theme,
|
|
49
|
-
theme = _ref$theme === void 0 ?
|
|
70
|
+
theme = _ref$theme === void 0 ? DEFAULT_BASE_THEME : _ref$theme,
|
|
71
|
+
_ref$screenMode = _ref.screenMode,
|
|
72
|
+
screenMode = _ref$screenMode === void 0 ? DEFAULT_SCREEN_MODE : _ref$screenMode,
|
|
50
73
|
children = _ref.children;
|
|
51
|
-
var isRootProvider = react.useContext(ThemeContext) === undefined; // RegEx to check for `np-theme-` class name
|
|
74
|
+
var isRootProvider = react.useContext(ThemeContext).theme === undefined; // RegEx to check for `np-theme-` class name
|
|
52
75
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
53
76
|
|
|
54
77
|
var themeClass = new RegExp(/\bnp-theme-[a-z-]+\b/, 'g'); // useEffect hook used to apply the theme class to the HTML element
|
|
@@ -60,17 +83,17 @@ var ThemeProvider = function ThemeProvider(_ref) {
|
|
|
60
83
|
// Remove all the theme classes from the documentElement
|
|
61
84
|
(_document$documentEle = document.documentElement.className.match(themeClass)) === null || _document$documentEle === void 0 ? void 0 : _document$documentEle.map(function (item) {
|
|
62
85
|
document.documentElement.classList.remove(item);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
document.documentElement.classList.add("np-theme-".concat(theme));
|
|
86
|
+
});
|
|
87
|
+
getThemeClassName(theme, screenMode).split(' ').forEach(function (item) {
|
|
88
|
+
document.documentElement.classList.add(item);
|
|
89
|
+
});
|
|
70
90
|
}
|
|
71
|
-
}, [isRootProvider, theme,
|
|
91
|
+
}, [isRootProvider, theme, screenMode]);
|
|
72
92
|
return jsxRuntime.jsx(ThemeContext.Provider, {
|
|
73
|
-
value:
|
|
93
|
+
value: {
|
|
94
|
+
theme: theme,
|
|
95
|
+
screenMode: screenMode
|
|
96
|
+
},
|
|
74
97
|
children: jsxRuntime.jsx(ThemedChildren, {
|
|
75
98
|
children: children
|
|
76
99
|
})
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/const.ts","../../src/helpers.ts","../../src/useTheme.ts","../../src/ThemedChildren.tsx","../../src/ThemeProvider.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/const.ts","../../src/helpers.ts","../../src/useTheme.ts","../../src/ThemedChildren.tsx","../../src/ThemeProvider.tsx"],"sourcesContent":["// TODO: Change 'light' with 'legacy' in future\nexport const baseThemes = ['light', 'personal'];\nexport const extraThemes = ['forest-green'];\nexport const screenModes = ['light', 'dark'];\n\nexport type BaseTheme = typeof baseThemes[number];\nexport type ExtraTheme = typeof extraThemes[number];\nexport type ScreenMode = typeof screenModes[number];\n\nexport const DEFAULT_BASE_THEME = 'light' as const;\nexport const DEFAULT_SCREEN_MODE = 'light' as const;\n\nexport type Theming = {\n theme?: BaseTheme | ExtraTheme;\n screenMode?: ScreenMode;\n};\n","import { BaseTheme, ScreenMode, ExtraTheme, extraThemes, DEFAULT_BASE_THEME } from './const';\n\nexport const isThemeModern = (theme: BaseTheme | ExtraTheme): boolean =>\n extraThemes.includes(theme) || theme === 'personal';\n\nexport const isExtraTheme = (theme: ExtraTheme): theme is ExtraTheme =>\n extraThemes.includes(theme as ExtraTheme);\n\nexport const isScreenModeDark = (theme: BaseTheme, screenMode: ScreenMode): boolean =>\n theme !== DEFAULT_BASE_THEME && screenMode === 'dark';\n\nexport const getThemeClassName = (\n theme: BaseTheme | ExtraTheme,\n screenMode: ScreenMode,\n) => {\n if (!isThemeModern(theme)) {\n return `np-theme-${theme}`;\n }\n\n let classes = `np-theme-personal`;\n\n if (isExtraTheme(theme)) {\n classes += ` ${classes}--${theme}`;\n } else if (screenMode === 'dark' ) {\n classes += ` ${classes}--${screenMode}`;\n }\n\n return classes;\n};\n","import { useContext, useMemo } from 'react';\n\nimport { ThemeContext } from './ThemeProvider';\nimport { BaseTheme, ScreenMode, ExtraTheme, DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { isThemeModern, isScreenModeDark, getThemeClassName } from './helpers';\n\ninterface ThemeHookValue {\n theme: BaseTheme | ExtraTheme;\n screenMode: ScreenMode;\n isModern: boolean;\n isScreenModeDark: boolean;\n className: string;\n}\n\nexport const useTheme = (): ThemeHookValue => {\n const theme: BaseTheme | ExtraTheme = useContext(ThemeContext).theme ?? DEFAULT_BASE_THEME;\n const screenMode: ScreenMode = theme !== DEFAULT_BASE_THEME\n ? useContext(ThemeContext).screenMode ?? DEFAULT_SCREEN_MODE\n : DEFAULT_SCREEN_MODE;\n\n return useMemo(\n () => ({\n theme,\n screenMode,\n isModern: isThemeModern(theme),\n isScreenModeDark: isScreenModeDark(theme, screenMode),\n className: getThemeClassName(theme, screenMode),\n }),\n [theme, screenMode],\n );\n};\n","import { ReactNode } from 'react';\n\nimport { useTheme } from './useTheme';\n\ntype ThemedChildrenProps = { children: ReactNode };\n\nexport const ThemedChildren = ({ children }: ThemedChildrenProps) => {\n const { className } = useTheme();\n\n return <div className={className}>{children}</div>;\n};\n","import { createContext, PropsWithChildren, useContext, useEffect } from 'react';\n\nimport { ThemedChildren } from './ThemedChildren';\nimport { BaseTheme, ExtraTheme, ScreenMode, Theming, DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { getThemeClassName } from './helpers';\n\nexport const ThemeContext = createContext<{\n theme: BaseTheme | ExtraTheme | undefined,\n screenMode: ScreenMode | undefined,\n}>({ theme: undefined, screenMode: undefined });\n\ntype ThemeProviderProps = PropsWithChildren<Theming>;\n\nexport const ThemeProvider = ({\n theme = DEFAULT_BASE_THEME,\n screenMode = DEFAULT_SCREEN_MODE,\n children,\n}: ThemeProviderProps) => {\n const isRootProvider = useContext(ThemeContext).theme === undefined;\n\n // RegEx to check for `np-theme-` class name\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const themeClass = new RegExp(/\\bnp-theme-[a-z-]+\\b/, 'g');\n\n // useEffect hook used to apply the theme class to the HTML element\n useEffect(() => {\n if (isRootProvider) {\n // Remove all the theme classes from the documentElement\n document.documentElement.className.match(themeClass)?.map((item) => {\n document.documentElement.classList.remove(item);\n });\n getThemeClassName(theme, screenMode).split(' ').forEach(item => {\n document.documentElement.classList.add(item);\n })\n }\n }, [isRootProvider, theme, screenMode]);\n\n return (\n <ThemeContext.Provider value={{ theme, screenMode }}>\n <ThemedChildren>{children}</ThemedChildren>\n </ThemeContext.Provider>\n );\n};\n"],"names":["extraThemes","DEFAULT_BASE_THEME","DEFAULT_SCREEN_MODE","isThemeModern","theme","includes","isExtraTheme","isScreenModeDark","screenMode","getThemeClassName","classes","useTheme","useContext","ThemeContext","useMemo","isModern","className","ThemedChildren","children","_jsx","createContext","undefined","ThemeProvider","isRootProvider","themeClass","RegExp","useEffect","documentElement","match","map","item","document","classList","remove","split","forEach","add","Provider","value"],"mappings":"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"}
|
package/dist/es/index.d.ts
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { PropsWithChildren } from "react";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
];
|
|
9
|
-
type
|
|
3
|
+
// TODO: Change 'light' with 'legacy' in future
|
|
4
|
+
declare const baseThemes: string[];
|
|
5
|
+
declare const extraThemes: string[];
|
|
6
|
+
declare const screenModes: string[];
|
|
7
|
+
type BaseTheme = (typeof baseThemes)[number];
|
|
8
|
+
type ExtraTheme = (typeof extraThemes)[number];
|
|
9
|
+
type ScreenMode = (typeof screenModes)[number];
|
|
10
10
|
type Theming = {
|
|
11
|
-
theme?:
|
|
11
|
+
theme?: BaseTheme | ExtraTheme;
|
|
12
|
+
screenMode?: ScreenMode;
|
|
12
13
|
};
|
|
13
14
|
type ThemeProviderProps = PropsWithChildren<Theming>;
|
|
14
|
-
declare const ThemeProvider: ({ theme, children }: ThemeProviderProps) => JSX.Element;
|
|
15
|
+
declare const ThemeProvider: ({ theme, screenMode, children }: ThemeProviderProps) => JSX.Element;
|
|
15
16
|
interface ThemeHookValue {
|
|
16
|
-
theme:
|
|
17
|
+
theme: BaseTheme | ExtraTheme;
|
|
18
|
+
screenMode: ScreenMode;
|
|
17
19
|
isModern: boolean;
|
|
18
|
-
|
|
20
|
+
isScreenModeDark: boolean;
|
|
19
21
|
className: string;
|
|
20
22
|
}
|
|
21
23
|
declare const useTheme: () => ThemeHookValue;
|
|
22
|
-
export type {
|
|
24
|
+
export type { BaseTheme, ExtraTheme, ScreenMode, Theming };
|
|
23
25
|
export { ThemeProvider, useTheme };
|
package/dist/es/index.js
CHANGED
|
@@ -1,32 +1,50 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { useContext, useMemo, createContext, useEffect } from 'react';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
var
|
|
6
|
-
var
|
|
4
|
+
// TODO: Change 'light' with 'legacy' in future
|
|
5
|
+
var extraThemes = ['forest-green'];
|
|
6
|
+
var DEFAULT_BASE_THEME = 'light';
|
|
7
|
+
var DEFAULT_SCREEN_MODE = 'light';
|
|
7
8
|
|
|
8
9
|
var isThemeModern = function isThemeModern(theme) {
|
|
9
|
-
return
|
|
10
|
+
return extraThemes.includes(theme) || theme === 'personal';
|
|
10
11
|
};
|
|
11
|
-
var
|
|
12
|
-
return
|
|
12
|
+
var isExtraTheme = function isExtraTheme(theme) {
|
|
13
|
+
return extraThemes.includes(theme);
|
|
13
14
|
};
|
|
14
|
-
var
|
|
15
|
-
return
|
|
15
|
+
var isScreenModeDark = function isScreenModeDark(theme, screenMode) {
|
|
16
|
+
return theme !== DEFAULT_BASE_THEME && screenMode === 'dark';
|
|
17
|
+
};
|
|
18
|
+
var getThemeClassName = function getThemeClassName(theme, screenMode) {
|
|
19
|
+
if (!isThemeModern(theme)) {
|
|
20
|
+
return "np-theme-".concat(theme);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
var classes = "np-theme-personal";
|
|
24
|
+
|
|
25
|
+
if (isExtraTheme(theme)) {
|
|
26
|
+
classes += " ".concat(classes, "--").concat(theme);
|
|
27
|
+
} else if (screenMode === 'dark') {
|
|
28
|
+
classes += " ".concat(classes, "--").concat(screenMode);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return classes;
|
|
16
32
|
};
|
|
17
33
|
|
|
18
34
|
var useTheme = function useTheme() {
|
|
19
|
-
var _useContext;
|
|
35
|
+
var _useContext$theme, _useContext$screenMod;
|
|
20
36
|
|
|
21
|
-
var theme = (_useContext = useContext(ThemeContext)) !== null && _useContext !== void 0 ? _useContext :
|
|
37
|
+
var theme = (_useContext$theme = useContext(ThemeContext).theme) !== null && _useContext$theme !== void 0 ? _useContext$theme : DEFAULT_BASE_THEME;
|
|
38
|
+
var screenMode = theme !== DEFAULT_BASE_THEME ? (_useContext$screenMod = useContext(ThemeContext).screenMode) !== null && _useContext$screenMod !== void 0 ? _useContext$screenMod : DEFAULT_SCREEN_MODE : DEFAULT_SCREEN_MODE;
|
|
22
39
|
return useMemo(function () {
|
|
23
40
|
return {
|
|
24
41
|
theme: theme,
|
|
42
|
+
screenMode: screenMode,
|
|
25
43
|
isModern: isThemeModern(theme),
|
|
26
|
-
|
|
27
|
-
className: getThemeClassName(theme)
|
|
44
|
+
isScreenModeDark: isScreenModeDark(theme, screenMode),
|
|
45
|
+
className: getThemeClassName(theme, screenMode)
|
|
28
46
|
};
|
|
29
|
-
}, [theme]);
|
|
47
|
+
}, [theme, screenMode]);
|
|
30
48
|
};
|
|
31
49
|
|
|
32
50
|
var ThemedChildren = function ThemedChildren(_ref) {
|
|
@@ -41,12 +59,17 @@ var ThemedChildren = function ThemedChildren(_ref) {
|
|
|
41
59
|
});
|
|
42
60
|
};
|
|
43
61
|
|
|
44
|
-
var ThemeContext = /*#__PURE__*/createContext(
|
|
62
|
+
var ThemeContext = /*#__PURE__*/createContext({
|
|
63
|
+
theme: undefined,
|
|
64
|
+
screenMode: undefined
|
|
65
|
+
});
|
|
45
66
|
var ThemeProvider = function ThemeProvider(_ref) {
|
|
46
67
|
var _ref$theme = _ref.theme,
|
|
47
|
-
theme = _ref$theme === void 0 ?
|
|
68
|
+
theme = _ref$theme === void 0 ? DEFAULT_BASE_THEME : _ref$theme,
|
|
69
|
+
_ref$screenMode = _ref.screenMode,
|
|
70
|
+
screenMode = _ref$screenMode === void 0 ? DEFAULT_SCREEN_MODE : _ref$screenMode,
|
|
48
71
|
children = _ref.children;
|
|
49
|
-
var isRootProvider = useContext(ThemeContext) === undefined; // RegEx to check for `np-theme-` class name
|
|
72
|
+
var isRootProvider = useContext(ThemeContext).theme === undefined; // RegEx to check for `np-theme-` class name
|
|
50
73
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
51
74
|
|
|
52
75
|
var themeClass = new RegExp(/\bnp-theme-[a-z-]+\b/, 'g'); // useEffect hook used to apply the theme class to the HTML element
|
|
@@ -58,17 +81,17 @@ var ThemeProvider = function ThemeProvider(_ref) {
|
|
|
58
81
|
// Remove all the theme classes from the documentElement
|
|
59
82
|
(_document$documentEle = document.documentElement.className.match(themeClass)) === null || _document$documentEle === void 0 ? void 0 : _document$documentEle.map(function (item) {
|
|
60
83
|
document.documentElement.classList.remove(item);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
document.documentElement.classList.add("np-theme-".concat(theme));
|
|
84
|
+
});
|
|
85
|
+
getThemeClassName(theme, screenMode).split(' ').forEach(function (item) {
|
|
86
|
+
document.documentElement.classList.add(item);
|
|
87
|
+
});
|
|
68
88
|
}
|
|
69
|
-
}, [isRootProvider, theme,
|
|
89
|
+
}, [isRootProvider, theme, screenMode]);
|
|
70
90
|
return jsx(ThemeContext.Provider, {
|
|
71
|
-
value:
|
|
91
|
+
value: {
|
|
92
|
+
theme: theme,
|
|
93
|
+
screenMode: screenMode
|
|
94
|
+
},
|
|
72
95
|
children: jsx(ThemedChildren, {
|
|
73
96
|
children: children
|
|
74
97
|
})
|
package/dist/es/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/const.ts","../../src/helpers.ts","../../src/useTheme.ts","../../src/ThemedChildren.tsx","../../src/ThemeProvider.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/const.ts","../../src/helpers.ts","../../src/useTheme.ts","../../src/ThemedChildren.tsx","../../src/ThemeProvider.tsx"],"sourcesContent":["// TODO: Change 'light' with 'legacy' in future\nexport const baseThemes = ['light', 'personal'];\nexport const extraThemes = ['forest-green'];\nexport const screenModes = ['light', 'dark'];\n\nexport type BaseTheme = typeof baseThemes[number];\nexport type ExtraTheme = typeof extraThemes[number];\nexport type ScreenMode = typeof screenModes[number];\n\nexport const DEFAULT_BASE_THEME = 'light' as const;\nexport const DEFAULT_SCREEN_MODE = 'light' as const;\n\nexport type Theming = {\n theme?: BaseTheme | ExtraTheme;\n screenMode?: ScreenMode;\n};\n","import { BaseTheme, ScreenMode, ExtraTheme, extraThemes, DEFAULT_BASE_THEME } from './const';\n\nexport const isThemeModern = (theme: BaseTheme | ExtraTheme): boolean =>\n extraThemes.includes(theme) || theme === 'personal';\n\nexport const isExtraTheme = (theme: ExtraTheme): theme is ExtraTheme =>\n extraThemes.includes(theme as ExtraTheme);\n\nexport const isScreenModeDark = (theme: BaseTheme, screenMode: ScreenMode): boolean =>\n theme !== DEFAULT_BASE_THEME && screenMode === 'dark';\n\nexport const getThemeClassName = (\n theme: BaseTheme | ExtraTheme,\n screenMode: ScreenMode,\n) => {\n if (!isThemeModern(theme)) {\n return `np-theme-${theme}`;\n }\n\n let classes = `np-theme-personal`;\n\n if (isExtraTheme(theme)) {\n classes += ` ${classes}--${theme}`;\n } else if (screenMode === 'dark' ) {\n classes += ` ${classes}--${screenMode}`;\n }\n\n return classes;\n};\n","import { useContext, useMemo } from 'react';\n\nimport { ThemeContext } from './ThemeProvider';\nimport { BaseTheme, ScreenMode, ExtraTheme, DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { isThemeModern, isScreenModeDark, getThemeClassName } from './helpers';\n\ninterface ThemeHookValue {\n theme: BaseTheme | ExtraTheme;\n screenMode: ScreenMode;\n isModern: boolean;\n isScreenModeDark: boolean;\n className: string;\n}\n\nexport const useTheme = (): ThemeHookValue => {\n const theme: BaseTheme | ExtraTheme = useContext(ThemeContext).theme ?? DEFAULT_BASE_THEME;\n const screenMode: ScreenMode = theme !== DEFAULT_BASE_THEME\n ? useContext(ThemeContext).screenMode ?? DEFAULT_SCREEN_MODE\n : DEFAULT_SCREEN_MODE;\n\n return useMemo(\n () => ({\n theme,\n screenMode,\n isModern: isThemeModern(theme),\n isScreenModeDark: isScreenModeDark(theme, screenMode),\n className: getThemeClassName(theme, screenMode),\n }),\n [theme, screenMode],\n );\n};\n","import { ReactNode } from 'react';\n\nimport { useTheme } from './useTheme';\n\ntype ThemedChildrenProps = { children: ReactNode };\n\nexport const ThemedChildren = ({ children }: ThemedChildrenProps) => {\n const { className } = useTheme();\n\n return <div className={className}>{children}</div>;\n};\n","import { createContext, PropsWithChildren, useContext, useEffect } from 'react';\n\nimport { ThemedChildren } from './ThemedChildren';\nimport { BaseTheme, ExtraTheme, ScreenMode, Theming, DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';\nimport { getThemeClassName } from './helpers';\n\nexport const ThemeContext = createContext<{\n theme: BaseTheme | ExtraTheme | undefined,\n screenMode: ScreenMode | undefined,\n}>({ theme: undefined, screenMode: undefined });\n\ntype ThemeProviderProps = PropsWithChildren<Theming>;\n\nexport const ThemeProvider = ({\n theme = DEFAULT_BASE_THEME,\n screenMode = DEFAULT_SCREEN_MODE,\n children,\n}: ThemeProviderProps) => {\n const isRootProvider = useContext(ThemeContext).theme === undefined;\n\n // RegEx to check for `np-theme-` class name\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const themeClass = new RegExp(/\\bnp-theme-[a-z-]+\\b/, 'g');\n\n // useEffect hook used to apply the theme class to the HTML element\n useEffect(() => {\n if (isRootProvider) {\n // Remove all the theme classes from the documentElement\n document.documentElement.className.match(themeClass)?.map((item) => {\n document.documentElement.classList.remove(item);\n });\n getThemeClassName(theme, screenMode).split(' ').forEach(item => {\n document.documentElement.classList.add(item);\n })\n }\n }, [isRootProvider, theme, screenMode]);\n\n return (\n <ThemeContext.Provider value={{ theme, screenMode }}>\n <ThemedChildren>{children}</ThemedChildren>\n </ThemeContext.Provider>\n );\n};\n"],"names":["extraThemes","DEFAULT_BASE_THEME","DEFAULT_SCREEN_MODE","isThemeModern","theme","includes","isExtraTheme","isScreenModeDark","screenMode","getThemeClassName","classes","useTheme","useContext","ThemeContext","useMemo","isModern","className","ThemedChildren","children","_jsx","createContext","undefined","ThemeProvider","isRootProvider","themeClass","RegExp","useEffect","documentElement","match","map","item","document","classList","remove","split","forEach","add","Provider","value"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wise/components-theming",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Provides theming support for the Wise Design system components",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
"dist/",
|
|
44
44
|
"src/"
|
|
45
45
|
],
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "fe552dbe8a4c3503c8e54f9c146d26080da5ea6a"
|
|
47
47
|
}
|
package/src/ThemeProvider.tsx
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { createContext, PropsWithChildren, useContext, useEffect } from 'react';
|
|
2
2
|
|
|
3
3
|
import { ThemedChildren } from './ThemedChildren';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { BaseTheme, ExtraTheme, ScreenMode, Theming, DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';
|
|
5
|
+
import { getThemeClassName } from './helpers';
|
|
6
6
|
|
|
7
|
-
export const ThemeContext = createContext<
|
|
7
|
+
export const ThemeContext = createContext<{
|
|
8
|
+
theme: BaseTheme | ExtraTheme | undefined,
|
|
9
|
+
screenMode: ScreenMode | undefined,
|
|
10
|
+
}>({ theme: undefined, screenMode: undefined });
|
|
8
11
|
|
|
9
12
|
type ThemeProviderProps = PropsWithChildren<Theming>;
|
|
10
13
|
|
|
11
14
|
export const ThemeProvider = ({
|
|
12
|
-
theme =
|
|
15
|
+
theme = DEFAULT_BASE_THEME,
|
|
16
|
+
screenMode = DEFAULT_SCREEN_MODE,
|
|
13
17
|
children,
|
|
14
18
|
}: ThemeProviderProps) => {
|
|
15
|
-
const isRootProvider = useContext(ThemeContext) === undefined;
|
|
19
|
+
const isRootProvider = useContext(ThemeContext).theme === undefined;
|
|
16
20
|
|
|
17
21
|
// RegEx to check for `np-theme-` class name
|
|
18
22
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -25,16 +29,14 @@ export const ThemeProvider = ({
|
|
|
25
29
|
document.documentElement.className.match(themeClass)?.map((item) => {
|
|
26
30
|
document.documentElement.classList.remove(item);
|
|
27
31
|
});
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
document.documentElement.classList.add(`np-theme-${theme}`);
|
|
32
|
+
getThemeClassName(theme, screenMode).split(' ').forEach(item => {
|
|
33
|
+
document.documentElement.classList.add(item);
|
|
34
|
+
})
|
|
33
35
|
}
|
|
34
|
-
}, [isRootProvider, theme,
|
|
36
|
+
}, [isRootProvider, theme, screenMode]);
|
|
35
37
|
|
|
36
38
|
return (
|
|
37
|
-
<ThemeContext.Provider value={theme}>
|
|
39
|
+
<ThemeContext.Provider value={{ theme, screenMode }}>
|
|
38
40
|
<ThemedChildren>{children}</ThemedChildren>
|
|
39
41
|
</ThemeContext.Provider>
|
|
40
42
|
);
|
package/src/const.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
export const
|
|
3
|
-
export const
|
|
1
|
+
// TODO: Change 'light' with 'legacy' in future
|
|
2
|
+
export const baseThemes = ['light', 'personal'];
|
|
3
|
+
export const extraThemes = ['forest-green'];
|
|
4
|
+
export const screenModes = ['light', 'dark'];
|
|
4
5
|
|
|
5
|
-
export type
|
|
6
|
-
export type
|
|
7
|
-
export type
|
|
6
|
+
export type BaseTheme = typeof baseThemes[number];
|
|
7
|
+
export type ExtraTheme = typeof extraThemes[number];
|
|
8
|
+
export type ScreenMode = typeof screenModes[number];
|
|
8
9
|
|
|
9
|
-
export const
|
|
10
|
+
export const DEFAULT_BASE_THEME = 'light' as const;
|
|
11
|
+
export const DEFAULT_SCREEN_MODE = 'light' as const;
|
|
10
12
|
|
|
11
13
|
export type Theming = {
|
|
12
|
-
theme?:
|
|
14
|
+
theme?: BaseTheme | ExtraTheme;
|
|
15
|
+
screenMode?: ScreenMode;
|
|
13
16
|
};
|
package/src/helpers.ts
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BaseTheme, ScreenMode, ExtraTheme, extraThemes, DEFAULT_BASE_THEME } from './const';
|
|
2
2
|
|
|
3
|
-
export const isThemeModern = (theme:
|
|
4
|
-
|
|
3
|
+
export const isThemeModern = (theme: BaseTheme | ExtraTheme): boolean =>
|
|
4
|
+
extraThemes.includes(theme) || theme === 'personal';
|
|
5
5
|
|
|
6
|
-
export const
|
|
7
|
-
|
|
6
|
+
export const isExtraTheme = (theme: ExtraTheme): theme is ExtraTheme =>
|
|
7
|
+
extraThemes.includes(theme as ExtraTheme);
|
|
8
8
|
|
|
9
|
-
export const
|
|
9
|
+
export const isScreenModeDark = (theme: BaseTheme, screenMode: ScreenMode): boolean =>
|
|
10
|
+
theme !== DEFAULT_BASE_THEME && screenMode === 'dark';
|
|
11
|
+
|
|
12
|
+
export const getThemeClassName = (
|
|
13
|
+
theme: BaseTheme | ExtraTheme,
|
|
14
|
+
screenMode: ScreenMode,
|
|
15
|
+
) => {
|
|
16
|
+
if (!isThemeModern(theme)) {
|
|
17
|
+
return `np-theme-${theme}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let classes = `np-theme-personal`;
|
|
21
|
+
|
|
22
|
+
if (isExtraTheme(theme)) {
|
|
23
|
+
classes += ` ${classes}--${theme}`;
|
|
24
|
+
} else if (screenMode === 'dark' ) {
|
|
25
|
+
classes += ` ${classes}--${screenMode}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return classes;
|
|
29
|
+
};
|
package/src/index.ts
CHANGED
package/src/useTheme.spec.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { renderHook } from '@testing-library/react-hooks';
|
|
2
2
|
|
|
3
|
+
import { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';
|
|
3
4
|
import { ThemeProvider } from './ThemeProvider';
|
|
4
5
|
import { useTheme } from './useTheme';
|
|
5
6
|
|
|
@@ -10,14 +11,15 @@ describe('useTheme', () => {
|
|
|
10
11
|
} = renderHook(() => useTheme());
|
|
11
12
|
|
|
12
13
|
expect(current).toStrictEqual({
|
|
13
|
-
theme:
|
|
14
|
+
theme: DEFAULT_BASE_THEME,
|
|
15
|
+
screenMode: DEFAULT_SCREEN_MODE,
|
|
14
16
|
isModern: false,
|
|
15
|
-
|
|
17
|
+
isScreenModeDark: false,
|
|
16
18
|
className: 'np-theme-light',
|
|
17
19
|
});
|
|
18
20
|
});
|
|
19
21
|
|
|
20
|
-
it('returns
|
|
22
|
+
it('returns personal theme', () => {
|
|
21
23
|
const {
|
|
22
24
|
result: { current },
|
|
23
25
|
} = renderHook(() => useTheme(), {
|
|
@@ -28,10 +30,70 @@ describe('useTheme', () => {
|
|
|
28
30
|
});
|
|
29
31
|
|
|
30
32
|
expect(current).toStrictEqual({
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
theme: 'personal',
|
|
34
|
+
screenMode: DEFAULT_SCREEN_MODE,
|
|
33
35
|
isModern: true,
|
|
36
|
+
isScreenModeDark: false,
|
|
37
|
+
className: 'np-theme-personal',
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('returns default screen mode if used default light theme', () => {
|
|
42
|
+
const {
|
|
43
|
+
result: { current },
|
|
44
|
+
} = renderHook(() => useTheme(), {
|
|
45
|
+
wrapper: ThemeProvider,
|
|
46
|
+
initialProps: {
|
|
47
|
+
theme: DEFAULT_BASE_THEME,
|
|
48
|
+
screenMode: 'dark' as const,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
expect(current).toStrictEqual({
|
|
53
|
+
theme: DEFAULT_BASE_THEME,
|
|
54
|
+
screenMode: DEFAULT_SCREEN_MODE,
|
|
55
|
+
isModern: false,
|
|
56
|
+
isScreenModeDark: false,
|
|
57
|
+
className: 'np-theme-light',
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('returns dark screen mode', () => {
|
|
62
|
+
const {
|
|
63
|
+
result: { current },
|
|
64
|
+
} = renderHook(() => useTheme(), {
|
|
65
|
+
wrapper: ThemeProvider,
|
|
66
|
+
initialProps: {
|
|
67
|
+
theme: 'personal' as const,
|
|
68
|
+
screenMode: 'dark' as const,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
expect(current).toStrictEqual({
|
|
34
73
|
theme: 'personal',
|
|
74
|
+
screenMode: 'dark',
|
|
75
|
+
isModern: true,
|
|
76
|
+
isScreenModeDark: true,
|
|
77
|
+
className: 'np-theme-personal np-theme-personal--dark',
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('returns forest-green theme', () => {
|
|
82
|
+
const {
|
|
83
|
+
result: { current },
|
|
84
|
+
} = renderHook(() => useTheme(), {
|
|
85
|
+
wrapper: ThemeProvider,
|
|
86
|
+
initialProps: {
|
|
87
|
+
theme: 'forest-green' as const,
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(current).toStrictEqual({
|
|
92
|
+
theme: 'forest-green',
|
|
93
|
+
screenMode: DEFAULT_SCREEN_MODE,
|
|
94
|
+
isModern: true,
|
|
95
|
+
isScreenModeDark: false,
|
|
96
|
+
className: 'np-theme-personal np-theme-personal--forest-green',
|
|
35
97
|
});
|
|
36
98
|
});
|
|
37
99
|
});
|
package/src/useTheme.ts
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
import { useContext, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
import { ThemeContext } from './ThemeProvider';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { BaseTheme, ScreenMode, ExtraTheme, DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';
|
|
5
|
+
import { isThemeModern, isScreenModeDark, getThemeClassName } from './helpers';
|
|
6
6
|
|
|
7
7
|
interface ThemeHookValue {
|
|
8
|
-
theme:
|
|
8
|
+
theme: BaseTheme | ExtraTheme;
|
|
9
|
+
screenMode: ScreenMode;
|
|
9
10
|
isModern: boolean;
|
|
10
|
-
|
|
11
|
+
isScreenModeDark: boolean;
|
|
11
12
|
className: string;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export const useTheme = (): ThemeHookValue => {
|
|
15
|
-
const theme = useContext(ThemeContext) ??
|
|
16
|
+
const theme: BaseTheme | ExtraTheme = useContext(ThemeContext).theme ?? DEFAULT_BASE_THEME;
|
|
17
|
+
const screenMode: ScreenMode = theme !== DEFAULT_BASE_THEME
|
|
18
|
+
? useContext(ThemeContext).screenMode ?? DEFAULT_SCREEN_MODE
|
|
19
|
+
: DEFAULT_SCREEN_MODE;
|
|
16
20
|
|
|
17
21
|
return useMemo(
|
|
18
22
|
() => ({
|
|
19
23
|
theme,
|
|
24
|
+
screenMode,
|
|
20
25
|
isModern: isThemeModern(theme),
|
|
21
|
-
|
|
22
|
-
className: getThemeClassName(theme),
|
|
26
|
+
isScreenModeDark: isScreenModeDark(theme, screenMode),
|
|
27
|
+
className: getThemeClassName(theme, screenMode),
|
|
23
28
|
}),
|
|
24
|
-
[theme],
|
|
29
|
+
[theme, screenMode],
|
|
25
30
|
);
|
|
26
31
|
};
|