import React, { FunctionComponent, useCallback, useState, MouseEvent, TouchEvent, } from 'react'; import { Item, SlideDirection } from '../../types/carousel'; import { getPageX } from '../../helpers'; import { useWindowWidthChange } from '../../hooks'; import styles from '../../styles/styles.module.css'; export const ItemProvider: FunctionComponent = ( props: ItemProviderProps, ) => { const [width, setWidth] = useState(200); const ref = useCallback( (node) => { if (node !== null) { const calculated = node.getBoundingClientRect().width / props.show; setWidth(calculated); props.widthCallBack(calculated); } }, [width], ); // tslint:disable-next-line: no-unused-expression props.responsive && useWindowWidthChange((change: number) => { setWidth(width - change); }); const [drag, setDrag] = useState({ initial: props.transform, start: 0, isDown: false, drag: 0, finished: true, pointers: true, }); const handleDragStart = (e: MouseEvent | TouchEvent) => { e.persist(); setDrag({ ...drag, isDown: true, start: getPageX(e), initial: props.transform, finished: false, }); }; const handleDragFinish = (e: MouseEvent | TouchEvent) => { e.persist(); if (drag.finished) { return; } if (Math.abs(drag.drag) < width * props.swipeOn) { props.dragCallback(props.transform); return setDrag({ initial: props.transform, start: 0, isDown: false, drag: 0, finished: true, pointers: true, }); } props.slideCallback(drag.drag > 0 ? SlideDirection.Right : SlideDirection.Left); setDrag({ ...drag, drag: 0, isDown: false, finished: true, pointers: true }); return; }; const handleDragMove = (e: MouseEvent | TouchEvent) => { e.persist(); if (!drag.isDown) { return; } const pos = getPageX(e); setDrag({ ...drag, drag: drag.start - pos, pointers: false }); }; const swipeProps = props.swiping ? { onTouchCancel: handleDragFinish, onTouchEnd: handleDragFinish, onTouchMove: handleDragMove, onTouchStart: handleDragStart, onMouseDown: handleDragStart, onMouseLeave: handleDragFinish, onMouseUp: handleDragFinish, onMouseMove: handleDragMove, } : {}; return (
{props.items.map((item, i) => (
{item}
))}
); }; export interface ItemProviderProps { items: Item[]; show: number; slide: number; widthCallBack: (width: number) => void; dragCallback: (transform: number) => void; slideCallback: (direction: SlideDirection) => void; transition: number; transform: number; swiping: boolean; swipeOn: number; responsive: boolean; infinite: boolean; }