'use client';
import { arrow, autoUpdate, flip, limitShift, offset, shift, useFloating } from '@floating-ui/react-dom';
import React, { useCallback, useEffect, useId, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { styled } from 'styled-components';
import { useOverlayStack } from '~/components/OverlayStackProvider';
import { PortalPassthrough } from '~/components/PortalPassthrough';
import { tokens } from '~/tokens';
import { hasResizeObserver } from '~/utilities/feature-detection';
import { convertLegacyUnitValue } from '~/utilities/legacy-units';
function noop() {
    // Noop
}
const StyledPopover = styled.div `
  isolation: isolate;
  z-index: ${tokens.global.layer.z12};
  border-radius: ${tokens.global.radius.md};
  background-color: ${tokens.global.bg.elevated.default};
  box-shadow: ${tokens.global.boxShadow.mid};
  max-width: ${({ maxWidth }) => (maxWidth ? convertLegacyUnitValue(maxWidth) : '248px')};
  min-width: ${({ minWidth }) => (minWidth ? convertLegacyUnitValue(minWidth) : '160px')};
`;
const StyledContent = styled.div `
  padding: ${tokens.global.space.x16};
  border-radius: ${tokens.global.radius.md};
  background-color: ${tokens.global.bg.elevated.default};
`;
function getArrowOffset(placement) {
    switch (placement) {
        case 'left':
        case 'left-end':
        case 'left-start':
            return 'right';
        case 'right':
        case 'right-end':
        case 'right-start':
            return 'left';
        case 'bottom':
        case 'bottom-end':
        case 'bottom-start':
            return 'top';
        case 'top':
        case 'top-end':
        case 'top-start':
        default:
            return 'bottom';
    }
}
const StyledArrow = styled.div `
  position: absolute;
  width: ${tokens.global.space.x48};
  height: ${tokens.global.space.x48};
  pointer-events: none;
  ${({ arrowX }) => arrowX !== undefined && `left: ${arrowX}px;`}
  ${({ arrowY }) => arrowY !== undefined && `top: ${arrowY}px;`}
    ${({ placement }) => `${getArrowOffset(placement)}: -16px;`}

    &::after {
    display: block;
    content: '';
    position: absolute;
    z-index: -1;
    border-radius: 1px;
    box-shadow: ${tokens.global.boxShadow.mid};
    background-color: ${tokens.global.bg.elevated.default};
    width: 27px;
    height: 27px;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(45deg);
  }
`;
export function Popover({ children, content, 'data-tag': dataTag, hideArrow = false, id: specifiedId, isOpen = false, maxWidth, minWidth, onCloseRequest = noop, preferredPlacement = 'top', renderMode = 'adjacent', autoPositioning = 'default', }) {
    const popoverId = useId();
    const id = specifiedId ?? popoverId ?? 'popover';
    useOverlayStack(id, isOpen);
    const [isMounted, setIsMounted] = useState(false);
    const arrowRef = useRef(null);
    const handleKeyDown = useCallback((e) => {
        if (e.key === 'Esc' || e.key === 'Escape') {
            onCloseRequest();
        }
    }, [onCloseRequest]);
    const middleware = [
        // Offset the popover by 16px
        offset(hideArrow ? 8 : 16),
        // If the popover is overflowing the viewport, allow for
        // shifting its position to ensure it remains visible
        shift({ limiter: limitShift(), padding: 12 }),
        arrow({ element: arrowRef }),
    ];
    // If `autoPositioning` is disabled we render `Popover` in the prefered placement location regardless of screen position.
    if (autoPositioning === 'default') {
        // By default the popover will be placed on the side given
        // via `preferredPlacement`. When there isn't enough space
        // on that side, we "flip" it to the opposite.
        middleware.splice(1, 0, flip());
    }
    const { floatingStyles, placement, refs, middlewareData: { arrow: { x: arrowX, y: arrowY } = {} }, } = useFloating({
        // Where we want to place the popover
        placement: preferredPlacement,
        // Some middleware for positioning calculations
        middleware,
        // So long as the popover is visible, re-calc positioning on
        // scroll and resize
        whileElementsMounted: hasResizeObserver ? autoUpdate : undefined,
    });
    // Track when component has rendered
    useEffect(() => {
        setIsMounted(true);
    }, []);
    // Handle outside clicks
    useEffect(() => {
        // Don't attach a handler if the popover is closed or if the
        // user has not provided an `onCloseRequest` callback.
        if (!isOpen || onCloseRequest === noop) {
            return noop;
        }
        const container = refs.floating.current;
        // We manually wire up the `reference` callback to the wrapped element.
        const trigger = refs.reference.current;
        function handleClick(e) {
            if (container === null) {
                return;
            }
            const target = e.target;
            if (!container.contains(target) && !trigger.contains(target)) {
                onCloseRequest();
            }
        }
        window.addEventListener('click', handleClick, true);
        return () => {
            window.removeEventListener('click', handleClick, true);
        };
    }, [isOpen, onCloseRequest, refs.floating, refs.reference, renderMode]);
    const popover = (
    // Putting a keydown handler here just to rely on this as a boundary
    // eslint-disable-next-line jsx-a11y/no-static-element-interactions
    <div onKeyDown={handleKeyDown}>
      <PortalPassthrough>
        <StyledPopover ref={refs.setFloating} role="dialog" id={id} data-tag={dataTag} style={floatingStyles} maxWidth={maxWidth} minWidth={minWidth}>
          <StyledContent>{content}</StyledContent>
          {!hideArrow && <StyledArrow ref={arrowRef} placement={placement} arrowX={arrowX} arrowY={arrowY}/>}
        </StyledPopover>
      </PortalPassthrough>
    </div>);
    // Handle legacy children API
    if (typeof children === 'function') {
        return (<>
        {children({
                ref: refs.setReference,
                ariaProps: {
                    'aria-controls': isOpen ? id : undefined,
                    'aria-expanded': isOpen,
                },
            })}
        {isOpen && renderMode === 'adjacent' && popover}
        {isOpen && renderMode === 'portal' && isMounted && createPortal(popover, document.body)}
      </>);
    }
    return (<>
      {React.cloneElement(React.Children.only(children), {
            ref: refs.setReference,
            'aria-controls': isOpen ? id : undefined,
            'aria-expanded': isOpen,
        })}
      {isOpen && renderMode === 'adjacent' && popover}
      {isOpen && renderMode === 'portal' && isMounted && createPortal(popover, document.body)}
    </>);
}
//# sourceMappingURL=index.jsx.map