@telus-uds/components-base 3.12.0 → 3.12.2
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/Carousel/Carousel.js +26 -0
- package/lib/cjs/Carousel/CarouselContext.js +7 -4
- package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +13 -2
- package/lib/cjs/Carousel/Constants.js +2 -1
- package/lib/cjs/Listbox/ListboxOverlay.js +6 -7
- package/lib/esm/Carousel/Carousel.js +27 -1
- package/lib/esm/Carousel/CarouselContext.js +7 -4
- package/lib/esm/Carousel/CarouselItem/CarouselItem.js +13 -2
- package/lib/esm/Carousel/Constants.js +1 -0
- package/lib/esm/Listbox/ListboxOverlay.js +6 -7
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/Carousel/Carousel.jsx +30 -0
- package/src/Carousel/CarouselContext.jsx +17 -4
- package/src/Carousel/CarouselItem/CarouselItem.jsx +17 -2
- package/src/Carousel/Constants.js +1 -0
- package/src/Listbox/ListboxOverlay.jsx +5 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,29 @@
|
|
|
1
1
|
# Change Log - @telus-uds/components-base
|
|
2
2
|
|
|
3
|
-
This log was last generated on Fri,
|
|
3
|
+
This log was last generated on Fri, 25 Jul 2025 04:09:38 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 3.12.2
|
|
8
|
+
|
|
9
|
+
Fri, 25 Jul 2025 04:09:38 GMT
|
|
10
|
+
|
|
11
|
+
### Patches
|
|
12
|
+
|
|
13
|
+
- `Carousel`: fix tab navigation (guillermo.peitzner@telus.com)
|
|
14
|
+
- Bump @telus-uds/system-theme-tokens to v4.11.0
|
|
15
|
+
|
|
16
|
+
## 3.12.1
|
|
17
|
+
|
|
18
|
+
Wed, 16 Jul 2025 15:18:31 GMT
|
|
19
|
+
|
|
20
|
+
### Patches
|
|
21
|
+
|
|
22
|
+
- `ListboxOverlay`: fix console warning (guillermo.peitzner@telus.com)
|
|
23
|
+
|
|
7
24
|
## 3.12.0
|
|
8
25
|
|
|
9
|
-
Fri, 11 Jul 2025 22:
|
|
26
|
+
Fri, 11 Jul 2025 22:22:37 GMT
|
|
10
27
|
|
|
11
28
|
### Minor changes
|
|
12
29
|
|
|
@@ -172,6 +172,31 @@ const getTotalItems = (enableDisplayMultipleItemsPerSlide, childrenArray, viewpo
|
|
|
172
172
|
}
|
|
173
173
|
return childrenArray.length;
|
|
174
174
|
};
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Determines the maximum number of items that can be displayed per slide based on viewport
|
|
178
|
+
*
|
|
179
|
+
* @param {boolean} enableDisplayMultipleItemsPerSlide - Flag indicating whether multiple items per slide is enabled
|
|
180
|
+
* @param {string} viewport - The current viewport size ('xs', 'sm', 'md', 'lg', 'xl')
|
|
181
|
+
* @returns {number} The maximum number of items that can be displayed per slide
|
|
182
|
+
*/
|
|
183
|
+
const getMaximumItemsForSlide = (enableDisplayMultipleItemsPerSlide, viewport) => {
|
|
184
|
+
if (enableDisplayMultipleItemsPerSlide) {
|
|
185
|
+
switch (viewport) {
|
|
186
|
+
case 'xs':
|
|
187
|
+
case 'sm':
|
|
188
|
+
return _Constants.ITEMS_PER_VIEWPORT_XS_SM;
|
|
189
|
+
case 'md':
|
|
190
|
+
return _Constants.ITEMS_PER_VIEWPORT_MD;
|
|
191
|
+
case 'lg':
|
|
192
|
+
case 'xl':
|
|
193
|
+
return _Constants.ITEMS_PER_VIEWPORT_LG_XL;
|
|
194
|
+
default:
|
|
195
|
+
return _Constants.ITEMS_PER_VIEWPORT_XS_SM;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return _Constants.ITEMS_PER_VIEWPORT_XS_SM;
|
|
199
|
+
};
|
|
175
200
|
const selectRootContainerStyles = (enableHero, viewport) => {
|
|
176
201
|
if (enableHero && viewport === 'xl' && _Platform.default.OS === 'web') {
|
|
177
202
|
return {
|
|
@@ -867,6 +892,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
|
|
|
867
892
|
firstFocusRef: firstFocusRef,
|
|
868
893
|
refocus: refocus,
|
|
869
894
|
width: containerLayout.width,
|
|
895
|
+
maximumItemsForSlide: getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport),
|
|
870
896
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
|
|
871
897
|
style: [staticStyles.root, {
|
|
872
898
|
...(_Platform.default.OS === 'web' ? {
|
|
@@ -21,7 +21,8 @@ const CarouselProvider = _ref => {
|
|
|
21
21
|
refocus = false,
|
|
22
22
|
themeTokens,
|
|
23
23
|
totalItems,
|
|
24
|
-
width
|
|
24
|
+
width,
|
|
25
|
+
maximumItemsForSlide
|
|
25
26
|
} = _ref;
|
|
26
27
|
const value = _react.default.useMemo(() => ({
|
|
27
28
|
activeIndex,
|
|
@@ -31,8 +32,9 @@ const CarouselProvider = _ref => {
|
|
|
31
32
|
refocus,
|
|
32
33
|
themeTokens,
|
|
33
34
|
totalItems,
|
|
34
|
-
width
|
|
35
|
-
|
|
35
|
+
width,
|
|
36
|
+
maximumItemsForSlide
|
|
37
|
+
}), [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width, maximumItemsForSlide]);
|
|
36
38
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(CarouselContext.Provider, {
|
|
37
39
|
value: value,
|
|
38
40
|
children: children
|
|
@@ -55,5 +57,6 @@ CarouselProvider.propTypes = {
|
|
|
55
57
|
refocus: _propTypes.default.bool,
|
|
56
58
|
themeTokens: (0, _utils.getTokensPropType)('Carousel'),
|
|
57
59
|
totalItems: _propTypes.default.number.isRequired,
|
|
58
|
-
width: _propTypes.default.number.isRequired
|
|
60
|
+
width: _propTypes.default.number.isRequired,
|
|
61
|
+
maximumItemsForSlide: _propTypes.default.number
|
|
59
62
|
};
|
|
@@ -94,13 +94,23 @@ const CarouselItem = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
94
94
|
} = _ref2;
|
|
95
95
|
const {
|
|
96
96
|
width,
|
|
97
|
-
activeIndex
|
|
97
|
+
activeIndex,
|
|
98
|
+
goTo,
|
|
99
|
+
maximumItemsForSlide
|
|
98
100
|
} = (0, _CarouselContext.useCarousel)();
|
|
99
101
|
const selectedProps = selectProps({
|
|
100
102
|
...rest,
|
|
101
103
|
...(0, _utils.getA11yPropsFromHtmlTag)(tag, rest.accessibilityRole)
|
|
102
104
|
});
|
|
103
|
-
const focusabilityProps = activeIndex === elementIndex ? {} : _utils.a11yProps.nonFocusableProps;
|
|
105
|
+
const focusabilityProps = activeIndex === elementIndex || enablePeeking ? {} : _utils.a11yProps.nonFocusableProps;
|
|
106
|
+
const handleFocus = _react.default.useCallback(event => {
|
|
107
|
+
if (_Platform.default.OS === 'web' && elementIndex >= maximumItemsForSlide * (activeIndex + 1)) {
|
|
108
|
+
goTo(activeIndex + 1);
|
|
109
|
+
}
|
|
110
|
+
if (rest.onFocus) {
|
|
111
|
+
rest.onFocus(event);
|
|
112
|
+
}
|
|
113
|
+
}, [elementIndex, activeIndex, goTo, maximumItemsForSlide, rest]);
|
|
104
114
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
|
|
105
115
|
style: selectContainerStyle({
|
|
106
116
|
width,
|
|
@@ -114,6 +124,7 @@ const CarouselItem = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
114
124
|
...selectedProps,
|
|
115
125
|
...focusabilityProps,
|
|
116
126
|
ref: ref,
|
|
127
|
+
onFocus: handleFocus,
|
|
117
128
|
children: children
|
|
118
129
|
});
|
|
119
130
|
});
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.PEEKING_MULTIPLIER = exports.NEGATIVE_MULTIPLIER = exports.LARGE_VIEWPORT_MARGIN = exports.ITEMS_PER_VIEWPORT_MD = exports.ITEMS_PER_VIEWPORT_LG_XL = exports.HERO_POSITION_OFFSET = exports.GAP_BETWEEN_ITEMS = exports.DEFAULT_VIEWPORT_MARGIN = exports.DEFAULT_POSITION_OFFSET = exports.ACTIVE_INDEX_OFFSET_MULTIPLIER = void 0;
|
|
6
|
+
exports.PEEKING_MULTIPLIER = exports.NEGATIVE_MULTIPLIER = exports.LARGE_VIEWPORT_MARGIN = exports.ITEMS_PER_VIEWPORT_XS_SM = exports.ITEMS_PER_VIEWPORT_MD = exports.ITEMS_PER_VIEWPORT_LG_XL = exports.HERO_POSITION_OFFSET = exports.GAP_BETWEEN_ITEMS = exports.DEFAULT_VIEWPORT_MARGIN = exports.DEFAULT_POSITION_OFFSET = exports.ACTIVE_INDEX_OFFSET_MULTIPLIER = void 0;
|
|
7
|
+
const ITEMS_PER_VIEWPORT_XS_SM = exports.ITEMS_PER_VIEWPORT_XS_SM = 1;
|
|
7
8
|
const ITEMS_PER_VIEWPORT_MD = exports.ITEMS_PER_VIEWPORT_MD = 2;
|
|
8
9
|
const ITEMS_PER_VIEWPORT_LG_XL = exports.ITEMS_PER_VIEWPORT_LG_XL = 3;
|
|
9
10
|
const GAP_BETWEEN_ITEMS = exports.GAP_BETWEEN_ITEMS = 16;
|
|
@@ -62,13 +62,12 @@ const DropdownOverlay = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
|
|
|
62
62
|
});
|
|
63
63
|
const withPortal = Overlay => {
|
|
64
64
|
// eslint-disable-next-line react/display-name, react/no-multi-comp
|
|
65
|
-
return props => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
};
|
|
65
|
+
return /*#__PURE__*/_react.default.forwardRef((props, ref) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_Portal.default, {
|
|
66
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Overlay, {
|
|
67
|
+
...props,
|
|
68
|
+
ref: ref
|
|
69
|
+
})
|
|
70
|
+
}));
|
|
72
71
|
};
|
|
73
72
|
DropdownOverlay.displayName = 'DropdownOverlay';
|
|
74
73
|
DropdownOverlay.propTypes = {
|
|
@@ -21,7 +21,7 @@ import CarouselTabsPanel from './CarouselTabs/CarouselTabsPanel';
|
|
|
21
21
|
import CarouselTabsPanelItem from './CarouselTabs/CarouselTabsPanelItem';
|
|
22
22
|
import dictionary from './dictionary';
|
|
23
23
|
import Box from '../Box';
|
|
24
|
-
import { ITEMS_PER_VIEWPORT_MD, ITEMS_PER_VIEWPORT_LG_XL, DEFAULT_POSITION_OFFSET, LARGE_VIEWPORT_MARGIN, DEFAULT_VIEWPORT_MARGIN, PEEKING_MULTIPLIER, ACTIVE_INDEX_OFFSET_MULTIPLIER, NEGATIVE_MULTIPLIER } from './Constants';
|
|
24
|
+
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, ACTIVE_INDEX_OFFSET_MULTIPLIER, NEGATIVE_MULTIPLIER } from './Constants';
|
|
25
25
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
26
26
|
const TRANSITION_MODES = {
|
|
27
27
|
MANUAL: 'manual',
|
|
@@ -165,6 +165,31 @@ const getTotalItems = (enableDisplayMultipleItemsPerSlide, childrenArray, viewpo
|
|
|
165
165
|
}
|
|
166
166
|
return childrenArray.length;
|
|
167
167
|
};
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Determines the maximum number of items that can be displayed per slide based on viewport
|
|
171
|
+
*
|
|
172
|
+
* @param {boolean} enableDisplayMultipleItemsPerSlide - Flag indicating whether multiple items per slide is enabled
|
|
173
|
+
* @param {string} viewport - The current viewport size ('xs', 'sm', 'md', 'lg', 'xl')
|
|
174
|
+
* @returns {number} The maximum number of items that can be displayed per slide
|
|
175
|
+
*/
|
|
176
|
+
const getMaximumItemsForSlide = (enableDisplayMultipleItemsPerSlide, viewport) => {
|
|
177
|
+
if (enableDisplayMultipleItemsPerSlide) {
|
|
178
|
+
switch (viewport) {
|
|
179
|
+
case 'xs':
|
|
180
|
+
case 'sm':
|
|
181
|
+
return ITEMS_PER_VIEWPORT_XS_SM;
|
|
182
|
+
case 'md':
|
|
183
|
+
return ITEMS_PER_VIEWPORT_MD;
|
|
184
|
+
case 'lg':
|
|
185
|
+
case 'xl':
|
|
186
|
+
return ITEMS_PER_VIEWPORT_LG_XL;
|
|
187
|
+
default:
|
|
188
|
+
return ITEMS_PER_VIEWPORT_XS_SM;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return ITEMS_PER_VIEWPORT_XS_SM;
|
|
192
|
+
};
|
|
168
193
|
const selectRootContainerStyles = (enableHero, viewport) => {
|
|
169
194
|
if (enableHero && viewport === 'xl' && Platform.OS === 'web') {
|
|
170
195
|
return {
|
|
@@ -860,6 +885,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
860
885
|
firstFocusRef: firstFocusRef,
|
|
861
886
|
refocus: refocus,
|
|
862
887
|
width: containerLayout.width,
|
|
888
|
+
maximumItemsForSlide: getMaximumItemsForSlide(enableDisplayMultipleItemsPerSlide, viewport),
|
|
863
889
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
864
890
|
style: [staticStyles.root, {
|
|
865
891
|
...(Platform.OS === 'web' ? {
|
|
@@ -13,7 +13,8 @@ const CarouselProvider = _ref => {
|
|
|
13
13
|
refocus = false,
|
|
14
14
|
themeTokens,
|
|
15
15
|
totalItems,
|
|
16
|
-
width
|
|
16
|
+
width,
|
|
17
|
+
maximumItemsForSlide
|
|
17
18
|
} = _ref;
|
|
18
19
|
const value = React.useMemo(() => ({
|
|
19
20
|
activeIndex,
|
|
@@ -23,8 +24,9 @@ const CarouselProvider = _ref => {
|
|
|
23
24
|
refocus,
|
|
24
25
|
themeTokens,
|
|
25
26
|
totalItems,
|
|
26
|
-
width
|
|
27
|
-
|
|
27
|
+
width,
|
|
28
|
+
maximumItemsForSlide
|
|
29
|
+
}), [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width, maximumItemsForSlide]);
|
|
28
30
|
return /*#__PURE__*/_jsx(CarouselContext.Provider, {
|
|
29
31
|
value: value,
|
|
30
32
|
children: children
|
|
@@ -46,6 +48,7 @@ CarouselProvider.propTypes = {
|
|
|
46
48
|
refocus: PropTypes.bool,
|
|
47
49
|
themeTokens: getTokensPropType('Carousel'),
|
|
48
50
|
totalItems: PropTypes.number.isRequired,
|
|
49
|
-
width: PropTypes.number.isRequired
|
|
51
|
+
width: PropTypes.number.isRequired,
|
|
52
|
+
maximumItemsForSlide: PropTypes.number
|
|
50
53
|
};
|
|
51
54
|
export { CarouselProvider, useCarousel };
|
|
@@ -87,13 +87,23 @@ const CarouselItem = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
87
87
|
} = _ref2;
|
|
88
88
|
const {
|
|
89
89
|
width,
|
|
90
|
-
activeIndex
|
|
90
|
+
activeIndex,
|
|
91
|
+
goTo,
|
|
92
|
+
maximumItemsForSlide
|
|
91
93
|
} = useCarousel();
|
|
92
94
|
const selectedProps = selectProps({
|
|
93
95
|
...rest,
|
|
94
96
|
...getA11yPropsFromHtmlTag(tag, rest.accessibilityRole)
|
|
95
97
|
});
|
|
96
|
-
const focusabilityProps = activeIndex === elementIndex ? {} : a11yProps.nonFocusableProps;
|
|
98
|
+
const focusabilityProps = activeIndex === elementIndex || enablePeeking ? {} : a11yProps.nonFocusableProps;
|
|
99
|
+
const handleFocus = React.useCallback(event => {
|
|
100
|
+
if (Platform.OS === 'web' && elementIndex >= maximumItemsForSlide * (activeIndex + 1)) {
|
|
101
|
+
goTo(activeIndex + 1);
|
|
102
|
+
}
|
|
103
|
+
if (rest.onFocus) {
|
|
104
|
+
rest.onFocus(event);
|
|
105
|
+
}
|
|
106
|
+
}, [elementIndex, activeIndex, goTo, maximumItemsForSlide, rest]);
|
|
97
107
|
return /*#__PURE__*/_jsx(View, {
|
|
98
108
|
style: selectContainerStyle({
|
|
99
109
|
width,
|
|
@@ -107,6 +117,7 @@ const CarouselItem = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
107
117
|
...selectedProps,
|
|
108
118
|
...focusabilityProps,
|
|
109
119
|
ref: ref,
|
|
120
|
+
onFocus: handleFocus,
|
|
110
121
|
children: children
|
|
111
122
|
});
|
|
112
123
|
});
|
|
@@ -55,13 +55,12 @@ const DropdownOverlay = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
55
55
|
});
|
|
56
56
|
const withPortal = Overlay => {
|
|
57
57
|
// eslint-disable-next-line react/display-name, react/no-multi-comp
|
|
58
|
-
return props => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
};
|
|
58
|
+
return /*#__PURE__*/React.forwardRef((props, ref) => /*#__PURE__*/_jsx(Portal, {
|
|
59
|
+
children: /*#__PURE__*/_jsx(Overlay, {
|
|
60
|
+
...props,
|
|
61
|
+
ref: ref
|
|
62
|
+
})
|
|
63
|
+
}));
|
|
65
64
|
};
|
|
66
65
|
DropdownOverlay.displayName = 'DropdownOverlay';
|
|
67
66
|
DropdownOverlay.propTypes = {
|
package/lib/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"@gorhom/portal": "^1.0.14",
|
|
13
13
|
"@react-native-picker/picker": "^2.9.0",
|
|
14
14
|
"@telus-uds/system-constants": "^3.0.0",
|
|
15
|
-
"@telus-uds/system-theme-tokens": "^4.
|
|
15
|
+
"@telus-uds/system-theme-tokens": "^4.11.0",
|
|
16
16
|
"airbnb-prop-types": "^2.16.0",
|
|
17
17
|
"css-mediaquery": "^0.1.2",
|
|
18
18
|
"expo-document-picker": "^13.0.1",
|
|
@@ -84,6 +84,6 @@
|
|
|
84
84
|
"standard-engine": {
|
|
85
85
|
"skip": true
|
|
86
86
|
},
|
|
87
|
-
"version": "3.12.
|
|
87
|
+
"version": "3.12.2",
|
|
88
88
|
"types": "types/index.d.ts"
|
|
89
89
|
}
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"@gorhom/portal": "^1.0.14",
|
|
13
13
|
"@react-native-picker/picker": "^2.9.0",
|
|
14
14
|
"@telus-uds/system-constants": "^3.0.0",
|
|
15
|
-
"@telus-uds/system-theme-tokens": "^4.
|
|
15
|
+
"@telus-uds/system-theme-tokens": "^4.11.0",
|
|
16
16
|
"airbnb-prop-types": "^2.16.0",
|
|
17
17
|
"css-mediaquery": "^0.1.2",
|
|
18
18
|
"expo-document-picker": "^13.0.1",
|
|
@@ -84,6 +84,6 @@
|
|
|
84
84
|
"standard-engine": {
|
|
85
85
|
"skip": true
|
|
86
86
|
},
|
|
87
|
-
"version": "3.12.
|
|
87
|
+
"version": "3.12.2",
|
|
88
88
|
"types": "types/index.d.ts"
|
|
89
89
|
}
|
|
@@ -27,6 +27,7 @@ import CarouselTabsPanelItem from './CarouselTabs/CarouselTabsPanelItem'
|
|
|
27
27
|
import dictionary from './dictionary'
|
|
28
28
|
import Box from '../Box'
|
|
29
29
|
import {
|
|
30
|
+
ITEMS_PER_VIEWPORT_XS_SM,
|
|
30
31
|
ITEMS_PER_VIEWPORT_MD,
|
|
31
32
|
ITEMS_PER_VIEWPORT_LG_XL,
|
|
32
33
|
DEFAULT_POSITION_OFFSET,
|
|
@@ -211,6 +212,31 @@ const getTotalItems = (enableDisplayMultipleItemsPerSlide, childrenArray, viewpo
|
|
|
211
212
|
return childrenArray.length
|
|
212
213
|
}
|
|
213
214
|
|
|
215
|
+
/**
|
|
216
|
+
* Determines the maximum number of items that can be displayed per slide based on viewport
|
|
217
|
+
*
|
|
218
|
+
* @param {boolean} enableDisplayMultipleItemsPerSlide - Flag indicating whether multiple items per slide is enabled
|
|
219
|
+
* @param {string} viewport - The current viewport size ('xs', 'sm', 'md', 'lg', 'xl')
|
|
220
|
+
* @returns {number} The maximum number of items that can be displayed per slide
|
|
221
|
+
*/
|
|
222
|
+
const getMaximumItemsForSlide = (enableDisplayMultipleItemsPerSlide, viewport) => {
|
|
223
|
+
if (enableDisplayMultipleItemsPerSlide) {
|
|
224
|
+
switch (viewport) {
|
|
225
|
+
case 'xs':
|
|
226
|
+
case 'sm':
|
|
227
|
+
return ITEMS_PER_VIEWPORT_XS_SM
|
|
228
|
+
case 'md':
|
|
229
|
+
return ITEMS_PER_VIEWPORT_MD
|
|
230
|
+
case 'lg':
|
|
231
|
+
case 'xl':
|
|
232
|
+
return ITEMS_PER_VIEWPORT_LG_XL
|
|
233
|
+
default:
|
|
234
|
+
return ITEMS_PER_VIEWPORT_XS_SM
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return ITEMS_PER_VIEWPORT_XS_SM
|
|
238
|
+
}
|
|
239
|
+
|
|
214
240
|
const selectRootContainerStyles = (enableHero, viewport) => {
|
|
215
241
|
if (enableHero && viewport === 'xl' && Platform.OS === 'web') {
|
|
216
242
|
return {
|
|
@@ -993,6 +1019,10 @@ const Carousel = React.forwardRef(
|
|
|
993
1019
|
firstFocusRef={firstFocusRef}
|
|
994
1020
|
refocus={refocus}
|
|
995
1021
|
width={containerLayout.width}
|
|
1022
|
+
maximumItemsForSlide={getMaximumItemsForSlide(
|
|
1023
|
+
enableDisplayMultipleItemsPerSlide,
|
|
1024
|
+
viewport
|
|
1025
|
+
)}
|
|
996
1026
|
>
|
|
997
1027
|
<View
|
|
998
1028
|
style={[
|
|
@@ -13,7 +13,8 @@ const CarouselProvider = ({
|
|
|
13
13
|
refocus = false,
|
|
14
14
|
themeTokens,
|
|
15
15
|
totalItems,
|
|
16
|
-
width
|
|
16
|
+
width,
|
|
17
|
+
maximumItemsForSlide
|
|
17
18
|
}) => {
|
|
18
19
|
const value = React.useMemo(
|
|
19
20
|
() => ({
|
|
@@ -24,9 +25,20 @@ const CarouselProvider = ({
|
|
|
24
25
|
refocus,
|
|
25
26
|
themeTokens,
|
|
26
27
|
totalItems,
|
|
27
|
-
width
|
|
28
|
+
width,
|
|
29
|
+
maximumItemsForSlide
|
|
28
30
|
}),
|
|
29
|
-
[
|
|
31
|
+
[
|
|
32
|
+
activeIndex,
|
|
33
|
+
goTo,
|
|
34
|
+
getCopyWithPlaceholders,
|
|
35
|
+
itemLabel,
|
|
36
|
+
refocus,
|
|
37
|
+
totalItems,
|
|
38
|
+
themeTokens,
|
|
39
|
+
width,
|
|
40
|
+
maximumItemsForSlide
|
|
41
|
+
]
|
|
30
42
|
)
|
|
31
43
|
return <CarouselContext.Provider value={value}>{children}</CarouselContext.Provider>
|
|
32
44
|
}
|
|
@@ -48,7 +60,8 @@ CarouselProvider.propTypes = {
|
|
|
48
60
|
refocus: PropTypes.bool,
|
|
49
61
|
themeTokens: getTokensPropType('Carousel'),
|
|
50
62
|
totalItems: PropTypes.number.isRequired,
|
|
51
|
-
width: PropTypes.number.isRequired
|
|
63
|
+
width: PropTypes.number.isRequired,
|
|
64
|
+
maximumItemsForSlide: PropTypes.number
|
|
52
65
|
}
|
|
53
66
|
|
|
54
67
|
export { CarouselProvider, useCarousel }
|
|
@@ -102,14 +102,28 @@ const CarouselItem = React.forwardRef(
|
|
|
102
102
|
},
|
|
103
103
|
ref
|
|
104
104
|
) => {
|
|
105
|
-
const { width, activeIndex } = useCarousel()
|
|
105
|
+
const { width, activeIndex, goTo, maximumItemsForSlide } = useCarousel()
|
|
106
106
|
|
|
107
107
|
const selectedProps = selectProps({
|
|
108
108
|
...rest,
|
|
109
109
|
...getA11yPropsFromHtmlTag(tag, rest.accessibilityRole)
|
|
110
110
|
})
|
|
111
111
|
|
|
112
|
-
const focusabilityProps =
|
|
112
|
+
const focusabilityProps =
|
|
113
|
+
activeIndex === elementIndex || enablePeeking ? {} : a11yProps.nonFocusableProps
|
|
114
|
+
|
|
115
|
+
const handleFocus = React.useCallback(
|
|
116
|
+
(event) => {
|
|
117
|
+
if (Platform.OS === 'web' && elementIndex >= maximumItemsForSlide * (activeIndex + 1)) {
|
|
118
|
+
goTo(activeIndex + 1)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (rest.onFocus) {
|
|
122
|
+
rest.onFocus(event)
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
[elementIndex, activeIndex, goTo, maximumItemsForSlide, rest]
|
|
126
|
+
)
|
|
113
127
|
|
|
114
128
|
return (
|
|
115
129
|
<View
|
|
@@ -125,6 +139,7 @@ const CarouselItem = React.forwardRef(
|
|
|
125
139
|
{...selectedProps}
|
|
126
140
|
{...focusabilityProps}
|
|
127
141
|
ref={ref}
|
|
142
|
+
onFocus={handleFocus}
|
|
128
143
|
>
|
|
129
144
|
{children}
|
|
130
145
|
</View>
|
|
@@ -55,13 +55,11 @@ const DropdownOverlay = React.forwardRef(
|
|
|
55
55
|
|
|
56
56
|
const withPortal = (Overlay) => {
|
|
57
57
|
// eslint-disable-next-line react/display-name, react/no-multi-comp
|
|
58
|
-
return (props) =>
|
|
59
|
-
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
)
|
|
64
|
-
}
|
|
58
|
+
return React.forwardRef((props, ref) => (
|
|
59
|
+
<Portal>
|
|
60
|
+
<Overlay {...props} ref={ref} />
|
|
61
|
+
</Portal>
|
|
62
|
+
))
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
DropdownOverlay.displayName = 'DropdownOverlay'
|