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