mirror of
https://github.com/element-plus/element-plus.git
synced 2024-11-27 02:01:15 +08:00
feat(components): [virtual-table] Table (#7083)
* feat(components): [virtual-table] Table - Add composable for column management. * Update table props
This commit is contained in:
parent
5849909577
commit
9a05d5cdc2
@ -1,4 +1,4 @@
|
|||||||
import { definePropType } from '@element-plus/utils'
|
import { definePropType, mutable } from '@element-plus/utils'
|
||||||
|
|
||||||
import type { CSSProperties } from 'vue'
|
import type { CSSProperties } from 'vue'
|
||||||
import type { Column, KeyType } from './types'
|
import type { Column, KeyType } from './types'
|
||||||
@ -31,6 +31,11 @@ export const dataType = {
|
|||||||
|
|
||||||
export const expandColumnKey = String
|
export const expandColumnKey = String
|
||||||
|
|
||||||
|
export const expandKeys = {
|
||||||
|
type: definePropType<KeyType[]>(Array),
|
||||||
|
default: () => mutable([]),
|
||||||
|
} as const
|
||||||
|
|
||||||
export const requiredNumber = {
|
export const requiredNumber = {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
@ -38,7 +43,7 @@ export const requiredNumber = {
|
|||||||
|
|
||||||
export const rowKey = {
|
export const rowKey = {
|
||||||
type: definePropType<KeyType>([String, Number, Symbol]),
|
type: definePropType<KeyType>([String, Number, Symbol]),
|
||||||
required: true,
|
default: 'id',
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,11 +20,13 @@ export const tableV2HeaderProps = buildProps({
|
|||||||
},
|
},
|
||||||
headerHeight: {
|
headerHeight: {
|
||||||
type: definePropType<number | number[]>([Number, Array]),
|
type: definePropType<number | number[]>([Number, Array]),
|
||||||
required: true,
|
default: 50,
|
||||||
},
|
},
|
||||||
rowWidth: requiredNumberType,
|
rowWidth: requiredNumberType,
|
||||||
rowHeight: requiredNumberType,
|
rowHeight: {
|
||||||
|
type: Number,
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
height: requiredNumberType,
|
height: requiredNumberType,
|
||||||
width: requiredNumberType,
|
width: requiredNumberType,
|
||||||
} as const)
|
} as const)
|
||||||
|
@ -1,4 +1,16 @@
|
|||||||
import { buildProps, definePropType } from '@element-plus/utils'
|
import { buildProps, definePropType } from '@element-plus/utils'
|
||||||
|
import {
|
||||||
|
classType,
|
||||||
|
columns,
|
||||||
|
dataType,
|
||||||
|
expandKeys,
|
||||||
|
fixedDataType,
|
||||||
|
requiredNumber,
|
||||||
|
rowKey,
|
||||||
|
} from './common'
|
||||||
|
import { tableV2RowProps } from './row'
|
||||||
|
import { tableV2HeaderProps } from './header'
|
||||||
|
import { tableV2GridProps } from './grid'
|
||||||
|
|
||||||
import type { ExtractPropTypes, StyleValue } from 'vue'
|
import type { ExtractPropTypes, StyleValue } from 'vue'
|
||||||
import type {
|
import type {
|
||||||
@ -53,13 +65,17 @@ export type RowClassNameGetter<T> = (
|
|||||||
export type ColumnSortHandler<T> = (params: ColumnSortParams<T>) => void
|
export type ColumnSortHandler<T> = (params: ColumnSortParams<T>) => void
|
||||||
|
|
||||||
export const tableV2Props = buildProps({
|
export const tableV2Props = buildProps({
|
||||||
|
cache: tableV2GridProps.cache,
|
||||||
|
estimatedRowHeight: tableV2RowProps.estimatedRowHeight,
|
||||||
|
rowKey,
|
||||||
/**
|
/**
|
||||||
* extra props deriver
|
* extra props deriver
|
||||||
*/
|
*/
|
||||||
cellProps: {
|
cellProps: {
|
||||||
type: definePropType<any | ExtraCellPropGetter<any>>([Object, Function]),
|
type: definePropType<any | ExtraCellPropGetter<any>>([Object, Function]),
|
||||||
},
|
},
|
||||||
headerClassName: {
|
// Header attributes
|
||||||
|
headerClass: {
|
||||||
type: definePropType<string | HeaderClassNameGetter<any>>([
|
type: definePropType<string | HeaderClassNameGetter<any>>([
|
||||||
String,
|
String,
|
||||||
Function,
|
Function,
|
||||||
@ -77,55 +93,54 @@ export const tableV2Props = buildProps({
|
|||||||
Function,
|
Function,
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
rowClassName: {
|
headerHeight: tableV2HeaderProps.headerHeight,
|
||||||
|
/**
|
||||||
|
* Footer attributes
|
||||||
|
*/
|
||||||
|
footerHeight: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Row attributes
|
||||||
|
*/
|
||||||
|
rowClass: {
|
||||||
type: definePropType<string | RowClassNameGetter<any>>([String, Function]),
|
type: definePropType<string | RowClassNameGetter<any>>([String, Function]),
|
||||||
},
|
},
|
||||||
rowProps: {
|
rowProps: {
|
||||||
type: definePropType<any | ExtractRowPropGetter<any>>([Object, Function]),
|
type: definePropType<any | ExtractRowPropGetter<any>>([Object, Function]),
|
||||||
},
|
},
|
||||||
|
rowHeight: Number,
|
||||||
/**
|
/**
|
||||||
* Data models
|
* Data models
|
||||||
*/
|
*/
|
||||||
columns: {
|
columns,
|
||||||
type: definePropType<Column<any>[]>(Array),
|
data: dataType,
|
||||||
required: true,
|
fixedData: fixedDataType,
|
||||||
},
|
|
||||||
fixedData: {
|
|
||||||
type: definePropType<any[]>(Array),
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
type: definePropType<any[]>(Array),
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expanded keys
|
* Expanded keys
|
||||||
*/
|
*/
|
||||||
expandedRowKeys: {
|
expandColumnKey: tableV2RowProps.expandColumnKey,
|
||||||
type: definePropType<KeyType[]>(Array),
|
expandedRowKeys: expandKeys,
|
||||||
},
|
defaultExpandedRowKeys: expandKeys,
|
||||||
defaultExpandedRowKeys: {
|
|
||||||
type: definePropType<KeyType[]>(Array),
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attributes
|
* Attributes
|
||||||
*/
|
*/
|
||||||
classNames: {
|
class: classType,
|
||||||
type: definePropType<string | string[]>([String, Array]),
|
|
||||||
},
|
|
||||||
disabled: Boolean,
|
disabled: Boolean,
|
||||||
footerHeight: {
|
fixed: Boolean,
|
||||||
type: definePropType<number | number[]>([Number, Array]),
|
|
||||||
},
|
|
||||||
headerHeight: {
|
|
||||||
type: definePropType<number | number[]>([Number, Array]),
|
|
||||||
},
|
|
||||||
style: {
|
style: {
|
||||||
type: definePropType<StyleValue>([String, Array, Object]),
|
type: definePropType<StyleValue>([String, Array, Object]),
|
||||||
},
|
},
|
||||||
|
width: requiredNumber,
|
||||||
|
height: Number,
|
||||||
|
maxHeight: Number,
|
||||||
|
|
||||||
sortBy: {
|
sortBy: {
|
||||||
type: definePropType<{ key: KeyType; order: SortOrder }>(Object),
|
type: definePropType<{ key: KeyType; order: SortOrder }>(Object),
|
||||||
|
default: () => ({} as { key: KeyType; order: SortOrder }),
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,6 +149,10 @@ export const tableV2Props = buildProps({
|
|||||||
onColumnSort: {
|
onColumnSort: {
|
||||||
type: definePropType<ColumnSortParams<any>>(Function),
|
type: definePropType<ColumnSortParams<any>>(Function),
|
||||||
},
|
},
|
||||||
|
onExpandedRowsChange: Function,
|
||||||
|
onRowExpand: Function,
|
||||||
|
onScroll: tableV2GridProps.onScroll,
|
||||||
|
rowEventHandlers: tableV2RowProps.rowEventHandlers,
|
||||||
} as const)
|
} as const)
|
||||||
|
|
||||||
export type TableV2Props = ExtractPropTypes<typeof tableV2Props>
|
export type TableV2Props = ExtractPropTypes<typeof tableV2Props>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { RendererElement, RendererNode, StyleValue, VNode } from 'vue'
|
import type { CSSProperties, RendererElement, RendererNode, VNode } from 'vue'
|
||||||
|
|
||||||
import type { sortOrders } from './constants'
|
import type { sortOrders } from './constants'
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ export type Column<T = any> = {
|
|||||||
maxWidth?: number
|
maxWidth?: number
|
||||||
minWidth?: number
|
minWidth?: number
|
||||||
resizable?: boolean
|
resizable?: boolean
|
||||||
style?: StyleValue
|
style?: CSSProperties
|
||||||
sortable?: boolean
|
sortable?: boolean
|
||||||
width: number
|
width: number
|
||||||
/**
|
/**
|
||||||
@ -83,6 +83,8 @@ export type Column<T = any> = {
|
|||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Columns<T> = Column<T>[]
|
||||||
|
|
||||||
export type CustomizedCellsType = VNode<
|
export type CustomizedCellsType = VNode<
|
||||||
RendererNode,
|
RendererNode,
|
||||||
RendererElement,
|
RendererElement,
|
||||||
|
119
packages/components/table-v2/src/useTable.ts
Normal file
119
packages/components/table-v2/src/useTable.ts
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import { computed, unref } from 'vue'
|
||||||
|
|
||||||
|
import type { CSSProperties, Ref } from 'vue'
|
||||||
|
import type { Column, Columns } from './types'
|
||||||
|
|
||||||
|
const getColumnStyle = (
|
||||||
|
column: Column<any>,
|
||||||
|
fixedColumn: boolean
|
||||||
|
): CSSProperties => {
|
||||||
|
const style = {
|
||||||
|
...(column.style ?? {}),
|
||||||
|
width: column.width,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fixedColumn) {
|
||||||
|
if (column.maxWidth) style.maxWidth = column.maxWidth
|
||||||
|
if (column.minWidth) style.maxWidth = column.minWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
|
||||||
|
function useColumns(columns: Ref<Columns<any>>, fixed: Ref<boolean>) {
|
||||||
|
let mappedColumnsCopy: Columns<any> = []
|
||||||
|
|
||||||
|
const mappedColumns = computed(() => {
|
||||||
|
const _columns = unref(columns)
|
||||||
|
const ret = _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 = mappedColumnsCopy[idx].width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...column,
|
||||||
|
width,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mappedColumnsCopy = ret
|
||||||
|
return ret
|
||||||
|
})
|
||||||
|
|
||||||
|
const visibleColumns = computed(() => {
|
||||||
|
return unref(mappedColumns).filter((column) => !column.hidden)
|
||||||
|
})
|
||||||
|
|
||||||
|
const fixedColumnsOnLeft = computed(() =>
|
||||||
|
unref(visibleColumns).filter(
|
||||||
|
(column) => column.fixed === 'left' || column.fixed === true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const fixedColumnOnRight = computed(() =>
|
||||||
|
unref(visibleColumns).filter((column) => column.fixed === 'right')
|
||||||
|
)
|
||||||
|
|
||||||
|
const normalColumns = computed(() =>
|
||||||
|
unref(visibleColumns).filter((column) => !column.fixed)
|
||||||
|
)
|
||||||
|
|
||||||
|
const mainColumns = computed(() => {
|
||||||
|
const ret: Columns<any> = []
|
||||||
|
|
||||||
|
unref(fixedColumnsOnLeft).forEach((column) => {
|
||||||
|
ret.push({
|
||||||
|
...column,
|
||||||
|
isPlaceholder: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
unref(normalColumns).forEach((column) => {
|
||||||
|
ret.push(column)
|
||||||
|
})
|
||||||
|
|
||||||
|
unref(fixedColumnOnRight).forEach((column) => {
|
||||||
|
ret.push({
|
||||||
|
...column,
|
||||||
|
isPlaceholder: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return ret
|
||||||
|
})
|
||||||
|
|
||||||
|
const columnsStyle = computed(() => {
|
||||||
|
const columns = unref(mappedColumns)
|
||||||
|
|
||||||
|
return columns.reduce<Record<Column<any>['key'], CSSProperties>>(
|
||||||
|
(style, column) => {
|
||||||
|
style[column.key] = getColumnStyle(column, unref(fixed))
|
||||||
|
return style
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
columns: mappedColumns,
|
||||||
|
columnsStyle,
|
||||||
|
fixedColumnsOnLeft,
|
||||||
|
fixedColumnOnRight,
|
||||||
|
mainColumns,
|
||||||
|
normalColumns,
|
||||||
|
visibleColumns,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function useTable() {
|
||||||
|
// to be filled
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useColumns, useTable }
|
Loading…
Reference in New Issue
Block a user