define(["require", "exports", "tslib", "react", "../../Utilities", "../../Icon", "../../ContextualMenu", "./BaseButton.classNames", "./SplitButton/SplitButton.classNames"], function (require, exports, tslib_1, React, Utilities_1, Icon_1, ContextualMenu_1, BaseButton_classNames_1, SplitButton_classNames_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var BaseButton = /** @class */ (function (_super) {
        tslib_1.__extends(BaseButton, _super);
        function BaseButton(props, rootClassName) {
            var _this = _super.call(this, props) || this;
            _this._buttonElement = Utilities_1.createRef();
            _this._splitButtonContainer = Utilities_1.createRef();
            _this._onRenderIcon = function (buttonProps, defaultRender) {
                var iconProps = _this.props.iconProps;
                if (iconProps) {
                    return (React.createElement(Icon_1.Icon, tslib_1.__assign({}, iconProps, { className: _this._classNames.icon })));
                }
                return null;
            };
            _this._onRenderTextContents = function () {
                var _a = _this.props, text = _a.text, children = _a.children, description = _a.description, _b = _a.onRenderText, onRenderText = _b === void 0 ? _this._onRenderText : _b, _c = _a.onRenderDescription, onRenderDescription = _c === void 0 ? _this._onRenderDescription : _c;
                if (text || typeof (children) === 'string' || description) {
                    return (React.createElement("div", { className: _this._classNames.textContainer },
                        onRenderText(_this.props, _this._onRenderText),
                        onRenderDescription(_this.props, _this._onRenderDescription)));
                }
                return ([
                    onRenderText(_this.props, _this._onRenderText),
                    onRenderDescription(_this.props, _this._onRenderDescription)
                ]);
            };
            _this._onRenderText = function () {
                var text = _this.props.text;
                var children = _this.props.children;
                // For backwards compat, we should continue to take in the text content from children.
                if (text === undefined && typeof (children) === 'string') {
                    text = children;
                }
                if (text) {
                    return (React.createElement("div", { key: _this._labelId, className: _this._classNames.label, id: _this._labelId }, text));
                }
                return null;
            };
            _this._onRenderChildren = function () {
                var children = _this.props.children;
                // If children is just a string, either it or the text will be rendered via onRenderLabel
                // If children is another component, it will be rendered after text
                if (typeof (children) === 'string') {
                    return null;
                }
                return children;
            };
            _this._onRenderDescription = function (props) {
                var description = props.description;
                // ms-Button-description is only shown when the button type is compound.
                // In other cases it will not be displayed.
                return description ? (React.createElement("div", { key: _this._descriptionId, className: _this._classNames.description, id: _this._descriptionId }, description)) : (null);
            };
            _this._onRenderAriaDescription = function () {
                var ariaDescription = _this.props.ariaDescription;
                // If ariaDescription is given, descriptionId will be assigned to ariaDescriptionSpan,
                // otherwise it will be assigned to descriptionSpan.
                return ariaDescription ? (React.createElement("span", { className: _this._classNames.screenReaderText, id: _this._ariaDescriptionId }, ariaDescription)) : (null);
            };
            _this._onRenderMenuIcon = function (props) {
                var menuIconProps = _this.props.menuIconProps;
                return (React.createElement(Icon_1.Icon, tslib_1.__assign({ iconName: 'ChevronDown' }, menuIconProps, { className: _this._classNames.menuIcon })));
            };
            _this._onRenderMenu = function (menuProps) {
                var _a = menuProps.onDismiss, onDismiss = _a === void 0 ? _this._dismissMenu : _a;
                return (React.createElement(ContextualMenu_1.ContextualMenu, tslib_1.__assign({ id: _this._labelId + '-menu', directionalHint: 4 /* bottomLeftEdge */ }, menuProps, { className: 'ms-BaseButton-menuhost ' + menuProps.className, target: _this._isSplitButton ? _this._splitButtonContainer.value : _this._buttonElement.value, labelElementId: _this._labelId, onDismiss: onDismiss })));
            };
            _this._dismissMenu = function () {
                _this.setState({ menuProps: null });
            };
            _this._openMenu = function () {
                if (_this.props.menuProps) {
                    _this.setState({ menuProps: _this.props.menuProps });
                }
            };
            _this._onToggleMenu = function () {
                if (_this._splitButtonContainer.value) {
                    _this._splitButtonContainer.value.focus();
                }
                var menuProps = _this.props.menuProps;
                var currentMenuProps = _this.state.menuProps;
                currentMenuProps ? _this._dismissMenu() : _this._openMenu();
            };
            _this._onSplitButtonPrimaryClick = function (ev) {
                if (_this._isExpanded) {
                    _this._dismissMenu();
                }
                if (_this.props.onClick) {
                    _this.props.onClick(ev);
                }
            };
            _this._onMouseDown = function (ev) {
                if (_this.props.onMouseDown) {
                    _this.props.onMouseDown(ev);
                }
                ev.preventDefault();
            };
            _this._onSplitButtonContainerKeyDown = function (ev) {
                if (ev.which === 13 /* enter */) {
                    if (_this._buttonElement.value) {
                        _this._buttonElement.value.click();
                        ev.preventDefault();
                        ev.stopPropagation();
                    }
                }
                else {
                    _this._onMenuKeyDown(ev);
                }
            };
            _this._onMenuKeyDown = function (ev) {
                if (_this.props.disabled) {
                    return;
                }
                if (_this.props.onKeyDown) {
                    _this.props.onKeyDown(ev);
                }
                var onMenuClick = _this.props.onMenuClick;
                if (onMenuClick) {
                    onMenuClick(ev, _this);
                }
                if (!ev.defaultPrevented &&
                    _this.props.menuTriggerKeyCode !== null &&
                    _this._isValidMenuOpenKey(ev)) {
                    _this._onToggleMenu();
                    ev.preventDefault();
                    ev.stopPropagation();
                }
            };
            _this._onMenuClick = function (ev) {
                var onMenuClick = _this.props.onMenuClick;
                if (onMenuClick) {
                    onMenuClick(ev, _this);
                }
                if (!ev.defaultPrevented) {
                    _this._onToggleMenu();
                    ev.preventDefault();
                    ev.stopPropagation();
                }
            };
            _this._warnConditionallyRequiredProps(['menuProps', 'onClick'], 'split', _this.props.split);
            _this._warnDeprecations({
                rootProps: undefined
            });
            _this._labelId = Utilities_1.getId();
            _this._descriptionId = Utilities_1.getId();
            _this._ariaDescriptionId = Utilities_1.getId();
            _this.state = {
                menuProps: null
            };
            return _this;
        }
        Object.defineProperty(BaseButton.prototype, "_isSplitButton", {
            get: function () {
                return (!!this.props.menuProps && !!this.props.onClick) && this.props.split === true;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(BaseButton.prototype, "_isExpanded", {
            get: function () {
                return !!this.state.menuProps;
            },
            enumerable: true,
            configurable: true
        });
        BaseButton.prototype.render = function () {
            var _a = this.props, ariaDescription = _a.ariaDescription, ariaLabel = _a.ariaLabel, ariaHidden = _a.ariaHidden, className = _a.className, description = _a.description, disabled = _a.disabled, primaryDisabled = _a.primaryDisabled, href = _a.href, iconProps = _a.iconProps, menuIconProps = _a.menuIconProps, styles = _a.styles, text = _a.text, checked = _a.checked, variantClassName = _a.variantClassName, theme = _a.theme, getClassNames = _a.getClassNames;
            var menuProps = this.state.menuProps;
            // Button is disabled if the whole button (in case of splitbutton is disabled) or if the primary action is disabled
            var isPrimaryButtonDisabled = (disabled || primaryDisabled);
            this._classNames = getClassNames ? getClassNames(theme, className, variantClassName, iconProps && iconProps.className, menuIconProps && menuIconProps.className, isPrimaryButtonDisabled, checked, !!menuProps, this.props.split) : BaseButton_classNames_1.getBaseButtonClassNames(styles, className, variantClassName, iconProps && iconProps.className, menuIconProps && menuIconProps.className, isPrimaryButtonDisabled, checked, !!menuProps, this.props.split);
            var _b = this, _ariaDescriptionId = _b._ariaDescriptionId, _labelId = _b._labelId, _descriptionId = _b._descriptionId;
            // Anchor tag cannot be disabled hence in disabled state rendering
            // anchor button as normal button
            var renderAsAnchor = !isPrimaryButtonDisabled && !!href;
            var tag = renderAsAnchor ? 'a' : 'button';
            var nativeProps = Utilities_1.getNativeProps(Utilities_1.assign(renderAsAnchor ? {} : { type: 'button' }, this.props.rootProps, this.props), renderAsAnchor ? Utilities_1.anchorProperties : Utilities_1.buttonProperties, [
                'disabled' // let disabled buttons be focused and styled as disabled.
            ]);
            // Check for ariaDescription, description or aria-describedby in the native props to determine source of aria-describedby
            // otherwise default to null.
            var ariaDescribedBy;
            if (ariaDescription) {
                ariaDescribedBy = _ariaDescriptionId;
            }
            else if (description) {
                ariaDescribedBy = _descriptionId;
            }
            else if (nativeProps['aria-describedby']) {
                ariaDescribedBy = nativeProps['aria-describedby'];
            }
            else {
                ariaDescribedBy = null;
            }
            // If an explicit ariaLabel is given, use that as the label and we're done.
            // If an explicit aria-labelledby is given, use that and we're done.
            // If any kind of description is given (which will end up as an aria-describedby attribute),
            // set the labelledby element. Otherwise, the button is labeled implicitly by the descendent
            // text on the button (if it exists). Never set both aria-label and aria-labelledby.
            var ariaLabelledBy = null;
            if (!ariaLabel) {
                if (nativeProps['aria-labelledby']) {
                    ariaLabelledBy = nativeProps['aria-labelledby'];
                }
                else if (ariaDescribedBy) {
                    ariaLabelledBy = text ? _labelId : null;
                }
            }
            var buttonProps = Utilities_1.assign(nativeProps, {
                className: this._classNames.root,
                ref: this._buttonElement,
                'disabled': isPrimaryButtonDisabled,
                'aria-label': ariaLabel,
                'aria-labelledby': ariaLabelledBy,
                'aria-describedby': ariaDescribedBy,
                'data-is-focusable': (this.props['data-is-focusable'] === false || disabled || this._isSplitButton) ? false : true,
                'aria-pressed': checked
            });
            if (ariaHidden) {
                buttonProps['aria-hidden'] = true;
            }
            if (this._isSplitButton) {
                return (this._onRenderSplitButtonContent(tag, buttonProps));
            }
            else if (this.props.menuProps) {
                Utilities_1.assign(buttonProps, {
                    'onKeyDown': this._onMenuKeyDown,
                    'onClick': this._onMenuClick,
                    'aria-expanded': this._isExpanded,
                    'aria-owns': this.state.menuProps ? this._labelId + '-menu' : null,
                    'aria-haspopup': true
                });
            }
            return this._onRenderContent(tag, buttonProps);
        };
        BaseButton.prototype.componentDidUpdate = function (prevProps, prevState) {
            // If Button's menu was closed, run onAfterMenuDismiss
            if (this.props.onAfterMenuDismiss && prevState.menuProps && !this.state.menuProps) {
                this.props.onAfterMenuDismiss();
            }
        };
        BaseButton.prototype.focus = function () {
            if (this._isSplitButton && this._splitButtonContainer.value) {
                this._splitButtonContainer.value.focus();
            }
            else if (this._buttonElement.value) {
                this._buttonElement.value.focus();
            }
        };
        BaseButton.prototype.dismissMenu = function () {
            this._dismissMenu();
        };
        BaseButton.prototype.openMenu = function () {
            this._openMenu();
        };
        BaseButton.prototype._onRenderContent = function (tag, buttonProps) {
            var props = this.props;
            var Tag = tag;
            var menuIconProps = props.menuIconProps, menuProps = props.menuProps, _a = props.onRenderIcon, onRenderIcon = _a === void 0 ? this._onRenderIcon : _a, _b = props.onRenderAriaDescription, onRenderAriaDescription = _b === void 0 ? this._onRenderAriaDescription : _b, _c = props.onRenderChildren, onRenderChildren = _c === void 0 ? this._onRenderChildren : _c, _d = props.onRenderMenu, onRenderMenu = _d === void 0 ? this._onRenderMenu : _d, _e = props.onRenderMenuIcon, onRenderMenuIcon = _e === void 0 ? this._onRenderMenuIcon : _e;
            var Content = (React.createElement(Tag, tslib_1.__assign({}, buttonProps),
                React.createElement("div", { className: this._classNames.flexContainer },
                    onRenderIcon(props, this._onRenderIcon),
                    this._onRenderTextContents(),
                    onRenderAriaDescription(props, this._onRenderAriaDescription),
                    onRenderChildren(props, this._onRenderChildren),
                    !this._isSplitButton && (menuProps || menuIconProps || this.props.onRenderMenuIcon) && onRenderMenuIcon(this.props, this._onRenderMenuIcon),
                    this.state.menuProps && !this.state.menuProps.doNotLayer && onRenderMenu(menuProps, this._onRenderMenu))));
            if (menuProps && menuProps.doNotLayer) {
                return (React.createElement("div", { style: { display: 'inline-block' } },
                    Content,
                    this.state.menuProps && onRenderMenu(menuProps, this._onRenderMenu)));
            }
            return Content;
        };
        BaseButton.prototype._onRenderSplitButtonContent = function (tag, buttonProps) {
            var _a = this.props, _b = _a.styles, styles = _b === void 0 ? {} : _b, disabled = _a.disabled, checked = _a.checked, getSplitButtonClassNames = _a.getSplitButtonClassNames, onClick = _a.onClick, primaryDisabled = _a.primaryDisabled;
            var classNames = getSplitButtonClassNames ? getSplitButtonClassNames(!!disabled, !!this.state.menuProps, !!checked) : styles && SplitButton_classNames_1.getClassNames(styles, !!disabled, !!this.state.menuProps, !!checked);
            Utilities_1.assign(buttonProps, {
                onClick: undefined,
                tabIndex: -1,
                'data-is-focusable': false
            });
            return (React.createElement("div", { role: 'button', "aria-labelledby": buttonProps.ariaLabel, "aria-disabled": disabled, "aria-haspopup": true, "aria-expanded": this._isExpanded, "aria-pressed": this.props.checked, "aria-describedby": buttonProps.ariaDescription, className: classNames && classNames.splitButtonContainer, onKeyDown: this._onSplitButtonContainerKeyDown, ref: this._splitButtonContainer, "data-is-focusable": true, onClick: !disabled && !primaryDisabled ? this._onSplitButtonPrimaryClick : undefined, tabIndex: !disabled ? 0 : undefined },
                React.createElement("span", { style: { 'display': 'flex' } },
                    this._onRenderContent(tag, buttonProps),
                    this._onRenderSplitButtonMenuButton(classNames),
                    this._onRenderSplitButtonDivider(classNames))));
        };
        BaseButton.prototype._onRenderSplitButtonDivider = function (classNames) {
            if (classNames && classNames.divider) {
                return React.createElement("span", { className: classNames.divider });
            }
            return null;
        };
        BaseButton.prototype._onRenderSplitButtonMenuButton = function (classNames) {
            var menuIconProps = this.props.menuIconProps;
            var splitButtonAriaLabel = this.props.splitButtonAriaLabel;
            if (menuIconProps === undefined) {
                menuIconProps = {
                    iconName: 'ChevronDown'
                };
            }
            var splitButtonProps = {
                'styles': classNames,
                'checked': this.props.checked,
                'disabled': this.props.disabled,
                'onClick': this._onMenuClick,
                'menuProps': undefined,
                'iconProps': menuIconProps,
                'ariaLabel': splitButtonAriaLabel,
                'aria-haspopup': true,
                'aria-expanded': this._isExpanded,
                'data-is-focusable': false
            };
            return React.createElement(BaseButton, tslib_1.__assign({}, splitButtonProps, { onMouseDown: this._onMouseDown, tabIndex: -1 }));
        };
        /**
         * Returns if the user hits a valid keyboard key to open the menu
         * @param ev - the keyboard event
         * @returns True if user clicks on custom trigger key if enabled or alt + down arrow if not. False otherwise.
         */
        BaseButton.prototype._isValidMenuOpenKey = function (ev) {
            if (this.props.menuTriggerKeyCode) {
                return ev.which === this.props.menuTriggerKeyCode;
            }
            else {
                return ev.which === 40 /* down */ && (ev.altKey || ev.metaKey);
            }
        };
        BaseButton.defaultProps = {
            baseClassName: 'ms-Button',
            classNames: {},
            styles: {},
            split: false,
        };
        return BaseButton;
    }(Utilities_1.BaseComponent));
    exports.BaseButton = BaseButton;
});
//# sourceMappingURL=BaseButton.js.map