UNPKG

@react-hook/media-query

Version:

React hooks that update when media queries change between matched and unmatched states.

1 lines 9.29 kB
{"version":3,"file":"index.dev.mjs","sources":["../../src/index.tsx"],"sourcesContent":["import * as React from 'react'\n\nfunction queriesDidChange(\n prevQueries: MediaQueries<unknown>,\n nextQueries: MediaQueries<unknown>\n): boolean {\n if (nextQueries === prevQueries) return false\n const nextQueriesArr = Object.values(nextQueries)\n const prevQueriesArr = Object.values(prevQueries)\n if (nextQueriesArr.length !== prevQueriesArr.length) return true\n if (nextQueriesArr.some((q, i) => q !== prevQueriesArr[i])) return true\n const prevKeys = Object.keys(prevQueries)\n return Object.keys(nextQueries).some((n, i) => n !== prevKeys[i])\n}\n\nfunction init<T>(queries: MediaQueries<T>): State<T> {\n const queryKeys = Object.keys(queries) as (keyof MediaQueries<T>)[]\n /* istanbul ignore next */\n if (typeof window === 'undefined')\n return queryKeys.reduce(\n (curr: State<any>, key) => {\n curr.matches[key] = false\n curr.mediaQueries[key] = {} as MediaQueryList\n return curr\n },\n {mediaQueries: {}, matches: {}}\n )\n\n return queryKeys.reduce(\n (state: State<any>, name): State<T> => {\n const mql = window.matchMedia(queries[name])\n state.mediaQueries[name] = mql\n state.matches[name] = mql.matches\n return state\n },\n {mediaQueries: {}, matches: {}}\n )\n}\n\nfunction reducer<T>(state: State<T>, action: Action<T>): State<T> {\n switch (action.type) {\n case 'updateMatches':\n return {\n matches: Object.keys(state.mediaQueries).reduce(\n (prev: Matches<any>, key: string) => {\n prev[key] = state.mediaQueries[key as keyof T].matches\n return prev\n },\n {}\n ),\n mediaQueries: state.mediaQueries,\n }\n\n case 'setQueries':\n return init(action.queries)\n }\n}\n\n/**\n * A hook that returns a [`MediaQueryMatches`](#mediaquerymatches) object which will\n * tell you if specific media queries matched, all media queries matched, or\n * any media queries matched. Matches in this hook will always return `false` when\n * rendering on the server.\n *\n * @param queryMap The media queries you want to match against e.g. `{screen: \"screen\", width: \"(min-width: 12em)\"}`\n */\nexport function useMediaQueries<T>(\n queryMap: MediaQueries<T>\n): MediaQueryMatches<T> {\n const prevQueries = React.useRef<MediaQueries<T>>(queryMap)\n const [state, dispatch] = React.useReducer<\n React.Reducer<State<T>, Action<T>>,\n MediaQueries<T>\n >(reducer, queryMap, init)\n\n React.useEffect(() => {\n if (queriesDidChange(queryMap, prevQueries.current)) {\n dispatch({type: 'setQueries', queries: queryMap})\n prevQueries.current = queryMap\n }\n }, [queryMap])\n\n React.useEffect(() => {\n const queries: MediaQueryList[] = Object.values(state.mediaQueries)\n const callbacks: (() => void)[] = queries.map((mq) => {\n const callback = () => dispatch({type: 'updateMatches'})\n if (typeof mq.addListener !== 'undefined') mq.addListener(callback)\n else mq.addEventListener('change', callback)\n\n return callback\n })\n\n return () => {\n queries.forEach((mq: MediaQueryList, i: number) => {\n if (typeof mq.addListener !== 'undefined')\n mq.removeListener(callbacks[i])\n else mq.removeEventListener('change', callbacks[i])\n })\n }\n }, [state.mediaQueries])\n\n const {matches} = state\n const matchValues = React.useMemo<boolean[]>(() => Object.values(matches), [\n matches,\n ])\n\n return {\n matches,\n matchesAny: matchValues.some(Boolean),\n matchesAll: matchValues.length > 0 && matchValues.every(Boolean),\n }\n}\n\n/**\n * A hook that returns `true` if the media query matched and `false` if not. This\n * hook will always return `false` when rendering on the server.\n *\n * @param query The media query you want to match against e.g. `\"only screen and (min-width: 12em)\"`\n */\nexport function useMediaQuery(query: string) {\n return useMediaQueries(getObj(query)).matchesAll\n}\n\nconst cache: Record<string, MediaQueries<{default: string}>> = {}\n\nfunction getObj(query: string): MediaQueries<{default: string}> {\n if (cache[query] === void 0) cache[query] = {default: query}\n return cache[query]\n}\n\nexport type MediaQueries<T> = {\n [Name in keyof T]: string\n}\n\nexport type Matches<T> = {\n [Name in keyof T]: boolean\n}\n\ninterface State<T> {\n mediaQueries: {[Name in keyof T]: MediaQueryList}\n matches: Matches<T>\n}\n\ntype UpdateMatchesAction = {\n type: 'updateMatches'\n}\ntype SetQueriesAction<T> = {\n type: 'setQueries'\n queries: MediaQueries<T>\n}\ntype Action<T> = UpdateMatchesAction | SetQueriesAction<T>\n\nexport interface MediaQueryMatches<T> {\n /**\n * Returns a map of query key/didMatch pairs\n */\n matches: Matches<T>\n /**\n * `true` if any of the media queries matched\n */\n matchesAny: boolean\n /**\n * `true` if all of the media queries matched\n */\n matchesAll: boolean\n}\n"],"names":["queriesDidChange","prevQueries","nextQueries","nextQueriesArr","Object","values","prevQueriesArr","length","some","q","i","prevKeys","keys","n","curr","key","matches","mediaQueries","init","queries","queryKeys","window","reduce","state","name","mql","matchMedia","reducer","action","prev","type","useMediaQueries","queryMap","React","dispatch","current","mq","callback","addListener","addEventListener","callbacks","map","removeListener","removeEventListener","forEach","matchValues","matchesAny","Boolean","matchesAll","every","useMediaQuery","query","getObj","cache","default"],"mappings":"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"}