Skip to content

Commit

Permalink
Merge pull request #6 from BQXBQX/dev-bqx
Browse files Browse the repository at this point in the history
Dev bqx
  • Loading branch information
BQXBQX committed Jan 29, 2024
2 parents 3d0a465 + 3c99d7f commit b0edba4
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 43 deletions.
15 changes: 3 additions & 12 deletions packages/competition/src/App.tsx
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down Expand Up @@ -37,6 +27,7 @@ function App() {
</>
}
></Sheet>
<Carousel number={6} width={500}></Carousel>
</>
);
}
Expand Down
9 changes: 8 additions & 1 deletion packages/ui/lib/Carousel/Carousel.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
.carouselAll {
display: grid;
grid-auto-flow: column;
transition: all 0.4s ease-out;
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;
}
}
}
29 changes: 29 additions & 0 deletions packages/ui/lib/Carousel/Carousel.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -22,6 +39,18 @@ const defaultProps: CarouselProps = {};
export const DefaultCarousel: Story = {
args: {
...defaultProps,
width: 300,
height: 300,
CarouselItems: [
{ children: <div style={styles}>1</div> },
{ children: <div style={styles}>2</div> },
{ children: <div style={styles}>3</div> },
{ children: <div style={styles}>4</div> },
{ children: <div style={styles}>5</div> },
],
onChange: test,
defaultSelected: 2,
selected: 1,
},
};

Expand Down
133 changes: 103 additions & 30 deletions packages/ui/lib/Carousel/Carousel.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,64 @@
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';

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<HTMLDivElement, CarouselProps>(
({ width = 400, number = 4 }, ref) => {
const [select, setSelect] = useState<number>(0);
(
{ width = 400, CarouselItems = undefined, height, onChange, defaultSelected, selected },
ref,
) => {
const [select, setSelect] = useState<number>(defaultSelected || 0);
const [startX, setStartX] = useState<number>(0);
const [endX, setEndX] = useState<number>(0);
const [startTime, setStartTime] = useState<number>(0);
const [endTime, setEndTime] = useState<number>(0);
const [isDragging, setIsDragging] = useState<boolean>(false);
const [difference, setDifference] = useState<number>(0);
const [isChanged, setIsChanged] = useState<boolean>(false);

const [itemsNumber, setItemsNumber] = useState<number>(0);
const divRef = useRef<HTMLDivElement>(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) => {
Expand All @@ -50,68 +76,115 @@ export const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(

useEffect(() => {
if (divRef.current) {
if (select === 0) divRef.current.style.transform = `translateX(${-difference}px)`;
else divRef.current.style.transform = `translateX(-${width * select + difference}px)`;
divRef.current.style.transition = 'auto';
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) => {
setEndX(e.clientX);
setEndTime(Date.now());
if (Math.abs(difference) >= 200 && difference > 0 && select !== number - 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 && divRef.current && select === number - 1 && select === 0) {
if (
Math.abs(difference) < width / 2 &&
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 (
<CarouselItem
key={index}
width={item.width || width}
height={item.height || height}
>
{item.children}
</CarouselItem>
);
})}
</>
);
});

return (
<>
<div
className={carouselClass}
ref={ref}
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '10px' }}
>
<Button
onClick={pre}
color="tertiary"
>
Pre
</Button>
<div
className={styles['carouselAll']}
ref={divRef}
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
className={carouselClass}
ref={ref}
style={{ width: `${width}px`, height: `${height}px` }}
>
<div style={{ background: 'black', height: '200px', width: '400px' }}></div>
<div style={{ background: 'red', height: '200px', width: '400px' }}></div>
<div style={{ background: 'green', height: '200px', width: '400px' }}></div>
<div style={{ background: 'blue', height: '200px', width: '400px' }}></div>
<div
className={styles['carouselAll']}
ref={divRef}
onMouseDown={handleMouseDown}
onMouseMove={handleMouseMove}
onMouseUp={handleMouseUp}
style={{ width: `${width}px`, height: `${height}px` }}
>
{CarouselItems && <Content CarouselItems={CarouselItems}></Content>}
</div>
</div>
<Button
onClick={next}
color="tertiary"
>
Next
</Button>
</div>
<Button onClick={pre}>Pre</Button>
<Button onClick={next}>Next</Button>
</>
);
},
Expand Down
35 changes: 35 additions & 0 deletions packages/ui/lib/Carousel/CarouselItem.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLDivElement, CarouselItemProps>(
({ children, width, height }, ref) => {
return (
<>
<div
ref={ref}
className={`${styles['item']}`}
style={{ width: `${width}px`, height: `${height}px` }}
>
{children}
</div>
</>
);
},
);

CarouselItem.displayName = 'CarouselItem';
1 change: 1 addition & 0 deletions packages/ui/lib/Carousel/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './Carousel';
export * from './CarouselItem';
1 change: 1 addition & 0 deletions packages/ui/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export * from './Navbar';
export * from './Pagination';
export * from './Calendar';
export * from './Sheet';
export * from './Carousel'

0 comments on commit b0edba4

Please sign in to comment.