import classNames from "classnames" ; import * as React from "react" ; import { AbstractPureComponent2 , Button , DISPLAYNAME_PREFIX , InputGroupProps2 , InputGroup , IPopoverProps , IRef , Keys , Popover , Position , refHandler , setRef , } from "@blueprintjs/core" ; import { Classes , IListItemsProps } from "../../common" ; import { IQueryListRendererProps , QueryList } from "../query-list/queryList" ; export type SelectProps < T > = ISelectProps < T > ; deprecated export interface ISelectProps < T > extends IListItemsProps < T > { /**
     * Whether the component should take up the full width of its container.
     * This overrides `popoverProps.fill`. You also have to ensure that the child
     * component has `fill` set to `true` or is styled appropriately.
     */ fill ? : boolean ; default filterable ? : boolean ; default disabled ? : boolean ; /**
     * Props to spread to the query `InputGroup`. Use `query` and
     * `onQueryChange` instead of `inputProps.value` and `inputProps.onChange`
     * to control this input.
     */ inputProps ? : InputGroupProps2 ; default matchTargetWidth ? : boolean ; /** Props to spread to `Popover`. Note that `content` cannot be changed. */ popoverProps ? : Partial < IPopoverProps > & object ; default resetOnClose ? : boolean ; } export interface ISelectState { isOpen : boolean ; } export class Select < T > extends AbstractPureComponent2 < SelectProps < T > , ISelectState > { public static displayName = `${ DISPLAYNAME_PREFIX }.Select` ; public static ofType < U > ( ) { return Select as new ( props ) => Select < U > ; } public state : ISelectState = { isOpen : false } ; private TypedQueryList = QueryList . ofType < T > ( ) ; public inputElement : HTMLInputElement | null = null ; private queryList : QueryList < T > | null = null ; private previousFocusedElement : HTMLElement | undefined ; private handleInputRef : IRef < HTMLInputElement > = refHandler ( this , "inputElement" , this . props . inputProps ?. inputRef ) ; private handleQueryListRef = ( ref ) => ( this . queryList = ref ) ; public render ( ) { const { filterable , inputProps , popoverProps , ... restProps } = this . props ; return ( < this . TypedQueryList { ... restProps } onItemSelect = { this . handleItemSelect } ref = { this . handleQueryListRef } renderer = { this . renderQueryList } / > ) ; } public componentDidUpdate ( prevProps , prevState ) { if ( prevProps . inputProps ?. inputRef !== this . props . inputProps ?. inputRef ) { setRef ( prevProps . inputProps ?. inputRef , null ) ; this . handleInputRef = refHandler ( this , "inputElement" , this . props . inputProps ?. inputRef ) ; setRef ( this . props . inputProps ?. inputRef , this . inputElement ) ; } if ( this . state . isOpen && ! prevState . isOpen && this . queryList != null ) { this . queryList . scrollActiveItemIntoView ( ) ; } } private renderQueryList = ( listProps ) => { const { fill , filterable = true , disabled = false , inputProps = { } , popoverProps = { } , matchTargetWidth , } = this . props ; if ( fill ) { popoverProps . fill = true ; } if ( matchTargetWidth ) { if ( popoverProps . modifiers == null ) { popoverProps . modifiers = { } ; } popoverProps . modifiers . minWidth = { enabled : true , fn : data => { data . styles . width = `${ data . offsets . reference . width }px` ; return data ; } , order : 800 , } ; popoverProps . usePortal = false ; popoverProps . wrapperTagName = "div" ; } const input = ( < InputGroup leftIcon = "search" placeholder = "Filter..." rightElement = { this . maybeRenderClearButton ( listProps . query ) } { ... inputProps } inputRef = { this . handleInputRef } onChange = { listProps . handleQueryChange } value = { listProps . query } / > ) ; const { handleKeyDown , handleKeyUp } = listProps ; return ( < Popover autoFocus = { false } enforceFocus = { false } isOpen = { this . state . isOpen } disabled = { disabled } position = { Position . BOTTOM_LEFT } { ... popoverProps } className = { classNames ( listProps . className , popoverProps . className ) } onInteraction = { this . handlePopoverInteraction } popoverClassName = { classNames ( Classes . SELECT_POPOVER , popoverProps . popoverClassName , { [ Classes . SELECT_MATCH_TARGET_WIDTH ] : matchTargetWidth , } ) } onOpening = { this . handlePopoverOpening } onOpened = { this . handlePopoverOpened } onClosing = { this . handlePopoverClosing } > < div onKeyDown = { this . state . isOpen ? handleKeyDown : this . handleTargetKeyDown } onKeyUp = { this . state . isOpen ? handleKeyUp : undefined } > { this . props . children } < /div> < div onKeyDown = { handleKeyDown } onKeyUp = { handleKeyUp } > { filterable ? input : undefined } { listProps . itemList } < /div> { } < /Popover>); } ; private maybeRenderClearButton ( query ) { return query . length > 0 ? < Button icon = "cross" minimal = { true } onClick = { this . resetQuery } / > : undefined ; } private handleTargetKeyDown = ( event ) => { if ( event . which === Keys . ARROW_UP || event . which === Keys . ARROW_DOWN ) { event . preventDefault ( ) ; this . setState ( { isOpen : true } ) ; } } ; private handleItemSelect = ( item , event ? ) => { this . setState ( { isOpen : false } ) ; this . props . onItemSelect ?. ( item , event ) ; } ; private handlePopoverInteraction = ( isOpen , event ? ) => { this . setState ( { isOpen } ) ; this . props . popoverProps ?. onInteraction ?. ( isOpen , event ) ; } ; private handlePopoverOpening = ( node ) => { this . previousFocusedElement = document . activeElement as HTMLElement ; if ( this . props . resetOnClose ) { this . resetQuery ( ) ; } this . props . popoverProps ?. onOpening ?. ( node ) ; } ; private handlePopoverOpened = ( node ) => { if ( this . queryList != null ) { this . queryList . scrollActiveItemIntoView ( ) ; } this . requestAnimationFrame ( ( ) => { const { inputProps = { } } = this . props ; if ( inputProps . autoFocus !== false ) { this . inputElement ?. focus ( ) ; } } ) ; this . props . popoverProps ?. onOpened ?. ( node ) ; } ; private handlePopoverClosing = ( node ) => { this . requestAnimationFrame ( ( ) => { if ( this . previousFocusedElement !== undefined ) { this . previousFocusedElement . focus ( ) ; this . previousFocusedElement = undefined ; } } ) ; this . props . popoverProps ?. onClosing ?. ( node ) ; } ; private resetQuery = ( ) => this . queryList && this . queryList . setQuery ( "" , true ) ; }