dub-step
Version:
A set of primitives for building step/index based UI widgets controlled by swipe, timers, and/or buttons.
1,281 lines (1,127 loc) β’ 75.4 kB
JavaScript
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 5);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
} ())
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch(e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch(e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;
process.listeners = function (name) { return [] }
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
*/
function makeEmptyFunction(arg) {
return function () {
return arg;
};
}
/**
* This function accepts and discards inputs; it has no side effects. This is
* primarily useful idiomatically for overridable function endpoints which
* always need to be callable, since JS lacks a null-call idiom ala Cocoa.
*/
var emptyFunction = function emptyFunction() {};
emptyFunction.thatReturns = makeEmptyFunction;
emptyFunction.thatReturnsFalse = makeEmptyFunction(false);
emptyFunction.thatReturnsTrue = makeEmptyFunction(true);
emptyFunction.thatReturnsNull = makeEmptyFunction(null);
emptyFunction.thatReturnsThis = function () {
return this;
};
emptyFunction.thatReturnsArgument = function (arg) {
return arg;
};
module.exports = emptyFunction;
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(process) {/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
/**
* Use invariant() to assert state which your program assumes to be true.
*
* Provide sprintf-style format (only %s is supported) and arguments
* to provide information about what broke and what you were
* expecting.
*
* The invariant message will be stripped in production, but the invariant
* will remain to ensure logic does not differ in production.
*/
var validateFormat = function validateFormat(format) {};
if (process.env.NODE_ENV !== 'production') {
validateFormat = function validateFormat(format) {
if (format === undefined) {
throw new Error('invariant requires an error message argument');
}
};
}
function invariant(condition, format, a, b, c, d, e, f) {
validateFormat(format);
if (!condition) {
var error;
if (format === undefined) {
error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
} else {
var args = [a, b, c, d, e, f];
var argIndex = 0;
error = new Error(format.replace(/%s/g, function () {
return args[argIndex++];
}));
error.name = 'Invariant Violation';
}
error.framesToPop = 1; // we don't care about invariant's own frame
throw error;
}
}
module.exports = invariant;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/**
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
module.exports = ReactPropTypesSecret;
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(process) {/**
* Copyright 2014-2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
var emptyFunction = __webpack_require__(1);
/**
* Similar to invariant but only logs a warning if the condition is not met.
* This can be used to log issues in development environments in critical
* paths. Removing the logging code for production environments will keep the
* same logic and follow the same code paths.
*/
var warning = emptyFunction;
if (process.env.NODE_ENV !== 'production') {
var printWarning = function printWarning(format) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var argIndex = 0;
var message = 'Warning: ' + format.replace(/%s/g, function () {
return args[argIndex++];
});
if (typeof console !== 'undefined') {
console.error(message);
}
try {
// --- Welcome to debugging React ---
// This error was thrown as a convenience so that you can use this stack
// to find the callsite that caused this warning to fire.
throw new Error(message);
} catch (x) {}
};
warning = function warning(condition, format) {
if (format === undefined) {
throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument');
}
if (format.indexOf('Failed Composite propType: ') === 0) {
return; // Ignore CompositeComponent proptype check.
}
if (!condition) {
for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
args[_key2 - 2] = arguments[_key2];
}
printWarning.apply(undefined, [format].concat(args));
}
};
}
module.exports = warning;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
/***/ }),
/* 5 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(6);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_prop_types__ = __webpack_require__(7);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_prop_types___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1_prop_types__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__utils__ = __webpack_require__(11);
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
/**
* # DubStep
* <h1 align="center">
* dub-step πΊπ½
* </br>
* <img src="https://user-images.githubusercontent.com/1127238/30524706-690c72e0-9bad-11e7-9feb-4c76f572bdfc.png" alt="dub-step logo" title="dub-step logo" width="100">
* </h1>
* <p align="center">Primitives for building step based UI widgets controlled by swipe, timers, and/or buttons.</p>
* <hr />
* </br>
* Many existing carousel/swipe solutions in one way or another end up dictating the markup of your UI. They expose many options to allow for extensibility, but this results in a convoluted API that is not flexible. In these cases, your often very specific design must be fit into an existing rigid solution.
* dub-step simply manages the state needed to power a carousel, slideshow, photo gallery, or even multi-step forms, allowing you to build the UI how you want. It uses the <a href="https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9">function as child</a> and "prop getter" patterns, which gives you maximum flexibility with a minimal API.
*
* dub-step provides an API for updating the state of an index or "step".
* - Directly when an "action" like `next` is called.
* - Incrementally when the provided Next/Previous components are clicked.
* - On swipe when a Step component is swiped.
* - On a timer when the provided Play/Pause components are clicked.
*
*/
var DubStep = function (_Component) {
_inherits(DubStep, _Component);
/**
* These props affect how/when the step and associated state is updated.
*
* @type {object}
* @property {number} total - The total number of steps. Defaults to `0`.
* @property {number} defaultStep - The initial step of dub-step. Defaults to `0`.
* @property {boolean} cycle - Whether or not dub-step should cycle. Defaults to `false`.
* @property {number} stepInterval - The number of steps to interate when navigating. Defaults to `1`.
* @property {boolean} autoPlay - Should dub-step autoPlay? Defaults to `false`.
* @property {number} duration - How long should each step wait? Defaults to `0`.
* @property {boolean} vertical - Are the steps changing vertically? Defaults to `false`.
* @property {boolean} swipe - Are the steps swipable? Defaults to `false`.
* @property {boolean} draggable - Are the steps draggable on desktop? Defaults to `false`.
* @property {boolean} pauseOnHover - Should dub-step pause on hover? Defaults to `false`.
* @property {number} touchThreshold - How much it takes to change steps. Defaults to `20`.
* @property {number} swipeIterateOnly - Regardless of swipe direction, the step is iterated. Defaults to `false`.
* @property {number} animationSpeed - The transition animation speed. Defaults to `0`.
* @property {function} onBeforeChange - Called immediately before the step is changed. Defaults to `() => {}`.
* @property {function} onChange - Called once the step has changed. Defaults to `() => {}`.
* @property {function} onAfterChange - Called after the step has changed and after animationSpeed seconds if present. Defaults to `() => {}`.
* @property {function} onPlay - Called when played. Defaults to `() => {}`.
* @property {function} onPause - Called when paused. Defaults to `() => {}`.
* @property {function} onNext - Called when iterating to the next step. Defaults to `() => {}`.
* @property {function} onPrevious - Called when iterating to the previous step. Defaults to `() => {}`.
* @property {function} onSwipeStart - Called when swiping/dragging has begun. Defaults to `() => {}`.
* @property {function} onSwipeMove - Called when a swipe/drag is moved. Warning: This gets called _a lot_. Defaults to `() => {}`.
* @property {function} onSwipeEnd - Called when a swipe/drag is cancelled. Defaults to `() => {}`.
* @property {function|array} children - Called with an object containing current state and prop getters.
*/
function DubStep(props) {
_classCallCheck(this, DubStep);
var _this = _possibleConstructorReturn(this, (DubStep.__proto__ || Object.getPrototypeOf(DubStep)).call(this, props));
_initialiseProps.call(_this);
if (_this.props.cycle && !_this.props.total) {
throw new Error('Cannot use the cycle prop without a total prop.');
}
if (_this.props.autoPlay && !_this.props.duration) {
throw new Error('Cannot use the autoPlay prop without a duration prop.');
}
return _this;
}
/**
* @type {object}
* @private
* @property {number} step - state - The current step of dub-step. Controlled.
* @property {boolean} paused - state - Is dub-step paused? Controlled.
* @property {boolean} animating - state - Is the step component transition animating?
* @property {boolean} swiping - state - Has the swipe threshold been reached?
* @property {boolean} dragging - state - Has the step component been initially dragged?
* @property {number} swipeLeftDistance - state - A number representing the distance the step component has been dragged horizontally.
* @property {number} swipeDownDistance - state - A number representing the distance the step component has been dragged vertically.
* @property {boolean} swiped - state - Has the step component been dragged enough to be moved to the next/previous step?
* @property {number} swipeRatio - state - A number between 0 and 1 with nearness to 1 representing closeness to being swiped.
* @property {number} swipeDirectionSign - state - Either 1 or -1. 1 representing right and -1 representing left.
* @property {object} touchObject - Holds meta data used to calculate the swipe state. Not exposed through getStateAndHelpers.
*/
_createClass(DubStep, [{
key: 'componentDidMount',
value: function componentDidMount() {
if (this.props.duration && !this.getControlledProp('paused')) {
this.interval = this.startPlaying();
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps, prevState) {
if (this.getControlledProp('paused') || this.props.duration && !this.props.cycle && this.getControlledProp('step') === this.props.total - 1) {
this.interval = this.stopPlaying();
} else if (this.props.duration && (prevProps.paused || prevState.paused)) {
this.interval = this.startPlaying();
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
if (this.interval) {
this.stopPlaying();
}
}
}, {
key: 'getControlledProp',
value: function getControlledProp(prop) {
var state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.state;
return this.isPropControlled(prop) ? this.props[prop] : state[prop];
}
}, {
key: 'getNextStep',
value: function getNextStep() {
var step = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getControlledProp('step');
if (this.props.total) {
if (this.props.cycle) {
if (step + this.props.stepInterval > this.props.total - 1) {
return 0;
}
} else if (step + this.props.stepInterval > this.props.total - 1) {
return this.props.total - 1;
}
}
return step + this.props.stepInterval;
}
}, {
key: 'getPreviousStep',
value: function getPreviousStep() {
var step = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getControlledProp('step');
if (this.props.total) {
if (this.props.cycle) {
if (step - this.props.stepInterval < 0) {
return this.props.total - 1;
}
} else if (step - this.props.stepInterval < 0) {
return 0;
}
}
return step - this.props.stepInterval;
}
/**
* The state of dub-step and prop getters/actions for changing the state are exposed as a parameter to the render prop.
*
* The paramters of this function can be split into 4 categories: State, Components, Actions.
* - *State:* State properties of dub-step exposed to your render code. Controlled state can be passed as a prop and "controlled"
* by an outside component/router/store.
* - *Components* Components that control the current step. They take a `component` prop which allows you to control your UI,
* add internal props, and pass through any additional props you add. Examples include: Step, Next, Previous, Play, Pause.
* _NOTE:_ Each component has an alternative and respective "prop getter", if that pattern is preferred. These are functions named get*ControlProps.
* Call/spread these on the element you're rendering for a given purpose. For example: `<button {...getNextControlProps(otherProps)}))>Next</button>`.
* It's advisable to pass all your props to that function rather than applying them on the element yourself to avoid your props being overridden (or overriding the props returned).
* - *Actions:* Call these to directly change the state of dub-step.
*
* @typedef {object} StateAndHelpers
*
* @property {number} step - state - The current step of dub-step. Controlled.
* @property {boolean} paused - state - Is dub-step paused? Controlled.
* @property {boolean} animating - state - Is the step component transition animating?
* @property {boolean} swiping - state - Has the swipe threshold been reached?
* @property {boolean} dragging - state - Has the step component been initially dragged?
* @property {number} swipeLeftDistance - state - A number representing the distance the step component has been dragged horizontally.
* @property {number} swipeDownDistance - state - A number representing the distance the step component has been dragged vertically.
* @property {boolean} swiped - state - Has the step component been dragged enough to be moved to the next/previous step?
* @property {number} swipeRatio - state - A number between 0 and 1 with nearness to 1 representing closeness to being swiped.
* @property {number} swipeDirectionSign - state - Either 1 or -1. 1 representing right and -1 representing left.
*
* @property {ReactElement} Step - Component - This component is responsible for tracking touch/drag interactions and sets dub-steps swipe state properties respectively.
* Alternatively, use `getStepProps` if you prefer the prop getter patern. Returns the props you should apply to an element you render that is expected to have swipe/drag interactions.
* @property {ReactElement} Next - Component - This component is responsible for incrementing the step by the stepInterval value.
* Alternatively, use `getNextControlProps` if you prefer the prop getter pattern. It returns the props you should apply to a next button element you render.
* @property {ReactElement} Previous - Component - This component is responsible for decrementing the step by the stepInterval value.
* Alternatively, use `getPreviousControlProps` if you prefer the prop getter patern. It returns the props you should apply to a previous/back button element you render.
* @property {ReactElement} Play - Component - This component is responsible for starting an internal interval that increments the step by the stepInterval value.
* Alternatively, use `getPlayControlProps` if you prefer the prop getter patern. It returns the props you should apply to a play button element you render.
* @property {ReactElement} Pause - Component - This component is responsible for clearing an internal interval that increments the step by the stepInterval value.
* Alternatively, use `getPauseControlProps` if you prefer the prop getter patern. It returns the props you should apply to a pause button element you render.
* @property {ReactElement} StepIndex - Component - This component is responsible for setting the current step of dub-step. _NOTE: It takes a step prop representing the step to which dub-step should change._
* Alternatively, use `getStepControlProps` if you prefer the prop getter patern. It returns the props you should apply to an element you render that sets the step of dub-step.
*
* @property {function} next - Action - Increments the step by the stepInterval.
* @property {function} previous - Action - Decrements the step by the stepInterval.
* @property {function} play - Action - Starts the dub-step incrementor interval.
* @property {function} pause - Action - Pauses dub-step.
*/
/**
* Returns state and helpers for render callback.
* @private
*
* @return {StateAndHelpers}
* The state and helper functions exposed as a parameter to the render callback
*/
}, {
key: 'getStateAndHelpers',
value: function getStateAndHelpers() {
return {
// State
step: this.getControlledProp('step'),
paused: this.getControlledProp('paused'),
animating: this.state.animating,
swiping: this.state.swiping,
dragging: this.state.dragging,
swipeLeftDistance: this.state.swipeLeftDistance,
swipeDownDistance: this.state.swipeDownDistance,
swiped: this.state.swiped,
swipeRatio: this.state.swipeRatio,
swipeDirectionSign: this.state.swipeDirectionSign,
// Component/Prop getters
Next: this.Next,
getNextControlProps: this.getNextControlProps,
Previous: this.Previous,
getPreviousControlProps: this.getPreviousControlProps,
Pause: this.Pause,
getPauseControlProps: this.getPauseControlProps,
Play: this.Play,
getPlayControlProps: this.getPlayControlProps,
StepIndex: this.StepIndex,
getStepControlProps: this.getStepControlProps,
Step: this.Step,
getStepProps: this.getStepProps,
// Actions
next: this.next,
previous: this.previous,
pause: this.pause,
play: this.play
};
}
/**
* This component is responsible for tracking touch/drag interactions and sets dub-steps swipe state properties respectively.
*
* @example
* // In this example, GlamorousDogeImg is a glamorous.img. The only required prop here is component. The rest gets passed through for glamorous to for styling purposes (Like css transforms).
* // NOTE: Glamorous is only used as an example. Any kind of component can be passed to the component prop.
* // If no component is passed, a div will be used.
* <Step
* component={GlamorousDogeImg}
* swipeLeftDistance={swipeLeftDistance}
* dragging={dragging}
* src={url}
* alt="doge pic"
* />
*
* @param {object} props
* @param {ReactElement|string} [props.component=div] The element to render
* @return {ReactElement}
*/
/**
* This component is responsible for incrementing the step by the stepInterval value.
*
* @example
* <Next>Next</Next>
*
* @param {object} props
* @param {ReactElement|string} [props.component=button] The element to render
* @return {ReactElement}
*/
/**
* This component is responsible for decrementing the step by the stepInterval value.
*
* @example
* <Previous>Previous</Previous>
*
* @param {object} props
* @param {ReactElement|string} [props.component=button] The element to render
* @return {ReactElement}
*/
/**
* This component is responsible for starting an internal interval that increments the step by the stepInterval value.
*
* @example
* // Any dub-step component can be customized by passing a `component` prop.
* <Play component={MyCustomPlayButton}>Play</Play>
*
* @param {object} props
* @param {ReactElement|string} [props.component=button] The element to render
* @return {ReactElement}
*/
/**
* This component is responsible for clearing an internal interval that increments the step by the stepInterval value.
*
* @example
* <Pause>Stop</Pause>
*
* @param {object} props
* @param {ReactElement|string} [props.component=button] The element to render
* @return {ReactElement}
*/
/**
* This component is responsible for setting the current step of dub-step.
*
* @example
* // Remember, any other prop added gets passed through to the component.
* <StepIndex
* step={index}
* onMouseEnter={() => console.log(`About to switch to step ${index}`)}
* >
* {stepNumber}
* </StepIndex>
*
* @param {object} props
* @param {number} step The step to which dub-step should change.
* @param {ReactElement|string} [props.component=button] The element to render
* @return {ReactElement}
*/
}, {
key: 'isPropControlled',
value: function isPropControlled(prop) {
return this.props[prop] !== undefined;
}
}, {
key: 'startPlaying',
value: function startPlaying() {
var _this2 = this;
return setInterval(function () {
_this2.next();
}, this.props.duration);
}
}, {
key: 'stopPlaying',
value: function stopPlaying() {
return clearInterval(this.interval);
}
}, {
key: 'render',
value: function render() {
var renderProp = Object(__WEBPACK_IMPORTED_MODULE_2__utils__["c" /* unwrapArray */])(this.props.children);
return renderProp(this.getStateAndHelpers());
}
}]);
return DubStep;
}(__WEBPACK_IMPORTED_MODULE_0_react__["Component"]);
DubStep.propTypes = {
total: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.number,
defaultStep: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.number,
cycle: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.bool,
stepInterval: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.number,
autoPlay: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.bool,
duration: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.number,
vertical: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.bool,
swipe: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.bool,
draggable: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.bool,
pauseOnHover: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.bool,
touchThreshold: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.number,
swipeIterateOnly: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.bool,
animationSpeed: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.number,
onBeforeChange: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.func,
onChange: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.func,
onAfterChange: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.func,
onPlay: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.func,
onPause: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.func,
onNext: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.func,
onPrevious: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.func,
onSwipeStart: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.func,
onSwipeMove: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.func,
onSwipeEnd: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.func,
children: __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.oneOfType([__WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.func, __WEBPACK_IMPORTED_MODULE_1_prop_types___default.a.array]).isRequired
};
DubStep.defaultProps = {
total: 0,
defaultStep: 0,
stepInterval: 1,
cycle: false,
swipe: false,
draggable: false,
duration: 0,
autoPlay: false,
touchThreshold: 20,
vertical: false,
pauseOnHover: false,
swipeIterateOnly: false,
animationSpeed: 0,
onBeforeChange: function onBeforeChange() {},
onChange: function onChange() {},
onAfterChange: function onAfterChange() {},
onPlay: function onPlay() {},
onPause: function onPause() {},
onNext: function onNext() {},
onPrevious: function onPrevious() {},
onSwipeStart: function onSwipeStart() {},
onSwipeMove: function onSwipeMove() {},
onSwipeEnd: function onSwipeEnd() {}
};
var _initialiseProps = function _initialiseProps() {
var _this3 = this;
this.state = {
step: this.getControlledProp('step', { step: this.props.defaultStep }),
paused: this.getControlledProp('paused', {
paused: !this.props.autoPlay
}),
animating: false,
swiping: false,
dragging: false,
swipeLeftDistance: 0,
swipeDownDistance: 0,
swiped: false,
swipeRatio: 0,
swipeDirectionSign: 1,
touchObject: {
startX: 0,
startY: 0,
curX: 0,
curY: 0,
swipeLength: 0
}
};
this.getStepProps = function () {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return Object.assign({}, props, {
onMouseDown: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onMouseDown, _this3.swipeStart),
onMouseMove: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onMouseMove, _this3.state.dragging ? _this3.swipeMove : function () {}),
onMouseUp: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onMouseUp, _this3.swipeEnd),
onMouseLeave: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onMouseLeave, _this3.state.dragging ? _this3.swipeEnd : _this3.mouseLeave),
onTouchStart: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onTouchStart, _this3.swipeStart),
onTouchMove: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onTouchMove, _this3.state.dragging ? _this3.swipeMove : function () {}),
onTouchEnd: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onTouchEnd, _this3.swipeEnd),
onTouchCancel: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onTouchCancel, _this3.state.dragging ? _this3.swipeEnd : function () {}),
onMouseEnter: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onMouseEnter, _this3.mouseEnter),
onMouseOver: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onMouseOver, _this3.mouseOver)
});
};
this.getPreviousControlProps = function () {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return Object.assign({
'aria-label': 'previous'
}, props, {
onClick: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onClick, _this3.previous)
});
};
this.getNextControlProps = function () {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return Object.assign({
'aria-label': 'next'
}, props, {
onClick: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onClick, _this3.next)
});
};
this.getPauseControlProps = function () {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return Object.assign({
'aria-label': 'pause'
}, props, {
onClick: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onClick, _this3.pause)
});
};
this.getPlayControlProps = function () {
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return Object.assign({
'aria-label': 'play'
}, props, {
onClick: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(props.onClick, _this3.play)
});
};
this.getStepControlProps = function () {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { step: 0 };
var step = _ref.step,
rest = _objectWithoutProperties(_ref, ['step']);
return Object.assign({
'aria-label': 'change'
}, rest, {
onClick: Object(__WEBPACK_IMPORTED_MODULE_2__utils__["a" /* callAll */])(rest.onClick, function () {
return _this3.changeSlide(step);
})
});
};
this.setStepState = function (nextState) {
var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {};
_this3.interval = _this3.stopPlaying();
if (_this3.isPropControlled('step')) {
_this3.props.onChange(nextState.step, _this3.getStateAndHelpers());
callback();
} else {
_this3.setState(nextState, function () {
if (!_this3.interval && _this3.props.duration && !_this3.getControlledProp('paused')) {
_this3.interval = _this3.startPlaying();
}
_this3.props.onChange(_this3.getControlledProp('step'), _this3.getStateAndHelpers());
callback();
});
}
};
this.setPlayState = function (paused) {
if (!_this3.props.duration) {
return;
}
_this3.setState({ paused: paused });
};
this.Step = function (_ref2) {
var _ref2$component = _ref2.component,
Comp = _ref2$component === undefined ? 'div' : _ref2$component,
otherProps = _objectWithoutProperties(_ref2, ['component']);
return __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement(Comp, _this3.getStepProps(otherProps));
};
this.Next = function (_ref3) {
var _ref3$component = _ref3.component,
Comp = _ref3$component === undefined ? 'button' : _ref3$component,
otherProps = _objectWithoutProperties(_ref3, ['component']);
return __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement(Comp, _this3.getNextControlProps(otherProps));
};
this.Previous = function (_ref4) {
var _ref4$component = _ref4.component,
Comp = _ref4$component === undefined ? 'button' : _ref4$component,
otherProps = _objectWithoutProperties(_ref4, ['component']);
return __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement(Comp, _this3.getPreviousControlProps(otherProps));
};
this.Play = function (_ref5) {
var _ref5$component = _ref5.component,
Comp = _ref5$component === undefined ? 'button' : _ref5$component,
otherProps = _objectWithoutProperties(_ref5, ['component']);
return __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement(Comp, _this3.getPlayControlProps(otherProps));
};
this.Pause = function (_ref6) {
var _ref6$component = _ref6.component,
Comp = _ref6$component === undefined ? 'button' : _ref6$component,
otherProps = _objectWithoutProperties(_ref6, ['component']);
return __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement(Comp, _this3.getPauseControlProps(otherProps));
};
this.StepIndex = function (_ref7) {
var _ref7$component = _ref7.component,
Comp = _ref7$component === undefined ? 'button' : _ref7$component,
step = _ref7.step,
otherProps = _objectWithoutProperties(_ref7, ['component', 'step']);
return __WEBPACK_IMPORTED_MODULE_0_react___default.a.createElement(Comp, _this3.getStepControlProps(Object.assign({ step: step }, otherProps)));
};
this.next = function () {
var nextStep = _this3.getNextStep();
_this3.props.onNext(nextStep, _this3.getStateAndHelpers());
return _this3.changeSlide(nextStep);
};
this.previous = function () {
var previousStep = _this3.getPreviousStep();
_this3.props.onPrevious(previousStep, _this3.getStateAndHelpers());
_this3.changeSlide(previousStep);
};
this.pause = function () {
if (!_this3.isPropControlled('paused')) {
_this3.setPlayState(true);
}
_this3.props.onPause(_this3.getStateAndHelpers());
};
this.play = function () {
if (!_this3.isPropControlled('paused')) {
_this3.setPlayState(false);
}
_this3.props.onPlay(_this3.getStateAndHelpers());
};
this.mouseEnter = function (e) {
e.preventDefault();
if (!_this3.getControlledProp('paused') && _this3.props.pauseOnHover) {
_this3.pause();
_this3.wasPlaying = true;
}
};
this.mouseLeave = function (e) {
e.preventDefault();
if (_this3.wasPlaying === true && _this3.getControlledProp('paused') && _this3.props.pauseOnHover) {
_this3.play();
delete _this3.wasPlaying;
}
};
this.swipeStart = function (e) {
if (_this3.props.swipe === false || 'ontouchend' in document && _this3.props.swipe === false) {
return;
} else if (_this3.props.draggable === false && e.type.indexOf('mouse') !== -1) {
return;
}
var posX = e.touches !== undefined ? e.touches[0].pageX : e.clientX;
var posY = e.touches !== undefined ? e.touches[0].pageY : e.clientY;
_this3.targetSize = e.target[_this3.props.vertical ? 'offsetHeight' : 'offsetWidth'];
_this3.setState({
dragging: true,
touchObject: {
startX: posX,
startY: posY,
curX: posX,
curY: posY,
swipeLength: 0
}
}, function () {
_this3.props.onSwipeStart({
dragging: true,
touchObject: _this3.state.touchObject
});
});
};
this.swipeMove = function (e) {
e.preventDefault();
if (!_this3.state.dragging) {
return;
}
if (_this3.state.animating) {
return;
}
var touchObject = _this3.state.touchObject;
var axis = _this3.props.vertical ? 'Y' : 'X';
touchObject.curX = e.touches ? e.touches[0].pageX : e.clientX;
touchObject.curY = e.touches ? e.touches[0].pageY : e.clientY;
touchObject.swipeLengthX = Math.round(Math.sqrt(Math.pow(touchObject.curX - touchObject.startX, 2)));
touchObject.swipeLengthY = Math.round(Math.sqrt(Math.pow(touchObject.curY - touchObject.startY, 2)));
touchObject.swipeLength = Math.round(Math.sqrt(Math.pow(touchObject['cur' + axis] - touchObject['start' + axis], 2)));
var positionOffsetX = touchObject.curX > touchObject.startX ? 1 : -1;
var positionOffsetY = touchObject.curY > touchObject.startY ? 1 : -1;
var swipeLeftDistance = touchObject.swipeLengthX * positionOffsetX;
var swipeDownDistance = touchObject.swipeLengthY * positionOffsetY;
var swipeDirectionSign = Object(__WEBPACK_IMPORTED_MODULE_2__utils__["b" /* getSign */])(_this3.props.vertical ? swipeDownDistance : swipeLeftDistance);
_this3.setState({
touchObject: touchObject,
swipeLeftDistance: swipeLeftDistance,
swipeDownDistance: swipeDownDistance,
swiped: touchObject['swipeLength' + axis] > _this3.targetSize / _this3.props.touchThreshold,
swipeRatio: touchObject['swipeLength' + axis] / (_this3.targetSize / _this3.props.touchThreshold),
swipeDirectionSign: swipeDirectionSign
}, function () {
_this3.props.onSwipeMove({ swipeLeftDistance: swipeLeftDistance, swipeDownDistance: swipeDownDistance, swiped: _this3.state.swiped }, _this3.getStateAndHelpers());
});
if (touchObject.swipeLength > 4) {
_this3.setState({ swiping: true });
}
};
this.swipeEnd = function (e) {
if (!_this3.state.dragging) {
if (_this3.props.swipe) {
e.preventDefault();
}
return;
}
var swipeDirectionSign = _this3.state.swipeDirectionSign;
var touchObject = _this3.state.touchObject;
var minSwipe = _this3.targetSize / _this3.props.touchThreshold;
var wasAnimating = _this3.state.animating;
// Reset the state of touch related state variables.
var resetState = {
dragging: false,
swiping: false,
swiped: false,
swipeRatio: 0,
swipeDirectionSign: 1,
swipeLeftDistance: 0,
swipeDownDistance: 0,
touchObject: {
startX: 0,
startY: 0,
curX: 0,
curY: 0,
swipeLength: 0,
swipeLengthX: 0,
swipeLengthY: 0
}
};
_this3.setState(resetState, function () {
_this3.props.onSwipeEnd(resetState, _this3.getStateAndHelpers());
});
if (wasAnimating) {
return;
}
if (!touchObject.swipeLength) {
return;
}
if (touchObject.swipeLength > minSwipe) {
e.preventDefault();
if (_this3.props.swipeIterateOnly || swipeDirectionSign === -1) {
_this3.next();
} else {
_this3.previous();
}
}
};
this.changeSlide = function (step) {
if (_this3.props.onBeforeChange) {
_this3.props.onBeforeChange(step, _this3.getStateAndHelpers());
}
var nextStateChanges = {
animating: false,
step: step,
swipeLeftDistance: 0,
swipeDownDistance: 0
};
var callback = function callback() {
_this3.setStepState(nextStateChanges, function () {
if (_this3.props.onAfterChange) {
_this3.props.onAfterChange(step, _this3.getStateAndHelpers());
}
delete _this3.animationEndCallback;
});
};
_this3.setState({
// Only set animating if there is a animationSpeed prop.
animating: Boolean(_this3.props.animationSpeed)
}, function () {
if (_this3.props.animationSpeed) {
_this3.animationEndCallback = setTimeout(callback, _this3.props.animationSpeed);
} else {
callback();
}
});
};
};
/* harmony default export */ __webpack_exports__["default"] = (DubStep);
/***/ }),
/* 6 */
/***/ (function(module, exports) {
module.exports = require("react");
/***/ }),
/* 7 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(process) {/**
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
if (process.env.NODE_ENV !== 'production') {
var REACT_ELEMENT_TYPE = (typeof Symbol === 'function' &&
Symbol.for &&
Symbol.for('react.element')) ||
0xeac7;
var isValidElement = function(object) {
return typeof object === 'object' &&
object !== null &&
object.$$typeof === REACT_ELEMENT_TYPE;
};
// By explicitly using