Socket
Socket
Sign inDemoInstall

nuka-carousel

Package Overview
Dependencies
Maintainers
27
Versions
143
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nuka-carousel - npm Package Compare versions

Comparing version 5.3.0 to 5.4.0

es/hooks/use-tween.js

153

es/carousel.js

@@ -76,3 +76,2 @@ "use strict";

disableAnimation = props.disableAnimation,
disableEdgeSwiping = props.disableEdgeSwiping,
desktopDraggingEnabled = props.dragging,

@@ -87,2 +86,3 @@ propsDragThreshold = props.dragThreshold,

onDragStart = props.onDragStart,
onUserNavigation = props.onUserNavigation,
pauseOnHover = props.pauseOnHover,

@@ -94,3 +94,3 @@ renderAnnounceSlideMessage = props.renderAnnounceSlideMessage,

slidesToShow = props.slidesToShow,
propsSpeed = props.speed,
speed = props.speed,
style = props.style,

@@ -115,19 +115,19 @@ mobileDraggingEnabled = props.swiping,

_useState4 = _slicedToArray(_useState3, 2),
isAnimating = _useState4[0],
setIsAnimating = _useState4[1];
pause = _useState4[0],
setPause = _useState4[1];
var _useState5 = (0, _react.useState)(false),
_useState6 = _slicedToArray(_useState5, 2),
pause = _useState6[0],
setPause = _useState6[1];
isDragging = _useState6[0],
setIsDragging = _useState6[1];
var _useState7 = (0, _react.useState)(false),
var _useState7 = (0, _react.useState)(0),
_useState8 = _slicedToArray(_useState7, 2),
isDragging = _useState8[0],
setIsDragging = _useState8[1];
dragDistance = _useState8[0],
setDragDistance = _useState8[1];
var _useState9 = (0, _react.useState)(0),
_useState10 = _slicedToArray(_useState9, 2),
dragDistance = _useState10[0],
setDragDistance = _useState10[1];
animationDistance = _useState10[0],
setAnimationDistance = _useState10[1];

@@ -140,9 +140,15 @@ var prevXPosition = (0, _react.useRef)(null);

var autoplayLastTriggeredRef = (0, _react.useRef)(null);
var animationEndTimeout = (0, _react.useRef)();
var isMounted = (0, _react.useRef)(true);
var setSliderListRef = (0, _react.useCallback)(function (node) {
if (node) {
// disable img draggable attribute by default, this will improve the dragging
// applying the querySelectorAll on just the descendants of the sliderList prevents
// impacting DOM elements outside our scope
node.querySelectorAll('.slider-list img').forEach(function (el) {
return el.setAttribute('draggable', 'false');
});
}
var _getIndexes = (0, _utils.getIndexes)(currentSlide, currentSlide - slidesToScroll, slideCount),
_getIndexes2 = _slicedToArray(_getIndexes, 1),
slide = _getIndexes2[0];
sliderListRef.current = node;
}, []);
(0, _react.useEffect)(function () {

@@ -154,37 +160,46 @@ isMounted.current = true;

}, []);
(0, _react.useEffect)(function () {
// disable img draggable attribute by default, this will improve the dragging
document.querySelectorAll('.slider-list img').forEach(function (el) {
return el.setAttribute('draggable', 'false');
});
}, []);
var carouselRef = innerRef || defaultCarouselRef;
var goToSlide = (0, _react.useCallback)(function (targetSlideIndex) {
// Boil down the target index (-Infinity < targetSlideIndex < Infinity) to
// a user-friendly index (0 ≤ targetSlideIndex < slideCount)
var userFacingIndex = (targetSlideIndex % slideCount + slideCount) % slideCount;
var slideChanged = targetSlideIndex !== currentSlide;
slideChanged && beforeSlide(slide, userFacingIndex); // if animation is disabled decrease the speed to 40
var goToSlide = (0, _react.useCallback)(function (targetSlideUnbounded) {
if (!sliderListRef.current || !carouselRef.current) return;
var targetSlideBounded = (0, _utils.getBoundedIndex)(targetSlideUnbounded, slideCount);
var slideChanged = targetSlideUnbounded !== currentSlide;
slideChanged && beforeSlide(currentSlide, targetSlideBounded); // Calculate the distance the slide transition animation needs to cover.
var msToEndOfAnimation = !disableAnimation ? propsSpeed || 500 : 40;
var currentOffset = sliderListRef.current.getBoundingClientRect().left - carouselRef.current.getBoundingClientRect().left;
var sliderWidth = sliderListRef.current.offsetWidth;
var targetOffset = (0, _sliderList.getPercentOffsetForSlide)(targetSlideBounded, slideCount, slidesToShow, cellAlign, wrapAround) / 100 * sliderWidth;
if (!disableAnimation) {
setIsAnimating(true);
clearTimeout(animationEndTimeout.current);
animationEndTimeout.current = setTimeout(function () {
if (!isMounted.current) return;
setIsAnimating(false);
}, msToEndOfAnimation);
if (wrapAround) {
// We have to do a bit of a recovery effort to figure out the closest
// offset based on the direction we're going in the slides. The reason
// it's complicated is because, when wrapped, both the current offset
// and the calculated target offset are based on bounded slide indices -
// that is, when wrapping, we often skip back to the first or last slide
// seamlessly to make the carousel appear to infinitely repeat
// The DOM width of `slideCount` slides
var slideSetWidth = sliderWidth / 3;
if (targetSlideUnbounded < 0) {
targetOffset += slideSetWidth;
}
if (targetSlideUnbounded >= slideCount) {
targetOffset -= slideSetWidth;
}
}
setAnimationDistance(targetOffset - currentOffset);
if (slideChanged) {
setCurrentSlide(targetSlideIndex);
setCurrentSlide(targetSlideBounded); // if animation is disabled decrease the speed to 40
var msToEndOfAnimation = !disableAnimation ? speed || 500 : 40;
setTimeout(function () {
if (!isMounted.current) return;
afterSlide(userFacingIndex);
afterSlide(targetSlideBounded);
}, msToEndOfAnimation);
}
}, [slide, afterSlide, beforeSlide, slideCount, currentSlide, disableAnimation, propsSpeed]);
}, [afterSlide, beforeSlide, carouselRef, cellAlign, currentSlide, disableAnimation, speed, slideCount, slidesToShow, wrapAround]);
var nextSlide = (0, _react.useCallback)(function () {
var nextSlideIndex = (0, _utils.getNextMoveIndex)(scrollMode, wrapAround, currentSlide, slideCount, propsSlidesToScroll, slidesToShow, cellAlign);
var nextSlideIndex = (0, _utils.getNextMoveIndex)(scrollMode, wrapAround, currentSlide, slideCount, slidesToScroll, slidesToShow, cellAlign);

@@ -194,5 +209,5 @@ if (currentSlide !== nextSlideIndex) {

}
}, [cellAlign, currentSlide, goToSlide, propsSlidesToScroll, scrollMode, slideCount, slidesToShow, wrapAround]);
}, [cellAlign, currentSlide, goToSlide, slidesToScroll, scrollMode, slideCount, slidesToShow, wrapAround]);
var prevSlide = (0, _react.useCallback)(function () {
var prevSlideIndex = (0, _utils.getPrevMoveIndex)(scrollMode, wrapAround, currentSlide, propsSlidesToScroll, slidesToShow, cellAlign);
var prevSlideIndex = (0, _utils.getPrevMoveIndex)(scrollMode, wrapAround, currentSlide, slidesToScroll, slidesToShow, cellAlign);

@@ -202,3 +217,3 @@ if (currentSlide !== prevSlideIndex) {

}
}, [cellAlign, currentSlide, goToSlide, propsSlidesToScroll, scrollMode, slidesToShow, wrapAround]); // When user changed the slideIndex property from outside.
}, [cellAlign, currentSlide, goToSlide, slidesToScroll, scrollMode, slidesToShow, wrapAround]); // When user changed the slideIndex property from outside.

@@ -251,14 +266,4 @@ var prevMovedToSlideIndex = (0, _react.useRef)(slideIndex);

};
}, [pause, autoplay, autoplayInterval, autoplayReverse, prevSlide, nextSlide]); // Makes the carousel infinity when wrapAround is enabled
}, [pause, autoplay, autoplayInterval, autoplayReverse, prevSlide, nextSlide]);
(0, _react.useEffect)(function () {
if (wrapAround && !isAnimating && !isDragging) {
if (currentSlide <= -slidesToShow) {
setCurrentSlide(slideCount - -currentSlide);
} else if (currentSlide >= slideCount) {
setCurrentSlide(currentSlide - slideCount);
}
}
}, [currentSlide, isAnimating, isDragging, slideCount, slidesToShow, wrapAround]);
var onKeyDown = function onKeyDown(event) {

@@ -282,2 +287,3 @@ var keyCommand = null;

case 'nextSlide':
onUserNavigation(event);
nextSlide();

@@ -287,2 +293,3 @@ break;

case 'previousSlide':
onUserNavigation(event);
prevSlide();

@@ -294,2 +301,3 @@ break;

{
onUserNavigation(event);
var dotIndices = (0, _defaultControls.getDotIndexes)(slideCount, slidesToScroll, scrollMode, slidesToShow, wrapAround, cellAlign);

@@ -366,8 +374,12 @@

if (dragDistance > 0) {
nextSlideIndex = (0, _utils.getNextMoveIndex)(scrollMode, wrapAround, nextSlideIndex, slideCount, propsSlidesToScroll, slidesToShow, cellAlign);
nextSlideIndex = (0, _utils.getNextMoveIndex)(scrollMode, wrapAround, nextSlideIndex, slideCount, slidesToScroll, slidesToShow, cellAlign);
} else {
nextSlideIndex = (0, _utils.getPrevMoveIndex)(scrollMode, wrapAround, nextSlideIndex, propsSlidesToScroll, slidesToShow, cellAlign);
nextSlideIndex = (0, _utils.getPrevMoveIndex)(scrollMode, wrapAround, nextSlideIndex, slidesToScroll, slidesToShow, cellAlign);
}
}
if (nextSlideIndex !== currentSlide) {
onUserNavigation(e);
}
goToSlide(nextSlideIndex);

@@ -456,3 +468,2 @@ };

var slides = filteredSlides.map(function (child, index) {
var isCurrentSlide = wrapAround ? currentSlide === index || currentSlide === index + slideCount || currentSlide === index - slideCount : currentSlide === index;
return /*#__PURE__*/_react["default"].createElement(_slide["default"], {

@@ -463,3 +474,3 @@ key: "".concat(typeOfSlide, "-").concat(index),

index: index,
isCurrentSlide: isCurrentSlide,
isCurrentSlide: currentSlide === index,
typeOfSlide: typeOfSlide,

@@ -470,3 +481,3 @@ wrapAround: wrapAround,

slidesToShow: slidesToShow,
speed: propsSpeed,
speed: speed,
zoomScale: zoomScale,

@@ -492,3 +503,3 @@ cellAlign: cellAlign,

message: renderAnnounceSlideMessage({
currentSlide: slide,
currentSlide: currentSlide,
count: slideCount

@@ -520,6 +531,20 @@ })

onTouchMove: onTouchMove
}, /*#__PURE__*/_react["default"].createElement("div", {
className: "slider-list",
style: (0, _sliderList.getSliderListStyles)(slideCount, currentSlide, isAnimating, slidesToShow, cellAlign, wrapAround, propsSpeed, isDragging ? preDragOffset.current - dragDistance : 0, slidesToScroll, scrollMode, disableEdgeSwiping, animation),
ref: sliderListRef
}, /*#__PURE__*/_react["default"].createElement(_sliderList.SliderList, {
animationDistance: animationDistance,
cellAlign: cellAlign,
currentSlide: currentSlide,
disableEdgeSwiping: props.disableEdgeSwiping,
draggedOffset: preDragOffset.current - dragDistance,
disableAnimation: disableAnimation,
easing: props.easing,
edgeEasing: props.edgeEasing,
isDragging: isDragging,
ref: setSliderListRef,
scrollMode: scrollMode,
animation: animation,
slideCount: slideCount,
slidesToScroll: slidesToScroll,
slidesToShow: slidesToShow,
speed: speed,
wrapAround: wrapAround
}, wrapAround ? renderSlides('prev-cloned') : null, renderSlides(), wrapAround ? renderSlides('next-cloned') : null)));

@@ -526,0 +551,0 @@ };

@@ -38,9 +38,45 @@ "use strict";

});
/**
* Mock dimensions for the carousel for calculations where carousel dimensions
* are used, such as with dragging thresholds
*/
var createCarouselRefWithMockedDimensions = function createCarouselRefWithMockedDimensions() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_ref$defaultWidth = _ref.defaultWidth,
defaultWidth = _ref$defaultWidth === void 0 ? 600 : _ref$defaultWidth;
var refValue = null;
var widthGetterMock = jest.fn(function () {
return defaultWidth;
});
var carouselRef = Object.create({}, {
current: {
get: function get() {
return refValue;
},
set: function set(newValue) {
refValue = newValue;
if (refValue) {
Object.defineProperty(refValue, 'offsetWidth', {
get: widthGetterMock
});
}
}
}
});
return {
ref: carouselRef,
widthGetterMock: widthGetterMock
};
};
describe('Carousel', function () {
var renderCarousel = function renderCarousel() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _ref$slideCount = _ref.slideCount,
slideCount = _ref$slideCount === void 0 ? 5 : _ref$slideCount,
props = _objectWithoutProperties(_ref, _excluded);
var _ref2$slideCount = _ref2.slideCount,
slideCount = _ref2$slideCount === void 0 ? 5 : _ref2$slideCount,
props = _objectWithoutProperties(_ref2, _excluded);

@@ -128,6 +164,7 @@ return (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_carousel["default"], props, _toConsumableArray(Array(slideCount)).map(function (_, index) {

};
var slideCount = 8;
renderCarousel({
enableKeyboardControls: true,
keyCodeConfig: keyCodeConfig,
slideCount: 8,
slideCount: slideCount,
beforeSlide: beforeSlide

@@ -166,3 +203,3 @@ });

expect(beforeSlide).toHaveBeenLastCalledWith(0, 7);
expect(beforeSlide).toHaveBeenLastCalledWith(0, slideCount - 1);

@@ -173,4 +210,212 @@ _react2.fireEvent.keyDown(carouselFrame, {

expect(beforeSlide).toHaveBeenLastCalledWith(7, 0);
expect(beforeSlide).toHaveBeenLastCalledWith(slideCount - 1, 0);
});
it('detects user-triggered navigation', function () {
var beforeSlide = jest.fn();
var onUserNavigation = jest.fn();
var keyCodeConfig = {
nextSlide: [39],
previousSlide: [37],
firstSlide: [81],
lastSlide: [69],
pause: [32]
};
var autoplayInterval = 3000;
var slideCount = 8;
renderCarousel({
enableKeyboardControls: true,
autoplay: true,
autoplayInterval: autoplayInterval,
keyCodeConfig: keyCodeConfig,
innerRef: createCarouselRefWithMockedDimensions().ref,
slideCount: slideCount,
beforeSlide: beforeSlide,
onUserNavigation: onUserNavigation
});
expect(onUserNavigation).toHaveBeenCalledTimes(0); // Let enough time pass that autoplay triggers navigation
(0, _react2.act)(function () {
jest.advanceTimersByTime(autoplayInterval);
}); // Make sure the navigation happened, but did not trigger the
// `onUserNavigation` callback (because it wasn't user-initiated)
expect(onUserNavigation).toHaveBeenCalledTimes(0);
expect(beforeSlide).toHaveBeenLastCalledWith(0, 1);
var carouselFrame = _react2.screen.getByRole('region'); // Simulating keyboard shortcut use to navigate
_react2.fireEvent.keyDown(carouselFrame, {
keyCode: keyCodeConfig.nextSlide[0]
});
expect(beforeSlide).toHaveBeenLastCalledWith(1, 2);
expect(onUserNavigation).toHaveBeenCalledTimes(1);
_react2.fireEvent.keyDown(carouselFrame, {
keyCode: keyCodeConfig.previousSlide[0]
});
expect(onUserNavigation).toHaveBeenCalledTimes(2);
_react2.fireEvent.keyDown(carouselFrame, {
keyCode: keyCodeConfig.lastSlide[0]
});
expect(onUserNavigation).toHaveBeenCalledTimes(3);
_react2.fireEvent.keyDown(carouselFrame, {
keyCode: keyCodeConfig.firstSlide[0]
});
expect(onUserNavigation).toHaveBeenCalledTimes(4); // Simulating clicks on default controls to navigate
_react2.fireEvent.click(_react2.screen.getByRole('button', {
name: /next/
}));
expect(onUserNavigation).toHaveBeenCalledTimes(5);
_react2.fireEvent.click(_react2.screen.getByRole('button', {
name: /prev/
}));
expect(onUserNavigation).toHaveBeenCalledTimes(6);
_react2.fireEvent.click(_react2.screen.getByRole('button', {
name: /slide 2/
}));
expect(onUserNavigation).toHaveBeenCalledTimes(7); // Simulating drag to navigate
_react2.fireEvent.mouseDown(carouselFrame, {
clientX: 100
});
_react2.fireEvent.mouseMove(carouselFrame, {
clientX: 100
});
jest.advanceTimersByTime(100);
_react2.fireEvent.mouseMove(carouselFrame, {
clientX: 700
});
_react2.fireEvent.mouseUp(carouselFrame, {
clientX: 700
});
expect(onUserNavigation).toHaveBeenCalledTimes(8); // Simulating swipe to navigate
_react2.fireEvent.touchStart(carouselFrame, {
touches: [{
pageX: 700
}]
});
_react2.fireEvent.touchMove(carouselFrame, {
touches: [{
pageX: 700
}]
});
jest.advanceTimersByTime(100);
_react2.fireEvent.touchMove(carouselFrame, {
touches: [{
pageX: 100
}]
});
_react2.fireEvent.touchEnd(carouselFrame, {
touches: [{
pageX: 100
}]
});
expect(onUserNavigation).toHaveBeenCalledTimes(9); // Should not be triggering navigation callback when dragging didn't trigger navigation
_react2.fireEvent.mouseDown(carouselFrame, {
clientX: 100
});
_react2.fireEvent.mouseMove(carouselFrame, {
clientX: 100
});
jest.advanceTimersByTime(10);
_react2.fireEvent.mouseMove(carouselFrame, {
clientX: 105
});
_react2.fireEvent.mouseUp(carouselFrame, {
clientX: 105
});
expect(onUserNavigation).toHaveBeenCalledTimes(9);
});
it('calls default control callbacks when interacted with', function () {
var beforeSlide = jest.fn();
var nextButtonOnClick = jest.fn();
var prevButtonOnClick = jest.fn();
var pagingDotsOnClick = jest.fn();
var slideCount = 8;
renderCarousel({
slideCount: slideCount,
beforeSlide: beforeSlide,
defaultControlsConfig: {
nextButtonOnClick: nextButtonOnClick,
prevButtonOnClick: prevButtonOnClick,
pagingDotsOnClick: pagingDotsOnClick
}
}); // Simulating clicks on default controls to navigate
expect(nextButtonOnClick).toHaveBeenCalledTimes(0);
_react2.fireEvent.click(_react2.screen.getByRole('button', {
name: /next/
}));
expect(nextButtonOnClick).toHaveBeenCalledTimes(1);
expect(prevButtonOnClick).toHaveBeenCalledTimes(0);
_react2.fireEvent.click(_react2.screen.getByRole('button', {
name: /prev/
}));
expect(prevButtonOnClick).toHaveBeenCalledTimes(1);
expect(pagingDotsOnClick).toHaveBeenCalledTimes(0);
_react2.fireEvent.click(_react2.screen.getByRole('button', {
name: /slide 2/
}));
expect(pagingDotsOnClick).toHaveBeenCalledTimes(1); // Check that calling preventDefault in the custom callback will stop the
// default behavior (navigation) before it happens
var preventDefault = function preventDefault(event) {
return event.preventDefault();
};
nextButtonOnClick.mockImplementation(preventDefault);
prevButtonOnClick.mockImplementation(preventDefault);
pagingDotsOnClick.mockImplementation(preventDefault);
expect(beforeSlide).toHaveBeenCalledTimes(3);
_react2.fireEvent.click(_react2.screen.getByRole('button', {
name: /next/
}));
_react2.fireEvent.click(_react2.screen.getByRole('button', {
name: /prev/
}));
_react2.fireEvent.click(_react2.screen.getByRole('button', {
name: /slide 2/
}));
expect(beforeSlide).toHaveBeenCalledTimes(3);
});
});

@@ -14,2 +14,4 @@ "use strict";

var _defaultControls = require("./default-controls");
var _types = require("./types");

@@ -61,2 +63,10 @@

var disableCheckProps = _objectSpread(_objectSpread({}, props), {}, {
currentSlide: currentSlide,
slideCount: slideCount
});
var nextDisabled = (0, _defaultControls.nextButtonDisabled)(disableCheckProps);
var previousDisabled = (0, _defaultControls.prevButtonDisabled)(disableCheckProps);
var pagingDotsIndices = (0, _defaultControls.getDotIndexes)(slideCount, slidesToScroll, props.scrollMode, props.slidesToShow, props.wrapAround, props.cellAlign);
return controlsMap.map(function (control) {

@@ -88,4 +98,8 @@ var _props$control$funcNa;

defaultControlsConfig: props.defaultControlsConfig || {},
pagingDotsIndices: pagingDotsIndices,
goToSlide: goToSlide,
nextDisabled: nextDisabled,
nextSlide: nextSlide,
onUserNavigation: props.onUserNavigation,
previousDisabled: previousDisabled,
previousSlide: prevSlide,

@@ -92,0 +106,0 @@ scrollMode: props.scrollMode,

@@ -18,2 +18,6 @@ "use strict";

var easeOut = function easeOut(t) {
return Math.pow(t - 1, 3) + 1;
};
var defaultProps = {

@@ -36,4 +40,4 @@ adaptiveHeight: false,

dragThreshold: 0.5,
easing: _types.D3EasingFunctions.EaseCircleOut,
edgeEasing: _types.D3EasingFunctions.EaseElasticOut,
easing: easeOut,
edgeEasing: easeOut,
enableKeyboardControls: false,

@@ -54,2 +58,4 @@ frameAriaLabel: 'carousel-slider',

},
onUserNavigation: function onUserNavigation() {// do nothing
},
pauseOnHover: true,

@@ -56,0 +62,0 @@ renderAnnounceSlideMessage: _announceSlide.defaultRenderAnnounceSlideMessage,

@@ -14,2 +14,4 @@ "use strict";

var _utils = require("./utils");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

@@ -38,6 +40,6 @@

var prevButtonDisabled = function prevButtonDisabled(_ref) {
var currentSlide = _ref.currentSlide,
wrapAround = _ref.wrapAround,
cellAlign = _ref.cellAlign,
slidesToShow = _ref.slidesToShow;
var cellAlign = _ref.cellAlign,
currentSlide = _ref.currentSlide,
slidesToShow = _ref.slidesToShow,
wrapAround = _ref.wrapAround;

@@ -64,15 +66,21 @@ // inifite carousel

var PreviousButton = function PreviousButton(props) {
var PreviousButton = function PreviousButton(_ref2) {
var previousSlide = _ref2.previousSlide,
_ref2$defaultControls = _ref2.defaultControlsConfig,
prevButtonClassName = _ref2$defaultControls.prevButtonClassName,
_ref2$defaultControls2 = _ref2$defaultControls.prevButtonStyle,
prevButtonStyle = _ref2$defaultControls2 === void 0 ? {} : _ref2$defaultControls2,
prevButtonText = _ref2$defaultControls.prevButtonText,
prevButtonOnClick = _ref2$defaultControls.prevButtonOnClick,
onUserNavigation = _ref2.onUserNavigation,
disabled = _ref2.previousDisabled;
var handleClick = function handleClick(event) {
prevButtonOnClick === null || prevButtonOnClick === void 0 ? void 0 : prevButtonOnClick(event);
if (event.defaultPrevented) return;
onUserNavigation(event);
event.preventDefault();
props === null || props === void 0 ? void 0 : props.previousSlide();
previousSlide();
};
var _ref2 = props.defaultControlsConfig || {},
prevButtonClassName = _ref2.prevButtonClassName,
_ref2$prevButtonStyle = _ref2.prevButtonStyle,
prevButtonStyle = _ref2$prevButtonStyle === void 0 ? {} : _ref2$prevButtonStyle,
prevButtonText = _ref2.prevButtonText;
var disabled = prevButtonDisabled(props);
return /*#__PURE__*/_react["default"].createElement("button", {

@@ -91,7 +99,7 @@ className: prevButtonClassName,

var nextButtonDisabled = function nextButtonDisabled(_ref3) {
var currentSlide = _ref3.currentSlide,
var cellAlign = _ref3.cellAlign,
currentSlide = _ref3.currentSlide,
slideCount = _ref3.slideCount,
slidesToShow = _ref3.slidesToShow,
wrapAround = _ref3.wrapAround,
cellAlign = _ref3.cellAlign;
wrapAround = _ref3.wrapAround;

@@ -118,14 +126,21 @@ // inifite carousel

var NextButton = function NextButton(props) {
var NextButton = function NextButton(_ref4) {
var nextSlide = _ref4.nextSlide,
_ref4$defaultControls = _ref4.defaultControlsConfig,
nextButtonClassName = _ref4$defaultControls.nextButtonClassName,
_ref4$defaultControls2 = _ref4$defaultControls.nextButtonStyle,
nextButtonStyle = _ref4$defaultControls2 === void 0 ? {} : _ref4$defaultControls2,
nextButtonText = _ref4$defaultControls.nextButtonText,
nextButtonOnClick = _ref4$defaultControls.nextButtonOnClick,
disabled = _ref4.nextDisabled,
onUserNavigation = _ref4.onUserNavigation;
var handleClick = function handleClick(event) {
nextButtonOnClick === null || nextButtonOnClick === void 0 ? void 0 : nextButtonOnClick(event);
if (event.defaultPrevented) return;
onUserNavigation(event);
event.preventDefault();
props.nextSlide();
nextSlide();
};
var defaultControlsConfig = props.defaultControlsConfig;
var nextButtonClassName = defaultControlsConfig.nextButtonClassName,
_defaultControlsConfi = defaultControlsConfig.nextButtonStyle,
nextButtonStyle = _defaultControlsConfi === void 0 ? {} : _defaultControlsConfi,
nextButtonText = defaultControlsConfig.nextButtonText;
var disabled = nextButtonDisabled(props);
return /*#__PURE__*/_react["default"].createElement("button", {

@@ -223,3 +238,14 @@ className: nextButtonClassName,

var PagingDots = function PagingDots(props) {
var PagingDots = function PagingDots(_ref5) {
var pagingDotsIndices = _ref5.pagingDotsIndices,
_ref5$defaultControls = _ref5.defaultControlsConfig,
pagingDotsContainerClassName = _ref5$defaultControls.pagingDotsContainerClassName,
pagingDotsClassName = _ref5$defaultControls.pagingDotsClassName,
_ref5$defaultControls2 = _ref5$defaultControls.pagingDotsStyle,
pagingDotsStyle = _ref5$defaultControls2 === void 0 ? {} : _ref5$defaultControls2,
pagingDotsOnClick = _ref5$defaultControls.pagingDotsOnClick,
currentSlide = _ref5.currentSlide,
onUserNavigation = _ref5.onUserNavigation,
slideCount = _ref5.slideCount,
goToSlide = _ref5.goToSlide;
var listStyles = {

@@ -242,20 +268,11 @@ position: 'relative',

}, []);
var indexes = getDotIndexes(props.slideCount, props.slidesToScroll, props.scrollMode, props.slidesToShow, props.wrapAround, props.cellAlign);
var _props$defaultControl = props.defaultControlsConfig,
pagingDotsContainerClassName = _props$defaultControl.pagingDotsContainerClassName,
pagingDotsClassName = _props$defaultControl.pagingDotsClassName,
_props$defaultControl2 = _props$defaultControl.pagingDotsStyle,
pagingDotsStyle = _props$defaultControl2 === void 0 ? {} : _props$defaultControl2;
var currentSlideBounded = (0, _utils.getBoundedIndex)(currentSlide, slideCount);
return /*#__PURE__*/_react["default"].createElement("ul", {
className: pagingDotsContainerClassName,
style: listStyles
}, indexes.map(function (index, i) {
var isActive = props.currentSlide === index || props.currentSlide - props.slideCount === index || props.currentSlide + props.slideCount === index; // the below condition checks and sets navigation dots active if the current slide falls in the current index range
if (props.currentSlide < index && props.currentSlide > indexes[i - 1]) {
isActive = true;
}
}, pagingDotsIndices.map(function (slideIndex, i) {
var isActive = currentSlideBounded === slideIndex || // sets navigation dots active if the current slide falls in the current index range
currentSlideBounded < slideIndex && (i === 0 || currentSlideBounded > pagingDotsIndices[i - 1]);
return /*#__PURE__*/_react["default"].createElement("li", {
key: index,
key: slideIndex,
className: isActive ? 'paging-item active' : 'paging-item'

@@ -266,4 +283,9 @@ }, /*#__PURE__*/_react["default"].createElement("button", {

style: _objectSpread(_objectSpread({}, getButtonStyles(isActive)), pagingDotsStyle),
onClick: props.goToSlide.bind(null, index),
"aria-label": "slide ".concat(index + 1, " bullet"),
onClick: function onClick(event) {
pagingDotsOnClick === null || pagingDotsOnClick === void 0 ? void 0 : pagingDotsOnClick(event);
if (event.defaultPrevented) return;
onUserNavigation(event);
goToSlide(slideIndex);
},
"aria-label": "slide ".concat(slideIndex + 1, " bullet"),
"aria-selected": isActive

@@ -275,3 +297,4 @@ }, /*#__PURE__*/_react["default"].createElement("svg", {

"aria-hidden": "true",
focusable: "false"
focusable: "false",
viewBox: "0 0 6 6"
}, /*#__PURE__*/_react["default"].createElement("circle", {

@@ -278,0 +301,0 @@ cx: "3",

@@ -6,70 +6,25 @@ "use strict";

});
exports.getSliderListStyles = void 0;
exports.getPercentOffsetForSlide = exports.SliderList = void 0;
var _react = _interopRequireDefault(require("react"));
var _defaultControls = require("./default-controls");
var _useTween2 = require("./hooks/use-tween");
var _types = require("./types");
var getSliderListWidth = function getSliderListWidth(slideCount, slidesToShow, wrapAround) {
var visibleSlides = slidesToShow;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
if (wrapAround) {
var _percentage = slideCount * 100 / visibleSlides;
var getPercentOffsetForSlide = function getPercentOffsetForSlide(currentSlide, slideCount, slidesToShow, cellAlign, wrapAround) {
// When wrapAround is enabled, we show the slides 3 times
var renderedSlideCount = wrapAround ? 3 * slideCount : slideCount;
var singleSlidePercentOfWhole = 100 / renderedSlideCount; // When wrap is on, -33.33% puts us right on the center, true set of slides
// (the left and right sets are clones meant to avoid visual gaps)
return "".concat(3 * _percentage, "%");
}
var slide0Offset = wrapAround ? -100 / 3 : 0;
var percentage = slideCount * 100 / visibleSlides;
return "".concat(percentage, "%");
};
var getPercentOffsetForSlide = function getPercentOffsetForSlide(slideCount, initialValue, currentSlide, cellAlign, wrapAround) {
if (cellAlign === _types.Alignment.Left) {
if (wrapAround) {
var _slideTransition = 100 / (3 * slideCount);
var currentTransition = initialValue - _slideTransition * (currentSlide - 1);
return currentTransition - _slideTransition;
}
var slideTransition = 100 / slideCount * currentSlide;
return -(slideTransition + initialValue);
} else if (cellAlign === _types.Alignment.Center) {
if (wrapAround) {
var _slideTransition3 = 100 / (3 * slideCount);
var _currentTransition = initialValue - _slideTransition3 * (currentSlide - 1);
return _currentTransition - _slideTransition3;
}
var _slideTransition2 = 100 / slideCount * currentSlide;
return initialValue - _slideTransition2;
} else if (cellAlign === _types.Alignment.Right) {
if (wrapAround) {
var _slideTransition5 = 100 / (3 * slideCount);
var _currentTransition2 = initialValue - _slideTransition5 * (currentSlide - 1);
return _currentTransition2 - _slideTransition5;
}
var _slideTransition4 = 100 / slideCount * currentSlide;
return initialValue - _slideTransition4;
}
return initialValue;
};
var getPositioning = function getPositioning(cellAlign, slidesToShow, slideCount, currentSlide, wrapAround, draggedOffset, clampIndices) {
// When wrapAround is enabled, we show the slides 3 times
var totalCount = wrapAround ? 3 * slideCount : slideCount;
var slideSize = 100 / totalCount;
var initialValue = wrapAround ? -slideCount * slideSize : 0;
if (cellAlign === _types.Alignment.Right && slidesToShow > 1) {
var excessSlides = slidesToShow - 1;
initialValue += slideSize * excessSlides;
slide0Offset += singleSlidePercentOfWhole * excessSlides;
}

@@ -82,49 +37,86 @@

var excessLeftSlides = _excessSlides / 2;
initialValue += slideSize * excessLeftSlides;
slide0Offset += singleSlidePercentOfWhole * excessLeftSlides;
}
var slideBasedOffset = getPercentOffsetForSlide(slideCount, initialValue, currentSlide, cellAlign, wrapAround); // Special-case this. It's better to return undefined rather than a
// transform of 0 pixels since transforms can cause flickering in chrome.
var currentSlideOffsetFrom0 = 100 / renderedSlideCount * currentSlide;
return slide0Offset - currentSlideOffsetFrom0;
};
if (draggedOffset === 0 && slideBasedOffset === 0) {
return undefined;
}
exports.getPercentOffsetForSlide = getPercentOffsetForSlide;
var clampOffsets = null;
var SliderList = /*#__PURE__*/_react["default"].forwardRef(function (_ref, forwardedRef) {
var animation = _ref.animation,
animationDistance = _ref.animationDistance,
cellAlign = _ref.cellAlign,
children = _ref.children,
currentSlide = _ref.currentSlide,
disableAnimation = _ref.disableAnimation,
disableEdgeSwiping = _ref.disableEdgeSwiping,
draggedOffset = _ref.draggedOffset,
easing = _ref.easing,
edgeEasing = _ref.edgeEasing,
isDragging = _ref.isDragging,
scrollMode = _ref.scrollMode,
slideCount = _ref.slideCount,
slidesToScroll = _ref.slidesToScroll,
slidesToShow = _ref.slidesToShow,
speed = _ref.speed,
wrapAround = _ref.wrapAround;
// When wrapAround is enabled, we show the slides 3 times
var renderedSlideCount = wrapAround ? 3 * slideCount : slideCount;
var listVisibleWidth = "".concat(renderedSlideCount * 100 / slidesToShow, "%");
var percentOffsetForSlideProps = [slideCount, slidesToShow, cellAlign, wrapAround]; // We recycle dot index generation to determine the leftmost and rightmost
// indices used, to be used in calculating the x-translation values we need
// to limit to or when edgeEasing should be used.
if (clampIndices) {
clampOffsets = clampIndices.map(function (index) {
return getPercentOffsetForSlide(slideCount, initialValue, index, cellAlign, wrapAround);
});
var dotIndexes = (0, _defaultControls.getDotIndexes)(slideCount, slidesToScroll, scrollMode, slidesToShow, wrapAround, cellAlign);
var clampedDraggedOffset = "".concat(draggedOffset, "px");
if (isDragging && disableEdgeSwiping && !wrapAround) {
var clampOffsets = [dotIndexes[0], dotIndexes[dotIndexes.length - 1]].map(function (index) {
return getPercentOffsetForSlide.apply(void 0, [index].concat(percentOffsetForSlideProps));
}); // Offsets are seemingly backwards because the rightmost slide creates
// the most negative translate value
clampedDraggedOffset = "clamp(".concat(clampOffsets[1], "%, ").concat(draggedOffset, "px, ").concat(clampOffsets[0], "%)");
}
var clampedDraggedOffset = clampOffsets ? // Offsets are seemingly backwards because the rightmost slide creates
// the most negative translate value
"clamp(".concat(clampOffsets[1], "%, ").concat(draggedOffset, "px, ").concat(clampOffsets[0], "%)") : "".concat(draggedOffset, "px");
return "translate3d(".concat(draggedOffset ? clampedDraggedOffset : "".concat(slideBasedOffset, "%"), ", 0, 0)");
};
var slideBasedOffset = getPercentOffsetForSlide.apply(void 0, [currentSlide].concat(percentOffsetForSlideProps));
var isEdgeEasing = !disableEdgeSwiping && !wrapAround && (currentSlide === dotIndexes[0] && animationDistance < 0 || currentSlide === dotIndexes[dotIndexes.length - 1] && animationDistance > 0);
var getSliderListStyles = function getSliderListStyles(slideCount, currentSlide, isAnimating, slidesToShow, cellAlign, wrapAround, speed, draggedOffset, slidesToScroll, scrollMode, disableEdgeSwiping, slideAnimation) {
var width = getSliderListWidth(slideCount, slidesToShow, wrapAround); // When disableEdgeSwiping=true, we recycle dot index generation to determine
// the leftmost and rightmost indices used, to be used in calculating the
// x-translation values we need to limit to.
var _useTween = (0, _useTween2.useTween)(speed, !isEdgeEasing ? easing : edgeEasing, // animationDistance is assumed to be unique enough that it can be used to
// detect when a new animation should start. This is used in addition to
// currentSlide because some animations, such as those with edgeEasing, do
// not occur due to a change in value of currentSlide
currentSlide + animationDistance, isDragging || disableAnimation || animation === 'fade'),
transition = _useTween.value,
isAnimating = _useTween.isAnimating; // Return undefined if the transform would be 0 pixels since transforms can
// cause flickering in chrome.
var clampIndices = null;
if (disableEdgeSwiping && !wrapAround) {
var dotIndexes = (0, _defaultControls.getDotIndexes)(slideCount, slidesToScroll, scrollMode, slidesToShow, wrapAround, cellAlign);
clampIndices = [dotIndexes[0], dotIndexes[dotIndexes.length - 1]];
var positioning;
if (isDragging || slideBasedOffset !== 0 || isAnimating) {
if (isDragging) {
positioning = "translateX(".concat(clampedDraggedOffset, ")");
} else {
var transitionOffset = isAnimating ? (1 - transition) * animationDistance : 0;
positioning = "translateX(calc(".concat(slideBasedOffset, "% - ").concat(transitionOffset, "px))");
}
}
var positioning = getPositioning(cellAlign, slidesToShow, slideCount, currentSlide, wrapAround, draggedOffset, clampIndices);
return {
width: width,
textAlign: 'left',
userSelect: 'auto',
transition: draggedOffset === 0 && isAnimating && slideAnimation !== 'fade' ? "".concat(speed, "ms cubic-bezier(0.16, 1, 0.3, 1) 0s") : undefined,
transform: positioning,
display: 'flex'
};
};
return /*#__PURE__*/_react["default"].createElement("div", {
ref: forwardedRef,
className: "slider-list",
style: {
width: listVisibleWidth,
textAlign: 'left',
userSelect: 'auto',
transform: positioning,
display: 'flex'
}
}, children);
});
exports.getSliderListStyles = getSliderListStyles;
exports.SliderList = SliderList;
SliderList.displayName = 'SliderList';

@@ -6,3 +6,3 @@ "use strict";

});
exports.ScrollMode = exports.Positions = exports.Directions = exports.D3EasingFunctions = exports.Alignment = void 0;
exports.ScrollMode = exports.Positions = exports.Directions = exports.Alignment = void 0;

@@ -50,45 +50,2 @@ /* eslint-disable no-shadow */

ScrollMode["remainder"] = "remainder";
})(ScrollMode || (exports.ScrollMode = ScrollMode = {}));
var D3EasingFunctions;
exports.D3EasingFunctions = D3EasingFunctions;
(function (D3EasingFunctions) {
D3EasingFunctions["EaseLinear"] = "easeLinear";
D3EasingFunctions["EaseQuad"] = "easeQuad";
D3EasingFunctions["EaseQuadIn"] = "easeQuadIn";
D3EasingFunctions["EaseQuadOut"] = "easeQuadOut";
D3EasingFunctions["EaseQuadInOut"] = "easeQuadInOut";
D3EasingFunctions["EaseCubic"] = "easeCubic";
D3EasingFunctions["EaseCubicIn"] = "easeCubicIn";
D3EasingFunctions["EaseCubicOut"] = "easeCubicOut";
D3EasingFunctions["EaseCubicInOut"] = "easeCubicInOut";
D3EasingFunctions["EasePoly"] = "easePoly";
D3EasingFunctions["EasePolyIn"] = "easePolyIn";
D3EasingFunctions["EasePolyOut"] = "easePolyOut";
D3EasingFunctions["EasePolyInOut"] = "easePolyInOut";
D3EasingFunctions["EaseSin"] = "easeSin";
D3EasingFunctions["EaseSinIn"] = "easeSinIn";
D3EasingFunctions["EaseSinOut"] = "easeSinOut";
D3EasingFunctions["EaseSinInOut"] = "easeSinInOut";
D3EasingFunctions["EaseExp"] = "easeExp";
D3EasingFunctions["EaseExpIn"] = "easeExpIn";
D3EasingFunctions["EaseExpOut"] = "easeExpOut";
D3EasingFunctions["EaseExpInOut"] = "easeExpInOut";
D3EasingFunctions["EaseCircle"] = "easeCircle";
D3EasingFunctions["EaseCircleIn"] = "easeCircleIn";
D3EasingFunctions["EaseCircleOut"] = "easeCircleOut";
D3EasingFunctions["EaseCircleInOut"] = "easeCircleInOut";
D3EasingFunctions["EaseBack"] = "easeBack";
D3EasingFunctions["EaseBackIn"] = "easeBackIn";
D3EasingFunctions["EaseBackOut"] = "easeBackOut";
D3EasingFunctions["EaseBackInOut"] = "easeBackInOut";
D3EasingFunctions["EaseBounce"] = "easeBounce";
D3EasingFunctions["EaseBounceIn"] = "easeBounceIn";
D3EasingFunctions["EaseBounceOut"] = "easeBounceOut";
D3EasingFunctions["EaseBounceInOut"] = "easeBounceInOut";
D3EasingFunctions["EaseElastic"] = "easeElastic";
D3EasingFunctions["EaseElasticIn"] = "easeElasticIn";
D3EasingFunctions["EaseElasticOut"] = "easeElasticOut";
D3EasingFunctions["EaseElasticInOut"] = "easeElasticInOut";
})(D3EasingFunctions || (exports.D3EasingFunctions = D3EasingFunctions = {}));
})(ScrollMode || (exports.ScrollMode = ScrollMode = {}));

@@ -6,3 +6,3 @@ "use strict";

});
exports.isSlideVisible = exports.getPrevMoveIndex = exports.getNextMoveIndex = exports.getIndexes = exports.getDefaultSlideIndex = void 0;
exports.isSlideVisible = exports.getPrevMoveIndex = exports.getNextMoveIndex = exports.getDefaultSlideIndex = exports.getBoundedIndex = void 0;

@@ -13,23 +13,2 @@ var _defaultControls = require("./default-controls");

var getIndexes = function getIndexes(slide, endSlide, slideCount) {
var slideIndex = slide;
var endSlideIndex = endSlide;
if (slideIndex < 0) {
slideIndex += slideCount;
} else if (slideIndex > slideCount - 1) {
slideIndex -= slideCount;
}
if (endSlideIndex < 0) {
endSlideIndex += slideCount;
} else if (endSlideIndex > slideCount - 1) {
endSlideIndex -= slideCount;
}
return [slideIndex, endSlideIndex];
};
exports.getIndexes = getIndexes;
var isSlideVisible = function isSlideVisible(currentSlide, indexToCheck, slidesToShow, cellAlign) {

@@ -106,3 +85,14 @@ // The addition or subtraction of constants (1 , 0.5) in the following

};
/**
* Boils down an unbounded index (-Infinity < index < Infinity) to a bounded one
* (0 ≤ index < slideCount)
*/
exports.getDefaultSlideIndex = getDefaultSlideIndex;
exports.getDefaultSlideIndex = getDefaultSlideIndex;
var getBoundedIndex = function getBoundedIndex(rawIndex, slideCount) {
return (rawIndex % slideCount + slideCount) % slideCount;
};
exports.getBoundedIndex = getBoundedIndex;

@@ -7,3 +7,3 @@ "use strict";

var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8, _templateObject9;
var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8, _templateObject9, _templateObject10;

@@ -86,2 +86,10 @@ function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }

});
});
describe('getBoundedIndex', function () {
it.each(_templateObject10 || (_templateObject10 = _taggedTemplateLiteral(["\n rawIndex | slideCount | expected\n ", " | ", " | ", "\n ", " | ", " | ", "\n ", " | ", " | ", "\n ", " | ", " | ", "\n ", " | ", " | ", "\n ", " | ", " | ", "\n ", " | ", " | ", "\n ", " | ", " | ", "\n ", " | ", " | ", "\n ", " | ", " | ", "\n ", " | ", " | ", "\n ", " | ", " | ", "\n "])), 0, 1, 0, 1, 2, 1, 2, 2, 0, 3, 2, 1, 4, 2, 0, -1, 2, 1, -2, 2, 0, -2, 3, 1, -3, 3, 0, -6, 3, 0, -7, 3, 2, -7.5, 3, 1.5)('gets the right index when bounds applied ' + '(rawIndex $rawIndex, slideCount $slideCount)', function (_ref10) {
var rawIndex = _ref10.rawIndex,
slideCount = _ref10.slideCount,
expected = _ref10.expected;
expect((0, _utils.getBoundedIndex)(rawIndex, slideCount)).toEqual(expected);
});
});

@@ -51,3 +51,3 @@ "use strict";

const props = rawProps;
const { adaptiveHeight, adaptiveHeightAnimation, afterSlide, animation, autoplay, autoplayInterval, autoplayReverse, beforeSlide, cellAlign, cellSpacing, children, className, disableAnimation, disableEdgeSwiping, dragging: desktopDraggingEnabled, dragThreshold: propsDragThreshold, enableKeyboardControls, frameAriaLabel, innerRef, keyCodeConfig, onDrag, onDragEnd, onDragStart, pauseOnHover, renderAnnounceSlideMessage, scrollMode, slideIndex, slidesToScroll: propsSlidesToScroll, slidesToShow, speed: propsSpeed, style, swiping: mobileDraggingEnabled, wrapAround, zoomScale, } = props;
const { adaptiveHeight, adaptiveHeightAnimation, afterSlide, animation, autoplay, autoplayInterval, autoplayReverse, beforeSlide, cellAlign, cellSpacing, children, className, disableAnimation, dragging: desktopDraggingEnabled, dragThreshold: propsDragThreshold, enableKeyboardControls, frameAriaLabel, innerRef, keyCodeConfig, onDrag, onDragEnd, onDragStart, onUserNavigation, pauseOnHover, renderAnnounceSlideMessage, scrollMode, slideIndex, slidesToScroll: propsSlidesToScroll, slidesToShow, speed, style, swiping: mobileDraggingEnabled, wrapAround, zoomScale, } = props;
const filteredSlides = react_1.default.Children.toArray(children).filter(Boolean);

@@ -57,6 +57,6 @@ const slideCount = filteredSlides.length;

const [currentSlide, setCurrentSlide] = (0, react_1.useState)(() => (0, utils_1.getDefaultSlideIndex)(slideIndex, slideCount, slidesToShow, slidesToScroll, cellAlign, autoplayReverse, scrollMode));
const [isAnimating, setIsAnimating] = (0, react_1.useState)(false);
const [pause, setPause] = (0, react_1.useState)(false);
const [isDragging, setIsDragging] = (0, react_1.useState)(false);
const [dragDistance, setDragDistance] = (0, react_1.useState)(0);
const [animationDistance, setAnimationDistance] = (0, react_1.useState)(0);
const prevXPosition = (0, react_1.useRef)(null);

@@ -68,5 +68,14 @@ const preDragOffset = (0, react_1.useRef)(0);

const autoplayLastTriggeredRef = (0, react_1.useRef)(null);
const animationEndTimeout = (0, react_1.useRef)();
const isMounted = (0, react_1.useRef)(true);
const [slide] = (0, utils_1.getIndexes)(currentSlide, currentSlide - slidesToScroll, slideCount);
const setSliderListRef = (0, react_1.useCallback)((node) => {
if (node) {
// disable img draggable attribute by default, this will improve the dragging
// applying the querySelectorAll on just the descendants of the sliderList prevents
// impacting DOM elements outside our scope
node
.querySelectorAll('.slider-list img')
.forEach((el) => el.setAttribute('draggable', 'false'));
}
sliderListRef.current = node;
}, []);
(0, react_1.useEffect)(() => {

@@ -78,45 +87,57 @@ isMounted.current = true;

}, []);
(0, react_1.useEffect)(() => {
// disable img draggable attribute by default, this will improve the dragging
document
.querySelectorAll('.slider-list img')
.forEach((el) => el.setAttribute('draggable', 'false'));
}, []);
const carouselRef = innerRef || defaultCarouselRef;
const goToSlide = (0, react_1.useCallback)((targetSlideIndex) => {
// Boil down the target index (-Infinity < targetSlideIndex < Infinity) to
// a user-friendly index (0 ≤ targetSlideIndex < slideCount)
const userFacingIndex = ((targetSlideIndex % slideCount) + slideCount) % slideCount;
const slideChanged = targetSlideIndex !== currentSlide;
slideChanged && beforeSlide(slide, userFacingIndex);
// if animation is disabled decrease the speed to 40
const msToEndOfAnimation = !disableAnimation ? propsSpeed || 500 : 40;
if (!disableAnimation) {
setIsAnimating(true);
clearTimeout(animationEndTimeout.current);
animationEndTimeout.current = setTimeout(() => {
if (!isMounted.current)
return;
setIsAnimating(false);
}, msToEndOfAnimation);
const goToSlide = (0, react_1.useCallback)((targetSlideUnbounded) => {
if (!sliderListRef.current || !carouselRef.current)
return;
const targetSlideBounded = (0, utils_1.getBoundedIndex)(targetSlideUnbounded, slideCount);
const slideChanged = targetSlideUnbounded !== currentSlide;
slideChanged && beforeSlide(currentSlide, targetSlideBounded);
// Calculate the distance the slide transition animation needs to cover.
const currentOffset = sliderListRef.current.getBoundingClientRect().left -
carouselRef.current.getBoundingClientRect().left;
const sliderWidth = sliderListRef.current.offsetWidth;
let targetOffset = ((0, slider_list_1.getPercentOffsetForSlide)(targetSlideBounded, slideCount, slidesToShow, cellAlign, wrapAround) /
100) *
sliderWidth;
if (wrapAround) {
// We have to do a bit of a recovery effort to figure out the closest
// offset based on the direction we're going in the slides. The reason
// it's complicated is because, when wrapped, both the current offset
// and the calculated target offset are based on bounded slide indices -
// that is, when wrapping, we often skip back to the first or last slide
// seamlessly to make the carousel appear to infinitely repeat
// The DOM width of `slideCount` slides
const slideSetWidth = sliderWidth / 3;
if (targetSlideUnbounded < 0) {
targetOffset += slideSetWidth;
}
if (targetSlideUnbounded >= slideCount) {
targetOffset -= slideSetWidth;
}
}
setAnimationDistance(targetOffset - currentOffset);
if (slideChanged) {
setCurrentSlide(targetSlideIndex);
setCurrentSlide(targetSlideBounded);
// if animation is disabled decrease the speed to 40
const msToEndOfAnimation = !disableAnimation ? speed || 500 : 40;
setTimeout(() => {
if (!isMounted.current)
return;
afterSlide(userFacingIndex);
afterSlide(targetSlideBounded);
}, msToEndOfAnimation);
}
}, [
slide,
afterSlide,
beforeSlide,
slideCount,
carouselRef,
cellAlign,
currentSlide,
disableAnimation,
propsSpeed,
speed,
slideCount,
slidesToShow,
wrapAround,
]);
const nextSlide = (0, react_1.useCallback)(() => {
const nextSlideIndex = (0, utils_1.getNextMoveIndex)(scrollMode, wrapAround, currentSlide, slideCount, propsSlidesToScroll, slidesToShow, cellAlign);
const nextSlideIndex = (0, utils_1.getNextMoveIndex)(scrollMode, wrapAround, currentSlide, slideCount, slidesToScroll, slidesToShow, cellAlign);
if (currentSlide !== nextSlideIndex) {

@@ -129,3 +150,3 @@ goToSlide(nextSlideIndex);

goToSlide,
propsSlidesToScroll,
slidesToScroll,
scrollMode,

@@ -137,3 +158,3 @@ slideCount,

const prevSlide = (0, react_1.useCallback)(() => {
const prevSlideIndex = (0, utils_1.getPrevMoveIndex)(scrollMode, wrapAround, currentSlide, propsSlidesToScroll, slidesToShow, cellAlign);
const prevSlideIndex = (0, utils_1.getPrevMoveIndex)(scrollMode, wrapAround, currentSlide, slidesToScroll, slidesToShow, cellAlign);
if (currentSlide !== prevSlideIndex) {

@@ -146,3 +167,3 @@ goToSlide(prevSlideIndex);

goToSlide,
propsSlidesToScroll,
slidesToScroll,
scrollMode,

@@ -208,20 +229,2 @@ slidesToShow,

]);
// Makes the carousel infinity when wrapAround is enabled
(0, react_1.useEffect)(() => {
if (wrapAround && !isAnimating && !isDragging) {
if (currentSlide <= -slidesToShow) {
setCurrentSlide(slideCount - -currentSlide);
}
else if (currentSlide >= slideCount) {
setCurrentSlide(currentSlide - slideCount);
}
}
}, [
currentSlide,
isAnimating,
isDragging,
slideCount,
slidesToShow,
wrapAround,
]);
const onKeyDown = (event) => {

@@ -244,5 +247,7 @@ let keyCommand = null;

case 'nextSlide':
onUserNavigation(event);
nextSlide();
break;
case 'previousSlide':
onUserNavigation(event);
prevSlide();

@@ -252,2 +257,3 @@ break;

case 'lastSlide': {
onUserNavigation(event);
const dotIndices = (0, default_controls_1.getDotIndexes)(slideCount, slidesToScroll, scrollMode, slidesToShow, wrapAround, cellAlign);

@@ -317,8 +323,11 @@ if (keyCommand === 'firstSlide') {

if (dragDistance > 0) {
nextSlideIndex = (0, utils_1.getNextMoveIndex)(scrollMode, wrapAround, nextSlideIndex, slideCount, propsSlidesToScroll, slidesToShow, cellAlign);
nextSlideIndex = (0, utils_1.getNextMoveIndex)(scrollMode, wrapAround, nextSlideIndex, slideCount, slidesToScroll, slidesToShow, cellAlign);
}
else {
nextSlideIndex = (0, utils_1.getPrevMoveIndex)(scrollMode, wrapAround, nextSlideIndex, propsSlidesToScroll, slidesToShow, cellAlign);
nextSlideIndex = (0, utils_1.getPrevMoveIndex)(scrollMode, wrapAround, nextSlideIndex, slidesToScroll, slidesToShow, cellAlign);
}
}
if (nextSlideIndex !== currentSlide) {
onUserNavigation(e);
}
goToSlide(nextSlideIndex);

@@ -403,8 +412,3 @@ };

const slides = filteredSlides.map((child, index) => {
const isCurrentSlide = wrapAround
? currentSlide === index ||
currentSlide === index + slideCount ||
currentSlide === index - slideCount
: currentSlide === index;
return ((0, jsx_runtime_1.jsx)(slide_1.default, Object.assign({ count: slideCount, currentSlide: currentSlide, index: index, isCurrentSlide: isCurrentSlide, typeOfSlide: typeOfSlide, wrapAround: wrapAround, cellSpacing: cellSpacing, animation: animation, slidesToShow: slidesToShow, speed: propsSpeed, zoomScale: zoomScale, cellAlign: cellAlign, onVisibleSlideHeightChange: handleVisibleSlideHeightChange, adaptiveHeight: adaptiveHeight, initializedAdaptiveHeight: initializedAdaptiveHeight }, { children: child }), `${typeOfSlide}-${index}`));
return ((0, jsx_runtime_1.jsx)(slide_1.default, Object.assign({ count: slideCount, currentSlide: currentSlide, index: index, isCurrentSlide: currentSlide === index, typeOfSlide: typeOfSlide, wrapAround: wrapAround, cellSpacing: cellSpacing, animation: animation, slidesToShow: slidesToShow, speed: speed, zoomScale: zoomScale, cellAlign: cellAlign, onVisibleSlideHeightChange: handleVisibleSlideHeightChange, adaptiveHeight: adaptiveHeight, initializedAdaptiveHeight: initializedAdaptiveHeight }, { children: child }), `${typeOfSlide}-${index}`));
});

@@ -416,7 +420,7 @@ return slides;

}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave }, { children: [(0, jsx_runtime_1.jsx)(announce_slide_1.default, { ariaLive: autoplay && !pause ? 'off' : 'polite', message: renderAnnounceSlideMessage({
currentSlide: slide,
currentSlide,
count: slideCount,
}) }), (0, controls_1.default)(props, slideCount, currentSlide, goToSlide, nextSlide, prevSlide, slidesToScroll), (0, jsx_runtime_1.jsx)("div", Object.assign({ className: ['slider-frame', className || ''].join(' ').trim(), style: Object.assign({ overflow: 'hidden', width: '100%', position: 'relative', outline: 'none', height: frameHeight, transition: adaptiveHeightAnimation
? 'height 300ms ease-in-out'
: undefined, willChange: 'height', userSelect: 'none' }, style), "aria-label": frameAriaLabel, role: "region", tabIndex: 0, onKeyDown: enableKeyboardControls ? onKeyDown : undefined, ref: carouselRef, onMouseUp: onMouseUp, onMouseDown: onMouseDown, onMouseMove: onMouseMove, onMouseLeave: onMouseUp, onTouchStart: onTouchStart, onTouchEnd: handleDragEnd, onTouchMove: onTouchMove }, { children: (0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "slider-list", style: (0, slider_list_1.getSliderListStyles)(slideCount, currentSlide, isAnimating, slidesToShow, cellAlign, wrapAround, propsSpeed, isDragging ? preDragOffset.current - dragDistance : 0, slidesToScroll, scrollMode, disableEdgeSwiping, animation), ref: sliderListRef }, { children: [wrapAround ? renderSlides('prev-cloned') : null, renderSlides(), wrapAround ? renderSlides('next-cloned') : null] })) }))] })));
: undefined, willChange: 'height', userSelect: 'none' }, style), "aria-label": frameAriaLabel, role: "region", tabIndex: 0, onKeyDown: enableKeyboardControls ? onKeyDown : undefined, ref: carouselRef, onMouseUp: onMouseUp, onMouseDown: onMouseDown, onMouseMove: onMouseMove, onMouseLeave: onMouseUp, onTouchStart: onTouchStart, onTouchEnd: handleDragEnd, onTouchMove: onTouchMove }, { children: (0, jsx_runtime_1.jsxs)(slider_list_1.SliderList, Object.assign({ animationDistance: animationDistance, cellAlign: cellAlign, currentSlide: currentSlide, disableEdgeSwiping: props.disableEdgeSwiping, draggedOffset: preDragOffset.current - dragDistance, disableAnimation: disableAnimation, easing: props.easing, edgeEasing: props.edgeEasing, isDragging: isDragging, ref: setSliderListRef, scrollMode: scrollMode, animation: animation, slideCount: slideCount, slidesToScroll: slidesToScroll, slidesToShow: slidesToShow, speed: speed, wrapAround: wrapAround }, { children: [wrapAround ? renderSlides('prev-cloned') : null, renderSlides(), wrapAround ? renderSlides('next-cloned') : null] })) }))] })));
};

@@ -423,0 +427,0 @@ exports.Carousel = Carousel;

@@ -29,2 +29,24 @@ "use strict";

});
/**
* Mock dimensions for the carousel for calculations where carousel dimensions
* are used, such as with dragging thresholds
*/
const createCarouselRefWithMockedDimensions = ({ defaultWidth = 600 } = {}) => {
let refValue = null;
const widthGetterMock = jest.fn(() => defaultWidth);
const carouselRef = Object.create({}, {
current: {
get: () => refValue,
set(newValue) {
refValue = newValue;
if (refValue) {
Object.defineProperty(refValue, 'offsetWidth', {
get: widthGetterMock,
});
}
},
},
});
return { ref: carouselRef, widthGetterMock };
};
describe('Carousel', () => {

@@ -91,6 +113,7 @@ const renderCarousel = (_a = {}) => {

};
const slideCount = 8;
renderCarousel({
enableKeyboardControls: true,
keyCodeConfig,
slideCount: 8,
slideCount,
beforeSlide,

@@ -112,7 +135,117 @@ });

react_1.fireEvent.keyDown(carouselFrame, { keyCode: keyCodeConfig.lastSlide[0] });
expect(beforeSlide).toHaveBeenLastCalledWith(0, 7);
expect(beforeSlide).toHaveBeenLastCalledWith(0, slideCount - 1);
react_1.fireEvent.keyDown(carouselFrame, { keyCode: keyCodeConfig.firstSlide[0] });
expect(beforeSlide).toHaveBeenLastCalledWith(7, 0);
expect(beforeSlide).toHaveBeenLastCalledWith(slideCount - 1, 0);
});
it('detects user-triggered navigation', () => {
const beforeSlide = jest.fn();
const onUserNavigation = jest.fn();
const keyCodeConfig = {
nextSlide: [39],
previousSlide: [37],
firstSlide: [81],
lastSlide: [69],
pause: [32],
};
const autoplayInterval = 3000;
const slideCount = 8;
renderCarousel({
enableKeyboardControls: true,
autoplay: true,
autoplayInterval,
keyCodeConfig,
innerRef: createCarouselRefWithMockedDimensions().ref,
slideCount,
beforeSlide,
onUserNavigation,
});
expect(onUserNavigation).toHaveBeenCalledTimes(0);
// Let enough time pass that autoplay triggers navigation
(0, react_1.act)(() => {
jest.advanceTimersByTime(autoplayInterval);
});
// Make sure the navigation happened, but did not trigger the
// `onUserNavigation` callback (because it wasn't user-initiated)
expect(onUserNavigation).toHaveBeenCalledTimes(0);
expect(beforeSlide).toHaveBeenLastCalledWith(0, 1);
const carouselFrame = react_1.screen.getByRole('region');
// Simulating keyboard shortcut use to navigate
react_1.fireEvent.keyDown(carouselFrame, { keyCode: keyCodeConfig.nextSlide[0] });
expect(beforeSlide).toHaveBeenLastCalledWith(1, 2);
expect(onUserNavigation).toHaveBeenCalledTimes(1);
react_1.fireEvent.keyDown(carouselFrame, {
keyCode: keyCodeConfig.previousSlide[0],
});
expect(onUserNavigation).toHaveBeenCalledTimes(2);
react_1.fireEvent.keyDown(carouselFrame, { keyCode: keyCodeConfig.lastSlide[0] });
expect(onUserNavigation).toHaveBeenCalledTimes(3);
react_1.fireEvent.keyDown(carouselFrame, { keyCode: keyCodeConfig.firstSlide[0] });
expect(onUserNavigation).toHaveBeenCalledTimes(4);
// Simulating clicks on default controls to navigate
react_1.fireEvent.click(react_1.screen.getByRole('button', { name: /next/ }));
expect(onUserNavigation).toHaveBeenCalledTimes(5);
react_1.fireEvent.click(react_1.screen.getByRole('button', { name: /prev/ }));
expect(onUserNavigation).toHaveBeenCalledTimes(6);
react_1.fireEvent.click(react_1.screen.getByRole('button', { name: /slide 2/ }));
expect(onUserNavigation).toHaveBeenCalledTimes(7);
// Simulating drag to navigate
react_1.fireEvent.mouseDown(carouselFrame, { clientX: 100 });
react_1.fireEvent.mouseMove(carouselFrame, { clientX: 100 });
jest.advanceTimersByTime(100);
react_1.fireEvent.mouseMove(carouselFrame, { clientX: 700 });
react_1.fireEvent.mouseUp(carouselFrame, { clientX: 700 });
expect(onUserNavigation).toHaveBeenCalledTimes(8);
// Simulating swipe to navigate
react_1.fireEvent.touchStart(carouselFrame, { touches: [{ pageX: 700 }] });
react_1.fireEvent.touchMove(carouselFrame, { touches: [{ pageX: 700 }] });
jest.advanceTimersByTime(100);
react_1.fireEvent.touchMove(carouselFrame, { touches: [{ pageX: 100 }] });
react_1.fireEvent.touchEnd(carouselFrame, { touches: [{ pageX: 100 }] });
expect(onUserNavigation).toHaveBeenCalledTimes(9);
// Should not be triggering navigation callback when dragging didn't trigger navigation
react_1.fireEvent.mouseDown(carouselFrame, { clientX: 100 });
react_1.fireEvent.mouseMove(carouselFrame, { clientX: 100 });
jest.advanceTimersByTime(10);
react_1.fireEvent.mouseMove(carouselFrame, { clientX: 105 });
react_1.fireEvent.mouseUp(carouselFrame, { clientX: 105 });
expect(onUserNavigation).toHaveBeenCalledTimes(9);
});
it('calls default control callbacks when interacted with', () => {
const beforeSlide = jest.fn();
const nextButtonOnClick = jest.fn();
const prevButtonOnClick = jest.fn();
const pagingDotsOnClick = jest.fn();
const slideCount = 8;
renderCarousel({
slideCount,
beforeSlide,
defaultControlsConfig: {
nextButtonOnClick,
prevButtonOnClick,
pagingDotsOnClick,
},
});
// Simulating clicks on default controls to navigate
expect(nextButtonOnClick).toHaveBeenCalledTimes(0);
react_1.fireEvent.click(react_1.screen.getByRole('button', { name: /next/ }));
expect(nextButtonOnClick).toHaveBeenCalledTimes(1);
expect(prevButtonOnClick).toHaveBeenCalledTimes(0);
react_1.fireEvent.click(react_1.screen.getByRole('button', { name: /prev/ }));
expect(prevButtonOnClick).toHaveBeenCalledTimes(1);
expect(pagingDotsOnClick).toHaveBeenCalledTimes(0);
react_1.fireEvent.click(react_1.screen.getByRole('button', { name: /slide 2/ }));
expect(pagingDotsOnClick).toHaveBeenCalledTimes(1);
// Check that calling preventDefault in the custom callback will stop the
// default behavior (navigation) before it happens
const preventDefault = (event) => event.preventDefault();
nextButtonOnClick.mockImplementation(preventDefault);
prevButtonOnClick.mockImplementation(preventDefault);
pagingDotsOnClick.mockImplementation(preventDefault);
expect(beforeSlide).toHaveBeenCalledTimes(3);
react_1.fireEvent.click(react_1.screen.getByRole('button', { name: /next/ }));
react_1.fireEvent.click(react_1.screen.getByRole('button', { name: /prev/ }));
react_1.fireEvent.click(react_1.screen.getByRole('button', { name: /slide 2/ }));
expect(beforeSlide).toHaveBeenCalledTimes(3);
});
});
//# sourceMappingURL=carousel.test.js.map

@@ -6,2 +6,3 @@ "use strict";

const control_styles_1 = require("./control-styles");
const default_controls_1 = require("./default-controls");
const types_1 = require("./types");

@@ -23,2 +24,7 @@ const controlsMap = [

}
const disableCheckProps = Object.assign(Object.assign({}, props), { currentSlide,
slideCount });
const nextDisabled = (0, default_controls_1.nextButtonDisabled)(disableCheckProps);
const previousDisabled = (0, default_controls_1.prevButtonDisabled)(disableCheckProps);
const pagingDotsIndices = (0, default_controls_1.getDotIndexes)(slideCount, slidesToScroll, props.scrollMode, props.slidesToShow, props.wrapAround, props.cellAlign);
return controlsMap.map((control) => {

@@ -43,4 +49,8 @@ var _a;

defaultControlsConfig: props.defaultControlsConfig || {},
pagingDotsIndices,
goToSlide,
nextDisabled,
nextSlide,
onUserNavigation: props.onUserNavigation,
previousDisabled,
previousSlide: prevSlide,

@@ -47,0 +57,0 @@ scrollMode: props.scrollMode,

@@ -7,2 +7,3 @@ "use strict";

const announce_slide_1 = require("./announce-slide");
const easeOut = (t) => Math.pow((t - 1), 3) + 1;
const defaultProps = {

@@ -27,4 +28,4 @@ adaptiveHeight: false,

dragThreshold: 0.5,
easing: types_1.D3EasingFunctions.EaseCircleOut,
edgeEasing: types_1.D3EasingFunctions.EaseElasticOut,
easing: easeOut,
edgeEasing: easeOut,
enableKeyboardControls: false,

@@ -48,2 +49,5 @@ frameAriaLabel: 'carousel-slider',

},
onUserNavigation: () => {
// do nothing
},
pauseOnHover: true,

@@ -50,0 +54,0 @@ renderAnnounceSlideMessage: announce_slide_1.defaultRenderAnnounceSlideMessage,

/// <reference types="react" />
import { Alignment, ControlProps, ScrollMode } from './types';
export declare const prevButtonDisabled: ({ currentSlide, wrapAround, cellAlign, slidesToShow, }: ControlProps) => boolean;
export declare const PreviousButton: (props: ControlProps) => JSX.Element;
export declare const nextButtonDisabled: ({ currentSlide, slideCount, slidesToShow, wrapAround, cellAlign, }: ControlProps) => boolean;
export declare const NextButton: (props: ControlProps) => JSX.Element;
export declare const prevButtonDisabled: ({ cellAlign, currentSlide, slidesToShow, wrapAround, }: Pick<ControlProps, 'cellAlign' | 'currentSlide' | 'slidesToShow' | 'wrapAround'>) => boolean;
export declare const PreviousButton: ({ previousSlide, defaultControlsConfig: { prevButtonClassName, prevButtonStyle, prevButtonText, prevButtonOnClick, }, onUserNavigation, previousDisabled: disabled, }: ControlProps) => JSX.Element;
export declare const nextButtonDisabled: ({ cellAlign, currentSlide, slideCount, slidesToShow, wrapAround, }: Pick<ControlProps, 'cellAlign' | 'currentSlide' | 'slideCount' | 'slidesToShow' | 'wrapAround'>) => boolean;
export declare const NextButton: ({ nextSlide, defaultControlsConfig: { nextButtonClassName, nextButtonStyle, nextButtonText, nextButtonOnClick, }, nextDisabled: disabled, onUserNavigation, }: ControlProps) => JSX.Element;
/**

@@ -11,3 +11,3 @@ * Calculate the indices that each dot will jump to when clicked

export declare const getDotIndexes: (slideCount: number, slidesToScroll: number, scrollMode: ScrollMode, slidesToShow: number, wrapAround: boolean, cellAlign: Alignment) => number[];
export declare const PagingDots: (props: ControlProps) => JSX.Element;
export declare const PagingDots: ({ pagingDotsIndices, defaultControlsConfig: { pagingDotsContainerClassName, pagingDotsClassName, pagingDotsStyle, pagingDotsOnClick, }, currentSlide, onUserNavigation, slideCount, goToSlide, }: ControlProps) => JSX.Element;
//# sourceMappingURL=default-controls.d.ts.map

@@ -5,5 +5,5 @@ "use strict";

const jsx_runtime_1 = require("react/jsx-runtime");
/* eslint-disable complexity */
const react_1 = require("react");
const types_1 = require("./types");
const utils_1 = require("./utils");
const defaultButtonStyles = (disabled) => ({

@@ -18,3 +18,3 @@ border: 0,

});
const prevButtonDisabled = ({ currentSlide, wrapAround, cellAlign, slidesToShow, }) => {
const prevButtonDisabled = ({ cellAlign, currentSlide, slidesToShow, wrapAround, }) => {
// inifite carousel

@@ -35,13 +35,15 @@ if (wrapAround) {

exports.prevButtonDisabled = prevButtonDisabled;
const PreviousButton = (props) => {
const PreviousButton = ({ previousSlide, defaultControlsConfig: { prevButtonClassName, prevButtonStyle = {}, prevButtonText, prevButtonOnClick, }, onUserNavigation, previousDisabled: disabled, }) => {
const handleClick = (event) => {
prevButtonOnClick === null || prevButtonOnClick === void 0 ? void 0 : prevButtonOnClick(event);
if (event.defaultPrevented)
return;
onUserNavigation(event);
event.preventDefault();
props === null || props === void 0 ? void 0 : props.previousSlide();
previousSlide();
};
const { prevButtonClassName, prevButtonStyle = {}, prevButtonText, } = props.defaultControlsConfig || {};
const disabled = (0, exports.prevButtonDisabled)(props);
return ((0, jsx_runtime_1.jsx)("button", Object.assign({ className: prevButtonClassName, style: Object.assign(Object.assign({}, defaultButtonStyles(disabled)), prevButtonStyle), disabled: disabled, onClick: handleClick, "aria-label": "previous", type: "button" }, { children: prevButtonText || 'Prev' })));
};
exports.PreviousButton = PreviousButton;
const nextButtonDisabled = ({ currentSlide, slideCount, slidesToShow, wrapAround, cellAlign, }) => {
const nextButtonDisabled = ({ cellAlign, currentSlide, slideCount, slidesToShow, wrapAround, }) => {
// inifite carousel

@@ -63,10 +65,11 @@ if (wrapAround) {

exports.nextButtonDisabled = nextButtonDisabled;
const NextButton = (props) => {
const NextButton = ({ nextSlide, defaultControlsConfig: { nextButtonClassName, nextButtonStyle = {}, nextButtonText, nextButtonOnClick, }, nextDisabled: disabled, onUserNavigation, }) => {
const handleClick = (event) => {
nextButtonOnClick === null || nextButtonOnClick === void 0 ? void 0 : nextButtonOnClick(event);
if (event.defaultPrevented)
return;
onUserNavigation(event);
event.preventDefault();
props.nextSlide();
nextSlide();
};
const { defaultControlsConfig } = props;
const { nextButtonClassName, nextButtonStyle = {}, nextButtonText, } = defaultControlsConfig;
const disabled = (0, exports.nextButtonDisabled)(props);
return ((0, jsx_runtime_1.jsx)("button", Object.assign({ className: nextButtonClassName, style: Object.assign(Object.assign({}, defaultButtonStyles(disabled)), nextButtonStyle), disabled: disabled, onClick: handleClick, "aria-label": "next", type: "button" }, { children: nextButtonText || 'Next' })));

@@ -137,3 +140,3 @@ };

exports.getDotIndexes = getDotIndexes;
const PagingDots = (props) => {
const PagingDots = ({ pagingDotsIndices, defaultControlsConfig: { pagingDotsContainerClassName, pagingDotsClassName, pagingDotsStyle = {}, pagingDotsOnClick, }, currentSlide, onUserNavigation, slideCount, goToSlide, }) => {
const listStyles = {

@@ -154,13 +157,15 @@ position: 'relative',

}), []);
const indexes = (0, exports.getDotIndexes)(props.slideCount, props.slidesToScroll, props.scrollMode, props.slidesToShow, props.wrapAround, props.cellAlign);
const { pagingDotsContainerClassName, pagingDotsClassName, pagingDotsStyle = {}, } = props.defaultControlsConfig;
return ((0, jsx_runtime_1.jsx)("ul", Object.assign({ className: pagingDotsContainerClassName, style: listStyles }, { children: indexes.map((index, i) => {
let isActive = props.currentSlide === index ||
props.currentSlide - props.slideCount === index ||
props.currentSlide + props.slideCount === index;
// the below condition checks and sets navigation dots active if the current slide falls in the current index range
if (props.currentSlide < index && props.currentSlide > indexes[i - 1]) {
isActive = true;
}
return ((0, jsx_runtime_1.jsx)("li", Object.assign({ className: isActive ? 'paging-item active' : 'paging-item' }, { children: (0, jsx_runtime_1.jsx)("button", Object.assign({ className: pagingDotsClassName, type: "button", style: Object.assign(Object.assign({}, getButtonStyles(isActive)), pagingDotsStyle), onClick: props.goToSlide.bind(null, index), "aria-label": `slide ${index + 1} bullet`, "aria-selected": isActive }, { children: (0, jsx_runtime_1.jsx)("svg", Object.assign({ className: "paging-dot", width: "6", height: "6", "aria-hidden": "true", focusable: "false" }, { children: (0, jsx_runtime_1.jsx)("circle", { cx: "3", cy: "3", r: "3" }) })) })) }), index));
const currentSlideBounded = (0, utils_1.getBoundedIndex)(currentSlide, slideCount);
return ((0, jsx_runtime_1.jsx)("ul", Object.assign({ className: pagingDotsContainerClassName, style: listStyles }, { children: pagingDotsIndices.map((slideIndex, i) => {
const isActive = currentSlideBounded === slideIndex ||
// sets navigation dots active if the current slide falls in the current index range
(currentSlideBounded < slideIndex &&
(i === 0 || currentSlideBounded > pagingDotsIndices[i - 1]));
return ((0, jsx_runtime_1.jsx)("li", Object.assign({ className: isActive ? 'paging-item active' : 'paging-item' }, { children: (0, jsx_runtime_1.jsx)("button", Object.assign({ className: pagingDotsClassName, type: "button", style: Object.assign(Object.assign({}, getButtonStyles(isActive)), pagingDotsStyle), onClick: (event) => {
pagingDotsOnClick === null || pagingDotsOnClick === void 0 ? void 0 : pagingDotsOnClick(event);
if (event.defaultPrevented)
return;
onUserNavigation(event);
goToSlide(slideIndex);
}, "aria-label": `slide ${slideIndex + 1} bullet`, "aria-selected": isActive }, { children: (0, jsx_runtime_1.jsx)("svg", Object.assign({ className: "paging-dot", width: "6", height: "6", "aria-hidden": "true", focusable: "false", viewBox: "0 0 6 6" }, { children: (0, jsx_runtime_1.jsx)("circle", { cx: "3", cy: "3", r: "3" }) })) })) }), slideIndex));
}) })));

@@ -167,0 +172,0 @@ };

@@ -1,4 +0,14 @@

import React from 'react';
import { Alignment, ScrollMode } from './types';
export declare const getSliderListStyles: (slideCount: number, currentSlide: number, isAnimating: boolean, slidesToShow: number, cellAlign: Alignment, wrapAround: boolean, speed: number, draggedOffset: number, slidesToScroll: number, scrollMode: ScrollMode, disableEdgeSwiping: boolean, slideAnimation?: 'fade' | 'zoom') => React.CSSProperties;
import React, { ReactNode } from 'react';
import { Alignment, InternalCarouselProps } from './types';
export declare const getPercentOffsetForSlide: (currentSlide: number, slideCount: number, slidesToShow: number, cellAlign: Alignment, wrapAround: boolean) => number;
interface SliderListProps extends Pick<InternalCarouselProps, 'cellAlign' | 'disableAnimation' | 'disableEdgeSwiping' | 'easing' | 'edgeEasing' | 'scrollMode' | 'animation' | 'slidesToScroll' | 'slidesToShow' | 'speed' | 'wrapAround'> {
animationDistance: number;
children: ReactNode;
currentSlide: number;
draggedOffset: number;
isDragging: boolean;
slideCount: number;
}
export declare const SliderList: React.ForwardRefExoticComponent<SliderListProps & React.RefAttributes<HTMLDivElement>>;
export {};
//# sourceMappingURL=slider-list.d.ts.map
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSliderListStyles = void 0;
exports.SliderList = exports.getPercentOffsetForSlide = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importDefault(require("react"));
const default_controls_1 = require("./default-controls");
const use_tween_1 = require("./hooks/use-tween");
const types_1 = require("./types");
const getSliderListWidth = (slideCount, slidesToShow, wrapAround) => {
const visibleSlides = slidesToShow;
if (wrapAround) {
const percentage = (slideCount * 100) / visibleSlides;
return `${3 * percentage}%`;
}
const percentage = (slideCount * 100) / visibleSlides;
return `${percentage}%`;
};
const getPercentOffsetForSlide = (slideCount, initialValue, currentSlide, cellAlign, wrapAround) => {
if (cellAlign === types_1.Alignment.Left) {
if (wrapAround) {
const slideTransition = 100 / (3 * slideCount);
const currentTransition = initialValue - slideTransition * (currentSlide - 1);
return currentTransition - slideTransition;
}
const slideTransition = (100 / slideCount) * currentSlide;
return -(slideTransition + initialValue);
}
else if (cellAlign === types_1.Alignment.Center) {
if (wrapAround) {
const slideTransition = 100 / (3 * slideCount);
const currentTransition = initialValue - slideTransition * (currentSlide - 1);
return currentTransition - slideTransition;
}
const slideTransition = (100 / slideCount) * currentSlide;
return initialValue - slideTransition;
}
else if (cellAlign === types_1.Alignment.Right) {
if (wrapAround) {
const slideTransition = 100 / (3 * slideCount);
const currentTransition = initialValue - slideTransition * (currentSlide - 1);
return currentTransition - slideTransition;
}
const slideTransition = (100 / slideCount) * currentSlide;
return initialValue - slideTransition;
}
return initialValue;
};
const getPositioning = (cellAlign, slidesToShow, slideCount, currentSlide, wrapAround, draggedOffset, clampIndices) => {
const getPercentOffsetForSlide = (currentSlide, slideCount, slidesToShow, cellAlign, wrapAround) => {
// When wrapAround is enabled, we show the slides 3 times
const totalCount = wrapAround ? 3 * slideCount : slideCount;
const slideSize = 100 / totalCount;
let initialValue = wrapAround ? -slideCount * slideSize : 0;
const renderedSlideCount = wrapAround ? 3 * slideCount : slideCount;
const singleSlidePercentOfWhole = 100 / renderedSlideCount;
// When wrap is on, -33.33% puts us right on the center, true set of slides
// (the left and right sets are clones meant to avoid visual gaps)
let slide0Offset = wrapAround ? -100 / 3 : 0;
if (cellAlign === types_1.Alignment.Right && slidesToShow > 1) {
const excessSlides = slidesToShow - 1;
initialValue += slideSize * excessSlides;
slide0Offset += singleSlidePercentOfWhole * excessSlides;
}

@@ -58,44 +27,67 @@ if (cellAlign === types_1.Alignment.Center && slidesToShow > 1) {

const excessLeftSlides = excessSlides / 2;
initialValue += slideSize * excessLeftSlides;
slide0Offset += singleSlidePercentOfWhole * excessLeftSlides;
}
const slideBasedOffset = getPercentOffsetForSlide(slideCount, initialValue, currentSlide, cellAlign, wrapAround);
// Special-case this. It's better to return undefined rather than a
// transform of 0 pixels since transforms can cause flickering in chrome.
if (draggedOffset === 0 && slideBasedOffset === 0) {
return undefined;
const currentSlideOffsetFrom0 = (100 / renderedSlideCount) * currentSlide;
return slide0Offset - currentSlideOffsetFrom0;
};
exports.getPercentOffsetForSlide = getPercentOffsetForSlide;
exports.SliderList = react_1.default.forwardRef(({ animation, animationDistance, cellAlign, children, currentSlide, disableAnimation, disableEdgeSwiping, draggedOffset, easing, edgeEasing, isDragging, scrollMode, slideCount, slidesToScroll, slidesToShow, speed, wrapAround, }, forwardedRef) => {
// When wrapAround is enabled, we show the slides 3 times
const renderedSlideCount = wrapAround ? 3 * slideCount : slideCount;
const listVisibleWidth = `${(renderedSlideCount * 100) / slidesToShow}%`;
const percentOffsetForSlideProps = [
slideCount,
slidesToShow,
cellAlign,
wrapAround,
];
// We recycle dot index generation to determine the leftmost and rightmost
// indices used, to be used in calculating the x-translation values we need
// to limit to or when edgeEasing should be used.
const dotIndexes = (0, default_controls_1.getDotIndexes)(slideCount, slidesToScroll, scrollMode, slidesToShow, wrapAround, cellAlign);
let clampedDraggedOffset = `${draggedOffset}px`;
if (isDragging && disableEdgeSwiping && !wrapAround) {
const clampOffsets = [
dotIndexes[0],
dotIndexes[dotIndexes.length - 1],
].map((index) => (0, exports.getPercentOffsetForSlide)(index, ...percentOffsetForSlideProps));
// Offsets are seemingly backwards because the rightmost slide creates
// the most negative translate value
clampedDraggedOffset = `clamp(${clampOffsets[1]}%, ${draggedOffset}px, ${clampOffsets[0]}%)`;
}
let clampOffsets = null;
if (clampIndices) {
clampOffsets = clampIndices.map((index) => getPercentOffsetForSlide(slideCount, initialValue, index, cellAlign, wrapAround));
const slideBasedOffset = (0, exports.getPercentOffsetForSlide)(currentSlide, ...percentOffsetForSlideProps);
const isEdgeEasing = !disableEdgeSwiping &&
!wrapAround &&
((currentSlide === dotIndexes[0] && animationDistance < 0) ||
(currentSlide === dotIndexes[dotIndexes.length - 1] &&
animationDistance > 0));
const { value: transition, isAnimating } = (0, use_tween_1.useTween)(speed, !isEdgeEasing ? easing : edgeEasing,
// animationDistance is assumed to be unique enough that it can be used to
// detect when a new animation should start. This is used in addition to
// currentSlide because some animations, such as those with edgeEasing, do
// not occur due to a change in value of currentSlide
currentSlide + animationDistance, isDragging || disableAnimation || animation === 'fade');
// Return undefined if the transform would be 0 pixels since transforms can
// cause flickering in chrome.
let positioning;
if (isDragging || slideBasedOffset !== 0 || isAnimating) {
if (isDragging) {
positioning = `translateX(${clampedDraggedOffset})`;
}
else {
const transitionOffset = isAnimating
? (1 - transition) * animationDistance
: 0;
positioning = `translateX(calc(${slideBasedOffset}% - ${transitionOffset}px))`;
}
}
const clampedDraggedOffset = clampOffsets
? // Offsets are seemingly backwards because the rightmost slide creates
// the most negative translate value
`clamp(${clampOffsets[1]}%, ${draggedOffset}px, ${clampOffsets[0]}%)`
: `${draggedOffset}px`;
return `translate3d(${draggedOffset ? clampedDraggedOffset : `${slideBasedOffset}%`}, 0, 0)`;
};
const getSliderListStyles = (slideCount, currentSlide, isAnimating, slidesToShow, cellAlign, wrapAround, speed, draggedOffset, slidesToScroll, scrollMode, disableEdgeSwiping, slideAnimation) => {
const width = getSliderListWidth(slideCount, slidesToShow, wrapAround);
// When disableEdgeSwiping=true, we recycle dot index generation to determine
// the leftmost and rightmost indices used, to be used in calculating the
// x-translation values we need to limit to.
let clampIndices = null;
if (disableEdgeSwiping && !wrapAround) {
const dotIndexes = (0, default_controls_1.getDotIndexes)(slideCount, slidesToScroll, scrollMode, slidesToShow, wrapAround, cellAlign);
clampIndices = [dotIndexes[0], dotIndexes[dotIndexes.length - 1]];
}
const positioning = getPositioning(cellAlign, slidesToShow, slideCount, currentSlide, wrapAround, draggedOffset, clampIndices);
return {
width,
textAlign: 'left',
userSelect: 'auto',
transition: draggedOffset === 0 && isAnimating && slideAnimation !== 'fade'
? `${speed}ms cubic-bezier(0.16, 1, 0.3, 1) 0s`
: undefined,
transform: positioning,
display: 'flex',
};
};
exports.getSliderListStyles = getSliderListStyles;
return ((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: forwardedRef, className: "slider-list", style: {
width: listVisibleWidth,
textAlign: 'left',
userSelect: 'auto',
transform: positioning,
display: 'flex',
} }, { children: children })));
});
exports.SliderList.displayName = 'SliderList';
//# sourceMappingURL=slider-list.js.map

@@ -39,52 +39,16 @@ import { ReactNode, CSSProperties, MutableRefObject } from 'react';

}
export declare enum D3EasingFunctions {
EaseLinear = "easeLinear",
EaseQuad = "easeQuad",
EaseQuadIn = "easeQuadIn",
EaseQuadOut = "easeQuadOut",
EaseQuadInOut = "easeQuadInOut",
EaseCubic = "easeCubic",
EaseCubicIn = "easeCubicIn",
EaseCubicOut = "easeCubicOut",
EaseCubicInOut = "easeCubicInOut",
EasePoly = "easePoly",
EasePolyIn = "easePolyIn",
EasePolyOut = "easePolyOut",
EasePolyInOut = "easePolyInOut",
EaseSin = "easeSin",
EaseSinIn = "easeSinIn",
EaseSinOut = "easeSinOut",
EaseSinInOut = "easeSinInOut",
EaseExp = "easeExp",
EaseExpIn = "easeExpIn",
EaseExpOut = "easeExpOut",
EaseExpInOut = "easeExpInOut",
EaseCircle = "easeCircle",
EaseCircleIn = "easeCircleIn",
EaseCircleOut = "easeCircleOut",
EaseCircleInOut = "easeCircleInOut",
EaseBack = "easeBack",
EaseBackIn = "easeBackIn",
EaseBackOut = "easeBackOut",
EaseBackInOut = "easeBackInOut",
EaseBounce = "easeBounce",
EaseBounceIn = "easeBounceIn",
EaseBounceOut = "easeBounceOut",
EaseBounceInOut = "easeBounceInOut",
EaseElastic = "easeElastic",
EaseElasticIn = "easeElasticIn",
EaseElasticOut = "easeElasticOut",
EaseElasticInOut = "easeElasticInOut"
}
interface DefaultControlsConfig {
containerClassName?: string;
nextButtonClassName?: string;
nextButtonOnClick?: React.MouseEventHandler;
nextButtonStyle?: CSSProperties;
nextButtonText?: string;
nextButtonText?: ReactNode;
pagingDotsClassName?: string;
pagingDotsContainerClassName?: string;
pagingDotsOnClick?: React.MouseEventHandler;
pagingDotsStyle?: CSSProperties;
prevButtonClassName?: string;
prevButtonOnClick?: React.MouseEventHandler;
prevButtonStyle?: CSSProperties;
prevButtonText?: string;
prevButtonText?: ReactNode;
}

@@ -109,54 +73,36 @@ export interface KeyCodeConfig {

}) => string;
export interface ControlProps {
export interface ControlProps extends Pick<InternalCarouselProps, 'cellAlign' | 'cellSpacing' | 'defaultControlsConfig' | 'onUserNavigation' | 'scrollMode' | 'slidesToScroll' | 'slidesToShow' | 'vertical' | 'wrapAround'> {
/**
* When displaying more than one slide, sets which position to anchor the current slide to.
* Current slide index
*/
cellAlign: Alignment;
currentSlide: number;
/**
* Space between slides, as an integer, but reflected as px
* The indices for the paging dots
*/
cellSpacing: number;
pagingDotsIndices: number[];
/**
* Current slide index
* Go to a specific slide
* @param targetIndex Index to go to
*/
currentSlide: number;
goToSlide: (targetIndex: number) => void;
/**
* This prop lets you apply custom classes and styles to the default Next, Previous, and Paging Dots controls
* Whether the "next" button should be disabled or not
*/
defaultControlsConfig: DefaultControlsConfig;
nextDisabled: boolean;
/**
* Go to X slide method
* @param index Slide's index to go
* Go to the next slide
*/
goToSlide: (index: number) => void;
nextSlide: () => void;
/**
* Go to the next slide method
* Whether the "previous" button should be disabled or not
*/
nextSlide: () => void;
previousDisabled: boolean;
/**
* Go to the previous slide method
* Go to the previous slide
*/
previousSlide: () => void;
scrollMode: ScrollMode;
/**
* Total amount of slides
* Total number of slides
*/
slideCount: number;
/**
* Slides to scroll at once
*/
slidesToScroll: number;
/**
* Slides to show at once
*/
slidesToShow: number;
/**
* Enable the slides to transition vertically
*/
vertical: boolean;
/**
* Sets infinite wrapAround mode
* @default false
*/
wrapAround: boolean;
}

@@ -170,2 +116,8 @@ export declare type RenderControlFunctionNames = 'renderTopLeftControls' | 'renderTopCenterControls' | 'renderTopRightControls' | 'renderCenterLeftControls' | 'renderCenterCenterControls' | 'renderCenterRightControls' | 'renderBottomLeftControls' | 'renderBottomCenterControls' | 'renderBottomRightControls';

declare type RenderControls = ((props: ControlProps) => ReactNode) | null;
/**
* Animation easing function accepting a normalized time between 0 and 1,
* inclusive, and returning an eased time, which equals 0 at normalizedTime==0
* and equals 1 at normalizedTime==1
*/
export declare type EasingFunction = (normalizedTime: number) => number;
export interface InternalCarouselProps {

@@ -253,15 +205,9 @@ /**

/**
* Not migrated yet
*
* Animation easing function
* @see https://github.com/d3/d3-ease
*/
easing: D3EasingFunctions;
easing: EasingFunction;
/**
* Not migrated yet
*
* Animation easing function when swipe exceeds edge
* @see https://github.com/d3/d3-ease
*/
edgeEasing: D3EasingFunctions;
edgeEasing: EasingFunction;
/**

@@ -287,12 +233,18 @@ * When set to true, disable keyboard controls

*/
onDragStart: (e?: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>) => void;
onDragStart: (e: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>) => void;
/**
* optional callback function
*/
onDrag: (e?: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>) => void;
onDrag: (e: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>) => void;
/**
* optional callback function
*/
onDragEnd: (e?: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>) => void;
onDragEnd: (e: React.TouchEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>) => void;
/**
* Callback called when user-triggered navigation occurs: dragging/swiping,
* clicking one of the controls (custom controls not included), or using a
* keyboard shortcut
*/
onUserNavigation: (e: React.TouchEvent | React.MouseEvent | React.KeyboardEvent) => void;
/**
* Pause autoPlay when mouse is over carousel

@@ -299,0 +251,0 @@ * @default true

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.D3EasingFunctions = exports.ScrollMode = exports.Positions = exports.Directions = exports.Alignment = void 0;
exports.ScrollMode = exports.Positions = exports.Directions = exports.Alignment = void 0;
/* eslint-disable no-shadow */

@@ -35,42 +35,2 @@ var Alignment;

})(ScrollMode = exports.ScrollMode || (exports.ScrollMode = {}));
var D3EasingFunctions;
(function (D3EasingFunctions) {
D3EasingFunctions["EaseLinear"] = "easeLinear";
D3EasingFunctions["EaseQuad"] = "easeQuad";
D3EasingFunctions["EaseQuadIn"] = "easeQuadIn";
D3EasingFunctions["EaseQuadOut"] = "easeQuadOut";
D3EasingFunctions["EaseQuadInOut"] = "easeQuadInOut";
D3EasingFunctions["EaseCubic"] = "easeCubic";
D3EasingFunctions["EaseCubicIn"] = "easeCubicIn";
D3EasingFunctions["EaseCubicOut"] = "easeCubicOut";
D3EasingFunctions["EaseCubicInOut"] = "easeCubicInOut";
D3EasingFunctions["EasePoly"] = "easePoly";
D3EasingFunctions["EasePolyIn"] = "easePolyIn";
D3EasingFunctions["EasePolyOut"] = "easePolyOut";
D3EasingFunctions["EasePolyInOut"] = "easePolyInOut";
D3EasingFunctions["EaseSin"] = "easeSin";
D3EasingFunctions["EaseSinIn"] = "easeSinIn";
D3EasingFunctions["EaseSinOut"] = "easeSinOut";
D3EasingFunctions["EaseSinInOut"] = "easeSinInOut";
D3EasingFunctions["EaseExp"] = "easeExp";
D3EasingFunctions["EaseExpIn"] = "easeExpIn";
D3EasingFunctions["EaseExpOut"] = "easeExpOut";
D3EasingFunctions["EaseExpInOut"] = "easeExpInOut";
D3EasingFunctions["EaseCircle"] = "easeCircle";
D3EasingFunctions["EaseCircleIn"] = "easeCircleIn";
D3EasingFunctions["EaseCircleOut"] = "easeCircleOut";
D3EasingFunctions["EaseCircleInOut"] = "easeCircleInOut";
D3EasingFunctions["EaseBack"] = "easeBack";
D3EasingFunctions["EaseBackIn"] = "easeBackIn";
D3EasingFunctions["EaseBackOut"] = "easeBackOut";
D3EasingFunctions["EaseBackInOut"] = "easeBackInOut";
D3EasingFunctions["EaseBounce"] = "easeBounce";
D3EasingFunctions["EaseBounceIn"] = "easeBounceIn";
D3EasingFunctions["EaseBounceOut"] = "easeBounceOut";
D3EasingFunctions["EaseBounceInOut"] = "easeBounceInOut";
D3EasingFunctions["EaseElastic"] = "easeElastic";
D3EasingFunctions["EaseElasticIn"] = "easeElasticIn";
D3EasingFunctions["EaseElasticOut"] = "easeElasticOut";
D3EasingFunctions["EaseElasticInOut"] = "easeElasticInOut";
})(D3EasingFunctions = exports.D3EasingFunctions || (exports.D3EasingFunctions = {}));
//# sourceMappingURL=types.js.map
import { Alignment, ScrollMode } from './types';
export declare const getIndexes: (slide: number, endSlide: number, slideCount: number) => [number, number];
export declare const isSlideVisible: (currentSlide: number, indexToCheck: number, slidesToShow: number, cellAlign: Alignment) => boolean;

@@ -7,2 +6,7 @@ export declare const getNextMoveIndex: (scrollMode: ScrollMode, wrapAround: boolean, currentSlide: number, slideCount: number, slidesToScroll: number, slidesToShow: number, cellAlign: Alignment) => number;

export declare const getDefaultSlideIndex: (slideIndex: number | undefined, slideCount: number, slidesToShow: number, slidesToScroll: number, cellAlign: Alignment, autoplayReverse: boolean, scrollMode: ScrollMode) => number;
/**
* Boils down an unbounded index (-Infinity < index < Infinity) to a bounded one
* (0 ≤ index < slideCount)
*/
export declare const getBoundedIndex: (rawIndex: number, slideCount: number) => number;
//# sourceMappingURL=utils.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDefaultSlideIndex = exports.getPrevMoveIndex = exports.getNextMoveIndex = exports.isSlideVisible = exports.getIndexes = void 0;
exports.getBoundedIndex = exports.getDefaultSlideIndex = exports.getPrevMoveIndex = exports.getNextMoveIndex = exports.isSlideVisible = void 0;
const default_controls_1 = require("./default-controls");
const types_1 = require("./types");
const getIndexes = (slide, endSlide, slideCount) => {
let slideIndex = slide;
let endSlideIndex = endSlide;
if (slideIndex < 0) {
slideIndex += slideCount;
}
else if (slideIndex > slideCount - 1) {
slideIndex -= slideCount;
}
if (endSlideIndex < 0) {
endSlideIndex += slideCount;
}
else if (endSlideIndex > slideCount - 1) {
endSlideIndex -= slideCount;
}
return [slideIndex, endSlideIndex];
};
exports.getIndexes = getIndexes;
const isSlideVisible = (currentSlide, indexToCheck, slidesToShow, cellAlign) => {

@@ -87,2 +69,10 @@ // The addition or subtraction of constants (1 , 0.5) in the following

exports.getDefaultSlideIndex = getDefaultSlideIndex;
/**
* Boils down an unbounded index (-Infinity < index < Infinity) to a bounded one
* (0 ≤ index < slideCount)
*/
const getBoundedIndex = (rawIndex, slideCount) => {
return ((rawIndex % slideCount) + slideCount) % slideCount;
};
exports.getBoundedIndex = getBoundedIndex;
//# sourceMappingURL=utils.js.map

@@ -250,2 +250,22 @@ "use strict";

});
describe('getBoundedIndex', () => {
it.each `
rawIndex | slideCount | expected
${0} | ${1} | ${0}
${1} | ${2} | ${1}
${2} | ${2} | ${0}
${3} | ${2} | ${1}
${4} | ${2} | ${0}
${-1} | ${2} | ${1}
${-2} | ${2} | ${0}
${-2} | ${3} | ${1}
${-3} | ${3} | ${0}
${-6} | ${3} | ${0}
${-7} | ${3} | ${2}
${-7.5} | ${3} | ${1.5}
`('gets the right index when bounds applied ' +
'(rawIndex $rawIndex, slideCount $slideCount)', ({ rawIndex, slideCount, expected }) => {
expect((0, utils_1.getBoundedIndex)(rawIndex, slideCount)).toEqual(expected);
});
});
//# sourceMappingURL=utils.test.js.map
{
"name": "nuka-carousel",
"version": "5.3.0",
"version": "5.4.0",
"description": "Pure React Carousel",

@@ -22,2 +22,3 @@ "main": "lib/index.js",

"@testing-library/react": "^13.3.0",
"@types/d3-ease": "^3.0.0",
"@types/exenv": "^1.2.0",

@@ -30,2 +31,3 @@ "@types/node": "^18.7.5",

"chromatic": "^6.2.0",
"d3-ease": "^3.0.1",
"exenv": "^1.2.0",

@@ -32,0 +34,0 @@ "jest-environment-jsdom": "^28.1.3",

@@ -81,3 +81,3 @@ # nuka-carousel

| className | `string` | Slider frame class name | `''` |
| defaultControlsConfig | <pre>interface DefaultControlsConfig { &#13; containerClassName?: string; &#13; nextButtonClassName?: string; &#13; nextButtonStyle?: CSSProperties; &#13; nextButtonText?: string; &#13; pagingDotsClassName?: string; &#13; pagingDotsContainerClassName?: string; &#13; pagingDotsStyle?: CSSProperties; &#13; prevButtonClassName?: string; &#13; prevButtonStyle?: CSSProperties; &#13; prevButtonText?: string; &#13;}</pre> | This prop lets you apply custom classes and styles to the default `Container`. `Next`, `Previous`, and `Paging Dots` controls. More information on how to customize these controls can be found below.| `{}` |
| defaultControlsConfig | <pre>interface DefaultControlsConfig { &#13; containerClassName?: string; &#13; nextButtonClassName?: string; &#13; nextButtonOnClick?: (event: React.MouseEvent) => void; &#13; nextButtonStyle?: CSSProperties; &#13; nextButtonText?: React.ReactNode; &#13; pagingDotsClassName?: string; &#13; pagingDotsContainerClassName?: string; &#13; pagingDotsOnClick?: (event: React.MouseEvent) => void; &#13; pagingDotsStyle?: CSSProperties; &#13; prevButtonClassName?: string; &#13; prevButtonOnClick?: (event: React.MouseEvent) => void; &#13; prevButtonStyle?: CSSProperties; &#13; prevButtonText?: React.ReactNode; &#13;}</pre> | This prop lets you apply custom classes and styles to the default `Container`. `Next`, `Previous`, and `Paging Dots` controls. More information on how to customize these controls can be found in the [defaultControlsConfig section](#defaultcontrolsconfig).| `{}` |
| disableAnimation | `boolean` | When set to `true`, will disable animation. | `false` |

@@ -87,2 +87,4 @@ | disableEdgeSwiping | `boolean` | When set to `true`, will disable swiping before first slide and after last slide. | `false` |

| dragThreshold | `number` | The percentage (from 0 to 1) of a slide that the user needs to drag before a slide change is triggered. | `0.5` |
| easing | `(normalizedTime: number) => number` | Animation easing function. See the [Easing section](#easing-and-edgeeasing) for more details | A cubic easeOut function |
| edgeEasing | `(normalizedTime: number) => number` | Animation easing function when swipe exceeds edge. See the [Easing section](#easing-and-edgeeasing) for more details | A cubic easeOut function |
| enableKeyboardControls | `boolean` | When set to `true` will enable keyboard controls when the carousel has focus. If the carousel does not have focus, keyboard controls will be ignored. | `false` |

@@ -92,5 +94,6 @@ | frameAriaLabel | `string` | Customize the aria-label of the frame container of the carousel. This is useful when you have more than one carousel on the page. | `''` |

| keyCodeConfig | <pre>interface KeyCodeConfig { &#13; firstSlide?: number[]; &#13; lastSlide?: number[];&#13; nextSlide?: number[]; &#13; pause?: number[]; &#13; previousSlide?: number[]; &#13;}</pre> | If `enableKeyboardControls` prop is true, you can pass configuration for the keyCode so you can override the default keyboard keys configured. | `{ nextSlide: [39, 68, 38, 87], previousSlide: [37, 65, 40, 83], firstSlide: [81], lastSlide: [69], pause: [32] }` |
| onDragStart | `(e?: React.TouchEvent<HTMLDivElement> \| React.MouseEvent<HTMLDivElement>) => void;` | Adds a callback to capture event at the start of swiping/dragging slides | |
| onDrag | `(e?: React.TouchEvent<HTMLDivElement> \| React.MouseEvent<HTMLDivElement>) => void;` | Adds a callback to capture swiping/dragging event on slides | |
| onDragEnd | `(e?: React.TouchEvent<HTMLDivElement> \| React.MouseEvent<HTMLDivElement>) => void;` | Adds a callback to capture event at the ent of swiping/dragging slides | |
| onDragStart | `(e: React.TouchEvent<HTMLDivElement> \| React.MouseEvent<HTMLDivElement>) => void;` | Adds a callback to capture event at the start of swiping/dragging slides | |
| onDrag | `(e: React.TouchEvent<HTMLDivElement> \| React.MouseEvent<HTMLDivElement>) => void;` | Adds a callback to capture swiping/dragging event on slides | |
| onDragEnd | `(e: React.TouchEvent<HTMLDivElement> \| React.MouseEvent<HTMLDivElement>) => void;` | Adds a callback to capture event at the end of swiping/dragging slides | |
| onUserNavigation | `(e: React.TouchEvent \| React.MouseEvent \| React.KeyboardEvent) => void;` | Callback called when user-triggered navigation occurs: dragging/swiping, clicking one of the controls (custom controls not included), or using a keyboard shortcut | |
| pauseOnHover | `boolean` | Pause autoPlay when mouse is over carousel. | `true` |

@@ -120,2 +123,32 @@ | renderAnnounceSlideMessage | `(props: Pick<CarouselState, 'currentSlide' \| 'count'>) => string` | Renders message in the ARIA live region that is announcing the current slide on slide change | Render function that returns `"Slide {currentSlide + 1} of {slideCount}"` |

- You can remove all render controls using the `withoutControls` prop on `Carousel`.
- The render functions receive a `ControlProps` argument containing the following props from the Carousel props, using default values if not originally defined:
```
cellAlign
cellSpacing
defaultControlsConfig
onUserNavigation
scrollMode
slidesToScroll
slidesToShow
wrapAround
```
Additionally, the following data and callbacks are provided to make creating controls easier:
| Name | Type | Description |
| :------------------- | ------------------------------- | :------------------------------------------------------ |
| currentSlide | `number` | Current slide index |
| pagingDotsIndices | `number[]` | The indices for the paging dots |
| goToSlide | `(targetIndex: number) => void` | Go to a specific slide |
| nextDisabled | `boolean` | Whether the "next" button should be disabled or not |
| nextSlide | `() => void` | Go to the next slide |
| previousDisabled | `boolean` | Whether the "previous" button should be disabled or not |
| previousSlide | `() => void` | Go to the previous slide |
| slideCount | `number` | Total number of slides |
Example:
```jsx

@@ -126,7 +159,11 @@ <Carousel

)}
renderCenterLeftControls={({ previousSlide }) => (
<button onClick={previousSlide}>Previous</button>
renderCenterLeftControls={({ previousDisabled, previousSlide }) => (
<button onClick={previousSlide} disabled={previousDisabled}>
Previous
</button>
)}
renderCenterRightControls={({ nextSlide }) => (
<button onClick={nextSlide}>Next</button>
renderCenterRightControls={({ nextDisabled, nextSlide }) => (
<button onClick={nextSlide} disabled={nextDisabled}>
Next
</button>
)}

@@ -138,6 +175,21 @@ >

- The function returns the props for `goToSlide`, `nextSlide` and `previousSlide` functions, in addition to `slideCount` and `currentSlide` values. You can also remove all render controls using `withoutControls`.
- NOTE: The className `slide-visible` is added to the currently visible slide or slides (when `slidesToShow` > 1). The className `slide-current` is added to the currently "active" slide.
#### easing and edgeEasing
`(normalizedTime: number) => number`
A function accepting a normalized time between 0 and 1, inclusive, and returning an eased time, which equals 0 at normalizedTime==0 and equals 1 at normalizedTime==1. You can plug in your own custom easing function (e.g., `(t) => t` for a linear transition), or import functions from a different library, like [`d3-ease`](https://github.com/d3/d3-ease).
```jsx
import { easeCircleOut, easeElasticOut } from 'd3-ease';
// ...
<Carousel easing={easeCircleOut} edgeEasing={easeElasticOut}>
{/* Carousel Content */}
</Carousel>
```
Please note that using a function for `easing` with "In" in it (ease**In**Out, easeElastic**In**, etc.) will make swiping transitions feel a bit clunky, as the velocity at the end of the swipe will suddenly drop to follow the slow startup speed of the "In" easing function. In general, when using custom easing functions, try out both swiping and clicking on the navigation buttons to see how the transitions feel.
#### renderAnnounceSlideMessage

@@ -165,10 +217,13 @@

nextButtonClassName?: string;
nextButtonOnClick?: (event: React.MouseEvent) => void;
nextButtonStyle?: CSSProperties;
nextButtonText?: string;
nextButtonText?: React.ReactNode;
pagingDotsClassName?: string;
pagingDotsContainerClassName?: string;
pagingDotsOnClick?: (event: React.MouseEvent) => void;
pagingDotsStyle?: CSSProperties;
prevButtonClassName?: string;
prevButtonOnClick?: (event: React.MouseEvent) => void;
prevButtonStyle?: CSSProperties;
prevButtonText?: string;
prevButtonText?: React.ReactNode;
}

@@ -181,2 +236,3 @@ ```

- The props ending with `Style` let you apply inline styles to its respective control.
- The props ending with `OnClick` let you listen for user interaction with the controls.
- The text label for the `Previous` button and `Next` button can be customized using `prevButtonText` and `nextButtonText`, respectively.

@@ -183,0 +239,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc