import autobind from "autobind-decorator" ; import * as React from "react" ; import { HotKeys } from "react-hotkeys" ; import { DirectoryItemIcon } from "components/blocks" ; import LoggedError from "errors/LoggedError" ; import { IHandlers } from "models" ; import { IInputItemProps } from "props/blocks" ; import { IInputItemState } from "states/blocks" ; import "styles/blocks/InputItem.scss" ; /** The input component to create a new directory item. */ class InputItem extends React . Component < IInputItemProps , IInputItemState > { /** Handler functions for the given events this component handles. */ private handlers : IHandlers = { moveBack : ( ) => { } , moveDown : ( ) => { } , moveUp : ( ) => { } } ; /** A reference to this input element. */ private input ? : HTMLInputElement | null ; param props public constructor ( props ) { super ( props ) ; this . state = { isInvalid : false } ; } /** Sets the focus to this item immediately after mounting. */ public componentDidMount ( ) { this . input && this . input . focus ( ) ; } param nextProps param nextState returns public shouldComponentUpdate ( nextProps , nextState ) { return this . state . isInvalid !== nextState . isInvalid ; } returns public render ( ) { const inputStyle = { border : this . state . isInvalid ? `2px solid ${ this . props . theme . inputItem . invalidInput }` : `2px solid ${ this . props . theme . primaryBackgroundColour }` } ; const icon = this . props . creatingItemType && < DirectoryItemIcon directoryItemType = { this . props . creatingItemType } theme = { this . props . theme } / > ; return ( < HotKeys handlers = { this . handlers } > < div className = "Item InputItem" > { icon } < input type = "text" style = { inputStyle } ref = { input => this . input = input } onKeyUp = { this . handleKeyUp } / > < /div> < /HotKeys>); } param event @ autobind private handleKeyUp ( event ) { if ( ! this . input ) { return ; } if ( this . props . sendUpCreateItem ) { return this . handleCreate ( event ) ; } else if ( this . props . sendUpRenameItem ) { return this . handleRename ( event ) ; } throw new LoggedError ( "No callback function passed to InputItem component" ) ; } param event require private handleCreate ( event ) { if ( event . key === "Escape" ) { return this . props . sendUpCreateItem ! ( ) ; } if ( ! this . validate ( this . input ! . value ) ) { this . setState ( { isInvalid : true } as IInputItemState ) ; return ; } else { this . setState ( { isInvalid : false } as IInputItemState ) ; } if ( event . key === "Enter" ) { return this . props . sendUpCreateItem ! ( this . input ! . value , this . props . creatingItemType ) ; } } param event require private handleRename ( event ) { if ( event . key === "Escape" ) { return this . props . sendUpRenameItem ! ( ) ; } if ( ! this . validate ( this . input ! . value ) ) { this . setState ( { isInvalid : true } as IInputItemState ) ; return ; } else { this . setState ( { isInvalid : false } as IInputItemState ) ; } if ( event . key === "Enter" ) { if ( ! this . props . thisItem ) { throw new LoggedError ( "thisItem is not defined" ) ; } return this . props . sendUpRenameItem ! ( this . props . thisItem . name , this . input ! . value ) ; } } param content returns private validate ( content ) { if ( ! content ) { return false ; } if ( this . props . otherItems . some ( item => item . name === content ) ) { return false ; } return true ; } } export default InputItem ;