UNPKG

react-sled

Version:

react-sled is a carousel made with react-spring.

846 lines (799 loc) 35.4 kB
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