@telus-uds/components-base 3.25.0 → 3.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +28 -1
  2. package/lib/cjs/Card/Card.js +34 -13
  3. package/lib/cjs/Card/CardBase.js +78 -11
  4. package/lib/cjs/Card/PressableCardBase.js +147 -8
  5. package/lib/cjs/Carousel/Carousel.js +161 -77
  6. package/lib/cjs/Carousel/CarouselContext.js +10 -4
  7. package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +11 -7
  8. package/lib/cjs/Carousel/Constants.js +22 -2
  9. package/lib/cjs/Checkbox/Checkbox.js +43 -13
  10. package/lib/cjs/InputSupports/InputSupports.js +2 -1
  11. package/lib/cjs/List/List.js +24 -9
  12. package/lib/cjs/List/ListItem.js +18 -1
  13. package/lib/cjs/List/ListItemBase.js +27 -8
  14. package/lib/cjs/List/ListItemMark.js +33 -62
  15. package/lib/cjs/List/PressableListItemBase.js +1 -0
  16. package/lib/cjs/PriceLockup/PriceLockup.js +1 -1
  17. package/lib/esm/Card/Card.js +34 -13
  18. package/lib/esm/Card/CardBase.js +78 -11
  19. package/lib/esm/Card/PressableCardBase.js +148 -9
  20. package/lib/esm/Carousel/Carousel.js +153 -69
  21. package/lib/esm/Carousel/CarouselContext.js +10 -4
  22. package/lib/esm/Carousel/CarouselItem/CarouselItem.js +11 -7
  23. package/lib/esm/Carousel/Constants.js +21 -1
  24. package/lib/esm/Checkbox/Checkbox.js +43 -13
  25. package/lib/esm/InputSupports/InputSupports.js +2 -1
  26. package/lib/esm/List/List.js +24 -9
  27. package/lib/esm/List/ListItem.js +19 -2
  28. package/lib/esm/List/ListItemBase.js +27 -8
  29. package/lib/esm/List/ListItemMark.js +33 -62
  30. package/lib/esm/List/PressableListItemBase.js +1 -0
  31. package/lib/esm/PriceLockup/PriceLockup.js +1 -1
  32. package/lib/package.json +2 -2
  33. package/package.json +2 -2
  34. package/src/Card/Card.jsx +29 -7
  35. package/src/Card/CardBase.jsx +88 -8
  36. package/src/Card/PressableCardBase.jsx +135 -9
  37. package/src/Carousel/Carousel.jsx +185 -88
  38. package/src/Carousel/CarouselContext.jsx +12 -4
  39. package/src/Carousel/CarouselItem/CarouselItem.jsx +10 -6
  40. package/src/Carousel/Constants.js +24 -0
  41. package/src/Checkbox/Checkbox.jsx +29 -7
  42. package/src/InputSupports/InputSupports.jsx +6 -1
  43. package/src/List/List.jsx +33 -9
  44. package/src/List/ListItem.jsx +33 -11
  45. package/src/List/ListItemBase.jsx +33 -9
  46. package/src/List/ListItemMark.jsx +32 -53
  47. package/src/List/PressableListItemBase.jsx +1 -0
  48. package/src/PriceLockup/PriceLockup.jsx +1 -1
@@ -11,6 +11,7 @@ var _PanResponder = _interopRequireDefault(require("react-native-web/dist/cjs/ex
11
11
  var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
12
12
  var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
13
13
  var _Dimensions = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Dimensions"));
14
+ var _Easing = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Easing"));
14
15
  var _propTypes = _interopRequireDefault(require("prop-types"));
15
16
  var _ThemeProvider = require("../ThemeProvider");
16
17
  var _ViewportProvider = require("../ViewportProvider");
@@ -30,11 +31,6 @@ var _Box = _interopRequireDefault(require("../Box"));
30
31
  var _Constants = require("./Constants");
31
32
  var _jsxRuntime = require("react/jsx-runtime");
32
33
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
33
- const TRANSITION_MODES = {
34
- MANUAL: 'manual',
35
- AUTOMATIC: 'automatic',
36
- SWIPE: 'swipe'
37
- };
38
34
  const staticStyles = _StyleSheet.default.create({
39
35
  root: {
40
36
  backgroundColor: 'transparent',
@@ -83,7 +79,7 @@ const selectHeroContainerStyles = (width, hidden) => ({
83
79
  width,
84
80
  visibility: hidden ? 'hidden' : 'visible'
85
81
  });
86
- const getDynamicPositionProperty = areStylesAppliedOnPreviousButton => areStylesAppliedOnPreviousButton ? 'left' : 'right';
82
+ const getDynamicPositionProperty = areStylesAppliedOnPreviousButton => areStylesAppliedOnPreviousButton ? _Constants.POSITION_PROPERTIES.LEFT : _Constants.POSITION_PROPERTIES.RIGHT;
87
83
  const selectControlButtonPositionStyles = _ref => {
88
84
  let {
89
85
  positionVariant,
@@ -93,23 +89,36 @@ const selectControlButtonPositionStyles = _ref => {
93
89
  enablePeeking,
94
90
  enableDisplayMultipleItemsPerSlide,
95
91
  isAutoPlayEnabled,
96
- viewport
92
+ viewport,
93
+ maxWidth,
94
+ viewportWidth
97
95
  } = _ref;
98
96
  const styles = {};
99
- if (positionVariant === 'edge') {
100
- styles[positionProperty] = -1 * (buttonWidth / 2);
101
- } else if (positionVariant === 'inside') {
102
- styles[positionProperty] = _Constants.DEFAULT_POSITION_OFFSET;
103
- } else if (positionVariant === 'outside') {
97
+ let positionOffset = 0;
98
+ if (positionVariant === _Constants.POSITION_VARIANTS.EDGE) {
99
+ positionOffset = -1 * (buttonWidth / 2);
100
+ } else if (positionVariant === _Constants.POSITION_VARIANTS.INSIDE) {
101
+ positionOffset = _Constants.DEFAULT_POSITION_OFFSET;
102
+ } else if (positionVariant === _Constants.POSITION_VARIANTS.OUTSIDE) {
104
103
  if (enablePeeking || enableDisplayMultipleItemsPerSlide || isAutoPlayEnabled && viewport === 'xs') {
105
- styles[positionProperty] = 0;
104
+ positionOffset = 0;
106
105
  } else {
107
- styles[positionProperty] = -1 * (spaceBetweenSlideAndButton + buttonWidth);
106
+ positionOffset = -1 * (spaceBetweenSlideAndButton + buttonWidth);
107
+ }
108
+ }
109
+ if (enablePeeking) {
110
+ if (positionProperty === _Constants.POSITION_PROPERTIES.RIGHT) {
111
+ const rightMargin = (viewportWidth - maxWidth) / 2;
112
+ positionOffset += rightMargin;
113
+ } else if (positionProperty === _Constants.POSITION_PROPERTIES.LEFT) {
114
+ const leftMargin = (viewportWidth - maxWidth) / 2;
115
+ positionOffset += leftMargin;
108
116
  }
109
117
  }
118
+ styles[positionProperty] = positionOffset;
110
119
  return styles;
111
120
  };
112
- const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, areStylesAppliedOnPreviousButton, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport) => {
121
+ const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, areStylesAppliedOnPreviousButton, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, viewportWidth) => {
113
122
  const styles = {
114
123
  zIndex: 1,
115
124
  position: 'absolute'
@@ -131,7 +140,9 @@ const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWi
131
140
  enablePeeking,
132
141
  enableDisplayMultipleItemsPerSlide,
133
142
  isAutoPlayEnabled,
134
- viewport
143
+ viewport,
144
+ maxWidth,
145
+ viewportWidth
135
146
  })
136
147
  };
137
148
  };
@@ -197,7 +208,7 @@ const getMaximumItemsForSlide = (enableDisplayMultipleItemsPerSlide, viewport) =
197
208
  }
198
209
  return _Constants.ITEMS_PER_VIEWPORT_XS_SM;
199
210
  };
200
- const selectRootContainerStyles = (enableHero, viewport) => {
211
+ const selectRootContainerStyles = (enableHero, viewport, enablePeeking) => {
201
212
  if (enableHero && viewport === 'xl' && _Platform.default.OS === 'web') {
202
213
  return {
203
214
  alignItems: 'center'
@@ -208,15 +219,25 @@ const selectRootContainerStyles = (enableHero, viewport) => {
208
219
  paddingHorizontal: 16
209
220
  };
210
221
  }
222
+ if (enablePeeking) {
223
+ return {
224
+ width: '100%'
225
+ };
226
+ }
211
227
  return {};
212
228
  };
213
- const selectMainContainerStyles = (enableHero, viewport, maxWidth) => {
214
- if (enableHero && viewport === 'xl' && _Platform.default.OS === 'web') {
229
+ const selectMainContainerStyles = (enableHero, viewport, maxWidth, enablePeeking) => {
230
+ if (enableHero && viewport === 'xl' && _Platform.default.OS === 'web' && !enablePeeking) {
215
231
  return {
216
232
  width: '100%',
217
233
  maxWidth: maxWidth || 1200
218
234
  };
219
235
  }
236
+ if (enablePeeking) {
237
+ return {
238
+ width: '100%'
239
+ };
240
+ }
220
241
  if (maxWidth !== null && maxWidth !== undefined) {
221
242
  return {
222
243
  maxWidth,
@@ -226,14 +247,20 @@ const selectMainContainerStyles = (enableHero, viewport, maxWidth) => {
226
247
  }
227
248
  return {};
228
249
  };
229
- const selectNavigationStyles = (tabs, enableHero, viewport) => {
250
+ const selectNavigationStyles = (tabs, enableHero, viewport, enablePeeking, maxWidth) => {
230
251
  let marginHorizontal = 0;
231
252
  if (enableHero && tabs) {
232
253
  marginHorizontal = viewport === 'xl' ? _Constants.LARGE_VIEWPORT_MARGIN : _Constants.DEFAULT_VIEWPORT_MARGIN;
233
254
  }
234
- return {
255
+ const styles = {
235
256
  marginHorizontal
236
257
  };
258
+ if (enablePeeking && maxWidth) {
259
+ styles.maxWidth = maxWidth;
260
+ styles.alignSelf = 'center';
261
+ styles.width = '100%';
262
+ }
263
+ return styles;
237
264
  };
238
265
 
239
266
  /**
@@ -242,23 +269,18 @@ const selectNavigationStyles = (tabs, enableHero, viewport) => {
242
269
  * @param {number} containerWidth - The width of the carousel container.
243
270
  * @param {boolean} enablePeeking - Flag indicating whether peeking is enabled.
244
271
  * @param {Object} viewport - The viewport configuration object used to determine peeking properties.
245
- * @param {React.MutableRefObject<number>} activeIndexRef - A ref object holding the current active index of the carousel.
272
+ * @param {number} maxWidth - The maximum width constraint for the carousel content.
246
273
  * @returns {number} The calculated final width of the carousel container.
247
274
  */
248
- const calculateFinalWidth = (containerWidth, enablePeeking, viewport, activeIndexRef) => {
275
+ const calculateFinalWidth = (containerWidth, enablePeeking, viewport, maxWidth) => {
249
276
  let finalWidth = containerWidth;
250
277
  if (enablePeeking) {
251
278
  const {
252
279
  peekingGap,
253
- peekingMiddleSpace,
254
- peekingMarginLeft
280
+ peekingMiddleSpace
255
281
  } = getPeekingProps(viewport);
256
- const slideWide = containerWidth - (peekingMiddleSpace * _Constants.PEEKING_MULTIPLIER + peekingGap * _Constants.PEEKING_MULTIPLIER);
257
- if (activeIndexRef.current === 0) {
258
- finalWidth = slideWide + peekingMarginLeft - peekingMiddleSpace;
259
- } else {
260
- finalWidth = slideWide + peekingGap;
261
- }
282
+ const baseWidth = maxWidth || containerWidth;
283
+ finalWidth = baseWidth - peekingMiddleSpace * _Constants.PEEKING_MULTIPLIER + peekingGap;
262
284
  }
263
285
  return finalWidth;
264
286
  };
@@ -369,6 +391,8 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
369
391
  autoPlay = false,
370
392
  enablePeeking = false,
371
393
  contentMaxWidth,
394
+ swipeReleaseStyle = _Constants.SWIPE_RELEASE_STYLES.INSTANT,
395
+ swipeReleaseDuration = _Constants.DEFAULT_SWIPE_RELEASE_DURATION,
372
396
  ...rest
373
397
  } = _ref3;
374
398
  let childrenArray = (0, _utils.unpackFragment)(children);
@@ -379,7 +403,10 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
379
403
  } = (0, _ThemeProvider.useTheme)();
380
404
  const contentMaxWidthValue = (0, _utils.useResponsiveProp)(contentMaxWidth);
381
405
  const responsiveWidth = (0, _utils.useResponsiveProp)(themeOptions?.contentMaxWidth);
382
- const maxWidth = (0, _utils.resolveContentMaxWidth)(contentMaxWidthValue, responsiveWidth);
406
+ let maxWidth = null;
407
+ if (enablePeeking || contentMaxWidth !== undefined) {
408
+ maxWidth = contentMaxWidthValue === undefined ? responsiveWidth : (0, _utils.resolveContentMaxWidth)(contentMaxWidthValue, responsiveWidth);
409
+ }
383
410
  const totalItems = getTotalItems(enableDisplayMultipleItemsPerSlide, childrenArray, viewport);
384
411
  const autoPlayFeatureEnabled = autoPlay && slideDuration > 0 && transitionDuration > 0 && totalItems > 1;
385
412
  // if `Carousel` only has one `Carousel.Item`, convert this to a single-item array
@@ -442,8 +469,16 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
442
469
  const [isCarouselPlaying, setisCarouselPlaying] = _react.default.useState(autoPlayFeatureEnabled);
443
470
  const isSwiping = _react.default.useRef(false);
444
471
  const autoPlayRef = _react.default.useRef(null);
472
+ const [rootContainerLayout, setRootContainerLayout] = _react.default.useState({
473
+ x: 0,
474
+ y: 0,
475
+ width: 0,
476
+ height: 0
477
+ });
478
+ const rootContainerLayoutRef = _react.default.useRef(rootContainerLayout);
445
479
  const isFirstSlide = !activeIndex;
446
480
  const isLastSlide = activeIndex + 1 >= totalItems;
481
+ const currentViewportWidth = rootContainerLayout.width;
447
482
  const handleAnimationStart = _react.default.useCallback(function () {
448
483
  if (typeof onAnimationStart === 'function') onAnimationStart(...arguments);
449
484
  setIsAnimating(true);
@@ -461,15 +496,15 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
461
496
  if (enablePeeking) {
462
497
  const {
463
498
  peekingGap,
464
- peekingMiddleSpace,
465
- peekingMarginLeft
499
+ peekingMiddleSpace
466
500
  } = getPeekingProps(viewport);
467
501
  let finalWidth;
468
- const slideWide = containerLayoutRef.current.width - (peekingMiddleSpace * _Constants.PEEKING_MULTIPLIER + peekingGap * _Constants.PEEKING_MULTIPLIER);
502
+ const baseWidth = maxWidth || containerLayoutRef.current.width;
503
+ const slideWide = baseWidth - peekingMiddleSpace * _Constants.PEEKING_MULTIPLIER;
469
504
  if (activeIndexRef.current === 0) {
470
505
  finalWidth = 0;
471
506
  } else {
472
- finalWidth = slideWide + peekingMarginLeft - peekingMiddleSpace + (slideWide + peekingGap) * (activeIndexRef.current - _Constants.ACTIVE_INDEX_OFFSET_MULTIPLIER);
507
+ finalWidth = (slideWide + peekingGap) * activeIndexRef.current;
473
508
  }
474
509
  animatedX.current = finalWidth * _Constants.NEGATIVE_MULTIPLIER;
475
510
  } else {
@@ -496,8 +531,9 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
496
531
  y: 0
497
532
  });
498
533
  }
499
- }, [pan, animatedX, heroPan, heroAnimatedX, enableHero, viewport, enablePeeking]);
500
- const animate = _react.default.useCallback((panToAnimate, toValue, toIndex) => {
534
+ }, [pan, animatedX, heroPan, heroAnimatedX, enableHero, viewport, enablePeeking, maxWidth]);
535
+ const animate = _react.default.useCallback(function (panToAnimate, toValue, toIndex) {
536
+ let isSwipeRelease = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
501
537
  const applicableTransitionDuration = isLastSlide && toIndex === 0 ? loopDuration : transitionDuration;
502
538
  const handleAnimationEndToIndex = function () {
503
539
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
@@ -505,10 +541,23 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
505
541
  }
506
542
  return handleAnimationEnd(toIndex, ...args);
507
543
  };
508
- if (reduceMotionRef.current || isSwiping.current) {
544
+ if (reduceMotionRef.current) {
545
+ _Animated.default.timing(panToAnimate, {
546
+ toValue,
547
+ duration: _Constants.INSTANT_ANIMATION_DURATION,
548
+ useNativeDriver: false
549
+ }).start(handleAnimationEndToIndex);
550
+ } else if (isSwipeRelease && swipeReleaseStyle === _Constants.SWIPE_RELEASE_STYLES.EASE_OUT) {
509
551
  _Animated.default.timing(panToAnimate, {
510
552
  toValue,
511
- duration: 1,
553
+ duration: swipeReleaseDuration,
554
+ easing: _Easing.default.out(_Easing.default.cubic),
555
+ useNativeDriver: false
556
+ }).start(handleAnimationEndToIndex);
557
+ } else if (isSwiping.current || isSwipeRelease) {
558
+ _Animated.default.timing(panToAnimate, {
559
+ toValue,
560
+ duration: _Constants.INSTANT_ANIMATION_DURATION,
512
561
  useNativeDriver: false
513
562
  }).start(handleAnimationEndToIndex);
514
563
  } else if (isAutoPlayEnabled) {
@@ -532,7 +581,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
532
581
  useNativeDriver: false
533
582
  }).start(handleAnimationEndToIndex);
534
583
  }
535
- }, [springConfig, handleAnimationEnd, transitionDuration, loopDuration, isLastSlide, isAutoPlayEnabled, enablePeeking, enableDisplayMultipleItemsPerSlide]);
584
+ }, [springConfig, handleAnimationEnd, transitionDuration, loopDuration, isLastSlide, isAutoPlayEnabled, enablePeeking, enableDisplayMultipleItemsPerSlide, swipeReleaseStyle, swipeReleaseDuration]);
536
585
  const stopAutoplay = _react.default.useCallback(() => {
537
586
  if (autoPlayRef?.current) {
538
587
  clearTimeout(autoPlayRef?.current);
@@ -555,25 +604,26 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
555
604
  };
556
605
  let skipChanges = !delta;
557
606
  let calcDelta = delta;
607
+ const isSwipeRelease = transitionMode === _Constants.TRANSITION_MODES.SWIPE;
558
608
  if (activeIndexRef.current <= 0 && delta < 0) {
559
- skipChanges = transitionMode !== TRANSITION_MODES.AUTOMATIC;
609
+ skipChanges = transitionMode !== _Constants.TRANSITION_MODES.AUTOMATIC;
560
610
  calcDelta = totalItems + delta;
561
611
  } else if (activeIndexRef.current + 1 >= totalItems && delta > 0) {
562
- skipChanges = transitionMode !== TRANSITION_MODES.AUTOMATIC;
612
+ skipChanges = transitionMode !== _Constants.TRANSITION_MODES.AUTOMATIC;
563
613
  calcDelta = -1 * activeIndexRef.current + delta - 1;
564
614
  }
565
615
  const index = activeIndexRef.current + calcDelta;
566
616
  if (skipChanges) {
567
617
  isTransitioningRef.current = true;
568
- animate(pan, toValue, index);
618
+ animate(pan, toValue, index, isSwipeRelease);
569
619
  if (enableHero) {
570
- animate(heroPan, toValue, index);
620
+ animate(heroPan, toValue, index, isSwipeRelease);
571
621
  }
572
622
  return calcDelta;
573
623
  }
574
624
  stopAutoplay();
575
625
  setActiveIndex(index);
576
- const finalWidth = calculateFinalWidth(containerLayoutRef.current.width, enablePeeking, viewport, activeIndexRef);
626
+ const finalWidth = calculateFinalWidth(containerLayoutRef.current.width, enablePeeking, viewport, maxWidth);
577
627
  toValue.x = finalWidth * -1 * calcDelta;
578
628
  const heroToValue = {
579
629
  x: 0,
@@ -581,33 +631,33 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
581
631
  };
582
632
  heroToValue.x = heroContainerLayoutRef.current.width * -1 * calcDelta;
583
633
  isTransitioningRef.current = true;
584
- animate(pan, toValue, index);
634
+ animate(pan, toValue, index, isSwipeRelease);
585
635
  if (enableHero) {
586
- animate(heroPan, heroToValue, index);
636
+ animate(heroPan, heroToValue, index, isSwipeRelease);
587
637
  }
588
638
  if (isCarouselPlaying) {
589
639
  stopAutoplay();
590
- if (index === 0 && activeIndexRef.current + 1 === totalItems && transitionMode === TRANSITION_MODES.AUTOMATIC) {
640
+ if (index === 0 && activeIndexRef.current + 1 === totalItems && transitionMode === _Constants.TRANSITION_MODES.AUTOMATIC) {
591
641
  setisCarouselPlaying(false);
592
642
  } else if (isAutoPlayEnabled) {
593
643
  autoPlayRef.current = setTimeout(() => {
594
644
  updateOffset();
595
645
  handleAnimationStart(activeIndexRef.current);
596
- updateIndex(slideDuration < 0 ? -1 : 1, TRANSITION_MODES.AUTOMATIC);
646
+ updateIndex(slideDuration < 0 ? -1 : 1, _Constants.TRANSITION_MODES.AUTOMATIC);
597
647
  triggerRefocus();
598
648
  }, Math.abs(slideDuration) * 1000);
599
649
  }
600
650
  }
601
651
  if (onIndexChanged) onIndexChanged(calcDelta, index);
602
652
  return calcDelta;
603
- }, [handleAnimationStart, triggerRefocus, slideDuration, updateOffset, animate, totalItems, onIndexChanged, isCarouselPlaying, stopAutoplay, isAutoPlayEnabled, viewport, enablePeeking, pan, heroPan, enableHero]);
653
+ }, [handleAnimationStart, triggerRefocus, slideDuration, updateOffset, animate, totalItems, onIndexChanged, isCarouselPlaying, stopAutoplay, isAutoPlayEnabled, viewport, enablePeeking, pan, heroPan, enableHero, maxWidth]);
604
654
  const startAutoplay = _react.default.useCallback(() => {
605
655
  stopAutoplay();
606
656
  if (isAutoPlayEnabled) {
607
657
  autoPlayRef.current = setTimeout(() => {
608
658
  updateOffset();
609
659
  handleAnimationStart(activeIndexRef.current);
610
- updateIndex(slideDuration < 0 ? -1 : 1, TRANSITION_MODES.AUTOMATIC);
660
+ updateIndex(slideDuration < 0 ? -1 : 1, _Constants.TRANSITION_MODES.AUTOMATIC);
611
661
  triggerRefocus();
612
662
  }, Math.abs(slideDuration) * 1000);
613
663
  }
@@ -620,7 +670,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
620
670
  }, [updateIndex, updateOffset, handleAnimationStart, triggerRefocus]);
621
671
  const goToNeighboring = _react.default.useCallback(function () {
622
672
  let toPrev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
623
- let transitionMode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : TRANSITION_MODES.MANUAL;
673
+ let transitionMode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _Constants.TRANSITION_MODES.MANUAL;
624
674
  fixOffsetAndGo(toPrev ? -1 : 1, transitionMode);
625
675
  }, [fixOffsetAndGo]);
626
676
  _react.default.useEffect(() => {
@@ -635,6 +685,9 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
635
685
  _react.default.useEffect(() => {
636
686
  heroContainerLayoutRef.current = heroContainerLayout;
637
687
  }, [heroContainerLayout]);
688
+ _react.default.useEffect(() => {
689
+ rootContainerLayoutRef.current = rootContainerLayout;
690
+ }, [rootContainerLayout]);
638
691
  _react.default.useEffect(() => {
639
692
  pan.x.addListener(_ref5 => {
640
693
  let {
@@ -743,6 +796,25 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
743
796
  } = _ref11;
744
797
  return setPreviousNextNavigationButtonWidth(width);
745
798
  };
799
+ const onRootContainerLayout = _ref12 => {
800
+ let {
801
+ nativeEvent: {
802
+ layout: {
803
+ x,
804
+ y,
805
+ width,
806
+ height
807
+ }
808
+ }
809
+ } = _ref12;
810
+ return setRootContainerLayout(prevState => ({
811
+ ...prevState,
812
+ x,
813
+ y,
814
+ width,
815
+ height
816
+ }));
817
+ };
746
818
  const isSwipeAllowed = _react.default.useCallback(() => {
747
819
  if (totalItems === 1) {
748
820
  return false;
@@ -780,16 +852,16 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
780
852
  startAutoplay();
781
853
  }
782
854
  const correction = gesture.moveX - gesture.x0;
855
+ isSwiping.current = false;
783
856
  if (Math.abs(correction) < containerLayoutRef.current.width * minDistanceForAction) {
784
857
  animate(pan, {
785
858
  x: 0,
786
859
  y: 0
787
- }, 0);
860
+ }, activeIndexRef.current, true);
788
861
  } else {
789
862
  const delta = correction > 0 ? -1 : 1;
790
- updateIndex(delta, TRANSITION_MODES.SWIPE);
863
+ updateIndex(delta, _Constants.TRANSITION_MODES.SWIPE);
791
864
  }
792
- isSwiping.current = false;
793
865
  }
794
866
  }), [pan, updateIndex, updateOffset, animate, isSwipeAllowed, minDistanceForAction, handleAnimationStart, minDistanceToCapture, startAutoplay, stopAutoplay, isCarouselPlaying]);
795
867
  const heroPanResponder = _react.default.useMemo(() => _PanResponder.default.create({
@@ -820,16 +892,16 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
820
892
  startAutoplay();
821
893
  }
822
894
  const correction = gesture.moveX - gesture.x0;
895
+ isSwiping.current = false;
823
896
  if (Math.abs(correction) < containerLayoutRef.current.width * minDistanceForAction) {
824
897
  animate(heroPan, {
825
898
  x: 0,
826
899
  y: 0
827
- }, 0);
900
+ }, activeIndexRef.current, true);
828
901
  } else {
829
902
  const delta = correction > 0 ? -1 : 1;
830
- updateIndex(delta, TRANSITION_MODES.SWIPE);
903
+ updateIndex(delta, _Constants.TRANSITION_MODES.SWIPE);
831
904
  }
832
- isSwiping.current = false;
833
905
  }
834
906
  }), [heroPan, updateIndex, updateOffset, animate, isSwipeAllowed, minDistanceForAction, handleAnimationStart, minDistanceToCapture, startAutoplay, stopAutoplay, isCarouselPlaying]);
835
907
  const goToNext = _react.default.useCallback(() => {
@@ -842,7 +914,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
842
914
  let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
843
915
  const delta = index - activeIndexRef.current;
844
916
  if (delta) {
845
- fixOffsetAndGo(delta, TRANSITION_MODES.MANUAL);
917
+ fixOffsetAndGo(delta, _Constants.TRANSITION_MODES.MANUAL);
846
918
  }
847
919
  }, [fixOffsetAndGo]);
848
920
 
@@ -908,9 +980,10 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
908
980
  }
909
981
  }, [isTransitioningRef]);
910
982
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
911
- style: selectRootContainerStyles(enableHero, viewport),
983
+ style: selectRootContainerStyles(enableHero, viewport, enablePeeking),
984
+ onLayout: onRootContainerLayout,
912
985
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
913
- style: selectMainContainerStyles(enableHero, viewport, maxWidth),
986
+ style: selectMainContainerStyles(enableHero, viewport, maxWidth, enablePeeking),
914
987
  children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_CarouselContext.CarouselProvider, {
915
988
  activeIndex: activeIndex,
916
989
  goTo: goTo,
@@ -922,6 +995,8 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
922
995
  refocus: refocus,
923
996
  width: containerLayout.width,
924
997
  maximumItemsForSlide: getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport),
998
+ maxWidth: maxWidth,
999
+ viewportWidth: currentViewportWidth,
925
1000
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
926
1001
  style: [staticStyles.root, {
927
1002
  ...(_Platform.default.OS === 'web' ? {
@@ -944,7 +1019,9 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
944
1019
  enablePeeking,
945
1020
  enableDisplayMultipleItemsPerSlide,
946
1021
  isAutoPlayEnabled,
947
- viewport
1022
+ viewport,
1023
+ maxWidth,
1024
+ viewportWidth: currentViewportWidth
948
1025
  })],
949
1026
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconButton.default, {
950
1027
  icon: isCarouselPlaying ? pauseIcon : playIcon,
@@ -953,7 +1030,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
953
1030
  onPress: onAnimationControlButtonPress
954
1031
  })
955
1032
  }) : null, showPreviousNextNavigation && totalItems > 1 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
956
- style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, true, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport),
1033
+ style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, true, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, currentViewportWidth),
957
1034
  testID: "previous-button-container",
958
1035
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconButton.default, {
959
1036
  onLayout: onPreviousNextNavigationButtonLayout,
@@ -991,16 +1068,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
991
1068
  children: childrenArray.map((element, index) => {
992
1069
  let hidden = !isAnimating && index !== activeIndex;
993
1070
  if (enablePeeking && !isAnimating) {
994
- if (enableDisplayMultipleItemsPerSlide) {
995
- const maxItemsForSlide = getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport);
996
- if (index >= activeIndex * maxItemsForSlide - 1 && index < activeIndex * maxItemsForSlide + maxItemsForSlide + 1) {
997
- hidden = false;
998
- } else {
999
- hidden = true;
1000
- }
1001
- } else if (index >= activeIndex - 1 && index <= activeIndex + 1) {
1002
- hidden = false;
1003
- }
1071
+ hidden = false;
1004
1072
  } else if (!enablePeeking && enableDisplayMultipleItemsPerSlide && !isAnimating) {
1005
1073
  const maxItemsForSlide = getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport);
1006
1074
  if (index >= activeIndex * maxItemsForSlide && index < activeIndex * maxItemsForSlide + maxItemsForSlide) {
@@ -1022,7 +1090,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
1022
1090
  })
1023
1091
  })
1024
1092
  }), showPreviousNextNavigation && totalItems > 1 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
1025
- style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, false, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport),
1093
+ style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, false, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, currentViewportWidth),
1026
1094
  testID: "next-button-container",
1027
1095
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconButton.default, {
1028
1096
  onLayout: onPreviousNextNavigationButtonLayout,
@@ -1034,7 +1102,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
1034
1102
  })
1035
1103
  }) : null]
1036
1104
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
1037
- style: selectNavigationStyles(tabs, enableHero, viewport),
1105
+ style: selectNavigationStyles(tabs, enableHero, viewport, enablePeeking, maxWidth),
1038
1106
  children: showPanelNavigation ? activePanelNavigation : null
1039
1107
  })]
1040
1108
  })
@@ -1285,7 +1353,23 @@ Carousel.propTypes = {
1285
1353
  md: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
1286
1354
  sm: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number]),
1287
1355
  xs: _propTypes.default.oneOfType([_propTypes.default.oneOf(['max', 'full']), _propTypes.default.number])
1288
- })
1356
+ }),
1357
+ /**
1358
+ * Animation style for swipe release transitions.
1359
+ * - `'instant'`: Immediate snap to position (current default)
1360
+ * - `'ease-out'`: Smooth deceleration animation
1361
+ * - Default value is `'instant'`
1362
+ * - Use `swipeReleaseDuration` to customize the animation duration when using `'ease-out'`
1363
+ *
1364
+ * @deprecated The default will change to `'ease-out'` in Q2 2026 (introduced Jan 2026).
1365
+ */
1366
+ swipeReleaseStyle: _propTypes.default.oneOf(['instant', 'ease-out']),
1367
+ /**
1368
+ * Duration in milliseconds of the ease-out animation when releasing a swipe gesture.
1369
+ * Only applies when `swipeReleaseStyle` is set to `'ease-out'`.
1370
+ * - Default value is `500` (500ms)
1371
+ */
1372
+ swipeReleaseDuration: _propTypes.default.number
1289
1373
  };
1290
1374
  Carousel.Item = _CarouselItem.default;
1291
1375
  Carousel.displayName = 'Carousel';
@@ -22,7 +22,9 @@ const CarouselProvider = _ref => {
22
22
  themeTokens,
23
23
  totalItems,
24
24
  width,
25
- maximumItemsForSlide
25
+ maximumItemsForSlide,
26
+ maxWidth,
27
+ viewportWidth
26
28
  } = _ref;
27
29
  const value = _react.default.useMemo(() => ({
28
30
  activeIndex,
@@ -33,8 +35,10 @@ const CarouselProvider = _ref => {
33
35
  themeTokens,
34
36
  totalItems,
35
37
  width,
36
- maximumItemsForSlide
37
- }), [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width, maximumItemsForSlide]);
38
+ maximumItemsForSlide,
39
+ maxWidth,
40
+ viewportWidth
41
+ }), [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width, maximumItemsForSlide, maxWidth, viewportWidth]);
38
42
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(CarouselContext.Provider, {
39
43
  value: value,
40
44
  children: children
@@ -58,5 +62,7 @@ CarouselProvider.propTypes = {
58
62
  themeTokens: (0, _utils.getTokensPropType)('Carousel'),
59
63
  totalItems: _propTypes.default.number.isRequired,
60
64
  width: _propTypes.default.number.isRequired,
61
- maximumItemsForSlide: _propTypes.default.number
65
+ maximumItemsForSlide: _propTypes.default.number,
66
+ maxWidth: _propTypes.default.number,
67
+ viewportWidth: _propTypes.default.number
62
68
  };
@@ -19,26 +19,26 @@ const selectContainerStyle = _ref => {
19
19
  width,
20
20
  elementIndex,
21
21
  enablePeeking,
22
- peekingMarginLeft,
23
22
  peekingGap,
24
23
  hidden,
25
24
  enableDisplayMultipleItemsPerSlide,
26
25
  viewport,
27
- peekingMiddleSpace
26
+ peekingMiddleSpace,
27
+ maxWidth,
28
+ viewportWidth
28
29
  } = _ref;
29
30
  let adjustedWidth = width;
30
31
  let marginLeft = 0;
31
32
  if (enablePeeking) {
32
33
  const isFirst = elementIndex === 0;
33
- adjustedWidth = width - (peekingMiddleSpace * 2 + peekingGap * 2);
34
+ const baseWidth = maxWidth || width;
35
+ adjustedWidth = baseWidth - peekingMiddleSpace * 2;
34
36
  if (isFirst) {
35
- marginLeft = peekingMarginLeft;
37
+ marginLeft = peekingMiddleSpace + (viewportWidth - maxWidth) / 2;
36
38
  } else {
37
39
  marginLeft = peekingGap;
38
40
  }
39
41
  }
40
-
41
- // Adjust width and margins for multiple items per slide.
42
42
  if (enableDisplayMultipleItemsPerSlide) {
43
43
  switch (viewport) {
44
44
  case 'xs':
@@ -96,7 +96,9 @@ const CarouselItem = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
96
96
  width,
97
97
  activeIndex,
98
98
  goTo,
99
- maximumItemsForSlide
99
+ maximumItemsForSlide,
100
+ maxWidth,
101
+ viewportWidth
100
102
  } = (0, _CarouselContext.useCarousel)();
101
103
  const selectedProps = selectProps({
102
104
  ...rest,
@@ -139,6 +141,8 @@ const CarouselItem = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
139
141
  enablePeeking,
140
142
  enableDisplayMultipleItemsPerSlide,
141
143
  viewport,
144
+ maxWidth,
145
+ viewportWidth,
142
146
  ...peekingProps
143
147
  }),
144
148
  ...selectedProps,
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.PEEKING_MULTIPLIER = exports.NEGATIVE_MULTIPLIER = exports.LARGE_VIEWPORT_MARGIN = exports.ITEMS_PER_VIEWPORT_XS_SM = exports.ITEMS_PER_VIEWPORT_MD = exports.ITEMS_PER_VIEWPORT_LG_XL = exports.HERO_POSITION_OFFSET = exports.GAP_BETWEEN_ITEMS = exports.DEFAULT_VIEWPORT_MARGIN = exports.DEFAULT_POSITION_OFFSET = exports.ACTIVE_INDEX_OFFSET_MULTIPLIER = void 0;
6
+ exports.TRANSITION_MODES = exports.SWIPE_RELEASE_STYLES = exports.POSITION_VARIANTS = exports.POSITION_PROPERTIES = exports.PEEKING_MULTIPLIER = exports.NEGATIVE_MULTIPLIER = exports.LARGE_VIEWPORT_MARGIN = exports.ITEMS_PER_VIEWPORT_XS_SM = exports.ITEMS_PER_VIEWPORT_MD = exports.ITEMS_PER_VIEWPORT_LG_XL = exports.INSTANT_ANIMATION_DURATION = exports.HERO_POSITION_OFFSET = exports.GAP_BETWEEN_ITEMS = exports.DEFAULT_VIEWPORT_MARGIN = exports.DEFAULT_SWIPE_RELEASE_DURATION = exports.DEFAULT_POSITION_OFFSET = exports.ACTIVE_INDEX_OFFSET_MULTIPLIER = void 0;
7
7
  const ITEMS_PER_VIEWPORT_XS_SM = exports.ITEMS_PER_VIEWPORT_XS_SM = 1;
8
8
  const ITEMS_PER_VIEWPORT_MD = exports.ITEMS_PER_VIEWPORT_MD = 2;
9
9
  const ITEMS_PER_VIEWPORT_LG_XL = exports.ITEMS_PER_VIEWPORT_LG_XL = 3;
@@ -14,4 +14,24 @@ const LARGE_VIEWPORT_MARGIN = exports.LARGE_VIEWPORT_MARGIN = 40;
14
14
  const DEFAULT_VIEWPORT_MARGIN = exports.DEFAULT_VIEWPORT_MARGIN = 10;
15
15
  const PEEKING_MULTIPLIER = exports.PEEKING_MULTIPLIER = 2;
16
16
  const ACTIVE_INDEX_OFFSET_MULTIPLIER = exports.ACTIVE_INDEX_OFFSET_MULTIPLIER = 1;
17
- const NEGATIVE_MULTIPLIER = exports.NEGATIVE_MULTIPLIER = -1;
17
+ const NEGATIVE_MULTIPLIER = exports.NEGATIVE_MULTIPLIER = -1;
18
+ const TRANSITION_MODES = exports.TRANSITION_MODES = {
19
+ MANUAL: 'manual',
20
+ AUTOMATIC: 'automatic',
21
+ SWIPE: 'swipe'
22
+ };
23
+ const SWIPE_RELEASE_STYLES = exports.SWIPE_RELEASE_STYLES = {
24
+ INSTANT: 'instant',
25
+ EASE_OUT: 'ease-out'
26
+ };
27
+ const INSTANT_ANIMATION_DURATION = exports.INSTANT_ANIMATION_DURATION = 1;
28
+ const DEFAULT_SWIPE_RELEASE_DURATION = exports.DEFAULT_SWIPE_RELEASE_DURATION = 500;
29
+ const POSITION_VARIANTS = exports.POSITION_VARIANTS = {
30
+ EDGE: 'edge',
31
+ INSIDE: 'inside',
32
+ OUTSIDE: 'outside'
33
+ };
34
+ const POSITION_PROPERTIES = exports.POSITION_PROPERTIES = {
35
+ LEFT: 'left',
36
+ RIGHT: 'right'
37
+ };