UNPKG

@yamada-ui/react

Version:

React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion

97 lines (93 loc) 3.25 kB
"use client"; import { utils_exports } from "../../utils/index.js"; import { useEnvironment } from "../../core/system/environment-provider.js"; import { useSystem } from "../../core/system/system-provider.js"; import { useCallback, useMemo, useRef, useSyncExternalStore } from "react"; //#region src/hooks/use-breakpoint/use-breakpoint.ts /** * `useBreakpoint` is a custom hook that returns the current breakpoint. * This hook monitors changes in the window size and returns the appropriate value. * * @see https://yamada-ui.com/docs/hooks/use-breakpoint */ const useBreakpoint = () => { const animationFrameId = useRef(0); const { breakpoints, config } = useSystem(); const { getWindow } = useEnvironment(); const { containerRef, direction = "down", identifier = "@media screen" } = config.breakpoint ?? {}; const hasContainer = !!containerRef; const queries = useMemo(() => { return breakpoints.queries.map(({ breakpoint, maxW, minMaxQuery, minW }) => { const searchValue = identifier === "@media screen" ? "@media screen and " : `${identifier} `; return { breakpoint, maxW, minW, query: minMaxQuery?.replace(searchValue, "") ?? "" }; }); }, [breakpoints, identifier]); const hasQueries = !!queries.length; const getBreakpoint = useCallback((width) => { if ((0, utils_exports.isUndefined)(width)) { const win = getWindow(); if (hasContainer || !hasQueries) return "base"; for (const { breakpoint, query } of queries) if ((win?.matchMedia(query))?.matches) return breakpoint; } else for (const { breakpoint, maxW, minW } of queries) if (direction !== "up") { if ((minW ?? 0) <= width) return breakpoint; } else if (width <= (maxW ?? Infinity)) return breakpoint; return "base"; }, [ direction, getWindow, hasContainer, hasQueries, queries ]); const breakpointRef = useRef(getBreakpoint()); const subscribe = useCallback((listener) => { if (!hasContainer || !hasQueries) { const observer = queries.map(({ breakpoint, query }) => { const mql = getWindow()?.matchMedia(query); const onChange = (e) => { if (e.matches) breakpointRef.current = breakpoint; listener(); }; mql?.addEventListener("change", onChange); return () => { mql?.removeEventListener("change", onChange); }; }); return () => { observer.forEach((unobserve) => unobserve()); }; } else if ((0, utils_exports.createdDom)()) { const observer = new ResizeObserver(([entry]) => { if (!entry) return; cancelAnimationFrame(animationFrameId.current); const { width } = entry.contentRect; breakpointRef.current = getBreakpoint(width); animationFrameId.current = requestAnimationFrame(listener); }); if (containerRef.current) observer.observe(containerRef.current); return () => { observer.disconnect(); cancelAnimationFrame(animationFrameId.current); }; } else return utils_exports.noop; }, [ containerRef, getBreakpoint, getWindow, hasContainer, hasQueries, queries ]); const getSnapshot = useCallback(() => { return breakpointRef.current; }, []); return useSyncExternalStore(subscribe, getSnapshot, getSnapshot); }; //#endregion export { useBreakpoint }; //# sourceMappingURL=use-breakpoint.js.map