UNPKG

@muvehealth/fixins

Version:

Component library for Muvehealth

170 lines (159 loc) 4.41 kB
// @flow import React, { PureComponent } from 'react' import path from 'ramda/src/path' import prop from 'ramda/src/prop' import styled from 'react-emotion' import withProps from 'recompose/withProps' import { fontSize, space, minWidth, themeGet } from 'styled-system' import Box from '../Box' import ErrorMessage from '../ErrorMessage' import { DataCheckmark } from '../Icons' import { isNotEmptyOrNotNil, shouldForwardProp } from '../../utils' import { type InputType, type MetaType } from '../../types' type Props = { 'data-id'?: string, defaultChecked?: boolean, id?: string, input?: InputType, label: string, meta?: MetaType, readOnly?: boolean, } const propOrInputProp = (property, props) => { const mainProp = prop(property, props) const inputProp = path(['input', property], props) return mainProp != null ? mainProp : inputProp } class Checkbox extends PureComponent<Props & InputType> { static defaultProps = { 'data-id': undefined, defaultChecked: null, id: undefined, input: undefined, meta: undefined, readOnly: false, } render() { const { defaultChecked, id, input, label, meta, name, onChange, onFocus, onBlur, readOnly, value, ...styles } = this.props // Account for Checkbox from CheckboxGroup or individual Checkbox const inputId = id != null ? id : `${prop('name', input)}-${label}` const inputDefaultChecked = defaultChecked != null ? defaultChecked : prop('value', input) return ( <Box> <Input // eslint-disable-next-line react/destructuring-assignment data-id={this.props['data-id']} defaultChecked={inputDefaultChecked} id={inputId} readOnly={readOnly} type="checkbox" name={propOrInputProp('name', this.props)} value={propOrInputProp('value', this.props)} onChange={propOrInputProp('onChange', this.props)} onFocus={propOrInputProp('onFocus', this.props)} onBlur={propOrInputProp('onBlur', this.props)} /> <Label htmlFor={inputId} // $FlowFixMe: Dont want to limit styled-system props {...styles} > {label} </Label> { prop('touched', meta) === true && isNotEmptyOrNotNil(prop('error', meta)) && ( <ErrorMessage message={prop('error', meta)} maxWidth={116} /> ) } </Box> ) } } export const Label = withProps({ fontSize: 2, })(styled('label', { shouldForwardProp })( { alignItems: 'center', cursor: 'pointer', display: 'flex', position: 'relative', '@media not print': { '::before': { content: '""', display: 'inline-block', verticalAlign: 'middle', minHeight: 32, minWidth: 32, marginRight: 16, }, '::after': { backgroundColor: 'transparent', backgroundPosition: 'center', backgroundRepeat: 'no-repeat', content: '""', height: 32, left: 0, position: 'absolute', transformOrigin: 'center', transform: 'scale(0)', transition: 'transform 0.2s', top: 'calc(50% - 16px)', width: 32, zIndex: 2, }, '[readonly] + &': { cursor: 'not-allowed', pointerEvents: 'none', }, 'fieldset[disabled] &': { cursor: 'default', }, }, '@media print': { marginRight: 16, }, }, fontSize, minWidth, space, props => ({ color: themeGet('colors.darkGray', '#4A4A4A')(props), '::before': { backgroundColor: themeGet('colors.inputGray', '#F0F0F0')(props), }, '::after': { backgroundImage: `url("data:image/svg+xml;charset=utf8,${DataCheckmark('%2313535F')}")`, }, }), )) export const Input = styled('input')({ '@media not print': { border: 0, clip: 'rect(0 0 0 0)', clipPath: 'inset(50%)', height: 1, margin: -1, overflow: 'hidden', padding: 0, position: 'absolute', width: 1, whiteSpace: 'nowrap', }, }, props => ({ ':checked + label': { '::before': { backgroundColor: themeGet('colors.superLightBlue', '#D2FEFF')(props), }, '::after': { color: themeGet('colors.textBlue', '#13535F')(props), transform: 'none', }, }, })) export default Checkbox