import type { Exact } from '../../types'; import { type PlatformType } from '../platform'; import { BREAKPOINTS } from './breakpoints'; import { type SizeTypeValues, VIEW_WIDTH_TO_CSS_BREAKPOINT_MAP, ViewHeight, type ViewHeightType, ViewWidth, type ViewWidthType, } from './constants'; import type { CSSBreakpointsClassNames, MediaQueries } from './types'; /** * @public */ export function getViewWidthByViewportWidth(viewportWidth: number): ViewWidthType { if (viewportWidth >= BREAKPOINTS.DESKTOP) { return ViewWidth.DESKTOP; } if (viewportWidth >= BREAKPOINTS.TABLET) { return ViewWidth.TABLET; } if (viewportWidth >= BREAKPOINTS.SMALL_TABLET) { return ViewWidth.SMALL_TABLET; } if (viewportWidth >= BREAKPOINTS.MOBILE) { return ViewWidth.MOBILE; } return ViewWidth.SMALL_MOBILE; } export function getViewWidthByMediaQueries(mediaQueries: MediaQueries): ViewWidthType { /* eslint-disable no-restricted-properties */ if (mediaQueries.desktopPlus.matches) { return ViewWidth.DESKTOP; } if (mediaQueries.tablet.matches) { return ViewWidth.TABLET; } if (mediaQueries.smallTablet.matches) { return ViewWidth.SMALL_TABLET; } if (mediaQueries.mobile.matches) { return ViewWidth.MOBILE; } /* eslint-enable no-restricted-properties */ return ViewWidth.SMALL_MOBILE; } /** * @public */ export function getViewHeightByViewportHeight(viewportHeight: number): ViewHeightType { if (viewportHeight >= BREAKPOINTS.MEDIUM_HEIGHT) { return ViewHeight.MEDIUM; } if (viewportHeight >= BREAKPOINTS.MOBILE_LANDSCAPE_HEIGHT) { return ViewHeight.SMALL; } return ViewHeight.EXTRA_SMALL; } export function getViewHeightByMediaQueries(mediaQueries: MediaQueries): ViewHeightType { /* eslint-disable no-restricted-properties */ if (mediaQueries.mediumHeight.matches) { return ViewHeight.MEDIUM; } if (mediaQueries.mobileLandscapeHeight.matches) { return ViewHeight.SMALL; } /* eslint-enable no-restricted-properties */ return ViewHeight.EXTRA_SMALL; } export function getSizeX(viewWidth: ViewWidthType): SizeTypeValues { return viewWidth <= ViewWidth.MOBILE ? 'compact' : 'regular'; } export function isCompactByViewWidth( viewWidth: ViewWidthType | undefined, hasPointer?: boolean, ): boolean | undefined { return viewWidth !== undefined && viewWidth >= ViewWidth.SMALL_TABLET && hasPointer; } export function isCompactByViewHeight(viewHeight: ViewHeightType | undefined): boolean { return viewHeight !== undefined && viewHeight <= ViewHeight.EXTRA_SMALL; } export function getSizeY( viewWidth: ViewWidthType, viewHeight: ViewHeightType, hasPointer: boolean, ): SizeTypeValues { if (isCompactByViewWidth(viewWidth, hasPointer) || isCompactByViewHeight(viewHeight)) { return 'compact'; } return 'regular'; } /** * Проверка на Desktop. * * Функция гарантировано вернёт `boolean` или `null` в зависимости от условий. * * Возвращаем `null` в случае, если у нас недостаточно данных, чтобы определить платформу. * * ⚠️ При передаче 'vkcom' всегда будет возвращать `true`. */ export function tryToCheckIsDesktop( viewWidth: ViewWidthType, viewHeight: ViewHeightType, hasPointer: undefined | boolean, platform?: PlatformType, ): boolean; export function tryToCheckIsDesktop( viewWidth: ViewWidthType, viewHeight: undefined, hasPointer: boolean, platform?: PlatformType, ): boolean; export function tryToCheckIsDesktop( viewWidth: undefined | ViewWidthType, viewHeight: undefined, hasPointer: undefined, platform?: PlatformType, ): null; export function tryToCheckIsDesktop( viewWidth: undefined, viewHeight: undefined | ViewHeightType, hasPointer: undefined, platform?: PlatformType, ): null; export function tryToCheckIsDesktop( viewWidth: undefined, viewHeight: undefined, hasPointer: undefined | boolean, platform?: PlatformType, ): null; export function tryToCheckIsDesktop( viewWidth: undefined | ViewWidthType, viewHeight: undefined | ViewHeightType, hasPointer: undefined | boolean, platform?: PlatformType, ): null | boolean; export function tryToCheckIsDesktop( viewWidth: undefined | ViewWidthType, viewHeight: undefined | ViewHeightType, hasPointer: undefined | boolean, platform?: PlatformType, ): null | boolean { // см. https://github.com/VKCOM/VKUI/pull/2473 const IS_VKCOM_CRUTCH = platform === 'vkcom'; if ( ((viewWidth === undefined || hasPointer === undefined) && (viewWidth === undefined || viewHeight === undefined)) || (hasPointer === undefined && viewHeight === undefined) ) { return IS_VKCOM_CRUTCH ? true : null; } const widthIsLikeDesktop = viewWidth >= ViewWidth.SMALL_TABLET; const otherParametersIsLikeDesktop = hasPointer || (viewHeight !== undefined ? viewHeight >= ViewHeight.MEDIUM : false); return (widthIsLikeDesktop && otherParametersIsLikeDesktop) || IS_VKCOM_CRUTCH; } /** * Конвертирует `viewWidth` в CSS брейкпоинты (см. тесты для наглядности). * * > Note: используется восклицательный знак (!), чтобы принудить TS поверить, что св-во точно не может быть * > `undefined`. Это всё из-за применения `Partial<...>` для объекта. */ export function viewWidthToClassName>( breakpointClassNames: Exact, viewWidth: ViewWidthType | 'none' = 'none', ): string | null { if (viewWidth === 'none') { return breakpointClassNames.hasOwnProperty('none') ? breakpointClassNames['none']! : null; } const breakpoints: string[] = []; const breakpointName = VIEW_WIDTH_TO_CSS_BREAKPOINT_MAP[viewWidth]; if (breakpointClassNames.hasOwnProperty(breakpointName)) { breakpoints.push(breakpointClassNames[breakpointName]!); } if (viewWidth >= ViewWidth.MOBILE) { if (breakpointClassNames.hasOwnProperty('mobilePlus')) { breakpoints.push(breakpointClassNames['mobilePlus']!); } } if (viewWidth >= ViewWidth.SMALL_TABLET) { if (breakpointClassNames.hasOwnProperty('smallTabletPlus')) { breakpoints.push(breakpointClassNames['smallTabletPlus']!); } } else { if (breakpointClassNames.hasOwnProperty('smallTabletMinus')) { breakpoints.push(breakpointClassNames['smallTabletMinus']!); } } if (viewWidth >= ViewWidth.TABLET) { if (breakpointClassNames.hasOwnProperty('tabletPlus')) { breakpoints.push(breakpointClassNames['tabletPlus']!); } } else { if (breakpointClassNames.hasOwnProperty('tabletMinus')) { breakpoints.push(breakpointClassNames['tabletMinus']!); } } return breakpoints.length > 0 ? breakpoints.join(' ') : null; }