@telus-uds/components-base 1.8.5 → 1.11.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 (69) hide show
  1. package/CHANGELOG.md +47 -2
  2. package/component-docs.json +666 -27
  3. package/lib/Card/Card.js +9 -4
  4. package/lib/Carousel/Carousel.js +672 -0
  5. package/lib/Carousel/CarouselContext.js +59 -0
  6. package/lib/Carousel/CarouselItem/CarouselItem.js +92 -0
  7. package/lib/Carousel/CarouselItem/index.js +13 -0
  8. package/lib/Carousel/dictionary.js +23 -0
  9. package/lib/Carousel/index.js +32 -0
  10. package/lib/ExpandCollapse/Panel.js +10 -1
  11. package/lib/InputSupports/InputSupports.js +10 -3
  12. package/lib/InputSupports/useInputSupports.js +3 -2
  13. package/lib/Modal/Modal.js +4 -0
  14. package/lib/Skeleton/Skeleton.js +1 -0
  15. package/lib/StepTracker/StepTracker.js +15 -12
  16. package/lib/TextInput/TextInput.js +3 -12
  17. package/lib/TextInput/TextInputBase.js +9 -0
  18. package/lib/TextInput/propTypes.js +3 -8
  19. package/lib/index.js +23 -0
  20. package/lib/utils/props/clickProps.js +2 -2
  21. package/lib/utils/props/handlerProps.js +77 -31
  22. package/lib/utils/props/textInputProps.js +8 -1
  23. package/lib/utils/useScrollBlocking.js +66 -0
  24. package/lib/utils/useScrollBlocking.native.js +11 -0
  25. package/lib-module/Card/Card.js +5 -4
  26. package/lib-module/Carousel/Carousel.js +617 -0
  27. package/lib-module/Carousel/CarouselContext.js +43 -0
  28. package/lib-module/Carousel/CarouselItem/CarouselItem.js +75 -0
  29. package/lib-module/Carousel/CarouselItem/index.js +2 -0
  30. package/lib-module/Carousel/dictionary.js +16 -0
  31. package/lib-module/Carousel/index.js +2 -0
  32. package/lib-module/ExpandCollapse/Panel.js +9 -1
  33. package/lib-module/InputSupports/InputSupports.js +10 -3
  34. package/lib-module/InputSupports/useInputSupports.js +3 -2
  35. package/lib-module/Modal/Modal.js +3 -0
  36. package/lib-module/Skeleton/Skeleton.js +1 -0
  37. package/lib-module/StepTracker/StepTracker.js +14 -12
  38. package/lib-module/TextInput/TextInput.js +3 -9
  39. package/lib-module/TextInput/TextInputBase.js +10 -1
  40. package/lib-module/TextInput/propTypes.js +4 -8
  41. package/lib-module/index.js +2 -0
  42. package/lib-module/utils/props/clickProps.js +2 -2
  43. package/lib-module/utils/props/handlerProps.js +78 -31
  44. package/lib-module/utils/props/textInputProps.js +8 -1
  45. package/lib-module/utils/useScrollBlocking.js +58 -0
  46. package/lib-module/utils/useScrollBlocking.native.js +2 -0
  47. package/package.json +3 -3
  48. package/src/Card/Card.jsx +6 -4
  49. package/src/Carousel/Carousel.jsx +649 -0
  50. package/src/Carousel/CarouselContext.jsx +30 -0
  51. package/src/Carousel/CarouselItem/CarouselItem.jsx +66 -0
  52. package/src/Carousel/CarouselItem/index.js +3 -0
  53. package/src/Carousel/dictionary.js +16 -0
  54. package/src/Carousel/index.js +2 -0
  55. package/src/ExpandCollapse/Panel.jsx +8 -1
  56. package/src/InputSupports/InputSupports.jsx +18 -3
  57. package/src/InputSupports/useInputSupports.js +2 -2
  58. package/src/Modal/Modal.jsx +3 -1
  59. package/src/Skeleton/Skeleton.jsx +1 -0
  60. package/src/StepTracker/StepTracker.jsx +21 -8
  61. package/src/TextInput/TextInput.jsx +2 -9
  62. package/src/TextInput/TextInputBase.jsx +11 -1
  63. package/src/TextInput/propTypes.js +3 -7
  64. package/src/index.js +2 -0
  65. package/src/utils/props/clickProps.js +2 -2
  66. package/src/utils/props/handlerProps.js +64 -16
  67. package/src/utils/props/textInputProps.js +7 -1
  68. package/src/utils/useScrollBlocking.js +57 -0
  69. package/src/utils/useScrollBlocking.native.js +2 -0
@@ -0,0 +1,672 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = _interopRequireDefault(require("react"));
9
+
10
+ var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
11
+
12
+ var _Animated = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Animated"));
13
+
14
+ var _PanResponder = _interopRequireDefault(require("react-native-web/dist/cjs/exports/PanResponder"));
15
+
16
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
17
+
18
+ var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
19
+
20
+ var _propTypes = _interopRequireDefault(require("prop-types"));
21
+
22
+ var _ThemeProvider = require("../ThemeProvider");
23
+
24
+ var _ViewportProvider = require("../ViewportProvider");
25
+
26
+ var _utils = require("../utils");
27
+
28
+ var _A11yInfoProvider = require("../A11yInfoProvider");
29
+
30
+ var _CarouselContext = require("./CarouselContext");
31
+
32
+ var _CarouselItem = _interopRequireDefault(require("./CarouselItem"));
33
+
34
+ var _StepTracker = _interopRequireDefault(require("../StepTracker"));
35
+
36
+ var _StackView = _interopRequireDefault(require("../StackView"));
37
+
38
+ var _IconButton = _interopRequireDefault(require("../IconButton"));
39
+
40
+ var _dictionary = _interopRequireDefault(require("./dictionary"));
41
+
42
+ var _jsxRuntime = require("react/jsx-runtime");
43
+
44
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
45
+
46
+ const staticStyles = _StyleSheet.default.create({
47
+ root: {
48
+ backgroundColor: 'transparent',
49
+ justifyContent: 'center',
50
+ alignItems: 'center',
51
+ position: 'relative',
52
+ top: 0,
53
+ left: 0
54
+ }
55
+ });
56
+
57
+ const staticTokens = {
58
+ stackView: {
59
+ justifyContent: 'center'
60
+ },
61
+ stepTracker: {
62
+ showStepLabel: false,
63
+ showStepTrackerLabel: true,
64
+ knobCompletedBackgroundColor: 'none',
65
+ connectorCompletedColor: 'none',
66
+ connectorColor: 'none'
67
+ }
68
+ };
69
+
70
+ const selectContainerStyles = width => ({
71
+ backgroundColor: 'transparent',
72
+ overflow: 'hidden',
73
+ width
74
+ });
75
+
76
+ const selectSwipeAreaStyles = (count, width) => ({
77
+ width: width * count,
78
+ justifyContent: 'space-between',
79
+ flexDirection: 'row'
80
+ });
81
+
82
+ const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, areStylesAppliedOnPreviousButton) => {
83
+ const styles = {
84
+ zIndex: 1,
85
+ position: 'absolute'
86
+ };
87
+ const dynamicPositionProperty = areStylesAppliedOnPreviousButton ? 'left' : 'right';
88
+
89
+ if (isFirstSlide) {
90
+ styles.visibility = areStylesAppliedOnPreviousButton ? 'hidden' : 'visible';
91
+ } else if (isLastSlide) {
92
+ styles.visibility = areStylesAppliedOnPreviousButton ? 'visible' : 'hidden';
93
+ } else {
94
+ styles.visibility = 'visible';
95
+ }
96
+
97
+ if (previousNextNavigationPosition === 'edge') {
98
+ styles[dynamicPositionProperty] = -1 * (previousNextNavigationButtonWidth / 2);
99
+ } else if (previousNextNavigationPosition === 'inside') {
100
+ styles[dynamicPositionProperty] = 0;
101
+ } else if (previousNextNavigationPosition === 'outside') {
102
+ styles[dynamicPositionProperty] = -1 * (spaceBetweenSlideAndPreviousNextNavigation + previousNextNavigationButtonWidth);
103
+ }
104
+
105
+ return styles;
106
+ };
107
+
108
+ const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.viewProps]);
109
+ /**
110
+ * Carousel is a general-purpose content slider that can be used to render content in terms of slides.
111
+
112
+ ## Usage
113
+ - `Carousel` is a top-level export from `@telus-uds/components-base` which is used to render a Carousel
114
+ - Immediately within `Carousel`, individual slides are wrapped in `Carousel.Item` for the top-level `Carousel` to know how to identify an individual slide
115
+ - You can use any UDS component or other platform-specific component, (based on the platform you're rendering) to achieve any desired layout
116
+ - By default, Carousel takea all the `width` available to it and the `height` is determined based on the content in the slide with more content
117
+ - You may want to wrap Carousel in other layout components like `Box`, `FlexGrid` etc, to achieve a responsive layout of your need
118
+
119
+ ## `useCarousel` custom hook
120
+
121
+ ```jsx
122
+ import { useCarousel } from '@telus-uds/components-base'
123
+
124
+ const SomeComponentWithinCarouselItem = () => {
125
+ const {
126
+ activeIndex,
127
+ totalItems,
128
+ width,
129
+ goTo
130
+ } = useCarousel()
131
+ return <Text>Hi!</Text>
132
+ }
133
+ ```
134
+
135
+ You can use `useCarousel` to hook into internal state of the Carousel component like:
136
+ - `activeIndex`: Index of the current slide
137
+ - `totalItems`: Total number of items/slides passed to the Carousel
138
+ - `width`: Width of the individual carousel slide
139
+ - `goTo`: A function to go to a particular slide by passing the index of that slide, e.g: goTo(0) where `0` is the index of the first slide
140
+
141
+ ## Accessibility
142
+
143
+ - Top-level `Carousel` and `Carousel.Item` can take all possible React Native's `View` and `a11y` props
144
+ - If your slide contains input elements like buttons, you may want to configure them to be only focusable when `activeIndex` is equal to the current slide index in order to avoid tabbing going between slides
145
+
146
+ ## Platform considerations
147
+ The component is available on both native platforms and web.
148
+
149
+ ## Other considerations
150
+ - You may want to use the same kind of layout in all your slides to avoid visual and height differences
151
+ - `previous` and `next` navigation buttons are automatically removed in `sm` and `xs` viewports, as these smaller viewports offers swipe functionality
152
+
153
+ ## Tokens
154
+
155
+ You can override the following tokens in exceptional circumstances:
156
+ - `previousIcon` - Icon of the previous button
157
+ - `nextIcon` - Icon of the next button
158
+ - `showPreviousNextNavigation` - If you want to show/hide the previous/next navigation
159
+ - `showPanelNavigation` - If you want to show/hide the panel navigation
160
+ - `spaceBetweenSlideAndPreviousNextNavigation` - Horizontal space between slide and previous/next navigational buttons
161
+ - `spaceBetweenSlideAndPanelNavigation` - Vertical space between slide area and panel navigation area
162
+ */
163
+
164
+ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
165
+ let {
166
+ tokens,
167
+ variant,
168
+ children,
169
+ itemLabel = 'item',
170
+ previousNextNavigationPosition = 'inside',
171
+ previousNextIconSize = 'default',
172
+ minDistanceToCapture = 5,
173
+ minDistanceForAction = 0.2,
174
+ onAnimationStart,
175
+ onAnimationEnd,
176
+ onIndexChanged,
177
+ springConfig = undefined,
178
+ onRenderPanelNavigation,
179
+ tag = 'ul',
180
+ accessibilityRole = 'adjustable',
181
+ accessibilityLabel = 'carousel',
182
+ copy,
183
+ ...rest
184
+ } = _ref;
185
+ const viewport = (0, _ViewportProvider.useViewport)();
186
+ const {
187
+ previousIcon,
188
+ nextIcon,
189
+ showPreviousNextNavigation,
190
+ showPanelNavigation,
191
+ spaceBetweenSlideAndPreviousNextNavigation,
192
+ spaceBetweenSlideAndPanelNavigation
193
+ } = (0, _ThemeProvider.useThemeTokens)('Carousel', tokens, variant, {
194
+ viewport
195
+ });
196
+
197
+ const [activeIndex, setActiveIndex] = _react.default.useState(0);
198
+
199
+ const [isAnimating, setIsAnimating] = _react.default.useState(false);
200
+
201
+ const handleAnimationStart = _react.default.useCallback(function () {
202
+ if (typeof onAnimationStart === 'function') onAnimationStart(...arguments);
203
+ setIsAnimating(true);
204
+ }, [onAnimationStart]);
205
+
206
+ const handleAnimationEnd = _react.default.useCallback(function () {
207
+ if (typeof onAnimationEnd === 'function') onAnimationEnd(...arguments);
208
+ setIsAnimating(false);
209
+ }, [onAnimationEnd]);
210
+
211
+ const getCopy = (0, _utils.useCopy)({
212
+ dictionary: _dictionary.default,
213
+ copy
214
+ });
215
+
216
+ const childrenArray = _react.default.Children.toArray(children);
217
+
218
+ const systemProps = selectProps({ ...rest,
219
+ accessibilityRole,
220
+ accessibilityLabel,
221
+ accessibilityValue: {
222
+ min: 1,
223
+ max: childrenArray.length,
224
+ now: activeIndex + 1
225
+ }
226
+ });
227
+ const {
228
+ reduceMotionEnabled
229
+ } = (0, _A11yInfoProvider.useA11yInfo)();
230
+
231
+ const [containerLayout, setContainerLayout] = _react.default.useState({
232
+ x: 0,
233
+ y: 0,
234
+ width: 0
235
+ });
236
+
237
+ const [previousNextNavigationButtonWidth, setPreviousNextNavigationButtonWidth] = _react.default.useState(0);
238
+
239
+ const pan = _react.default.useRef(new _Animated.default.ValueXY()).current;
240
+
241
+ const animatedX = _react.default.useRef(0);
242
+
243
+ const animatedY = _react.default.useRef(0);
244
+
245
+ const isFirstSlide = !activeIndex;
246
+ const isLastSlide = activeIndex + 1 >= children.length;
247
+ const panelNavigationTokens = { ...staticTokens.stepTracker,
248
+ containerPaddingTop: spaceBetweenSlideAndPanelNavigation
249
+ };
250
+
251
+ const onContainerLayout = _ref2 => {
252
+ let {
253
+ nativeEvent: {
254
+ layout: {
255
+ x,
256
+ y,
257
+ width
258
+ }
259
+ }
260
+ } = _ref2;
261
+ return setContainerLayout(prevState => ({ ...prevState,
262
+ x,
263
+ y,
264
+ width
265
+ }));
266
+ };
267
+
268
+ const onPreviousNextNavigationButtonLayout = _ref3 => {
269
+ let {
270
+ nativeEvent: {
271
+ layout: {
272
+ width
273
+ }
274
+ }
275
+ } = _ref3;
276
+ return setPreviousNextNavigationButtonWidth(width);
277
+ };
278
+
279
+ const updateOffset = _react.default.useCallback(() => {
280
+ animatedX.current = containerLayout.width * activeIndex * -1;
281
+ animatedY.current = 0;
282
+ pan.setOffset({
283
+ x: animatedX.current,
284
+ y: animatedY.current
285
+ });
286
+ pan.setValue({
287
+ x: 0,
288
+ y: 0
289
+ });
290
+ }, [activeIndex, containerLayout.width, pan, animatedX]);
291
+
292
+ const animate = _react.default.useCallback((toValue, toIndex) => {
293
+ const handleAnimationEndToIndex = function () {
294
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
295
+ args[_key] = arguments[_key];
296
+ }
297
+
298
+ return handleAnimationEnd(toIndex, ...args);
299
+ };
300
+
301
+ if (reduceMotionEnabled) {
302
+ _Animated.default.timing(pan, {
303
+ toValue,
304
+ duration: 1,
305
+ useNativeDriver: false
306
+ }).start(handleAnimationEndToIndex);
307
+ } else {
308
+ _Animated.default.spring(pan, { ...springConfig,
309
+ toValue,
310
+ useNativeDriver: false
311
+ }).start(handleAnimationEndToIndex);
312
+ }
313
+ }, [pan, springConfig, reduceMotionEnabled, handleAnimationEnd]);
314
+
315
+ const updateIndex = _react.default.useCallback(function () {
316
+ let delta = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
317
+ const toValue = {
318
+ x: 0,
319
+ y: 0
320
+ };
321
+ let skipChanges = !delta;
322
+ let calcDelta = delta;
323
+
324
+ if (activeIndex <= 0 && delta < 0) {
325
+ skipChanges = true;
326
+ calcDelta = children.length + delta;
327
+ } else if (activeIndex + 1 >= children.length && delta > 0) {
328
+ skipChanges = true;
329
+ calcDelta = -1 * activeIndex + delta - 1;
330
+ }
331
+
332
+ const index = activeIndex + calcDelta;
333
+
334
+ if (skipChanges) {
335
+ animate(toValue, index);
336
+ return calcDelta;
337
+ }
338
+
339
+ setActiveIndex(index);
340
+ toValue.x = containerLayout.width * -1 * calcDelta;
341
+ animate(toValue, index);
342
+ if (onIndexChanged) onIndexChanged(calcDelta);
343
+ return calcDelta;
344
+ }, [containerLayout.width, activeIndex, animate, children.length, onIndexChanged]);
345
+
346
+ const fixOffsetAndGo = _react.default.useCallback(delta => {
347
+ updateOffset();
348
+ handleAnimationStart(activeIndex);
349
+ updateIndex(delta);
350
+ }, [updateIndex, updateOffset, activeIndex, handleAnimationStart]);
351
+
352
+ const goToNeighboring = _react.default.useCallback(function () {
353
+ let toPrev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
354
+ fixOffsetAndGo(toPrev ? -1 : 1);
355
+ }, [fixOffsetAndGo]);
356
+
357
+ const isSwipeAllowed = _react.default.useCallback(() => {
358
+ if (_Platform.default.OS === 'web') {
359
+ return !!(viewport === 'xs' || viewport === 'sm');
360
+ }
361
+
362
+ return true;
363
+ }, [viewport]);
364
+
365
+ const panResponder = _react.default.useMemo(() => _PanResponder.default.create({
366
+ onPanResponderTerminationRequest: () => false,
367
+ onMoveShouldSetResponderCapture: () => true,
368
+ onMoveShouldSetPanResponderCapture: (_, gestureState) => {
369
+ if (!isSwipeAllowed()) {
370
+ return false;
371
+ }
372
+
373
+ handleAnimationStart(activeIndex);
374
+ return Math.abs(gestureState.dx) > minDistanceToCapture;
375
+ },
376
+ onPanResponderGrant: () => updateOffset(),
377
+ onPanResponderMove: _Animated.default.event([null, {
378
+ dx: pan.x
379
+ }], {
380
+ useNativeDriver: false
381
+ }),
382
+ onPanResponderRelease: (_, gesture) => {
383
+ const correction = gesture.moveX - gesture.x0;
384
+
385
+ if (Math.abs(correction) < containerLayout.width * minDistanceForAction) {
386
+ animate({
387
+ x: 0,
388
+ y: 0
389
+ }, 0);
390
+ } else {
391
+ const delta = correction > 0 ? -1 : 1;
392
+ updateIndex(delta);
393
+ }
394
+ }
395
+ }), [containerLayout.width, updateIndex, updateOffset, animate, isSwipeAllowed, activeIndex, minDistanceForAction, handleAnimationStart, minDistanceToCapture, pan.x]);
396
+
397
+ _react.default.useEffect(() => {
398
+ pan.x.addListener(_ref4 => {
399
+ let {
400
+ value
401
+ } = _ref4;
402
+ animatedX.current = value;
403
+ });
404
+ pan.y.addListener(_ref5 => {
405
+ let {
406
+ value
407
+ } = _ref5;
408
+ animatedY.current = value;
409
+ });
410
+ return () => {
411
+ pan.x.removeAllListeners();
412
+ pan.y.removeAllListeners();
413
+ };
414
+ }, [pan.x, pan.y]);
415
+
416
+ const goToNext = _react.default.useCallback(() => {
417
+ goToNeighboring();
418
+ }, [goToNeighboring]);
419
+
420
+ const goToPrev = _react.default.useCallback(() => {
421
+ goToNeighboring(true);
422
+ }, [goToNeighboring]);
423
+
424
+ const goTo = _react.default.useCallback(function () {
425
+ let index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
426
+ const delta = index - activeIndex;
427
+
428
+ if (delta) {
429
+ fixOffsetAndGo(delta);
430
+ }
431
+ }, [fixOffsetAndGo, activeIndex]); // @TODO: - these are Allium-theme variants and won't have any effect in themes that don't implement them.
432
+ // Normally we avoid setting variants of subcomponents, however this could be re-considered.
433
+ // Related discussion - https://github.com/telus/universal-design-system/issues/1549
434
+
435
+
436
+ const previousNextIconButtonVariants = {
437
+ size: previousNextIconSize,
438
+ raised: true
439
+ };
440
+
441
+ const getCopyWithPlaceholders = copyKey => {
442
+ const copyText = getCopy(copyKey).replace(/%\{itemLabel\}/g, itemLabel).replace(/%\{stepNumber\}/g, activeIndex + 1).replace(/%\{stepCount\}/g, childrenArray.length); // First word might be a lowercase placeholder: capitalize the first letter
443
+
444
+ return "".concat(copyText[0].toUpperCase()).concat(copyText.slice(1));
445
+ };
446
+
447
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_CarouselContext.CarouselProvider, {
448
+ activeIndex: activeIndex,
449
+ totalItems: childrenArray.length,
450
+ width: containerLayout.width,
451
+ goTo: goTo,
452
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
453
+ style: staticStyles.root,
454
+ onLayout: onContainerLayout,
455
+ ref: ref,
456
+ ...systemProps,
457
+ children: [showPreviousNextNavigation && /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
458
+ style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, true),
459
+ testID: "previous-button-container",
460
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconButton.default, {
461
+ onLayout: onPreviousNextNavigationButtonLayout,
462
+ icon: previousIcon,
463
+ onPress: goToPrev,
464
+ variant: previousNextIconButtonVariants,
465
+ accessibilityLabel: getCopyWithPlaceholders('iconButtonLabel').replace('%{targetStep}', activeIndex)
466
+ })
467
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
468
+ style: selectContainerStyles(containerLayout.width),
469
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Animated.default.View, {
470
+ style: _StyleSheet.default.flatten([selectSwipeAreaStyles(children.length, containerLayout.width), {
471
+ transform: [{
472
+ translateX: pan.x
473
+ }, {
474
+ translateY: pan.y
475
+ }]
476
+ }]),
477
+ ...panResponder.panHandlers,
478
+ ...(0, _utils.getA11yPropsFromHtmlTag)(tag),
479
+ children: childrenArray.map((element, index) => {
480
+ const hidden = !isAnimating && index !== activeIndex;
481
+
482
+ const clonedElement = /*#__PURE__*/_react.default.cloneElement(element, {
483
+ elementIndex: index,
484
+ hidden
485
+ });
486
+
487
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_react.default.Fragment, {
488
+ children: clonedElement
489
+ }, index.toFixed(2));
490
+ })
491
+ })
492
+ }), showPreviousNextNavigation && /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
493
+ style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, false),
494
+ testID: "next-button-container",
495
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconButton.default, {
496
+ onLayout: onPreviousNextNavigationButtonLayout,
497
+ icon: nextIcon,
498
+ onPress: goToNext,
499
+ variant: previousNextIconButtonVariants,
500
+ accessibilityLabel: getCopyWithPlaceholders('iconButtonLabel').replace('%{targetStep}', activeIndex + 2)
501
+ })
502
+ })]
503
+ }), showPanelNavigation ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_StackView.default, {
504
+ direction: "row",
505
+ tokens: staticTokens.stackView,
506
+ children: onRenderPanelNavigation ? onRenderPanelNavigation({
507
+ activeIndex,
508
+ totalItems: childrenArray.length
509
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_StepTracker.default, {
510
+ current: activeIndex,
511
+ steps: childrenArray.map((_, index) => String(index)),
512
+ copy: {
513
+ // Give StepTracker copy from Carousel's language and dictionary
514
+ stepLabel: getCopyWithPlaceholders('stepLabel'),
515
+ stepTrackerLabel: getCopyWithPlaceholders('stepTrackerLabel')
516
+ },
517
+ tokens: panelNavigationTokens
518
+ })
519
+ }) : null]
520
+ });
521
+ });
522
+
523
+ Carousel.propTypes = { ...selectedSystemPropTypes,
524
+ tokens: (0, _utils.getTokensPropType)('Carousel'),
525
+ variant: _utils.variantProp.propType,
526
+
527
+ /**
528
+ * Slides to render in Carousel. Wrap individual slides in `Carousel.Item`
529
+ */
530
+ children: _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.node), _propTypes.default.node]).isRequired,
531
+
532
+ /**
533
+ * Lowercase language-appropriate user-facing description of what each Carousel slide represents.
534
+ * This is used when generating item labels. For example, if a carousel contains offers,
535
+ * pass itemLabel="summer offer" (or copy="fr" and an appropriate French translation) to genereate
536
+ * accessible labels such as "Summer offer 1 of 3" and "Show summer offer 2 of 3".
537
+ */
538
+ itemLabel: _propTypes.default.string,
539
+
540
+ /**
541
+ * `inside` renders the previous and next buttons inside the slide
542
+ * `outside` renders the previous and next buttons outside the slide
543
+ * `edge` renders the previous and next buttons at the edge of the slide
544
+ */
545
+ previousNextNavigationPosition: _propTypes.default.oneOf(['inside', 'outside', 'edge']),
546
+
547
+ /**
548
+ * Defines the size of the `IconButton` which is being used to render next and previous buttons
549
+ */
550
+ previousNextIconSize: _propTypes.default.oneOf(['default', 'small', 'large']),
551
+
552
+ /**
553
+ * Carousel uses `Animated.spring` to animate slide changes, use this option to pass custom animation configuration
554
+ */
555
+ springConfig: _propTypes.default.object,
556
+
557
+ /**
558
+ * Minimal part of slide width must be swiped for changing index.
559
+ * Otherwise animation restore current slide. Default value 0.2 means that 20% must be swiped for change index
560
+ */
561
+ minDistanceForAction: _propTypes.default.number,
562
+
563
+ /**
564
+ * Initiate animation after swipe this distance.
565
+ */
566
+ minDistanceToCapture: _propTypes.default.number,
567
+
568
+ /**
569
+ * Called when active index changed
570
+ * This function is also provided with a parameter indicating changed index (either 1, or -1)
571
+ * Use it as follows:
572
+ * ```js
573
+ * const onIndexChangedCallback = React.useCallback((changedIndex) => {
574
+ * console.log(changedIndex)
575
+ * }, []) // pass local dependencies as per your component
576
+ * <Carousel
577
+ * onIndexChanged={onIndexChangedCallback}
578
+ * >
579
+ * <Carousel.Item>First Slide</Carousel.Item>
580
+ * </Carousel>
581
+ * ```
582
+ * Caution: Always consider wrapping your callback for `onIndexChanged` in `useCallback` in order to avoid bugs and performance issues
583
+ */
584
+ onIndexChanged: _propTypes.default.func,
585
+
586
+ /**
587
+ * Use this to render a custom panel navigation element instead of dots navigation
588
+ * This function is also provided with an object with the following properties
589
+ * activeIndex: index of current slide
590
+ * totalItems: total number of slides
591
+ * Use it as follows:
592
+ * ```js
593
+ * <Carousel
594
+ * onRenderPanelNavigation={({ totalItems, activeIndex }) => <Text>Showing {activeIndex + 1}</Text>}
595
+ * >
596
+ * <Carousel.Item>First Slide</Carousel.Item>
597
+ * </Carousel>
598
+ * ```
599
+ */
600
+ onRenderPanelNavigation: _propTypes.default.func,
601
+
602
+ /**
603
+ * When slide animation start
604
+ * This function is also provided with a parameter indicating the current slide index before animation starts
605
+ * Use it as follows:
606
+ * ```js
607
+ * const onAnimationStartCallback = React.useCallback((currentIndex) => {
608
+ * console.log(currentIndex)
609
+ * }, []) // pass local dependencies as per your component
610
+ * <Carousel
611
+ * onAnimationStart={onAnimationStartCallback}
612
+ * >
613
+ * <Carousel.Item>First Slide</Carousel.Item>
614
+ * </Carousel>
615
+ * ```
616
+ * Caution: Always consider wrapping your callback for `onAnimationStart` in `useCallback` in order to avoid bugs and performance issues
617
+ */
618
+ onAnimationStart: _propTypes.default.func,
619
+
620
+ /**
621
+ * When slide animation end with parameter of current index (after animation ends)
622
+ * This function is also provided with a parameter indicating the updated slide index after animation ends
623
+ * Use it as follows:
624
+ * ```js
625
+ * const onAnimationEndCallback = React.useCallback((changedIndex) => {
626
+ * console.log(changedIndex)
627
+ * }, []) // pass local dependencies as per your component
628
+ * <Carousel
629
+ * onAnimationEnd={onAnimationEndCallback}
630
+ * >
631
+ * <Carousel.Item>First Slide</Carousel.Item>
632
+ * </Carousel>
633
+ * ```
634
+ * Caution: Always consider wrapping your callback for `onAnimationEnd` in `useCallback` in order to avoid bugs and performance issues
635
+ */
636
+ onAnimationEnd: _propTypes.default.func,
637
+
638
+ /**
639
+ * Use this to override the default text for panel navigation
640
+ */
641
+ panelNavigationTextDictionary: _propTypes.default.shape({
642
+ en: _propTypes.default.shape({
643
+ stepTrackerLabel: _propTypes.default.string.isRequired
644
+ }),
645
+ fr: _propTypes.default.shape({
646
+ stepTrackerLabel: _propTypes.default.string.isRequired
647
+ })
648
+ }),
649
+
650
+ /**
651
+ * Provide custom accessibilityRole for Carousel container
652
+ */
653
+ accessibilityRole: _propTypes.default.string,
654
+
655
+ /**
656
+ * Provide custom accessibilityLabel for Carousel container
657
+ */
658
+ accessibilityLabel: _propTypes.default.string,
659
+
660
+ /**
661
+ * HTML tag to use for the Carousel item's immediate parent. Defaults to `'ul'` so that
662
+ * assistive technology tools know to intepret the carousel as a list.
663
+ *
664
+ * Note that if the immediate Carousel children do not all render as `'li'` elements,
665
+ * this should be changed (e.g. pass tag="div") because only 'li' is a valid child of 'ul'.
666
+ */
667
+ tag: _propTypes.default.oneOf(_utils.layoutTags)
668
+ };
669
+ Carousel.Item = _CarouselItem.default;
670
+ Carousel.displayName = 'Carousel';
671
+ var _default = Carousel;
672
+ exports.default = _default;