UNPKG

@yamada-ui/use-breakpoint

Version:

Yamada UI useBreakpoint custom hook

1 lines 9.75 kB
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { ResponsiveObject, StyledTheme, Theme } from \"@yamada-ui/core\"\nimport type { DependencyList } from \"react\"\nimport { useTheme } from \"@yamada-ui/core\"\nimport { createdDom, useUpdateEffect } from \"@yamada-ui/utils\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\n\n/**\n * `useBreakpoint` is a custom hook that returns the current breakpoint.\n * This hook monitors changes in the window size and returns the appropriate value.\n *\n * @see Docs https://yamada-ui.com/hooks/use-breakpoint\n */\nexport const useBreakpoint = () => {\n const animationFrameId = useRef(0)\n const { theme } = useTheme()\n\n const breakpoints = theme.__breakpoints\n const {\n containerRef,\n direction = \"down\",\n identifier = \"@media screen\",\n } = theme.__config?.breakpoint ?? {}\n const hasContainer = !!containerRef\n\n if (!breakpoints) {\n console.warn(\n \"useBreakpoint: `breakpoints` is undefined. Seems you forgot to put theme in `breakpoints`\",\n )\n }\n\n const queries = useMemo(() => {\n if (!breakpoints) return []\n\n return breakpoints.queries.map(\n ({ breakpoint, maxW, minMaxQuery, minW }) => {\n const searchValue =\n identifier === \"@media screen\"\n ? \"@media screen and \"\n : `${identifier} `\n const query = minMaxQuery?.replace(searchValue, \"\") ?? \"\"\n\n return {\n breakpoint,\n maxW,\n minW,\n query,\n }\n },\n )\n }, [breakpoints, identifier])\n\n const hasQueries = !!queries.length\n\n const [breakpoint, setBreakpoint] = useState(() => {\n if (!createdDom() || hasContainer || !hasQueries) return \"base\"\n\n for (const { breakpoint, query } of queries) {\n const mql = window.matchMedia(query)\n\n if (mql.matches) return breakpoint\n }\n })\n\n const getBreakpoint = useCallback(\n (width: number) => {\n for (const { breakpoint, maxW, minW } of queries) {\n if (direction !== \"up\") {\n if ((minW ?? 0) <= width) return breakpoint\n } else {\n if (width <= (maxW ?? Infinity)) return breakpoint\n }\n }\n\n return \"base\"\n },\n [queries, direction],\n )\n\n useEffect(() => {\n if (!hasContainer || !hasQueries) return\n\n if (!createdDom()) return\n\n const observer = new ResizeObserver(([entry]) => {\n if (!entry) return\n\n cancelAnimationFrame(animationFrameId.current)\n\n const { width } = entry.contentRect\n\n animationFrameId.current = requestAnimationFrame(() => {\n const breakpoint = getBreakpoint(width)\n\n setBreakpoint(breakpoint)\n })\n })\n\n if (containerRef.current) observer.observe(containerRef.current)\n\n return () => {\n observer.disconnect()\n\n if (process.env.NODE_ENV !== \"test\")\n cancelAnimationFrame(animationFrameId.current)\n }\n }, [hasQueries, hasContainer, containerRef, getBreakpoint])\n\n useEffect(() => {\n if (hasContainer || !hasQueries) return\n\n const observer = queries.map(({ breakpoint, query }): (() => void) => {\n const mql = window.matchMedia(query)\n\n const onChange = (e: MediaQueryListEvent) => {\n if (e.matches) setBreakpoint(breakpoint)\n }\n\n if (typeof mql.addEventListener === \"function\")\n mql.addEventListener(\"change\", onChange)\n\n return () => {\n if (typeof mql.removeEventListener === \"function\")\n mql.removeEventListener(\"change\", onChange)\n }\n })\n\n return () => {\n observer.forEach((unobserve) => unobserve())\n }\n }, [queries, hasQueries, hasContainer])\n\n return breakpoint as Theme[\"breakpoints\"]\n}\n\n/**\n * `useBreakpointValue` is a custom hook that returns the value of the current breakpoint from the provided object.\n * This hook monitors changes in the window size and returns the appropriate value.\n *\n * @see Docs https://yamada-ui.com/hooks/use-breakpoint-value\n */\nexport const useBreakpointValue = <T>(values: ResponsiveObject<T>): T => {\n const { theme } = useTheme()\n const breakpoint = useBreakpoint()\n\n return useMemo(\n () => getBreakpointValue<T>(values)(theme, breakpoint),\n [values, theme, breakpoint],\n )\n}\n\nexport const getBreakpointValue =\n <T>(values: ResponsiveObject<T> = {}) =>\n (theme: StyledTheme | undefined, breakpoint: Theme[\"breakpoints\"]): T => {\n if (!theme) {\n console.warn(\"getBreakpointValue: `theme` is undefined.\")\n }\n\n const breakpoints = theme?.__breakpoints?.keys ?? []\n\n if (!breakpoints.length) {\n console.warn(\"getBreakpointValue: `breakpoints` is undefined.\")\n }\n\n const currentIndex = breakpoints.indexOf(breakpoint)\n\n for (let i = currentIndex; 0 < i; i--) {\n const nextBreakpoint = breakpoints[i]\n\n if (nextBreakpoint && values.hasOwnProperty(nextBreakpoint)) {\n return values[nextBreakpoint] as T\n }\n }\n\n return values.base as T\n }\n\n/**\n * `useBreakpointState` is a custom hook that takes a responsive object as an initial state and returns a state corresponding to the current breakpoint.\n *\n * @see Docs https://yamada-ui.com/hooks/use-breakpoint-state\n */\nexport const useBreakpointState = <T>(initialState: ResponsiveObject<T>) => {\n const state = useBreakpointValue(initialState)\n\n return useState(state)\n}\n\n/**\n * `useBreakpointEffect` is a custom hook that executes a specific callback function when the breakpoint changes.\n *\n * @see Docs https://yamada-ui.com/hooks/use-breakpoint-effect\n */\nexport const useBreakpointEffect = (\n callback: (breakpoint: Theme[\"breakpoints\"]) => void,\n deps: DependencyList,\n) => {\n const breakpoint = useBreakpoint()\n\n useEffect(() => {\n callback(breakpoint)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [breakpoint, ...deps])\n}\n\n/**\n * `useUpdateBreakpointEffect` is a custom hook that skips the side effect on the initial render and executes a specific callback function when the breakpoint changes.\n *\n * @see Docs https://yamada-ui.com/hooks/use-update-breakpoint-effect\n */\nexport const useUpdateBreakpointEffect = (\n callback: (breakpoint: Theme[\"breakpoints\"]) => void,\n deps: DependencyList,\n) => {\n const breakpoint = useBreakpoint()\n\n useUpdateEffect(() => {\n callback(breakpoint)\n }, [breakpoint, ...deps])\n}\n"],"mappings":"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","names":["breakpoint","_a"]}