-
Notifications
You must be signed in to change notification settings - Fork 30
/
CheckboxGroup.js
116 lines (99 loc) · 3.34 KB
/
CheckboxGroup.js
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
import React, { createContext, useContext } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { useField, useFormikContext } from 'formik';
import Feedback from './Feedback';
import FormGroup from './FormGroup';
import Label from './Label';
export const CheckboxGroupContext = createContext();
export const useCheckboxGroup = (name) => {
const { setFieldValue } = useFormikContext();
const { name: groupName, groupOnChange, value = [], ...rest } = useContext(CheckboxGroupContext);
const toggle = () => {
const valueArray = [...value];
const indexOfVal = valueArray.indexOf(name);
if (indexOfVal === -1) {
valueArray.push(name);
} else {
valueArray.splice(indexOfVal, 1);
}
setFieldValue(groupName, valueArray);
if (groupOnChange) {
groupOnChange(valueArray);
}
};
return { toggle, value: value.indexOf(name) > -1, ...rest };
};
const CheckboxGroup = ({
name,
children,
onChange: groupOnChange,
groupClassName,
label,
labelClassName,
required,
helpId,
isHelpVideoType,
...rest
}) => {
const [field, metadata] = useField(name);
const classes = classNames(
groupClassName,
'form-control border-0 p-0 h-auto',
metadata.touched ? 'is-touched' : 'is-untouched',
metadata.touched && metadata.error && 'is-invalid'
);
let tag = 'div';
let legend = null;
if (label) {
tag = 'fieldset';
const legendId = `${name}-legend`.toLowerCase();
const srRequiredAsterisk = required ? '* ' : null;
const styles = { cursor: 'default', lineHeight: 'inherit', color: '#000' };
const labelClasses = classNames('form-inline', labelClassName, !labelClassName && 'h4 font-weight-normal');
legend = (
<>
<legend id={legendId} className="sr-only">
{srRequiredAsterisk}
{label}
</legend>
<div className={labelClasses} style={styles}>
<Label tag="div" aria-hidden helpId={helpId} required={required} isHelpVideoType={isHelpVideoType}>
{label}
</Label>
</div>
</>
);
}
return (
// eslint-disable-next-line react/jsx-no-constructed-context-values
<CheckboxGroupContext.Provider value={{ ...field, groupOnChange, metadata }}>
<FormGroup tag={tag} for={name} {...rest}>
{legend}
<div className={classes} data-testid={`check-items-${name}`}>
{children}
</div>
<Feedback name={name} />
</FormGroup>
</CheckboxGroupContext.Provider>
);
};
CheckboxGroup.propTypes = {
/** Name of the checkbox group. Should match name given in initialValues/validationSchema. */
name: PropTypes.string.isRequired,
children: PropTypes.node,
/** Class name to apply to the form control. */
groupClassName: PropTypes.string,
/** Help topic id, adds <FieldHelpIcon/> next to the label (should not be within label for accessibility). */
helpId: PropTypes.string,
/** Label for the group or checkboxes. */
label: PropTypes.node,
onChange: PropTypes.func,
/** Class name to apply to the Label. Default is Legend styling */
labelClassName: PropTypes.string,
/** Will add <RequiredAsterisk /> to label. */
required: PropTypes.bool,
/** Allows the type of `<FieldHelpIcon/>` to be changed between help-icon and video-help */
isHelpVideoType: PropTypes.bool,
};
export default CheckboxGroup;