useMediaQuery.js
5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"use strict";
'use client';
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.unstable_createUseMediaQuery = unstable_createUseMediaQuery;
var React = _interopRequireWildcard(require("react"));
var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
var _useThemeProps = require("../useThemeProps");
var _useThemeWithoutDefault = _interopRequireDefault(require("../useThemeWithoutDefault"));
// TODO React 17: Remove `useMediaQueryOld` once React 17 support is removed
function useMediaQueryOld(query, defaultMatches, matchMedia, ssrMatchMedia, noSsr) {
const [match, setMatch] = React.useState(() => {
if (noSsr && matchMedia) {
return matchMedia(query).matches;
}
if (ssrMatchMedia) {
return ssrMatchMedia(query).matches;
}
// Once the component is mounted, we rely on the
// event listeners to return the correct matches value.
return defaultMatches;
});
(0, _useEnhancedEffect.default)(() => {
if (!matchMedia) {
return undefined;
}
const queryList = matchMedia(query);
const updateMatch = () => {
setMatch(queryList.matches);
};
updateMatch();
queryList.addEventListener('change', updateMatch);
return () => {
queryList.removeEventListener('change', updateMatch);
};
}, [query, matchMedia]);
return match;
}
// See https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379 for why
const safeReact = {
...React
};
const maybeReactUseSyncExternalStore = safeReact.useSyncExternalStore;
function useMediaQueryNew(query, defaultMatches, matchMedia, ssrMatchMedia, noSsr) {
const getDefaultSnapshot = React.useCallback(() => defaultMatches, [defaultMatches]);
const getServerSnapshot = React.useMemo(() => {
if (noSsr && matchMedia) {
return () => matchMedia(query).matches;
}
if (ssrMatchMedia !== null) {
const {
matches
} = ssrMatchMedia(query);
return () => matches;
}
return getDefaultSnapshot;
}, [getDefaultSnapshot, query, ssrMatchMedia, noSsr, matchMedia]);
const [getSnapshot, subscribe] = React.useMemo(() => {
if (matchMedia === null) {
return [getDefaultSnapshot, () => () => {}];
}
const mediaQueryList = matchMedia(query);
return [() => mediaQueryList.matches, notify => {
mediaQueryList.addEventListener('change', notify);
return () => {
mediaQueryList.removeEventListener('change', notify);
};
}];
}, [getDefaultSnapshot, matchMedia, query]);
const match = maybeReactUseSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
return match;
}
// eslint-disable-next-line @typescript-eslint/naming-convention
function unstable_createUseMediaQuery(params = {}) {
const {
themeId
} = params;
return function useMediaQuery(queryInput, options = {}) {
let theme = (0, _useThemeWithoutDefault.default)();
if (theme && themeId) {
theme = theme[themeId] || theme;
}
// Wait for jsdom to support the match media feature.
// All the browsers MUI support have this built-in.
// This defensive check is here for simplicity.
// Most of the time, the match media logic isn't central to people tests.
const supportMatchMedia = typeof window !== 'undefined' && typeof window.matchMedia !== 'undefined';
const {
defaultMatches = false,
matchMedia = supportMatchMedia ? window.matchMedia : null,
ssrMatchMedia = null,
noSsr = false
} = (0, _useThemeProps.getThemeProps)({
name: 'MuiUseMediaQuery',
props: options,
theme
});
if (process.env.NODE_ENV !== 'production') {
if (typeof queryInput === 'function' && theme === null) {
console.error(['MUI: The `query` argument provided is invalid.', 'You are providing a function without a theme in the context.', 'One of the parent elements needs to use a ThemeProvider.'].join('\n'));
}
}
let query = typeof queryInput === 'function' ? queryInput(theme) : queryInput;
query = query.replace(/^@media( ?)/m, '');
if (query.includes('print')) {
console.warn([`MUI: You have provided a \`print\` query to the \`useMediaQuery\` hook.`, 'Using the print media query to modify print styles can lead to unexpected results.', 'Consider using the `displayPrint` field in the `sx` prop instead.', 'More information about `displayPrint` on our docs: https://mui.com/system/display/#display-in-print.'].join('\n'));
}
const useMediaQueryImplementation = maybeReactUseSyncExternalStore !== undefined ? useMediaQueryNew : useMediaQueryOld;
const match = useMediaQueryImplementation(query, defaultMatches, matchMedia, ssrMatchMedia, noSsr);
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line react-hooks/rules-of-hooks
React.useDebugValue({
query,
match
});
}
return match;
};
}
const useMediaQuery = unstable_createUseMediaQuery();
var _default = exports.default = useMediaQuery;