All files / elements/forms/CheckboxField component.js

100% Statements 43/43
100% Branches 4/4
100% Functions 7/7
100% Lines 40/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218                                              9x 92x 92x 9x 92x     92x 92x               9x       9x       9x                                   9x 38x           38x 38x             9x       9x         9x           9x         9x         9x                 9x         9x 92x 92x 92x 92x 92x                           9x         9x       9x                   39x 39x                         39x 1x       1x   38x 92x 38x                             9x                           9x                
import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { flexDirection, fontWeight, space } from 'styled-system';
import {
  colorCore,
  ellipsisCore,
  fontFamilyCore,
  fontSizeCore,
  fontStyleCore,
  letterSpacingCore,
  lineHeightCore,
  scaleFont,
  spaceProps,
  textAlignCore,
  textDecorationCore,
  typography,
} from 'src/utils/styledHelpers';
import { passThrough, removeSomeProps } from 'src/utils/componentHelpers';
import { CheckboxGroup, Checkbox } from 'react-checkbox-group';
import { PlainText } from 'src/elements/forms/utils';
import { getGlobalStyles } from 'src/global-styles';
 
const { grid: { gutter } } = getGlobalStyles();
const opacity = props => `${props.disabled ? 'opacity: 0.6;' : ''}`;
const marginRight = () => `margin-right: ${scaleFont(gutter, 1)};`;
const CheckboxLabelComponent = ({ children, ...props }) => {
  const propsToTrim = [
    ...Object.keys(typography.propTypes),
  ];
  const labelProps = removeSomeProps(props, propsToTrim);
  return (
    // eslint-disable-next-line jsx-a11y/label-has-associated-control, jsx-a11y/label-has-for
    <label {...labelProps}>
      { children }
    </label>
  );
};
 
CheckboxLabelComponent.propTypes = {
  children: PropTypes.any,
};
 
CheckboxLabelComponent.defaultProps = {
  children: null,
};
 
const CheckboxLabel = styled(CheckboxLabelComponent)`
  ${colorCore}
  ${ellipsisCore}
  ${fontFamilyCore}
  ${fontSizeCore}
  ${fontWeight}
  ${letterSpacingCore}
  ${lineHeightCore}
  ${fontStyleCore}
  ${textAlignCore}
  ${textDecorationCore}
  ${marginRight}
  ${opacity}
  align-items: baseline;
  align-self: flex-start;
  cursor: pointer;
`;
 
const Wrapper = ({ children, ...props }) => {
  const propsToTrim = [
    'controlGroupProps',
    'controlLabelProps',
    'flexDirection',
    ...Object.keys(spaceProps.propTypes),
  ];
  const checkboxGroupProps = removeSomeProps(props, propsToTrim);
  return (
    <CheckboxGroup {...checkboxGroupProps}>
      { children }
    </CheckboxGroup>
  );
};
 
Wrapper.propTypes = {
  children: PropTypes.any,
};
 
Wrapper.defaultProps = {
  children: null,
};
 
 
const CheckboxGroupWrapper = styled(Wrapper)`
  display: flex;
  ${space}
  ${flexDirection}
`;
 
CheckboxGroupWrapper.propTypes = {
  ...flexDirection.propTypes,
  ...spaceProps.propTypes,
};
 
CheckboxGroupWrapper.defaultProps = {
  pb: 2,
  px: 3,
};
 
const propsToTrimLabel = [
  'controlId',
  'controlLabelProps',
  'plainText',
  'name',
  'onChange',
  'option',
];
 
const propsToTrimControl = [
  ...propsToTrimLabel,
  ...Object.keys(typography.propTypes),
];
 
const SingleCheckBox = props => {
  const { disabled, option } = props;
  const propsForCheckboxLabel = removeSomeProps(passThrough(Checkbox, props), propsToTrimLabel);
  const propsForCheckboxControl = removeSomeProps(passThrough(Checkbox, props), propsToTrimControl);
  const stylePropsForCheckBox = { cursor: 'pointer', marginRight: scaleFont(gutter, 0.5) };
  return (
    <CheckboxLabel key={`${option.label}-label`} {...propsForCheckboxLabel}>
      <Checkbox
        key={option.label}
        disabled={disabled}
        id={option.value}
        {...propsForCheckboxControl}
        style={stylePropsForCheckBox}
        value={option.value}
      />
      {option.label}
    </CheckboxLabel>
  );
};
SingleCheckBox.propTypes = {
  disabled: PropTypes.bool,
  option: PropTypes.any.isRequired,
  ...typography.propTypes,
};
SingleCheckBox.defaultProps = {
  disabled: false,
};
 
export const CheckboxFieldComponent = props => {
  const {
    controlId,
    flexDirection: direction,
    name,
    onChange,
    options,
    plainText,
    value,
    wrapperProps,
  } = props;
  const propsToTrim = [
    'controlGroupProps',
    'controlId',
    'controlLabelProps',
    'flexDirection',
    'labelText',
    'name',
    'onChange',
    'options',
    'plainText',
    'wrapperProps',
  ];
 
  if (plainText) {
    const plainTextProps = {
      value,
      ...removeSomeProps(props, propsToTrim),
    };
    return (<PlainText {...plainTextProps} />);
  }
  const checkboxProps = removeSomeProps(props, propsToTrim);
  const optionsList = options.map(option => (SingleCheckBox({ ...checkboxProps, option })));
  return (
    <CheckboxGroupWrapper
      checkboxDepth={2}
      flexDirection={direction}
      id={controlId}
      name={name}
      onChange={onChange}
      value={value}
      {...wrapperProps}
    >
      { optionsList }
    </CheckboxGroupWrapper>
  );
};
 
CheckboxFieldComponent.propTypes = {
  controlId: PropTypes.string,
  flexDirection: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.array,
  ]),
  name: PropTypes.string,
  onChange: PropTypes.func,
  options: PropTypes.any.isRequired,
  plainText: PropTypes.bool,
  value: PropTypes.any,
  ...typography.propTypes,
};
 
CheckboxFieldComponent.defaultProps = {
  controlId: '',
  flexDirection: '',
  name: '',
  onChange: null,
  plainText: false,
  value: null,
};