import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { forwardRef, useState, useCallback } from 'react';
import styled, { css } from 'styled-components';
import { defaultThemeProp } from '../../theme';
import { useConsolidatedRef, useUID, useFocusWithin, useDirection, useTestIds, useEscape } from '../../hooks';
import Button, { StyledButton } from '../Button';
import Popover, { StyledPopover } from '../Popover';
import Menu from '../Menu';
import Icon, { registerIcon, StyledIcon } from '../Icon';
import * as arrowMicroDownIcon from '../Icon/icons/arrow-micro-down.icon';
import Text, { StyledText } from '../Text';
import Flex from '../Flex';
import { Count } from '../Badges';
import { withTestIds } from '../../utils';
import { getMenuButtonTestIds } from './MenuButton.test-ids';
registerIcon(arrowMicroDownIcon);
export const StyledMenuButton = styled.button(({ theme: { base: { spacing } } }) => {
    return css `
      gap: ${spacing};
      flex-shrink: 0;
      white-space: nowrap;
      max-width: 100%;

      & + ${StyledPopover} + ${StyledButton} {
        margin-inline-start: ${spacing};
      }
    `;
});
StyledMenuButton.defaultProps = defaultThemeProp;
const StyledMenuButtonChildren = styled.span(({ theme, padIcon }) => {
    const { base: { 'hit-area': { 'mouse-min': hitAreaMouse, 'finger-min': hitAreaFinger } }, components: { icon: { size: { s: iconSize } } } } = theme;
    return css `
    max-width: 100%;

    ${padIcon &&
        css `
      padding-inline-start: calc((${hitAreaMouse} - ${iconSize}) / 2);

      @media (pointer: coarse) {
        padding-inline-start: calc(${hitAreaFinger} - ${iconSize} * 2);
      }
    `}

    ${StyledText} {
      text-overflow: ellipsis;
      overflow: hidden;
    }

    ${StyledIcon}:last-child:not(:first-child) {
      /* Offsets the flex gap to make the down arrow appear to trail the text. */
      margin-inline-start: -${theme.base.spacing};
    }
  `;
});
const StyledMenuButtonPopover = styled(Popover) `
  min-width: 20ch;
`;
const MenuButton = forwardRef(function MenuButton(props, ref) {
    const uid = useUID();
    const { testId, id = uid, text, menu, popover, onClick, icon, count, iconOnly = false, showArrow = false, ...restProps } = props;
    const testIds = useTestIds(testId, getMenuButtonTestIds);
    const [isOpen, setIsOpen] = useState(false);
    const buttonRef = useConsolidatedRef(ref);
    const popoverRef = useConsolidatedRef(popover?.ref);
    const menuRef = useConsolidatedRef(menu?.ref);
    // FIXME: Type assertion required for issue in useFocusWithin generic
    useFocusWithin([popoverRef, buttonRef], useCallback(isFocused => {
        if (!isFocused)
            setIsOpen(false);
    }, []));
    useEscape(e => {
        if (isOpen) {
            setIsOpen(false);
            e.stopPropagation();
        }
    }, buttonRef);
    const { rtl } = useDirection();
    return (_jsxs(_Fragment, { children: [_jsx(Button, { "data-testid": testIds.root, as: StyledMenuButton, "aria-label": text, ...restProps, id: id, ref: buttonRef, "aria-expanded": isOpen, "aria-haspopup": 'menu', "aria-controls": isOpen ? `${id}-popover` : undefined, label: iconOnly && !isOpen ? text : undefined, onClick: (e) => {
                    // e.detail is 0 when triggered by keyboard.
                    const mouseClick = e.detail > 0;
                    if (isOpen) {
                        if (mouseClick) {
                            // Close the menu if it is open and it is a *mouse* click on the button.
                            setIsOpen(false);
                        }
                    }
                    else {
                        // Open the menu if it's closed, for mouse or keyboard click.
                        setIsOpen(true);
                    }
                    // If the menu is closed or the user mouse clicks.
                    // This avoids Enter key firing onClick when selecting a menu item.
                    if (!isOpen || mouseClick) {
                        onClick?.(e);
                    }
                }, icon: iconOnly, children: _jsxs(Flex, { as: StyledMenuButtonChildren, container: { alignItems: 'center', gap: 1 }, padIcon: iconOnly && showArrow, children: [icon && _jsx(Icon, { name: icon }), !iconOnly && (_jsxs(_Fragment, { children: [_jsx(Text, { children: text }), typeof count === 'number' && _jsx(Count, { children: count })] })), (!iconOnly || showArrow) && _jsx(Icon, { name: 'arrow-micro-down' })] }) }), _jsx(StyledMenuButtonPopover, { placement: rtl ? 'bottom-end' : 'bottom-start', hideOnTargetHidden: true, ...popover, id: `${id}-popover`, show: !!menu && isOpen, target: buttonRef.current, ref: popoverRef, children: menu && (_jsx(Menu, { testId: testIds.root, ...menu, ref: menuRef, items: menu.items, onItemClick: (itemId, e) => {
                        // When clicking an item (by mouse or keyboard) and the menu is not multi-select, close the menu.
                        if (menu.mode !== 'multi-select') {
                            setIsOpen(false);
                        }
                        menu.onItemClick?.(itemId, e);
                    }, focusControlEl: menu.focusControlEl || buttonRef.current || undefined })) })] }));
});
export default withTestIds(MenuButton, getMenuButtonTestIds);
//# sourceMappingURL=MenuButton.js.map