UNPKG

@grafana/ui

Version:
249 lines (242 loc) • 8.76 kB
'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