50 lines
1.5 KiB
TypeScript
50 lines
1.5 KiB
TypeScript
import * as React from 'react';
|
|
import { useTheme } from '@mui/material/styles';
|
|
|
|
type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
|
|
type FnName = 'up' | 'down' | 'between' | 'only' | 'not';
|
|
|
|
export function useMediaQuery(fn: 'up' | 'down', key: Breakpoint | number): boolean;
|
|
|
|
export function useMediaQuery(fn: 'between', start: Breakpoint | number, end: Breakpoint | number): boolean;
|
|
|
|
export function useMediaQuery(fn: 'only' | 'not', key: Breakpoint): boolean;
|
|
|
|
export function useMediaQuery(fn: FnName, start: Breakpoint | number, end?: Breakpoint | number): boolean {
|
|
const theme = useTheme();
|
|
const [matches, setMatches] = React.useState<boolean>(false);
|
|
|
|
let mq: string;
|
|
|
|
if (['up', 'down'].includes(fn) && start) {
|
|
mq = theme.breakpoints[fn as 'up' | 'down'](start);
|
|
} else if (fn === 'between' && start && end) {
|
|
mq = theme.breakpoints[fn as 'between'](start, end);
|
|
} else if (['only', 'not'].includes(fn) && start) {
|
|
mq = theme.breakpoints[fn as 'only' | 'not'](start as Breakpoint);
|
|
} else {
|
|
throw new Error('Invalid useMediaQuery params');
|
|
}
|
|
|
|
mq = mq.replace(/^@media(?: ?)/m, '');
|
|
|
|
React.useEffect((): (() => void) => {
|
|
setMatches(window.matchMedia(mq).matches);
|
|
|
|
function handler(event: MediaQueryListEvent): void {
|
|
setMatches(event.matches);
|
|
}
|
|
|
|
const mediaQueryList = window.matchMedia(mq);
|
|
|
|
mediaQueryList.addEventListener('change', handler);
|
|
|
|
return (): void => {
|
|
mediaQueryList.removeEventListener('change', handler);
|
|
};
|
|
}, [mq]);
|
|
|
|
return matches;
|
|
}
|