UNPKG

5.12 kBTypeScriptView Raw
1import { PureComponent } from "react";
2import { IndexRange } from "../../index";
3import { CellMeasurerCacheInterface, KeyMapper, MeasuredCellParent } from "./CellMeasurer";
4/**
5 * Specifies the number of miliseconds during which to disable pointer events while a scroll is in progress.
6 * This improves performance and makes scrolling smoother.
7 */
8export const DEFAULT_SCROLLING_RESET_TIME_INTERVAL = 150;
9
10export type OnCellsRenderedCallback = (params: IndexRange) => void;
11
12export type OnScrollCallback = (params: { clientHeight: number; scrollHeight: number; scrollTop: number }) => void;
13
14export type MasonryCellProps = {
15 index: number;
16 isScrolling: boolean;
17 key: React.Key;
18 parent: MeasuredCellParent;
19 style?: React.CSSProperties | undefined;
20};
21
22export type CellRenderer = (props: MasonryCellProps) => React.ReactNode;
23
24export type MasonryProps = {
25 autoHeight: boolean;
26 cellCount: number;
27 cellMeasurerCache: CellMeasurerCacheInterface;
28 cellPositioner: Positioner;
29 cellRenderer: CellRenderer;
30 className?: string | undefined;
31 height: number;
32 id?: string | undefined;
33 keyMapper?: KeyMapper | undefined;
34 onCellsRendered?: OnCellsRenderedCallback | undefined;
35 onScroll?: OnScrollCallback | undefined;
36 overscanByPixels?: number | undefined;
37 role?: string | undefined;
38 scrollingResetTimeInterval?: number | undefined;
39 style?: React.CSSProperties | undefined;
40 tabIndex?: number | null | undefined;
41 width: number;
42 /**
43 * PLEASE NOTE
44 * The [key: string]: any; line is here on purpose
45 * This is due to the need of force re-render of PureComponent
46 * Check the following link if you want to know more
47 * https://github.com/bvaughn/react-virtualized#pass-thru-props
48 */
49 [key: string]: any;
50};
51
52export type MasonryState = {
53 isScrolling: boolean;
54 scrollTop: number;
55};
56
57/**
58 * This component efficiently displays arbitrarily positioned cells using windowing techniques.
59 * Cell position is determined by an injected `cellPositioner` property.
60 * Windowing is vertical; this component does not support horizontal scrolling.
61 *
62 * Rendering occurs in two phases:
63 * 1) First pass uses estimated cell sizes (provided by the cache) to determine how many cells to measure in a batch.
64 * Batch size is chosen using a fast, naive layout algorithm that stacks images in order until the viewport has been filled.
65 * After measurement is complete (componentDidMount or componentDidUpdate) this component evaluates positioned cells
66 * in order to determine if another measurement pass is required (eg if actual cell sizes were less than estimated sizes).
67 * All measurements are permanently cached (keyed by `keyMapper`) for performance purposes.
68 * 2) Second pass uses the external `cellPositioner` to layout cells.
69 * At this time the positioner has access to cached size measurements for all cells.
70 * The positions it returns are cached by Masonry for fast access later.
71 * Phase one is repeated if the user scrolls beyond the current layout's bounds.
72 * If the layout is invalidated due to eg a resize, cached positions can be cleared using `recomputeCellPositions()`.
73 *
74 * Animation constraints:
75 * Simple animations are supported (eg translate/slide into place on initial reveal).
76 * More complex animations are not (eg flying from one position to another on resize).
77 *
78 * Layout constraints:
79 * This component supports multi-column layout.
80 * The height of each item may vary.
81 * The width of each item must not exceed the width of the column it is "in".
82 * The left position of all items within a column must align.
83 * (Items may not span multiple columns.)
84 */
85export class Masonry extends PureComponent<MasonryProps, MasonryState> {
86 static defaultProps: {
87 autoHeight: false;
88 keyMapper: identity;
89 onCellsRendered: noop;
90 onScroll: noop;
91 overscanByPixels: 20;
92 role: "grid";
93 scrollingResetTimeInterval: typeof DEFAULT_SCROLLING_RESET_TIME_INTERVAL;
94 style: emptyObject;
95 tabIndex: 0;
96 };
97
98 clearCellPositions(): void;
99
100 // HACK This method signature was intended for Grid
101 invalidateCellSizeAfterRender(params: { rowIndex: number }): void;
102
103 recomputeCellPositions(): void;
104
105 static getDerivedStateFromProps(nextProps: MasonryProps, prevState: MasonryState): MasonryState | null;
106}
107
108export default Masonry;
109
110export type emptyObject = {};
111
112export type identity = <T>(value: T) => T;
113
114export type noop = () => void;
115
116export type Position = {
117 left: number;
118 top: number;
119};
120
121export type createCellPositionerParams = {
122 cellMeasurerCache: CellMeasurerCacheInterface;
123 columnCount: number;
124 columnWidth: number;
125 spacer?: number | undefined;
126};
127
128export type resetParams = {
129 columnCount: number;
130 columnWidth: number;
131 spacer?: number | undefined;
132};
133
134export type Positioner = ((index: number) => Position) & {
135 reset: (params: resetParams) => void;
136};
137
138export const createCellPositioner: (params: createCellPositionerParams) => Positioner;