/**
* @file 单元格
*/
import cns from 'classnames'
import React, { useContext, useState, CSSProperties } from 'react'
import { concat } from '../utils'
import { InternalColumnOptions, InternalRecord } from './defs'
import { dataTableCtx } from './context'
import { Sorter } from './sort'
import { Filter } from './filter'
import { useColumnWidth, useColumnWidthReporter } from './column-width'
import { useHorizontalScroll } from './horizontal-scroll'
export function BodyCell({ column, record, recordIdx }: {
column: InternalColumnOptions
record: InternalRecord
recordIdx: number
}) {
const { baseCls } = useContext(dataTableCtx)
const { style, className } = useCellFixColumn(column, concat(baseCls, 'body', 'td'))
const value = column.accessor != null ? (record.data as any)[column.accessor] : undefined
return (
{column.render(value, record.data, recordIdx)}
|
)
}
export function MeasureCell({ column }: {
column: InternalColumnOptions
}) {
const { baseCls } = useContext(dataTableCtx)
const className = cns(
concat(baseCls, 'body', 'td'),
concat(baseCls, 'measure-cell')
)
const [wrapper, setWrapper] = useState(null)
useColumnWidthReporter(column.internalId, wrapper)
return |
}
export function HeadCell({ column }: {
column: InternalColumnOptions
}) {
const { baseCls } = useContext(dataTableCtx)
const thCls = concat(baseCls, 'head', 'th')
const [wrapper, setWrapper] = useState(null)
const { style, className } = useCellFixColumn(column, thCls)
return (
{column.title}
{column.sort && }
{column.filter && }
|
)
}
function useCellFixColumn(column: InternalColumnOptions, className: string) {
const { columns } = useContext(dataTableCtx)
const { widths } = useColumnWidth()
const { scrollLeft, scrollRight } = useHorizontalScroll()
let style: CSSProperties | undefined
let hasRightShadow = false
let hasLeftShadow = false
if (column.fixed != null) {
style = {
background: 'inherit',
zIndex: 1,
position: 'sticky'
}
let columnIdx = -1
let lastFixLeftIdx = -1
let firstFixRightIdx = -1
for (let i = 0; i < columns.length; i++) {
const c = columns[i]
if (c.fixed === 'left') lastFixLeftIdx = i
if (c === column) columnIdx = i
if (firstFixRightIdx === -1 && c.fixed === 'right') firstFixRightIdx = i
}
if (column.fixed === 'left') {
const prevColumns = columns.slice(0, columnIdx)
const prevColumnsWidth = sum(prevColumns.map(c => widths[c.internalId]))
style.left = prevColumnsWidth + 'px'
hasRightShadow = columnIdx === lastFixLeftIdx && scrollLeft > 0
}
if (column.fixed === 'right') {
const nextColumns = columns.slice(columnIdx + 1)
const nextColumnsWidth = sum(nextColumns.map(c => widths[c.internalId]))
style.right = nextColumnsWidth + 'px'
hasLeftShadow = columnIdx === firstFixRightIdx && scrollRight > 0
}
}
const { baseCls } = useContext(dataTableCtx)
className = cns(
className,
hasRightShadow && concat(baseCls, 'cell-right-shadow'),
hasLeftShadow && concat(baseCls, 'cell-left-shadow')
)
return { style, className }
}
function sum(nums: Array) {
return nums.reduce((s, n) => s + (n ?? 0), 0)
}