1
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
||||
import * as React from 'react';
|
||||
import type { OnCustomizeScroll, ScrollConfig } from '../interface';
|
||||
export interface GridProps<RecordType = any> {
|
||||
data: RecordType[];
|
||||
onScroll: OnCustomizeScroll;
|
||||
}
|
||||
export interface GridRef {
|
||||
scrollLeft: number;
|
||||
nativeElement: HTMLDivElement;
|
||||
scrollTo: (scrollConfig: ScrollConfig) => void;
|
||||
}
|
||||
declare const ResponseGrid: React.ForwardRefExoticComponent<GridProps<any> & React.RefAttributes<GridRef>>;
|
||||
export default ResponseGrid;
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
import { useContext } from '@rc-component/context';
|
||||
import VirtualList from '@rc-component/virtual-list';
|
||||
import * as React from 'react';
|
||||
import TableContext, { responseImmutable } from "../context/TableContext";
|
||||
import useFlattenRecords from "../hooks/useFlattenRecords";
|
||||
import BodyLine from "./BodyLine";
|
||||
import { GridContext, StaticContext } from "./context";
|
||||
const Grid = /*#__PURE__*/React.forwardRef((props, ref) => {
|
||||
const {
|
||||
data,
|
||||
onScroll
|
||||
} = props;
|
||||
const {
|
||||
flattenColumns,
|
||||
onColumnResize,
|
||||
getRowKey,
|
||||
expandedKeys,
|
||||
prefixCls,
|
||||
childrenColumnName,
|
||||
scrollX,
|
||||
direction
|
||||
} = useContext(TableContext, ['flattenColumns', 'onColumnResize', 'getRowKey', 'prefixCls', 'expandedKeys', 'childrenColumnName', 'scrollX', 'direction']);
|
||||
const {
|
||||
sticky,
|
||||
scrollY,
|
||||
listItemHeight,
|
||||
getComponent,
|
||||
onScroll: onTablePropScroll
|
||||
} = useContext(StaticContext);
|
||||
|
||||
// =========================== Ref ============================
|
||||
const listRef = React.useRef(null);
|
||||
|
||||
// =========================== Data ===========================
|
||||
const flattenData = useFlattenRecords(data, childrenColumnName, expandedKeys, getRowKey);
|
||||
|
||||
// ========================== Column ==========================
|
||||
const columnsWidth = React.useMemo(() => {
|
||||
let total = 0;
|
||||
return flattenColumns.map(({
|
||||
width,
|
||||
minWidth,
|
||||
key
|
||||
}) => {
|
||||
const finalWidth = Math.max(width || 0, minWidth || 0);
|
||||
total += finalWidth;
|
||||
return [key, finalWidth, total];
|
||||
});
|
||||
}, [flattenColumns]);
|
||||
const columnsOffset = React.useMemo(() => columnsWidth.map(colWidth => colWidth[2]), [columnsWidth]);
|
||||
React.useEffect(() => {
|
||||
columnsWidth.forEach(([key, width]) => {
|
||||
onColumnResize(key, width);
|
||||
});
|
||||
}, [columnsWidth]);
|
||||
|
||||
// =========================== Ref ============================
|
||||
React.useImperativeHandle(ref, () => {
|
||||
const obj = {
|
||||
scrollTo: config => {
|
||||
const {
|
||||
offset,
|
||||
...restConfig
|
||||
} = config;
|
||||
|
||||
// If offset is provided, force align to 'top' for consistent behavior
|
||||
if (offset) {
|
||||
listRef.current?.scrollTo({
|
||||
...restConfig,
|
||||
offset,
|
||||
align: 'top'
|
||||
});
|
||||
} else {
|
||||
listRef.current?.scrollTo(config);
|
||||
}
|
||||
},
|
||||
nativeElement: listRef.current?.nativeElement
|
||||
};
|
||||
Object.defineProperty(obj, 'scrollLeft', {
|
||||
get: () => listRef.current?.getScrollInfo().x || 0,
|
||||
set: value => {
|
||||
listRef.current?.scrollTo({
|
||||
left: value
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/54734
|
||||
Object.defineProperty(obj, 'scrollTop', {
|
||||
get: () => listRef.current?.getScrollInfo().y || 0,
|
||||
set: value => {
|
||||
listRef.current?.scrollTo({
|
||||
top: value
|
||||
});
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
});
|
||||
|
||||
// ======================= Col/Row Span =======================
|
||||
const getRowSpan = (column, index) => {
|
||||
const record = flattenData[index]?.record;
|
||||
const {
|
||||
onCell
|
||||
} = column;
|
||||
if (onCell) {
|
||||
const cellProps = onCell(record, index);
|
||||
return cellProps?.rowSpan ?? 1;
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
const extraRender = info => {
|
||||
const {
|
||||
start,
|
||||
end,
|
||||
getSize,
|
||||
offsetY
|
||||
} = info;
|
||||
|
||||
// Do nothing if no data
|
||||
if (end < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find first rowSpan column
|
||||
let firstRowSpanColumns = flattenColumns.filter(
|
||||
// rowSpan is 0
|
||||
column => getRowSpan(column, start) === 0);
|
||||
let startIndex = start;
|
||||
for (let i = start; i >= 0; i -= 1) {
|
||||
firstRowSpanColumns = firstRowSpanColumns.filter(column => getRowSpan(column, i) === 0);
|
||||
if (!firstRowSpanColumns.length) {
|
||||
startIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find last rowSpan column
|
||||
let lastRowSpanColumns = flattenColumns.filter(
|
||||
// rowSpan is not 1
|
||||
column => getRowSpan(column, end) !== 1);
|
||||
let endIndex = end;
|
||||
for (let i = end; i < flattenData.length; i += 1) {
|
||||
lastRowSpanColumns = lastRowSpanColumns.filter(column => getRowSpan(column, i) !== 1);
|
||||
if (!lastRowSpanColumns.length) {
|
||||
endIndex = Math.max(i - 1, end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Collect the line who has rowSpan
|
||||
const spanLines = [];
|
||||
for (let i = startIndex; i <= endIndex; i += 1) {
|
||||
const item = flattenData[i];
|
||||
|
||||
// This code will never reach, just incase
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
if (flattenColumns.some(column => getRowSpan(column, i) > 1)) {
|
||||
spanLines.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Patch extra line on the page
|
||||
const nodes = spanLines.map(index => {
|
||||
const item = flattenData[index];
|
||||
const rowKey = getRowKey(item.record, index);
|
||||
const getHeight = rowSpan => {
|
||||
const endItemIndex = index + rowSpan - 1;
|
||||
const endItem = flattenData[endItemIndex];
|
||||
if (!endItem || !endItem.record) {
|
||||
// clamp 到当前可用的最后一行,或退化为默认高度
|
||||
const safeEndIndex = Math.min(endItemIndex, flattenData.length - 1);
|
||||
const safeEndItem = flattenData[safeEndIndex];
|
||||
const endItemKey = getRowKey(safeEndItem.record, safeEndIndex);
|
||||
const sizeInfo = getSize(rowKey, endItemKey);
|
||||
return sizeInfo.bottom - sizeInfo.top;
|
||||
}
|
||||
const endItemKey = getRowKey(endItem.record, endItemIndex);
|
||||
const sizeInfo = getSize(rowKey, endItemKey);
|
||||
return sizeInfo.bottom - sizeInfo.top;
|
||||
};
|
||||
const sizeInfo = getSize(rowKey);
|
||||
return /*#__PURE__*/React.createElement(BodyLine, {
|
||||
key: index,
|
||||
data: item,
|
||||
rowKey: rowKey,
|
||||
index: index,
|
||||
style: {
|
||||
top: -offsetY + sizeInfo.top
|
||||
},
|
||||
extra: true,
|
||||
getHeight: getHeight
|
||||
});
|
||||
});
|
||||
return nodes;
|
||||
};
|
||||
|
||||
// ========================= Context ==========================
|
||||
const gridContext = React.useMemo(() => ({
|
||||
columnsOffset
|
||||
}), [columnsOffset]);
|
||||
|
||||
// ========================== Render ==========================
|
||||
const tblPrefixCls = `${prefixCls}-tbody`;
|
||||
|
||||
// default 'div' in @rc-component/virtual-list
|
||||
const wrapperComponent = getComponent(['body', 'wrapper']);
|
||||
|
||||
// ========================== Sticky Scroll Bar ==========================
|
||||
const horizontalScrollBarStyle = {};
|
||||
if (sticky) {
|
||||
horizontalScrollBarStyle.position = 'sticky';
|
||||
horizontalScrollBarStyle.bottom = 0;
|
||||
if (typeof sticky === 'object' && sticky.offsetScroll) {
|
||||
horizontalScrollBarStyle.bottom = sticky.offsetScroll;
|
||||
}
|
||||
}
|
||||
return /*#__PURE__*/React.createElement(GridContext.Provider, {
|
||||
value: gridContext
|
||||
}, /*#__PURE__*/React.createElement(VirtualList, {
|
||||
fullHeight: false,
|
||||
ref: listRef,
|
||||
prefixCls: `${tblPrefixCls}-virtual`,
|
||||
styles: {
|
||||
horizontalScrollBar: horizontalScrollBarStyle
|
||||
},
|
||||
className: tblPrefixCls,
|
||||
height: scrollY,
|
||||
itemHeight: listItemHeight || 24,
|
||||
data: flattenData,
|
||||
itemKey: item => getRowKey(item.record),
|
||||
component: wrapperComponent,
|
||||
scrollWidth: scrollX,
|
||||
direction: direction,
|
||||
onVirtualScroll: ({
|
||||
x
|
||||
}) => {
|
||||
onScroll({
|
||||
currentTarget: listRef.current?.nativeElement,
|
||||
scrollLeft: x
|
||||
});
|
||||
},
|
||||
onScroll: onTablePropScroll,
|
||||
extraRender: extraRender
|
||||
}, (item, index, itemProps) => {
|
||||
const rowKey = getRowKey(item.record, index);
|
||||
return /*#__PURE__*/React.createElement(BodyLine, {
|
||||
data: item,
|
||||
rowKey: rowKey,
|
||||
index: index,
|
||||
style: itemProps.style
|
||||
});
|
||||
}));
|
||||
});
|
||||
const ResponseGrid = responseImmutable(Grid);
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
ResponseGrid.displayName = 'ResponseGrid';
|
||||
}
|
||||
export default ResponseGrid;
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import * as React from 'react';
|
||||
import type { FlattenData } from '../hooks/useFlattenRecords';
|
||||
export interface BodyLineProps<RecordType = any> {
|
||||
data: FlattenData<RecordType>;
|
||||
index: number;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
rowKey: React.Key;
|
||||
/** Render cell only when it has `rowSpan > 1` */
|
||||
extra?: boolean;
|
||||
getHeight?: (rowSpan: number) => number;
|
||||
}
|
||||
declare const ResponseBodyLine: React.ForwardRefExoticComponent<BodyLineProps<any> & React.RefAttributes<HTMLDivElement>>;
|
||||
export default ResponseBodyLine;
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
||||
import { useContext } from '@rc-component/context';
|
||||
import { clsx } from 'clsx';
|
||||
import * as React from 'react';
|
||||
import Cell from "../Cell";
|
||||
import TableContext, { responseImmutable } from "../context/TableContext";
|
||||
import useRowInfo from "../hooks/useRowInfo";
|
||||
import VirtualCell from "./VirtualCell";
|
||||
import { StaticContext } from "./context";
|
||||
import { computedExpandedClassName } from "../utils/expandUtil";
|
||||
const BodyLine = /*#__PURE__*/React.forwardRef((props, ref) => {
|
||||
const {
|
||||
data,
|
||||
index,
|
||||
className,
|
||||
rowKey,
|
||||
style,
|
||||
extra,
|
||||
getHeight,
|
||||
...restProps
|
||||
} = props;
|
||||
const {
|
||||
record,
|
||||
indent,
|
||||
index: renderIndex
|
||||
} = data;
|
||||
const {
|
||||
scrollX,
|
||||
flattenColumns,
|
||||
prefixCls,
|
||||
fixColumn,
|
||||
componentWidth
|
||||
} = useContext(TableContext, ['prefixCls', 'flattenColumns', 'fixColumn', 'componentWidth', 'scrollX']);
|
||||
const {
|
||||
getComponent
|
||||
} = useContext(StaticContext, ['getComponent']);
|
||||
const rowInfo = useRowInfo(record, rowKey, index, indent);
|
||||
const RowComponent = getComponent(['body', 'row'], 'div');
|
||||
const cellComponent = getComponent(['body', 'cell'], 'div');
|
||||
|
||||
// ========================== Expand ==========================
|
||||
const {
|
||||
rowSupportExpand,
|
||||
expanded,
|
||||
rowProps,
|
||||
expandedRowRender,
|
||||
expandedRowClassName
|
||||
} = rowInfo;
|
||||
let expandRowNode;
|
||||
if (rowSupportExpand && expanded) {
|
||||
const expandContent = expandedRowRender(record, index, indent + 1, expanded);
|
||||
const expandedClsName = computedExpandedClassName(expandedRowClassName, record, index, indent);
|
||||
let additionalProps = {};
|
||||
if (fixColumn) {
|
||||
additionalProps = {
|
||||
style: {
|
||||
['--virtual-width']: `${componentWidth}px`
|
||||
}
|
||||
};
|
||||
}
|
||||
const rowCellCls = `${prefixCls}-expanded-row-cell`;
|
||||
expandRowNode = /*#__PURE__*/React.createElement(RowComponent, {
|
||||
className: clsx(`${prefixCls}-expanded-row`, `${prefixCls}-expanded-row-level-${indent + 1}`, expandedClsName)
|
||||
}, /*#__PURE__*/React.createElement(Cell, {
|
||||
component: cellComponent,
|
||||
prefixCls: prefixCls,
|
||||
className: clsx(rowCellCls, {
|
||||
[`${rowCellCls}-fixed`]: fixColumn
|
||||
}),
|
||||
additionalProps: additionalProps
|
||||
}, expandContent));
|
||||
}
|
||||
|
||||
// ========================== Render ==========================
|
||||
const rowStyle = {
|
||||
...style,
|
||||
width: scrollX
|
||||
};
|
||||
if (extra) {
|
||||
rowStyle.position = 'absolute';
|
||||
rowStyle.pointerEvents = 'none';
|
||||
}
|
||||
const rowNode = /*#__PURE__*/React.createElement(RowComponent, _extends({}, rowProps, restProps, {
|
||||
"data-row-key": rowKey,
|
||||
ref: rowSupportExpand ? null : ref,
|
||||
className: clsx(className, `${prefixCls}-row`, rowProps?.className, {
|
||||
[`${prefixCls}-row-extra`]: extra
|
||||
}),
|
||||
style: {
|
||||
...rowStyle,
|
||||
...rowProps?.style
|
||||
}
|
||||
}), flattenColumns.map((column, colIndex) => {
|
||||
return /*#__PURE__*/React.createElement(VirtualCell, {
|
||||
key: colIndex,
|
||||
component: cellComponent,
|
||||
rowInfo: rowInfo,
|
||||
column: column,
|
||||
colIndex: colIndex,
|
||||
indent: indent,
|
||||
index: index,
|
||||
renderIndex: renderIndex,
|
||||
record: record,
|
||||
inverse: extra,
|
||||
getHeight: getHeight
|
||||
});
|
||||
}));
|
||||
if (rowSupportExpand) {
|
||||
return /*#__PURE__*/React.createElement("div", {
|
||||
ref: ref
|
||||
}, rowNode, expandRowNode);
|
||||
}
|
||||
return rowNode;
|
||||
});
|
||||
const ResponseBodyLine = responseImmutable(BodyLine);
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
ResponseBodyLine.displayName = 'BodyLine';
|
||||
}
|
||||
export default ResponseBodyLine;
|
||||
Generated
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
import * as React from 'react';
|
||||
import type useRowInfo from '../hooks/useRowInfo';
|
||||
import type { ColumnType, CustomizeComponent } from '../interface';
|
||||
export interface VirtualCellProps<RecordType> {
|
||||
rowInfo: ReturnType<typeof useRowInfo<RecordType>>;
|
||||
column: ColumnType<RecordType>;
|
||||
colIndex: number;
|
||||
indent: number;
|
||||
index: number;
|
||||
component?: CustomizeComponent;
|
||||
/** Used for `column.render` */
|
||||
renderIndex: number;
|
||||
record: RecordType;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
/** Render cell only when it has `rowSpan > 1` */
|
||||
inverse?: boolean;
|
||||
getHeight?: (rowSpan: number) => number;
|
||||
}
|
||||
/**
|
||||
* Return the width of the column by `colSpan`.
|
||||
* When `colSpan` is `0` will be trade as `1`.
|
||||
*/
|
||||
export declare function getColumnWidth(colIndex: number, colSpan: number, columnsOffset: number[]): number;
|
||||
declare const VirtualCell: <RecordType>(props: VirtualCellProps<RecordType>) => React.JSX.Element;
|
||||
export default VirtualCell;
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
||||
import { useContext } from '@rc-component/context';
|
||||
import { clsx } from 'clsx';
|
||||
import * as React from 'react';
|
||||
import { getCellProps } from "../Body/BodyRow";
|
||||
import Cell from "../Cell";
|
||||
import { GridContext } from "./context";
|
||||
/**
|
||||
* Return the width of the column by `colSpan`.
|
||||
* When `colSpan` is `0` will be trade as `1`.
|
||||
*/
|
||||
export function getColumnWidth(colIndex, colSpan, columnsOffset) {
|
||||
const mergedColSpan = colSpan || 1;
|
||||
return columnsOffset[colIndex + mergedColSpan] - (columnsOffset[colIndex] || 0);
|
||||
}
|
||||
const VirtualCell = props => {
|
||||
const {
|
||||
rowInfo,
|
||||
column,
|
||||
colIndex,
|
||||
indent,
|
||||
index,
|
||||
component,
|
||||
renderIndex,
|
||||
record,
|
||||
style,
|
||||
className,
|
||||
inverse,
|
||||
getHeight
|
||||
} = props;
|
||||
const {
|
||||
render,
|
||||
dataIndex,
|
||||
className: columnClassName,
|
||||
width: colWidth
|
||||
} = column;
|
||||
const {
|
||||
columnsOffset
|
||||
} = useContext(GridContext, ['columnsOffset']);
|
||||
|
||||
// TODO: support `expandableRowOffset`
|
||||
const {
|
||||
key,
|
||||
fixedInfo,
|
||||
appendCellNode,
|
||||
additionalCellProps
|
||||
} = getCellProps(rowInfo, column, colIndex, indent, index);
|
||||
const {
|
||||
style: cellStyle,
|
||||
colSpan = 1,
|
||||
rowSpan = 1
|
||||
} = additionalCellProps;
|
||||
|
||||
// ========================= ColWidth =========================
|
||||
// column width
|
||||
const startColIndex = colIndex - 1;
|
||||
const concatColWidth = getColumnWidth(startColIndex, colSpan, columnsOffset);
|
||||
|
||||
// margin offset
|
||||
const marginOffset = colSpan > 1 ? colWidth - concatColWidth : 0;
|
||||
|
||||
// ========================== Style ===========================
|
||||
const mergedStyle = {
|
||||
...cellStyle,
|
||||
...style,
|
||||
flex: `0 0 ${concatColWidth}px`,
|
||||
width: `${concatColWidth}px`,
|
||||
marginRight: marginOffset,
|
||||
pointerEvents: 'auto'
|
||||
};
|
||||
|
||||
// When `colSpan` or `rowSpan` is `0`, should skip render.
|
||||
const needHide = React.useMemo(() => {
|
||||
if (inverse) {
|
||||
return rowSpan <= 1;
|
||||
} else {
|
||||
return colSpan === 0 || rowSpan === 0 || rowSpan > 1;
|
||||
}
|
||||
}, [rowSpan, colSpan, inverse]);
|
||||
|
||||
// 0 rowSpan or colSpan should not render
|
||||
if (needHide) {
|
||||
mergedStyle.visibility = 'hidden';
|
||||
} else if (inverse) {
|
||||
mergedStyle.height = getHeight?.(rowSpan);
|
||||
}
|
||||
const mergedRender = needHide ? () => null : render;
|
||||
|
||||
// ========================== Render ==========================
|
||||
const cellSpan = {};
|
||||
|
||||
// Virtual should reset `colSpan` & `rowSpan`
|
||||
if (rowSpan === 0 || colSpan === 0) {
|
||||
cellSpan.rowSpan = 1;
|
||||
cellSpan.colSpan = 1;
|
||||
}
|
||||
return /*#__PURE__*/React.createElement(Cell, _extends({
|
||||
className: clsx(columnClassName, className),
|
||||
ellipsis: column.ellipsis,
|
||||
align: column.align,
|
||||
scope: column.rowScope,
|
||||
component: component,
|
||||
prefixCls: rowInfo.prefixCls,
|
||||
key: key,
|
||||
record: record,
|
||||
index: index,
|
||||
renderIndex: renderIndex,
|
||||
dataIndex: dataIndex,
|
||||
render: mergedRender,
|
||||
shouldCellUpdate: column.shouldCellUpdate
|
||||
}, fixedInfo, {
|
||||
appendNode: appendCellNode,
|
||||
additionalProps: {
|
||||
...additionalCellProps,
|
||||
style: mergedStyle,
|
||||
...cellSpan
|
||||
}
|
||||
}));
|
||||
};
|
||||
export default VirtualCell;
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/// <reference types="react" />
|
||||
import type { GetComponent, TableSticky } from '../interface';
|
||||
export interface StaticContextProps {
|
||||
scrollY: number;
|
||||
listItemHeight: number;
|
||||
sticky: boolean | TableSticky;
|
||||
getComponent: GetComponent;
|
||||
onScroll?: React.UIEventHandler<HTMLDivElement>;
|
||||
}
|
||||
export declare const StaticContext: import("@rc-component/context").SelectorContext<StaticContextProps>;
|
||||
export interface GridContextProps {
|
||||
columnsOffset: number[];
|
||||
}
|
||||
export declare const GridContext: import("@rc-component/context").SelectorContext<GridContextProps>;
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import { createContext } from '@rc-component/context';
|
||||
export const StaticContext = createContext(null);
|
||||
export const GridContext = createContext(null);
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import type { CompareProps } from '@rc-component/context/lib/Immutable';
|
||||
import * as React from 'react';
|
||||
import type { Reference } from '../interface';
|
||||
import { type TableProps } from '../Table';
|
||||
export interface VirtualTableProps<RecordType> extends Omit<TableProps<RecordType>, 'scroll'> {
|
||||
listItemHeight?: number;
|
||||
scroll: {
|
||||
x?: number;
|
||||
y?: number;
|
||||
};
|
||||
}
|
||||
export type ForwardGenericVirtualTable = (<RecordType>(props: TableProps<RecordType> & React.RefAttributes<Reference>) => React.ReactElement<any>) & {
|
||||
displayName?: string;
|
||||
};
|
||||
export declare const genVirtualTable: (shouldTriggerRender?: CompareProps<ForwardGenericVirtualTable>) => ForwardGenericVirtualTable;
|
||||
declare const _default: ForwardGenericVirtualTable;
|
||||
export default _default;
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
||||
import { clsx } from 'clsx';
|
||||
import { useEvent, warning } from '@rc-component/util';
|
||||
import * as React from 'react';
|
||||
import { INTERNAL_HOOKS } from "../constant";
|
||||
import { makeImmutable } from "../context/TableContext";
|
||||
import Table, { DEFAULT_PREFIX } from "../Table";
|
||||
import Grid from "./BodyGrid";
|
||||
import { StaticContext } from "./context";
|
||||
import getValue from "@rc-component/util/es/utils/get";
|
||||
const renderBody = (rawData, props) => {
|
||||
const {
|
||||
ref,
|
||||
onScroll
|
||||
} = props;
|
||||
return /*#__PURE__*/React.createElement(Grid, {
|
||||
ref: ref,
|
||||
data: rawData,
|
||||
onScroll: onScroll
|
||||
});
|
||||
};
|
||||
const VirtualTable = (props, ref) => {
|
||||
const {
|
||||
data,
|
||||
columns,
|
||||
scroll,
|
||||
sticky,
|
||||
prefixCls = DEFAULT_PREFIX,
|
||||
className,
|
||||
listItemHeight,
|
||||
components,
|
||||
onScroll
|
||||
} = props;
|
||||
let {
|
||||
x: scrollX,
|
||||
y: scrollY
|
||||
} = scroll || {};
|
||||
|
||||
// Fill scrollX
|
||||
if (typeof scrollX !== 'number') {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
warning(!scrollX, '`scroll.x` in virtual table must be number.');
|
||||
}
|
||||
scrollX = 1;
|
||||
}
|
||||
|
||||
// Fill scrollY
|
||||
if (typeof scrollY !== 'number') {
|
||||
scrollY = 500;
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
warning(false, '`scroll.y` in virtual table must be number.');
|
||||
}
|
||||
}
|
||||
const getComponent = useEvent((path, defaultComponent) => getValue(components, path) || defaultComponent);
|
||||
|
||||
// Memo this
|
||||
const onInternalScroll = useEvent(onScroll);
|
||||
|
||||
// ========================= Context ==========================
|
||||
const context = React.useMemo(() => ({
|
||||
sticky,
|
||||
scrollY,
|
||||
listItemHeight,
|
||||
getComponent,
|
||||
onScroll: onInternalScroll
|
||||
}), [sticky, scrollY, listItemHeight, getComponent, onInternalScroll]);
|
||||
|
||||
// ========================== Render ==========================
|
||||
return /*#__PURE__*/React.createElement(StaticContext.Provider, {
|
||||
value: context
|
||||
}, /*#__PURE__*/React.createElement(Table, _extends({}, props, {
|
||||
className: clsx(className, `${prefixCls}-virtual`),
|
||||
scroll: {
|
||||
...scroll,
|
||||
x: scrollX
|
||||
},
|
||||
components: {
|
||||
...components,
|
||||
// fix https://github.com/ant-design/ant-design/issues/48991
|
||||
body: data?.length ? renderBody : undefined
|
||||
},
|
||||
columns: columns,
|
||||
internalHooks: INTERNAL_HOOKS,
|
||||
tailor: true,
|
||||
ref: ref
|
||||
})));
|
||||
};
|
||||
const RefVirtualTable = /*#__PURE__*/React.forwardRef(VirtualTable);
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
RefVirtualTable.displayName = 'VirtualTable';
|
||||
}
|
||||
export const genVirtualTable = shouldTriggerRender => {
|
||||
return makeImmutable(RefVirtualTable, shouldTriggerRender);
|
||||
};
|
||||
export default genVirtualTable();
|
||||
Reference in New Issue
Block a user