react-sled
Version:
react-sled is a carousel made with react-spring.
846 lines (799 loc) • 35.4 kB
JavaScript
import React, { createContext, useContext, useReducer, useEffect, useRef, useState } from 'react';
import { useSpring, animated } from 'react-spring';
import { useDrag } from 'react-use-gesture';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
}
var stateFromProps = {
width: null,
proportion: null,
select: null,
keyboard: true,
dragging: true,
dragDistance: '25ow',
autoPlayInterval: null,
config: { mass: 1, tension: 210, friction: 20, clamp: true },
pauseOnMouseOver: true,
stopOnInteraction: false,
rewind: false,
pause: false,
onSledEnd: null,
onAnimationStart: null,
onAnimationEnd: null
};
var ViewsProps = __assign({}, stateFromProps);
var initialState = __assign({ currentIndex: 0, prevIndex: undefined, pause: false, viewCount: 0, hasFocus: false, direction: 'horizontal', showElements: 1, slideBy: 1, slideSteps: 1, sliderSize: 0, dimensions: { width: 0, height: 0 }, dimensionsDOM: { width: 0, height: 0 } }, stateFromProps);
/**
* https://github.com/lodash/lodash/blob/master/clamp.js
* Clamps `number` within the inclusive `lower` and `upper` bounds.
*/
function clamp(number, lower, upper) {
number = +number;
lower = +lower;
upper = +upper;
lower = lower === lower ? lower : 0;
upper = upper === upper ? upper : 0;
if (number === number) {
number = number <= upper ? number : upper;
number = number >= lower ? number : lower;
}
return number;
}
function getNext(currentIndex, slideSteps, rewind) {
if (currentIndex === slideSteps - 1 && !rewind) {
return clamp(currentIndex, 0, slideSteps - 1);
}
return (currentIndex + 1) % slideSteps;
}
function getPrev(currentIndex, slideSteps, rewind) {
if (currentIndex === 0 && !rewind) {
return clamp(currentIndex, 0, slideSteps - 1);
}
return (currentIndex - 1 + slideSteps) % slideSteps;
}
function reducer(state, action) {
switch (action.type) {
case 'NEXT': return __assign(__assign({}, state), { currentIndex: getNext(state.currentIndex, state.slideSteps, state.rewind), prevIndex: state.currentIndex });
case 'PREV': return __assign(__assign({}, state), { currentIndex: getPrev(state.currentIndex, state.slideSteps, state.rewind), prevIndex: state.currentIndex });
case 'SELECT': return __assign(__assign({}, state), { currentIndex: clamp(action.index, 0, state.slideSteps - 1), prevIndex: state.currentIndex });
case 'SET_DIRECTION': return __assign(__assign({}, state), { direction: action.direction });
case 'SET_PAUSE': return __assign(__assign({}, state), { pause: action.pause });
case 'SET_MOUSEOVER': return __assign(__assign({}, state), { pauseOnMouseOver: action.pauseOnMouseOver });
case 'SET_VIEWCOUNT': return __assign(__assign({}, state), { viewCount: action.count });
case 'SET_FOCUS': return __assign(__assign({}, state), { hasFocus: action.focus });
case 'SET_DIMENSIONS': return __assign(__assign({}, state), { dimensions: action.dimensions });
case 'SET_DIMENSIONS_DOM': return __assign(__assign({}, state), { dimensionsDOM: action.dimensionsDOM });
case 'SET_PROPORTION': return __assign(__assign({}, state), { proportion: action.proportion });
case 'SET_DRAGGING': return __assign(__assign({}, state), { dragging: action.dragging });
case 'SET_DRAG_DISTANCE': return __assign(__assign({}, state), { dragDistance: action.dragDistance });
case 'SET_AUTOPLAY': return __assign(__assign({}, state), { autoPlayInterval: action.autoPlayInterval });
case 'SET_CONFIG': return __assign(__assign({}, state), { config: action.config });
case 'SET_REWIND': return __assign(__assign({}, state), { rewind: action.rewind });
case 'SET_STOPONINTERACTION': return __assign(__assign({}, state), { stopOnInteraction: action.stopOnInteraction });
case 'SET_SLIDEBY': return __assign(__assign({}, state), { slideBy: action.slideBy });
case 'SET_SLIDESTEPS': return __assign(__assign({}, state), { slideSteps: action.slideSteps });
case 'SET_SHOWELEMENTS': return __assign(__assign({}, state), { showElements: action.showElements });
case 'SET_SLIDERSIZE': return __assign(__assign({}, state), { sliderSize: action.sliderSize });
default: return state;
}
}
// https://medium.com/simply/state-management-with-react-hooks-and-context-api-at-10-lines-of-code-baf6be8302c
var StateContext = createContext(initialState);
var StateProvider = function (_a) {
var children = _a.children;
var _b = useReducer(reducer, initialState), state = _b[0], dispatch = _b[1];
return (React.createElement(StateContext.Provider, { value: [state, dispatch] }, children));
};
var useStateContext = function () {
var _a = useContext(StateContext), state = _a[0], dispatch = _a[1];
return [state, dispatch];
};
var Sled = function (props) {
var children = props.children;
return (React.createElement(StateProvider, null, children));
};
var useDragGesture = (function (set) {
var _a = useStateContext(), _b = _a[0], dragging = _b.dragging, dragDistance = _b.dragDistance, _c = _b.dimensions, width = _c.width, height = _c.height, currentIndex = _b.currentIndex, direction = _b.direction, stopOnInteraction = _b.stopOnInteraction, showElements = _b.showElements, slideBy = _b.slideBy, dispatch = _a[1];
var bind = useDrag(function (_a) {
var down = _a.down, _b = _a.movement, xDelta = _b[0], yDelta = _b[1], _c = _a.direction, xDir = _c[0], yDir = _c[1], distance = _a.distance, cancel = _a.cancel, canceled = _a.canceled;
if (canceled)
return;
if (stopOnInteraction) {
dispatch({ type: 'SET_AUTOPLAY', autoPlayInterval: undefined });
}
if (down && distance > dragDistance) {
var dirValue = direction === 'horizontal' ? xDir : yDir;
dispatch({
type: dirValue > 0
? 'PREV'
: 'NEXT',
pause: true
});
cancel();
}
set(function () {
var x = direction === 'horizontal'
? (-currentIndex * (width / showElements * slideBy)) + (down ? xDelta : 0)
: (-currentIndex * (height / showElements * slideBy)) + (down ? yDelta : 0);
return {
x: x,
immediate: false,
cursor: down ? 'grabbing' : 'grab',
onStart: undefined,
onRest: undefined
};
});
dispatch({ type: 'SET_PAUSE', pause: true });
});
return dragging && bind;
});
var useFocus = function (ref) {
var _a = useStateContext(), dispatch = _a[1];
useEffect(function () {
function onFocus() {
dispatch({ type: 'SET_FOCUS', focus: true });
}
function onBlur() {
dispatch({ type: 'SET_FOCUS', focus: false });
}
ref.current.addEventListener('focus', onFocus);
ref.current.addEventListener('blur', onBlur);
return function () {
ref.current.removeEventListener('focus', onFocus);
ref.current.removeEventListener('blur', onBlur);
};
}, []);
};
var useCursor = (function () {
var dragging = useStateContext()[0].dragging;
var _a = React.useState('auto'), cursor = _a[0], setCursor = _a[1];
React.useEffect(function () {
setCursor(dragging ? 'grab' : 'auto');
}, [dragging]);
return cursor;
});
function useX () {
var _a = useStateContext()[0], direction = _a.direction, _b = _a.dimensions, width = _b.width, height = _b.height, showElements = _a.showElements, slideBy = _a.slideBy, currentIndex = _a.currentIndex;
var _c = React.useState(0), x = _c[0], setX = _c[1];
React.useEffect(function () {
if (direction === 'horizontal') {
setX(-currentIndex * (width / showElements * slideBy));
}
else {
setX(-currentIndex * (height / showElements * slideBy));
}
}, [direction, width, height, showElements, slideBy, currentIndex]);
return x;
}
function useSliderStyles() {
var _a = useStateContext()[0], sliderSize = _a.sliderSize, direction = _a.direction, dragging = _a.dragging;
var _b = React.useState({}), styles = _b[0], setStyles = _b[1];
React.useEffect(function () {
var defaultStyles = {
position: 'absolute',
top: 0,
left: 0,
willChange: 'transform',
overflow: 'hidden',
cursor: dragging ? 'grab' : 'auto'
};
if (direction === 'vertical') {
setStyles(__assign(__assign({}, defaultStyles), { width: '100%', height: sliderSize || 0 }));
}
else {
setStyles(__assign(__assign({}, defaultStyles), { width: sliderSize || 0, height: '100%', display: 'flex' }));
}
}, [direction, dragging, sliderSize]);
return styles;
}
function useViewStyles() {
var _a = useStateContext()[0], _b = _a.dimensions, width = _b.width, height = _b.height, viewCount = _a.viewCount, direction = _a.direction, showElements = _a.showElements;
var _c = React.useState({}), styles = _c[0], setStyles = _c[1];
React.useEffect(function () {
var defaultStyles = {
position: 'relative',
};
if (direction === 'vertical') {
setStyles(__assign(__assign({}, defaultStyles), { width: '100%', height: height / showElements }));
}
else {
setStyles(__assign(__assign({}, defaultStyles), { width: width / showElements, height: '100%' }));
}
}, [width, height, direction, viewCount, showElements]);
return styles;
}
var SledSprings = function (_a) {
var onAnimationStart = _a.onAnimationStart, onAnimationEnd = _a.onAnimationEnd, onSledEnd = _a.onSledEnd, children = _a.children;
var _b = useStateContext(), _c = _b[0], currentIndex = _c.currentIndex, viewCount = _c.viewCount, direction = _c.direction, _d = _c.dimensions, width = _d.width, height = _d.height, config = _c.config, dispatch = _b[1];
var cursor = useCursor();
var x = useX();
var _e = useSpring(function () { return ({
x: 0,
cursor: cursor,
config: config,
immediate: true
}); }), props = _e[0], set = _e[1];
var springRef = React.useRef();
useFocus(springRef);
var _f = React.useState(false), dimensionsUpdated = _f[0], setDimensionsUpdated = _f[1];
useEffect(function () {
setDimensionsUpdated(true);
}, [width, height]);
useEffect(function () {
if (!dimensionsUpdated)
return;
setDimensionsUpdated(false);
set({
x: x,
immediate: true,
onStart: null,
onRest: null,
});
}, [x, dimensionsUpdated]);
useEffect(function () {
if (dimensionsUpdated)
return;
set({
config: config,
x: x,
cursor: cursor,
immediate: false,
onStart: function () {
dispatch({ type: 'SET_PAUSE', pause: true });
if (typeof onAnimationStart === 'function')
onAnimationStart();
},
onRest: function () {
dispatch({ type: 'SET_PAUSE', pause: false });
if (typeof onAnimationEnd === 'function')
onAnimationEnd();
if (currentIndex === viewCount - 1) {
if (typeof onSledEnd === 'function')
onSledEnd();
}
},
});
}, [x, currentIndex, dimensionsUpdated, viewCount, cursor]);
var bind = useDragGesture(set);
var sliderStyles = useSliderStyles();
var viewStyles = useViewStyles();
return (React.createElement(animated.div, __assign({}, bind ? bind() : {}, { className: 'sled-slider', ref: springRef, style: __assign(__assign({}, sliderStyles), { transform: direction === 'horizontal'
? props.x.to(function (x) { return "translate3d(" + x + "px,0,0)"; })
: props.x.to(function (x) { return "translate3d(0," + x + "px,0)"; }), cursor: props.cursor }) }), React.Children.map(children, function (child) { return (React.createElement("div", { className: "sled-element", style: viewStyles }, child)); })));
};
var useDirection = (function (direction) {
var _a = useStateContext(), dispatch = _a[1];
React.useEffect(function () {
if (direction) {
dispatch({ type: 'SET_DIRECTION', direction: direction });
}
}, [direction]);
});
var useDimensionsDOM = (function (width, height) {
var _a = useStateContext(), dispatch = _a[1];
React.useEffect(function () {
if (!width && !height) {
dispatch({
type: 'SET_DIMENSIONS_DOM',
dimensionsDOM: { width: '100%', height: null }
});
dispatch({ type: 'SET_PROPORTION', proportion: '2:1' });
return;
}
dispatch({
type: 'SET_DIMENSIONS_DOM',
dimensionsDOM: { width: width, height: height }
});
}, [width, height]);
});
// https://github.com/chodorowicz/ts-debounce/blob/master/src/index.ts
function debounce(func, waitMilliseconds, options) {
if (waitMilliseconds === void 0) { waitMilliseconds = 50; }
if (options === void 0) { options = {
isImmediate: false
}; }
var timeoutId;
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var context = this;
var doLater = function () {
timeoutId = undefined;
if (!options.isImmediate) {
func.apply(context, args);
}
};
var shouldCallNow = options.isImmediate && timeoutId === undefined;
if (timeoutId !== undefined) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(doLater, waitMilliseconds);
if (shouldCallNow) {
func.apply(context, args);
}
};
}
function getProportion(_a) {
var width = _a.width, height = _a.height, offsetWidth = _a.offsetWidth, offsetHeight = _a.offsetHeight, proportion = _a.proportion, dispatch = _a.dispatch;
if (!proportion)
return;
var _b = proportion.split(':'), proportionWidth = _b[0], proportionHeight = _b[1];
var dimensions = { width: 0, height: 0 };
if (width) {
var heightValue = (offsetWidth * +proportionHeight) / +proportionWidth;
dimensions = {
width: offsetWidth,
height: heightValue
};
}
else {
var widthValue = (offsetHeight * +proportionWidth) / +proportionHeight;
dimensions = {
width: widthValue,
height: offsetHeight
};
}
dispatch({
type: 'SET_DIMENSIONS',
dimensions: dimensions
});
}
var useDimensions = (function (ref) {
var _a = useStateContext(), _b = _a[0], dimensionsDOM = _b.dimensionsDOM, proportion = _b.proportion, dispatch = _a[1];
React.useEffect(function () {
function onResize() {
var _a = ref.current, offsetWidth = _a.offsetWidth, offsetHeight = _a.offsetHeight;
getProportion(__assign(__assign({}, dimensionsDOM), { offsetWidth: offsetWidth,
offsetHeight: offsetHeight,
proportion: proportion,
dispatch: dispatch }));
}
onResize();
var dOnResize = debounce(onResize, 200);
window.addEventListener('resize', dOnResize);
return function () { return window.removeEventListener('resize', dOnResize); };
}, [dimensionsDOM, proportion]);
});
var useProportion = (function (width, height, proportion) {
var _a = useStateContext(), dispatch = _a[1];
React.useEffect(function () {
if (!height && !proportion) {
dispatch({ type: 'SET_PROPORTION', proportion: '2:1' });
}
else {
dispatch({ type: 'SET_PROPORTION', proportion: proportion });
}
}, [width, height, proportion]);
});
var useKeyboard = function (keyboard) {
var _a = useStateContext(), _b = _a[0], hasFocus = _b.hasFocus, stopOnInteraction = _b.stopOnInteraction, dispatch = _a[1];
var hasFocusRef = useRef(false);
useEffect(function () {
hasFocusRef.current = hasFocus;
}, [hasFocus]);
useEffect(function () {
function onKeyup(event) {
if (!hasFocusRef.current)
return;
if (stopOnInteraction) {
dispatch({ type: 'SET_AUTOPLAY', autoPlayInterval: undefined });
}
switch (event.keyCode) {
case 37:
dispatch({ type: 'PREV' });
break;
case 39:
dispatch({ type: 'NEXT' });
break;
}
}
if (keyboard) {
document.addEventListener('keyup', onKeyup);
return function () { return document.removeEventListener('keyup', onKeyup); };
}
}, [keyboard, stopOnInteraction]);
};
function getDistance(distance, width) {
switch (typeof distance) {
case 'number': return distance;
case 'string':
if (distance.indexOf('%') >= 0) {
return (width / 100) * +distance.replace('%', '');
}
var distanceNumber = parseInt(distance, 10);
if (distanceNumber) {
return distanceNumber;
}
console.warn('Sled-Error: dragDistance must either be a String with unit % or a number.');
return 40;
default:
return 40;
}
}
var useDragging = (function (dragging, dragDistance) {
var _a = useStateContext(), width = _a[0].dimensions.width, dispatch = _a[1];
useEffect(function () {
var distance = getDistance(dragDistance, width);
dispatch({ type: 'SET_DRAG_DISTANCE', dragDistance: distance });
}, [dispatch, dragDistance, width]);
useEffect(function () {
dispatch({ type: 'SET_DRAGGING', dragging: dragging });
}, [dispatch, dragging]);
});
var useMouseOver = (function (pauseOnMouseOver, ref) {
var _a = useStateContext(), autoPlayInterval = _a[0].autoPlayInterval, dispatch = _a[1];
useEffect(function () {
dispatch({ type: 'SET_PAUSE', pause: false });
function onMouseEnter() {
dispatch({ type: 'SET_MOUSEOVER', pauseOnMouseOver: true });
dispatch({ type: 'SET_PAUSE', pause: true });
}
function onMouseLeave() {
dispatch({ type: 'SET_MOUSEOVER', pauseOnMouseOver: false });
dispatch({ type: 'SET_PAUSE', pause: false });
}
if (pauseOnMouseOver && autoPlayInterval) {
ref.current.addEventListener('mouseenter', onMouseEnter);
ref.current.addEventListener('mouseover', onMouseEnter);
ref.current.addEventListener('mouseout', onMouseLeave);
return function () {
dispatch({ type: 'SET_MOUSEOVER', pauseOnMouseOver: false });
ref.current.removeEventListener('mouseenter', onMouseEnter);
ref.current.removeEventListener('mouseover', onMouseEnter);
ref.current.removeEventListener('mouseout', onMouseLeave);
};
}
}, [pauseOnMouseOver, autoPlayInterval, dispatch, ref]);
});
var useSelect = function (select) {
var _a = useStateContext(), dispatch = _a[1];
useEffect(function () {
if (typeof select === 'number') {
dispatch({ type: 'SELECT', index: select });
}
else {
dispatch({ type: select === 'next' ? 'NEXT' : 'PREV' });
}
}, [select]);
};
function useViewCount (children) {
var _a = useStateContext(), dispatch = _a[1];
useEffect(function () {
dispatch({ type: 'SET_VIEWCOUNT', count: React.Children.toArray(children).length });
}, [children]);
}
var useInterval = function (callback, interval) {
var savedCallback = useRef(callback);
useEffect(function () {
savedCallback.current = callback;
});
useEffect(function () {
function tick() {
savedCallback.current();
}
if (typeof interval === 'number') {
var id_1 = setInterval(tick, interval);
return function () { return clearInterval(id_1); };
}
}, [interval]);
};
var useAutoPlay = (function (autoPlayIntervalNew) {
var _a = useStateContext(), _b = _a[0], pause = _b.pause, autoPlayInterval = _b.autoPlayInterval, dispatch = _a[1];
useEffect(function () {
if (typeof autoPlayIntervalNew === 'number') {
dispatch({ type: 'SET_AUTOPLAY', autoPlayInterval: autoPlayIntervalNew });
}
else {
console.warn("Sled-Error: \"autoplay\" must be of type \"number\", not \"" + typeof autoPlayIntervalNew + "\".");
}
}, [autoPlayIntervalNew]);
useInterval(function () {
dispatch({ type: 'NEXT' });
}, !pause && autoPlayInterval);
});
var useConfig = (function (config) {
var _a = useStateContext(), dispatch = _a[1];
useEffect(function () {
dispatch({ type: 'SET_CONFIG', config: config });
}, [config, dispatch]);
});
var useRewind = (function (rewind) {
var _a = useStateContext(), dispatch = _a[1];
useEffect(function () {
dispatch({ type: 'SET_REWIND', rewind: rewind });
}, [rewind]);
});
var usePause = (function (pause) {
var _a = useStateContext(), dispatch = _a[1];
useEffect(function () {
dispatch({ type: 'SET_PAUSE', pause: pause });
}, [pause]);
});
var useStopOnInteraction = function (stopOnInteraction) {
var _a = useStateContext(), dispatch = _a[1];
useEffect(function () {
dispatch({ type: 'SET_STOPONINTERACTION', stopOnInteraction: stopOnInteraction });
}, [stopOnInteraction]);
};
var useShowElements = function (showElements) {
var _a = useStateContext(), dispatch = _a[1];
useEffect(function () {
if (showElements) {
dispatch({ type: 'SET_SHOWELEMENTS', showElements: showElements });
}
}, [showElements]);
};
var useShowElements$1 = function (slideBy) {
var _a = useStateContext(), dispatch = _a[1];
useEffect(function () {
if (slideBy) {
dispatch({ type: 'SET_SLIDEBY', slideBy: slideBy });
}
}, [slideBy]);
};
var useSlideSteps = function () {
var _a = useStateContext(), _b = _a[0], viewCount = _b.viewCount, slideBy = _b.slideBy, dispatch = _a[1];
useEffect(function () {
var slideSteps = Math.ceil(viewCount / slideBy);
dispatch({ type: 'SET_SLIDESTEPS', slideSteps: slideSteps });
}, [viewCount, slideBy]);
};
function useSliderStyles$1() {
var _a = useStateContext(), _b = _a[0], _c = _b.dimensions, width = _c.width, height = _c.height, viewCount = _b.viewCount, direction = _b.direction, showElements = _b.showElements, dispatch = _a[1];
React.useEffect(function () {
if (direction === 'vertical') {
dispatch({ type: 'SET_SLIDERSIZE', sliderSize: (height / showElements) * viewCount });
}
else {
dispatch({ type: 'SET_SLIDERSIZE', sliderSize: (width / showElements) * viewCount });
}
}, [direction, width, height, showElements, viewCount]);
}
var SledViews = function (_a) {
var children = _a.children, style = _a.style, width = _a.width, height = _a.height, proportion = _a.proportion, direction = _a.direction, select = _a.select, slideBy = _a.slideBy, showElements = _a.showElements, keyboard = _a.keyboard, dragging = _a.dragging, dragDistance = _a.dragDistance, autoPlayInterval = _a.autoPlayInterval, config = _a.config, pauseOnMouseOver = _a.pauseOnMouseOver, stopOnInteraction = _a.stopOnInteraction, rewind = _a.rewind, pause = _a.pause, onSledEnd = _a.onSledEnd, onAnimationStart = _a.onAnimationStart, onAnimationEnd = _a.onAnimationEnd;
var viewsRef = useRef();
var _b = useStateContext()[0], dimensions = _b.dimensions, dimensionsDOM = _b.dimensionsDOM;
useProportion(width, height, proportion);
useDimensionsDOM(width, height);
useDimensions(viewsRef);
useDirection(direction);
useFocus(viewsRef);
useViewCount(children);
useRewind(rewind);
usePause(pause);
useShowElements(showElements);
useShowElements$1(slideBy);
useSliderStyles$1();
useSlideSteps();
useStopOnInteraction(stopOnInteraction);
useMouseOver(pauseOnMouseOver, viewsRef);
useSelect(select);
useKeyboard(keyboard);
useDragging(dragging, dragDistance);
useAutoPlay(autoPlayInterval);
useConfig(config);
return (React.createElement("div", { className: 'sled', ref: viewsRef, style: __assign(__assign({}, dimensionsDOM), style), tabIndex: 0 },
React.createElement("div", { className: 'sled-sizer', style: dimensions },
React.createElement(SledSprings, { onAnimationStart: onAnimationStart, onAnimationEnd: onAnimationEnd, onSledEnd: onSledEnd }, children))));
};
SledViews.defaultProps = ViewsProps;
var useDirectionDisabled = function (select) {
var _a = useStateContext()[0], rewind = _a.rewind, currentIndex = _a.currentIndex, viewCount = _a.viewCount;
var _b = useState(false), disabled = _b[0], setDisabled = _b[1];
useEffect(function () {
if (typeof select === 'string') {
if (rewind) {
setDisabled(false);
return;
}
if (select === 'next' && currentIndex === viewCount - 1) {
setDisabled(true);
}
else if (select === 'prev' && currentIndex === 0) {
setDisabled(true);
}
else {
setDisabled(false);
}
}
}, [currentIndex, rewind]);
return disabled;
};
function getClassName(type, select, className) {
var currentIndex = useStateContext()[0].currentIndex;
var directionDisabled = useDirectionDisabled(select);
var baseClass = 'sled-control';
var typeClass = baseClass + "-" + type;
var typeClassSpecific = typeClass + "-" + select;
var distinctClass = baseClass + "-" + (className || type + '-default');
var disabledClasses = [
baseClass + "-disabled",
typeClass + "-disabled",
distinctClass + "-disabled"
];
var activeClasses = [
baseClass + "-active",
typeClass + "-active",
distinctClass + "-active"
];
var classes = [
baseClass,
typeClass,
typeClassSpecific,
distinctClass,
];
if (select === currentIndex) { // isActive
return __spreadArrays(classes, activeClasses).join(' ');
}
if (directionDisabled) {
return __spreadArrays(classes, disabledClasses).join(' ');
}
return classes.join(' ');
}
var useClassName = (function (select, className) {
switch (typeof select) {
case 'number':
return getClassName('index', select, className);
case 'string':
default:
return getClassName('direction', select, className);
}
});
var useLabel = (function (select) {
switch (typeof select) {
case 'number':
return "Slide to view with index " + select + ".";
case 'string':
default:
return "Slide to " + (select === 'next' ? 'next' : 'previous') + " view.";
}
});
var onClickFunction = function (select) {
var _a = useStateContext(), stopOnInteraction = _a[0].stopOnInteraction, dispatch = _a[1];
function onClick() {
if (stopOnInteraction) {
dispatch({ type: 'SET_AUTOPLAY', autoPlayInterval: undefined });
}
if (typeof select === 'number') {
dispatch({ type: 'SELECT', index: select });
}
else {
dispatch({ type: select === 'next' ? 'NEXT' : 'PREV' });
}
}
return onClick;
};
var SledControl = function (_a) {
var children = _a.children, select = _a.select, style = _a.style, className = _a.className;
var controlRef = useRef();
useFocus(controlRef);
var directionDisabled = useDirectionDisabled(select);
var classNames = useClassName(select, className);
var label = useLabel(select);
var onClick = onClickFunction(select);
var currentIndex = useStateContext()[0].currentIndex;
return (React.createElement("div", __assign({ className: classNames, style: style, ref: controlRef, role: 'button', "aria-label": label, tabIndex: 0, onClick: onClick }, select === currentIndex || directionDisabled ? { 'aria-disabled': true } : {}), children));
};
var SledProgressSeparators = function (_a) {
var className = _a.className;
var slideSteps = useStateContext()[0].slideSteps;
return slideSteps && (React.createElement("div", { className: "sled-progress-" + className + "-separators" }, __spreadArrays(Array(slideSteps - 1)).map(function (_, index) { return (React.createElement("div", { key: index, className: "sled-progress-" + className + "-separator", style: {
position: 'relative',
height: '100%'
} })); })));
};
function getX(slideSteps, currentIndex, goPrevNext) {
if (goPrevNext === void 0) { goPrevNext = 0; }
return 100 - ((100 / slideSteps) * (currentIndex + goPrevNext));
}
var SledProgressTrack = function (_a) {
var className = _a.className;
var _b = useStateContext()[0], currentIndex = _b.currentIndex, prevIndex = _b.prevIndex, slideSteps = _b.slideSteps, autoPlayInterval = _b.autoPlayInterval, pause = _b.pause, pauseOnMouseOver = _b.pauseOnMouseOver, config = _b.config;
var _c = useSpring(function () { return ({
from: { x: 100 }
}); }), props = _c[0], set = _c[1];
useEffect(function () {
if (pauseOnMouseOver) {
set({
config: config,
x: getX(slideSteps, currentIndex),
reset: false
});
}
}, [pauseOnMouseOver]);
useEffect(function () {
if (!slideSteps)
return;
var xCalc = getX(slideSteps, currentIndex, !autoPlayInterval && 1);
if (currentIndex === 0) {
set({
config: config,
from: { x: 100 },
x: xCalc,
reset: slideSteps > 2
? prevIndex !== 1
: true
});
}
else {
set({
config: config,
x: xCalc,
reset: false
});
}
}, [slideSteps, currentIndex, autoPlayInterval]);
useEffect(function () {
if (!autoPlayInterval)
return;
set({
config: autoPlayInterval && !pause
? { duration: autoPlayInterval }
: config,
from: { x: getX(slideSteps, currentIndex) },
x: getX(slideSteps, currentIndex, !pause && 1),
reset: true
});
}, [pause, autoPlayInterval, slideSteps, currentIndex]);
return (React.createElement(animated.div, { className: "sled-progress-" + className + "-track", style: {
position: 'absolute',
left: 0,
width: '100%',
pointerEvents: 'none',
transform: props.x.to(function (x) { return "translateX(-" + x + "%)"; })
} }));
};
var SledProgressControls = function (_a) {
var className = _a.className;
var slideSteps = useStateContext()[0].slideSteps;
return (React.createElement("div", { className: "sled-progress-" + className + "-controls" }, __spreadArrays(Array(slideSteps ? slideSteps || 1 : 1)).map(function (view, index) { return (React.createElement(SledControl, { key: index, select: index, className: "sled-progress-" + className + "-control", style: {
flexGrow: 1,
height: '100%',
cursor: 'pointer',
background: 'none',
border: 'none',
outline: 'none',
} })); })));
};
var SledProgress = function (_a) {
var className = _a.className, style = _a.style;
var _b = React.useState(className || ' default'), defaultClass = _b[0], setDefaultClass = _b[1];
React.useEffect(function () {
setDefaultClass(className || 'default');
}, [className]);
return (React.createElement("div", { className: "sled-progress-" + defaultClass, style: style, role: 'progressBar' },
React.createElement("div", { className: "sled-progress-" + defaultClass + "-rail" }),
React.createElement(SledProgressTrack, { className: defaultClass }),
React.createElement(SledProgressSeparators, { className: defaultClass }),
React.createElement(SledProgressControls, { className: defaultClass })));
};
export { SledControl as Control, SledProgress as Progress, Sled, SledViews as Views, useStateContext as useSledStore };
//# sourceMappingURL=index.es.js.map