UNPKG

azure-devops-ui

Version:

React components for building web UI in Azure DevOps

118 lines (117 loc) 7.46 kB
import "../../CommonImports"; import "../../Core/core.css"; import "./IdentityPickerSuggestionsList.css"; import * as React from "react"; import { format } from '../../Core/Util/String'; import { Button } from '../../Button'; import { Icon } from '../../Icon'; import { Persona, PersonaSize } from '../../Persona'; import * as Resources from '../../Resources.IdentityPicker'; import { Tooltip } from '../../TooltipEx'; import { KeyCode } from '../../Util'; import { getScopedGroupParts, getSignInAddress, isGithubUser, isRemoveMRUFixEnabled, shouldShowIdentityCard } from "../IdentityPickerDropdown/IdentityPickerUtils"; import { IdentityType } from "../IdentityPickerDropdown/SharedIdentityPicker.Props"; export class IdentityPickerSuggestionItem extends React.Component { constructor(props) { super(props); this.contactCardButtonRef = React.createRef(); this.removeButtonRef = React.createRef(); this.handleButtonKeyDown = (keyCode, targetRef) => (e) => { if (isRemoveMRUFixEnabled() && e.which === keyCode && targetRef.current) { targetRef.current.focus(); e.preventDefault(); e.stopPropagation(); // Track keyboard navigation between buttons document.dispatchEvent(new CustomEvent('vss-telemetry-proxy', { detail: { area: "vss-identity-picker", component: "IdentityPickerSuggestionItem", feature: "IdentityPicker.MRU", level: 3, method: "handleButtonKeyDown", message: "Navigate between MRU buttons with arrow keys" }, bubbles: true })); } }; this.onRemoveButtonKeyDown = this.handleButtonKeyDown(KeyCode.rightArrow, this.contactCardButtonRef); this.onContactCardButtonKeyDown = this.handleButtonKeyDown(KeyCode.leftArrow, this.removeButtonRef); this.state = { focused: false }; this.onFocus = this.onFocus.bind(this); this.onBlur = this.onBlur.bind(this); } onFocus() { this.setState({ focused: true }); } onBlur() { this.setState({ focused: false }); } render() { const identity = this.props.item; const showRemoveButton = isRemoveMRUFixEnabled() && !!this.props.onRemoveFromMRU && identity.isMru; let signInAddress = getSignInAddress(identity); let displayName = identity.displayName; const scopedGroupParts = getScopedGroupParts(identity); if (scopedGroupParts) { displayName = scopedGroupParts.name; if (!signInAddress) { signInAddress = scopedGroupParts.scope; } } return (React.createElement("div", { className: "bolt-picker-suggesteditem flex-row flex-grow flex-center scroll-hidden", onFocus: this.onFocus, onBlur: this.onBlur }, this.props.renderSuggestion && identity.entityType === IdentityType.Custom ? (this.props.renderSuggestion(this.props)) : (React.createElement("div", { className: "bolt-picker-suggesteditem-text flex-row flex-grow flex-center text-ellipsis" }, React.createElement(Persona, { ariaHidden: true, className: "bolt-picker-persona text-ellipsis", identity: identity, size: PersonaSize.size24 }), React.createElement("div", { className: "bolt-picker-persona-name flex-column flex-grow" }, displayName && (React.createElement(Tooltip, { text: identity.displayName, overflowOnly: identity.displayName === displayName }, React.createElement("div", { className: "fontSizeM text-ellipsis" }, displayName))), !signInAddress ? (undefined) : (React.createElement("div", { className: "flex-row" }, isGithubUser(identity) && (React.createElement(Icon, { className: "bolt-identitypicker-github-icon flex-row flex-center justify-center", iconName: "GitHubLogo" })), React.createElement("div", { className: "fontSize secondary-text text-ellipsis" }, signInAddress)))))), showRemoveButton && (React.createElement(Button, { ariaLabel: format(Resources.RemoveFromRecent, displayName), className: "identity-picker-delete-icon", iconProps: { iconName: "Cancel", className: "flex-shrink" }, onClick: (e) => { this.props.onRemoveFromMRU && this.props.onRemoveFromMRU(identity); e.preventDefault(); e.stopPropagation(); // Track remove button click document.dispatchEvent(new CustomEvent('vss-telemetry-proxy', { detail: { area: "vss-identity-picker", component: "IdentityPickerSuggestionItem", feature: "IdentityPicker.MRU", level: 3, method: "onRemoveButtonClick", message: "Remove button clicked to remove identity from MRU" }, bubbles: true })); }, onBlur: this.props.onBlur, onFocus: this.props.onFocus, onKeyDown: this.onRemoveButtonKeyDown, ref: this.removeButtonRef, subtle: true, tooltipProps: { text: format(Resources.RemoveFromRecent, displayName), showOnFocus: true }, tabIndex: this.state.focused ? 0 : -1, ariaHidden: this.state.focused ? false : true })), !!this.props.onOpenPersonaCard && shouldShowIdentityCard(identity) && (React.createElement(Button, { ariaLabel: Resources.IdentityPickerProfileCardButtonTooltip, className: "bolt-contact-card-button flex-noshrink", iconProps: { iconName: "ContactCard", className: "flex-shrink" }, onClick: (e) => { this.props.onOpenPersonaCard && this.props.onOpenPersonaCard(identity); e.preventDefault(); }, onBlur: this.props.onBlur, onFocus: this.props.onFocus, // TODO: When removing feature flag, change to: onKeyDown={this.onContactCardButtonKeyDown} onKeyDown: showRemoveButton ? this.onContactCardButtonKeyDown : undefined, ref: this.contactCardButtonRef, subtle: true, tooltipProps: { text: Resources.IdentityPickerProfileCardButtonTooltip, showOnFocus: true }, tabIndex: this.state.focused ? 0 : -1, ariaHidden: this.state.focused ? false : true })))); } focus() { if (isRemoveMRUFixEnabled() && this.removeButtonRef.current) { this.removeButtonRef.current.focus(); // Track focus on remove button document.dispatchEvent(new CustomEvent('vss-telemetry-proxy', { detail: { area: "vss-identity-picker", component: "IdentityPickerSuggestionItem", feature: "IdentityPicker.MRU", level: 3, method: "focus", message: "Focus set on remove button" }, bubbles: true })); } else if (this.contactCardButtonRef.current) { this.contactCardButtonRef.current.focus(); } } }