UNPKG

office-ui-fabric-react

Version:

Reusable React components for building experiences for Microsoft 365.

395 lines • 21.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var React = require("react"); var Utilities_1 = require("../../../Utilities"); var SuggestionsCore_1 = require("./SuggestionsCore"); var stylesImport = require("./SuggestionsControl.scss"); var Styling_1 = require("../../../Styling"); var styles = stylesImport; var SuggestionItemType; (function (SuggestionItemType) { SuggestionItemType[SuggestionItemType["header"] = 0] = "header"; SuggestionItemType[SuggestionItemType["suggestion"] = 1] = "suggestion"; SuggestionItemType[SuggestionItemType["footer"] = 2] = "footer"; })(SuggestionItemType = exports.SuggestionItemType || (exports.SuggestionItemType = {})); var SuggestionsHeaderFooterItem = /** @class */ (function (_super) { tslib_1.__extends(SuggestionsHeaderFooterItem, _super); function SuggestionsHeaderFooterItem(props) { var _this = _super.call(this, props) || this; Utilities_1.initializeComponentRef(_this); return _this; } SuggestionsHeaderFooterItem.prototype.render = function () { var _a; var _b = this.props, renderItem = _b.renderItem, onExecute = _b.onExecute, isSelected = _b.isSelected, id = _b.id, className = _b.className; return onExecute ? (React.createElement("div", { id: id, onClick: onExecute, className: Utilities_1.css('ms-Suggestions-sectionButton', className, styles.actionButton, (_a = {}, _a['is-selected ' + styles.buttonSelected] = isSelected, _a)) }, renderItem())) : (React.createElement("div", { id: id, className: Utilities_1.css('ms-Suggestions-section', className, styles.suggestionsTitle) }, renderItem())); }; return SuggestionsHeaderFooterItem; }(React.Component)); exports.SuggestionsHeaderFooterItem = SuggestionsHeaderFooterItem; /** * Class when used with SuggestionsStore, renders a suggestions control with customizable headers and footers */ var SuggestionsControl = /** @class */ (function (_super) { tslib_1.__extends(SuggestionsControl, _super); function SuggestionsControl(suggestionsProps) { var _this = _super.call(this, suggestionsProps) || this; _this._selectedElement = React.createRef(); _this._suggestions = React.createRef(); _this.SuggestionsOfProperType = SuggestionsCore_1.SuggestionsCore; Utilities_1.initializeComponentRef(_this); _this.state = { selectedHeaderIndex: -1, selectedFooterIndex: -1, suggestions: suggestionsProps.suggestions, }; return _this; } SuggestionsControl.prototype.componentDidMount = function () { this.resetSelectedItem(); }; SuggestionsControl.prototype.componentDidUpdate = function () { this.scrollSelected(); }; SuggestionsControl.prototype.UNSAFE_componentWillReceiveProps = function (newProps) { var _this = this; if (newProps.suggestions) { this.setState({ suggestions: newProps.suggestions }, function () { _this.resetSelectedItem(); }); } }; SuggestionsControl.prototype.componentWillUnmount = function () { var _a; (_a = this._suggestions.current) === null || _a === void 0 ? void 0 : _a.deselectAllSuggestions(); }; SuggestionsControl.prototype.render = function () { var _a = this.props, className = _a.className, headerItemsProps = _a.headerItemsProps, footerItemsProps = _a.footerItemsProps, suggestionsAvailableAlertText = _a.suggestionsAvailableAlertText; var screenReaderTextStyles = Styling_1.mergeStyles(Styling_1.hiddenContentStyle); var shouldAlertSuggestionsAvailableText = this.state.suggestions && this.state.suggestions.length > 0 && suggestionsAvailableAlertText; return (React.createElement("div", { className: Utilities_1.css('ms-Suggestions', className ? className : '', styles.root) }, headerItemsProps && this.renderHeaderItems(), this._renderSuggestions(), footerItemsProps && this.renderFooterItems(), shouldAlertSuggestionsAvailableText ? (React.createElement("span", { role: "alert", "aria-live": "polite", className: screenReaderTextStyles }, suggestionsAvailableAlertText)) : null)); }; Object.defineProperty(SuggestionsControl.prototype, "currentSuggestion", { get: function () { var _a; return ((_a = this._suggestions.current) === null || _a === void 0 ? void 0 : _a.getCurrentItem()) || undefined; }, enumerable: true, configurable: true }); Object.defineProperty(SuggestionsControl.prototype, "currentSuggestionIndex", { get: function () { return this._suggestions.current ? this._suggestions.current.currentIndex : -1; }, enumerable: true, configurable: true }); Object.defineProperty(SuggestionsControl.prototype, "selectedElement", { get: function () { var _a; return this._selectedElement.current ? this._selectedElement.current : (_a = this._suggestions.current) === null || _a === void 0 ? void 0 : _a.selectedElement; }, enumerable: true, configurable: true }); SuggestionsControl.prototype.hasSuggestionSelected = function () { var _a; return ((_a = this._suggestions.current) === null || _a === void 0 ? void 0 : _a.hasSuggestionSelected()) || false; }; SuggestionsControl.prototype.hasSelection = function () { var _a = this.state, selectedHeaderIndex = _a.selectedHeaderIndex, selectedFooterIndex = _a.selectedFooterIndex; return selectedHeaderIndex !== -1 || this.hasSuggestionSelected() || selectedFooterIndex !== -1; }; SuggestionsControl.prototype.executeSelectedAction = function () { var _a; var _b = this.props, headerItemsProps = _b.headerItemsProps, footerItemsProps = _b.footerItemsProps; var _c = this.state, selectedHeaderIndex = _c.selectedHeaderIndex, selectedFooterIndex = _c.selectedFooterIndex; if (headerItemsProps && selectedHeaderIndex !== -1 && selectedHeaderIndex < headerItemsProps.length) { var selectedHeaderItem = headerItemsProps[selectedHeaderIndex]; if (selectedHeaderItem.onExecute) { selectedHeaderItem.onExecute(); } } else if ((_a = this._suggestions.current) === null || _a === void 0 ? void 0 : _a.hasSuggestionSelected()) { this.props.completeSuggestion(); } else if (footerItemsProps && selectedFooterIndex !== -1 && selectedFooterIndex < footerItemsProps.length) { var selectedFooterItem = footerItemsProps[selectedFooterIndex]; if (selectedFooterItem.onExecute) { selectedFooterItem.onExecute(); } } }; SuggestionsControl.prototype.removeSuggestion = function (index) { var _a, _b; (_a = this._suggestions.current) === null || _a === void 0 ? void 0 : _a.removeSuggestion(index ? index : (_b = this._suggestions.current) === null || _b === void 0 ? void 0 : _b.currentIndex); }; /** * Handles the key down, returns true, if the event was handled, false otherwise * @param keyCode - The keyCode to handle */ SuggestionsControl.prototype.handleKeyDown = function (keyCode) { var _a, _b, _c, _d; var _e = this.state, selectedHeaderIndex = _e.selectedHeaderIndex, selectedFooterIndex = _e.selectedFooterIndex; var isKeyDownHandled = false; if (keyCode === Utilities_1.KeyCodes.down) { if (selectedHeaderIndex === -1 && !((_a = this._suggestions.current) === null || _a === void 0 ? void 0 : _a.hasSuggestionSelected()) && selectedFooterIndex === -1) { this.selectFirstItem(); } else if (selectedHeaderIndex !== -1) { this.selectNextItem(SuggestionItemType.header); isKeyDownHandled = true; } else if ((_b = this._suggestions.current) === null || _b === void 0 ? void 0 : _b.hasSuggestionSelected()) { this.selectNextItem(SuggestionItemType.suggestion); isKeyDownHandled = true; } else if (selectedFooterIndex !== -1) { this.selectNextItem(SuggestionItemType.footer); isKeyDownHandled = true; } } else if (keyCode === Utilities_1.KeyCodes.up) { if (selectedHeaderIndex === -1 && !((_c = this._suggestions.current) === null || _c === void 0 ? void 0 : _c.hasSuggestionSelected()) && selectedFooterIndex === -1) { this.selectLastItem(); } else if (selectedHeaderIndex !== -1) { this.selectPreviousItem(SuggestionItemType.header); isKeyDownHandled = true; } else if ((_d = this._suggestions.current) === null || _d === void 0 ? void 0 : _d.hasSuggestionSelected()) { this.selectPreviousItem(SuggestionItemType.suggestion); isKeyDownHandled = true; } else if (selectedFooterIndex !== -1) { this.selectPreviousItem(SuggestionItemType.footer); isKeyDownHandled = true; } } else if (keyCode === Utilities_1.KeyCodes.enter || keyCode === Utilities_1.KeyCodes.tab) { if (this.hasSelection()) { this.executeSelectedAction(); isKeyDownHandled = true; } } return isKeyDownHandled; }; // TODO get the element to scroll into view properly regardless of direction. SuggestionsControl.prototype.scrollSelected = function () { if (this._selectedElement.current) { this._selectedElement.current.scrollIntoView(false); } }; SuggestionsControl.prototype.renderHeaderItems = function () { var _this = this; var _a = this.props, headerItemsProps = _a.headerItemsProps, suggestionsHeaderContainerAriaLabel = _a.suggestionsHeaderContainerAriaLabel; var selectedHeaderIndex = this.state.selectedHeaderIndex; return headerItemsProps ? (React.createElement("div", { className: Utilities_1.css('ms-Suggestions-headerContainer', styles.suggestionsContainer), id: "suggestionHeader-list", role: "list", "aria-label": suggestionsHeaderContainerAriaLabel }, headerItemsProps.map(function (headerItemProps, index) { var isSelected = selectedHeaderIndex !== -1 && selectedHeaderIndex === index; return headerItemProps.shouldShow() ? (React.createElement("div", { ref: isSelected ? _this._selectedElement : undefined, id: 'sug-header' + index, key: 'sug-header' + index, role: "listitem", "aria-label": headerItemProps.ariaLabel }, React.createElement(SuggestionsHeaderFooterItem, { id: 'sug-header-item' + index, isSelected: isSelected, renderItem: headerItemProps.renderItem, onExecute: headerItemProps.onExecute, className: headerItemProps.className }))) : null; }))) : null; }; SuggestionsControl.prototype.renderFooterItems = function () { var _this = this; var _a = this.props, footerItemsProps = _a.footerItemsProps, suggestionsFooterContainerAriaLabel = _a.suggestionsFooterContainerAriaLabel; var selectedFooterIndex = this.state.selectedFooterIndex; return footerItemsProps ? (React.createElement("div", { className: Utilities_1.css('ms-Suggestions-footerContainer', styles.suggestionsContainer), id: "suggestionFooter-list", role: "list", "aria-label": suggestionsFooterContainerAriaLabel }, footerItemsProps.map(function (footerItemProps, index) { var isSelected = selectedFooterIndex !== -1 && selectedFooterIndex === index; return footerItemProps.shouldShow() ? (React.createElement("div", { ref: isSelected ? _this._selectedElement : undefined, id: 'sug-footer' + index, key: 'sug-footer' + index, role: "listitem", "aria-label": footerItemProps.ariaLabel }, React.createElement(SuggestionsHeaderFooterItem, { id: 'sug-footer-item' + index, isSelected: isSelected, renderItem: footerItemProps.renderItem, onExecute: footerItemProps.onExecute, className: footerItemProps.className }))) : null; }))) : null; }; SuggestionsControl.prototype._renderSuggestions = function () { var TypedSuggestions = this.SuggestionsOfProperType; return React.createElement(TypedSuggestions, tslib_1.__assign({ ref: this._suggestions }, this.props, { suggestions: this.state.suggestions })); }; /** * Selects the next selectable item */ SuggestionsControl.prototype.selectNextItem = function (itemType, originalItemType) { // If the recursive calling has not found a selectable item in the other suggestion item type groups // And the method is being called again with the original item type, // Select the first selectable item of this suggestion item type group (could be the currently selected item) if (itemType === originalItemType) { this._selectNextItemOfItemType(itemType); return; } var startedItemType = originalItemType !== undefined ? originalItemType : itemType; // Try to set the selection to the next selectable item, of the same suggestion item type group // If this is the original item type, use the current index var selectionChanged = this._selectNextItemOfItemType(itemType, startedItemType === itemType ? this._getCurrentIndexForType(itemType) : undefined); // If the selection did not change, try to select from the next suggestion type group if (!selectionChanged) { this.selectNextItem(this._getNextItemSectionType(itemType), startedItemType); } }; /** * Selects the previous selectable item */ SuggestionsControl.prototype.selectPreviousItem = function (itemType, originalItemType) { // If the recursive calling has not found a selectable item in the other suggestion item type groups // And the method is being called again with the original item type, // Select the last selectable item of this suggestion item type group (could be the currently selected item) if (itemType === originalItemType) { this._selectPreviousItemOfItemType(itemType); return; } var startedItemType = originalItemType !== undefined ? originalItemType : itemType; // Try to set the selection to the previous selectable item, of the same suggestion item type group var selectionChanged = this._selectPreviousItemOfItemType(itemType, startedItemType === itemType ? this._getCurrentIndexForType(itemType) : undefined); // If the selection did not change, try to select from the previous suggestion type group if (!selectionChanged) { this.selectPreviousItem(this._getPreviousItemSectionType(itemType), startedItemType); } }; /** * Resets the selected state and selects the first selectable item */ SuggestionsControl.prototype.resetSelectedItem = function () { var _a; this.setState({ selectedHeaderIndex: -1, selectedFooterIndex: -1 }); (_a = this._suggestions.current) === null || _a === void 0 ? void 0 : _a.deselectAllSuggestions(); // Select the first item if the shouldSelectFirstItem prop is not set or it is set and it returns true if (this.props.shouldSelectFirstItem === undefined || this.props.shouldSelectFirstItem()) { this.selectFirstItem(); } }; /** * Selects the first item */ SuggestionsControl.prototype.selectFirstItem = function () { if (this._selectNextItemOfItemType(SuggestionItemType.header)) { return; } if (this._selectNextItemOfItemType(SuggestionItemType.suggestion)) { return; } this._selectNextItemOfItemType(SuggestionItemType.footer); }; /** * Selects the last item */ SuggestionsControl.prototype.selectLastItem = function () { if (this._selectPreviousItemOfItemType(SuggestionItemType.footer)) { return; } if (this._selectPreviousItemOfItemType(SuggestionItemType.suggestion)) { return; } this._selectPreviousItemOfItemType(SuggestionItemType.header); }; /** * Selects the next item in the suggestion item type group, given the current index * If none is able to be selected, returns false, otherwise returns true * @param itemType - The suggestion item type * @param currentIndex - The current index, default is -1 */ SuggestionsControl.prototype._selectNextItemOfItemType = function (itemType, currentIndex) { if (currentIndex === void 0) { currentIndex = -1; } var _a, _b; if (itemType === SuggestionItemType.suggestion) { if (this.state.suggestions.length > currentIndex + 1) { (_a = this._suggestions.current) === null || _a === void 0 ? void 0 : _a.setSelectedSuggestion(currentIndex + 1); this.setState({ selectedHeaderIndex: -1, selectedFooterIndex: -1 }); return true; } } else { var isHeader = itemType === SuggestionItemType.header; var itemProps = isHeader ? this.props.headerItemsProps : this.props.footerItemsProps; if (itemProps && itemProps.length > currentIndex + 1) { for (var i = currentIndex + 1; i < itemProps.length; i++) { var item = itemProps[i]; if (item.onExecute && item.shouldShow()) { this.setState({ selectedHeaderIndex: isHeader ? i : -1 }); this.setState({ selectedFooterIndex: isHeader ? -1 : i }); (_b = this._suggestions.current) === null || _b === void 0 ? void 0 : _b.deselectAllSuggestions(); return true; } } } } return false; }; /** * Selects the previous item in the suggestion item type group, given the current index * If none is able to be selected, returns false, otherwise returns true * @param itemType - The suggestion item type * @param currentIndex - The current index. If none is provided, the default is the items length of specified type */ SuggestionsControl.prototype._selectPreviousItemOfItemType = function (itemType, currentIndex) { var _a, _b; if (itemType === SuggestionItemType.suggestion) { var index = currentIndex !== undefined ? currentIndex : this.state.suggestions.length; if (index > 0) { (_a = this._suggestions.current) === null || _a === void 0 ? void 0 : _a.setSelectedSuggestion(index - 1); this.setState({ selectedHeaderIndex: -1, selectedFooterIndex: -1 }); return true; } } else { var isHeader = itemType === SuggestionItemType.header; var itemProps = isHeader ? this.props.headerItemsProps : this.props.footerItemsProps; if (itemProps) { var index = currentIndex !== undefined ? currentIndex : itemProps.length; if (index > 0) { for (var i = index - 1; i >= 0; i--) { var item = itemProps[i]; if (item.onExecute && item.shouldShow()) { this.setState({ selectedHeaderIndex: isHeader ? i : -1 }); this.setState({ selectedFooterIndex: isHeader ? -1 : i }); (_b = this._suggestions.current) === null || _b === void 0 ? void 0 : _b.deselectAllSuggestions(); return true; } } } } } return false; }; SuggestionsControl.prototype._getCurrentIndexForType = function (itemType) { switch (itemType) { case SuggestionItemType.header: return this.state.selectedHeaderIndex; case SuggestionItemType.suggestion: return this._suggestions.current.currentIndex; case SuggestionItemType.footer: return this.state.selectedFooterIndex; } }; SuggestionsControl.prototype._getNextItemSectionType = function (itemType) { switch (itemType) { case SuggestionItemType.header: return SuggestionItemType.suggestion; case SuggestionItemType.suggestion: return SuggestionItemType.footer; case SuggestionItemType.footer: return SuggestionItemType.header; } }; SuggestionsControl.prototype._getPreviousItemSectionType = function (itemType) { switch (itemType) { case SuggestionItemType.header: return SuggestionItemType.footer; case SuggestionItemType.suggestion: return SuggestionItemType.header; case SuggestionItemType.footer: return SuggestionItemType.suggestion; } }; return SuggestionsControl; }(React.Component)); exports.SuggestionsControl = SuggestionsControl; //# sourceMappingURL=SuggestionsControl.js.map