UNPKG

react-smooth-carousel-dots

Version:

Custom Carousel Dots component to plug in to any your Carousels.

204 lines (184 loc) 6.27 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } import { useState, useEffect } from "react"; import usePrevious from "./use-previous"; var range = (start, end) => { if (start === 0 && end === 0) return [0]; return Array(end - start + 1).fill().map((_, idx) => start + idx); }; var defaultHolderStyle = { display: "flex", alignItems: "center", overflow: "hidden", transition: "all 0.5s ease" }; var defaultDotsStyle = { flexShrink: 0, transition: "all 0.5s ease" }; var defaultDotStyle = { width: "100%", height: "100%", borderRadius: "50%", backgroundColor: "rgba(255, 255, 255, 0.5)", flexShrink: 0, transition: "transform 0.5s ease, background 0.3s ease-in-out, opacity 0.3s ease-in-out" }; var defaultActiveDotStyle = { backgroundColor: "white" }; var defaultVisibleDotStyle = { opacity: 1 }; var defaultSmallDotStyle = { transform: "scale(0.6667)" }; var defaultMediumDotStyle = { transform: "scale(0.8333)" }; var defaultBigDotStyle = { transform: "scale(1)" }; var useCarouselDots = props => { var { total, current, size = 12, margin = 3, padding = 16, visible = 3 } = props; if (total == null) { throw new Error("'total' cannot be null/undefined"); } if (total <= 0) { throw new Error("'total' cannot be less than or equal to 0"); } if (visible < 3) { throw new Error("'visible' cannot be less than 3"); } var _visible = visible; if (total <= 3) { _visible = total; } if (_visible > 3 && _visible !== total && visible % 2 === 0) { throw new Error("'visible' cannot be an even number"); } if (_visible > total) { throw new Error("'visible' cannot be more than 'total'"); } var prevCurrent = usePrevious(current); var dotFullWidth = size + margin * 2; var center = Math.round(_visible / 2); var centerIndex = Math.floor(_visible / 2); var [translate, setTranslate] = useState(0); var [visibleDots, setVisibleDots] = useState(range(0, _visible - 1)); var [mediumDots, setMediumDots] = useState(range(0, centerIndex + centerIndex - 1)); var [bigDots, setBigDots] = useState(range(0, centerIndex)); var [isLooping, setIsLooping] = useState(false); useEffect(() => { if (current < centerIndex) { setTranslate(0); setVisibleDots(range(0, _visible - 1)); } else if (total - center < current) { setTranslate((total - _visible) * dotFullWidth); setVisibleDots(range(total - _visible, total - 1)); } else { setTranslate((current - centerIndex) * dotFullWidth); setVisibleDots(range(current - centerIndex, current + centerIndex)); } }, [current, center, centerIndex, dotFullWidth, total, _visible]); useEffect(() => { if (current < center) { if (_visible === 3) { setMediumDots(range(0, _visible)); } else { setMediumDots(range(0, centerIndex + centerIndex - 1)); } setBigDots(range(0, centerIndex)); } else if (total - center - 1 < current) { if (_visible === 3) { setMediumDots(range(total - _visible, total - 1)); } else { setMediumDots(range(total - centerIndex - centerIndex, total - 1)); } setBigDots(range(total - center, total - 1)); } else { if (_visible === 3) { setMediumDots(range(current - 1, current + 1)); setBigDots([current]); } else { setMediumDots(range(current - 2, current + 2)); setBigDots(range(current - 1, current + 1)); } } }, [current, center, centerIndex, total, _visible]); useEffect(() => { if (prevCurrent === 0 && current === total - 1 || prevCurrent === total - 1 && current === 0) { setIsLooping(true); setTimeout(() => setIsLooping(false), 300); } }, [current, prevCurrent, total]); var getHolderStyle = { height: size, paddingLeft: padding, paddingRight: padding, width: _visible * dotFullWidth + padding * 2 }; var getDotsStyle = { height: size, width: size, marginRight: margin, marginLeft: margin, transform: "translateX(-" + translate + "px)" }; var getDotStyle = _objectSpread({ opacity: 0 }, isLooping && { opacity: 1, transform: "scale(1)" }); if (total === visible || total <= 3) { return { defaultHolderStyle, getHolderStyle, dots: range(0, total - 1), defaultDotsStyle, getDotsStyle, defaultDotStyle, getDotStyle, defaultVisibleDotStyle, defaultActiveDotStyle, defaultSmallDotStyle, defaultMediumDotStyle, defaultBigDotStyle, isSmall: () => false, isMedium: () => false, isBig: () => true, isActive: dot => current === dot, isVisible: dot => visibleDots.includes(dot) }; } return { defaultHolderStyle, getHolderStyle, dots: range(0, total - 1), defaultDotsStyle, getDotsStyle, defaultDotStyle, getDotStyle, defaultVisibleDotStyle, defaultActiveDotStyle, defaultSmallDotStyle, defaultMediumDotStyle, defaultBigDotStyle, isSmall: dot => !mediumDots.includes(dot), isMedium: dot => mediumDots.includes(dot), isBig: dot => bigDots.includes(dot), isActive: dot => current === dot, isVisible: dot => visibleDots.includes(dot) }; }; export default useCarouselDots; //# sourceMappingURL=use-carousel-dots.js.map