UNPKG

17.8 kBTypeScriptView Raw
1import type * as PropTypes from "prop-types";
2import { Component, JSX, PureComponent, ReactNode } from "react";
3import { Alignment, Index, IndexRange, OverscanIndexRange, ScrollEventData } from "../../index";
4import { CellMeasurerCache } from "./CellMeasurer";
5import { Grid, GridCoreProps } from "./Grid";
6
7export type SortParams = {
8 defaultSortDirection: SortDirectionType;
9 event: MouseEvent;
10 sortBy: string;
11};
12
13export type SortDirectionMap = { [key: string]: SortDirectionType };
14
15export type MultiSortOptions = {
16 defaultSortBy?: string[] | undefined;
17 defaultSortDirection?: SortDirectionMap | undefined;
18};
19
20export type MultiSortReturn = {
21 /**
22 * Sort property to be passed to the `Table` component.
23 * This function updates `sortBy` and `sortDirection` values.
24 */
25 sort: (params: SortParams) => void;
26
27 /**
28 * Specifies the fields currently responsible for sorting data,
29 * In order of importance.
30 */
31 sortBy: string[];
32
33 /**
34 * Specifies the direction a specific field is being sorted in.
35 */
36 sortDirection: SortDirectionMap;
37};
38
39export function createMultiSort(
40 sortCallback: (params: { sortBy: string; sortDirection: SortDirectionType }) => void,
41 options?: MultiSortOptions,
42): MultiSortReturn;
43
44export type TableCellDataGetterParams = {
45 columnData?: any;
46 dataKey: string;
47 rowData: any;
48};
49export type TableCellProps = {
50 cellData?: any;
51 columnData?: any;
52 columnIndex: number;
53 dataKey: string;
54 isScrolling: boolean;
55 parent?: any;
56 rowData: any;
57 rowIndex: number;
58};
59export type TableHeaderProps = {
60 columnData?: any;
61 dataKey: string;
62 disableSort?: boolean | undefined;
63 label?: ReactNode | undefined;
64 sortBy?: string | undefined;
65 sortDirection?: SortDirectionType | undefined;
66};
67export type TableHeaderRowProps = {
68 className: string;
69 columns: React.ReactNode[];
70 style: React.CSSProperties;
71 scrollbarWidth: number;
72 height: number;
73 width: number;
74};
75export type TableRowProps = {
76 className: string;
77 columns: any[];
78 index: number;
79 isScrolling: boolean;
80 key: string;
81 onRowClick?: ((params: RowMouseEventHandlerParams) => void) | undefined;
82 onRowDoubleClick?: ((params: RowMouseEventHandlerParams) => void) | undefined;
83 onRowMouseOver?: ((params: RowMouseEventHandlerParams) => void) | undefined;
84 onRowMouseOut?: ((params: RowMouseEventHandlerParams) => void) | undefined;
85 onRowRightClick?: ((params: RowMouseEventHandlerParams) => void) | undefined;
86 rowData: any;
87 style: any;
88};
89
90export type TableCellDataGetter = (params: TableCellDataGetterParams) => any;
91export type TableCellRenderer = (props: TableCellProps) => React.ReactNode;
92export type TableHeaderRenderer = (props: TableHeaderProps) => React.ReactNode;
93export type TableHeaderRowRenderer = (props: TableHeaderRowProps) => React.ReactNode;
94export type TableRowRenderer = (props: TableRowProps) => React.ReactNode;
95
96// https://github.com/bvaughn/react-virtualized/blob/master/docs/Column.md
97export type ColumnProps = {
98 /** Optional aria-label value to set on the column header */
99 "aria-label"?: string | undefined;
100 /**
101 * Callback responsible for returning a cell's data, given its :dataKey
102 * ({ columnData: any, dataKey: string, rowData: any }): any
103 */
104 cellDataGetter?: TableCellDataGetter | undefined;
105 /**
106 * Callback responsible for rendering a cell's contents.
107 * ({ cellData: any, columnData: any, dataKey: string, rowData: any, rowIndex: number }): node
108 */
109 cellRenderer?: TableCellRenderer | undefined;
110 /** Optional CSS class to apply to cell */
111 className?: string | undefined;
112 /** Optional additional data passed to this column's :cellDataGetter */
113 columnData?: any;
114 /** Uniquely identifies the row-data attribute correspnding to this cell */
115 dataKey: any;
116 /** Default sort order when clicked for the first time. Valid options include "ASC" and "DESC". Defaults to "ASC" */
117 defaultSortDirection?: SortDirectionType | undefined;
118 /** If sort is enabled for the table at large, disable it for this column */
119 disableSort?: boolean | undefined;
120 /** Flex grow style; defaults to 0 */
121 flexGrow?: number | undefined;
122 /** Flex shrink style; defaults to 1 */
123 flexShrink?: number | undefined;
124 /** Optional CSS class to apply to this column's header */
125 headerClassName?: string | undefined;
126 /**
127 * Optional callback responsible for rendering a column header contents.
128 * ({ columnData: object, dataKey: string, disableSort: boolean, label: string, sortBy: string, sortDirection: string }): PropTypes.node
129 */
130 headerRenderer?: TableHeaderRenderer | undefined;
131 /** Optional inline style to apply to this column's header */
132 headerStyle?: React.CSSProperties | undefined;
133 /** Optional id to set on the column header; used for aria-describedby */
134 id?: string | undefined;
135 /** Header label for this column */
136 label?: ReactNode | undefined;
137 /** Maximum width of column; this property will only be used if :flexGrow is > 0. */
138 maxWidth?: number | undefined;
139 /** Minimum width of column. */
140 minWidth?: number | undefined;
141 /** Optional inline style to apply to cell */
142 style?: React.CSSProperties | undefined;
143 /** Flex basis (width) for this column; This value can grow or shrink based on :flexGrow and :flexShrink properties. */
144 width: number;
145};
146export class Column extends Component<ColumnProps> {
147 static propTypes: {
148 "aria-label": PropTypes.Requireable<string>;
149 cellDataGetter: PropTypes.Requireable<TableCellDataGetter>;
150 cellRenderer: PropTypes.Requireable<TableCellRenderer>;
151 className: PropTypes.Requireable<string>;
152 columnData: PropTypes.Requireable<object>;
153 dataKey: PropTypes.Validator<string>;
154 disableSort: PropTypes.Requireable<boolean>;
155 flexGrow: PropTypes.Requireable<number>;
156 flexShrink: PropTypes.Requireable<number>;
157 headerClassName: PropTypes.Requireable<string>;
158 headerRenderer: PropTypes.Validator<TableHeaderRowRenderer>;
159 label: PropTypes.Requireable<string>;
160 maxWidth: PropTypes.Requireable<number>;
161 minWidth: PropTypes.Requireable<number>;
162 style: PropTypes.Requireable<React.CSSProperties>;
163 width: PropTypes.Validator<number>;
164 id: PropTypes.Requireable<string>;
165 };
166
167 static defaultProps: {
168 cellDataGetter: TableCellDataGetter;
169 cellRenderer: TableCellRenderer;
170 flexGrow: 0;
171 flexShrink: 1;
172 headerRenderer: TableHeaderRenderer;
173 style: {};
174 };
175}
176
177export type RowMouseEventHandlerParams = {
178 rowData: any;
179 index: number;
180 event: React.MouseEvent<any>;
181};
182
183export type HeaderMouseEventHandlerParams = {
184 dataKey: string;
185 columnData: any;
186 event: React.MouseEvent<any>;
187};
188
189// ref: https://github.com/bvaughn/react-virtualized/blob/master/docs/Table.md
190export type TableProps = GridCoreProps & {
191 "aria-label"?: string | undefined;
192 deferredMeasurementCache?: CellMeasurerCache | undefined;
193 /**
194 * Removes fixed height from the scrollingContainer so that the total height
195 * of rows can stretch the window. Intended for use with WindowScroller
196 */
197 autoHeight?: boolean | undefined;
198 /** One or more Columns describing the data displayed in this row */
199 children?: React.ReactNode | undefined;
200 /** Optional CSS class name */
201 className?: string | undefined;
202 /** Disable rendering the header at all */
203 disableHeader?: boolean | undefined;
204 /**
205 * Used to estimate the total height of a Table before all of its rows have actually been measured.
206 * The estimated total height is adjusted as rows are rendered.
207 */
208 estimatedRowSize?: number | undefined;
209 /** Optional custom CSS class name to attach to inner Grid element. */
210 gridClassName?: string | undefined;
211 /** Optional inline style to attach to inner Grid element. */
212 gridStyle?: any;
213 /** Optional CSS class to apply to all column headers */
214 headerClassName?: string | undefined;
215 /** Fixed height of header row */
216 headerHeight: number;
217 /**
218 * Responsible for rendering a table row given an array of columns:
219 * Should implement the following interface: ({
220 * className: string,
221 * columns: any[],
222 * style: any
223 * }): PropTypes.node
224 */
225 headerRowRenderer?: TableHeaderRowRenderer | undefined;
226 /** Optional custom inline style to attach to table header columns. */
227 headerStyle?: any;
228 /** Fixed/available height for out DOM element */
229 height?: number | undefined;
230 /** Optional id */
231 id?: string | undefined;
232 /** Optional renderer to be used in place of table body rows when rowCount is 0 */
233 noRowsRenderer?: (() => JSX.Element | null) | undefined;
234 /**
235 * Optional callback when a column's header is clicked.
236 * ({ columnData: any, dataKey: string }): void
237 */
238 onHeaderClick?: ((params: HeaderMouseEventHandlerParams) => void) | undefined;
239 /**
240 * Callback invoked when a user clicks on a table row.
241 * ({ index: number }): void
242 */
243 onRowClick?: ((info: RowMouseEventHandlerParams) => void) | undefined;
244 /**
245 * Callback invoked when a user double-clicks on a table row.
246 * ({ index: number }): void
247 */
248 onRowDoubleClick?: ((info: RowMouseEventHandlerParams) => void) | undefined;
249 /**
250 * Callback invoked when the mouse leaves a table row.
251 * ({ index: number }): void
252 */
253 onRowMouseOut?: ((info: RowMouseEventHandlerParams) => void) | undefined;
254 /**
255 * Callback invoked when a user moves the mouse over a table row.
256 * ({ index: number }): void
257 */
258 onRowMouseOver?: ((info: RowMouseEventHandlerParams) => void) | undefined;
259 /**
260 * Callback invoked with information about the slice of rows that were just rendered.
261 * ({ startIndex, stopIndex }): void
262 */
263 onRowsRendered?: ((info: IndexRange & OverscanIndexRange) => void) | undefined;
264 /**
265 * Callback invoked whenever the scroll offset changes within the inner scrollable region.
266 * This callback can be used to sync scrolling between lists, tables, or grids.
267 * ({ clientHeight, scrollHeight, scrollTop }): void
268 */
269 onScroll?: ((info: ScrollEventData) => void) | undefined;
270 /**
271 * Number of rows to render above/below the visible bounds of the list.
272 * These rows can help for smoother scrolling on touch devices.
273 */
274 overscanRowCount?: number | undefined;
275 /**
276 * Optional CSS class to apply to all table rows (including the header row).
277 * This property can be a CSS class name (string) or a function that returns a class name.
278 * If a function is provided its signature should be: ({ index: number }): string
279 */
280 rowClassName?: string | ((info: Index) => string) | undefined;
281 /**
282 * Callback responsible for returning a data row given an index.
283 * ({ index: number }): any
284 */
285 rowGetter?: ((info: Index) => any) | undefined;
286 /**
287 * Either a fixed row height (number) or a function that returns the height of a row given its index.
288 * ({ index: number }): number
289 */
290 rowHeight: number | ((info: Index) => number);
291 /** Number of rows in table. */
292 rowCount: number;
293 /**
294 * Responsible for rendering a table row given an array of columns:
295 * Should implement the following interface: ({
296 * className: string,
297 * columns: Array,
298 * index: number,
299 * isScrolling: boolean,
300 * onRowClick: ?Function,
301 * onRowDoubleClick: ?Function,
302 * onRowMouseOver: ?Function,
303 * onRowMouseOut: ?Function,
304 * rowData: any,
305 * style: any
306 * }): PropTypes.node
307 */
308 rowRenderer?: TableRowRenderer | undefined;
309 /** Optional custom inline style to attach to table rows. */
310 rowStyle?: React.CSSProperties | ((info: Index) => React.CSSProperties) | undefined;
311 /** See Grid#scrollToAlignment */
312 scrollToAlignment?: string | undefined;
313 /** Row index to ensure visible (by forcefully scrolling if necessary) */
314 scrollToIndex?: number | undefined;
315 /** Vertical offset. */
316 scrollTop?: number | undefined;
317 /**
318 * Sort function to be called if a sortable header is clicked.
319 * ({ sortBy: string, sortDirection: SortDirection }): void
320 */
321 sort?: ((info: { sortBy: string; sortDirection: SortDirectionType }) => void) | undefined;
322 /** Table data is currently sorted by this :dataKey (if it is sorted at all) */
323 sortBy?: string | undefined;
324 /** Table data is currently sorted in this direction (if it is sorted at all) */
325 sortDirection?: SortDirectionType | undefined;
326 /** Optional inline style */
327 style?: React.CSSProperties | undefined;
328 /** Tab index for focus */
329 tabIndex?: number | null | undefined;
330 /** Width of list */
331 width?: number | undefined;
332};
333
334export const defaultCellDataGetter: TableCellDataGetter;
335export const defaultCellRenderer: TableCellRenderer;
336export const defaultHeaderRenderer: () => Array<React.ReactElement<TableHeaderProps>>;
337export const defaultHeaderRowRenderer: TableHeaderRowRenderer;
338export const defaultRowRenderer: TableRowRenderer;
339
340export type SortDirectionStatic = {
341 /**
342 * Sort items in ascending order.
343 * This means arranging from the lowest value to the highest (e.g. a-z, 0-9).
344 */
345 ASC: "ASC";
346
347 /**
348 * Sort items in descending order.
349 * This means arranging from the highest value to the lowest (e.g. z-a, 9-0).
350 */
351 DESC: "DESC";
352};
353
354export const SortDirection: SortDirectionStatic;
355
356export type SortDirectionType = "ASC" | "DESC";
357
358export const SortIndicator: React.FunctionComponent<{
359 sortDirection?: SortDirectionType | undefined;
360}>;
361
362/**
363 * Table component with fixed headers and virtualized rows for improved performance with large data sets.
364 * This component expects explicit width, height, and padding parameters.
365 */
366export class Table extends PureComponent<TableProps> {
367 static propTypes: {
368 "aria-label": PropTypes.Requireable<string>;
369 autoHeight: PropTypes.Requireable<boolean>;
370 children: PropTypes.Validator<Column>;
371 className: PropTypes.Requireable<string>;
372 disableHeader: PropTypes.Requireable<boolean>;
373 estimatedRowSize: PropTypes.Validator<number>;
374 gridClassName: PropTypes.Requireable<string>;
375 gridStyle: PropTypes.Requireable<React.CSSProperties>;
376 headerClassName: PropTypes.Requireable<string>;
377 headerHeight: PropTypes.Validator<number>;
378 headerRowRenderer: PropTypes.Requireable<TableHeaderRowRenderer>;
379 headerStyle: PropTypes.Requireable<React.CSSProperties>;
380 height: PropTypes.Validator<number>;
381 id: PropTypes.Requireable<string>;
382 noRowsRenderer: PropTypes.Requireable<() => JSX.Element>;
383 onHeaderClick: PropTypes.Requireable<(params: HeaderMouseEventHandlerParams) => void>;
384 onRowClick: PropTypes.Requireable<(params: RowMouseEventHandlerParams) => void>;
385 onRowDoubleClick: PropTypes.Requireable<(params: RowMouseEventHandlerParams) => void>;
386 onRowMouseOut: PropTypes.Requireable<(params: RowMouseEventHandlerParams) => void>;
387 onRowMouseOver: PropTypes.Requireable<(params: RowMouseEventHandlerParams) => void>;
388 onRowsRendered: PropTypes.Requireable<(params: IndexRange & OverscanIndexRange) => void>;
389 onScroll: PropTypes.Requireable<(params: ScrollEventData) => void>;
390 overscanRowCount: PropTypes.Validator<number>;
391 rowClassName: PropTypes.Requireable<string | ((params: Index) => string)>;
392 rowGetter: PropTypes.Validator<(params: Index) => any>;
393 rowHeight: PropTypes.Validator<number | ((params: Index) => number)>;
394 rowCount: PropTypes.Validator<number>;
395 rowRenderer: PropTypes.Requireable<(props: TableRowProps) => React.ReactNode>;
396 rowStyle: PropTypes.Validator<React.CSSProperties | ((params: Index) => React.CSSProperties)>;
397 scrollToAlignment: PropTypes.Validator<Alignment>;
398 scrollToIndex: PropTypes.Validator<number>;
399 scrollTop: PropTypes.Requireable<number>;
400 sort: PropTypes.Requireable<(params: { sortBy: string; sortDirection: SortDirectionType }) => void>;
401 sortBy: PropTypes.Requireable<string>;
402 sortDirection: PropTypes.Validator<SortDirectionType>;
403 style: PropTypes.Requireable<React.CSSProperties>;
404 tabIndex: PropTypes.Requireable<number>;
405 width: PropTypes.Validator<number>;
406 };
407
408 static defaultProps: {
409 disableHeader: false;
410 estimatedRowSize: 30;
411 headerHeight: 0;
412 headerStyle: {};
413 noRowsRenderer: () => null;
414 onRowsRendered: () => null;
415 onScroll: () => null;
416 overscanRowCount: 10;
417 rowRenderer: TableRowRenderer;
418 headerRowRenderer: TableHeaderRowRenderer;
419 rowStyle: {};
420 scrollToAlignment: "auto";
421 scrollToIndex: -1;
422 style: {};
423 };
424
425 Grid: Grid;
426
427 forceUpdateGrid(): void;
428
429 getScrollbarWidth(): number;
430
431 /** See Grid#getOffsetForCell */
432 getOffsetForRow(params: { alignment?: Alignment | undefined; index?: number | undefined }): number;
433
434 /** See Grid#scrollToPosition */
435 scrollToPosition(scrollTop?: number): void;
436
437 /** See Grid#measureAllCells */
438 measureAllRows(): void;
439
440 /** See Grid#recomputeGridSize */
441 recomputeRowHeights(index?: number): void;
442
443 /** See Grid#scrollToCell */
444 scrollToRow(index?: number): void;
445}
446
447export default Table;