@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
JavaScript
"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