UNPKG

react-multiselect-checkboxes

Version:

Spiffy multiselect with checkboxes

115 lines (108 loc) 3.07 kB
import React from 'react'; import PropTypes from 'prop-types'; import { css } from 'emotion'; import CheckboxWithIndeterminate from './CheckboxWithIndeterminate'; function CheckboxGroup(props) { const { children, className, cx, getStyles, Heading, setValue, data, label, getValue, theme, selectProps: { getOptionValue }, } = props; const getOptionValue = props.selectProps.getOptionValue; const optionsIncludes = (v) => !!data.options.find((opt) => getOptionValue(opt) === getOptionValue(v)); const numCheckedOptions = getValue().filter((v) => optionsIncludes(v)).length; const checked = numCheckedOptions === data.options.length; const indeterminate = numCheckedOptions > 0 && !checked; const checkboxProps = { indeterminate, checked }; const selectAllOptions = () => { const newValue = [...getValue().filter((v) => !optionsIncludes(v)), ...data.options]; setValue(newValue); }; const clearOptions = () => { const newValue = getValue().filter((v) => !optionsIncludes(v)); setValue(newValue); }; return ( <div className={cx(css(getStyles('group', props)), { group: true }, className)}> <Heading checkboxProps={checkboxProps} getStyles={getStyles} cx={cx} theme={theme} onClick={() => { if (indeterminate || checked) { clearOptions(); } else { selectAllOptions(); } }} > {label} </Heading> <div>{children}</div> </div> ); } CheckboxGroup.propTypes = { children: PropTypes.node, className: PropTypes.string, cx: PropTypes.func.isRequired, getStyles: PropTypes.func.isRequired, Heading: PropTypes.func.isRequired, getValue: PropTypes.func.isRequired, setValue: PropTypes.func.isRequired, label: PropTypes.string.isRequired, data: PropTypes.shape({ options: PropTypes.arrayOf( PropTypes.shape({ label: PropTypes.node, value: PropTypes.any, }), ), }).isRequired, theme: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types }; CheckboxGroup.defaultProps = { children: null, className: undefined, }; export function CheckboxGroupHeading(props) { const { className, cx, getStyles, children, checkboxProps, ...cleanProps } = props; return ( <div className={cx( css(getStyles('groupHeading', { ...props, ...checkboxProps })), { 'group-heading': true }, className, )} {...cleanProps} > <CheckboxWithIndeterminate readOnly type="checkbox" {...checkboxProps} /> {children} </div> ); } CheckboxGroupHeading.propTypes = { children: PropTypes.node, className: PropTypes.string, cx: PropTypes.func.isRequired, getStyles: PropTypes.func.isRequired, checkboxProps: PropTypes.shape({ checked: PropTypes.bool, indeterminate: PropTypes.bool, }).isRequired, }; CheckboxGroupHeading.defaultProps = { children: null, className: undefined, }; export default CheckboxGroup;