diff --git a/packages/components/table-v2/src/expand-icon.tsx b/packages/components/table-v2/src/expand-icon.tsx new file mode 100644 index 0000000000..ffb929a44e --- /dev/null +++ b/packages/components/table-v2/src/expand-icon.tsx @@ -0,0 +1,36 @@ +import { defineComponent } from 'vue' +import ElIcon from '@element-plus/components/icon' +import { CaretRight } from '@element-plus/icons-vue' + +import type { TableV2RowCellRenderParam } from './table-row' + +const ExpandIcon = defineComponent( + ( + props: TableV2RowCellRenderParam['expandIconProps'] & { + expanded: boolean + expandable: boolean + } + ) => { + const { expanded, expandable, onExpand } = props + + const expandIconProps = { + onClick: expandable ? () => onExpand(!expanded) : undefined, + } as any + + const style = expanded + ? { + transform: 'rotate(90deg)', + } + : undefined + + return ( + + + + ) + } +) + +export default ExpandIcon + +export type ExpandIconInstance = InstanceType diff --git a/packages/components/table-v2/src/grid.ts b/packages/components/table-v2/src/grid.ts index af2e6330d7..1bd3eda3de 100644 --- a/packages/components/table-v2/src/grid.ts +++ b/packages/components/table-v2/src/grid.ts @@ -55,7 +55,7 @@ export const tableV2GridProps = buildProps({ /** * Event handlers */ - onRowRendered: { + onRowsRendered: { type: definePropType<(params: onRowRenderedParams) => void>(Function), }, onScroll: { diff --git a/packages/components/table-v2/src/table-grid.tsx b/packages/components/table-v2/src/table-grid.tsx index d7b9ae206a..0e529d0998 100644 --- a/packages/components/table-v2/src/table-grid.tsx +++ b/packages/components/table-v2/src/table-grid.tsx @@ -59,7 +59,7 @@ const useTableGrid = (props: TableV2GridProps) => { rowVisibleStart, rowVisibleEnd, }: GridItemRenderedEvtParams) { - props.onRowRendered?.({ + props.onRowsRendered?.({ rowCacheStart, rowCacheEnd, rowVisibleStart, diff --git a/packages/components/table-v2/src/table-v2.tsx b/packages/components/table-v2/src/table-v2.tsx index 6bdd2d9b13..132040be3d 100644 --- a/packages/components/table-v2/src/table-v2.tsx +++ b/packages/components/table-v2/src/table-v2.tsx @@ -1,7 +1,7 @@ -import { defineComponent, provide, unref } from 'vue' +import { computed, defineComponent, provide, unref } from 'vue' import { get } from 'lodash-unified' import { useNamespace } from '@element-plus/hooks' -import { isFunction } from '@element-plus/utils' +import { isFunction, isObject } from '@element-plus/utils' import { useTable } from './use-table' import { tryCall } from './utils' import { TableV2InjectionKey } from './tokens' @@ -12,7 +12,9 @@ import { tableV2Props } from './table' import Table from './table-grid' import TableRow from './table-row' import TableCell from './table-cell' +import ExpandIcon from './expand-icon' +import type { VNode } from 'vue' import type { TableGridRowSlotParams } from './table-grid' import type { TableV2RowCellRenderParam } from './table-row' @@ -24,8 +26,12 @@ const TableV2 = defineComponent({ const ns = useNamespace('table-v2') const { - columns, columnsStyles, + columnsTotalWidth, + // fixedColumnsOnLeft, + // fixedColumnOnRight, + mainColumns, + mainTableHeight, depthMap, expandedRowKeys, hasFixedColumns, @@ -33,14 +39,51 @@ const TableV2 = defineComponent({ mainTableRef, isResetting, isScrolling, + vScrollbarSize, + onScroll, onRowHovered, onRowExpanded, + onRowsRendered, } = useTable(props) + const bodyWidth = computed(() => { + const { fixed, width } = props + const ret = width - unref(vScrollbarSize) + return fixed ? Math.max(Math.round(unref(columnsTotalWidth)), ret) : ret + }) + + const headerWidth = computed( + () => unref(bodyWidth) + (props.fixed ? unref(vScrollbarSize) : 0) + ) + function renderMainTable() { + const { + cache, + data, + estimatedRowHeight, + headerHeight, + rowHeight, + width, + } = props + return ( - +
{renderTableRow}
) @@ -130,6 +173,7 @@ const TableV2 = defineComponent({ columns, column, columnIndex, + expandIconProps, isScrolling, rowData, rowIndex, @@ -141,7 +185,7 @@ const TableV2 = defineComponent({
) } - const { dataKey, dataGetter } = props + const { dataKey, dataGetter, rowKey } = props const CellComponent = slots.cell || ((props) => ) const cellData = isFunction(dataGetter) @@ -167,13 +211,22 @@ const TableV2 = defineComponent({ column.align === Alignment.RIGHT && ns.em(scope, 'align-right'), ] - // TODO: Add expand icon - // expandIconProps, - // let ExpandIcon - // if (isObject(expandIconProps)) { - // ExpandIcon =
- // } - // {ExpandIcon} + const expanded = + rowIndex >= 0 && unref(expandedRowKeys).includes(rowData[rowKey]) + + const expandable = (rowData.children?.length ?? 0) > 0 + + let Icon: VNode | undefined + + if (isObject(expandIconProps)) { + Icon = ( + + ) + } return (
{Cell} + {Icon}
) } diff --git a/packages/components/table-v2/src/table.ts b/packages/components/table-v2/src/table.ts index 68ff8c805f..bc9bff2d5b 100644 --- a/packages/components/table-v2/src/table.ts +++ b/packages/components/table-v2/src/table.ts @@ -144,7 +144,7 @@ export const tableV2Props = buildProps({ type: definePropType([String, Array, Object]), }, width: requiredNumber, - height: Number, + height: requiredNumber, maxHeight: Number, /** diff --git a/packages/components/table-v2/src/use-columns.ts b/packages/components/table-v2/src/use-columns.ts index 6745d701d4..1c3ededbff 100644 --- a/packages/components/table-v2/src/use-columns.ts +++ b/packages/components/table-v2/src/use-columns.ts @@ -106,6 +106,13 @@ function useColumns(columns: Ref, fixed: Ref) { ) }) + const columnsTotalWidth = computed(() => { + return unref(visibleColumns).reduce( + (width, column) => width + column.width, + 0 + ) + }) + watch( columns, (val) => { @@ -132,6 +139,7 @@ function useColumns(columns: Ref, fixed: Ref) { return { columns: _columns, columnsStyles, + columnsTotalWidth, fixedColumnsOnLeft, fixedColumnOnRight, hasFixedColumns, diff --git a/packages/components/table-v2/src/use-table.ts b/packages/components/table-v2/src/use-table.ts index a8d12646ce..d699ce82a0 100644 --- a/packages/components/table-v2/src/use-table.ts +++ b/packages/components/table-v2/src/use-table.ts @@ -30,8 +30,12 @@ function useTable(props: TableV2Props) { const { columns, columnsStyles, - getColumn, + columnsTotalWidth, + fixedColumnsOnLeft, + fixedColumnOnRight, hasFixedColumns, + mainColumns, + getColumn, updateColumnWidth, } = useColumns(toRef(props, 'columns'), toRef(props, 'fixed')) // state @@ -58,9 +62,9 @@ function useTable(props: TableV2Props) { const mainTableHeights = shallowRef({}) const rightTableHeights = shallowRef({}) const hScrollbarSize = shallowRef(0) - // const vScrollbarSize = shallowRef(0) + const vScrollbarSize = shallowRef(0) - const tableHeight = computed(() => { + const mainTableHeight = computed(() => { const { height = 0, maxHeight = 0, footerHeight } = props if (maxHeight > 0) { @@ -83,7 +87,7 @@ function useTable(props: TableV2Props) { }) const windowHeight = computed(() => { - return unref(tableHeight) - unref(headerHeight) - unref(fixedRowsHeight) + return unref(mainTableHeight) - unref(headerHeight) - unref(fixedRowsHeight) }) function doScroll(params: ScrollPos) { @@ -319,10 +323,18 @@ function useTable(props: TableV2Props) { isScrolling, hoveringRowKey, hasFixedColumns, + hScrollbarSize, + vScrollbarSize, // records columnsStyles, + columnsTotalWidth, expandedRowKeys, depthMap, + fixedColumnsOnLeft, + fixedColumnOnRight, + mainColumns, + // metadata + mainTableHeight, // methods scrollTo,