@grafana/ui
Version:
Grafana Components Library
105 lines (100 loc) • 4.43 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var react = require('@floating-ui/react');
var React = require('react');
var i18n = require('@grafana/i18n');
var floating = require('../../utils/floating.cjs');
var measureText = require('../../utils/measureText.cjs');
var MessageRows = require('./MessageRows.cjs');
var getComboboxStyles = require('./getComboboxStyles.cjs');
;
const WIDTH_CALCULATION_LIMIT_ITEMS = 1e5;
const POPOVER_PADDING = 16;
const SCROLL_CONTAINER_PADDING = 8;
const ICON_WIDTH = 28;
const MESSAGE_ROW_PADDING = 32;
const useComboboxFloat = (items, isOpen) => {
var _a, _b;
const inputRef = React.useRef(null);
const floatingRef = React.useRef(null);
const scrollRef = React.useRef(null);
const [popoverMaxSize, setPopoverMaxSize] = React.useState({
width: 0,
height: 0
});
const scrollbarWidth = React.useMemo(() => getScrollbarWidth(), []);
const middleware = [
react.autoPlacement({
// see https://floating-ui.com/docs/autoplacement
allowedPlacements: ["bottom-start", "bottom-end", "top-start", "top-end"],
boundary: (_a = document.getElementById(floating.BOUNDARY_ELEMENT_ID)) != null ? _a : void 0,
crossAxis: true
}),
react.size({
apply({ availableWidth, availableHeight }) {
const preferredMaxWidth = availableWidth - POPOVER_PADDING;
const preferredMaxHeight = availableHeight - POPOVER_PADDING;
const width = Math.max(preferredMaxWidth, 0);
const height = Math.min(Math.max(preferredMaxHeight, getComboboxStyles.MENU_OPTION_HEIGHT * 6), getComboboxStyles.POPOVER_MAX_HEIGHT);
setPopoverMaxSize({ width, height });
}
})
];
const elements = { reference: inputRef.current, floating: floatingRef.current };
const { floatingStyles } = react.useFloating({
strategy: "fixed",
open: isOpen,
placement: "bottom-start",
middleware,
elements,
whileElementsMounted: react.autoUpdate
});
const longestItemWidth = React.useMemo(() => {
var _a2, _b2;
let longestLabel = "";
let longestLabelIndex = -1;
let longestDescription = "";
const itemsToLookAt = Math.min(items.length, WIDTH_CALCULATION_LIMIT_ITEMS);
for (let i = 0; i < itemsToLookAt; i++) {
const itemLabel = (_a2 = items[i].label) != null ? _a2 : items[i].value.toString();
if (itemLabel.length > longestLabel.length) {
longestLabel = itemLabel;
longestLabelIndex = i;
}
const itemDescription = (_b2 = items[i].description) != null ? _b2 : "";
if (itemDescription.length > longestDescription.length) {
longestDescription = itemDescription;
}
}
const labelWidth = measureText.measureText(longestLabel, getComboboxStyles.MENU_ITEM_FONT_SIZE, getComboboxStyles.MENU_ITEM_FONT_WEIGHT).width;
const descriptionWidth = longestDescription ? measureText.measureText(longestDescription, getComboboxStyles.MENU_ITEM_DESCRIPTION_FONT_SIZE).width : 0;
const iconSize = longestLabelIndex > -1 && items[longestLabelIndex].icon ? ICON_WIDTH : 0;
const textWidth = Math.max(labelWidth + iconSize, descriptionWidth);
const itemWidth = textWidth + SCROLL_CONTAINER_PADDING + getComboboxStyles.MENU_ITEM_PADDING * 2 + scrollbarWidth;
const noOptionsText = i18n.t(MessageRows.NO_OPTIONS_I18N_KEY, "No options found.");
const noOptionsWidth = measureText.measureText(noOptionsText, getComboboxStyles.MENU_ITEM_FONT_SIZE).width + MESSAGE_ROW_PADDING + scrollbarWidth;
return Math.max(itemWidth, noOptionsWidth);
}, [items, scrollbarWidth]);
const floatStyles = {
...floatingStyles,
width: longestItemWidth,
maxWidth: popoverMaxSize.width,
minWidth: (_b = inputRef.current) == null ? void 0 : _b.offsetWidth,
maxHeight: popoverMaxSize.height
};
return { inputRef, floatingRef, scrollRef, floatStyles };
};
function getScrollbarWidth() {
var _a;
const outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.overflow = "scroll";
document.body.appendChild(outer);
const inner = document.createElement("div");
outer.appendChild(inner);
const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;
(_a = outer.parentNode) == null ? void 0 : _a.removeChild(outer);
return scrollbarWidth;
}
exports.useComboboxFloat = useComboboxFloat;
//# sourceMappingURL=useComboboxFloat.cjs.map