UNPKG

@atlaskit/primitives

Version:

Primitives are token-backed low-level building blocks.

72 lines (69 loc) 6.17 kB
var _window, _window$matchMedia, _window2, _window2$matchMedia, _window3, _window3$matchMedia, _window4, _window4$matchMedia, _window5, _window5$matchMedia, _window6, _window6$matchMedia, _window7, _window7$matchMedia, _window8, _window8$matchMedia, _window9, _window9$matchMedia, _window10, _window10$matchMedia, _window11, _window11$matchMedia; import { useEffect, useRef } from 'react'; import { bind } from 'bind-event-listener'; import { useLayoutEffect } from '@atlaskit/ds-lib/use-layout-effect'; import { UNSAFE_media } from './media-helper'; const queries = { 'above.xxs': typeof window === 'undefined' ? undefined : (_window = window) === null || _window === void 0 ? void 0 : (_window$matchMedia = _window.matchMedia) === null || _window$matchMedia === void 0 ? void 0 : _window$matchMedia.call(_window, UNSAFE_media.above.xxs.replace('@media ', '').trim()), 'above.xs': typeof window === 'undefined' ? undefined : (_window2 = window) === null || _window2 === void 0 ? void 0 : (_window2$matchMedia = _window2.matchMedia) === null || _window2$matchMedia === void 0 ? void 0 : _window2$matchMedia.call(_window2, UNSAFE_media.above.xs.replace('@media ', '').trim()), 'above.sm': typeof window === 'undefined' ? undefined : (_window3 = window) === null || _window3 === void 0 ? void 0 : (_window3$matchMedia = _window3.matchMedia) === null || _window3$matchMedia === void 0 ? void 0 : _window3$matchMedia.call(_window3, UNSAFE_media.above.sm.replace('@media ', '').trim()), 'above.md': typeof window === 'undefined' ? undefined : (_window4 = window) === null || _window4 === void 0 ? void 0 : (_window4$matchMedia = _window4.matchMedia) === null || _window4$matchMedia === void 0 ? void 0 : _window4$matchMedia.call(_window4, UNSAFE_media.above.md.replace('@media ', '').trim()), 'above.lg': typeof window === 'undefined' ? undefined : (_window5 = window) === null || _window5 === void 0 ? void 0 : (_window5$matchMedia = _window5.matchMedia) === null || _window5$matchMedia === void 0 ? void 0 : _window5$matchMedia.call(_window5, UNSAFE_media.above.lg.replace('@media ', '').trim()), 'above.xl': typeof window === 'undefined' ? undefined : (_window6 = window) === null || _window6 === void 0 ? void 0 : (_window6$matchMedia = _window6.matchMedia) === null || _window6$matchMedia === void 0 ? void 0 : _window6$matchMedia.call(_window6, UNSAFE_media.above.xl.replace('@media ', '').trim()), 'below.xs': typeof window === 'undefined' ? undefined : (_window7 = window) === null || _window7 === void 0 ? void 0 : (_window7$matchMedia = _window7.matchMedia) === null || _window7$matchMedia === void 0 ? void 0 : _window7$matchMedia.call(_window7, UNSAFE_media.below.xs.replace('@media ', '').trim()), 'below.sm': typeof window === 'undefined' ? undefined : (_window8 = window) === null || _window8 === void 0 ? void 0 : (_window8$matchMedia = _window8.matchMedia) === null || _window8$matchMedia === void 0 ? void 0 : _window8$matchMedia.call(_window8, UNSAFE_media.below.sm.replace('@media ', '').trim()), 'below.md': typeof window === 'undefined' ? undefined : (_window9 = window) === null || _window9 === void 0 ? void 0 : (_window9$matchMedia = _window9.matchMedia) === null || _window9$matchMedia === void 0 ? void 0 : _window9$matchMedia.call(_window9, UNSAFE_media.below.md.replace('@media ', '').trim()), 'below.lg': typeof window === 'undefined' ? undefined : (_window10 = window) === null || _window10 === void 0 ? void 0 : (_window10$matchMedia = _window10.matchMedia) === null || _window10$matchMedia === void 0 ? void 0 : _window10$matchMedia.call(_window10, UNSAFE_media.below.lg.replace('@media ', '').trim()), 'below.xl': typeof window === 'undefined' ? undefined : (_window11 = window) === null || _window11 === void 0 ? void 0 : (_window11$matchMedia = _window11.matchMedia) === null || _window11$matchMedia === void 0 ? void 0 : _window11$matchMedia.call(_window11, UNSAFE_media.below.xl.replace('@media ', '').trim()) }; /** * A hook which returnes a `window.matchMedia` result to help you build responsively around breakpoints in JavaScript. * * The returning value **WILL NOT** update or react to change. You can use `mq.matches` to get the latest version and you can use the optional listener argument to react to changes as desired. * * @important * - This will always be `null` in SSR and the event listener should not fire on SSR => clientside hydration. * - `above.xxs` will always be truthy, your listener should never fire. * * @experimental This hook only works on the client-side and is not safe in an SSR environment as `window` is unavailable (and the user's viewport would be unknown) * * @example * const mq = useMediaQuery('below.md', useCallback((event) => console.log('changed', event.matches)), [])) * const isMobile = mq?.matches; * * @returns * - `MediaQueryList`, primarily used to get if that media query is currently * - `null` when `matchMedia` is unavailable, eg. in SSR. */ export const UNSAFE_useMediaQuery = (queryString, listener) => { const listenerRef = useRef(listener); useEffect(() => { // Bind the listener if changed so it's called on the next change event; no guarantee on timing. listenerRef.current = listener; }, [listener]); /** * We explicitly only react to boolean changes for binding our listener * Changes to the functional reference are ignored. */ const hasListener = !!listener; /** * The `matchMedia(…)` return value for our breakpoint query. */ const mq = queries[queryString]; useLayoutEffect(() => { listenerRef.current = listener; // Bind the listener now in case the `useEffect` hasn't fired above yet if (!mq || !hasListener || !listenerRef.current) { return; } return bind(mq, { type: 'change', listener: event => { // We explicitly call the current version of the function return listenerRef.current(event); } }); }, // eslint-disable-next-line react-hooks/exhaustive-deps -- explicitly do not trigger the effect on `listener` reference change, only on a boolean representation of it. [mq, hasListener]); return mq || null; };