@fibery/ui-kit 1.0.5 → 1.0.6
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/package.json +3 -1
- package/src/media-query-utils.ts +24 -0
- package/src/theme-settings.ts +100 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fibery/ui-kit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"private": false,
|
|
6
6
|
"files": [
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
"src/Button.d.ts",
|
|
9
9
|
"src/Button.js",
|
|
10
10
|
"src/designSystem.ts",
|
|
11
|
+
"src/theme-settings.ts",
|
|
12
|
+
"src/media-query-utils.ts",
|
|
11
13
|
"src/create-inline-theme.ts",
|
|
12
14
|
"src/form-field-loader.tsx",
|
|
13
15
|
"src/ThemeProvider.tsx",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
2
|
+
const noop = () => {};
|
|
3
|
+
export function getMediaQueryList(query: string) {
|
|
4
|
+
// need for test
|
|
5
|
+
return typeof window !== undefined && window.matchMedia
|
|
6
|
+
? window.matchMedia(query)
|
|
7
|
+
: ({matches: false, addEventListener: noop, removeEventListener: noop} as unknown as MediaQueryList);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function subscribeOnChange(mediaQueryList: MediaQueryList, cb: (evt: MediaQueryListEvent) => void): () => void {
|
|
11
|
+
// Safari 13 doesn't support addEventListener here
|
|
12
|
+
if (mediaQueryList.addEventListener) {
|
|
13
|
+
mediaQueryList.addEventListener("change", cb);
|
|
14
|
+
return () => {
|
|
15
|
+
mediaQueryList.removeEventListener("change", cb);
|
|
16
|
+
};
|
|
17
|
+
} else if (mediaQueryList.addListener) {
|
|
18
|
+
mediaQueryList.addListener(cb);
|
|
19
|
+
return () => {
|
|
20
|
+
mediaQueryList.removeListener(cb);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return noop;
|
|
24
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {getMediaQueryList, subscribeOnChange as subscribeOnMediaQueryChange} from "./media-query-utils";
|
|
2
|
+
|
|
3
|
+
const listenersThemeMode = new Map();
|
|
4
|
+
const listenersThemePreference = new Map();
|
|
5
|
+
|
|
6
|
+
const themePreferenceKey = "theme-preference";
|
|
7
|
+
|
|
8
|
+
export type ThemePreference = "dark" | "light" | "auto";
|
|
9
|
+
|
|
10
|
+
export type ThemeMode = "dark" | "light" | "old";
|
|
11
|
+
|
|
12
|
+
export function getThemePreference(): ThemePreference {
|
|
13
|
+
try {
|
|
14
|
+
const item = localStorage.getItem(themePreferenceKey);
|
|
15
|
+
if (item === "auto") {
|
|
16
|
+
return "auto";
|
|
17
|
+
} else if (item === "dark") {
|
|
18
|
+
return "dark";
|
|
19
|
+
} else if (item === "light") {
|
|
20
|
+
return "light";
|
|
21
|
+
}
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return "auto";
|
|
24
|
+
}
|
|
25
|
+
return "auto";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const darkModeQuery = "(prefers-color-scheme: dark)";
|
|
29
|
+
|
|
30
|
+
function getDarkMediaQuery() {
|
|
31
|
+
return getMediaQueryList(darkModeQuery);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getThemeMode(): ThemeMode {
|
|
35
|
+
const preference = getThemePreference();
|
|
36
|
+
|
|
37
|
+
if (preference === "auto") {
|
|
38
|
+
return getDarkMediaQuery().matches ? "dark" : "light";
|
|
39
|
+
} else if (preference === "dark") {
|
|
40
|
+
return "dark";
|
|
41
|
+
}
|
|
42
|
+
return "light";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function setThemePreference(preference: ThemePreference) {
|
|
46
|
+
try {
|
|
47
|
+
if (getThemePreference() !== preference) {
|
|
48
|
+
localStorage.setItem(themePreferenceKey, preference);
|
|
49
|
+
listenersThemeMode.forEach((cb) => {
|
|
50
|
+
cb(getThemeMode());
|
|
51
|
+
});
|
|
52
|
+
listenersThemePreference.forEach((cb) => {
|
|
53
|
+
cb(preference);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
} catch (e) {
|
|
57
|
+
// skip error
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function subscribeOnThemePreferenceChange(cb: (themePreference: ThemePreference) => void): () => void {
|
|
62
|
+
listenersThemePreference.set(cb, cb);
|
|
63
|
+
let currentPref = getThemePreference();
|
|
64
|
+
const storageListener = () => {
|
|
65
|
+
const newPref = getThemePreference();
|
|
66
|
+
if (currentPref !== newPref) {
|
|
67
|
+
currentPref = newPref;
|
|
68
|
+
cb(newPref);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
window.addEventListener("storage", storageListener);
|
|
72
|
+
return () => {
|
|
73
|
+
listenersThemePreference.delete(cb);
|
|
74
|
+
window.removeEventListener("storage", storageListener);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function subscribeOnThemeModeChange(cb: (themeMode: ThemeMode) => void): () => void {
|
|
79
|
+
listenersThemeMode.set(cb, cb);
|
|
80
|
+
let currentPref = getThemePreference();
|
|
81
|
+
const darkMediaQuery = getDarkMediaQuery();
|
|
82
|
+
const storageListener = () => {
|
|
83
|
+
const newPref = getThemePreference();
|
|
84
|
+
if (currentPref !== newPref) {
|
|
85
|
+
currentPref = newPref;
|
|
86
|
+
cb(getThemeMode());
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
window.addEventListener("storage", storageListener);
|
|
90
|
+
const unsubscribe = subscribeOnMediaQueryChange(darkMediaQuery, () => {
|
|
91
|
+
if (getThemePreference() === "auto") {
|
|
92
|
+
cb(getThemeMode());
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return () => {
|
|
96
|
+
listenersThemeMode.delete(cb);
|
|
97
|
+
unsubscribe();
|
|
98
|
+
window.removeEventListener("storage", storageListener);
|
|
99
|
+
};
|
|
100
|
+
}
|