office-ui-fabric-react
Version:
Reusable React components for building experiences for Office 365.
648 lines • 33.7 kB
JavaScript
import * as tslib_1 from "tslib";
import * as React from 'react';
import { ContextualMenuItemType } from './ContextualMenu.types';
import { FocusZone, FocusZoneDirection } from '../../FocusZone';
import { getContextualMenuClassNames, getItemClassNames, getSplitButtonVerticalDividerClassNames } from './ContextualMenu.classNames';
import { BaseComponent, anchorProperties, buttonProperties, getNativeProps, assign, getId, getRTL, autobind, getDocument, getWindow, customizable, getFirstFocusable, getLastFocusable } from '../../Utilities';
import { withResponsiveMode, ResponsiveMode } from '../../utilities/decorators/withResponsiveMode';
import { Callout } from '../../Callout';
import { Icon } from '../../Icon';
import { VerticalDivider } from '../../Divider';
export function hasSubmenu(item) {
return !!(item.subMenuProps || item.items);
}
export function getSubmenuItems(item) {
return item.subMenuProps ? item.subMenuProps.items : item.items;
}
/**
* Determines the effective checked state of a menu item.
*
* @param item {IContextualMenuItem} to get the check state of.
* @returns {true} if the item is checked.
* @returns {false} if the item is unchecked.
* @returns {null} if the item is not checkable.
*/
function getIsChecked(item) {
if (item.canCheck) {
return !!(item.isChecked || item.checked);
}
if (typeof item.isChecked === 'boolean') {
return item.isChecked;
}
if (typeof item.checked === 'boolean') {
return item.checked;
}
// Item is not checkable.
return null;
}
/**
* Returns true if a list of menu items can contain a checkbox
*/
export function canAnyMenuItemsCheck(items) {
return items.some(function (item) {
if (item.canCheck) {
return true;
}
// If the item is a section, check if any of the items in the section can check.
if (item.sectionProps && item.sectionProps.items.some(function (submenuItem) { return submenuItem.canCheck === true; })) {
return true;
}
return false;
});
}
var ContextualMenu = /** @class */ (function (_super) {
tslib_1.__extends(ContextualMenu, _super);
function ContextualMenu(props) {
var _this = _super.call(this, props) || this;
_this._scrollIdleDelay = 250 /* ms */;
_this.state = {
contextualMenuItems: undefined,
subMenuId: getId('ContextualMenu')
};
_this._warnDeprecations({
'targetPoint': 'target',
'useTargetPoint': 'target',
});
_this._isFocusingPreviousElement = false;
_this._isScrollIdle = true;
return _this;
}
ContextualMenu_1 = ContextualMenu;
ContextualMenu.prototype.dismiss = function (ev, dismissAll) {
var onDismiss = this.props.onDismiss;
if (onDismiss) {
onDismiss(ev, dismissAll);
}
};
ContextualMenu.prototype.componentWillUpdate = function (newProps) {
if (newProps.target !== this.props.target) {
var newTarget = 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.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);
if (this.props.onMenuOpened) {
this.props.onMenuOpened(this.props);
}
};
// 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);
}
if (this.props.onMenuDismissed) {
this.props.onMenuDismissed(this.props);
}
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, id = _a.id, targetPoint = _a.targetPoint, useTargetPoint = _a.useTargetPoint, beakWidth = _a.beakWidth, directionalHint = _a.directionalHint, directionalHintForRTL = _a.directionalHintForRTL, gapSpace = _a.gapSpace, coverTarget = _a.coverTarget, ariaLabel = _a.ariaLabel, doNotLayer = _a.doNotLayer, arrowDirection = _a.arrowDirection, target = _a.target, bounds = _a.bounds, useTargetWidth = _a.useTargetWidth, useTargetAsMinWidth = _a.useTargetAsMinWidth, directionalHintFixed = _a.directionalHintFixed, shouldFocusOnMount = _a.shouldFocusOnMount, title = _a.title, customStyles = _a.styles, theme = _a.theme, calloutProps = _a.calloutProps, _b = _a.onRenderSubMenu, onRenderSubMenu = _b === void 0 ? this._onRenderSubMenu : _b;
var menuClassNames = this.props.getMenuClassNames || getContextualMenuClassNames;
this._classNames = menuClassNames(theme, className);
var hasIcons = itemsHaveIcons(items);
function itemsHaveIcons(contextualMenuItems) {
for (var _i = 0, contextualMenuItems_1 = contextualMenuItems; _i < contextualMenuItems_1.length; _i++) {
var item = contextualMenuItems_1[_i];
if (!!item.icon || !!item.iconProps) {
return true;
}
if (item.itemType === ContextualMenuItemType.Section && item.sectionProps && itemsHaveIcons(item.sectionProps.items)) {
return true;
}
}
return false;
}
var hasCheckmarks = canAnyMenuItemsCheck(items);
var submenuProps = this.state.expandedMenuItemKey ? this._getSubmenuProps() : null;
isBeakVisible = isBeakVisible === undefined ? this.props.responsiveMode <= ResponsiveMode.medium : isBeakVisible;
/**
* When useTargetWidth is true, get the width of the target element and apply it for the context menu container
*/
var contextMenuStyle;
var targetAsHtmlElement = this._target;
if ((useTargetWidth || useTargetAsMinWidth) && targetAsHtmlElement && targetAsHtmlElement.offsetWidth) {
var targetWidth = targetAsHtmlElement.offsetWidth;
if (useTargetWidth) {
contextMenuStyle = {
width: targetWidth
};
}
else if (useTargetAsMinWidth) {
contextMenuStyle = {
minWidth: targetWidth
};
}
}
// The menu should only return if items were provided, if no items were provided then it should not appear.
if (items && items.length > 0) {
var indexCorrection_1 = 0;
var totalItemCount_1 = 0;
for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
var item = items_1[_i];
if (item.itemType !== ContextualMenuItemType.Divider &&
item.itemType !== ContextualMenuItemType.Header) {
totalItemCount_1++;
}
}
return (React.createElement(Callout, tslib_1.__assign({}, calloutProps, { target: useTargetPoint ? targetPoint : target, isBeakVisible: isBeakVisible, beakWidth: beakWidth, directionalHint: directionalHint, directionalHintForRTL: directionalHintForRTL, gapSpace: gapSpace, coverTarget: coverTarget, doNotLayer: doNotLayer, className: 'ms-ContextualMenu-Callout', setInitialFocus: shouldFocusOnMount, onDismiss: this.props.onDismiss, onScroll: this._onScroll, bounds: bounds, directionalHintFixed: directionalHintFixed }),
React.createElement("div", { role: 'menu', "aria-label": ariaLabel, "aria-labelledby": labelElementId, style: contextMenuStyle, ref: function (host) { return _this._host = host; }, id: id, className: this._classNames.container, tabIndex: 0, onKeyDown: this._onMenuKeyDown },
title && React.createElement("div", { className: this._classNames.title, role: 'heading', "aria-level": 1 },
" ",
title,
" "),
(items && items.length) ? (React.createElement(FocusZone, { className: this._classNames.root, direction: arrowDirection, isCircularNavigation: true, allowTabKey: true },
React.createElement("ul", { role: 'presentation', className: this._classNames.list, onKeyDown: this._onKeyDown }, items.map(function (item, index) {
if (item.itemType === ContextualMenuItemType.Divider ||
item.itemType === ContextualMenuItemType.Header) {
indexCorrection_1++;
}
return _this._renderMenuItem(item, index, index - indexCorrection_1, totalItemCount_1, hasCheckmarks, hasIcons);
})))) : (null),
submenuProps && onRenderSubMenu(submenuProps, this._onRenderSubMenu))));
}
else {
return null;
}
};
ContextualMenu.prototype._onRenderSubMenu = function (subMenuProps) {
return React.createElement(ContextualMenu_1, tslib_1.__assign({}, subMenuProps));
};
ContextualMenu.prototype._renderMenuItem = function (item, index, focusableElementIndex, totalItemCount, hasCheckmarks, hasIcons) {
var renderedItems = [];
var iconProps = this._getIconProps(item);
// We only send a dividerClassName when the item to be rendered is a divider. For all other cases, the default divider style is used.
var dividerClassName = item.itemType === ContextualMenuItemType.Divider ? item.className : undefined;
var subMenuIconClassName = item.submenuIconProps ? item.submenuIconProps.className : '';
var getClassNames = item.getItemClassNames || getItemClassNames;
var itemClassNames = getClassNames(this.props.theme, this._isItemDisabled(item), (this.state.expandedMenuItemKey === item.key), !!getIsChecked(item), !!item.href, (iconProps.iconName !== 'None'), item.className, dividerClassName, iconProps.className, subMenuIconClassName);
if (item.name === '-') {
item.itemType = ContextualMenuItemType.Divider;
}
switch (item.itemType) {
case ContextualMenuItemType.Divider:
renderedItems.push(this._renderSeparator(index, itemClassNames));
break;
case ContextualMenuItemType.Header:
renderedItems.push(this._renderSeparator(index, itemClassNames));
var headerItem = this._renderHeaderMenuItem(item, itemClassNames, index, hasCheckmarks, hasIcons);
renderedItems.push(this._renderListItem(headerItem, item.key || index, itemClassNames, item.title));
break;
case ContextualMenuItemType.Section:
renderedItems.push(this._renderSectionItem(item, itemClassNames, index, hasCheckmarks, hasIcons));
break;
default:
var menuItem = this._renderNormalItem(item, itemClassNames, index, focusableElementIndex, totalItemCount, hasCheckmarks, hasIcons);
renderedItems.push(this._renderListItem(menuItem, item.key || index, itemClassNames, item.title));
break;
}
return renderedItems;
};
ContextualMenu.prototype._renderSectionItem = function (item, menuClassNames, index, hasCheckmarks, hasIcons) {
var _this = this;
var section = item.sectionProps;
if (!section) {
return;
}
var headerItem;
if (section.title) {
var headerContextualMenuItem = {
key: "section-" + section.title + "-title",
itemType: ContextualMenuItemType.Header,
name: section.title,
};
headerItem = this._renderHeaderMenuItem(headerContextualMenuItem, menuClassNames, index, hasCheckmarks, hasIcons);
}
if (section.items && section.items.length > 0) {
return (React.createElement("li", { role: 'presentation', key: section.key },
React.createElement("div", { role: 'group' },
React.createElement("ul", { className: this._classNames.list },
section.topDivider && this._renderSeparator(index, menuClassNames, true, true),
headerItem && this._renderListItem(headerItem, item.key || index, menuClassNames, item.title),
section.items.map(function (contextualMenuItem, itemsIndex) { return (_this._renderMenuItem(contextualMenuItem, itemsIndex, itemsIndex, section.items.length, hasCheckmarks, hasIcons)); }),
section.bottomDivider && this._renderSeparator(index, menuClassNames, false, true)))));
}
};
ContextualMenu.prototype._renderListItem = function (content, key, classNames, title) {
return (React.createElement("li", { role: 'presentation', title: title, key: key, className: classNames.item }, content));
};
ContextualMenu.prototype._renderSeparator = function (index, classNames, top, fromSection) {
if (fromSection || index > 0) {
return (React.createElement("li", { role: 'separator', key: 'separator-' + index + (top === undefined ? '' : (top ? '-top' : '-bottom')), className: classNames.divider }));
}
return null;
};
ContextualMenu.prototype._renderNormalItem = function (item, classNames, index, focusableElementIndex, totalItemCount, hasCheckmarks, hasIcons) {
if (item.onRender) {
return [item.onRender(item, this.dismiss)];
}
if (item.href) {
return this._renderAnchorMenuItem(item, classNames, index, focusableElementIndex, totalItemCount, hasCheckmarks, hasIcons);
}
if (item.split && hasSubmenu(item)) {
return this._renderSplitButton(item, classNames, index, focusableElementIndex, totalItemCount, hasCheckmarks, hasIcons);
}
return this._renderButtonItem(item, classNames, index, focusableElementIndex, totalItemCount, hasCheckmarks, hasIcons);
};
ContextualMenu.prototype._renderHeaderMenuItem = function (item, classNames, index, hasCheckmarks, hasIcons) {
return (React.createElement("div", { className: this._classNames.header, style: item.style, role: 'heading', "aria-level": this.props.title ? 2 : 1 }, this._renderMenuItemChildren(item, classNames, index, hasCheckmarks, hasIcons)));
};
ContextualMenu.prototype._renderAnchorMenuItem = function (item, classNames, index, focusableElementIndex, totalItemCount, hasCheckmarks, hasIcons) {
return (React.createElement("div", null,
React.createElement("a", tslib_1.__assign({}, getNativeProps(item, anchorProperties), { href: item.href, target: item.target, className: classNames.root, role: 'menuitem', "aria-posinset": focusableElementIndex + 1, "aria-setsize": totalItemCount, "aria-disabled": this._isItemDisabled(item), style: item.style, onClick: this._onAnchorClick.bind(this, item) }), this._renderMenuItemChildren(item, classNames, index, hasCheckmarks, hasIcons))));
};
ContextualMenu.prototype._renderButtonItem = function (item, classNames, index, focusableElementIndex, totalItemCount, 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 isChecked = getIsChecked(item);
var canCheck = isChecked !== null;
var defaultRole = canCheck ? 'menuitemcheckbox' : 'menuitem';
var itemButtonProperties = {
className: classNames.root,
onClick: this._onItemClick.bind(this, item),
onKeyDown: hasSubmenu(item) ? this._onItemKeyDown.bind(this, item) : null,
onMouseEnter: this._onItemMouseEnter.bind(this, item),
onMouseLeave: this._onMouseItemLeave.bind(this, item),
onMouseDown: function (ev) { return _this._onItemMouseDown(item, ev); },
onMouseMove: this._onItemMouseMove.bind(this, item),
disabled: this._isItemDisabled(item),
href: item.href,
title: item.title,
'aria-label': ariaLabel,
'aria-haspopup': hasSubmenu(item) || null,
'aria-owns': item.key === expandedMenuItemKey ? subMenuId : null,
'aria-expanded': hasSubmenu(item) ? item.key === expandedMenuItemKey : null,
'aria-checked': isChecked,
'aria-posinset': focusableElementIndex + 1,
'aria-setsize': totalItemCount,
'aria-disabled': this._isItemDisabled(item),
role: item.role || defaultRole,
style: item.style
};
return (React.createElement("button", tslib_1.__assign({}, getNativeProps(item, buttonProperties), itemButtonProperties, { children: this._renderMenuItemChildren(item, classNames, index, hasCheckmarks, hasIcons) })));
};
ContextualMenu.prototype._renderSplitButton = function (item, classNames, index, focusableElementIndex, totalItemCount, hasCheckmarks, hasIcons) {
return (React.createElement("div", { "aria-labelledby": item.ariaLabel, "aria-disabled": this._isItemDisabled(item), "aria-haspopup": true, "aria-describedby": item.ariaDescription, "aria-checked": item.isChecked || item.checked },
React.createElement("span", { "aria-hidden": true, className: classNames.splitContainer },
this._renderSplitPrimaryButton(item, classNames, index, hasCheckmarks, hasIcons),
this._renderSplitDivider(item),
this._renderSplitIconButton(item, classNames, index))));
};
ContextualMenu.prototype._renderSplitPrimaryButton = function (item, classNames, index, hasCheckmarks, hasIcons) {
var isChecked = getIsChecked(item);
var canCheck = isChecked !== null;
var defaultRole = canCheck ? 'menuitemcheckbox' : 'menuitem';
var itemProps = {
key: item.key,
onClick: this._executeItemClick.bind(this, item),
disabled: this._isItemDisabled(item) || item.primaryDisabled,
name: item.name,
className: classNames.splitPrimary,
role: item.role || defaultRole,
canCheck: item.canCheck,
isChecked: item.isChecked,
checked: item.checked,
icon: item.icon,
iconProps: item.iconProps
};
return React.createElement('button', getNativeProps(itemProps, buttonProperties), this._renderMenuItemChildren(itemProps, classNames, index, hasCheckmarks, hasIcons));
};
ContextualMenu.prototype._renderSplitIconButton = function (item, classNames, index) {
var _this = this;
var itemProps = {
onClick: this._onItemClick.bind(this, item),
disabled: this._isItemDisabled(item),
className: classNames.splitMenu,
subMenuProps: item.subMenuProps,
submenuIconProps: item.submenuIconProps,
split: true,
};
return React.createElement('button', assign({}, getNativeProps(itemProps, buttonProperties), {
onKeyDown: this._onItemKeyDown.bind(this, item),
onMouseEnter: this._onItemMouseEnter.bind(this, item),
onMouseLeave: this._onMouseItemLeave.bind(this, item),
onMouseDown: function (ev) { return _this._onItemMouseDown(item, ev); },
onMouseMove: this._onItemMouseMove.bind(this, item)
}), this._renderMenuItemChildren(itemProps, classNames, index, false, false));
};
ContextualMenu.prototype._renderSplitDivider = function (item) {
var getDividerClassnames = item.getSplitButtonVerticalDividerClassNames || getSplitButtonVerticalDividerClassNames;
return React.createElement(VerticalDivider, { getClassNames: getDividerClassnames });
};
ContextualMenu.prototype._renderMenuItemChildren = function (item, classNames, index, hasCheckmarks, hasIcons) {
var isItemChecked = getIsChecked(item);
return (React.createElement("div", { className: item.split ? classNames.linkContentMenu : classNames.linkContent },
(hasCheckmarks) ? (React.createElement(Icon, { iconName: isItemChecked === true ? 'CheckMark' : '', className: classNames.checkmarkIcon, onClick: this._onItemClick.bind(this, item) })) : (null),
(hasIcons) ? (this._renderIcon(item, classNames)) : (null),
item.name ? (React.createElement("span", { className: classNames.label }, item.name)) : null,
hasSubmenu(item) ? (React.createElement(Icon, tslib_1.__assign({ iconName: getRTL() ? 'ChevronLeft' : 'ChevronRight' }, item.submenuIconProps, { className: classNames.subMenuIcon }))) : (null)));
};
ContextualMenu.prototype._getIconProps = function (item) {
var iconProps = item.iconProps ? item.iconProps : {
iconName: item.icon
};
return iconProps;
};
ContextualMenu.prototype._renderIcon = function (item, classNames) {
// Only present to allow continued use of item.icon which is deprecated.
var iconProps = this._getIconProps(item);
return React.createElement(Icon, tslib_1.__assign({}, iconProps, { className: classNames.icon }));
};
ContextualMenu.prototype._onKeyDown = function (ev) {
var submenuCloseKey = getRTL() ? 39 /* right */ : 37 /* left */;
if (ev.which === 27 /* escape */
|| (ev.which === submenuCloseKey && this.props.isSubMenu && this.props.arrowDirection === 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._onMenuKeyDown = function (ev) {
if (ev.which === 27 /* escape */) {
this._isFocusingPreviousElement = true;
ev.preventDefault();
ev.stopPropagation();
this.dismiss(ev);
return;
}
if (!this._host) {
return;
}
var elementToFocus = ev.which === 38 /* up */ ?
getLastFocusable(this._host, this._host.lastChild, true) :
ev.which === 40 /* down */ ?
getFirstFocusable(this._host, this._host.firstChild, true) :
null;
if (elementToFocus) {
elementToFocus.focus();
ev.preventDefault();
ev.stopPropagation();
}
};
/**
* Scroll handler for the callout to make sure the mouse events
* for updating focus are not interacting during scroll
*/
ContextualMenu.prototype._onScroll = function () {
var _this = this;
if (!this._isScrollIdle && this._scrollIdleTimeoutId !== undefined) {
this._async.clearTimeout(this._scrollIdleTimeoutId);
this._scrollIdleTimeoutId = undefined;
}
else {
this._isScrollIdle = false;
}
this._scrollIdleTimeoutId = this._async.setTimeout(function () { _this._isScrollIdle = true; }, this._scrollIdleDelay);
};
ContextualMenu.prototype._onItemMouseEnter = function (item, ev) {
var _this = this;
if (!this._isScrollIdle) {
return;
}
var targetElement = ev.currentTarget;
if (item.key !== this.state.expandedMenuItemKey) {
if (hasSubmenu(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);
}
}
targetElement.focus();
};
ContextualMenu.prototype._onItemMouseMove = function (item, ev) {
var _this = this;
var targetElement = ev.currentTarget;
if (!this._isScrollIdle || targetElement === this._targetWindow.document.activeElement) {
return;
}
if (item.key !== this.state.expandedMenuItemKey) {
if (hasSubmenu(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);
}
}
targetElement.focus();
};
ContextualMenu.prototype._onMouseItemLeave = function (item, ev) {
if (!this._isScrollIdle) {
return;
}
if (this._enterTimerId !== undefined) {
this._async.clearTimeout(this._enterTimerId);
this._enterTimerId = undefined;
}
if (item.key === this.state.expandedMenuItemKey && hasSubmenu(item)) {
return;
}
/**
* IE11 focus() method forces parents to scroll to top of element.
* Edge and IE expose a setActive() function for focusable divs that
* sets the page focus but does not scroll the parent element.
*/
if (this._host.setActive) {
this._host.setActive();
}
else {
this._host.focus();
}
};
ContextualMenu.prototype._onItemMouseDown = function (item, ev) {
if (item.onMouseDown) {
item.onMouseDown(item, ev);
}
};
ContextualMenu.prototype._onItemClick = function (item, ev) {
var items = getSubmenuItems(item);
if (!hasSubmenu(item) && (!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);
}
else if (this.props.onItemClick) {
this.props.onItemClick(ev, item);
}
!ev.defaultPrevented && this.dismiss(ev, true);
};
ContextualMenu.prototype._onItemKeyDown = function (item, ev) {
var openKey = getRTL() ? 37 /* left */ : 39 /* 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.expandedMenuItemKey) {
this._onSubMenuDismiss();
}
this.setState({
expandedMenuItemKey: item.key,
submenuTarget: target
});
}
};
ContextualMenu.prototype._getSubmenuProps = function () {
var _a = this.state, submenuTarget = _a.submenuTarget, expandedMenuItemKey = _a.expandedMenuItemKey;
var item = this._findItemByKey(expandedMenuItemKey);
var submenuProps = null;
if (item) {
submenuProps = {
items: getSubmenuItems(item),
target: submenuTarget,
onDismiss: this._onSubMenuDismiss,
isSubMenu: true,
id: this.state.subMenuId,
shouldFocusOnMount: true,
directionalHint: getRTL() ? 8 /* leftTopEdge */ : 11 /* rightTopEdge */,
className: this.props.className,
gapSpace: 0,
isBeakVisible: false
};
if (item.subMenuProps) {
assign(submenuProps, item.subMenuProps);
}
}
return submenuProps;
};
ContextualMenu.prototype._findItemByKey = function (key) {
var items = this.props.items;
return this._findItemByKeyFromItems(key, items);
};
/**
* Returns the item that mathes a given key if any.
* @param key The key of the item to match
* @param items The items to look for the key
*/
ContextualMenu.prototype._findItemByKeyFromItems = function (key, items) {
for (var _i = 0, items_2 = items; _i < items_2.length; _i++) {
var item = items_2[_i];
if (item.itemType === ContextualMenuItemType.Section && item.sectionProps) {
var match = this._findItemByKeyFromItems(key, item.sectionProps.items);
if (match) {
return match;
}
}
else if (item.key && item.key === key) {
return item;
}
}
};
ContextualMenu.prototype._onSubMenuDismiss = function (ev, dismissAll) {
if (dismissAll) {
this.dismiss(ev, dismissAll);
}
else {
this.setState({
dismissedMenuItemKey: this.state.expandedMenuItemKey,
expandedMenuItemKey: undefined,
submenuTarget: undefined
});
}
};
ContextualMenu.prototype._setTargetWindowAndElement = function (target) {
if (target) {
if (typeof target === 'string') {
var currentDoc = getDocument();
this._target = currentDoc ? currentDoc.querySelector(target) : null;
this._targetWindow = getWindow();
}
else if (target.stopPropagation) {
this._targetWindow = getWindow(target.toElement);
this._target = target;
}
else if (target.x !== undefined && target.y !== undefined) {
this._targetWindow = getWindow();
this._target = target;
}
else {
var targetElement = target;
this._targetWindow = getWindow(targetElement);
this._target = target;
}
}
else {
this._targetWindow = getWindow();
}
};
ContextualMenu.prototype._isItemDisabled = function (item) {
return !!(item.isDisabled || item.disabled);
};
// The default ContextualMenu properties have no items and beak, the default submenu direction is right and top.
ContextualMenu.defaultProps = {
items: [],
shouldFocusOnMount: true,
gapSpace: 0,
directionalHint: 7 /* bottomAutoEdge */,
beakWidth: 16,
arrowDirection: FocusZoneDirection.vertical,
getMenuClassNames: getContextualMenuClassNames,
};
tslib_1.__decorate([
autobind
], ContextualMenu.prototype, "dismiss", null);
tslib_1.__decorate([
autobind
], ContextualMenu.prototype, "_onKeyDown", null);
tslib_1.__decorate([
autobind
], ContextualMenu.prototype, "_onMenuKeyDown", null);
tslib_1.__decorate([
autobind
], ContextualMenu.prototype, "_onScroll", null);
tslib_1.__decorate([
autobind
], ContextualMenu.prototype, "_onMouseItemLeave", null);
tslib_1.__decorate([
autobind
], ContextualMenu.prototype, "_onSubMenuDismiss", null);
ContextualMenu = ContextualMenu_1 = tslib_1.__decorate([
customizable('ContextualMenu', ['theme']),
withResponsiveMode
], ContextualMenu);
return ContextualMenu;
var ContextualMenu_1;
}(BaseComponent));
export { ContextualMenu };
//# sourceMappingURL=ContextualMenu.js.map