diff --git a/external/core-config/src/CoreConfigContext.tsx b/external/core-config/src/CoreConfigContext.tsx index bc491b32a8..577d799710 100644 --- a/external/core-config/src/CoreConfigContext.tsx +++ b/external/core-config/src/CoreConfigContext.tsx @@ -2,12 +2,12 @@ import { createContext, useContext } from 'react'; export type CoreConfigContext = { breakpoint: number; - ssrView: 'desktop' | 'mobile'; + client: 'desktop' | 'mobile'; }; export const CoreConfigContext = createContext({ breakpoint: 1024, - ssrView: 'desktop', + client: 'desktop', }); export const useCoreConfig = (overrides: Partial = {}) => { diff --git a/packages/amount-input/src/Component.tsx b/packages/amount-input/src/Component.tsx index dbb98a4b51..d648416136 100644 --- a/packages/amount-input/src/Component.tsx +++ b/packages/amount-input/src/Component.tsx @@ -2,7 +2,6 @@ import React, { FocusEvent, forwardRef, Fragment, useCallback, useEffect, useSta import cn from 'classnames'; import { Input, InputProps } from '@alfalab/core-components-input'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; import { withSuffix } from '@alfalab/core-components-with-suffix'; import { CurrencyCodes } from '@alfalab/data'; import { formatAmount, THINSP } from '@alfalab/utils'; @@ -135,8 +134,9 @@ export const AmountInput = forwardRef( onChange, onClear, onBlur, - breakpoint = getComponentBreakpoint(), onKeyDown, + breakpoint, + client, transparentMinor = true, inputClassName, label, @@ -363,6 +363,7 @@ export const AmountInput = forwardRef( dataTestId={dataTestId} ref={ref} breakpoint={breakpoint} + client={client} /> ); diff --git a/packages/button/src/Component.responsive.tsx b/packages/button/src/Component.responsive.tsx index 21dd37e2b0..233b5ec691 100644 --- a/packages/button/src/Component.responsive.tsx +++ b/packages/button/src/Component.responsive.tsx @@ -11,8 +11,8 @@ export const Button = forwardRef boolean); }; diff --git a/packages/calendar-input/package.json b/packages/calendar-input/package.json index b4916a761a..2522a38707 100644 --- a/packages/calendar-input/package.json +++ b/packages/calendar-input/package.json @@ -17,6 +17,7 @@ "dependencies": { "@alfalab/core-components-calendar": "^7.14.2", "@alfalab/core-components-date-input": "^4.4.4", + "@alfalab/core-components-mq": "^4.3.0", "@alfalab/core-components-popover": "^6.3.2", "@alfalab/hooks": "^1.13.0", "@alfalab/icons-glyph": "^2.139.0", diff --git a/packages/calendar-input/src/Component.responsive.tsx b/packages/calendar-input/src/Component.responsive.tsx index 5d75911432..ef2b669ff5 100644 --- a/packages/calendar-input/src/Component.responsive.tsx +++ b/packages/calendar-input/src/Component.responsive.tsx @@ -2,8 +2,7 @@ import React, { forwardRef } from 'react'; // eslint-disable-next-line @typescript-eslint/no-unused-vars import { DateInputProps } from '@alfalab/core-components-date-input'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; -import { useMedia } from '@alfalab/hooks'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { CalendarInputProps } from './components/calendar-input/Component'; import { CalendarInputDesktop } from './desktop'; @@ -15,6 +14,11 @@ export type CalendarInputResponsiveProps = Omit & { * @default 1024 */ breakpoint?: number; + + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; }; export type CalendarInputMedia = 'desktop' | 'mobile'; @@ -24,16 +28,10 @@ export type CalendarInputMedia = 'desktop' | 'mobile'; * use UniversalDateInput instead */ export const CalendarInputResponsive = forwardRef( - ({ breakpoint = getComponentBreakpoint(), ...restProps }, ref) => { - const [view] = useMedia( - [ - ['mobile', `(max-width: ${breakpoint - 1}px)`], - ['desktop', `(min-width: ${breakpoint}px)`], - ], - 'desktop', - ); + ({ breakpoint, client, ...restProps }, ref) => { + const isDesktop = useIsDesktop(breakpoint, client === 'desktop'); - return view === 'desktop' ? ( + return isDesktop ? ( ) : ( diff --git a/packages/calendar-input/tsconfig.json b/packages/calendar-input/tsconfig.json index 2077a213d3..becceb3d57 100644 --- a/packages/calendar-input/tsconfig.json +++ b/packages/calendar-input/tsconfig.json @@ -11,6 +11,7 @@ "@alfalab/core-components-input/*": ["../input/src/*"], "@alfalab/core-components-button/*": ["../button/src/*"], "@alfalab/core-components-calendar/*": ["../calendar/src/*"], + "@alfalab/core-components-popover/*": ["../popover/src/*"], "@alfalab/core-components-*": ["../*/src"] } }, @@ -19,6 +20,7 @@ { "path": "../date-input" }, { "path": "../popover" }, { "path": "../modal" }, - { "path": "../shared" }, + { "path": "../mq" }, + { "path": "../shared" } ] } diff --git a/packages/calendar/src/Component.responsive.tsx b/packages/calendar/src/Component.responsive.tsx index 80d25e03e8..96aed1e67b 100644 --- a/packages/calendar/src/Component.responsive.tsx +++ b/packages/calendar/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { CalendarMobile, CalendarMobileProps } from './components/calendar-mobile'; import { CalendarDesktop, CalendarDesktopProps } from './desktop'; @@ -14,15 +13,29 @@ export type ResponsiveCalendarProps = CalendarDesktopProps & */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; export const CalendarResponsive = forwardRef( - ({ breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, ref) => { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + ( + { + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, + ref, + ) => { + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return isDesktop ? ( diff --git a/packages/checkbox-group/src/Component.responsive.tsx b/packages/checkbox-group/src/Component.responsive.tsx index 0de8d952a1..04fe7fda79 100644 --- a/packages/checkbox-group/src/Component.responsive.tsx +++ b/packages/checkbox-group/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { FC } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { BaseCheckboxGroupProps } from './components/base-checkbox-group'; import { CheckboxGroupDesktop } from './desktop'; @@ -14,20 +13,25 @@ export type CheckboxGroupProps = Omit & { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; export const CheckboxGroup: FC = ({ - breakpoint = getComponentBreakpoint(), - defaultMatchMediaValue, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', ...restProps }) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? CheckboxGroupDesktop : CheckboxGroupMobile; diff --git a/packages/code-input/src/Component.responsive.tsx b/packages/code-input/src/Component.responsive.tsx index 50bdb528e5..04d8345564 100644 --- a/packages/code-input/src/Component.responsive.tsx +++ b/packages/code-input/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { CodeInputDesktop } from './desktop'; import { CodeInputMobile } from './mobile'; @@ -14,17 +13,29 @@ export type CodeInputProps = Omit & { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; export const CodeInput = forwardRef( - ({ breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, ref) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + ( + { + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, + ref, + ) => { + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? CodeInputDesktop : CodeInputMobile; diff --git a/packages/confirmation/src/component.responsive.tsx b/packages/confirmation/src/component.responsive.tsx index 27e73f24a8..aca9e3bec8 100644 --- a/packages/confirmation/src/component.responsive.tsx +++ b/packages/confirmation/src/component.responsive.tsx @@ -1,7 +1,6 @@ import React, { FC } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { ConfirmationDesktop } from './desktop'; import { ConfirmationMobile } from './mobile'; @@ -17,18 +16,25 @@ export type ResponsiveConfirmationProps = Omit< */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; export const ConfirmationResponsive: FC = ({ - breakpoint = getComponentBreakpoint(), - defaultMatchMediaValue = true, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', ...restProps }) => { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return isDesktop ? ( diff --git a/packages/confirmation/src/components/base-confirmation/component.tsx b/packages/confirmation/src/components/base-confirmation/component.tsx index 0640fa5000..63d6541156 100644 --- a/packages/confirmation/src/components/base-confirmation/component.tsx +++ b/packages/confirmation/src/components/base-confirmation/component.tsx @@ -1,7 +1,6 @@ import React, { ComponentType, FC, useEffect, useMemo } from 'react'; import cn from 'classnames'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; import { usePrevious } from '@alfalab/hooks'; import { ConfirmationContext } from '../../context'; @@ -40,7 +39,8 @@ export const BaseConfirmation: FC = ({ mobile, clearCodeOnError = true, hideCountdownSection = false, - breakpoint = getComponentBreakpoint(), + breakpoint, + client, initialScreenHintSlot, errorVisibleDuration, ...restProps @@ -103,6 +103,7 @@ export const BaseConfirmation: FC = ({ phone, blockSmsRetry, breakpoint, + client, onTempBlockFinished, onChangeState, onChangeScreen, diff --git a/packages/confirmation/src/components/screens/fatal-error/component.tsx b/packages/confirmation/src/components/screens/fatal-error/component.tsx index 8720942b29..7110e8f14b 100644 --- a/packages/confirmation/src/components/screens/fatal-error/component.tsx +++ b/packages/confirmation/src/components/screens/fatal-error/component.tsx @@ -17,7 +17,7 @@ export type FatalErrorProps = { }; export const FatalError: FC = ({ mobile }) => { - const { alignContent, texts, onFatalErrorOkButtonClick, breakpoint } = + const { alignContent, texts, onFatalErrorOkButtonClick, breakpoint, client } = useContext(ConfirmationContext); return ( @@ -41,6 +41,7 @@ export const FatalError: FC = ({ mobile }) => { onClick={onFatalErrorOkButtonClick} className={styles.button} breakpoint={breakpoint} + client={client} > {texts.fatalErrorButton} diff --git a/packages/confirmation/src/components/screens/hint/component.tsx b/packages/confirmation/src/components/screens/hint/component.tsx index 3094a5edb8..8d0bbd41b7 100644 --- a/packages/confirmation/src/components/screens/hint/component.tsx +++ b/packages/confirmation/src/components/screens/hint/component.tsx @@ -18,7 +18,7 @@ export type HintProps = { }; export const Hint: FC = ({ mobile }) => { - const { alignContent, texts, onChangeScreen, onChangeState, breakpoint } = + const { alignContent, texts, onChangeScreen, onChangeState, breakpoint, client } = useContext(ConfirmationContext); const handleReturnButtonClick = () => { @@ -110,6 +110,7 @@ export const Hint: FC = ({ mobile }) => { onClick={handleReturnButtonClick} className={styles.hintButton} breakpoint={breakpoint} + client={client} > {texts.hintButton} diff --git a/packages/confirmation/src/components/screens/initial/countdown-section.tsx b/packages/confirmation/src/components/screens/initial/countdown-section.tsx index ada328d93b..d5d7d8ee49 100644 --- a/packages/confirmation/src/components/screens/initial/countdown-section.tsx +++ b/packages/confirmation/src/components/screens/initial/countdown-section.tsx @@ -25,7 +25,8 @@ export const CountdownSection: FC = ({ mobile, handleSmsRetryClick, }) => { - const { state, texts, timeLeft, blockSmsRetry, breakpoint } = useContext(ConfirmationContext); + const { state, texts, timeLeft, blockSmsRetry, breakpoint, client } = + useContext(ConfirmationContext); const renderText = (text?: string) => ( = ({ onClick={handleSmsRetryClick} className={cn(styles.getCodeButton, { [styles.getCodeButtonMobile]: mobile })} breakpoint={breakpoint} + client={client} > {texts.buttonRetry} diff --git a/packages/confirmation/src/context.ts b/packages/confirmation/src/context.ts index 6f261be5b0..9d1273f417 100644 --- a/packages/confirmation/src/context.ts +++ b/packages/confirmation/src/context.ts @@ -17,6 +17,7 @@ export const ConfirmationContext = createContext({ phone: '', hideCountdownSection: false, breakpoint: 1024, + client: 'desktop', initialScreenHintSlot: null, onTempBlockFinished: mockFn, onInputFinished: mockFn, diff --git a/packages/confirmation/src/types.ts b/packages/confirmation/src/types.ts index 63ce82095d..99f97898e0 100644 --- a/packages/confirmation/src/types.ts +++ b/packages/confirmation/src/types.ts @@ -123,6 +123,11 @@ export type ConfirmationProps = { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Продолжительность отображения ошибки * @default 1300 @@ -156,14 +161,10 @@ export type TConfirmationContext = Required< | 'clearCodeOnError' | 'initialScreenHintSlot' | 'errorVisibleDuration' + | 'breakpoint' + | 'client' > & { timeLeft: number; - } & { - /** - * Контрольная точка для кнопки, с нее начинается desktop версия - * @default 1024 - */ - breakpoint?: number; }; export type ConfirmationTexts = { diff --git a/packages/custom-picker-button/src/Component.responsive.tsx b/packages/custom-picker-button/src/Component.responsive.tsx index 5878f16be6..eea9516819 100644 --- a/packages/custom-picker-button/src/Component.responsive.tsx +++ b/packages/custom-picker-button/src/Component.responsive.tsx @@ -2,12 +2,11 @@ import React, { forwardRef } from 'react'; // eslint-disable-next-line @typescript-eslint/no-unused-vars import { CustomButtonProps } from '@alfalab/core-components-custom-button'; -import { useMatchMedia } from '@alfalab/core-components-mq'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import type { AdditionalMobileProps, BottomSheetSelectMobileProps, } from '@alfalab/core-components-select/shared'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; import { CustomPickerButtonDesktop, CustomPickerButtonDesktopProps } from './desktop'; import { CustomPickerButtonMobile } from './mobile'; @@ -21,8 +20,14 @@ export type CustomPickerButtonResponsiveProps = CustomPickerButtonDesktopProps & */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; @@ -38,14 +43,14 @@ export const CustomPickerButtonResponsive = forwardRef< footer, swipeable, bottomSheetProps, - breakpoint = getComponentBreakpoint(), - defaultMatchMediaValue, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', ...restProps }, ref, ) => { - const query = `(min-width: ${breakpoint}px)`; - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return isDesktop ? ( ( - ({ breakpoint = getComponentBreakpoint(), ...restProps }, ref) => { - const [view] = useMedia( - [ - ['mobile', `(max-width: ${breakpoint - 1}px)`], - ['desktop', `(min-width: ${breakpoint}px)`], - ], - 'desktop', - ); + ({ breakpoint, client, ...restProps }, ref) => { + const isDesktop = useIsDesktop(breakpoint, client === 'desktop'); - return view === 'desktop' ? ( + return isDesktop ? ( ) : ( diff --git a/packages/date-range-input/tsconfig.json b/packages/date-range-input/tsconfig.json index b855bc2cfe..2ee196ecbf 100644 --- a/packages/date-range-input/tsconfig.json +++ b/packages/date-range-input/tsconfig.json @@ -11,6 +11,7 @@ "@alfalab/core-components-input/*": ["../input/src/*"], "@alfalab/core-components-button/*": ["../button/src/*"], "@alfalab/core-components-calendar/*": ["../calendar/src/*"], + "@alfalab/core-components-mq/*": ["../mq/src/*"], "@alfalab/core-components-*": ["../*/src"] } }, @@ -21,5 +22,6 @@ { "path": "../popover" }, { "path": "../shared" }, { "path": "../modal" }, + { "path": "../mq" } ] } diff --git a/packages/date-time-input/package.json b/packages/date-time-input/package.json index 1325587166..d0e99249c3 100644 --- a/packages/date-time-input/package.json +++ b/packages/date-time-input/package.json @@ -18,6 +18,7 @@ "@alfalab/core-components-calendar": "^7.14.2", "@alfalab/core-components-input": "^15.2.0", "@alfalab/core-components-icon-button": "^6.10.1", + "@alfalab/core-components-mq": "^4.3.0", "@alfalab/core-components-popover": "^6.3.2", "@alfalab/hooks": "^1.13.0", "@alfalab/icons-glyph": "^2.139.0", diff --git a/packages/date-time-input/src/Component.responsive.tsx b/packages/date-time-input/src/Component.responsive.tsx index 5c5a8f8379..9036568bd1 100644 --- a/packages/date-time-input/src/Component.responsive.tsx +++ b/packages/date-time-input/src/Component.responsive.tsx @@ -2,8 +2,7 @@ import React, { forwardRef } from 'react'; // eslint-disable-next-line @typescript-eslint/no-unused-vars import { InputProps } from '@alfalab/core-components-input'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; -import { useMedia } from '@alfalab/hooks'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { DateTimeInputProps } from './components/date-time-input/Component'; import { DateTimeInputDesktop } from './desktop'; @@ -15,21 +14,20 @@ export type DateTimeInputResponsiveProps = Omit( - ({ breakpoint = getComponentBreakpoint(), ...restProps }, ref) => { - const [view] = useMedia( - [ - ['mobile', `(max-width: ${breakpoint - 1}px)`], - ['desktop', `(min-width: ${breakpoint}px)`], - ], - 'desktop', - ); + ({ breakpoint, client, ...restProps }, ref) => { + const isDesktop = useIsDesktop(breakpoint, client === 'desktop'); - return view === 'desktop' ? ( + return isDesktop ? ( ) : ( diff --git a/packages/date-time-input/tsconfig.json b/packages/date-time-input/tsconfig.json index 35660fac48..faf52ba3c5 100644 --- a/packages/date-time-input/tsconfig.json +++ b/packages/date-time-input/tsconfig.json @@ -11,6 +11,7 @@ "@alfalab/core-components-form-control/*": ["../form-control/src/*"], "@alfalab/core-components-button/*": ["../button/src/*"], "@alfalab/core-components-calendar/*": ["../calendar/src/*"], + "@alfalab/core-components-mq/*": ["../mq/src/*"], "@alfalab/core-components-*": ["../*/src"] } }, @@ -21,5 +22,6 @@ { "path": "../popover" }, { "path": "../modal" }, { "path": "../shared" }, + { "path": "../mq" } ] } diff --git a/packages/filter-tag/src/Component.responsive.tsx b/packages/filter-tag/src/Component.responsive.tsx index 047bef4b80..ccf0f167cb 100644 --- a/packages/filter-tag/src/Component.responsive.tsx +++ b/packages/filter-tag/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { BaseFilterTagProps } from './components/base-filter-tag'; import { FilterTagDesktop } from './desktop'; @@ -14,20 +13,30 @@ export type FilterTagProps = Omit & { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; export const FilterTag = forwardRef( ( - { children, breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, + { + children, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, ref, ) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? FilterTagDesktop : FilterTagMobile; diff --git a/packages/form-control/src/Component.responsive.tsx b/packages/form-control/src/Component.responsive.tsx index 179045e1e2..e5d26f3019 100644 --- a/packages/form-control/src/Component.responsive.tsx +++ b/packages/form-control/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { BaseFormControlProps } from './components/base-form-control'; import { FormControlDesktop } from './desktop'; @@ -14,17 +13,29 @@ export type FormControlProps = Omit boolean); }; export const FormControl = forwardRef( - ({ breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, ref) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + ( + { + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, + ref, + ) => { + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? FormControlDesktop : FormControlMobile; diff --git a/packages/gallery/package.json b/packages/gallery/package.json index 80bad0cc3a..459612db13 100644 --- a/packages/gallery/package.json +++ b/packages/gallery/package.json @@ -16,6 +16,7 @@ "dependencies": { "@alfalab/core-components-base-modal": "^5.8.2", "@alfalab/core-components-icon-button": "^6.10.1", + "@alfalab/core-components-mq": "^4.3.0", "@alfalab/core-components-tooltip": "^7.6.0", "@alfalab/core-components-typography": "^4.10.2", "@alfalab/hooks": "^1.13.0", diff --git a/packages/gallery/src/Component.tsx b/packages/gallery/src/Component.tsx index 5d04a673a1..4749b5c79c 100644 --- a/packages/gallery/src/Component.tsx +++ b/packages/gallery/src/Component.tsx @@ -3,7 +3,7 @@ import cn from 'classnames'; import SwiperCore from 'swiper'; import { BaseModal } from '@alfalab/core-components-base-modal'; -import { useMedia } from '@alfalab/hooks'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { Header, HeaderMobile, ImageViewer, InfoBar, NavigationBar } from './components'; import { GalleryContext } from './context'; @@ -79,15 +79,7 @@ export const Gallery: FC = ({ const [playingVideo, setPlayingVideo] = useState(DEFAULT_PLAYING_VIDEO); const [hideNavigation, setHideNavigation] = useState(DEFAULT_HIDE_NAVIGATION); - const [view] = useMedia<'desktop' | 'mobile'>( - [ - ['mobile', '(max-width: 1023px)'], - ['desktop', '(min-width: 1024px)'], - ], - 'desktop', - ); - - const isMobile = view === 'mobile'; + const isDesktop = useIsDesktop(); const isCurrentVideo = !!imagesMeta[currentSlideIndex]?.player?.current; @@ -199,7 +191,7 @@ export const Gallery: FC = ({ // eslint-disable-next-line react/jsx-no-constructed-context-values const galleryContext: GalleryContext = { - view, + view: isDesktop ? 'desktop' : 'mobile', singleSlide, currentSlideIndex, images, @@ -235,16 +227,16 @@ export const Gallery: FC = ({ onUnmount={onUnmount} >
- {view === 'desktop' ?
: } + {isDesktop ?
: }
diff --git a/packages/gallery/tsconfig.json b/packages/gallery/tsconfig.json index 12a49fe92b..8801bf92d4 100644 --- a/packages/gallery/tsconfig.json +++ b/packages/gallery/tsconfig.json @@ -9,7 +9,8 @@ "@alfalab/core-components-*": ["../*/src"], "@alfalab/core-components-button/*": ["../button/src/*"], "@alfalab/core-components-tooltip/*": ["../tooltip/src/*"], - "@alfalab/core-components-icon-view/*": ["../icon-view/src/*"] + "@alfalab/core-components-icon-view/*": ["../icon-view/src/*"], + "@alfalab/core-components-mq/*": ["../mq/src/*"] } }, "references": [ @@ -18,5 +19,6 @@ { "path": "../icon-button" }, { "path": "../typography" }, { "path": "../base-modal" }, + { "path": "../mq" } ] } diff --git a/packages/input-autocomplete/src/Component.responsive.tsx b/packages/input-autocomplete/src/Component.responsive.tsx index c0313e44f6..4b9cc0fae6 100644 --- a/packages/input-autocomplete/src/Component.responsive.tsx +++ b/packages/input-autocomplete/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { InputAutocompleteDesktop } from './desktop'; import { InputAutocompleteMobile } from './mobile'; @@ -13,14 +12,15 @@ export const InputAutocomplete = forwardRef< >( ( { - breakpoint = getComponentBreakpoint(), - defaultMatchMediaValue = true, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', mobileProps, ...restProps }, ref, ) => { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return isDesktop ? ( } /> diff --git a/packages/input-autocomplete/src/types.ts b/packages/input-autocomplete/src/types.ts index 7a366e776f..e3b4a35cf4 100644 --- a/packages/input-autocomplete/src/types.ts +++ b/packages/input-autocomplete/src/types.ts @@ -94,8 +94,14 @@ export interface InputAutocompleteProps extends InputAutocompleteCommonProps { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); } diff --git a/packages/input/src/Component.responsive.tsx b/packages/input/src/Component.responsive.tsx index 016c53a694..e78b9f91ba 100644 --- a/packages/input/src/Component.responsive.tsx +++ b/packages/input/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { BaseInputProps } from './components/base-input'; import { InputDesktop } from './desktop'; @@ -14,17 +13,29 @@ export type InputProps = Omit & { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; export const Input = forwardRef( - ({ breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, ref) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + ( + { + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, + ref, + ) => { + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? InputDesktop : InputMobile; diff --git a/packages/international-phone-input/src/Component.responsive.tsx b/packages/international-phone-input/src/Component.responsive.tsx index 4094fe2945..569a19eccb 100644 --- a/packages/international-phone-input/src/Component.responsive.tsx +++ b/packages/international-phone-input/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { InternationalPhoneInputDesktop } from './desktop'; import { InternationalPhoneInputMobile } from './mobile'; @@ -10,14 +9,24 @@ import { InternationalPhoneInputProps } from './types'; export const InternationalPhoneInput = React.forwardRef< HTMLInputElement, InternationalPhoneInputProps ->(({ breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, ref) => { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); +>( + ( + { + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, + ref, + ) => { + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); - return isDesktop ? ( - - ) : ( - - ); -}); + return isDesktop ? ( + + ) : ( + + ); + }, +); InternationalPhoneInput.displayName = 'InternationalPhoneInput'; diff --git a/packages/international-phone-input/src/types.ts b/packages/international-phone-input/src/types.ts index 43c6f68663..8d989b026a 100644 --- a/packages/international-phone-input/src/types.ts +++ b/packages/international-phone-input/src/types.ts @@ -126,8 +126,14 @@ export type InternationalPhoneInputProps = InternationalPhoneInputDesktopProps & */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; diff --git a/packages/markdown/src/Component.responsive.tsx b/packages/markdown/src/Component.responsive.tsx index 1e3d46976e..6eb1a3371c 100644 --- a/packages/markdown/src/Component.responsive.tsx +++ b/packages/markdown/src/Component.responsive.tsx @@ -1,21 +1,18 @@ import React from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint, isClient } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { Markdown } from './Component'; import { MarkdownResponsiveProps } from './typings'; export const MarkdownResponsiveComponent: React.FC = ({ - breakpoint = getComponentBreakpoint(), - defaultMatchMediaValue, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', children, ...restProps }) => { - const query = `(min-width: ${breakpoint}px)`; - const getDefaultValue = () => (isClient() ? window.matchMedia(query).matches : false); - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue ?? getDefaultValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return ( diff --git a/packages/markdown/src/typings.ts b/packages/markdown/src/typings.ts index 63ece196ba..3bbb14a4e2 100644 --- a/packages/markdown/src/typings.ts +++ b/packages/markdown/src/typings.ts @@ -42,8 +42,14 @@ export type MarkdownResponsiveProps = Omit & { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; diff --git a/packages/modal/src/Component.responsive.tsx b/packages/modal/src/Component.responsive.tsx index 35035e62bc..5ca5392191 100644 --- a/packages/modal/src/Component.responsive.tsx +++ b/packages/modal/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { Content } from './components/content/Component'; import { Controls } from './components/controls'; @@ -14,13 +13,14 @@ const ModalResponsiveComponent = forwardRef { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return ( diff --git a/packages/modal/src/typings.ts b/packages/modal/src/typings.ts index cb00e4c84d..1a419f32b1 100644 --- a/packages/modal/src/typings.ts +++ b/packages/modal/src/typings.ts @@ -43,8 +43,14 @@ export type ModalResponsiveProps = ModalDesktopProps & { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; diff --git a/packages/mq/src/useIsDesktop.ts b/packages/mq/src/useIsDesktop.ts index 260a1de66e..3e961aaca3 100644 --- a/packages/mq/src/useIsDesktop.ts +++ b/packages/mq/src/useIsDesktop.ts @@ -1,20 +1,21 @@ import { useCoreConfig } from '@alfalab/core-config'; + import { useMatchMedia } from './useMatchMedia'; export function useIsDesktop(breakpoint?: number, defaultValue?: boolean | (() => boolean)) { - let ssrView; + let client; if (typeof defaultValue === 'boolean') { - ssrView = defaultValue ? 'desktop' : 'mobile'; + client = defaultValue ? 'desktop' : 'mobile'; } else if (typeof defaultValue === 'function') { - ssrView = defaultValue() ? 'desktop' : 'mobile'; + client = defaultValue() ? 'desktop' : 'mobile'; } - const config = useCoreConfig({ breakpoint, ssrView }); + const config = useCoreConfig({ breakpoint, client }); const query = `(min-width: ${config.breakpoint}px)`; - const [isDesktop] = useMatchMedia(query, config.ssrView === 'desktop'); + const [isDesktop] = useMatchMedia(query, config.client === 'desktop'); return isDesktop; } diff --git a/packages/number-input/src/Component.responsive.tsx b/packages/number-input/src/Component.responsive.tsx index 9da758b953..55fa6e89a3 100644 --- a/packages/number-input/src/Component.responsive.tsx +++ b/packages/number-input/src/Component.responsive.tsx @@ -1,16 +1,23 @@ import React, { forwardRef } from 'react'; import { Input } from '@alfalab/core-components-input'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { NumberInput, NumberInputProps } from './components/number-input'; export type NumberInputResponsiveProps = Omit; export const NumberInputResponsive = forwardRef( - ({ breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, ref) => { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + ( + { + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, + ref, + ) => { + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return ( ( - ({ breakpoint = 1024, defaultMatchMediaValue, ...restProps }, ref) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + ( + { + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, + ref, + ) => { + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? PassCodeDesktop : PassCodeMobile; diff --git a/packages/pass-code/src/Component.tsx b/packages/pass-code/src/Component.tsx index 5abf493870..4023b25096 100644 --- a/packages/pass-code/src/Component.tsx +++ b/packages/pass-code/src/Component.tsx @@ -65,8 +65,14 @@ export type BasePassCodeProps = { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); diff --git a/packages/pattern-lock-v1/src/Component.responsive.tsx b/packages/pattern-lock-v1/src/Component.responsive.tsx index 345f9d39ea..c29a64b8eb 100644 --- a/packages/pattern-lock-v1/src/Component.responsive.tsx +++ b/packages/pattern-lock-v1/src/Component.responsive.tsx @@ -1,7 +1,7 @@ import React, { forwardRef } from 'react'; import type { TPatternLockInstance } from 'react-canvas-pattern-lock'; -import { useMatchMedia } from '@alfalab/core-components-mq'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { PatternLockDesktopV1 } from './desktop'; import { PatternLockMobileV1 } from './mobile'; @@ -12,10 +12,8 @@ import { PatternLockProps } from './typings'; * Использует PatternLock */ export const PatternLockV1 = forwardRef( - ({ breakpoint = 1024, ...restProps }, ref) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query); + ({ breakpoint, ...restProps }, ref) => { + const isDesktop = useIsDesktop(); const Component = isDesktop ? PatternLockDesktopV1 : PatternLockMobileV1; diff --git a/packages/pattern-lock/src/Component.responsive.tsx b/packages/pattern-lock/src/Component.responsive.tsx index 626770df1f..f2265e9e4e 100644 --- a/packages/pattern-lock/src/Component.responsive.tsx +++ b/packages/pattern-lock/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import type { TPatternLockInstance } from '@alfalab/react-canvas-pattern-lock'; import { PatternLockDesktop } from './desktop'; @@ -9,10 +8,16 @@ import { PatternLockMobile } from './mobile'; import { PatternLockProps } from './typings'; export const PatternLock = forwardRef( - ({ breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, ref) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + ( + { + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, + ref, + ) => { + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? PatternLockDesktop : PatternLockMobile; diff --git a/packages/pattern-lock/src/typings.ts b/packages/pattern-lock/src/typings.ts index 0bdc007dd0..d7af45b38e 100644 --- a/packages/pattern-lock/src/typings.ts +++ b/packages/pattern-lock/src/typings.ts @@ -88,8 +88,14 @@ export type PatternLockProps = CommonPatternLockProps & { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; diff --git a/packages/picker-button/package.json b/packages/picker-button/package.json index b8ab38a4ca..62cc0e4d3e 100644 --- a/packages/picker-button/package.json +++ b/packages/picker-button/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "@alfalab/core-components-button": "^11.9.0", + "@alfalab/core-components-mq": "^4.3.0", "@alfalab/core-components-select": "^17.15.2", "@alfalab/core-components-popover": "^6.3.2", "@alfalab/hooks": "^1.13.0", diff --git a/packages/picker-button/src/Component.responsive.tsx b/packages/picker-button/src/Component.responsive.tsx index fa9d4c8045..3e41068e33 100644 --- a/packages/picker-button/src/Component.responsive.tsx +++ b/packages/picker-button/src/Component.responsive.tsx @@ -1,11 +1,10 @@ import React, { forwardRef } from 'react'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import type { AdditionalMobileProps, BottomSheetSelectMobileProps, } from '@alfalab/core-components-select/shared'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; -import { useMedia } from '@alfalab/hooks'; import { PickerButtonDesktop, PickerButtonDesktopProps } from './desktop'; import { PickerButtonMobile } from './mobile'; @@ -18,6 +17,11 @@ export type PickerButtonResponsiveProps = PickerButtonDesktopProps & * @default 1024 */ breakpoint?: number; + + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; }; export const PickerButtonResponsive = forwardRef( @@ -28,20 +32,15 @@ export const PickerButtonResponsive = forwardRef { - const [view] = useMedia( - [ - ['mobile', `(max-width: ${breakpoint - 1}px)`], - ['desktop', `(min-width: ${breakpoint}px)`], - ], - 'desktop', - ); + const isDesktop = useIsDesktop(breakpoint, client === 'desktop'); - return view === 'desktop' ? ( + return isDesktop ? ( & { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; export const Plate = forwardRef( ( - { children, breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, + { + children, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, ref, ) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? PlateDesktop : PlateMobile; diff --git a/packages/radio-group/src/Component.responsive.tsx b/packages/radio-group/src/Component.responsive.tsx index 0e417dabe1..d56da806e4 100644 --- a/packages/radio-group/src/Component.responsive.tsx +++ b/packages/radio-group/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { BaseRadioGroupProps } from './components/base-radio-group'; import { RadioGroupDesktop } from './desktop'; @@ -14,17 +13,29 @@ export type RadioGroupProps = Omit & { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; export const RadioGroup = forwardRef( - ({ breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, ref) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + ( + { + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, + ref, + ) => { + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? RadioGroupDesktop : RadioGroupMobile; diff --git a/packages/select-with-tags/src/Component.responsive.tsx b/packages/select-with-tags/src/Component.responsive.tsx index 71d4e7500e..93cdd9ed0b 100644 --- a/packages/select-with-tags/src/Component.responsive.tsx +++ b/packages/select-with-tags/src/Component.responsive.tsx @@ -3,16 +3,23 @@ import React, { forwardRef } from 'react'; import { BottomSheet } from '@alfalab/core-components-bottom-sheet'; import { FormControlDesktop } from '@alfalab/core-components-form-control/desktop'; import { FormControlMobile } from '@alfalab/core-components-form-control/mobile'; -import { useMatchMedia } from '@alfalab/core-components-mq'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { Popover } from '@alfalab/core-components-popover'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; import { BaseSelectWithTags } from './components/base-select-with-tags'; import { SelectWithTagsProps } from './types'; export const SelectWithTags = forwardRef( - ({ breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, ref) => { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + ( + { + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, + ref, + ) => { + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return ( boolean); }; diff --git a/packages/select/src/Component.responsive.tsx b/packages/select/src/Component.responsive.tsx index 2b522c6f69..d318b8287c 100644 --- a/packages/select/src/Component.responsive.tsx +++ b/packages/select/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { SelectDesktop } from './desktop'; import { SelectMobile } from './mobile'; @@ -15,13 +14,14 @@ export const SelectResponsive = forwardRef< { onScroll, fieldProps, - breakpoint = getComponentBreakpoint(), - defaultMatchMediaValue, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', ...restProps }, ref, ) => { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); if (isDesktop) { return ( diff --git a/packages/select/src/typings.ts b/packages/select/src/typings.ts index ee59212e42..a297226eaa 100644 --- a/packages/select/src/typings.ts +++ b/packages/select/src/typings.ts @@ -919,8 +919,14 @@ export type SelectProps = BaseSelectProps & */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; diff --git a/packages/shared/src/customBreakpoints/injectCustomBreakpoint-768.ts b/packages/shared/src/customBreakpoints/injectCustomBreakpoint-768.ts deleted file mode 100644 index 7d4f6de474..0000000000 --- a/packages/shared/src/customBreakpoints/injectCustomBreakpoint-768.ts +++ /dev/null @@ -1,5 +0,0 @@ -/* eslint-disable func-names */ -(function () { - globalThis.globalBreakpointDesktop = 768; -})(); -/* eslint-enable func-names */ diff --git a/packages/shared/src/getComponentBreakpoint/getComponentBreakpoint.test.ts b/packages/shared/src/getComponentBreakpoint/getComponentBreakpoint.test.ts deleted file mode 100644 index 74c03681b2..0000000000 --- a/packages/shared/src/getComponentBreakpoint/getComponentBreakpoint.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { getComponentBreakpoint } from './getComponentBreakpoint'; - -describe('getComponentBreakpoint', () => { - it('get default value', () => { - const breakpoint = getComponentBreakpoint(); - expect(breakpoint).toBe(1024); - }); - - it('get custom value', () => { - Object.defineProperty(window, 'getComputedStyle', { - value: () => { - return { - getPropertyValue: () => { - return 768; - }, - }; - }, - }); - - const customBreakpoint = getComponentBreakpoint(); - - expect(customBreakpoint).toBe(768); - }); -}); diff --git a/packages/shared/src/getComponentBreakpoint/getComponentBreakpoint.ts b/packages/shared/src/getComponentBreakpoint/getComponentBreakpoint.ts deleted file mode 100644 index ae073c516b..0000000000 --- a/packages/shared/src/getComponentBreakpoint/getComponentBreakpoint.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { isClient } from '../isClient'; - -/* eslint-disable vars-on-top, no-var, @typescript-eslint/no-namespace */ -declare global { - namespace globalThis { - var globalBreakpointDesktop: number; - } -} -/* eslint-disable vars-on-top, no-var, @typescript-eslint/no-namespace */ - -const defaultComponentBreakpoint = 1024; - -const getCSSCustomBreakpoint = (): number | null => { - // проверяем глобальный css custom property - const breakpoint = - isClient() && - window - ?.getComputedStyle(document.documentElement) - ?.getPropertyValue('--global-breakpoint-desktop'); - - return breakpoint ? parseFloat(breakpoint) : null; -}; - -export function getComponentBreakpoint(): number { - const cssCustomBreakpoint = getCSSCustomBreakpoint(); - - if (cssCustomBreakpoint) { - return cssCustomBreakpoint; - } - - if (globalThis.globalBreakpointDesktop) { - return globalThis.globalBreakpointDesktop; - } - - return defaultComponentBreakpoint; -} diff --git a/packages/shared/src/getComponentBreakpoint/index.ts b/packages/shared/src/getComponentBreakpoint/index.ts deleted file mode 100644 index 10f93d7bb1..0000000000 --- a/packages/shared/src/getComponentBreakpoint/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { getComponentBreakpoint } from './getComponentBreakpoint'; diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index e2ec03cfc7..82099d6245 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -10,4 +10,3 @@ export * from './os'; export * from './dom'; export * from './exhaustiveCheck'; export * from './context/PortalContext'; -export * from './getComponentBreakpoint'; diff --git a/packages/side-panel/src/Component.responsive.tsx b/packages/side-panel/src/Component.responsive.tsx index 81475ab58c..69117dc9da 100644 --- a/packages/side-panel/src/Component.responsive.tsx +++ b/packages/side-panel/src/Component.responsive.tsx @@ -2,8 +2,7 @@ import React, { FC, forwardRef, useContext, useMemo } from 'react'; import { BaseModalProps } from '@alfalab/core-components-base-modal'; import { DrawerProps } from '@alfalab/core-components-drawer'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint, isClient } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { Controls } from './components/controls'; import { Header } from './components/header/Component'; @@ -32,8 +31,14 @@ export type SidePanelResponsiveProps = BaseModalProps & */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; @@ -58,18 +63,16 @@ const SidePanelResponsiveComponent = forwardRef { - const query = `(min-width: ${breakpoint}px)`; - const getDefaultValue = () => (isClient() ? window.matchMedia(query).matches : false); - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue ?? getDefaultValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const view = isDesktop ? 'desktop' : 'mobile'; diff --git a/packages/system-message/src/Components.responsive.tsx b/packages/system-message/src/Components.responsive.tsx index e8656e275c..bbc9703732 100644 --- a/packages/system-message/src/Components.responsive.tsx +++ b/packages/system-message/src/Components.responsive.tsx @@ -1,22 +1,19 @@ import React from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint, isClient } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { SystemMessage } from './Component'; import type { SystemMessageResponsiveProps } from './types'; import { createCompound } from './utils'; const SystemMessageResponsiveComponent: React.FC = ({ - breakpoint = getComponentBreakpoint(), - defaultMatchMediaValue, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', children, ...restProps }) => { - const query = `(min-width: ${breakpoint}px)`; - const getDefaultValue = () => (isClient() ? window.matchMedia(query).matches : false); - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue ?? getDefaultValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return ( diff --git a/packages/system-message/src/types.ts b/packages/system-message/src/types.ts index 7aa075a496..44a6b558a2 100644 --- a/packages/system-message/src/types.ts +++ b/packages/system-message/src/types.ts @@ -43,8 +43,14 @@ export type SystemMessageResponsiveProps = Omit */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; diff --git a/packages/tabs/src/components/primary-tablist/Component.collapsible.tsx b/packages/tabs/src/components/primary-tablist/Component.collapsible.tsx index f217e9fa84..0a9c6f7c55 100644 --- a/packages/tabs/src/components/primary-tablist/Component.collapsible.tsx +++ b/packages/tabs/src/components/primary-tablist/Component.collapsible.tsx @@ -7,7 +7,6 @@ import { PickerButtonDesktop, PickerButtonDesktopProps, } from '@alfalab/core-components-picker-button/desktop'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; import { useTablistTitles } from '../../hooks/use-tablist-titles'; import { createSyntheticMouseEvent } from '../../synthetic-events'; @@ -26,7 +25,8 @@ export const CollapsiblePrimaryTabList = ({ fullWidthScroll, onChange, dataTestId, - breakpoint = getComponentBreakpoint(), + breakpoint, + client, defaultMatchMediaValue, textStyle, showSkeleton, @@ -39,8 +39,9 @@ export const CollapsiblePrimaryTabList = ({ titles, selectedId, collapsedTabsIds, - breakpoint, onChange, + breakpoint, + client, defaultMatchMediaValue, }); diff --git a/packages/tabs/src/components/primary-tablist/Component.responsive.tsx b/packages/tabs/src/components/primary-tablist/Component.responsive.tsx index 48fb8ed51c..00c4ae0687 100644 --- a/packages/tabs/src/components/primary-tablist/Component.responsive.tsx +++ b/packages/tabs/src/components/primary-tablist/Component.responsive.tsx @@ -1,7 +1,6 @@ import React from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { TabListProps } from '../../typings'; @@ -10,12 +9,13 @@ import { PrimaryTabListMobile } from './Component.mobile'; export const PrimaryTabListResponsive = ({ size, - breakpoint = getComponentBreakpoint(), + breakpoint, + client, fullWidthScroll, - defaultMatchMediaValue, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', ...restProps }: TabListProps) => { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return isDesktop ? ( { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return isDesktop ? ( diff --git a/packages/tabs/src/components/tabs/Component.responsive.tsx b/packages/tabs/src/components/tabs/Component.responsive.tsx index 654da08bc9..cf584a30e6 100644 --- a/packages/tabs/src/components/tabs/Component.responsive.tsx +++ b/packages/tabs/src/components/tabs/Component.responsive.tsx @@ -16,5 +16,17 @@ export type TabsResponsiveProps = Omit ; +}: TabsResponsiveProps) => ( + +); diff --git a/packages/tabs/src/components/tabs/Component.tsx b/packages/tabs/src/components/tabs/Component.tsx index ddc7bb6f1f..69800a0d1e 100644 --- a/packages/tabs/src/components/tabs/Component.tsx +++ b/packages/tabs/src/components/tabs/Component.tsx @@ -1,7 +1,5 @@ import React, { cloneElement } from 'react'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; - import { TabsProps } from '../../typings'; export const Tabs = ({ @@ -9,7 +7,6 @@ export const Tabs = ({ className, containerClassName, size, - defaultMatchMediaValue, children, selectedId, scrollable, @@ -18,7 +15,9 @@ export const Tabs = ({ keepMounted = false, dataTestId, onChange, - breakpoint = getComponentBreakpoint(), + breakpoint, + client, + defaultMatchMediaValue, tagShape, tagView, showSkeleton = false, @@ -67,8 +66,9 @@ export const Tabs = ({ onChange={onChange} dataTestId={dataTestId} defaultMatchMediaValue={defaultMatchMediaValue} - fullWidthScroll={fullWidthScroll} breakpoint={breakpoint} + client={client} + fullWidthScroll={fullWidthScroll} tagShape={tagShape} tagView={tagView} textStyle={textStyle} diff --git a/packages/tabs/src/hooks/use-tablist-titles.ts b/packages/tabs/src/hooks/use-tablist-titles.ts index 593b5f7dff..12b8606393 100644 --- a/packages/tabs/src/hooks/use-tablist-titles.ts +++ b/packages/tabs/src/hooks/use-tablist-titles.ts @@ -1,6 +1,6 @@ import { useMemo } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { TabListProps } from '../typings'; @@ -11,20 +11,26 @@ export const useTablistTitles = ({ titles = [], selectedId, collapsedTabsIds, - breakpoint, onChange, - defaultMatchMediaValue, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', }: Pick< TabListProps, - 'titles' | 'selectedId' | 'collapsedTabsIds' | 'onChange' | 'defaultMatchMediaValue' -> & - Required>) => { + | 'titles' + | 'selectedId' + | 'collapsedTabsIds' + | 'onChange' + | 'defaultMatchMediaValue' + | 'breakpoint' + | 'client' +>) => { const { containerRef, addonRef, idsCollapsedElements } = useCollapsibleElements< HTMLDivElement, HTMLInputElement >('[role=tab]', [titles, collapsedTabsIds]); - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const tablistTitles = useMemo(() => { const idsCollapsedTitles: string[] = []; diff --git a/packages/tabs/src/typings.ts b/packages/tabs/src/typings.ts index a943b43360..7895406f21 100644 --- a/packages/tabs/src/typings.ts +++ b/packages/tabs/src/typings.ts @@ -60,11 +60,6 @@ export type TabsProps = { */ size?: 'xxs' | 'xs' | 's' | 'm' | 'l' | 'xl'; - /** - * Значение по-умолчанию для хука useMatchMedia - */ - defaultMatchMediaValue?: boolean | (() => boolean); - /** * Мобильный вид */ @@ -106,11 +101,22 @@ export type TabsProps = { dataTestId?: string; /** - * Контрольная точка для тега, с нее начинается desktop версия + * Контрольная точка, с нее начинается desktop версия * @default 1024 */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + + /** + * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client + */ + defaultMatchMediaValue?: boolean | (() => boolean); + /** * Форма тега (для view secondary только) */ @@ -229,11 +235,18 @@ export type TabListProps = Pick< * Заголовки табов */ titles?: TabListTitle[]; + /** * Контрольная точка, с нее начинается desktop версия * @default 1024 */ breakpoint?: number; + + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Дополнительные инлайн стили для заголовка */ diff --git a/packages/tag/src/Component.responsive.tsx b/packages/tag/src/Component.responsive.tsx index 47dace7167..db67ee0a83 100644 --- a/packages/tag/src/Component.responsive.tsx +++ b/packages/tag/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { BaseTagProps } from './components/base-tag'; import { TagDesktop } from './desktop'; @@ -14,20 +13,30 @@ export type TagProps = Omit & { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; export const Tag = forwardRef( ( - { children, breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, + { + children, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, ref, ) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? TagDesktop : TagMobile; diff --git a/packages/textarea/package.json b/packages/textarea/package.json index 3c4f01c247..8a85048900 100644 --- a/packages/textarea/package.json +++ b/packages/textarea/package.json @@ -15,6 +15,7 @@ }, "dependencies": { "@alfalab/core-components-form-control": "^12.6.0", + "@alfalab/core-components-mq": "^4.3.0", "@alfalab/core-components-shared": "^0.13.0", "@alfalab/hooks": "^1.13.0", "classnames": "^2.3.1", diff --git a/packages/textarea/src/Component.tsx b/packages/textarea/src/Component.tsx index 6de1fc7015..3842acf831 100644 --- a/packages/textarea/src/Component.tsx +++ b/packages/textarea/src/Component.tsx @@ -4,8 +4,9 @@ import TextareaAutosize from 'react-textarea-autosize'; import cn from 'classnames'; import { FormControl } from '@alfalab/core-components-form-control'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { getDataTestId } from '@alfalab/core-components-shared'; -import { useFocus, useMedia } from '@alfalab/hooks'; +import { useFocus } from '@alfalab/hooks'; import { PseudoTextArea } from './components'; import { SIZE_TO_CLASSNAME_MAP } from './consts'; @@ -61,12 +62,15 @@ export const Textarea = forwardRef( nativeScrollbar: nativeScrollbarProp, wrapperRef, breakpoint, + client, ...restProps }, ref, ) => { const uncontrolled = value === undefined; - let [nativeScrollbar] = useMedia([[true, '(max-width: 1023px)']], false); + + const isDesktop = useIsDesktop(breakpoint, client === 'desktop'); + let nativeScrollbar = !isDesktop; nativeScrollbar = Boolean(nativeScrollbarProp ?? nativeScrollbar); diff --git a/packages/textarea/src/typings.ts b/packages/textarea/src/typings.ts index 5efd2a9a67..fbb697a8a7 100644 --- a/packages/textarea/src/typings.ts +++ b/packages/textarea/src/typings.ts @@ -157,6 +157,11 @@ export type TextareaIncomeProps = { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Ref для обертки textarea */ diff --git a/packages/textarea/tsconfig.json b/packages/textarea/tsconfig.json index d241349eab..d967b50cdb 100644 --- a/packages/textarea/tsconfig.json +++ b/packages/textarea/tsconfig.json @@ -7,8 +7,9 @@ "baseUrl": ".", "paths": { "@alfalab/core-components-*": ["../*/src"], - "@alfalab/core-components-form-control/*": ["../form-control/src/*"] + "@alfalab/core-components-form-control/*": ["../form-control/src/*"], + "@alfalab/core-components-mq/*": ["../mq/src/*"] } }, - "references": [{ "path": "../form-control" }, { "path": "../shared" }] + "references": [{ "path": "../form-control" }, { "path": "../shared" }, { "path": "../mq" }] } diff --git a/packages/toast-plate/src/Component.responsive.tsx b/packages/toast-plate/src/Component.responsive.tsx index fe483997a9..f2b4cbc2ac 100644 --- a/packages/toast-plate/src/Component.responsive.tsx +++ b/packages/toast-plate/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { BaseToastPlateProps } from './components/base-toast-plate'; import { ToastPlateDesktop } from './desktop'; @@ -14,20 +13,30 @@ export type ToastPlateProps = Omit & { */ breakpoint?: number; + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; + /** * Значение по-умолчанию для хука useMatchMedia + * @deprecated Используйте client */ defaultMatchMediaValue?: boolean | (() => boolean); }; export const ToastPlate = forwardRef( ( - { children, breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, + { + children, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, ref, ) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? ToastPlateDesktop : ToastPlateMobile; diff --git a/packages/toast/src/Component.responsive.tsx b/packages/toast/src/Component.responsive.tsx index e0f779bc17..a5f9758a43 100644 --- a/packages/toast/src/Component.responsive.tsx +++ b/packages/toast/src/Component.responsive.tsx @@ -1,7 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { BaseToastProps } from './components/base-toast'; import { ToastDesktop } from './desktop'; @@ -11,12 +10,16 @@ export type ToastProps = BaseToastProps; export const Toast = forwardRef( ( - { children, breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, ...restProps }, + { + children, + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + ...restProps + }, ref, ) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); const Component = isDesktop ? ToastDesktop : ToastMobile; diff --git a/packages/tooltip/src/Component.responsive.tsx b/packages/tooltip/src/Component.responsive.tsx index 089a75d1d6..f2fad9e46d 100644 --- a/packages/tooltip/src/Component.responsive.tsx +++ b/packages/tooltip/src/Component.responsive.tsx @@ -1,21 +1,21 @@ import React, { FC } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { TooltipDesktop } from './desktop'; import { TooltipMobile } from './mobile'; import { TooltipResponsiveProps } from './types'; export const TooltipResponsive: FC = ({ - defaultMatchMediaValue, children, actionButtonTitle, bottomSheetProps, - breakpoint = getComponentBreakpoint(), + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', ...restProps }) => { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return isDesktop ? ( {children} diff --git a/packages/tooltip/src/types.ts b/packages/tooltip/src/types.ts index 6b456b331d..b260797e37 100644 --- a/packages/tooltip/src/types.ts +++ b/packages/tooltip/src/types.ts @@ -169,11 +169,6 @@ export type TooltipMobileProps = Omit, 'actionButton'> }; export type TooltipResponsiveProps = Omit & { - /** - * Значение по-умолчанию для хука useMatchMedia - */ - defaultMatchMediaValue?: boolean | (() => boolean); - /** * Обработчик открытия */ @@ -205,4 +200,15 @@ export type TooltipResponsiveProps = Omit boolean); }; diff --git a/packages/typography/src/title-responsive/component.tsx b/packages/typography/src/title-responsive/component.tsx index 8839c6e4c6..c7a0a4a656 100644 --- a/packages/typography/src/title-responsive/component.tsx +++ b/packages/typography/src/title-responsive/component.tsx @@ -1,6 +1,6 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { Title, TitleProps } from '../title'; import { TitleMobile } from '../title-mobile'; @@ -11,15 +11,18 @@ export type TitleResponsiveProps = TitleProps & { * @default 1024 */ breakpoint?: number; + + /** + * Версия, которая будет использоваться при серверном рендеринге + */ + client?: 'desktop' | 'mobile'; }; export const TitleResponsive = forwardRef< HTMLHeadingElement | HTMLDivElement, TitleResponsiveProps ->(({ defaultMatchMediaValue, breakpoint = 1024, ...restProps }, ref) => { - const query = `(min-width: ${breakpoint}px)`; - - const [isDesktop] = useMatchMedia(query, defaultMatchMediaValue); +>(({ breakpoint, client, ...restProps }, ref) => { + const isDesktop = useIsDesktop(breakpoint, client === 'desktop'); const Component = isDesktop ? Title : TitleMobile; diff --git a/packages/universal-date-input/src/Component.responsive.tsx b/packages/universal-date-input/src/Component.responsive.tsx index 2ad94db26b..869a1c5d25 100644 --- a/packages/universal-date-input/src/Component.responsive.tsx +++ b/packages/universal-date-input/src/Component.responsive.tsx @@ -1,17 +1,22 @@ import React, { forwardRef } from 'react'; -import { useMatchMedia } from '@alfalab/core-components-mq'; -import { getComponentBreakpoint } from '@alfalab/core-components-shared'; +import { useIsDesktop } from '@alfalab/core-components-mq'; import { BaseUniversalDateInput } from './components/base-universal-date-input'; import type { UniversalDateInputProps } from './types'; export const UniversalDateInput = forwardRef( ( - { breakpoint = getComponentBreakpoint(), defaultMatchMediaValue, view, ...restProps }, + { + breakpoint, + client, + defaultMatchMediaValue = client === undefined ? undefined : client === 'desktop', + view, + ...restProps + }, ref, ) => { - const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue); + const isDesktop = useIsDesktop(breakpoint, defaultMatchMediaValue); return (