UNPKG

@muvehealth/fixins

Version:

Component library for Muvehealth

164 lines (153 loc) 4.52 kB
// @flow import React, { PureComponent } from 'react' import { any, append, equals, map, pathOr, prop, propOr, reject } from 'ramda' import Box from '../../elements/Box' import Checkbox from '../../elements/Checkbox' import ErrorMessage from '../../elements/ErrorMessage' import Grid from '../../elements/Grid' import Label from '../../elements/Label' import { isNotEmptyOrNotNil } from '../../utils' import { type EventType, type InputType, type MetaType } from '../../types' const checkboxGridModifierProps = (modifier, columns) => { switch (modifier) { case 'vertical': return null default: return { gridTemplateColumns: [ '1fr', `repeat(${columns != null ? columns : 4}, 1fr)`, `repeat(${columns != null ? columns : 4}, 1fr)`, ], gridTemplateRows: [ `repeat(${columns != null ? columns : 4}, 1fr)`, '1fr', '1fr', ], } } } type Props = { change?: (string | () => string, Array<string> | () => Array<string>) => void, columns?: number, input?: InputType, gridStyles?: {}, label: string, labelColor?: ?string, labelModifier?: ?string, labelTextStyle?: string, meta?: MetaType, modifier?: string, noLabel?: boolean, onChange?: ?(boolean, Array<string>) => void, onChangeDouble?: ?(boolean, Array<string>) => void, readOnly?: boolean, values: Array<{ label: string, value: string, id?: ?string, }>, } type State = { values: Array<string>, } class CheckboxGroup extends PureComponent<Props, State> { static defaultProps = { change: undefined, columns: 4, gridStyles: undefined, input: undefined, labelColor: undefined, labelModifier: undefined, labelTextStyle: '', meta: undefined, modifier: 'horizontal', noLabel: false, onChange: undefined, onChangeDouble: undefined, readOnly: false, } // eslint-disable-next-line react/no-unused-state state = { values: [] } componentWillMount() { this.setState((state, props) => ({ values: pathOr([], ['input', 'value'], props), })) } handleOnChange = (e: EventType) => { const { target } = e this.setState((state, props) => { let newValues = state.values const { change, input, onChange, onChangeDouble } = props if (target && target.checked) { newValues = append(target.value, state.values) } else if (target && !target.checked) { newValues = reject(equals(target.value), state.values) } if (change && input) { change(input.name, newValues) } if (onChangeDouble != null) { onChangeDouble(target.checked, newValues) } else if (onChange) { onChange(target.checked, newValues) } return { values: newValues, } }) } render() { const { columns, input, label, labelColor, labelModifier, labelTextStyle, meta, modifier, noLabel, onChange, onChangeDouble, readOnly, values, gridStyles, ...styles } = this.props return ( <Box {...styles}> <Label color={labelColor} fontSize={2} hidden={noLabel} htmlFor={prop('name', input)} mb={4} textStyle={labelModifier === 'decal' ? 'uppercase' : labelTextStyle} modifier={labelModifier} > {label} </Label> <Grid gridColumnGap={3} gridRowGap={4} {...checkboxGridModifierProps(modifier, columns)} // $FlowFixMe: Dont want to limit styled-system props {...gridStyles} > { map(({ label: optionLabel, value: optionValue }) => ( <Checkbox defaultChecked={any(equals(optionValue), propOr([], 'value', input))} id={`${prop('name', input)}-${optionLabel}`} key={optionLabel} label={optionLabel} name={prop('name', input)} onFocus={prop('onFocus', input)} onChange={this.handleOnChange} onBlur={this.handleOnChange} readOnly={readOnly === true} value={optionValue} /> ), values) } </Grid> { prop('touched', meta) === true && isNotEmptyOrNotNil(prop('error', meta)) && ( <ErrorMessage message={prop('error', meta)} maxWidth={116} /> ) } </Box> ) } } export default CheckboxGroup