@grafana/ui
Version:
Grafana Components Library
80 lines (77 loc) • 3.1 kB
JavaScript
import { autoPlacement, size, useFloating, autoUpdate } from '@floating-ui/react';
import { useRef, useState, useMemo } from 'react';
import { measureText } from '../../utils/measureText.mjs';
import { MENU_ITEM_FONT_WEIGHT, MENU_ITEM_FONT_SIZE, MENU_ITEM_PADDING, MENU_OPTION_HEIGHT, POPOVER_MAX_HEIGHT } from './getComboboxStyles.mjs';
const WIDTH_CALCULATION_LIMIT_ITEMS = 1e5;
const POPOVER_PADDING = 16;
const SCROLL_CONTAINER_PADDING = 8;
const useComboboxFloat = (items, isOpen) => {
var _a;
const inputRef = useRef(null);
const floatingRef = useRef(null);
const scrollRef = useRef(null);
const [popoverMaxSize, setPopoverMaxSize] = useState({
width: 0,
height: 0
});
const scrollbarWidth = useMemo(() => getScrollbarWidth(), []);
const middleware = [
autoPlacement({
// see https://floating-ui.com/docs/autoplacement
allowedPlacements: ["bottom-start", "bottom-end", "top-start", "top-end"],
boundary: document.body,
crossAxis: true
}),
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, MENU_OPTION_HEIGHT * 6), POPOVER_MAX_HEIGHT);
setPopoverMaxSize({ width, height });
}
})
];
const elements = { reference: inputRef.current, floating: floatingRef.current };
const { floatingStyles } = useFloating({
strategy: "fixed",
open: isOpen,
placement: "bottom-start",
middleware,
elements,
whileElementsMounted: autoUpdate
});
const longestItemWidth = useMemo(() => {
var _a2;
let longestItem = "";
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();
longestItem = itemLabel.length > longestItem.length ? itemLabel : longestItem;
}
const size2 = measureText(longestItem, MENU_ITEM_FONT_SIZE, MENU_ITEM_FONT_WEIGHT).width;
return size2 + SCROLL_CONTAINER_PADDING + MENU_ITEM_PADDING * 2 + scrollbarWidth;
}, [items, scrollbarWidth]);
const floatStyles = {
...floatingStyles,
width: longestItemWidth,
maxWidth: popoverMaxSize.width,
minWidth: (_a = inputRef.current) == null ? void 0 : _a.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;
}
export { useComboboxFloat };
//# sourceMappingURL=useComboboxFloat.mjs.map