{"version":3,"sources":["../src/components/Popover/usePopover.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useControllableState, useEventCallback, useId, useTimeout } from '@fluentui/react-utilities';\nimport { usePositioning, resolvePositioningShorthand } from '../../hooks';\nimport type { PopoverProps, PopoverState, PopoverContextValue, OpenPopoverEvents } from './Popover.types';\n\nconst SUPPORTS_POPOVER_OPEN_SELECTOR =\n  typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('selector(:popover-open)');\n\ntype ToggleEvent = Event & { newState?: 'open' | 'closed' };\n\nconst isDialogElement = (el: Element | null): el is HTMLDialogElement =>\n  !!el && typeof (el as HTMLDialogElement).showModal === 'function';\n\n/**\n * Returns the state for a Popover component.\n */\nexport const usePopover = (props: PopoverProps): PopoverState => {\n  const {\n    openOnHover = false,\n    openOnContext = false,\n    mouseLeaveDelay = 500,\n    withArrow = false,\n    trapFocus = false,\n  } = props;\n\n  const [open, setOpenState] = useControllableState({\n    state: props.open,\n    defaultState: props.defaultOpen,\n    initialState: false,\n  });\n\n  const [contextTarget, setContextTarget] = React.useState<{ x: number; y: number } | undefined>(undefined);\n\n  const onOpenChange = useEventCallback((e: OpenPopoverEvents, shouldOpen: boolean) => {\n    props.onOpenChange?.(e, { event: e, type: e.type, open: shouldOpen });\n  });\n\n  const [setOpenTimeout, clearOpenTimeout] = useTimeout();\n\n  const setOpen = useEventCallback((e: OpenPopoverEvents, shouldOpen: boolean) => {\n    clearOpenTimeout();\n\n    if (shouldOpen && e.type === 'contextmenu') {\n      const mouseEvent = e as React.MouseEvent<HTMLElement>;\n      setContextTarget({ x: mouseEvent.clientX, y: mouseEvent.clientY });\n    }\n\n    if (!shouldOpen) {\n      setContextTarget(undefined);\n    }\n\n    if (e.type === 'mouseleave') {\n      setOpenTimeout(() => {\n        setOpenState(shouldOpen);\n        onOpenChange(e, shouldOpen);\n      }, mouseLeaveDelay);\n    } else {\n      setOpenState(shouldOpen);\n      onOpenChange(e, shouldOpen);\n    }\n  });\n\n  const toggleOpen = React.useCallback(\n    (e: OpenPopoverEvents) => {\n      setOpen(e, !open);\n    },\n    [setOpen, open],\n  );\n\n  const triggerRef = React.useRef<HTMLElement>(null);\n  const contentRef = React.useRef<HTMLElement>(null);\n  const arrowRef = React.useRef<HTMLDivElement>(null);\n\n  const generatedSurfaceId = useId('fui-popover-surface-');\n  const surfaceId = props.id ?? generatedSurfaceId;\n\n  const positioning = usePositioning(resolvePositioningShorthand(props.positioning));\n\n  const onSurfaceToggle = useEventCallback((event: Event) => {\n    const toggle = event as ToggleEvent;\n    const nextOpen = toggle.newState === 'open';\n\n    if (nextOpen === open) {\n      return;\n    }\n\n    setOpenState(nextOpen);\n    props.onOpenChange?.(event, { event, type: event.type, open: nextOpen });\n  });\n\n  const onSurfaceClose = useEventCallback((event: Event) => {\n    setOpenState(false);\n    props.onOpenChange?.(event, { event, type: event.type, open: false });\n  });\n\n  React.useEffect(() => {\n    const surface = contentRef.current;\n\n    if (!surface) {\n      return;\n    }\n\n    if (!open) {\n      if (isDialogElement(surface) && surface.open) {\n        surface.close();\n      }\n      return;\n    }\n\n    if (trapFocus) {\n      if (!isDialogElement(surface)) {\n        return;\n      }\n\n      if (!surface.open) {\n        surface.showModal();\n      }\n\n      surface.addEventListener('close', onSurfaceClose);\n      return () => surface.removeEventListener('close', onSurfaceClose);\n    }\n\n    if (typeof surface.showPopover !== 'function') {\n      return;\n    }\n\n    if (!(SUPPORTS_POPOVER_OPEN_SELECTOR && surface.matches(':popover-open'))) {\n      surface.showPopover();\n    }\n\n    surface.addEventListener('toggle', onSurfaceToggle);\n    return () => surface.removeEventListener('toggle', onSurfaceToggle);\n  }, [open, trapFocus, contentRef, onSurfaceToggle, onSurfaceClose]);\n\n  const children = React.Children.toArray(props.children) as React.ReactElement[];\n\n  if (process.env.NODE_ENV !== 'production') {\n    if (children.length === 0) {\n      // eslint-disable-next-line no-console\n      console.warn('Popover must contain at least one child');\n    }\n\n    if (children.length > 2) {\n      // eslint-disable-next-line no-console\n      console.warn('Popover must contain at most two children');\n    }\n  }\n\n  let popoverTrigger: React.ReactElement | undefined;\n  let popoverSurface: React.ReactElement | undefined;\n\n  if (children.length === 2) {\n    popoverTrigger = children[0];\n    popoverSurface = children[1];\n  } else if (children.length === 1) {\n    popoverSurface = children[0];\n  }\n\n  return {\n    open,\n    setOpen,\n    toggleOpen,\n    triggerRef,\n    contentRef,\n    arrowRef,\n    popoverTrigger,\n    popoverSurface,\n    openOnHover,\n    openOnContext,\n    withArrow,\n    trapFocus,\n    onOpenChange: props.onOpenChange,\n    contextTarget,\n    setContextTarget,\n    positioning,\n    surfaceId,\n  };\n};\n\nexport const usePopoverContextValues = (state: PopoverState): { popover: PopoverContextValue } => {\n  const {\n    open,\n    setOpen,\n    toggleOpen,\n    triggerRef,\n    contentRef,\n    arrowRef,\n    openOnHover,\n    openOnContext,\n    withArrow,\n    trapFocus,\n    positioning,\n    surfaceId,\n  } = state;\n\n  return {\n    popover: {\n      open,\n      setOpen,\n      toggleOpen,\n      triggerRef,\n      contentRef,\n      arrowRef,\n      openOnHover,\n      openOnContext,\n      withArrow,\n      trapFocus,\n      positioning: {\n        targetRef: positioning.targetRef,\n        containerRef: positioning.containerRef,\n      },\n      surfaceId,\n    },\n  };\n};\n"],"names":["usePopover","usePopoverContextValues","SUPPORTS_POPOVER_OPEN_SELECTOR","CSS","supports","isDialogElement","el","showModal","props","openOnHover","openOnContext","mouseLeaveDelay","withArrow","trapFocus","open","setOpenState","useControllableState","state","defaultState","defaultOpen","initialState","contextTarget","setContextTarget","React","useState","undefined","onOpenChange","useEventCallback","e","shouldOpen","event","type","setOpenTimeout","clearOpenTimeout","useTimeout","setOpen","mouseEvent","x","clientX","y","clientY","toggleOpen","useCallback","triggerRef","useRef","contentRef","arrowRef","generatedSurfaceId","useId","surfaceId","id","positioning","usePositioning","resolvePositioningShorthand","onSurfaceToggle","toggle","nextOpen","newState","onSurfaceClose","useEffect","surface","current","close","addEventListener","removeEventListener","showPopover","matches","children","Children","toArray","process","env","NODE_ENV","length","console","warn","popoverTrigger","popoverSurface","popover","targetRef","containerRef"],"mappings":"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"}