office-ui-fabric-react
Version:
Reusable React components for building experiences for Office 365.
245 lines • 15.3 kB
JavaScript
define(["require", "exports", "tslib", "react", "../../Utilities", "../../Styling", "../../Icon", "../../common/DirectionalHint", "../../ContextualMenu", "./BaseButton.classNames", "./SplitButton/SplitButton.classNames"], function (require, exports, tslib_1, React, Utilities_1, Styling_1, Icon_1, DirectionalHint_1, ContextualMenu_1, BaseButton_classNames_1, SplitButton_classNames_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var BaseButton = (function (_super) {
tslib_1.__extends(BaseButton, _super);
function BaseButton(props, rootClassName) {
var _this = _super.call(this, props) || this;
_this._warnConditionallyRequiredProps(['menuProps', 'onClick'], 'split', _this.props.split);
_this._warnDeprecations({
rootProps: undefined,
icon: 'iconProps',
menuIconName: 'menuIconProps',
toggled: 'checked'
});
_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, className = _a.className, description = _a.description, disabled = _a.disabled, href = _a.href, iconProps = _a.iconProps, styles = _a.styles, text = _a.text, checked = _a.checked, variantClassName = _a.variantClassName;
this._classNames = BaseButton_classNames_1.getClassNames(styles, className, variantClassName, iconProps && iconProps.className, disabled, checked, !!this.state.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 = !disabled && !!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 tabIndex = (this.props.tabIndex === undefined) ? (this._isSplitButton ? -1 : 0) : this.props.tabIndex;
var buttonProps = Utilities_1.assign(nativeProps, {
className: this._classNames.root,
ref: this._resolveRef('_buttonElement'),
'disabled': disabled,
tabIndex: tabIndex,
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledBy,
'aria-describedby': ariaDescribedBy,
'data-is-focusable': (this.props['data-is-focusable'] === false || disabled) ? false : true,
'aria-pressed': checked
});
if (this._isSplitButton) {
return (this._onRenderSplitButtonContent(tag, buttonProps));
}
else if (this.props.menuProps) {
Utilities_1.assign(buttonProps, {
'onClick': this._onToggleMenu,
'aria-expanded': this._isExpanded,
'aria-owns': this.state.menuProps ? this._labelId + '-menu' : null,
'aria-haspopup': true
});
}
return this._onRenderContent(tag, buttonProps);
};
BaseButton.prototype.focus = function () {
if (this._buttonElement) {
this._buttonElement.focus();
}
};
BaseButton.prototype._onRenderContent = function (tag, buttonProps) {
var props = this.props;
var baseClassName = props.baseClassName, styles = props.styles, menuIconName = props.menuIconName, menuIconProps = props.menuIconProps, menuProps = props.menuProps, _a = props.onRenderIcon, onRenderIcon = _a === void 0 ? this._onRenderIcon : _a, _b = props.onRenderText, onRenderText = _b === void 0 ? this._onRenderText : _b, _c = props.onRenderDescription, onRenderDescription = _c === void 0 ? this._onRenderDescription : _c, _d = props.onRenderAriaDescription, onRenderAriaDescription = _d === void 0 ? this._onRenderAriaDescription : _d, _e = props.onRenderChildren, onRenderChildren = _e === void 0 ? this._onRenderChildren : _e, _f = props.onRenderMenu, onRenderMenu = _f === void 0 ? this._onRenderMenu : _f, _g = props.onRenderMenuIcon, onRenderMenuIcon = _g === void 0 ? this._onRenderMenuIcon : _g;
return React.createElement(tag, buttonProps, React.createElement('div', { className: this._classNames.flexContainer }, onRenderIcon(props, this._onRenderIcon), onRenderText(props, this._onRenderText), onRenderDescription(props, this._onRenderDescription), onRenderAriaDescription(props, this._onRenderAriaDescription), onRenderChildren(props, this._onRenderChildren), !this._isSplitButton && (menuProps || menuIconName || menuIconProps || this.props.onRenderMenuIcon) && onRenderMenuIcon(this.props, this._onRenderMenuIcon), this.state.menuProps && onRenderMenu(menuProps, this._onRenderMenu)));
};
BaseButton.prototype._onRenderIcon = function (buttonProps, defaultRender) {
var _a = this.props, baseClassName = _a.baseClassName, disabled = _a.disabled, icon = _a.icon, iconProps = _a.iconProps, styles = _a.styles, checked = _a.checked;
if (icon || iconProps) {
iconProps = iconProps || {
iconName: icon
};
}
if (iconProps) {
return Icon_1.Icon(tslib_1.__assign({}, iconProps, { className: this._classNames.icon }));
}
return null;
};
BaseButton.prototype._onRenderText = function () {
var _a = this.props, children = _a.children, disabled = _a.disabled, styles = _a.styles, text = _a.text;
// 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("span", { className: this._classNames.label, id: this._labelId }, text));
}
return null;
};
BaseButton.prototype._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;
};
BaseButton.prototype._onRenderDescription = function (props) {
var description = this.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("span", { className: this._classNames.description, id: this._descriptionId }, description)) : (null);
};
BaseButton.prototype._onRenderAriaDescription = function () {
var _a = this.props, ariaDescription = _a.ariaDescription, styles = _a.styles;
// If ariaDescription is given, descriptionId will be assigned to ariaDescriptionSpan,
// otherwise it will be assigned to descriptionSpan.
return ariaDescription ? (React.createElement("span", { className: "" + (styles.screenReaderText || Styling_1.mergeStyles(Styling_1.hideText)), id: this._ariaDescriptionId }, ariaDescription)) : (null);
};
BaseButton.prototype._onRenderMenuIcon = function (props) {
var _a = this.props, baseClassName = _a.baseClassName, checked = _a.checked, disabled = _a.disabled, menuIconName = _a.menuIconName, menuIconProps = _a.menuIconProps;
if (menuIconProps === undefined) {
menuIconProps = {
iconName: menuIconName === undefined ? 'ChevronDown' : menuIconName
};
}
return (menuIconProps ?
React.createElement(Icon_1.Icon, tslib_1.__assign({}, menuIconProps, { className: this._classNames.menuIcon }))
:
null);
};
BaseButton.prototype._onRenderMenu = function (menuProps) {
return (React.createElement(ContextualMenu_1.ContextualMenu, tslib_1.__assign({ id: this._labelId + '-menu', directionalHint: DirectionalHint_1.DirectionalHint.bottomLeftEdge }, menuProps, { className: 'ms-BaseButton-menuhost ' + menuProps.className, target: this._buttonElement, labelElementId: this._labelId, onDismiss: this._onToggleMenu })));
};
BaseButton.prototype._onToggleMenu = function () {
var menuProps = this.props.menuProps;
var currentMenuProps = this.state.menuProps;
this.setState({ menuProps: currentMenuProps ? null : menuProps });
};
BaseButton.prototype._onRenderSplitButtonContent = function (tag, buttonProps) {
var _a = this.props, styles = _a.styles, disabled = _a.disabled;
return (React.createElement("div", { "aria-labelledby": buttonProps.ariaLabel, "aria-disabled": disabled, "aria-haspopup": true, "aria-expanded": this._isExpanded, "aria-pressed": this.props.checked, "aria-describedby": buttonProps.ariaDescription, className: Utilities_1.css(disabled ? styles.splitButtonContainerDisabled : styles.splitButtonContainer), tabIndex: 0, onKeyDown: this.props.disabled ? undefined : this._onSplitButtonKeyDown },
React.createElement("span", { "aria-hidden": true, style: { 'display': 'flex' } },
this._onRenderContent(tag, buttonProps),
this._onRenderSplitButtonMenuButton())));
};
BaseButton.prototype._onRenderSplitButtonMenuButton = function () {
var _a = this.props, menuIconName = _a.menuIconName, menuIconProps = _a.menuIconProps, styles = _a.styles, disabled = _a.disabled, checked = _a.checked;
if (menuIconProps === undefined) {
menuIconProps = {
iconName: menuIconName === undefined ? 'ChevronDown' : menuIconName
};
}
var classNames = styles ? SplitButton_classNames_1.getClassNames(styles, disabled || false, !!this.state.menuProps, checked || false) : undefined;
return (React.createElement(BaseButton, { tabIndex: -1, styles: classNames, checked: this.props.checked, disabled: this.props.disabled, onClick: this._onToggleMenu, menuProps: undefined, iconProps: menuIconProps }));
};
BaseButton.prototype._onSplitButtonKeyDown = function (ev) {
switch (ev.which) {
case 13 /* enter */:
case 32 /* space */:
this.props.onClick(null);
return;
}
if (ev.altKey) {
switch (ev.which) {
case 40 /* down */:
this._onToggleMenu();
return;
}
}
};
BaseButton.defaultProps = {
baseClassName: 'ms-Button',
classNames: {},
styles: {},
split: false
};
tslib_1.__decorate([
Utilities_1.autobind
], BaseButton.prototype, "_onRenderIcon", null);
tslib_1.__decorate([
Utilities_1.autobind
], BaseButton.prototype, "_onRenderText", null);
tslib_1.__decorate([
Utilities_1.autobind
], BaseButton.prototype, "_onRenderChildren", null);
tslib_1.__decorate([
Utilities_1.autobind
], BaseButton.prototype, "_onRenderDescription", null);
tslib_1.__decorate([
Utilities_1.autobind
], BaseButton.prototype, "_onRenderAriaDescription", null);
tslib_1.__decorate([
Utilities_1.autobind
], BaseButton.prototype, "_onRenderMenuIcon", null);
tslib_1.__decorate([
Utilities_1.autobind
], BaseButton.prototype, "_onRenderMenu", null);
tslib_1.__decorate([
Utilities_1.autobind
], BaseButton.prototype, "_onToggleMenu", null);
tslib_1.__decorate([
Utilities_1.autobind
], BaseButton.prototype, "_onSplitButtonKeyDown", null);
return BaseButton;
}(Utilities_1.BaseComponent));
exports.BaseButton = BaseButton;
});
//# sourceMappingURL=BaseButton.js.map