From 3cb32795738e8f07e9108c11c6a16f85341a3f26 Mon Sep 17 00:00:00 2001 From: BQX Date: Mon, 29 Jan 2024 17:50:09 +0800 Subject: [PATCH 1/3] feat(ui): carousel #2 --- packages/ui/lib/Carousel/Carousel.module.scss | 2 +- packages/ui/lib/Carousel/Carousel.tsx | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/ui/lib/Carousel/Carousel.module.scss b/packages/ui/lib/Carousel/Carousel.module.scss index fa7d239..1798cb1 100644 --- a/packages/ui/lib/Carousel/Carousel.module.scss +++ b/packages/ui/lib/Carousel/Carousel.module.scss @@ -5,6 +5,6 @@ .carouselAll { display: grid; grid-auto-flow: column; - transition: all 0.4s ease-out; + transition: all 0.4s cubic-bezier(0.49, 0.1, 0.48, 0.9); } } diff --git a/packages/ui/lib/Carousel/Carousel.tsx b/packages/ui/lib/Carousel/Carousel.tsx index 8398656..f144e05 100644 --- a/packages/ui/lib/Carousel/Carousel.tsx +++ b/packages/ui/lib/Carousel/Carousel.tsx @@ -50,14 +50,17 @@ export const Carousel = React.forwardRef( useEffect(() => { if (divRef.current) { + divRef.current.style.transition = 'auto'; if (select === 0) divRef.current.style.transform = `translateX(${-difference}px)`; else divRef.current.style.transform = `translateX(-${width * select + difference}px)`; } }, [difference, select, width]); useEffect(() => { - if (difference === 0 && divRef.current) + if (difference === 0 && divRef.current) { + divRef.current.style.transition = ''; divRef.current.style.transform = `translateX(-${width * select}px)`; + } }, [select, width, difference]); const handleMouseUp = (e: React.MouseEvent) => { From bef1c9dbfd88bbea1c4aa4aec8fa6bc0fd2d2fa6 Mon Sep 17 00:00:00 2001 From: BQX Date: Mon, 29 Jan 2024 21:17:52 +0800 Subject: [PATCH 2/3] feat(ui): carousel #3 --- packages/competition/src/App.tsx | 15 +-- packages/ui/lib/Carousel/Carousel.module.scss | 9 +- packages/ui/lib/Carousel/Carousel.stories.tsx | 29 ++++ packages/ui/lib/Carousel/Carousel.tsx | 126 ++++++++++++++---- packages/ui/lib/Carousel/CarouselItem.tsx | 35 +++++ packages/ui/lib/Carousel/index.ts | 1 + packages/ui/lib/index.ts | 1 + 7 files changed, 175 insertions(+), 41 deletions(-) create mode 100644 packages/ui/lib/Carousel/CarouselItem.tsx diff --git a/packages/competition/src/App.tsx b/packages/competition/src/App.tsx index 3d28dc0..6eb0647 100644 --- a/packages/competition/src/App.tsx +++ b/packages/competition/src/App.tsx @@ -1,15 +1,5 @@ -import { Button } from "@sast/oj-ui"; -import { - Checkbox, - Dialog, - Input, - Radio, - RadioGroup, - Sheet, - SheetTrigger, - SheetHeader, - // SheetTrigger, -} from "@sast/oj-ui"; +import { Button, CarouselItem } from "@sast/oj-ui"; +import { Sheet, Carousel } from "@sast/oj-ui"; import { useState } from "react"; function App() { @@ -37,6 +27,7 @@ function App() { } > + ); } diff --git a/packages/ui/lib/Carousel/Carousel.module.scss b/packages/ui/lib/Carousel/Carousel.module.scss index 1798cb1..b859bb6 100644 --- a/packages/ui/lib/Carousel/Carousel.module.scss +++ b/packages/ui/lib/Carousel/Carousel.module.scss @@ -5,6 +5,13 @@ .carouselAll { display: grid; grid-auto-flow: column; - transition: all 0.4s cubic-bezier(0.49, 0.1, 0.48, 0.9); + transition: all 0.4s cubic-bezier(0.65, 0.22, 0.27, 0.74); + .item { + width: 400px; + height: 200px; + display: flex; + align-items: center; + justify-content: center; + } } } diff --git a/packages/ui/lib/Carousel/Carousel.stories.tsx b/packages/ui/lib/Carousel/Carousel.stories.tsx index 89bf6f1..69ca3d8 100644 --- a/packages/ui/lib/Carousel/Carousel.stories.tsx +++ b/packages/ui/lib/Carousel/Carousel.stories.tsx @@ -3,6 +3,23 @@ import type { Meta, StoryObj } from '@storybook/react'; import React from 'react'; import { Carousel, type CarouselProps } from './Carousel'; +const test = (value: number) => { + console.log('select number', value); +}; + +const styles = { + width: '280px', + height: '280px', + border: '1px solid black', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + borderRadius: '10px', + fontSize: '40px', + fontWeight: '1000', + boxShadow: '0px 3px 10px #808080', +}; + const meta = { title: 'Components/Carousel', component: Carousel, @@ -22,6 +39,18 @@ const defaultProps: CarouselProps = {}; export const DefaultCarousel: Story = { args: { ...defaultProps, + width: 300, + height: 300, + CarouselItems: [ + { children:
1
}, + { children:
2
}, + { children:
3
}, + { children:
4
}, + { children:
5
}, + ], + onChange: test, + defaultSelected: 2, + selected: 1, }, }; diff --git a/packages/ui/lib/Carousel/Carousel.tsx b/packages/ui/lib/Carousel/Carousel.tsx index f144e05..805b4db 100644 --- a/packages/ui/lib/Carousel/Carousel.tsx +++ b/packages/ui/lib/Carousel/Carousel.tsx @@ -1,5 +1,5 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { Button } from '..'; +import React, { memo, useEffect, useRef, useState } from 'react'; +import { Button, type CarouselItemProps, CarouselItem } from '..'; import classNames from 'classnames'; import styles from './Carousel.module.scss'; @@ -7,16 +7,39 @@ export interface CarouselProps { /** * width of the carousel */ - width: number; + width?: number; /** - * number of the item + * height of the Carousel */ - number: number; + height?: number; + /** + * CarouselItems of the carousel + */ + CarouselItems?: CarouselItemProps[]; + /** + * onChange : the onChange of the Carousel + */ + onChange?: (value: number) => void; + /** + * defaultselect the defaultselect of the Carousel + */ + defaultSelected?: number; + /** + * select of the Carousel + */ + selected?: number; +} + +interface ContentProps { + CarouselItems: CarouselItemProps[]; } export const Carousel = React.forwardRef( - ({ width = 400, number = 4 }, ref) => { - const [select, setSelect] = useState(0); + ( + { width = 400, CarouselItems = undefined, height, onChange, defaultSelected, selected }, + ref, + ) => { + const [select, setSelect] = useState(defaultSelected || 0); const [startX, setStartX] = useState(0); const [endX, setEndX] = useState(0); const [startTime, setStartTime] = useState(0); @@ -24,15 +47,18 @@ export const Carousel = React.forwardRef( const [isDragging, setIsDragging] = useState(false); const [difference, setDifference] = useState(0); const [isChanged, setIsChanged] = useState(false); - + const [itemsNumber, setItemsNumber] = useState(0); const divRef = useRef(null); + useEffect(() => { + selected && setSelect(selected); + }, [selected]); const pre = () => { select !== 0 && setSelect(select - 1); }; const next = () => { - select !== number - 1 && setSelect(select + 1); + select !== itemsNumber - 1 && setSelect(select + 1); }; const handleMouseDown = (e: React.MouseEvent) => { @@ -51,8 +77,7 @@ export const Carousel = React.forwardRef( useEffect(() => { if (divRef.current) { divRef.current.style.transition = 'auto'; - if (select === 0) divRef.current.style.transform = `translateX(${-difference}px)`; - else divRef.current.style.transform = `translateX(-${width * select + difference}px)`; + divRef.current.style.transform = `translateX(${-(width * select + difference)}px)`; } }, [difference, select, width]); @@ -66,7 +91,7 @@ export const Carousel = React.forwardRef( const handleMouseUp = (e: React.MouseEvent) => { setEndX(e.clientX); setEndTime(Date.now()); - if (Math.abs(difference) >= 200 && difference > 0 && select !== number - 1) { + if (Math.abs(difference) >= 200 && difference > 0 && select !== itemsNumber - 1) { setSelect(select + 1); setIsChanged(true); } @@ -74,47 +99,92 @@ export const Carousel = React.forwardRef( setSelect(select - 1); setIsChanged(true); } - if (Math.abs(difference) < 200 && divRef.current && select === number - 1 && select === 0) { + if ( + Math.abs(difference) < 200 && + divRef.current && + select === itemsNumber - 1 && + select === 0 + ) { divRef.current.style.transform = `translateX(-${width * select}px)`; } setDifference(0); setIsDragging(false); }; + useEffect(() => { + onChange && onChange(select); + }, [select, onChange]); + useEffect(() => { if (difference === 0 && !isChanged) { const duration = endTime - startTime; const space = endX - startX; const v = space / duration; - v < -0.3 && select !== number - 1 && setSelect(select + 1); - v > 0.3 && select != 0 && setSelect(select - 1); + v < -0.5 && select !== itemsNumber - 1 && setSelect(select + 1); + v > 0.5 && select != 0 && setSelect(select - 1); } setIsChanged(false); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [difference]); const carouselClass = classNames(styles['base']); + useEffect(() => { + CarouselItems && setItemsNumber(CarouselItems.length); + }, [CarouselItems]); + + const Content = memo(function content({ CarouselItems }: ContentProps) { + return ( + <> + {CarouselItems?.map((item, index) => { + return ( + + {item.children} + + ); + })} + + ); + }); + return ( <>
+
-
-
-
-
+
+ {CarouselItems && } +
+
- - ); }, diff --git a/packages/ui/lib/Carousel/CarouselItem.tsx b/packages/ui/lib/Carousel/CarouselItem.tsx new file mode 100644 index 0000000..c44de6b --- /dev/null +++ b/packages/ui/lib/Carousel/CarouselItem.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import styles from './Carousel.module.scss'; + +export interface CarouselItemProps { + /** + * children of the CarouselItem + */ + children?: React.ReactNode; + /** + * width of the CarouselItem + */ + width?: number; + /** + * height of the CarouselItem + */ + height?: number; +} + +export const CarouselItem = React.forwardRef( + ({ children, width, height }, ref) => { + return ( + <> +
+ {children} +
+ + ); + }, +); + +CarouselItem.displayName = 'CarouselItem'; diff --git a/packages/ui/lib/Carousel/index.ts b/packages/ui/lib/Carousel/index.ts index c0ab199..d6759ba 100644 --- a/packages/ui/lib/Carousel/index.ts +++ b/packages/ui/lib/Carousel/index.ts @@ -1 +1,2 @@ export * from './Carousel'; +export * from './CarouselItem'; diff --git a/packages/ui/lib/index.ts b/packages/ui/lib/index.ts index 9ece3a3..abd9dfa 100644 --- a/packages/ui/lib/index.ts +++ b/packages/ui/lib/index.ts @@ -15,3 +15,4 @@ export * from './Navbar'; export * from './Pagination'; export * from './Calendar'; export * from './Sheet'; +export * from './Carousel' From 3c99d7fa7ef94e374141864a2a242257904139f2 Mon Sep 17 00:00:00 2001 From: BQX Date: Mon, 29 Jan 2024 21:19:24 +0800 Subject: [PATCH 3/3] feat(ui): carousel #4 --- packages/ui/lib/Carousel/Carousel.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ui/lib/Carousel/Carousel.tsx b/packages/ui/lib/Carousel/Carousel.tsx index 805b4db..729432c 100644 --- a/packages/ui/lib/Carousel/Carousel.tsx +++ b/packages/ui/lib/Carousel/Carousel.tsx @@ -91,16 +91,16 @@ export const Carousel = React.forwardRef( const handleMouseUp = (e: React.MouseEvent) => { setEndX(e.clientX); setEndTime(Date.now()); - if (Math.abs(difference) >= 200 && difference > 0 && select !== itemsNumber - 1) { + if (Math.abs(difference) >= width / 2 && difference > 0 && select !== itemsNumber - 1) { setSelect(select + 1); setIsChanged(true); } - if (Math.abs(difference) >= 200 && difference < 0 && select !== 0) { + if (Math.abs(difference) >= width / 2 && difference < 0 && select !== 0) { setSelect(select - 1); setIsChanged(true); } if ( - Math.abs(difference) < 200 && + Math.abs(difference) < width / 2 && divRef.current && select === itemsNumber - 1 && select === 0