{"version":3,"file":"useComboboxFloat.mjs","sources":["../../../../src/components/Combobox/useComboboxFloat.ts"],"sourcesContent":["import { autoUpdate, autoPlacement, size, useFloating } from '@floating-ui/react';\nimport { useMemo, useRef, useState } from 'react';\n\nimport { t } from '@grafana/i18n';\n\nimport { BOUNDARY_ELEMENT_ID } from '../../utils/floating';\nimport { measureText } from '../../utils/measureText';\n\nimport { NO_OPTIONS_I18N_KEY } from './MessageRows';\nimport {\n  MENU_ITEM_DESCRIPTION_FONT_SIZE,\n  MENU_ITEM_FONT_SIZE,\n  MENU_ITEM_FONT_WEIGHT,\n  MENU_ITEM_PADDING,\n  MENU_OPTION_HEIGHT,\n  POPOVER_MAX_HEIGHT,\n} from './getComboboxStyles';\nimport { type ComboboxOption } from './types';\n\n// Only consider the first n items when calculating the width of the popover.\nconst WIDTH_CALCULATION_LIMIT_ITEMS = 100_000;\n\n// Clearance around the popover to prevent it from being too close to the edge of the viewport\nconst POPOVER_PADDING = 16;\n\nconst SCROLL_CONTAINER_PADDING = 8;\n\n// 16px svg width + 12px Icon padding\nconst ICON_WIDTH = 28;\n\n// MessageRow uses Box padding={2} = theme.spacing(2) = 16px each side\nconst MESSAGE_ROW_PADDING = 32;\n\nexport const useComboboxFloat = (items: Array<ComboboxOption<string | number>>, isOpen: boolean) => {\n  const inputRef = useRef<HTMLInputElement>(null);\n  const floatingRef = useRef<HTMLDivElement>(null);\n  const scrollRef = useRef<HTMLDivElement>(null);\n  const [popoverMaxSize, setPopoverMaxSize] = useState<{ width: number; height: number }>({\n    width: 0,\n    height: 0,\n  }); // set initial values to prevent infinite size, briefly removing the list virtualization\n\n  const scrollbarWidth = useMemo(() => getScrollbarWidth(), []);\n\n  // the order of middleware is important!\n  const middleware = [\n    autoPlacement({\n      // see https://floating-ui.com/docs/autoplacement\n      allowedPlacements: ['bottom-start', 'bottom-end', 'top-start', 'top-end'],\n      boundary: document.getElementById(BOUNDARY_ELEMENT_ID) ?? undefined,\n      crossAxis: true,\n    }),\n    size({\n      apply({ availableWidth, availableHeight }) {\n        const preferredMaxWidth = availableWidth - POPOVER_PADDING;\n        const preferredMaxHeight = availableHeight - POPOVER_PADDING;\n\n        const width = Math.max(preferredMaxWidth, 0);\n        const height = Math.min(Math.max(preferredMaxHeight, MENU_OPTION_HEIGHT * 6), POPOVER_MAX_HEIGHT);\n\n        setPopoverMaxSize({ width, height });\n      },\n    }),\n  ];\n  const elements = { reference: inputRef.current, floating: floatingRef.current };\n  const { floatingStyles } = useFloating({\n    strategy: 'fixed',\n    open: isOpen,\n    placement: 'bottom-start',\n    middleware,\n    elements,\n    whileElementsMounted: autoUpdate,\n  });\n\n  const longestItemWidth = useMemo(() => {\n    let longestLabel = '';\n    let longestLabelIndex = -1;\n    let longestDescription = '';\n    // @todo sort by string length DESC\n    const itemsToLookAt = Math.min(items.length, WIDTH_CALCULATION_LIMIT_ITEMS);\n\n    for (let i = 0; i < itemsToLookAt; i++) {\n      const itemLabel = items[i].label ?? items[i].value.toString();\n      if (itemLabel.length > longestLabel.length) {\n        longestLabel = itemLabel;\n        longestLabelIndex = i;\n      }\n      const itemDescription = items[i].description ?? '';\n      if (itemDescription.length > longestDescription.length) {\n        longestDescription = itemDescription;\n      }\n    }\n\n    const labelWidth = measureText(longestLabel, MENU_ITEM_FONT_SIZE, MENU_ITEM_FONT_WEIGHT).width;\n    const descriptionWidth = longestDescription\n      ? measureText(longestDescription, MENU_ITEM_DESCRIPTION_FONT_SIZE).width\n      : 0;\n    const iconSize = longestLabelIndex > -1 && items[longestLabelIndex].icon ? ICON_WIDTH : 0;\n\n    const textWidth = Math.max(labelWidth + iconSize, descriptionWidth);\n    const itemWidth = textWidth + SCROLL_CONTAINER_PADDING + MENU_ITEM_PADDING * 2 + scrollbarWidth;\n\n    const noOptionsText = t(NO_OPTIONS_I18N_KEY, 'No options found.');\n    const noOptionsWidth = measureText(noOptionsText, MENU_ITEM_FONT_SIZE).width + MESSAGE_ROW_PADDING + scrollbarWidth;\n\n    return Math.max(itemWidth, noOptionsWidth);\n  }, [items, scrollbarWidth]);\n\n  const floatStyles = {\n    ...floatingStyles,\n    width: longestItemWidth,\n    maxWidth: popoverMaxSize.width,\n    minWidth: inputRef.current?.offsetWidth,\n\n    maxHeight: popoverMaxSize.height,\n  };\n\n  return { inputRef, floatingRef, scrollRef, floatStyles };\n};\n\n// Creates a temporary div with a scrolling inner div to calculate the width of the scrollbar\nfunction getScrollbarWidth(): number {\n  const outer = document.createElement('div');\n  outer.style.visibility = 'hidden';\n  outer.style.overflow = 'scroll';\n  document.body.appendChild(outer);\n\n  const inner = document.createElement('div');\n  outer.appendChild(inner);\n\n  const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;\n\n  outer.parentNode?.removeChild(outer);\n\n  return scrollbarWidth;\n}\n"],"names":["_a","_b"],"mappings":"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"}