@visactor/vtable
Version:
canvas table width high performance
490 lines (489 loc) • 20.1 kB
TypeScript
import type { RectProps, MaybePromiseOrUndefined, IDimensionInfo, SortOrder, BaseCellInfo, CellInfo } from './common';
import type { ColumnIconOption, SvgIcon } from './icon';
export type { HeaderData } from './list-table/layout-map/api';
export type LayoutObjectId = number | string;
import type { Rect } from '../tools/Rect';
import type { BaseTableAPI, BaseTableConstructorOptions, ListTableProtected, PivotChartProtected, PivotTableProtected } from './base-table';
import type { Aggregation, AggregationType, CustomAggregation, FilterRules, IPivotTableDataConfig, SortType } from './new-data-set';
import type { Either } from '../tools/helper';
import type { IChartIndicator, IColumnDimension, ICornerDefine, IIndicator, IRowDimension, ITitleDefine } from './pivot-table';
import type { ColumnsDefine } from './list-table';
import type { ITableAxisOption } from './component/axis';
import type { IEditor } from '@visactor/vtable-editors';
import type { ITextStyleOption } from '../body-helper/style';
import type { CachedDataSource, DataSource } from '../data';
import type { EditManager } from '../edit/edit-manager';
import type { ICustomRender } from './customElement';
import type { ICustomLayout } from './customLayout';
import type { StylePropertyFunctionArg } from './style-define';
import type { LineAxisAttributes } from './../vrender';
export interface CellAddress {
col: number;
row: number;
}
export interface CellAddressWithBound {
col: number;
row: number;
rect?: RectProps;
x?: number;
y?: number;
}
export interface CellRange {
start: CellAddress;
end: CellAddress;
isCustom?: boolean;
}
export type FieldGetter = (record: any, col?: number, row?: number, table?: BaseTableAPI) => any;
export type FieldSetter = (record: any, value: any) => void;
export interface FieldAssessor {
get: FieldGetter;
set: FieldSetter;
}
export type FieldDef = string | number | string[];
export type FieldKeyDef = string | number;
export type FieldFormat = FieldGetter | FieldAssessor;
export type FieldData = MaybePromiseOrUndefined;
export type WidthModeDef = 'standard' | 'adaptive' | 'autoWidth';
export type HeightModeDef = 'standard' | 'adaptive' | 'autoHeight';
export type WidthAdaptiveModeDef = 'only-body' | 'all';
export type HeightAdaptiveModeDef = 'only-body' | 'all';
export type ShowColumnRowType = 'column' | 'row' | 'none' | 'all';
export type CellLocation = 'body' | 'rowHeader' | 'columnHeader' | 'cornerHeader';
export type CellPivotRole = 'normal' | 'sub-total' | 'grand-total' | undefined;
export type CellSubLocation = 'body' | 'rowHeader' | 'columnHeader' | 'cornerHeader' | 'bottomFrozen' | 'rightFrozen' | 'rightTopCorner' | 'leftBottomCorner' | 'rightBottomCorner' | 'rowSeriesNumber' | 'colSeriesNumber';
export interface SelectAllOnCtrlAOption {
disableHeaderSelect?: boolean;
disableRowSeriesNumberSelect?: boolean;
}
export interface TableKeyboardOptions {
moveFocusCellOnTab?: boolean;
editCellOnEnter?: boolean;
moveFocusCellOnEnter?: boolean;
moveEditCellOnArrowKeys?: boolean;
selectAllOnCtrlA?: boolean | SelectAllOnCtrlAOption;
cutSelected?: boolean;
copySelected?: boolean;
getCopyCellValue?: {
value?: (col: number, row: number) => string | number;
html?: (col: number, row: number) => string;
};
showCopyCellBorder?: boolean;
pasteValueToCell?: boolean;
processFormulaBeforePaste?: (values: (string | number)[][], sourceStartCol: number, sourceStartRow: number, targetStartCol: number, targetStartRow: number) => (string | number)[][];
moveSelectedCellOnArrowKeys?: boolean;
ctrlMultiSelect?: boolean;
shiftMultiSelect?: boolean;
}
export interface TableEventOptions {
preventDefaultContextMenu?: boolean;
contextmenuReturnAllSelectedCells?: boolean;
}
export interface IRowSeriesNumber {
width?: number | 'auto';
title?: string;
field?: string | number;
format?: (col?: number, row?: number, table?: BaseTableAPI) => any;
headerType?: 'text' | 'link' | 'image' | 'video' | 'checkbox';
cellType?: 'text' | 'link' | 'image' | 'video' | 'checkbox' | 'radio';
style?: ITextStyleOption | ((styleArg: StylePropertyFunctionArg) => ITextStyleOption);
headerStyle?: ITextStyleOption | ((styleArg: StylePropertyFunctionArg) => ITextStyleOption);
headerIcon?: string | ColumnIconOption | (string | ColumnIconOption)[];
icon?: string | ColumnIconOption | (string | ColumnIconOption)[] | ((args: CellInfo) => undefined | string | ColumnIconOption | (string | ColumnIconOption)[]);
dragOrder?: boolean;
disableColumnResize?: boolean;
enableTreeCheckbox?: boolean;
customLayout?: ICustomLayout;
headerCustomLayout?: ICustomLayout;
}
export interface ColumnSeriesNumber {
enable: boolean;
align?: 'top' | 'bottom';
span?: number | 'dependOnNear';
title?: string;
field?: FieldDef;
format?: (col?: number, row?: number, table?: BaseTableAPI) => any;
cellType?: 'text' | 'link' | 'image' | 'video' | 'checkbox';
style?: ITextStyleOption | ((styleArg: StylePropertyFunctionArg) => ITextStyleOption);
headerStyle?: ITextStyleOption | ((styleArg: StylePropertyFunctionArg) => ITextStyleOption);
icon?: string | ColumnIconOption | (string | ColumnIconOption)[] | ((args: CellInfo) => undefined | string | ColumnIconOption | (string | ColumnIconOption)[]);
selectRangeInclude?: boolean;
dragOrder?: boolean;
showDragOrderIcon?: boolean;
}
export interface DataSourceAPI {
clearCurrentIndexedData: () => void;
length: number;
get: (index: number) => MaybePromiseOrUndefined;
getField: <F extends FieldDef>(index: number, field: F, col: number, row: number, table: BaseTableAPI) => FieldData;
hasField: (index: number, field: FieldDef) => boolean;
sort: (rules: Array<SortState>) => void;
clearSortedMap: () => void;
updatePagination: (pagination: IPagination) => void;
getIndexKey: (index: number) => number | number[];
hierarchyExpandLevel: number;
getGroupLength?: () => number;
}
export interface SortState {
field: FieldDef;
order: SortOrder;
orderFn?: (a: any, b: any, order: string) => -1 | 0 | 1;
}
export interface PivotSortState {
col: number;
row: number;
order: SortType;
}
export interface IPagination {
totalCount?: number;
perPageCount: number;
currentPage?: number;
}
export type HeaderValues = Map<any, any>;
export interface ListTableConstructorOptions extends BaseTableConstructorOptions {
records?: any[];
addRecordRule?: 'Array' | 'Object';
dataSource?: CachedDataSource | DataSource;
showHeader?: boolean;
columns?: ColumnsDefine;
header?: ColumnsDefine;
transpose?: boolean;
hierarchyIndent?: number;
hierarchyExpandLevel?: number;
hierarchyTextStartAlignment?: boolean;
headerHierarchyType?: 'grid-tree';
headerExpandLevel?: number;
pagination?: IPagination;
sortState?: SortState | SortState[];
multipleSort?: boolean;
headerEditor?: string | IEditor | ((args: BaseCellInfo & {
table: BaseTableAPI;
}) => string | IEditor);
editor?: string | IEditor | ((args: BaseCellInfo & {
table: BaseTableAPI;
}) => string | IEditor);
editCellTrigger?: 'doubleclick' | 'click' | 'api' | 'keydown' | ('doubleclick' | 'click' | 'api' | 'keydown')[];
frozenColDragHeaderMode?: 'disabled' | 'adjustFrozenCount' | 'fixedFrozenCount';
dragOrder?: BaseTableConstructorOptions['dragOrder'] & {
frozenColDragHeaderMode?: 'disabled' | 'adjustFrozenCount' | 'fixedFrozenCount';
maintainArrayDataOrder?: boolean;
};
aggregation?: Aggregation | CustomAggregation | (Aggregation | CustomAggregation)[] | ((args: {
col: number;
field: string;
}) => Aggregation | CustomAggregation | (Aggregation | CustomAggregation)[] | null);
showAggregationWhenEmpty?: boolean;
enableTreeNodeMerge?: boolean;
groupConfig?: {
groupBy: GroupByOption;
titleCustomLayout?: ICustomLayout;
titleFieldFormat?: (record: any, col?: number, row?: number, table?: BaseTableAPI) => string;
enableTreeStickCell?: boolean;
titleCheckbox?: boolean;
};
groupBy?: GroupByOption;
groupTitleCustomLayout?: ICustomLayout;
groupTitleFieldFormat?: (record: any, col?: number, row?: number, table?: BaseTableAPI) => string;
enableTreeStickCell?: boolean;
columnWidthConfig?: {
key: string | number;
width: number;
}[];
rowHeightConfig?: {
key: number;
height: number;
}[];
syncRecordOperationsToSourceRecords?: boolean;
}
export type GroupByOption = string | string[] | GroupConfig | GroupConfig[];
export type GroupConfig = {
key: string;
sort?: SortOrder;
};
export interface ListTableAPI extends BaseTableAPI {
transpose: boolean;
options: ListTableConstructorOptions;
editorManager: EditManager;
sortState: SortState[] | SortState | null;
internalProps: ListTableProtected;
isListTable: () => true;
isPivotTable: () => false;
changeCellValue: (col: number, row: number, value: string | number | null, workOnEditableCell?: boolean, triggerEvent?: boolean, noTriggerChangeCellValuesEvent?: boolean) => void;
changeCellValuesByRanges: (ranges: CellRange[], value: string | number | null, workOnEditableCell?: boolean, triggerEvent?: boolean, noTriggerChangeCellValuesEvent?: boolean) => void;
changeCellValues: (col: number, row: number, values: (string | number)[][], workOnEditableCell?: boolean, triggerEvent?: boolean, noTriggerChangeCellValuesEvent?: boolean) => Promise<boolean[][]> | boolean[][];
changeCellValueByRecord: (recordIndex: number | number[], field: FieldDef, value: string | number | null, options?: {
triggerEvent?: boolean;
noTriggerChangeCellValuesEvent?: boolean;
autoRefresh?: boolean;
}) => void;
changeCellValuesByRecords: (changeValues: {
recordIndex: number | number[];
field: FieldDef;
value: string | number | null;
}[], options?: {
triggerEvent?: boolean;
noTriggerChangeCellValuesEvent?: boolean;
autoRefresh?: boolean;
}) => void;
changeCellValueBySource: (recordIndex: number | number[], field: FieldDef, value: string | number | null, triggerEvent?: boolean, noTriggerChangeCellValuesEvent?: boolean) => void;
changeCellValuesBySource: (changeValues: {
recordIndex: number | number[];
field: FieldDef;
value: string | number | null;
}[], triggerEvent?: boolean, noTriggerChangeCellValuesEvent?: boolean) => void;
refreshAfterSourceChange: (options?: {
reapplyFilter?: boolean;
reapplySort?: boolean;
clearRowHeightCache?: boolean;
}) => void;
getFieldData: (field: FieldDef | FieldFormat | undefined, col: number, row: number) => FieldData;
getEditor: (col: number, row: number) => IEditor;
startEditCell: (col?: number, row?: number, value?: string | number) => void;
completeEditCell: () => void;
cancelEditCell: () => void;
addRecord: (record: any, recordIndex?: number | number[], triggerEvent?: boolean) => void;
addRecords: (records: any[], recordIndex?: number | number[], triggerEvent?: boolean) => void;
deleteRecords: (recordIndexs: number[] | number[][], triggerEvent?: boolean) => void;
updateRecords: (records: any[], recordIndexs: (number | number[])[], triggerEvent?: boolean) => void;
updateFilterRules: (filterRules: FilterRules, options: {
clearRowHeightCache?: boolean;
}) => void;
getAggregateValuesByField: (field: string | number) => {
col: number;
aggregateValue: {
aggregationType: AggregationType;
value: number | string;
}[];
}[];
getBodyRowIndexByRecordIndex: (index: number | number[]) => number;
_hasHierarchyTreeHeader: () => boolean;
}
export interface PivotTableConstructorOptions extends BaseTableConstructorOptions {
records?: any[];
columnResizeType?: 'column' | 'indicator' | 'all' | 'indicatorGroup';
rowResizeType?: 'row' | 'indicator' | 'all' | 'indicatorGroup';
pivotSortState?: {
dimensions: IDimensionInfo[];
order: SortOrder;
}[];
columnWidthConfig?: {
dimensions: IDimensionInfo[];
width: number;
}[];
columnWidthConfigForRowHeader?: {
dimensions: IDimensionInfo[];
width: number;
}[];
rowHierarchyType?: 'grid' | 'tree' | 'grid-tree';
columnHierarchyType?: 'grid' | 'grid-tree';
rowExpandLevel?: number;
columnExpandLevel?: number;
rowHierarchyIndent?: number;
rowHierarchyTextStartAlignment?: boolean;
columnTree?: IHeaderTreeDefine[];
rowTree?: IHeaderTreeDefine[];
rows?: (IRowDimension | string)[];
columns?: (IColumnDimension | string)[];
indicators?: (IIndicator | string)[];
indicatorsAsCol?: boolean;
indicatorIndex?: number;
hideIndicatorName?: boolean;
corner?: ICornerDefine;
showColumnHeader?: boolean;
showRowHeader?: boolean;
columnHeaderTitle?: ITitleDefine;
rowHeaderTitle?: ITitleDefine;
dataConfig?: IPivotTableDataConfig;
indicatorTitle?: string;
pagination?: IPagination;
extensionRows?: IExtensionRowDefine[];
editor?: string | IEditor | ((args: BaseCellInfo & {
table: BaseTableAPI;
}) => string | IEditor);
headerEditor?: string | IEditor | ((args: BaseCellInfo & {
table: BaseTableAPI;
}) => string | IEditor);
editCellTrigger?: 'doubleclick' | 'click' | 'api' | 'keydown' | ('doubleclick' | 'click' | 'api' | 'keydown')[];
supplementIndicatorNodes?: boolean;
parseCustomTreeToMatchRecords?: boolean;
resize?: {
columnResizeType?: 'column' | 'indicator' | 'all' | 'indicatorGroup';
rowResizeType?: 'row' | 'indicator' | 'all' | 'indicatorGroup';
} & BaseTableConstructorOptions['resize'];
}
export interface PivotChartConstructorOptions extends BaseTableConstructorOptions {
records?: any[] | Record<string, any[]>;
columnResizeType?: 'column' | 'indicator' | 'all' | 'indicatorGroup';
rowResizeType?: 'row' | 'indicator' | 'all' | 'indicatorGroup';
columnTree?: IHeaderTreeDefine[];
rowTree?: IHeaderTreeDefine[];
rows?: (IRowDimension | string)[];
columns?: (IColumnDimension | string)[];
indicators?: (IChartIndicator | string)[];
indicatorsAsCol?: boolean;
hideIndicatorName?: boolean;
corner?: ICornerDefine;
showColumnHeader?: boolean;
showRowHeader?: boolean;
columnHeaderTitle?: ITitleDefine;
rowHeaderTitle?: ITitleDefine;
indicatorTitle?: string;
axes?: ITableAxisOption[];
resize?: {
columnResizeType?: 'column' | 'indicator' | 'all' | 'indicatorGroup';
rowResizeType?: 'row' | 'indicator' | 'all' | 'indicatorGroup';
} & BaseTableConstructorOptions['resize'];
columnWidthConfig?: {
dimensions: IDimensionInfo[];
width: number;
}[];
columnWidthConfigForRowHeader?: {
dimensions: IDimensionInfo[];
width: number;
}[];
chartDimensionLinkage?: {
showTooltip?: boolean;
heightLimitToShowTooltipForEdgeRow?: number;
widthLimitToShowTooltipForEdgeColumn?: number;
labelHoverOnAxis?: {
left?: LineAxisAttributes['labelHoverOnAxis'];
right?: LineAxisAttributes['labelHoverOnAxis'];
top?: LineAxisAttributes['labelHoverOnAxis'];
bottom?: LineAxisAttributes['labelHoverOnAxis'];
};
selectedStateFilter?: (datum: any) => boolean;
selectedReverseStateFilter?: (datum: any) => boolean;
inBrushStateFilter?: (datum: any) => boolean;
outOfBrushStateFilter?: (datum: any) => boolean;
listenBrushChange?: boolean;
brushChangeDelay?: number;
clearChartState?: () => void;
};
}
export interface PivotTableAPI extends BaseTableAPI {
internalProps: PivotTableProtected;
records?: any;
options: PivotTableConstructorOptions;
editorManager: EditManager;
pivotSortState: {
dimensions: IDimensionInfo[];
order: SortOrder;
}[];
isListTable: () => false;
isPivotTable: () => true;
getPivotSortState: (col: number, row: number) => SortOrder;
toggleHierarchyState: (col: number, row: number) => void;
changeCellValue: (col: number, row: number, value: string | number | null, workOnEditableCell: boolean) => void;
changeCellValues: (col: number, row: number, values: (string | number)[][], workOnEditableCell: boolean) => void;
getCellRowHeaderFullPaths: (col: number) => IDimensionInfo[];
getCellAddressByHeaderPaths: (dimensionPaths: {
colHeaderPaths: IDimensionInfo[];
rowHeaderPaths: IDimensionInfo[];
cellLocation: CellLocation;
} | IDimensionInfo[]) => CellAddress;
}
export interface PivotChartAPI extends BaseTableAPI {
internalProps: PivotChartProtected;
records?: any | Record<string, any[]>;
options: PivotChartConstructorOptions;
isListTable: () => false;
isPivotTable: () => true;
getCellAddressByHeaderPaths: (dimensionPaths: {
colHeaderPaths: IDimensionInfo[];
rowHeaderPaths: IDimensionInfo[];
cellLocation: CellLocation;
} | IDimensionInfo[]) => CellAddress;
}
export type SetPasteValueTestData = CellAddress & {
table: BaseTableAPI;
record: any;
value: string;
oldValue: any;
};
export interface InlineAPI {
width: (arg: {
ctx: CanvasRenderingContext2D;
}) => number;
font: () => string | null;
color: () => string | null;
canDraw: () => boolean;
onReady: (callback: Function) => void;
draw: (opt: any) => void;
canBreak: () => boolean;
}
export interface CellContext {
readonly col: number;
readonly row: number;
readonly value: FieldData;
readonly dataValue: FieldData;
showIcon?: SvgIcon;
getContext: () => CanvasRenderingContext2D;
toCurrentContext: () => CellContext;
getDrawRect: () => RectProps | null;
getRect: () => RectProps;
setRectFilter: (rectFilter: (base: RectProps) => RectProps) => void;
updateRect: (rect: Rect | RectProps) => void;
updateDrawRect: (rect: Rect | RectProps) => void;
}
export declare enum Placement {
top = "top",
bottom = "bottom",
left = "left",
right = "right"
}
export declare enum HierarchyState {
expand = "expand",
collapse = "collapse",
none = "none",
loading = "loading"
}
export type IHeaderTreeDefine = Either<IDimensionHeaderNode, IIndicatorHeaderNode>;
export interface IIndicatorHeaderNode {
indicatorKey: string | number;
value?: string;
children?: IHeaderTreeDefine[] | null;
levelSpan?: number;
hide?: boolean;
}
export interface IDimensionHeaderNode {
dimensionKey: string | number;
value: string;
children?: IHeaderTreeDefine[] | true;
hierarchyState?: HierarchyState;
virtual?: boolean;
levelSpan?: number;
}
export interface IExtensionRowDefine {
rows: (IRowDimension | string)[];
rowTree: IHeaderTreeDefine[] | ((args: {
dimensionKey: string | number;
value: string;
}[]) => IHeaderTreeDefine[]);
}
export type StickCell = {
col: number;
row: number;
dx: number;
dy: number;
};
export type CustomMergeCell = CustomMergeCellFunc | CustomMergeCellArray;
export type CustomMergeCellFunc = (col: number, row: number, table: BaseTableAPI) => undefined | CustomMerge;
export type CustomMergeCellArray = CustomMerge[];
export type CustomMerge = {
range: CellRange;
text?: string;
style?: ITextStyleOption;
customLayout?: ICustomLayout;
customRender?: ICustomRender;
};
export type ColumnInfo = {
col: number;
left: number;
right: number;
width: number;
};
export type RowInfo = {
row: number;
top: number;
bottom: number;
height: number;
};