refactor: table
parent
60ea53ce91
commit
a948e663a9
|
@ -142,26 +142,6 @@ export default defineComponent<BodyRowProps<unknown>>({
|
|||
const key = columnsKey[colIndex];
|
||||
const fixedInfo = fixedInfoList[colIndex];
|
||||
|
||||
// ============= Used for nest expandable =============
|
||||
let appendCellNode;
|
||||
if (colIndex === (expandIconColumnIndex || 0) && nestExpandable.value) {
|
||||
appendCellNode = (
|
||||
<>
|
||||
<span
|
||||
style={{ paddingLeft: `${indentSize * indent}px` }}
|
||||
class={`${prefixCls}-row-indent indent-level-${indent}`}
|
||||
/>
|
||||
{expandIcon({
|
||||
prefixCls,
|
||||
expanded: expanded.value,
|
||||
expandable: hasNestChildren.value,
|
||||
record,
|
||||
onExpand: onInternalTriggerExpand,
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
let additionalCellProps;
|
||||
if (column.customCell) {
|
||||
additionalCellProps = column.customCell(record, index);
|
||||
|
@ -180,8 +160,30 @@ export default defineComponent<BodyRowProps<unknown>>({
|
|||
dataIndex={dataIndex}
|
||||
customRender={customRender}
|
||||
{...fixedInfo}
|
||||
appendNode={appendCellNode}
|
||||
additionalProps={additionalCellProps}
|
||||
v-slots={{
|
||||
// ============= Used for nest expandable =============
|
||||
appendNode: () => {
|
||||
if (colIndex === (expandIconColumnIndex || 0) && nestExpandable.value) {
|
||||
return (
|
||||
<>
|
||||
<span
|
||||
style={{ paddingLeft: `${indentSize * indent}px` }}
|
||||
class={`${prefixCls}-row-indent indent-level-${indent}`}
|
||||
/>
|
||||
{expandIcon({
|
||||
prefixCls,
|
||||
expanded: expanded.value,
|
||||
expandable: hasNestChildren.value,
|
||||
record,
|
||||
onExpand: onInternalTriggerExpand,
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
|
|
@ -43,24 +43,6 @@ export default defineComponent<ExpandedRowProps>({
|
|||
colSpan,
|
||||
} = props;
|
||||
|
||||
let contentNode: any = slots.default?.();
|
||||
|
||||
if (fixColumn) {
|
||||
contentNode = (
|
||||
<div
|
||||
style={{
|
||||
width: componentWidth - (fixHeader ? tableContext.scrollbarSize : 0),
|
||||
position: 'sticky',
|
||||
left: 0,
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
class={`${prefixCls}-expanded-row-fixed`}
|
||||
>
|
||||
{contentNode}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Component
|
||||
class={attrs.class}
|
||||
|
@ -68,9 +50,33 @@ export default defineComponent<ExpandedRowProps>({
|
|||
display: expanded ? null : 'none',
|
||||
}}
|
||||
>
|
||||
<Cell component={cellComponent} prefixCls={prefixCls} colSpan={colSpan}>
|
||||
{contentNode}
|
||||
</Cell>
|
||||
<Cell
|
||||
component={cellComponent}
|
||||
prefixCls={prefixCls}
|
||||
colSpan={colSpan}
|
||||
v-slots={{
|
||||
default: () => {
|
||||
let contentNode: any = slots.default?.();
|
||||
|
||||
if (fixColumn) {
|
||||
contentNode = (
|
||||
<div
|
||||
style={{
|
||||
width: componentWidth - (fixHeader ? tableContext.scrollbarSize : 0),
|
||||
position: 'sticky',
|
||||
left: 0,
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
class={`${prefixCls}-expanded-row-fixed`}
|
||||
>
|
||||
{contentNode}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return contentNode;
|
||||
},
|
||||
}}
|
||||
></Cell>
|
||||
</Component>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -16,7 +16,6 @@ export interface BodyProps<RecordType> {
|
|||
expandedKeys: Set<Key>;
|
||||
customRow: GetComponentProps<RecordType>;
|
||||
rowExpandable: (record: RecordType) => boolean;
|
||||
// emptyNode: React.ReactNode;
|
||||
childrenColumnName: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,14 +22,12 @@ function isRenderCell<RecordType = DefaultRecordType>(
|
|||
|
||||
export interface CellProps<RecordType = DefaultRecordType> {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
record?: RecordType;
|
||||
/** `record` index. Not `column` index. */
|
||||
index?: number;
|
||||
dataIndex?: DataIndex;
|
||||
customRender?: ColumnType<RecordType>['customRender'];
|
||||
component?: CustomizeComponent;
|
||||
children?: any;
|
||||
colSpan?: number;
|
||||
rowSpan?: number;
|
||||
ellipsis?: CellEllipsisType;
|
||||
|
@ -46,6 +44,7 @@ export interface CellProps<RecordType = DefaultRecordType> {
|
|||
// Additional
|
||||
/** @private Used for `expandable` with nest tree */
|
||||
appendNode?: any;
|
||||
|
||||
additionalProps?: HTMLAttributes;
|
||||
|
||||
rowType?: 'header' | 'body' | 'footer';
|
||||
|
@ -56,18 +55,39 @@ export interface CellProps<RecordType = DefaultRecordType> {
|
|||
}
|
||||
export default defineComponent<CellProps>({
|
||||
name: 'Cell',
|
||||
props: [] as any,
|
||||
props: [
|
||||
'prefixCls',
|
||||
'record',
|
||||
'index',
|
||||
'dataIndex',
|
||||
'customRender',
|
||||
'children',
|
||||
'component',
|
||||
'colSpan',
|
||||
'rowSpan',
|
||||
'fixLeft',
|
||||
'fixRight',
|
||||
'firstFixLeft',
|
||||
'lastFixLeft',
|
||||
'firstFixRight',
|
||||
'lastFixRight',
|
||||
'appendNode',
|
||||
'additionalProps',
|
||||
'ellipsis',
|
||||
'align',
|
||||
'rowType',
|
||||
'isSticky',
|
||||
'column',
|
||||
] as any,
|
||||
slots: ['appendNode'],
|
||||
setup(props) {
|
||||
setup(props, { slots }) {
|
||||
return () => {
|
||||
const {
|
||||
prefixCls,
|
||||
className,
|
||||
record,
|
||||
index,
|
||||
dataIndex,
|
||||
customRender,
|
||||
children,
|
||||
component: Component = 'td',
|
||||
colSpan,
|
||||
rowSpan,
|
||||
|
@ -77,7 +97,7 @@ export default defineComponent<CellProps>({
|
|||
lastFixLeft,
|
||||
firstFixRight,
|
||||
lastFixRight,
|
||||
appendNode,
|
||||
appendNode = slots.appendNode?.(),
|
||||
additionalProps = {},
|
||||
ellipsis,
|
||||
align,
|
||||
|
@ -90,7 +110,7 @@ export default defineComponent<CellProps>({
|
|||
// ==================== Child Node ====================
|
||||
let cellProps: CellType;
|
||||
let childNode;
|
||||
|
||||
const children = slots.default?.();
|
||||
if (validateValue(children)) {
|
||||
childNode = children;
|
||||
} else {
|
||||
|
@ -127,8 +147,7 @@ export default defineComponent<CellProps>({
|
|||
colSpan: cellColSpan,
|
||||
rowSpan: cellRowSpan,
|
||||
style: cellStyle,
|
||||
className: cellClassName,
|
||||
class: cellClass,
|
||||
class: cellClassName,
|
||||
...restCellProps
|
||||
} = cellProps || {};
|
||||
const mergedColSpan = cellColSpan !== undefined ? cellColSpan : colSpan;
|
||||
|
@ -179,7 +198,6 @@ export default defineComponent<CellProps>({
|
|||
rowSpan: mergedRowSpan && mergedRowSpan !== 1 ? mergedRowSpan : null,
|
||||
class: classNames(
|
||||
cellPrefixCls,
|
||||
className,
|
||||
{
|
||||
[`${cellPrefixCls}-fix-left`]: isFixLeft,
|
||||
[`${cellPrefixCls}-fix-left-first`]: firstFixLeft,
|
||||
|
@ -193,7 +211,6 @@ export default defineComponent<CellProps>({
|
|||
},
|
||||
additionalProps.class,
|
||||
cellClassName,
|
||||
cellClass,
|
||||
),
|
||||
style: {
|
||||
...parseStyleText(additionalProps.style as any),
|
||||
|
|
|
@ -6,8 +6,6 @@ import type { AlignType } from '../interface';
|
|||
import { getCellFixedInfo } from '../utils/fixUtil';
|
||||
|
||||
export interface SummaryCellProps {
|
||||
className?: string;
|
||||
children?: any;
|
||||
index: number;
|
||||
colSpan?: number;
|
||||
rowSpan?: number;
|
||||
|
@ -38,7 +36,7 @@ export default defineComponent<SummaryCellProps>({
|
|||
|
||||
return (
|
||||
<Cell
|
||||
className={attrs.class as string}
|
||||
class={attrs.class as string}
|
||||
index={index}
|
||||
component="td"
|
||||
prefixCls={prefixCls}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
export default function FooterRow(props, { slots }) {
|
||||
return <tr {...props}>{slots.default?.()}</tr>;
|
||||
}
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'FooterRow',
|
||||
setup(_props, { slots }) {
|
||||
return () => <tr>{slots.default?.()}</tr>;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { FunctionalComponent } from 'vue';
|
||||
import { computed, defineComponent, FunctionalComponent, onBeforeUnmount, watchEffect } from 'vue';
|
||||
import { useInjectTable } from '../context/TableContext';
|
||||
import Cell from './Cell';
|
||||
import Row from './Row';
|
||||
|
||||
|
@ -11,16 +12,22 @@ export interface SummaryFC extends FunctionalComponent<SummaryProps> {
|
|||
Cell: typeof Cell;
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntactic sugar. Do not support HOC.
|
||||
*/
|
||||
const Summary: SummaryFC = (_props, { slots }) => {
|
||||
return slots.default?.();
|
||||
};
|
||||
|
||||
Summary.Row = Row;
|
||||
Summary.Cell = Cell;
|
||||
|
||||
Summary.displayName = 'Summary';
|
||||
let indexGuid = 0;
|
||||
const Summary = defineComponent<SummaryProps>({
|
||||
props: ['fixed'] as any,
|
||||
name: 'Summary',
|
||||
setup(props, { slots }) {
|
||||
const tableContext = useInjectTable();
|
||||
const uniKey = `table-summary-uni-key-${++indexGuid}`;
|
||||
const fixed = computed(() => (props.fixed as string) === '' || props.fixed);
|
||||
watchEffect(() => {
|
||||
tableContext.summaryCollect(uniKey, fixed.value);
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
tableContext.summaryCollect(uniKey, false);
|
||||
});
|
||||
return () => slots.default?.();
|
||||
},
|
||||
});
|
||||
|
||||
export default Summary;
|
||||
|
|
|
@ -29,8 +29,8 @@ function parseHeaderRows<RecordType>(
|
|||
const colSpans: number[] = columns.filter(Boolean).map(column => {
|
||||
const cell: CellType<RecordType> = {
|
||||
key: column.key,
|
||||
className: classNames(column.className, column.class),
|
||||
children: column.title,
|
||||
class: classNames(column.className, column.class),
|
||||
// children: column.title,
|
||||
column,
|
||||
colStart: currentColIndex,
|
||||
};
|
||||
|
|
|
@ -86,6 +86,7 @@ export default defineComponent<RowProps>({
|
|||
additionalProps={additionalProps}
|
||||
rowType="header"
|
||||
column={column}
|
||||
v-slots={{ default: () => column.title }}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
|
|
@ -1,26 +1,20 @@
|
|||
import ColumnGroup from './sugar/ColumnGroup';
|
||||
import Column from './sugar/Column';
|
||||
import Header from './Header/Header';
|
||||
import type {
|
||||
GetRowKey,
|
||||
ColumnsType,
|
||||
TableComponents,
|
||||
Key,
|
||||
DefaultRecordType,
|
||||
TriggerEventHandler,
|
||||
GetComponentProps,
|
||||
ExpandableConfig,
|
||||
LegacyExpandableProps,
|
||||
GetComponent,
|
||||
PanelRender,
|
||||
TableLayout,
|
||||
ExpandableType,
|
||||
RowClassName,
|
||||
CustomizeComponent,
|
||||
ColumnType,
|
||||
CustomizeScrollBody,
|
||||
TableSticky,
|
||||
FixedType,
|
||||
} from './interface';
|
||||
import Body from './Body';
|
||||
import useColumns from './hooks/useColumns';
|
||||
|
@ -28,16 +22,13 @@ import { useLayoutState, useTimeoutLock } from './hooks/useFrame';
|
|||
import { getPathValue, mergeObject, validateValue, getColumnsKey } from './utils/valueUtil';
|
||||
import useStickyOffsets from './hooks/useStickyOffsets';
|
||||
import ColGroup from './ColGroup';
|
||||
import { getExpandableProps, getDataAndAriaProps } from './utils/legacyUtil';
|
||||
import Panel from './Panel';
|
||||
import Footer, { FooterComponents } from './Footer';
|
||||
import Footer from './Footer';
|
||||
import { findAllChildrenKeys, renderExpandIcon } from './utils/expandUtil';
|
||||
import { getCellFixedInfo } from './utils/fixUtil';
|
||||
import StickyScrollBar from './stickyScrollBar';
|
||||
import useSticky from './hooks/useSticky';
|
||||
import FixedHolder from './FixedHolder';
|
||||
import type { SummaryProps } from './Footer/Summary';
|
||||
import Summary from './Footer/Summary';
|
||||
import {
|
||||
computed,
|
||||
CSSProperties,
|
||||
|
@ -59,6 +50,10 @@ import isVisible from '../vc-util/Dom/isVisible';
|
|||
import { getTargetScrollBarSize } from '../_util/getScrollBarSize';
|
||||
import classNames from '../_util/classNames';
|
||||
import { EventHandler } from '../_util/EventInterface';
|
||||
import VCResizeObserver from '../vc-resize-observer';
|
||||
import { useProvideTable } from './context/TableContext';
|
||||
import { useProvideBody } from './context/BodyContext';
|
||||
import { useProvideResize } from './context/ResizeContext';
|
||||
|
||||
// Used for conditions cache
|
||||
const EMPTY_DATA = [];
|
||||
|
@ -85,8 +80,8 @@ export interface TableProps<RecordType = unknown> extends LegacyExpandableProps<
|
|||
rowClassName?: string | RowClassName<RecordType>;
|
||||
|
||||
// Additional Part
|
||||
// title?: PanelRender<RecordType>;
|
||||
// footer?: PanelRender<RecordType>;
|
||||
title?: PanelRender<RecordType>;
|
||||
footer?: PanelRender<RecordType>;
|
||||
// summary?: (data: readonly RecordType[]) => any;
|
||||
|
||||
// Customize
|
||||
|
@ -103,40 +98,14 @@ export interface TableProps<RecordType = unknown> extends LegacyExpandableProps<
|
|||
expandColumnWidth?: number;
|
||||
expandIconColumnIndex?: number;
|
||||
|
||||
// // =================================== Internal ===================================
|
||||
// /**
|
||||
// * @private Internal usage, may remove by refactor. Should always use `columns` instead.
|
||||
// *
|
||||
// * !!! DO NOT USE IN PRODUCTION ENVIRONMENT !!!
|
||||
// */
|
||||
// internalHooks?: string;
|
||||
|
||||
// /**
|
||||
// * @private Internal usage, may remove by refactor. Should always use `columns` instead.
|
||||
// *
|
||||
// * !!! DO NOT USE IN PRODUCTION ENVIRONMENT !!!
|
||||
// */
|
||||
// // Used for antd table transform column with additional column
|
||||
// transformColumns?: (columns: ColumnsType<RecordType>) => ColumnsType<RecordType>;
|
||||
|
||||
// /**
|
||||
// * @private Internal usage, may remove by refactor.
|
||||
// *
|
||||
// * !!! DO NOT USE IN PRODUCTION ENVIRONMENT !!!
|
||||
// */
|
||||
// internalRefs?: {
|
||||
// body: React.MutableRefObject<HTMLDivElement>;
|
||||
// };
|
||||
|
||||
sticky?: boolean | TableSticky;
|
||||
}
|
||||
|
||||
export default defineComponent<TableProps>({
|
||||
name: 'Table',
|
||||
slots: ['title', 'footer', 'summary', 'emptyText'],
|
||||
inheritAttrs: false,
|
||||
emits: ['expand', 'expandedRowsChange'],
|
||||
setup(props, { slots, attrs, emit }) {
|
||||
setup(props, { slots, emit }) {
|
||||
const mergedData = computed(() => props.data || EMPTY_DATA);
|
||||
const hasData = computed(() => !!mergedData.value.length);
|
||||
|
||||
|
@ -432,13 +401,58 @@ export default defineComponent<TableProps>({
|
|||
const emptyNode = () => {
|
||||
return hasData.value ? null : slots.emptyText?.() || 'No Data';
|
||||
};
|
||||
useProvideTable(
|
||||
reactive({
|
||||
...reactivePick(props, 'prefixCls', 'direction'),
|
||||
getComponent,
|
||||
scrollbarSize,
|
||||
fixedInfoList: computed(() =>
|
||||
flattenColumns.value.map((_, colIndex) =>
|
||||
getCellFixedInfo(
|
||||
colIndex,
|
||||
colIndex,
|
||||
flattenColumns.value,
|
||||
stickyOffsets.value,
|
||||
props.direction,
|
||||
),
|
||||
),
|
||||
),
|
||||
isSticky: computed(() => stickyState.value.isSticky),
|
||||
summaryCollect,
|
||||
}),
|
||||
);
|
||||
|
||||
useProvideBody(
|
||||
reactive({
|
||||
...reactivePick(
|
||||
props,
|
||||
'rowClassName',
|
||||
'expandedRowClassName',
|
||||
'expandRowByClick',
|
||||
'expandedRowRender',
|
||||
'expandIconColumnIndex',
|
||||
'indentSize',
|
||||
),
|
||||
columns,
|
||||
flattenColumns,
|
||||
tableLayout: mergedTableLayout,
|
||||
componentWidth,
|
||||
fixHeader,
|
||||
fixColumn,
|
||||
horizonScroll,
|
||||
expandIcon: mergedExpandIcon,
|
||||
expandableType,
|
||||
onTriggerExpand,
|
||||
}),
|
||||
);
|
||||
|
||||
useProvideResize({
|
||||
onColumnResize,
|
||||
});
|
||||
|
||||
return () => {
|
||||
const {
|
||||
prefixCls,
|
||||
rowClassName,
|
||||
data,
|
||||
rowKey,
|
||||
scroll,
|
||||
tableLayout,
|
||||
direction,
|
||||
|
@ -450,10 +464,8 @@ export default defineComponent<TableProps>({
|
|||
// Customize
|
||||
id,
|
||||
showHeader,
|
||||
components,
|
||||
customHeaderRow,
|
||||
rowExpandable,
|
||||
sticky,
|
||||
|
||||
customRow,
|
||||
} = props;
|
||||
|
@ -648,7 +660,36 @@ export default defineComponent<TableProps>({
|
|||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
|
||||
let fullTable = (
|
||||
<div
|
||||
class={classNames(prefixCls, {
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
[`${prefixCls}-ping-left`]: pingedLeft.value,
|
||||
[`${prefixCls}-ping-right`]: pingedRight.value,
|
||||
[`${prefixCls}-layout-fixed`]: tableLayout === 'fixed',
|
||||
[`${prefixCls}-fixed-header`]: fixHeader.value,
|
||||
/** No used but for compatible */
|
||||
[`${prefixCls}-fixed-column`]: fixColumn.value,
|
||||
[`${prefixCls}-scroll-horizontal`]: horizonScroll.value,
|
||||
[`${prefixCls}-has-fix-left`]: flattenColumns.value[0] && flattenColumns.value[0].fixed,
|
||||
[`${prefixCls}-has-fix-right`]:
|
||||
flattenColumns.value[columnCount.value - 1] &&
|
||||
flattenColumns.value[columnCount.value - 1].fixed === 'right',
|
||||
})}
|
||||
id={id}
|
||||
ref={fullTableRef}
|
||||
>
|
||||
{title && <Panel class={`${prefixCls}-title`}>{title(mergedData.value)}</Panel>}
|
||||
<div class={`${prefixCls}-container`}>{groupTableNode}</div>
|
||||
{footer && <Panel class={`${prefixCls}-footer`}>{footer(mergedData.value)}</Panel>}
|
||||
</div>
|
||||
);
|
||||
|
||||
if (horizonScroll.value) {
|
||||
fullTable = <VCResizeObserver onResize={onFullTableResize}>{fullTable}</VCResizeObserver>;
|
||||
}
|
||||
return fullTable;
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -15,6 +15,8 @@ export interface TableContextProps {
|
|||
fixedInfoList: readonly FixedInfo[];
|
||||
|
||||
isSticky: boolean;
|
||||
|
||||
summaryCollect: (uniKey: string, fixed: boolean | string) => void;
|
||||
}
|
||||
|
||||
export const BodyContextKey: InjectionKey<TableContextProps> = Symbol('TableContextProps');
|
||||
|
|
|
@ -120,7 +120,6 @@ function useColumns<RecordType>({
|
|||
}: {
|
||||
prefixCls?: Ref<string>;
|
||||
columns?: Ref<ColumnsType<RecordType>>;
|
||||
// children?: React.ReactNode;
|
||||
expandable: Ref<boolean>;
|
||||
expandedKeys: Ref<Set<Key>>;
|
||||
getRowKey: Ref<GetRowKey<RecordType>>;
|
||||
|
@ -134,11 +133,6 @@ function useColumns<RecordType>({
|
|||
expandFixed?: Ref<FixedType>;
|
||||
}): // transformColumns: (columns: ColumnsType<RecordType>) => ColumnsType<RecordType>,
|
||||
[ComputedRef<ColumnsType<RecordType>>, ComputedRef<readonly ColumnType<RecordType>[]>] {
|
||||
// const baseColumns = React.useMemo<ColumnsType<RecordType>>(
|
||||
// () => columns || convertChildrenToColumns(children),
|
||||
// [columns, children],
|
||||
// );
|
||||
|
||||
// Add expand column
|
||||
const withExpandColumns = computed<ColumnsType<RecordType>>(() => {
|
||||
if (expandable.value) {
|
||||
|
|
|
@ -36,9 +36,8 @@ export type RowClassName<RecordType> = (
|
|||
export interface CellType<RecordType = DefaultRecordType> {
|
||||
key?: Key;
|
||||
class?: string;
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
children?: any;
|
||||
// children?: any;
|
||||
column?: ColumnsType<RecordType>[number];
|
||||
colSpan?: number;
|
||||
rowSpan?: number;
|
||||
|
|
Loading…
Reference in New Issue