/** * 此插件用于开启行选择 */ import React, { useCallback, useMemo, useRef } from 'react' import { ColumnInstance, Hooks, TableToggleAllRowsSelectedProps } from 'react-table' import cns from 'classnames' import { InternalCheckbox as Checkbox } from '../../Checkbox/InternalCheckbox' import { Radio } from '../../Radio' import { concat } from '../../utils' import { useReportWidth } from '../hooks' import { useColumnWidths } from '../providers/ColumnWidthsProvider' import { useHorizontalScroll } from '../providers/HorizontalScrollProvider' import { useTable } from '../providers/TableProvider' import { TableProps } from '../types' import { getFixedStyle } from '../utils' type Props = TableToggleAllRowsSelectedProps & { position: 'header' | 'cell' } // 这里只作为事件的触发器,不负责状态的加工处理 function SelectBox(props: Props) { const { indeterminate, onChange, position, ...rest } = props const { selectionType } = useTable() function handleChange(value: boolean) { onChange?.({ target: { checked: value } } as any) } if (selectionType === 'single') { if (position === 'header') { return null } return } return ( ) } export default function withSelectionColumn(tableProps: TableProps) { return function _withSelectionColumn(hooks: Hooks) { hooks.columns.push(columns => [ { id: 'selection', // ColumnWidthsProvider 需要根据实际宽度生成 col,也就是被 react-table 修改过后的 columns // 而不是用户最开始传入的 columns,所以这里需要给一个宽度让 table 知道行选择列也是有宽度的 // 54: 14 宽度 + 20 左右 padding width: '54px', // eslint-disable-next-line react/display-name, @typescript-eslint/naming-convention Header: ({ column, getToggleAllRowsSelectedProps, columns: _columns, index: columnIndex }) => { const { prefix: tablePrefix } = useTable() const bodyPrefix = concat(tablePrefix, 'body') const tdPrefix = concat(bodyPrefix, 'td') const { reportHeadCellWidth } = useColumnWidths() const ref = useRef(null) const { colWidths } = useColumnWidths() const { pinnedLeft } = useHorizontalScroll() const fixed = tableProps.selection?.fixed const fixedStyle = useMemo( () => getFixedStyle(colWidths, columnIndex, _columns, fixed), [colWidths, columnIndex, _columns, fixed] ) const isLeftLast = fixed === 'left' && pinnedLeft === columnIndex useReportWidth(ref, useCallback(nextWidth => { reportHeadCellWidth(column.id, nextWidth) }, [column.id, reportHeadCellWidth])) return ( ) }, // eslint-disable-next-line react/display-name, @typescript-eslint/naming-convention Cell: ({ column, columns: _columns, row, index: columnIndex }) => { const { prefix: tablePrefix } = useTable() const bodyPrefix = concat(tablePrefix, 'body') const tdPrefix = concat(bodyPrefix, 'td') const { reportBodyCellWidth } = useColumnWidths() const ref = useRef(null) const { colWidths } = useColumnWidths() const { pinnedLeft } = useHorizontalScroll() const fixed = tableProps.selection?.fixed const fixedStyle = useMemo( () => getFixedStyle(colWidths, columnIndex, _columns, fixed), [colWidths, columnIndex, _columns, fixed] ) const isLeftLast = fixed === 'left' && pinnedLeft === columnIndex useReportWidth(ref, useCallback(nextWidth => { reportBodyCellWidth(column.id, nextWidth) }, [column.id, reportBodyCellWidth])) return ( ) }, meta: tableProps.selection?.fixed ? { fixed: tableProps.selection?.fixed } : {} } as ColumnInstance, ...columns ]) } }