From e7ddbcf38354bdb409832fcacba8ba8b5ab2923c Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 3 Jul 2024 18:03:23 +0200 Subject: [PATCH] refactor: use shared HorizontalScroll component for Chips and Calendar --- src/common/Chips/Chips.less | 15 ------- src/common/Chips/Chips.tsx | 27 ++----------- .../HorizontalScroll/HorizontalScroll.less | 20 ++++++++++ .../HorizontalScroll/HorizontalScroll.tsx | 40 +++++++++++++++++++ src/common/HorizontalScroll/index.ts | 4 ++ src/common/index.js | 2 + src/routes/Calendar/Table/Cell/Cell.less | 1 - src/routes/Calendar/Table/Cell/Cell.tsx | 6 +-- 8 files changed, 73 insertions(+), 42 deletions(-) create mode 100644 src/common/HorizontalScroll/HorizontalScroll.less create mode 100644 src/common/HorizontalScroll/HorizontalScroll.tsx create mode 100644 src/common/HorizontalScroll/index.ts diff --git a/src/common/Chips/Chips.less b/src/common/Chips/Chips.less index cf0e85917..7d7e15d18 100644 --- a/src/common/Chips/Chips.less +++ b/src/common/Chips/Chips.less @@ -1,7 +1,5 @@ // Copyright (C) 2017-2024 Smart code 203358507 -@mask-width: 10%; - .chips { position: relative; width: 100%; @@ -9,17 +7,4 @@ align-items: center; justify-content: flex-start; gap: 1rem; - overflow-x: auto; - - &.left { - mask-image: linear-gradient(90deg, rgba(0, 0, 0, 1) calc(100% - @mask-width), rgba(0, 0, 0, 0) 100%); - } - - &.right { - mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) @mask-width); - } - - &.center { - mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) @mask-width, rgba(0, 0, 0, 1) calc(100% - @mask-width), rgba(0, 0, 0, 0) 100%); - } } \ No newline at end of file diff --git a/src/common/Chips/Chips.tsx b/src/common/Chips/Chips.tsx index 4e02c620f..e07b00e8c 100644 --- a/src/common/Chips/Chips.tsx +++ b/src/common/Chips/Chips.tsx @@ -1,7 +1,7 @@ // Copyright (C) 2017-2024 Smart code 203358507 -import React, { memo, useEffect, useRef, useState } from 'react'; -import classNames from 'classnames'; +import React, { memo } from 'react'; +import HorizontalScroll from '../HorizontalScroll'; import Chip from './Chip'; import styles from './Chips.less'; @@ -16,28 +16,9 @@ type Props = { onSelect: (value: string) => {}, }; -const SCROLL_THRESHOLD = 1; - const Chips = memo(({ options, selected, onSelect }: Props) => { - const ref = useRef(null); - const [scrollPosition, setScrollPosition] = useState('left'); - - useEffect(() => { - const onScroll = ({ target }: Event) => { - const { scrollLeft, scrollWidth, offsetWidth} = target as HTMLDivElement; - const position = - (scrollLeft - SCROLL_THRESHOLD) <= 0 ? 'left' : - (scrollLeft + offsetWidth + SCROLL_THRESHOLD) >= scrollWidth ? 'right' : - 'center'; - setScrollPosition(position); - }; - - ref.current?.addEventListener('scroll', onScroll); - return () => ref.current?.removeEventListener('scroll', onScroll); - }, []); - return ( -
+ { options.map(({ label, value }) => ( { /> )) } -
+ ); }); diff --git a/src/common/HorizontalScroll/HorizontalScroll.less b/src/common/HorizontalScroll/HorizontalScroll.less new file mode 100644 index 000000000..cb4b9be7c --- /dev/null +++ b/src/common/HorizontalScroll/HorizontalScroll.less @@ -0,0 +1,20 @@ +// Copyright (C) 2017-2024 Smart code 203358507 + +@mask-width: 10%; + +.horizontal-scroll { + position: relative; + overflow-x: auto; + + &.left { + mask-image: linear-gradient(90deg, rgba(0, 0, 0, 1) calc(100% - @mask-width), rgba(0, 0, 0, 0) 100%); + } + + &.right { + mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) @mask-width); + } + + &.center { + mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) @mask-width, rgba(0, 0, 0, 1) calc(100% - @mask-width), rgba(0, 0, 0, 0) 100%); + } +} diff --git a/src/common/HorizontalScroll/HorizontalScroll.tsx b/src/common/HorizontalScroll/HorizontalScroll.tsx new file mode 100644 index 000000000..b4c23b19b --- /dev/null +++ b/src/common/HorizontalScroll/HorizontalScroll.tsx @@ -0,0 +1,40 @@ +// Copyright (C) 2017-2024 Smart code 203358507 + +import React, { useRef, useEffect, useState } from 'react'; +import classNames from 'classnames'; +import styles from './HorizontalScroll.less'; + +const SCROLL_THRESHOLD = 1; + +type Props = { + className: string, + children: React.ReactNode, +}; + +const HorizontalScroll = ({ className, children }: Props) => { + const ref = useRef(null); + const [scrollPosition, setScrollPosition] = useState('left'); + + useEffect(() => { + const onScroll = ({ target }: Event) => { + const { scrollLeft, scrollWidth, offsetWidth } = target as HTMLDivElement; + + setScrollPosition(() => ( + (scrollLeft - SCROLL_THRESHOLD) <= 0 ? 'left' : + (scrollLeft + offsetWidth + SCROLL_THRESHOLD) >= scrollWidth ? 'right' : + 'center' + )); + }; + + ref.current?.addEventListener('scroll', onScroll); + return () => ref.current?.removeEventListener('scroll', onScroll); + }, []); + + return ( +
+ {children} +
+ ); +}; + +export default HorizontalScroll; diff --git a/src/common/HorizontalScroll/index.ts b/src/common/HorizontalScroll/index.ts new file mode 100644 index 000000000..4fc875461 --- /dev/null +++ b/src/common/HorizontalScroll/index.ts @@ -0,0 +1,4 @@ +// Copyright (C) 2017-2024 Smart code 203358507 + +import HorizontalScroll from './HorizontalScroll'; +export default HorizontalScroll; diff --git a/src/common/index.js b/src/common/index.js index 8046dab15..fd4f838db 100644 --- a/src/common/index.js +++ b/src/common/index.js @@ -16,6 +16,7 @@ const MetaRow = require('./MetaRow'); const ModalDialog = require('./ModalDialog'); const Multiselect = require('./Multiselect'); const { HorizontalNavBar, VerticalNavBar } = require('./NavBar'); +const { default: HorizontalScroll } = require('./HorizontalScroll'); const PaginationInput = require('./PaginationInput'); const PlayIconCircleCentered = require('./PlayIconCircleCentered'); const Popup = require('./Popup'); @@ -64,6 +65,7 @@ module.exports = { ModalDialog, Multiselect, HorizontalNavBar, + HorizontalScroll, VerticalNavBar, PaginationInput, PlayIconCircleCentered, diff --git a/src/routes/Calendar/Table/Cell/Cell.less b/src/routes/Calendar/Table/Cell/Cell.less index a9a7117b7..25b7b4a48 100644 --- a/src/routes/Calendar/Table/Cell/Cell.less +++ b/src/routes/Calendar/Table/Cell/Cell.less @@ -45,7 +45,6 @@ gap: 1rem; height: 0; padding: 1rem; - overflow-x: scroll; .item { flex: none; diff --git a/src/routes/Calendar/Table/Cell/Cell.tsx b/src/routes/Calendar/Table/Cell/Cell.tsx index d54f05e24..471ecc4f6 100644 --- a/src/routes/Calendar/Table/Cell/Cell.tsx +++ b/src/routes/Calendar/Table/Cell/Cell.tsx @@ -2,7 +2,7 @@ import React, { useMemo } from 'react'; import classNames from 'classnames'; -import { Button, Image } from 'stremio/common'; +import { Button, Image, HorizontalScroll } from 'stremio/common'; import styles from './Cell.less'; type Props = { @@ -37,7 +37,7 @@ const Cell = ({ selected, monthInfo, date, items, onClick }: Props) => { {date.day} -
+ { items.map(({ id, name, poster, deepLinks }) => ( )) } -
+ ); };