UNPKG

@grafana/ui

Version:
158 lines (153 loc) • 6.9 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var jsxRuntime = require('react/jsx-runtime'); var css = require('@emotion/css'); var reactVirtual = require('@tanstack/react-virtual'); var React = require('react'); var ThemeContext = require('../../themes/ThemeContext.cjs'); var Checkbox = require('../Forms/Checkbox.cjs'); var Icon = require('../Icon/Icon.cjs'); var Stack = require('../Layout/Stack/Stack.cjs'); var ScrollContainer = require('../ScrollContainer/ScrollContainer.cjs'); var MessageRows = require('./MessageRows.cjs'); var getComboboxStyles = require('./getComboboxStyles.cjs'); var types = require('./types.cjs'); var utils = require('./utils.cjs'); "use strict"; const VIRTUAL_OVERSCAN_ITEMS = 4; const ComboboxList = ({ options, highlightedIndex, selectedItems = [], scrollRef, getItemProps, enableAllOption, isMultiSelect = false, error = false, loading = false, noOptionsMessage }) => { const styles = ThemeContext.useStyles2(getComboboxStyles.getComboboxStyles); const estimateSize = React.useCallback( (index) => { const firstGroupItem = utils.isNewGroup(options[index], index > 0 ? options[index - 1] : void 0); const hasDescription = "description" in options[index]; const hasGroup = "group" in options[index]; let itemHeight = getComboboxStyles.MENU_OPTION_HEIGHT; if (hasDescription) { itemHeight = getComboboxStyles.MENU_OPTION_HEIGHT_DESCRIPTION; } if (firstGroupItem && hasGroup) { itemHeight += getComboboxStyles.MENU_OPTION_HEIGHT; } return itemHeight; }, [options] ); const rowVirtualizer = reactVirtual.useVirtualizer({ count: options.length, getScrollElement: () => scrollRef.current, estimateSize, getItemKey: (index) => { var _a, _b; return (_b = (_a = options[index]) == null ? void 0 : _a.value) != null ? _b : index; }, overscan: VIRTUAL_OVERSCAN_ITEMS }); const isOptionSelected = React.useCallback( (item) => selectedItems.some((opt) => opt.value === item.value), [selectedItems] ); const allItemsSelected = enableAllOption && options.length > 1 && selectedItems.length === options.length - 1; return /* @__PURE__ */ jsxRuntime.jsxs(ScrollContainer.ScrollContainer, { showScrollIndicators: true, maxHeight: "inherit", ref: scrollRef, padding: 0.5, children: [ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: rowVirtualizer.getTotalSize() }, className: styles.menuUlContainer, children: rowVirtualizer.getVirtualItems().map((virtualRow, index, allVirtualRows) => { var _a; const item = options[virtualRow.index]; const startingNewGroup = utils.isNewGroup(item, options[virtualRow.index - 1]); const groupHeaderIndex = allVirtualRows.find((row) => { const rowItem = options[row.index]; return rowItem.group === item.group; }); const groupHeaderItem = groupHeaderIndex && options[groupHeaderIndex.index]; const itemId = `combobox-option-${item.value}`; const groupHeaderId = groupHeaderItem ? `combobox-option-group-${groupHeaderItem.value}` : void 0; return ( // Wrapping div should have no styling other than virtual list positioning. // It's children (header and option) should appear as flat list items. /* @__PURE__ */ jsxRuntime.jsxs( "div", { className: styles.listItem, style: { height: virtualRow.size, transform: `translateY(${virtualRow.start}px)` }, children: [ startingNewGroup && /* @__PURE__ */ jsxRuntime.jsx( "div", { role: "presentation", "data-testid": "combobox-option-group", id: groupHeaderId, className: css.cx( styles.optionGroupHeader, item.group && styles.optionGroupLabel, virtualRow.index === 0 && styles.optionFirstGroupHeader ), children: item.group } ), /* @__PURE__ */ jsxRuntime.jsxs( "div", { className: css.cx( styles.option, !isMultiSelect && isOptionSelected(item) && styles.optionSelected, highlightedIndex === virtualRow.index && !item.infoOption && styles.optionFocused, item.infoOption && styles.optionInfo ), ...getItemProps({ item, index: virtualRow.index, id: itemId, "aria-describedby": groupHeaderId }), children: [ isMultiSelect && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.optionAccessory, children: !item.infoOption && /* @__PURE__ */ jsxRuntime.jsx( Checkbox.Checkbox, { value: allItemsSelected || isOptionSelected(item), indeterminate: item.value === types.ALL_OPTION_VALUE && selectedItems.length > 0 && !allItemsSelected, "aria-labelledby": itemId, onClick: (e) => { e.stopPropagation(); }, "data-testid": `${itemId}-checkbox` }, itemId ) }), /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.optionBody, children: [ /* @__PURE__ */ jsxRuntime.jsxs(Stack.Stack, { direction: "row", alignItems: "center", children: [ item.icon && /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { name: item.icon }), /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.optionLabel, children: (_a = item.label) != null ? _a : item.value }) ] }), item.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.optionDescription, children: item.description }) ] }) ] } ) ] }, item.value ) ); }) }), /* @__PURE__ */ jsxRuntime.jsxs("div", { "aria-live": "polite", children: [ error && /* @__PURE__ */ jsxRuntime.jsx(MessageRows.AsyncError, {}), !loading && options.length === 0 && !error && /* @__PURE__ */ jsxRuntime.jsx(MessageRows.NotFoundError, { message: noOptionsMessage }), loading && options.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(MessageRows.LoadingOptions, {}) ] }) ] }); }; exports.ComboboxList = ComboboxList; //# sourceMappingURL=ComboboxList.cjs.map