@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 CHANGED
@@ -1,12 +1,29 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Fri, 11 Jul 2025 22:15:36 GMT and should not be manually modified.
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:15:36 GMT
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
- }), [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width]);
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
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Portal.default, {
67
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Overlay, {
68
- ...props
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
- }), [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width]);
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
  });
@@ -1,3 +1,4 @@
1
+ export const ITEMS_PER_VIEWPORT_XS_SM = 1;
1
2
  export const ITEMS_PER_VIEWPORT_MD = 2;
2
3
  export const ITEMS_PER_VIEWPORT_LG_XL = 3;
3
4
  export const GAP_BETWEEN_ITEMS = 16;
@@ -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
- return /*#__PURE__*/_jsx(Portal, {
60
- children: /*#__PURE__*/_jsx(Overlay, {
61
- ...props
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.10.0",
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.0",
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.10.0",
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.0",
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
- [activeIndex, goTo, getCopyWithPlaceholders, itemLabel, refocus, totalItems, themeTokens, width]
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 = activeIndex === elementIndex ? {} : a11yProps.nonFocusableProps
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>
@@ -1,3 +1,4 @@
1
+ export const ITEMS_PER_VIEWPORT_XS_SM = 1
1
2
  export const ITEMS_PER_VIEWPORT_MD = 2
2
3
  export const ITEMS_PER_VIEWPORT_LG_XL = 3
3
4
  export const GAP_BETWEEN_ITEMS = 16
@@ -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
- return (
60
- <Portal>
61
- <Overlay {...props} />
62
- </Portal>
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'