license import { css } from "aphrodite" ; import React from "react" ; import { BUTTON_STYLE } from "./styles" ; export interface ButtonSpec { content ? : React . ReactNode ; title ? : string ; value : string | number | null ; } interface Props { allowEmpty ? : boolean ; buttons : ButtonSpec [ ] ; value : string | number | null ; onChange ( value ) : void ; } /**
 * ButtonGroup is an aesthetically pleasing group of buttons.
 *
 * The class requires these properties:
 *   buttons - an array of objects with keys:
 *     "value": this is the value returned when the button is selected
 *     "content": this is the JSX shown within the button, typically a string
 *         that gets rendered as the button's display text
 *     "title": this is the title-text shown on hover
 *   onChange - a function that is provided with the updated value
 *     (which it then is responsible for updating)
 *
 * The class has these optional properties:
 *   value - the initial value of the button selected, defaults to null.
 *   allowEmpty - if false, exactly one button _must_ be selected; otherwise
 *     it defaults to true and _at most_ one button (0 or 1) may be selected.
 *
 * Requires stylesheets/perseus-admin-package/editor.less to look nice.
 */ export default class ButtonGroup extends React . PureComponent < Props > { static defaultProps : Partial < Props > = { allowEmpty : true , value : null , } ; render ( ) { const value = this . props . value ; const buttons = this . props . buttons . map ( ( button , i ) => { const buttonGroupClassName = css ( BUTTON_STYLE . buttonStyle , button . value === value && BUTTON_STYLE . selectedStyle ) ; return ( < button className = { buttonGroupClassName } onClick = { this . handleClick } id = { String ( i ) } key = { String ( i ) } data - value = { JSON . stringify ( button . value ) } title = { button . title } type = "button" > { button . content || String ( button . value ) } < /button>); } ) ; const outerStyle = { display : "inline-block" , } ; return < div style = { outerStyle } > { buttons } < /div>; } private handleClick = ( ev ) : void => { this . toggleSelect ( JSON . parse ( ev . currentTarget . dataset . value || "null" ) ) ; } ; private toggleSelect ( newValue ) { const value = this . props . value ; if ( this . props . allowEmpty ) { this . props . onChange ( value !== newValue ? newValue : null ) ; } else { this . props . onChange ( newValue ) ; } } }