UNPKG

@gravity-ui/uikit

Version:

Gravity UI base styling and components

74 lines (73 loc) 2.79 kB
/* eslint-disable valid-jsdoc */ import * as React from 'react'; export const mockMediaQueryList = { media: '', matches: false, onchange: () => { }, addListener: () => { }, removeListener: () => { }, addEventListener: () => { }, removeEventListener: () => { }, dispatchEvent: (_) => true, }; export const makeCurrentActiveMediaExpressions = (mediaToValue) => ({ s: `(max-width: ${mediaToValue.m - 1}px)`, m: `(min-width: ${mediaToValue.m}px) and (max-width: ${mediaToValue.l - 1}px)`, l: `(min-width: ${mediaToValue.l}px) and (max-width: ${mediaToValue.xl - 1}px)`, xl: `(min-width: ${mediaToValue.xl}px) and (max-width: ${mediaToValue.xxl - 1}px)`, xxl: `(min-width: ${mediaToValue.xxl}px) and (max-width: ${mediaToValue.xxxl - 1}px)`, xxxl: `(min-width: ${mediaToValue.xxxl}px)`, }); const safeMatchMedia = (query) => { if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') { return mockMediaQueryList; } return window.matchMedia(query); }; class Queries { queryListsDecl = []; constructor(breakpointsMap) { const mediaToExpressionMap = makeCurrentActiveMediaExpressions(breakpointsMap); this.queryListsDecl = [ // order important here ['s', safeMatchMedia(mediaToExpressionMap.s)], ['m', safeMatchMedia(mediaToExpressionMap.m)], ['l', safeMatchMedia(mediaToExpressionMap.l)], ['xl', safeMatchMedia(mediaToExpressionMap.xl)], ['xxl', safeMatchMedia(mediaToExpressionMap.xxl)], ['xxxl', safeMatchMedia(mediaToExpressionMap.xxxl)], ]; } getCurrentActiveMedia() { const activeMedia = this.queryListsDecl.find(([_, queryList]) => queryList.matches); if (!activeMedia) { return 's'; } return activeMedia[0]; } addListeners(fn) { this.queryListsDecl.forEach(([_, queryList]) => queryList.addEventListener('change', fn)); } removeListeners(fn) { this.queryListsDecl.forEach(([_, queryList]) => queryList.removeEventListener('change', fn)); } } /** * @private - use `useLayoutContext` hook instead */ export const useCurrentActiveMediaQuery = (breakpointsMap, initialMediaQuery = 's') => { const [state, _setState] = React.useState(initialMediaQuery); React.useLayoutEffect(() => { const queries = new Queries(breakpointsMap); const setState = () => { _setState(queries.getCurrentActiveMedia()); }; queries.addListeners(setState); setState(); return () => { queries.removeListeners(setState); }; }, [breakpointsMap]); return state; }; //# sourceMappingURL=useCurrentActiveMediaQuery.js.map