diff --git a/packages/components/table-v2/index.ts b/packages/components/table-v2/index.ts index e69de29bb2..7221b72c78 100644 --- a/packages/components/table-v2/index.ts +++ b/packages/components/table-v2/index.ts @@ -0,0 +1 @@ +export type { Column } from './src/types' diff --git a/packages/components/table-v2/src/column.ts b/packages/components/table-v2/src/column.ts index 9df8ab4da6..a4102184e4 100644 --- a/packages/components/table-v2/src/column.ts +++ b/packages/components/table-v2/src/column.ts @@ -1,11 +1,13 @@ import { buildProps, definePropType } from '@element-plus/utils' -import type { CSSProperties, ExtractPropTypes } from 'vue' +import type { CSSProperties, Component, ExtractPropTypes } from 'vue' import type { Alignment, CellRenderer, + CellRendererParams, FixedDirection, - HeaderRenderer, + HeaderCellRenderer, + HeaderCellRendererParams, } from './types' const widthType = { @@ -44,11 +46,15 @@ export const tableV2ColumnProps = buildProps({ // getters & renderers cellRenderer: { - type: definePropType>(Function), + type: definePropType< + CellRenderer | Component> + >([Function, Object]), }, headerRenderer: { - type: definePropType>(Function), + type: definePropType< + HeaderCellRenderer | Component> + >([Function, Object]), }, } as const) diff --git a/packages/components/table-v2/src/renderers/cell.tsx b/packages/components/table-v2/src/renderers/cell.tsx index 970b49a53d..1e53a15a18 100644 --- a/packages/components/table-v2/src/renderers/cell.tsx +++ b/packages/components/table-v2/src/renderers/cell.tsx @@ -4,9 +4,10 @@ import TableCell from '../table-cell' import ExpandIcon from '../expand-icon' import { Alignment } from '../constants' import { placeholderSign } from '../private' -import { enforceUnit } from '../utils' +import { componentToSlot, enforceUnit } from '../utils' import type { FunctionalComponent, UnwrapNestedRefs, VNode } from 'vue' +import type { CellRendererParams } from '../types' import type { TableV2RowCellRenderParam } from '../table-row' import type { UseNamespaceReturn } from '@element-plus/hooks' import type { UseTableReturn } from '../use-table' @@ -51,9 +52,15 @@ const CellRenderer: FunctionalComponent = ( if (column.placeholderSign === placeholderSign) { return
} - const { dataKey, dataGetter } = column + const { cellRenderer, dataKey, dataGetter } = column + + const columnCellRenderer = componentToSlot(cellRenderer) + + const CellComponent = + columnCellRenderer || + slots.default || + ((props: CellRendererParams) => ) - const CellComponent = slots.cell || ((props) => ) const cellData = isFunction(dataGetter) ? dataGetter({ columns, column, columnIndex, rowData, rowIndex }) : get(rowData, dataKey ?? '') diff --git a/packages/components/table-v2/src/renderers/header-cell.tsx b/packages/components/table-v2/src/renderers/header-cell.tsx index e727bc4c93..4c3668f7da 100644 --- a/packages/components/table-v2/src/renderers/header-cell.tsx +++ b/packages/components/table-v2/src/renderers/header-cell.tsx @@ -3,7 +3,7 @@ import HeaderCell from '../table-header-cell' import SortIcon from '../sort-icon' import { Alignment, SortOrder, oppositeOrderMap } from '../constants' import { placeholderSign } from '../private' -import { tryCall } from '../utils' +import { componentToSlot, tryCall } from '../utils' import type { FunctionalComponent, UnwrapNestedRefs } from 'vue' import type { UseNamespaceReturn } from '@element-plus/hooks' @@ -28,7 +28,8 @@ type HeaderCellRendererProps = TableV2HeaderRowCellRendererParams & } const HeaderCellRenderer: FunctionalComponent = ( - props + props, + { slots } ) => { const { column, @@ -52,14 +53,18 @@ const HeaderCellRenderer: FunctionalComponent = ( /** * render Cell children */ - const cellRenderer = - headerCellRenderer || - ((props: TableV2HeaderCell) => ) - const Cell = cellRenderer({ + const cellProps = { ...props, class: ns.e('header-cell-text'), - }) + } + + const cellRenderer = + componentToSlot(headerCellRenderer) || + slots.default || + ((props: TableV2HeaderCell) => ) + + const Cell = cellRenderer(cellProps) /** * Render cell container and sort indicator @@ -85,7 +90,7 @@ const HeaderCellRenderer: FunctionalComponent = ( // column.key === resizingKey && ns.is('resizing'), ] - const cellProps = { + const cellWrapperProps = { ...tryCall(headerCellProps, props), onClick: column.sortable ? onColumnSorted : undefined, class: cellKls, @@ -95,7 +100,7 @@ const HeaderCellRenderer: FunctionalComponent = ( // For now we don't deliver resizable column feature since it has some UX issue. return ( -
+
{Cell} {sortable && ( diff --git a/packages/components/table-v2/src/table-v2.tsx b/packages/components/table-v2/src/table-v2.tsx index 3caec846fa..5277e13685 100644 --- a/packages/components/table-v2/src/table-v2.tsx +++ b/packages/components/table-v2/src/table-v2.tsx @@ -19,6 +19,7 @@ import type { TableV2HeaderRendererParams } from './table-header' import type { TableV2HeaderRowCellRendererParams } from './table-header-row' const COMPONENT_NAME = 'ElTableV2' + const TableV2 = defineComponent({ name: COMPONENT_NAME, props: tableV2Props, @@ -221,9 +222,14 @@ const TableV2 = defineComponent({ {{ row: slots.row, - cell: (props: TableV2RowCellRenderParam) => ( - - ), + cell: (props: TableV2RowCellRenderParam) => + slots.cell ? ( + + {slots.cell} + + ) : ( + + ), }} ), @@ -231,9 +237,14 @@ const TableV2 = defineComponent({
{{ header: slots.header, - cell: (props: TableV2HeaderRowCellRendererParams) => ( - - ), + cell: (props: TableV2HeaderRowCellRendererParams) => + slots['header-cell'] ? ( + + {slots['header-cell']} + + ) : ( + + ), }}
), diff --git a/packages/components/table-v2/src/types.ts b/packages/components/table-v2/src/types.ts index 0e79601f21..b2767d2308 100644 --- a/packages/components/table-v2/src/types.ts +++ b/packages/components/table-v2/src/types.ts @@ -18,7 +18,7 @@ export type ColumnCommonParams = { columnIndex: number } -export type HeaderRendererParams = { +export type HeaderCellRendererParams = { headerIndex: number } & ColumnCommonParams @@ -49,7 +49,9 @@ export type HeaderClassGetter = ( */ export type CellRenderer = (params: CellRendererParams) => VNode -export type HeaderCellRenderer = (params: HeaderRendererParams) => VNode +export type HeaderCellRenderer = ( + params: HeaderCellRendererParams +) => VNode export type Column = { key: KeyType @@ -61,7 +63,7 @@ export type Column = { fixed?: true | FixedDirection title?: string hidden?: boolean - headerClass: HeaderClassGetter | string + headerClass?: HeaderClassGetter | string maxWidth?: number minWidth?: number resizable?: boolean diff --git a/packages/components/table-v2/src/use-columns.ts b/packages/components/table-v2/src/use-columns.ts index 517721cd9c..033ff8af07 100644 --- a/packages/components/table-v2/src/use-columns.ts +++ b/packages/components/table-v2/src/use-columns.ts @@ -1,4 +1,4 @@ -import { computed, ref, unref, watchEffect } from 'vue' +import { computed, unref } from 'vue' import { placeholderSign } from './private' import type { CSSProperties, Ref } from 'vue' @@ -34,33 +34,9 @@ const calcColumnStyle = ( return style } -const mapColumns = (columns: AnyColumn, currentColumns: AnyColumn) => { - return columns.map((column) => { - if (!column.resizable) return column - - let { width } = column - if (column.resizable) { - const idx = columns.findIndex( - (predicated) => column.key === predicated.key - ) - if (idx >= 0 && columns[idx].width === column.width) { - width = currentColumns[idx].width - } - } - return { - ...column, - width, - } - }) -} - function useColumns(columns: Ref, fixed: Ref) { - let __columns: AnyColumn = [] - - const _columns = ref([]) - const visibleColumns = computed(() => { - return unref(_columns).filter((column) => !column.hidden) + return unref(columns).filter((column) => !column.hidden) }) const fixedColumnsOnLeft = computed(() => @@ -106,9 +82,9 @@ function useColumns(columns: Ref, fixed: Ref) { }) const columnsStyles = computed(() => { - const columns = unref(_columns) + const _columns = unref(columns) - return columns.reduce['key'], CSSProperties>>( + return _columns.reduce['key'], CSSProperties>>( (style, column) => { style[column.key] = calcColumnStyle(column, unref(fixed)) return style @@ -124,14 +100,8 @@ function useColumns(columns: Ref, fixed: Ref) { ) }) - watchEffect(() => { - const mappedColumns = mapColumns(unref(columns), __columns) - _columns.value = mappedColumns - __columns = mappedColumns - }) - const getColumn = (key: KeyType) => { - return unref(_columns).find((column) => column.key === key) + return unref(columns).find((column) => column.key === key) } const getColumnStyle = (key: KeyType) => { @@ -143,7 +113,7 @@ function useColumns(columns: Ref, fixed: Ref) { } return { - columns: _columns, + columns, columnsStyles, columnsTotalWidth, fixedColumnsOnLeft, diff --git a/packages/components/table-v2/src/utils.ts b/packages/components/table-v2/src/utils.ts index 4f223b15e1..e33324767d 100644 --- a/packages/components/table-v2/src/utils.ts +++ b/packages/components/table-v2/src/utils.ts @@ -1,6 +1,7 @@ +import { h, isVNode } from 'vue' import { addUnit, isArray, isFunction } from '@element-plus/utils' -import type { CSSProperties } from 'vue' +import type { CSSProperties, Component, Slot } from 'vue' const sumReducer = (sum: number, num: number) => sum + num @@ -23,3 +24,10 @@ export const enforceUnit = (style: CSSProperties) => { return style } + +export const componentToSlot = ( + ComponentLike: JSX.Element | ((props: T) => Component) | undefined +) => + isVNode(ComponentLike) + ? (props: T) => h(ComponentLike, props) + : (ComponentLike as Slot)