UNPKG

@uifabric/experiments

Version:

Experimental React components for building experiences for Microsoft 365.

295 lines 15.4 kB
define(["require", "exports", "tslib", "react", "./FloatingSuggestions.scss", "office-ui-fabric-react/lib/Utilities", "office-ui-fabric-react/lib/Callout", "./Suggestions/SuggestionsControl"], function (require, exports, tslib_1, React, styles, Utilities_1, Callout_1, SuggestionsControl_1) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var FloatingSuggestions = /** @class */ (function (_super) { tslib_1.__extends(FloatingSuggestions, _super); function FloatingSuggestions(basePickerProps) { var _this = _super.call(this, basePickerProps) || this; _this.root = React.createRef(); _this.suggestionsControl = React.createRef(); _this.isComponentMounted = false; _this.onQueryStringChanged = function (queryString) { if (queryString !== _this.state.queryString) { _this.setState({ queryString: queryString, }); if (_this.props.onInputChanged) { _this.props.onInputChanged(queryString); } _this.updateValue(queryString); } }; _this.hidePicker = function () { if (_this.props.onSuggestionsHidden && _this.isSuggestionsShown) { _this.props.onSuggestionsHidden(); } _this.setState({ suggestionsVisible: false, }); }; _this.showPicker = function (updateValue) { if (updateValue === void 0) { updateValue = false; } if (_this.props.onSuggestionsShown && !_this.isSuggestionsShown) { _this.props.onSuggestionsShown(); } _this.setState({ suggestionsVisible: true, }); // Update the suggestions if updateValue == true var value = _this.props.inputElement ? _this.props.inputElement.value : ''; if (updateValue) { _this.updateValue(value); } }; _this.onCurrentlySelectedSuggestionChosen = function () { if (_this.suggestionsControl.current && _this.suggestionsControl.current.hasSuggestionSelected()) { _this._onSuggestionSelected(_this.suggestionsControl.current.currentSuggestion.item); } }; _this._onSuggestionClick = function (ev, item, index) { _this._onSuggestionSelected(item); _this._updateSuggestionsVisible(false /*shouldShow*/); }; _this._onSuggestionRemove = function (ev, item, index) { if (_this.props.onRemoveSuggestion) { _this.props.onRemoveSuggestion(item); } if (_this.suggestionsControl.current) { _this.suggestionsControl.current.removeSuggestion(index); } }; _this._onKeyDown = function (ev) { if (!_this.state.suggestionsVisible || (_this.props.inputElement && ev.target instanceof Node && !_this.props.inputElement.contains(ev.target))) { return; } // eslint-disable-next-line deprecation/deprecation var keyCode = ev.which; switch (keyCode) { case Utilities_1.KeyCodes.escape: _this.hidePicker(); ev.preventDefault(); ev.stopPropagation(); break; case Utilities_1.KeyCodes.tab: case Utilities_1.KeyCodes.enter: if (!ev.shiftKey && !ev.ctrlKey && _this.suggestionsControl.current && _this.suggestionsControl.current.handleKeyDown(keyCode)) { ev.preventDefault(); ev.stopPropagation(); } else { // no selection. Try to force resolve the current query _this._validateAndInsertCurrentQueryString(); } break; case Utilities_1.KeyCodes.del: if (_this.props.onRemoveSuggestion && _this.suggestionsControl.current && _this.suggestionsControl.current.hasSuggestionSelected && _this.suggestionsControl.current.currentSuggestion && ev.shiftKey) { _this.props.onRemoveSuggestion(_this.suggestionsControl.current.currentSuggestion.item); _this.suggestionsControl.current.removeSuggestion(); _this.forceUpdate(); ev.stopPropagation(); } break; case Utilities_1.KeyCodes.up: if (_this.suggestionsControl.current && _this.suggestionsControl.current.handleKeyDown(keyCode)) { ev.preventDefault(); ev.stopPropagation(); _this._updateActiveDescendant(); } break; case Utilities_1.KeyCodes.down: if (_this.suggestionsControl.current && _this.suggestionsControl.current.handleKeyDown(keyCode)) { ev.preventDefault(); ev.stopPropagation(); _this._updateActiveDescendant(); } break; } }; _this._validateAndInsertCurrentQueryString = function () { if (_this.state.queryString && _this.props.isQueryForceResolveable && _this.props.createForceResolvedItem) { var isForceResolvable = _this.props.isQueryForceResolveable(_this.state.queryString); if (!isForceResolvable) { return; } var itemToConvert = _this.props.createForceResolvedItem(_this.state.queryString); var convertedItems = _this.suggestionStore.convertSuggestionsToSuggestionItems([itemToConvert]); _this._onSuggestionSelected(convertedItems[0].item); } }; _this._async = new Utilities_1.Async(_this); Utilities_1.initializeComponentRef(_this); _this.suggestionStore = basePickerProps.suggestionsStore; _this.state = { queryString: '', didBind: false, }; return _this; } Object.defineProperty(FloatingSuggestions.prototype, "inputText", { // TODO FloatingSuggestions should not be responsible for getting the // input text. get: function () { return this.state.queryString; }, enumerable: true, configurable: true }); Object.defineProperty(FloatingSuggestions.prototype, "suggestions", { get: function () { return this.suggestionStore.suggestions; }, enumerable: true, configurable: true }); FloatingSuggestions.prototype.forceResolveSuggestion = function () { if (this.suggestionsControl.current && this.suggestionsControl.current.hasSuggestionSelected()) { this.onCurrentlySelectedSuggestionChosen(); } else { this._validateAndInsertCurrentQueryString(); } }; Object.defineProperty(FloatingSuggestions.prototype, "currentSelectedSuggestionIndex", { get: function () { return this.suggestionsControl.current ? this.suggestionsControl.current.currentSuggestionIndex : -1; }, enumerable: true, configurable: true }); Object.defineProperty(FloatingSuggestions.prototype, "isSuggestionsShown", { get: function () { return this.state.suggestionsVisible === undefined ? false : this.state.suggestionsVisible; }, enumerable: true, configurable: true }); FloatingSuggestions.prototype.componentDidMount = function () { this._bindToInputElement(); this.isComponentMounted = true; this._onResolveSuggestions = this._async.debounce(this._onResolveSuggestions, this.props.resolveDelay); }; FloatingSuggestions.prototype.componentDidUpdate = function () { this._bindToInputElement(); }; FloatingSuggestions.prototype.componentWillUnmount = function () { this._unbindFromInputElement(); this.isComponentMounted = false; this._async.dispose(); }; FloatingSuggestions.prototype.UNSAFE_componentWillReceiveProps = function (newProps) { if (newProps.suggestionItems) { this.updateSuggestions(newProps.suggestionItems); } }; FloatingSuggestions.prototype.updateSuggestions = function (suggestions, forceUpdate) { if (forceUpdate === void 0) { forceUpdate = false; } this.suggestionStore.updateSuggestions(suggestions); if (forceUpdate) { this.forceUpdate(); } }; FloatingSuggestions.prototype.render = function () { var className = this.props.className; return (React.createElement("div", { ref: this.root, className: Utilities_1.css('ms-BasePicker ms-BaseFloatingPicker', className ? className : '') }, this._renderSuggestions())); }; FloatingSuggestions.prototype.updateValue = function (updatedValue) { if (updatedValue === '') { this.updateSuggestionWithZeroState(); } else { this._onResolveSuggestions(updatedValue); } }; FloatingSuggestions.prototype.updateSuggestionWithZeroState = function () { if (this.props.onZeroQuerySuggestion) { var suggestions = this.props.onZeroQuerySuggestion(); this.updateSuggestionsList(suggestions || []); } else { this.hidePicker(); } }; FloatingSuggestions.prototype.updateSuggestionsList = function (suggestions) { var _this = this; // Check to see if the returned value is an array, if it is then just pass it into the next function. // If the returned value is not an array then check to see if it's a promise or PromiseLike. // If it is then resolve it asynchronously. if (Array.isArray(suggestions)) { this.updateSuggestions(suggestions, true /*forceUpdate*/); } else if (suggestions && suggestions.then) { // Ensure that the promise will only use the callback if it was the most recent one. var promise_1 = (this.currentPromise = suggestions); promise_1.then(function (newSuggestions) { // Only update if the next promise has not yet resolved and // the floating picker is still mounted. if (promise_1 === _this.currentPromise && _this.isComponentMounted) { _this.updateSuggestions(newSuggestions, true /*forceUpdate*/); } }); } }; FloatingSuggestions.prototype._renderSuggestions = function () { // Express this as 2 separate statements instead of a single one, because `undefined` isn't filtered out of the type // when using `|| SuggestionsControl` var TypedSuggestionsControl = this .props.onRenderSuggestionControl; if (TypedSuggestionsControl === undefined) { TypedSuggestionsControl = SuggestionsControl_1.SuggestionsControl; } return this.state.suggestionsVisible ? (React.createElement(Callout_1.Callout, { className: styles.callout, isBeakVisible: false, gapSpace: 5, target: this.props.inputElement, onDismiss: this.hidePicker, directionalHint: Callout_1.DirectionalHint.bottomLeftEdge, directionalHintForRTL: Callout_1.DirectionalHint.bottomRightEdge, calloutWidth: this.props.calloutWidth ? this.props.calloutWidth : 0 }, React.createElement(TypedSuggestionsControl, { onRenderSuggestion: this.props.onRenderSuggestionsItem, onSuggestionClick: this._onSuggestionClick, onSuggestionRemove: this._onSuggestionRemove, suggestions: this.suggestionStore.getSuggestions(), componentRef: this.suggestionsControl, onCurrentlySelectedSuggestionChosen: this.onCurrentlySelectedSuggestionChosen, shouldLoopSelection: false }))) : null; }; FloatingSuggestions.prototype._onSuggestionSelected = function (item) { if (this.props.onSuggestionSelected) { this.props.onSuggestionSelected(item); } }; FloatingSuggestions.prototype._updateActiveDescendant = function () { if (this.props.inputElement && this.suggestionsControl.current && this.suggestionsControl.current.selectedElement) { var selectedElId = this.suggestionsControl.current.selectedElement.getAttribute('id'); if (selectedElId) { this.props.inputElement.setAttribute('aria-activedescendant', selectedElId); } } }; FloatingSuggestions.prototype._onResolveSuggestions = function (updatedValue) { var suggestions = this.props.onResolveSuggestions(updatedValue); this._updateSuggestionsVisible(true /*shouldShow*/); if (suggestions !== null) { this.updateSuggestionsList(suggestions); } }; FloatingSuggestions.prototype._updateSuggestionsVisible = function (shouldShow) { if (shouldShow) { this.showPicker(); } else { this.hidePicker(); } }; FloatingSuggestions.prototype._bindToInputElement = function () { if (this.props.inputElement && !this.state.didBind) { this.props.inputElement.addEventListener('keydown', this._onKeyDown); this.setState({ didBind: true }); } }; FloatingSuggestions.prototype._unbindFromInputElement = function () { if (this.props.inputElement && this.state.didBind) { this.props.inputElement.removeEventListener('keydown', this._onKeyDown); this.setState({ didBind: false }); } }; return FloatingSuggestions; }(React.Component)); exports.FloatingSuggestions = FloatingSuggestions; }); //# sourceMappingURL=FloatingSuggestions.js.map