Skip to content

Commit

Permalink
fix: carousel bug
Browse files Browse the repository at this point in the history
  • Loading branch information
BQXBQX committed Sep 29, 2024
1 parent 0fa2302 commit c65d3d0
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 56 deletions.
7 changes: 2 additions & 5 deletions packages/ui-react/lib/Carousel/Carousel.module.scss
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
@use '../variables' as *;
.base {
width: 400px;
height: 200px;
overflow: hidden;
.carouselAll {
.carousel-all {
display: grid;
grid-auto-flow: column;
transition: all 0.4s $cubic-bezier;
height: 100%;
.item {
width: 400px;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
Expand Down
14 changes: 9 additions & 5 deletions packages/ui-react/lib/Carousel/Carousel.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,30 @@ const defaultProps: CarouselProps = {};
export const DefaultCarousel: Story = {
args: {
...defaultProps,
selectedIndex: 1,
width: 300,
height: 300,
CarouselItems: [
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,
onChange: test,
defaultSelectedIndex: 2,
className: 'test',
style:{
width:'500px',
height:'500px'
}
},
};

export const ExampleCarousel: Story = {
args: {
...defaultProps,
CarouselItems: [
carouselItems: [
{ children: <div>1</div> },
{ children: <div>2</div> },
{ children: <div>3</div> },
Expand Down
117 changes: 72 additions & 45 deletions packages/ui-react/lib/Carousel/Carousel.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import React, { memo, useEffect, useRef, useState, type HtmlHTMLAttributes } from 'react';
import React, { memo, useEffect, useMemo, useRef, useState, type HtmlHTMLAttributes } from 'react';
import { type CarouselItemProps, CarouselItem } from '..';
import classNames from 'classnames';
import styles from './Carousel.module.scss';

export interface CarouselProps extends HtmlHTMLAttributes<HTMLDivElement> {
export interface CarouselProps extends Omit<HtmlHTMLAttributes<HTMLDivElement>, 'onChange'> {
/**
* select of the Carousel
*/
selectedIndex?: number;
/**
* defaultselect the defaultselect of the Carousel
*/
defaultSelectedIndex?: number;
/**
* width of the carousel
*/
Expand All @@ -15,19 +23,11 @@ export interface CarouselProps extends HtmlHTMLAttributes<HTMLDivElement> {
/**
* CarouselItems of the carousel
*/
CarouselItems?: CarouselItemProps[];
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;
onChange?: (value: number) => void;
/**
* isSliding
*/
Expand All @@ -49,12 +49,12 @@ interface ContentProps {
export const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
(
{
width = 400,
CarouselItems = undefined,
height,
onchange,
defaultSelected,
selected,
// width,
carouselItems,
// height,
onChange,
defaultSelectedIndex,
selectedIndex,
isSliding = true,
className,
itemClassName,
Expand All @@ -66,7 +66,7 @@ export const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
// one is whether it has reached the halfway position,
// and the second is the speed of movement, when the dragging speed is greater than 0.5, it is automatically switched.
// 这个轮播图的界定判断由两个因素决定,一个是是否到达了一半的位置,第二个是移动的速度,当拖拽速度大于0.5时,自动进行切换。
const [select, setSelect] = useState<number>(defaultSelected || 0);
const [select, setSelect] = useState<number>(defaultSelectedIndex || 0);
const [startX, setStartX] = useState<number>(0);
const [endX, setEndX] = useState<number>(0);
const [startTime, setStartTime] = useState<number>(0);
Expand All @@ -75,16 +75,40 @@ export const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
const [difference, setDifference] = useState<number>(0);
const [isChanged, setIsChanged] = useState<boolean>(false);
const [itemsNumber, setItemsNumber] = useState<number>(0);
const divRef = useRef<HTMLDivElement>(null);
const containerRef = useRef<HTMLDivElement | null>(null);
const viewRef = useRef<HTMLDivElement | null>(null);
const [width, setWidth] = useState<number>(0);
const [height, setHeight] = useState<number>(0);

useEffect(() => {
const handleResize = () => {
if (containerRef.current) {
setWidth(containerRef.current.offsetWidth);
setHeight(containerRef.current.offsetHeight);
}
};

// Initialize container width on mount
handleResize();

// Update container width on window resize
window.addEventListener('resize', handleResize);

// Clean up event listener on unmount
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);

useEffect(() => {
selected !== undefined && setSelect(selected);
}, [selected]);
selectedIndex !== undefined && setSelect(selectedIndex);
}, [selectedIndex]);

const handleMouseDown = (e: React.MouseEvent) => {
setStartX(e.clientX);
setStartTime(Date.now());
setIsDragging(true);
console.log('startX', startX);
};

const handleMouseMove = (e: React.MouseEvent) => {
Expand All @@ -95,16 +119,16 @@ export const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
};

useEffect(() => {
if (divRef.current) {
divRef.current.style.transition = 'auto';
divRef.current.style.transform = `translateX(${-(width * select + difference)}px)`;
if (containerRef.current) {
containerRef.current.style.transition = 'auto';
containerRef.current.style.transform = `translateX(${-(width * select + difference)}px)`;
}
}, [difference, select, width]);

useEffect(() => {
if (difference === 0 && divRef.current) {
divRef.current.style.transition = '';
divRef.current.style.transform = `translateX(-${width * select}px)`;
if (difference === 0 && containerRef.current) {
containerRef.current.style.transition = '';
containerRef.current.style.transform = `translateX(-${width * select}px)`;
}
}, [select, width, difference]);

Expand All @@ -121,19 +145,19 @@ export const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
setIsChanged(true);
} else if (
Math.abs(difference) < width / 2 &&
divRef.current &&
containerRef.current &&
select === itemsNumber - 1 &&
select === 0
) {
divRef.current.style.transform = `translateX(-${width * select}px)`;
containerRef.current.style.transform = `translateX(-${width * select}px)`;
}
setDifference(0);
setIsDragging(false);
};

useEffect(() => {
onchange && onchange(select);
}, [select, onchange]);
onChange && onChange(select);
}, [select, onChange]);

useEffect(() => {
if (difference === 0 && !isChanged) {
Expand All @@ -152,10 +176,10 @@ export const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
const carouselClass = classNames(styles['base']);

useEffect(() => {
CarouselItems && setItemsNumber(CarouselItems.length);
}, [CarouselItems]);
carouselItems && setItemsNumber(carouselItems.length);
}, [carouselItems]);

const Content = memo(function content({ CarouselItems }: ContentProps) {
const Content = function content({ CarouselItems }: ContentProps) {
return (
<>
{CarouselItems?.map((item, index) => {
Expand All @@ -172,24 +196,27 @@ export const Carousel = React.forwardRef<HTMLDivElement, CarouselProps>(
})}
</>
);
});
};

return (
<div
className={`${carouselClass} ${className}`}
ref={ref}
style={{ width: `${width}px`, height: `${height}px` }}
className={`${carouselClass} ${className}`}
{...rest}
>
<div
className={styles['carouselAll']}
ref={divRef}
onMouseDown={() => isSliding && handleMouseDown}
onMouseMove={() => isSliding && handleMouseMove}
onMouseUp={() => isSliding && handleMouseUp}
style={{ width: `${width}px`, height: `${height}px` }}
style={{ width: '100%', height: '100%' }}
ref={viewRef}
>
{CarouselItems && <Content CarouselItems={CarouselItems}></Content>}
<div
className={styles['carousel-all']}
ref={containerRef}
onMouseDown={(e) => isSliding && handleMouseDown(e)}
onMouseMove={(e) => isSliding && handleMouseMove(e)}
onMouseUp={(e) => isSliding && handleMouseUp(e)}
>
{carouselItems.length && <Content CarouselItems={carouselItems}></Content>}
</div>
</div>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ui-aurora/react",
"version": "0.0.19",
"version": "0.0.20",
"description": "A React UI library built for SASTOJ",
"author": "sast",
"license": "MIT",
Expand Down

1 comment on commit c65d3d0

@vercel
Copy link

@vercel vercel bot commented on c65d3d0 Sep 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

sast-ui – ./

sast-ui-sast.vercel.app
sast-ui-git-main-sast.vercel.app

Please sign in to comment.