@telus-uds/components-base 1.10.0 → 1.12.1

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 (117) hide show
  1. package/CHANGELOG.md +37 -3
  2. package/component-docs.json +413 -62
  3. package/lib/BaseProvider/index.js +7 -2
  4. package/lib/Button/ButtonBase.js +18 -14
  5. package/lib/Carousel/Carousel.js +92 -71
  6. package/lib/Carousel/CarouselContext.js +12 -4
  7. package/lib/Carousel/CarouselItem/CarouselItem.js +24 -9
  8. package/lib/Carousel/CarouselStepTracker/CarouselStepTracker.js +56 -0
  9. package/lib/Carousel/CarouselStepTracker/index.js +13 -0
  10. package/lib/Carousel/dictionary.js +23 -0
  11. package/lib/Checkbox/Checkbox.js +7 -3
  12. package/lib/Checkbox/CheckboxGroup.js +1 -1
  13. package/lib/Feedback/Feedback.js +18 -10
  14. package/lib/Icon/IconText.js +5 -0
  15. package/lib/InputLabel/InputLabel.js +11 -5
  16. package/lib/InputSupports/InputSupports.js +10 -3
  17. package/lib/InputSupports/useInputSupports.js +3 -2
  18. package/lib/Link/LinkBase.js +7 -3
  19. package/lib/List/ListItem.js +7 -3
  20. package/lib/Modal/Modal.js +4 -0
  21. package/lib/Notification/Notification.js +7 -2
  22. package/lib/Pagination/Pagination.js +7 -3
  23. package/lib/RadioCard/RadioCard.js +6 -1
  24. package/lib/Select/Select.js +7 -3
  25. package/lib/Skeleton/Skeleton.js +1 -0
  26. package/lib/StepTracker/Step.js +8 -4
  27. package/lib/StepTracker/StepTracker.js +17 -13
  28. package/lib/Tabs/TabsItem.js +4 -0
  29. package/lib/TextInput/TextInput.js +3 -1
  30. package/lib/TextInput/TextInputBase.js +7 -3
  31. package/lib/ThemeProvider/ThemeProvider.js +20 -3
  32. package/lib/ThemeProvider/utils/styles.js +8 -1
  33. package/lib/ThemeProvider/utils/theme-tokens.js +1 -1
  34. package/lib/Typography/Typography.js +6 -2
  35. package/lib/index.js +9 -0
  36. package/lib/utils/index.js +9 -0
  37. package/lib/utils/props/clickProps.js +2 -2
  38. package/lib/utils/props/handlerProps.js +77 -31
  39. package/lib/utils/useScrollBlocking.js +66 -0
  40. package/lib/utils/useScrollBlocking.native.js +11 -0
  41. package/lib-module/BaseProvider/index.js +7 -2
  42. package/lib-module/Button/ButtonBase.js +7 -3
  43. package/lib-module/Carousel/Carousel.js +85 -70
  44. package/lib-module/Carousel/CarouselContext.js +11 -4
  45. package/lib-module/Carousel/CarouselItem/CarouselItem.js +25 -10
  46. package/lib-module/Carousel/CarouselStepTracker/CarouselStepTracker.js +42 -0
  47. package/lib-module/Carousel/CarouselStepTracker/index.js +2 -0
  48. package/lib-module/Carousel/dictionary.js +16 -0
  49. package/lib-module/Checkbox/Checkbox.js +8 -4
  50. package/lib-module/Checkbox/CheckboxGroup.js +1 -1
  51. package/lib-module/Feedback/Feedback.js +19 -11
  52. package/lib-module/Icon/IconText.js +5 -0
  53. package/lib-module/InputLabel/InputLabel.js +12 -6
  54. package/lib-module/InputSupports/InputSupports.js +10 -3
  55. package/lib-module/InputSupports/useInputSupports.js +3 -2
  56. package/lib-module/Link/LinkBase.js +8 -4
  57. package/lib-module/List/ListItem.js +8 -4
  58. package/lib-module/Modal/Modal.js +3 -0
  59. package/lib-module/Notification/Notification.js +8 -3
  60. package/lib-module/Pagination/Pagination.js +8 -4
  61. package/lib-module/RadioCard/RadioCard.js +7 -2
  62. package/lib-module/Select/Select.js +8 -4
  63. package/lib-module/Skeleton/Skeleton.js +1 -0
  64. package/lib-module/StepTracker/Step.js +9 -5
  65. package/lib-module/StepTracker/StepTracker.js +17 -14
  66. package/lib-module/Tabs/TabsItem.js +5 -1
  67. package/lib-module/TextInput/TextInput.js +3 -1
  68. package/lib-module/TextInput/TextInputBase.js +8 -4
  69. package/lib-module/ThemeProvider/ThemeProvider.js +20 -3
  70. package/lib-module/ThemeProvider/utils/styles.js +8 -1
  71. package/lib-module/ThemeProvider/utils/theme-tokens.js +1 -1
  72. package/lib-module/Typography/Typography.js +7 -3
  73. package/lib-module/index.js +1 -0
  74. package/lib-module/utils/index.js +1 -0
  75. package/lib-module/utils/props/clickProps.js +2 -2
  76. package/lib-module/utils/props/handlerProps.js +78 -31
  77. package/lib-module/utils/useScrollBlocking.js +58 -0
  78. package/lib-module/utils/useScrollBlocking.native.js +2 -0
  79. package/package.json +3 -3
  80. package/src/BaseProvider/index.jsx +6 -3
  81. package/src/Button/ButtonBase.jsx +8 -3
  82. package/src/Carousel/Carousel.jsx +106 -74
  83. package/src/Carousel/CarouselContext.jsx +15 -4
  84. package/src/Carousel/CarouselItem/CarouselItem.jsx +26 -8
  85. package/src/Carousel/CarouselStepTracker/CarouselStepTracker.jsx +36 -0
  86. package/src/Carousel/CarouselStepTracker/index.js +3 -0
  87. package/src/Carousel/dictionary.js +16 -0
  88. package/src/Checkbox/Checkbox.jsx +14 -11
  89. package/src/Checkbox/CheckboxGroup.jsx +1 -1
  90. package/src/Feedback/Feedback.jsx +14 -7
  91. package/src/Icon/IconText.jsx +2 -0
  92. package/src/InputLabel/InputLabel.jsx +13 -12
  93. package/src/InputSupports/InputSupports.jsx +18 -3
  94. package/src/InputSupports/useInputSupports.js +2 -2
  95. package/src/Link/LinkBase.jsx +10 -4
  96. package/src/List/ListItem.jsx +9 -4
  97. package/src/Modal/Modal.jsx +3 -1
  98. package/src/Notification/Notification.jsx +5 -3
  99. package/src/Pagination/Pagination.jsx +6 -4
  100. package/src/RadioCard/RadioCard.jsx +3 -2
  101. package/src/Select/Select.jsx +12 -3
  102. package/src/Skeleton/Skeleton.jsx +1 -0
  103. package/src/StepTracker/Step.jsx +12 -4
  104. package/src/StepTracker/StepTracker.jsx +20 -13
  105. package/src/Tabs/TabsItem.jsx +3 -2
  106. package/src/TextInput/TextInput.jsx +1 -1
  107. package/src/TextInput/TextInputBase.jsx +11 -3
  108. package/src/ThemeProvider/ThemeProvider.jsx +16 -3
  109. package/src/ThemeProvider/utils/styles.js +9 -1
  110. package/src/ThemeProvider/utils/theme-tokens.js +1 -1
  111. package/src/Typography/Typography.jsx +11 -12
  112. package/src/index.js +1 -0
  113. package/src/utils/index.js +1 -0
  114. package/src/utils/props/clickProps.js +2 -2
  115. package/src/utils/props/handlerProps.js +64 -16
  116. package/src/utils/useScrollBlocking.js +57 -0
  117. package/src/utils/useScrollBlocking.native.js +2 -0
@@ -7,13 +7,13 @@ import Platform from "react-native-web/dist/exports/Platform";
7
7
  import PropTypes from 'prop-types';
8
8
  import { useThemeTokens } from '../ThemeProvider';
9
9
  import { useViewport } from '../ViewportProvider';
10
- import { getTokensPropType, variantProp, selectSystemProps, a11yProps, viewProps } from '../utils';
10
+ import { getTokensPropType, getA11yPropsFromHtmlTag, layoutTags, variantProp, selectSystemProps, a11yProps, viewProps, useCopy } from '../utils';
11
11
  import { useA11yInfo } from '../A11yInfoProvider';
12
12
  import { CarouselProvider } from './CarouselContext';
13
13
  import CarouselItem from './CarouselItem';
14
- import StepTracker from '../StepTracker';
15
- import StackView from '../StackView';
16
14
  import IconButton from '../IconButton';
15
+ import CarouselStepTracker from './CarouselStepTracker/CarouselStepTracker';
16
+ import dictionary from './dictionary';
17
17
  import { jsx as _jsx } from "react/jsx-runtime";
18
18
  import { jsxs as _jsxs } from "react/jsx-runtime";
19
19
  const staticStyles = StyleSheet.create({
@@ -26,18 +26,6 @@ const staticStyles = StyleSheet.create({
26
26
  left: 0
27
27
  }
28
28
  });
29
- const staticTokens = {
30
- stackView: {
31
- justifyContent: 'center'
32
- },
33
- stepTracker: {
34
- showStepLabel: false,
35
- showStepTrackerLabel: true,
36
- knobCompletedBackgroundColor: 'none',
37
- connectorCompletedColor: 'none',
38
- connectorColor: 'none'
39
- }
40
- };
41
29
 
42
30
  const selectContainerStyles = width => ({
43
31
  backgroundColor: 'transparent',
@@ -77,14 +65,6 @@ const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWi
77
65
  return styles;
78
66
  };
79
67
 
80
- const defaultPanelNavigationDictionary = {
81
- en: {
82
- stepTrackerLabel: 'Showing %{stepNumber} of %{stepCount}'
83
- },
84
- fr: {
85
- stepTrackerLabel: 'Étape %{stepNumber} sur %{stepCount}: %{stepLabel}'
86
- }
87
- };
88
68
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
89
69
  /**
90
70
  * Carousel is a general-purpose content slider that can be used to render content in terms of slides.
@@ -146,6 +126,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
146
126
  tokens,
147
127
  variant,
148
128
  children,
129
+ itemLabel = 'item',
149
130
  previousNextNavigationPosition = 'inside',
150
131
  previousNextIconSize = 'default',
151
132
  minDistanceToCapture = 5,
@@ -154,24 +135,38 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
154
135
  onAnimationEnd,
155
136
  onIndexChanged,
156
137
  springConfig = undefined,
157
- onRenderPanelNavigation,
158
- panelNavigationTextDictionary = defaultPanelNavigationDictionary,
138
+ panelNavigation = /*#__PURE__*/_jsx(CarouselStepTracker, {}),
139
+ tag = 'ul',
159
140
  accessibilityRole = 'adjustable',
160
141
  accessibilityLabel = 'carousel',
142
+ copy,
161
143
  ...rest
162
144
  } = _ref;
163
145
  const viewport = useViewport();
146
+ const themeTokens = useThemeTokens('Carousel', tokens, variant, {
147
+ viewport
148
+ });
164
149
  const {
165
150
  previousIcon,
166
151
  nextIcon,
167
152
  showPreviousNextNavigation,
168
153
  showPanelNavigation,
169
- spaceBetweenSlideAndPreviousNextNavigation,
170
- spaceBetweenSlideAndPanelNavigation
171
- } = useThemeTokens('Carousel', tokens, variant, {
172
- viewport
173
- });
154
+ spaceBetweenSlideAndPreviousNextNavigation
155
+ } = themeTokens;
174
156
  const [activeIndex, setActiveIndex] = React.useState(0);
157
+ const [isAnimating, setIsAnimating] = React.useState(false);
158
+ const handleAnimationStart = React.useCallback(function () {
159
+ if (typeof onAnimationStart === 'function') onAnimationStart(...arguments);
160
+ setIsAnimating(true);
161
+ }, [onAnimationStart]);
162
+ const handleAnimationEnd = React.useCallback(function () {
163
+ if (typeof onAnimationEnd === 'function') onAnimationEnd(...arguments);
164
+ setIsAnimating(false);
165
+ }, [onAnimationEnd]);
166
+ const getCopy = useCopy({
167
+ dictionary,
168
+ copy
169
+ });
175
170
  const childrenArray = React.Children.toArray(children);
176
171
  const systemProps = selectProps({ ...rest,
177
172
  accessibilityRole,
@@ -196,9 +191,6 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
196
191
  const animatedY = React.useRef(0);
197
192
  const isFirstSlide = !activeIndex;
198
193
  const isLastSlide = activeIndex + 1 >= children.length;
199
- const panelNavigationTokens = { ...staticTokens.stepTracker,
200
- containerPaddingTop: spaceBetweenSlideAndPanelNavigation
201
- };
202
194
 
203
195
  const onContainerLayout = _ref2 => {
204
196
  let {
@@ -240,20 +232,28 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
240
232
  y: 0
241
233
  });
242
234
  }, [activeIndex, containerLayout.width, pan, animatedX]);
243
- const animate = React.useCallback(toValue => {
235
+ const animate = React.useCallback((toValue, toIndex) => {
236
+ const handleAnimationEndToIndex = function () {
237
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
238
+ args[_key] = arguments[_key];
239
+ }
240
+
241
+ return handleAnimationEnd(toIndex, ...args);
242
+ };
243
+
244
244
  if (reduceMotionEnabled) {
245
245
  Animated.timing(pan, {
246
246
  toValue,
247
247
  duration: 1,
248
248
  useNativeDriver: false
249
- }).start();
249
+ }).start(handleAnimationEndToIndex);
250
250
  } else {
251
251
  Animated.spring(pan, { ...springConfig,
252
252
  toValue,
253
253
  useNativeDriver: false
254
- }).start();
254
+ }).start(handleAnimationEndToIndex);
255
255
  }
256
- }, [pan, springConfig, reduceMotionEnabled]);
256
+ }, [pan, springConfig, reduceMotionEnabled, handleAnimationEnd]);
257
257
  const updateIndex = React.useCallback(function () {
258
258
  let delta = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
259
259
  const toValue = {
@@ -271,24 +271,24 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
271
271
  calcDelta = -1 * activeIndex + delta - 1;
272
272
  }
273
273
 
274
+ const index = activeIndex + calcDelta;
275
+
274
276
  if (skipChanges) {
275
- animate(toValue);
277
+ animate(toValue, index);
276
278
  return calcDelta;
277
279
  }
278
280
 
279
- const index = activeIndex + calcDelta;
280
281
  setActiveIndex(index);
281
282
  toValue.x = containerLayout.width * -1 * calcDelta;
282
- animate(toValue);
283
+ animate(toValue, index);
283
284
  if (onIndexChanged) onIndexChanged(calcDelta);
284
- if (onAnimationEnd) onAnimationEnd(index);
285
285
  return calcDelta;
286
- }, [containerLayout.width, activeIndex, animate, children.length, onIndexChanged, onAnimationEnd]);
286
+ }, [containerLayout.width, activeIndex, animate, children.length, onIndexChanged]);
287
287
  const fixOffsetAndGo = React.useCallback(delta => {
288
288
  updateOffset();
289
- if (onAnimationStart) onAnimationStart(activeIndex);
289
+ handleAnimationStart(activeIndex);
290
290
  updateIndex(delta);
291
- }, [updateIndex, updateOffset, activeIndex, onAnimationStart]);
291
+ }, [updateIndex, updateOffset, activeIndex, handleAnimationStart]);
292
292
  const goToNeighboring = React.useCallback(function () {
293
293
  let toPrev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
294
294
  fixOffsetAndGo(toPrev ? -1 : 1);
@@ -308,7 +308,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
308
308
  return false;
309
309
  }
310
310
 
311
- if (onAnimationStart) onAnimationStart(activeIndex);
311
+ handleAnimationStart(activeIndex);
312
312
  return Math.abs(gestureState.dx) > minDistanceToCapture;
313
313
  },
314
314
  onPanResponderGrant: () => updateOffset(),
@@ -324,13 +324,13 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
324
324
  animate({
325
325
  x: 0,
326
326
  y: 0
327
- });
327
+ }, 0);
328
328
  } else {
329
329
  const delta = correction > 0 ? -1 : 1;
330
330
  updateIndex(delta);
331
331
  }
332
332
  }
333
- }), [containerLayout.width, updateIndex, updateOffset, animate, isSwipeAllowed, activeIndex, minDistanceForAction, onAnimationStart, minDistanceToCapture, pan.x]);
333
+ }), [containerLayout.width, updateIndex, updateOffset, animate, isSwipeAllowed, activeIndex, minDistanceForAction, handleAnimationStart, minDistanceToCapture, pan.x]);
334
334
  React.useEffect(() => {
335
335
  pan.x.addListener(_ref4 => {
336
336
  let {
@@ -370,11 +370,18 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
370
370
  size: previousNextIconSize,
371
371
  raised: true
372
372
  };
373
+ const getCopyWithPlaceholders = React.useCallback(copyKey => {
374
+ 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
375
+
376
+ return "".concat(copyText[0].toUpperCase()).concat(copyText.slice(1));
377
+ }, [activeIndex, childrenArray.length, itemLabel, getCopy]);
373
378
  return /*#__PURE__*/_jsxs(CarouselProvider, {
374
379
  activeIndex: activeIndex,
375
380
  totalItems: childrenArray.length,
376
381
  width: containerLayout.width,
377
382
  goTo: goTo,
383
+ getCopyWithPlaceholders: getCopyWithPlaceholders,
384
+ themeTokens: themeTokens,
378
385
  children: [/*#__PURE__*/_jsxs(View, {
379
386
  style: staticStyles.root,
380
387
  onLayout: onContainerLayout,
@@ -388,7 +395,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
388
395
  icon: previousIcon,
389
396
  onPress: goToPrev,
390
397
  variant: previousNextIconButtonVariants,
391
- accessibilityLabel: "previous-button"
398
+ accessibilityLabel: getCopyWithPlaceholders('iconButtonLabel').replace('%{targetStep}', activeIndex)
392
399
  })
393
400
  }), /*#__PURE__*/_jsx(View, {
394
401
  style: selectContainerStyles(containerLayout.width),
@@ -401,9 +408,12 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
401
408
  }]
402
409
  }]),
403
410
  ...panResponder.panHandlers,
411
+ ...getA11yPropsFromHtmlTag(tag),
404
412
  children: childrenArray.map((element, index) => {
413
+ const hidden = !isAnimating && index !== activeIndex;
405
414
  const clonedElement = /*#__PURE__*/React.cloneElement(element, {
406
- elementIndex: index
415
+ elementIndex: index,
416
+ hidden
407
417
  });
408
418
  return /*#__PURE__*/_jsx(React.Fragment, {
409
419
  children: clonedElement
@@ -418,22 +428,10 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref, ref) => {
418
428
  icon: nextIcon,
419
429
  onPress: goToNext,
420
430
  variant: previousNextIconButtonVariants,
421
- accessibilityLabel: "next-button"
431
+ accessibilityLabel: getCopyWithPlaceholders('iconButtonLabel').replace('%{targetStep}', activeIndex + 2)
422
432
  })
423
433
  })]
424
- }), showPanelNavigation ? /*#__PURE__*/_jsx(StackView, {
425
- direction: "row",
426
- tokens: staticTokens.stackView,
427
- children: onRenderPanelNavigation ? onRenderPanelNavigation({
428
- activeIndex,
429
- totalItems: childrenArray.length
430
- }) : /*#__PURE__*/_jsx(StepTracker, {
431
- current: activeIndex,
432
- steps: childrenArray.map((_, index) => String(index)),
433
- dictionary: panelNavigationTextDictionary,
434
- tokens: panelNavigationTokens
435
- })
436
- }) : null]
434
+ }), showPanelNavigation ? panelNavigation : null]
437
435
  });
438
436
  });
439
437
  Carousel.propTypes = { ...selectedSystemPropTypes,
@@ -445,6 +443,14 @@ Carousel.propTypes = { ...selectedSystemPropTypes,
445
443
  */
446
444
  children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
447
445
 
446
+ /**
447
+ * Lowercase language-appropriate user-facing description of what each Carousel slide represents.
448
+ * This is used when generating item labels. For example, if a carousel contains offers,
449
+ * pass itemLabel="summer offer" (or copy="fr" and an appropriate French translation) to genereate
450
+ * accessible labels such as "Summer offer 1 of 3" and "Show summer offer 2 of 3".
451
+ */
452
+ itemLabel: PropTypes.string,
453
+
448
454
  /**
449
455
  * `inside` renders the previous and next buttons inside the slide
450
456
  * `outside` renders the previous and next buttons outside the slide
@@ -492,20 +498,20 @@ Carousel.propTypes = { ...selectedSystemPropTypes,
492
498
  onIndexChanged: PropTypes.func,
493
499
 
494
500
  /**
495
- * Use this to render a custom panel navigation element instead of dots navigation
496
- * This function is also provided with an object with the following properties
497
- * activeIndex: index of current slide
498
- * totalItems: total number of slides
501
+ * Use this to render a custom panel navigation element instead of the default StepTracker's based navigation
502
+ * You can make use of `useCarousel` within your custom panel navigation component to hook into various Carousel states such as:
503
+ * - activeIndex: index of current slide
504
+ * - totalItems: total number of slides
499
505
  * Use it as follows:
500
506
  * ```js
501
507
  * <Carousel
502
- * onRenderPanelNavigation={({ totalItems, activeIndex }) => <Text>Showing {activeIndex + 1}</Text>}
508
+ * panelNavigation={<CustomPanelNavigation />}
503
509
  * >
504
510
  * <Carousel.Item>First Slide</Carousel.Item>
505
511
  * </Carousel>
506
512
  * ```
507
513
  */
508
- onRenderPanelNavigation: PropTypes.func,
514
+ panelNavigation: PropTypes.element,
509
515
 
510
516
  /**
511
517
  * When slide animation start
@@ -563,7 +569,16 @@ Carousel.propTypes = { ...selectedSystemPropTypes,
563
569
  /**
564
570
  * Provide custom accessibilityLabel for Carousel container
565
571
  */
566
- accessibilityLabel: PropTypes.string
572
+ accessibilityLabel: PropTypes.string,
573
+
574
+ /**
575
+ * HTML tag to use for the Carousel item's immediate parent. Defaults to `'ul'` so that
576
+ * assistive technology tools know to intepret the carousel as a list.
577
+ *
578
+ * Note that if the immediate Carousel children do not all render as `'li'` elements,
579
+ * this should be changed (e.g. pass tag="div") because only 'li' is a valid child of 'ul'.
580
+ */
581
+ tag: PropTypes.oneOf(layoutTags)
567
582
  };
568
583
  Carousel.Item = CarouselItem;
569
584
  Carousel.displayName = 'Carousel';
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
+ import { getTokensPropType } from '../utils';
3
4
  import { jsx as _jsx } from "react/jsx-runtime";
4
5
  const CarouselContext = /*#__PURE__*/React.createContext();
5
6
 
@@ -9,14 +10,18 @@ const CarouselProvider = _ref => {
9
10
  activeIndex,
10
11
  totalItems,
11
12
  width,
12
- goTo
13
+ goTo,
14
+ getCopyWithPlaceholders,
15
+ themeTokens
13
16
  } = _ref;
14
17
  const value = React.useMemo(() => ({
15
18
  activeIndex,
16
19
  totalItems,
17
20
  width,
18
- goTo
19
- }), [activeIndex, totalItems, width, goTo]);
21
+ goTo,
22
+ getCopyWithPlaceholders,
23
+ themeTokens
24
+ }), [activeIndex, totalItems, width, goTo, getCopyWithPlaceholders, themeTokens]);
20
25
  return /*#__PURE__*/_jsx(CarouselContext.Provider, {
21
26
  value: value,
22
27
  children: children
@@ -38,6 +43,8 @@ CarouselProvider.propTypes = {
38
43
  activeIndex: PropTypes.number.isRequired,
39
44
  totalItems: PropTypes.number.isRequired,
40
45
  width: PropTypes.number.isRequired,
41
- goTo: PropTypes.func.isRequired
46
+ goTo: PropTypes.func.isRequired,
47
+ getCopyWithPlaceholders: PropTypes.func.isRequired,
48
+ themeTokens: getTokensPropType('Carousel')
42
49
  };
43
50
  export { CarouselProvider, useCarousel };
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import View from "react-native-web/dist/exports/View";
4
4
  import Platform from "react-native-web/dist/exports/Platform";
5
- import { selectSystemProps, a11yProps, viewProps } from '../../utils';
5
+ import { layoutTags, getA11yPropsFromHtmlTag, selectSystemProps, a11yProps, viewProps } from '../../utils';
6
6
  import { useCarousel } from '../CarouselContext';
7
7
  import { jsx as _jsx } from "react/jsx-runtime";
8
8
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
@@ -15,23 +15,29 @@ const CarouselItem = _ref => {
15
15
  let {
16
16
  children,
17
17
  elementIndex,
18
+ tag = 'li',
19
+ hidden,
18
20
  ...rest
19
21
  } = _ref;
20
22
  const {
21
23
  width,
22
- activeIndex,
23
- totalItems
24
+ activeIndex
24
25
  } = useCarousel();
25
26
  const selectedProps = selectProps({ ...rest,
26
- // `group` role crashes the app on Android so setting it to `none` for Android
27
- accessibilityRole: Platform.OS === 'android' ? 'none' : 'group',
28
- accessibilityLabel: "Showing ".concat(elementIndex + 1, " of ").concat(totalItems)
27
+ ...getA11yPropsFromHtmlTag(tag, rest.accessibilityRole)
29
28
  });
30
29
  const focusabilityProps = activeIndex === elementIndex ? {} : a11yProps.nonFocusableProps;
30
+ const style = {
31
+ width
32
+ };
33
+
34
+ if (hidden && Platform.OS === 'web') {
35
+ // On web, visibility: hidden makes all children non-focusable. It doesn't exist on native.
36
+ style.visibility = 'hidden';
37
+ }
38
+
31
39
  return /*#__PURE__*/_jsx(View, {
32
- style: {
33
- width
34
- },
40
+ style: style,
35
41
  ...selectedProps,
36
42
  ...focusabilityProps,
37
43
  children: children
@@ -54,7 +60,16 @@ CarouselItem.propTypes = { ...selectedSystemPropTypes,
54
60
  /**
55
61
  * Content of the slide
56
62
  */
57
- children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired
63
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]).isRequired,
64
+
65
+ /**
66
+ * Sets the HTML tag of the outer container. By default `'li'` so that assistive technology sees
67
+ * the Carousel as a list of items.
68
+ *
69
+ * Carousel's innermost container defaults to `'ul'` which can be overridden. If the tag of either
70
+ * `Carousel` or `Carousel.Item` is overriden, the other should be too, to avoid producing invalid HTML.
71
+ */
72
+ tag: PropTypes.oneOf(layoutTags)
58
73
  };
59
74
  CarouselItem.displayName = 'Carousel.Item';
60
75
  export default CarouselItem;
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { useCarousel } from '../CarouselContext';
3
+ import StepTracker from '../../StepTracker';
4
+ import StackView from '../../StackView';
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+
7
+ const CarouselStepTracker = () => {
8
+ const {
9
+ activeIndex,
10
+ totalItems,
11
+ getCopyWithPlaceholders,
12
+ themeTokens
13
+ } = useCarousel();
14
+ const stackViewTokens = {
15
+ justifyContent: 'center'
16
+ };
17
+ const stepTrackerTokens = {
18
+ showStepLabel: false,
19
+ showStepTrackerLabel: true,
20
+ knobCompletedBackgroundColor: 'none',
21
+ connectorCompletedColor: 'none',
22
+ connectorColor: 'none',
23
+ containerPaddingTop: themeTokens.spaceBetweenSlideAndPanelNavigation
24
+ };
25
+ const steps = Array.from(Array(totalItems)).map((_, index) => String(index));
26
+ return /*#__PURE__*/_jsx(StackView, {
27
+ direction: "row",
28
+ tokens: stackViewTokens,
29
+ children: /*#__PURE__*/_jsx(StepTracker, {
30
+ current: activeIndex,
31
+ steps: steps,
32
+ copy: {
33
+ // Give StepTracker copy from Carousel's language and dictionary
34
+ stepLabel: getCopyWithPlaceholders('stepLabel'),
35
+ stepTrackerLabel: getCopyWithPlaceholders('stepTrackerLabel')
36
+ },
37
+ tokens: stepTrackerTokens
38
+ })
39
+ });
40
+ };
41
+
42
+ export default CarouselStepTracker;
@@ -0,0 +1,2 @@
1
+ import CarouselStepTracker from './CarouselStepTracker';
2
+ export default CarouselStepTracker;
@@ -0,0 +1,16 @@
1
+ // 'stepLabel' and 'stepTrackerLabel' are passed down to StepTracker
2
+ export default {
3
+ en: {
4
+ carouselLabel: '%{stepCount} items',
5
+ iconButtonLabel: 'Show %{itemLabel} %{targetStep} of %{stepCount}',
6
+ stepLabel: '%{itemLabel} %{stepNumber}',
7
+ stepTrackerLabel: '%{itemLabel} %{stepNumber} of %{stepCount}'
8
+ },
9
+ fr: {
10
+ // TODO: French translations here
11
+ carouselLabel: '(fr) %{stepCount} items',
12
+ iconButtonLabel: '(fr) Show %{itemLabel} %{targetStep} of %{stepCount}',
13
+ stepLabel: '(fr) %{itemLabel} %{stepNumber}',
14
+ stepTrackerLabel: '(fr) %{itemLabel} %{stepNumber} of %{stepCount}'
15
+ }
16
+ };
@@ -9,7 +9,7 @@ import CheckboxInput from './CheckboxInput';
9
9
  import CheckboxLabel from '../InputLabel/LabelContent';
10
10
  import Feedback from '../Feedback';
11
11
  import StackView from '../StackView';
12
- import { applyShadowToken, applyTextStyles, useThemeTokensCallback } from '../ThemeProvider';
12
+ import { applyShadowToken, applyTextStyles, useTheme, useThemeTokensCallback } from '../ThemeProvider';
13
13
  import { a11yProps, focusHandlerProps, getTokensPropType, selectSystemProps, useInputValue, variantProp, viewProps } from '../utils';
14
14
  import useUniqueId from '../utils/useUniqueId';
15
15
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -47,7 +47,7 @@ const selectInputStyles = (_ref, isChecked) => {
47
47
  };
48
48
  };
49
49
 
50
- const selectLabelStyles = _ref2 => {
50
+ const selectLabelStyles = (_ref2, themeOptions) => {
51
51
  let {
52
52
  labelColor,
53
53
  labelFontName,
@@ -63,7 +63,8 @@ const selectLabelStyles = _ref2 => {
63
63
  fontName: labelFontName,
64
64
  fontWeight: labelFontWeight,
65
65
  fontSize: labelFontSize,
66
- lineHeight: labelLineHeight
66
+ lineHeight: labelLineHeight,
67
+ themeOptions
67
68
  })
68
69
  };
69
70
  };
@@ -187,6 +188,9 @@ const Checkbox = /*#__PURE__*/forwardRef((_ref5, ref) => {
187
188
 
188
189
  const uniqueId = useUniqueId('checkbox');
189
190
  const inputId = id !== null && id !== void 0 ? id : uniqueId;
191
+ const {
192
+ themeOptions
193
+ } = useTheme();
190
194
  return /*#__PURE__*/_jsx(View, {
191
195
  style: staticStyles.wrapper,
192
196
  ref: ref,
@@ -218,7 +222,7 @@ const Checkbox = /*#__PURE__*/forwardRef((_ref5, ref) => {
218
222
  pressed
219
223
  });
220
224
  const iconTokens = selectIconTokens(stateTokens);
221
- const labelStyles = selectLabelStyles(stateTokens);
225
+ const labelStyles = selectLabelStyles(stateTokens, themeOptions);
222
226
  const alignWithLabel = label ? [staticStyles.alignWithLabel, {
223
227
  height: labelStyles.lineHeight
224
228
  }] : null;
@@ -46,7 +46,7 @@ const [selectItemProps, selectedItemPropTypes] = selectSystemProps([a11yProps, f
46
46
  * @example
47
47
  * ```jsx
48
48
  * <CheckboxGroup
49
- * initialCheckedId="check1"
49
+ * initialCheckedIds="check1"
50
50
  * items={[
51
51
  * { label: 'Checkbox 1', id: 'check1' },
52
52
  * { label: 'Checkbox 2', id: 'check2' },
@@ -3,7 +3,7 @@ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
3
3
  import Text from "react-native-web/dist/exports/Text";
4
4
  import View from "react-native-web/dist/exports/View";
5
5
  import PropTypes from 'prop-types';
6
- import { applyTextStyles, useThemeTokens } from '../ThemeProvider';
6
+ import { applyTextStyles, useTheme, useThemeTokens } from '../ThemeProvider';
7
7
  import { a11yProps, getTokensPropType, selectSystemProps, selectTokens, variantProp, viewProps } from '../utils';
8
8
  import StackView from '../StackView';
9
9
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -12,24 +12,29 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
12
12
 
13
13
  const selectStyles = tokens => selectTokens('Feedback', tokens);
14
14
 
15
- const selectTitleTextStyles = _ref => {
15
+ const selectTitleTextStyles = (_ref, themeOptions) => {
16
16
  let {
17
17
  titleFontSize,
18
18
  ...tokens
19
19
  } = _ref;
20
- return applyTextStyles(selectTokens('Typography', { ...tokens,
21
- fontSize: titleFontSize
22
- }));
20
+ return applyTextStyles({ ...selectTokens('Typography', { ...tokens,
21
+ fontSize: titleFontSize,
22
+ themeOptions
23
+ }),
24
+ themeOptions
25
+ });
23
26
  };
24
27
 
25
- const selectContentTextStyles = _ref2 => {
28
+ const selectContentTextStyles = (_ref2, themeOptions) => {
26
29
  let {
27
30
  contentFontSize,
28
31
  ...tokens
29
32
  } = _ref2;
30
- return applyTextStyles(selectTokens('Typography', { ...tokens,
31
- fontSize: contentFontSize
32
- }));
33
+ return applyTextStyles({ ...selectTokens('Typography', { ...tokens,
34
+ fontSize: contentFontSize
35
+ }),
36
+ themeOptions
37
+ });
33
38
  };
34
39
 
35
40
  const selectIconTokens = _ref3 => {
@@ -90,8 +95,11 @@ const Feedback = /*#__PURE__*/forwardRef((_ref5, ref) => {
90
95
  const {
91
96
  icon: IconComponent
92
97
  } = themeTokens;
93
- const titleTextStyles = selectTitleTextStyles(themeTokens);
94
- const contentTextStyles = selectContentTextStyles(themeTokens);
98
+ const {
99
+ themeOptions
100
+ } = useTheme();
101
+ const titleTextStyles = selectTitleTextStyles(themeTokens, themeOptions);
102
+ const contentTextStyles = selectContentTextStyles(themeTokens, themeOptions);
95
103
  const content = typeof children === 'string' ? /*#__PURE__*/_jsx(Text, {
96
104
  style: contentTextStyles,
97
105
  children: children
@@ -51,6 +51,9 @@ const IconText = /*#__PURE__*/forwardRef((_ref, ref) => {
51
51
  });
52
52
  IconText.displayName = 'IconText';
53
53
  IconText.propTypes = {
54
+ /* eslint-disable react/no-unused-prop-types */
55
+ // eslint is having hard time seeing these props through forwardRef
56
+
54
57
  /**
55
58
  * Amount of space to separate the text content and icon. Uses the themes's spacing scale
56
59
  * (see useSpacingScale for more info).
@@ -79,5 +82,7 @@ IconText.propTypes = {
79
82
  * `<Typography>` component, or a component that renders `<Text>`.
80
83
  */
81
84
  children: PropTypes.node
85
+ /* eslint-enable react/no-unused-prop-types */
86
+
82
87
  };
83
88
  export default IconText;