/* eslint-disable react-hooks/exhaustive-deps */
import React, { memo, forwardRef, useImperativeHandle, useRef, useMemo } from 'react'
import { Table as AntdTable, TableProps, Empty } from 'antd'
import { run, classnames, isObject, isArray } from '@fexd/tools'
import { useMemoizedFn, useLatest } from 'ahooks'
import { useProps, createPlugin } from '../../utils'
import useQueryFieldPlugin from '../queryField'
import useModalPlugin from '../modal'
import useConfigPlugin from '../config'
import useStickyScrollBar from './useStickyScrollBar'
import useResizableColumns, { ResizableTitle } from './useResizableColumns'
import useToolbar from './useToolbar'
import usePagination from './usePagination'
import useColumns from './useColumns'
import useSelectable from './useSelectable'
import useExpandable from './useExpandable'
import useItem from './useItem'
const TdCell = memo(function TdCell(props: any) {
// https://juejin.cn/post/7063332320339099678
// onMouseEnter, onMouseLeave在数据量多的时候,会严重阻塞表格单元格渲染,严重影响性能
const { onMouseEnter, onMouseLeave, children, style, ...restProps } = props
const cell = useMemo(
() => (
{children}
|
),
[children, style],
)
return cell
})
const PluginTable = memo(
forwardRef(function PluginTable({}, ref) {
const {
pure,
rowKey,
dataSource: propDataSource,
mainStyle,
mainClassName,
loading: propLoading,
sticky,
components: propComponents,
resizableHeader,
noTableHeaderEllipsis,
__EXTRA_PROPS__,
...restProps
} = useProps()
const { size, t } = useConfigPlugin(({ size, t }) => [size, t])
const queryField = useQueryFieldPlugin(({ loading, paginationParams, selectedItems, dataSource, isSearched }) => [
loading,
paginationParams,
selectedItems,
dataSource,
isSearched,
])
const { loading: queryFieldLoading, setExtraParams, dataSource: tableDataSource } = queryField
const loading = queryFieldLoading || propLoading
const dataSource = propDataSource ?? tableDataSource
const tableWrapperDomRef = useRef(null)
const tableContentDomRef = useRef(null)
const tableToolbarDomRef = useRef(null)
const antdTableRef = useRef(null)
const { renderStation } = useModalPlugin(() => [])
const { hasToolbar, renderToolbar } = useToolbar({
ref: tableToolbarDomRef,
})
const columns = useColumns()
const expandableConfig = useExpandable()
const { rowSelection, renderBatchToolbar, handleRowSelectionByClick, toggleRowSelectionByClick } =
useSelectable(expandableConfig)
const antdTablePaginationConfig = usePagination()
const resizableColumns = useResizableColumns(columns)
useStickyScrollBar(antdTableRef, antdTablePaginationConfig)
const tableColumns = resizableHeader ? resizableColumns : columns
const tableColumnsRef = useLatest(tableColumns)
useImperativeHandle(ref, () => ({
tableWrapperDomRef,
tableToolbarDomRef,
tableContentDomRef,
antdTableRef,
tableColumnsRef,
}))
return (
{run(renderStation)}
{run(renderToolbar)}
{run(renderBatchToolbar)}
({ x: 'max-content' }), [])}
size={size as any}
onChange={useMemoizedFn(async (pagination, filters, sorters, extra) => {
switch (extra?.action) {
case 'paginate': {
// do nothing
break
}
default: {
setExtraParams({ filters, sorters })
queryField.search()
}
}
})}
{...(restProps as Omit, 'title'>)}
locale={{
emptyText: (
),
...(isObject(restProps?.locale) ? restProps?.locale : {}),
}}
onRow={useMemoizedFn((item, ...args: any[]) => {
const customerConfig = run(restProps, 'onRow', item, ...args) ?? {}
return {
...customerConfig,
className: classnames(customerConfig?.className, {
'f-pro-table-row-clickable': toggleRowSelectionByClick || expandableConfig?.expandRowByClick,
}),
onClick(...args: any[]) {
handleRowSelectionByClick(item)
run(customerConfig, 'onClick', ...args)
},
}
})}
loading={loading}
pagination={antdTablePaginationConfig}
title={undefined}
rowSelection={rowSelection}
expandable={expandableConfig}
components={useMemo(
() => ({
...(propComponents ?? {}),
header: {
...(resizableHeader ? { cell: ResizableTitle } : {}),
...(propComponents?.header ?? {}),
},
body: {
cell: TdCell,
...(propComponents?.body ?? {}),
},
}),
[propComponents, resizableHeader],
)}
className={classnames('f-pro-table-ant-table', restProps?.className, {
'f-pro-table-header-no-ellipsis': noTableHeaderEllipsis,
})}
sticky={sticky as boolean}
rowKey={rowKey}
// dataSource={dataSource}
dataSource={isArray(dataSource) ? dataSource : isObject(dataSource) ? Object.values(dataSource) : []}
columns={tableColumns}
/>
)
}),
)
export const useTablePlugin = createPlugin(() => {
const tableRef = useRef<{
tableWrapperDomRef: HTMLDivElement
tableToolbarDomRef: HTMLDivElement
tableContentDomRef: HTMLDivElement
antdTableRef: any
tableColumnsRef: any[]
}>(null)
return {
tableRef,
render: () => ,
}
}, 'table')
export default useTablePlugin
export { useItem }