{"version":3,"file":"useMenuVirtualList.mjs","names":[],"sources":["../../../src/base-ui/virtual/useMenuVirtualList.tsx"],"sourcesContent":["'use client';\n\nimport type React from 'react';\nimport {\n  Children,\n  cloneElement,\n  isValidElement,\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\nimport type { VirtualizerHandle } from 'virtua';\n\nimport type { VirtualListProps } from './type';\nimport { usePointerScrollGuard } from './VirtualScrollArea';\n\nconst LIST_ITEM_SELECTOR = '[role^=\"menuitem\"], [role=\"option\"]';\nconst INDEX_ATTRIBUTE = 'data-virtual-index';\nconst MAX_JUMP_FRAMES = 60;\n\ninterface VirtualChildProps {\n  'aria-disabled'?: boolean | 'true' | 'false';\n  'aria-label'?: string;\n  'children'?: React.ReactNode;\n  'disabled'?: boolean;\n  'label'?: string;\n  'onFocus'?: (event: React.FocusEvent<HTMLElement>) => void;\n}\n\nexport interface ListEntry {\n  disabled: boolean;\n  label: string;\n}\n\nexport interface UseMenuVirtualListParams extends Pick<\n  VirtualListProps,\n  'getItemLabel' | 'keepMounted'\n> {\n  children: React.ReactNode;\n  enabled: boolean | undefined;\n  /**\n   * Idle time after which the typeahead query resets; matches Base UI's per-component value.\n   * @default 500\n   */\n  typeaheadResetMs?: number;\n}\n\nexport const flattenText = (node: React.ReactNode): string => {\n  if (node == null || typeof node === 'boolean') return '';\n  if (typeof node === 'string' || typeof node === 'number') return String(node);\n  if (Array.isArray(node)) return node.map(flattenText).join('');\n  if (isValidElement<{ children?: React.ReactNode }>(node)) return flattenText(node.props.children);\n  return '';\n};\n\nconst readEntry = (\n  child: React.ReactNode,\n  index: number,\n  getItemLabel: UseMenuVirtualListParams['getItemLabel'],\n): ListEntry => {\n  if (!isValidElement<VirtualChildProps>(child)) return { disabled: true, label: '' };\n  const props = child.props;\n  const label =\n    getItemLabel?.(child, index) ??\n    props.label ??\n    props['aria-label'] ??\n    flattenText(props.children);\n  const disabled =\n    Boolean(props.disabled) || props['aria-disabled'] === true || props['aria-disabled'] === 'true';\n  return { disabled, label: label.trim() };\n};\n\nexport const findMatch = (entries: ListEntry[], query: string, startIndex: number) => {\n  if (entries.length === 0) return -1;\n  const lowerQuery = query.toLowerCase();\n  const start = ((startIndex % entries.length) + entries.length) % entries.length;\n  for (let offset = 0; offset < entries.length; offset += 1) {\n    const index = (start + offset) % entries.length;\n    const entry = entries[index];\n    if (!entry.disabled && entry.label.toLowerCase().startsWith(lowerQuery)) return index;\n  }\n  return -1;\n};\n\nexport const findEdge = (entries: ListEntry[], fromEnd: boolean) => {\n  if (fromEnd) {\n    for (let index = entries.length - 1; index >= 0; index -= 1) {\n      if (!entries[index].disabled) return index;\n    }\n    return -1;\n  }\n  return entries.findIndex((entry) => !entry.disabled);\n};\n\nexport function useMenuVirtualList({\n  children,\n  enabled,\n  getItemLabel,\n  keepMounted,\n  typeaheadResetMs = 500,\n}: UseMenuVirtualListParams) {\n  const viewportRef = useRef<HTMLDivElement | null>(null);\n  const virtualizerRef = useRef<VirtualizerHandle | null>(null);\n  const focusedItemRef = useRef<HTMLElement | null>(null);\n  const activeIndexRef = useRef<number | null>(null);\n  const [activeIndex, setActiveIndex] = useState<number | null>(null);\n  // A Home/End/typeahead target stays mounted until focus actually lands on it, so the\n  // focusin resync (which re-sets the active index to the still-focused old row) can't unmount\n  // it mid-scroll on a large jump.\n  const jumpTargetRef = useRef<number | null>(null);\n  const [jumpTarget, setJumpTarget] = useState<number | null>(null);\n  const { pointerScrollRef, scrollGuardProps } = usePointerScrollGuard();\n\n  const entries = useMemo(\n    () =>\n      enabled\n        ? (Children.map(children, (child, index) => readEntry(child, index, getItemLabel)) ?? [])\n        : [],\n    [children, enabled, getItemLabel],\n  );\n\n  // Base UI scrolls the focused item into view right after focusing it; while the pointer is\n  // scrolling that would yank the list back, so the item's scrollIntoView checks the guard.\n  const guardScrollIntoView = useCallback(\n    (item: HTMLElement) => {\n      if (Object.hasOwn(item, 'scrollIntoView')) return;\n      item.scrollIntoView = (...args) => {\n        if (!pointerScrollRef.current) HTMLElement.prototype.scrollIntoView.call(item, ...args);\n      };\n    },\n    [pointerScrollRef],\n  );\n\n  // Keeps focus inside the popup on the viewport, so a row unmounting under the old focus never\n  // drops focus to the body mid-jump — Base UI Menu closes on focus-out.\n  const parkFocus = useCallback(() => {\n    const viewport = viewportRef.current;\n    if (viewport && !viewport.contains(document.activeElement)) {\n      viewport.focus({ preventScroll: true });\n    }\n  }, []);\n\n  const settleScrollRef = useRef(-1);\n  // Focus the jump target only once the scroll has settled on it (its row is mounted and the\n  // offset stopped changing), so we never focus a row that's about to unmount and orphan focus.\n  const focusJumpTarget = useCallback(() => {\n    const index = jumpTargetRef.current;\n    const viewport = viewportRef.current;\n    if (index === null || !viewport) return false;\n    parkFocus();\n    const scrollTop = viewport.scrollTop;\n    const settled = scrollTop === settleScrollRef.current;\n    settleScrollRef.current = scrollTop;\n    if (!settled) return false;\n    const child = viewport.querySelector<HTMLElement>(`[${INDEX_ATTRIBUTE}=\"${index}\"]`);\n    const target =\n      child &&\n      (child.matches(LIST_ITEM_SELECTOR)\n        ? child\n        : child.querySelector<HTMLElement>(LIST_ITEM_SELECTOR));\n    if (!target) return false;\n    guardScrollIntoView(target);\n    focusedItemRef.current = target;\n    target.focus({ preventScroll: true });\n    return true;\n  }, [guardScrollIntoView, parkFocus]);\n\n  // The virtualizer shifts its window in response to keyboard nav and jumps, so react to every\n  // DOM change: finish a pending jump the moment its target mounts, otherwise keep Base UI's\n  // highlight index in step by re-firing focusin on the still-focused row (or, if it was\n  // unmounted, park focus on the viewport so the popup keydown handlers stay reachable).\n  useEffect(() => {\n    const viewport = viewportRef.current;\n    if (!enabled || !viewport) return;\n    const observer = new MutationObserver(() => {\n      if (jumpTargetRef.current !== null) {\n        focusJumpTarget();\n        return;\n      }\n      const focusedItem = focusedItemRef.current;\n      const active = document.activeElement;\n      if (focusedItem && !focusedItem.isConnected && active === document.body) {\n        focusedItemRef.current = null;\n        viewport.focus({ preventScroll: true });\n        return;\n      }\n      if (focusedItem && active === focusedItem) {\n        focusedItem.dispatchEvent(new FocusEvent('focusin', { bubbles: true }));\n      }\n    });\n    observer.observe(viewport, { childList: true, subtree: true });\n    return () => observer.disconnect();\n  }, [enabled, focusJumpTarget]);\n\n  const jumpFrameRef = useRef<number | null>(null);\n  useEffect(() => {\n    return () => {\n      if (jumpFrameRef.current !== null) cancelAnimationFrame(jumpFrameRef.current);\n    };\n  }, []);\n\n  const jumpTo = useCallback(\n    (index: number) => {\n      activeIndexRef.current = index;\n      jumpTargetRef.current = index;\n      setActiveIndex(index);\n      setJumpTarget(index);\n      // Park focus on the viewport (inside the popup) before scrolling, so the row being\n      // unmounted underneath the old focus never drops focus to the body — which would trip\n      // Base UI Menu's focus-out close mid-jump.\n      viewportRef.current?.focus({ preventScroll: true });\n      settleScrollRef.current = -1;\n      virtualizerRef.current?.scrollToIndex(index, { align: 'nearest' });\n      // The MutationObserver finishes the jump on mount; kick it in case the target is already\n      // mounted (a short jump) and produces no mutation.\n      if (jumpFrameRef.current !== null) cancelAnimationFrame(jumpFrameRef.current);\n      let frames = 0;\n      const kick = () => {\n        jumpFrameRef.current = null;\n        focusJumpTarget();\n        frames += 1;\n        // Loop until the real focus event lands (which clears `jumpTargetRef` in onFocus), so a\n        // mid-scroll remount that orphans focus is recovered on the next frame; cap so a target\n        // that never mounts can't spin forever.\n        if (jumpTargetRef.current !== null && frames < MAX_JUMP_FRAMES) {\n          jumpFrameRef.current = requestAnimationFrame(kick);\n        } else if (jumpTargetRef.current !== null) {\n          jumpTargetRef.current = null;\n          setJumpTarget(null);\n        }\n      };\n      jumpFrameRef.current = requestAnimationFrame(kick);\n    },\n    [focusJumpTarget],\n  );\n\n  const queryRef = useRef('');\n  const lastMatchRef = useRef<number | null>(null);\n  const resetTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const resetQuery = useCallback(() => {\n    queryRef.current = '';\n    if (resetTimeoutRef.current) clearTimeout(resetTimeoutRef.current);\n    resetTimeoutRef.current = null;\n  }, []);\n\n  useEffect(() => {\n    return () => {\n      if (resetTimeoutRef.current) clearTimeout(resetTimeoutRef.current);\n    };\n  }, []);\n\n  // Runs in the capture phase so Base UI's own Home/End and typeahead, which only see the\n  // mounted rows, never get the event. Mirrors `useTypeahead`: printable keys accumulate for\n  // `typeaheadResetMs`, a lone space activates while a space mid-query keeps typing, rapid\n  // repeats of one letter cycle through matches, and the search starts after the focused row\n  // and wraps.\n  const handleKeyDownCapture = useCallback(\n    (event: React.KeyboardEvent<HTMLElement>) => {\n      if (!enabled || entries.length === 0) return;\n      if (event.target instanceof HTMLElement && event.target.matches('input, textarea')) return;\n\n      if (event.key === 'Home' || event.key === 'End') {\n        const fromEnd = event.key === 'End';\n        const index = findEdge(entries, fromEnd);\n        if (index === -1) return;\n        event.preventDefault();\n        event.stopPropagation();\n        resetQuery();\n        jumpTo(index);\n        return;\n      }\n\n      if (event.key.length !== 1 || event.ctrlKey || event.metaKey || event.altKey) return;\n      if (event.key === ' ' && queryRef.current === '') return;\n      event.preventDefault();\n      event.stopPropagation();\n\n      const isNewSession = queryRef.current === '';\n      const allowRapidRepeat = entries.every(\n        (entry) =>\n          entry.disabled || entry.label[0]?.toLowerCase() !== entry.label[1]?.toLowerCase(),\n      );\n      if (allowRapidRepeat && queryRef.current === event.key) {\n        queryRef.current = '';\n      }\n      queryRef.current += event.key;\n      if (resetTimeoutRef.current) clearTimeout(resetTimeoutRef.current);\n      resetTimeoutRef.current = setTimeout(resetQuery, typeaheadResetMs);\n\n      const previous =\n        isNewSession || queryRef.current.length === 1\n          ? (activeIndexRef.current ?? lastMatchRef.current ?? -1)\n          : (lastMatchRef.current ?? activeIndexRef.current ?? -1);\n      const startIndex = queryRef.current.length === 1 ? previous + 1 : previous;\n      const index = findMatch(entries, queryRef.current, startIndex);\n      if (index !== -1) {\n        lastMatchRef.current = index;\n        jumpTo(index);\n      } else if (event.key !== ' ') {\n        resetQuery();\n      }\n    },\n    [enabled, entries, jumpTo, resetQuery, typeaheadResetMs],\n  );\n\n  const virtualChildren = useMemo(() => {\n    if (!enabled) return children;\n    return Children.map(children, (child, index) => {\n      if (!isValidElement<VirtualChildProps>(child)) return child;\n      const { onFocus } = child.props;\n      const extraProps: Record<string, unknown> = {\n        [INDEX_ATTRIBUTE]: index,\n        onFocus: (event: React.FocusEvent<HTMLElement>) => {\n          onFocus?.(event);\n          const item = (event.target as HTMLElement).closest<HTMLElement>(LIST_ITEM_SELECTOR);\n          if (item && event.currentTarget.contains(item)) {\n            focusedItemRef.current = item;\n            guardScrollIntoView(item);\n          }\n          activeIndexRef.current = index;\n          setActiveIndex(index);\n          if (jumpTargetRef.current === index) {\n            jumpTargetRef.current = null;\n            setJumpTarget(null);\n          }\n        },\n      };\n      return cloneElement(child, extraProps);\n    });\n  }, [children, enabled, guardScrollIntoView]);\n\n  const keepMountedIndices = useMemo(() => {\n    if (!enabled) return undefined;\n    const count = Children.count(children);\n    const indices = new Set(keepMounted);\n    if (activeIndex !== null) indices.add(activeIndex);\n    if (jumpTarget !== null) indices.add(jumpTarget);\n    const inRange = [...indices].filter((index) => index >= 0 && index < count);\n    return inRange.length ? inRange : undefined;\n  }, [activeIndex, children, enabled, jumpTarget, keepMounted]);\n\n  // While a jump is in flight, a row unmounting under focus fires blur → focus to the body,\n  // which trips Base UI Menu's focus-out close. Catch it and pull focus back to the viewport\n  // (still inside the popup) synchronously before the close can run.\n  const handleBlur = useCallback((event: React.FocusEvent<HTMLElement>) => {\n    if (jumpTargetRef.current === null) return;\n    const viewport = viewportRef.current;\n    if (!viewport) return;\n    if (event.relatedTarget && viewport.contains(event.relatedTarget)) return;\n    viewport.focus({ preventScroll: true });\n  }, []);\n\n  const viewportProps = useMemo(\n    () => ({ ...scrollGuardProps, onBlur: handleBlur, onKeyDownCapture: handleKeyDownCapture }),\n    [handleBlur, handleKeyDownCapture, scrollGuardProps],\n  );\n\n  return { keepMountedIndices, viewportProps, viewportRef, virtualChildren, virtualizerRef };\n}\n"],"mappings":"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"}