@telus-uds/components-base 1.12.1 → 1.14.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 (84) hide show
  1. package/CHANGELOG.md +41 -2
  2. package/component-docs.json +888 -66
  3. package/lib/Button/ButtonBase.js +36 -7
  4. package/lib/Button/ButtonGroup.js +7 -0
  5. package/lib/Button/propTypes.js +18 -0
  6. package/lib/Carousel/Carousel.js +69 -12
  7. package/lib/Carousel/CarouselContext.js +17 -11
  8. package/lib/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +73 -0
  9. package/lib/Carousel/CarouselTabs/CarouselTabs.js +70 -0
  10. package/lib/Carousel/CarouselTabs/CarouselTabsPanel.js +95 -0
  11. package/lib/Carousel/CarouselTabs/CarouselTabsPanelItem.js +148 -0
  12. package/lib/Carousel/CarouselTabs/index.js +13 -0
  13. package/lib/Carousel/CarouselThumbnail.js +99 -0
  14. package/lib/Carousel/CarouselThumbnailNavigation.js +87 -0
  15. package/lib/Carousel/dictionary.js +4 -2
  16. package/lib/Carousel/index.js +10 -1
  17. package/lib/Checkbox/CheckboxGroup.js +7 -0
  18. package/lib/Icon/IconText.js +1 -1
  19. package/lib/Link/InlinePressable.js +1 -8
  20. package/lib/Link/LinkBase.js +6 -7
  21. package/lib/List/ListItem.js +1 -1
  22. package/lib/Notification/Notification.js +37 -22
  23. package/lib/Radio/RadioGroup.js +8 -0
  24. package/lib/RadioCard/RadioCardGroup.js +7 -0
  25. package/lib/SkipLink/SkipLink.js +216 -0
  26. package/lib/SkipLink/index.js +13 -0
  27. package/lib/ThemeProvider/ThemeProvider.js +6 -1
  28. package/lib/ToggleSwitch/ToggleSwitchGroup.js +7 -0
  29. package/lib/index.js +9 -0
  30. package/lib-module/Button/ButtonBase.js +35 -7
  31. package/lib-module/Button/ButtonGroup.js +7 -0
  32. package/lib-module/Button/propTypes.js +17 -0
  33. package/lib-module/Carousel/Carousel.js +66 -11
  34. package/lib-module/Carousel/CarouselContext.js +17 -11
  35. package/lib-module/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +51 -0
  36. package/lib-module/Carousel/CarouselTabs/CarouselTabs.js +50 -0
  37. package/lib-module/Carousel/CarouselTabs/CarouselTabsPanel.js +76 -0
  38. package/lib-module/Carousel/CarouselTabs/CarouselTabsPanelItem.js +126 -0
  39. package/lib-module/Carousel/CarouselTabs/index.js +2 -0
  40. package/lib-module/Carousel/CarouselThumbnail.js +85 -0
  41. package/lib-module/Carousel/CarouselThumbnailNavigation.js +66 -0
  42. package/lib-module/Carousel/dictionary.js +4 -2
  43. package/lib-module/Carousel/index.js +2 -1
  44. package/lib-module/Checkbox/CheckboxGroup.js +7 -0
  45. package/lib-module/Icon/IconText.js +1 -1
  46. package/lib-module/Link/InlinePressable.js +1 -8
  47. package/lib-module/Link/LinkBase.js +6 -7
  48. package/lib-module/List/ListItem.js +1 -1
  49. package/lib-module/Notification/Notification.js +38 -23
  50. package/lib-module/Radio/RadioGroup.js +8 -0
  51. package/lib-module/RadioCard/RadioCardGroup.js +7 -0
  52. package/lib-module/SkipLink/SkipLink.js +188 -0
  53. package/lib-module/SkipLink/index.js +2 -0
  54. package/lib-module/ThemeProvider/ThemeProvider.js +5 -1
  55. package/lib-module/ToggleSwitch/ToggleSwitchGroup.js +7 -0
  56. package/lib-module/index.js +1 -0
  57. package/package.json +46 -47
  58. package/src/Button/ButtonBase.jsx +28 -9
  59. package/src/Button/ButtonGroup.jsx +6 -0
  60. package/src/Button/propTypes.js +14 -0
  61. package/src/Carousel/Carousel.jsx +68 -10
  62. package/src/Carousel/CarouselContext.jsx +22 -9
  63. package/src/Carousel/CarouselFirstFocus/CarouselFirstFocus.jsx +49 -0
  64. package/src/Carousel/CarouselTabs/CarouselTabs.jsx +37 -0
  65. package/src/Carousel/CarouselTabs/CarouselTabsPanel.jsx +69 -0
  66. package/src/Carousel/CarouselTabs/CarouselTabsPanelItem.jsx +119 -0
  67. package/src/Carousel/CarouselTabs/index.js +3 -0
  68. package/src/Carousel/CarouselThumbnail.jsx +77 -0
  69. package/src/Carousel/CarouselThumbnailNavigation.jsx +53 -0
  70. package/src/Carousel/dictionary.js +4 -2
  71. package/src/Carousel/index.js +1 -0
  72. package/src/Checkbox/CheckboxGroup.jsx +7 -0
  73. package/src/Icon/IconText.jsx +1 -1
  74. package/src/Link/InlinePressable.jsx +2 -8
  75. package/src/Link/LinkBase.jsx +8 -17
  76. package/src/List/ListItem.jsx +1 -1
  77. package/src/Notification/Notification.jsx +35 -20
  78. package/src/Radio/RadioGroup.jsx +7 -0
  79. package/src/RadioCard/RadioCardGroup.jsx +6 -0
  80. package/src/SkipLink/SkipLink.jsx +179 -0
  81. package/src/SkipLink/index.js +3 -0
  82. package/src/ThemeProvider/ThemeProvider.jsx +7 -1
  83. package/src/ToggleSwitch/ToggleSwitchGroup.jsx +6 -0
  84. package/src/index.js +1 -0
@@ -6,22 +6,26 @@ const CarouselContext = /*#__PURE__*/React.createContext();
6
6
 
7
7
  const CarouselProvider = _ref => {
8
8
  let {
9
- children,
10
9
  activeIndex,
11
- totalItems,
12
- width,
10
+ children,
13
11
  goTo,
14
12
  getCopyWithPlaceholders,
15
- themeTokens
13
+ itemLabel,
14
+ refocus = false,
15
+ themeTokens,
16
+ totalItems,
17
+ width
16
18
  } = _ref;
17
19
  const value = React.useMemo(() => ({
18
20
  activeIndex,
19
- totalItems,
20
- width,
21
21
  goTo,
22
22
  getCopyWithPlaceholders,
23
- themeTokens
24
- }), [activeIndex, totalItems, width, goTo, getCopyWithPlaceholders, themeTokens]);
23
+ itemLabel,
24
+ refocus,
25
+ themeTokens,
26
+ totalItems,
27
+ width
28
+ }), [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width]);
25
29
  return /*#__PURE__*/_jsx(CarouselContext.Provider, {
26
30
  value: value,
27
31
  children: children
@@ -41,10 +45,12 @@ function useCarousel() {
41
45
  CarouselProvider.propTypes = {
42
46
  children: PropTypes.arrayOf(PropTypes.element).isRequired,
43
47
  activeIndex: PropTypes.number.isRequired,
44
- totalItems: PropTypes.number.isRequired,
45
- width: PropTypes.number.isRequired,
46
48
  goTo: PropTypes.func.isRequired,
47
49
  getCopyWithPlaceholders: PropTypes.func.isRequired,
48
- themeTokens: getTokensPropType('Carousel')
50
+ itemLabel: PropTypes.string.isRequired,
51
+ refocus: PropTypes.bool,
52
+ themeTokens: getTokensPropType('Carousel'),
53
+ totalItems: PropTypes.number.isRequired,
54
+ width: PropTypes.number.isRequired
49
55
  };
50
56
  export { CarouselProvider, useCarousel };
@@ -0,0 +1,51 @@
1
+ import React, { forwardRef } from 'react';
2
+ import Pressable from "react-native-web/dist/exports/Pressable";
3
+ import Platform from "react-native-web/dist/exports/Platform";
4
+ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
5
+ import { PropTypes } from 'prop-types';
6
+ import { useCarousel } from '../CarouselContext';
7
+ /**
8
+ * Focus target so that when a new slide is shown, the user can tab into
9
+ * its content using the keyboard.
10
+ *
11
+ * @TODO rework this after integrating with SkipLink when available.
12
+ */
13
+
14
+ import { jsx as _jsx } from "react/jsx-runtime";
15
+ const CarouselFirstFocus = /*#__PURE__*/forwardRef((_ref, ref) => {
16
+ let {
17
+ title
18
+ } = _ref;
19
+ const {
20
+ getCopyWithPlaceholders
21
+ } = useCarousel(); // TODO: integrate skip link description if behaving as skip link.
22
+ // Consider moving this content to aria-live area while only the skip link is focused.
23
+
24
+ const accessibilityLabel = "".concat(title, ", ").concat(getCopyWithPlaceholders('stepTrackerLabel'));
25
+ const accessibilityRole = Platform.select({
26
+ web: 'link',
27
+ // The focused item will ultimately be a skip link.
28
+ default: 'button' // 'link' role usually denotes opening browser on Native.
29
+
30
+ });
31
+ return /*#__PURE__*/_jsx(Pressable // TODO: integrate skip link functionality, jump focus to after Carousel
32
+ , {
33
+ onPress: undefined,
34
+ ref: ref,
35
+ accessibilityLabel: accessibilityLabel,
36
+ accessibilityRole: accessibilityRole,
37
+ style: StyleSheet.absoluteFill,
38
+ focusable: true
39
+ });
40
+ });
41
+ CarouselFirstFocus.displayName = 'CarouselFirstFocus';
42
+ CarouselFirstFocus.propTypes = {
43
+ /**
44
+ * Simple description of this carousel for screenreaders, to be read before
45
+ * "{itemLabel} {index} of {count}.
46
+ *
47
+ * For example, "Summer offers" in "Summer offers, offer 1 of 3"
48
+ */
49
+ title: PropTypes.string
50
+ };
51
+ export default CarouselFirstFocus;
@@ -0,0 +1,50 @@
1
+ var _CarouselTabs$propTyp, _CarouselTabs$propTyp2;
2
+
3
+ import React, { forwardRef } from 'react';
4
+ import PropTypes from 'prop-types';
5
+ import { useResponsiveProp } from '../../utils';
6
+ import Carousel from '../Carousel';
7
+ import CarouselTabsPanel from './CarouselTabsPanel';
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+ const CarouselTabs = /*#__PURE__*/forwardRef((_ref, ref) => {
10
+ let {
11
+ items,
12
+ refocus = true,
13
+ ...carouselProps
14
+ } = _ref;
15
+ const panelNavigation = useResponsiveProp({
16
+ md: /*#__PURE__*/_jsx(CarouselTabsPanel, {
17
+ items: items
18
+ })
19
+ });
20
+ return /*#__PURE__*/_jsx(Carousel, {
21
+ refocus: refocus,
22
+ ...carouselProps,
23
+ ref: ref,
24
+ panelNavigation: panelNavigation,
25
+ children: items.map(_ref2 => {
26
+ let {
27
+ title,
28
+ content
29
+ } = _ref2;
30
+ return /*#__PURE__*/_jsx(React.Fragment, {
31
+ children: content
32
+ }, title);
33
+ })
34
+ });
35
+ });
36
+ CarouselTabs.displayName = 'CarouselTabs';
37
+ CarouselTabs.propTypes = {
38
+ /**
39
+ * An array of objects where title is the string shown in the slide's tab and content is the JSX for the slide itself
40
+ */
41
+ items: PropTypes.arrayOf(PropTypes.shape({
42
+ title: PropTypes.string.isRequired,
43
+ content: PropTypes.node.isRequired
44
+ })),
45
+ ...Carousel.propTypes
46
+ }; // CarouselTabs doesn't require `children` prop, it uses `items` instead.
47
+ // eslint-disable-next-line react/forbid-foreign-prop-types
48
+
49
+ if ((_CarouselTabs$propTyp = CarouselTabs.propTypes) !== null && _CarouselTabs$propTyp !== void 0 && _CarouselTabs$propTyp.children) (_CarouselTabs$propTyp2 = CarouselTabs.propTypes) === null || _CarouselTabs$propTyp2 === void 0 ? true : delete _CarouselTabs$propTyp2.children;
50
+ export default CarouselTabs;
@@ -0,0 +1,76 @@
1
+ import React, { forwardRef, useRef } from 'react';
2
+ import View from "react-native-web/dist/exports/View";
3
+ import PropTypes from 'prop-types';
4
+ import StackView from '../../StackView';
5
+ import { useCarousel } from '../CarouselContext';
6
+ import CarouselTabsPanelItem from './CarouselTabsPanelItem';
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ import { Fragment as _Fragment } from "react/jsx-runtime";
9
+ import { jsxs as _jsxs } from "react/jsx-runtime";
10
+ const CarouselTabsPanel = /*#__PURE__*/forwardRef((_ref, ref) => {
11
+ let {
12
+ items
13
+ } = _ref;
14
+ const {
15
+ activeIndex,
16
+ goTo
17
+ } = useCarousel();
18
+ const nextFocusRef = useRef();
19
+ const firstTabRef = useRef(); // TODO: figure out a better cross-brand way to specify subcomponent variants.
20
+ // For now, this picks an Allium variant, and does nothing in brands that lack it.
21
+ // See similar comment in Carousel and https://github.com/telus/universal-design-system/issues/1549
22
+
23
+ const dividerVariant = {
24
+ decorative: true
25
+ };
26
+ const lastTabSelected = activeIndex === items.length - 1;
27
+ return /*#__PURE__*/_jsxs(_Fragment, {
28
+ children: [/*#__PURE__*/_jsx(View, {
29
+ focusable: true,
30
+ accessible: true,
31
+ onFocus: event => {
32
+ // When user forward-tabs into this section, focus the next tab; if they backwards-tab
33
+ // (shift-tab) back into the carousel content, don't interfere.
34
+ const previousWebFocus = event.relatedTarget;
35
+ if (previousWebFocus !== firstTabRef.current) nextFocusRef.current.focus();
36
+ }
37
+ }), /*#__PURE__*/_jsx(StackView, {
38
+ direction: "row",
39
+ space: 3,
40
+ divider: {
41
+ variant: dividerVariant
42
+ },
43
+ ref: ref,
44
+ children: items.map((_ref2, index) => {
45
+ let {
46
+ title,
47
+ onPress,
48
+ ...panelItemProps
49
+ } = _ref2;
50
+ const selected = index === activeIndex;
51
+ const isNext = index === activeIndex + 1; // Selected item should be always unfocusable and unpressable
52
+
53
+ const handlePress = selected ? undefined : event => {
54
+ if (typeof onPress === 'function') onPress(event, index);
55
+ goTo(index);
56
+ };
57
+ return /*#__PURE__*/_jsx(CarouselTabsPanelItem, {
58
+ ref: isNext && nextFocusRef || index === 0 && firstTabRef || null,
59
+ title: title,
60
+ selected: selected,
61
+ onPress: handlePress,
62
+ ...panelItemProps
63
+ }, title);
64
+ })
65
+ }), /*#__PURE__*/_jsx(View, {
66
+ focusable: true,
67
+ accessible: true,
68
+ ref: lastTabSelected ? nextFocusRef : null
69
+ })]
70
+ });
71
+ });
72
+ CarouselTabsPanel.displayName = 'CarouselTabsPanel';
73
+ CarouselTabsPanel.propTypes = {
74
+ items: PropTypes.arrayOf(PropTypes.shape(CarouselTabsPanelItem.propTypes || {}))
75
+ };
76
+ export default CarouselTabsPanel;
@@ -0,0 +1,126 @@
1
+ import React, { forwardRef, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import Pressable from "react-native-web/dist/exports/Pressable";
4
+ import Text from "react-native-web/dist/exports/Text";
5
+ import Platform from "react-native-web/dist/exports/Platform";
6
+ import { applyTextStyles, useThemeTokensCallback } from '../../ThemeProvider';
7
+ import { selectSystemProps, a11yProps, pressProps, viewProps, textProps, getTokensPropType, variantProp, resolvePressableState } from '../../utils';
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+ const [selectPressProps, pressPropTypes] = selectSystemProps([a11yProps, pressProps, viewProps]);
10
+ const [selectTextProps, textPropTypes] = selectSystemProps([textProps]);
11
+
12
+ const selectContainerStyles = _ref => {
13
+ let {
14
+ paddingLeft,
15
+ paddingRight,
16
+ paddingTop,
17
+ paddingBottom = 0,
18
+ borderBottomColor,
19
+ borderBottomWidth = 0,
20
+ borderBottomStyle,
21
+ flex,
22
+ alignItems,
23
+ justifyContent
24
+ } = _ref;
25
+ return {
26
+ paddingLeft,
27
+ paddingRight,
28
+ paddingTop,
29
+ paddingBottom: paddingBottom - borderBottomWidth,
30
+ borderBottomColor,
31
+ borderBottomWidth,
32
+ borderBottomStyle,
33
+ flex,
34
+ alignItems,
35
+ justifyContent,
36
+ ...Platform.select({
37
+ // Removes the default browser :focus outline
38
+ web: {
39
+ outline: 'none'
40
+ }
41
+ })
42
+ };
43
+ };
44
+
45
+ const selectTextStyles = _ref2 => {
46
+ let {
47
+ fontSize,
48
+ fontScaleCap,
49
+ lineHeight,
50
+ letterSpacing,
51
+ fontWeight,
52
+ fontName,
53
+ color
54
+ } = _ref2;
55
+ return applyTextStyles({
56
+ fontSize,
57
+ fontScaleCap,
58
+ lineHeight,
59
+ letterSpacing,
60
+ fontWeight,
61
+ fontName,
62
+ color
63
+ });
64
+ };
65
+
66
+ const CarouselTabsPanelItem = /*#__PURE__*/forwardRef((_ref3, ref) => {
67
+ let {
68
+ title,
69
+ selected,
70
+ inactive,
71
+ variant,
72
+ tokens,
73
+ accessibilityRole = 'tab',
74
+ ...rest
75
+ } = _ref3;
76
+ // Workaround for React Native Web https://github.com/necolas/react-native-web/issues/2357
77
+ // Don't allow disabled to be set while focus is true else focus state gets locked `true`
78
+ // (must refocus _after_ calling `goTo`, else focus target content is not up to date)
79
+ const [isFocused, setIsFocused] = useState(false);
80
+ const disabled = (inactive || selected) && !isFocused;
81
+ const getTokens = useThemeTokensCallback('CarouselTabsPanelItem', tokens, variant);
82
+
83
+ const resolveTokens = pressState => getTokens(resolvePressableState(pressState, {
84
+ selected
85
+ }));
86
+
87
+ const getContainerStyle = pressState => selectContainerStyles(resolveTokens(pressState));
88
+
89
+ const getTextStyle = pressState => selectTextStyles(resolveTokens(pressState));
90
+
91
+ const {
92
+ onPress,
93
+ ...selectedPressProps
94
+ } = selectPressProps(rest);
95
+
96
+ const handleKeyDown = event => {
97
+ // Allow using the spacebar for navigation
98
+ if ((event === null || event === void 0 ? void 0 : event.key) === ' ') onPress(event);
99
+ };
100
+
101
+ return /*#__PURE__*/_jsx(Pressable, {
102
+ onPress: onPress,
103
+ style: getContainerStyle,
104
+ accessibilityRole: accessibilityRole,
105
+ ref: ref,
106
+ onKeyDown: handleKeyDown,
107
+ onFocus: () => setIsFocused(true),
108
+ onBlur: () => setIsFocused(false),
109
+ disabled: disabled,
110
+ ...selectedPressProps,
111
+ children: pressState => /*#__PURE__*/_jsx(Text, {
112
+ style: getTextStyle(pressState),
113
+ ...selectTextProps(rest),
114
+ children: title
115
+ })
116
+ });
117
+ });
118
+ CarouselTabsPanelItem.displayName = 'CarouselTabsPanelItem';
119
+ CarouselTabsPanelItem.propTypes = { ...pressPropTypes,
120
+ ...textPropTypes,
121
+ title: PropTypes.string.isRequired,
122
+ selected: PropTypes.bool,
123
+ tokens: getTokensPropType('CarouselTabsPanelItem'),
124
+ variant: variantProp.propType
125
+ };
126
+ export default CarouselTabsPanelItem;
@@ -0,0 +1,2 @@
1
+ import CarouselTabs from './CarouselTabs';
2
+ export default CarouselTabs;
@@ -0,0 +1,85 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import Pressable from "react-native-web/dist/exports/Pressable";
4
+ import Image from "react-native-web/dist/exports/Image";
5
+ import { useCarousel } from './CarouselContext';
6
+ /**
7
+ * `Carousel.Thumbnail` is used to wrap the content of an individual slide and is suppsoed to be the
8
+ * only top-level component passed to the `Carousel`
9
+ */
10
+
11
+ import { jsx as _jsx } from "react/jsx-runtime";
12
+
13
+ const CarouselThumbnail = _ref => {
14
+ let {
15
+ accessibilityLabel,
16
+ alt,
17
+ index,
18
+ src
19
+ } = _ref;
20
+ const {
21
+ activeIndex,
22
+ itemLabel,
23
+ totalItems,
24
+ getCopyWithPlaceholders,
25
+ goTo,
26
+ themeTokens
27
+ } = useCarousel();
28
+ const thumbnailTitle = alt !== null && alt !== void 0 ? alt : getCopyWithPlaceholders('stepTrackerLabel').replace(/%\{itemLabel\}/g, itemLabel).replace(/%\{stepNumber\}/g, index).replace(/%\{stepCount\}/g, totalItems);
29
+
30
+ const handlePress = () => goTo(index);
31
+
32
+ const handleKeyDown = event => {
33
+ // Allow using the spacebar for navigation
34
+ if ((event === null || event === void 0 ? void 0 : event.key) === ' ') goTo(index);
35
+ };
36
+
37
+ const {
38
+ thumbnailBorderColor,
39
+ thumbnailBorderRadius,
40
+ thumbnailBorderWidth,
41
+ thumbnailMargin,
42
+ thumbnailPadding,
43
+ thumbnailSelectedBorderColor,
44
+ thumbnailSelectedBorderWidth,
45
+ thumbnailSize
46
+ } = themeTokens;
47
+ const styles = {
48
+ pressable: {
49
+ borderColor: thumbnailBorderColor,
50
+ borderRadius: thumbnailBorderRadius,
51
+ borderWidth: thumbnailBorderWidth,
52
+ margin: thumbnailMargin,
53
+ padding: thumbnailPadding
54
+ },
55
+ image: {
56
+ height: thumbnailSize,
57
+ width: thumbnailSize
58
+ },
59
+ selected: {
60
+ borderColor: thumbnailSelectedBorderColor,
61
+ borderWidth: thumbnailSelectedBorderWidth,
62
+ padding: thumbnailPadding - thumbnailSelectedBorderWidth + thumbnailBorderWidth
63
+ }
64
+ };
65
+ return /*#__PURE__*/_jsx(Pressable, {
66
+ onKeyDown: handleKeyDown,
67
+ onPress: handlePress,
68
+ style: [styles.pressable, index === activeIndex && styles.selected],
69
+ children: /*#__PURE__*/_jsx(Image, {
70
+ accessibilityIgnoresInvertColors: true,
71
+ accessibilityLabel: accessibilityLabel !== null && accessibilityLabel !== void 0 ? accessibilityLabel : alt,
72
+ source: src,
73
+ style: styles.image,
74
+ title: thumbnailTitle
75
+ })
76
+ }, src);
77
+ };
78
+
79
+ CarouselThumbnail.propTypes = {
80
+ accessibilityLabel: PropTypes.string,
81
+ alt: PropTypes.string,
82
+ index: PropTypes.number,
83
+ src: PropTypes.string
84
+ };
85
+ export default CarouselThumbnail;
@@ -0,0 +1,66 @@
1
+ import React, { forwardRef } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import View from "react-native-web/dist/exports/View";
4
+ import { useCarousel } from './CarouselContext';
5
+ import CarouselThumbnail from './CarouselThumbnail';
6
+ import { StackWrap } from '../StackView';
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ const CarouselThumbnailNavigation = /*#__PURE__*/forwardRef((_ref, ref) => {
9
+ let {
10
+ thumbnails = []
11
+ } = _ref;
12
+ const {
13
+ totalItems,
14
+ themeTokens
15
+ } = useCarousel();
16
+
17
+ if (thumbnails.length !== totalItems) {
18
+ throw new Error('Thumbnail set provided does not match the number of slides in the carousel');
19
+ }
20
+
21
+ const {
22
+ thumbnailContainerPaddingTop,
23
+ thumbnailMargin
24
+ } = themeTokens;
25
+ const stackWrapTokens = {
26
+ justifyContent: 'flex-start'
27
+ };
28
+ const containerStyles = {
29
+ justifyContent: 'center',
30
+ alignItems: 'center',
31
+ paddingTop: thumbnailContainerPaddingTop - thumbnailMargin
32
+ };
33
+ return /*#__PURE__*/_jsx(View, {
34
+ style: containerStyles,
35
+ children: /*#__PURE__*/_jsx(StackWrap, {
36
+ direction: "row",
37
+ tokens: stackWrapTokens,
38
+ ref: ref,
39
+ children: thumbnails.map((_ref2, index) => {
40
+ let {
41
+ accessibilityLabel,
42
+ alt,
43
+ src
44
+ } = _ref2;
45
+ return /*#__PURE__*/_jsx(CarouselThumbnail, {
46
+ accessibilityLabel: accessibilityLabel,
47
+ alt: alt,
48
+ index: index,
49
+ src: src
50
+ }, src);
51
+ })
52
+ })
53
+ });
54
+ });
55
+ CarouselThumbnailNavigation.displayName = 'CarouselThumbnailNavigation';
56
+ CarouselThumbnailNavigation.propTypes = {
57
+ /**
58
+ * An array of objects containing information on the thumbnail images.
59
+ */
60
+ thumbnails: PropTypes.arrayOf(PropTypes.shape({
61
+ accessibilityLabel: PropTypes.string,
62
+ alt: PropTypes.string,
63
+ src: PropTypes.string
64
+ })).isRequired
65
+ };
66
+ export default CarouselThumbnailNavigation;
@@ -4,13 +4,15 @@ export default {
4
4
  carouselLabel: '%{stepCount} items',
5
5
  iconButtonLabel: 'Show %{itemLabel} %{targetStep} of %{stepCount}',
6
6
  stepLabel: '%{itemLabel} %{stepNumber}',
7
- stepTrackerLabel: '%{itemLabel} %{stepNumber} of %{stepCount}'
7
+ stepTrackerLabel: '%{itemLabel} %{stepNumber} of %{stepCount}',
8
+ skipLink: 'Skip %{title}'
8
9
  },
9
10
  fr: {
10
11
  // TODO: French translations here
11
12
  carouselLabel: '(fr) %{stepCount} items',
12
13
  iconButtonLabel: '(fr) Show %{itemLabel} %{targetStep} of %{stepCount}',
13
14
  stepLabel: '(fr) %{itemLabel} %{stepNumber}',
14
- stepTrackerLabel: '(fr) %{itemLabel} %{stepNumber} of %{stepCount}'
15
+ stepTrackerLabel: '(fr) %{itemLabel} %{stepNumber} of %{stepCount}',
16
+ skipLink: '(fr) Skip %{title}'
15
17
  }
16
18
  };
@@ -1,2 +1,3 @@
1
1
  export * from './CarouselContext';
2
- export { default as Carousel } from './Carousel';
2
+ export { default as Carousel } from './Carousel';
3
+ export { default as CarouselTabs } from './CarouselTabs';
@@ -67,6 +67,7 @@ const CheckboxGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
67
67
  legend,
68
68
  tooltip,
69
69
  hint,
70
+ hintPosition = 'inline',
70
71
  validation,
71
72
  feedback,
72
73
  initialCheckedIds,
@@ -133,6 +134,7 @@ const CheckboxGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
133
134
  legend: legend,
134
135
  tooltip: tooltip,
135
136
  hint: hint,
137
+ hintPosition: hintPosition,
136
138
  space: fieldSpace,
137
139
  feedback: feedback,
138
140
  inactive: inactive,
@@ -182,6 +184,11 @@ CheckboxGroup.propTypes = { ...selectedSystemPropTypes,
182
184
  */
183
185
  hint: PropTypes.string,
184
186
 
187
+ /**
188
+ * Position of the hint relative to label. Use `below` to display a larger hint below the label.
189
+ */
190
+ hintPosition: PropTypes.oneOf(['inline', 'below']),
191
+
185
192
  /**
186
193
  * Optional tooltip text content to include alongside the legend and hint.
187
194
  */
@@ -68,7 +68,7 @@ IconText.propTypes = {
68
68
  /**
69
69
  * A valid UDS icon component imported from a UDS palette.
70
70
  */
71
- icon: PropTypes.func,
71
+ icon: PropTypes.elementType,
72
72
 
73
73
  /**
74
74
  * Props that will be passed to the icon component. By default the icon's `scalesWithText`
@@ -9,8 +9,6 @@ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
9
9
  * InlinePressable is an alternative to React Native's Pressable that works better when nested
10
10
  * inline inside Text. It accepts the same props as React Native's Pressable.
11
11
  *
12
- * On Web it simply passes its props to Pressable and defaults to `inline-flex` instead of `flex`.
13
- *
14
12
  * @param {PressableProps} PressableProps
15
13
  */
16
14
  // React Native exports prop Types but not propTypes, use JSDoc types here rather than duplicate RN
@@ -21,12 +19,11 @@ const InlinePressable = /*#__PURE__*/forwardRef((_ref, ref) => {
21
19
  let {
22
20
  children,
23
21
  style,
24
- inline = false,
25
22
  ...props
26
23
  } = _ref;
27
24
  return /*#__PURE__*/_jsx(Pressable, {
28
25
  ref: ref,
29
- style: pressState => [staticStyles[inline ? 'inline' : 'inlineFlex'], typeof style === 'function' ? style(pressState) : style],
26
+ style: pressState => [staticStyles.inline, typeof style === 'function' ? style(pressState) : style],
30
27
  ...props,
31
28
  children: pressState => typeof children === 'function' ? children(pressState) : children
32
29
  });
@@ -34,11 +31,7 @@ const InlinePressable = /*#__PURE__*/forwardRef((_ref, ref) => {
34
31
  InlinePressable.displayName = 'InlinePressable';
35
32
  const staticStyles = StyleSheet.create({
36
33
  inline: {
37
- // Stop Pressable defaulting to (block) flex
38
34
  display: 'inline'
39
- },
40
- inlineFlex: {
41
- display: 'inline-flex'
42
35
  }
43
36
  });
44
37
  export default InlinePressable;
@@ -12,7 +12,7 @@ import { IconText, iconComponentPropTypes } from '../Icon';
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
13
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, linkProps, viewProps]);
14
14
 
15
- const selectOuterBorderStyles = _ref => {
15
+ const selectOuterBorderStyles = (_ref, hasIcon) => {
16
16
  let {
17
17
  outerBorderColor,
18
18
  outerBorderWidth,
@@ -33,7 +33,8 @@ const selectOuterBorderStyles = _ref => {
33
33
  }),
34
34
  // Stops focus ring stretching horizontally if parent has display: block
35
35
  // width: fit-content isn't supported on Firefox; can't cascade props like CSS `width: fit-content; width: --moz-fit-content;`
36
- display: 'inline-flex'
36
+ display: hasIcon ? 'inline-flex' : 'inline' // Stop Pressable defaulting to (block) flex
37
+
37
38
  } : {}
38
39
  );
39
40
  };
@@ -169,14 +170,12 @@ const LinkBase = /*#__PURE__*/forwardRef((_ref6, ref) => {
169
170
  themeOptions
170
171
  } = useTheme();
171
172
  return /*#__PURE__*/_jsx(InlinePressable, { ...selectedProps,
172
- inline: hasIcon // assuming links without icons should be inline (even if they are long)
173
- ,
174
173
  ref: ref,
175
174
  style: linkState => {
176
175
  const themeTokens = resolveLinkTokens(linkState);
177
- const outerBorderStyles = selectOuterBorderStyles(themeTokens);
176
+ const outerBorderStyles = selectOuterBorderStyles(themeTokens, hasIcon);
178
177
  const decorationStyles = selectDecorationStyles(themeTokens);
179
- return [outerBorderStyles, blockLeftStyle, decorationStyles, hasIcon && staticStyles.rowContainer];
178
+ return [outerBorderStyles, blockLeftStyle, decorationStyles, staticStyles.rowContainer];
180
179
  },
181
180
  children: linkState => {
182
181
  const themeTokens = resolveLinkTokens(linkState);
@@ -218,7 +217,7 @@ LinkBase.propTypes = { ...selectedSystemPropTypes,
218
217
  * A function component for an SVG icon to render inside the link. Inherits size and color from
219
218
  * the link and any Typography the link is nested inside.
220
219
  */
221
- icon: PropTypes.func,
220
+ icon: PropTypes.elementType,
222
221
 
223
222
  /**
224
223
  * When `icon` is provided, use `iconPosition` to place the Icon to the left or right side of Link.
@@ -225,7 +225,7 @@ ListItem.propTypes = { ...selectedSystemPropTypes,
225
225
  /**
226
226
  * Renders side item icon
227
227
  */
228
- icon: PropTypes.func,
228
+ icon: PropTypes.elementType,
229
229
 
230
230
  /**
231
231
  * Will set display icon color