diff --git a/shared.js b/shared.js index 0f4dc12c23..bbdd7185ae 100644 --- a/shared.js +++ b/shared.js @@ -32,7 +32,7 @@ module.exports = { "--viewWidth-desktopPlus": MEDIA_QUERIES.DESKTOP_PLUS, - "--viewWidth-tabletPlus": `(min-width: ${BREAKPOINTS.TABLET}px)`, + "--viewWidth-tabletPlus": MEDIA_QUERIES.SMALL_TABLET_PLUS, "--viewWidth-tablet": MEDIA_QUERIES.TABLET, "--viewWidth-tabletMinus": `(max-width: ${BREAKPOINTS.TABLET - 1}px)`, diff --git a/src/components/SplitCol/SplitCol.tsx b/src/components/SplitCol/SplitCol.tsx index ce5dfa97df..7e451d12b2 100644 --- a/src/components/SplitCol/SplitCol.tsx +++ b/src/components/SplitCol/SplitCol.tsx @@ -3,10 +3,40 @@ import { classNamesString } from "../../lib/classNames"; import { getSizeXClassName } from "../../helpers/getSizeXClassName"; import { getViewWidthClassName } from "../../helpers/getViewWidthClassName"; import { useAdaptivity } from "../../hooks/useAdaptivity"; -import { BREAKPOINTS, ViewWidth } from "../../lib/adaptivity"; -import { useDOM } from "../../lib/dom"; +import { ViewWidth } from "../../lib/adaptivity"; +import { useObjectMemo } from "../../hooks/useObjectMemo"; +import { useMediaQueries } from "../../hooks/useMediaQueries"; import styles from "./SplitCol.module.css"; +function useTransitionAnimate(animateProp?: boolean) { + const { viewWidth } = useAdaptivity(); + const [animate, setAnimate] = React.useState(Boolean(animateProp)); + const mediaQueries = useMediaQueries(); + + React.useEffect(() => { + if (animateProp !== undefined) { + setAnimate(animateProp); + return; + } + + if (viewWidth !== undefined) { + setAnimate(viewWidth < ViewWidth.TABLET); + return; + } + + // eslint-disable-next-line no-restricted-properties + const listener = () => setAnimate(!mediaQueries.smallTabletPlus.matches); + listener(); + + mediaQueries.smallTabletPlus.addEventListener("change", listener); + return () => { + mediaQueries.smallTabletPlus.removeEventListener("change", listener); + }; + }, [animateProp, viewWidth, mediaQueries]); + + return animate; +} + export interface SplitColContextProps { colRef: React.RefObject | null; animate: boolean; @@ -52,7 +82,7 @@ export const SplitCol = (props: SplitColProps) => { maxWidth, minWidth, spaced, - animate: _animate, + animate: animateProp, fixed, style, autoSpaced, @@ -62,27 +92,12 @@ export const SplitCol = (props: SplitColProps) => { } = props; const baseRef = React.useRef(null); const { viewWidth, sizeX } = useAdaptivity(); - const [animate, setAnimate] = React.useState(Boolean(_animate)); - const { window } = useDOM(); + const animate = useTransitionAnimate(animateProp); - React.useEffect(() => { - if (_animate === undefined) { - setAnimate( - viewWidth !== undefined - ? viewWidth < ViewWidth.TABLET - : window!.innerWidth < BREAKPOINTS.SMALL_TABLET - ); - } else { - setAnimate(_animate); - } - }, [_animate, viewWidth, window]); - - const contextValue = React.useMemo(() => { - return { - colRef: baseRef, - animate, - }; - }, [baseRef, animate]); + const contextValue = useObjectMemo({ + colRef: baseRef, + animate, + }); return (
{ storedMediaQueries.window = window; storedMediaQueries.mediaQueries = { desktopPlus: matchMedia(MEDIA_QUERIES.DESKTOP_PLUS), + smallTabletPlus: matchMedia(MEDIA_QUERIES.SMALL_TABLET_PLUS), tablet: matchMedia(MEDIA_QUERIES.TABLET), smallTablet: matchMedia(MEDIA_QUERIES.SMALL_TABLET), mobile: matchMedia(MEDIA_QUERIES.MOBILE), diff --git a/src/lib/adaptivity/types.ts b/src/lib/adaptivity/types.ts index a2525e76ba..c1f51f5eb7 100644 --- a/src/lib/adaptivity/types.ts +++ b/src/lib/adaptivity/types.ts @@ -22,6 +22,7 @@ export type CSSBreakpoints = export type JSBreakpoints = | "desktopPlus" | "tablet" + | "smallTabletPlus" | "smallTablet" | "mobile" | "mediumHeight" diff --git a/src/lib/browser.ts b/src/lib/browser.ts index 9647bedc83..66d63042e9 100644 --- a/src/lib/browser.ts +++ b/src/lib/browser.ts @@ -50,11 +50,6 @@ export function computeBrowserInfo(userAgent = ""): BrowserInfo { * ⚠️ Желательно избегать использование этой эмуляции в SSR. */ export function mediaQueryNull(query: string): MediaQueryList { - console.error(`[mediaQueryNull] Похоже, вы пытаетесь использовать \`Window.matchMedia()\` API вне браузера. - -Постарайтесь этого избегать, чтобы не было ошибок при гидратации: при SSR нет информации о размерах экрана. - -Используйте CSS Media Query или библиотеку по типу https://github.com/artsy/fresnel.`); return { matches: false, media: query, diff --git a/src/shared/breakpoints.js b/src/shared/breakpoints.js index d717bf06f0..cfc2d48b62 100644 --- a/src/shared/breakpoints.js +++ b/src/shared/breakpoints.js @@ -24,6 +24,7 @@ const MEDIA_QUERIES = { TABLET: `(min-width: ${BREAKPOINTS.TABLET}px) and (max-width: ${BREAKPOINTS.DESKTOP - 1}px)`, // prettier-ignore + SMALL_TABLET_PLUS: `(min-width: ${BREAKPOINTS.TABLET}px)`, SMALL_TABLET: `(min-width: ${BREAKPOINTS.SMALL_TABLET}px) and (max-width: ${BREAKPOINTS.TABLET - 1}px)`, // prettier-ignore MOBILE: `(min-width: ${BREAKPOINTS.MOBILE}px) and (max-width: ${BREAKPOINTS.SMALL_TABLET - 1}px)`, // prettier-ignore