@telus-uds/components-base 1.54.0 → 1.55.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.
@@ -189,6 +189,14 @@ function verticalAlignRow(verticalAlign) {
189
189
  alignItems: verticalAlignToFlexRowAlign[verticalAlign]
190
190
  };
191
191
  }
192
+
193
+ const calculateBorderRadius = (borderRadius, outerBorderGap, outerBorderWidth) => {
194
+ if (borderRadius) {
195
+ return borderRadius + outerBorderGap + outerBorderWidth;
196
+ }
197
+
198
+ return null;
199
+ };
192
200
  /**
193
201
  * Use on an outer container to create an outer border with an optional gap around it
194
202
  * that matches the border radius of any inner border.
@@ -200,12 +208,20 @@ const applyOuterBorder = _ref4 => {
200
208
  outerBorderColor,
201
209
  outerBorderWidth = 0,
202
210
  outerBorderGap = 0,
203
- borderRadius = 0
211
+ borderRadius,
212
+ borderTopLeftRadius,
213
+ borderTopRightRadius,
214
+ borderBottomLeftRadius,
215
+ borderBottomRightRadius
204
216
  } = _ref4;
205
217
  return {
206
218
  margin: 0 - outerBorderWidth - outerBorderGap,
207
219
  padding: outerBorderGap,
208
- borderRadius: borderRadius + outerBorderGap + outerBorderWidth,
220
+ borderRadius: calculateBorderRadius(borderRadius, outerBorderGap, outerBorderWidth),
221
+ borderTopLeftRadius: calculateBorderRadius(borderTopLeftRadius, outerBorderGap, outerBorderWidth),
222
+ borderTopRightRadius: calculateBorderRadius(borderTopRightRadius, outerBorderGap, outerBorderWidth),
223
+ borderBottomLeftRadius: calculateBorderRadius(borderBottomLeftRadius, outerBorderGap, outerBorderWidth),
224
+ borderBottomRightRadius: calculateBorderRadius(borderBottomRightRadius, outerBorderGap, outerBorderWidth),
209
225
  borderWidth: outerBorderWidth,
210
226
  borderColor: outerBorderColor
211
227
  };
@@ -26,11 +26,13 @@ const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_u
26
26
  const selectInnerContainerStyles = _ref => {
27
27
  let {
28
28
  borderRadius,
29
- width
29
+ width,
30
+ backgroundColor
30
31
  } = _ref;
31
32
  return {
32
33
  borderRadius,
33
- width
34
+ width,
35
+ backgroundColor
34
36
  };
35
37
  };
36
38
 
@@ -13,7 +13,10 @@ const CarouselStepTracker = _ref => {
13
13
  activeIndex,
14
14
  totalItems,
15
15
  getCopyWithPlaceholders,
16
- themeTokens
16
+ themeTokens: {
17
+ stepTrackerCurrentBackgroundColor,
18
+ ...themeTokens
19
+ }
17
20
  } = useCarousel();
18
21
  const stackViewTokens = {
19
22
  justifyContent: 'center'
@@ -21,7 +24,8 @@ const CarouselStepTracker = _ref => {
21
24
  const stepTrackerTokens = {
22
25
  showStepLabel: false,
23
26
  showStepTrackerLabel: true,
24
- knobCompletedBackgroundColor: 'none',
27
+ // TODO: StepTracker 'isComplete'/'isCurrent' is incorrect, see line StepTracker/Step.jsx line 63, refactor incorrect values and remove this
28
+ knobCompletedBackgroundColor: stepTrackerCurrentBackgroundColor ?? 'none',
25
29
  connectorCompletedColor: 'none',
26
30
  connectorColor: 'none',
27
31
  containerPaddingTop: themeTokens.spaceBetweenSlideAndPanelNavigation
@@ -21,19 +21,20 @@ const CarouselTabsPanel = /*#__PURE__*/forwardRef((_ref, ref) => {
21
21
  } = useCarousel();
22
22
  const nextFocusRef = useRef();
23
23
  const firstTabRef = useRef();
24
- const [isInverse, setIsInverse] = useState(false); // TODO: figure out a better cross-brand way to specify subcomponent variants.
25
- // For now, this picks an Allium variant, and does nothing in brands that lack it.
26
- // See similar comment in Carousel and https://github.com/telus/universal-design-system/issues/1549
27
-
28
- const dividerVariant = {
29
- decorative: true
30
- };
24
+ const [isInverse, setIsInverse] = useState(false);
31
25
  const lastTabSelected = activeIndex === items.length - 1; // Get current select tab style
32
26
 
33
27
  useEffect(() => {
34
28
  const [selectedVariantIsInverse] = items.filter((_, index) => index === activeIndex);
35
29
  setIsInverse(selectedVariantIsInverse === null || selectedVariantIsInverse === void 0 ? void 0 : selectedVariantIsInverse.inverse);
36
- }, [items, activeIndex]);
30
+ }, [items, activeIndex]); // TODO: figure out a better cross-brand way to specify subcomponent variants.
31
+ // For now, this picks an Allium variant, and does nothing in brands that lack it.
32
+ // See similar comment in Carousel and https://github.com/telus/universal-design-system/issues/1549
33
+
34
+ const dividerVariant = {
35
+ decorative: true,
36
+ inverse: isInverse
37
+ };
37
38
  return /*#__PURE__*/_jsxs(View, {
38
39
  style: selectTabPanelStyle(),
39
40
  children: [/*#__PURE__*/_jsx(StackView, {
@@ -3,28 +3,48 @@ import PropTypes from 'prop-types';
3
3
  import Pressable from "react-native-web/dist/exports/Pressable";
4
4
  import Image from "react-native-web/dist/exports/Image";
5
5
  import { useCarousel } from './CarouselContext';
6
+ import { useThemeTokensCallback } from '../ThemeProvider';
7
+ import { useViewport } from '../ViewportProvider';
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+
10
+ const selectPressableTokens = _ref => {
11
+ let {
12
+ borderColor,
13
+ borderRadius,
14
+ borderWidth,
15
+ margin,
16
+ padding
17
+ } = _ref;
18
+ return {
19
+ borderColor,
20
+ borderRadius,
21
+ borderWidth,
22
+ margin,
23
+ padding
24
+ };
25
+ };
6
26
  /**
7
27
  * `Carousel.Thumbnail` is used to wrap the content of an individual slide and is suppsoed to be the
8
28
  * only top-level component passed to the `Carousel`
9
29
  */
10
30
 
11
- import { jsx as _jsx } from "react/jsx-runtime";
12
31
 
13
- const CarouselThumbnail = _ref => {
32
+ const CarouselThumbnail = _ref2 => {
14
33
  let {
15
34
  accessibilityLabel,
16
35
  alt,
17
36
  index,
18
37
  src
19
- } = _ref;
38
+ } = _ref2;
20
39
  const {
21
40
  activeIndex,
22
41
  itemLabel,
23
42
  totalItems,
24
43
  getCopyWithPlaceholders,
25
- goTo,
26
- themeTokens
44
+ goTo
27
45
  } = useCarousel();
46
+ const getThumbnailTokens = useThemeTokensCallback('CarouselThumbnail');
47
+ const viewport = useViewport();
28
48
  const thumbnailTitle = alt ?? getCopyWithPlaceholders('stepTrackerLabel').replace(/%\{itemLabel\}/g, itemLabel).replace(/%\{stepNumber\}/g, index).replace(/%\{stepCount\}/g, totalItems);
29
49
 
30
50
  const handlePress = () => goTo(index);
@@ -35,37 +55,41 @@ const CarouselThumbnail = _ref => {
35
55
  };
36
56
 
37
57
  const {
38
- thumbnailBorderColor,
39
- thumbnailBorderRadius,
40
- thumbnailBorderWidth,
41
- thumbnailMargin,
42
- thumbnailPadding,
43
- thumbnailSelectedBorderColor,
44
- thumbnailSelectedBorderWidth,
45
- thumbnailSize
46
- } = themeTokens;
58
+ borderWidth,
59
+ padding,
60
+ selectedBorderColor,
61
+ selectedBorderWidth,
62
+ size
63
+ } = getThumbnailTokens({
64
+ viewport
65
+ });
47
66
  const styles = {
48
- pressable: {
49
- borderColor: thumbnailBorderColor,
50
- borderRadius: thumbnailBorderRadius,
51
- borderWidth: thumbnailBorderWidth,
52
- margin: thumbnailMargin,
53
- padding: thumbnailPadding
54
- },
55
67
  image: {
56
- height: thumbnailSize,
57
- width: thumbnailSize
68
+ height: size,
69
+ width: size
58
70
  },
59
71
  selected: {
60
- borderColor: thumbnailSelectedBorderColor,
61
- borderWidth: thumbnailSelectedBorderWidth,
62
- padding: thumbnailPadding - thumbnailSelectedBorderWidth + thumbnailBorderWidth
72
+ borderColor: selectedBorderColor,
73
+ borderWidth: selectedBorderWidth,
74
+ padding: padding - selectedBorderWidth + borderWidth
63
75
  }
64
76
  };
65
77
  return /*#__PURE__*/_jsx(Pressable, {
66
78
  onKeyDown: handleKeyDown,
67
79
  onPress: handlePress,
68
- style: [styles.pressable, index === activeIndex && styles.selected],
80
+ style: _ref3 => {
81
+ let {
82
+ hovered,
83
+ pressed,
84
+ focused
85
+ } = _ref3;
86
+ const pressableStyles = selectPressableTokens(getThumbnailTokens({
87
+ hover: hovered,
88
+ pressed,
89
+ focus: focused
90
+ }));
91
+ return [pressableStyles, index === activeIndex && styles.selected];
92
+ },
69
93
  children: /*#__PURE__*/_jsx(Image, {
70
94
  accessibilityIgnoresInvertColors: true,
71
95
  accessibilityLabel: accessibilityLabel ?? alt,
@@ -4,14 +4,21 @@ import View from "react-native-web/dist/exports/View";
4
4
  import { useCarousel } from './CarouselContext';
5
5
  import CarouselThumbnail from './CarouselThumbnail';
6
6
  import { StackWrap } from '../StackView';
7
+ import { useThemeTokens } from '../ThemeProvider';
8
+ import { useViewport } from '../ViewportProvider';
7
9
  import { jsx as _jsx } from "react/jsx-runtime";
8
10
  const CarouselThumbnailNavigation = /*#__PURE__*/forwardRef((_ref, ref) => {
9
11
  let {
10
12
  thumbnails = []
11
13
  } = _ref;
14
+ const viewport = useViewport();
12
15
  const {
13
- totalItems,
14
- themeTokens
16
+ alignItems
17
+ } = useThemeTokens('CarouselThumbnail', {}, {
18
+ viewport
19
+ });
20
+ const {
21
+ totalItems
15
22
  } = useCarousel();
16
23
 
17
24
  if (thumbnails.length !== totalItems) {
@@ -19,15 +26,15 @@ const CarouselThumbnailNavigation = /*#__PURE__*/forwardRef((_ref, ref) => {
19
26
  }
20
27
 
21
28
  const {
22
- thumbnailContainerPaddingTop,
23
- thumbnailMargin
24
- } = themeTokens;
29
+ containerPaddingTop: thumbnailContainerPaddingTop,
30
+ margin: thumbnailMargin
31
+ } = useThemeTokens('CarouselThumbnail');
25
32
  const stackWrapTokens = {
26
33
  justifyContent: 'flex-start'
27
34
  };
28
35
  const containerStyles = {
29
36
  justifyContent: 'center',
30
- alignItems: 'center',
37
+ alignItems,
31
38
  paddingTop: thumbnailContainerPaddingTop - thumbnailMargin
32
39
  };
33
40
  return /*#__PURE__*/_jsx(View, {
@@ -13,10 +13,14 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
13
13
  const selectOuterStyle = _ref => {
14
14
  let {
15
15
  backgroundColor,
16
- borderRadius,
17
16
  outerBorderWidth,
18
17
  outerBorderColor,
19
18
  outerBorderGap,
19
+ borderRadius,
20
+ borderTopLeftRadius,
21
+ borderTopRightRadius,
22
+ borderBottomLeftRadius,
23
+ borderBottomRightRadius,
20
24
  shadow
21
25
  } = _ref;
22
26
  return [{
@@ -24,6 +28,10 @@ const selectOuterStyle = _ref => {
24
28
  ...applyShadowToken(shadow),
25
29
  ...applyOuterBorder({
26
30
  borderRadius,
31
+ borderTopLeftRadius,
32
+ borderTopRightRadius,
33
+ borderBottomLeftRadius,
34
+ borderBottomRightRadius,
27
35
  outerBorderWidth,
28
36
  outerBorderColor,
29
37
  outerBorderGap
@@ -37,20 +45,46 @@ const selectOuterStyle = _ref => {
37
45
  }, staticStyles.outer];
38
46
  };
39
47
 
48
+ const calculatePadding = (padding, borderWidth) => padding && Math.max(0, padding - borderWidth); // Stable size as border changes
49
+
50
+
40
51
  const selectInnerStyle = _ref2 => {
41
52
  let {
42
53
  borderColor,
43
- borderWidth = 0,
54
+ borderWidth,
55
+ borderTopLeftRadius,
56
+ borderTopRightRadius,
57
+ borderBottomLeftRadius,
58
+ borderBottomRightRadius,
44
59
  borderRadius,
45
- padding = 0
60
+ padding = 0,
61
+ borderTopWidth,
62
+ borderRightWidth,
63
+ borderBottomWidth,
64
+ borderLeftWidth,
65
+ paddingLeft,
66
+ paddingRight,
67
+ paddingTop,
68
+ paddingBottom
46
69
  } = _ref2;
47
70
  return {
48
71
  // Inner borders animate with the icon and should be treated like a themable feature of the icon
49
72
  borderColor,
50
73
  borderRadius,
51
74
  borderWidth,
52
- padding: Math.max(0, padding - borderWidth) // Stable size as border changes
53
-
75
+ borderTopLeftRadius,
76
+ borderTopRightRadius,
77
+ borderBottomLeftRadius,
78
+ borderBottomRightRadius,
79
+ borderTopWidth,
80
+ borderRightWidth,
81
+ borderBottomWidth,
82
+ borderLeftWidth,
83
+ padding: calculatePadding(padding, borderWidth),
84
+ paddingLeft: calculatePadding(paddingLeft, borderLeftWidth),
85
+ paddingRight: calculatePadding(paddingRight, borderRightWidth),
86
+ paddingTop: calculatePadding(paddingTop, borderTopWidth),
87
+ paddingBottom: calculatePadding(paddingBottom, borderBottomWidth)
54
88
  };
55
89
  };
56
90
  /**
@@ -107,7 +141,7 @@ const IconButton = /*#__PURE__*/forwardRef((_ref3, ref) => {
107
141
  return /*#__PURE__*/_jsx(View, {
108
142
  style: selectInnerStyle(themeTokens),
109
143
  children: /*#__PURE__*/_jsx(Icon, {
110
- icon: IconComponent,
144
+ icon: IconComponent || themeTokens.icon,
111
145
  title: selectedProps.accessibilityLabel,
112
146
  tokens: selectTokens('Icon', themeTokens, 'icon'),
113
147
  variant: variant
@@ -124,7 +158,7 @@ IconButton.propTypes = { ...selectedSystemPropTypes,
124
158
  /**
125
159
  * Defines the icon to be rendered
126
160
  */
127
- icon: PropTypes.elementType.isRequired,
161
+ icon: PropTypes.elementType,
128
162
 
129
163
  /**
130
164
  * URL to navigate to when the `Iconbutton` is pressed
@@ -171,22 +171,39 @@ export function verticalAlignRow(verticalAlign) {
171
171
  alignItems: verticalAlignToFlexRowAlign[verticalAlign]
172
172
  };
173
173
  }
174
+
175
+ const calculateBorderRadius = (borderRadius, outerBorderGap, outerBorderWidth) => {
176
+ if (borderRadius) {
177
+ return borderRadius + outerBorderGap + outerBorderWidth;
178
+ }
179
+
180
+ return null;
181
+ };
174
182
  /**
175
183
  * Use on an outer container to create an outer border with an optional gap around it
176
184
  * that matches the border radius of any inner border.
177
185
  */
178
186
 
187
+
179
188
  export const applyOuterBorder = _ref4 => {
180
189
  let {
181
190
  outerBorderColor,
182
191
  outerBorderWidth = 0,
183
192
  outerBorderGap = 0,
184
- borderRadius = 0
193
+ borderRadius,
194
+ borderTopLeftRadius,
195
+ borderTopRightRadius,
196
+ borderBottomLeftRadius,
197
+ borderBottomRightRadius
185
198
  } = _ref4;
186
199
  return {
187
200
  margin: 0 - outerBorderWidth - outerBorderGap,
188
201
  padding: outerBorderGap,
189
- borderRadius: borderRadius + outerBorderGap + outerBorderWidth,
202
+ borderRadius: calculateBorderRadius(borderRadius, outerBorderGap, outerBorderWidth),
203
+ borderTopLeftRadius: calculateBorderRadius(borderTopLeftRadius, outerBorderGap, outerBorderWidth),
204
+ borderTopRightRadius: calculateBorderRadius(borderTopRightRadius, outerBorderGap, outerBorderWidth),
205
+ borderBottomLeftRadius: calculateBorderRadius(borderBottomLeftRadius, outerBorderGap, outerBorderWidth),
206
+ borderBottomRightRadius: calculateBorderRadius(borderBottomRightRadius, outerBorderGap, outerBorderWidth),
190
207
  borderWidth: outerBorderWidth,
191
208
  borderColor: outerBorderColor
192
209
  };
@@ -10,11 +10,13 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
10
10
  const selectInnerContainerStyles = _ref => {
11
11
  let {
12
12
  borderRadius,
13
- width
13
+ width,
14
+ backgroundColor
14
15
  } = _ref;
15
16
  return {
16
17
  borderRadius,
17
- width
18
+ width,
19
+ backgroundColor
18
20
  };
19
21
  };
20
22
 
package/package.json CHANGED
@@ -10,8 +10,8 @@
10
10
  "@floating-ui/react-dom": "^1.0.1",
11
11
  "@floating-ui/react-native": "^0.8.1",
12
12
  "@gorhom/portal": "^1.0.14",
13
- "@telus-uds/system-constants": "^1.2.1",
14
- "@telus-uds/system-theme-tokens": "^2.37.0",
13
+ "@telus-uds/system-constants": "^1.3.0",
14
+ "@telus-uds/system-theme-tokens": "^2.38.0",
15
15
  "airbnb-prop-types": "^2.16.0",
16
16
  "lodash.debounce": "^4.0.8",
17
17
  "lodash.merge": "^4.6.2",
@@ -72,5 +72,5 @@
72
72
  "standard-engine": {
73
73
  "skip": true
74
74
  },
75
- "version": "1.54.0"
75
+ "version": "1.55.0"
76
76
  }
@@ -5,18 +5,26 @@ import StackView from '../../StackView'
5
5
  import { variantProp } from '../../utils'
6
6
 
7
7
  const CarouselStepTracker = ({ variant }) => {
8
- const { activeIndex, totalItems, getCopyWithPlaceholders, themeTokens } = useCarousel()
8
+ const {
9
+ activeIndex,
10
+ totalItems,
11
+ getCopyWithPlaceholders,
12
+ themeTokens: { stepTrackerCurrentBackgroundColor, ...themeTokens }
13
+ } = useCarousel()
9
14
  const stackViewTokens = {
10
15
  justifyContent: 'center'
11
16
  }
17
+
12
18
  const stepTrackerTokens = {
13
19
  showStepLabel: false,
14
20
  showStepTrackerLabel: true,
15
- knobCompletedBackgroundColor: 'none',
21
+ // TODO: StepTracker 'isComplete'/'isCurrent' is incorrect, see line StepTracker/Step.jsx line 63, refactor incorrect values and remove this
22
+ knobCompletedBackgroundColor: stepTrackerCurrentBackgroundColor ?? 'none',
16
23
  connectorCompletedColor: 'none',
17
24
  connectorColor: 'none',
18
25
  containerPaddingTop: themeTokens.spaceBetweenSlideAndPanelNavigation
19
26
  }
27
+
20
28
  const steps = Array.from(Array(totalItems)).map((_, index) => String(index))
21
29
  return (
22
30
  <StackView direction="row" tokens={stackViewTokens}>
@@ -17,11 +17,6 @@ const CarouselTabsPanel = forwardRef(({ items }, ref) => {
17
17
  const firstTabRef = useRef()
18
18
  const [isInverse, setIsInverse] = useState(false)
19
19
 
20
- // TODO: figure out a better cross-brand way to specify subcomponent variants.
21
- // For now, this picks an Allium variant, and does nothing in brands that lack it.
22
- // See similar comment in Carousel and https://github.com/telus/universal-design-system/issues/1549
23
- const dividerVariant = { decorative: true }
24
-
25
20
  const lastTabSelected = activeIndex === items.length - 1
26
21
 
27
22
  // Get current select tab style
@@ -30,6 +25,11 @@ const CarouselTabsPanel = forwardRef(({ items }, ref) => {
30
25
  setIsInverse(selectedVariantIsInverse?.inverse)
31
26
  }, [items, activeIndex])
32
27
 
28
+ // TODO: figure out a better cross-brand way to specify subcomponent variants.
29
+ // For now, this picks an Allium variant, and does nothing in brands that lack it.
30
+ // See similar comment in Carousel and https://github.com/telus/universal-design-system/issues/1549
31
+ const dividerVariant = { decorative: true, inverse: isInverse }
32
+
33
33
  return (
34
34
  <View style={selectTabPanelStyle()}>
35
35
  <StackView direction="row" space={3} divider={{ variant: dividerVariant }} ref={ref}>
@@ -2,14 +2,25 @@ import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import { Pressable, Image } from 'react-native'
4
4
  import { useCarousel } from './CarouselContext'
5
+ import { useThemeTokensCallback } from '../ThemeProvider'
6
+ import { useViewport } from '../ViewportProvider'
7
+
8
+ const selectPressableTokens = ({ borderColor, borderRadius, borderWidth, margin, padding }) => ({
9
+ borderColor,
10
+ borderRadius,
11
+ borderWidth,
12
+ margin,
13
+ padding
14
+ })
5
15
 
6
16
  /**
7
17
  * `Carousel.Thumbnail` is used to wrap the content of an individual slide and is suppsoed to be the
8
18
  * only top-level component passed to the `Carousel`
9
19
  */
10
20
  const CarouselThumbnail = ({ accessibilityLabel, alt, index, src }) => {
11
- const { activeIndex, itemLabel, totalItems, getCopyWithPlaceholders, goTo, themeTokens } =
12
- useCarousel()
21
+ const { activeIndex, itemLabel, totalItems, getCopyWithPlaceholders, goTo } = useCarousel()
22
+ const getThumbnailTokens = useThemeTokensCallback('CarouselThumbnail')
23
+ const viewport = useViewport()
13
24
  const thumbnailTitle =
14
25
  alt ??
15
26
  getCopyWithPlaceholders('stepTrackerLabel')
@@ -21,32 +32,17 @@ const CarouselThumbnail = ({ accessibilityLabel, alt, index, src }) => {
21
32
  // Allow using the spacebar for navigation
22
33
  if (event?.key === ' ') goTo(index)
23
34
  }
24
- const {
25
- thumbnailBorderColor,
26
- thumbnailBorderRadius,
27
- thumbnailBorderWidth,
28
- thumbnailMargin,
29
- thumbnailPadding,
30
- thumbnailSelectedBorderColor,
31
- thumbnailSelectedBorderWidth,
32
- thumbnailSize
33
- } = themeTokens
35
+ const { borderWidth, padding, selectedBorderColor, selectedBorderWidth, size } =
36
+ getThumbnailTokens({ viewport })
34
37
  const styles = {
35
- pressable: {
36
- borderColor: thumbnailBorderColor,
37
- borderRadius: thumbnailBorderRadius,
38
- borderWidth: thumbnailBorderWidth,
39
- margin: thumbnailMargin,
40
- padding: thumbnailPadding
41
- },
42
38
  image: {
43
- height: thumbnailSize,
44
- width: thumbnailSize
39
+ height: size,
40
+ width: size
45
41
  },
46
42
  selected: {
47
- borderColor: thumbnailSelectedBorderColor,
48
- borderWidth: thumbnailSelectedBorderWidth,
49
- padding: thumbnailPadding - thumbnailSelectedBorderWidth + thumbnailBorderWidth
43
+ borderColor: selectedBorderColor,
44
+ borderWidth: selectedBorderWidth,
45
+ padding: padding - selectedBorderWidth + borderWidth
50
46
  }
51
47
  }
52
48
 
@@ -55,7 +51,17 @@ const CarouselThumbnail = ({ accessibilityLabel, alt, index, src }) => {
55
51
  key={src}
56
52
  onKeyDown={handleKeyDown}
57
53
  onPress={handlePress}
58
- style={[styles.pressable, index === activeIndex && styles.selected]}
54
+ style={({ hovered, pressed, focused }) => {
55
+ const pressableStyles = selectPressableTokens(
56
+ getThumbnailTokens({
57
+ hover: hovered,
58
+ pressed,
59
+ focus: focused
60
+ })
61
+ )
62
+
63
+ return [pressableStyles, index === activeIndex && styles.selected]
64
+ }}
59
65
  >
60
66
  <Image
61
67
  accessibilityIgnoresInvertColors
@@ -4,19 +4,24 @@ import { View } from 'react-native'
4
4
  import { useCarousel } from './CarouselContext'
5
5
  import CarouselThumbnail from './CarouselThumbnail'
6
6
  import { StackWrap } from '../StackView'
7
+ import { useThemeTokens } from '../ThemeProvider'
8
+ import { useViewport } from '../ViewportProvider'
7
9
 
8
10
  const CarouselThumbnailNavigation = forwardRef(({ thumbnails = [] }, ref) => {
9
- const { totalItems, themeTokens } = useCarousel()
11
+ const viewport = useViewport()
12
+ const { alignItems } = useThemeTokens('CarouselThumbnail', {}, { viewport })
13
+ const { totalItems } = useCarousel()
10
14
  if (thumbnails.length !== totalItems) {
11
15
  throw new Error('Thumbnail set provided does not match the number of slides in the carousel')
12
16
  }
13
- const { thumbnailContainerPaddingTop, thumbnailMargin } = themeTokens
17
+ const { containerPaddingTop: thumbnailContainerPaddingTop, margin: thumbnailMargin } =
18
+ useThemeTokens('CarouselThumbnail')
14
19
  const stackWrapTokens = {
15
20
  justifyContent: 'flex-start'
16
21
  }
17
22
  const containerStyles = {
18
23
  justifyContent: 'center',
19
- alignItems: 'center',
24
+ alignItems,
20
25
  paddingTop: thumbnailContainerPaddingTop - thumbnailMargin
21
26
  }
22
27