'use strict';

var React = require('react');
var classnames = require('classnames');
var framerMotion = require('framer-motion');
var jobberHooks = require('@jobber/hooks');
var floatingUi_react = require('./floating-ui.react-cjs.js');
var Tree = require('./Tree-cjs.js');
require('react-dom');
var Button = require('./Button-cjs.js');
var Typography = require('./Typography-cjs.js');
var Icon = require('./Icon-cjs.js');
var useFormFieldFocus = require('./useFormFieldFocus-cjs.js');
var maxHeight = require('./maxHeight-cjs.js');

/*
 * Copyright 2020 Adobe. All rights reserved.
 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under
 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
 * OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */ 



const $3b117e43dc0ca95d$export$27c701ed9e449e99 = /*#__PURE__*/ (React).forwardRef(({ children: children, ...props }, ref)=>{
    ref = (Tree.$df56164dff5785e2$export$4338b53315abf666)(ref);
    let { pressProps: pressProps } = (Tree.$f6c31cce2adf654f$export$45712eceda6fad21)({
        ...props,
        ref: ref
    });
    let { focusableProps: focusableProps } = (Tree.$f645667febf57a63$export$4c014de7c8940b4c)(props, ref);
    let child = (React).Children.only(children);
    (React.useEffect)(()=>{
        if (process.env.NODE_ENV === 'production') return;
        let el = ref.current;
        if (!el || !(el instanceof (Tree.$431fbd86ca7dc216$export$f21a1ffae260145a)(el).Element)) {
            console.error('<Pressable> child must forward its ref to a DOM element.');
            return;
        }
        if (!props.isDisabled && !(Tree.$b4b717babfbb907b$export$4c063cf1350e6fed)(el)) {
            console.warn('<Pressable> child must be focusable. Please ensure the tabIndex prop is passed through.');
            return;
        }
        if (el.localName !== 'button' && el.localName !== 'input' && el.localName !== 'select' && el.localName !== 'textarea' && el.localName !== 'a' && el.localName !== 'area' && el.localName !== 'summary') {
            let role = el.getAttribute('role');
            if (!role) console.warn('<Pressable> child must have an interactive ARIA role.');
            else if (// https://w3c.github.io/aria/#widget_roles
            role !== 'application' && role !== 'button' && role !== 'checkbox' && role !== 'combobox' && role !== 'gridcell' && role !== 'link' && role !== 'menuitem' && role !== 'menuitemcheckbox' && role !== 'menuitemradio' && role !== 'option' && role !== 'radio' && role !== 'searchbox' && role !== 'separator' && role !== 'slider' && role !== 'spinbutton' && role !== 'switch' && role !== 'tab' && role !== 'textbox' && role !== 'treeitem') console.warn(`<Pressable> child must have an interactive ARIA role. Got "${role}".`);
        }
    }, [
        ref,
        props.isDisabled
    ]);
    // @ts-ignore
    let childRef = parseInt((React).version, 10) < 19 ? child.ref : child.props.ref;
    return /*#__PURE__*/ (React).cloneElement(child, {
        ...(Tree.$3ef42575df84b30b$export$9d1611c77c2fe928)(pressProps, focusableProps, child.props),
        // @ts-ignore
        ref: (Tree.$5dc95899b306f630$export$c9058316764c140e)(childRef, ref)
    });
});

var styles = {"wrapper":"fpi0W91w2ag-","floatingContainer":"ba-Kj6mvQUw-","menu":"-DayvgvIcVo-","legacySection":"VsRRunpS6Yo-","separator":"jnggqK3YTIU-","triggerWrapper":"oRQQVVq-yxA-","ariaMenu":"QInUBKqkrl0-","ariaItem":"bWR8m7-LKg4-","ariaSection":"PH5vvtLgvXI-","ariaSectionHeader":"iJjIifpa9bk-","sectionHeader":"Bq7pLWj3jm4-","legacyAction":"P4Sdaq0-lZs-","action":"M1BgN-oCmKw-","destructive":"U9ihZZavz9w-","overlay":"_7we5hh6kYs8-","fullWidth":"_5OJ7B6mFcwk-","screenReaderOnly":"Bzvkz60bwWE-","spinning":"_0-VzuzHdi8o-"};

const SMALL_SCREEN_BREAKPOINT = 490;
const MENU_OFFSET = 6;
const MENU_MAX_HEIGHT_PERCENTAGE = 72;
const Y_TRANSLATION_DESKTOP = 10;
const Y_TRANSLATION_MOBILE = 150;
const MENU_ANIMATION_DURATION = 0.25;
const OVERLAY_ANIMATION_DURATION = 0.15;
const MENU_ANIMATION_CONFIG = {
    duration: MENU_ANIMATION_DURATION,
    type: "tween",
};
const OVERLAY_ANIMATION_CONFIG = {
    duration: OVERLAY_ANIMATION_DURATION,
    type: "tween",
};

const composeOverlayVariation = {
    hidden: { opacity: 0 },
    visible: { opacity: 1 },
};
const animationVariation = {
    overlayStartStop: { opacity: 0 },
    startOrStop: (placement) => {
        let y = Y_TRANSLATION_DESKTOP;
        if (placement === null || placement === void 0 ? void 0 : placement.includes("bottom"))
            y *= -1;
        if (isMobileDevice())
            y = Y_TRANSLATION_MOBILE;
        return { opacity: 0, y };
    },
    done: { opacity: 1, y: 0 },
};
function isMobileDevice() {
    if (typeof window === "undefined") {
        return false;
    }
    return window.innerWidth <= SMALL_SCREEN_BREAKPOINT;
}
function isLegacy(props) {
    return "items" in props;
}
const MotionMenu = framerMotion.motion.create(Tree.$3674c52c6b3c5bce$export$d9b273488cd8ce6f);
// Single implementation
function Menu(props) {
    if (isLegacy(props)) {
        return React.createElement(MenuLegacy, Object.assign({}, props));
    }
    return (React.createElement(MenuComposable, { onOpenChange: props.onOpenChange, open: props.open, defaultOpen: props.defaultOpen }, props.children));
}
// eslint-disable-next-line max-statements
function MenuLegacy({ activator, items, UNSAFE_className, UNSAFE_style, }) {
    var _a;
    const [visible, setVisible] = React.useState(false);
    const [referenceElement, setReferenceElement] = React.useState(null);
    const [activeIndex, setActiveIndex] = React.useState(null);
    const listRef = React.useRef([]);
    const { width } = jobberHooks.useWindowDimensions();
    const buttonID = React.useId();
    const menuID = React.useId();
    const fullWidth = ((_a = activator === null || activator === void 0 ? void 0 : activator.props) === null || _a === void 0 ? void 0 : _a.fullWidth) || false;
    const wrapperClasses = classnames(styles.wrapper, {
        [styles.fullWidth]: fullWidth,
    });
    // Ensure focus returns to the activator when closed
    jobberHooks.useRefocusOnActivator(visible);
    const isLargeScreen = width >= SMALL_SCREEN_BREAKPOINT;
    const middleware = React.useMemo(() => {
        if (isLargeScreen) {
            return [
                floatingUi_react.offset(MENU_OFFSET),
                floatingUi_react.flip({ fallbackPlacements: ["bottom-end", "top-start", "top-end"] }),
                floatingUi_react.size({
                    apply({ availableHeight, elements }) {
                        // The inner element is the scrollable menu that requires the max height
                        const menuElement = elements.floating.querySelector('[role="menu"]');
                        if (menuElement) {
                            const viewportHeight = window.innerHeight;
                            const maxHeightVh = (viewportHeight * MENU_MAX_HEIGHT_PERCENTAGE) / 100;
                            const maxHeight$1 = maxHeight.calculateMaxHeight(availableHeight, {
                                maxHeight: maxHeightVh,
                            });
                            Object.assign(menuElement.style, {
                                maxHeight: `${maxHeight$1}px`,
                            });
                        }
                    },
                }),
            ];
        }
        return [];
    }, [isLargeScreen]);
    const { refs, floatingStyles, context } = floatingUi_react.useFloating({
        open: visible,
        onOpenChange: (isOpen) => {
            setVisible(isOpen);
        },
        placement: "bottom-start",
        strategy: "fixed",
        middleware,
        elements: {
            reference: referenceElement,
        },
        whileElementsMounted: floatingUi_react.autoUpdate,
    });
    const dismiss = floatingUi_react.useDismiss(context);
    const listNavigation = floatingUi_react.useListNavigation(context, {
        listRef,
        activeIndex,
        onNavigate: setActiveIndex,
        loop: true,
    });
    const { getReferenceProps, getFloatingProps, getItemProps } = floatingUi_react.useInteractions([dismiss, listNavigation]);
    const positionAttributes = isLargeScreen
        ? {
            style: floatingStyles,
        }
        : {};
    if (!activator) {
        activator = (React.createElement(Button.Button, { fullWidth: true, label: "More Actions", icon: "more", type: "secondary" }));
    }
    let itemIndexCounter = 0;
    const renderedSections = items === null || items === void 0 ? void 0 : items.map((item, key) => (React.createElement("div", { key: key, className: styles.legacySection },
        item.header && (React.createElement(SectionHeader, { text: item.header, UNSAFE_style: UNSAFE_style === null || UNSAFE_style === void 0 ? void 0 : UNSAFE_style.header, UNSAFE_className: UNSAFE_className === null || UNSAFE_className === void 0 ? void 0 : UNSAFE_className.header })),
        item.actions.map(action => {
            const currentIndex = itemIndexCounter++;
            return (React.createElement(Action, Object.assign({ UNSAFE_style: UNSAFE_style === null || UNSAFE_style === void 0 ? void 0 : UNSAFE_style.action, UNSAFE_className: UNSAFE_className === null || UNSAFE_className === void 0 ? void 0 : UNSAFE_className.action, sectionLabel: item.header, key: action.label, tabIndex: activeIndex === currentIndex ? 0 : -1, setItemNode: node => {
                    listRef.current[currentIndex] = node;
                }, getItemProps: getItemProps }, action)));
        }))));
    return (React.createElement("div", { className: wrapperClasses, onClick: handleParentClick },
        React.createElement("div", Object.assign({ ref: setReferenceElement }, getReferenceProps()), React.cloneElement(activator, {
            onClick: toggle(activator.props.onClick),
            id: buttonID,
            ariaControls: menuID,
            ariaExpanded: visible,
            ariaHaspopup: true,
        })),
        React.createElement(MenuPortal, null,
            React.createElement(framerMotion.AnimatePresence, null, visible && (React.createElement(React.Fragment, null,
                React.createElement(framerMotion.motion.div, { className: styles.overlay, onClick: toggle(), variants: animationVariation, initial: "overlayStartStop", animate: "done", exit: "overlayStartStop", transition: Object.assign({}, OVERLAY_ANIMATION_CONFIG) }),
                React.createElement("div", Object.assign({ ref: refs.setFloating, className: styles.floatingContainer }, getFloatingProps({
                    onKeyDown: event => {
                        if (event.key === "Tab") {
                            event.preventDefault();
                        }
                    },
                }), positionAttributes, useFormFieldFocus.formFieldFocusAttribute), items.length > 0 && (React.createElement(framerMotion.motion.div, { className: classnames(styles.menu, UNSAFE_className === null || UNSAFE_className === void 0 ? void 0 : UNSAFE_className.menu), role: "menu", "data-elevation": "elevated", "aria-labelledby": buttonID, id: menuID, onClick: hide, variants: animationVariation, initial: "startOrStop", animate: "done", exit: "startOrStop", custom: context === null || context === void 0 ? void 0 : context.placement, transition: Object.assign({}, MENU_ANIMATION_CONFIG), style: UNSAFE_style === null || UNSAFE_style === void 0 ? void 0 : UNSAFE_style.menu }, renderedSections)))))))));
    function toggle(callbackPassthrough) {
        return (event) => {
            setVisible(!visible);
            callbackPassthrough && callbackPassthrough(event);
        };
    }
    function hide() {
        setVisible(false);
        setActiveIndex(null);
    }
    function handleParentClick(event) {
        // Since the menu is being rendered within the same parent as the activator,
        // we need to stop the click event from bubbling up. If the Menu component
        // gets added within a parent that has a click handler, any click on the
        // menu will trigger the parent's click handler.
        event.stopPropagation();
    }
}
function SectionHeader({ text, UNSAFE_style, UNSAFE_className, }) {
    return (React.createElement("div", { className: classnames(styles.sectionHeader, UNSAFE_className), "aria-hidden": true, style: UNSAFE_style },
        React.createElement(DefaultHeaderContent, null, text)));
}
function Action(props) {
    const { label, sectionLabel, icon, iconColor, destructive, UNSAFE_style, UNSAFE_className, onClick, tabIndex, setItemNode, getItemProps, } = props;
    const buttonClasses = classnames(styles.action, styles.legacyAction, {
        [styles.destructive]: destructive,
    });
    return (React.createElement("button", Object.assign({ className: classnames(buttonClasses, UNSAFE_className), style: UNSAFE_style, key: label, type: "button" }, getItemProps({
        ref: setItemNode,
        role: "menuitem",
        onClick,
        tabIndex,
    })),
        React.createElement(DefaultItemContent, { label: label, icon: icon, iconColor: iconColor, destructive: destructive, sectionLabel: sectionLabel })));
}
function DefaultItemContent({ label, icon, iconColor, destructive, sectionLabel, }) {
    return (React.createElement(React.Fragment, null,
        icon && (React.createElement("div", null,
            React.createElement(Icon.Icon, { color: destructive ? "destructive" : iconColor, name: icon }))),
        React.createElement(Typography.Typography, { element: "span", fontWeight: "semiBold", textColor: destructive ? "destructive" : "text" },
            sectionLabel && (React.createElement("span", { className: styles.screenReaderOnly }, sectionLabel)),
            label)));
}
function DefaultHeaderContent({ children, }) {
    return (React.createElement(Typography.Typography, { element: "h6", size: "base", textColor: "textSecondary", fontWeight: "regular", textCase: "none" }, children));
}
function MenuPortal({ children }) {
    const mounted = jobberHooks.useIsMounted();
    if (!(mounted === null || mounted === void 0 ? void 0 : mounted.current)) {
        return null;
    }
    return React.createElement(floatingUi_react.FloatingPortal, null, children);
}
const MenuAnimationContext = React.createContext(null);
function useMenuAnimation() {
    const ctx = React.useContext(MenuAnimationContext);
    if (!ctx) {
        throw new Error("MenuAnimationContext used outside provider");
    }
    return ctx;
}
function MenuComposable({ children, onOpenChange, open, defaultOpen, }) {
    const isInitiallyOpen = Boolean(open !== null && open !== void 0 ? open : defaultOpen);
    const [animation, setAnimation] = React.useState(isInitiallyOpen ? "visible" : "unmounted");
    const derivedAnimation = getDerivedAnimation(open, animation);
    return (React.createElement(MenuAnimationContext.Provider, { value: { state: derivedAnimation, setState: setAnimation } },
        React.createElement(Tree.$3674c52c6b3c5bce$export$27d2ad3c5815583e, { isOpen: open, defaultOpen: defaultOpen, onOpenChange: isOpen => {
                setAnimation(isOpen ? "visible" : "hidden");
                onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(isOpen);
            } }, children)));
}
function getDerivedAnimation(open, animation) {
    const isControlled = open !== undefined;
    if (!isControlled)
        return animation;
    if (open)
        return "visible";
    // When controlled and closing, allow local state to progress to "unmounted"
    // so the Popover can be removed from the DOM once exit completes.
    return animation === "unmounted" ? "unmounted" : "hidden";
}
const MenuTriggerComposable = React.forwardRef(function MenuTriggerComposable({ ariaLabel, children }, ref) {
    return (React.createElement($3b117e43dc0ca95d$export$27c701ed9e449e99, { "aria-label": ariaLabel },
        React.createElement("div", { role: "button", className: styles.triggerWrapper, ref: ref }, children)));
});
function MenuContentComposable({ children, UNSAFE_style, UNSAFE_className, }) {
    const { state: animation, setState } = useMenuAnimation();
    const isMobile = isMobileDevice();
    return (React.createElement(React.Fragment, null,
        React.createElement(Tree.$07b14b47974efb58$export$5b6b19405a83ff9d, { isExiting: animation === "hidden", placement: "bottom start", offset: MENU_OFFSET }, ({ placement }) => {
            const directionModifier = (placement === null || placement === void 0 ? void 0 : placement.includes("bottom")) ? -1 : 1;
            const variants = isMobile
                ? {
                    hidden: { opacity: 0, y: Y_TRANSLATION_MOBILE },
                    visible: { opacity: 1, y: 0 },
                }
                : {
                    hidden: {
                        opacity: 0,
                        y: Y_TRANSLATION_DESKTOP * directionModifier,
                    },
                    visible: { opacity: 1, y: 0 },
                };
            return (React.createElement(MotionMenu, { key: `menu-content-${placement !== null && placement !== void 0 ? placement : "pending"}`, className: classnames(styles.menu, styles.ariaMenu, UNSAFE_className), style: UNSAFE_style, variants: variants, initial: "hidden", 
                // placement is null on first render cycle, so we need to wait for it to be defined
                animate: placement ? animation : false, transition: Object.assign({}, MENU_ANIMATION_CONFIG), onAnimationComplete: animationState => {
                    setState(prev => animationState === "hidden" && prev === "hidden"
                        ? "unmounted"
                        : prev);
                } }, children));
        }),
        isMobile && React.createElement(MenuMobileUnderlay, { animation: animation })));
}
function MenuMobileUnderlay({ animation }) {
    if (animation === "unmounted")
        return null;
    return (React.createElement(framerMotion.motion.div, { key: "menu-mobile-underlay", variants: composeOverlayVariation, initial: "hidden", transition: Object.assign({}, OVERLAY_ANIMATION_CONFIG), className: styles.overlay, animate: animation }));
}
function MenuSeparatorComposable({ UNSAFE_style, UNSAFE_className, }) {
    return (React.createElement(Tree.$431f98aba6844401$export$1ff3c3f08ae963c0, { className: classnames(styles.separator, UNSAFE_className), style: UNSAFE_style, "data-testid": "ATL-Menu-Separator" }));
}
function MenuSectionComposable({ children, UNSAFE_style, UNSAFE_className, ariaLabel, }) {
    return (React.createElement(Tree.$3674c52c6b3c5bce$export$4b1545b4f2016d26, { "aria-label": ariaLabel, className: classnames(styles.ariaSection, UNSAFE_className), style: UNSAFE_style }, children));
}
function MenuHeaderComposable(props) {
    const { UNSAFE_style, UNSAFE_className } = props;
    return (React.createElement(Tree.$72a5793c14baf454$export$8b251419efc915eb, { className: classnames(styles.sectionHeader, styles.ariaSectionHeader, UNSAFE_className), style: UNSAFE_style }, props.children));
}
const MenuItemComposable = React.forwardRef(function MenuItemComposable(props, ref) {
    const { UNSAFE_style, UNSAFE_className } = props;
    const className = classnames(styles.action, styles.ariaItem, UNSAFE_className);
    if (props.href) {
        const { href, target, rel, onClick } = props;
        return (React.createElement(Tree.$3674c52c6b3c5bce$export$2ce376c2cc3355c8, { ref: ref, className: className, style: UNSAFE_style, textValue: props.textValue, href: href, target: target, rel: rel, onClick: onClick },
            React.createElement(MenuItemContext.Provider, { value: { variation: props.variation } }, props.children)));
    }
    return (React.createElement(Tree.$3674c52c6b3c5bce$export$2ce376c2cc3355c8, { ref: ref, className: className, style: UNSAFE_style, textValue: props.textValue, onAction: () => {
            var _a;
            // Zero-arg activation for non-link items
            (_a = props.onClick) === null || _a === void 0 ? void 0 : _a.call(props);
        } },
        React.createElement(MenuItemContext.Provider, { value: { variation: props.variation } }, props.children)));
});
const MenuItemContext = React.createContext(null);
function useMenuItemContext() {
    const ctx = React.useContext(MenuItemContext);
    return ctx !== null && ctx !== void 0 ? ctx : {};
}
function MenuItemIconComposable(props) {
    const { variation } = useMenuItemContext();
    return (React.createElement("div", { "data-menu-slot": "icon" },
        React.createElement(Icon.Icon, Object.assign({}, props, { color: variation === "destructive" ? "destructive" : props.color }))));
}
function MenuItemLabelComposable(props) {
    const { variation } = useMenuItemContext();
    return (React.createElement("div", { "data-menu-slot": "label" },
        React.createElement(Typography.Typography, { element: "span", fontWeight: "semiBold", textColor: variation === "destructive" ? "destructive" : "text" }, props.children)));
}
function MenuHeaderLabel(props) {
    return React.createElement(DefaultHeaderContent, null, props.children);
}
Menu.Section = MenuSectionComposable;
Menu.Header = MenuHeaderComposable;
Menu.Item = MenuItemComposable;
Menu.Trigger = MenuTriggerComposable;
Menu.Content = MenuContentComposable;
Menu.Separator = MenuSeparatorComposable;
Menu.ItemIcon = MenuItemIconComposable;
Menu.ItemLabel = MenuItemLabelComposable;
Menu.HeaderLabel = MenuHeaderLabel;

exports.Menu = Menu;
