@grafana/ui
Version:
Grafana Components Library
158 lines (153 loc) • 6.9 kB
JavaScript
;
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');
;
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