UNPKG

@grafana/ui

Version:
105 lines (100 loc) 4.43 kB
'use strict'; 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'); "use strict"; 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