'use client'; import { useEffect, useState } from 'react'; /** * Subscribe to a CSS media query. * * SSR-safe: returns `defaultValue` (default `false`) when `window` is * undefined or `matchMedia` is unavailable. On mount, syncs to the current * match state and subscribes to `change` events. Re-subscribes when the * `query` string changes and cleans up its listener on unmount. * * @example * const isDesktop = useMediaQuery('(min-width: 768px)'); */ export function useMediaQuery(query: string, defaultValue: boolean = false): boolean { const [matches, setMatches] = useState(() => { if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') { return defaultValue; } return window.matchMedia(query).matches; }); useEffect(() => { if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') { return; } const mql = window.matchMedia(query); setMatches(mql.matches); const handler = (event: MediaQueryListEvent) => { setMatches(event.matches); }; if (typeof mql.addEventListener === 'function') { mql.addEventListener('change', handler); return () => mql.removeEventListener('change', handler); } // Legacy Safari fallback mql.addListener(handler); return () => mql.removeListener(handler); }, [query]); return matches; }