UNPKG

azure-devops-ui

Version:

React components for building web UI in Azure DevOps

1 lines 13.5 kB
import"../../CommonImports";import"../../Core/core.css";import"./IdentityPickerDropdown.css";import*as React from"react";import*as Resources from"../../Resources.IdentityPicker";import{ObservableArray,ObservableLike,ObservableValue}from"../../Core/Observable";import{TimerManagement}from"../../Core/TimerManagement";import{makeCancelable}from"../../Core/Util/Promise";import{format,localeIgnoreCaseComparer,startsWith}from"../../Core/Util/String";import{FocusWithin}from"../../FocusWithin";import{Icon,IconSize}from"../../Icon";import{Measure}from"../../Measure";import{Observer}from"../../Observer";import{Persona,PersonaSize}from"../../Persona";import{TextField}from"../../TextField";import{css,KeyCode}from"../../Util";import{Location}from"../../Utilities/Position";import{IdentityPickerSuggestionItem}from"../IdentityPickerSuggestionsList/IdentityPickerSuggestionItem";import{IdentityPickerSuggestionsList}from"../IdentityPickerSuggestionsList/IdentityPickerSuggestionsList";import{isRemoveMRUFixEnabled,shouldShowIdentityCard}from"./IdentityPickerUtils";import{IdentityType}from"./SharedIdentityPicker.Props";let textFieldId=1;class CustomIdentityPickerDropdown extends React.Component{constructor(e){super(e),this.focusWithin=React.createRef(),this.inputElement=React.createRef(),this.itemRefs={},this.openedIdentityCard=new ObservableValue(void 0),this.outerElement=React.createRef(),this.nonIdentitySuggestions=[],this.suggestionsLoading=new ObservableValue(!1),this.isEditing=new ObservableValue(!1),this.selectedIndex=new ObservableValue(-1),this.suggestions=new ObservableArray([]),this.textFieldId="identity-picker-downdown-textfield-"+textFieldId++,this.onPickerDismiss=()=>{this.props.onSuggestionsVisibleChanged(!1)},this.renderSuggestionItem=t=>React.createElement("div",{className:"flex-row flex-grow scroll-hidden",onKeyDown:this.onKeyDownSuggestionItem},React.createElement(IdentityPickerSuggestionItem,Object.assign({},t,{onOpenPersonaCard:this.openPersonaCard,onRemoveFromMRU:isRemoveMRUFixEnabled()?this.onRemoveFromMRU:void 0,ref:e=>this.itemRefs[t.item.entityId]=e,renderSuggestion:this.props.renderCustomIdentitySuggestion&&this.renderCustomSuggestionItem}))),this.renderCustomSuggestionItem=e=>this.props.renderCustomIdentitySuggestion&&this.props.renderCustomIdentitySuggestion(e.item),this.renderPersonaCoin=t=>React.createElement(Observer,{selectedIdentity:this.props.value,isEditing:this.isEditing},e=>e.selectedIdentity&&!e.isEditing?React.createElement(Persona,{className:css("flex-row flex-center justify-center",t),identity:e.selectedIdentity,size:PersonaSize.size24}):React.createElement(Icon,{className:css("flex-row flex-center justify-center",t),iconName:"Contact",size:IconSize.medium})),this.openPersonaCard=e=>{shouldShowIdentityCard(e)&&(this.openedIdentityCard.value=e)},this.closePersonaCard=()=>{this.openedIdentityCard.value=void 0,this.inputElement.current&&(this.inputElement.current.focus(),ObservableLike.getValue(this.props.suggestionsVisible)||this.props.onSuggestionsVisibleChanged(!0))},this.onRemoveFromMRU=s=>{var e,t;isRemoveMRUFixEnabled()&&null!=(t=(e=this.props.pickerProvider).removeIdentitiesFromMRU)&&t.call(e,[s]).then(e=>{var t;e?(e=this.suggestions.value.filter(e=>e.entityId!==s.entityId),t=this.selectedIndex.value,this.cachedResults={},this.setSuggestions(e,Math.min(t,e.length-1)),document.dispatchEvent(new CustomEvent("vss-telemetry-proxy",{detail:{area:"vss-identity-picker",component:"CustomIdentityPickerDropdown",feature:"IdentityPicker.MRU",level:3,method:"onRemoveFromMRU",message:"Successfully removed identity from MRU"},bubbles:!0}))):document.dispatchEvent(new CustomEvent("vss-telemetry-proxy",{detail:{area:"vss-identity-picker",component:"CustomIdentityPickerDropdown",feature:"IdentityPicker.MRU",level:3,method:"onRemoveFromMRU",message:"Failed to remove identity from MRU"},bubbles:!0}))})},this.completeSuggestion=()=>{let e;return e=0<this.suggestions.value.length&&ObservableLike.getValue(this.props.suggestionsVisible)&&-1!==this.selectedIndex.value?this.suggestions.value[this.selectedIndex.value]:(this.selectedIndex.value=-1,this.props.resolveUnrecognizedIdentity&&this.props.resolveUnrecognizedIdentity(ObservableLike.getValue(this.props.textValue))),this.selectedPersonaChanged(e),e&&this.props.onSuggestionsVisibleChanged(!1),Boolean(e)},this.onBlur=()=>{this.props.onSuggestionsVisibleChanged(!1),this.openedIdentityCard.value||(""===ObservableLike.getValue(this.props.textValue)&&this.selectedPersonaChanged(),this.props.onBlur&&this.props.onBlur())},this.onClearClicked=e=>{this.clear(),e.preventDefault()},this.onClearKeyDown=e=>{e.which===KeyCode.enter&&(this.clear(),e.preventDefault())},this.clear=()=>{var e;this.props.onClear&&this.props.onClear(),this.props.onChange(void 0),this.lastPickedIdentity=void 0,this.suggestions.value=[],null!=(e=this.inputElement.current)&&e.focus()},this.onClick=()=>{(""===ObservableLike.getValue(this.props.textValue)&&this.props.pickerProvider.onEmptyInputFocus||ObservableLike.getValue(this.props.value)&&0===this.suggestions.length)&&this.updateSuggestionsList(this.props.pickerProvider.onEmptyInputFocus()),this.props.onSuggestionsVisibleChanged(!ObservableLike.getValue(this.props.suggestionsVisible)),this.inputElement.current.select()},this.onFocus=e=>{var t=this.props["onFocus"];""===ObservableLike.getValue(this.props.textValue)&&this.props.pickerProvider.onEmptyInputFocus&&!ObservableLike.getValue(this.props.suggestionsVisible)&&this.updateSuggestionsList(this.props.pickerProvider.onEmptyInputFocus()),t&&t(e)},this.onKeyDown=e=>{if(!e.isDefaultPrevented()){var t=e.which,s=ObservableLike.getValue(this.props.suggestionsVisible),i=this.inputElement.current&&this.inputElement.current.inputElement.current;switch(t){case KeyCode.escape:!this.openedIdentityCard.value||this.suggestions.value&&this.suggestions.value[this.selectedIndex.value]||this.selectedPersonaChanged(),s&&(this.props.onSuggestionsVisibleChanged(!1),this.openedIdentityCard.value=void 0,e.stopPropagation());break;case KeyCode.tab:case KeyCode.enter:!e.shiftKey&&s?this.completeSuggestion()&&(e.preventDefault(),e.stopPropagation()):s?this.completeSuggestion():t===KeyCode.enter&&i&&!i.value&&this.selectedPersonaChanged(void 0);break;case KeyCode.rightArrow:this.suggestions.value&&this.suggestions.value[this.selectedIndex.value]&&i&&i.value.length===i.selectionEnd&&(this.focusContactCardButton(this.suggestions.value[this.selectedIndex.value]),e.preventDefault());break;case KeyCode.upArrow:s&&this.suggestions.value&&(this.selectedIndex.value=Math.max(0,this.selectedIndex.value-1),this.forceUpdate(),e.preventDefault(),e.stopPropagation());break;case KeyCode.downArrow:s&&this.suggestions.value?(this.selectedIndex.value=Math.min(this.suggestions.value.length-1,this.selectedIndex.value+1),this.forceUpdate(),e.preventDefault(),e.stopPropagation()):this.props.onSuggestionsVisibleChanged(!0)}}},this.onKeyDownSuggestionItem=e=>{e.defaultPrevented||e.which!==KeyCode.leftArrow&&e.which!==KeyCode.escape&&e.which!==KeyCode.tab||this.inputElement.current&&(this.inputElement.current.focus(),e.preventDefault())},this.focusContactCardButton=e=>{this.itemRefs[e.entityId]&&this.itemRefs[e.entityId].focus()},this.onResolveSuggestions=e=>{var t=this.props.pickerProvider.onFilterIdentities(e.toLocaleLowerCase(),[]);null!==t&&this.updateSuggestionsList(t,e)},this.onSearchChange=(e,t)=>{var s;0==t.length&&(s=this.props["onClear"],s)&&s(),this.selectedIndex.value=-1,this.isEditing.value=!0,this.props.onInputChange(t),this.updateValue(t)},this.onSuggestionClick=e=>{this.selectedIndex.value=e.index,this.selectedPersonaChanged(e.item),this.props.onSuggestionsVisibleChanged(!1)},this.onTextFieldChanged=(e,t)=>{this.setState({width:Math.max(e,296)})},this.selectedPersonaChanged=e=>{this.lastPickedIdentity!==e&&e&&this.props.pickerProvider.addIdentitiesToMRU&&this.props.pickerProvider.addIdentitiesToMRU([e]),!1!==this.props.onChange(e)?(this.props.onInputChange(e?e.displayName:""),this.lastPickedIdentity=e):(this.props.onInputChange(""),this.props.onChange(void 0),this.lastPickedIdentity=void 0),this.isEditing.value=!1},this.updateValue=e=>{this.props.onSuggestionsVisibleChanged(!!e),this.cachedResults[e]?this.updateSuggestionsList(this.cachedResults[e],e):this.onResolveSuggestions(e)},this.cachedResults={},this.timerManagement=new TimerManagement,this.lastPickedIdentity=ObservableLike.getValue(e.value),this.state={width:296}}render(){const{ariaLabel:r,ariaLabelledBy:a,autoFocus:l,disabled:d,editPlaceholder:u=Resources.IdentityPickerPlaceholderFocusText,placeholder:h=Resources.IdentityPickerPlaceholderText,required:c}=this.props;return React.createElement(Observer,{suggestionsVisible:this.props.suggestionsVisible},o=>React.createElement(FocusWithin,{onBlur:this.onBlur,onFocus:this.onFocus,ref:this.focusWithin},n=>React.createElement(React.Fragment,null,React.createElement(Observer,{selectedIdentity:this.props.value,selectedIndex:this.selectedIndex,suggestionsLoading:this.suggestionsLoading,textValue:this.props.textValue},e=>{let t;o.suggestionsVisible&&(t=-1===e.selectedIndex||e.suggestionsLoading?"sug-list-transition":this.suggestions&&this.suggestions.length?"sug-row-"+e.selectedIndex:"sug-list-no-results");var s=o.suggestionsVisible?"tag-picker-callout":void 0,i=n.hasFocus||e.selectedIdentity?u:h;return React.createElement(Measure,{onMeasure:this.onTextFieldChanged},React.createElement("div",{className:"bolt-identitypickerdropdown flex-row flex-grow",ref:this.outerElement,onKeyDown:this.onKeyDown},React.createElement(TextField,{ariaExpanded:o.suggestionsVisible,ariaActiveDescendant:t,ariaAutoComplete:"list",ariaControls:s,autoFocus:l,ariaHasPopup:"listbox",ariaLabel:r||(""===e.textValue?i:e.textValue),ariaLabelledBy:a,className:css(this.props.className,"bolt-identitypickerdropdown-textField flex-row flex-center",n.hasFocus&&"bolt-identitypickerdropdown-open"),containerClassName:"bolt-identitypickerdropdown-container flex-column flex-grow",inputId:null!=(s=this.props.inputId)?s:this.textFieldId,onBlur:n.onBlur,onChange:this.onSearchChange,onClick:this.onClick,onFocus:n.onFocus,prefixIconProps:{render:this.renderPersonaCoin},placeholder:i,ref:this.inputElement,required:c,role:"combobox",suffixIconProps:e.textValue&&!d?{ariaHidden:"false",iconName:"Clear",className:"bolt-identity-picker-clearButton fontSize",role:"button",ariaLabel:format(Resources.Remove,e.textValue),onClick:this.onClearClicked,onKeyDown:this.onClearKeyDown,tabIndex:0}:void 0,value:e.textValue,disabled:d})))}),React.createElement(Observer,{openedIdentityCard:this.openedIdentityCard,selectedIndex:this.selectedIndex},e=>React.createElement(IdentityPickerSuggestionsList,{calloutProps:{anchorElement:this.outerElement.current,anchorOrigin:{horizontal:Location.start,vertical:Location.end},calloutOrigin:{horizontal:Location.start,vertical:Location.start},contentShadow:!0,id:"tag-picker-callout",onDismiss:this.onPickerDismiss,role:"presentation"},suggestionsVisible:o.suggestionsVisible||!!e.openedIdentityCard,isLoading:this.suggestionsLoading,onBlur:n.onBlur,onFocus:n.onFocus,onSuggestionClicked:this.onSuggestionClick,onClosePersonaCard:this.closePersonaCard,onDismiss:this.onPickerDismiss,onOpenPersonaCard:this.openPersonaCard,openedIdentityCard:e.openedIdentityCard,pickerProvider:this.props.pickerProvider,renderSuggestion:this.renderSuggestionItem,suggestions:this.suggestions,suggestionTarget:this.outerElement.current,selectedIndex:e.selectedIndex,width:this.state.width,resultsMaximumNumber:this.props.suggestionItemsMaximumCount,suggestionsContainerAriaLabel:this.props.suggestionsContainerAriaLabel})))))}componentDidMount(){this.updateValue=this.timerManagement.debounce(this.updateValue,250),this.props.autoFocus&&(ObservableLike.getValue(this.props.textValue),this.props.pickerProvider.onEmptyInputFocus,this.updateSuggestionsList(this.props.pickerProvider.onEmptyInputFocus()),this.inputElement.current&&this.inputElement.current.select(),this.props.onSuggestionsVisibleChanged(!0)),this.setState({width:this.outerElement.current.clientWidth})}componentWillUnmount(){this.currentPromise&&this.currentPromise.cancel()}updateSuggestionsList(e,s){var t=e;if(Array.isArray(t))this.updateSuggestions(t,s);else if(e&&e.then){this.suggestionsLoading.value=!0;let t=[];this.props.pickerProvider.getAdditionalEntries&&(this.nonIdentitySuggestions=this.props.pickerProvider.getAdditionalEntries().map(e=>({displayName:e,entityType:IdentityType.Custom,entityId:e,originDirectory:"",originId:""})),t=this.nonIdentitySuggestions&&s?this.nonIdentitySuggestions.filter(e=>startsWith(e.displayName,s)):this.nonIdentitySuggestions);const i=this.currentPromise=makeCancelable(e);i.promise.then(e=>{i===this.currentPromise&&(e=t.length?[...e,...t].sort((e,t)=>localeIgnoreCaseComparer(e.displayName,t.displayName)):e,this.updateSuggestions(e,s),s&&""!==s&&this.suggestions.value&&0<this.suggestions.value.length&&(this.cachedResults[s]=e),this.suggestionsLoading.value=!1)})}}setSuggestions(e,t){this.suggestions.value=e,this.updateIndexTimer&&window.cancelAnimationFrame(this.updateIndexTimer),this.updateIndexTimer=window.requestAnimationFrame(()=>{this.selectedIndex.value=t})}updateSuggestions(e,t){(void 0===t||this.inputElement.current&&ObservableLike.getValue(this.props.textValue)===t)&&this.setSuggestions(e,""===ObservableLike.getValue(this.props.textValue)?-1:0)}}export{CustomIdentityPickerDropdown};