office-ui-fabric-react
Version:
Reusable React components for building experiences for Office 365.
261 lines (259 loc) • 17 kB
JavaScript
define(["require", "exports", "tslib", "react", "../../Utilities", "../../FocusZone", "../../ContextualMenu", "../../common/DirectionalHint", "../../Icon", "../../Styling", "./CommandBar.scss"], function (require, exports, tslib_1, React, Utilities_1, FocusZone_1, ContextualMenu_1, DirectionalHint_1, Icon_1, Styling_1, stylesImport) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var styles = stylesImport;
var OVERFLOW_KEY = 'overflow';
var OVERFLOW_WIDTH = 41.5;
var CommandBar = (function (_super) {
tslib_1.__extends(CommandBar, _super);
function CommandBar(props) {
var _this = _super.call(this, props) || this;
_this.state = _this._getStateFromProps(props);
_this._id = Utilities_1.getId('CommandBar');
return _this;
}
CommandBar.prototype.componentDidMount = function () {
// Asynchronously update command bar layout to eliminate forced synchronous reflow
this._asyncMeasure();
this._events.on(window, 'resize', this._updateRenderedItems);
};
CommandBar.prototype.componentWillReceiveProps = function (nextProps) {
this.setState(this._getStateFromProps(nextProps));
this._commandItemWidths = null;
};
CommandBar.prototype.componentDidUpdate = function (prevProps, prevStates) {
if (!this._commandItemWidths) {
// Asynchronously update command bar layout to eliminate forced synchronous reflow
this._asyncMeasure();
}
};
CommandBar.prototype.render = function () {
var _this = this;
var _a = this.props, isSearchBoxVisible = _a.isSearchBoxVisible, searchPlaceholderText = _a.searchPlaceholderText, className = _a.className;
var _b = this.state, renderedItems = _b.renderedItems, contextualMenuProps = _b.contextualMenuProps, expandedMenuItemKey = _b.expandedMenuItemKey, expandedMenuId = _b.expandedMenuId, renderedOverflowItems = _b.renderedOverflowItems, contextualMenuTarget = _b.contextualMenuTarget, renderedFarItems = _b.renderedFarItems;
var searchBox;
if (isSearchBoxVisible) {
searchBox = (React.createElement("div", { className: Utilities_1.css('ms-CommandBarSearch', styles.search), ref: 'searchSurface' },
React.createElement("input", { className: Utilities_1.css('ms-CommandBarSearch-input', styles.searchInput), type: 'text', placeholder: searchPlaceholderText }),
React.createElement("div", { className: Utilities_1.css('ms-CommandBarSearch-iconWrapper ms-CommandBarSearch-iconSearchWrapper', styles.searchIconWrapper, styles.searchIconSearchWrapper) }, Icon_1.Icon({ iconName: 'Search' })),
React.createElement("div", { className: Utilities_1.css('ms-CommandBarSearch-iconWrapper ms-CommandBarSearch-iconClearWrapper', Styling_1.FontClassNames.small, styles.searchIconWrapper, styles.searchIconClearWrapper) },
React.createElement(Icon_1.Icon, { iconName: 'cancel' }))));
}
return (React.createElement("div", { className: Utilities_1.css('ms-CommandBar', styles.root, className), ref: 'commandBarRegion' },
searchBox,
React.createElement(FocusZone_1.FocusZone, { ref: 'focusZone', className: styles.container, direction: FocusZone_1.FocusZoneDirection.horizontal, role: 'menubar' },
React.createElement("div", { className: Utilities_1.css('ms-CommandBar-primaryCommands', styles.primaryCommands), ref: 'commandSurface' }, renderedItems.map(function (item, index) { return (_this._renderItemInCommandBar(item, index, expandedMenuItemKey)); }).concat((renderedOverflowItems && renderedOverflowItems.length) ? [
React.createElement("div", { className: Utilities_1.css('ms-CommandBarItem', styles.item), key: OVERFLOW_KEY, ref: OVERFLOW_KEY },
React.createElement("button", { type: 'button', id: this._id + OVERFLOW_KEY, className: Utilities_1.css('ms-CommandBarItem-link', styles.itemLink, (_c = {},
_c['is-expanded ' + styles.itemLinkIsExpanded] = (expandedMenuItemKey === OVERFLOW_KEY),
_c)), onClick: this._onOverflowClick, role: 'menuitem', "aria-label": this.props.elipisisAriaLabel || '', "aria-haspopup": true, "data-automation-id": 'commandBarOverflow' },
React.createElement(Icon_1.Icon, { className: Utilities_1.css('ms-CommandBarItem-overflow', styles.itemOverflow), iconName: 'more' })))
] : [])),
React.createElement("div", { className: Utilities_1.css('ms-CommandBar-sideCommands', styles.sideCommands), ref: 'farCommandSurface' }, renderedFarItems.map(function (item, index) { return (_this._renderItemInCommandBar(item, index, expandedMenuItemKey, true)); }))),
(contextualMenuProps) ?
(React.createElement(ContextualMenu_1.ContextualMenu, tslib_1.__assign({ className: Utilities_1.css('ms-CommandBar-menuHost'), directionalHint: DirectionalHint_1.DirectionalHint.bottomAutoEdge }, contextualMenuProps, { targetElement: contextualMenuTarget, labelElementId: expandedMenuId, onDismiss: this._onContextMenuDismiss }))) : (null)));
var _c;
};
CommandBar.prototype.focus = function () {
this.refs.focusZone.focus();
};
CommandBar.prototype._renderItemInCommandBar = function (item, index, expandedMenuItemKey, isFarItem) {
var _this = this;
if (item.onRender) {
return React.createElement("div", { className: Utilities_1.css('ms-CommandBarItem', styles.item, item.className), key: item.key, ref: item.key }, item.onRender(item));
}
var itemKey = item.key || String(index);
var isLink = item.onClick || ContextualMenu_1.hasSubmenuItems(item);
var className = Utilities_1.css(isLink ? ('ms-CommandBarItem-link ' + styles.itemLink) : ('ms-CommandBarItem-text ' + styles.itemText), !item.name && ('ms-CommandBarItem--noName ' + styles.itemLinkIsNoName), (expandedMenuItemKey === item.key) && ('is-expanded ' + styles.itemLinkIsExpanded));
var hasIcon = !!item.icon || !!item.iconProps;
return React.createElement("div", { className: Utilities_1.css('ms-CommandBarItem', styles.item, item.className), key: itemKey, ref: itemKey }, (function () {
if (isLink) {
return React.createElement("button", tslib_1.__assign({}, Utilities_1.getNativeProps(item, Utilities_1.buttonProperties), { id: _this._id + item.key, className: className, onClick: function (ev) { return _this._onItemClick(ev, item); }, "data-command-key": index, "aria-haspopup": ContextualMenu_1.hasSubmenuItems(item), role: 'menuitem', "aria-label": item.ariaLabel || item.name }),
(hasIcon) ? _this._renderIcon(item) : (null),
(!!item.name) && (React.createElement("span", { className: Utilities_1.css('ms-CommandBarItem-commandText', styles.itemCommandText) }, item.name)),
ContextualMenu_1.hasSubmenuItems(item) ? (React.createElement(Icon_1.Icon, { className: Utilities_1.css('ms-CommandBarItem-chevronDown', styles.itemChevronDown), iconName: 'ChevronDown' })) : (null));
}
else if (item.href) {
return React.createElement("a", tslib_1.__assign({}, Utilities_1.getNativeProps(item, Utilities_1.anchorProperties), { id: _this._id + item.key, className: className, href: item.href, "data-command-key": index, "aria-haspopup": ContextualMenu_1.hasSubmenuItems(item), role: 'menuitem', "aria-label": item.ariaLabel || item.name }),
(hasIcon) ? _this._renderIcon(item) : (null),
(!!item.name) && (React.createElement("span", { className: Utilities_1.css('ms-CommandBarItem-commandText', styles.itemCommandText) }, item.name)));
}
else {
return React.createElement("div", tslib_1.__assign({}, Utilities_1.getNativeProps(item, Utilities_1.divProperties), { id: _this._id + item.key, className: className, "data-command-key": index, "aria-haspopup": ContextualMenu_1.hasSubmenuItems(item) }),
(hasIcon) ? _this._renderIcon(item) : (null),
React.createElement("span", { className: Utilities_1.css('ms-CommandBarItem-commandText', styles.itemCommandText), "aria-hidden": 'true', role: 'presentation' }, item.name));
}
})());
};
CommandBar.prototype._renderIcon = function (item) {
// Only present to allow continued use of item.icon which is deprecated.
var iconProps = item.iconProps ? item.iconProps : {
iconName: item.icon
};
// Use the default icon color for the known icon names
var iconColorClassName = iconProps.iconName === 'None' ? '' : ('ms-CommandBarItem-iconColor ' + styles.itemIconColor);
var iconClassName = Utilities_1.css('ms-CommandBarItem-icon', styles.itemIcon, iconColorClassName, iconProps.className);
return React.createElement(Icon_1.Icon, tslib_1.__assign({}, iconProps, { className: iconClassName }));
};
CommandBar.prototype._asyncMeasure = function () {
var _this = this;
this._async.requestAnimationFrame(function () {
_this._updateItemMeasurements();
_this._updateRenderedItems();
});
};
CommandBar.prototype._updateItemMeasurements = function () {
// the generated width for overflow is 35 in chrome, 38 in IE, but the actual value is 41.5
if (this.refs[OVERFLOW_KEY] || (this.props.overflowItems && this.props.overflowItems.length)) {
this._overflowWidth = OVERFLOW_WIDTH;
}
else {
this._overflowWidth = 0;
}
if (!this._commandItemWidths) {
this._commandItemWidths = {};
}
for (var i = 0; i < this.props.items.length; i++) {
var item = this.props.items[i];
if (!this._commandItemWidths[item.key]) {
var el = this.refs[item.key];
if (el) {
this._commandItemWidths[item.key] = el.getBoundingClientRect().width;
}
}
}
};
CommandBar.prototype._updateRenderedItems = function () {
var _a = this.props, items = _a.items, overflowItems = _a.overflowItems;
var commandSurface = this.refs.commandSurface;
var farCommandSurface = this.refs.farCommandSurface;
var commandBarRegion = this.refs.commandBarRegion;
var searchSurface = this.refs.searchSurface;
var renderedItems = [].concat(items);
var renderedOverflowItems = overflowItems;
var consumedWidth = 0;
var isOverflowVisible = overflowItems && overflowItems.length;
var style = window.getComputedStyle(commandSurface);
var availableWidth = commandBarRegion.clientWidth - parseInt(style.marginLeft, 10) - parseInt(style.marginRight, 10);
if (searchSurface) {
availableWidth -= searchSurface.getBoundingClientRect().width;
}
if (farCommandSurface) {
availableWidth -= farCommandSurface.getBoundingClientRect().width;
}
if (isOverflowVisible) {
availableWidth -= this._overflowWidth;
}
for (var i = 0; i < renderedItems.length; i++) {
var item = renderedItems[i];
var itemWidth = this._commandItemWidths[item.key];
if ((consumedWidth + itemWidth) >= availableWidth) {
if (i > 0 && !isOverflowVisible && (availableWidth - consumedWidth) < OVERFLOW_WIDTH) {
i--;
}
renderedOverflowItems = renderedItems.splice(i).concat(overflowItems);
break;
}
else {
consumedWidth += itemWidth;
}
}
var renderedContextualMenuProps = this._getContextualMenuPropsAfterUpdate(renderedItems.concat(this.state.renderedFarItems), renderedOverflowItems);
this.setState({
renderedItems: renderedItems,
renderedOverflowItems: renderedOverflowItems,
expandedMenuItemKey: renderedContextualMenuProps ? this.state.expandedMenuItemKey : null,
contextualMenuProps: renderedContextualMenuProps,
contextualMenuTarget: renderedContextualMenuProps ? this.state.contextualMenuTarget : null
});
};
CommandBar.prototype._onItemClick = function (ev, item) {
if (item.key === this.state.expandedMenuItemKey || !ContextualMenu_1.hasSubmenuItems(item)) {
this._onContextMenuDismiss();
}
else {
this.setState({
expandedMenuId: ev.currentTarget.id,
expandedMenuItemKey: item.key,
contextualMenuProps: this._getContextualMenuPropsFromItem(item),
contextualMenuTarget: ev.currentTarget
});
}
if (item.onClick) {
item.onClick(ev, item);
}
};
CommandBar.prototype._onOverflowClick = function (ev) {
if (this.state.expandedMenuItemKey === OVERFLOW_KEY) {
this._onContextMenuDismiss();
}
else {
this.setState({
expandedMenuId: ev.currentTarget.id,
expandedMenuItemKey: OVERFLOW_KEY,
contextualMenuProps: { items: this.state.renderedOverflowItems },
contextualMenuTarget: ev.currentTarget
});
}
};
CommandBar.prototype._onContextMenuDismiss = function (ev) {
if (!ev || !ev.relatedTarget || !this.refs.commandSurface.contains(ev.relatedTarget)) {
var contextualMenuProps = this.state.contextualMenuProps;
if (contextualMenuProps && contextualMenuProps.onDismiss) {
this.state.contextualMenuProps.onDismiss(ev);
}
this.setState({
expandedMenuItemKey: null,
contextualMenuProps: null,
contextualMenuTarget: null
});
}
else {
ev.stopPropagation();
ev.preventDefault();
}
};
CommandBar.prototype._getStateFromProps = function (nextProps) {
return {
renderedItems: nextProps.items || [],
renderedOverflowItems: null,
contextualMenuProps: this._getContextualMenuPropsAfterUpdate(nextProps.items.concat(nextProps.farItems), nextProps.overflowItems),
renderedFarItems: nextProps.farItems || null
};
};
CommandBar.prototype._getContextualMenuPropsAfterUpdate = function (renderedItems, overflowItems) {
var _this = this;
if (this.state && this.state.expandedMenuItemKey) {
if (this.state.expandedMenuItemKey === OVERFLOW_KEY) {
// Keep the overflow menu open
return { items: overflowItems };
}
else {
// Find the currently open key in the new props
var matchingItem = renderedItems.filter(function (item) { return item.key === _this.state.expandedMenuItemKey; });
if (matchingItem.length === 1) {
return this._getContextualMenuPropsFromItem(matchingItem[0]);
}
}
}
return null;
};
CommandBar.prototype._getContextualMenuPropsFromItem = function (item) {
return item.subMenuProps || (item.items && { items: item.items });
};
return CommandBar;
}(Utilities_1.BaseComponent));
CommandBar.defaultProps = {
items: [],
overflowItems: [],
farItems: []
};
tslib_1.__decorate([
Utilities_1.autobind
], CommandBar.prototype, "_onOverflowClick", null);
tslib_1.__decorate([
Utilities_1.autobind
], CommandBar.prototype, "_onContextMenuDismiss", null);
exports.CommandBar = CommandBar;
});
//# sourceMappingURL=CommandBar.js.map