import classNames from "classnames" ; import * as React from "react" ; import { AbstractPureComponent2 , Alignment , Classes , ActionProps , IElementRefProps , Keys , MaybeElement , Utils , } from "../../common" ; import { Icon , IconName , IconSize } from "../icon/icon" ; import { Spinner } from "../spinner/spinner" ; export type ButtonProps < E extends HTMLButtonElement | HTMLAnchorElement = HTMLButtonElement > = IButtonProps < E > ; deprecated export interface IButtonProps < E extends HTMLButtonElement | HTMLAnchorElement = HTMLButtonElement > extends ActionProps , IElementRefProps < E > { default active ? : boolean ; default alignText ? : Alignment ; /** Whether this button should expand to fill its container. */ fill ? : boolean ; /** Whether this button should use large styles. */ large ? : boolean ; default loading ? : boolean ; /** Whether this button should use minimal styles. */ minimal ? : boolean ; /** Whether this button should use outlined styles. */ outlined ? : boolean ; /** Name of a Blueprint UI icon (or an icon element) to render after the text. */ rightIcon ? : IconName | MaybeElement ; /** Whether this button should use small styles. */ small ? : boolean ; default type ? : "submit" | "reset" | "button" ; } deprecated export type IAnchorButtonProps = ButtonProps < HTMLAnchorElement > ; export type AnchorButtonProps = IAnchorButtonProps ; export interface IButtonState { isActive : boolean ; } export abstract class AbstractButton < E extends HTMLButtonElement | HTMLAnchorElement > extends AbstractPureComponent2 < ButtonProps < E > & ( E extends HTMLButtonElement ? React . ButtonHTMLAttributes < HTMLButtonElement > : React . AnchorHTMLAttributes < HTMLAnchorElement > ) , IButtonState > { public state = { isActive : false , } ; protected abstract buttonRef : HTMLElement | null ; private currentKeyDown ? : number ; public abstract render ( ) ; protected getCommonButtonProps ( ) { const { active , alignText , fill , large , loading , outlined , minimal , small , tabIndex } = this . props ; const disabled = this . props . disabled || loading ; const className = classNames ( Classes . BUTTON , { [ Classes . ACTIVE ] : ! disabled && ( active || this . state . isActive ) , [ Classes . DISABLED ] : disabled , [ Classes . FILL ] : fill , [ Classes . LARGE ] : large , [ Classes . LOADING ] : loading , [ Classes . MINIMAL ] : minimal , [ Classes . OUTLINED ] : outlined , [ Classes . SMALL ] : small , } , Classes . alignmentClass ( alignText ) , Classes . intentClass ( this . props . intent ) , this . props . className ) ; return { className , disabled , onBlur : this . handleBlur , onClick : disabled ? undefined : this . props . onClick , onKeyDown : this . handleKeyDown , onKeyUp : this . handleKeyUp , tabIndex : disabled ? - 1 : tabIndex , } ; } protected handleKeyDown = ( e ) => { if ( Keys . isKeyboardClick ( e . which ) ) { e . preventDefault ( ) ; if ( e . which !== this . currentKeyDown ) { this . setState ( { isActive : true } ) ; } } this . currentKeyDown = e . which ; this . props . onKeyDown ?. ( e ) ; } ; protected handleKeyUp = ( e ) => { if ( Keys . isKeyboardClick ( e . which ) ) { this . setState ( { isActive : false } ) ; this . buttonRef ?. click ( ) ; } this . currentKeyDown = undefined ; this . props . onKeyUp ?. ( e ) ; } ; protected handleBlur = ( e ) => { if ( this . state . isActive ) { this . setState ( { isActive : false } ) ; } this . props . onBlur ?. ( e ) ; } ; protected renderChildren ( ) { const { children , icon , loading , rightIcon , text } = this . props ; return [ loading && < Spinner key = "loading" className = { Classes . BUTTON_SPINNER } size = { IconSize . LARGE } / > , < Icon key = "leftIcon" icon = { icon } / > , ( ! Utils . isReactNodeEmpty ( text ) || ! Utils . isReactNodeEmpty ( children ) ) && ( < span key = "text" className = { Classes . BUTTON_TEXT } > { text } { children } < /span>), < Icon key = "rightIcon" icon = { rightIcon } / > , ] ; } }