import cx from 'classnames'
import React, { useState } from 'react'
import { ExpansionCell, icons, InlineFlexCell } from '../common-views'
import type { ArtColumn, TableTransform } from '../interfaces'
import { internals } from '../internals'
import { treeMetaSymbol } from '../pipeline/features'
import { isLeafNode as standardIsLeafNode, mergeCellProps } from '../utils'
import { warnTransformsDeprecated } from './warnTransformsDeprecated'
const ICON_WIDTH = 16
/** @deprecated transform 用法已经过时,请使用 pipeline 来对表格进行拓展 */
export interface TreeModeOptions {
primaryKey: string
openKeys: string[]
onChangeOpenKeys(nextKeys: string[], key: string, action: 'expand' | 'collapse'): void
isLeafNode?(node: any, nodeMeta: { depth: number; expanded: boolean; rowKey: string }): boolean
/** icon 的缩进值,一般为负数,此时 icon 将向左偏移. 默认为 -6 */
iconIndent?: number
/** icon 与右侧文本的距离,默认为 0 */
iconGap?: number
/** 每一级缩进产生的距离,默认为 16 */
indentSize?: number
clickArea?: 'cell' | 'content' | 'icon'
treeMetaKey?: string | symbol
stopClickEventPropagation?: boolean
}
/** @deprecated transform 用法已经过时,请使用 pipeline 来对表格进行拓展 */
export function makeTreeModeTransform({
onChangeOpenKeys,
openKeys,
primaryKey,
iconIndent = -6,
iconGap = 0,
indentSize = 16,
isLeafNode = standardIsLeafNode,
clickArea = 'cell',
treeMetaKey = treeMetaSymbol,
stopClickEventPropagation,
}: TreeModeOptions): TableTransform {
warnTransformsDeprecated('makeTreeModeTransform')
const openKeySet = new Set(openKeys)
const toggle = (rowKey: string) => {
const expanded = openKeySet.has(rowKey)
if (expanded) {
onChangeOpenKeys(
openKeys.filter((key) => key !== rowKey),
rowKey,
'collapse',
)
} else {
onChangeOpenKeys([...openKeys, rowKey], rowKey, 'expand')
}
}
return ({ columns, dataSource }) => {
return {
columns: processColumns(columns),
dataSource: processDataSource(dataSource),
}
function processDataSource(input: any[]) {
const result: any[] = []
dfs(input, 0)
function dfs(nodes: any[], depth: number) {
if (nodes == null) {
return
}
for (const node of nodes) {
const rowKey = node[primaryKey]
const expanded = openKeySet.has(rowKey)
const isLeaf = isLeafNode(node, { depth, expanded, rowKey })
const treeMeta = { depth, isLeaf, expanded, rowKey }
result.push({ [treeMetaKey]: treeMeta, ...node })
if (!isLeaf && expanded) {
dfs(node.children, depth + 1)
}
}
}
return result
}
function processColumns(columns: ArtColumn[]) {
if (columns.length === 0) {
return columns
}
const [firstCol, ...others] = columns
const render = (value: any, record: any, recordIndex: number) => {
const content = internals.safeRender(firstCol, record, recordIndex)
if (record[treeMetaKey] == null) {
// 没有 treeMeta 信息的话,就返回原先的渲染结果
return content
}
const { rowKey, depth, isLeaf, expanded } = record[treeMetaKey]
const indent = iconIndent + depth * indentSize
if (isLeaf) {
return (
{content}
)
}
const onClick = (e: React.MouseEvent) => {
if (stopClickEventPropagation) {
e.stopPropagation()
}
toggle(rowKey)
}
const expandCls = expanded ? 'expanded' : 'collapsed'
return (
{content}
)
}
const getCellProps = (value: any, record: any, rowIndex: number) => {
const prevProps = internals.safeGetCellProps(firstCol, record, rowIndex)
if (record[treeMetaKey] == null) {
// 没有 treeMeta 信息的话,就返回原先的 cellProps
return prevProps
}
const { isLeaf, rowKey } = record[treeMetaKey]
if (isLeaf) {
return prevProps
}
return mergeCellProps(prevProps, {
onClick(e) {
if (stopClickEventPropagation) {
e.stopPropagation()
}
toggle(rowKey)
},
style: { cursor: 'pointer' },
})
}
return [
{
...firstCol,
title: (
{internals.safeRenderHeader(firstCol)}
),
render,
getCellProps: clickArea === 'cell' ? getCellProps : firstCol.getCellProps,
},
...others,
]
}
}
}
/** @deprecated transform 用法已经过时,请使用 pipeline 来对表格进行拓展 */
export function useTreeModeTransform({
defaultOpenKeys = [],
...others
}: Omit & { defaultOpenKeys?: string[] }) {
const [openKeys, onChangeOpenKeys] = useState(defaultOpenKeys)
return makeTreeModeTransform({
openKeys,
onChangeOpenKeys,
...others,
})
}