office-ui-fabric-react
Version:
Reusable React components for building experiences for Office 365.
673 lines • 35.4 kB
JavaScript
import * as tslib_1 from "tslib";
import * as React from 'react';
import { CommandButton } from '../../Button';
import { Callout } from '../../Callout';
import { Checkbox } from '../../Checkbox';
import { FocusZone, FocusZoneDirection } from '../../FocusZone';
import { Icon } from '../../Icon';
import { KeytipData } from '../../KeytipData';
import { Label } from '../../Label';
import { Panel } from '../../Panel';
import { BaseComponent, createRef, divProperties, findIndex, getFirstFocusable, getId, getLastFocusable, getNativeProps, mergeAriaAttributeValues, classNamesFunction } from '../../Utilities';
import { ResponsiveMode, withResponsiveMode } from '../../utilities/decorators/withResponsiveMode';
import { SelectableOptionMenuItemType } from '../../utilities/selectableOption/SelectableOption.types';
import { DropdownMenuItemType } from './Dropdown.types';
import { DropdownSizePosCache } from './utilities/DropdownSizePosCache';
var getClassNames = classNamesFunction();
var DropdownBase = /** @class */ (function (_super) {
tslib_1.__extends(DropdownBase, _super);
function DropdownBase(props) {
var _this = _super.call(this, props) || this;
_this._host = createRef();
_this._focusZone = createRef();
_this._dropDown = createRef();
_this._scrollIdleDelay = 250 /* ms */;
_this._sizePosCache = new DropdownSizePosCache();
// Render text in dropdown input
_this._onRenderTitle = function (item) {
var _a = _this.props.multiSelectDelimiter, multiSelectDelimiter = _a === void 0 ? ', ' : _a;
var displayTxt = item.map(function (i) { return i.text; }).join(multiSelectDelimiter);
return React.createElement("span", null, displayTxt);
};
// Render placeHolder text in dropdown input
_this._onRenderPlaceHolder = function (props) {
if (!props.placeHolder) {
return null;
}
return React.createElement("span", null, props.placeHolder);
};
// Render Callout or Panel container and pass in list
_this._onRenderContainer = function (props) {
var _a = _this.props, _b = _a.onRenderList, onRenderList = _b === void 0 ? _this._onRenderList : _b, responsiveMode = _a.responsiveMode, calloutProps = _a.calloutProps, panelProps = _a.panelProps, dropdownWidth = _a.dropdownWidth;
var isSmall = responsiveMode <= ResponsiveMode.medium;
return isSmall ? (React.createElement(Panel, tslib_1.__assign({ className: _this._classNames.panel, isOpen: true, isLightDismiss: true, onDismissed: _this._onDismiss, hasCloseButton: false }, panelProps), onRenderList(props, _this._onRenderList))) : (React.createElement(Callout, tslib_1.__assign({ isBeakVisible: false, gapSpace: 0, doNotLayer: false, directionalHintFixed: false, directionalHint: 4 /* bottomLeftEdge */ }, calloutProps, { className: _this._classNames.callout, target: _this._dropDown.current, onDismiss: _this._onDismiss, onScroll: _this._onScroll, onPositioned: _this._onPositioned, calloutWidth: dropdownWidth || (_this._dropDown.current ? _this._dropDown.current.clientWidth : 0) }), onRenderList(props, _this._onRenderList)));
};
// Render Caret Down Icon
_this._onRenderCaretDown = function (props) {
return React.createElement(Icon, { className: _this._classNames.caretDown, iconName: "ChevronDown" });
};
// Render List of items
_this._onRenderList = function (props) {
var _a = _this.props.onRenderItem, onRenderItem = _a === void 0 ? _this._onRenderItem : _a;
var id = _this._id;
var _b = _this.state.selectedIndices, selectedIndices = _b === void 0 ? [] : _b;
return (React.createElement("div", { className: _this._classNames.dropdownItemsWrapper, onKeyDown: _this._onZoneKeyDown, onKeyUp: _this._onZoneKeyUp, ref: _this._host, tabIndex: 0 },
React.createElement(FocusZone, { ref: _this._focusZone, direction: FocusZoneDirection.vertical, defaultActiveElement: selectedIndices[0] !== undefined ? "#" + id + "-list" + selectedIndices[0] : undefined, id: id + '-list', className: _this._classNames.dropdownItems, "aria-labelledby": id + '-label', role: "listbox" }, _this.props.options.map(function (item, index) { return onRenderItem(tslib_1.__assign({}, item, { index: index }), _this._onRenderItem); }))));
};
// Render items
_this._onRenderItem = function (item) {
switch (item.itemType) {
case SelectableOptionMenuItemType.Divider:
return _this._renderSeparator(item);
case SelectableOptionMenuItemType.Header:
return _this._renderHeader(item);
default:
return _this._renderOption(item);
}
};
// Render menu item
_this._renderOption = function (item) {
var _a = _this.props.onRenderOption, onRenderOption = _a === void 0 ? _this._onRenderOption : _a;
var _b = _this.state.selectedIndices, selectedIndices = _b === void 0 ? [] : _b;
var id = _this._id;
var isItemSelected = item.index !== undefined && selectedIndices ? selectedIndices.indexOf(item.index) > -1 : false;
// select the right classname based on the combination of selected/disabled
var itemClassName = isItemSelected && item.disabled === true // preciate: both selected and disabled
? _this._classNames.dropdownItemSelectedAndDisabled
: isItemSelected // preciate: selected only
? _this._classNames.dropdownItemSelected
: item.disabled === true // predicate: disabled only
? _this._classNames.dropdownItemDisabled
: _this._classNames.dropdownItem;
return !_this.props.multiSelect ? (React.createElement(CommandButton, { id: id + '-list' + item.index, key: item.key, "data-index": item.index, "data-is-focusable": !item.disabled, disabled: item.disabled, className: itemClassName, onClick: _this._onItemClick(item), onMouseEnter: _this._onItemMouseEnter.bind(_this, item), onMouseLeave: _this._onMouseItemLeave.bind(_this, item), onMouseMove: _this._onItemMouseMove.bind(_this, item), role: "option", "aria-selected": isItemSelected ? 'true' : 'false', ariaLabel: item.ariaLabel || item.text, title: item.title ? item.title : item.text }, onRenderOption(item, _this._onRenderOption))) : (React.createElement(Checkbox, { id: id + '-list' + item.index, key: item.key, "data-index": item.index, "data-is-focusable": !item.disabled, disabled: item.disabled, onChange: _this._onItemClick(item), inputProps: {
onMouseEnter: _this._onItemMouseEnter.bind(_this, item),
onMouseLeave: _this._onMouseItemLeave.bind(_this, item),
onMouseMove: _this._onItemMouseMove.bind(_this, item)
}, label: item.text, title: item.title ? item.title : item.text, onRenderLabel: _this._onRenderLabel.bind(_this, item), className: itemClassName, role: "option", "aria-selected": isItemSelected ? 'true' : 'false', checked: isItemSelected }));
};
// Render content of item (i.e. text/icon inside of button)
_this._onRenderOption = function (item) {
return React.createElement("span", { className: _this._classNames.dropdownOptionText }, item.text);
};
// Render custom label for drop down item
_this._onRenderLabel = function (item) {
var _a = _this.props.onRenderOption, onRenderOption = _a === void 0 ? _this._onRenderOption : _a;
return onRenderOption(item, _this._onRenderOption);
};
_this._onPositioned = function () {
if (_this._focusZone.current) {
// Focusing an element can trigger a reflow. Making this wait until there is an animation
// frame can improve perf significantly.
_this._async.requestAnimationFrame(function () { return _this._focusZone.current.focus(); });
}
};
_this._onItemClick = function (item) {
return function (event) {
if (!item.disabled) {
_this.setSelectedIndex(event, item.index);
if (!_this.props.multiSelect) {
// only close the callout when it's in single-select mode
_this.setState({
isOpen: false
});
}
}
};
};
/**
* Scroll handler for the callout to make sure the mouse events
* for updating focus are not interacting during scroll
*/
_this._onScroll = function () {
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);
};
_this._onMouseItemLeave = function (item, ev) {
if (_this._shouldIgnoreMouseEvent()) {
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.current) {
if (_this._host.current.setActive) {
try {
_this._host.current.setActive();
}
catch (e) {
/* no-op */
}
}
else {
_this._host.current.focus();
}
}
};
_this._onDismiss = function () {
_this.setState({ isOpen: false });
if (_this._dropDown.current) {
_this._dropDown.current.focus();
}
};
_this._onDropdownBlur = function (ev) {
// hasFocus tracks whether the root element has focus so always update the state.
_this.setState({ hasFocus: false });
if (_this.state.isOpen) {
// Do not onBlur when the callout is opened
return;
}
if (_this.props.onBlur) {
_this.props.onBlur(ev);
}
};
_this._onDropdownKeyDown = function (ev) {
// Take note if we are processing a altKey or metaKey keydown
// so that the menu does not collapse if no other keys are pressed
_this._processingExpandCollapseKeyOnly = _this._isExpandCollapseKey(ev);
if (_this.props.onKeyDown) {
_this.props.onKeyDown(ev);
if (ev.defaultPrevented) {
return;
}
}
var newIndex;
var selectedIndex = _this.state.selectedIndices.length ? _this.state.selectedIndices[0] : -1;
var containsExpandCollapseModifier = ev.altKey || ev.metaKey;
var isOpen = _this.state.isOpen;
switch (ev.which) {
case 13 /* enter */:
_this.setState({
isOpen: !isOpen
});
break;
case 27 /* escape */:
if (!isOpen) {
return;
}
_this.setState({
isOpen: false
});
break;
case 38 /* up */:
if (containsExpandCollapseModifier) {
if (isOpen) {
_this.setState({ isOpen: false });
break;
}
return;
}
if (_this.props.multiSelect) {
_this.setState({ isOpen: true });
}
else if (!_this._isDisabled()) {
newIndex = _this._moveIndex(ev, -1, selectedIndex - 1, selectedIndex);
}
break;
case 40 /* down */:
if (containsExpandCollapseModifier) {
ev.stopPropagation();
ev.preventDefault();
}
if ((containsExpandCollapseModifier && !isOpen) || _this.props.multiSelect) {
_this.setState({ isOpen: true });
}
else if (!_this._isDisabled()) {
newIndex = _this._moveIndex(ev, 1, selectedIndex + 1, selectedIndex);
}
break;
case 36 /* home */:
if (!_this.props.multiSelect) {
newIndex = _this._moveIndex(ev, 1, 0, selectedIndex);
}
break;
case 35 /* end */:
if (!_this.props.multiSelect) {
newIndex = _this._moveIndex(ev, -1, _this.props.options.length - 1, selectedIndex);
}
break;
case 32 /* space */:
// event handled in _onDropdownKeyUp
break;
default:
return;
}
if (newIndex !== selectedIndex) {
ev.stopPropagation();
ev.preventDefault();
}
};
_this._onDropdownKeyUp = function (ev) {
var shouldHandleKey = _this._processingExpandCollapseKeyOnly && _this._isExpandCollapseKey(ev);
_this._processingExpandCollapseKeyOnly = false;
var isOpen = _this.state.isOpen;
if (_this.props.onKeyUp) {
_this.props.onKeyUp(ev);
if (ev.preventDefault) {
return;
}
}
switch (ev.which) {
case 32 /* space */:
_this.setState({
isOpen: !isOpen
});
break;
default:
if (shouldHandleKey && isOpen) {
_this.setState({ isOpen: false });
}
return;
}
ev.stopPropagation();
ev.preventDefault();
};
_this._onZoneKeyDown = function (ev) {
var elementToFocus;
// Take note if we are processing a altKey or metaKey keydown
// so that the menu does not collapse if no other keys are pressed
_this._processingExpandCollapseKeyOnly = _this._isExpandCollapseKey(ev);
var containsExpandCollapseModifier = ev.altKey || ev.metaKey;
switch (ev.which) {
case 38 /* up */:
if (containsExpandCollapseModifier) {
_this.setState({ isOpen: false });
}
else {
if (_this._host.current) {
elementToFocus = getLastFocusable(_this._host.current, _this._host.current.lastChild, true);
}
}
break;
// All directional keystrokes should be canceled when the zone is rendered.
// This avoids the body scroll from reacting and thus dismissing the dropdown.
case 36 /* home */:
case 35 /* end */:
case 33 /* pageUp */:
case 34 /* pageDown */:
break;
case 40 /* down */:
if (!containsExpandCollapseModifier && _this._host.current) {
elementToFocus = getFirstFocusable(_this._host.current, _this._host.current.firstChild, true);
}
break;
case 27 /* escape */:
_this.setState({ isOpen: false });
break;
case 9 /* tab */:
_this.setState({ isOpen: false });
return;
default:
return;
}
if (elementToFocus) {
elementToFocus.focus();
}
ev.stopPropagation();
ev.preventDefault();
};
_this._onZoneKeyUp = function (ev) {
var shouldHandleKey = _this._processingExpandCollapseKeyOnly && _this._isExpandCollapseKey(ev);
_this._processingExpandCollapseKeyOnly = false;
if (shouldHandleKey && _this.state.isOpen) {
_this.setState({ isOpen: false });
ev.preventDefault();
}
};
_this._onDropdownClick = function (ev) {
if (_this.props.onClick) {
_this.props.onClick(ev);
if (ev.preventDefault) {
return;
}
}
var isOpen = _this.state.isOpen;
var disabled = _this._isDisabled();
if (!disabled) {
_this.setState({
isOpen: !isOpen
});
}
};
_this._onFocus = function (ev) {
var _a = _this.state, isOpen = _a.isOpen, selectedIndices = _a.selectedIndices;
var multiSelect = _this.props.multiSelect;
var disabled = _this._isDisabled();
if (!isOpen && selectedIndices.length === 0 && !multiSelect && !disabled) {
// Per aria
_this._moveIndex(ev, 1, 0, -1);
}
_this.setState({ hasFocus: true });
return;
};
/**
* Because the isDisabled prop is deprecated, we have had to repeat this logic all over the place.
* This helper method avoids all the repetition.
*/
_this._isDisabled = function () {
var disabled = _this.props.disabled;
var isDisabled = _this.props.isDisabled;
// Remove this deprecation workaround at 1.0.0
if (isDisabled !== undefined) {
disabled = isDisabled;
}
return disabled;
};
_this._warnDeprecations({
isDisabled: 'disabled',
onChanged: 'onChange'
});
_this._warnMutuallyExclusive({
defaultSelectedKey: 'selectedKey',
defaultSelectedKeys: 'selectedKeys',
selectedKeys: 'selectedKey',
multiSelect: 'defaultSelectedKey',
selectedKey: 'multiSelect'
});
_this._id = props.id || getId('Dropdown');
_this._isScrollIdle = true;
_this._processingExpandCollapseKeyOnly = false;
var selectedIndices;
if (_this.props.multiSelect) {
var selectedKeys = props.defaultSelectedKeys !== undefined ? props.defaultSelectedKeys : props.selectedKeys;
selectedIndices = _this._getSelectedIndexes(props.options, selectedKeys);
}
else {
var selectedKey = props.defaultSelectedKey !== undefined ? props.defaultSelectedKey : props.selectedKey;
selectedIndices = _this._getSelectedIndexes(props.options, selectedKey);
_this._sizePosCache.updateOptions(props.options);
}
_this.state = {
isOpen: false,
selectedIndices: selectedIndices,
hasFocus: false
};
return _this;
}
DropdownBase.prototype.componentWillReceiveProps = function (newProps) {
// In controlled component usage where selectedKey is provided, update the selectedIndex
// state if the key or options change.
var selectedKeyProp = this.props.multiSelect ? 'selectedKeys' : 'selectedKey';
if (newProps[selectedKeyProp] !== undefined &&
(newProps[selectedKeyProp] !== this.props[selectedKeyProp] || newProps.options !== this.props.options)) {
this.setState({
selectedIndices: this._getSelectedIndexes(newProps.options, newProps[selectedKeyProp])
});
}
if (newProps.options !== this.props.options && // preexisting code assumes purity of the options...
!newProps.multiSelect // only relevant in single selection
) {
this._sizePosCache.updateOptions(newProps.options);
}
};
DropdownBase.prototype.componentDidUpdate = function (prevProps, prevState) {
if (prevState.isOpen === true && this.state.isOpen === false) {
this._gotMouseMove = false;
if (this._dropDown.current) {
this._dropDown.current.focus();
}
if (this.props.onDismiss) {
this.props.onDismiss();
}
}
};
// Primary Render
DropdownBase.prototype.render = function () {
var _this = this;
var id = this._id;
var _a = this.props, className = _a.className, label = _a.label, options = _a.options, ariaLabel = _a.ariaLabel, required = _a.required, errorMessage = _a.errorMessage, multiSelect = _a.multiSelect, keytipProps = _a.keytipProps, propStyles = _a.styles, theme = _a.theme, panelProps = _a.panelProps, calloutProps = _a.calloutProps, _b = _a.onRenderTitle, onRenderTitle = _b === void 0 ? this._onRenderTitle : _b, _c = _a.onRenderContainer, onRenderContainer = _c === void 0 ? this._onRenderContainer : _c, _d = _a.onRenderPlaceHolder, onRenderPlaceHolder = _d === void 0 ? this._onRenderPlaceHolder : _d, _e = _a.onRenderCaretDown, onRenderCaretDown = _e === void 0 ? this._onRenderCaretDown : _e;
var _f = this.state, isOpen = _f.isOpen, selectedIndices = _f.selectedIndices, hasFocus = _f.hasFocus;
var selectedOptions = this._getAllSelectedOptions(options, selectedIndices);
var divProps = getNativeProps(this.props, divProperties);
var disabled = this._isDisabled();
var optionId = id + '-option';
var ariaAttrs = multiSelect
? {
role: undefined,
ariaActiveDescendant: undefined,
childRole: undefined,
ariaSetSize: undefined,
ariaPosInSet: undefined,
ariaSelected: undefined
}
: // single select
{
role: 'listbox',
ariaActiveDescendant: isOpen && selectedIndices.length === 1 && selectedIndices[0] >= 0
? this._id + '-list' + selectedIndices[0]
: optionId,
childRole: 'option',
ariaSetSize: this._sizePosCache.optionSetSize,
ariaPosInSet: this._sizePosCache.positionInSet(selectedIndices[0]),
ariaSelected: selectedIndices[0] === undefined ? undefined : true
};
this._classNames = getClassNames(propStyles, {
theme: theme,
className: className,
hasError: Boolean(errorMessage && errorMessage.length > 0),
isOpen: isOpen,
required: required,
disabled: disabled,
isRenderingPlaceholder: !selectedOptions.length,
panelClassName: !!panelProps ? panelProps.className : undefined,
calloutClassName: !!calloutProps ? calloutProps.className : undefined
});
var labelStyles = this._classNames.subComponentStyles
? this._classNames.subComponentStyles.label
: undefined;
return (React.createElement("div", { className: this._classNames.root },
label && (React.createElement(Label, { className: this._classNames.label, id: id + '-label', htmlFor: id, required: required, styles: labelStyles }, label)),
React.createElement(KeytipData, { keytipProps: keytipProps, disabled: disabled }, function (keytipAttributes) { return (React.createElement("div", tslib_1.__assign({}, keytipAttributes, { "data-is-focusable": !disabled, ref: _this._dropDown, id: id, tabIndex: disabled ? -1 : 0, "aria-expanded": isOpen ? 'true' : 'false', role: ariaAttrs.role, "aria-label": ariaLabel, "aria-labelledby": id + '-label', "aria-describedby": mergeAriaAttributeValues(optionId, keytipAttributes['aria-describedby']), "aria-activedescendant": ariaAttrs.ariaActiveDescendant, "aria-disabled": disabled, "aria-owns": isOpen ? id + '-list' : undefined }, divProps, { className: _this._classNames.dropdown, onBlur: _this._onDropdownBlur, onKeyDown: _this._onDropdownKeyDown, onKeyUp: _this._onDropdownKeyUp, onClick: _this._onDropdownClick, onFocus: _this._onFocus }),
React.createElement("span", { id: optionId, className: _this._classNames.title, "aria-atomic": true, role: ariaAttrs.childRole, "aria-live": !hasFocus || disabled || multiSelect || isOpen ? 'off' : 'assertive', "aria-label": selectedOptions.length ? selectedOptions[0].text : _this.props.placeHolder, "aria-setsize": ariaAttrs.ariaSetSize, "aria-posinset": ariaAttrs.ariaPosInSet, "aria-selected": ariaAttrs.ariaSelected }, // If option is selected render title, otherwise render the placeholder text
selectedOptions.length
? onRenderTitle(selectedOptions, _this._onRenderTitle)
: onRenderPlaceHolder(_this.props, _this._onRenderPlaceHolder)),
React.createElement("span", { className: _this._classNames.caretDownWrapper }, onRenderCaretDown(_this.props, _this._onRenderCaretDown)))); }),
isOpen && onRenderContainer(this.props, this._onRenderContainer),
errorMessage && errorMessage.length > 0 && React.createElement("div", { className: this._classNames.errorMessage }, errorMessage)));
};
DropdownBase.prototype.focus = function (shouldOpenOnFocus) {
if (this._dropDown.current && this._dropDown.current.tabIndex !== -1) {
this._dropDown.current.focus();
if (shouldOpenOnFocus) {
this.setState({
isOpen: true
});
}
}
};
DropdownBase.prototype.setSelectedIndex = function (event, index) {
var _a = this.props, onChange = _a.onChange, onChanged = _a.onChanged, options = _a.options, selectedKey = _a.selectedKey, selectedKeys = _a.selectedKeys, multiSelect = _a.multiSelect;
var _b = this.state.selectedIndices, selectedIndices = _b === void 0 ? [] : _b;
var checked = selectedIndices ? selectedIndices.indexOf(index) > -1 : false;
index = Math.max(0, Math.min(options.length - 1, index));
if (!multiSelect && index === selectedIndices[0]) {
return;
}
else if (!multiSelect && selectedKey === undefined) {
// Set the selected option if this is an uncontrolled component
this.setState({
selectedIndices: [index]
});
}
else if (multiSelect && selectedKeys === undefined) {
var newIndexes = selectedIndices ? this._copyArray(selectedIndices) : [];
if (checked) {
var position = newIndexes.indexOf(index);
if (position > -1) {
// unchecked the current one
newIndexes.splice(position, 1);
}
}
else {
// add the new selected index into the existing one
newIndexes.push(index);
}
this.setState({
selectedIndices: newIndexes
});
}
if (onChange) {
// for single-select, option passed in will always be selected.
// for multi-select, flip the checked value
var changedOpt = multiSelect ? tslib_1.__assign({}, options[index], { selected: !checked }) : options[index];
onChange(event, changedOpt, index);
}
if (onChanged) {
// for single-select, option passed in will always be selected.
// for multi-select, flip the checked value
var changedOpt = multiSelect ? tslib_1.__assign({}, options[index], { selected: !checked }) : options[index];
onChanged(changedOpt, index);
}
};
DropdownBase.prototype._copyArray = function (array) {
var newArray = [];
for (var _i = 0, array_1 = array; _i < array_1.length; _i++) {
var element = array_1[_i];
newArray.push(element);
}
return newArray;
};
/**
* Finds the next valid Dropdown option and sets the selected index to it.
* @param stepValue Value of how many items the function should traverse. Should be -1 or 1.
* @param index Index of where the search should start
* @param selectedIndex The selectedIndex Dropdown's state
* @returns The next valid dropdown option's index
*/
DropdownBase.prototype._moveIndex = function (event, stepValue, index, selectedIndex) {
var options = this.props.options;
// Return selectedIndex if nothing has changed or options is empty
if (selectedIndex === index || options.length === 0) {
return selectedIndex;
}
// Set starting index to 0 if index is < 0
if (index < 0) {
index = 0;
}
// Set starting index to last option index if greater than options.length
if (index >= options.length) {
index = options.length - 1;
}
var stepCounter = 0;
// If current index is a header or divider, or disabled, increment by step
while (options[index].itemType === DropdownMenuItemType.Header ||
options[index].itemType === DropdownMenuItemType.Divider ||
options[index].disabled) {
// If stepCounter exceeds length of options, then return selectedIndex (-1)
if (stepCounter >= options.length) {
return selectedIndex;
}
// If index + stepValue is out of bounds, wrap around
if (index + stepValue < 0) {
index = options.length;
}
else if (index + stepValue >= options.length) {
index = -1;
}
index = index + stepValue;
stepCounter++;
}
this.setSelectedIndex(event, index);
return index;
};
// Render separator
DropdownBase.prototype._renderSeparator = function (item) {
var index = item.index, key = item.key;
if (index > 0) {
return React.createElement("div", { role: "separator", key: key, className: this._classNames.dropdownDivider });
}
return null;
};
DropdownBase.prototype._renderHeader = function (item) {
var _a = this.props.onRenderOption, onRenderOption = _a === void 0 ? this._onRenderOption : _a;
var key = item.key;
return (React.createElement("div", { key: key, className: this._classNames.dropdownItemHeader }, onRenderOption(item, this._onRenderOption)));
};
DropdownBase.prototype._onItemMouseEnter = function (item, ev) {
if (this._shouldIgnoreMouseEvent()) {
return;
}
var targetElement = ev.currentTarget;
targetElement.focus();
};
DropdownBase.prototype._onItemMouseMove = function (item, ev) {
var targetElement = ev.currentTarget;
this._gotMouseMove = true;
if (!this._isScrollIdle || document.activeElement === targetElement) {
return;
}
targetElement.focus();
};
DropdownBase.prototype._shouldIgnoreMouseEvent = function () {
return !this._isScrollIdle || !this._gotMouseMove;
};
// Get all selected indexes for multi-select mode
DropdownBase.prototype._getSelectedIndexes = function (options, selectedKey) {
if (selectedKey === undefined) {
if (this.props.multiSelect) {
return this._getAllSelectedIndices(options);
}
var selectedIndex = this._getSelectedIndex(options, null);
return selectedIndex !== -1 ? [selectedIndex] : [];
}
else if (!Array.isArray(selectedKey)) {
return [this._getSelectedIndex(options, selectedKey)];
}
var selectedIndices = [];
for (var _i = 0, selectedKey_1 = selectedKey; _i < selectedKey_1.length; _i++) {
var key = selectedKey_1[_i];
selectedIndices.push(this._getSelectedIndex(options, key));
}
return selectedIndices;
};
// Get all selected options for multi-select mode
DropdownBase.prototype._getAllSelectedOptions = function (options, selectedIndices) {
var selectedOptions = [];
for (var _i = 0, selectedIndices_1 = selectedIndices; _i < selectedIndices_1.length; _i++) {
var index = selectedIndices_1[_i];
var option = options[index];
if (option) {
selectedOptions.push(option);
}
}
return selectedOptions;
};
DropdownBase.prototype._getAllSelectedIndices = function (options) {
return options
.map(function (option, index) { return (option.selected ? index : -1); })
.filter(function (index) { return index !== -1; });
};
DropdownBase.prototype._getSelectedIndex = function (options, selectedKey) {
return findIndex(options, function (option) {
// tslint:disable-next-line:triple-equals
if (selectedKey != null) {
return option.key === selectedKey;
}
else {
return !!option.isSelected || !!option.selected;
}
});
};
DropdownBase.prototype._isExpandCollapseKey = function (ev) {
return ev.which === 18 /* alt */ || ev.key === 'Meta';
};
DropdownBase.defaultProps = {
options: []
};
DropdownBase = tslib_1.__decorate([
withResponsiveMode
], DropdownBase);
return DropdownBase;
}(BaseComponent));
export { DropdownBase };
//# sourceMappingURL=Dropdown.base.js.map