import classNames from "classnames" ; import * as React from "react" ; import { polyfill } from "react-lifecycles-compat" ; import { AbstractPureComponent2 , Classes , IRef } from "../../common" ; import * as Errors from "../../common/errors" ; import { DISPLAYNAME_PREFIX , HTMLInputProps , IControlledProps , ControlledProps2 , IntentProps , Props , MaybeElement , removeNonHTMLProps , } from "../../common/props" ; import { Icon , IconName } from "../icon/icon" ; import { AsyncControllableInput } from "./asyncControllableInput" ; export type InputGroupProps = IInputGroupProps ; deprecated export interface IInputGroupProps extends IControlledProps , IntentProps , Props { default asyncControl ? : boolean ; default disabled ? : boolean ; /**
     * Whether the component should take up the full width of its container.
     */ fill ? : boolean ; /** Ref handler or a ref object that receives HTML `<input>` element backing this component. */ inputRef ? : IRef < HTMLInputElement > ; /**
     * Element to render on the left side of input.  This prop is mutually exclusive
     * with `leftIcon`.
     */ leftElement ? : JSX . Element ; /**
     * Name of a Blueprint UI icon to render on the left side of the input group,
     * before the user's cursor.  This prop is mutually exclusive with `leftElement`.
     * Usage with content is deprecated.  Use `leftElement` for elements.
     */ leftIcon ? : IconName | MaybeElement ; /** Whether this input should use large styles. */ large ? : boolean ; /** Whether this input should use small styles. */ small ? : boolean ; /** Placeholder text in the absence of any value. */ placeholder ? : string ; /**
     * Element to render on right side of input.
     * For best results, use a minimal button, tag, or small spinner.
     */ rightElement ? : JSX . Element ; /** Whether the input (and any buttons) should appear with rounded caps. */ round ? : boolean ; default type ? : string ; } export type InputGroupProps2 = IInputGroupProps2 ; deprecated export interface IInputGroupProps2 extends Omit < HTMLInputProps , keyof ControlledProps2 > , ControlledProps2 , IntentProps , Props { default asyncControl ? : boolean ; default disabled ? : boolean ; /**
     * Whether the component should take up the full width of its container.
     */ fill ? : boolean ; /** Ref handler or a ref object that receives HTML `<input>` element backing this component. */ inputRef ? : IRef < HTMLInputElement > ; /**
     * Element to render on the left side of input.  This prop is mutually exclusive
     * with `leftIcon`.
     */ leftElement ? : JSX . Element ; /**
     * Name of a Blueprint UI icon to render on the left side of the input group,
     * before the user's cursor.  This prop is mutually exclusive with `leftElement`.
     * Usage with content is deprecated.  Use `leftElement` for elements.
     */ leftIcon ? : IconName | MaybeElement ; /** Whether this input should use large styles. */ large ? : boolean ; /** Whether this input should use small styles. */ small ? : boolean ; /** Placeholder text in the absence of any value. */ placeholder ? : string ; /**
     * Element to render on right side of input.
     * For best results, use a minimal button, tag, or small spinner.
     */ rightElement ? : JSX . Element ; /** Whether the input (and any buttons) should appear with rounded caps. */ round ? : boolean ; default type ? : string ; } export interface IInputGroupState { leftElementWidth ? : number ; rightElementWidth ? : number ; } @ polyfill export class InputGroup extends AbstractPureComponent2 < InputGroupProps2 , IInputGroupState > { public static displayName = `${ DISPLAYNAME_PREFIX }.InputGroup` ; public state : IInputGroupState = { } ; private leftElement : HTMLElement | null = null ; private rightElement : HTMLElement | null = null ; private refHandlers = { leftElement : ( ref ) => ( this . leftElement = ref ) , rightElement : ( ref ) => ( this . rightElement = ref ) , } ; public render ( ) { const { asyncControl = false , className , disabled , fill , inputRef , intent , large , small , round } = this . props ; const inputGroupClasses = classNames ( Classes . INPUT_GROUP , Classes . intentClass ( intent ) , { [ Classes . DISABLED ] : disabled , [ Classes . FILL ] : fill , [ Classes . LARGE ] : large , [ Classes . SMALL ] : small , [ Classes . ROUND ] : round , } , className ) ; const style = { ... this . props . style , paddingLeft : this . state . leftElementWidth , paddingRight : this . state . rightElementWidth , } ; const inputProps = { type : "text" , ... removeNonHTMLProps ( this . props ) , className : Classes . INPUT , style , } ; return ( < div className = { inputGroupClasses } > { this . maybeRenderLeftElement ( ) } { asyncControl ? ( < AsyncControllableInput { ... inputProps } inputRef = { inputRef } / > ) : ( < input { ... inputProps } ref = { inputRef } / > ) } { this . maybeRenderRightElement ( ) } < /div>); } public componentDidMount ( ) { this . updateInputWidth ( ) ; } public componentDidUpdate ( prevProps ) { const { leftElement , rightElement } = this . props ; if ( prevProps . leftElement !== leftElement || prevProps . rightElement !== rightElement ) { this . updateInputWidth ( ) ; } } protected validateProps ( props ) { if ( props . leftElement != null && props . leftIcon != null ) { console . warn ( Errors . INPUT_WARN_LEFT_ELEMENT_LEFT_ICON_MUTEX ) ; } } private maybeRenderLeftElement ( ) { const { leftElement , leftIcon } = this . props ; if ( leftElement != null ) { return ( < span className = { Classes . INPUT_LEFT_CONTAINER } ref = { this . refHandlers . leftElement } > { leftElement } < /span>); } else if ( leftIcon != null ) { return < Icon icon = { leftIcon } />; } return undefined ; } private maybeRenderRightElement ( ) { const { rightElement } = this . props ; if ( rightElement == null ) { return undefined ; } return ( < span className = { Classes . INPUT_ACTION } ref = { this . refHandlers . rightElement } > { rightElement } < /span>); } private updateInputWidth ( ) { const { leftElementWidth , rightElementWidth } = this . state ; if ( this . leftElement != null ) { const { clientWidth } = this . leftElement ; if ( leftElementWidth === undefined || Math . abs ( clientWidth - leftElementWidth ) > 2 ) { this . setState ( { leftElementWidth : clientWidth } ) ; } } else { this . setState ( { leftElementWidth : undefined } ) ; } if ( this . rightElement != null ) { const { clientWidth } = this . rightElement ; if ( rightElementWidth === undefined || Math . abs ( clientWidth - rightElementWidth ) > 2 ) { this . setState ( { rightElementWidth : clientWidth } ) ; } } else { this . setState ( { rightElementWidth : undefined } ) ; } } }