import React from 'react' ; import classnames from 'classnames' ; import { withRipple , InjectedProps , RippledComponentProps , } from '@material/react-ripple' ; import { MDCIconButtonToggleAdapter } from '@material/icon-button/adapter' ; import { MDCIconButtonToggleFoundation } from '@material/icon-button/foundation' ; import { MDCIconButtonToggleEventDetail } from '@material/icon-button/types' ; import IconToggle from './IconToggle' ; const ARIA_PRESSED = 'aria-pressed' ; interface ElementAttributes { [ ARIA_PRESSED ] ? : boolean | 'false' | 'mixed' | 'true' ; } type IconButtonTypes = HTMLButtonElement | HTMLAnchorElement ; export interface IconButtonBaseProps extends ElementAttributes { handleChange ? : ( evt : MDCIconButtonToggleEventDetail ) => void ; isLink ? : boolean ; } interface IconButtonBaseState extends ElementAttributes { classList : Set < string > ; } export interface IconButtonProps < T extends IconButtonTypes > extends InjectedProps < T > , IconButtonBaseProps , React . HTMLProps < T > { } class IconButtonBase < T extends IconButtonTypes > extends React . Component < IconButtonProps < T > , IconButtonBaseState > { foundation ! : MDCIconButtonToggleFoundation ; constructor ( props ) { super ( props ) ; this . state = { classList : new Set ( ) , [ ARIA_PRESSED ] : props [ ARIA_PRESSED ] , } ; } static defaultProps = { className : '' , handleChange : ( ) => { } , initRipple : ( ) => { } , isLink : false , onClick : ( ) => { } , unbounded : true , } ; componentDidMount ( ) { this . foundation = new MDCIconButtonToggleFoundation ( this . adapter ) ; this . foundation . init ( ) ; } get classes ( ) { const { classList } = this . state ; const { className } = this . props ; return classnames ( 'mdc-icon-button' , Array . from ( classList ) , className ) ; } get adapter ( ) : MDCIconButtonToggleAdapter { return { addClass : ( className ) => this . setState ( { classList : this . state . classList . add ( className ) } ) , removeClass : ( className ) => { const { classList } = this . state ; classList . delete ( className ) ; this . setState ( { classList } ) ; } , hasClass : ( className ) => this . classes . split ( ' ' ) . includes ( className ) , setAttr : this . updateState , notifyChange : this . props . handleChange ! , } ; } updateState = ( key , value ) => { this . setState ( ( prevState ) => ( { ... prevState , [ key ] : value , } ) ) ; } ; handleClick_ = ( e ) => { this . props . onClick ! ( e ) ; this . foundation . handleClick ( ) ; } ; render ( ) { const { children , initRipple , isLink , className , handleChange , onClick , unbounded , [ ARIA_PRESSED ] : ariaPressed , ... otherProps } = this . props ; const props = { className : this . classes , ref : initRipple , [ ARIA_PRESSED ] : this . state [ ARIA_PRESSED ] , onClick : this . handleClick_ , ... otherProps , } ; if ( isLink ) { return ( < a { ... ( props as IconButtonProps < HTMLAnchorElement > ) } > { children } < /a>); } return ( < button { ... ( props as IconButtonProps < HTMLButtonElement > ) } > { children } < /button>); } } const IconButton = withRipple < IconButtonProps < IconButtonTypes > , IconButtonTypes > ( IconButtonBase ) ; export default IconButton ; export { IconToggle , IconButtonBase } ;