import * as React from 'react'; import {Slide} from './Slide'; import {ISlideConfig} from "../models/ISlideConfig"; import {CSSProperties} from "react"; import {ISlidePrallaxConfig} from "../models/ISlidePrallaxConfig"; import {AutoSlideBackground} from "./AutoSlideBackground"; interface IAutoSlidesContainerProps { height: number; transitionSpeed: number; slides: ISlideConfig[]; parallax: ISlidePrallaxConfig; currentSlideIndex: number; onChange?: (index: number) => void; } interface IAutoSlidesContainerState { currentSlideIndex: number; userSlideIndex?: number; } export class AutoSlidesContainer extends React.Component { public static defaultProps = { transitionSpeed: 2000, onChange: () => {} }; static getDerivedStateFromProps(props: IAutoSlidesContainerProps, state: IAutoSlidesContainerState) { if (typeof props.currentSlideIndex !=='undefined' && props.currentSlideIndex !== state.userSlideIndex && AutoSlidesContainer.isValidSlideIndex(props.currentSlideIndex, props) ) { return { currentSlideIndex: props.currentSlideIndex, userSlideIndex: props.currentSlideIndex } } return null; } static isValidSlideIndex(slideIndex: number, props: IAutoSlidesContainerProps) { return slideIndex < props.slides.length && slideIndex >= 0 } public state = { currentSlideIndex: 0, }; private touchStart: number; private prevWheelDelta = 0; private block = false; componentDidMount() { window.addEventListener('wheel', this.handleMouseWheel, {passive: false}); window.addEventListener('DOMMouseScroll', this.handleMouseWheel, {passive: false}); window.addEventListener('keydown', this.handleKeyDown); window.addEventListener('touchstart', this.handleTouchStart); window.addEventListener('touchmove', this.handleTouchMove, {passive: false}); } componentDidUpdate(prevProps: IAutoSlidesContainerProps, prevState: IAutoSlidesContainerState) { if (prevState.currentSlideIndex !== this.state.currentSlideIndex) { this.props.onChange!(this.state.currentSlideIndex); } } componentWillUnmount() { window.removeEventListener('wheel', this.handleMouseWheel); window.removeEventListener('DOMMouseScroll', this.handleMouseWheel); window.removeEventListener('keydown', this.handleKeyDown); window.removeEventListener('touchstart', this.handleTouchStart); window.removeEventListener('touchmove', this.handleTouchMove); } handleMouseWheel = (event: MouseWheelEvent) => { event.preventDefault(); const delta = event.wheelDelta || -event.deltaY; if (!this.block) { if (Math.abs(this.prevWheelDelta) < Math.abs(delta) || delta % 120 === 0) { this.updateCurrentPage(delta < 0); } } this.prevWheelDelta = delta; }; handleKeyDown = (event: KeyboardEvent) => { if (!this.block) { switch (event.key) { case "ArrowUp": this.updateCurrentPage(false); break; case "ArrowDown": this.updateCurrentPage(true); break; } } }; handleTouchStart = (event: TouchEvent) => { this.touchStart = event.touches[0].pageY; }; handleTouchMove = (event: TouchEvent) => { event.preventDefault(); if (!this.block) { const touchDelta = event.touches[0].pageY - this.touchStart; if (Math.abs(touchDelta) > 30) { this.updateCurrentPage(touchDelta < 0); this.touchStart = event.touches[0].pageY; } } }; updateCurrentPage(nextPage: boolean) { const currentSlideIndex = (nextPage ? 1 : -1) + this.state.currentSlideIndex; if (AutoSlidesContainer.isValidSlideIndex(currentSlideIndex, this.props)) { this.setState({ currentSlideIndex, }); this.block = true; } } getHeight() { return this.props.height; } renderSlides() { const height = this.getHeight(); return this.props.slides.map((props, index) => { const isCurrent = index === this.state.currentSlideIndex; const isBottom = index > this.state.currentSlideIndex; const isTop = index < this.state.currentSlideIndex; return ( {props.content} ); }); } getScrollToTop() { return this.state.currentSlideIndex * this.getHeight() * -1; } onTransitionEnd = () => { this.block = false; }; render() { return (
{this.renderSlides()}
) } private getContainerStyle() { const scrollToTop = this.getScrollToTop(); return { height: '100%', position: 'relative', touchAction: 'none', padding: 0, margin: 0, transform: `translate3d(0px, ${scrollToTop}px, 0px)`, transition: `all ${this.props.transitionSpeed}ms ease`, } as CSSProperties; } }