react-window 1.8.10 → 2.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +9 -161
  2. package/dist/react-window.cjs +22 -0
  3. package/dist/react-window.d.ts +217 -0
  4. package/dist/react-window.js +812 -0
  5. package/docs/assets/index-DlGpNu0r.css +1 -0
  6. package/docs/assets/index-fVOw1dKb.js +67 -0
  7. package/docs/data/addresses.json +7954 -0
  8. package/docs/data/contacts.json +4202 -0
  9. package/docs/data/names.json +1002 -0
  10. package/docs/favicon.svg +16 -0
  11. package/docs/generated/README.md +1 -0
  12. package/docs/generated/code-snippets/CellComponent.json +4 -0
  13. package/docs/generated/code-snippets/FixedHeightList.json +4 -0
  14. package/docs/generated/code-snippets/FixedHeightRowComponent.json +4 -0
  15. package/docs/generated/code-snippets/FlexboxLayout.json +4 -0
  16. package/docs/generated/code-snippets/Grid.json +4 -0
  17. package/docs/generated/code-snippets/ListVariableRowHeights.json +4 -0
  18. package/docs/generated/code-snippets/columnWidth.json +4 -0
  19. package/docs/generated/code-snippets/gridRefClickEventHandler.json +3 -0
  20. package/docs/generated/code-snippets/listRefClickEventHandler.json +3 -0
  21. package/docs/generated/code-snippets/rowHeight.json +4 -0
  22. package/docs/generated/code-snippets/useGridRef.json +4 -0
  23. package/docs/generated/code-snippets/useGridRefImport.json +3 -0
  24. package/docs/generated/code-snippets/useListRef.json +4 -0
  25. package/docs/generated/code-snippets/useListRefImport.json +3 -0
  26. package/docs/generated/js-docs/Grid.json +314 -0
  27. package/docs/generated/js-docs/List.json +266 -0
  28. package/docs/index.html +30 -0
  29. package/docs/og.html +42 -0
  30. package/docs/og.png +0 -0
  31. package/docs/stats.html +4949 -0
  32. package/docs/svgs/checkbox-checked.svg +1 -0
  33. package/docs/svgs/checkbox-indeterminate.svg +1 -0
  34. package/docs/svgs/checkbox-unchecked.svg +1 -0
  35. package/docs/svgs/github.svg +3 -0
  36. package/docs/svgs/npm.svg +1 -0
  37. package/docs/svgs/radio-checked.svg +1 -0
  38. package/docs/svgs/radio-unchecked.svg +1 -0
  39. package/package.json +70 -90
  40. package/LICENSE.md +0 -21
  41. package/dist/index-dev.umd.js +0 -2
  42. package/dist/index-dev.umd.js.map +0 -1
  43. package/dist/index-prod.umd.js +0 -2
  44. package/dist/index-prod.umd.js.map +0 -1
  45. package/dist/index.cjs.js +0 -2087
  46. package/dist/index.cjs.js.flow +0 -3
  47. package/dist/index.cjs.js.map +0 -1
  48. package/dist/index.esm.js +0 -2076
  49. package/dist/index.esm.js.flow +0 -3
  50. package/dist/index.esm.js.map +0 -1
  51. package/src/FixedSizeGrid.js +0 -244
  52. package/src/FixedSizeList.js +0 -137
  53. package/src/VariableSizeGrid.js +0 -507
  54. package/src/VariableSizeList.js +0 -317
  55. package/src/areEqual.js +0 -18
  56. package/src/createGridComponent.js +0 -919
  57. package/src/createListComponent.js +0 -745
  58. package/src/domHelpers.js +0 -72
  59. package/src/index.js +0 -9
  60. package/src/shallowDiffers.js +0 -17
  61. package/src/shouldComponentUpdate.js +0 -16
  62. package/src/timer.js +0 -37
@@ -1,317 +0,0 @@
1
- // @flow
2
-
3
- import createListComponent from './createListComponent';
4
-
5
- import type { Props, ScrollToAlign } from './createListComponent';
6
-
7
- const DEFAULT_ESTIMATED_ITEM_SIZE = 50;
8
-
9
- type VariableSizeProps = {|
10
- estimatedItemSize: number,
11
- ...Props<any>,
12
- |};
13
-
14
- type itemSizeGetter = (index: number) => number;
15
-
16
- type ItemMetadata = {|
17
- offset: number,
18
- size: number,
19
- |};
20
- type InstanceProps = {|
21
- itemMetadataMap: { [index: number]: ItemMetadata },
22
- estimatedItemSize: number,
23
- lastMeasuredIndex: number,
24
- |};
25
-
26
- const getItemMetadata = (
27
- props: Props<any>,
28
- index: number,
29
- instanceProps: InstanceProps
30
- ): ItemMetadata => {
31
- const { itemSize } = ((props: any): VariableSizeProps);
32
- const { itemMetadataMap, lastMeasuredIndex } = instanceProps;
33
-
34
- if (index > lastMeasuredIndex) {
35
- let offset = 0;
36
- if (lastMeasuredIndex >= 0) {
37
- const itemMetadata = itemMetadataMap[lastMeasuredIndex];
38
- offset = itemMetadata.offset + itemMetadata.size;
39
- }
40
-
41
- for (let i = lastMeasuredIndex + 1; i <= index; i++) {
42
- let size = ((itemSize: any): itemSizeGetter)(i);
43
-
44
- itemMetadataMap[i] = {
45
- offset,
46
- size,
47
- };
48
-
49
- offset += size;
50
- }
51
-
52
- instanceProps.lastMeasuredIndex = index;
53
- }
54
-
55
- return itemMetadataMap[index];
56
- };
57
-
58
- const findNearestItem = (
59
- props: Props<any>,
60
- instanceProps: InstanceProps,
61
- offset: number
62
- ) => {
63
- const { itemMetadataMap, lastMeasuredIndex } = instanceProps;
64
-
65
- const lastMeasuredItemOffset =
66
- lastMeasuredIndex > 0 ? itemMetadataMap[lastMeasuredIndex].offset : 0;
67
-
68
- if (lastMeasuredItemOffset >= offset) {
69
- // If we've already measured items within this range just use a binary search as it's faster.
70
- return findNearestItemBinarySearch(
71
- props,
72
- instanceProps,
73
- lastMeasuredIndex,
74
- 0,
75
- offset
76
- );
77
- } else {
78
- // If we haven't yet measured this high, fallback to an exponential search with an inner binary search.
79
- // The exponential search avoids pre-computing sizes for the full set of items as a binary search would.
80
- // The overall complexity for this approach is O(log n).
81
- return findNearestItemExponentialSearch(
82
- props,
83
- instanceProps,
84
- Math.max(0, lastMeasuredIndex),
85
- offset
86
- );
87
- }
88
- };
89
-
90
- const findNearestItemBinarySearch = (
91
- props: Props<any>,
92
- instanceProps: InstanceProps,
93
- high: number,
94
- low: number,
95
- offset: number
96
- ): number => {
97
- while (low <= high) {
98
- const middle = low + Math.floor((high - low) / 2);
99
- const currentOffset = getItemMetadata(props, middle, instanceProps).offset;
100
-
101
- if (currentOffset === offset) {
102
- return middle;
103
- } else if (currentOffset < offset) {
104
- low = middle + 1;
105
- } else if (currentOffset > offset) {
106
- high = middle - 1;
107
- }
108
- }
109
-
110
- if (low > 0) {
111
- return low - 1;
112
- } else {
113
- return 0;
114
- }
115
- };
116
-
117
- const findNearestItemExponentialSearch = (
118
- props: Props<any>,
119
- instanceProps: InstanceProps,
120
- index: number,
121
- offset: number
122
- ): number => {
123
- const { itemCount } = props;
124
- let interval = 1;
125
-
126
- while (
127
- index < itemCount &&
128
- getItemMetadata(props, index, instanceProps).offset < offset
129
- ) {
130
- index += interval;
131
- interval *= 2;
132
- }
133
-
134
- return findNearestItemBinarySearch(
135
- props,
136
- instanceProps,
137
- Math.min(index, itemCount - 1),
138
- Math.floor(index / 2),
139
- offset
140
- );
141
- };
142
-
143
- const getEstimatedTotalSize = (
144
- { itemCount }: Props<any>,
145
- { itemMetadataMap, estimatedItemSize, lastMeasuredIndex }: InstanceProps
146
- ) => {
147
- let totalSizeOfMeasuredItems = 0;
148
-
149
- // Edge case check for when the number of items decreases while a scroll is in progress.
150
- // https://github.com/bvaughn/react-window/pull/138
151
- if (lastMeasuredIndex >= itemCount) {
152
- lastMeasuredIndex = itemCount - 1;
153
- }
154
-
155
- if (lastMeasuredIndex >= 0) {
156
- const itemMetadata = itemMetadataMap[lastMeasuredIndex];
157
- totalSizeOfMeasuredItems = itemMetadata.offset + itemMetadata.size;
158
- }
159
-
160
- const numUnmeasuredItems = itemCount - lastMeasuredIndex - 1;
161
- const totalSizeOfUnmeasuredItems = numUnmeasuredItems * estimatedItemSize;
162
-
163
- return totalSizeOfMeasuredItems + totalSizeOfUnmeasuredItems;
164
- };
165
-
166
- const VariableSizeList = createListComponent({
167
- getItemOffset: (
168
- props: Props<any>,
169
- index: number,
170
- instanceProps: InstanceProps
171
- ): number => getItemMetadata(props, index, instanceProps).offset,
172
-
173
- getItemSize: (
174
- props: Props<any>,
175
- index: number,
176
- instanceProps: InstanceProps
177
- ): number => instanceProps.itemMetadataMap[index].size,
178
-
179
- getEstimatedTotalSize,
180
-
181
- getOffsetForIndexAndAlignment: (
182
- props: Props<any>,
183
- index: number,
184
- align: ScrollToAlign,
185
- scrollOffset: number,
186
- instanceProps: InstanceProps,
187
- scrollbarSize: number
188
- ): number => {
189
- const { direction, height, layout, width } = props;
190
-
191
- // TODO Deprecate direction "horizontal"
192
- const isHorizontal = direction === 'horizontal' || layout === 'horizontal';
193
- const size = (((isHorizontal ? width : height): any): number);
194
- const itemMetadata = getItemMetadata(props, index, instanceProps);
195
-
196
- // Get estimated total size after ItemMetadata is computed,
197
- // To ensure it reflects actual measurements instead of just estimates.
198
- const estimatedTotalSize = getEstimatedTotalSize(props, instanceProps);
199
-
200
- const maxOffset = Math.max(
201
- 0,
202
- Math.min(estimatedTotalSize - size, itemMetadata.offset)
203
- );
204
- const minOffset = Math.max(
205
- 0,
206
- itemMetadata.offset - size + itemMetadata.size + scrollbarSize
207
- );
208
-
209
- if (align === 'smart') {
210
- if (
211
- scrollOffset >= minOffset - size &&
212
- scrollOffset <= maxOffset + size
213
- ) {
214
- align = 'auto';
215
- } else {
216
- align = 'center';
217
- }
218
- }
219
-
220
- switch (align) {
221
- case 'start':
222
- return maxOffset;
223
- case 'end':
224
- return minOffset;
225
- case 'center':
226
- return Math.round(minOffset + (maxOffset - minOffset) / 2);
227
- case 'auto':
228
- default:
229
- if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
230
- return scrollOffset;
231
- } else if (scrollOffset < minOffset) {
232
- return minOffset;
233
- } else {
234
- return maxOffset;
235
- }
236
- }
237
- },
238
-
239
- getStartIndexForOffset: (
240
- props: Props<any>,
241
- offset: number,
242
- instanceProps: InstanceProps
243
- ): number => findNearestItem(props, instanceProps, offset),
244
-
245
- getStopIndexForStartIndex: (
246
- props: Props<any>,
247
- startIndex: number,
248
- scrollOffset: number,
249
- instanceProps: InstanceProps
250
- ): number => {
251
- const { direction, height, itemCount, layout, width } = props;
252
-
253
- // TODO Deprecate direction "horizontal"
254
- const isHorizontal = direction === 'horizontal' || layout === 'horizontal';
255
- const size = (((isHorizontal ? width : height): any): number);
256
- const itemMetadata = getItemMetadata(props, startIndex, instanceProps);
257
- const maxOffset = scrollOffset + size;
258
-
259
- let offset = itemMetadata.offset + itemMetadata.size;
260
- let stopIndex = startIndex;
261
-
262
- while (stopIndex < itemCount - 1 && offset < maxOffset) {
263
- stopIndex++;
264
- offset += getItemMetadata(props, stopIndex, instanceProps).size;
265
- }
266
-
267
- return stopIndex;
268
- },
269
-
270
- initInstanceProps(props: Props<any>, instance: any): InstanceProps {
271
- const { estimatedItemSize } = ((props: any): VariableSizeProps);
272
-
273
- const instanceProps = {
274
- itemMetadataMap: {},
275
- estimatedItemSize: estimatedItemSize || DEFAULT_ESTIMATED_ITEM_SIZE,
276
- lastMeasuredIndex: -1,
277
- };
278
-
279
- instance.resetAfterIndex = (
280
- index: number,
281
- shouldForceUpdate?: boolean = true
282
- ) => {
283
- instanceProps.lastMeasuredIndex = Math.min(
284
- instanceProps.lastMeasuredIndex,
285
- index - 1
286
- );
287
-
288
- // We could potentially optimize further by only evicting styles after this index,
289
- // But since styles are only cached while scrolling is in progress-
290
- // It seems an unnecessary optimization.
291
- // It's unlikely that resetAfterIndex() will be called while a user is scrolling.
292
- instance._getItemStyleCache(-1);
293
-
294
- if (shouldForceUpdate) {
295
- instance.forceUpdate();
296
- }
297
- };
298
-
299
- return instanceProps;
300
- },
301
-
302
- shouldResetStyleCacheOnItemSizeChange: false,
303
-
304
- validateProps: ({ itemSize }: Props<any>): void => {
305
- if (process.env.NODE_ENV !== 'production') {
306
- if (typeof itemSize !== 'function') {
307
- throw Error(
308
- 'An invalid "itemSize" prop has been specified. ' +
309
- 'Value should be a function. ' +
310
- `"${itemSize === null ? 'null' : typeof itemSize}" was specified.`
311
- );
312
- }
313
- }
314
- },
315
- });
316
-
317
- export default VariableSizeList;
package/src/areEqual.js DELETED
@@ -1,18 +0,0 @@
1
- // @flow
2
-
3
- import shallowDiffers from './shallowDiffers';
4
-
5
- // Custom comparison function for React.memo().
6
- // It knows to compare individual style props and ignore the wrapper object.
7
- // See https://reactjs.org/docs/react-api.html#reactmemo
8
- export default function areEqual(
9
- prevProps: Object,
10
- nextProps: Object
11
- ): boolean {
12
- const { style: prevStyle, ...prevRest } = prevProps;
13
- const { style: nextStyle, ...nextRest } = nextProps;
14
-
15
- return (
16
- !shallowDiffers(prevStyle, nextStyle) && !shallowDiffers(prevRest, nextRest)
17
- );
18
- }