carbon-react 114.13.1 → 114.14.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/esm/__internal__/input-icon-toggle/input-icon-toggle.component.js +2 -1
- package/esm/components/link/link.component.d.ts +2 -0
- package/esm/components/link/link.component.js +7 -1
- package/esm/components/menu/__internal__/keyboard-navigation/index.d.ts +4 -2
- package/esm/components/menu/__internal__/keyboard-navigation/index.js +16 -15
- package/esm/components/menu/__internal__/locators.d.ts +6 -0
- package/esm/components/menu/__internal__/locators.js +6 -0
- package/esm/components/menu/__internal__/submenu/submenu.component.js +109 -108
- package/esm/components/menu/menu-full-screen/menu-full-screen.component.js +1 -2
- package/esm/components/menu/menu-item/index.js +0 -1
- package/esm/components/menu/menu-item/menu-item.component.js +77 -51
- package/esm/components/menu/menu-item/menu-item.d.ts +7 -3
- package/esm/components/menu/menu.component.js +33 -37
- package/esm/components/menu/menu.context.d.ts +2 -2
- package/esm/components/menu/menu.context.js +2 -2
- package/esm/components/menu/scrollable-block/scrollable-block.component.js +6 -24
- package/esm/components/select/filterable-select/filterable-select.component.js +15 -2
- package/esm/components/select/filterable-select/filterable-select.d.ts +7 -0
- package/esm/components/select/list-action-button/list-action-button.style.js +4 -1
- package/esm/components/select/multi-select/multi-select.component.js +15 -2
- package/esm/components/select/multi-select/multi-select.d.ts +7 -0
- package/esm/components/select/option/option.component.js +16 -5
- package/esm/components/select/option/option.style.js +4 -0
- package/esm/components/select/option-group-header/option-group-header.component.js +20 -8
- package/esm/components/select/option-group-header/option-group-header.style.js +3 -2
- package/esm/components/select/option-row/option-row.component.js +16 -5
- package/esm/components/select/option-row/option-row.style.js +4 -0
- package/esm/components/select/select-list/select-list-container.style.js +11 -1
- package/esm/components/select/select-list/select-list.component.js +136 -62
- package/esm/components/select/select-list/select-list.style.js +15 -18
- package/esm/components/select/simple-select/simple-select.component.js +15 -2
- package/esm/components/select/simple-select/simple-select.d.ts +7 -0
- package/lib/__internal__/input-icon-toggle/input-icon-toggle.component.js +2 -1
- package/lib/components/link/link.component.d.ts +2 -0
- package/lib/components/link/link.component.js +7 -1
- package/lib/components/menu/__internal__/keyboard-navigation/index.d.ts +4 -2
- package/lib/components/menu/__internal__/keyboard-navigation/index.js +16 -15
- package/lib/components/menu/__internal__/locators.d.ts +6 -0
- package/lib/components/menu/__internal__/locators.js +18 -0
- package/lib/components/menu/__internal__/submenu/submenu.component.js +111 -113
- package/lib/components/menu/menu-full-screen/menu-full-screen.component.js +1 -2
- package/lib/components/menu/menu-item/menu-item.component.js +76 -52
- package/lib/components/menu/menu-item/menu-item.d.ts +7 -3
- package/lib/components/menu/menu.component.js +33 -37
- package/lib/components/menu/menu.context.d.ts +2 -2
- package/lib/components/menu/menu.context.js +2 -2
- package/lib/components/menu/scrollable-block/scrollable-block.component.js +6 -25
- package/lib/components/select/filterable-select/filterable-select.component.js +15 -2
- package/lib/components/select/filterable-select/filterable-select.d.ts +7 -0
- package/lib/components/select/list-action-button/list-action-button.style.js +4 -1
- package/lib/components/select/multi-select/multi-select.component.js +15 -2
- package/lib/components/select/multi-select/multi-select.d.ts +7 -0
- package/lib/components/select/option/option.component.js +16 -5
- package/lib/components/select/option/option.style.js +4 -0
- package/lib/components/select/option-group-header/option-group-header.component.js +20 -6
- package/lib/components/select/option-group-header/option-group-header.style.js +3 -2
- package/lib/components/select/option-row/option-row.component.js +16 -5
- package/lib/components/select/option-row/option-row.style.js +4 -0
- package/lib/components/select/select-list/select-list-container.style.js +11 -1
- package/lib/components/select/select-list/select-list.component.js +139 -63
- package/lib/components/select/select-list/select-list.style.js +15 -18
- package/lib/components/select/simple-select/simple-select.component.js +15 -2
- package/lib/components/select/simple-select/simple-select.d.ts +7 -0
- package/package.json +2 -1
- package/esm/components/select/select-list/update-list-scroll.js +0 -21
- package/lib/components/select/select-list/update-list-scroll.js +0 -28
|
@@ -11,6 +11,10 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
|
11
11
|
|
|
12
12
|
var _dom = require("@floating-ui/dom");
|
|
13
13
|
|
|
14
|
+
var _reactVirtual = require("@tanstack/react-virtual");
|
|
15
|
+
|
|
16
|
+
var _findLastIndex = _interopRequireDefault(require("lodash/findLastIndex"));
|
|
17
|
+
|
|
14
18
|
var _useScrollBlock = _interopRequireDefault(require("../../../hooks/__internal__/useScrollBlock"));
|
|
15
19
|
|
|
16
20
|
var _selectList = require("./select-list.style");
|
|
@@ -19,8 +23,6 @@ var _popover = _interopRequireDefault(require("../../../__internal__/popover"));
|
|
|
19
23
|
|
|
20
24
|
var _optionRow = _interopRequireDefault(require("../option-row/option-row.component"));
|
|
21
25
|
|
|
22
|
-
var _updateListScroll = _interopRequireDefault(require("./update-list-scroll"));
|
|
23
|
-
|
|
24
26
|
var _getNextChildByText = _interopRequireDefault(require("../utils/get-next-child-by-text"));
|
|
25
27
|
|
|
26
28
|
var _getNextIndexByKey = _interopRequireDefault(require("../utils/get-next-index-by-key"));
|
|
@@ -47,6 +49,12 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
|
|
|
47
49
|
|
|
48
50
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
49
51
|
|
|
52
|
+
const TABLE_HEADER_HEIGHT = 48;
|
|
53
|
+
const SCROLL_OPTIONS = {
|
|
54
|
+
smoothScroll: false,
|
|
55
|
+
align: "end"
|
|
56
|
+
};
|
|
57
|
+
|
|
50
58
|
const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
51
59
|
listMaxHeight = 180,
|
|
52
60
|
listActionButton,
|
|
@@ -69,8 +77,12 @@ const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
69
77
|
flipEnabled = true,
|
|
70
78
|
isOpen,
|
|
71
79
|
multiselectValues,
|
|
80
|
+
enableVirtualScroll,
|
|
81
|
+
virtualScrollOverscan = 5,
|
|
72
82
|
...listProps
|
|
73
83
|
}, listContainerRef) => {
|
|
84
|
+
var _childIdsRef$current;
|
|
85
|
+
|
|
74
86
|
const [currentOptionsListIndex, setCurrentOptionsListIndex] = (0, _react.useState)(-1);
|
|
75
87
|
const [scrollbarWidth, setScrollbarWidth] = (0, _react.useState)(0);
|
|
76
88
|
const lastFilter = (0, _react.useRef)("");
|
|
@@ -81,6 +93,19 @@ const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
81
93
|
blockScroll,
|
|
82
94
|
allowScroll
|
|
83
95
|
} = (0, _useScrollBlock.default)();
|
|
96
|
+
const actionButtonHeight = (0, _react.useRef)(0);
|
|
97
|
+
const overscan = enableVirtualScroll ? virtualScrollOverscan : _react.default.Children.count(children);
|
|
98
|
+
const virtualizer = (0, _reactVirtual.useVirtualizer)({
|
|
99
|
+
count: _react.default.Children.count(children),
|
|
100
|
+
getScrollElement: () => listContainerRef.current,
|
|
101
|
+
estimateSize: () => 40,
|
|
102
|
+
// value doesn't really seem to matter since we're dynamically measuring, but 40px is the height of a single-line option
|
|
103
|
+
overscan,
|
|
104
|
+
paddingStart: multiColumn ? TABLE_HEADER_HEIGHT : 0,
|
|
105
|
+
scrollPaddingEnd: actionButtonHeight.current
|
|
106
|
+
});
|
|
107
|
+
const items = virtualizer.getVirtualItems();
|
|
108
|
+
const listHeight = virtualizer.getTotalSize();
|
|
84
109
|
(0, _react.useEffect)(() => {
|
|
85
110
|
if (isOpen) {
|
|
86
111
|
blockScroll();
|
|
@@ -100,43 +125,67 @@ const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
100
125
|
const anchorRef = (0, _react.useMemo)(() => ({
|
|
101
126
|
current: anchorElement
|
|
102
127
|
}), [anchorElement]);
|
|
103
|
-
const optionRefList = (0, _react.useMemo)(() => _react.default.Children.map(children, child => {
|
|
104
|
-
if ((child === null || child === void 0 ? void 0 : child.type) === _option.default || (child === null || child === void 0 ? void 0 : child.type) === _optionRow.default) {
|
|
105
|
-
return /*#__PURE__*/_react.default.createRef();
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return null;
|
|
109
|
-
}).filter(child => child), [children]);
|
|
110
128
|
const handleSelect = (0, _react.useCallback)(optionData => {
|
|
111
129
|
onSelect({ ...optionData,
|
|
112
130
|
selectionType: "click"
|
|
113
131
|
});
|
|
114
132
|
}, [onSelect]);
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
133
|
+
const childIdsRef = (0, _react.useRef)(null); // childIds should be stable except when children are added or removed - can't use useMemo
|
|
134
|
+
// as that isn't absolutely guaranteed to never rerun when dependencies haven't changed.
|
|
135
|
+
|
|
136
|
+
const setChildIds = () => {
|
|
137
|
+
childIdsRef.current = _react.default.Children.map(children, () => (0, _guid.default)());
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
if (((_childIdsRef$current = childIdsRef.current) === null || _childIdsRef$current === void 0 ? void 0 : _childIdsRef$current.length) !== _react.default.Children.count(children)) {
|
|
141
|
+
setChildIds();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const childIds = childIdsRef.current;
|
|
145
|
+
const childrenList = (0, _react.useMemo)(() => _react.default.Children.toArray(children), [children]);
|
|
146
|
+
const optionChildrenList = (0, _react.useMemo)(() => childrenList.filter(child => child.type === _option.default || child.type === _optionRow.default), [childrenList]);
|
|
147
|
+
const {
|
|
148
|
+
measureElement
|
|
149
|
+
} = virtualizer;
|
|
150
|
+
|
|
151
|
+
const measureCallback = element => {
|
|
152
|
+
// need a guard to prevent crash with too many rerenders when closing the list
|
|
153
|
+
if (isOpen) {
|
|
154
|
+
measureElement(element);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const renderedChildren = items.map(item => {
|
|
159
|
+
const {
|
|
160
|
+
index,
|
|
161
|
+
start
|
|
162
|
+
} = item;
|
|
163
|
+
const child = childrenList[index];
|
|
164
|
+
|
|
165
|
+
if (!child) {
|
|
118
166
|
return child;
|
|
119
167
|
}
|
|
120
168
|
|
|
169
|
+
const optionChildIndex = optionChildrenList.indexOf(child);
|
|
170
|
+
const isOption = optionChildIndex > -1;
|
|
121
171
|
const newProps = {
|
|
122
172
|
index,
|
|
123
173
|
id: childIds[index],
|
|
124
174
|
onSelect: handleSelect,
|
|
125
|
-
hidden: isLoading &&
|
|
126
|
-
|
|
175
|
+
hidden: isLoading && childrenList.length === 1,
|
|
176
|
+
// these need to be inline styles rather than implemented in styled-components to avoid it generating thousands of classes
|
|
177
|
+
style: {
|
|
178
|
+
transform: `translateY(${start}px)`
|
|
179
|
+
},
|
|
180
|
+
"aria-setsize": isOption ? optionChildrenList.length : undefined,
|
|
181
|
+
"aria-posinset": isOption ? optionChildIndex + 1 : undefined,
|
|
182
|
+
// needed to dynamically compute the size
|
|
183
|
+
ref: measureCallback,
|
|
184
|
+
"data-index": index
|
|
127
185
|
};
|
|
128
186
|
return /*#__PURE__*/_react.default.cloneElement(child, newProps);
|
|
129
|
-
})
|
|
130
|
-
const
|
|
131
|
-
const lastOptionIndex = (0, _react.useMemo)(() => {
|
|
132
|
-
let lastIndex = 0;
|
|
133
|
-
childrenList.forEach((element, index) => {
|
|
134
|
-
if (element.type === _option.default || element.type === _optionRow.default) {
|
|
135
|
-
lastIndex = index;
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
return lastIndex;
|
|
139
|
-
}, [childrenList]);
|
|
187
|
+
});
|
|
188
|
+
const lastOptionIndex = (0, _findLastIndex.default)(childrenList, child => child.type === _option.default || child.type === _optionRow.default);
|
|
140
189
|
const getNextHighlightableItemIndex = (0, _react.useCallback)((key, indexOfHighlighted) => {
|
|
141
190
|
const lastIndex = lastOptionIndex;
|
|
142
191
|
let nextIndex = (0, _getNextIndexByKey.default)(key, indexOfHighlighted, lastIndex, isLoading);
|
|
@@ -167,16 +216,15 @@ const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
167
216
|
|
|
168
217
|
const {
|
|
169
218
|
text,
|
|
170
|
-
value
|
|
171
|
-
id: itemId
|
|
219
|
+
value
|
|
172
220
|
} = childrenList[nextIndex].props;
|
|
173
221
|
onSelect({
|
|
174
222
|
text,
|
|
175
223
|
value,
|
|
176
224
|
selectionType: "navigationKey",
|
|
177
|
-
id:
|
|
225
|
+
id: childIds[nextIndex]
|
|
178
226
|
});
|
|
179
|
-
}, [childrenList, currentOptionsListIndex, getIndexOfMatch, getNextHighlightableItemIndex, highlightedValue, onSelect]);
|
|
227
|
+
}, [childrenList, currentOptionsListIndex, getIndexOfMatch, getNextHighlightableItemIndex, highlightedValue, onSelect, childIds]);
|
|
180
228
|
const handleActionButtonTab = (0, _react.useCallback)((event, isActionButtonFocused) => {
|
|
181
229
|
if (isActionButtonFocused) {
|
|
182
230
|
onSelect({
|
|
@@ -216,12 +264,11 @@ const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
216
264
|
}
|
|
217
265
|
|
|
218
266
|
const {
|
|
219
|
-
id: itemId,
|
|
220
267
|
text,
|
|
221
268
|
value
|
|
222
269
|
} = currentOption.props;
|
|
223
270
|
onSelect({
|
|
224
|
-
id:
|
|
271
|
+
id: childIds[currentOptionsListIndex],
|
|
225
272
|
text,
|
|
226
273
|
value,
|
|
227
274
|
selectionType: "enterKey"
|
|
@@ -230,9 +277,10 @@ const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
230
277
|
focusOnAnchor();
|
|
231
278
|
highlightNextItem(key);
|
|
232
279
|
}
|
|
233
|
-
}, [childrenList, listActionButton, handleActionButtonTab, onSelectListClose, currentOptionsListIndex, onSelect, highlightNextItem, focusOnAnchor, isOpen]);
|
|
280
|
+
}, [childrenList, listActionButton, handleActionButtonTab, onSelectListClose, currentOptionsListIndex, onSelect, highlightNextItem, focusOnAnchor, isOpen, childIds]);
|
|
234
281
|
const handleListScroll = (0, _react.useCallback)(event => {
|
|
235
282
|
const element = event.target;
|
|
283
|
+
/* istanbul ignore else */
|
|
236
284
|
|
|
237
285
|
if (onListScrollBottom && element.scrollHeight - element.scrollTop === element.clientHeight) {
|
|
238
286
|
onListScrollBottom();
|
|
@@ -240,14 +288,14 @@ const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
240
288
|
}, [onListScrollBottom]);
|
|
241
289
|
(0, _react.useEffect)(() => {
|
|
242
290
|
const keyboardEvent = "keydown";
|
|
243
|
-
const listElement =
|
|
291
|
+
const listElement = listContainerRef.current;
|
|
244
292
|
window.addEventListener(keyboardEvent, handleGlobalKeydown);
|
|
245
293
|
listElement.addEventListener("scroll", handleListScroll);
|
|
246
294
|
return function cleanup() {
|
|
247
295
|
window.removeEventListener(keyboardEvent, handleGlobalKeydown);
|
|
248
296
|
listElement.removeEventListener("scroll", handleListScroll);
|
|
249
297
|
};
|
|
250
|
-
}, [handleGlobalKeydown, handleListScroll]);
|
|
298
|
+
}, [handleGlobalKeydown, handleListScroll, listContainerRef]);
|
|
251
299
|
(0, _react.useEffect)(() => {
|
|
252
300
|
if (!filterText || filterText === lastFilter.current) {
|
|
253
301
|
lastFilter.current = filterText;
|
|
@@ -263,10 +311,10 @@ const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
263
311
|
}
|
|
264
312
|
|
|
265
313
|
const indexOfMatch = getIndexOfMatch(match.props.value);
|
|
266
|
-
|
|
314
|
+
virtualizer.scrollToIndex(indexOfMatch, SCROLL_OPTIONS);
|
|
267
315
|
return indexOfMatch;
|
|
268
316
|
});
|
|
269
|
-
}, [childrenList, filterText, getIndexOfMatch,
|
|
317
|
+
}, [childrenList, filterText, getIndexOfMatch, virtualizer]);
|
|
270
318
|
(0, _react.useEffect)(() => {
|
|
271
319
|
if (!highlightedValue) {
|
|
272
320
|
return;
|
|
@@ -274,13 +322,19 @@ const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
274
322
|
|
|
275
323
|
const indexOfMatch = getIndexOfMatch(highlightedValue);
|
|
276
324
|
setCurrentOptionsListIndex(indexOfMatch);
|
|
277
|
-
|
|
278
|
-
|
|
325
|
+
virtualizer.scrollToIndex(indexOfMatch, SCROLL_OPTIONS); // TODO: is there a better way than calling handleListScroll manually?
|
|
326
|
+
|
|
327
|
+
handleListScroll({
|
|
328
|
+
target: listContainerRef.current
|
|
329
|
+
});
|
|
330
|
+
}, [getIndexOfMatch, highlightedValue, virtualizer, handleListScroll, listContainerRef]);
|
|
279
331
|
(0, _react.useEffect)(() => {
|
|
280
|
-
if (isLoading && currentOptionsListIndex === lastOptionIndex) {
|
|
281
|
-
|
|
332
|
+
if (isLoading && currentOptionsListIndex === lastOptionIndex && lastOptionIndex > -1) {
|
|
333
|
+
virtualizer.scrollToIndex(lastOptionIndex, { ...SCROLL_OPTIONS,
|
|
334
|
+
align: "start"
|
|
335
|
+
});
|
|
282
336
|
}
|
|
283
|
-
}, [children, currentOptionsListIndex, isLoading, lastOptionIndex]);
|
|
337
|
+
}, [children, currentOptionsListIndex, isLoading, lastOptionIndex, listContainerRef, virtualizer]);
|
|
284
338
|
const popoverMiddleware = (0, _react.useMemo)(() => [(0, _dom.offset)(3), (0, _dom.size)({
|
|
285
339
|
apply({
|
|
286
340
|
rects,
|
|
@@ -295,21 +349,37 @@ const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
295
349
|
fallbackStrategy: "initialPlacement"
|
|
296
350
|
})] : [])], [flipEnabled]);
|
|
297
351
|
|
|
298
|
-
const loader = () =>
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
352
|
+
const loader = () => {
|
|
353
|
+
return /*#__PURE__*/_react.default.createElement(_selectList.StyledSelectLoaderContainer, {
|
|
354
|
+
key: "loader"
|
|
355
|
+
}, /*#__PURE__*/_react.default.createElement(_loader.default, {
|
|
356
|
+
"data-role": loaderDataRole
|
|
357
|
+
}));
|
|
358
|
+
};
|
|
304
359
|
|
|
305
|
-
let selectListContent =
|
|
360
|
+
let selectListContent = renderedChildren;
|
|
361
|
+
const listBoxProps = {
|
|
362
|
+
role: "listbox",
|
|
363
|
+
id,
|
|
364
|
+
"aria-labelledby": labelId,
|
|
365
|
+
"aria-multiselectable": multiselectValues ? true : undefined
|
|
366
|
+
};
|
|
367
|
+
(0, _react.useLayoutEffect)(() => {
|
|
368
|
+
if (listActionButton && isOpen) {
|
|
369
|
+
var _listActionButtonRef$, _listActionButtonRef$2;
|
|
370
|
+
|
|
371
|
+
actionButtonHeight.current = ((_listActionButtonRef$ = listActionButtonRef.current) === null || _listActionButtonRef$ === void 0 ? void 0 : (_listActionButtonRef$2 = _listActionButtonRef$.parentElement) === null || _listActionButtonRef$2 === void 0 ? void 0 : _listActionButtonRef$2.offsetHeight) || 0;
|
|
372
|
+
}
|
|
373
|
+
}, [listActionButton, isOpen]);
|
|
306
374
|
|
|
307
375
|
if (multiColumn) {
|
|
308
376
|
selectListContent = /*#__PURE__*/_react.default.createElement(_selectList.StyledSelectListTable, null, /*#__PURE__*/_react.default.createElement(_selectList.StyledSelectListTableHeader, {
|
|
309
377
|
scrollbarWidth: scrollbarWidth
|
|
310
|
-
}, tableHeader), /*#__PURE__*/_react.default.createElement(_selectList.StyledSelectListTableBody, {
|
|
311
|
-
|
|
312
|
-
|
|
378
|
+
}, tableHeader), /*#__PURE__*/_react.default.createElement(_selectList.StyledSelectListTableBody, _extends({}, listBoxProps, {
|
|
379
|
+
"aria-labelledby": labelId,
|
|
380
|
+
ref: tableRef,
|
|
381
|
+
listHeight: listHeight - TABLE_HEADER_HEIGHT
|
|
382
|
+
}), renderedChildren));
|
|
313
383
|
}
|
|
314
384
|
|
|
315
385
|
return /*#__PURE__*/_react.default.createElement(_selectListContext.default.Provider, {
|
|
@@ -327,20 +397,17 @@ const SelectList = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
327
397
|
animationFrame: true
|
|
328
398
|
}, /*#__PURE__*/_react.default.createElement(_selectListContainer.default, _extends({
|
|
329
399
|
"data-element": "select-list-wrapper",
|
|
330
|
-
ref: listContainerRef
|
|
331
|
-
|
|
332
|
-
|
|
400
|
+
ref: listContainerRef,
|
|
401
|
+
maxHeight: listMaxHeight + actionButtonHeight.current,
|
|
402
|
+
isLoading: isLoading
|
|
403
|
+
}, listProps), /*#__PURE__*/_react.default.createElement(_selectList.StyledSelectList, _extends({
|
|
333
404
|
as: multiColumn ? "div" : "ul",
|
|
334
|
-
"
|
|
335
|
-
|
|
336
|
-
role: "listbox",
|
|
337
|
-
"aria-multiselectable": multiselectValues ? true : undefined,
|
|
405
|
+
"data-element": "select-list"
|
|
406
|
+
}, multiColumn ? {} : listBoxProps, {
|
|
338
407
|
ref: listRef,
|
|
339
408
|
tabIndex: "-1",
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
maxHeight: listMaxHeight
|
|
343
|
-
}, selectListContent, isLoading && loader()), listActionButton && /*#__PURE__*/_react.default.createElement(_listActionButton.default, {
|
|
409
|
+
listHeight: multiColumn ? undefined : listHeight
|
|
410
|
+
}), selectListContent), isLoading && loader(), listActionButton && /*#__PURE__*/_react.default.createElement(_listActionButton.default, {
|
|
344
411
|
ref: listActionButtonRef,
|
|
345
412
|
listActionButton: listActionButton,
|
|
346
413
|
onListAction: onListAction
|
|
@@ -411,7 +478,16 @@ SelectList.propTypes = {
|
|
|
411
478
|
isOpen: _propTypes.default.bool,
|
|
412
479
|
|
|
413
480
|
/** array of selected values, if rendered as part of a MultiSelect */
|
|
414
|
-
multiselectValues: _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.string), _propTypes.default.arrayOf(_propTypes.default.object)])
|
|
481
|
+
multiselectValues: _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.string), _propTypes.default.arrayOf(_propTypes.default.object)]),
|
|
482
|
+
|
|
483
|
+
/** Set this prop to enable a virtualised list of options. If it is not used then all options will be in the
|
|
484
|
+
* DOM at all times, which may cause performance problems on very large lists */
|
|
485
|
+
enableVirtualScroll: _propTypes.default.bool,
|
|
486
|
+
|
|
487
|
+
/** The number of options to render into the DOM at once, either side of the currently-visible ones.
|
|
488
|
+
* Higher values make for smoother scrolling but may impact performance.
|
|
489
|
+
* Only used if the `enableVirtualScroll` prop is set. */
|
|
490
|
+
virtualScrollOverscan: _propTypes.default.number
|
|
415
491
|
};
|
|
416
492
|
var _default = SelectList;
|
|
417
493
|
exports.default = _default;
|
|
@@ -13,40 +13,30 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
|
|
|
13
13
|
|
|
14
14
|
const StyledSelectList = _styledComponents.default.ul`
|
|
15
15
|
${({
|
|
16
|
-
|
|
17
|
-
multiColumn
|
|
16
|
+
listHeight
|
|
18
17
|
}) => (0, _styledComponents.css)`
|
|
19
18
|
box-sizing: border-box;
|
|
20
19
|
display: flex;
|
|
21
20
|
align-items: flex-start;
|
|
22
21
|
flex-direction: column;
|
|
23
22
|
list-style-type: none;
|
|
24
|
-
max-height: ${({
|
|
25
|
-
maxHeight
|
|
26
|
-
}) => `${maxHeight}`}px;
|
|
27
23
|
margin: 0;
|
|
28
24
|
outline: none;
|
|
29
|
-
overflow-x: hidden;
|
|
30
|
-
overflow-y: ${multiColumn ? "hidden" : "auto"};
|
|
31
25
|
padding: 0;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
`}}
|
|
26
|
+
position: relative;
|
|
27
|
+
width: 100%;
|
|
28
|
+
${listHeight === undefined ? "" : `height: ${listHeight}px;`}
|
|
36
29
|
`}
|
|
37
30
|
`;
|
|
38
31
|
exports.StyledSelectList = StyledSelectList;
|
|
39
|
-
|
|
40
|
-
maxHeight: "180px"
|
|
41
|
-
};
|
|
42
|
-
const StyledSelectLoaderContainer = _styledComponents.default.li`
|
|
32
|
+
const StyledSelectLoaderContainer = _styledComponents.default.div`
|
|
43
33
|
display: flex;
|
|
44
34
|
align-items: center;
|
|
45
35
|
justify-content: center;
|
|
46
|
-
flex-grow: 1;
|
|
47
36
|
padding-top: 24px;
|
|
48
37
|
padding-bottom: 24px;
|
|
49
38
|
width: 100%;
|
|
39
|
+
flex-grow: 1;
|
|
50
40
|
`;
|
|
51
41
|
exports.StyledSelectLoaderContainer = StyledSelectLoaderContainer;
|
|
52
42
|
const StyledSelectListTable = _styledComponents.default.table`
|
|
@@ -57,6 +47,7 @@ const StyledSelectListTable = _styledComponents.default.table`
|
|
|
57
47
|
min-width: 100%;
|
|
58
48
|
white-space: nowrap;
|
|
59
49
|
height: 180px;
|
|
50
|
+
overflow-y: auto;
|
|
60
51
|
|
|
61
52
|
thead,
|
|
62
53
|
tr {
|
|
@@ -69,6 +60,10 @@ const StyledSelectListTable = _styledComponents.default.table`
|
|
|
69
60
|
exports.StyledSelectListTable = StyledSelectListTable;
|
|
70
61
|
const StyledSelectListTableHeader = _styledComponents.default.thead`
|
|
71
62
|
border-bottom: 1px solid var(--colorsUtilityMajor050);
|
|
63
|
+
position: sticky;
|
|
64
|
+
top: 0;
|
|
65
|
+
left: 0;
|
|
66
|
+
z-index: 1;
|
|
72
67
|
|
|
73
68
|
tr {
|
|
74
69
|
width: ${({
|
|
@@ -105,9 +100,11 @@ const StyledSelectListTableHeader = _styledComponents.default.thead`
|
|
|
105
100
|
exports.StyledSelectListTableHeader = StyledSelectListTableHeader;
|
|
106
101
|
const StyledSelectListTableBody = _styledComponents.default.tbody`
|
|
107
102
|
display: block;
|
|
108
|
-
overflow-y: auto;
|
|
109
103
|
width: 100%;
|
|
110
104
|
table-layout: fixed;
|
|
111
|
-
|
|
105
|
+
width: 100%;
|
|
106
|
+
height: ${({
|
|
107
|
+
listHeight
|
|
108
|
+
}) => `${listHeight}px`};
|
|
112
109
|
`;
|
|
113
110
|
exports.StyledSelectListTableBody = StyledSelectListTableBody;
|
|
@@ -70,6 +70,8 @@ const SimpleSelect = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
70
70
|
listPlacement = "bottom",
|
|
71
71
|
flipEnabled = true,
|
|
72
72
|
inputRef,
|
|
73
|
+
enableVirtualScroll,
|
|
74
|
+
virtualScrollOverscan,
|
|
73
75
|
...props
|
|
74
76
|
}, ref) => {
|
|
75
77
|
const selectListId = (0, _react.useRef)((0, _guid.default)());
|
|
@@ -378,7 +380,9 @@ const SimpleSelect = /*#__PURE__*/_react.default.forwardRef(({
|
|
|
378
380
|
loaderDataRole: "simple-select-list-loader",
|
|
379
381
|
listPlacement: listPlacement,
|
|
380
382
|
flipEnabled: flipEnabled,
|
|
381
|
-
isOpen: isOpen
|
|
383
|
+
isOpen: isOpen,
|
|
384
|
+
enableVirtualScroll: enableVirtualScroll,
|
|
385
|
+
virtualScrollOverscan: virtualScrollOverscan
|
|
382
386
|
}, children);
|
|
383
387
|
|
|
384
388
|
return /*#__PURE__*/_react.default.createElement(_select.default, _extends({
|
|
@@ -459,7 +463,16 @@ SimpleSelect.propTypes = {
|
|
|
459
463
|
listPlacement: _propTypes.default.oneOf(["top", "bottom", "right", "left"]),
|
|
460
464
|
|
|
461
465
|
/** Use the opposite list placement if the set placement does not fit */
|
|
462
|
-
flipEnabled: _propTypes.default.bool
|
|
466
|
+
flipEnabled: _propTypes.default.bool,
|
|
467
|
+
|
|
468
|
+
/** Set this prop to enable a virtualised list of options. If it is not used then all options will be in the
|
|
469
|
+
* DOM at all times, which may cause performance problems on very large lists */
|
|
470
|
+
enableVirtualScroll: _propTypes.default.bool,
|
|
471
|
+
|
|
472
|
+
/** The number of options to render into the DOM at once, either side of the currently-visible ones.
|
|
473
|
+
* Higher values make for smoother scrolling but may impact performance.
|
|
474
|
+
* Only used if the `enableVirtualScroll` prop is set. */
|
|
475
|
+
virtualScrollOverscan: _propTypes.default.number
|
|
463
476
|
};
|
|
464
477
|
SimpleSelect.defaultProps = {
|
|
465
478
|
disablePortal: false,
|
|
@@ -44,6 +44,13 @@ export interface SimpleSelectProps
|
|
|
44
44
|
listPlacement?: Side;
|
|
45
45
|
/** Use the opposite list placement if the set placement does not fit */
|
|
46
46
|
flipEnabled?: boolean;
|
|
47
|
+
/** Set this prop to enable a virtualised list of options. If it is not used then all options will be in the
|
|
48
|
+
* DOM at all times, which may cause performance problems on very large lists */
|
|
49
|
+
enableVirtualScroll?: boolean;
|
|
50
|
+
/** The number of options to render into the DOM at once, either side of the currently-visible ones.
|
|
51
|
+
* Higher values make for smoother scrolling but may impact performance.
|
|
52
|
+
* Only used if the `enableVirtualScroll` prop is set. */
|
|
53
|
+
virtualScrollOverscan?: number;
|
|
47
54
|
}
|
|
48
55
|
|
|
49
56
|
declare function SimpleSelect(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "carbon-react",
|
|
3
|
-
"version": "114.
|
|
3
|
+
"version": "114.14.0",
|
|
4
4
|
"description": "A library of reusable React components for easily building user interfaces.",
|
|
5
5
|
"files": [
|
|
6
6
|
"lib",
|
|
@@ -166,6 +166,7 @@
|
|
|
166
166
|
"@floating-ui/react-dom": "^1.0.1",
|
|
167
167
|
"@octokit/rest": "^18.12.0",
|
|
168
168
|
"@styled-system/prop-types": "^5.1.5",
|
|
169
|
+
"@tanstack/react-virtual": "^3.0.0-beta.39",
|
|
169
170
|
"@types/styled-system": "^5.1.11",
|
|
170
171
|
"chalk": "^4.1.1",
|
|
171
172
|
"ci-info": "^3.3.2",
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export default function updateListScrollTop(indexOfCurrent, list, options) {
|
|
2
|
-
if (!list || !options[indexOfCurrent] || options[indexOfCurrent].current === null) {
|
|
3
|
-
list.scrollTop = 0;
|
|
4
|
-
return;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
let newPosition = 0;
|
|
8
|
-
const {
|
|
9
|
-
offsetHeight: listHeight
|
|
10
|
-
} = list;
|
|
11
|
-
const {
|
|
12
|
-
offsetTop: itemTop,
|
|
13
|
-
offsetHeight: currentItemHeight
|
|
14
|
-
} = options[indexOfCurrent].current;
|
|
15
|
-
|
|
16
|
-
if (itemTop + currentItemHeight > listHeight) {
|
|
17
|
-
newPosition = itemTop + currentItemHeight - listHeight;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
list.scrollTop = newPosition;
|
|
21
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = updateListScrollTop;
|
|
7
|
-
|
|
8
|
-
function updateListScrollTop(indexOfCurrent, list, options) {
|
|
9
|
-
if (!list || !options[indexOfCurrent] || options[indexOfCurrent].current === null) {
|
|
10
|
-
list.scrollTop = 0;
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
let newPosition = 0;
|
|
15
|
-
const {
|
|
16
|
-
offsetHeight: listHeight
|
|
17
|
-
} = list;
|
|
18
|
-
const {
|
|
19
|
-
offsetTop: itemTop,
|
|
20
|
-
offsetHeight: currentItemHeight
|
|
21
|
-
} = options[indexOfCurrent].current;
|
|
22
|
-
|
|
23
|
-
if (itemTop + currentItemHeight > listHeight) {
|
|
24
|
-
newPosition = itemTop + currentItemHeight - listHeight;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
list.scrollTop = newPosition;
|
|
28
|
-
}
|