UNPKG

rsuite

Version:

A suite of react components

71 lines (67 loc) 2.64 kB
'use client'; import canUseDOM from 'dom-lib/canUseDOM'; import { breakpointValues } from "../internals/styled-system/index.js"; import { useSyncExternalStore, useCallback, useRef, useMemo } from 'react'; import { createBreakpoints } from "./breakpoints.js"; // Create enhanced breakpoint system using shared breakpoint values const breakpointSystem = createBreakpoints(breakpointValues); // Create media query map that combines legacy breakpoints with enhanced conditions const mediaQuerySizeMap = breakpointSystem.createMediaQueryMap(); /** * Create a MediaQueryList object or a mock for server-side rendering */ const matchMedia = query => { if (canUseDOM) { return window.matchMedia(query); } return { matches: false, media: query }; }; /** * React hook that tracks state of a CSS media query * @version 5.48.0 * @unstable Please note that this API is not stable and may change in the future. * @see https://rsuitejs.com/components/use-media-query * @param query - The media query string or array of query strings * @param enabled - Whether to enable the media query, defaults to true */ export function useMediaQuery(query, enabled = true) { const queries = Array.isArray(query) ? query : [query]; const mediaQueries = useMemo(() => queries.map(query => mediaQuerySizeMap[query] || query), [...queries]); // If not enabled, we don't need to set up any media queries if (!enabled) { return queries.map(() => false); } const mediaQueryArray = useRef(mediaQueries.map(query => matchMedia(query).matches)); const subscribe = useCallback(callback => { const list = mediaQueries.map(query => matchMedia(query)); const handleChange = event => { const index = list.findIndex(item => item.media === event.media); if (index !== -1) { // The store snapshot returned by getSnapshot must be immutable. So we need to create a new array. const nextMediaQueryArray = mediaQueryArray.current.slice(); nextMediaQueryArray[index] = event.matches; mediaQueryArray.current = nextMediaQueryArray; } callback(); }; list.forEach(query => { query.addEventListener('change', handleChange); }); return () => { list.forEach(query => { query.removeEventListener('change', handleChange); }); }; }, [mediaQueries]); const getSnapshot = useCallback(() => { return mediaQueryArray.current; }, []); const getServerSnapshot = useCallback(() => { return mediaQueryArray.current; }, []); return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); } export default useMediaQuery;