@gravity-ui/uikit
Version:
Gravity UI base styling and components
81 lines (80 loc) • 3.16 kB
JavaScript
import * as React from 'react';
import { useLayoutEffect } from "../../../hooks/index.js";
export const mockMediaQueryList = {
media: '',
matches: false,
onchange: () => { },
addListener: () => { },
removeListener: () => { },
addEventListener: () => { },
removeEventListener: () => { },
dispatchEvent: (_) => true,
};
export const makeCurrentActiveMediaExpressions = (mediaToValue) => ({
xs: `(max-width: ${mediaToValue.s - 1}px)`,
s: `(min-width: ${mediaToValue.s}px) and (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 {
fix;
queryListsDecl = [];
constructor(breakpointsMap, fixBreakpoints) {
const mediaToExpressionMap = makeCurrentActiveMediaExpressions(breakpointsMap);
this.fix = fixBreakpoints;
this.queryListsDecl = [
// order important here
['xs', safeMatchMedia(mediaToExpressionMap.xs)],
['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)?.[0];
if (!activeMedia) {
return this.fix ? 'xs' : 's';
}
else if (activeMedia === 'xs' && !this.fix) {
return 's';
}
return activeMedia;
}
addListeners(fn) {
this.queryListsDecl.forEach(([_, queryList]) => queryList.addEventListener('change', fn));
}
removeListeners(fn) {
this.queryListsDecl.forEach(([_, queryList]) => queryList.removeEventListener('change', fn));
}
}
/**
* @private
*/
export const useCurrentActiveMediaQuery = (breakpointsMap, fixBreakpoints, initialMediaQuery) => {
const [state, _setState] = React.useState(initialMediaQuery ?? (fixBreakpoints ? 'xs' : 's'));
useLayoutEffect(() => {
const queries = new Queries(breakpointsMap, fixBreakpoints);
const setState = () => {
_setState(queries.getCurrentActiveMedia());
};
queries.addListeners(setState);
setState();
return () => {
queries.removeListeners(setState);
};
}, [breakpointsMap, fixBreakpoints]);
return state;
};
//# sourceMappingURL=useCurrentActiveMediaQuery.js.map