diff --git a/common/changes/@uifabric/experiments/amyngu-newSuggestions_2018-02-08-21-28.json b/common/changes/@uifabric/experiments/amyngu-newSuggestions_2018-02-08-21-28.json new file mode 100644 index 00000000000000..3241f919c49463 --- /dev/null +++ b/common/changes/@uifabric/experiments/amyngu-newSuggestions_2018-02-08-21-28.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "@uifabric/experiments", + "comment": "Use new \"use current input\" command in Suggestions", + "type": "minor" + } + ], + "packageName": "@uifabric/experiments", + "email": "amyngu@microsoft.com" +} \ No newline at end of file diff --git a/common/changes/office-ui-fabric-react/amyngu-newSuggestions_2018-02-08-21-28.json b/common/changes/office-ui-fabric-react/amyngu-newSuggestions_2018-02-08-21-28.json new file mode 100644 index 00000000000000..b9bd42d5e19a41 --- /dev/null +++ b/common/changes/office-ui-fabric-react/amyngu-newSuggestions_2018-02-08-21-28.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "packageName": "office-ui-fabric-react", + "comment": "Add \"use current input command\" and remove need to explicity call focus when moving between suggestions and commands", + "type": "minor" + } + ], + "packageName": "office-ui-fabric-react", + "email": "amyngu@microsoft.com" +} \ No newline at end of file diff --git a/packages/experiments/src/components/ExtendedPicker/examples/ExtendedPeoplePicker.Basic.Example.tsx b/packages/experiments/src/components/ExtendedPicker/examples/ExtendedPeoplePicker.Basic.Example.tsx index f7e13e84bba915..36cdd40ed5eb94 100644 --- a/packages/experiments/src/components/ExtendedPicker/examples/ExtendedPeoplePicker.Basic.Example.tsx +++ b/packages/experiments/src/components/ExtendedPicker/examples/ExtendedPeoplePicker.Basic.Example.tsx @@ -22,22 +22,12 @@ export interface IPeoplePickerExampleState { mostRecentlyUsed: IPersonaProps[]; } -const suggestionProps: IBasePickerSuggestionsProps = { - suggestionsHeaderText: 'Suggested People', - mostRecentlyUsedHeaderText: 'Suggested Contacts', - noResultsFoundText: 'No results found', - loadingText: 'Loading', - showRemoveButtons: true, - suggestionsAvailableAlertText: 'People Picker Suggestions available', - suggestionsContainerAriaLabel: 'Suggested contacts', - searchForMoreText: 'Search more', -}; - // tslint:disable-next-line:no-any export class ExtendedPeoplePickerTypesExample extends BaseComponent<{}, IPeoplePickerExampleState> { private _picker: ExtendedPeoplePicker; private _floatingPickerProps: IBaseFloatingPickerProps; private _selectedItemsListProps: ISelectedPeopleProps; + private _suggestionProps: IBasePickerSuggestionsProps; constructor(props: {}) { super(props); @@ -54,15 +44,28 @@ export class ExtendedPeoplePickerTypesExample extends BaseComponent<{}, IPeopleP mostRecentlyUsed: mru, }; + this._suggestionProps = { + suggestionsHeaderText: 'Suggested People', + mostRecentlyUsedHeaderText: 'Suggested Contacts', + noResultsFoundText: 'No results found', + loadingText: 'Loading', + showRemoveButtons: true, + suggestionsAvailableAlertText: 'People Picker Suggestions available', + suggestionsContainerAriaLabel: 'Suggested contacts', + searchForMoreText: 'Search more', + forceResolveText: 'Use this name', + }; + this._floatingPickerProps = { suggestionsController: new SuggestionsController(), onResolveSuggestions: this._onFilterChanged, getTextFromItem: this._getTextFromItem, - pickerSuggestionsProps: suggestionProps, + pickerSuggestionsProps: this._suggestionProps, key: 'normal', onRemoveSuggestion: this._onRemoveSuggestion, onValidateInput: this._validateInput, onZeroQuerySuggestion: this._returnMostRecentlyUsed, + showForceResolve: this._shouldShowForceResolve, }; this._selectedItemsListProps = { @@ -193,6 +196,12 @@ export class ExtendedPeoplePickerTypesExample extends BaseComponent<{}, IPeopleP return copyText; } + @autobind + private _shouldShowForceResolve(): boolean { + return this._validateInput(this._picker.floatingPicker.inputText) + && this._picker.floatingPicker.suggestions.length === 0; + } + private _listContainsPersona(persona: IPersonaProps, personas: IPersonaProps[]): boolean { if (!personas || !personas.length || personas.length === 0) { return false; diff --git a/packages/experiments/src/components/FloatingPicker/BaseFloatingPicker.tsx b/packages/experiments/src/components/FloatingPicker/BaseFloatingPicker.tsx index a7da08048a00ac..d682d8dc5dd574 100644 --- a/packages/experiments/src/components/FloatingPicker/BaseFloatingPicker.tsx +++ b/packages/experiments/src/components/FloatingPicker/BaseFloatingPicker.tsx @@ -54,6 +54,15 @@ export class BaseFloatingPicker> extend }; } + public get inputText(): string { + return this.state.queryString; + } + + // tslint:disable-next-line:no-any + public get suggestions(): any[] { + return this.suggestionStore.suggestions; + } + public forceResolveSuggestion(): void { if (this.suggestionStore.hasSelectedSuggestion()) { this.completeSuggestion(); @@ -87,7 +96,6 @@ export class BaseFloatingPicker> extend this.setState({ suggestionsVisible: false, }); - console.log('hidepicker'); } public showPicker(): void { @@ -129,12 +137,14 @@ export class BaseFloatingPicker> extend @autobind public refocusSuggestions(keyCode: KeyCodes): void { - if (keyCode === KeyCodes.up) { - this.suggestionStore.setSelectedSuggestion( - this.suggestionStore.suggestions.length - 1 - ); - } else if (keyCode === KeyCodes.down) { - this.suggestionStore.setSelectedSuggestion(0); + if (this.suggestionStore.suggestions && this.suggestionStore.suggestions.length > 0) { + if (keyCode === KeyCodes.up) { + this.suggestionStore.setSelectedSuggestion( + this.suggestionStore.suggestions.length - 1 + ); + } else if (keyCode === KeyCodes.down) { + this.suggestionStore.setSelectedSuggestion(0); + } } } @@ -169,6 +179,8 @@ export class BaseFloatingPicker> extend calloutWidth={ this.props.calloutWidth ? this.props.calloutWidth : 0 } > > extend !(this.props.inputElement as HTMLElement).contains(ev.target as HTMLElement))) { return; } - switch (ev.which) { + let keyCode = ev.which; + switch (keyCode) { case KeyCodes.escape: this.setState({ suggestionsVisible: false }); ev.preventDefault(); @@ -350,8 +363,9 @@ export class BaseFloatingPicker> extend case KeyCodes.tab: case KeyCodes.enter: - if ( - !ev.shiftKey && + if (this.suggestionElement.hasSuggestedActionSelected()) { + this.suggestionElement.executeSelectedAction(); + } else if (!ev.shiftKey && !ev.ctrlKey && this.suggestionStore.hasSelectedSuggestion()) { this.completeSuggestion(); @@ -378,38 +392,49 @@ export class BaseFloatingPicker> extend break; case KeyCodes.up: - if ( - this.state.moreSuggestionsAvailable && - this.suggestionElement.props.searchForMoreText && - this.suggestionStore.currentIndex === 0 - ) { - this.suggestionElement.focusSearchForMoreButton(); - this.suggestionStore.deselectAllSuggestions(); - this.forceUpdate(); + if (this.suggestionElement.tryHandleKeyDown(keyCode, this.suggestionStore.currentIndex)) { + ev.preventDefault(); + ev.stopPropagation(); } else { - if (this.suggestionStore.previousSuggestion()) { + if (this.suggestionElement.hasSuggestedAction() && + this.suggestionStore.currentIndex === 0 + ) { ev.preventDefault(); ev.stopPropagation(); - this.onSuggestionSelect(); + this.suggestionElement.focusAboveSuggestions(); + this.suggestionStore.deselectAllSuggestions(); + this.forceUpdate(); + } else { + if (this.suggestionStore.previousSuggestion()) { + ev.preventDefault(); + ev.stopPropagation(); + this.onSuggestionSelect(); + } } } break; case KeyCodes.down: - if ( - this.state.moreSuggestionsAvailable && - this.suggestionElement.props.searchForMoreText && - this.suggestionStore.currentIndex + 1 === - this.suggestionStore.suggestions.length - ) { - this.suggestionElement.focusSearchForMoreButton(); - this.suggestionStore.deselectAllSuggestions(); - this.forceUpdate(); + if (this.suggestionElement.tryHandleKeyDown(keyCode, this.suggestionStore.currentIndex)) { + ev.preventDefault(); + ev.stopPropagation(); } else { - if (this.suggestionStore.nextSuggestion()) { + if ( + this.suggestionElement.hasSuggestedAction() && + this.suggestionStore.currentIndex + 1 === + this.suggestionStore.suggestions.length + ) { ev.preventDefault(); ev.stopPropagation(); - this.onSuggestionSelect(); + this.suggestionElement.focusBelowSuggestions(); + this.suggestionStore.deselectAllSuggestions(); + this.forceUpdate(); + } else { + if (this.suggestionStore.nextSuggestion()) { + ev.preventDefault(); + ev.stopPropagation(); + this.onSuggestionSelect(); + } } } break; @@ -463,10 +488,10 @@ export class BaseFloatingPicker> extend this.updateSuggestionsList(suggestions, updatedValue); } + @autobind private _onValidateInput(): void { if ( this.props.onValidateInput && - (this.props.onValidateInput as ((input: string) => boolean))(this.state.queryString) !== true && this.props.createGenericItem ) { let itemToConvert = (this.props.createGenericItem as (( @@ -481,6 +506,11 @@ export class BaseFloatingPicker> extend } } + @autobind + private _showForceResolve(): boolean { + return this.props.showForceResolve ? this.props.showForceResolve() : false; + } + private _getTextFromItem(item: T, currentValue?: string): string { if (this.props.getTextFromItem) { return (this.props.getTextFromItem as ((item: T, currentValue?: string) => string))(item, currentValue); diff --git a/packages/experiments/src/components/FloatingPicker/BaseFloatingPicker.types.ts b/packages/experiments/src/components/FloatingPicker/BaseFloatingPicker.types.ts index 88669257e1275e..72612318643564 100644 --- a/packages/experiments/src/components/FloatingPicker/BaseFloatingPicker.types.ts +++ b/packages/experiments/src/components/FloatingPicker/BaseFloatingPicker.types.ts @@ -98,6 +98,11 @@ export interface IBaseFloatingPickerProps extends React.Props { isValid: boolean ) => ISuggestionModel; + /** + * The callback that should be called to see if the force resolve command should be shown + */ + showForceResolve?: () => boolean; + /** * The items that the base picker should currently display as selected. If this is provided then the picker will act as a controlled * component. @@ -113,4 +118,4 @@ export interface IBaseFloatingPickerProps extends React.Props { * Width for the suggestions callout */ calloutWidth?: number; -} +} \ No newline at end of file diff --git a/packages/office-ui-fabric-react/src/components/pickers/BasePicker.tsx b/packages/office-ui-fabric-react/src/components/pickers/BasePicker.tsx index b5473a54698110..649e214b2e89a8 100644 --- a/packages/office-ui-fabric-react/src/components/pickers/BasePicker.tsx +++ b/packages/office-ui-fabric-react/src/components/pickers/BasePicker.tsx @@ -155,10 +155,12 @@ export class BasePicker> extends BaseComponent< @autobind public refocusSuggestions(keyCode: KeyCodes) { this.resetFocus(); - if (keyCode === KeyCodes.up) { - this.suggestionStore.setSelectedSuggestion(this.suggestionStore.suggestions.length - 1); - } else if (keyCode === KeyCodes.down) { - this.suggestionStore.setSelectedSuggestion(0); + if (this.suggestionStore.suggestions && this.suggestionStore.suggestions.length > 0) { + if (keyCode === KeyCodes.up) { + this.suggestionStore.setSelectedSuggestion(this.suggestionStore.suggestions.length - 1); + } else if (keyCode === KeyCodes.down) { + this.suggestionStore.setSelectedSuggestion(0); + } } } @@ -443,7 +445,8 @@ export class BasePicker> extends BaseComponent< @autobind protected onKeyDown(ev: React.KeyboardEvent) { - switch (ev.which) { + let keyCode = ev.which; + switch (keyCode) { case KeyCodes.escape: if (this.state.suggestionsVisible) { this.setState({ suggestionsVisible: false }); @@ -454,7 +457,9 @@ export class BasePicker> extends BaseComponent< case KeyCodes.tab: case KeyCodes.enter: - if (!ev.shiftKey && this.suggestionStore.hasSelectedSuggestion() && this.state.suggestionsVisible) { + if (this.suggestionElement.hasSuggestedActionSelected()) { + this.suggestionElement.executeSelectedAction(); + } else if (!ev.shiftKey && this.suggestionStore.hasSelectedSuggestion() && this.state.suggestionsVisible) { this.completeSuggestion(); ev.preventDefault(); ev.stopPropagation(); @@ -488,15 +493,22 @@ export class BasePicker> extends BaseComponent< case KeyCodes.up: if (ev.target === this.input.inputElement && this.state.suggestionsVisible) { - if (this.state.moreSuggestionsAvailable && this.suggestionElement.props.searchForMoreText && this.suggestionStore.currentIndex === 0) { - this.suggestionElement.focusSearchForMoreButton(); - this.suggestionStore.deselectAllSuggestions(); - this.forceUpdate(); + if (this.suggestionElement.tryHandleKeyDown(keyCode, this.suggestionStore.currentIndex)) { + ev.preventDefault(); + ev.stopPropagation(); } else { - if (this.suggestionStore.previousSuggestion()) { + if (this.suggestionElement.hasSuggestedAction() && this.suggestionStore.currentIndex === 0) { ev.preventDefault(); ev.stopPropagation(); - this.onSuggestionSelect(); + this.suggestionElement.focusAboveSuggestions(); + this.suggestionStore.deselectAllSuggestions(); + this.forceUpdate(); + } else { + if (this.suggestionStore.previousSuggestion()) { + ev.preventDefault(); + ev.stopPropagation(); + this.onSuggestionSelect(); + } } } } @@ -504,18 +516,24 @@ export class BasePicker> extends BaseComponent< case KeyCodes.down: if (ev.target === this.input.inputElement && this.state.suggestionsVisible) { - if (this.state.moreSuggestionsAvailable && this.suggestionElement.props.searchForMoreText && (this.suggestionStore.currentIndex + 1) === this.suggestionStore.suggestions.length) { - this.suggestionElement.focusSearchForMoreButton(); - this.suggestionStore.deselectAllSuggestions(); - this.forceUpdate(); + if (this.suggestionElement.tryHandleKeyDown(keyCode, this.suggestionStore.currentIndex)) { + ev.preventDefault(); + ev.stopPropagation(); } else { - if (this.suggestionStore.nextSuggestion()) { + if (this.suggestionElement.hasSuggestedAction() && (this.suggestionStore.currentIndex + 1) === this.suggestionStore.suggestions.length) { ev.preventDefault(); ev.stopPropagation(); - this.onSuggestionSelect(); + this.suggestionElement.focusBelowSuggestions(); + this.suggestionStore.deselectAllSuggestions(); + this.forceUpdate(); + } else { + if (this.suggestionStore.nextSuggestion()) { + ev.preventDefault(); + ev.stopPropagation(); + this.onSuggestionSelect(); + } } } - } break; } diff --git a/packages/office-ui-fabric-react/src/components/pickers/BasePicker.types.ts b/packages/office-ui-fabric-react/src/components/pickers/BasePicker.types.ts index 4e15c252db4ca1..d8841b5265c0fa 100644 --- a/packages/office-ui-fabric-react/src/components/pickers/BasePicker.types.ts +++ b/packages/office-ui-fabric-react/src/components/pickers/BasePicker.types.ts @@ -162,6 +162,10 @@ export interface IBasePickerSuggestionsProps { * The text that should appear on the button to search for more. */ searchForMoreText?: string; + /** + * The text that appears indicating to the use to force resolve the input + */ + forceResolveText?: string; /** * The text to display while the results are loading. */ diff --git a/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.scss b/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.scss index 350d4ca0aa8121..c8a4d6fe6eb526 100644 --- a/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.scss +++ b/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.scss @@ -61,7 +61,7 @@ } } -.searchMoreButton { +.actionButton { background: none; border: 0; cursor: pointer; @@ -93,6 +93,10 @@ } } +.buttonSelected { + background-color: $ms-color-themeLight; +} + .suggestionsTitle { padding: 0 12px; color: $ms-color-themePrimary; diff --git a/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.tsx b/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.tsx index cf07bd537d4df3..229057ebde17ac 100644 --- a/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.tsx +++ b/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.tsx @@ -11,6 +11,16 @@ import { ISuggestionItemProps, ISuggestionsProps } from './Suggestions.types'; import * as stylesImport from './Suggestions.scss'; const styles: any = stylesImport; +export enum SuggestionActionType { + none, + forceResolve, + searchMore, +} + +export interface ISuggestionsState { + selectedActionType: SuggestionActionType; +} + export class SuggestionsItem extends BaseComponent, {}> { public render() { let { @@ -51,14 +61,18 @@ export class SuggestionsItem extends BaseComponent, { } } -export class Suggestions extends BaseComponent, {}> { +export class Suggestions extends BaseComponent, ISuggestionsState> { + protected _forceResolveButton: IButton; protected _searchForMoreButton: IButton; protected _selectedElement: HTMLDivElement; private SuggestionsItemOfProperType = SuggestionsItem as new (props: ISuggestionItemProps) => SuggestionsItem; constructor(suggestionsProps: ISuggestionsProps) { super(suggestionsProps); + this.state = { + selectedActionType: SuggestionActionType.none, + }; } public componentDidUpdate() { @@ -67,6 +81,9 @@ export class Suggestions extends BaseComponent, {}> { public render() { let { + forceResolveText, + createGenericItem, + showForceResolve, mostRecentlyUsedHeaderText, searchForMoreText, className, @@ -83,7 +100,7 @@ export class Suggestions extends BaseComponent, {}> { resultsFooterFull, resultsFooter, suggestionsAvailableAlertText, - suggestionsHeaderText + suggestionsHeaderText, } = this.props; let noResults = () => { @@ -100,6 +117,7 @@ export class Suggestions extends BaseComponent, {}> { headerText = mostRecentlyUsedHeaderText; } let footerTitle = (suggestions.length >= (resultsMaximumNumber as number)) ? resultsFooterFull : resultsFooter; + let hasNoSuggestions = (!suggestions || !suggestions.length) && !isLoading; return (
extends BaseComponent, {}> { (
{ headerText }
) : (null) } + { forceResolveText && this._shouldShowForceResolve() && ( + + { forceResolveText } + + ) } { isLoading && ( ) } - { (!suggestions || !suggestions.length) && !isLoading ? + { hasNoSuggestions ? (onRenderNoResultFound ? onRenderNoResultFound(undefined, noResults) : noResults()) : this._renderSuggestions() } { searchForMoreText && moreSuggestionsAvailable && ( { searchForMoreText } @@ -155,6 +192,113 @@ export class Suggestions extends BaseComponent, {}> { ); } + /** + * Returns true if the event was handled, false otherwise + */ + @autobind + public tryHandleKeyDown(keyCode: number, currentSuggestionIndex: number): boolean { + let isEventHandled = false; + let newSelectedActionType = null; + let currentSelectedAction = this.state.selectedActionType; + let suggestionLength = this.props.suggestions.length; + if (keyCode === KeyCodes.down) { + switch (currentSelectedAction) { + case SuggestionActionType.forceResolve: + if (suggestionLength > 0) { + this._refocusOnSuggestions(keyCode); + newSelectedActionType = SuggestionActionType.none; + } else if (this._searchForMoreButton) { + newSelectedActionType = SuggestionActionType.searchMore; + } else { + newSelectedActionType = SuggestionActionType.forceResolve; + } + break; + case SuggestionActionType.searchMore: + if (this._forceResolveButton) { + newSelectedActionType = SuggestionActionType.forceResolve; + } else if (suggestionLength > 0) { + this._refocusOnSuggestions(keyCode); + newSelectedActionType = SuggestionActionType.none; + } else { + newSelectedActionType = SuggestionActionType.searchMore; + } + break; + case SuggestionActionType.none: + if (currentSuggestionIndex === -1 && this._forceResolveButton) { + newSelectedActionType = SuggestionActionType.forceResolve; + } + break; + } + } else if (keyCode === KeyCodes.up) { + switch (currentSelectedAction) { + case SuggestionActionType.forceResolve: + if (this._searchForMoreButton) { + newSelectedActionType = SuggestionActionType.searchMore; + } else if (suggestionLength > 0) { + this._refocusOnSuggestions(keyCode); + newSelectedActionType = SuggestionActionType.none; + } + break; + case SuggestionActionType.searchMore: + if (suggestionLength > 0) { + this._refocusOnSuggestions(keyCode); + newSelectedActionType = SuggestionActionType.none; + } else if (this._forceResolveButton) { + newSelectedActionType = SuggestionActionType.forceResolve; + } + break; + case SuggestionActionType.none: + if (currentSuggestionIndex === -1 && this._searchForMoreButton) { + newSelectedActionType = SuggestionActionType.searchMore; + } + break; + } + } + + if (newSelectedActionType !== null) { + this.setState({ selectedActionType: newSelectedActionType }); + isEventHandled = true; + } + + return isEventHandled; + } + + public hasSuggestedAction(): boolean { + return this._searchForMoreButton !== undefined || this._forceResolveButton !== undefined; + } + + public hasSuggestedActionSelected(): boolean { + return (this.state.selectedActionType !== SuggestionActionType.none); + } + + public executeSelectedAction(): void { + switch (this.state.selectedActionType) { + case SuggestionActionType.forceResolve: + this._forceResolve(); + break; + case SuggestionActionType.searchMore: + this._getMoreResults(); + break; + } + } + + public focusAboveSuggestions(): void { + let newSelectedActionType = null; + if (this._forceResolveButton) { + this.setState({ selectedActionType: SuggestionActionType.forceResolve }); + } else if (this._searchForMoreButton) { + this.setState({ selectedActionType: SuggestionActionType.searchMore }); + } + } + + public focusBelowSuggestions(): void { + if (this._searchForMoreButton) { + this.setState({ selectedActionType: SuggestionActionType.searchMore }); + } else if (this._forceResolveButton) { + this.setState({ selectedActionType: SuggestionActionType.forceResolve }); + } + } + public focusSearchForMoreButton() { if (this._searchForMoreButton) { this._searchForMoreButton.focus(); @@ -218,6 +362,18 @@ export class Suggestions extends BaseComponent, {}> { } } + @autobind + private _forceResolve() { + if (this.props.createGenericItem) { + this.props.createGenericItem(); + } + } + + @autobind + private _shouldShowForceResolve() { + return this.props.showForceResolve ? this.props.showForceResolve() : false; + } + @autobind private _onClickTypedSuggestionsItem(item: T, index: number): (ev: React.MouseEvent) => void { return (ev: React.MouseEvent): void => { @@ -226,9 +382,9 @@ export class Suggestions extends BaseComponent, {}> { } @autobind - private _onKeyDown(ev: React.KeyboardEvent) { - if ((ev.keyCode === KeyCodes.up || ev.keyCode === KeyCodes.down) && typeof this.props.refocusSuggestions === 'function') { - this.props.refocusSuggestions(ev.keyCode); + private _refocusOnSuggestions(keyCode: number): void { + if (typeof this.props.refocusSuggestions === 'function') { + this.props.refocusSuggestions(keyCode); } } diff --git a/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.types.ts b/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.types.ts index 7874e3626641d4..10f711966da78f 100644 --- a/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.types.ts +++ b/packages/office-ui-fabric-react/src/components/pickers/Suggestions/Suggestions.types.ts @@ -41,6 +41,18 @@ export interface ISuggestionsProps extends React.Props { * The callback that should be called when the user attempts to get more results */ onGetMoreResults?: () => void; + /** + * The text that appears indicating to the use to force resolve the input + */ + forceResolveText?: string; + /** + * The callback that should be called to see if the force resolve command should be shown + */ + showForceResolve?: () => boolean; + /** + * The callback that should be called when the user attempts to use the input text as as item + */ + createGenericItem?: () => void; /** * The CSS classname of the suggestions list. */ diff --git a/packages/office-ui-fabric-react/src/components/pickers/Suggestions/SuggestionsController.ts b/packages/office-ui-fabric-react/src/components/pickers/Suggestions/SuggestionsController.ts index d35720a8a6c712..14b30cd849f8d8 100644 --- a/packages/office-ui-fabric-react/src/components/pickers/Suggestions/SuggestionsController.ts +++ b/packages/office-ui-fabric-react/src/components/pickers/Suggestions/SuggestionsController.ts @@ -97,8 +97,10 @@ export class SuggestionsController { } public deselectAllSuggestions(): void { - this.suggestions[this.currentIndex].selected = false; - this.currentIndex = -1; + if (this.currentIndex > -1) { + this.suggestions[this.currentIndex].selected = false; + this.currentIndex = -1; + } } public setSelectedSuggestion(index: number): void {