67 lines
1.8 KiB
TypeScript
67 lines
1.8 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
|
|
function readBreakpoints(lg: number, md: number, sm: number) {
|
|
if (typeof window === "undefined" || typeof window.matchMedia === "undefined") {
|
|
return {
|
|
isLg: false,
|
|
isMd: false,
|
|
isSm: false,
|
|
isXs: false,
|
|
};
|
|
}
|
|
|
|
const lgMedia = matchMedia(`(min-width: ${lg}px)`);
|
|
const mdMedia = matchMedia(
|
|
`(max-width: ${lg - 1}px) and (min-width: ${md}px)`
|
|
);
|
|
const smMedia = matchMedia(
|
|
`(max-width: ${md - 1}px) and (min-width: ${sm}px)`
|
|
);
|
|
const xsMedia = matchMedia(`(max-width: ${sm - 1}px)`);
|
|
|
|
return {
|
|
isLg: lgMedia.matches,
|
|
isMd: mdMedia.matches,
|
|
isSm: smMedia.matches,
|
|
isXs: xsMedia.matches,
|
|
};
|
|
}
|
|
|
|
export function useMediaQueries(lg = 1440, md = 768, sm = 640) {
|
|
const [state, setState] = useState(() => readBreakpoints(lg, md, sm));
|
|
|
|
useEffect(() => {
|
|
const lgMedia = matchMedia(`(min-width: ${lg}px)`);
|
|
const mdMedia = matchMedia(
|
|
`(max-width: ${lg - 1}px) and (min-width: ${md}px)`
|
|
);
|
|
const smMedia = matchMedia(
|
|
`(max-width: ${md - 1}px) and (min-width: ${sm}px)`
|
|
);
|
|
const xsMedia = matchMedia(`(max-width: ${sm - 1}px)`);
|
|
|
|
const sync = () => setState(readBreakpoints(lg, md, sm));
|
|
|
|
lgMedia.addEventListener("change", sync);
|
|
mdMedia.addEventListener("change", sync);
|
|
smMedia.addEventListener("change", sync);
|
|
xsMedia.addEventListener("change", sync);
|
|
|
|
sync();
|
|
|
|
return () => {
|
|
lgMedia.removeEventListener("change", sync);
|
|
mdMedia.removeEventListener("change", sync);
|
|
smMedia.removeEventListener("change", sync);
|
|
xsMedia.removeEventListener("change", sync);
|
|
};
|
|
}, [lg, md, sm]);
|
|
|
|
return {
|
|
isLg: state.isLg,
|
|
isMd: state.isMd,
|
|
isSm: state.isSm,
|
|
isXs: state.isXs,
|
|
};
|
|
}
|