import React, { useEffect, useState } from 'react' import styled from 'styled-components' import { BaseTable, Classes } from '../base-table' import type { TableTransform } from '../interfaces' import { internals } from '../internals' import { isLeafNode, mergeCellProps, traverseColumn } from '../utils' import { warnTransformsDeprecated } from './warnTransformsDeprecated' const AUTO_WIDTH_WRAPPER_CLS = 'auto-width-wrapper' const AUTO_WIDTH_EXPANDER_CLS = 'auto-width-expander' const AutoWidthWrapper = styled.div` height: 100%; display: inline-flex; align-items: center; white-space: nowrap; padding: 8px 12px; ` function isSameArray(arr1: number[], arr2: number[]) { return arr1.length === arr2.length && arr1.every((x, i) => x === arr2[i]) } /** 自适应列宽 * * @deprecated transform 用法已经过时,请使用 pipeline 来对表格进行拓展 * * @param tableRef BaseTable 的 ref * @param options 参数 * @param deps 重新调整列宽的依赖数组,每当依赖数组发生变化时, useAutoWidthTransform 会根据单元格内容的实际渲染宽度 设置单元格的宽度 * * options 说明: * - options.appendExpander 是否在列的末尾追加可伸缩列 * - options.expanderVisibility 设置为 `'hidden'` 可以隐藏可伸缩列 * - options.wrapperStyle 单元格中 div.auto-width-wrapper 的样式 * - options.initColumnWidth 自适应的初始列宽 * * 注意 useAutoWidthTransform 是一个 React hooks,要遵循 hooks 的用法规范 * */ export function useAutoWidthTransform( tableRef: React.MutableRefObject, options?: { wrapperStyle?: React.CSSProperties initColumnWidth?: number appendExpander?: boolean expanderVisibility?: 'visible' | 'hidden' }, deps?: any[], ): TableTransform { warnTransformsDeprecated('useAutoWidthTransform') const [widthList, setWidthList] = useState([]) useEffect(() => { const artTable = tableRef.current.getDoms().artTable const rows = Array.from(artTable.querySelectorAll(`.${Classes.tableRow}`)) if (rows.length === 0) { return } const preferredWidthList: number[] = [] for (const row of rows) { const autoWidthDivList = row.querySelectorAll(`.${AUTO_WIDTH_WRAPPER_CLS}`) autoWidthDivList.forEach((div, i) => { preferredWidthList[i] = Math.max(preferredWidthList[i] ?? 0, div.scrollWidth) }) } if (!isSameArray(preferredWidthList, widthList)) { setWidthList(preferredWidthList) } }, deps) let i = 0 const innerTransform = traverseColumn((col) => { if (!isLeafNode(col)) { return col } if (!col.features?.autoWidth) { return col } const { max = Infinity, min = -Infinity } = col.features.autoWidth const width = widthList[i++] ?? col.width ?? options?.initColumnWidth const clampedWidth = Math.max(min, Math.min(max, width)) return { ...col, width: clampedWidth, getCellProps(_, record, rowIndex) { return mergeCellProps(internals.safeGetCellProps(col, record, rowIndex), { style: { padding: 0 }, }) }, render(_, record, rowIndex) { return ( {internals.safeRender(col, record, rowIndex)} ) }, } }) return (input) => { const { columns, dataSource } = innerTransform(input) const expanderVisibility = options?.expanderVisibility ?? 'visible' return { columns: options?.appendExpander ? columns.concat([ { name: '', headerCellProps: { className: AUTO_WIDTH_EXPANDER_CLS, style: { background: expanderVisibility === 'hidden' ? 'var(--bgcolor)' : undefined, border: expanderVisibility === 'hidden' ? 'none' : undefined, }, }, getCellProps() { return { className: AUTO_WIDTH_EXPANDER_CLS, style: { visibility: expanderVisibility }, } }, }, ]) : columns, dataSource, } } }