UNPKG

@supunlakmal/hooks

Version:

A collection of reusable React hooks

77 lines 3.45 kB
import { useEffect, useState } from 'react'; // Define default breakpoints (inspired by Tailwind CSS) const defaultBreakpoints = { sm: '(min-width: 640px)', md: '(min-width: 768px)', lg: '(min-width: 1024px)', xl: '(min-width: 1280px)', '2xl': '(min-width: 1536px)', }; // Use 'as const' for stricter type inference /** * Custom hook to determine the currently active responsive breakpoint based on window width. * * @template K Type of the breakpoint keys (defaults to keys of defaultBreakpoints). * @param {Record<K, string>} [customBreakpoints] - Optional custom breakpoints object. Keys are breakpoint names, values are media query strings. * @returns {K | null} The key of the largest currently active breakpoint, or null if none match. */ export const useBreakpoint = (customBreakpoints) => { const breakpoints = customBreakpoints !== null && customBreakpoints !== void 0 ? customBreakpoints : defaultBreakpoints; const [activeBreakpoint, setActiveBreakpoint] = useState(null); useEffect(() => { if (typeof window === 'undefined' || !window.matchMedia) { return; // Cannot determine breakpoint on server or without matchMedia } const mediaQueryLists = []; const listeners = []; const checkBreakpoints = () => { // Sort keys by descending min-width value extracted from the query const sortedKeys = Object.entries(breakpoints) .sort(([, queryA], [, queryB]) => { var _a, _b; const widthA = parseInt(((_a = queryA.match(/\d+/)) === null || _a === void 0 ? void 0 : _a[0]) || '0', 10); const widthB = parseInt(((_b = queryB.match(/\d+/)) === null || _b === void 0 ? void 0 : _b[0]) || '0', 10); return widthB - widthA; // Sort descending by width }) .map(([key]) => key); let currentActive = null; for (const key of sortedKeys) { const mediaQuery = breakpoints[key]; if (window.matchMedia(mediaQuery).matches) { currentActive = key; break; // Found the largest active breakpoint } } setActiveBreakpoint(currentActive); }; // Initial check checkBreakpoints(); // Set up listeners for changes Object.entries(breakpoints).forEach(([key, query]) => { const mql = window.matchMedia(query); const listener = () => { checkBreakpoints(); // Re-check all breakpoints on any change }; if (mql.addEventListener) { mql.addEventListener('change', listener); } else { mql.addListener(listener); // Deprecated fallback } mediaQueryLists.push({ key: key, mql }); listeners.push({ mql, listener }); }); // Cleanup listeners return () => { listeners.forEach(({ mql, listener }) => { if (mql.removeEventListener) { mql.removeEventListener('change', listener); } else { mql.removeListener(listener); } }); }; }, [breakpoints]); // Re-run effect if breakpoints object changes return activeBreakpoint; }; //# sourceMappingURL=useBreakpoint.js.map