import classNames from "classnames" ; import * as React from "react" ; import { polyfill } from "react-lifecycles-compat" ; import { AbstractPureComponent2 , Alignment , Classes , IRef , refHandler , setRef } from "../../common" ; import { DISPLAYNAME_PREFIX , HTMLInputProps , Props } from "../../common/props" ; export type ControlProps = IControlProps ; deprecated export interface IControlProps extends Props , HTMLInputProps { default alignIndicator ? : Alignment ; /** Whether the control is checked. */ checked ? : boolean ; /** JSX label for the control. */ children ? : React . ReactNode ; /** Whether the control is initially checked (uncontrolled mode). */ defaultChecked ? : boolean ; /** Whether the control is non-interactive. */ disabled ? : boolean ; /** Ref handler that receives HTML `<input>` element backing this component. */ inputRef ? : IRef < HTMLInputElement > ; /** Whether the control should appear as an inline element. */ inline ? : boolean ; /**
     * Text label for the control.
     *
     * Use `children` or `labelElement` to supply JSX content. This prop actually supports JSX elements,
     * but TypeScript will throw an error because `HTMLAttributes` only allows strings.
     */ label ? : string ; /**
     * JSX Element label for the control.
     *
     * This prop is a workaround for TypeScript consumers as the type definition for `label` only
     * accepts strings. JavaScript consumers can provide a JSX element directly to `label`.
     */ labelElement ? : React . ReactNode ; /** Whether this control should use large styles. */ large ? : boolean ; /** Event handler invoked when input value is changed. */ onChange ? : React . FormEventHandler < HTMLInputElement > ; default tagName ? : keyof JSX . IntrinsicElements ; } /** Internal props for Checkbox/Radio/Switch to render correctly. */ interface IControlInternalProps extends ControlProps { type : "checkbox" | "radio" ; typeClassName : string ; indicatorChildren ? : React . ReactNode ; } /**
 * Renders common control elements, with additional props to customize appearance.
 * This component is not exported and is only used in this file for `Checkbox`, `Radio`, and `Switch` below.
 */ const Control = ( { alignIndicator , children , className , indicatorChildren , inline , inputRef , label , labelElement , large , style , type , typeClassName , tagName = "label" , ... htmlProps } ) => { const classes = classNames ( Classes . CONTROL , typeClassName , { [ Classes . DISABLED ] : htmlProps . disabled , [ Classes . INLINE ] : inline , [ Classes . LARGE ] : large , } , Classes . alignmentClass ( alignIndicator ) , className ) ; return React . createElement ( tagName , { className : classes , style } , < input { ... htmlProps } ref = { inputRef } type = { type } / > , < span className = { Classes . CONTROL_INDICATOR } > { indicatorChildren } < /span>, label, labelElement, children); } ; export type SwitchProps = ISwitchProps ; deprecated export interface ISwitchProps extends ControlProps { default innerLabelChecked ? : string ; /**
     * Text to display inside the switch indicator when unchecked.
     */ innerLabel ? : string ; } @ polyfill export class Switch extends AbstractPureComponent2 < SwitchProps > { public static displayName = `${ DISPLAYNAME_PREFIX }.Switch` ; public render ( ) { const { innerLabelChecked , innerLabel , ... controlProps } = this . props ; const switchLabels = innerLabel || innerLabelChecked ? [ < div key = "checked" className = { Classes . CONTROL_INDICATOR_CHILD } > < div className = { Classes . SWITCH_INNER_TEXT } > { innerLabelChecked ? innerLabelChecked : innerLabel } < /div> < /div>, < div key = "unchecked" className = { Classes . CONTROL_INDICATOR_CHILD } > < div className = { Classes . SWITCH_INNER_TEXT } > { innerLabel } < /div> < /div>, ] : null ; return ( < Control { ... controlProps } type = "checkbox" typeClassName = { Classes . SWITCH } indicatorChildren = { switchLabels } / > ) ; } } deprecated export type IRadioProps = ControlProps ; export type RadioProps = IRadioProps ; @ polyfill export class Radio extends AbstractPureComponent2 < RadioProps > { public static displayName = `${ DISPLAYNAME_PREFIX }.Radio` ; public render ( ) { return < Control { ... this . props } type = "radio" typeClassName = { Classes . RADIO } / > ; } } export type CheckboxProps = ICheckboxProps ; deprecated export interface ICheckboxProps extends ControlProps { /** Whether this checkbox is initially indeterminate (uncontrolled mode). */ defaultIndeterminate ? : boolean ; /**
     * Whether this checkbox is indeterminate, or "partially checked."
     * The checkbox will appear with a small dash instead of a tick to indicate that the value
     * is not exactly true or false.
     *
     * Note that this prop takes precendence over `checked`: if a checkbox is marked both
     * `checked` and `indeterminate` via props, it will appear as indeterminate in the DOM.
     */ indeterminate ? : boolean ; } export interface ICheckboxState { indeterminate : boolean ; } @ polyfill export class Checkbox extends AbstractPureComponent2 < CheckboxProps , ICheckboxState > { public static displayName = `${ DISPLAYNAME_PREFIX }.Checkbox` ; public static getDerivedStateFromProps ( { indeterminate } ) { if ( indeterminate != null ) { return { indeterminate } ; } return null ; } public state : ICheckboxState = { indeterminate : this . props . indeterminate || this . props . defaultIndeterminate || false , } ; public input : HTMLInputElement | null = null ; private handleInputRef : IRef < HTMLInputElement > = refHandler ( this , "input" , this . props . inputRef ) ; public render ( ) { const { defaultIndeterminate , indeterminate , ... controlProps } = this . props ; return ( < Control { ... controlProps } inputRef = { this . handleInputRef } onChange = { this . handleChange } type = "checkbox" typeClassName = { Classes . CHECKBOX } / > ) ; } public componentDidMount ( ) { this . updateIndeterminate ( ) ; } public componentDidUpdate ( prevProps ) { this . updateIndeterminate ( ) ; if ( prevProps . inputRef !== this . props . inputRef ) { setRef ( prevProps . inputRef , null ) ; this . handleInputRef = refHandler ( this , "input" , this . props . inputRef ) ; setRef ( this . props . inputRef , this . input ) ; } } private updateIndeterminate ( ) { if ( this . input != null ) { this . input . indeterminate = this . state . indeterminate ; } } private handleChange = ( evt ) => { const { indeterminate } = evt . target ; if ( this . props . indeterminate == null ) { this . setState ( { indeterminate } ) ; } this . props . onChange ?. ( evt ) ; } ; }