var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var __assign = (this && this.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
define(["require", "exports", "react", "./ContextualMenu.Props", "../../common/DirectionalHint", "../../FocusZone", "../../Utilities", "../../Callout", "../../Icon", "./ContextualMenu.scss"], function (require, exports, React, ContextualMenu_Props_1, DirectionalHint_1, FocusZone_1, Utilities_1, Callout_1, Icon_1, ContextualMenu_scss_1) {
    "use strict";
    var ContextualMenuType;
    (function (ContextualMenuType) {
        ContextualMenuType[ContextualMenuType["vertical"] = 0] = "vertical";
        ContextualMenuType[ContextualMenuType["horizontal"] = 1] = "horizontal";
    })(ContextualMenuType || (ContextualMenuType = {}));
    var HorizontalAlignmentHint;
    (function (HorizontalAlignmentHint) {
        HorizontalAlignmentHint[HorizontalAlignmentHint["auto"] = 0] = "auto";
        HorizontalAlignmentHint[HorizontalAlignmentHint["left"] = 1] = "left";
        HorizontalAlignmentHint[HorizontalAlignmentHint["center"] = 2] = "center";
        HorizontalAlignmentHint[HorizontalAlignmentHint["right"] = 3] = "right";
    })(HorizontalAlignmentHint || (HorizontalAlignmentHint = {}));
    var VerticalAlignmentHint;
    (function (VerticalAlignmentHint) {
        VerticalAlignmentHint[VerticalAlignmentHint["top"] = 0] = "top";
        VerticalAlignmentHint[VerticalAlignmentHint["center"] = 1] = "center";
        VerticalAlignmentHint[VerticalAlignmentHint["bottom"] = 2] = "bottom";
    })(VerticalAlignmentHint || (VerticalAlignmentHint = {}));
    function hasSubmenuItems(item) {
        var submenuItems = getSubmenuItems(item);
        return !!(submenuItems && submenuItems.length);
    }
    exports.hasSubmenuItems = hasSubmenuItems;
    function getSubmenuItems(item) {
        return item.subMenuProps ? item.subMenuProps.items : item.items;
    }
    exports.getSubmenuItems = getSubmenuItems;
    var ContextualMenu = (function (_super) {
        __extends(ContextualMenu, _super);
        function ContextualMenu(props) {
            var _this = _super.call(this, props) || this;
            _this.state = {
                contextualMenuItems: null,
                subMenuId: Utilities_1.getId('ContextualMenu')
            };
            _this._isFocusingPreviousElement = false;
            _this._enterTimerId = 0;
            return _this;
        }
        ContextualMenu.prototype.dismiss = function (ev, dismissAll) {
            var onDismiss = this.props.onDismiss;
            if (onDismiss) {
                onDismiss(ev, dismissAll);
            }
        };
        ContextualMenu.prototype.componentWillUpdate = function (newProps) {
            if (newProps.targetElement !== this.props.targetElement || newProps.target !== this.props.target) {
                var newTarget = newProps.targetElement ? newProps.targetElement : newProps.target;
                this._setTargetWindowAndElement(newTarget);
            }
        };
        // Invoked once, both on the client and server, immediately before the initial rendering occurs.
        ContextualMenu.prototype.componentWillMount = function () {
            var target = this.props.targetElement ? this.props.targetElement : this.props.target;
            this._setTargetWindowAndElement(target);
            this._previousActiveElement = this._targetWindow ? this._targetWindow.document.activeElement : null;
        };
        // Invoked once, only on the client (not on the server), immediately after the initial rendering occurs.
        ContextualMenu.prototype.componentDidMount = function () {
            this._events.on(this._targetWindow, 'resize', this.dismiss);
        };
        // Invoked immediately before a component is unmounted from the DOM.
        ContextualMenu.prototype.componentWillUnmount = function () {
            var _this = this;
            if (this._isFocusingPreviousElement && this._previousActiveElement) {
                // This slight delay is required so that we can unwind the stack, let react try to mess with focus, and then
                // apply the correct focus. Without the setTimeout, we end up focusing the correct thing, and then React wants
                // to reset the focus back to the thing it thinks should have been focused.
                setTimeout(function () { return _this._previousActiveElement.focus(); }, 0);
            }
            this._events.dispose();
            this._async.dispose();
        };
        ContextualMenu.prototype.render = function () {
            var _this = this;
            var _a = this.props, className = _a.className, items = _a.items, isBeakVisible = _a.isBeakVisible, labelElementId = _a.labelElementId, targetElement = _a.targetElement, id = _a.id, targetPoint = _a.targetPoint, useTargetPoint = _a.useTargetPoint, beakWidth = _a.beakWidth, directionalHint = _a.directionalHint, gapSpace = _a.gapSpace, coverTarget = _a.coverTarget, ariaLabel = _a.ariaLabel, doNotLayer = _a.doNotLayer, arrowDirection = _a.arrowDirection, target = _a.target, bounds = _a.bounds, directionalHintFixed = _a.directionalHintFixed, shouldFocusOnMount = _a.shouldFocusOnMount;
            var submenuProps = this.state.submenuProps;
            var hasIcons = !!(items && items.some(function (item) { return !!item.icon || !!item.iconProps; }));
            var hasCheckmarks = !!(items && items.some(function (item) { return !!item.canCheck; }));
            // The menu should only return if items were provided, if no items were provided then it should not appear.
            if (items && items.length > 0) {
                return (React.createElement(Callout_1.Callout, { target: target, targetElement: targetElement, targetPoint: targetPoint, useTargetPoint: useTargetPoint, isBeakVisible: isBeakVisible, beakWidth: beakWidth, directionalHint: directionalHint, gapSpace: gapSpace, coverTarget: coverTarget, doNotLayer: doNotLayer, className: 'ms-ContextualMenu-Callout', setInitialFocus: shouldFocusOnMount, onDismiss: this.props.onDismiss, bounds: bounds, directionalHintFixed: directionalHintFixed },
                    React.createElement("div", { ref: function (host) { return _this._host = host; }, id: id, className: Utilities_1.css('ms-ContextualMenu-container', className) },
                        (items && items.length) ? (React.createElement(FocusZone_1.FocusZone, { className: Utilities_1.css('ms-ContextualMenu is-open', ContextualMenu_scss_1.default.root), direction: arrowDirection, ariaLabelledBy: labelElementId, ref: function (focusZone) { return _this._focusZone = focusZone; }, role: 'menu' },
                            React.createElement("ul", { className: Utilities_1.css('ms-ContextualMenu-list is-open', ContextualMenu_scss_1.default.list), onKeyDown: this._onKeyDown, "aria-label": ariaLabel }, items.map(function (item, index) { return (_this._renderMenuItem(item, index, hasCheckmarks, hasIcons)); })))) : (null),
                        submenuProps ? (React.createElement(ContextualMenu, __assign({}, submenuProps))) : (null))));
            }
            else {
                return null;
            }
        };
        ContextualMenu.prototype._renderMenuItem = function (item, index, hasCheckmarks, hasIcons) {
            var renderedItems = [];
            if (item.name === '-') {
                item.itemType = ContextualMenu_Props_1.ContextualMenuItemType.Divider;
            }
            switch (item.itemType) {
                case ContextualMenu_Props_1.ContextualMenuItemType.Divider:
                    renderedItems.push(this._renderSeparator(index, item.className));
                    break;
                case ContextualMenu_Props_1.ContextualMenuItemType.Header:
                    renderedItems.push(this._renderSeparator(index));
                    var headerItem = this._renderHeaderMenuItem(item, index, hasCheckmarks, hasIcons);
                    renderedItems.push(this._renderListItem(headerItem, item.key || index, item.className, item.title));
                    break;
                default:
                    var menuItem = this._renderNormalItem(item, index, hasCheckmarks, hasIcons);
                    renderedItems.push(this._renderListItem(menuItem, item.key || index, item.className, item.title));
                    break;
            }
            return renderedItems;
        };
        ContextualMenu.prototype._renderListItem = function (content, key, className, title) {
            return React.createElement("li", { role: 'menuitem', title: title, key: key, className: Utilities_1.css('ms-ContextualMenu-item', ContextualMenu_scss_1.default.item, className) }, content);
        };
        ContextualMenu.prototype._renderSeparator = function (index, className) {
            if (index > 0) {
                return React.createElement("li", { role: 'separator', key: 'separator-' + index, className: Utilities_1.css('ms-ContextualMenu-divider', ContextualMenu_scss_1.default.divider, className) });
            }
            return null;
        };
        ContextualMenu.prototype._renderNormalItem = function (item, index, hasCheckmarks, hasIcons) {
            if (item.onRender) {
                return [item.onRender(item)];
            }
            if (item.href) {
                return this._renderAnchorMenuItem(item, index, hasCheckmarks, hasIcons);
            }
            return this._renderButtonItem(item, index, hasCheckmarks, hasIcons);
        };
        ContextualMenu.prototype._renderHeaderMenuItem = function (item, index, hasCheckmarks, hasIcons) {
            return (React.createElement("div", { className: Utilities_1.css('ms-ContextualMenu-header', ContextualMenu_scss_1.default.header), style: item.style }, this._renderMenuItemChildren(item, index, hasCheckmarks, hasIcons)));
        };
        ContextualMenu.prototype._renderAnchorMenuItem = function (item, index, hasCheckmarks, hasIcons) {
            return (React.createElement("div", null,
                React.createElement("a", __assign({}, Utilities_1.getNativeProps(item, Utilities_1.anchorProperties), { href: item.href, className: Utilities_1.css('ms-ContextualMenu-link', ContextualMenu_scss_1.default.link, (item.isDisabled || item.disabled) && 'is-disabled'), role: 'menuitem', style: item.style, onClick: this._onAnchorClick.bind(this, item) }),
                    (hasIcons) ? (this._renderIcon(item)) : (null),
                    React.createElement("span", { className: Utilities_1.css('ms-ContextualMenu-linkText', ContextualMenu_scss_1.default.linkText) },
                        " ",
                        item.name,
                        " "))));
        };
        ContextualMenu.prototype._renderButtonItem = function (item, index, hasCheckmarks, hasIcons) {
            var _this = this;
            var _a = this.state, expandedMenuItemKey = _a.expandedMenuItemKey, subMenuId = _a.subMenuId;
            var ariaLabel = '';
            if (item.ariaLabel) {
                ariaLabel = item.ariaLabel;
            }
            else if (item.name) {
                ariaLabel = item.name;
            }
            var itemButtonProperties = {
                className: Utilities_1.css('ms-ContextualMenu-link', ContextualMenu_scss_1.default.link, (_b = {},
                    _b['is-expanded ' + ContextualMenu_scss_1.default.isExpanded] = (expandedMenuItemKey === item.key),
                    _b)),
                onClick: this._onItemClick.bind(this, item),
                onKeyDown: hasSubmenuItems(item) ? this._onItemKeyDown.bind(this, item) : null,
                onMouseEnter: this._onItemMouseEnter.bind(this, item),
                onMouseLeave: this._onMouseLeave,
                onMouseDown: function (ev) { return _this._onItemMouseDown(item, ev); },
                disabled: item.isDisabled || item.disabled,
                role: 'menuitem',
                href: item.href,
                title: item.title,
                'aria-label': ariaLabel,
                'aria-haspopup': hasSubmenuItems(item) ? true : null,
                'aria-owns': item.key === expandedMenuItemKey ? subMenuId : null,
                style: item.style,
            };
            return React.createElement('button', Utilities_1.assign({}, Utilities_1.getNativeProps(item, Utilities_1.buttonProperties), itemButtonProperties), this._renderMenuItemChildren(item, index, hasCheckmarks, hasIcons));
            var _b;
        };
        ContextualMenu.prototype._renderMenuItemChildren = function (item, index, hasCheckmarks, hasIcons) {
            var isItemChecked = item.isChecked || item.checked;
            return (React.createElement("div", { className: Utilities_1.css('ms-ContextualMenu-linkContent', ContextualMenu_scss_1.default.linkContent) },
                (hasCheckmarks) ? (React.createElement(Icon_1.Icon, { iconName: isItemChecked ? 'CheckMark' : 'CustomIcon', className: Utilities_1.css('ms-ContextualMenu-icon', ContextualMenu_scss_1.default.icon), onClick: this._onItemClick.bind(this, item) })) : (null),
                (hasIcons) ? (this._renderIcon(item)) : (null),
                React.createElement("span", { className: Utilities_1.css('ms-ContextualMenu-itemText', ContextualMenu_scss_1.default.itemText) }, item.name),
                hasSubmenuItems(item) ? (React.createElement(Icon_1.Icon, __assign({ iconName: Utilities_1.getRTL() ? 'ChevronLeft' : 'ChevronRight' }, item.submenuIconProps, { className: Utilities_1.css('ms-ContextualMenu-submenuIcon', ContextualMenu_scss_1.default.submenuIcon, item.submenuIconProps ? item.submenuIconProps.className : '') }))) : (null)));
        };
        ContextualMenu.prototype._renderIcon = function (item) {
            // Only present to allow continued use of item.icon which is deprecated.
            var iconProps = item.iconProps ? item.iconProps : {
                iconName: 'CustomIcon',
                className: item.icon ? 'ms-Icon--' + item.icon : ''
            };
            // Use the default icon color for the known icon names
            var iconColorClassName = iconProps.iconName === 'None' ? '' : ('ms-ContextualMenu-iconColor ' + ContextualMenu_scss_1.default.iconColor);
            var iconClassName = Utilities_1.css('ms-ContextualMenu-icon', ContextualMenu_scss_1.default.icon, iconColorClassName, iconProps.className);
            return React.createElement(Icon_1.Icon, __assign({}, iconProps, { className: iconClassName }));
        };
        ContextualMenu.prototype._onKeyDown = function (ev) {
            var submenuCloseKey = Utilities_1.getRTL() ? Utilities_1.KeyCodes.right : Utilities_1.KeyCodes.left;
            if (ev.which === Utilities_1.KeyCodes.escape
                || ev.which === Utilities_1.KeyCodes.tab
                || (ev.which === submenuCloseKey && this.props.isSubMenu && this.props.arrowDirection === FocusZone_1.FocusZoneDirection.vertical)) {
                // When a user presses escape, we will try to refocus the previous focused element.
                this._isFocusingPreviousElement = true;
                ev.preventDefault();
                ev.stopPropagation();
                this.dismiss(ev);
            }
        };
        ContextualMenu.prototype._onItemMouseEnter = function (item, ev) {
            var _this = this;
            var targetElement = ev.currentTarget;
            if (item.key !== this.state.expandedMenuItemKey) {
                if (hasSubmenuItems(item)) {
                    this._enterTimerId = this._async.setTimeout(function () { return _this._onItemSubMenuExpand(item, targetElement); }, 500);
                }
                else {
                    this._enterTimerId = this._async.setTimeout(function () { return _this._onSubMenuDismiss(ev); }, 500);
                }
            }
        };
        ContextualMenu.prototype._onMouseLeave = function (ev) {
            this._async.clearTimeout(this._enterTimerId);
        };
        ContextualMenu.prototype._onItemMouseDown = function (item, ev) {
            if (item.onMouseDown) {
                item.onMouseDown(item, ev);
            }
        };
        ContextualMenu.prototype._onItemClick = function (item, ev) {
            var items = getSubmenuItems(item);
            if (!items || !items.length) {
                this._executeItemClick(item, ev);
            }
            else {
                if (item.key === this.state.expandedMenuItemKey) {
                    this._onSubMenuDismiss(ev);
                }
                else {
                    this._onItemSubMenuExpand(item, ev.currentTarget);
                }
            }
            ev.stopPropagation();
            ev.preventDefault();
        };
        ContextualMenu.prototype._onAnchorClick = function (item, ev) {
            this._executeItemClick(item, ev);
            ev.stopPropagation();
        };
        ContextualMenu.prototype._executeItemClick = function (item, ev) {
            if (item.onClick) {
                item.onClick(ev, item);
            }
            this.dismiss(ev, true);
        };
        ContextualMenu.prototype._onItemKeyDown = function (item, ev) {
            var openKey = Utilities_1.getRTL() ? Utilities_1.KeyCodes.left : Utilities_1.KeyCodes.right;
            if (ev.which === openKey) {
                this._onItemSubMenuExpand(item, ev.currentTarget);
                ev.preventDefault();
            }
        };
        ContextualMenu.prototype._onItemSubMenuExpand = function (item, target) {
            if (this.state.expandedMenuItemKey !== item.key) {
                if (this.state.submenuProps) {
                    this._onSubMenuDismiss();
                }
                var submenuProps = {
                    items: getSubmenuItems(item),
                    target: target,
                    onDismiss: this._onSubMenuDismiss,
                    isSubMenu: true,
                    id: this.state.subMenuId,
                    shouldFocusOnMount: true,
                    directionalHint: Utilities_1.getRTL() ? DirectionalHint_1.DirectionalHint.leftTopEdge : DirectionalHint_1.DirectionalHint.rightTopEdge,
                    className: this.props.className,
                    gapSpace: 0
                };
                if (item.subMenuProps) {
                    Utilities_1.assign(submenuProps, item.subMenuProps);
                }
                this.setState({
                    expandedMenuItemKey: item.key,
                    submenuProps: submenuProps,
                });
            }
        };
        ContextualMenu.prototype._onSubMenuDismiss = function (ev, dismissAll) {
            if (dismissAll) {
                this.dismiss(ev, dismissAll);
            }
            else {
                this.setState({
                    dismissedMenuItemKey: this.state.expandedMenuItemKey,
                    expandedMenuItemKey: null,
                    submenuProps: null
                });
            }
        };
        ContextualMenu.prototype._setTargetWindowAndElement = function (target) {
            if (target) {
                if (typeof target === 'string') {
                    var currentDoc = Utilities_1.getDocument();
                    this._target = currentDoc ? currentDoc.querySelector(target) : null;
                    this._targetWindow = Utilities_1.getWindow();
                }
                else if (target.stopPropagation) {
                    this._target = target;
                    this._targetWindow = Utilities_1.getWindow(target.toElement);
                }
                else {
                    var targetElement = target;
                    this._target = target;
                    this._targetWindow = Utilities_1.getWindow(targetElement);
                }
            }
            else {
                this._targetWindow = Utilities_1.getWindow();
            }
        };
        return ContextualMenu;
    }(Utilities_1.BaseComponent));
    // The default ContextualMenu properities have no items and beak, the default submenu direction is right and top.
    ContextualMenu.defaultProps = {
        items: [],
        shouldFocusOnMount: true,
        isBeakVisible: false,
        gapSpace: 0,
        directionalHint: DirectionalHint_1.DirectionalHint.bottomAutoEdge,
        beakWidth: 16,
        arrowDirection: FocusZone_1.FocusZoneDirection.vertical,
    };
    __decorate([
        Utilities_1.autobind
    ], ContextualMenu.prototype, "dismiss", null);
    __decorate([
        Utilities_1.autobind
    ], ContextualMenu.prototype, "_onKeyDown", null);
    __decorate([
        Utilities_1.autobind
    ], ContextualMenu.prototype, "_onMouseLeave", null);
    __decorate([
        Utilities_1.autobind
    ], ContextualMenu.prototype, "_onSubMenuDismiss", null);
    exports.ContextualMenu = ContextualMenu;
});

//# sourceMappingURL=ContextualMenu.js.map
