{"version":3,"file":"Dropdown.mjs","sources":["../../../../src/components/Dropdown/Dropdown.tsx"],"sourcesContent":["import { css } from '@emotion/css';\nimport {\n  FloatingFocusManager,\n  autoUpdate,\n  offset as floatingUIOffset,\n  useClick,\n  useDismiss,\n  useFloating,\n  useInteractions,\n} from '@floating-ui/react';\nimport { useCallback, useRef, useState } from 'react';\nimport * as React from 'react';\nimport { CSSTransition } from 'react-transition-group';\n\nimport { GrafanaTheme2 } from '@grafana/data';\n\nimport { useStyles2 } from '../../themes/ThemeContext';\nimport { getPositioningMiddleware } from '../../utils/floating';\nimport { renderOrCallToRender } from '../../utils/reactUtils';\nimport { getPlacement } from '../../utils/tooltipUtils';\nimport { Portal } from '../Portal/Portal';\nimport { TooltipPlacement } from '../Tooltip/types';\n\nexport interface Props {\n  overlay: React.ReactElement | (() => React.ReactElement);\n  placement?: TooltipPlacement;\n  children: React.ReactElement<Record<string, unknown>>;\n  root?: HTMLElement;\n  /** Amount in pixels to nudge the dropdown vertically and horizontally, respectively. */\n  offset?: [number, number];\n  onVisibleChange?: (state: boolean) => void;\n}\n\n/**\n * Hook up a menu or other overlay to any trigger.\n *\n * https://developers.grafana.com/ui/latest/index.html?path=/docs/overlays-dropdown--docs\n */\nexport const Dropdown = React.memo(({ children, overlay, placement, offset, root, onVisibleChange }: Props) => {\n  const [show, setShow] = useState(false);\n  const transitionRef = useRef(null);\n  const floatingUIPlacement = getPlacement(placement);\n\n  const handleOpenChange = useCallback(\n    (newState: boolean) => {\n      setShow(newState);\n      onVisibleChange?.(newState);\n    },\n    [onVisibleChange]\n  );\n\n  // the order of middleware is important!\n  const middleware = [\n    floatingUIOffset({\n      mainAxis: offset?.[0] ?? 8,\n      crossAxis: offset?.[1] ?? 0,\n    }),\n    ...getPositioningMiddleware(floatingUIPlacement),\n  ];\n\n  const { context, refs, floatingStyles } = useFloating({\n    open: show,\n    placement: floatingUIPlacement,\n    onOpenChange: handleOpenChange,\n    middleware,\n    whileElementsMounted: autoUpdate,\n  });\n\n  const click = useClick(context);\n  const dismiss = useDismiss(context);\n  const { getReferenceProps, getFloatingProps } = useInteractions([dismiss, click]);\n\n  const animationDuration = 150;\n  const animationStyles = useStyles2(getStyles, animationDuration);\n\n  const onOverlayClicked = () => {\n    handleOpenChange(false);\n  };\n\n  const handleKeys = (event: React.KeyboardEvent) => {\n    if (event.key === 'Tab') {\n      handleOpenChange(false);\n    }\n  };\n\n  return (\n    <>\n      {React.cloneElement(children, {\n        ref: refs.setReference,\n        ...getReferenceProps(),\n      })}\n      {show && (\n        <Portal root={root}>\n          <FloatingFocusManager context={context}>\n            {/*\n              this is handling bubbled events from the inner overlay\n              see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/no-static-element-interactions.md#case-the-event-handler-is-only-being-used-to-capture-bubbled-events\n            */}\n            {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */}\n            <div\n              ref={refs.setFloating}\n              style={floatingStyles}\n              onClick={onOverlayClicked}\n              onKeyDown={handleKeys}\n              {...getFloatingProps()}\n            >\n              <CSSTransition\n                nodeRef={transitionRef}\n                appear={true}\n                in={true}\n                timeout={{ appear: animationDuration, exit: 0, enter: 0 }}\n                classNames={animationStyles}\n              >\n                <div ref={transitionRef}>{renderOrCallToRender(overlay, {})}</div>\n              </CSSTransition>\n            </div>\n          </FloatingFocusManager>\n        </Portal>\n      )}\n    </>\n  );\n});\n\nDropdown.displayName = 'Dropdown';\n\nconst getStyles = (theme: GrafanaTheme2, duration: number) => {\n  return {\n    appear: css({\n      opacity: '0',\n      position: 'relative',\n      transformOrigin: 'top',\n      [theme.transitions.handleMotion('no-preference')]: {\n        transform: 'scaleY(0.5)',\n      },\n    }),\n    appearActive: css({\n      opacity: '1',\n      [theme.transitions.handleMotion('no-preference')]: {\n        transform: 'scaleY(1)',\n        transition: `transform ${duration}ms cubic-bezier(0.2, 0, 0.2, 1), opacity ${duration}ms cubic-bezier(0.2, 0, 0.2, 1)`,\n      },\n    }),\n  };\n};\n"],"names":["offset","floatingUIOffset"],"mappings":"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"}