@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.
- package/CHANGELOG.md +28 -1
- package/lib/cjs/Card/Card.js +34 -13
- package/lib/cjs/Card/CardBase.js +78 -11
- package/lib/cjs/Card/PressableCardBase.js +147 -8
- package/lib/cjs/Carousel/Carousel.js +161 -77
- package/lib/cjs/Carousel/CarouselContext.js +10 -4
- package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +11 -7
- package/lib/cjs/Carousel/Constants.js +22 -2
- package/lib/cjs/Checkbox/Checkbox.js +43 -13
- package/lib/cjs/InputSupports/InputSupports.js +2 -1
- package/lib/cjs/List/List.js +24 -9
- package/lib/cjs/List/ListItem.js +18 -1
- package/lib/cjs/List/ListItemBase.js +27 -8
- package/lib/cjs/List/ListItemMark.js +33 -62
- package/lib/cjs/List/PressableListItemBase.js +1 -0
- package/lib/cjs/PriceLockup/PriceLockup.js +1 -1
- package/lib/esm/Card/Card.js +34 -13
- package/lib/esm/Card/CardBase.js +78 -11
- package/lib/esm/Card/PressableCardBase.js +148 -9
- package/lib/esm/Carousel/Carousel.js +153 -69
- package/lib/esm/Carousel/CarouselContext.js +10 -4
- package/lib/esm/Carousel/CarouselItem/CarouselItem.js +11 -7
- package/lib/esm/Carousel/Constants.js +21 -1
- package/lib/esm/Checkbox/Checkbox.js +43 -13
- package/lib/esm/InputSupports/InputSupports.js +2 -1
- package/lib/esm/List/List.js +24 -9
- package/lib/esm/List/ListItem.js +19 -2
- package/lib/esm/List/ListItemBase.js +27 -8
- package/lib/esm/List/ListItemMark.js +33 -62
- package/lib/esm/List/PressableListItemBase.js +1 -0
- package/lib/esm/PriceLockup/PriceLockup.js +1 -1
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/Card/Card.jsx +29 -7
- package/src/Card/CardBase.jsx +88 -8
- package/src/Card/PressableCardBase.jsx +135 -9
- package/src/Carousel/Carousel.jsx +185 -88
- package/src/Carousel/CarouselContext.jsx +12 -4
- package/src/Carousel/CarouselItem/CarouselItem.jsx +10 -6
- package/src/Carousel/Constants.js +24 -0
- package/src/Checkbox/Checkbox.jsx +29 -7
- package/src/InputSupports/InputSupports.jsx +6 -1
- package/src/List/List.jsx +33 -9
- package/src/List/ListItem.jsx +33 -11
- package/src/List/ListItemBase.jsx +33 -9
- package/src/List/ListItemMark.jsx +32 -53
- package/src/List/PressableListItemBase.jsx +1 -0
- package/src/PriceLockup/PriceLockup.jsx +1 -1
|
@@ -5,6 +5,7 @@ import PanResponder from "react-native-web/dist/exports/PanResponder";
|
|
|
5
5
|
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
6
6
|
import Platform from "react-native-web/dist/exports/Platform";
|
|
7
7
|
import Dimensions from "react-native-web/dist/exports/Dimensions";
|
|
8
|
+
import Easing from "react-native-web/dist/exports/Easing";
|
|
8
9
|
import PropTypes from 'prop-types';
|
|
9
10
|
import { useThemeTokens, useTheme } from '../ThemeProvider';
|
|
10
11
|
import { useViewport } from '../ViewportProvider';
|
|
@@ -21,13 +22,8 @@ import CarouselTabsPanel from './CarouselTabs/CarouselTabsPanel';
|
|
|
21
22
|
import CarouselTabsPanelItem from './CarouselTabs/CarouselTabsPanelItem';
|
|
22
23
|
import dictionary from './dictionary';
|
|
23
24
|
import Box from '../Box';
|
|
24
|
-
import { ITEMS_PER_VIEWPORT_XS_SM, ITEMS_PER_VIEWPORT_MD, ITEMS_PER_VIEWPORT_LG_XL, DEFAULT_POSITION_OFFSET, LARGE_VIEWPORT_MARGIN, DEFAULT_VIEWPORT_MARGIN, PEEKING_MULTIPLIER,
|
|
25
|
+
import { ITEMS_PER_VIEWPORT_XS_SM, ITEMS_PER_VIEWPORT_MD, ITEMS_PER_VIEWPORT_LG_XL, DEFAULT_POSITION_OFFSET, LARGE_VIEWPORT_MARGIN, DEFAULT_VIEWPORT_MARGIN, PEEKING_MULTIPLIER, NEGATIVE_MULTIPLIER, TRANSITION_MODES, SWIPE_RELEASE_STYLES, INSTANT_ANIMATION_DURATION, DEFAULT_SWIPE_RELEASE_DURATION, POSITION_VARIANTS, POSITION_PROPERTIES } from './Constants';
|
|
25
26
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
26
|
-
const TRANSITION_MODES = {
|
|
27
|
-
MANUAL: 'manual',
|
|
28
|
-
AUTOMATIC: 'automatic',
|
|
29
|
-
SWIPE: 'swipe'
|
|
30
|
-
};
|
|
31
27
|
const staticStyles = StyleSheet.create({
|
|
32
28
|
root: {
|
|
33
29
|
backgroundColor: 'transparent',
|
|
@@ -76,7 +72,7 @@ const selectHeroContainerStyles = (width, hidden) => ({
|
|
|
76
72
|
width,
|
|
77
73
|
visibility: hidden ? 'hidden' : 'visible'
|
|
78
74
|
});
|
|
79
|
-
const getDynamicPositionProperty = areStylesAppliedOnPreviousButton => areStylesAppliedOnPreviousButton ?
|
|
75
|
+
const getDynamicPositionProperty = areStylesAppliedOnPreviousButton => areStylesAppliedOnPreviousButton ? POSITION_PROPERTIES.LEFT : POSITION_PROPERTIES.RIGHT;
|
|
80
76
|
const selectControlButtonPositionStyles = _ref => {
|
|
81
77
|
let {
|
|
82
78
|
positionVariant,
|
|
@@ -86,23 +82,36 @@ const selectControlButtonPositionStyles = _ref => {
|
|
|
86
82
|
enablePeeking,
|
|
87
83
|
enableDisplayMultipleItemsPerSlide,
|
|
88
84
|
isAutoPlayEnabled,
|
|
89
|
-
viewport
|
|
85
|
+
viewport,
|
|
86
|
+
maxWidth,
|
|
87
|
+
viewportWidth
|
|
90
88
|
} = _ref;
|
|
91
89
|
const styles = {};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
90
|
+
let positionOffset = 0;
|
|
91
|
+
if (positionVariant === POSITION_VARIANTS.EDGE) {
|
|
92
|
+
positionOffset = -1 * (buttonWidth / 2);
|
|
93
|
+
} else if (positionVariant === POSITION_VARIANTS.INSIDE) {
|
|
94
|
+
positionOffset = DEFAULT_POSITION_OFFSET;
|
|
95
|
+
} else if (positionVariant === POSITION_VARIANTS.OUTSIDE) {
|
|
97
96
|
if (enablePeeking || enableDisplayMultipleItemsPerSlide || isAutoPlayEnabled && viewport === 'xs') {
|
|
98
|
-
|
|
97
|
+
positionOffset = 0;
|
|
99
98
|
} else {
|
|
100
|
-
|
|
99
|
+
positionOffset = -1 * (spaceBetweenSlideAndButton + buttonWidth);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (enablePeeking) {
|
|
103
|
+
if (positionProperty === POSITION_PROPERTIES.RIGHT) {
|
|
104
|
+
const rightMargin = (viewportWidth - maxWidth) / 2;
|
|
105
|
+
positionOffset += rightMargin;
|
|
106
|
+
} else if (positionProperty === POSITION_PROPERTIES.LEFT) {
|
|
107
|
+
const leftMargin = (viewportWidth - maxWidth) / 2;
|
|
108
|
+
positionOffset += leftMargin;
|
|
101
109
|
}
|
|
102
110
|
}
|
|
111
|
+
styles[positionProperty] = positionOffset;
|
|
103
112
|
return styles;
|
|
104
113
|
};
|
|
105
|
-
const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, areStylesAppliedOnPreviousButton, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport) => {
|
|
114
|
+
const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, areStylesAppliedOnPreviousButton, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, viewportWidth) => {
|
|
106
115
|
const styles = {
|
|
107
116
|
zIndex: 1,
|
|
108
117
|
position: 'absolute'
|
|
@@ -124,7 +133,9 @@ const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWi
|
|
|
124
133
|
enablePeeking,
|
|
125
134
|
enableDisplayMultipleItemsPerSlide,
|
|
126
135
|
isAutoPlayEnabled,
|
|
127
|
-
viewport
|
|
136
|
+
viewport,
|
|
137
|
+
maxWidth,
|
|
138
|
+
viewportWidth
|
|
128
139
|
})
|
|
129
140
|
};
|
|
130
141
|
};
|
|
@@ -190,7 +201,7 @@ const getMaximumItemsForSlide = (enableDisplayMultipleItemsPerSlide, viewport) =
|
|
|
190
201
|
}
|
|
191
202
|
return ITEMS_PER_VIEWPORT_XS_SM;
|
|
192
203
|
};
|
|
193
|
-
const selectRootContainerStyles = (enableHero, viewport) => {
|
|
204
|
+
const selectRootContainerStyles = (enableHero, viewport, enablePeeking) => {
|
|
194
205
|
if (enableHero && viewport === 'xl' && Platform.OS === 'web') {
|
|
195
206
|
return {
|
|
196
207
|
alignItems: 'center'
|
|
@@ -201,15 +212,25 @@ const selectRootContainerStyles = (enableHero, viewport) => {
|
|
|
201
212
|
paddingHorizontal: 16
|
|
202
213
|
};
|
|
203
214
|
}
|
|
215
|
+
if (enablePeeking) {
|
|
216
|
+
return {
|
|
217
|
+
width: '100%'
|
|
218
|
+
};
|
|
219
|
+
}
|
|
204
220
|
return {};
|
|
205
221
|
};
|
|
206
|
-
const selectMainContainerStyles = (enableHero, viewport, maxWidth) => {
|
|
207
|
-
if (enableHero && viewport === 'xl' && Platform.OS === 'web') {
|
|
222
|
+
const selectMainContainerStyles = (enableHero, viewport, maxWidth, enablePeeking) => {
|
|
223
|
+
if (enableHero && viewport === 'xl' && Platform.OS === 'web' && !enablePeeking) {
|
|
208
224
|
return {
|
|
209
225
|
width: '100%',
|
|
210
226
|
maxWidth: maxWidth || 1200
|
|
211
227
|
};
|
|
212
228
|
}
|
|
229
|
+
if (enablePeeking) {
|
|
230
|
+
return {
|
|
231
|
+
width: '100%'
|
|
232
|
+
};
|
|
233
|
+
}
|
|
213
234
|
if (maxWidth !== null && maxWidth !== undefined) {
|
|
214
235
|
return {
|
|
215
236
|
maxWidth,
|
|
@@ -219,14 +240,20 @@ const selectMainContainerStyles = (enableHero, viewport, maxWidth) => {
|
|
|
219
240
|
}
|
|
220
241
|
return {};
|
|
221
242
|
};
|
|
222
|
-
const selectNavigationStyles = (tabs, enableHero, viewport) => {
|
|
243
|
+
const selectNavigationStyles = (tabs, enableHero, viewport, enablePeeking, maxWidth) => {
|
|
223
244
|
let marginHorizontal = 0;
|
|
224
245
|
if (enableHero && tabs) {
|
|
225
246
|
marginHorizontal = viewport === 'xl' ? LARGE_VIEWPORT_MARGIN : DEFAULT_VIEWPORT_MARGIN;
|
|
226
247
|
}
|
|
227
|
-
|
|
248
|
+
const styles = {
|
|
228
249
|
marginHorizontal
|
|
229
250
|
};
|
|
251
|
+
if (enablePeeking && maxWidth) {
|
|
252
|
+
styles.maxWidth = maxWidth;
|
|
253
|
+
styles.alignSelf = 'center';
|
|
254
|
+
styles.width = '100%';
|
|
255
|
+
}
|
|
256
|
+
return styles;
|
|
230
257
|
};
|
|
231
258
|
|
|
232
259
|
/**
|
|
@@ -235,23 +262,18 @@ const selectNavigationStyles = (tabs, enableHero, viewport) => {
|
|
|
235
262
|
* @param {number} containerWidth - The width of the carousel container.
|
|
236
263
|
* @param {boolean} enablePeeking - Flag indicating whether peeking is enabled.
|
|
237
264
|
* @param {Object} viewport - The viewport configuration object used to determine peeking properties.
|
|
238
|
-
* @param {
|
|
265
|
+
* @param {number} maxWidth - The maximum width constraint for the carousel content.
|
|
239
266
|
* @returns {number} The calculated final width of the carousel container.
|
|
240
267
|
*/
|
|
241
|
-
const calculateFinalWidth = (containerWidth, enablePeeking, viewport,
|
|
268
|
+
const calculateFinalWidth = (containerWidth, enablePeeking, viewport, maxWidth) => {
|
|
242
269
|
let finalWidth = containerWidth;
|
|
243
270
|
if (enablePeeking) {
|
|
244
271
|
const {
|
|
245
272
|
peekingGap,
|
|
246
|
-
peekingMiddleSpace
|
|
247
|
-
peekingMarginLeft
|
|
273
|
+
peekingMiddleSpace
|
|
248
274
|
} = getPeekingProps(viewport);
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
finalWidth = slideWide + peekingMarginLeft - peekingMiddleSpace;
|
|
252
|
-
} else {
|
|
253
|
-
finalWidth = slideWide + peekingGap;
|
|
254
|
-
}
|
|
275
|
+
const baseWidth = maxWidth || containerWidth;
|
|
276
|
+
finalWidth = baseWidth - peekingMiddleSpace * PEEKING_MULTIPLIER + peekingGap;
|
|
255
277
|
}
|
|
256
278
|
return finalWidth;
|
|
257
279
|
};
|
|
@@ -362,6 +384,8 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
362
384
|
autoPlay = false,
|
|
363
385
|
enablePeeking = false,
|
|
364
386
|
contentMaxWidth,
|
|
387
|
+
swipeReleaseStyle = SWIPE_RELEASE_STYLES.INSTANT,
|
|
388
|
+
swipeReleaseDuration = DEFAULT_SWIPE_RELEASE_DURATION,
|
|
365
389
|
...rest
|
|
366
390
|
} = _ref3;
|
|
367
391
|
let childrenArray = unpackFragment(children);
|
|
@@ -372,7 +396,10 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
372
396
|
} = useTheme();
|
|
373
397
|
const contentMaxWidthValue = useResponsiveProp(contentMaxWidth);
|
|
374
398
|
const responsiveWidth = useResponsiveProp(themeOptions?.contentMaxWidth);
|
|
375
|
-
|
|
399
|
+
let maxWidth = null;
|
|
400
|
+
if (enablePeeking || contentMaxWidth !== undefined) {
|
|
401
|
+
maxWidth = contentMaxWidthValue === undefined ? responsiveWidth : resolveContentMaxWidth(contentMaxWidthValue, responsiveWidth);
|
|
402
|
+
}
|
|
376
403
|
const totalItems = getTotalItems(enableDisplayMultipleItemsPerSlide, childrenArray, viewport);
|
|
377
404
|
const autoPlayFeatureEnabled = autoPlay && slideDuration > 0 && transitionDuration > 0 && totalItems > 1;
|
|
378
405
|
// if `Carousel` only has one `Carousel.Item`, convert this to a single-item array
|
|
@@ -435,8 +462,16 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
435
462
|
const [isCarouselPlaying, setisCarouselPlaying] = React.useState(autoPlayFeatureEnabled);
|
|
436
463
|
const isSwiping = React.useRef(false);
|
|
437
464
|
const autoPlayRef = React.useRef(null);
|
|
465
|
+
const [rootContainerLayout, setRootContainerLayout] = React.useState({
|
|
466
|
+
x: 0,
|
|
467
|
+
y: 0,
|
|
468
|
+
width: 0,
|
|
469
|
+
height: 0
|
|
470
|
+
});
|
|
471
|
+
const rootContainerLayoutRef = React.useRef(rootContainerLayout);
|
|
438
472
|
const isFirstSlide = !activeIndex;
|
|
439
473
|
const isLastSlide = activeIndex + 1 >= totalItems;
|
|
474
|
+
const currentViewportWidth = rootContainerLayout.width;
|
|
440
475
|
const handleAnimationStart = React.useCallback(function () {
|
|
441
476
|
if (typeof onAnimationStart === 'function') onAnimationStart(...arguments);
|
|
442
477
|
setIsAnimating(true);
|
|
@@ -454,15 +489,15 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
454
489
|
if (enablePeeking) {
|
|
455
490
|
const {
|
|
456
491
|
peekingGap,
|
|
457
|
-
peekingMiddleSpace
|
|
458
|
-
peekingMarginLeft
|
|
492
|
+
peekingMiddleSpace
|
|
459
493
|
} = getPeekingProps(viewport);
|
|
460
494
|
let finalWidth;
|
|
461
|
-
const
|
|
495
|
+
const baseWidth = maxWidth || containerLayoutRef.current.width;
|
|
496
|
+
const slideWide = baseWidth - peekingMiddleSpace * PEEKING_MULTIPLIER;
|
|
462
497
|
if (activeIndexRef.current === 0) {
|
|
463
498
|
finalWidth = 0;
|
|
464
499
|
} else {
|
|
465
|
-
finalWidth =
|
|
500
|
+
finalWidth = (slideWide + peekingGap) * activeIndexRef.current;
|
|
466
501
|
}
|
|
467
502
|
animatedX.current = finalWidth * NEGATIVE_MULTIPLIER;
|
|
468
503
|
} else {
|
|
@@ -489,8 +524,9 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
489
524
|
y: 0
|
|
490
525
|
});
|
|
491
526
|
}
|
|
492
|
-
}, [pan, animatedX, heroPan, heroAnimatedX, enableHero, viewport, enablePeeking]);
|
|
493
|
-
const animate = React.useCallback((panToAnimate, toValue, toIndex)
|
|
527
|
+
}, [pan, animatedX, heroPan, heroAnimatedX, enableHero, viewport, enablePeeking, maxWidth]);
|
|
528
|
+
const animate = React.useCallback(function (panToAnimate, toValue, toIndex) {
|
|
529
|
+
let isSwipeRelease = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
494
530
|
const applicableTransitionDuration = isLastSlide && toIndex === 0 ? loopDuration : transitionDuration;
|
|
495
531
|
const handleAnimationEndToIndex = function () {
|
|
496
532
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
@@ -498,10 +534,23 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
498
534
|
}
|
|
499
535
|
return handleAnimationEnd(toIndex, ...args);
|
|
500
536
|
};
|
|
501
|
-
if (reduceMotionRef.current
|
|
537
|
+
if (reduceMotionRef.current) {
|
|
538
|
+
Animated.timing(panToAnimate, {
|
|
539
|
+
toValue,
|
|
540
|
+
duration: INSTANT_ANIMATION_DURATION,
|
|
541
|
+
useNativeDriver: false
|
|
542
|
+
}).start(handleAnimationEndToIndex);
|
|
543
|
+
} else if (isSwipeRelease && swipeReleaseStyle === SWIPE_RELEASE_STYLES.EASE_OUT) {
|
|
502
544
|
Animated.timing(panToAnimate, {
|
|
503
545
|
toValue,
|
|
504
|
-
duration:
|
|
546
|
+
duration: swipeReleaseDuration,
|
|
547
|
+
easing: Easing.out(Easing.cubic),
|
|
548
|
+
useNativeDriver: false
|
|
549
|
+
}).start(handleAnimationEndToIndex);
|
|
550
|
+
} else if (isSwiping.current || isSwipeRelease) {
|
|
551
|
+
Animated.timing(panToAnimate, {
|
|
552
|
+
toValue,
|
|
553
|
+
duration: INSTANT_ANIMATION_DURATION,
|
|
505
554
|
useNativeDriver: false
|
|
506
555
|
}).start(handleAnimationEndToIndex);
|
|
507
556
|
} else if (isAutoPlayEnabled) {
|
|
@@ -525,7 +574,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
525
574
|
useNativeDriver: false
|
|
526
575
|
}).start(handleAnimationEndToIndex);
|
|
527
576
|
}
|
|
528
|
-
}, [springConfig, handleAnimationEnd, transitionDuration, loopDuration, isLastSlide, isAutoPlayEnabled, enablePeeking, enableDisplayMultipleItemsPerSlide]);
|
|
577
|
+
}, [springConfig, handleAnimationEnd, transitionDuration, loopDuration, isLastSlide, isAutoPlayEnabled, enablePeeking, enableDisplayMultipleItemsPerSlide, swipeReleaseStyle, swipeReleaseDuration]);
|
|
529
578
|
const stopAutoplay = React.useCallback(() => {
|
|
530
579
|
if (autoPlayRef?.current) {
|
|
531
580
|
clearTimeout(autoPlayRef?.current);
|
|
@@ -548,6 +597,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
548
597
|
};
|
|
549
598
|
let skipChanges = !delta;
|
|
550
599
|
let calcDelta = delta;
|
|
600
|
+
const isSwipeRelease = transitionMode === TRANSITION_MODES.SWIPE;
|
|
551
601
|
if (activeIndexRef.current <= 0 && delta < 0) {
|
|
552
602
|
skipChanges = transitionMode !== TRANSITION_MODES.AUTOMATIC;
|
|
553
603
|
calcDelta = totalItems + delta;
|
|
@@ -558,15 +608,15 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
558
608
|
const index = activeIndexRef.current + calcDelta;
|
|
559
609
|
if (skipChanges) {
|
|
560
610
|
isTransitioningRef.current = true;
|
|
561
|
-
animate(pan, toValue, index);
|
|
611
|
+
animate(pan, toValue, index, isSwipeRelease);
|
|
562
612
|
if (enableHero) {
|
|
563
|
-
animate(heroPan, toValue, index);
|
|
613
|
+
animate(heroPan, toValue, index, isSwipeRelease);
|
|
564
614
|
}
|
|
565
615
|
return calcDelta;
|
|
566
616
|
}
|
|
567
617
|
stopAutoplay();
|
|
568
618
|
setActiveIndex(index);
|
|
569
|
-
const finalWidth = calculateFinalWidth(containerLayoutRef.current.width, enablePeeking, viewport,
|
|
619
|
+
const finalWidth = calculateFinalWidth(containerLayoutRef.current.width, enablePeeking, viewport, maxWidth);
|
|
570
620
|
toValue.x = finalWidth * -1 * calcDelta;
|
|
571
621
|
const heroToValue = {
|
|
572
622
|
x: 0,
|
|
@@ -574,9 +624,9 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
574
624
|
};
|
|
575
625
|
heroToValue.x = heroContainerLayoutRef.current.width * -1 * calcDelta;
|
|
576
626
|
isTransitioningRef.current = true;
|
|
577
|
-
animate(pan, toValue, index);
|
|
627
|
+
animate(pan, toValue, index, isSwipeRelease);
|
|
578
628
|
if (enableHero) {
|
|
579
|
-
animate(heroPan, heroToValue, index);
|
|
629
|
+
animate(heroPan, heroToValue, index, isSwipeRelease);
|
|
580
630
|
}
|
|
581
631
|
if (isCarouselPlaying) {
|
|
582
632
|
stopAutoplay();
|
|
@@ -593,7 +643,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
593
643
|
}
|
|
594
644
|
if (onIndexChanged) onIndexChanged(calcDelta, index);
|
|
595
645
|
return calcDelta;
|
|
596
|
-
}, [handleAnimationStart, triggerRefocus, slideDuration, updateOffset, animate, totalItems, onIndexChanged, isCarouselPlaying, stopAutoplay, isAutoPlayEnabled, viewport, enablePeeking, pan, heroPan, enableHero]);
|
|
646
|
+
}, [handleAnimationStart, triggerRefocus, slideDuration, updateOffset, animate, totalItems, onIndexChanged, isCarouselPlaying, stopAutoplay, isAutoPlayEnabled, viewport, enablePeeking, pan, heroPan, enableHero, maxWidth]);
|
|
597
647
|
const startAutoplay = React.useCallback(() => {
|
|
598
648
|
stopAutoplay();
|
|
599
649
|
if (isAutoPlayEnabled) {
|
|
@@ -628,6 +678,9 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
628
678
|
React.useEffect(() => {
|
|
629
679
|
heroContainerLayoutRef.current = heroContainerLayout;
|
|
630
680
|
}, [heroContainerLayout]);
|
|
681
|
+
React.useEffect(() => {
|
|
682
|
+
rootContainerLayoutRef.current = rootContainerLayout;
|
|
683
|
+
}, [rootContainerLayout]);
|
|
631
684
|
React.useEffect(() => {
|
|
632
685
|
pan.x.addListener(_ref5 => {
|
|
633
686
|
let {
|
|
@@ -736,6 +789,25 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
736
789
|
} = _ref11;
|
|
737
790
|
return setPreviousNextNavigationButtonWidth(width);
|
|
738
791
|
};
|
|
792
|
+
const onRootContainerLayout = _ref12 => {
|
|
793
|
+
let {
|
|
794
|
+
nativeEvent: {
|
|
795
|
+
layout: {
|
|
796
|
+
x,
|
|
797
|
+
y,
|
|
798
|
+
width,
|
|
799
|
+
height
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
} = _ref12;
|
|
803
|
+
return setRootContainerLayout(prevState => ({
|
|
804
|
+
...prevState,
|
|
805
|
+
x,
|
|
806
|
+
y,
|
|
807
|
+
width,
|
|
808
|
+
height
|
|
809
|
+
}));
|
|
810
|
+
};
|
|
739
811
|
const isSwipeAllowed = React.useCallback(() => {
|
|
740
812
|
if (totalItems === 1) {
|
|
741
813
|
return false;
|
|
@@ -773,16 +845,16 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
773
845
|
startAutoplay();
|
|
774
846
|
}
|
|
775
847
|
const correction = gesture.moveX - gesture.x0;
|
|
848
|
+
isSwiping.current = false;
|
|
776
849
|
if (Math.abs(correction) < containerLayoutRef.current.width * minDistanceForAction) {
|
|
777
850
|
animate(pan, {
|
|
778
851
|
x: 0,
|
|
779
852
|
y: 0
|
|
780
|
-
},
|
|
853
|
+
}, activeIndexRef.current, true);
|
|
781
854
|
} else {
|
|
782
855
|
const delta = correction > 0 ? -1 : 1;
|
|
783
856
|
updateIndex(delta, TRANSITION_MODES.SWIPE);
|
|
784
857
|
}
|
|
785
|
-
isSwiping.current = false;
|
|
786
858
|
}
|
|
787
859
|
}), [pan, updateIndex, updateOffset, animate, isSwipeAllowed, minDistanceForAction, handleAnimationStart, minDistanceToCapture, startAutoplay, stopAutoplay, isCarouselPlaying]);
|
|
788
860
|
const heroPanResponder = React.useMemo(() => PanResponder.create({
|
|
@@ -813,16 +885,16 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
813
885
|
startAutoplay();
|
|
814
886
|
}
|
|
815
887
|
const correction = gesture.moveX - gesture.x0;
|
|
888
|
+
isSwiping.current = false;
|
|
816
889
|
if (Math.abs(correction) < containerLayoutRef.current.width * minDistanceForAction) {
|
|
817
890
|
animate(heroPan, {
|
|
818
891
|
x: 0,
|
|
819
892
|
y: 0
|
|
820
|
-
},
|
|
893
|
+
}, activeIndexRef.current, true);
|
|
821
894
|
} else {
|
|
822
895
|
const delta = correction > 0 ? -1 : 1;
|
|
823
896
|
updateIndex(delta, TRANSITION_MODES.SWIPE);
|
|
824
897
|
}
|
|
825
|
-
isSwiping.current = false;
|
|
826
898
|
}
|
|
827
899
|
}), [heroPan, updateIndex, updateOffset, animate, isSwipeAllowed, minDistanceForAction, handleAnimationStart, minDistanceToCapture, startAutoplay, stopAutoplay, isCarouselPlaying]);
|
|
828
900
|
const goToNext = React.useCallback(() => {
|
|
@@ -901,9 +973,10 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
901
973
|
}
|
|
902
974
|
}, [isTransitioningRef]);
|
|
903
975
|
return /*#__PURE__*/_jsxs(View, {
|
|
904
|
-
style: selectRootContainerStyles(enableHero, viewport),
|
|
976
|
+
style: selectRootContainerStyles(enableHero, viewport, enablePeeking),
|
|
977
|
+
onLayout: onRootContainerLayout,
|
|
905
978
|
children: [/*#__PURE__*/_jsx(View, {
|
|
906
|
-
style: selectMainContainerStyles(enableHero, viewport, maxWidth),
|
|
979
|
+
style: selectMainContainerStyles(enableHero, viewport, maxWidth, enablePeeking),
|
|
907
980
|
children: /*#__PURE__*/_jsxs(CarouselProvider, {
|
|
908
981
|
activeIndex: activeIndex,
|
|
909
982
|
goTo: goTo,
|
|
@@ -915,6 +988,8 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
915
988
|
refocus: refocus,
|
|
916
989
|
width: containerLayout.width,
|
|
917
990
|
maximumItemsForSlide: getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport),
|
|
991
|
+
maxWidth: maxWidth,
|
|
992
|
+
viewportWidth: currentViewportWidth,
|
|
918
993
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
919
994
|
style: [staticStyles.root, {
|
|
920
995
|
...(Platform.OS === 'web' ? {
|
|
@@ -937,7 +1012,9 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
937
1012
|
enablePeeking,
|
|
938
1013
|
enableDisplayMultipleItemsPerSlide,
|
|
939
1014
|
isAutoPlayEnabled,
|
|
940
|
-
viewport
|
|
1015
|
+
viewport,
|
|
1016
|
+
maxWidth,
|
|
1017
|
+
viewportWidth: currentViewportWidth
|
|
941
1018
|
})],
|
|
942
1019
|
children: /*#__PURE__*/_jsx(IconButton, {
|
|
943
1020
|
icon: isCarouselPlaying ? pauseIcon : playIcon,
|
|
@@ -946,7 +1023,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
946
1023
|
onPress: onAnimationControlButtonPress
|
|
947
1024
|
})
|
|
948
1025
|
}) : null, showPreviousNextNavigation && totalItems > 1 ? /*#__PURE__*/_jsx(View, {
|
|
949
|
-
style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, true, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport),
|
|
1026
|
+
style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, true, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, currentViewportWidth),
|
|
950
1027
|
testID: "previous-button-container",
|
|
951
1028
|
children: /*#__PURE__*/_jsx(IconButton, {
|
|
952
1029
|
onLayout: onPreviousNextNavigationButtonLayout,
|
|
@@ -984,16 +1061,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
984
1061
|
children: childrenArray.map((element, index) => {
|
|
985
1062
|
let hidden = !isAnimating && index !== activeIndex;
|
|
986
1063
|
if (enablePeeking && !isAnimating) {
|
|
987
|
-
|
|
988
|
-
const maxItemsForSlide = getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport);
|
|
989
|
-
if (index >= activeIndex * maxItemsForSlide - 1 && index < activeIndex * maxItemsForSlide + maxItemsForSlide + 1) {
|
|
990
|
-
hidden = false;
|
|
991
|
-
} else {
|
|
992
|
-
hidden = true;
|
|
993
|
-
}
|
|
994
|
-
} else if (index >= activeIndex - 1 && index <= activeIndex + 1) {
|
|
995
|
-
hidden = false;
|
|
996
|
-
}
|
|
1064
|
+
hidden = false;
|
|
997
1065
|
} else if (!enablePeeking && enableDisplayMultipleItemsPerSlide && !isAnimating) {
|
|
998
1066
|
const maxItemsForSlide = getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport);
|
|
999
1067
|
if (index >= activeIndex * maxItemsForSlide && index < activeIndex * maxItemsForSlide + maxItemsForSlide) {
|
|
@@ -1015,7 +1083,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
1015
1083
|
})
|
|
1016
1084
|
})
|
|
1017
1085
|
}), showPreviousNextNavigation && totalItems > 1 ? /*#__PURE__*/_jsx(View, {
|
|
1018
|
-
style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, false, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport),
|
|
1086
|
+
style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, false, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, currentViewportWidth),
|
|
1019
1087
|
testID: "next-button-container",
|
|
1020
1088
|
children: /*#__PURE__*/_jsx(IconButton, {
|
|
1021
1089
|
onLayout: onPreviousNextNavigationButtonLayout,
|
|
@@ -1027,7 +1095,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
1027
1095
|
})
|
|
1028
1096
|
}) : null]
|
|
1029
1097
|
}), /*#__PURE__*/_jsx(View, {
|
|
1030
|
-
style: selectNavigationStyles(tabs, enableHero, viewport),
|
|
1098
|
+
style: selectNavigationStyles(tabs, enableHero, viewport, enablePeeking, maxWidth),
|
|
1031
1099
|
children: showPanelNavigation ? activePanelNavigation : null
|
|
1032
1100
|
})]
|
|
1033
1101
|
})
|
|
@@ -1278,7 +1346,23 @@ Carousel.propTypes = {
|
|
|
1278
1346
|
md: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
|
|
1279
1347
|
sm: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number]),
|
|
1280
1348
|
xs: PropTypes.oneOfType([PropTypes.oneOf(['max', 'full']), PropTypes.number])
|
|
1281
|
-
})
|
|
1349
|
+
}),
|
|
1350
|
+
/**
|
|
1351
|
+
* Animation style for swipe release transitions.
|
|
1352
|
+
* - `'instant'`: Immediate snap to position (current default)
|
|
1353
|
+
* - `'ease-out'`: Smooth deceleration animation
|
|
1354
|
+
* - Default value is `'instant'`
|
|
1355
|
+
* - Use `swipeReleaseDuration` to customize the animation duration when using `'ease-out'`
|
|
1356
|
+
*
|
|
1357
|
+
* @deprecated The default will change to `'ease-out'` in Q2 2026 (introduced Jan 2026).
|
|
1358
|
+
*/
|
|
1359
|
+
swipeReleaseStyle: PropTypes.oneOf(['instant', 'ease-out']),
|
|
1360
|
+
/**
|
|
1361
|
+
* Duration in milliseconds of the ease-out animation when releasing a swipe gesture.
|
|
1362
|
+
* Only applies when `swipeReleaseStyle` is set to `'ease-out'`.
|
|
1363
|
+
* - Default value is `500` (500ms)
|
|
1364
|
+
*/
|
|
1365
|
+
swipeReleaseDuration: PropTypes.number
|
|
1282
1366
|
};
|
|
1283
1367
|
Carousel.Item = CarouselItem;
|
|
1284
1368
|
Carousel.displayName = 'Carousel';
|
|
@@ -14,7 +14,9 @@ const CarouselProvider = _ref => {
|
|
|
14
14
|
themeTokens,
|
|
15
15
|
totalItems,
|
|
16
16
|
width,
|
|
17
|
-
maximumItemsForSlide
|
|
17
|
+
maximumItemsForSlide,
|
|
18
|
+
maxWidth,
|
|
19
|
+
viewportWidth
|
|
18
20
|
} = _ref;
|
|
19
21
|
const value = React.useMemo(() => ({
|
|
20
22
|
activeIndex,
|
|
@@ -25,8 +27,10 @@ const CarouselProvider = _ref => {
|
|
|
25
27
|
themeTokens,
|
|
26
28
|
totalItems,
|
|
27
29
|
width,
|
|
28
|
-
maximumItemsForSlide
|
|
29
|
-
|
|
30
|
+
maximumItemsForSlide,
|
|
31
|
+
maxWidth,
|
|
32
|
+
viewportWidth
|
|
33
|
+
}), [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width, maximumItemsForSlide, maxWidth, viewportWidth]);
|
|
30
34
|
return /*#__PURE__*/_jsx(CarouselContext.Provider, {
|
|
31
35
|
value: value,
|
|
32
36
|
children: children
|
|
@@ -49,6 +53,8 @@ CarouselProvider.propTypes = {
|
|
|
49
53
|
themeTokens: getTokensPropType('Carousel'),
|
|
50
54
|
totalItems: PropTypes.number.isRequired,
|
|
51
55
|
width: PropTypes.number.isRequired,
|
|
52
|
-
maximumItemsForSlide: PropTypes.number
|
|
56
|
+
maximumItemsForSlide: PropTypes.number,
|
|
57
|
+
maxWidth: PropTypes.number,
|
|
58
|
+
viewportWidth: PropTypes.number
|
|
53
59
|
};
|
|
54
60
|
export { CarouselProvider, useCarousel };
|
|
@@ -12,26 +12,26 @@ const selectContainerStyle = _ref => {
|
|
|
12
12
|
width,
|
|
13
13
|
elementIndex,
|
|
14
14
|
enablePeeking,
|
|
15
|
-
peekingMarginLeft,
|
|
16
15
|
peekingGap,
|
|
17
16
|
hidden,
|
|
18
17
|
enableDisplayMultipleItemsPerSlide,
|
|
19
18
|
viewport,
|
|
20
|
-
peekingMiddleSpace
|
|
19
|
+
peekingMiddleSpace,
|
|
20
|
+
maxWidth,
|
|
21
|
+
viewportWidth
|
|
21
22
|
} = _ref;
|
|
22
23
|
let adjustedWidth = width;
|
|
23
24
|
let marginLeft = 0;
|
|
24
25
|
if (enablePeeking) {
|
|
25
26
|
const isFirst = elementIndex === 0;
|
|
26
|
-
|
|
27
|
+
const baseWidth = maxWidth || width;
|
|
28
|
+
adjustedWidth = baseWidth - peekingMiddleSpace * 2;
|
|
27
29
|
if (isFirst) {
|
|
28
|
-
marginLeft =
|
|
30
|
+
marginLeft = peekingMiddleSpace + (viewportWidth - maxWidth) / 2;
|
|
29
31
|
} else {
|
|
30
32
|
marginLeft = peekingGap;
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
|
-
|
|
34
|
-
// Adjust width and margins for multiple items per slide.
|
|
35
35
|
if (enableDisplayMultipleItemsPerSlide) {
|
|
36
36
|
switch (viewport) {
|
|
37
37
|
case 'xs':
|
|
@@ -89,7 +89,9 @@ const CarouselItem = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
89
89
|
width,
|
|
90
90
|
activeIndex,
|
|
91
91
|
goTo,
|
|
92
|
-
maximumItemsForSlide
|
|
92
|
+
maximumItemsForSlide,
|
|
93
|
+
maxWidth,
|
|
94
|
+
viewportWidth
|
|
93
95
|
} = useCarousel();
|
|
94
96
|
const selectedProps = selectProps({
|
|
95
97
|
...rest,
|
|
@@ -132,6 +134,8 @@ const CarouselItem = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
132
134
|
enablePeeking,
|
|
133
135
|
enableDisplayMultipleItemsPerSlide,
|
|
134
136
|
viewport,
|
|
137
|
+
maxWidth,
|
|
138
|
+
viewportWidth,
|
|
135
139
|
...peekingProps
|
|
136
140
|
}),
|
|
137
141
|
...selectedProps,
|
|
@@ -8,4 +8,24 @@ export const LARGE_VIEWPORT_MARGIN = 40;
|
|
|
8
8
|
export const DEFAULT_VIEWPORT_MARGIN = 10;
|
|
9
9
|
export const PEEKING_MULTIPLIER = 2;
|
|
10
10
|
export const ACTIVE_INDEX_OFFSET_MULTIPLIER = 1;
|
|
11
|
-
export const NEGATIVE_MULTIPLIER = -1;
|
|
11
|
+
export const NEGATIVE_MULTIPLIER = -1;
|
|
12
|
+
export const TRANSITION_MODES = {
|
|
13
|
+
MANUAL: 'manual',
|
|
14
|
+
AUTOMATIC: 'automatic',
|
|
15
|
+
SWIPE: 'swipe'
|
|
16
|
+
};
|
|
17
|
+
export const SWIPE_RELEASE_STYLES = {
|
|
18
|
+
INSTANT: 'instant',
|
|
19
|
+
EASE_OUT: 'ease-out'
|
|
20
|
+
};
|
|
21
|
+
export const INSTANT_ANIMATION_DURATION = 1;
|
|
22
|
+
export const DEFAULT_SWIPE_RELEASE_DURATION = 500;
|
|
23
|
+
export const POSITION_VARIANTS = {
|
|
24
|
+
EDGE: 'edge',
|
|
25
|
+
INSIDE: 'inside',
|
|
26
|
+
OUTSIDE: 'outside'
|
|
27
|
+
};
|
|
28
|
+
export const POSITION_PROPERTIES = {
|
|
29
|
+
LEFT: 'left',
|
|
30
|
+
RIGHT: 'right'
|
|
31
|
+
};
|