import autobind from "autobind-decorator" ; import * as React from "react" ; import { HotKeys } from "react-hotkeys" ; import ReactModal from "react-modal" ; import { IHandlers , IKeyMap } from "models" ; import { IQuickSelectProps } from "props/modals" ; import { IQuickSelectState } from "states/modals" ; import Utils from "Utils" ; import "styles/panels/QuickSelect.scss" ; /**
 * A component that handles quick selection of an arbitrary list of actions.
 */ class QuickSelect extends React . Component < IQuickSelectProps , IQuickSelectState > { /** A keymap for hot keys when QuickSelect focused. */ private keyMap : IKeyMap = { close : [ "esc" ] , complete : [ "tab" ] , nextItem : [ "down" ] , previousItem : [ "up" ] , selectItem : [ "enter" ] } ; /** Handler functions for the given events this component handles. */ private handlers : IHandlers = { close : this . closeQuickSelect , complete : this . completeInput , nextItem : this . selectNextItem , previousItem : this . selectPreviousItem , selectItem : this . handleSelectItem } ; /** Styles for the ReactModal component this QuickSelect utilises. */ private styles = { content : { backgroundColor : this . props . theme . quickSelect . backgroundColour , border : undefined , borderRadius : "1px" , bottom : undefined , boxShadow : "0 5px 15px black" , color : this . props . theme . quickSelect . colour , left : "25%" , padding : "20px 10px" , right : "25%" , top : "0" } , overlay : { backgroundColor : "rgba(0, 0, 0, 0)" , zIndex : "200" } } ; /** The input field for the QuickSelect. */ private input ? : HTMLInputElement | null ; param props public constructor ( props ) { super ( props ) ; this . state = { selectedIndex : 0 } ; } returns public render ( ) { const { selectedColour , backgroundColour } = this . props . theme . quickSelect ; const items = this . props . initialItems . map ( ( item , i ) => { const containerBackground = { backgroundColor : this . state . selectedIndex === i ? selectedColour : backgroundColour } ; return < div key = { item . key as string } style = { containerBackground } > { item } < /div>; } ) ; return < ReactModal isOpen = { this . props . isOpen } style = { this . styles } contentLabel = "Quick Select" > < HotKeys keyMap = { this . keyMap } handlers = { this . handlers } focused > < input type = "text" value = { this . props . inputValue } onKeyUp = { this . props . onKeyUp } ref = { input => { this . input = input ; this . input && Utils . autoFocus ( this . input ) ; } } /> < ul > { items } < /ul> < /HotKeys> < /ReactModal>; } @ autobind private closeQuickSelect ( ) { this . props . onClose ( ) ; } @ autobind private completeInput ( ) { const selectedItem = this . props . initialItems [ this . state . selectedIndex ] ; if ( this . input ) { this . input . value = selectedItem . props . value ; } this . setState ( { selectedIndex : 0 } as IQuickSelectState ) ; this . props . onUpdate && this . props . onUpdate ( selectedItem . props . value ) ; } @ autobind private handleSelectItem ( ) { const selectedItem = this . props . initialItems [ this . state . selectedIndex ] ; this . props . onSelect ( selectedItem . props . value ) ; } @ autobind private selectNextItem ( ) { if ( this . state . selectedIndex < this . props . initialItems . length - 1 ) { this . setState ( currentState => ( { selectedIndex : currentState . selectedIndex + 1 } as IQuickSelectState ) ) ; } else { this . setState ( { selectedIndex : 0 } as IQuickSelectState ) ; } } @ autobind private selectPreviousItem ( ) { if ( this . state . selectedIndex > 0 ) { this . setState ( ( currentState ) => ( { selectedIndex : currentState . selectedIndex - 1 } as IQuickSelectState ) ) ; } else { this . setState ( { selectedIndex : this . props . initialItems . length - 1 } as IQuickSelectState ) ; } } } export default QuickSelect ;