@telus-uds/components-base 3.26.0 → 3.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -2
- package/lib/cjs/Card/Card.js +34 -13
- package/lib/cjs/Card/CardBase.js +78 -11
- package/lib/cjs/Card/PressableCardBase.js +147 -8
- package/lib/cjs/Carousel/Carousel.js +105 -50
- package/lib/cjs/Carousel/CarouselContext.js +10 -4
- package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +11 -7
- package/lib/cjs/Carousel/Constants.js +11 -2
- package/lib/cjs/Checkbox/Checkbox.js +43 -13
- package/lib/cjs/List/List.js +24 -9
- package/lib/cjs/List/ListItem.js +18 -1
- package/lib/cjs/List/ListItemBase.js +27 -8
- package/lib/cjs/List/ListItemMark.js +33 -62
- package/lib/cjs/List/PressableListItemBase.js +1 -0
- package/lib/esm/Card/Card.js +34 -13
- package/lib/esm/Card/CardBase.js +78 -11
- package/lib/esm/Card/PressableCardBase.js +148 -9
- package/lib/esm/Carousel/Carousel.js +106 -51
- package/lib/esm/Carousel/CarouselContext.js +10 -4
- package/lib/esm/Carousel/CarouselItem/CarouselItem.js +11 -7
- package/lib/esm/Carousel/Constants.js +10 -1
- package/lib/esm/Checkbox/Checkbox.js +43 -13
- package/lib/esm/List/List.js +24 -9
- package/lib/esm/List/ListItem.js +19 -2
- package/lib/esm/List/ListItemBase.js +27 -8
- package/lib/esm/List/ListItemMark.js +33 -62
- package/lib/esm/List/PressableListItemBase.js +1 -0
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/Card/Card.jsx +29 -7
- package/src/Card/CardBase.jsx +88 -8
- package/src/Card/PressableCardBase.jsx +135 -9
- package/src/Carousel/Carousel.jsx +119 -64
- package/src/Carousel/CarouselContext.jsx +12 -4
- package/src/Carousel/CarouselItem/CarouselItem.jsx +10 -6
- package/src/Carousel/Constants.js +10 -0
- package/src/Checkbox/Checkbox.jsx +29 -7
- package/src/List/List.jsx +33 -9
- package/src/List/ListItem.jsx +33 -11
- package/src/List/ListItemBase.jsx +33 -9
- package/src/List/ListItemMark.jsx +32 -53
- package/src/List/PressableListItemBase.jsx +1 -0
|
@@ -8,8 +8,74 @@ import { useViewport } from '../ViewportProvider';
|
|
|
8
8
|
import { applyOuterBorder, validateThemeTokens } from '../ThemeProvider';
|
|
9
9
|
import { a11yProps, clickProps, focusHandlerProps, getTokensSetPropType, linkProps, resolvePressableState, resolvePressableTokens, selectSystemProps, selectTokens, variantProp, viewProps, withLinkRouter } from '../utils';
|
|
10
10
|
import CardBase, { fullBleedContentPropTypes } from './CardBase';
|
|
11
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
12
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, viewProps]);
|
|
13
|
+
const selectFocusOverlayContainerStyles = tokens => {
|
|
14
|
+
const {
|
|
15
|
+
flex,
|
|
16
|
+
minWidth,
|
|
17
|
+
marginTop,
|
|
18
|
+
marginBottom,
|
|
19
|
+
marginLeft,
|
|
20
|
+
marginRight
|
|
21
|
+
} = tokens;
|
|
22
|
+
return {
|
|
23
|
+
flex: flex || 1,
|
|
24
|
+
minWidth: minWidth || 0,
|
|
25
|
+
marginTop,
|
|
26
|
+
marginBottom,
|
|
27
|
+
marginLeft,
|
|
28
|
+
marginRight
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
const selectFocusBorderStyles = tokens => {
|
|
32
|
+
const {
|
|
33
|
+
borderWidth,
|
|
34
|
+
borderColor,
|
|
35
|
+
borderRadius
|
|
36
|
+
} = tokens;
|
|
37
|
+
return {
|
|
38
|
+
borderWidth,
|
|
39
|
+
borderColor,
|
|
40
|
+
borderRadius: borderRadius || 0
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
const FocusBorderOverlay = _ref => {
|
|
44
|
+
let {
|
|
45
|
+
tokens,
|
|
46
|
+
pressableState,
|
|
47
|
+
children
|
|
48
|
+
} = _ref;
|
|
49
|
+
const {
|
|
50
|
+
borderWidth = 0
|
|
51
|
+
} = tokens;
|
|
52
|
+
const showFocusBorder = pressableState.focused && borderWidth > 0;
|
|
53
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
54
|
+
style: [staticStyles.focusOverlayContainer, selectFocusOverlayContainerStyles(tokens), Platform.OS === 'web' && staticStyles.webOutlineNone],
|
|
55
|
+
children: [children, showFocusBorder && /*#__PURE__*/_jsx(View, {
|
|
56
|
+
style: [staticStyles.focusBorder, selectFocusBorderStyles(tokens)],
|
|
57
|
+
accessible: false,
|
|
58
|
+
importantForAccessibility: "no"
|
|
59
|
+
})]
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
FocusBorderOverlay.propTypes = {
|
|
63
|
+
tokens: PropTypes.shape({
|
|
64
|
+
flex: PropTypes.number,
|
|
65
|
+
minWidth: PropTypes.number,
|
|
66
|
+
marginTop: PropTypes.number,
|
|
67
|
+
marginBottom: PropTypes.number,
|
|
68
|
+
marginLeft: PropTypes.number,
|
|
69
|
+
marginRight: PropTypes.number,
|
|
70
|
+
borderColor: PropTypes.string,
|
|
71
|
+
borderWidth: PropTypes.number,
|
|
72
|
+
borderRadius: PropTypes.number
|
|
73
|
+
}).isRequired,
|
|
74
|
+
pressableState: PropTypes.shape({
|
|
75
|
+
focused: PropTypes.bool
|
|
76
|
+
}).isRequired,
|
|
77
|
+
children: PropTypes.node
|
|
78
|
+
};
|
|
13
79
|
const tokenKeys = ['flex', 'backgroundColor', 'borderColor', 'gradient', 'borderRadius', 'borderWidth', 'paddingBottom', 'paddingLeft', 'paddingRight', 'paddingTop', 'marginTop', 'marginBottom', 'marginLeft', 'marginRight', 'minWidth', 'shadow', 'contentAlignItems', 'contentJustifyContent', 'contentFlexGrow', 'contentFlexShrink',
|
|
14
80
|
// Outer border tokens. TODO: centralise common token sets like these as part of
|
|
15
81
|
// https://github.com/telus/universal-design-system/issues/782
|
|
@@ -21,7 +87,7 @@ export const selectPressableCardTokens = tokens => Object.fromEntries(tokenKeys.
|
|
|
21
87
|
* based on these to an outer border and a base Card component. Not intended to be used in
|
|
22
88
|
* apps or sites directly: build themed components on top of this.
|
|
23
89
|
*/
|
|
24
|
-
const PressableCardBase = /*#__PURE__*/React.forwardRef((
|
|
90
|
+
const PressableCardBase = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
25
91
|
let {
|
|
26
92
|
children,
|
|
27
93
|
tokens,
|
|
@@ -35,7 +101,7 @@ const PressableCardBase = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
35
101
|
fullBleedContent,
|
|
36
102
|
accessibilityRole = href ? 'link' : undefined,
|
|
37
103
|
...rawRest
|
|
38
|
-
} =
|
|
104
|
+
} = _ref2;
|
|
39
105
|
const {
|
|
40
106
|
onPress,
|
|
41
107
|
...rest
|
|
@@ -52,11 +118,62 @@ const PressableCardBase = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
52
118
|
partial: true,
|
|
53
119
|
allowFunction: true
|
|
54
120
|
}), 'PressableCard');
|
|
55
|
-
const getCardTokens = pressableState =>
|
|
121
|
+
const getCardTokens = pressableState => {
|
|
122
|
+
const allTokens = getTokens(pressableState);
|
|
123
|
+
const cardTokens = selectTokens('Card', allTokens);
|
|
124
|
+
|
|
125
|
+
// Handle focus border transparency to avoid double borders
|
|
126
|
+
if (pressableState.focused && allTokens.borderWidth > 0) {
|
|
127
|
+
const result = {
|
|
128
|
+
...cardTokens,
|
|
129
|
+
borderColor: 'transparent'
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// Also handle backgroundImage for interactive states
|
|
133
|
+
if (backgroundImage) {
|
|
134
|
+
const {
|
|
135
|
+
hovered,
|
|
136
|
+
pressed,
|
|
137
|
+
focused
|
|
138
|
+
} = pressableState || {};
|
|
139
|
+
const isInteractiveState = hovered || pressed || focused;
|
|
140
|
+
if (!isInteractiveState) {
|
|
141
|
+
const {
|
|
142
|
+
backgroundColor,
|
|
143
|
+
...restTokens
|
|
144
|
+
} = result;
|
|
145
|
+
return restTokens;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Handle backgroundImage when not in focus state
|
|
152
|
+
if (backgroundImage) {
|
|
153
|
+
const {
|
|
154
|
+
hovered,
|
|
155
|
+
pressed,
|
|
156
|
+
focused
|
|
157
|
+
} = pressableState || {};
|
|
158
|
+
const isInteractiveState = hovered || pressed || focused;
|
|
159
|
+
if (!isInteractiveState) {
|
|
160
|
+
const {
|
|
161
|
+
backgroundColor,
|
|
162
|
+
...restTokens
|
|
163
|
+
} = cardTokens;
|
|
164
|
+
return restTokens;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return cardTokens;
|
|
168
|
+
};
|
|
56
169
|
const getOuterBorderStyle = pressableState => {
|
|
57
170
|
const {
|
|
58
171
|
flex,
|
|
59
172
|
minWidth,
|
|
173
|
+
marginTop,
|
|
174
|
+
marginBottom,
|
|
175
|
+
marginLeft,
|
|
176
|
+
marginRight,
|
|
60
177
|
outerBorderColor,
|
|
61
178
|
outerBorderGap = 0,
|
|
62
179
|
outerBorderWidth = 0,
|
|
@@ -65,6 +182,10 @@ const PressableCardBase = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
65
182
|
return {
|
|
66
183
|
flex,
|
|
67
184
|
minWidth: minWidth + outerBorderGap + outerBorderWidth,
|
|
185
|
+
marginTop,
|
|
186
|
+
marginBottom,
|
|
187
|
+
marginLeft,
|
|
188
|
+
marginRight,
|
|
68
189
|
...applyOuterBorder({
|
|
69
190
|
outerBorderColor,
|
|
70
191
|
outerBorderGap,
|
|
@@ -158,11 +279,15 @@ const PressableCardBase = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
158
279
|
...rest,
|
|
159
280
|
accessibilityRole
|
|
160
281
|
}),
|
|
161
|
-
children: pressableState => /*#__PURE__*/_jsx(
|
|
162
|
-
tokens:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
282
|
+
children: pressableState => /*#__PURE__*/_jsx(FocusBorderOverlay, {
|
|
283
|
+
tokens: getTokens(pressableState),
|
|
284
|
+
pressableState: pressableState,
|
|
285
|
+
children: /*#__PURE__*/_jsx(CardBase, {
|
|
286
|
+
tokens: getCardTokens(pressableState),
|
|
287
|
+
backgroundImage: backgroundImage,
|
|
288
|
+
fullBleedContent: fullBleedContent,
|
|
289
|
+
children: typeof children === 'function' ? children(getCardState(pressableState)) : children
|
|
290
|
+
})
|
|
166
291
|
})
|
|
167
292
|
});
|
|
168
293
|
});
|
|
@@ -177,6 +302,20 @@ const staticStyles = StyleSheet.create({
|
|
|
177
302
|
alignItems: 'stretch',
|
|
178
303
|
justifyContent: 'flex-start',
|
|
179
304
|
textDecorationLine: 'none'
|
|
305
|
+
},
|
|
306
|
+
focusOverlayContainer: {
|
|
307
|
+
position: 'relative'
|
|
308
|
+
},
|
|
309
|
+
webOutlineNone: {
|
|
310
|
+
outline: 'none'
|
|
311
|
+
},
|
|
312
|
+
focusBorder: {
|
|
313
|
+
position: 'absolute',
|
|
314
|
+
top: 0,
|
|
315
|
+
left: 0,
|
|
316
|
+
right: 0,
|
|
317
|
+
bottom: 0,
|
|
318
|
+
pointerEvents: 'none'
|
|
180
319
|
}
|
|
181
320
|
});
|
|
182
321
|
PressableCardBase.displayName = 'PressableCardBase';
|
|
@@ -22,7 +22,7 @@ import CarouselTabsPanel from './CarouselTabs/CarouselTabsPanel';
|
|
|
22
22
|
import CarouselTabsPanelItem from './CarouselTabs/CarouselTabsPanelItem';
|
|
23
23
|
import dictionary from './dictionary';
|
|
24
24
|
import Box from '../Box';
|
|
25
|
-
import { ITEMS_PER_VIEWPORT_XS_SM, ITEMS_PER_VIEWPORT_MD, ITEMS_PER_VIEWPORT_LG_XL, DEFAULT_POSITION_OFFSET, LARGE_VIEWPORT_MARGIN, DEFAULT_VIEWPORT_MARGIN, PEEKING_MULTIPLIER,
|
|
25
|
+
import { ITEMS_PER_VIEWPORT_XS_SM, ITEMS_PER_VIEWPORT_MD, ITEMS_PER_VIEWPORT_LG_XL, DEFAULT_POSITION_OFFSET, LARGE_VIEWPORT_MARGIN, DEFAULT_VIEWPORT_MARGIN, PEEKING_MULTIPLIER, NEGATIVE_MULTIPLIER, TRANSITION_MODES, SWIPE_RELEASE_STYLES, INSTANT_ANIMATION_DURATION, DEFAULT_SWIPE_RELEASE_DURATION, POSITION_VARIANTS, POSITION_PROPERTIES } from './Constants';
|
|
26
26
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
27
27
|
const staticStyles = StyleSheet.create({
|
|
28
28
|
root: {
|
|
@@ -72,7 +72,7 @@ const selectHeroContainerStyles = (width, hidden) => ({
|
|
|
72
72
|
width,
|
|
73
73
|
visibility: hidden ? 'hidden' : 'visible'
|
|
74
74
|
});
|
|
75
|
-
const getDynamicPositionProperty = areStylesAppliedOnPreviousButton => areStylesAppliedOnPreviousButton ?
|
|
75
|
+
const getDynamicPositionProperty = areStylesAppliedOnPreviousButton => areStylesAppliedOnPreviousButton ? POSITION_PROPERTIES.LEFT : POSITION_PROPERTIES.RIGHT;
|
|
76
76
|
const selectControlButtonPositionStyles = _ref => {
|
|
77
77
|
let {
|
|
78
78
|
positionVariant,
|
|
@@ -82,23 +82,36 @@ const selectControlButtonPositionStyles = _ref => {
|
|
|
82
82
|
enablePeeking,
|
|
83
83
|
enableDisplayMultipleItemsPerSlide,
|
|
84
84
|
isAutoPlayEnabled,
|
|
85
|
-
viewport
|
|
85
|
+
viewport,
|
|
86
|
+
maxWidth,
|
|
87
|
+
viewportWidth
|
|
86
88
|
} = _ref;
|
|
87
89
|
const styles = {};
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
let positionOffset = 0;
|
|
91
|
+
if (positionVariant === POSITION_VARIANTS.EDGE) {
|
|
92
|
+
positionOffset = -1 * (buttonWidth / 2);
|
|
93
|
+
} else if (positionVariant === POSITION_VARIANTS.INSIDE) {
|
|
94
|
+
positionOffset = DEFAULT_POSITION_OFFSET;
|
|
95
|
+
} else if (positionVariant === POSITION_VARIANTS.OUTSIDE) {
|
|
93
96
|
if (enablePeeking || enableDisplayMultipleItemsPerSlide || isAutoPlayEnabled && viewport === 'xs') {
|
|
94
|
-
|
|
97
|
+
positionOffset = 0;
|
|
95
98
|
} else {
|
|
96
|
-
|
|
99
|
+
positionOffset = -1 * (spaceBetweenSlideAndButton + buttonWidth);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (enablePeeking) {
|
|
103
|
+
if (positionProperty === POSITION_PROPERTIES.RIGHT) {
|
|
104
|
+
const rightMargin = (viewportWidth - maxWidth) / 2;
|
|
105
|
+
positionOffset += rightMargin;
|
|
106
|
+
} else if (positionProperty === POSITION_PROPERTIES.LEFT) {
|
|
107
|
+
const leftMargin = (viewportWidth - maxWidth) / 2;
|
|
108
|
+
positionOffset += leftMargin;
|
|
97
109
|
}
|
|
98
110
|
}
|
|
111
|
+
styles[positionProperty] = positionOffset;
|
|
99
112
|
return styles;
|
|
100
113
|
};
|
|
101
|
-
const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, areStylesAppliedOnPreviousButton, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport) => {
|
|
114
|
+
const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, areStylesAppliedOnPreviousButton, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, viewportWidth) => {
|
|
102
115
|
const styles = {
|
|
103
116
|
zIndex: 1,
|
|
104
117
|
position: 'absolute'
|
|
@@ -120,7 +133,9 @@ const selectPreviousNextNavigationButtonStyles = (previousNextNavigationButtonWi
|
|
|
120
133
|
enablePeeking,
|
|
121
134
|
enableDisplayMultipleItemsPerSlide,
|
|
122
135
|
isAutoPlayEnabled,
|
|
123
|
-
viewport
|
|
136
|
+
viewport,
|
|
137
|
+
maxWidth,
|
|
138
|
+
viewportWidth
|
|
124
139
|
})
|
|
125
140
|
};
|
|
126
141
|
};
|
|
@@ -186,7 +201,7 @@ const getMaximumItemsForSlide = (enableDisplayMultipleItemsPerSlide, viewport) =
|
|
|
186
201
|
}
|
|
187
202
|
return ITEMS_PER_VIEWPORT_XS_SM;
|
|
188
203
|
};
|
|
189
|
-
const selectRootContainerStyles = (enableHero, viewport) => {
|
|
204
|
+
const selectRootContainerStyles = (enableHero, viewport, enablePeeking) => {
|
|
190
205
|
if (enableHero && viewport === 'xl' && Platform.OS === 'web') {
|
|
191
206
|
return {
|
|
192
207
|
alignItems: 'center'
|
|
@@ -197,15 +212,25 @@ const selectRootContainerStyles = (enableHero, viewport) => {
|
|
|
197
212
|
paddingHorizontal: 16
|
|
198
213
|
};
|
|
199
214
|
}
|
|
215
|
+
if (enablePeeking) {
|
|
216
|
+
return {
|
|
217
|
+
width: '100%'
|
|
218
|
+
};
|
|
219
|
+
}
|
|
200
220
|
return {};
|
|
201
221
|
};
|
|
202
|
-
const selectMainContainerStyles = (enableHero, viewport, maxWidth) => {
|
|
203
|
-
if (enableHero && viewport === 'xl' && Platform.OS === 'web') {
|
|
222
|
+
const selectMainContainerStyles = (enableHero, viewport, maxWidth, enablePeeking) => {
|
|
223
|
+
if (enableHero && viewport === 'xl' && Platform.OS === 'web' && !enablePeeking) {
|
|
204
224
|
return {
|
|
205
225
|
width: '100%',
|
|
206
226
|
maxWidth: maxWidth || 1200
|
|
207
227
|
};
|
|
208
228
|
}
|
|
229
|
+
if (enablePeeking) {
|
|
230
|
+
return {
|
|
231
|
+
width: '100%'
|
|
232
|
+
};
|
|
233
|
+
}
|
|
209
234
|
if (maxWidth !== null && maxWidth !== undefined) {
|
|
210
235
|
return {
|
|
211
236
|
maxWidth,
|
|
@@ -215,14 +240,20 @@ const selectMainContainerStyles = (enableHero, viewport, maxWidth) => {
|
|
|
215
240
|
}
|
|
216
241
|
return {};
|
|
217
242
|
};
|
|
218
|
-
const selectNavigationStyles = (tabs, enableHero, viewport) => {
|
|
243
|
+
const selectNavigationStyles = (tabs, enableHero, viewport, enablePeeking, maxWidth) => {
|
|
219
244
|
let marginHorizontal = 0;
|
|
220
245
|
if (enableHero && tabs) {
|
|
221
246
|
marginHorizontal = viewport === 'xl' ? LARGE_VIEWPORT_MARGIN : DEFAULT_VIEWPORT_MARGIN;
|
|
222
247
|
}
|
|
223
|
-
|
|
248
|
+
const styles = {
|
|
224
249
|
marginHorizontal
|
|
225
250
|
};
|
|
251
|
+
if (enablePeeking && maxWidth) {
|
|
252
|
+
styles.maxWidth = maxWidth;
|
|
253
|
+
styles.alignSelf = 'center';
|
|
254
|
+
styles.width = '100%';
|
|
255
|
+
}
|
|
256
|
+
return styles;
|
|
226
257
|
};
|
|
227
258
|
|
|
228
259
|
/**
|
|
@@ -231,23 +262,18 @@ const selectNavigationStyles = (tabs, enableHero, viewport) => {
|
|
|
231
262
|
* @param {number} containerWidth - The width of the carousel container.
|
|
232
263
|
* @param {boolean} enablePeeking - Flag indicating whether peeking is enabled.
|
|
233
264
|
* @param {Object} viewport - The viewport configuration object used to determine peeking properties.
|
|
234
|
-
* @param {
|
|
265
|
+
* @param {number} maxWidth - The maximum width constraint for the carousel content.
|
|
235
266
|
* @returns {number} The calculated final width of the carousel container.
|
|
236
267
|
*/
|
|
237
|
-
const calculateFinalWidth = (containerWidth, enablePeeking, viewport,
|
|
268
|
+
const calculateFinalWidth = (containerWidth, enablePeeking, viewport, maxWidth) => {
|
|
238
269
|
let finalWidth = containerWidth;
|
|
239
270
|
if (enablePeeking) {
|
|
240
271
|
const {
|
|
241
272
|
peekingGap,
|
|
242
|
-
peekingMiddleSpace
|
|
243
|
-
peekingMarginLeft
|
|
273
|
+
peekingMiddleSpace
|
|
244
274
|
} = getPeekingProps(viewport);
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
finalWidth = slideWide + peekingMarginLeft - peekingMiddleSpace;
|
|
248
|
-
} else {
|
|
249
|
-
finalWidth = slideWide + peekingGap;
|
|
250
|
-
}
|
|
275
|
+
const baseWidth = maxWidth || containerWidth;
|
|
276
|
+
finalWidth = baseWidth - peekingMiddleSpace * PEEKING_MULTIPLIER + peekingGap;
|
|
251
277
|
}
|
|
252
278
|
return finalWidth;
|
|
253
279
|
};
|
|
@@ -370,7 +396,10 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
370
396
|
} = useTheme();
|
|
371
397
|
const contentMaxWidthValue = useResponsiveProp(contentMaxWidth);
|
|
372
398
|
const responsiveWidth = useResponsiveProp(themeOptions?.contentMaxWidth);
|
|
373
|
-
|
|
399
|
+
let maxWidth = null;
|
|
400
|
+
if (enablePeeking || contentMaxWidth !== undefined) {
|
|
401
|
+
maxWidth = contentMaxWidthValue === undefined ? responsiveWidth : resolveContentMaxWidth(contentMaxWidthValue, responsiveWidth);
|
|
402
|
+
}
|
|
374
403
|
const totalItems = getTotalItems(enableDisplayMultipleItemsPerSlide, childrenArray, viewport);
|
|
375
404
|
const autoPlayFeatureEnabled = autoPlay && slideDuration > 0 && transitionDuration > 0 && totalItems > 1;
|
|
376
405
|
// if `Carousel` only has one `Carousel.Item`, convert this to a single-item array
|
|
@@ -433,8 +462,16 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
433
462
|
const [isCarouselPlaying, setisCarouselPlaying] = React.useState(autoPlayFeatureEnabled);
|
|
434
463
|
const isSwiping = React.useRef(false);
|
|
435
464
|
const autoPlayRef = React.useRef(null);
|
|
465
|
+
const [rootContainerLayout, setRootContainerLayout] = React.useState({
|
|
466
|
+
x: 0,
|
|
467
|
+
y: 0,
|
|
468
|
+
width: 0,
|
|
469
|
+
height: 0
|
|
470
|
+
});
|
|
471
|
+
const rootContainerLayoutRef = React.useRef(rootContainerLayout);
|
|
436
472
|
const isFirstSlide = !activeIndex;
|
|
437
473
|
const isLastSlide = activeIndex + 1 >= totalItems;
|
|
474
|
+
const currentViewportWidth = rootContainerLayout.width;
|
|
438
475
|
const handleAnimationStart = React.useCallback(function () {
|
|
439
476
|
if (typeof onAnimationStart === 'function') onAnimationStart(...arguments);
|
|
440
477
|
setIsAnimating(true);
|
|
@@ -452,15 +489,15 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
452
489
|
if (enablePeeking) {
|
|
453
490
|
const {
|
|
454
491
|
peekingGap,
|
|
455
|
-
peekingMiddleSpace
|
|
456
|
-
peekingMarginLeft
|
|
492
|
+
peekingMiddleSpace
|
|
457
493
|
} = getPeekingProps(viewport);
|
|
458
494
|
let finalWidth;
|
|
459
|
-
const
|
|
495
|
+
const baseWidth = maxWidth || containerLayoutRef.current.width;
|
|
496
|
+
const slideWide = baseWidth - peekingMiddleSpace * PEEKING_MULTIPLIER;
|
|
460
497
|
if (activeIndexRef.current === 0) {
|
|
461
498
|
finalWidth = 0;
|
|
462
499
|
} else {
|
|
463
|
-
finalWidth =
|
|
500
|
+
finalWidth = (slideWide + peekingGap) * activeIndexRef.current;
|
|
464
501
|
}
|
|
465
502
|
animatedX.current = finalWidth * NEGATIVE_MULTIPLIER;
|
|
466
503
|
} else {
|
|
@@ -487,7 +524,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
487
524
|
y: 0
|
|
488
525
|
});
|
|
489
526
|
}
|
|
490
|
-
}, [pan, animatedX, heroPan, heroAnimatedX, enableHero, viewport, enablePeeking]);
|
|
527
|
+
}, [pan, animatedX, heroPan, heroAnimatedX, enableHero, viewport, enablePeeking, maxWidth]);
|
|
491
528
|
const animate = React.useCallback(function (panToAnimate, toValue, toIndex) {
|
|
492
529
|
let isSwipeRelease = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
493
530
|
const applicableTransitionDuration = isLastSlide && toIndex === 0 ? loopDuration : transitionDuration;
|
|
@@ -579,7 +616,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
579
616
|
}
|
|
580
617
|
stopAutoplay();
|
|
581
618
|
setActiveIndex(index);
|
|
582
|
-
const finalWidth = calculateFinalWidth(containerLayoutRef.current.width, enablePeeking, viewport,
|
|
619
|
+
const finalWidth = calculateFinalWidth(containerLayoutRef.current.width, enablePeeking, viewport, maxWidth);
|
|
583
620
|
toValue.x = finalWidth * -1 * calcDelta;
|
|
584
621
|
const heroToValue = {
|
|
585
622
|
x: 0,
|
|
@@ -606,7 +643,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
606
643
|
}
|
|
607
644
|
if (onIndexChanged) onIndexChanged(calcDelta, index);
|
|
608
645
|
return calcDelta;
|
|
609
|
-
}, [handleAnimationStart, triggerRefocus, slideDuration, updateOffset, animate, totalItems, onIndexChanged, isCarouselPlaying, stopAutoplay, isAutoPlayEnabled, viewport, enablePeeking, pan, heroPan, enableHero]);
|
|
646
|
+
}, [handleAnimationStart, triggerRefocus, slideDuration, updateOffset, animate, totalItems, onIndexChanged, isCarouselPlaying, stopAutoplay, isAutoPlayEnabled, viewport, enablePeeking, pan, heroPan, enableHero, maxWidth]);
|
|
610
647
|
const startAutoplay = React.useCallback(() => {
|
|
611
648
|
stopAutoplay();
|
|
612
649
|
if (isAutoPlayEnabled) {
|
|
@@ -641,6 +678,9 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
641
678
|
React.useEffect(() => {
|
|
642
679
|
heroContainerLayoutRef.current = heroContainerLayout;
|
|
643
680
|
}, [heroContainerLayout]);
|
|
681
|
+
React.useEffect(() => {
|
|
682
|
+
rootContainerLayoutRef.current = rootContainerLayout;
|
|
683
|
+
}, [rootContainerLayout]);
|
|
644
684
|
React.useEffect(() => {
|
|
645
685
|
pan.x.addListener(_ref5 => {
|
|
646
686
|
let {
|
|
@@ -749,6 +789,25 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
749
789
|
} = _ref11;
|
|
750
790
|
return setPreviousNextNavigationButtonWidth(width);
|
|
751
791
|
};
|
|
792
|
+
const onRootContainerLayout = _ref12 => {
|
|
793
|
+
let {
|
|
794
|
+
nativeEvent: {
|
|
795
|
+
layout: {
|
|
796
|
+
x,
|
|
797
|
+
y,
|
|
798
|
+
width,
|
|
799
|
+
height
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
} = _ref12;
|
|
803
|
+
return setRootContainerLayout(prevState => ({
|
|
804
|
+
...prevState,
|
|
805
|
+
x,
|
|
806
|
+
y,
|
|
807
|
+
width,
|
|
808
|
+
height
|
|
809
|
+
}));
|
|
810
|
+
};
|
|
752
811
|
const isSwipeAllowed = React.useCallback(() => {
|
|
753
812
|
if (totalItems === 1) {
|
|
754
813
|
return false;
|
|
@@ -914,9 +973,10 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
914
973
|
}
|
|
915
974
|
}, [isTransitioningRef]);
|
|
916
975
|
return /*#__PURE__*/_jsxs(View, {
|
|
917
|
-
style: selectRootContainerStyles(enableHero, viewport),
|
|
976
|
+
style: selectRootContainerStyles(enableHero, viewport, enablePeeking),
|
|
977
|
+
onLayout: onRootContainerLayout,
|
|
918
978
|
children: [/*#__PURE__*/_jsx(View, {
|
|
919
|
-
style: selectMainContainerStyles(enableHero, viewport, maxWidth),
|
|
979
|
+
style: selectMainContainerStyles(enableHero, viewport, maxWidth, enablePeeking),
|
|
920
980
|
children: /*#__PURE__*/_jsxs(CarouselProvider, {
|
|
921
981
|
activeIndex: activeIndex,
|
|
922
982
|
goTo: goTo,
|
|
@@ -928,6 +988,8 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
928
988
|
refocus: refocus,
|
|
929
989
|
width: containerLayout.width,
|
|
930
990
|
maximumItemsForSlide: getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport),
|
|
991
|
+
maxWidth: maxWidth,
|
|
992
|
+
viewportWidth: currentViewportWidth,
|
|
931
993
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
932
994
|
style: [staticStyles.root, {
|
|
933
995
|
...(Platform.OS === 'web' ? {
|
|
@@ -950,7 +1012,9 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
950
1012
|
enablePeeking,
|
|
951
1013
|
enableDisplayMultipleItemsPerSlide,
|
|
952
1014
|
isAutoPlayEnabled,
|
|
953
|
-
viewport
|
|
1015
|
+
viewport,
|
|
1016
|
+
maxWidth,
|
|
1017
|
+
viewportWidth: currentViewportWidth
|
|
954
1018
|
})],
|
|
955
1019
|
children: /*#__PURE__*/_jsx(IconButton, {
|
|
956
1020
|
icon: isCarouselPlaying ? pauseIcon : playIcon,
|
|
@@ -959,7 +1023,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
959
1023
|
onPress: onAnimationControlButtonPress
|
|
960
1024
|
})
|
|
961
1025
|
}) : null, showPreviousNextNavigation && totalItems > 1 ? /*#__PURE__*/_jsx(View, {
|
|
962
|
-
style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, true, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport),
|
|
1026
|
+
style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, true, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, currentViewportWidth),
|
|
963
1027
|
testID: "previous-button-container",
|
|
964
1028
|
children: /*#__PURE__*/_jsx(IconButton, {
|
|
965
1029
|
onLayout: onPreviousNextNavigationButtonLayout,
|
|
@@ -997,16 +1061,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
997
1061
|
children: childrenArray.map((element, index) => {
|
|
998
1062
|
let hidden = !isAnimating && index !== activeIndex;
|
|
999
1063
|
if (enablePeeking && !isAnimating) {
|
|
1000
|
-
|
|
1001
|
-
const maxItemsForSlide = getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport);
|
|
1002
|
-
if (index >= activeIndex * maxItemsForSlide - 1 && index < activeIndex * maxItemsForSlide + maxItemsForSlide + 1) {
|
|
1003
|
-
hidden = false;
|
|
1004
|
-
} else {
|
|
1005
|
-
hidden = true;
|
|
1006
|
-
}
|
|
1007
|
-
} else if (index >= activeIndex - 1 && index <= activeIndex + 1) {
|
|
1008
|
-
hidden = false;
|
|
1009
|
-
}
|
|
1064
|
+
hidden = false;
|
|
1010
1065
|
} else if (!enablePeeking && enableDisplayMultipleItemsPerSlide && !isAnimating) {
|
|
1011
1066
|
const maxItemsForSlide = getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport);
|
|
1012
1067
|
if (index >= activeIndex * maxItemsForSlide && index < activeIndex * maxItemsForSlide + maxItemsForSlide) {
|
|
@@ -1028,7 +1083,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
1028
1083
|
})
|
|
1029
1084
|
})
|
|
1030
1085
|
}), showPreviousNextNavigation && totalItems > 1 ? /*#__PURE__*/_jsx(View, {
|
|
1031
|
-
style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, false, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport),
|
|
1086
|
+
style: selectPreviousNextNavigationButtonStyles(previousNextNavigationButtonWidth, previousNextNavigationPosition, spaceBetweenSlideAndPreviousNextNavigation, isFirstSlide, isLastSlide, false, enablePeeking, enableDisplayMultipleItemsPerSlide, isAutoPlayEnabled, viewport, maxWidth, currentViewportWidth),
|
|
1032
1087
|
testID: "next-button-container",
|
|
1033
1088
|
children: /*#__PURE__*/_jsx(IconButton, {
|
|
1034
1089
|
onLayout: onPreviousNextNavigationButtonLayout,
|
|
@@ -1040,7 +1095,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
1040
1095
|
})
|
|
1041
1096
|
}) : null]
|
|
1042
1097
|
}), /*#__PURE__*/_jsx(View, {
|
|
1043
|
-
style: selectNavigationStyles(tabs, enableHero, viewport),
|
|
1098
|
+
style: selectNavigationStyles(tabs, enableHero, viewport, enablePeeking, maxWidth),
|
|
1044
1099
|
children: showPanelNavigation ? activePanelNavigation : null
|
|
1045
1100
|
})]
|
|
1046
1101
|
})
|
|
@@ -14,7 +14,9 @@ const CarouselProvider = _ref => {
|
|
|
14
14
|
themeTokens,
|
|
15
15
|
totalItems,
|
|
16
16
|
width,
|
|
17
|
-
maximumItemsForSlide
|
|
17
|
+
maximumItemsForSlide,
|
|
18
|
+
maxWidth,
|
|
19
|
+
viewportWidth
|
|
18
20
|
} = _ref;
|
|
19
21
|
const value = React.useMemo(() => ({
|
|
20
22
|
activeIndex,
|
|
@@ -25,8 +27,10 @@ const CarouselProvider = _ref => {
|
|
|
25
27
|
themeTokens,
|
|
26
28
|
totalItems,
|
|
27
29
|
width,
|
|
28
|
-
maximumItemsForSlide
|
|
29
|
-
|
|
30
|
+
maximumItemsForSlide,
|
|
31
|
+
maxWidth,
|
|
32
|
+
viewportWidth
|
|
33
|
+
}), [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width, maximumItemsForSlide, maxWidth, viewportWidth]);
|
|
30
34
|
return /*#__PURE__*/_jsx(CarouselContext.Provider, {
|
|
31
35
|
value: value,
|
|
32
36
|
children: children
|
|
@@ -49,6 +53,8 @@ CarouselProvider.propTypes = {
|
|
|
49
53
|
themeTokens: getTokensPropType('Carousel'),
|
|
50
54
|
totalItems: PropTypes.number.isRequired,
|
|
51
55
|
width: PropTypes.number.isRequired,
|
|
52
|
-
maximumItemsForSlide: PropTypes.number
|
|
56
|
+
maximumItemsForSlide: PropTypes.number,
|
|
57
|
+
maxWidth: PropTypes.number,
|
|
58
|
+
viewportWidth: PropTypes.number
|
|
53
59
|
};
|
|
54
60
|
export { CarouselProvider, useCarousel };
|
|
@@ -12,26 +12,26 @@ const selectContainerStyle = _ref => {
|
|
|
12
12
|
width,
|
|
13
13
|
elementIndex,
|
|
14
14
|
enablePeeking,
|
|
15
|
-
peekingMarginLeft,
|
|
16
15
|
peekingGap,
|
|
17
16
|
hidden,
|
|
18
17
|
enableDisplayMultipleItemsPerSlide,
|
|
19
18
|
viewport,
|
|
20
|
-
peekingMiddleSpace
|
|
19
|
+
peekingMiddleSpace,
|
|
20
|
+
maxWidth,
|
|
21
|
+
viewportWidth
|
|
21
22
|
} = _ref;
|
|
22
23
|
let adjustedWidth = width;
|
|
23
24
|
let marginLeft = 0;
|
|
24
25
|
if (enablePeeking) {
|
|
25
26
|
const isFirst = elementIndex === 0;
|
|
26
|
-
|
|
27
|
+
const baseWidth = maxWidth || width;
|
|
28
|
+
adjustedWidth = baseWidth - peekingMiddleSpace * 2;
|
|
27
29
|
if (isFirst) {
|
|
28
|
-
marginLeft =
|
|
30
|
+
marginLeft = peekingMiddleSpace + (viewportWidth - maxWidth) / 2;
|
|
29
31
|
} else {
|
|
30
32
|
marginLeft = peekingGap;
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
|
-
|
|
34
|
-
// Adjust width and margins for multiple items per slide.
|
|
35
35
|
if (enableDisplayMultipleItemsPerSlide) {
|
|
36
36
|
switch (viewport) {
|
|
37
37
|
case 'xs':
|
|
@@ -89,7 +89,9 @@ const CarouselItem = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
89
89
|
width,
|
|
90
90
|
activeIndex,
|
|
91
91
|
goTo,
|
|
92
|
-
maximumItemsForSlide
|
|
92
|
+
maximumItemsForSlide,
|
|
93
|
+
maxWidth,
|
|
94
|
+
viewportWidth
|
|
93
95
|
} = useCarousel();
|
|
94
96
|
const selectedProps = selectProps({
|
|
95
97
|
...rest,
|
|
@@ -132,6 +134,8 @@ const CarouselItem = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
132
134
|
enablePeeking,
|
|
133
135
|
enableDisplayMultipleItemsPerSlide,
|
|
134
136
|
viewport,
|
|
137
|
+
maxWidth,
|
|
138
|
+
viewportWidth,
|
|
135
139
|
...peekingProps
|
|
136
140
|
}),
|
|
137
141
|
...selectedProps,
|
|
@@ -19,4 +19,13 @@ export const SWIPE_RELEASE_STYLES = {
|
|
|
19
19
|
EASE_OUT: 'ease-out'
|
|
20
20
|
};
|
|
21
21
|
export const INSTANT_ANIMATION_DURATION = 1;
|
|
22
|
-
export const DEFAULT_SWIPE_RELEASE_DURATION = 500;
|
|
22
|
+
export const DEFAULT_SWIPE_RELEASE_DURATION = 500;
|
|
23
|
+
export const POSITION_VARIANTS = {
|
|
24
|
+
EDGE: 'edge',
|
|
25
|
+
INSIDE: 'inside',
|
|
26
|
+
OUTSIDE: 'outside'
|
|
27
|
+
};
|
|
28
|
+
export const POSITION_PROPERTIES = {
|
|
29
|
+
LEFT: 'left',
|
|
30
|
+
RIGHT: 'right'
|
|
31
|
+
};
|