@are-visual/virtual-table
Version:
### VirtualTable
415 lines (384 loc) • 18.9 kB
TypeScript
import * as react from 'react';
import { DetailedHTMLProps, HTMLAttributes, Key, ReactElement, CSSProperties, Ref, RefAttributes, ReactNode, TdHTMLAttributes, RefObject } from 'react';
type ScrollElement = HTMLElement | Window;
declare function getScrollParent(el: Element, root?: ScrollElement | null | undefined): ScrollElement;
declare function isWindow(arg: unknown): arg is Window;
declare function isDocument(arg: unknown): arg is Document;
declare function isRoot(arg: unknown): arg is HTMLHtmlElement;
declare function getScrollElement(el: unknown): Element;
declare function getScrollTop(node: ScrollElement): number;
declare function getRelativeOffsetTop(el: HTMLElement, ancestor: HTMLElement): number;
type NativeProps$1 = DetailedHTMLProps<HTMLAttributes<HTMLTableRowElement>, HTMLTableRowElement>;
interface OnRefCallbackArgs<T> {
node: HTMLTableRowElement | null;
rowKey: Key;
rowIndex: number;
rowData: T;
}
interface RowProps<T> extends Omit<NativeProps$1, 'children'> {
rowIndex: number;
rowKey: Key;
rowData: T;
columns: InnerColumnDescriptor<T>;
onRow?: OnRowType<T>;
renderRow?: MiddlewareRenderRow;
renderCell?: MiddlewareRenderCell;
onRefCallback?: (args: OnRefCallbackArgs<T>) => void;
}
declare const _default$3: <T>(props: RowProps<T>) => ReactElement;
interface TableBodyProps<T> extends Omit<NecessaryProps<T>, 'columns'>, Pick<RowProps<T>, 'onRow' | 'renderRow' | 'renderCell'> {
className?: string;
style?: CSSProperties;
defaultColumnWidth: number;
columns: InnerColumnDescriptor<T>;
bodyWrapperRef?: Ref<HTMLDivElement>;
bodyRootRef?: Ref<HTMLTableElement>;
bodyRef?: Ref<HTMLTableSectionElement>;
instance: TableInstance;
overscan: number;
estimateSize: number;
getOffsetTop: () => number;
getScroller: () => ScrollElement | undefined;
rowClassName?: (record: T, index: number) => string;
renderBodyWrapper?: MiddlewareRenderBodyWrapper;
renderBodyRoot?: MiddlewareRenderBodyRoot;
renderBody?: MiddlewareRenderBody;
renderBodyContent?: MiddlewareRenderBodyContent;
}
interface Hook<T> {
priority: number;
hook: Middleware<T>;
}
declare class TablePipeline<T> {
constructor();
hooks: Hook<T>[];
setHooks(value: Hook<T>[]): void;
use(options: MiddlewareContext<T>): MiddlewareResult<T>;
static defaultPipeline: TablePipeline<unknown>;
}
interface UseTablePipelineOptions<T = any> {
pipeline?: TablePipeline<T>;
use?: (Middleware<T> | Hook<T>)[];
}
declare function useTablePipeline<T = any>(options: UseTablePipelineOptions<T>): TablePipeline<T>;
interface VirtualTableCoreProps<T> extends NecessaryProps<T>, Pick<TableBodyProps<T>, 'rowClassName' | 'onRow'> {
bodyRootRef?: Ref<HTMLTableElement>;
instance?: TableInstance;
className?: string;
style?: CSSProperties;
tableBodyClassName?: string;
tableBodyStyle?: CSSProperties;
/** 开启表头 sticky,设置为 true 则默认 top 为 0,为 number 则是偏移量 */
stickyHeader?: number | boolean;
/** 预计每列宽度,需要横向虚拟化时,设置它 */
estimatedColumnWidth?: number;
/** 预计每行高度 @default 46 */
estimatedRowHeight?: number;
/** 在头和尾额外渲染多少行 @default 5 */
overscanRows?: number;
/** 横向虚拟化时,在头和尾额外渲染多少列 @default 3 */
overscanColumns?: number;
/** 开启表头虚拟滚动 @default true */
virtualHeader?: boolean;
/**
* 缺失宽度设置时的默认值(与虚拟化无关)
* @default 100
*/
defaultColumnWidth?: number;
pipeline?: TablePipeline<T>;
getOffsetTop?: () => number;
}
declare const _default$2: <T>(props: VirtualTableCoreProps<T> & RefAttributes<HTMLDivElement>) => ReactElement;
type FixedType = 'left' | 'right';
declare function isValidFixedLeft(fixed: unknown): fixed is "left";
declare function isValidFixedRight(fixed: unknown): fixed is "right";
declare function isValidFixed(fixed: unknown): fixed is "left" | "right";
type AnyObject = Record<string, any>;
type OnRowType<T = any> = (record: T, index: number) => Omit<DetailedHTMLProps<HTMLAttributes<HTMLTableRowElement>, HTMLTableRowElement>, 'children' | 'ref'>;
type AlignType = 'left' | 'right' | 'center';
interface ColumnExtra<T = any> {
}
interface ColumnTypeCommon<T> extends ColumnExtra<T> {
className?: string;
/** 表头列合并,设置为 0 时,不渲染 */
colSpan?: number;
title?: ReactNode;
align?: AlignType;
/** @default 100 */
width?: number;
fixed?: FixedType;
render?: (value: any, record: T, index: number) => ReactNode;
onHeaderCell?: (column: ColumnType<any>, index: number) => HTMLAttributes<any> & TdHTMLAttributes<any>;
onCell?: (data: T, index: number) => HTMLAttributes<any> & TdHTMLAttributes<any>;
}
type ColumnTypeWithKey<T> = ColumnTypeCommon<T> & {
key: Key;
[key: string]: unknown;
};
type ColumnTypeWithDataIndex<T> = ColumnTypeCommon<T> & {
dataIndex: keyof T | (string & {});
[key: string]: unknown;
};
type ColumnType<T> = ColumnTypeWithKey<T> | ColumnTypeWithDataIndex<T>;
type ColumnDescriptor<T = any> = {
key: Key;
type: 'blank';
width: number;
} | {
key: Key;
type: 'normal';
column: ColumnType<T>;
};
interface InnerColumnDescriptor<T> {
descriptor: ColumnDescriptor<T>[];
columns: ColumnType<T>[];
}
type Prettify$1<T> = {
[K in keyof T]: T[K];
} & {};
interface TableInstanceBuildIn<T = any> {
getCurrentProps: () => Prettify$1<Readonly<Omit<VirtualTableCoreProps<T>, 'defaultColumnWidth'> & Required<Pick<VirtualTableCoreProps<T>, 'estimatedRowHeight' | 'overscanRows' | 'overscanColumns' | 'defaultColumnWidth'>>>>;
/** 获取所有 middleware 处理过的 columns */
getColumns: () => ColumnType<T>[];
/** 获取所有 middleware 处理过的 dataSource */
getDataSource: () => T[];
getDOM: () => {
root: HTMLDivElement | null;
headerWrapper: HTMLDivElement | null;
bodyWrapper: HTMLDivElement | null;
bodyRoot: HTMLTableElement | null;
body: HTMLTableSectionElement | null;
};
/** 获取行虚拟化用到的数据 */
getRowVirtualizeState: () => {
startIndex: number;
endIndex: number;
overscan: number;
estimateSize: number;
};
/** 获取所有的行高信息。Map<rowKey, Map<key, number>> */
getRowHeightMap: () => Map<Key, Map<Key, number>>;
/** 通过索引值,获取指定行所对应的滚动数值 */
getScrollValueByRowIndex: (index: number) => number;
/** 通过 columnKey,获取指定列所对应的滚动数值 */
getScrollValueByColumnKey: (columnKey: Key) => number;
/** 通过索引值,滚动到指定行 */
scrollToRow: (index: number, behavior?: ScrollBehavior) => void;
/** 通过 columnKey,滚动到指定列 */
scrollToColumn: (columnKey: Key, behavior?: ScrollBehavior) => void;
scrollTo: (options: ScrollToOptions) => void;
/** 通过 columnKey 获取 column 定义 */
getColumnByKey: (columnKey: Key) => ColumnType<T> | undefined;
/** 通过索引获取 column 定义 */
getColumnByIndex: (index: number) => ColumnType<T> | undefined;
/** 通过索引获取 columnKey */
getColumnKeyByIndex: (index: number) => Key | undefined;
/** 获取所有的列宽 */
getColumnWidths: () => Map<Key, number>;
/** 通过 columnKey 获取列宽 */
getColumnWidthByKey: (columnKey: Key) => number | undefined;
}
interface TableInstance<T = any> extends TableInstanceBuildIn<T> {
extend: (args: Record<string, Function>) => void;
[key: PropertyKey]: Function;
}
interface NecessaryProps<T> {
dataSource: T[];
columns: ColumnType<T>[];
rowKey: (keyof T | (string & {})) | ((rowData: T) => Key);
}
type Prettify<T> = {
[K in keyof T]: T[K];
} & {};
interface MiddlewareContext<T> extends Readonly<NecessaryProps<T>> {
readonly estimatedRowHeight: number;
readonly rootRef: RefObject<HTMLDivElement>;
readonly headerWrapperRef: RefObject<HTMLDivElement>;
readonly bodyWrapperRef: RefObject<HTMLDivElement>;
readonly bodyRootRef: RefObject<HTMLTableElement>;
readonly bodyRef: RefObject<HTMLTableSectionElement>;
readonly getScroller: () => ScrollElement | undefined;
readonly getOffsetTop: () => number;
readonly instance: TableInstance;
[key: string]: unknown;
}
interface MiddlewareResult<T> extends MiddlewareContext<T>, MiddlewareRenders {
rowClassName?: (record: T, index: number) => string;
onRow?: OnRowType<T>;
[key: string]: unknown;
}
type Middleware<T> = (context: MiddlewareContext<T>) => MiddlewareResult<T>;
interface RenderOptions<T = any> {
column: ColumnType<T>;
columnWidths: Map<Key, number>;
rowKey: Key;
rowIndex: number;
startRowIndex: number;
columns: ColumnType<T>[];
rowData: T;
columnDescriptor: ColumnDescriptor<T>[];
}
type PipelineRenderOptions = Partial<RenderOptions>;
type PipelineRender = (children: ReactNode, options: PipelineRenderOptions) => ReactNode;
type MiddlewareRender<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor'>>) => ReactNode;
type MiddlewareRenderRoot<T = any> = (children: ReactNode, options: Prettify<Omit<RenderOptions<T>, keyof RenderOptions<T>>>) => ReactNode;
type MiddlewareRenderContent<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor'>>) => ReactNode;
type MiddlewareRenderHeaderWrapper<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor'>>) => ReactNode;
type MiddlewareRenderHeaderRoot<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor'>>) => ReactNode;
type MiddlewareRenderHeader<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor'>>) => ReactNode;
type MiddlewareRenderHeaderRow<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor'>>) => ReactNode;
type MiddlewareRenderHeaderCell<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor' | 'column' | 'columnWidths'>>) => ReactNode;
type MiddlewareRenderBodyWrapper<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor' | 'startRowIndex'>>) => ReactNode;
type MiddlewareRenderBodyRoot<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor' | 'startRowIndex'>>) => ReactNode;
type MiddlewareRenderBody<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor' | 'startRowIndex'>>) => ReactNode;
type MiddlewareRenderBodyContent<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor' | 'startRowIndex'>>) => ReactNode;
type MiddlewareRenderRow<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'columns' | 'columnDescriptor' | 'rowKey' | 'rowIndex' | 'rowData'>>) => ReactNode;
type MiddlewareRenderCell<T = any> = (children: ReactNode, options: Prettify<Pick<RenderOptions<T>, 'column'>>) => ReactNode;
type MergedMiddlewareRender<T = any> = MiddlewareRender<T> | MiddlewareRenderRoot<T> | MiddlewareRenderContent<T> | MiddlewareRenderHeaderWrapper<T> | MiddlewareRenderHeaderRoot<T> | MiddlewareRenderHeader<T> | MiddlewareRenderHeaderRow<T> | MiddlewareRenderHeaderCell<T> | MiddlewareRenderBodyWrapper<T> | MiddlewareRenderBodyRoot<T> | MiddlewareRenderBody<T> | MiddlewareRenderBodyContent<T> | MiddlewareRenderRow<T> | MiddlewareRenderCell<T>;
interface MiddlewareRenders {
/**
* 自定义最外层渲染,children 为 整个 VirtualTable。
*/
render?: MiddlewareRender;
/**
* 自定义 TableRoot(div.virtual-table) 的渲染。
* @note 注意:出于性能考虑,**需要自行对函数 memo**
*/
renderRoot?: MiddlewareRenderRoot;
/**
* 自定义渲染,children 为(TableHeader、TableBody)。
*/
renderContent?: MiddlewareRenderContent;
/**
* 自定义渲染 TableHeader。children 为 div.virtual-table-header
* @note 注意:出于性能考虑,**需要自行对函数 memo**
*/
renderHeaderWrapper?: MiddlewareRenderHeaderWrapper;
/**
* children 为 table
* @note 注意:出于性能考虑,**需要自行对函数 memo**
*/
renderHeaderRoot?: MiddlewareRenderHeaderRoot;
/**
* children 为 thead
* @note 注意:出于性能考虑,**需要自行对函数 memo**
*/
renderHeader?: MiddlewareRenderHeader;
/**
* children 为 tr
* @note 注意:出于性能考虑,**需要自行对函数 memo**
*/
renderHeaderRow?: MiddlewareRenderHeaderRow;
/**
* children 为 th
* @note 注意:出于性能考虑,**需要自行对函数 memo**
*/
renderHeaderCell?: MiddlewareRenderHeaderCell;
/**
* 自定义渲染 TableBody。children 为 div.virtual-table-body-wrapper
* @note 注意:出于性能考虑,**需要自行对函数 memo**
*/
renderBodyWrapper?: MiddlewareRenderBodyWrapper;
/**
* children 为 table.virtual-table-body
* @note 注意:出于性能考虑,**需要自行对函数 memo**
*/
renderBodyRoot?: MiddlewareRenderBodyRoot;
/**
* children 为 tbody
* @note 注意:出于性能考虑,**需要自行对函数 memo**
*/
renderBody?: MiddlewareRenderBody;
/**
* 默认情况下 children 是 ReactNode[],即 tbody 下渲染的各个 Row
*/
renderBodyContent?: MiddlewareRenderBodyContent;
/**
* children 为 tr
* @note 注意:出于性能考虑,**需要自行对函数 memo**
*/
renderRow?: MiddlewareRenderRow;
/**
* children 为 td
* @note 注意:出于性能考虑,**需要自行对函数 memo**
*/
renderCell?: MiddlewareRenderCell;
}
type NativeProps = DetailedHTMLProps<HTMLAttributes<HTMLTableCellElement>, HTMLTableCellElement>;
interface CellProps<T> extends Omit<NativeProps, 'children'> {
column: ColumnType<T>;
rowIndex: number;
rowData: T;
renderCell?: MiddlewareRenderCell;
}
declare const _default$1: <T>(props: CellProps<T>) => ReactElement;
interface ColgroupProps {
columns: ColumnDescriptor[];
defaultColumnWidth: number;
}
declare const _default: react.NamedExoticComponent<ColgroupProps>;
interface TableColumnsContextType {
widthList: Map<Key, number>;
}
declare function useColumnSizes(): TableColumnsContextType;
interface ContainerSizeState {
scrollContainerWidth: number;
scrollContainerHeight: number;
tableWidth: number;
tableHeight: number;
}
declare function useContainerSize(): ContainerSizeState;
type Listener = (scrollLeft: number, node: HTMLElement) => void;
interface HorizontalScrollContextState {
listen: (key: string, listener: Listener) => () => void;
notify: (key: string, options: {
scrollLeft: () => number;
node: HTMLElement;
}) => void;
}
declare function useHorizontalScrollContext(): HorizontalScrollContextState;
declare function useScrollSynchronize<T extends HTMLElement>(key: string): react.RefObject<T>;
interface TableRowManagerContextType {
getRowHeightList: () => number[];
/**
* @param rowKey
* @param key 唯一的 key,用于去重
* @param height 行高
*/
setRowHeightByRowKey: (rowKey: Key, key: Key, height: number) => void;
}
declare function useTableRowManager(): TableRowManagerContextType;
interface StickyContextState {
size: Map<Key, number>;
/** 每一列设置的 fixed 值 */
fixed: {
key: Key;
fixed: FixedType | undefined;
}[];
}
declare function useTableSticky(): StickyContextState;
declare const NormalRowHeightKey = "NormalRow";
/**
* 缓存数据(浅比较,如果是数组则对第一层进行浅比较)
*/
declare function useShallowMemo<T>(pickData: () => T): T;
declare function useStableFn<T extends Function>(callback: T): T;
declare function useTableInstance<T>(instance?: TableInstance<T>): TableInstance<T>;
/**
* 创建中间件,内部会浅比较 options,只有 options 改变才会返回新的函数。
*/
declare function createMiddleware<T, Args extends any[]>(hook: (ctx: MiddlewareContext<T>, ...args: Args) => MiddlewareResult<T>): (...args: Args) => Middleware<T>;
declare function getKey<T>(column: ColumnType<T>): Key;
declare function getRowKey<T>(rowData: T, rowKey: NecessaryProps<T>['rowKey']): Key;
declare function getColumnWidth<T>(column: ColumnType<T>, defaultColumnWidth: number): number;
interface ResizeRect {
width: number;
height: number;
}
declare function onResize(target: Window | HTMLElement, callback: (rect: ResizeRect) => void): () => void;
declare function findLastIndex<T>(arr: T[], predicate: (value: T, index: number) => boolean): number;
type PossibleRef<T> = Ref<T> | undefined;
declare function mergeRefs<T>(...refs: PossibleRef<T>[]): (node: T | null) => void;
declare function useMergedRef<T>(...refs: PossibleRef<T>[]): (node: T | null) => void;
export { _default as Colgroup, NormalRowHeightKey, TablePipeline, _default$2 as VirtualTable, _default$1 as VirtualTableCell, _default$3 as VirtualTableRow, createMiddleware, findLastIndex, getColumnWidth, getKey, getRelativeOffsetTop, getRowKey, getScrollElement, getScrollParent, getScrollTop, isDocument, isRoot, isValidFixed, isValidFixedLeft, isValidFixedRight, isWindow, mergeRefs, onResize, useColumnSizes, useContainerSize, useHorizontalScrollContext, useMergedRef, useScrollSynchronize, useShallowMemo, useStableFn, useTableInstance, useTablePipeline, useTableRowManager, useTableSticky };
export type { AlignType, AnyObject, ColumnDescriptor, ColumnExtra, ColumnType, ContainerSizeState, FixedType, HorizontalScrollContextState, MergedMiddlewareRender, Middleware, MiddlewareContext, MiddlewareRender, MiddlewareRenderBody, MiddlewareRenderBodyContent, MiddlewareRenderBodyRoot, MiddlewareRenderBodyWrapper, MiddlewareRenderCell, MiddlewareRenderContent, MiddlewareRenderHeader, MiddlewareRenderHeaderCell, MiddlewareRenderHeaderRoot, MiddlewareRenderHeaderRow, MiddlewareRenderHeaderWrapper, MiddlewareRenderRoot, MiddlewareRenderRow, MiddlewareRenders, MiddlewareResult, OnRowType, PipelineRender, PipelineRenderOptions, ScrollElement, StickyContextState, TableColumnsContextType, TableInstance, TableInstanceBuildIn, TableRowManagerContextType, UseTablePipelineOptions, CellProps as VirtualTableCellProps, VirtualTableCoreProps as VirtualTableProps, RowProps as VirtualTableRowProps };