mirror of
https://github.com/documenso/documenso.git
synced 2026-08-15 02:53:32 +10:00
35 lines
1.1 KiB
TypeScript
35 lines
1.1 KiB
TypeScript
import { useCallback, useSyncExternalStore } from 'react';
|
|
|
|
/**
|
|
* Tracks whether the given CSS media query currently matches.
|
|
*
|
|
* Returns `false` on the server since the viewport is unknown until hydration.
|
|
*/
|
|
export const useMediaQuery = (query: string) => {
|
|
const subscribe = useCallback(
|
|
(onStoreChange: () => void) => {
|
|
const mediaQueryList = window.matchMedia(query);
|
|
|
|
mediaQueryList.addEventListener('change', onStoreChange);
|
|
|
|
return () => mediaQueryList.removeEventListener('change', onStoreChange);
|
|
},
|
|
[query],
|
|
);
|
|
|
|
return useSyncExternalStore(
|
|
subscribe,
|
|
() => window.matchMedia(query).matches,
|
|
// The server snapshot: the viewport is unknown during SSR, so we assume
|
|
// the query does not match rather than throwing. React re-renders with
|
|
// the real value after hydration, so the only cost is a brief first
|
|
// paint with the non-matching variant.
|
|
() => false,
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Whether the viewport is below the Tailwind `md` breakpoint (768px).
|
|
*/
|
|
export const useIsMobileViewport = () => useMediaQuery('(max-width: 767px)');
|