Add scrolling carousel

master
Hasan Genc 5 years ago
parent f43229d96a
commit e02372f748
  1. 4
      src/components/carousel/index.tsx
  2. 46
      src/components/scrolling-carousel/index.tsx
  3. 10
      src/helpers/index.ts
  4. 4
      src/index.ts

@ -51,7 +51,9 @@ export const Carousel: FunctionComponent<CarouselProps> = (userProps: CarouselPr
isSliding: true,
});
setCurrent(next);
setShowArrow(getShowArrow(props.children.length, props.show, props.infinite, next));
setShowArrow(
getShowArrow(props.children.length, props.show, props.infinite, next),
);
setTimeout(() => {
if (props.infinite) {
setItems(cleanItems(rotated, slide, direction));

@ -7,8 +7,9 @@ import React, {
} from 'react';
import { Item, SlideDirection } from '../../types/carousel';
import styles from '../../styles/slider/styles.module.css';
import { getOuterWidth } from '../../helpers';
export const Slider: FunctionComponent<SliderProps> = ({
export const ScrollingCarousel: FunctionComponent<SliderProps> = ({
children,
className,
}: SliderProps) => {
@ -31,11 +32,16 @@ export const Slider: FunctionComponent<SliderProps> = ({
};
const [showArrow, setShowArrow] = useState<Arrows>(showArrows());
const onScroll = (_: Event) => {
setShowArrow(showArrows());
};
const ref = useCallback(
(node) => {
if (node !== null) {
Object.defineProperty(slider, 'current', { value: node });
setShowArrow(showArrows());
node.addEventListener('scroll', onScroll);
}
},
[slider],
@ -64,11 +70,36 @@ export const Slider: FunctionComponent<SliderProps> = ({
slider.current!.scrollLeft = position.scrollLeft - slide;
};
const calculateSlideAmount = (direction: SlideDirection): number => {
const _slider = slider.current!;
const currentView =
direction === SlideDirection.Left
? _slider.scrollLeft + _slider.offsetWidth
: _slider.scrollLeft;
const childNodes = Array.from(_slider.children) as HTMLElement[];
let nodeWidthSum = 0;
for (const node of childNodes) {
const nodeWidth = getOuterWidth(node);
nodeWidthSum += nodeWidth;
if (nodeWidthSum >= currentView) {
const showingPart =
direction === SlideDirection.Left
? nodeWidthSum - currentView
: nodeWidth;
return (_slider.offsetWidth - showingPart) * direction;
}
}
return _slider.offsetWidth;
};
const slide = (direction: SlideDirection) => {
const slideAmount = -1 * direction * slider.current!.offsetWidth * 0.9;
const slideAmount = calculateSlideAmount(direction);
const start = slider.current!.scrollLeft;
smoothHorizontalScroll(500, slideAmount, start);
setShowArrow(showArrows());
};
const smoothHorizontalScroll = (time: number, amount: number, start: number) => {
@ -85,16 +116,19 @@ export const Slider: FunctionComponent<SliderProps> = ({
const smoothHorizontalScrollBehavior = (amount: number) => {
slider.current!.scrollLeft = amount;
setShowArrow(showArrows());
};
return (
<div className={`${styles.sliderBase} ${className}`}>
{showArrow.left && (
<button onClick={() => slide(SlideDirection.Left)}>left</button>
<div data-arrow="left">
<button onClick={() => slide(SlideDirection.Right)} />
</div>
)}
{showArrow.right && (
<button onClick={() => slide(SlideDirection.Right)}>right</button>
<div data-arrow="right">
<button onClick={() => slide(SlideDirection.Left)} />
</div>
)}
<div
ref={ref}

@ -133,3 +133,13 @@ export function getPageX(e: TouchEvent | MouseEvent): number {
}
return 0;
}
export function getOuterWidth(el: HTMLElement) {
const style = getComputedStyle(el);
return (
el.offsetWidth +
(parseInt(style.marginLeft, 10) || 0) +
(parseInt(style.marginRight, 10) || 0)
);
}

@ -1,4 +1,4 @@
import { Carousel } from './components/carousel';
import { Slider } from './components/slider';
import { ScrollingCarousel } from './components/scrolling-carousel';
export { Carousel, Slider };
export { Carousel, ScrollingCarousel };

Loading…
Cancel
Save