'use client';
import { autoUpdate, flip, limitShift, offset, shift, size, useFloating } from '@floating-ui/react-dom';
import React from 'react';
import { createPortal } from 'react-dom';
import { css } from 'styled-components';
import { BodyText } from '~/components/BodyText';
import { Box } from '~/components/Box';
import { IconChevronDownAlt, IconChevronUpAlt } from '~/components/Icon';
import { InlineHelpText } from '~/components/InlineHelpText';
import { OverlayStackComponent } from '~/components/OverlayStackProvider';
import { PortalPassthrough } from '~/components/PortalPassthrough';
import { tokens } from '~/tokens';
import { filterForAriaProps } from '~/utilities/accessibility';
import { hasResizeObserver } from '~/utilities/feature-detection';
import parentIncludesEventTarget from '~/utilities/parentIncludesEventTarget';
import { DropdownList } from './DropdownList';
import { keyCodes } from './lib/keycodes';
import { DropdownContainer, DropdownHandle, DropdownHandleDiv } from './styled-components';
function DropdownPopper(props) {
    const { refs, floatingStyles } = useFloating({
        placement: props.rightAlign ? 'bottom-end' : 'bottom-start',
        middleware: [
            // Offset the dropdown UI by 8px
            offset(8),
            // Before resorting to vertical flips, shrink the UI
            size({
                apply({ availableHeight, elements, rects }) {
                    Object.assign(elements.floating.style, {
                        // Clamp dropdown height to either:
                        // * 56px - 40px plus 8px vertical padding
                        // * availableHeight minus 8px bottom margin buffer
                        maxHeight: `${Math.max(availableHeight - 8, 56)}px`,
                        width: props.fluidDropdownList ? `${rects.reference.width}px` : undefined,
                    });
                },
            }),
            // If the popover is overflowing the viewport, allow for
            // shifting its position to ensure it remains visible
            shift({ limiter: limitShift(), padding: 12 }),
            // Keep the dropdown in the viewport by moving it across
            // both axes
            flip(),
        ],
        // Re-calc position on scroll/resize
        whileElementsMounted(...args) {
            if (hasResizeObserver) {
                return autoUpdate(...args, { animationFrame: props.autoUpdate ?? false });
            }
            return () => null;
        },
    });
    return props.children({
        hostRef: refs.setReference,
        floatingRef: refs.setFloating,
        floatingStyles,
    });
}
/** @deprecated use `OverlayTriggerMenu` instead. */
// TODO (legacied react-prefer-function-component/react-prefer-function-component)
// This failure is legacied in and should be updated. DO NOT COPY.
// eslint-disable-next-line react-prefer-function-component/react-prefer-function-component
export class Dropdown extends React.Component {
    static defaultProps = {
        closeOnOutsideClick: true,
        placeholder: 'Select…',
        hideCaret: false,
        hasCustomButton: false,
        isDivDropdown: false,
        width: 'auto',
        maxHeight: 'none',
        renderMode: 'portal',
        hideOverflow: false,
    };
    static List = DropdownList;
    state = {
        isMounted: false,
        closingTimeoutId: null,
    };
    container;
    activator;
    get handleHitbox() {
        const handleTarget = this.activator;
        if (!handleTarget) {
            return null;
        }
        const h = handleTarget.getBoundingClientRect();
        return {
            left: Math.floor(h.left),
            right: Math.floor(h.right),
            top: Math.floor(h.top),
            bottom: Math.floor(h.bottom),
        };
    }
    get containerHitbox() {
        const containerTarget = this.container;
        if (!containerTarget) {
            return null;
        }
        const c = containerTarget.getBoundingClientRect();
        return {
            left: Math.floor(c.left),
            right: Math.floor(c.right),
            top: Math.floor(c.top),
            bottom: Math.floor(c.bottom),
        };
    }
    componentDidMount() {
        this.setState({ isMounted: true });
        document.addEventListener('keydown', this.handleKeyDown);
        if (this.props.onClose) {
            document.addEventListener('mousedown', this.handleMouseClickOutside);
        }
    }
    componentWillUnmount() {
        document.removeEventListener('keydown', this.handleKeyDown);
        if (this.props.onClose) {
            document.removeEventListener('mousedown', this.handleMouseClickOutside);
        }
    }
    handleKeyDown = (e) => {
        const { closeOnOutsideClick, isOpen, onClose } = this.props;
        if (!closeOnOutsideClick) {
            return;
        }
        if (isOpen && e.key === keyCodes.ESC && onClose) {
            onClose(e);
        }
    };
    handleMouseClickOutside = (e) => {
        const { closeOnOutsideClick, isOpen, onClose } = this.props;
        if (!closeOnOutsideClick || !isOpen || !onClose) {
            return;
        }
        // We also want to consider clicks on the toggle div as 'inside' clicks
        // so we don't preempt onClick's call of this.props.onClose
        if (parentIncludesEventTarget(e, this.container) ||
            parentIncludesEventTarget(e, this.activator)) {
            return;
        }
        e.stopPropagation();
        onClose(e);
    };
    toggleMenuShowing = (e) => {
        const { onOpen, onClose, isOpen } = this.props;
        if (!isOpen && onOpen) {
            onOpen(e);
        }
        else if (isOpen && onClose) {
            onClose(e);
        }
    };
    renderDisplayValue = () => {
        const { disabled, dropdownHandle } = this.props;
        const displayValue = this.props.displayValue || this.props.placeholder;
        return typeof displayValue === 'string' && !dropdownHandle ? (<BodyText color={disabled ? tokens.global.content.muted.default : tokens.global.content.regular.default}>
        {displayValue}
      </BodyText>) : (displayValue);
    };
    renderHandleContent = () => {
        const { hasCustomButton, dropdownHandle, disabled, isOpen, ariaLabel } = this.props;
        const children = this.renderHandleContentChildren();
        if (dropdownHandle) {
            const { component: DropdownHandleComponent, props } = dropdownHandle;
            if (hasCustomButton) {
                return (<DropdownHandleComponent {...props} onClick={!disabled ? this.toggleMenuShowing : undefined} aria-expanded={isOpen} aria-haspopup aria-label={ariaLabel} data-tag="menuToggleDiv">
            {children}
          </DropdownHandleComponent>);
            }
            return <DropdownHandleComponent {...props}>{children}</DropdownHandleComponent>;
        }
        return children;
    };
    renderHandleContentChildren = () => {
        const { hideCaret, isOpen } = this.props;
        const caretProps = {
            color: this.props.disabled ? tokens.global.content.muted.default : tokens.global.content.regular.default,
            size: '24px',
        };
        const caret = isOpen ? <IconChevronUpAlt {...caretProps}/> : <IconChevronDownAlt {...caretProps}/>;
        return (<Box alignContent="center" alignItems="center" display="flex" flexDirection="row" flexWrap="nowrap" justifyContent="space-between" width="100%">
        <Box mr={hideCaret ? 0 : 1.5} css={css `
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
          `}>
          {this.renderDisplayValue()}
        </Box>
        {!hideCaret && caret}
      </Box>);
    };
    renderHeader = () => {
        const { header } = this.props;
        return (<Box pb={3}>
        <BodyText as="p" color={tokens.global.content.muted.default}>
          {header}
        </BodyText>
      </Box>);
    };
    render() {
        const { ariaLabel, children, disabled, dropdownHandle: handleComponent, fluidWidth, fluidDropdownList, hasCustomButton, header, id, isDivDropdown, isOpen, maxHeight, minWidth, noHandleStyle, openOnHover, rightAlign, autoUpdatePosition, width, renderMode, hideOverflow, error, ...restProps } = this.props;
        const errorId = `${id ?? ''}-error`;
        const dropdownHandleProps = {
            'aria-expanded': isOpen,
            'aria-haspopup': true,
            'aria-label': ariaLabel,
            disabled,
            fluidWidth,
            hasCustomHandle: !!handleComponent || noHandleStyle,
            id,
            isOpen,
            minWidth,
            onMouseOver: openOnHover ? this.handleMouseOverHandle : undefined,
            openOnHover,
            error,
            ...filterForAriaProps(restProps),
        };
        return (<Box alignSelf="center" fluidWidth={fluidWidth} onMouseLeave={this.handleMouseLeave} position="relative">
        <OverlayStackComponent id={id ?? 'dropdown-fallback'} isOpen={isOpen ?? false}/>
        <DropdownPopper rightAlign={rightAlign} autoUpdate={autoUpdatePosition} fluidDropdownList={fluidDropdownList}>
          {({ floatingRef, hostRef, floatingStyles }) => {
                const container = (<PortalPassthrough>
                <DropdownContainer data-tag="dropdown-list" ref={(el) => {
                        if (typeof floatingRef === 'function') {
                            floatingRef(el);
                        }
                        this.containerRef(el);
                    }} style={floatingStyles} maxHeight={maxHeight} width={width} hideOverflow={hideOverflow}>
                  <Box p={2}>
                    {header && this.renderHeader()}
                    {children}
                  </Box>
                </DropdownContainer>
              </PortalPassthrough>);
                return (<>
                {isDivDropdown || hasCustomButton ? (<DropdownHandleDiv {...dropdownHandleProps} 
                    // You should not set aria-expanded on divs for accessibility
                    aria-expanded={undefined} data-tag={hasCustomButton ? undefined : 'menuToggleDiv'} ref={(el) => {
                            if (hostRef instanceof Function) {
                                hostRef(el);
                            }
                            this.activatorRef(el);
                        }}>
                    {this.renderHandleContent()}
                  </DropdownHandleDiv>) : (<DropdownHandle {...dropdownHandleProps} data-tag="menuToggleDiv" ref={(el) => {
                            if (hostRef instanceof Function) {
                                hostRef(el);
                            }
                            this.activatorRef(el);
                        }} onClick={!disabled ? this.toggleMenuShowing : undefined}>
                    {this.renderHandleContent()}
                  </DropdownHandle>)}

                {error && <InlineHelpText error={error} inputId={errorId}/>}

                {isOpen && renderMode === 'adjacent' && container}

                {isOpen &&
                        this.state.isMounted &&
                        renderMode === 'portal' &&
                        createPortal(container, window.document.body)}
              </>);
            }}
        </DropdownPopper>
      </Box>);
    }
    isMouseEventInHitbox(e) {
        if (!this.handleHitbox || !this.containerHitbox) {
            return false;
        }
        /**
         * If within handle hitbox (+ height of menu for gap b/w both)
         */
        if (e.clientX > this.handleHitbox.left &&
            e.clientX < this.handleHitbox.right &&
            e.clientY > this.handleHitbox.top &&
            e.clientY < this.containerHitbox.bottom) {
            return true;
        }
        /**
         * If within container hitbox
         */
        if (e.clientX > this.containerHitbox.left &&
            e.clientX < this.containerHitbox.right &&
            e.clientY > this.containerHitbox.top &&
            e.clientY < this.containerHitbox.bottom) {
            return true;
        }
        return false;
    }
    handleMouseOverHandle = (e) => {
        const { openOnHover, onOpen, isOpen } = this.props;
        if (openOnHover && onOpen && !isOpen) {
            onOpen(e);
        }
    };
    handleMouseLeave = (e) => {
        const { openOnHover, isOpen, onClose } = this.props;
        if (!openOnHover || !isOpen || !onClose || this.isMouseEventInHitbox(e)) {
            return;
        }
        e.stopPropagation();
        onClose(e);
    };
    containerRef(el) {
        if (el != null) {
            this.container = el;
        }
        return this.container;
    }
    activatorRef(el) {
        if (el != null) {
            this.activator = el;
        }
        return this.activator;
    }
}
//# sourceMappingURL=index.jsx.map