fixed-react-data-grid-custom
Version:
Excel-like grid component built with React, with editors, keyboard navigation, copy & paste, and the like
305 lines (304 loc) • 10.5 kB
TypeScript
import { KeyboardEvent, ReactNode } from 'react';
import { List } from 'immutable';
import { HeaderRowType, UpdateActions } from './enums';
export declare type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
export declare type SelectedRow<TRow> = TRow & {
isSelected: boolean;
};
interface ColumnValue<TRow, TDependentValue = unknown, TField extends keyof TRow = keyof TRow> {
/** The name of the column. By default it will be displayed in the header cell */
name: string;
/** A unique key to distinguish each column */
key: TField;
/** Column width. If not specified, it will be determined automatically based on grid width and specified widths of other columns*/
width?: number;
hidden?: boolean;
cellClass?: string;
/** By adding an event object with callbacks for the native react events you can bind events to a specific column. That will not break the default behaviour of the grid and will run only for the specified column */
events?: {
[key: string]: undefined | ((e: Event, info: ColumnEventInfo<TRow>) => void);
};
/** Formatter to be used to render the cell content */
formatter?: React.ReactElement | React.ComponentType<FormatterProps<TRow[TField], TDependentValue, TRow>>;
/** Enables cell editing. If set and no editor property specified, then a textinput will be used as the cell editor */
editable?: boolean | ((rowData: TRow) => boolean);
/** Enable dragging of a column */
draggable?: boolean;
/** Enable filtering of a column */
filterable?: boolean;
/** Determines whether column is frozen or not */
frozen?: boolean;
/** Enable resizing of a column */
resizable?: boolean;
/** Enable sorting of a column */
sortable?: boolean;
/** Sets the column sort order to be descending instead of ascending the first time the column is sorted */
sortDescendingFirst?: boolean;
/** Editor to be rendered when cell of column is being edited. If set, then the column is automatically set to be editable */
editor?: React.ReactElement | React.ComponentType<EditorProps<TRow[TField], TDependentValue, TRow>>;
/** Header renderer for each header cell */
headerRenderer?: React.ReactElement | React.ComponentType<HeaderRowProps<TRow>>;
/** Component to be used to filter the data of the column */
filterRenderer?: React.ComponentType<FilterRendererProps<TRow, TDependentValue>>;
onCellChange?(rowIdx: number, key: keyof TRow, dependentValues: TDependentValue, event: React.SyntheticEvent): void;
getRowMetaData?(rowData: TRow, column: CalculatedColumn<TRow, TDependentValue>): TDependentValue;
}
export declare type Column<TRow, TDependentValue = unknown, TField extends keyof TRow = keyof TRow> = TField extends keyof TRow ? ColumnValue<TRow, TDependentValue, TField> : never;
export declare type CalculatedColumn<TRow, TDependentValue = unknown, TField extends keyof TRow = keyof TRow> = Column<TRow, TDependentValue, TField> & {
idx: number;
width: number;
left: number;
};
export declare type ColumnList<TRow> = Column<TRow>[] | List<Column<TRow>>;
export interface ColumnMetrics<TRow> {
columns: CalculatedColumn<TRow>[];
width: number;
totalColumnWidth: number;
totalWidth: number;
minColumnWidth: number;
}
export interface RowData {
name?: string;
get?(key: PropertyKey): unknown;
__metaData?: RowGroupMetaData;
}
export interface CellMetaData<TRow> {
rowKey: keyof TRow;
onCellClick(position: Position): void;
onCellContextMenu(position: Position): void;
onCellDoubleClick(position: Position): void;
onDragEnter(overRowIdx: number): void;
onCellExpand?(options: SubRowOptions<TRow>): void;
onRowExpandToggle?(e: RowExpandToggleEvent): void;
onCellMouseDown?(position: Position): void;
onCellMouseEnter?(position: Position): void;
onAddSubRow?(): void;
onDeleteSubRow?(options: SubRowOptions<TRow>): void;
getCellActions?(column: CalculatedColumn<TRow>, rowData: TRow): CellActionButton[] | undefined;
}
export interface Position {
idx: number;
rowIdx: number;
}
export interface Range {
topLeft: Position;
bottomRight: Position;
}
export interface SelectedRange extends Range {
startCell: Position | null;
cursorCell: Position | null;
isDragging: boolean;
}
export interface Dimension {
width: number;
height: number;
top: number;
left: number;
zIndex: number;
}
export declare type RowGetter<TRow> = (rowIdx: number) => TRow;
export interface Editor<TValue = never> extends React.Component {
getInputNode(): Element | Text | undefined | null;
getValue(): TValue;
hasResults?(): boolean;
isSelectOpen?(): boolean;
validate?(value: unknown): boolean;
readonly disableContainerStyles?: boolean;
}
export interface FormatterProps<TValue, TDependentValue = unknown, TRow = any> {
rowIdx: number;
value: TValue;
column: CalculatedColumn<TRow, TDependentValue>;
row: TRow;
isScrolling: boolean;
dependentValues?: TDependentValue;
}
export interface EditorProps<TValue, TDependentValue = unknown, TRow = any> {
column: CalculatedColumn<TRow, TDependentValue>;
value: TValue;
rowMetaData?: TDependentValue;
rowData: TRow;
height: number;
onCommit(args?: {
key?: string;
}): void;
onCommitCancel(): void;
onBlur(): void;
onOverrideKeyDown(e: KeyboardEvent): void;
}
export interface HeaderRowProps<TRow> {
column: CalculatedColumn<TRow>;
rowType: HeaderRowType;
}
export interface CellRendererProps<TRow, TValue = unknown> {
idx: number;
rowIdx: number;
height: number;
value: TValue;
column: CalculatedColumn<TRow>;
rowData: TRow;
cellMetaData: CellMetaData<TRow>;
isScrolling: boolean;
scrollLeft: number;
isRowSelected?: boolean;
expandableOptions?: ExpandableOptions;
lastFrozenColumnIndex?: number;
}
export interface RowRendererProps<TRow> {
height: number;
columns: CalculatedColumn<TRow>[];
row: TRow;
cellRenderer?: React.ComponentType<CellRendererProps<TRow>>;
cellMetaData: CellMetaData<TRow>;
isSelected?: boolean;
idx: number;
extraClasses?: string;
subRowDetails?: SubRowDetails;
colOverscanStartIdx: number;
colOverscanEndIdx: number;
isScrolling: boolean;
scrollLeft: number;
lastFrozenColumnIndex?: number;
}
export interface FilterRendererProps<TRow, TFilterValue = unknown> {
column: CalculatedColumn<TRow>;
onChange?(event: AddFilterEvent<TRow>): void;
/** TODO: remove */
getValidFilterValues?(columnKey: keyof TRow): TFilterValue;
}
export interface SubRowDetails<TChildRow = unknown> {
canExpand: boolean;
field: string;
expanded: boolean;
children: TChildRow[];
treeDepth: number;
siblingIndex: number;
numberSiblings: number;
group?: boolean;
}
export interface SubRowOptions<TRow, TChildRow = unknown> {
rowIdx: number;
idx: number;
rowData: TRow;
expandArgs?: ExpandableOptions<TChildRow>;
}
export interface ExpandableOptions<TChildRow = unknown> {
canExpand: boolean;
field: string;
expanded: boolean;
children: TChildRow[];
treeDepth: number;
subRowDetails: SubRowDetails;
}
interface Action {
text: ReactNode;
callback(): void;
}
export interface CellActionButton {
icon: ReactNode;
actions?: Action[];
callback?(): void;
}
export interface ColumnEventInfo<TRow> extends Position {
rowId: unknown;
column: CalculatedColumn<TRow>;
}
export interface CellRenderer {
setScrollLeft(scrollLeft: number): void;
}
export interface RowRenderer<TRow> {
setScrollLeft(scrollLeft: number): void;
getRowTop?(): number;
getRowHeight?(): number;
getDecoratedComponentInstance?(idx: number): {
row: RowRenderer<TRow> & React.Component<RowRendererProps<TRow>>;
} | undefined;
}
export interface ScrollPosition {
scrollLeft: number;
scrollTop: number;
}
export interface InteractionMasksMetaData<TRow> {
onCheckCellIsEditable?(e: CheckCellIsEditableEvent<TRow>): boolean;
onCellCopyPaste?(e: CellCopyPasteEvent<TRow>): void;
onGridRowsUpdated(cellKey: keyof TRow, toRow1: number, toRow2: number, data: {
[key: string]: unknown;
}, // FIX ME: Use Pick<R, K>
updateAction: UpdateActions, fromRow?: number): void;
onDragHandleDoubleClick(data: Position & {
rowData: TRow;
}): void;
onCellSelected?(position: Position): void;
onCellDeSelected?(position: Position): void;
onCellRangeSelectionStarted?(selectedRange: SelectedRange): void;
onCellRangeSelectionUpdated?(selectedRange: SelectedRange): void;
onCellRangeSelectionCompleted?(selectedRange: SelectedRange): void;
onCommit(e: CommitEvent<TRow>): void;
}
export interface RowGroupMetaData {
isGroup: boolean;
treeDepth: number;
isExpanded: boolean;
columnGroupName: string;
columnGroupDisplayName: string;
getRowRenderer?(props: unknown, rowIdx: number): React.ReactElement;
}
export declare type RowSelection = {
indexes?: number[];
} | {
isSelectedKey?: string;
} | {
keys?: {
values: unknown[];
rowKey: string;
};
};
export interface HeaderRowData<TRow> {
rowType: HeaderRowType;
height: number;
filterable?: boolean;
onFilterChange?(args: AddFilterEvent<TRow>): void;
}
export interface AddFilterEvent<TRow> {
filterTerm: string;
column: Column<TRow>;
}
export interface CommitEvent<TRow, TUpdatedValue = never> {
cellKey: keyof TRow;
rowIdx: number;
updated: TUpdatedValue;
key?: string;
}
export interface RowExpandToggleEvent {
rowIdx: number;
shouldExpand: boolean;
columnGroupName: string;
name: string;
}
export interface GridRowsUpdatedEvent<TRow, TUpdatedValue = never> {
cellKey: keyof TRow;
fromRow: number;
toRow: number;
fromRowId: unknown;
toRowId: unknown;
rowIds: unknown[];
updated: TUpdatedValue;
action: UpdateActions;
fromRowData: TRow;
}
export interface CellCopyPasteEvent<TRow> {
cellKey: keyof TRow;
rowIdx: number;
fromRow: number;
toRow: number;
value: unknown;
}
export interface CheckCellIsEditableEvent<TRow> extends Position {
row: TRow;
column: CalculatedColumn<TRow>;
}
export interface RowSelectionParams<TRow> {
rowIdx: number;
row: TRow;
}
export {};