@grafana/ui
Version:
Grafana Components Library
249 lines (242 loc) • 8.76 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var jsxRuntime = require('react/jsx-runtime');
var css = require('@emotion/css');
var React = require('react');
var reactWindow = require('react-window');
var data = require('@grafana/data');
var e2eSelectors = require('@grafana/e2e-selectors');
var i18n = require('@grafana/i18n');
var ThemeContext = require('../../themes/ThemeContext.cjs');
var Button = require('../Button/Button.cjs');
var Icon = require('../Icon/Icon.cjs');
var ScrollContainer = require('../ScrollContainer/ScrollContainer.cjs');
var getSelectStyles = require('./getSelectStyles.cjs');
var types = require('./types.cjs');
function _interopNamespaceCompat(e) {
if (e && typeof e === 'object' && 'default' in e) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespaceCompat(React);
"use strict";
const SelectMenu = ({
children,
maxHeight,
innerRef,
innerProps,
selectProps
}) => {
var _a;
const theme = ThemeContext.useTheme2();
const styles = getSelectStyles.getSelectStyles(theme);
const { toggleAllOptions, components } = selectProps;
const optionsElement = (_a = components == null ? void 0 : components.Option) != null ? _a : SelectMenuOptions;
return /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
...innerProps,
"data-testid": e2eSelectors.selectors.components.Select.menu,
className: styles.menu,
style: { maxHeight },
"aria-label": i18n.t("grafana-ui.select.menu-label", "Select options menu"),
children: /* @__PURE__ */ jsxRuntime.jsxs(ScrollContainer.ScrollContainer, { ref: innerRef, maxHeight: "inherit", overflowX: "hidden", showScrollIndicators: true, padding: 0.5, children: [
toggleAllOptions && /* @__PURE__ */ jsxRuntime.jsx(
ToggleAllOption,
{
state: toggleAllOptions.state,
optionComponent: optionsElement,
selectedCount: toggleAllOptions.selectedCount,
onClick: toggleAllOptions.selectAllClicked
}
),
children
] })
}
);
};
SelectMenu.displayName = "SelectMenu";
const VIRTUAL_LIST_ITEM_HEIGHT = 37;
const VIRTUAL_LIST_WIDTH_ESTIMATE_MULTIPLIER = 8;
const VIRTUAL_LIST_PADDING = 8;
const VIRTUAL_LIST_WIDTH_EXTRA = 58;
const VirtualizedSelectMenu = ({
children,
maxHeight,
innerRef: scrollRef,
options,
selectProps,
focusedOption
}) => {
var _a;
const theme = ThemeContext.useTheme2();
const styles = getSelectStyles.getSelectStyles(theme);
const listRef = React.useRef(null);
const { toggleAllOptions, components } = selectProps;
const optionComponent = (_a = components == null ? void 0 : components.Option) != null ? _a : SelectMenuOptions;
const flattenedOptions = React.useMemo(
() => options.flatMap((option) => option.options ? [option, ...option.options] : [option]),
[options]
);
const focusedIndex = flattenedOptions.findIndex(
(option) => option.value === (focusedOption == null ? void 0 : focusedOption.value)
);
React.useLayoutEffect(() => {
var _a2;
(_a2 = listRef.current) == null ? void 0 : _a2.scrollToItem(focusedIndex);
}, [focusedIndex]);
if (!Array.isArray(children)) {
return null;
}
const flattenedChildren = children.flatMap((child, index) => {
if (hasArrayChildren(child)) {
const childWithoutChildren = React__namespace.cloneElement(child, {
children: null
});
return [
childWithoutChildren,
...child.props.children.slice(0, -1),
// add a bottom divider to the last item in the category
React__namespace.cloneElement(child.props.children.at(-1), {
innerProps: {
...child.props.children.at(-1).props.innerProps,
style: {
borderBottom: `1px solid ${theme.colors.border.weak}`,
height: VIRTUAL_LIST_ITEM_HEIGHT
}
}
})
];
}
return [child];
});
if (toggleAllOptions) {
flattenedChildren.unshift(
/* @__PURE__ */ jsxRuntime.jsx(
ToggleAllOption,
{
optionComponent,
state: toggleAllOptions.state,
selectedCount: toggleAllOptions.selectedCount,
onClick: toggleAllOptions.selectAllClicked
}
)
);
}
let longestOption = flattenedOptions.reduce((max, option) => {
var _a2, _b;
const length = (_b = (_a2 = option.label) == null ? void 0 : _a2.length) != null ? _b : 0;
return Math.max(max, length);
}, 0);
if (toggleAllOptions && longestOption < 12) {
longestOption = 12;
}
const widthEstimate = longestOption * VIRTUAL_LIST_WIDTH_ESTIMATE_MULTIPLIER + VIRTUAL_LIST_PADDING * 2 + VIRTUAL_LIST_WIDTH_EXTRA;
const heightEstimate = Math.min(flattenedChildren.length * VIRTUAL_LIST_ITEM_HEIGHT, maxHeight);
return /* @__PURE__ */ jsxRuntime.jsx(
reactWindow.FixedSizeList,
{
outerRef: scrollRef,
ref: listRef,
className: styles.menu,
height: heightEstimate,
width: widthEstimate,
"aria-label": i18n.t("grafana-ui.select.menu-label", "Select options menu"),
itemCount: flattenedChildren.length,
itemSize: VIRTUAL_LIST_ITEM_HEIGHT,
children: ({ index, style }) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...style, overflow: "hidden" }, children: flattenedChildren[index] })
}
);
};
const hasArrayChildren = (child) => {
return React__namespace.isValidElement(child) && Array.isArray(child.props.children);
};
VirtualizedSelectMenu.displayName = "VirtualizedSelectMenu";
const ToggleAllOption = ({
state,
onClick,
selectedCount,
optionComponent
}) => {
const theme = ThemeContext.useTheme2();
const styles = getSelectStyles.getSelectStyles(theme);
return /* @__PURE__ */ jsxRuntime.jsx(
"button",
{
"data-testid": e2eSelectors.selectors.components.Select.toggleAllOptions,
className: css.css(Button.clearButtonStyles(theme), styles.toggleAllButton, {
height: VIRTUAL_LIST_ITEM_HEIGHT
}),
onClick,
children: optionComponent({
isDisabled: false,
isSelected: state === types.ToggleAllState.allSelected,
isFocused: false,
data: {},
indeterminate: state === types.ToggleAllState.indeterminate,
innerRef: () => {
},
innerProps: {},
children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
/* @__PURE__ */ jsxRuntime.jsx(i18n.Trans, { i18nKey: "select.select-menu.selected-count", children: "Selected" }),
` (${selectedCount != null ? selectedCount : 0})`
] })
})
}
);
};
const SelectMenuOptions = ({
children,
data: data$1,
innerProps,
innerRef,
isFocused,
isSelected,
renderOptionLabel
}) => {
const theme = ThemeContext.useTheme2();
const styles = getSelectStyles.getSelectStyles(theme);
const icon = data$1.icon ? data.toIconName(data$1.icon) : void 0;
const { onMouseMove, onMouseOver, ...rest } = innerProps;
return /* @__PURE__ */ jsxRuntime.jsxs(
"div",
{
ref: innerRef,
className: css.cx(
styles.option,
isFocused && styles.optionFocused,
isSelected && styles.optionSelected,
data$1.isDisabled && styles.optionDisabled
),
...rest,
"data-testid": e2eSelectors.selectors.components.Select.option,
title: data$1.title,
children: [
icon && /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { name: icon, className: styles.optionIcon }),
data$1.imgUrl && /* @__PURE__ */ jsxRuntime.jsx("img", { className: styles.optionImage, src: data$1.imgUrl, alt: data$1.label || String(data$1.value) }),
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.optionBody, children: [
/* @__PURE__ */ jsxRuntime.jsx("span", { children: renderOptionLabel ? renderOptionLabel(data$1) : children }),
data$1.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.optionDescription, children: data$1.description }),
data$1.component && /* @__PURE__ */ jsxRuntime.jsx(data$1.component, {})
] })
]
}
);
};
SelectMenuOptions.displayName = "SelectMenuOptions";
exports.SelectMenu = SelectMenu;
exports.SelectMenuOptions = SelectMenuOptions;
exports.VirtualizedSelectMenu = VirtualizedSelectMenu;
//# sourceMappingURL=SelectMenu.cjs.map