import * as React from 'react'; import classNames from 'classnames'; import { polyfill } from 'react-lifecycles-compat'; import Checkbox, { CheckboxChangeEvent } from '../checkbox'; import Dropdown from '../dropdown'; import Menu from '../menu'; import Icon from '../icon'; import { SelectionCheckboxAllProps, SelectionCheckboxAllState, SelectionItem } from './interface'; function checkSelection({ store, getCheckboxPropsByItem, getRecordKey, data, type, byDefaultChecked, }: { store: SelectionCheckboxAllProps['store']; getCheckboxPropsByItem: SelectionCheckboxAllProps['getCheckboxPropsByItem']; getRecordKey: SelectionCheckboxAllProps['getRecordKey']; data: T[]; type: string; byDefaultChecked: boolean; }) { // type should be 'every' | 'some' if (type === 'every' || type === 'some') { return byDefaultChecked ? data[type]((item, i) => getCheckboxPropsByItem(item, i).defaultChecked) : data[type]( (item, i) => store.getState().selectedRowKeys.indexOf(getRecordKey(item, i)) >= 0, ); } return false; } function getIndeterminateState(props: SelectionCheckboxAllProps) { const { store, data } = props; if (!data.length) { return false; } const someCheckedNotByDefaultChecked = checkSelection({ ...props, data, type: 'some', byDefaultChecked: false, }) && !checkSelection({ ...props, data, type: 'every', byDefaultChecked: false, }); const someCheckedByDefaultChecked = checkSelection({ ...props, data, type: 'some', byDefaultChecked: true, }) && !checkSelection({ ...props, data, type: 'every', byDefaultChecked: true, }); if (store.getState().selectionDirty) { return someCheckedNotByDefaultChecked; } return someCheckedNotByDefaultChecked || someCheckedByDefaultChecked; } function getCheckState(props: SelectionCheckboxAllProps) { const { store, data } = props; if (!data.length) { return false; } if (store.getState().selectionDirty) { return checkSelection({ ...props, data, type: 'every', byDefaultChecked: false, }); } return ( checkSelection({ ...props, data, type: 'every', byDefaultChecked: false, }) || checkSelection({ ...props, data, type: 'every', byDefaultChecked: true, }) ); } class SelectionCheckboxAll extends React.Component< SelectionCheckboxAllProps, SelectionCheckboxAllState > { state = { checked: false, indeterminate: false, }; unsubscribe: () => void; defaultSelections: SelectionItem[]; constructor(props: SelectionCheckboxAllProps) { super(props); this.defaultSelections = props.hideDefaultSelections ? [] : [ { key: 'all', text: props.locale.selectAll, onSelect: () => {}, }, { key: 'invert', text: props.locale.selectInvert, onSelect: () => {}, }, ]; } static getDerivedStateFromProps( props: SelectionCheckboxAllProps, state: SelectionCheckboxAllState, ) { const checked = getCheckState(props); const indeterminate = getIndeterminateState(props); const newState: SelectionCheckboxAllState = {}; if (indeterminate !== state.indeterminate) { newState.indeterminate = indeterminate; } if (checked !== state.checked) { newState.checked = checked; } return newState; } componentDidMount() { this.subscribe(); } componentWillUnmount() { if (this.unsubscribe) { this.unsubscribe(); } } setCheckState(props: SelectionCheckboxAllProps) { const checked = getCheckState(props); const indeterminate = getIndeterminateState(props); this.setState(prevState => { const newState: SelectionCheckboxAllState = {}; if (indeterminate !== prevState.indeterminate) { newState.indeterminate = indeterminate; } if (checked !== prevState.checked) { newState.checked = checked; } return newState; }); } handleSelectAllChange = (e: CheckboxChangeEvent) => { const { checked } = e.target; this.props.onSelect(checked ? 'all' : 'removeAll', 0, null); }; subscribe() { const { store } = this.props; this.unsubscribe = store.subscribe(() => { this.setCheckState(this.props); }); } renderMenus(selections: SelectionItem[]) { return selections.map((selection, index) => { return (
{ this.props.onSelect(selection.key, index, selection.onSelect); }} > {selection.text}
); }); } render() { const { disabled, prefixCls, selections, getPopupContainer } = this.props; const { checked, indeterminate } = this.state; const selectionPrefixCls = `${prefixCls}-selection`; let customSelections: React.ReactNode = null; if (selections) { const newSelections = Array.isArray(selections) ? this.defaultSelections.concat(selections) : this.defaultSelections; const menu = ( {this.renderMenus(newSelections)} ); customSelections = newSelections.length > 0 ? (
) : null; } return (
{customSelections}
); } } polyfill(SelectionCheckboxAll); export default SelectionCheckboxAll;