Skip to content
Permalink
Browse files

feat: Add Carousel touch support via Hammer.js

Touch support should be provided for our Carousel components, as
per the upstream docs for Carousel (as of Bootstrap v4.2).
  • Loading branch information
bpas247 committed Jul 9, 2019
1 parent db5ac1a commit 0b6a4fa0c930de2723a30dbc6402fcbe00d20f11
Showing with 40 additions and 0 deletions.
  1. +1 −0 package.json
  2. +34 −0 src/Carousel.js
  3. +5 −0 yarn.lock
@@ -119,6 +119,7 @@
"@restart/hooks": "^0.3.0",
"classnames": "^2.2.6",
"dom-helpers": "^3.4.0",
"hammerjs": "^2.0.8",
"invariant": "^2.2.4",
"keycode": "^2.2.0",
"popper.js": "^1.14.7",
@@ -1,6 +1,7 @@
import classNames from 'classnames';
import styles from 'dom-helpers/style';
import transition from 'dom-helpers/transition';
import Hammer from 'hammerjs';
import React, { cloneElement } from 'react';
import PropTypes from 'prop-types';
import { uncontrollable } from 'uncontrollable';
@@ -99,6 +100,11 @@ const propTypes = {
* Set to null to deactivate.
*/
nextLabel: PropTypes.string,

/**
* Whether the carousel should support left/right swipe interactions on touchscreen devices.
*/
touch: PropTypes.bool,
};

const defaultProps = {
@@ -117,6 +123,7 @@ const defaultProps = {

nextIcon: <span aria-hidden="true" className="carousel-control-next-icon" />,
nextLabel: 'Next',
touch: true,
};

class Carousel extends React.Component {
@@ -131,6 +138,27 @@ class Carousel extends React.Component {

componentDidMount() {
this.cycle();
if (this.carousel && this.props.touch) {
this.hammer = new Hammer(this.carousel.current);
this.hammer.on('swipe', ev => {
const lastPossibleIndex = countChildren(this.props.children) - 1;
if (ev.direction === Hammer.DIRECTION_LEFT) {
this.to(
this.state.activeIndex === lastPossibleIndex
? 0
: this.state.activeIndex + 1,
ev,
);
} else if (ev.direction === Hammer.DIRECTION_RIGHT) {
this.to(
this.state.activeIndex === 0
? lastPossibleIndex
: this.state.activeIndex - 1,
ev,
);
}
});
}
}

static getDerivedStateFromProps(
@@ -219,6 +247,10 @@ class Carousel extends React.Component {
componentWillUnmount() {
clearTimeout(this.timeout);
this.isUnmounted = true;
if (this.hammer) {
this.hammer.stop();
this.hammer.destroy();
}
}

handleSlideEnd = () => {
@@ -427,6 +459,8 @@ class Carousel extends React.Component {
indicators,
controls,
wrap,
// eslint-disable-next-line no-unused-vars
touch,
prevIcon,
prevLabel,
nextIcon,
@@ -4113,6 +4113,11 @@ gud@^1.0.0:
resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0"
integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==

hammerjs@^2.0.8:
version "2.0.8"
resolved "https://registry.yarnpkg.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1"
integrity sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=

handlebars@^4.0.1, handlebars@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.1.tgz#6e4e41c18ebe7719ae4d38e5aca3d32fa3dd23d3"

0 comments on commit 0b6a4fa

Please sign in to comment.
You can’t perform that action at this time.