import autobind from 'autobind-decorator'; import _ from 'lodash'; import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { CheckBoxType, getOptionLabel, getSelectedValuesMap, Option, } from './CheckedSelectUtils'; type ChecklistProps = { onChange: (values: { value: string }[]) => void; value: { value: string }[]; options: Option[]; getOptionLabel?: ( option: Option, selectedValues: { [optionValue: string]: any }, checkBoxType?: CheckBoxType ) => JSX.Element; checkBoxType?: CheckBoxType; isDisabled?: boolean; unselectOthersWhenAllSelected?: boolean; numberOfColumnsPerRow?: number; }; function generateTableRows( selectComponents: JSX.Element[], numberOfColumnsPerRow: number = 1 ) { return _.chunk(selectComponents, numberOfColumnsPerRow).map(components => ( {components} )); } @observer export default class Checklist extends React.Component { constructor(props: any) { super(props); makeObservable(this); } public static defaultProps: Partial = { isDisabled: false, numberOfColumnsPerRow: 1, checkBoxType: CheckBoxType.HTML, }; @computed get selectedValues() { return getSelectedValuesMap(this.props.value); } public render() { return ( {generateTableRows( this.props.options.map(this.optionSelectComponent), this.props.numberOfColumnsPerRow )}
); } @autobind private getOptionLabel(option: Option): JSX.Element { return this.props.getOptionLabel ? this.props.getOptionLabel( option, this.selectedValues, this.props.checkBoxType ) : getOptionLabel( option, this.selectedValues, this.props.checkBoxType ); } @autobind protected optionSelectComponent(option: Option) { const onClick = () => this.handleSelect(option.value); return ( {this.getOptionLabel(option)} ); } @action.bound protected handleSelect(value: string) { // do nothing if disabled if (this.props.isDisabled) { return; } // only select current value if all selected already if ( this.props.unselectOthersWhenAllSelected && this.props.value.length === this.props.options.length ) { this.props.onChange([{ value }]); } // unselect if selected else if (this.selectedValues[value]) { this.props.onChange( this.props.value.filter(v => v.value !== value) ); } // select if not selected else { this.props.onChange([{ value }].concat(this.props.value)); } } }