"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UIContextualMenu = exports.UIContextualMenuLayoutType = exports.UIContextualMenuItemType = void 0;
exports.getUIcontextualMenuStyles = getUIcontextualMenuStyles;
exports.getUIContextualMenuItemStyles = getUIContextualMenuItemStyles;
exports.getUIcontextualMenuCalloutStyles = getUIcontextualMenuCalloutStyles;
const react_1 = __importDefault(require("react"));
const react_2 = require("@fluentui/react");
Object.defineProperty(exports, "UIContextualMenuItemType", { enumerable: true, get: function () { return react_2.ContextualMenuItemType; } });
const Icons_1 = require("../Icons");
var UIContextualMenuLayoutType;
(function (UIContextualMenuLayoutType) {
    UIContextualMenuLayoutType["DropdownMenu"] = "DropdownMenu";
    UIContextualMenuLayoutType["ContextualMenu"] = "ContextualMenu";
})(UIContextualMenuLayoutType || (exports.UIContextualMenuLayoutType = UIContextualMenuLayoutType = {}));
require("./UIContextualMenu.scss");
const DEFAULT_ZINDEX = 1000000;
/* Method receives callout style and extracts into raw styles object.
 *
 * @param {IStyleFunctionOrObject<ICalloutContentStyleProps, ICalloutContentStyles> | undefined} styles Callout styles.
 * @param {keyof ICalloutContentStyles} name Callout style type.
 * @returns {IRawStyle} Raw style object.
 */
const extractRawStyles = (styles, name) => {
    if (typeof styles === 'object' && typeof styles[name] === 'object') {
        return styles[name];
    }
    return {};
};
const submenuIconProps = { iconName: Icons_1.UiIcons.ArrowDown };
/**
 * ContextualMenu styles prop generator.
 *
 * @returns - consumable styles property for ContextualMenu
 */
function getUIcontextualMenuStyles() {
    return {
        root: {
            minWidth: 190,
            maxWidth: 300,
            background: 'var(--vscode-input-background)',
            border: 0
        }
    };
}
/**
 * ContextualMenu subcomponent styles prop generator.
 *
 * @param props Contextual menu properties.
 * @param currentItemHasSubmenu Item has submenu.
 * @param itemsHaveSubMenu At least one of sibling item has submenu.
 * @returns - consumable styles property for ContextualMenuItem
 */
function getUIContextualMenuItemStyles(props, currentItemHasSubmenu, itemsHaveSubMenu) {
    const { iconToLeft } = props ?? {};
    const padding = {};
    if (iconToLeft && itemsHaveSubMenu) {
        padding.label = currentItemHasSubmenu ? 10 : 19;
        padding.root = '0 3px !important';
    }
    else if (!iconToLeft && currentItemHasSubmenu) {
        padding.rootRight = '3px !important';
    }
    return {
        root: {
            padding: padding.root,
            paddingRight: padding.rootRight
        },
        checkmarkIcon: {
            color: 'var(--vscode-foreground)',
            maxHeight: 18,
            fontSize: 16,
            lineHeight: 18,
            margin: 0
        },
        icon: {
            marginLeft: 0,
            marginRight: 6
        },
        label: {
            lineHeight: 18,
            height: 18,
            paddingLeft: padding.label
        },
        linkContent: {
            fontSize: 13,
            height: 'auto'
        },
        subMenuIcon: {
            height: 16,
            width: 16,
            transform: iconToLeft ? 'rotate(90deg)' : 'rotate(-90deg)',
            transformOrigin: '50% 50%',
            lineHeight: 0
        }
    };
}
/**
 * ContextualMenu sub-component styles prop generator.
 *
 * @param styles External styles of contextual menu.
 * @param maxWidth Maximal width of callout
 * @returns consumable styles property for Callout
 */
function getUIcontextualMenuCalloutStyles(styles, maxWidth) {
    return {
        root: {
            maxWidth: maxWidth,
            ...(styles ? extractRawStyles(styles, 'root') : undefined)
        }
    };
}
/**
 * Recursively applies corresponding styles generator to each,
 * IContextualMenuItem, ICallourProps and IContxualMenuProps item in props tree.
 *
 * @param props Contextual menu properties.
 * @returns - mutated IContextualMenuItem prop with styles props generators applied to each menu tree node
 */
function injectContextualMenuItemsStyle(props) {
    const { items, iconToLeft } = props;
    const renderMenuWithIcons = items.some((item) => item.iconProps);
    const itemsHaveSubMenu = items.some((item) => item.subMenuProps);
    return items.map((item) => {
        if (!item.itemProps) {
            item.itemProps = {};
        }
        const submenu = !!item.subMenuProps;
        if (item.itemProps.styles) {
            item.itemProps.styles = {
                ...getUIContextualMenuItemStyles(props, submenu, itemsHaveSubMenu),
                ...item.itemProps.styles
            };
        }
        else {
            item.itemProps.styles = getUIContextualMenuItemStyles(props, submenu, itemsHaveSubMenu);
        }
        if (!item.submenuIconProps) {
            item.submenuIconProps = submenuIconProps;
        }
        if (item.iconProps || renderMenuWithIcons) {
            item.onRenderContent = (props, renderers) => {
                return (react_1.default.createElement(react_1.default.Fragment, null,
                    renderers.renderItemName(props),
                    item.iconProps && renderers.renderItemIcon(props)));
            };
        }
        else if (iconToLeft) {
            item.onRenderContent = (props, defaultRenders) => {
                return (react_1.default.createElement(react_1.default.Fragment, null,
                    defaultRenders.renderSubMenuIcon(props),
                    defaultRenders.renderCheckMarkIcon(props),
                    defaultRenders.renderItemIcon(props),
                    defaultRenders.renderItemName(props),
                    defaultRenders.renderSecondaryText(props)));
            };
        }
        return item;
    });
}
/**
 * Method returns class names string depending on props and component state.
 *
 * @param props Contextual menu properties.
 * @returns Class names of root element.
 */
function getClassNames(props) {
    const classNames = ['ts-ContextualMenu'];
    const { layoutType = UIContextualMenuLayoutType.DropdownMenu, iconToLeft } = props;
    const layoutClassName = layoutType === UIContextualMenuLayoutType.DropdownMenu
        ? 'ts-ContextualMenu--dropdown'
        : 'ts-ContextualMenu--contextual';
    classNames.push(layoutClassName);
    if (props.className) {
        classNames.push(props.className);
    }
    if (iconToLeft) {
        classNames.push('ts-ContextualMenu--reverse');
    }
    return classNames.join(' ');
}
/**
 * Method returns class names string for callout element depending on props and component state.
 *
 * @param props Contextual menu properties.
 * @param isSubmenu Is submenu.
 * @returns Class names of callout element.
 */
function getCalloutClassName(props, isSubmenu) {
    const classNames = ['ts-ContextualMenu-callout'];
    const { layoutType = UIContextualMenuLayoutType.DropdownMenu } = props;
    const layoutClassName = layoutType === UIContextualMenuLayoutType.DropdownMenu
        ? 'ts-ContextualMenu-callout--dropdown'
        : 'ts-ContextualMenu-callout--contextual';
    classNames.push(layoutClassName);
    if (isSubmenu && props.showSubmenuBeneath) {
        classNames.push('ts-ContextualMenu-callout--submenu-beneath');
    }
    if (props.calloutProps?.className) {
        classNames.push(props.calloutProps.className);
    }
    return classNames.join(' ');
}
const UIContextualMenu = (props) => {
    const { showSubmenuBeneath } = props;
    const zIndex = showSubmenuBeneath ? DEFAULT_ZINDEX - 1 : undefined;
    return (react_1.default.createElement(react_2.ContextualMenu, { isBeakVisible: false, beakWidth: 8, onRenderSubMenu: getSubMenu.bind(undefined, props, zIndex), ...props, className: getClassNames(props), items: injectContextualMenuItemsStyle(props), calloutProps: {
            styles: getUIcontextualMenuCalloutStyles(props.styles, props.maxWidth),
            ...props.calloutProps,
            className: getCalloutClassName(props)
        }, styles: { ...getUIcontextualMenuStyles(), ...props.styles } }));
};
exports.UIContextualMenu = UIContextualMenu;
/**
 * Method returns element for submenu of contextual menu.
 *
 * @param rootMenuProps Root contextual menu props.
 * @param zIndex z-index to apply for layer of submenu.
 * @param subMenuProps Submenu properties.
 * @returns Element for submenu of contextual menu.
 */
function getSubMenu(rootMenuProps, zIndex, subMenuProps) {
    if (!subMenuProps) {
        return null;
    }
    const { iconToLeft } = rootMenuProps;
    const zIndexOfSubmenu = zIndex !== undefined ? zIndex - 1 : undefined;
    return (react_1.default.createElement(exports.UIContextualMenu, { iconToLeft: iconToLeft, ...subMenuProps, calloutProps: {
            gapSpace: 10,
            layerProps: {
                styles: { root: { zIndex } }
            },
            ...subMenuProps.calloutProps,
            className: getCalloutClassName(rootMenuProps, true)
        }, onRenderSubMenu: getSubMenu.bind(undefined, rootMenuProps, zIndexOfSubmenu) }));
}
//# sourceMappingURL=UIContextualMenu.js.map