/** * @file 筛选相关逻辑 */ import cns from 'classnames' import React, { useContext, useRef, useState, useEffect } from 'react' import { addListener as addResizeListener, removeListener as removeResizeListener } from 'resize-detector' import { concat } from '../utils' import { CheckboxGroup, Checkbox } from '../Checkbox' import { RadioGroup, Radio } from '../Radio' import Button from '../Button' import { PopupContainerProvider } from '../PopupContainerProvider' import Dropdown, { DropdownRef } from '../Dropdown' import { FilterIcon } from '../icons' import { DataTableColumnSelectFilterOptions, DataTableColumnMultiSelectFilterOptions, DataTableColumnSelectFilterValue } from './defs' import { dataTableCtx } from './context' import { useLangData } from '../ConfigProvider' export function Filter({ options, headCellEl }: { options: DataTableColumnSelectFilterOptions | DataTableColumnMultiSelectFilterOptions headCellEl: HTMLTableHeaderCellElement | null }) { const { baseCls } = useContext(dataTableCtx) const cls = concat(baseCls, 'head', 'filter') const activeCls = concat(cls, 'active') const containerRef = useRef(null) const [offset, setOffset] = useState([0, 0]) const dropdownRef = useRef(null) useEffect(() => { const container = containerRef.current if (container && headCellEl) { const handDomChange = () => { const offsetX = headCellEl.getBoundingClientRect().left - container.getBoundingClientRect().left const offsetY = headCellEl.getBoundingClientRect().bottom - container.getBoundingClientRect().bottom setOffset([offsetX, offsetY]) } handDomChange() // icon 本身位置也可能发生变化,比如被排序 icon 挤开 addResizeListener(container, handDomChange) addResizeListener(headCellEl, handDomChange) return () => { removeResizeListener(container, handDomChange) removeResizeListener(headCellEl, handDomChange) } } }, [headCellEl]) // TODO 确认下 Dropdown 的 popup 为什么传了新的 align.offset 属性不刷新自己的位置的问题 // 上面代码 setOffset 之后,dropdown 弹窗位置不刷新,这里强制刷新对齐下 useEffect(() => dropdownRef.current?.forcePopupAlign(), [offset]) const [overlayVisible, setOverlayVisible] = useState(false) function closeOverlay() { setOverlayVisible(false) } const overlay = ( options.type === 'select' ? : ) const isActive = overlayVisible || !isFilterValueEmpty(options.value) const className = cns(cls, isActive && activeCls) return ( // 实现 icon 高亮的时候,考虑把 th 作为 container
) } function SelectFilerOverlay({ visible, onClose, options }: { visible: boolean onClose: () => void options: DataTableColumnSelectFilterOptions }) { const { baseCls } = useContext(dataTableCtx) const langData = useLangData('dataTable') const cls = concat(baseCls, 'head', 'filter', 'select') const [innerValue, setInnerValue] = useState(options.value) function handleOk() { options.onChange(innerValue) onClose() } function handleReset() { options.onChange(null) onClose() } // 展示浮层时,同步 value 到 innerValue useEffect(() => { if (visible) { setInnerValue(options.value) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [visible]) return (
    value={innerValue} onChange={setInnerValue}> {options.optionItems.map((item, i) => { const optionCls = concat(cls, 'option') const checkedCls = innerValue === item.value && concat(optionCls, 'checked') return (
  • {item.text}
  • ) })}
) } function MultiSelectFilerOverlay({ visible, onClose, options }: { visible: boolean onClose: () => void options: DataTableColumnMultiSelectFilterOptions }) { const { baseCls } = useContext(dataTableCtx) const langData = useLangData('dataTable') const cls = concat(baseCls, 'head', 'filter', 'select') const [innerValue, setInnerValue] = useState(options.value) function handleOk() { options.onChange(innerValue) onClose() } function handleReset() { options.onChange([]) onClose() } // 展示浮层时,同步 value 到 innerValue useEffect(() => { if (visible) { setInnerValue(options.value) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [visible]) return (
    value={innerValue} onChange={setInnerValue}> {options.optionItems.map((item, i) => { const optionCls = concat(cls, 'option') const checkedCls = innerValue.includes(item.value) && concat(optionCls, 'checked') return (
  • {item.text}
  • ) })}
) } function isFilterValueEmpty(value: DataTableColumnSelectFilterValue | DataTableColumnSelectFilterValue[] | null) { if (Array.isArray(value)) { return value.length === 0 } return value == null }