@primer/styled-react 1.0.4-rc.f372aa7ad → 1.0.5-rc.f3b0d9cc2
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/components/ThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/components/ThemeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAKzB,eAAO,MAAM,gBAAgB,QAAQ,CAAA;AAKrC,MAAM,MAAM,KAAK,GAAG;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAC,CAAA;AACxC,KAAK,SAAS,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAA;AACnD,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAAA;AAElD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,SAAS,CAAC,EAAE,iBAAiB,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;AA8CD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAyE/E,CAAA;AAED,wBAAgB,QAAQ;YAtHd,KAAK;kBACC,MAAM;gBACR,iBAAiB;wBACT,SAAS;0BACP,MAAM;gBAChB,MAAM;kBACJ,MAAM;kBACN,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;kBACvD,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;oBAC1C,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;EA+G7D;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,UAG1F;AAqED,eAAe,aAAa,CAAA"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import ReactDOM from 'react-dom';
|
|
3
2
|
import { ThemeProvider as ThemeProvider$1 } from 'styled-components';
|
|
4
3
|
import { theme, useId, useSyncedState } from '@primer/react';
|
|
5
4
|
import deepmerge from 'deepmerge';
|
|
@@ -18,15 +17,27 @@ const ThemeContext = /*#__PURE__*/React.createContext({
|
|
|
18
17
|
});
|
|
19
18
|
|
|
20
19
|
// inspired from __NEXT_DATA__, we use application/json to avoid CSRF policy with inline scripts
|
|
20
|
+
const serverHandoffCache = new Map();
|
|
21
|
+
const emptyHandoff = {};
|
|
21
22
|
const getServerHandoff = id => {
|
|
23
|
+
if (typeof document === 'undefined') return emptyHandoff;
|
|
24
|
+
const cached = serverHandoffCache.get(id);
|
|
25
|
+
if (cached !== undefined) return cached;
|
|
22
26
|
try {
|
|
23
27
|
const serverData = document.getElementById(`__PRIMER_DATA_${id}__`)?.textContent;
|
|
24
|
-
if (serverData)
|
|
28
|
+
if (serverData) {
|
|
29
|
+
const parsed = JSON.parse(serverData);
|
|
30
|
+
serverHandoffCache.set(id, parsed);
|
|
31
|
+
return parsed;
|
|
32
|
+
}
|
|
25
33
|
} catch (_error) {
|
|
26
34
|
// if document/element does not exist or JSON is invalid, supress error
|
|
27
35
|
}
|
|
28
|
-
|
|
36
|
+
const empty = {};
|
|
37
|
+
serverHandoffCache.set(id, empty);
|
|
38
|
+
return empty;
|
|
29
39
|
};
|
|
40
|
+
const emptySubscribe = () => () => {};
|
|
30
41
|
const ThemeProvider = ({
|
|
31
42
|
children,
|
|
32
43
|
...props
|
|
@@ -42,56 +53,33 @@ const ThemeProvider = ({
|
|
|
42
53
|
// Initialize state
|
|
43
54
|
const theme$1 = props.theme ?? fallbackTheme ?? theme;
|
|
44
55
|
const uniqueDataId = useId();
|
|
45
|
-
const {
|
|
46
|
-
resolvedServerColorMode
|
|
47
|
-
} = getServerHandoff(uniqueDataId);
|
|
48
|
-
const resolvedColorModePassthrough = React.useRef(resolvedServerColorMode);
|
|
49
56
|
const [colorMode, setColorMode] = useSyncedState(props.colorMode ?? fallbackColorMode ?? defaultColorMode);
|
|
50
57
|
const [dayScheme, setDayScheme] = useSyncedState(props.dayScheme ?? fallbackDayScheme ?? defaultDayScheme);
|
|
51
58
|
const [nightScheme, setNightScheme] = useSyncedState(props.nightScheme ?? fallbackNightScheme ?? defaultNightScheme);
|
|
52
59
|
const systemColorMode = useSystemColorMode();
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
const clientColorMode = resolveColorMode(colorMode, systemColorMode);
|
|
61
|
+
// During SSR/hydration, use the server-rendered color mode from the handoff script tag
|
|
62
|
+
// to avoid mismatches. After hydration, resolve from client state.
|
|
63
|
+
const resolvedColorMode = React.useSyncExternalStore(emptySubscribe, () => clientColorMode, () => getServerHandoff(uniqueDataId).resolvedServerColorMode ?? clientColorMode);
|
|
55
64
|
const colorScheme = chooseColorScheme(resolvedColorMode, dayScheme, nightScheme);
|
|
56
65
|
const {
|
|
57
66
|
resolvedTheme,
|
|
58
67
|
resolvedColorScheme
|
|
59
68
|
} = React.useMemo(() => applyColorScheme(theme$1, colorScheme), [theme$1, colorScheme]);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
setColorMode(resolvedColorModeOnClient);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// immediately after that, set the colorMode to what the user passed to respond to system color mode changes
|
|
76
|
-
setColorMode(colorMode);
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
resolvedColorModePassthrough.current = null;
|
|
80
|
-
}
|
|
81
|
-
}, [colorMode, systemColorMode, setColorMode]);
|
|
69
|
+
const contextValue = React.useMemo(() => ({
|
|
70
|
+
theme: resolvedTheme,
|
|
71
|
+
colorScheme,
|
|
72
|
+
colorMode,
|
|
73
|
+
resolvedColorMode,
|
|
74
|
+
resolvedColorScheme,
|
|
75
|
+
dayScheme,
|
|
76
|
+
nightScheme,
|
|
77
|
+
setColorMode,
|
|
78
|
+
setDayScheme,
|
|
79
|
+
setNightScheme
|
|
80
|
+
}), [resolvedTheme, colorScheme, colorMode, resolvedColorMode, resolvedColorScheme, dayScheme, nightScheme, setColorMode, setDayScheme, setNightScheme]);
|
|
82
81
|
return /*#__PURE__*/jsx(ThemeContext.Provider, {
|
|
83
|
-
value:
|
|
84
|
-
theme: resolvedTheme,
|
|
85
|
-
colorScheme,
|
|
86
|
-
colorMode,
|
|
87
|
-
resolvedColorMode,
|
|
88
|
-
resolvedColorScheme,
|
|
89
|
-
dayScheme,
|
|
90
|
-
nightScheme,
|
|
91
|
-
setColorMode,
|
|
92
|
-
setDayScheme,
|
|
93
|
-
setNightScheme
|
|
94
|
-
},
|
|
82
|
+
value: contextValue,
|
|
95
83
|
children: /*#__PURE__*/jsxs(ThemeProvider$1, {
|
|
96
84
|
theme: resolvedTheme,
|
|
97
85
|
children: [children, props.preventSSRMismatch ? /*#__PURE__*/jsx("script", {
|
|
@@ -115,48 +103,20 @@ function useColorSchemeVar(values, fallback) {
|
|
|
115
103
|
} = useTheme();
|
|
116
104
|
return values[colorScheme] ?? fallback;
|
|
117
105
|
}
|
|
106
|
+
function subscribeToSystemColorMode(callback) {
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
108
|
+
const media = window?.matchMedia?.('(prefers-color-scheme: dark)');
|
|
109
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
110
|
+
media?.addEventListener('change', callback);
|
|
111
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
112
|
+
return () => media?.removeEventListener('change', callback);
|
|
113
|
+
}
|
|
118
114
|
function useSystemColorMode() {
|
|
119
|
-
|
|
120
|
-
React.useEffect(() => {
|
|
121
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
122
|
-
const media = window?.matchMedia?.('(prefers-color-scheme: dark)');
|
|
123
|
-
function matchesMediaToColorMode(matches) {
|
|
124
|
-
return matches ? 'night' : 'day';
|
|
125
|
-
}
|
|
126
|
-
function handleChange(event) {
|
|
127
|
-
const isNight = event.matches;
|
|
128
|
-
setSystemColorMode(matchesMediaToColorMode(isNight));
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
132
|
-
if (media) {
|
|
133
|
-
// just in case the preference changed before the event listener was attached
|
|
134
|
-
const isNight = media.matches;
|
|
135
|
-
setSystemColorMode(matchesMediaToColorMode(isNight));
|
|
136
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
137
|
-
if (media.addEventListener !== undefined) {
|
|
138
|
-
media.addEventListener('change', handleChange);
|
|
139
|
-
return function cleanup() {
|
|
140
|
-
media.removeEventListener('change', handleChange);
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
144
|
-
else if (media.addListener !== undefined) {
|
|
145
|
-
media.addListener(handleChange);
|
|
146
|
-
return function cleanup() {
|
|
147
|
-
media.removeListener(handleChange);
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}, []);
|
|
152
|
-
return systemColorMode;
|
|
115
|
+
return React.useSyncExternalStore(subscribeToSystemColorMode, getSystemColorMode, () => 'day');
|
|
153
116
|
}
|
|
154
117
|
function getSystemColorMode() {
|
|
155
118
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
156
|
-
|
|
157
|
-
return 'night';
|
|
158
|
-
}
|
|
159
|
-
return 'day';
|
|
119
|
+
return window?.matchMedia?.('(prefers-color-scheme: dark)')?.matches ? 'night' : 'day';
|
|
160
120
|
}
|
|
161
121
|
function resolveColorMode(colorMode, systemColorMode) {
|
|
162
122
|
switch (colorMode) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@primer/styled-react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5-rc.f3b0d9cc2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -40,15 +40,18 @@
|
|
|
40
40
|
"@types/styled-system": "^5.1.23",
|
|
41
41
|
"@types/styled-system__css": "^5.0.16",
|
|
42
42
|
"@types/styled-system__theme-get": "^5.0.1",
|
|
43
|
+
"clsx": "^2.1.1",
|
|
44
|
+
"deepmerge": "^4.3.1",
|
|
45
|
+
"focus-visible": "^5.2.1",
|
|
43
46
|
"styled-system": "^5.1.5"
|
|
44
47
|
},
|
|
45
48
|
"devDependencies": {
|
|
46
49
|
"@babel/preset-react": "^7.28.5",
|
|
47
50
|
"@babel/preset-typescript": "^7.28.5",
|
|
48
51
|
"@primer/primitives": "10.x || 11.x",
|
|
49
|
-
"@primer/react": "^38.
|
|
52
|
+
"@primer/react": "^38.19.0",
|
|
50
53
|
"@rollup/plugin-babel": "^6.1.0",
|
|
51
|
-
"@storybook/react-vite": "^10.
|
|
54
|
+
"@storybook/react-vite": "^10.3.3",
|
|
52
55
|
"@types/react": "18.3.11",
|
|
53
56
|
"@types/react-dom": "18.3.1",
|
|
54
57
|
"@types/styled-components": "^5.1.26",
|