сhange event listeners to hook (#156)

* refactor: micro refactor of useEventListener hook

* refactor: changed addEventListener to useEventListener hook

* refactor: renamed props type names, TComponent -> Props

* refactor: removed customStyles prop from T9n

Co-authored-by: mirlan.maksitaliev <mirlan.maksitaliev@instatsport.com>
keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
Mirlan 5 years ago committed by GitHub
parent 14cbfaf47e
commit e5e1c032fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/features/Background/index.tsx
  2. 4
      src/features/Combobox/types.tsx
  3. 4
      src/features/Common/Checkbox/index.tsx
  4. 4
      src/features/Common/Radio/index.tsx
  5. 8
      src/features/Common/customStyles/index.tsx
  6. 4
      src/features/Logo/index.tsx
  7. 5
      src/features/Menu/index.tsx
  8. 4
      src/features/Menu/styled.tsx
  9. 4
      src/features/Modal/index.tsx
  10. 4
      src/features/MultiSourcePlayer/hooks/index.tsx
  11. 4
      src/features/MultiSourcePlayer/hooks/useProgressEvents.tsx
  12. 31
      src/features/OutsideClick/hooks/index.tsx
  13. 4
      src/features/Register/components/AdditionalSubscription/index.tsx
  14. 4
      src/features/Register/components/MainSubscription/index.tsx
  15. 4
      src/features/Register/components/Price/index.tsx
  16. 6
      src/features/Search/components/Header/index.tsx
  17. 6
      src/features/Search/components/Header/styled.tsx
  18. 98
      src/features/StreamPlayer/hooks/useSlider.tsx
  19. 16
      src/features/T9n/index.tsx
  20. 8
      src/features/Theme/config.tsx
  21. 8
      src/features/Theme/index.tsx
  22. 4
      src/features/UserAccount/CardNumber/index.tsx
  23. 12
      src/features/UserAccount/CardNumber/styled.tsx
  24. 4
      src/features/UserAccount/PageTitle/index.tsx
  25. 4
      src/features/UserAccount/TextNoBorder/index.tsx
  26. 4
      src/features/UserAccount/UserAccountSubscription/index.tsx
  27. 10
      src/features/UserAccount/UserAccountSubscription/styled.tsx
  28. 6
      src/features/UserAccount/VisaLogo/styled.tsx
  29. 35
      src/hooks/useEventListener.tsx
  30. 4
      src/types/styled-components.d.ts

@ -2,11 +2,11 @@ import React, { ReactNode } from 'react'
import { GradientBackground, ImageBackground } from './styled' import { GradientBackground, ImageBackground } from './styled'
type TBackground = { type Props = {
children: ReactNode, children: ReactNode,
} }
export const Background = ({ children }: TBackground) => ( export const Background = ({ children }: Props) => (
<ImageBackground> <ImageBackground>
<GradientBackground> <GradientBackground>
{children} {children}

@ -4,7 +4,7 @@ import type {
ReactNode, ReactNode,
} from 'react' } from 'react'
import type { TCustomStyles } from 'features/Common' import type { CustomStyles } from 'features/Common'
export type Option = { export type Option = {
children?: ReactNode, children?: ReactNode,
@ -22,7 +22,7 @@ export type Props<T> = Pick<InputHTMLAttributes<HTMLInputElement>, (
| 'placeholder' | 'placeholder'
| 'readOnly' | 'readOnly'
)> & { )> & {
customListStyles?: TCustomStyles, customListStyles?: CustomStyles,
error?: string | null, error?: string | null,
filterOptions?: boolean, filterOptions?: boolean,
label?: string, label?: string,

@ -6,7 +6,7 @@ import {
Label, Label,
} from './styled' } from './styled'
type TCheckbox = Pick<InputHTMLAttributes<HTMLInputElement>, ( type Props = Pick<InputHTMLAttributes<HTMLInputElement>, (
| 'checked' | 'checked'
| 'id' | 'id'
| 'name' | 'name'
@ -23,7 +23,7 @@ export const Checkbox = ({
name, name,
onChange, onChange,
value, value,
}: TCheckbox) => ( }: Props) => (
<Wrapper> <Wrapper>
<Input <Input
id={id} id={id}

@ -6,7 +6,7 @@ import {
Label, Label,
} from './styled' } from './styled'
type TCheckbox = Pick<InputHTMLAttributes<HTMLInputElement>, ( type Props = Pick<InputHTMLAttributes<HTMLInputElement>, (
| 'checked' | 'checked'
| 'id' | 'id'
| 'name' | 'name'
@ -23,7 +23,7 @@ export const Radio = ({
name, name,
onChange, onChange,
value, value,
}: TCheckbox) => ( }: Props) => (
<Wrapper> <Wrapper>
<Input <Input
id={id} id={id}

@ -1,11 +1,11 @@
import { css } from 'styled-components' import { css } from 'styled-components'
export type TCustomStyles = string | ReturnType<typeof css> export type CustomStyles = string | ReturnType<typeof css>
type TCustomStylesMixin = { type CustomStylesMixin = {
customstyles?: TCustomStyles, customstyles?: CustomStyles,
} }
export const customStylesMixin = css<TCustomStylesMixin>` export const customStylesMixin = css<CustomStylesMixin>`
${({ customstyles }) => customstyles} ${({ customstyles }) => customstyles}
` `

@ -2,12 +2,12 @@ import styled from 'styled-components/macro'
import { devices } from 'config/devices' import { devices } from 'config/devices'
type TLogo = { type Props = {
height?: number, height?: number,
width?: number, width?: number,
} }
export const Logo = styled.div<TLogo>` export const Logo = styled.div<Props>`
display: block; display: block;
width: ${({ width = 174 }) => width}px; width: ${({ width = 174 }) => width}px;
height: ${({ height = 40 }) => height}px; height: ${({ height = 40 }) => height}px;

@ -15,7 +15,7 @@ import {
MenuItem, MenuItem,
Icon, Icon,
StyledLink, StyledLink,
linkStyles, Title,
} from './styled' } from './styled'
export const Menu = () => { export const Menu = () => {
@ -43,10 +43,9 @@ export const Menu = () => {
</MenuItem> </MenuItem>
<MenuItem> <MenuItem>
<Icon image='logout' /> <Icon image='logout' />
<T9n <Title
t='logout' t='logout'
onClick={logout} onClick={logout}
customStyles={linkStyles}
/> />
</MenuItem> </MenuItem>
</MenuList> </MenuList>

@ -4,6 +4,8 @@ import styled, { css } from 'styled-components/macro'
import { devices } from 'config/devices' import { devices } from 'config/devices'
import { T9n } from 'features/T9n'
export const Wrapper = styled.nav` export const Wrapper = styled.nav`
position: relative; position: relative;
display: flex; display: flex;
@ -88,4 +90,6 @@ export const linkStyles = css`
color: #ccc; color: #ccc;
` `
export const Title = styled(T9n)`${linkStyles}`
export const StyledLink = styled(Link)`${linkStyles}` export const StyledLink = styled(Link)`${linkStyles}`

@ -11,7 +11,7 @@ import {
ModalCloseButton, ModalCloseButton,
} from './styled' } from './styled'
type TModalProps = { type Props = {
children: ReactNode, children: ReactNode,
close: () => void, close: () => void,
isOpen: boolean, isOpen: boolean,
@ -21,7 +21,7 @@ export const Modal = ({
children, children,
close, close,
isOpen, isOpen,
}: TModalProps) => { }: Props) => {
const modalRoot = useRef(document.getElementById('modal-root')) const modalRoot = useRef(document.getElementById('modal-root'))
return isOpen return isOpen

@ -131,13 +131,13 @@ export const useMultiSourcePlayer = ({
useEventListener({ useEventListener({
callback: playNextChapter, callback: playNextChapter,
event: 'ended', event: 'ended',
ref: videoRef, target: videoRef,
}) })
useEventListener({ useEventListener({
callback: onError, callback: onError,
event: 'error', event: 'error',
ref: videoRef, target: videoRef,
}) })
useEffect(() => { useEffect(() => {

@ -42,7 +42,7 @@ export const useLoadedEvent = ({
useEventListener({ useEventListener({
callback: listenLoadedProgress, callback: listenLoadedProgress,
event: 'progress', event: 'progress',
ref: videoRef, target: videoRef,
}) })
} }
@ -63,6 +63,6 @@ export const usePlayedEvent = ({
useEventListener({ useEventListener({
callback: listenPlayedProgresses, callback: listenPlayedProgresses,
event: 'timeupdate', event: 'timeupdate',
ref: videoRef, target: videoRef,
}) })
} }

@ -1,30 +1,27 @@
import { useEffect, useRef } from 'react' import { useRef } from 'react'
type TUseOutsideClickEffect = { import { useEventListener } from 'hooks'
type Args = {
onClick: Function, onClick: Function,
} }
export const useOutsideClickEffect = ({ export const useOutsideClickEffect = ({
onClick, onClick,
}: TUseOutsideClickEffect) => { }: Args) => {
const wrapperRef = useRef<HTMLDivElement>(null) const wrapperRef = useRef<HTMLDivElement>(null)
useEffect(() => { const handleOutsideClick = ({ target }: MouseEvent) => {
const handleOutsideClick = ({ target }: MouseEvent) => { const targetNode = target instanceof Node
const targetNode = target instanceof Node ? target
? target : null
: null
/** деструктуризация wrapperRef не сработает, ссылка на реф теряется */ /** деструктуризация wrapperRef не сработает, ссылка на реф теряется */
if (!wrapperRef.current?.contains(targetNode)) { if (!wrapperRef.current?.contains(targetNode)) {
onClick() onClick()
}
} }
}
window.addEventListener('click', handleOutsideClick) useEventListener({ callback: handleOutsideClick, event: 'click' })
return () => {
window.removeEventListener('click', handleOutsideClick)
}
}, [onClick, wrapperRef])
return wrapperRef return wrapperRef
} }

@ -9,12 +9,12 @@ import {
PriceItemCol, PriceItemCol,
} from './styled' } from './styled'
type TAdditionalSubscription = { type Props = {
price: number, price: number,
title: string, title: string,
} }
export const AdditionalSubscription = ({ price, title }: TAdditionalSubscription) => ( export const AdditionalSubscription = ({ price, title }: Props) => (
<PriceItem> <PriceItem>
<PriceItemCol> <PriceItemCol>
<Checkbox name='additionalSubscription' id={title} /> <Checkbox name='additionalSubscription' id={title} />

@ -9,12 +9,12 @@ import {
Row, Row,
} from '../SubscriptionsStep/styled' } from '../SubscriptionsStep/styled'
type TMainSubscription = { type Props = {
price: number, price: number,
title: string, title: string,
} }
export const MainSubscription = ({ price, title }: TMainSubscription) => ( export const MainSubscription = ({ price, title }: Props) => (
<SubscriptionWrapper> <SubscriptionWrapper>
<Row> <Row>
<Radio name='mainSubscription' id={title} /> <Radio name='mainSubscription' id={title} />

@ -7,7 +7,7 @@ import {
PriceDetails, PriceDetails,
} from './styled' } from './styled'
type TPrice = { type Props = {
amount: number, amount: number,
currency?: string, currency?: string,
perPeriod?: string, perPeriod?: string,
@ -17,7 +17,7 @@ export const Price = ({
amount, amount,
currency = '₽', currency = '₽',
perPeriod = 'month', perPeriod = 'month',
}: TPrice) => { }: Props) => {
const { translate } = useLexicsStore() const { translate } = useLexicsStore()
const perPeriodTranslated = translate(perPeriod) const perPeriodTranslated = translate(perPeriod)

@ -1,11 +1,9 @@
import React from 'react' import React from 'react'
import { T9n } from 'features/T9n'
import { import {
Wrapper, Wrapper,
Icon, Icon,
titleStyles, Title,
} from './styled' } from './styled'
type HeaderProps = { type HeaderProps = {
@ -16,6 +14,6 @@ type HeaderProps = {
export const Header = ({ image, title }: HeaderProps) => ( export const Header = ({ image, title }: HeaderProps) => (
<Wrapper> <Wrapper>
<Icon image={image} /> <Icon image={image} />
<T9n t={title} customStyles={titleStyles} /> <Title t={title} />
</Wrapper> </Wrapper>
) )

@ -1,4 +1,6 @@
import styled, { css } from 'styled-components/macro' import styled from 'styled-components/macro'
import { T9n } from 'features/T9n'
export const Wrapper = styled.div` export const Wrapper = styled.div`
display: flex; display: flex;
@ -17,7 +19,7 @@ export const Icon = styled.div<{ image: string }>`
background-repeat: no-repeat; background-repeat: no-repeat;
` `
export const titleStyles = css` export const Title = styled(T9n)`
letter-spacing: 0.02em; letter-spacing: 0.02em;
text-transform: uppercase; text-transform: uppercase;
color: #fff; color: #fff;

@ -1,8 +1,6 @@
import { import { useRef } from 'react'
useCallback,
useEffect, import { useEventListener, useToggle } from 'hooks'
useRef,
} from 'react'
const getNormalizedProgress = (fraction: number) => { const getNormalizedProgress = (fraction: number) => {
if (fraction > 1) return 1 if (fraction > 1) return 1
@ -10,22 +8,6 @@ const getNormalizedProgress = (fraction: number) => {
return fraction return fraction
} }
const useMouseState = () => {
const mouseDownRef = useRef(false)
const setMouseDown = useCallback(() => {
mouseDownRef.current = true
}, [])
const setMouseUp = useCallback(() => {
mouseDownRef.current = false
}, [])
return {
mouseDownRef,
setMouseDown,
setMouseUp,
}
}
type Args = { type Args = {
onChange: (progress: number) => void, onChange: (progress: number) => void,
} }
@ -33,49 +15,45 @@ type Args = {
export const useSlider = ({ onChange }: Args) => { export const useSlider = ({ onChange }: Args) => {
const ref = useRef<HTMLDivElement>(null) const ref = useRef<HTMLDivElement>(null)
const { const {
mouseDownRef, close: setMouseDown,
setMouseDown, isOpen: isMouseUp,
setMouseUp, open: setMouseUp,
} = useMouseState() } = useToggle(true)
useEffect(() => { const handleProgress = (mouseX: number) => {
const handleProgress = (mouseX: number) => { const track = ref.current
const track = ref.current if (!track) return
if (!mouseDownRef.current || !track) return
const x = mouseX - track.getBoundingClientRect().left
const x = mouseX - track.getBoundingClientRect().left const progress = getNormalizedProgress(x / track.offsetWidth)
const progress = getNormalizedProgress(x / track.offsetWidth) onChange(progress)
onChange(progress) }
}
const mouseDownListener = ({ clientX, target }: MouseEvent) => { const mouseDownListener = ({ clientX, target }: MouseEvent) => {
const track = ref.current const track = ref.current
if (target === track || track?.contains(target as Node)) { if (target === track || track?.contains(target as Node)) {
setMouseDown() setMouseDown()
handleProgress(clientX) handleProgress(clientX)
}
} }
}
const mouseUpListener = setMouseUp const mouseMoveListener = (e: MouseEvent) => {
if (isMouseUp) return
const mouseMoveListener = (e: MouseEvent) => { handleProgress(e.clientX)
handleProgress(e.clientX) }
}
window.addEventListener('mousedown', mouseDownListener) useEventListener({
window.addEventListener('mouseup', mouseUpListener) callback: mouseDownListener,
window.addEventListener('mousemove', mouseMoveListener) event: 'mousedown',
return () => { })
window.removeEventListener('mousedown', mouseDownListener) useEventListener({
window.removeEventListener('mouseup', mouseUpListener) callback: setMouseUp,
window.removeEventListener('mousemove', mouseMoveListener) event: 'mouseup',
} })
}, [ useEventListener({
onChange, callback: mouseMoveListener,
mouseDownRef, event: 'mousemove',
setMouseDown, })
setMouseUp,
])
return ref return ref
} }

@ -1,32 +1,26 @@
import React from 'react' import React from 'react'
import styled, { css } from 'styled-components/macro' import styled from 'styled-components/macro'
import { useLexicsStore } from 'features/LexicsStore' import { useLexicsStore } from 'features/LexicsStore'
type TCustomStyles = { customStyles?: string | ReturnType<typeof css> } const Text = styled.span``
const Text = styled.span<TCustomStyles>` type Props = {
${({ customStyles }) => customStyles}
`
type T9nProps = {
className?: string, className?: string,
onClick?: () => void, onClick?: () => void,
t: string | number, t: string | number,
} & TCustomStyles }
export const T9n = ({ export const T9n = ({
className, className,
customStyles,
onClick, onClick,
t, t,
}: T9nProps) => { }: Props) => {
const { translate } = useLexicsStore() const { translate } = useLexicsStore()
return ( return (
<Text <Text
onClick={onClick} onClick={onClick}
customStyles={customStyles}
className={className} className={className}
> >
{translate(String(t))} {translate(String(t))}

@ -5,7 +5,7 @@ export const lightTheme = {
secondary: '', secondary: '',
text: '', text: '',
}, },
name: 'light' as TName, name: 'light' as Name,
switchTheme: () => {}, switchTheme: () => {},
} }
@ -31,10 +31,10 @@ export const darkTheme = {
secondary: '#999999', secondary: '#999999',
text: '#fff', text: '#fff',
}, },
name: 'dark' as TName, name: 'dark' as Name,
switchTheme: () => {}, switchTheme: () => {},
} }
type TName = 'light' | 'dark' type Name = 'light' | 'dark'
export type TCustomTheme = typeof lightTheme export type CustomTheme = typeof lightTheme

@ -7,17 +7,17 @@ import React, {
import { ThemeProvider } from 'styled-components' import { ThemeProvider } from 'styled-components'
import { import {
TCustomTheme, CustomTheme,
lightTheme, lightTheme,
darkTheme, darkTheme,
} from './config' } from './config'
type TThemeProps = { type Props = {
children: ReactNode, children: ReactNode,
} }
export const Theme = ({ children }: TThemeProps) => { export const Theme = ({ children }: Props) => {
const [theme, setTheme] = useState<TCustomTheme>(darkTheme) const [theme, setTheme] = useState<CustomTheme>(darkTheme)
const switchTheme = useCallback( const switchTheme = useCallback(
() => { () => {

@ -6,7 +6,7 @@ import { T9n } from 'features/T9n'
import { VisaLogoWrapper } from '../VisaLogo' import { VisaLogoWrapper } from '../VisaLogo'
import { CardNumberWrapper, CardNumberTextWrapper } from './styled' import { CardNumberWrapper, CardNumberTextWrapper } from './styled'
type TUserAccountInput = { type Props = {
checked?: boolean, checked?: boolean,
label: string, label: string,
visa?: boolean, visa?: boolean,
@ -16,7 +16,7 @@ export const CardNumber = ({
checked, checked,
label, label,
visa, visa,
}: TUserAccountInput) => ( }: Props) => (
<CardNumberWrapper> <CardNumberWrapper>
<Radio <Radio
label={label} label={label}

@ -12,11 +12,11 @@ export const CardNumberWrapper = styled.div`
border-radius: 2px; border-radius: 2px;
margin: 20px 0; margin: 20px 0;
width: 100%; width: 100%;
${Label} { ${Label} {
font-size: 20px; font-size: 20px;
line-height: 24px; line-height: 24px;
&::before { &::before {
margin-left: 22px; margin-left: 22px;
} }
@ -32,7 +32,7 @@ export const TextWrapper = styled.p`
color: #666666; color: #666666;
white-space: nowrap; white-space: nowrap;
margin-right: 0; margin-right: 0;
&:hover { &:hover {
cursor: pointer; cursor: pointer;
} }
@ -42,11 +42,11 @@ export const CardNumberTextWrapper = styled(TextWrapper)`
margin-right: 24px; margin-right: 24px;
` `
export type TPriceWrapper = { export type Props = {
noMarginRight?: boolean, noMarginRight?: boolean,
} }
export const priceWrapperStyles = css<TPriceWrapper>` export const priceWrapperStyles = css<Props>`
margin-left: auto; margin-left: auto;
margin-right: 24px; margin-right: 24px;
@ -54,7 +54,7 @@ export const priceWrapperStyles = css<TPriceWrapper>`
font-size: 24px; font-size: 24px;
line-height: 21px; line-height: 21px;
} }
${PriceDetails} { ${PriceDetails} {
font-size: 12px; font-size: 12px;
line-height: 12px; line-height: 12px;

@ -5,11 +5,11 @@ import { BlockTitle } from 'features/Login/styled'
import { PageTitleWrapper, TitleTextWrapper } from './styled' import { PageTitleWrapper, TitleTextWrapper } from './styled'
type TPageTitle = { type Props = {
titleText: string, titleText: string,
} }
export const PageTitle = ({ titleText }: TPageTitle) => ( export const PageTitle = ({ titleText }: Props) => (
<PageTitleWrapper> <PageTitleWrapper>
<Logo /> <Logo />
<TitleTextWrapper> <TitleTextWrapper>

@ -5,7 +5,7 @@ import { Price } from 'features/Register/components/Price'
import { TextNoBorderWrapper, TextNoBorderTextWrapper } from './styled' import { TextNoBorderWrapper, TextNoBorderTextWrapper } from './styled'
import { PriceWrapper } from '../CardNumber/styled' import { PriceWrapper } from '../CardNumber/styled'
type TTextNoBorder = { type Props = {
amount: number, amount: number,
text: string, text: string,
} }
@ -13,7 +13,7 @@ type TTextNoBorder = {
export const TextNoBorder = ({ export const TextNoBorder = ({
amount, amount,
text, text,
}: TTextNoBorder) => ( }: Props) => (
<TextNoBorderWrapper> <TextNoBorderWrapper>
<TextNoBorderTextWrapper>{text}</TextNoBorderTextWrapper> <TextNoBorderTextWrapper>{text}</TextNoBorderTextWrapper>
<PriceWrapper> <PriceWrapper>

@ -12,7 +12,7 @@ import {
} from './styled' } from './styled'
import { PriceWrapper } from '../CardNumber/styled' import { PriceWrapper } from '../CardNumber/styled'
type TUserAccountSubscription = { type Props = {
amount: number, amount: number,
checked?: boolean, checked?: boolean,
inputType?: string, inputType?: string,
@ -32,7 +32,7 @@ export const UserAccountSubscription = ({
noMarginTop, noMarginTop,
packageAction, packageAction,
packageName, packageName,
}: TUserAccountSubscription) => ( }: Props) => (
<UserAccountSubscriptionWrapper <UserAccountSubscriptionWrapper
noMarginTop={noMarginTop} noMarginTop={noMarginTop}
noMarginBottom={noMarginBottom} noMarginBottom={noMarginBottom}

@ -5,12 +5,12 @@ import { Label as RadioLabel } from 'features/Common/Radio/styled'
import { TextWrapper } from '../CardNumber/styled' import { TextWrapper } from '../CardNumber/styled'
export type TUserAccountSubscriptionWrapper = { type Props = {
noMarginBottom?: boolean, noMarginBottom?: boolean,
noMarginTop?: boolean, noMarginTop?: boolean,
} }
export const UserAccountSubscriptionWrapperStyles = css<TUserAccountSubscriptionWrapper>` export const UserAccountSubscriptionWrapperStyles = css<Props>`
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
@ -33,7 +33,7 @@ export const UserAccountSubscriptionWrapperStyles = css<TUserAccountSubscription
margin-top: ${({ noMarginTop }) => (noMarginTop ? '0' : '20px')}; margin-top: ${({ noMarginTop }) => (noMarginTop ? '0' : '20px')};
margin-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '0' : '20px')}; margin-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '0' : '20px')};
width: 100%; width: 100%;
${RadioLabel}::before { ${RadioLabel}::before {
margin-left: 22px; margin-left: 22px;
} }
@ -41,7 +41,7 @@ export const UserAccountSubscriptionWrapperStyles = css<TUserAccountSubscription
export const UserAccountSubscriptionWrapper = styled.div` export const UserAccountSubscriptionWrapper = styled.div`
${UserAccountSubscriptionWrapperStyles}; ${UserAccountSubscriptionWrapperStyles};
&:nth-child(n+1) { &:nth-child(n+1) {
border-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '1px solid #000' : '')}; border-bottom: ${({ noMarginBottom }) => (noMarginBottom ? '1px solid #000' : '')};
border-top: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? 'none' : '')}; border-top: ${({ noMarginBottom, noMarginTop }) => (noMarginBottom && noMarginTop ? 'none' : '')};
@ -53,7 +53,7 @@ export const CheckboxWrapper = styled.div`
font-weight: bold; font-weight: bold;
font-size: 14px; font-size: 14px;
line-height: 24px; line-height: 24px;
&::before { &::before {
margin-left: 22px; margin-left: 22px;
} }

@ -1,16 +1,16 @@
import styled, { css } from 'styled-components/macro' import styled, { css } from 'styled-components/macro'
type TCardLogoStyled = { type Props = {
visa?: boolean, visa?: boolean,
} }
export const CardLogoStyles = css<TCardLogoStyled>` export const CardLogoStyles = css<Props>`
width: ${({ visa }) => `${visa ? 37 : 30}px`}; width: ${({ visa }) => `${visa ? 37 : 30}px`};
height: ${({ visa }) => `${visa ? 12 : 19}px`}; height: ${({ visa }) => `${visa ? 12 : 19}px`};
margin-right: 82px; margin-right: 82px;
background: ${({ visa }) => `url(/images/${visa ? 'visaLogo.png' : 'masterLogo.png'}) no-repeat`}; background: ${({ visa }) => `url(/images/${visa ? 'visaLogo.png' : 'masterLogo.png'}) no-repeat`};
` `
export const VisaLogoWrapper = styled.span<TCardLogoStyled>` export const VisaLogoWrapper = styled.span<Props>`
${CardLogoStyles} ${CardLogoStyles}
` `

@ -1,22 +1,24 @@
import type { RefObject } from 'react' import type { RefObject } from 'react'
import { useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'
type Args<E> = { type EventMap = HTMLElementEventMap | WindowEventMap
callback: (e: Event) => void,
element?: HTMLElement, type Target = RefObject<HTMLElement> | HTMLElement | Window
type Args<E extends keyof EventMap> = {
callback: (e: EventMap[E]) => void,
event: E, event: E,
ref?: RefObject<HTMLElement>, target?: Target,
} }
/** /**
* Хук для подписки и отписки на события * Хук для подписки и отписки на события
* на html element, window и react ref * на html element и window
*/ */
export const useEventListener = <E extends keyof HTMLElementEventMap>({ export const useEventListener = <E extends keyof EventMap>({
callback, callback,
element,
event, event,
ref, target = window,
}: Args<E>) => { }: Args<E>) => {
const callbackRef = useRef(callback) const callbackRef = useRef(callback)
@ -25,15 +27,20 @@ export const useEventListener = <E extends keyof HTMLElementEventMap>({
}, [callback]) }, [callback])
useEffect(() => { useEffect(() => {
const htmlElement = ref?.current || element || window const windowOrElement: HTMLElement | Window | null = 'current' in target
if (!htmlElement) return undefined ? target.current
: target
const listener = (e: Event) => { // типизировать сложно без any из за того что
// у window есть события которых нет у html element
// и наоборот
const listener = (e: any) => {
callbackRef.current(e) callbackRef.current(e)
} }
htmlElement.addEventListener(event, listener)
windowOrElement?.addEventListener(event, listener)
return () => { return () => {
htmlElement.removeEventListener(event, listener) windowOrElement?.removeEventListener(event, listener)
} }
}, [event, ref, element]) }, [event, target])
} }

@ -1,5 +1,5 @@
import { TCustomTheme } from '../features/Theme/config' import { CustomTheme } from '../features/Theme/config'
declare module 'styled-components' { declare module 'styled-components' {
export interface DefaultTheme extends TCustomTheme {} export interface DefaultTheme extends CustomTheme {}
} }

Loading…
Cancel
Save