import m from 'mithril' ; import classnames from 'classnames' ; import { AbstractComponent } from '../abstract-component' ; import { IInputAttrs , Input } from '../input' ; import { IButtonAttrs , Button } from '../button' ; import { IPopoverAttrs , Popover } from '../popover' ; import { TextArea } from '../text-area' ; import { Classes , safeCall , Keys , getClosest } from '../../_shared' ; export interface IInputPopoverAttrs extends Omit < IPopoverAttrs , 'content' > { default contentAttrs ? : any ; /** Initial value to display */ value ? : string ; /** Elements added before content */ header ? : m . Children ; /** Elements added after content */ footer ? : m . Children ; /** Whether to highlight input text on open */ hightlightOnOpen ? : boolean ; default inputAttrs ? : IInputAttrs ; default type ? : 'input' | 'textarea' ; /** Placeholder value for input  */ placeholder ? : string ; /**
     * Callback invoked when submit button is clicked
     * (or if type="input", submitOnEnter="true" and ENTER key is pressed)
     */ onSubmit : ( value : string ) => void ; default submitButtonAttrs ? : IButtonAttrs ; default submitButtonLabel ? : m . Children ; default submitOnEnter ? : boolean ; } export class InputPopover extends AbstractComponent < IInputPopoverAttrs > { private value : string ; public getDefaultAttrs ( ) { return { contentAttrs : { } , inputAttrs : { } , submitButtonAttrs : { } , submitButtonLabel : 'Submit' , type : 'input' } as IInputPopoverAttrs ; } public oninit ( vnode ) { super . oninit ( vnode ) ; this . value = vnode . attrs . value || '' ; } public view ( ) { const { class : className , value , header , contentAttrs , footer , inputAttrs , onSubmit , submitButtonAttrs , submitButtonLabel , placeholder , type , ... popoverAttrs } = this . attrs ; return m ( Popover , { class : classnames ( Classes . INPUT_POPOVER , className ) , autofocus : true , ... popoverAttrs , content : m ( `.${ Classes . INPUT_POPOVER_CONTENT }` , { ... contentAttrs , onkeydown : this . handleOnKeyDown } , [ header , this . renderInput ( ) , m ( Button , { class : Classes . POPOVER_DISSMISS , fluid : true , intent : 'primary' , label : submitButtonLabel , onclick : this . handleOnSubmit , ... submitButtonAttrs } ) , footer ] ) , onClosed : this . handleOnClosed , onOpened : this . handleOnOpened } ) ; } private renderInput ( ) { const { type , inputAttrs , placeholder } = this . attrs ; const component = type === 'textarea' ? TextArea : Input ; console . log ( this . value ) ; return m ( component , { autofocus : true , rows : 5 , fluid : true , value : this . value , onkeyup : ( e ) => this . value = ( e . target as HTMLInputElement ) . value , placeholder , ... inputAttrs } ) ; } private handleOnKeyDown = ( e ) => { const { type , submitOnEnter } = this . attrs ; if ( e . which === Keys . ENTER && type === 'input' && submitOnEnter ) { const contentEl = getClosest ( e . target , `.${ Classes . INPUT_POPOVER_CONTENT }` ) ! ; const submitBtnEl = contentEl . querySelector ( `.${ Classes . POPOVER_DISSMISS }` ) as HTMLElement ; submitBtnEl . click ( ) ; m . redraw ( ) ; } ( e as any ) . redraw = false ; } ; private handleOnSubmit = ( e ) => { const { submitButtonAttrs } = this . attrs ; this . attrs . onSubmit ( this . value ) ; safeCall ( submitButtonAttrs ! . onclick , e ) ; } ; private handleOnOpened = ( content ) => { const { type , hightlightOnOpen , onOpened } = this . attrs ; this . value = this . attrs . value || '' ; if ( hightlightOnOpen ) { const inputEl = content . querySelector ( type ! ) as HTMLInputElement ; requestAnimationFrame ( ( ) => inputEl . select ( ) ) ; } safeCall ( onOpened ) ; } ; private handleOnClosed = ( ) => { const { onClosed } = this . attrs ; safeCall ( onClosed ) ; } ; }