@docusaurus/theme-common 3.7.0-canary-6252 → 3.7.0-canary-6254
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.
|
@@ -5,20 +5,19 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import { type ReactNode } from 'react';
|
|
8
|
+
export type ColorMode = 'light' | 'dark';
|
|
9
|
+
export type ColorModeChoice = ColorMode | null;
|
|
8
10
|
type ContextValue = {
|
|
9
|
-
/**
|
|
11
|
+
/** The effective color mode. */
|
|
10
12
|
readonly colorMode: ColorMode;
|
|
13
|
+
/** The explicitly chosen color mode */
|
|
14
|
+
readonly colorModeChoice: ColorModeChoice;
|
|
11
15
|
/** Set new color mode. */
|
|
12
|
-
readonly setColorMode: (colorMode:
|
|
16
|
+
readonly setColorMode: (colorMode: ColorModeChoice) => void;
|
|
13
17
|
readonly isDarkTheme: boolean;
|
|
14
18
|
readonly setLightTheme: () => void;
|
|
15
19
|
readonly setDarkTheme: () => void;
|
|
16
20
|
};
|
|
17
|
-
declare const ColorModes: {
|
|
18
|
-
readonly light: "light";
|
|
19
|
-
readonly dark: "dark";
|
|
20
|
-
};
|
|
21
|
-
export type ColorMode = (typeof ColorModes)[keyof typeof ColorModes];
|
|
22
21
|
export declare function ColorModeProvider({ children, }: {
|
|
23
22
|
children: ReactNode;
|
|
24
23
|
}): ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"colorMode.d.ts","sourceRoot":"","sources":["../../src/contexts/colorMode.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAc,
|
|
1
|
+
{"version":3,"file":"colorMode.d.ts","sourceRoot":"","sources":["../../src/contexts/colorMode.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAc,EAMZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAMf,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAIzC,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,IAAI,CAAC;AAyB/C,KAAK,YAAY,GAAG;IAClB,gCAAgC;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,uCAAuC;IACvC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,0BAA0B;IAC1B,QAAQ,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,eAAe,KAAK,IAAI,CAAC;IAI5D,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,IAAI,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC;CACnC,CAAC;AAsMF,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;CACrB,GAAG,SAAS,CAGZ;AAED,wBAAgB,YAAY,IAAI,YAAY,CAS3C"}
|
|
@@ -4,20 +4,34 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import React, { useState, useCallback, useEffect, useContext, useMemo,
|
|
8
|
-
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
|
7
|
+
import React, { useState, useCallback, useEffect, useContext, useMemo, } from 'react';
|
|
9
8
|
import { ReactContextError } from '../utils/reactUtils';
|
|
10
9
|
import { createStorageSlot } from '../utils/storageUtils';
|
|
11
10
|
import { useThemeConfig } from '../utils/useThemeConfig';
|
|
11
|
+
function getSystemColorMode() {
|
|
12
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
13
|
+
? 'dark'
|
|
14
|
+
: 'light';
|
|
15
|
+
}
|
|
16
|
+
function subscribeToMedia(query, listener) {
|
|
17
|
+
const mql = window.matchMedia(query);
|
|
18
|
+
mql.addEventListener('change', listener);
|
|
19
|
+
return () => mql.removeEventListener('change', listener);
|
|
20
|
+
}
|
|
21
|
+
function subscribeToSystemColorModeChange(onChange) {
|
|
22
|
+
return subscribeToMedia('(prefers-color-scheme: dark)', () => onChange(getSystemColorMode()));
|
|
23
|
+
}
|
|
12
24
|
const Context = React.createContext(undefined);
|
|
13
25
|
const ColorModeStorageKey = 'theme';
|
|
14
26
|
const ColorModeStorage = createStorageSlot(ColorModeStorageKey);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
};
|
|
27
|
+
// We use data-theme-choice="system", not an absent attribute
|
|
28
|
+
// This is easier to handle for users with CSS
|
|
29
|
+
const SystemAttribute = 'system';
|
|
19
30
|
// Ensure to always return a valid colorMode even if input is invalid
|
|
20
|
-
const coerceToColorMode = (colorMode) => colorMode ===
|
|
31
|
+
const coerceToColorMode = (colorMode) => colorMode === 'dark' ? 'dark' : 'light';
|
|
32
|
+
const coerceToColorModeChoice = (colorMode) => colorMode === null || colorMode === SystemAttribute
|
|
33
|
+
? null
|
|
34
|
+
: coerceToColorMode(colorMode);
|
|
21
35
|
const ColorModeAttribute = {
|
|
22
36
|
get: () => {
|
|
23
37
|
return coerceToColorMode(document.documentElement.getAttribute('data-theme'));
|
|
@@ -26,14 +40,21 @@ const ColorModeAttribute = {
|
|
|
26
40
|
document.documentElement.setAttribute('data-theme', coerceToColorMode(colorMode));
|
|
27
41
|
},
|
|
28
42
|
};
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
43
|
+
const ColorModeChoiceAttribute = {
|
|
44
|
+
get: () => {
|
|
45
|
+
return coerceToColorModeChoice(document.documentElement.getAttribute('data-theme-choice'));
|
|
46
|
+
},
|
|
47
|
+
set: (colorMode) => {
|
|
48
|
+
document.documentElement.setAttribute('data-theme-choice', coerceToColorModeChoice(colorMode) ?? SystemAttribute);
|
|
49
|
+
},
|
|
34
50
|
};
|
|
35
|
-
const
|
|
36
|
-
|
|
51
|
+
const persistColorModeChoice = (newColorMode) => {
|
|
52
|
+
if (newColorMode === null) {
|
|
53
|
+
ColorModeStorage.del();
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
ColorModeStorage.set(coerceToColorMode(newColorMode));
|
|
57
|
+
}
|
|
37
58
|
};
|
|
38
59
|
// The color mode state is initialized in useEffect on purpose
|
|
39
60
|
// to avoid a React hydration mismatch errors
|
|
@@ -43,14 +64,21 @@ const storeColorMode = (newColorMode) => {
|
|
|
43
64
|
function useColorModeState() {
|
|
44
65
|
const { colorMode: { defaultMode }, } = useThemeConfig();
|
|
45
66
|
const [colorMode, setColorModeState] = useState(defaultMode);
|
|
67
|
+
const [colorModeChoice, setColorModeChoiceState] = useState(null);
|
|
46
68
|
useEffect(() => {
|
|
47
|
-
setColorModeState(
|
|
69
|
+
setColorModeState(ColorModeAttribute.get());
|
|
70
|
+
setColorModeChoiceState(ColorModeChoiceAttribute.get());
|
|
48
71
|
}, []);
|
|
49
|
-
return
|
|
72
|
+
return {
|
|
73
|
+
colorMode,
|
|
74
|
+
setColorModeState,
|
|
75
|
+
colorModeChoice,
|
|
76
|
+
setColorModeChoiceState,
|
|
77
|
+
};
|
|
50
78
|
}
|
|
51
79
|
function useContextValue() {
|
|
52
80
|
const { colorMode: { defaultMode, disableSwitch, respectPrefersColorScheme }, } = useThemeConfig();
|
|
53
|
-
const
|
|
81
|
+
const { colorMode, setColorModeState, colorModeChoice, setColorModeChoiceState, } = useColorModeState();
|
|
54
82
|
useEffect(() => {
|
|
55
83
|
// A site is deployed without disableSwitch
|
|
56
84
|
// => User visits the site and has a persisted value
|
|
@@ -60,81 +88,79 @@ function useContextValue() {
|
|
|
60
88
|
ColorModeStorage.del();
|
|
61
89
|
}
|
|
62
90
|
}, [disableSwitch]);
|
|
63
|
-
const setColorMode = useCallback((
|
|
91
|
+
const setColorMode = useCallback((newColorModeChoice, options = {}) => {
|
|
64
92
|
const { persist = true } = options;
|
|
65
|
-
|
|
93
|
+
// Reset to system/default color mode
|
|
94
|
+
if (newColorModeChoice === null) {
|
|
95
|
+
// Set the effective color
|
|
96
|
+
const newColorMode = respectPrefersColorScheme
|
|
97
|
+
? getSystemColorMode()
|
|
98
|
+
: defaultMode;
|
|
66
99
|
ColorModeAttribute.set(newColorMode);
|
|
67
100
|
setColorModeState(newColorMode);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
101
|
+
// Set the chosen color
|
|
102
|
+
ColorModeChoiceAttribute.set(null);
|
|
103
|
+
setColorModeChoiceState(null);
|
|
71
104
|
}
|
|
105
|
+
// Happy case, when an explicit color is provided
|
|
72
106
|
else {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
: ColorModes.light;
|
|
78
|
-
ColorModeAttribute.set(osColorMode);
|
|
79
|
-
setColorModeState(osColorMode);
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
ColorModeAttribute.set(defaultMode);
|
|
83
|
-
setColorModeState(defaultMode);
|
|
84
|
-
}
|
|
85
|
-
ColorModeStorage.del();
|
|
107
|
+
ColorModeAttribute.set(newColorModeChoice);
|
|
108
|
+
ColorModeChoiceAttribute.set(newColorModeChoice);
|
|
109
|
+
setColorModeState(newColorModeChoice);
|
|
110
|
+
setColorModeChoiceState(newColorModeChoice);
|
|
86
111
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (disableSwitch) {
|
|
90
|
-
return undefined;
|
|
112
|
+
if (persist) {
|
|
113
|
+
persistColorModeChoice(newColorModeChoice);
|
|
91
114
|
}
|
|
115
|
+
}, [
|
|
116
|
+
setColorModeState,
|
|
117
|
+
setColorModeChoiceState,
|
|
118
|
+
respectPrefersColorScheme,
|
|
119
|
+
defaultMode,
|
|
120
|
+
]);
|
|
121
|
+
// Synchronize theme color/choice mode with browser storage
|
|
122
|
+
useEffect(() => {
|
|
92
123
|
return ColorModeStorage.listen((e) => {
|
|
93
|
-
setColorMode(
|
|
124
|
+
setColorMode(coerceToColorModeChoice(e.newValue));
|
|
94
125
|
});
|
|
95
|
-
}, [
|
|
96
|
-
//
|
|
97
|
-
// be reset to dark when exiting print mode, disregarding user settings. When
|
|
98
|
-
// the listener fires only because of a print/screen switch, we don't change
|
|
99
|
-
// color mode. See https://github.com/facebook/docusaurus/pull/6490
|
|
100
|
-
const previousMediaIsPrint = useRef(false);
|
|
126
|
+
}, [setColorMode]);
|
|
127
|
+
// Synchronize theme color with system color
|
|
101
128
|
useEffect(() => {
|
|
102
|
-
if (
|
|
129
|
+
if (colorModeChoice !== null || !respectPrefersColorScheme) {
|
|
103
130
|
return undefined;
|
|
104
131
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
return () => mql.removeListener(onChange);
|
|
115
|
-
}, [setColorMode, disableSwitch, respectPrefersColorScheme]);
|
|
132
|
+
return subscribeToSystemColorModeChange((newSystemColorMode) => {
|
|
133
|
+
// Note: we don't use "setColorMode" on purpose
|
|
134
|
+
// The system changes should never be considered an explicit theme choice
|
|
135
|
+
// They only affect the "effective" color, and should never be persisted
|
|
136
|
+
// Note: this listener also fire when printing, see https://github.com/facebook/docusaurus/pull/6490
|
|
137
|
+
setColorModeState(newSystemColorMode);
|
|
138
|
+
ColorModeAttribute.set(newSystemColorMode);
|
|
139
|
+
});
|
|
140
|
+
}, [respectPrefersColorScheme, colorModeChoice, setColorModeState]);
|
|
116
141
|
return useMemo(() => ({
|
|
117
142
|
colorMode,
|
|
143
|
+
colorModeChoice,
|
|
118
144
|
setColorMode,
|
|
119
145
|
get isDarkTheme() {
|
|
120
146
|
if (process.env.NODE_ENV === 'development') {
|
|
121
147
|
console.error('`useColorMode().isDarkTheme` is deprecated. Please use `useColorMode().colorMode === "dark"` instead.');
|
|
122
148
|
}
|
|
123
|
-
return colorMode ===
|
|
149
|
+
return colorMode === 'dark';
|
|
124
150
|
},
|
|
125
151
|
setLightTheme() {
|
|
126
152
|
if (process.env.NODE_ENV === 'development') {
|
|
127
153
|
console.error('`useColorMode().setLightTheme` is deprecated. Please use `useColorMode().setColorMode("light")` instead.');
|
|
128
154
|
}
|
|
129
|
-
setColorMode(
|
|
155
|
+
setColorMode('light');
|
|
130
156
|
},
|
|
131
157
|
setDarkTheme() {
|
|
132
158
|
if (process.env.NODE_ENV === 'development') {
|
|
133
159
|
console.error('`useColorMode().setDarkTheme` is deprecated. Please use `useColorMode().setColorMode("dark")` instead.');
|
|
134
160
|
}
|
|
135
|
-
setColorMode(
|
|
161
|
+
setColorMode('dark');
|
|
136
162
|
},
|
|
137
|
-
}), [colorMode, setColorMode]);
|
|
163
|
+
}), [colorMode, colorModeChoice, setColorMode]);
|
|
138
164
|
}
|
|
139
165
|
export function ColorModeProvider({ children, }) {
|
|
140
166
|
const value = useContextValue();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"colorMode.js","sourceRoot":"","sources":["../../src/contexts/colorMode.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,EACZ,QAAQ,EACR,WAAW,EACX,SAAS,EACT,UAAU,EACV,OAAO,
|
|
1
|
+
{"version":3,"file":"colorMode.js","sourceRoot":"","sources":["../../src/contexts/colorMode.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,EACZ,QAAQ,EACR,WAAW,EACX,SAAS,EACT,UAAU,EACV,OAAO,GAER,MAAM,OAAO,CAAC;AACf,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAC,iBAAiB,EAAC,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAC,cAAc,EAAC,MAAM,yBAAyB,CAAC;AASvD,SAAS,kBAAkB;IACzB,OAAO,MAAM,CAAC,UAAU,CAAC,8BAA8B,CAAC,CAAC,OAAO;QAC9D,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,OAAO,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CACvB,KAAa,EACb,QAA8C;IAE9C,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACrC,GAAG,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACzC,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,gCAAgC,CACvC,QAAiD;IAEjD,OAAO,gBAAgB,CAAC,8BAA8B,EAAE,GAAG,EAAE,CAC3D,QAAQ,CAAC,kBAAkB,EAAE,CAAC,CAC/B,CAAC;AACJ,CAAC;AAiBD,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAA2B,SAAS,CAAC,CAAC;AAEzE,MAAM,mBAAmB,GAAG,OAAO,CAAC;AACpC,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;AAEhE,6DAA6D;AAC7D,8CAA8C;AAC9C,MAAM,eAAe,GAAG,QAAQ,CAAC;AAEjC,qEAAqE;AACrE,MAAM,iBAAiB,GAAG,CAAC,SAAwB,EAAa,EAAE,CAChE,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;AAC1C,MAAM,uBAAuB,GAAG,CAAC,SAAwB,EAAmB,EAAE,CAC5E,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,eAAe;IACjD,CAAC,CAAC,IAAI;IACN,CAAC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;AAEnC,MAAM,kBAAkB,GAAG;IACzB,GAAG,EAAE,GAAG,EAAE;QACR,OAAO,iBAAiB,CACtB,QAAQ,CAAC,eAAe,CAAC,YAAY,CAAC,YAAY,CAAC,CACpD,CAAC;IACJ,CAAC;IACD,GAAG,EAAE,CAAC,SAAoB,EAAE,EAAE;QAC5B,QAAQ,CAAC,eAAe,CAAC,YAAY,CACnC,YAAY,EACZ,iBAAiB,CAAC,SAAS,CAAC,CAC7B,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,MAAM,wBAAwB,GAAG;IAC/B,GAAG,EAAE,GAAG,EAAE;QACR,OAAO,uBAAuB,CAC5B,QAAQ,CAAC,eAAe,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAC3D,CAAC;IACJ,CAAC;IACD,GAAG,EAAE,CAAC,SAA0B,EAAE,EAAE;QAClC,QAAQ,CAAC,eAAe,CAAC,YAAY,CACnC,mBAAmB,EACnB,uBAAuB,CAAC,SAAS,CAAC,IAAI,eAAe,CACtD,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAAC,YAA6B,EAAE,EAAE;IAC/D,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;QAC1B,gBAAgB,CAAC,GAAG,EAAE,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,gBAAgB,CAAC,GAAG,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC,CAAC;IACxD,CAAC;AACH,CAAC,CAAC;AAEF,8DAA8D;AAC9D,6CAA6C;AAC7C,uDAAuD;AACvD,iEAAiE;AACjE,8DAA8D;AAC9D,SAAS,iBAAiB;IACxB,MAAM,EACJ,SAAS,EAAE,EAAC,WAAW,EAAC,GACzB,GAAG,cAAc,EAAE,CAAC;IAErB,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAY,WAAW,CAAC,CAAC;IACxE,MAAM,CAAC,eAAe,EAAE,uBAAuB,CAAC,GAC9C,QAAQ,CAAkB,IAAI,CAAC,CAAC;IAElC,SAAS,CAAC,GAAG,EAAE;QACb,iBAAiB,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5C,uBAAuB,CAAC,wBAAwB,CAAC,GAAG,EAAE,CAAC,CAAC;IAC1D,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO;QACL,SAAS;QACT,iBAAiB;QACjB,eAAe;QACf,uBAAuB;KACf,CAAC;AACb,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,EACJ,SAAS,EAAE,EAAC,WAAW,EAAE,aAAa,EAAE,yBAAyB,EAAC,GACnE,GAAG,cAAc,EAAE,CAAC;IACrB,MAAM,EACJ,SAAS,EACT,iBAAiB,EACjB,eAAe,EACf,uBAAuB,GACxB,GAAG,iBAAiB,EAAE,CAAC;IAExB,SAAS,CAAC,GAAG,EAAE;QACb,2CAA2C;QAC3C,oDAAoD;QACpD,sCAAsC;QACtC,mEAAmE;QACnE,IAAI,aAAa,EAAE,CAAC;YAClB,gBAAgB,CAAC,GAAG,EAAE,CAAC;QACzB,CAAC;IACH,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,MAAM,YAAY,GAAG,WAAW,CAC9B,CACE,kBAAmC,EACnC,UAA+B,EAAE,EACjC,EAAE;QACF,MAAM,EAAC,OAAO,GAAG,IAAI,EAAC,GAAG,OAAO,CAAC;QAEjC,qCAAqC;QACrC,IAAI,kBAAkB,KAAK,IAAI,EAAE,CAAC;YAChC,0BAA0B;YAC1B,MAAM,YAAY,GAAG,yBAAyB;gBAC5C,CAAC,CAAC,kBAAkB,EAAE;gBACtB,CAAC,CAAC,WAAW,CAAC;YAChB,kBAAkB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YACrC,iBAAiB,CAAC,YAAY,CAAC,CAAC;YAChC,uBAAuB;YACvB,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACnC,uBAAuB,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QACD,iDAAiD;aAC5C,CAAC;YACJ,kBAAkB,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YAC3C,wBAAwB,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YACjD,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;YACtC,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC,EACD;QACE,iBAAiB;QACjB,uBAAuB;QACvB,yBAAyB;QACzB,WAAW;KACZ,CACF,CAAC;IAEF,2DAA2D;IAC3D,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACnC,YAAY,CAAC,uBAAuB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnB,4CAA4C;IAC5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,eAAe,KAAK,IAAI,IAAI,CAAC,yBAAyB,EAAE,CAAC;YAC3D,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,gCAAgC,CAAC,CAAC,kBAAkB,EAAE,EAAE;YAC7D,+CAA+C;YAC/C,yEAAyE;YACzE,wEAAwE;YACxE,oGAAoG;YACpG,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;YACtC,kBAAkB,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,yBAAyB,EAAE,eAAe,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAEpE,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,CAAC;QACL,SAAS;QACT,eAAe;QACf,YAAY;QACZ,IAAI,WAAW;YACb,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;gBAC3C,OAAO,CAAC,KAAK,CACX,uGAAuG,CACxG,CAAC;YACJ,CAAC;YACD,OAAO,SAAS,KAAK,MAAM,CAAC;QAC9B,CAAC;QACD,aAAa;YACX,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;gBAC3C,OAAO,CAAC,KAAK,CACX,0GAA0G,CAC3G,CAAC;YACJ,CAAC;YACD,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QACD,YAAY;YACV,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;gBAC3C,OAAO,CAAC,KAAK,CACX,wGAAwG,CACzG,CAAC;YACJ,CAAC;YACD,YAAY,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;KACF,CAAC,EACF,CAAC,SAAS,EAAE,eAAe,EAAE,YAAY,CAAC,CAC3C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,EAChC,QAAQ,GAGT;IACC,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,iBAAiB,CACzB,mBAAmB,EACnB,gFAAgF,CACjF,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/theme-common",
|
|
3
|
-
"version": "3.7.0-canary-
|
|
3
|
+
"version": "3.7.0-canary-6254",
|
|
4
4
|
"description": "Common code for Docusaurus themes.",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
},
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@docusaurus/mdx-loader": "3.7.0-canary-
|
|
34
|
-
"@docusaurus/module-type-aliases": "3.7.0-canary-
|
|
35
|
-
"@docusaurus/utils": "3.7.0-canary-
|
|
36
|
-
"@docusaurus/utils-common": "3.7.0-canary-
|
|
33
|
+
"@docusaurus/mdx-loader": "3.7.0-canary-6254",
|
|
34
|
+
"@docusaurus/module-type-aliases": "3.7.0-canary-6254",
|
|
35
|
+
"@docusaurus/utils": "3.7.0-canary-6254",
|
|
36
|
+
"@docusaurus/utils-common": "3.7.0-canary-6254",
|
|
37
37
|
"@types/history": "^4.7.11",
|
|
38
38
|
"@types/react": "*",
|
|
39
39
|
"@types/react-router-config": "*",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"utility-types": "^3.10.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@docusaurus/core": "3.7.0-canary-
|
|
48
|
-
"@docusaurus/types": "3.7.0-canary-
|
|
47
|
+
"@docusaurus/core": "3.7.0-canary-6254",
|
|
48
|
+
"@docusaurus/types": "3.7.0-canary-6254",
|
|
49
49
|
"fs-extra": "^11.1.1",
|
|
50
50
|
"lodash": "^4.17.21"
|
|
51
51
|
},
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"engines": {
|
|
58
58
|
"node": ">=18.0"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "a877206d157c7a960696a43ea62d43c0a5d211e9"
|
|
61
61
|
}
|
|
@@ -11,19 +11,49 @@ import React, {
|
|
|
11
11
|
useEffect,
|
|
12
12
|
useContext,
|
|
13
13
|
useMemo,
|
|
14
|
-
useRef,
|
|
15
14
|
type ReactNode,
|
|
16
15
|
} from 'react';
|
|
17
|
-
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
|
18
16
|
import {ReactContextError} from '../utils/reactUtils';
|
|
19
17
|
import {createStorageSlot} from '../utils/storageUtils';
|
|
20
18
|
import {useThemeConfig} from '../utils/useThemeConfig';
|
|
21
19
|
|
|
20
|
+
// The "effective" color mode
|
|
21
|
+
export type ColorMode = 'light' | 'dark';
|
|
22
|
+
|
|
23
|
+
// The color mode explicitly chosen by the user
|
|
24
|
+
// null => no choice has been made, or the choice has been reverted to OS value
|
|
25
|
+
export type ColorModeChoice = ColorMode | null;
|
|
26
|
+
|
|
27
|
+
function getSystemColorMode(): ColorMode {
|
|
28
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
29
|
+
? 'dark'
|
|
30
|
+
: 'light';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function subscribeToMedia(
|
|
34
|
+
query: string,
|
|
35
|
+
listener: (event: MediaQueryListEvent) => void,
|
|
36
|
+
): () => void {
|
|
37
|
+
const mql = window.matchMedia(query);
|
|
38
|
+
mql.addEventListener('change', listener);
|
|
39
|
+
return () => mql.removeEventListener('change', listener);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function subscribeToSystemColorModeChange(
|
|
43
|
+
onChange: (newSystemColorMode: ColorMode) => void,
|
|
44
|
+
): () => void {
|
|
45
|
+
return subscribeToMedia('(prefers-color-scheme: dark)', () =>
|
|
46
|
+
onChange(getSystemColorMode()),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
22
50
|
type ContextValue = {
|
|
23
|
-
/**
|
|
51
|
+
/** The effective color mode. */
|
|
24
52
|
readonly colorMode: ColorMode;
|
|
53
|
+
/** The explicitly chosen color mode */
|
|
54
|
+
readonly colorModeChoice: ColorModeChoice;
|
|
25
55
|
/** Set new color mode. */
|
|
26
|
-
readonly setColorMode: (colorMode:
|
|
56
|
+
readonly setColorMode: (colorMode: ColorModeChoice) => void;
|
|
27
57
|
|
|
28
58
|
// TODO Docusaurus v4
|
|
29
59
|
// legacy APIs kept for retro-compatibility: deprecate them
|
|
@@ -37,16 +67,17 @@ const Context = React.createContext<ContextValue | undefined>(undefined);
|
|
|
37
67
|
const ColorModeStorageKey = 'theme';
|
|
38
68
|
const ColorModeStorage = createStorageSlot(ColorModeStorageKey);
|
|
39
69
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
} as const;
|
|
44
|
-
|
|
45
|
-
export type ColorMode = (typeof ColorModes)[keyof typeof ColorModes];
|
|
70
|
+
// We use data-theme-choice="system", not an absent attribute
|
|
71
|
+
// This is easier to handle for users with CSS
|
|
72
|
+
const SystemAttribute = 'system';
|
|
46
73
|
|
|
47
74
|
// Ensure to always return a valid colorMode even if input is invalid
|
|
48
|
-
const coerceToColorMode = (colorMode
|
|
49
|
-
colorMode ===
|
|
75
|
+
const coerceToColorMode = (colorMode: string | null): ColorMode =>
|
|
76
|
+
colorMode === 'dark' ? 'dark' : 'light';
|
|
77
|
+
const coerceToColorModeChoice = (colorMode: string | null): ColorModeChoice =>
|
|
78
|
+
colorMode === null || colorMode === SystemAttribute
|
|
79
|
+
? null
|
|
80
|
+
: coerceToColorMode(colorMode);
|
|
50
81
|
|
|
51
82
|
const ColorModeAttribute = {
|
|
52
83
|
get: () => {
|
|
@@ -62,15 +93,26 @@ const ColorModeAttribute = {
|
|
|
62
93
|
},
|
|
63
94
|
};
|
|
64
95
|
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
96
|
+
const ColorModeChoiceAttribute = {
|
|
97
|
+
get: () => {
|
|
98
|
+
return coerceToColorModeChoice(
|
|
99
|
+
document.documentElement.getAttribute('data-theme-choice'),
|
|
100
|
+
);
|
|
101
|
+
},
|
|
102
|
+
set: (colorMode: ColorModeChoice) => {
|
|
103
|
+
document.documentElement.setAttribute(
|
|
104
|
+
'data-theme-choice',
|
|
105
|
+
coerceToColorModeChoice(colorMode) ?? SystemAttribute,
|
|
106
|
+
);
|
|
107
|
+
},
|
|
70
108
|
};
|
|
71
109
|
|
|
72
|
-
const
|
|
73
|
-
|
|
110
|
+
const persistColorModeChoice = (newColorMode: ColorModeChoice) => {
|
|
111
|
+
if (newColorMode === null) {
|
|
112
|
+
ColorModeStorage.del();
|
|
113
|
+
} else {
|
|
114
|
+
ColorModeStorage.set(coerceToColorMode(newColorMode));
|
|
115
|
+
}
|
|
74
116
|
};
|
|
75
117
|
|
|
76
118
|
// The color mode state is initialized in useEffect on purpose
|
|
@@ -83,20 +125,33 @@ function useColorModeState() {
|
|
|
83
125
|
colorMode: {defaultMode},
|
|
84
126
|
} = useThemeConfig();
|
|
85
127
|
|
|
86
|
-
const [colorMode, setColorModeState] = useState(defaultMode);
|
|
128
|
+
const [colorMode, setColorModeState] = useState<ColorMode>(defaultMode);
|
|
129
|
+
const [colorModeChoice, setColorModeChoiceState] =
|
|
130
|
+
useState<ColorModeChoice>(null);
|
|
87
131
|
|
|
88
132
|
useEffect(() => {
|
|
89
|
-
setColorModeState(
|
|
133
|
+
setColorModeState(ColorModeAttribute.get());
|
|
134
|
+
setColorModeChoiceState(ColorModeChoiceAttribute.get());
|
|
90
135
|
}, []);
|
|
91
136
|
|
|
92
|
-
return
|
|
137
|
+
return {
|
|
138
|
+
colorMode,
|
|
139
|
+
setColorModeState,
|
|
140
|
+
colorModeChoice,
|
|
141
|
+
setColorModeChoiceState,
|
|
142
|
+
} as const;
|
|
93
143
|
}
|
|
94
144
|
|
|
95
145
|
function useContextValue(): ContextValue {
|
|
96
146
|
const {
|
|
97
147
|
colorMode: {defaultMode, disableSwitch, respectPrefersColorScheme},
|
|
98
148
|
} = useThemeConfig();
|
|
99
|
-
const
|
|
149
|
+
const {
|
|
150
|
+
colorMode,
|
|
151
|
+
setColorModeState,
|
|
152
|
+
colorModeChoice,
|
|
153
|
+
setColorModeChoiceState,
|
|
154
|
+
} = useColorModeState();
|
|
100
155
|
|
|
101
156
|
useEffect(() => {
|
|
102
157
|
// A site is deployed without disableSwitch
|
|
@@ -109,67 +164,70 @@ function useContextValue(): ContextValue {
|
|
|
109
164
|
}, [disableSwitch]);
|
|
110
165
|
|
|
111
166
|
const setColorMode = useCallback(
|
|
112
|
-
(
|
|
167
|
+
(
|
|
168
|
+
newColorModeChoice: ColorModeChoice,
|
|
169
|
+
options: {persist?: boolean} = {},
|
|
170
|
+
) => {
|
|
113
171
|
const {persist = true} = options;
|
|
114
172
|
|
|
115
|
-
|
|
173
|
+
// Reset to system/default color mode
|
|
174
|
+
if (newColorModeChoice === null) {
|
|
175
|
+
// Set the effective color
|
|
176
|
+
const newColorMode = respectPrefersColorScheme
|
|
177
|
+
? getSystemColorMode()
|
|
178
|
+
: defaultMode;
|
|
116
179
|
ColorModeAttribute.set(newColorMode);
|
|
117
180
|
setColorModeState(newColorMode);
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
ColorModeStorage.del();
|
|
181
|
+
// Set the chosen color
|
|
182
|
+
ColorModeChoiceAttribute.set(null);
|
|
183
|
+
setColorModeChoiceState(null);
|
|
184
|
+
}
|
|
185
|
+
// Happy case, when an explicit color is provided
|
|
186
|
+
else {
|
|
187
|
+
ColorModeAttribute.set(newColorModeChoice);
|
|
188
|
+
ColorModeChoiceAttribute.set(newColorModeChoice);
|
|
189
|
+
setColorModeState(newColorModeChoice);
|
|
190
|
+
setColorModeChoiceState(newColorModeChoice);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (persist) {
|
|
194
|
+
persistColorModeChoice(newColorModeChoice);
|
|
134
195
|
}
|
|
135
196
|
},
|
|
136
|
-
[
|
|
197
|
+
[
|
|
198
|
+
setColorModeState,
|
|
199
|
+
setColorModeChoiceState,
|
|
200
|
+
respectPrefersColorScheme,
|
|
201
|
+
defaultMode,
|
|
202
|
+
],
|
|
137
203
|
);
|
|
138
204
|
|
|
205
|
+
// Synchronize theme color/choice mode with browser storage
|
|
139
206
|
useEffect(() => {
|
|
140
|
-
if (disableSwitch) {
|
|
141
|
-
return undefined;
|
|
142
|
-
}
|
|
143
207
|
return ColorModeStorage.listen((e) => {
|
|
144
|
-
setColorMode(
|
|
208
|
+
setColorMode(coerceToColorModeChoice(e.newValue));
|
|
145
209
|
});
|
|
146
|
-
}, [
|
|
147
|
-
|
|
148
|
-
// PCS is coerced to light mode when printing, which causes the color mode to
|
|
149
|
-
// be reset to dark when exiting print mode, disregarding user settings. When
|
|
150
|
-
// the listener fires only because of a print/screen switch, we don't change
|
|
151
|
-
// color mode. See https://github.com/facebook/docusaurus/pull/6490
|
|
152
|
-
const previousMediaIsPrint = useRef(false);
|
|
210
|
+
}, [setColorMode]);
|
|
153
211
|
|
|
212
|
+
// Synchronize theme color with system color
|
|
154
213
|
useEffect(() => {
|
|
155
|
-
if (
|
|
214
|
+
if (colorModeChoice !== null || !respectPrefersColorScheme) {
|
|
156
215
|
return undefined;
|
|
157
216
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
return () => mql.removeListener(onChange);
|
|
168
|
-
}, [setColorMode, disableSwitch, respectPrefersColorScheme]);
|
|
217
|
+
return subscribeToSystemColorModeChange((newSystemColorMode) => {
|
|
218
|
+
// Note: we don't use "setColorMode" on purpose
|
|
219
|
+
// The system changes should never be considered an explicit theme choice
|
|
220
|
+
// They only affect the "effective" color, and should never be persisted
|
|
221
|
+
// Note: this listener also fire when printing, see https://github.com/facebook/docusaurus/pull/6490
|
|
222
|
+
setColorModeState(newSystemColorMode);
|
|
223
|
+
ColorModeAttribute.set(newSystemColorMode);
|
|
224
|
+
});
|
|
225
|
+
}, [respectPrefersColorScheme, colorModeChoice, setColorModeState]);
|
|
169
226
|
|
|
170
227
|
return useMemo(
|
|
171
228
|
() => ({
|
|
172
229
|
colorMode,
|
|
230
|
+
colorModeChoice,
|
|
173
231
|
setColorMode,
|
|
174
232
|
get isDarkTheme() {
|
|
175
233
|
if (process.env.NODE_ENV === 'development') {
|
|
@@ -177,7 +235,7 @@ function useContextValue(): ContextValue {
|
|
|
177
235
|
'`useColorMode().isDarkTheme` is deprecated. Please use `useColorMode().colorMode === "dark"` instead.',
|
|
178
236
|
);
|
|
179
237
|
}
|
|
180
|
-
return colorMode ===
|
|
238
|
+
return colorMode === 'dark';
|
|
181
239
|
},
|
|
182
240
|
setLightTheme() {
|
|
183
241
|
if (process.env.NODE_ENV === 'development') {
|
|
@@ -185,7 +243,7 @@ function useContextValue(): ContextValue {
|
|
|
185
243
|
'`useColorMode().setLightTheme` is deprecated. Please use `useColorMode().setColorMode("light")` instead.',
|
|
186
244
|
);
|
|
187
245
|
}
|
|
188
|
-
setColorMode(
|
|
246
|
+
setColorMode('light');
|
|
189
247
|
},
|
|
190
248
|
setDarkTheme() {
|
|
191
249
|
if (process.env.NODE_ENV === 'development') {
|
|
@@ -193,10 +251,10 @@ function useContextValue(): ContextValue {
|
|
|
193
251
|
'`useColorMode().setDarkTheme` is deprecated. Please use `useColorMode().setColorMode("dark")` instead.',
|
|
194
252
|
);
|
|
195
253
|
}
|
|
196
|
-
setColorMode(
|
|
254
|
+
setColorMode('dark');
|
|
197
255
|
},
|
|
198
256
|
}),
|
|
199
|
-
[colorMode, setColorMode],
|
|
257
|
+
[colorMode, colorModeChoice, setColorMode],
|
|
200
258
|
);
|
|
201
259
|
}
|
|
202
260
|
|