1 | import { Component, PureComponent, Requireable, Validator } from "react";
|
2 | import { Alignment, Index, Map, OverscanIndexRange } from "../../index";
|
3 | import { CellMeasurerCache, CellMeasurerCacheInterface, MeasuredCellParent } from "./CellMeasurer";
|
4 | import { List } from "./List";
|
5 | import { Table } from "./Table";
|
6 |
|
7 | export type RenderedSection = {
|
8 | columnOverscanStartIndex: number;
|
9 | columnOverscanStopIndex: number;
|
10 | columnStartIndex: number;
|
11 | columnStopIndex: number;
|
12 | rowOverscanStartIndex: number;
|
13 | rowOverscanStopIndex: number;
|
14 | rowStartIndex: number;
|
15 | rowStopIndex: number;
|
16 | };
|
17 |
|
18 | export type GridCellProps = {
|
19 | columnIndex: number;
|
20 | isScrolling: boolean;
|
21 | isVisible: boolean;
|
22 | key: string;
|
23 | parent: React.Component<GridCoreProps> & MeasuredCellParent;
|
24 | rowIndex: number;
|
25 | style: React.CSSProperties;
|
26 | };
|
27 | export type GridCellRenderer = (props: GridCellProps) => React.ReactNode;
|
28 |
|
29 | export type ConfigureParams = {
|
30 | cellCount: number;
|
31 | estimatedCellSize: number;
|
32 | };
|
33 | export type ContainerSizeAndOffset = {
|
34 | containerSize: number;
|
35 | offset: number;
|
36 | };
|
37 | export type SizeAndPositionData = {
|
38 | offset: number;
|
39 | size: number;
|
40 | };
|
41 | export type GetVisibleCellRangeParams = {
|
42 | containerSize: number;
|
43 | offset: number;
|
44 | };
|
45 | export type VisibleCellRange = {
|
46 | start: number;
|
47 | stop: number;
|
48 | };
|
49 | export type ScrollParams = {
|
50 | clientHeight: number;
|
51 | clientWidth: number;
|
52 | scrollHeight: number;
|
53 | scrollLeft: number;
|
54 | scrollTop: number;
|
55 | scrollWidth: number;
|
56 | };
|
57 | export type ScrollbarPresenceParams = {
|
58 | horizontal: boolean;
|
59 | size: number;
|
60 | vertical: boolean;
|
61 | };
|
62 | export type SectionRenderedParams = RenderedSection;
|
63 | export type SCROLL_DIRECTION_HORIZONTAL = "horizontal";
|
64 | export type SCROLL_DIRECTION_VERTICAL = "vertical";
|
65 | export type SCROLL_DIRECTION_BACKWARD = -1;
|
66 | export type SCROLL_DIRECTION_FORWARD = 1;
|
67 | export type OverscanIndicesGetterParams = {
|
68 | direction?: SCROLL_DIRECTION_HORIZONTAL | SCROLL_DIRECTION_VERTICAL | undefined;
|
69 | cellCount: number;
|
70 | overscanCellsCount: number;
|
71 | scrollDirection: SCROLL_DIRECTION_BACKWARD | SCROLL_DIRECTION_FORWARD;
|
72 | startIndex: number;
|
73 | stopIndex: number;
|
74 | };
|
75 |
|
76 | export type OverscanIndices = OverscanIndexRange;
|
77 |
|
78 | export type OverscanIndicesGetter = (params: OverscanIndicesGetterParams) => OverscanIndices;
|
79 |
|
80 | export type ScrollOffset = {
|
81 | scrollLeft: number;
|
82 | scrollTop: number;
|
83 | };
|
84 |
|
85 | export type CellSizeAndPositionManager = {
|
86 | areOffsetsAdjusted(): boolean;
|
87 | configure({ cellCount, estimatedCellSize }: ConfigureParams): void;
|
88 | getCellCount(): number;
|
89 | getEstimatedCellSize(): number;
|
90 | getLastMeasuredIndex(): number;
|
91 | getOffsetAdjustment({ containerSize, offset }: ContainerSizeAndOffset): number;
|
92 | |
93 |
|
94 |
|
95 |
|
96 | getSizeAndPositionOfCell(index: number): SizeAndPositionData;
|
97 | getSizeAndPositionOfLastMeasuredCell(): SizeAndPositionData;
|
98 | |
99 |
|
100 |
|
101 |
|
102 |
|
103 | getTotalSize(): number;
|
104 | |
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | getUpdatedOffsetForIndex(params: {
|
116 | align: string;
|
117 | containerSize: number;
|
118 | currentOffset: number;
|
119 | targetIndex: number;
|
120 | }): number;
|
121 | getVisibleCellRange(params: GetVisibleCellRangeParams): VisibleCellRange;
|
122 | |
123 |
|
124 |
|
125 |
|
126 |
|
127 | resetCell(index: number): void;
|
128 | };
|
129 |
|
130 | export type GridCellRangeProps = {
|
131 | cellCache: Map<any>;
|
132 | cellRenderer: GridCellRenderer;
|
133 | columnSizeAndPositionManager: CellSizeAndPositionManager;
|
134 | columnStartIndex: number;
|
135 | columnStopIndex: number;
|
136 | isScrolling: boolean;
|
137 | isScrollingOptOut: boolean;
|
138 | rowSizeAndPositionManager: CellSizeAndPositionManager;
|
139 | rowStartIndex: number;
|
140 | rowStopIndex: number;
|
141 | scrollLeft: number;
|
142 | scrollTop: number;
|
143 | deferredMeasurementCache: CellMeasurerCache;
|
144 | horizontalOffsetAdjustment: number;
|
145 | parent: React.Component<GridCoreProps> & MeasuredCellParent;
|
146 | styleCache: Map<React.CSSProperties>;
|
147 | verticalOffsetAdjustment: number;
|
148 | visibleColumnIndices: VisibleCellRange;
|
149 | visibleRowIndices: VisibleCellRange;
|
150 | };
|
151 | export type GridCellRangeRenderer = (params: GridCellRangeProps) => React.ReactNode[];
|
152 |
|
153 | export type GridCoreProps = {
|
154 | "aria-label"?: string | undefined;
|
155 | "aria-readonly"?: boolean | undefined;
|
156 | |
157 |
|
158 |
|
159 |
|
160 | autoContainerWidth?: boolean | undefined;
|
161 | |
162 |
|
163 |
|
164 |
|
165 | autoHeight?: boolean | undefined;
|
166 | |
167 |
|
168 |
|
169 |
|
170 | autoWidth?: boolean | undefined;
|
171 | |
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 | cellRangeRenderer?: GridCellRangeRenderer | undefined;
|
188 | |
189 |
|
190 |
|
191 | className?: string | undefined;
|
192 |
|
193 | containerProps?: object | undefined;
|
194 |
|
195 | containerRole?: string | undefined;
|
196 |
|
197 | containerStyle?: React.CSSProperties | undefined;
|
198 | |
199 |
|
200 |
|
201 |
|
202 | deferredMeasurementCache?: CellMeasurerCacheInterface | undefined;
|
203 | |
204 |
|
205 |
|
206 |
|
207 | estimatedColumnSize?: number | undefined;
|
208 | |
209 |
|
210 |
|
211 |
|
212 | estimatedRowSize?: number | undefined;
|
213 | |
214 |
|
215 |
|
216 | getScrollbarSize?: (() => number) | undefined;
|
217 | /**
|
218 | * Height of Grid; this property determines the number of visible (vs virtualized) rows.
|
219 | */
|
220 | height: number;
|
221 | /**
|
222 | * Optional custom id to attach to root Grid element.
|
223 | */
|
224 | id?: string | undefined;
|
225 | /**
|
226 | * Override internal is-scrolling state tracking.
|
227 | * This property is primarily intended for use with the WindowScroller component.
|
228 | */
|
229 | isScrolling?: boolean | undefined;
|
230 | /**
|
231 | * Optional renderer to be used in place of rows when either :rowCount or :columnCount is 0.
|
232 | */
|
233 | noContentRenderer?: (() => React.ReactNode) | undefined;
|
234 | /**
|
235 | * Callback invoked whenever the scroll offset changes within the inner scrollable region.
|
236 | * This callback can be used to sync scrolling between lists, tables, or grids.
|
237 | * ({ clientHeight, clientWidth, scrollHeight, scrollLeft, scrollTop, scrollWidth }): void
|
238 | */
|
239 | onScroll?: ((params: ScrollParams) => any) | undefined;
|
240 | /**
|
241 | * Called whenever a horizontal or vertical scrollbar is added or removed.
|
242 | * ({ horizontal: boolean, size: number, vertical: boolean }): void
|
243 | */
|
244 | onScrollbarPresenceChange?: ((params: ScrollbarPresenceParams) => any) | undefined;
|
245 | /**
|
246 | * Callback invoked with information about the section of the Grid that was just rendered.
|
247 | * ({ columnStartIndex, columnStopIndex, rowStartIndex, rowStopIndex }): void
|
248 | */
|
249 | onSectionRendered?: ((params: SectionRenderedParams) => any) | undefined;
|
250 | /**
|
251 | * Number of columns to render before/after the visible section of the grid.
|
252 | * These columns can help for smoother scrolling on touch devices or browsers that send scroll events infrequently.
|
253 | */
|
254 | overscanColumnCount?: number | undefined;
|
255 | /**
|
256 | * Calculates the number of cells to overscan before and after a specified range.
|
257 | * This function ensures that overscanning doesn't exceed the available cells.
|
258 | * Should implement the following interface: ({
|
259 | * cellCount: number,
|
260 | * overscanCellsCount: number,
|
261 | * scrollDirection: number,
|
262 | * startIndex: number,
|
263 | * stopIndex: number
|
264 | * }): {overscanStartIndex: number, overscanStopIndex: number}
|
265 | */
|
266 | overscanIndicesGetter?: OverscanIndicesGetter | undefined;
|
267 | /**
|
268 | * Number of rows to render above/below the visible section of the grid.
|
269 | * These rows can help for smoother scrolling on touch devices or browsers that send scroll events infrequently.
|
270 | */
|
271 | overscanRowCount?: number | undefined;
|
272 | /**
|
273 | * ARIA role for the grid element.
|
274 | */
|
275 | role?: string | undefined;
|
276 | /**
|
277 | * Either a fixed row height (number) or a function that returns the height of a row given its index.
|
278 | * Should implement the following interface: ({ index: number }): number
|
279 | */
|
280 | rowHeight: number | ((params: Index) => number);
|
281 | /**
|
282 | * Number of rows in grid.
|
283 | */
|
284 | rowCount: number;
|
285 | /** Wait this amount of time after the last scroll event before resetting Grid `pointer-events`. */
|
286 | scrollingResetTimeInterval?: number | undefined;
|
287 | /** Horizontal offset. */
|
288 | scrollLeft?: number | undefined;
|
289 | /**
|
290 | * Controls scroll-to-cell behavior of the Grid.
|
291 | * The default ("auto") scrolls the least amount possible to ensure that the specified cell is fully visible.
|
292 | * Use "start" to align cells to the top/left of the Grid and "end" to align bottom/right.
|
293 | */
|
294 | scrollToAlignment?: Alignment | undefined;
|
295 | /**
|
296 | * Column index to ensure visible (by forcefully scrolling if necessary)
|
297 | */
|
298 | scrollToColumn?: number | undefined;
|
299 | /** Vertical offset. */
|
300 | scrollTop?: number | undefined;
|
301 | /**
|
302 | * Row index to ensure visible (by forcefully scrolling if necessary)
|
303 | */
|
304 | scrollToRow?: number | undefined;
|
305 | /** Optional inline style */
|
306 | style?: React.CSSProperties | undefined;
|
307 | /** Tab index for focus */
|
308 | tabIndex?: number | null | undefined;
|
309 | /**
|
310 | * Width of Grid; this property determines the number of visible (vs virtualized) columns.
|
311 | */
|
312 | width: number;
|
313 | /**
|
314 | * PLEASE NOTE
|
315 | * The [key: string]: any; line is here on purpose
|
316 | * This is due to the need of force re-render of PureComponent
|
317 | * Check the following link if you want to know more
|
318 | * https://github.com/bvaughn/react-virtualized#pass-thru-props
|
319 | */
|
320 | [key: string]: any;
|
321 | };
|
322 |
|
323 | export type GridProps = GridCoreProps & {
|
324 | /**
|
325 | * Responsible for rendering a cell given an row and column index.
|
326 | * Should implement the following interface: ({ columnIndex: number, rowIndex: number }): PropTypes.node
|
327 | */
|
328 | cellRenderer: GridCellRenderer;
|
329 | /**
|
330 | * Number of columns in grid.
|
331 | */
|
332 | columnCount: number;
|
333 | /**
|
334 | * Either a fixed column width (number) or a function that returns the width of a column given its index.
|
335 | * Should implement the following interface: (index: number): number
|
336 | */
|
337 | columnWidth: number | ((params: Index) => number);
|
338 | };
|
339 |
|
340 | export type ScrollDirection = "horizontal" | "vertical";
|
341 |
|
342 | export type GridState = {
|
343 | isScrolling: boolean;
|
344 | scrollDirectionHorizontal: ScrollDirection;
|
345 | scrollDirectionVertical: ScrollDirection;
|
346 | scrollLeft: number;
|
347 | scrollTop: number;
|
348 | };
|
349 |
|
350 | /**
|
351 | * Specifies the number of miliseconds during which to disable pointer events while a scroll is in progress.
|
352 | * This improves performance and makes scrolling smoother.
|
353 | */
|
354 | export const DEFAULT_SCROLLING_RESET_TIME_INTERVAL = 150;
|
355 |
|
356 | /**
|
357 | * Renders tabular data with virtualization along the vertical and horizontal axes.
|
358 | * Row heights and column widths must be known ahead of time and specified as properties.
|
359 | */
|
360 | export class Grid extends PureComponent<GridProps, GridState> {
|
361 | static defaultProps: {
|
362 | "aria-label": "grid";
|
363 | "aria-readonly": true;
|
364 | autoContainerWidth: false;
|
365 | autoHeight: false;
|
366 | autoWidth: false;
|
367 | cellRangeRenderer: GridCellRangeRenderer;
|
368 | containerRole: "rowgroup";
|
369 | containerStyle: {};
|
370 | estimatedColumnSize: 100;
|
371 | estimatedRowSize: 30;
|
372 | getScrollbarSize: () => number;
|
373 | noContentRenderer: () => React.ReactNode;
|
374 | onScroll: () => void;
|
375 | onScrollbarPresenceChange: () => void;
|
376 | onSectionRendered: () => void;
|
377 | overscanColumnCount: 0;
|
378 | overscanIndicesGetter: OverscanIndicesGetter;
|
379 | overscanRowCount: 10;
|
380 | role: "grid";
|
381 | scrollingResetTimeInterval: typeof DEFAULT_SCROLLING_RESET_TIME_INTERVAL;
|
382 | scrollToAlignment: "auto";
|
383 | scrollToColumn: -1;
|
384 | scrollToRow: -1;
|
385 | style: {};
|
386 | tabIndex: 0;
|
387 | };
|
388 |
|
389 | |
390 |
|
391 |
|
392 | getOffsetForCell(
|
393 | params?: { alignment?: Alignment | undefined; columnIndex?: number | undefined; rowIndex?: number | undefined },
|
394 | ): ScrollOffset;
|
395 |
|
396 | |
397 |
|
398 |
|
399 |
|
400 | handleScrollEvent(params: Partial<ScrollOffset>): void;
|
401 |
|
402 | |
403 |
|
404 |
|
405 |
|
406 |
|
407 |
|
408 |
|
409 | invalidateCellSizeAfterRender(params: { columnIndex: number; rowIndex: number }): void;
|
410 |
|
411 | |
412 |
|
413 |
|
414 |
|
415 |
|
416 | measureAllCells(): void;
|
417 |
|
418 | |
419 |
|
420 |
|
421 |
|
422 |
|
423 | recomputeGridSize(params?: { columnIndex?: number | undefined; rowIndex?: number | undefined }): void;
|
424 |
|
425 | |
426 |
|
427 |
|
428 | scrollToCell(params: { columnIndex: number; rowIndex: number }): void;
|
429 |
|
430 | |
431 |
|
432 |
|
433 |
|
434 | scrollToPosition(params?: { scrollLeft: number; scrollTop: number }): void;
|
435 | }
|
436 |
|
437 | export default Grid;
|
438 |
|
439 | export const defaultCellRangeRenderer: GridCellRangeRenderer;
|
440 |
|
441 | export const accessibilityOverscanIndicesGetter: OverscanIndicesGetter;
|
442 |
|
443 | export const defaultOverscanIndicesGetter: OverscanIndicesGetter;
|