UNPKG

office-ui-fabric-react

Version:

Reusable React components for building experiences for Office 365.

280 lines • 17.3 kB
import * as tslib_1 from "tslib"; import * as React from 'react'; import { BaseComponent, autobind, buttonProperties, anchorProperties, css, divProperties, getId, getNativeProps } from '../../Utilities'; import { FocusZone, FocusZoneDirection } from '../../FocusZone'; import { ContextualMenu } from '../../ContextualMenu'; import { hasSubmenu } from '../../utilities/contextualMenu/index'; import { Icon } from '../../Icon'; import { FontClassNames } from '../../Styling'; import { TooltipHost } from '../../Tooltip'; import * as stylesImport from './CommandBar.scss'; var styles = stylesImport; var OVERFLOW_KEY = 'overflow'; var OVERFLOW_WIDTH = 41.5; var CommandBar = /** @class */ (function (_super) { tslib_1.__extends(CommandBar, _super); function CommandBar(props) { var _this = _super.call(this, props) || this; _this.state = _this._getStateFromProps(props); _this._id = 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: css('ms-CommandBarSearch', styles.search), ref: this._resolveRef('_searchSurface') }, React.createElement("input", { className: css('ms-CommandBarSearch-input', styles.searchInput), type: 'text', placeholder: searchPlaceholderText }), React.createElement("div", { className: css('ms-CommandBarSearch-iconWrapper ms-CommandBarSearch-iconSearchWrapper', styles.searchIconWrapper, styles.searchIconSearchWrapper) }, React.createElement(Icon, { iconName: 'Search' })), React.createElement("div", { className: css('ms-CommandBarSearch-iconWrapper ms-CommandBarSearch-iconClearWrapper', FontClassNames.small, styles.searchIconWrapper, styles.searchIconClearWrapper) }, React.createElement(Icon, { iconName: 'cancel' })))); } // Total # of menu items is regular items + far items + 1 for the ellipsis, if necessary var setSize = renderedItems.length + renderedFarItems.length + (renderedOverflowItems && renderedOverflowItems.length > 0 ? 1 : 0); var posInSet = 1; return (React.createElement("div", { className: css('ms-CommandBar', styles.root, className), ref: this._resolveRef('_commandBarRegion') }, searchBox, React.createElement(FocusZone, { ref: this._resolveRef('_focusZone'), className: styles.container, direction: FocusZoneDirection.horizontal, role: 'menubar' }, React.createElement("div", { className: css('ms-CommandBar-primaryCommands', styles.primaryCommands), ref: this._resolveRef('_commandSurface') }, renderedItems.map(function (item) { return (_this._renderItemInCommandBar(item, posInSet++, setSize, expandedMenuItemKey)); }).concat((renderedOverflowItems && renderedOverflowItems.length) ? [ React.createElement("div", { className: css('ms-CommandBarItem', styles.item), key: OVERFLOW_KEY, ref: this._resolveRef('_overflow') }, React.createElement("button", { type: 'button', id: this._id + OVERFLOW_KEY, className: css('ms-CommandBarItem-link', styles.itemLink, (_c = {}, _c['is-expanded ' + styles.itemLinkIsExpanded] = (expandedMenuItemKey === OVERFLOW_KEY), _c)), onClick: this._onOverflowClick, role: 'menuitem', "aria-expanded": this.state.expandedMenuItemKey === OVERFLOW_KEY, "aria-label": this.props.elipisisAriaLabel || '', "aria-haspopup": true, "aria-setsize": setSize, "aria-posinset": posInSet++, "data-automation-id": 'commandBarOverflow' }, React.createElement(Icon, { className: css('ms-CommandBarItem-overflow', styles.itemOverflow), iconName: 'more' }))) ] : [])), React.createElement("div", { className: css('ms-CommandBar-sideCommands', styles.sideCommands), ref: this._resolveRef('_farCommandSurface') }, renderedFarItems.map(function (item) { return (_this._renderItemInCommandBar(item, posInSet++, setSize, expandedMenuItemKey, true)); }))), (contextualMenuProps) ? (React.createElement(ContextualMenu, tslib_1.__assign({ className: css('ms-CommandBar-menuHost'), directionalHint: 7 /* bottomAutoEdge */ }, contextualMenuProps, { target: contextualMenuTarget, labelElementId: expandedMenuId, onDismiss: this._onContextMenuDismiss }))) : (null))); var _c; }; CommandBar.prototype.focus = function () { this._focusZone.focus(); }; CommandBar.prototype._renderItemInCommandBar = function (item, posInSet, setSize, expandedMenuItemKey, isFarItem) { if (item.onRender) { return (React.createElement("div", { className: css('ms-CommandBarItem', styles.item, item.className), key: item.key, ref: item.key }, item.onRender(item, this._onContextMenuDismiss))); } var itemKey = item.key || String(posInSet); var isLink = item.onClick || hasSubmenu(item); var className = 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; var isNameVisible = !!item.name && !item.iconOnly; var ariaLabel = item.ariaLabel || (item.iconOnly ? item.name : undefined); var command; if (isLink) { command = (React.createElement("button", tslib_1.__assign({}, getNativeProps(item, buttonProperties), { id: this._id + item.key, className: className, onClick: this._onItemClick(item), "data-command-key": itemKey, "aria-haspopup": hasSubmenu(item), "aria-expanded": hasSubmenu(item) ? expandedMenuItemKey === item.key : undefined, role: 'menuitem', "aria-label": ariaLabel, "aria-setsize": setSize, "aria-posinset": posInSet }), (hasIcon) ? this._renderIcon(item) : (null), isNameVisible && (React.createElement("span", { className: css('ms-CommandBarItem-commandText', styles.itemCommandText) }, item.name)), hasSubmenu(item) ? (React.createElement(Icon, { className: css('ms-CommandBarItem-chevronDown', styles.itemChevronDown), iconName: 'ChevronDown' })) : (null))); } else if (item.href) { // Allow the disabled property on anchor elements for commandbar command = (React.createElement("a", tslib_1.__assign({}, getNativeProps(item, anchorProperties.concat(['disabled'])), { id: this._id + item.key, className: className, href: item.disabled ? undefined : item.href, "data-command-key": itemKey, "aria-haspopup": hasSubmenu(item), role: 'menuitem', "aria-label": ariaLabel, "aria-setsize": setSize, "aria-posinset": posInSet }), (hasIcon) ? this._renderIcon(item) : (null), isNameVisible && (React.createElement("span", { className: css('ms-CommandBarItem-commandText', styles.itemCommandText) }, item.name)))); } else { // Allow the disabled property on div elements for commandbar command = (React.createElement("div", tslib_1.__assign({}, getNativeProps(item, divProperties.concat(['disabled'])), { id: this._id + item.key, className: className, "data-command-key": itemKey, "aria-haspopup": hasSubmenu(item), "aria-label": ariaLabel, "aria-setsize": setSize, "aria-posinset": posInSet }), (hasIcon) ? this._renderIcon(item) : (null), (isNameVisible) && (React.createElement("span", { className: css('ms-CommandBarItem-commandText', styles.itemCommandText), "aria-hidden": 'true', role: 'presentation' }, item.name)))); } if (item.iconOnly && item.name) { command = (React.createElement(TooltipHost, { content: item.name }, command)); } return (React.createElement("div", { className: css('ms-CommandBarItem', styles.item, item.className), key: itemKey, ref: itemKey }, command)); }; 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 = css('ms-CommandBarItem-icon', styles.itemIcon, iconColorClassName, iconProps.className); return React.createElement(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._overflow || (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._commandSurface; var farCommandSurface = this._farCommandSurface; var commandBarRegion = this._commandBarRegion; var searchSurface = this._searchSurface; var renderedItems = items.slice(); 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; } if (!this._commandItemWidths) { this._asyncMeasure(); return; } 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 : undefined, contextualMenuProps: renderedContextualMenuProps, contextualMenuTarget: renderedContextualMenuProps ? this.state.contextualMenuTarget : undefined }); }; CommandBar.prototype._onItemClick = function (item) { var _this = this; return function (ev) { if (item.key === _this.state.expandedMenuItemKey || !hasSubmenu(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._commandSurface.contains(ev.relatedTarget)) { var contextualMenuProps = this.state.contextualMenuProps; if (contextualMenuProps && contextualMenuProps.onDismiss) { this.state.contextualMenuProps.onDismiss(ev); } this.setState({ expandedMenuItemKey: undefined, contextualMenuProps: undefined, contextualMenuTarget: undefined }); } else { ev.stopPropagation(); ev.preventDefault(); } }; CommandBar.prototype._getStateFromProps = function (nextProps) { return { renderedItems: nextProps.items || [], contextualMenuProps: this._getContextualMenuPropsAfterUpdate(nextProps.items.concat(nextProps.farItems), nextProps.overflowItems), renderedFarItems: nextProps.farItems || undefined }; }; 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 }); }; CommandBar.defaultProps = { items: [], overflowItems: [], farItems: [] }; tslib_1.__decorate([ autobind ], CommandBar.prototype, "_onOverflowClick", null); tslib_1.__decorate([ autobind ], CommandBar.prototype, "_onContextMenuDismiss", null); return CommandBar; }(BaseComponent)); export { CommandBar }; //# sourceMappingURL=CommandBar.js.map