virtual-scroller 1.11.2 → 1.12.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.
- package/CHANGELOG.md +5 -0
- package/README.md +13 -11
- package/bundle/virtual-scroller-dom.js +1 -1
- package/bundle/virtual-scroller-dom.js.map +1 -1
- package/bundle/virtual-scroller-react.js +1 -1
- package/bundle/virtual-scroller-react.js.map +1 -1
- package/bundle/virtual-scroller.js +1 -1
- package/bundle/virtual-scroller.js.map +1 -1
- package/commonjs/DOM/ItemsContainer.js +10 -3
- package/commonjs/DOM/ItemsContainer.js.map +1 -1
- package/commonjs/DOM/VirtualScroller.js +13 -1
- package/commonjs/DOM/VirtualScroller.js.map +1 -1
- package/commonjs/ItemHeights.js +5 -5
- package/commonjs/ItemHeights.js.map +1 -1
- package/commonjs/ItemNotRenderedError.js +64 -0
- package/commonjs/ItemNotRenderedError.js.map +1 -0
- package/commonjs/Layout.test.js +10 -0
- package/commonjs/Layout.test.js.map +1 -1
- package/commonjs/VirtualScroller.js +23 -5
- package/commonjs/VirtualScroller.js.map +1 -1
- package/commonjs/VirtualScroller.layout.js +81 -39
- package/commonjs/VirtualScroller.layout.js.map +1 -1
- package/commonjs/VirtualScroller.onRender.js +97 -45
- package/commonjs/VirtualScroller.onRender.js.map +1 -1
- package/commonjs/VirtualScroller.state.js +50 -18
- package/commonjs/VirtualScroller.state.js.map +1 -1
- package/commonjs/react/VirtualScroller.js +31 -46
- package/commonjs/react/VirtualScroller.js.map +1 -1
- package/commonjs/react/useItemKeys.js +11 -3
- package/commonjs/react/useItemKeys.js.map +1 -1
- package/commonjs/react/useOnChange.js +19 -0
- package/commonjs/react/useOnChange.js.map +1 -0
- package/commonjs/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +7 -7
- package/commonjs/react/useOnItemHeightDidChange.js.map +1 -0
- package/commonjs/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +15 -14
- package/commonjs/react/useSetNewItemsOnItemsPropertyChange.js.map +1 -0
- package/commonjs/react/useState.js +162 -69
- package/commonjs/react/useState.js.map +1 -1
- package/commonjs/react/useStyle.js +3 -5
- package/commonjs/react/useStyle.js.map +1 -1
- package/commonjs/react/useUpdateItemKeysOnItemsChange.js +61 -0
- package/commonjs/react/useUpdateItemKeysOnItemsChange.js.map +1 -0
- package/commonjs/test/ItemsContainer.js +22 -1
- package/commonjs/test/ItemsContainer.js.map +1 -1
- package/commonjs/utility/debug.js +30 -6
- package/commonjs/utility/debug.js.map +1 -1
- package/dom/index.d.ts +1 -1
- package/index.cjs +2 -0
- package/index.d.ts +7 -1
- package/index.js +1 -0
- package/modules/DOM/ItemsContainer.js +8 -3
- package/modules/DOM/ItemsContainer.js.map +1 -1
- package/modules/DOM/VirtualScroller.js +13 -1
- package/modules/DOM/VirtualScroller.js.map +1 -1
- package/modules/ItemHeights.js +5 -5
- package/modules/ItemHeights.js.map +1 -1
- package/modules/ItemNotRenderedError.js +57 -0
- package/modules/ItemNotRenderedError.js.map +1 -0
- package/modules/Layout.test.js +10 -0
- package/modules/Layout.test.js.map +1 -1
- package/modules/VirtualScroller.js +17 -5
- package/modules/VirtualScroller.js.map +1 -1
- package/modules/VirtualScroller.layout.js +78 -39
- package/modules/VirtualScroller.layout.js.map +1 -1
- package/modules/VirtualScroller.onRender.js +98 -46
- package/modules/VirtualScroller.onRender.js.map +1 -1
- package/modules/VirtualScroller.state.js +50 -18
- package/modules/VirtualScroller.state.js.map +1 -1
- package/modules/react/VirtualScroller.js +31 -46
- package/modules/react/VirtualScroller.js.map +1 -1
- package/modules/react/useItemKeys.js +8 -3
- package/modules/react/useItemKeys.js.map +1 -1
- package/modules/react/useOnChange.js +11 -0
- package/modules/react/useOnChange.js.map +1 -0
- package/modules/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +6 -6
- package/modules/react/useOnItemHeightDidChange.js.map +1 -0
- package/modules/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +11 -13
- package/modules/react/useSetNewItemsOnItemsPropertyChange.js.map +1 -0
- package/modules/react/useState.js +156 -73
- package/modules/react/useState.js.map +1 -1
- package/modules/react/useStyle.js +3 -5
- package/modules/react/useStyle.js.map +1 -1
- package/{commonjs/react/useHandleItemIndexesChange.js → modules/react/useUpdateItemKeysOnItemsChange.js} +18 -21
- package/modules/react/useUpdateItemKeysOnItemsChange.js.map +1 -0
- package/modules/test/ItemsContainer.js +20 -1
- package/modules/test/ItemsContainer.js.map +1 -1
- package/modules/utility/debug.js +31 -6
- package/modules/utility/debug.js.map +1 -1
- package/package.json +1 -1
- package/source/DOM/ItemsContainer.js +8 -3
- package/source/DOM/VirtualScroller.js +11 -1
- package/source/ItemHeights.js +5 -5
- package/source/ItemNotRenderedError.js +16 -0
- package/source/Layout.test.js +9 -0
- package/source/VirtualScroller.js +14 -3
- package/source/VirtualScroller.layout.js +77 -38
- package/source/VirtualScroller.onRender.js +95 -42
- package/source/VirtualScroller.state.js +57 -20
- package/source/react/VirtualScroller.js +28 -39
- package/source/react/useItemKeys.js +9 -2
- package/source/react/useOnChange.js +11 -0
- package/source/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +5 -5
- package/source/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +11 -11
- package/source/react/useState.js +159 -71
- package/source/react/useStyle.js +2 -2
- package/source/react/{useHandleItemIndexesChange.js → useUpdateItemKeysOnItemsChange.js} +17 -9
- package/source/test/ItemsContainer.js +22 -1
- package/source/utility/debug.js +18 -4
- package/commonjs/react/useHandleItemIndexesChange.js.map +0 -1
- package/commonjs/react/useHandleItemsPropertyChange.js.map +0 -1
- package/commonjs/react/useOnItemHeightChange.js.map +0 -1
- package/modules/react/useHandleItemIndexesChange.js +0 -45
- package/modules/react/useHandleItemIndexesChange.js.map +0 -1
- package/modules/react/useHandleItemsPropertyChange.js.map +0 -1
- package/modules/react/useOnItemHeightChange.js.map +0 -1
|
@@ -13,6 +13,10 @@ var _debug = _interopRequireWildcard(require("./utility/debug.js"));
|
|
|
13
13
|
|
|
14
14
|
var _Layout = require("./Layout.js");
|
|
15
15
|
|
|
16
|
+
var _ItemNotRenderedError = _interopRequireDefault(require("./ItemNotRenderedError.js"));
|
|
17
|
+
|
|
18
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
19
|
+
|
|
16
20
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
17
21
|
|
|
18
22
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
@@ -122,7 +126,7 @@ function _default() {
|
|
|
122
126
|
// or an "Expand YouTube video" button, which would result
|
|
123
127
|
// in the actual height of the list item being different
|
|
124
128
|
// from what has been initially measured in `this.itemHeights[i]`,
|
|
125
|
-
// if the developer didn't call `.setItemState(i, newState)` and `.
|
|
129
|
+
// if the developer didn't call `.setItemState(i, newState)` and `.onItemHeightDidChange(i)`.
|
|
126
130
|
|
|
127
131
|
|
|
128
132
|
if (!validateWillBeHiddenItemHeightsAreAccurate.call(this, firstShownItemIndex, lastShownItemIndex)) {
|
|
@@ -164,7 +168,10 @@ function _default() {
|
|
|
164
168
|
|
|
165
169
|
this.onBeforeShowItems(this.getState().items, this.getState().itemHeights, firstShownItemIndex, lastShownItemIndex); // Set `this.firstNonMeasuredItemIndex`.
|
|
166
170
|
|
|
167
|
-
this.firstNonMeasuredItemIndex = firstNonMeasuredItemIndex; //
|
|
171
|
+
this.firstNonMeasuredItemIndex = firstNonMeasuredItemIndex; // if (firstNonMeasuredItemIndex !== undefined) {
|
|
172
|
+
// log('Non-measured item index that will be measured at next layout', firstNonMeasuredItemIndex)
|
|
173
|
+
// }
|
|
174
|
+
// Set "previously calculated layout".
|
|
168
175
|
//
|
|
169
176
|
// The "previously calculated layout" feature is not currently used.
|
|
170
177
|
//
|
|
@@ -187,9 +194,9 @@ function _default() {
|
|
|
187
194
|
// Instead of using a `this.previouslyCalculatedLayout` instance variable,
|
|
188
195
|
// this code could use `this.getState()` because it reflects what's currently on screen,
|
|
189
196
|
// but there's a single edge case when it could go out of sync —
|
|
190
|
-
// updating item heights externally via `.
|
|
197
|
+
// updating item heights externally via `.onItemHeightDidChange(i)`.
|
|
191
198
|
//
|
|
192
|
-
// If, for example, an item height was updated externally via `.
|
|
199
|
+
// If, for example, an item height was updated externally via `.onItemHeightDidChange(i)`
|
|
193
200
|
// then `this.getState().itemHeights` would get updated immediately but
|
|
194
201
|
// `this.getState().beforeItemsHeight` or `this.getState().afterItemsHeight`
|
|
195
202
|
// would still correspond to the previous item height, so those would be "stale".
|
|
@@ -281,7 +288,7 @@ function _default() {
|
|
|
281
288
|
* or an "Expand YouTube video" button, which would result
|
|
282
289
|
* in the actual height of the list item being different
|
|
283
290
|
* from what has been initially measured in `this.itemHeights[i]`,
|
|
284
|
-
* if the developer didn't call `.setItemState(i, newState)` and `.
|
|
291
|
+
* if the developer didn't call `.setItemState(i, newState)` and `.onItemHeightDidChange(i)`.
|
|
285
292
|
*/
|
|
286
293
|
|
|
287
294
|
|
|
@@ -295,26 +302,26 @@ function _default() {
|
|
|
295
302
|
// The item will be hidden. Re-measure its height.
|
|
296
303
|
// The rationale is that there could be a situation when an item's
|
|
297
304
|
// height has changed, and the developer has properly added an
|
|
298
|
-
// `.
|
|
305
|
+
// `.onItemHeightDidChange(i)` call to notify `VirtualScroller`
|
|
299
306
|
// about that change, but at the same time that wouldn't work.
|
|
300
307
|
// For example, suppose there's a list of several items on a page,
|
|
301
308
|
// and those items are in "minimized" state (having height 100px).
|
|
302
309
|
// Then, a user clicks an "Expand all items" button, and all items
|
|
303
310
|
// in the list are expanded (expanded item height is gonna be 700px).
|
|
304
|
-
// `VirtualScroller` demands that `.
|
|
311
|
+
// `VirtualScroller` demands that `.onItemHeightDidChange(i)` is called
|
|
305
312
|
// in such cases, and the developer has properly added the code to do that.
|
|
306
313
|
// So, if there were 10 "minimized" items visible on a page, then there
|
|
307
|
-
// will be 10 individual `.
|
|
308
|
-
// But, as the first `.
|
|
314
|
+
// will be 10 individual `.onItemHeightDidChange(i)` calls. No issues so far.
|
|
315
|
+
// But, as the first `.onItemHeightDidChange(i)` call executes, it immediately
|
|
309
316
|
// ("synchronously") triggers a re-layout, and that re-layout finds out
|
|
310
317
|
// that now, because the first item is big, it occupies most of the screen
|
|
311
318
|
// space, and only the first 3 items are visible on screen instead of 10,
|
|
312
319
|
// and so it leaves the first 3 items mounted and unmounts the rest 7.
|
|
313
320
|
// Then, after `VirtualScroller` has rerendered, the code returns to
|
|
314
|
-
// where it was executing, and calls `.
|
|
321
|
+
// where it was executing, and calls `.onItemHeightDidChange(i)` for the
|
|
315
322
|
// second item. It also triggers an immediate re-layout that finds out
|
|
316
323
|
// that only the first 2 items are visible on screen, and it unmounts
|
|
317
|
-
// the third one too. After that, it calls `.
|
|
324
|
+
// the third one too. After that, it calls `.onItemHeightDidChange(i)`
|
|
318
325
|
// for the third item, but that item is no longer rendered, so its height
|
|
319
326
|
// can't be measured, and the same's for all the rest of the original 10 items.
|
|
320
327
|
// So, even though the developer has written their code properly, the
|
|
@@ -334,7 +341,7 @@ function _default() {
|
|
|
334
341
|
}
|
|
335
342
|
|
|
336
343
|
isValid = false;
|
|
337
|
-
(0, _debug.warn)('Item index', i, 'is no longer visible and will be unmounted. Its height has changed from', previouslyMeasuredItemHeight, 'to', actualItemHeight, 'since it was last measured. This is not necessarily a bug, and could happen, for example, on screen width change, or when there\'re several `
|
|
344
|
+
(0, _debug.warn)('Item index', i, 'is no longer visible and will be unmounted. Its height has changed from', previouslyMeasuredItemHeight, 'to', actualItemHeight, 'since it was last measured. This is not necessarily a bug, and could happen, for example, on screen width change, or when there\'re several `onItemHeightDidChange(i)` calls issued at the same time, and the first one triggers a re-layout before the rest of them have had a chance to be executed.');
|
|
338
345
|
}
|
|
339
346
|
}
|
|
340
347
|
|
|
@@ -360,21 +367,23 @@ function _default() {
|
|
|
360
367
|
|
|
361
368
|
|
|
362
369
|
function updatePreviouslyCalculatedLayoutOnItemHeightChange(i, previousHeight, newHeight) {
|
|
363
|
-
|
|
370
|
+
var prevLayout = this.previouslyCalculatedLayout;
|
|
371
|
+
|
|
372
|
+
if (prevLayout) {
|
|
364
373
|
var heightDifference = newHeight - previousHeight;
|
|
365
374
|
|
|
366
|
-
if (i <
|
|
367
|
-
// Patch `
|
|
368
|
-
|
|
369
|
-
} else if (i >
|
|
370
|
-
// Could patch `.afterItemsHeight` of `
|
|
371
|
-
// if `.afterItemsHeight` property existed in `
|
|
372
|
-
if (
|
|
373
|
-
|
|
375
|
+
if (i < prevLayout.firstShownItemIndex) {
|
|
376
|
+
// Patch `prevLayout`'s `.beforeItemsHeight`.
|
|
377
|
+
prevLayout.beforeItemsHeight += heightDifference;
|
|
378
|
+
} else if (i > prevLayout.lastShownItemIndex) {
|
|
379
|
+
// Could patch `.afterItemsHeight` of `prevLayout` here,
|
|
380
|
+
// if `.afterItemsHeight` property existed in `prevLayout`.
|
|
381
|
+
if (prevLayout.afterItemsHeight !== undefined) {
|
|
382
|
+
prevLayout.afterItemsHeight += heightDifference;
|
|
374
383
|
}
|
|
375
384
|
} else {
|
|
376
|
-
// Patch `
|
|
377
|
-
|
|
385
|
+
// Patch `prevLayout`'s shown items height.
|
|
386
|
+
prevLayout.shownItemsHeight += newHeight - previousHeight;
|
|
378
387
|
}
|
|
379
388
|
}
|
|
380
389
|
}
|
|
@@ -394,8 +403,8 @@ function _default() {
|
|
|
394
403
|
return listTopOffset;
|
|
395
404
|
};
|
|
396
405
|
|
|
397
|
-
this.
|
|
398
|
-
(0, _debug["default"])('~
|
|
406
|
+
this._onItemHeightDidChange = function (i) {
|
|
407
|
+
(0, _debug["default"])('~ On Item Height Did Change was called ~');
|
|
399
408
|
(0, _debug["default"])('Item index', i);
|
|
400
409
|
|
|
401
410
|
var _this$getState2 = _this.getState(),
|
|
@@ -406,51 +415,84 @@ function _default() {
|
|
|
406
415
|
|
|
407
416
|
if (!(i >= firstShownItemIndex && i <= lastShownItemIndex)) {
|
|
408
417
|
// There could be valid cases when an item is no longer rendered
|
|
409
|
-
// by the time `.
|
|
418
|
+
// by the time `.onItemHeightDidChange(i)` gets called.
|
|
410
419
|
// For example, suppose there's a list of several items on a page,
|
|
411
420
|
// and those items are in "minimized" state (having height 100px).
|
|
412
421
|
// Then, a user clicks an "Expand all items" button, and all items
|
|
413
422
|
// in the list are expanded (expanded item height is gonna be 700px).
|
|
414
|
-
// `VirtualScroller` demands that `.
|
|
423
|
+
// `VirtualScroller` demands that `.onItemHeightDidChange(i)` is called
|
|
415
424
|
// in such cases, and the developer has properly added the code to do that.
|
|
416
425
|
// So, if there were 10 "minimized" items visible on a page, then there
|
|
417
|
-
// will be 10 individual `.
|
|
418
|
-
// But, as the first `.
|
|
426
|
+
// will be 10 individual `.onItemHeightDidChange(i)` calls. No issues so far.
|
|
427
|
+
// But, as the first `.onItemHeightDidChange(i)` call executes, it immediately
|
|
419
428
|
// ("synchronously") triggers a re-layout, and that re-layout finds out
|
|
420
429
|
// that now, because the first item is big, it occupies most of the screen
|
|
421
430
|
// space, and only the first 3 items are visible on screen instead of 10,
|
|
422
431
|
// and so it leaves the first 3 items mounted and unmounts the rest 7.
|
|
423
432
|
// Then, after `VirtualScroller` has rerendered, the code returns to
|
|
424
|
-
// where it was executing, and calls `.
|
|
433
|
+
// where it was executing, and calls `.onItemHeightDidChange(i)` for the
|
|
425
434
|
// second item. It also triggers an immediate re-layout that finds out
|
|
426
435
|
// that only the first 2 items are visible on screen, and it unmounts
|
|
427
|
-
// the third one too. After that, it calls `.
|
|
436
|
+
// the third one too. After that, it calls `.onItemHeightDidChange(i)`
|
|
428
437
|
// for the third item, but that item is no longer rendered, so its height
|
|
429
438
|
// can't be measured, and the same's for all the rest of the original 10 items.
|
|
430
439
|
// So, even though the developer has written their code properly, there're
|
|
431
440
|
// still situations when the item could be no longer rendered by the time
|
|
432
|
-
// `.
|
|
433
|
-
return (0, _debug.warn)('The item is no longer rendered. This is not necessarily a bug, and could happen, for example, when when a developer calls `
|
|
441
|
+
// `.onItemHeightDidChange(i)` gets called.
|
|
442
|
+
return (0, _debug.warn)('The item is no longer rendered. This is not necessarily a bug, and could happen, for example, when when a developer calls `onItemHeightDidChange(i)` while looping through a batch of items.');
|
|
434
443
|
}
|
|
435
444
|
|
|
436
445
|
var previousHeight = itemHeights[i];
|
|
437
446
|
|
|
438
447
|
if (previousHeight === undefined) {
|
|
439
|
-
return (0, _debug.reportError)("\"
|
|
448
|
+
return (0, _debug.reportError)("\"onItemHeightDidChange()\" has been called for item index ".concat(i, " but the item hasn't been rendered before."));
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
(0, _debug["default"])('~ Re-measure item height ~');
|
|
452
|
+
var newHeight;
|
|
453
|
+
|
|
454
|
+
try {
|
|
455
|
+
newHeight = remeasureItemHeight.call(_this, i);
|
|
456
|
+
} catch (error) {
|
|
457
|
+
// Successfully finishing an `onItemHeightDidChange(i)` call is not considered
|
|
458
|
+
// critical for `VirtualScroller`'s operation, so such errors could be ignored.
|
|
459
|
+
if (error instanceof _ItemNotRenderedError["default"]) {
|
|
460
|
+
return (0, _debug.reportError)("\"onItemHeightDidChange()\" has been called for item index ".concat(i, " but the item is not currently rendered and can't be measured. The exact error was: ").concat(error.message));
|
|
461
|
+
}
|
|
440
462
|
}
|
|
441
463
|
|
|
442
|
-
var newHeight = remeasureItemHeight.call(_this, i);
|
|
443
464
|
(0, _debug["default"])('Previous height', previousHeight);
|
|
444
465
|
(0, _debug["default"])('New height', newHeight);
|
|
445
466
|
|
|
446
467
|
if (previousHeight !== newHeight) {
|
|
447
|
-
(0, _debug["default"])('~ Item height has changed ~'); // Update or reset previously calculated layout
|
|
468
|
+
(0, _debug["default"])('~ Item height has changed. Should update layout. ~'); // Update or reset a previously calculated layout
|
|
469
|
+
// so that the "diff"s based on that layout in the future
|
|
470
|
+
// produce correct results.
|
|
448
471
|
|
|
449
472
|
updatePreviouslyCalculatedLayoutOnItemHeightChange.call(_this, i, previousHeight, newHeight); // Recalculate layout.
|
|
473
|
+
//
|
|
474
|
+
// If the `VirtualScroller` is already waiting for a state update to be rendered,
|
|
475
|
+
// delay `onItemHeightDidChange(i)`'s re-layout until that state update is rendered.
|
|
476
|
+
// The reason is that React `<VirtualScroller/>`'s `onHeightDidChange()` is meant to
|
|
477
|
+
// be called inside `useLayoutEffect()` hook. Due to how React is implemented internally,
|
|
478
|
+
// that might happen in the middle of the currently pending `setState()` operation
|
|
479
|
+
// being applied, resulting in weird "race condition" bugs.
|
|
480
|
+
//
|
|
450
481
|
|
|
451
|
-
_this.
|
|
452
|
-
|
|
453
|
-
|
|
482
|
+
if (_this.waitingForRender) {
|
|
483
|
+
(0, _debug["default"])('~ Another state update is already waiting to be rendered. Delay the layout update until then. ~');
|
|
484
|
+
_this.updateLayoutAfterRenderBecauseItemHeightChanged = true;
|
|
485
|
+
} else {
|
|
486
|
+
_this.onUpdateShownItemIndexes({
|
|
487
|
+
reason: _Layout.LAYOUT_REASON.ITEM_HEIGHT_CHANGED
|
|
488
|
+
});
|
|
489
|
+
} // If there was a request for `setState()` with new `items`, then the changes
|
|
490
|
+
// to `currentState.itemHeights[]` made above in a `remeasureItemHeight()` call
|
|
491
|
+
// would be overwritten when that pending `setState()` call gets applied.
|
|
492
|
+
// To fix that, the updates to current `itemHeights[]` are noted in
|
|
493
|
+
// `this.itemHeightsThatChangedWhileNewItemsWereBeingRendered` variable.
|
|
494
|
+
// That variable is then checked when the `setState()` call with the new `items`
|
|
495
|
+
// has been updated.
|
|
454
496
|
|
|
455
497
|
|
|
456
498
|
if (_this.newItemsWillBeRendered) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VirtualScroller.layout.js","names":["onUpdateShownItemIndexes","reason","stateUpdate","skip","updateState","newItemsWillBeRendered","widthHasChanged","_isResizing","getItemsCount","scroll","cancelScheduledLayout","cancelLayoutTimer","log","updateShownItemIndexes","call","startedAt","Date","now","getShownItemIndexes","firstShownItemIndex","lastShownItemIndex","shownItemsHeight","firstNonMeasuredItemIndex","listHeightMeasurement","hasSnapshot","getAnchorItemIndex","undefined","validateWillBeHiddenItemHeightsAreAccurate","beforeItemsHeight","layout","getBeforeItemsHeight","afterItemsHeight","getAfterItemsHeight","layoutDuration","bypass","SLOW_LAYOUT_DURATION","warn","getColumnsCount","itemHeights","getAverage","isDebug","getState","slice","itemStates","onBeforeShowItems","items","previouslyCalculatedLayout","getVisibleArea","visibleArea","getVisibleAreaBounds","latestLayoutVisibleArea","listTopOffsetInsideScrollableContainer","getListTopOffsetInsideScrollableContainer","top","bottom","itemsCount","visibleAreaTop","visibleAreaBottom","isVisible","itemsContainer","getHeight","getNonVisibleListShownItemIndexes","isValid","i","previouslyMeasuredItemHeight","actualItemHeight","remeasureItemHeight","updatePreviouslyCalculatedLayoutOnItemHeightChange","previousHeight","newHeight","heightDifference","listTopOffset","scrollableContainer","getItemsContainerTopOffset","listTopOffsetWatcher","onListTopOffset","_onItemHeightChange","reportError","LAYOUT_REASON","ITEM_HEIGHT_CHANGED","itemHeightsThatChangedWhileNewItemsWereBeingRendered","String","getPrerenderMargin","renderAheadMarginRatio","onItemInitialRender","measureItemHeightsAndSpacing","measureItemHeights","verticalSpacing","measureVerticalSpacingIfNotMeasured","layoutTimer","clearTimeout","layoutTimerStateUpdate","scheduleLayoutTimer","setTimeout"],"sources":["../source/VirtualScroller.layout.js"],"sourcesContent":["// For some weird reason, in Chrome, `setTimeout()` would lag up to a second (or more) behind.\r\n// Turns out, Chrome developers have deprecated `setTimeout()` API entirely without asking anyone.\r\n// Replacing `setTimeout()` with `requestAnimationFrame()` can work around that Chrome bug.\r\n// https://github.com/bvaughn/react-virtualized/issues/722\r\nimport { setTimeout, clearTimeout } from 'request-animation-frame-timeout'\r\n\r\nimport log, { warn, isDebug, reportError } from './utility/debug.js'\r\nimport { LAYOUT_REASON } from './Layout.js'\r\n\r\nexport default function() {\r\n\tthis.onUpdateShownItemIndexes = ({ reason, stateUpdate }) => {\r\n\t\t// In case of \"don't do anything\".\r\n\t\tconst skip = () => {\r\n\t\t\tif (stateUpdate) {\r\n\t\t\t\tthis.updateState(stateUpdate)\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If new `items` have been set and are waiting to be applied,\r\n\t\t// or if the viewport width has changed requiring a re-layout,\r\n\t\t// then temporarily stop all other updates like \"on scroll\" updates.\r\n\t\t// This prevents `state` being inconsistent, because, for example,\r\n\t\t// both `setItems()` and this function could update `VirtualScroller` state\r\n\t\t// and having them operate in parallel could result in incorrectly calculated\r\n\t\t// `beforeItemsHeight` / `afterItemsHeight` / `firstShownItemIndex` /\r\n\t\t// `lastShownItemIndex`, because, when operating in parallel, this function\r\n\t\t// would have different `items` than the `setItems()` function, so their\r\n\t\t// results could diverge.\r\n\t\tif (this.newItemsWillBeRendered || this.widthHasChanged || this._isResizing) {\r\n\t\t\treturn skip()\r\n\t\t}\r\n\r\n\t\t// If there're no items then there's no need to re-layout anything.\r\n\t\tif (this.getItemsCount() === 0) {\r\n\t\t\treturn skip()\r\n\t\t}\r\n\r\n\t\t// Cancel a \"re-layout when user stops scrolling\" timer.\r\n\t\tthis.scroll.cancelScheduledLayout()\r\n\r\n\t\t// Cancel a re-layout that is scheduled to run at the next \"frame\",\r\n\t\t// because a re-layout will be performed right now.\r\n\t\tstateUpdate = this.cancelLayoutTimer({ stateUpdate })\r\n\r\n\t\t// Perform a re-layout.\r\n\t\tlog(`~ Update Layout (on ${reason}) ~`)\r\n\t\tupdateShownItemIndexes.call(this, { stateUpdate })\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the \"from\" and \"to\" shown item indexes.\r\n\t * If the list is visible and some of the items being shown are new\r\n\t * and are required to be measured first, then\r\n\t * `firstNonMeasuredItemIndex` is defined.\r\n\t * If the list is visible and all items being shown have been encountered\r\n\t * (and measured) before, then `firstNonMeasuredItemIndex` is `undefined`.\r\n\t *\r\n\t * The `stateUpdate` parameter is just an optional \"additional\" state update.\r\n\t */\r\n\tfunction updateShownItemIndexes({ stateUpdate }) {\r\n\t\tconst startedAt = Date.now()\r\n\r\n\t\t// Get shown item indexes.\r\n\t\tlet {\r\n\t\t\tfirstShownItemIndex,\r\n\t\t\tlastShownItemIndex,\r\n\t\t\tshownItemsHeight,\r\n\t\t\tfirstNonMeasuredItemIndex\r\n\t\t} = getShownItemIndexes.call(this)\r\n\r\n\t\t// If scroll position is scheduled to be restored after render,\r\n\t\t// then the \"anchor\" item must be rendered, and all of the prepended\r\n\t\t// items before it, all in a single pass. This way, all of the\r\n\t\t// prepended items' heights could be measured right after the render\r\n\t\t// has finished, and the scroll position can then be immediately restored.\r\n\t\tif (this.listHeightMeasurement.hasSnapshot()) {\r\n\t\t\tif (lastShownItemIndex < this.listHeightMeasurement.getAnchorItemIndex()) {\r\n\t\t\t\tlastShownItemIndex = this.listHeightMeasurement.getAnchorItemIndex()\r\n\t\t\t}\r\n\t\t\t// `firstShownItemIndex` is always `0` when prepending items.\r\n\t\t\t// And `lastShownItemIndex` always covers all prepended items in this case.\r\n\t\t\t// None of the prepended items have been rendered before,\r\n\t\t\t// so their heights are unknown. The code at the start of this function\r\n\t\t\t// did therefore set `firstNonMeasuredItemIndex` to non-`undefined`\r\n\t\t\t// in order to render just the first prepended item in order to\r\n\t\t\t// measure it, and only then make a decision on how many other\r\n\t\t\t// prepended items to render. But since we've instructed the code\r\n\t\t\t// to show all of the prepended items at once, there's no need to\r\n\t\t\t// \"redo layout after render\". Additionally, if layout was re-done\r\n\t\t\t// after render, then there would be a short interval of visual\r\n\t\t\t// \"jitter\" due to the scroll position not being restored because it'd\r\n\t\t\t// wait for the second layout to finish instead of being restored\r\n\t\t\t// right after the first one.\r\n\t\t\tfirstNonMeasuredItemIndex = undefined\r\n\t\t}\r\n\r\n\t\t// Validate the heights of items to be hidden on next render.\r\n\t\t// For example, a user could click a \"Show more\" button,\r\n\t\t// or an \"Expand YouTube video\" button, which would result\r\n\t\t// in the actual height of the list item being different\r\n\t\t// from what has been initially measured in `this.itemHeights[i]`,\r\n\t\t// if the developer didn't call `.setItemState(i, newState)` and `.onItemHeightChange(i)`.\r\n\t\tif (!validateWillBeHiddenItemHeightsAreAccurate.call(this, firstShownItemIndex, lastShownItemIndex)) {\r\n\t\t\tlog('~ Because some of the will-be-hidden item heights (listed above) have changed since they\\'ve last been measured, redo layout. ~')\r\n\t\t\t// Redo layout, now with the correct item heights.\r\n\t\t\treturn updateShownItemIndexes.call(this, { stateUpdate });\r\n\t\t}\r\n\r\n\t\t// Measure \"before\" items height.\r\n\t\tconst beforeItemsHeight = this.layout.getBeforeItemsHeight(\r\n\t\t\tfirstShownItemIndex\r\n\t\t)\r\n\r\n\t\t// Measure \"after\" items height.\r\n\t\tconst afterItemsHeight = this.layout.getAfterItemsHeight(\r\n\t\t\tlastShownItemIndex,\r\n\t\t\tthis.getItemsCount()\r\n\t\t)\r\n\r\n\t\tconst layoutDuration = Date.now() - startedAt\r\n\r\n\t\t// Debugging.\r\n\t\tlog('~ Calculated Layout' + (this.bypass ? ' (bypass)' : '') + ' ~')\r\n\t\tif (layoutDuration < SLOW_LAYOUT_DURATION) {\r\n\t\t\t// log('Calculated in', layoutDuration, 'ms')\r\n\t\t} else {\r\n\t\t\twarn('Layout calculated in', layoutDuration, 'ms')\r\n\t\t}\r\n\t\tif (this.getColumnsCount()) {\r\n\t\t\tlog('Columns count', this.getColumnsCount())\r\n\t\t}\r\n\t\tlog('First shown item index', firstShownItemIndex)\r\n\t\tlog('Last shown item index', lastShownItemIndex)\r\n\t\tlog('Before items height', beforeItemsHeight)\r\n\t\tlog('After items height (actual or estimated)', afterItemsHeight)\r\n\t\tlog('Average item height (used for estimated after items height calculation)', this.itemHeights.getAverage())\r\n\t\tif (isDebug()) {\r\n\t\t\tlog('Item heights', this.getState().itemHeights.slice())\r\n\t\t\tlog('Item states', this.getState().itemStates.slice())\r\n\t\t}\r\n\r\n\t\t// Optionally preload items to be rendered.\r\n\t\tthis.onBeforeShowItems(\r\n\t\t\tthis.getState().items,\r\n\t\t\tthis.getState().itemHeights,\r\n\t\t\tfirstShownItemIndex,\r\n\t\t\tlastShownItemIndex\r\n\t\t)\r\n\r\n\t\t// Set `this.firstNonMeasuredItemIndex`.\r\n\t\tthis.firstNonMeasuredItemIndex = firstNonMeasuredItemIndex\r\n\r\n\t\t// Set \"previously calculated layout\".\r\n\t\t//\r\n\t\t// The \"previously calculated layout\" feature is not currently used.\r\n\t\t//\r\n\t\t// The current layout snapshot could be stored as a \"previously calculated layout\" variable\r\n\t\t// so that it could theoretically be used when calculating new layout incrementally\r\n\t\t// rather than from scratch, which would be an optimization.\r\n\t\t//\r\n\t\t// Currently, this feature is not used, and `shownItemsHeight` property\r\n\t\t// is not returned at all, so don't set any \"previously calculated layout\".\r\n\t\t//\r\n\t\tif (shownItemsHeight === undefined) {\r\n\t\t\tthis.previouslyCalculatedLayout = undefined\r\n\t\t} else {\r\n\t\t\t// If \"previously calculated layout\" feature would be implmeneted,\r\n\t\t\t// then this code would set \"previously calculate layout\" instance variable.\r\n\t\t\t//\r\n\t\t\t// What for would this instance variable be used?\r\n\t\t\t//\r\n\t\t\t// Instead of using a `this.previouslyCalculatedLayout` instance variable,\r\n\t\t\t// this code could use `this.getState()` because it reflects what's currently on screen,\r\n\t\t\t// but there's a single edge case when it could go out of sync —\r\n\t\t\t// updating item heights externally via `.onItemHeightChange(i)`.\r\n\t\t\t//\r\n\t\t\t// If, for example, an item height was updated externally via `.onItemHeightChange(i)`\r\n\t\t\t// then `this.getState().itemHeights` would get updated immediately but\r\n\t\t\t// `this.getState().beforeItemsHeight` or `this.getState().afterItemsHeight`\r\n\t\t\t// would still correspond to the previous item height, so those would be \"stale\".\r\n\t\t\t// On the other hand, same values in `this.previouslyCalculatedLayout` instance variable\r\n\t\t\t// can also be updated immediately, so they won't go out of sync with the updated item height.\r\n\t\t\t// That seems the only edge case when using a separate `this.previouslyCalculatedLayout`\r\n\t\t\t// instance variable instead of using `this.getState()` would theoretically be justified.\r\n\t\t\t//\r\n\t\t\tthis.previouslyCalculatedLayout = {\r\n\t\t\t\tfirstShownItemIndex,\r\n\t\t\t\tlastShownItemIndex,\r\n\t\t\t\tbeforeItemsHeight,\r\n\t\t\t\tshownItemsHeight\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Update `VirtualScroller` state.\r\n\t\t// `VirtualScroller` automatically re-renders on state updates.\r\n\t\t//\r\n\t\t// All `state` properties updated here should be overwritten in\r\n\t\t// the implementation of `setItems()` and `onResize()` methods\r\n\t\t// so that the `state` is not left in an inconsistent state\r\n\t\t// whenever there're concurrent `updateState()` updates that could\r\n\t\t// possibly conflict with one another — instead, those state updates\r\n\t\t// should overwrite each other in terms of priority.\r\n\t\t// These \"on scroll\" updates have the lowest priority compared to\r\n\t\t// the state updates originating from `setItems()` and `onResize()` methods.\r\n\t\t//\r\n\t\tthis.updateState({\r\n\t\t\tfirstShownItemIndex,\r\n\t\t\tlastShownItemIndex,\r\n\t\t\tbeforeItemsHeight,\r\n\t\t\tafterItemsHeight,\r\n\t\t\t...stateUpdate\r\n\t\t})\r\n\t}\r\n\r\n\tfunction getVisibleArea() {\r\n\t\tconst visibleArea = this.scroll.getVisibleAreaBounds()\r\n\t\tthis.latestLayoutVisibleArea = visibleArea\r\n\r\n\t\t// Subtract the top offset of the list inside the scrollable container.\r\n\t\tconst listTopOffsetInsideScrollableContainer = this.getListTopOffsetInsideScrollableContainer()\r\n\t\treturn {\r\n\t\t\ttop: visibleArea.top - listTopOffsetInsideScrollableContainer,\r\n\t\t\tbottom: visibleArea.bottom - listTopOffsetInsideScrollableContainer\r\n\t\t}\r\n\t}\r\n\r\n\tfunction getShownItemIndexes() {\r\n\t\tconst itemsCount = this.getItemsCount()\r\n\r\n\t\tconst {\r\n\t\t\ttop: visibleAreaTop,\r\n\t\t\tbottom: visibleAreaBottom\r\n\t\t} = getVisibleArea.call(this)\r\n\r\n\t\tif (this.bypass) {\r\n\t\t\treturn {\r\n\t\t\t\tfirstShownItemIndex: 0,\r\n\t\t\t\tlastShownItemIndex: itemsCount - 1,\r\n\t\t\t\t// shownItemsHeight: this.getState().itemHeights.reduce((sum, itemHeight) => sum + itemHeight, 0)\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Find the indexes of the items that are currently visible\r\n\t\t// (or close to being visible) in the scrollable container.\r\n\t\t// For scrollable containers other than the main screen, it could also\r\n\t\t// check the visibility of such scrollable container itself, because it\r\n\t\t// might be not visible.\r\n\t\t// If such kind of an optimization would hypothetically be implemented,\r\n\t\t// then it would also require listening for \"scroll\" events on the screen.\r\n\t\t// Overall, I suppose that such \"actual visibility\" feature would be\r\n\t\t// a very minor optimization and not something I'd deal with.\r\n\t\tconst isVisible = visibleAreaTop < this.itemsContainer.getHeight() && visibleAreaBottom > 0\r\n\t\tif (!isVisible) {\r\n\t\t\tlog('The entire list is off-screen. No items are visible.')\r\n\t\t\treturn this.layout.getNonVisibleListShownItemIndexes()\r\n\t\t}\r\n\r\n\t\t// Get shown item indexes.\r\n\t\treturn this.layout.getShownItemIndexes({\r\n\t\t\titemsCount: this.getItemsCount(),\r\n\t\t\tvisibleAreaTop,\r\n\t\t\tvisibleAreaBottom\r\n\t\t})\r\n\t}\r\n\r\n\t/**\r\n\t * Validates the heights of items to be hidden on next render.\r\n\t * For example, a user could click a \"Show more\" button,\r\n\t * or an \"Expand YouTube video\" button, which would result\r\n\t * in the actual height of the list item being different\r\n\t * from what has been initially measured in `this.itemHeights[i]`,\r\n\t * if the developer didn't call `.setItemState(i, newState)` and `.onItemHeightChange(i)`.\r\n\t */\r\n\tfunction validateWillBeHiddenItemHeightsAreAccurate(firstShownItemIndex, lastShownItemIndex) {\r\n\t\tlet isValid = true\r\n\t\tlet i = this.getState().firstShownItemIndex\r\n\t\twhile (i <= this.getState().lastShownItemIndex) {\r\n\t\t\tif (i >= firstShownItemIndex && i <= lastShownItemIndex) {\r\n\t\t\t\t// The item's still visible.\r\n\t\t\t} else {\r\n\t\t\t\t// The item will be hidden. Re-measure its height.\r\n\t\t\t\t// The rationale is that there could be a situation when an item's\r\n\t\t\t\t// height has changed, and the developer has properly added an\r\n\t\t\t\t// `.onItemHeightChange(i)` call to notify `VirtualScroller`\r\n\t\t\t\t// about that change, but at the same time that wouldn't work.\r\n\t\t\t\t// For example, suppose there's a list of several items on a page,\r\n\t\t\t\t// and those items are in \"minimized\" state (having height 100px).\r\n\t\t\t\t// Then, a user clicks an \"Expand all items\" button, and all items\r\n\t\t\t\t// in the list are expanded (expanded item height is gonna be 700px).\r\n\t\t\t\t// `VirtualScroller` demands that `.onItemHeightChange(i)` is called\r\n\t\t\t\t// in such cases, and the developer has properly added the code to do that.\r\n\t\t\t\t// So, if there were 10 \"minimized\" items visible on a page, then there\r\n\t\t\t\t// will be 10 individual `.onItemHeightChange(i)` calls. No issues so far.\r\n\t\t\t\t// But, as the first `.onItemHeightChange(i)` call executes, it immediately\r\n\t\t\t\t// (\"synchronously\") triggers a re-layout, and that re-layout finds out\r\n\t\t\t\t// that now, because the first item is big, it occupies most of the screen\r\n\t\t\t\t// space, and only the first 3 items are visible on screen instead of 10,\r\n\t\t\t\t// and so it leaves the first 3 items mounted and unmounts the rest 7.\r\n\t\t\t\t// Then, after `VirtualScroller` has rerendered, the code returns to\r\n\t\t\t\t// where it was executing, and calls `.onItemHeightChange(i)` for the\r\n\t\t\t\t// second item. It also triggers an immediate re-layout that finds out\r\n\t\t\t\t// that only the first 2 items are visible on screen, and it unmounts\r\n\t\t\t\t// the third one too. After that, it calls `.onItemHeightChange(i)`\r\n\t\t\t\t// for the third item, but that item is no longer rendered, so its height\r\n\t\t\t\t// can't be measured, and the same's for all the rest of the original 10 items.\r\n\t\t\t\t// So, even though the developer has written their code properly, the\r\n\t\t\t\t// `VirtualScroller` still ends up having incorrect `itemHeights[]`:\r\n\t\t\t\t// `[700px, 700px, 100px, 100px, 100px, 100px, 100px, 100px, 100px, 100px]`\r\n\t\t\t\t// while it should have been `700px` for all of them.\r\n\t\t\t\t// To work around such issues, every item's height is re-measured before it\r\n\t\t\t\t// gets hidden.\r\n\t\t\t\tconst previouslyMeasuredItemHeight = this.getState().itemHeights[i]\r\n\t\t\t\tconst actualItemHeight = remeasureItemHeight.call(this, i)\r\n\t\t\t\tif (actualItemHeight !== previouslyMeasuredItemHeight) {\r\n\t\t\t\t\tif (isValid) {\r\n\t\t\t\t\t\tlog('~ Validate will-be-hidden item heights. ~')\r\n\t\t\t\t\t\t// Update or reset previously calculated layout.\r\n\t\t\t\t\t\tupdatePreviouslyCalculatedLayoutOnItemHeightChange.call(this, i, previouslyMeasuredItemHeight, actualItemHeight)\r\n\t\t\t\t\t}\r\n\t\t\t\t\tisValid = false\r\n\t\t\t\t\twarn('Item index', i, 'is no longer visible and will be unmounted. Its height has changed from', previouslyMeasuredItemHeight, 'to', actualItemHeight, 'since it was last measured. This is not necessarily a bug, and could happen, for example, on screen width change, or when there\\'re several `onItemHeightChange(i)` calls issued at the same time, and the first one triggers a re-layout before the rest of them have had a chance to be executed.')\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ti++\r\n\t\t}\r\n\t\treturn isValid\r\n\t}\r\n\r\n\tfunction remeasureItemHeight(i) {\r\n\t\tconst { firstShownItemIndex } = this.getState()\r\n\t\treturn this.itemHeights.remeasureItemHeight(i, firstShownItemIndex)\r\n\t}\r\n\r\n\t// Updates the snapshot of the current layout when an item's height changes.\r\n\t//\r\n\t// The \"previously calculated layout\" feature is not currently used.\r\n\t//\r\n\t// The current layout snapshot could be stored as a \"previously calculated layout\" variable\r\n\t// so that it could theoretically be used when calculating new layout incrementally\r\n\t// rather than from scratch, which would be an optimization.\r\n\t//\r\n\tfunction updatePreviouslyCalculatedLayoutOnItemHeightChange(i, previousHeight, newHeight) {\r\n\t\tif (this.previouslyCalculatedLayout) {\r\n\t\t\tconst heightDifference = newHeight - previousHeight\r\n\t\t\tif (i < this.previouslyCalculatedLayout.firstShownItemIndex) {\r\n\t\t\t\t// Patch `this.previouslyCalculatedLayout`'s `.beforeItemsHeight`.\r\n\t\t\t\tthis.previouslyCalculatedLayout.beforeItemsHeight += heightDifference\r\n\t\t\t} else if (i > this.previouslyCalculatedLayout.lastShownItemIndex) {\r\n\t\t\t\t// Could patch `.afterItemsHeight` of `this.previouslyCalculatedLayout` here,\r\n\t\t\t\t// if `.afterItemsHeight` property existed in `this.previouslyCalculatedLayout`.\r\n\t\t\t\tif (this.previouslyCalculatedLayout.afterItemsHeight !== undefined) {\r\n\t\t\t\t\tthis.previouslyCalculatedLayout.afterItemsHeight += heightDifference\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t// Patch `this.previouslyCalculatedLayout`'s shown items height.\r\n\t\t\t\tthis.previouslyCalculatedLayout.shownItemsHeight += newHeight - previousHeight\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the list's top offset relative to the scrollable container's top edge.\r\n\t * @return {number}\r\n\t */\r\n\tthis.getListTopOffsetInsideScrollableContainer = () => {\r\n\t\tconst listTopOffset = this.scrollableContainer.getItemsContainerTopOffset()\r\n\t\tif (this.listTopOffsetWatcher) {\r\n\t\t\tthis.listTopOffsetWatcher.onListTopOffset(listTopOffset)\r\n\t\t}\r\n\t\treturn listTopOffset\r\n\t}\r\n\r\n\tthis._onItemHeightChange = (i) => {\r\n\t\tlog('~ Re-measure item height ~')\r\n\t\tlog('Item index', i)\r\n\r\n\t\tconst {\r\n\t\t\titemHeights,\r\n\t\t\tfirstShownItemIndex,\r\n\t\t\tlastShownItemIndex\r\n\t\t} = this.getState()\r\n\r\n\t\t// Check if the item is still rendered.\r\n\t\tif (!(i >= firstShownItemIndex && i <= lastShownItemIndex)) {\r\n\t\t\t// There could be valid cases when an item is no longer rendered\r\n\t\t\t// by the time `.onItemHeightChange(i)` gets called.\r\n\t\t\t// For example, suppose there's a list of several items on a page,\r\n\t\t\t// and those items are in \"minimized\" state (having height 100px).\r\n\t\t\t// Then, a user clicks an \"Expand all items\" button, and all items\r\n\t\t\t// in the list are expanded (expanded item height is gonna be 700px).\r\n\t\t\t// `VirtualScroller` demands that `.onItemHeightChange(i)` is called\r\n\t\t\t// in such cases, and the developer has properly added the code to do that.\r\n\t\t\t// So, if there were 10 \"minimized\" items visible on a page, then there\r\n\t\t\t// will be 10 individual `.onItemHeightChange(i)` calls. No issues so far.\r\n\t\t\t// But, as the first `.onItemHeightChange(i)` call executes, it immediately\r\n\t\t\t// (\"synchronously\") triggers a re-layout, and that re-layout finds out\r\n\t\t\t// that now, because the first item is big, it occupies most of the screen\r\n\t\t\t// space, and only the first 3 items are visible on screen instead of 10,\r\n\t\t\t// and so it leaves the first 3 items mounted and unmounts the rest 7.\r\n\t\t\t// Then, after `VirtualScroller` has rerendered, the code returns to\r\n\t\t\t// where it was executing, and calls `.onItemHeightChange(i)` for the\r\n\t\t\t// second item. It also triggers an immediate re-layout that finds out\r\n\t\t\t// that only the first 2 items are visible on screen, and it unmounts\r\n\t\t\t// the third one too. After that, it calls `.onItemHeightChange(i)`\r\n\t\t\t// for the third item, but that item is no longer rendered, so its height\r\n\t\t\t// can't be measured, and the same's for all the rest of the original 10 items.\r\n\t\t\t// So, even though the developer has written their code properly, there're\r\n\t\t\t// still situations when the item could be no longer rendered by the time\r\n\t\t\t// `.onItemHeightChange(i)` gets called.\r\n\t\t\treturn warn('The item is no longer rendered. This is not necessarily a bug, and could happen, for example, when when a developer calls `onItemHeightChange(i)` while looping through a batch of items.')\r\n\t\t}\r\n\r\n\t\tconst previousHeight = itemHeights[i]\r\n\t\tif (previousHeight === undefined) {\r\n\t\t\treturn reportError(`\"onItemHeightChange()\" has been called for item ${i}, but that item hasn't been rendered before.`)\r\n\t\t}\r\n\r\n\t\tconst newHeight = remeasureItemHeight.call(this, i)\r\n\r\n\t\tlog('Previous height', previousHeight)\r\n\t\tlog('New height', newHeight)\r\n\r\n\t\tif (previousHeight !== newHeight) {\r\n\t\t\tlog('~ Item height has changed ~')\r\n\r\n\t\t\t// Update or reset previously calculated layout.\r\n\t\t\tupdatePreviouslyCalculatedLayoutOnItemHeightChange.call(this, i, previousHeight, newHeight)\r\n\r\n\t\t\t// Recalculate layout.\r\n\t\t\tthis.onUpdateShownItemIndexes({ reason: LAYOUT_REASON.ITEM_HEIGHT_CHANGED })\r\n\r\n\t\t\t// Schedule the item height update for after the new items have been rendered.\r\n\t\t\tif (this.newItemsWillBeRendered) {\r\n\t\t\t\tif (!this.itemHeightsThatChangedWhileNewItemsWereBeingRendered) {\r\n\t\t\t\t\tthis.itemHeightsThatChangedWhileNewItemsWereBeingRendered = {}\r\n\t\t\t\t}\r\n\t\t\t\tthis.itemHeightsThatChangedWhileNewItemsWereBeingRendered[String(i)] = newHeight\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tthis.getPrerenderMargin = () => {\r\n\t\t// The list component renders not only the items that're currently visible\r\n\t\t// but also the items that lie within some extra vertical margin (called\r\n\t\t// \"prerender margin\") on top and bottom for future scrolling: this way,\r\n\t\t// there'll be significantly less layout recalculations as the user scrolls,\r\n\t\t// because now it doesn't have to recalculate layout on each scroll event.\r\n\t\t// By default, the \"prerender margin\" is equal to the screen height:\r\n\t\t// this seems to be the optimal value for \"Page Up\" / \"Page Down\" navigation\r\n\t\t// and optimized mouse wheel scrolling (a user is unlikely to continuously\r\n\t\t// scroll past the screen height, because they'd stop to read through\r\n\t\t// the newly visible items first, and when they do stop scrolling, that's\r\n\t\t// when layout gets recalculated).\r\n\t\tconst renderAheadMarginRatio = 1 // in scrollable container heights.\r\n\t\treturn this.scrollableContainer.getHeight() * renderAheadMarginRatio\r\n\t}\r\n\r\n\t/**\r\n\t * Calls `onItemFirstRender()` for items that haven't been\r\n\t * \"seen\" previously.\r\n\t * @param {any[]} items\r\n\t * @param {number[]} itemHeights\r\n\t * @param {number} firstShownItemIndex\r\n\t * @param {number} lastShownItemIndex\r\n\t */\r\n\tthis.onBeforeShowItems = (\r\n\t\titems,\r\n\t\titemHeights,\r\n\t\tfirstShownItemIndex,\r\n\t\tlastShownItemIndex\r\n\t) => {\r\n\t\tif (this.onItemInitialRender) {\r\n\t\t\tlet i = firstShownItemIndex\r\n\t\t\twhile (i <= lastShownItemIndex) {\r\n\t\t\t\tif (itemHeights[i] === undefined) {\r\n\t\t\t\t\tthis.onItemInitialRender(items[i])\r\n\t\t\t\t}\r\n\t\t\t\ti++\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tthis.measureItemHeightsAndSpacing = () => {\r\n\t\t// Measure \"newly shown\" item heights.\r\n\t\t// Also re-validate already measured items' heights.\r\n\t\tthis.itemHeights.measureItemHeights(\r\n\t\t\tthis.getState().firstShownItemIndex,\r\n\t\t\tthis.getState().lastShownItemIndex\r\n\t\t)\r\n\r\n\t\t// Measure item vertical spacing, if required.\r\n\t\tconst verticalSpacing = this.measureVerticalSpacingIfNotMeasured()\r\n\r\n\t\t// Return a state update if vertical spacing has been measured.\r\n\t\t// Doesn't set `verticalSpacing: 0` in `state` because it is effectively\r\n\t\t// same as `verticalSpacing: undefined` in terms code behavior and calculations.\r\n\t\t// Not having `verticalSpacing: 0` in `state` just makes the `state` object\r\n\t\t// a bit more cleaner and a bit less cluttered (easier for inspection).\r\n\t\tif (verticalSpacing && verticalSpacing !== 0) {\r\n\t\t\t// Return a state update.\r\n\t\t\t// Sets `verticalSpacing` property in `state`.\r\n\t\t\treturn {\r\n\t\t\t\tverticalSpacing\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tthis.cancelLayoutTimer = ({ stateUpdate }) => {\r\n\t\tif (this.layoutTimer) {\r\n\t\t\tclearTimeout(this.layoutTimer)\r\n\t\t\tthis.layoutTimer = undefined\r\n\t\t\t// Merge state updates.\r\n\t\t\tif (stateUpdate || this.layoutTimerStateUpdate) {\r\n\t\t\t\tstateUpdate = {\r\n\t\t\t\t\t...this.layoutTimerStateUpdate,\r\n\t\t\t\t\t...stateUpdate\r\n\t\t\t\t}\r\n\t\t\t\tthis.layoutTimerStateUpdate = undefined\r\n\t\t\t\treturn stateUpdate\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\treturn stateUpdate\r\n\t\t}\r\n\t}\r\n\r\n\tthis.scheduleLayoutTimer = ({ reason, stateUpdate }) => {\r\n\t\tthis.layoutTimerStateUpdate = stateUpdate\r\n\t\tthis.layoutTimer = setTimeout(() => {\r\n\t\t\tthis.layoutTimerStateUpdate = undefined\r\n\t\t\tthis.layoutTimer = undefined\r\n\t\t\tthis.onUpdateShownItemIndexes({\r\n\t\t\t\treason,\r\n\t\t\t\tstateUpdate\r\n\t\t\t})\r\n\t\t}, 0)\r\n\t}\r\n}\r\n\r\nconst SLOW_LAYOUT_DURATION = 15 // in milliseconds."],"mappings":";;;;;;;;;AAIA;;AAEA;;AACA;;;;;;;;;;;;AAEe,oBAAW;EAAA;;EACzB,KAAKA,wBAAL,GAAgC,gBAA6B;IAAA,IAA1BC,MAA0B,QAA1BA,MAA0B;IAAA,IAAlBC,WAAkB,QAAlBA,WAAkB;;IAC5D;IACA,IAAMC,IAAI,GAAG,SAAPA,IAAO,GAAM;MAClB,IAAID,WAAJ,EAAiB;QAChB,KAAI,CAACE,WAAL,CAAiBF,WAAjB;MACA;IACD,CAJD,CAF4D,CAQ5D;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;IACA,IAAI,KAAI,CAACG,sBAAL,IAA+B,KAAI,CAACC,eAApC,IAAuD,KAAI,CAACC,WAAhE,EAA6E;MAC5E,OAAOJ,IAAI,EAAX;IACA,CApB2D,CAsB5D;;;IACA,IAAI,KAAI,CAACK,aAAL,OAAyB,CAA7B,EAAgC;MAC/B,OAAOL,IAAI,EAAX;IACA,CAzB2D,CA2B5D;;;IACA,KAAI,CAACM,MAAL,CAAYC,qBAAZ,GA5B4D,CA8B5D;IACA;;;IACAR,WAAW,GAAG,KAAI,CAACS,iBAAL,CAAuB;MAAET,WAAW,EAAXA;IAAF,CAAvB,CAAd,CAhC4D,CAkC5D;;IACA,IAAAU,iBAAA,gCAA2BX,MAA3B;IACAY,sBAAsB,CAACC,IAAvB,CAA4B,KAA5B,EAAkC;MAAEZ,WAAW,EAAXA;IAAF,CAAlC;EACA,CArCD;EAuCA;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;EACC,SAASW,sBAAT,QAAiD;IAAA,IAAfX,WAAe,SAAfA,WAAe;IAChD,IAAMa,SAAS,GAAGC,IAAI,CAACC,GAAL,EAAlB,CADgD,CAGhD;;IACA,4BAKIC,mBAAmB,CAACJ,IAApB,CAAyB,IAAzB,CALJ;IAAA,IACCK,mBADD,yBACCA,mBADD;IAAA,IAECC,kBAFD,yBAECA,kBAFD;IAAA,IAGCC,gBAHD,yBAGCA,gBAHD;IAAA,IAICC,yBAJD,yBAICA,yBAJD,CAJgD,CAWhD;IACA;IACA;IACA;IACA;;;IACA,IAAI,KAAKC,qBAAL,CAA2BC,WAA3B,EAAJ,EAA8C;MAC7C,IAAIJ,kBAAkB,GAAG,KAAKG,qBAAL,CAA2BE,kBAA3B,EAAzB,EAA0E;QACzEL,kBAAkB,GAAG,KAAKG,qBAAL,CAA2BE,kBAA3B,EAArB;MACA,CAH4C,CAI7C;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;;;MACAH,yBAAyB,GAAGI,SAA5B;IACA,CAnC+C,CAqChD;IACA;IACA;IACA;IACA;IACA;;;IACA,IAAI,CAACC,0CAA0C,CAACb,IAA3C,CAAgD,IAAhD,EAAsDK,mBAAtD,EAA2EC,kBAA3E,CAAL,EAAqG;MACpG,IAAAR,iBAAA,EAAI,iIAAJ,EADoG,CAEpG;;MACA,OAAOC,sBAAsB,CAACC,IAAvB,CAA4B,IAA5B,EAAkC;QAAEZ,WAAW,EAAXA;MAAF,CAAlC,CAAP;IACA,CA/C+C,CAiDhD;;;IACA,IAAM0B,iBAAiB,GAAG,KAAKC,MAAL,CAAYC,oBAAZ,CACzBX,mBADyB,CAA1B,CAlDgD,CAsDhD;;IACA,IAAMY,gBAAgB,GAAG,KAAKF,MAAL,CAAYG,mBAAZ,CACxBZ,kBADwB,EAExB,KAAKZ,aAAL,EAFwB,CAAzB;IAKA,IAAMyB,cAAc,GAAGjB,IAAI,CAACC,GAAL,KAAaF,SAApC,CA5DgD,CA8DhD;;IACA,IAAAH,iBAAA,EAAI,yBAAyB,KAAKsB,MAAL,GAAc,WAAd,GAA4B,EAArD,IAA2D,IAA/D;;IACA,IAAID,cAAc,GAAGE,oBAArB,EAA2C,CAC1C;IACA,CAFD,MAEO;MACN,IAAAC,WAAA,EAAK,sBAAL,EAA6BH,cAA7B,EAA6C,IAA7C;IACA;;IACD,IAAI,KAAKI,eAAL,EAAJ,EAA4B;MAC3B,IAAAzB,iBAAA,EAAI,eAAJ,EAAqB,KAAKyB,eAAL,EAArB;IACA;;IACD,IAAAzB,iBAAA,EAAI,wBAAJ,EAA8BO,mBAA9B;IACA,IAAAP,iBAAA,EAAI,uBAAJ,EAA6BQ,kBAA7B;IACA,IAAAR,iBAAA,EAAI,qBAAJ,EAA2BgB,iBAA3B;IACA,IAAAhB,iBAAA,EAAI,0CAAJ,EAAgDmB,gBAAhD;IACA,IAAAnB,iBAAA,EAAI,yEAAJ,EAA+E,KAAK0B,WAAL,CAAiBC,UAAjB,EAA/E;;IACA,IAAI,IAAAC,cAAA,GAAJ,EAAe;MACd,IAAA5B,iBAAA,EAAI,cAAJ,EAAoB,KAAK6B,QAAL,GAAgBH,WAAhB,CAA4BI,KAA5B,EAApB;MACA,IAAA9B,iBAAA,EAAI,aAAJ,EAAmB,KAAK6B,QAAL,GAAgBE,UAAhB,CAA2BD,KAA3B,EAAnB;IACA,CAhF+C,CAkFhD;;;IACA,KAAKE,iBAAL,CACC,KAAKH,QAAL,GAAgBI,KADjB,EAEC,KAAKJ,QAAL,GAAgBH,WAFjB,EAGCnB,mBAHD,EAICC,kBAJD,EAnFgD,CA0FhD;;IACA,KAAKE,yBAAL,GAAiCA,yBAAjC,CA3FgD,CA6FhD;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;IACA,IAAID,gBAAgB,KAAKK,SAAzB,EAAoC;MACnC,KAAKoB,0BAAL,GAAkCpB,SAAlC;IACA,CAFD,MAEO;MACN;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,KAAKoB,0BAAL,GAAkC;QACjC3B,mBAAmB,EAAnBA,mBADiC;QAEjCC,kBAAkB,EAAlBA,kBAFiC;QAGjCQ,iBAAiB,EAAjBA,iBAHiC;QAIjCP,gBAAgB,EAAhBA;MAJiC,CAAlC;IAMA,CApI+C,CAsIhD;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;IACA,KAAKjB,WAAL;MACCe,mBAAmB,EAAnBA,mBADD;MAECC,kBAAkB,EAAlBA,kBAFD;MAGCQ,iBAAiB,EAAjBA,iBAHD;MAICG,gBAAgB,EAAhBA;IAJD,GAKI7B,WALJ;EAOA;;EAED,SAAS6C,cAAT,GAA0B;IACzB,IAAMC,WAAW,GAAG,KAAKvC,MAAL,CAAYwC,oBAAZ,EAApB;IACA,KAAKC,uBAAL,GAA+BF,WAA/B,CAFyB,CAIzB;;IACA,IAAMG,sCAAsC,GAAG,KAAKC,yCAAL,EAA/C;IACA,OAAO;MACNC,GAAG,EAAEL,WAAW,CAACK,GAAZ,GAAkBF,sCADjB;MAENG,MAAM,EAAEN,WAAW,CAACM,MAAZ,GAAqBH;IAFvB,CAAP;EAIA;;EAED,SAASjC,mBAAT,GAA+B;IAC9B,IAAMqC,UAAU,GAAG,KAAK/C,aAAL,EAAnB;;IAEA,2BAGIuC,cAAc,CAACjC,IAAf,CAAoB,IAApB,CAHJ;IAAA,IACM0C,cADN,wBACCH,GADD;IAAA,IAESI,iBAFT,wBAECH,MAFD;;IAKA,IAAI,KAAKpB,MAAT,EAAiB;MAChB,OAAO;QACNf,mBAAmB,EAAE,CADf;QAENC,kBAAkB,EAAEmC,UAAU,GAAG,CAF3B,CAGN;;MAHM,CAAP;IAKA,CAd6B,CAgB9B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;IACA,IAAMG,SAAS,GAAGF,cAAc,GAAG,KAAKG,cAAL,CAAoBC,SAApB,EAAjB,IAAoDH,iBAAiB,GAAG,CAA1F;;IACA,IAAI,CAACC,SAAL,EAAgB;MACf,IAAA9C,iBAAA,EAAI,sDAAJ;MACA,OAAO,KAAKiB,MAAL,CAAYgC,iCAAZ,EAAP;IACA,CA7B6B,CA+B9B;;;IACA,OAAO,KAAKhC,MAAL,CAAYX,mBAAZ,CAAgC;MACtCqC,UAAU,EAAE,KAAK/C,aAAL,EAD0B;MAEtCgD,cAAc,EAAdA,cAFsC;MAGtCC,iBAAiB,EAAjBA;IAHsC,CAAhC,CAAP;EAKA;EAED;AACD;AACA;AACA;AACA;AACA;AACA;AACA;;;EACC,SAAS9B,0CAAT,CAAoDR,mBAApD,EAAyEC,kBAAzE,EAA6F;IAC5F,IAAI0C,OAAO,GAAG,IAAd;IACA,IAAIC,CAAC,GAAG,KAAKtB,QAAL,GAAgBtB,mBAAxB;;IACA,OAAO4C,CAAC,IAAI,KAAKtB,QAAL,GAAgBrB,kBAA5B,EAAgD;MAC/C,IAAI2C,CAAC,IAAI5C,mBAAL,IAA4B4C,CAAC,IAAI3C,kBAArC,EAAyD,CACxD;MACA,CAFD,MAEO;QACN;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,IAAM4C,4BAA4B,GAAG,KAAKvB,QAAL,GAAgBH,WAAhB,CAA4ByB,CAA5B,CAArC;QACA,IAAME,gBAAgB,GAAGC,mBAAmB,CAACpD,IAApB,CAAyB,IAAzB,EAA+BiD,CAA/B,CAAzB;;QACA,IAAIE,gBAAgB,KAAKD,4BAAzB,EAAuD;UACtD,IAAIF,OAAJ,EAAa;YACZ,IAAAlD,iBAAA,EAAI,2CAAJ,EADY,CAEZ;;YACAuD,kDAAkD,CAACrD,IAAnD,CAAwD,IAAxD,EAA8DiD,CAA9D,EAAiEC,4BAAjE,EAA+FC,gBAA/F;UACA;;UACDH,OAAO,GAAG,KAAV;UACA,IAAA1B,WAAA,EAAK,YAAL,EAAmB2B,CAAnB,EAAsB,yEAAtB,EAAiGC,4BAAjG,EAA+H,IAA/H,EAAqIC,gBAArI,EAAuJ,qSAAvJ;QACA;MACD;;MACDF,CAAC;IACD;;IACD,OAAOD,OAAP;EACA;;EAED,SAASI,mBAAT,CAA6BH,CAA7B,EAAgC;IAC/B,qBAAgC,KAAKtB,QAAL,EAAhC;IAAA,IAAQtB,mBAAR,kBAAQA,mBAAR;;IACA,OAAO,KAAKmB,WAAL,CAAiB4B,mBAAjB,CAAqCH,CAArC,EAAwC5C,mBAAxC,CAAP;EACA,CAlUwB,CAoUzB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;EACA,SAASgD,kDAAT,CAA4DJ,CAA5D,EAA+DK,cAA/D,EAA+EC,SAA/E,EAA0F;IACzF,IAAI,KAAKvB,0BAAT,EAAqC;MACpC,IAAMwB,gBAAgB,GAAGD,SAAS,GAAGD,cAArC;;MACA,IAAIL,CAAC,GAAG,KAAKjB,0BAAL,CAAgC3B,mBAAxC,EAA6D;QAC5D;QACA,KAAK2B,0BAAL,CAAgClB,iBAAhC,IAAqD0C,gBAArD;MACA,CAHD,MAGO,IAAIP,CAAC,GAAG,KAAKjB,0BAAL,CAAgC1B,kBAAxC,EAA4D;QAClE;QACA;QACA,IAAI,KAAK0B,0BAAL,CAAgCf,gBAAhC,KAAqDL,SAAzD,EAAoE;UACnE,KAAKoB,0BAAL,CAAgCf,gBAAhC,IAAoDuC,gBAApD;QACA;MACD,CANM,MAMA;QACN;QACA,KAAKxB,0BAAL,CAAgCzB,gBAAhC,IAAoDgD,SAAS,GAAGD,cAAhE;MACA;IACD;EACD;EAED;AACD;AACA;AACA;;;EACC,KAAKhB,yCAAL,GAAiD,YAAM;IACtD,IAAMmB,aAAa,GAAG,KAAI,CAACC,mBAAL,CAAyBC,0BAAzB,EAAtB;;IACA,IAAI,KAAI,CAACC,oBAAT,EAA+B;MAC9B,KAAI,CAACA,oBAAL,CAA0BC,eAA1B,CAA0CJ,aAA1C;IACA;;IACD,OAAOA,aAAP;EACA,CAND;;EAQA,KAAKK,mBAAL,GAA2B,UAACb,CAAD,EAAO;IACjC,IAAAnD,iBAAA,EAAI,4BAAJ;IACA,IAAAA,iBAAA,EAAI,YAAJ,EAAkBmD,CAAlB;;IAEA,sBAII,KAAI,CAACtB,QAAL,EAJJ;IAAA,IACCH,WADD,mBACCA,WADD;IAAA,IAECnB,mBAFD,mBAECA,mBAFD;IAAA,IAGCC,kBAHD,mBAGCA,kBAHD,CAJiC,CAUjC;;;IACA,IAAI,EAAE2C,CAAC,IAAI5C,mBAAL,IAA4B4C,CAAC,IAAI3C,kBAAnC,CAAJ,EAA4D;MAC3D;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,OAAO,IAAAgB,WAAA,EAAK,2LAAL,CAAP;IACA;;IAED,IAAMgC,cAAc,GAAG9B,WAAW,CAACyB,CAAD,CAAlC;;IACA,IAAIK,cAAc,KAAK1C,SAAvB,EAAkC;MACjC,OAAO,IAAAmD,kBAAA,8DAA+Dd,CAA/D,kDAAP;IACA;;IAED,IAAMM,SAAS,GAAGH,mBAAmB,CAACpD,IAApB,CAAyB,KAAzB,EAA+BiD,CAA/B,CAAlB;IAEA,IAAAnD,iBAAA,EAAI,iBAAJ,EAAuBwD,cAAvB;IACA,IAAAxD,iBAAA,EAAI,YAAJ,EAAkByD,SAAlB;;IAEA,IAAID,cAAc,KAAKC,SAAvB,EAAkC;MACjC,IAAAzD,iBAAA,EAAI,6BAAJ,EADiC,CAGjC;;MACAuD,kDAAkD,CAACrD,IAAnD,CAAwD,KAAxD,EAA8DiD,CAA9D,EAAiEK,cAAjE,EAAiFC,SAAjF,EAJiC,CAMjC;;MACA,KAAI,CAACrE,wBAAL,CAA8B;QAAEC,MAAM,EAAE6E,qBAAA,CAAcC;MAAxB,CAA9B,EAPiC,CASjC;;;MACA,IAAI,KAAI,CAAC1E,sBAAT,EAAiC;QAChC,IAAI,CAAC,KAAI,CAAC2E,oDAAV,EAAgE;UAC/D,KAAI,CAACA,oDAAL,GAA4D,EAA5D;QACA;;QACD,KAAI,CAACA,oDAAL,CAA0DC,MAAM,CAAClB,CAAD,CAAhE,IAAuEM,SAAvE;MACA;IACD;EACD,CAnED;;EAqEA,KAAKa,kBAAL,GAA0B,YAAM;IAC/B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA,IAAMC,sBAAsB,GAAG,CAA/B,CAZ+B,CAYE;;IACjC,OAAO,KAAI,CAACX,mBAAL,CAAyBZ,SAAzB,KAAuCuB,sBAA9C;EACA,CAdD;EAgBA;AACD;AACA;AACA;AACA;AACA;AACA;AACA;;;EACC,KAAKvC,iBAAL,GAAyB,UACxBC,KADwB,EAExBP,WAFwB,EAGxBnB,mBAHwB,EAIxBC,kBAJwB,EAKpB;IACJ,IAAI,KAAI,CAACgE,mBAAT,EAA8B;MAC7B,IAAIrB,CAAC,GAAG5C,mBAAR;;MACA,OAAO4C,CAAC,IAAI3C,kBAAZ,EAAgC;QAC/B,IAAIkB,WAAW,CAACyB,CAAD,CAAX,KAAmBrC,SAAvB,EAAkC;UACjC,KAAI,CAAC0D,mBAAL,CAAyBvC,KAAK,CAACkB,CAAD,CAA9B;QACA;;QACDA,CAAC;MACD;IACD;EACD,CAfD;;EAiBA,KAAKsB,4BAAL,GAAoC,YAAM;IACzC;IACA;IACA,KAAI,CAAC/C,WAAL,CAAiBgD,kBAAjB,CACC,KAAI,CAAC7C,QAAL,GAAgBtB,mBADjB,EAEC,KAAI,CAACsB,QAAL,GAAgBrB,kBAFjB,EAHyC,CAQzC;;;IACA,IAAMmE,eAAe,GAAG,KAAI,CAACC,mCAAL,EAAxB,CATyC,CAWzC;IACA;IACA;IACA;IACA;;;IACA,IAAID,eAAe,IAAIA,eAAe,KAAK,CAA3C,EAA8C;MAC7C;MACA;MACA,OAAO;QACNA,eAAe,EAAfA;MADM,CAAP;IAGA;EACD,CAvBD;;EAyBA,KAAK5E,iBAAL,GAAyB,iBAAqB;IAAA,IAAlBT,WAAkB,SAAlBA,WAAkB;;IAC7C,IAAI,KAAI,CAACuF,WAAT,EAAsB;MACrB,IAAAC,0CAAA,EAAa,KAAI,CAACD,WAAlB;MACA,KAAI,CAACA,WAAL,GAAmB/D,SAAnB,CAFqB,CAGrB;;MACA,IAAIxB,WAAW,IAAI,KAAI,CAACyF,sBAAxB,EAAgD;QAC/CzF,WAAW,mCACP,KAAI,CAACyF,sBADE,GAEPzF,WAFO,CAAX;QAIA,KAAI,CAACyF,sBAAL,GAA8BjE,SAA9B;QACA,OAAOxB,WAAP;MACA;IACD,CAZD,MAYO;MACN,OAAOA,WAAP;IACA;EACD,CAhBD;;EAkBA,KAAK0F,mBAAL,GAA2B,iBAA6B;IAAA,IAA1B3F,MAA0B,SAA1BA,MAA0B;IAAA,IAAlBC,WAAkB,SAAlBA,WAAkB;IACvD,KAAI,CAACyF,sBAAL,GAA8BzF,WAA9B;IACA,KAAI,CAACuF,WAAL,GAAmB,IAAAI,wCAAA,EAAW,YAAM;MACnC,KAAI,CAACF,sBAAL,GAA8BjE,SAA9B;MACA,KAAI,CAAC+D,WAAL,GAAmB/D,SAAnB;;MACA,KAAI,CAAC1B,wBAAL,CAA8B;QAC7BC,MAAM,EAANA,MAD6B;QAE7BC,WAAW,EAAXA;MAF6B,CAA9B;IAIA,CAPkB,EAOhB,CAPgB,CAAnB;EAQA,CAVD;AAWA;;AAED,IAAMiC,oBAAoB,GAAG,EAA7B,C,CAAgC"}
|
|
1
|
+
{"version":3,"file":"VirtualScroller.layout.js","names":["onUpdateShownItemIndexes","reason","stateUpdate","skip","updateState","newItemsWillBeRendered","widthHasChanged","_isResizing","getItemsCount","scroll","cancelScheduledLayout","cancelLayoutTimer","log","updateShownItemIndexes","call","startedAt","Date","now","getShownItemIndexes","firstShownItemIndex","lastShownItemIndex","shownItemsHeight","firstNonMeasuredItemIndex","listHeightMeasurement","hasSnapshot","getAnchorItemIndex","undefined","validateWillBeHiddenItemHeightsAreAccurate","beforeItemsHeight","layout","getBeforeItemsHeight","afterItemsHeight","getAfterItemsHeight","layoutDuration","bypass","SLOW_LAYOUT_DURATION","warn","getColumnsCount","itemHeights","getAverage","isDebug","getState","slice","itemStates","onBeforeShowItems","items","previouslyCalculatedLayout","getVisibleArea","visibleArea","getVisibleAreaBounds","latestLayoutVisibleArea","listTopOffsetInsideScrollableContainer","getListTopOffsetInsideScrollableContainer","top","bottom","itemsCount","visibleAreaTop","visibleAreaBottom","isVisible","itemsContainer","getHeight","getNonVisibleListShownItemIndexes","isValid","i","previouslyMeasuredItemHeight","actualItemHeight","remeasureItemHeight","updatePreviouslyCalculatedLayoutOnItemHeightChange","previousHeight","newHeight","prevLayout","heightDifference","listTopOffset","scrollableContainer","getItemsContainerTopOffset","listTopOffsetWatcher","onListTopOffset","_onItemHeightDidChange","reportError","error","ItemNotRenderedError","message","waitingForRender","updateLayoutAfterRenderBecauseItemHeightChanged","LAYOUT_REASON","ITEM_HEIGHT_CHANGED","itemHeightsThatChangedWhileNewItemsWereBeingRendered","String","getPrerenderMargin","renderAheadMarginRatio","onItemInitialRender","measureItemHeightsAndSpacing","measureItemHeights","verticalSpacing","measureVerticalSpacingIfNotMeasured","layoutTimer","clearTimeout","layoutTimerStateUpdate","scheduleLayoutTimer","setTimeout"],"sources":["../source/VirtualScroller.layout.js"],"sourcesContent":["// For some weird reason, in Chrome, `setTimeout()` would lag up to a second (or more) behind.\r\n// Turns out, Chrome developers have deprecated `setTimeout()` API entirely without asking anyone.\r\n// Replacing `setTimeout()` with `requestAnimationFrame()` can work around that Chrome bug.\r\n// https://github.com/bvaughn/react-virtualized/issues/722\r\nimport { setTimeout, clearTimeout } from 'request-animation-frame-timeout'\r\n\r\nimport log, { warn, isDebug, reportError } from './utility/debug.js'\r\nimport { LAYOUT_REASON } from './Layout.js'\r\n\r\nimport ItemNotRenderedError from './ItemNotRenderedError.js'\r\n\r\nexport default function() {\r\n\tthis.onUpdateShownItemIndexes = ({ reason, stateUpdate }) => {\r\n\t\t// In case of \"don't do anything\".\r\n\t\tconst skip = () => {\r\n\t\t\tif (stateUpdate) {\r\n\t\t\t\tthis.updateState(stateUpdate)\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If new `items` have been set and are waiting to be applied,\r\n\t\t// or if the viewport width has changed requiring a re-layout,\r\n\t\t// then temporarily stop all other updates like \"on scroll\" updates.\r\n\t\t// This prevents `state` being inconsistent, because, for example,\r\n\t\t// both `setItems()` and this function could update `VirtualScroller` state\r\n\t\t// and having them operate in parallel could result in incorrectly calculated\r\n\t\t// `beforeItemsHeight` / `afterItemsHeight` / `firstShownItemIndex` /\r\n\t\t// `lastShownItemIndex`, because, when operating in parallel, this function\r\n\t\t// would have different `items` than the `setItems()` function, so their\r\n\t\t// results could diverge.\r\n\t\tif (this.newItemsWillBeRendered || this.widthHasChanged || this._isResizing) {\r\n\t\t\treturn skip()\r\n\t\t}\r\n\r\n\t\t// If there're no items then there's no need to re-layout anything.\r\n\t\tif (this.getItemsCount() === 0) {\r\n\t\t\treturn skip()\r\n\t\t}\r\n\r\n\t\t// Cancel a \"re-layout when user stops scrolling\" timer.\r\n\t\tthis.scroll.cancelScheduledLayout()\r\n\r\n\t\t// Cancel a re-layout that is scheduled to run at the next \"frame\",\r\n\t\t// because a re-layout will be performed right now.\r\n\t\tstateUpdate = this.cancelLayoutTimer({ stateUpdate })\r\n\r\n\t\t// Perform a re-layout.\r\n\t\tlog(`~ Update Layout (on ${reason}) ~`)\r\n\t\tupdateShownItemIndexes.call(this, { stateUpdate })\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the \"from\" and \"to\" shown item indexes.\r\n\t * If the list is visible and some of the items being shown are new\r\n\t * and are required to be measured first, then\r\n\t * `firstNonMeasuredItemIndex` is defined.\r\n\t * If the list is visible and all items being shown have been encountered\r\n\t * (and measured) before, then `firstNonMeasuredItemIndex` is `undefined`.\r\n\t *\r\n\t * The `stateUpdate` parameter is just an optional \"additional\" state update.\r\n\t */\r\n\tfunction updateShownItemIndexes({ stateUpdate }) {\r\n\t\tconst startedAt = Date.now()\r\n\r\n\t\t// Get shown item indexes.\r\n\t\tlet {\r\n\t\t\tfirstShownItemIndex,\r\n\t\t\tlastShownItemIndex,\r\n\t\t\tshownItemsHeight,\r\n\t\t\tfirstNonMeasuredItemIndex\r\n\t\t} = getShownItemIndexes.call(this)\r\n\r\n\t\t// If scroll position is scheduled to be restored after render,\r\n\t\t// then the \"anchor\" item must be rendered, and all of the prepended\r\n\t\t// items before it, all in a single pass. This way, all of the\r\n\t\t// prepended items' heights could be measured right after the render\r\n\t\t// has finished, and the scroll position can then be immediately restored.\r\n\t\tif (this.listHeightMeasurement.hasSnapshot()) {\r\n\t\t\tif (lastShownItemIndex < this.listHeightMeasurement.getAnchorItemIndex()) {\r\n\t\t\t\tlastShownItemIndex = this.listHeightMeasurement.getAnchorItemIndex()\r\n\t\t\t}\r\n\t\t\t// `firstShownItemIndex` is always `0` when prepending items.\r\n\t\t\t// And `lastShownItemIndex` always covers all prepended items in this case.\r\n\t\t\t// None of the prepended items have been rendered before,\r\n\t\t\t// so their heights are unknown. The code at the start of this function\r\n\t\t\t// did therefore set `firstNonMeasuredItemIndex` to non-`undefined`\r\n\t\t\t// in order to render just the first prepended item in order to\r\n\t\t\t// measure it, and only then make a decision on how many other\r\n\t\t\t// prepended items to render. But since we've instructed the code\r\n\t\t\t// to show all of the prepended items at once, there's no need to\r\n\t\t\t// \"redo layout after render\". Additionally, if layout was re-done\r\n\t\t\t// after render, then there would be a short interval of visual\r\n\t\t\t// \"jitter\" due to the scroll position not being restored because it'd\r\n\t\t\t// wait for the second layout to finish instead of being restored\r\n\t\t\t// right after the first one.\r\n\t\t\tfirstNonMeasuredItemIndex = undefined\r\n\t\t}\r\n\r\n\t\t// Validate the heights of items to be hidden on next render.\r\n\t\t// For example, a user could click a \"Show more\" button,\r\n\t\t// or an \"Expand YouTube video\" button, which would result\r\n\t\t// in the actual height of the list item being different\r\n\t\t// from what has been initially measured in `this.itemHeights[i]`,\r\n\t\t// if the developer didn't call `.setItemState(i, newState)` and `.onItemHeightDidChange(i)`.\r\n\t\tif (!validateWillBeHiddenItemHeightsAreAccurate.call(this, firstShownItemIndex, lastShownItemIndex)) {\r\n\t\t\tlog('~ Because some of the will-be-hidden item heights (listed above) have changed since they\\'ve last been measured, redo layout. ~')\r\n\t\t\t// Redo layout, now with the correct item heights.\r\n\t\t\treturn updateShownItemIndexes.call(this, { stateUpdate });\r\n\t\t}\r\n\r\n\t\t// Measure \"before\" items height.\r\n\t\tconst beforeItemsHeight = this.layout.getBeforeItemsHeight(\r\n\t\t\tfirstShownItemIndex\r\n\t\t)\r\n\r\n\t\t// Measure \"after\" items height.\r\n\t\tconst afterItemsHeight = this.layout.getAfterItemsHeight(\r\n\t\t\tlastShownItemIndex,\r\n\t\t\tthis.getItemsCount()\r\n\t\t)\r\n\r\n\t\tconst layoutDuration = Date.now() - startedAt\r\n\r\n\t\t// Debugging.\r\n\t\tlog('~ Calculated Layout' + (this.bypass ? ' (bypass)' : '') + ' ~')\r\n\t\tif (layoutDuration < SLOW_LAYOUT_DURATION) {\r\n\t\t\t// log('Calculated in', layoutDuration, 'ms')\r\n\t\t} else {\r\n\t\t\twarn('Layout calculated in', layoutDuration, 'ms')\r\n\t\t}\r\n\t\tif (this.getColumnsCount()) {\r\n\t\t\tlog('Columns count', this.getColumnsCount())\r\n\t\t}\r\n\t\tlog('First shown item index', firstShownItemIndex)\r\n\t\tlog('Last shown item index', lastShownItemIndex)\r\n\t\tlog('Before items height', beforeItemsHeight)\r\n\t\tlog('After items height (actual or estimated)', afterItemsHeight)\r\n\t\tlog('Average item height (used for estimated after items height calculation)', this.itemHeights.getAverage())\r\n\t\tif (isDebug()) {\r\n\t\t\tlog('Item heights', this.getState().itemHeights.slice())\r\n\t\t\tlog('Item states', this.getState().itemStates.slice())\r\n\t\t}\r\n\r\n\t\t// Optionally preload items to be rendered.\r\n\t\tthis.onBeforeShowItems(\r\n\t\t\tthis.getState().items,\r\n\t\t\tthis.getState().itemHeights,\r\n\t\t\tfirstShownItemIndex,\r\n\t\t\tlastShownItemIndex\r\n\t\t)\r\n\r\n\t\t// Set `this.firstNonMeasuredItemIndex`.\r\n\t\tthis.firstNonMeasuredItemIndex = firstNonMeasuredItemIndex\r\n\t\t// if (firstNonMeasuredItemIndex !== undefined) {\r\n\t\t// \tlog('Non-measured item index that will be measured at next layout', firstNonMeasuredItemIndex)\r\n\t\t// }\r\n\r\n\t\t// Set \"previously calculated layout\".\r\n\t\t//\r\n\t\t// The \"previously calculated layout\" feature is not currently used.\r\n\t\t//\r\n\t\t// The current layout snapshot could be stored as a \"previously calculated layout\" variable\r\n\t\t// so that it could theoretically be used when calculating new layout incrementally\r\n\t\t// rather than from scratch, which would be an optimization.\r\n\t\t//\r\n\t\t// Currently, this feature is not used, and `shownItemsHeight` property\r\n\t\t// is not returned at all, so don't set any \"previously calculated layout\".\r\n\t\t//\r\n\t\tif (shownItemsHeight === undefined) {\r\n\t\t\tthis.previouslyCalculatedLayout = undefined\r\n\t\t} else {\r\n\t\t\t// If \"previously calculated layout\" feature would be implmeneted,\r\n\t\t\t// then this code would set \"previously calculate layout\" instance variable.\r\n\t\t\t//\r\n\t\t\t// What for would this instance variable be used?\r\n\t\t\t//\r\n\t\t\t// Instead of using a `this.previouslyCalculatedLayout` instance variable,\r\n\t\t\t// this code could use `this.getState()` because it reflects what's currently on screen,\r\n\t\t\t// but there's a single edge case when it could go out of sync —\r\n\t\t\t// updating item heights externally via `.onItemHeightDidChange(i)`.\r\n\t\t\t//\r\n\t\t\t// If, for example, an item height was updated externally via `.onItemHeightDidChange(i)`\r\n\t\t\t// then `this.getState().itemHeights` would get updated immediately but\r\n\t\t\t// `this.getState().beforeItemsHeight` or `this.getState().afterItemsHeight`\r\n\t\t\t// would still correspond to the previous item height, so those would be \"stale\".\r\n\t\t\t// On the other hand, same values in `this.previouslyCalculatedLayout` instance variable\r\n\t\t\t// can also be updated immediately, so they won't go out of sync with the updated item height.\r\n\t\t\t// That seems the only edge case when using a separate `this.previouslyCalculatedLayout`\r\n\t\t\t// instance variable instead of using `this.getState()` would theoretically be justified.\r\n\t\t\t//\r\n\t\t\tthis.previouslyCalculatedLayout = {\r\n\t\t\t\tfirstShownItemIndex,\r\n\t\t\t\tlastShownItemIndex,\r\n\t\t\t\tbeforeItemsHeight,\r\n\t\t\t\tshownItemsHeight\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Update `VirtualScroller` state.\r\n\t\t// `VirtualScroller` automatically re-renders on state updates.\r\n\t\t//\r\n\t\t// All `state` properties updated here should be overwritten in\r\n\t\t// the implementation of `setItems()` and `onResize()` methods\r\n\t\t// so that the `state` is not left in an inconsistent state\r\n\t\t// whenever there're concurrent `updateState()` updates that could\r\n\t\t// possibly conflict with one another — instead, those state updates\r\n\t\t// should overwrite each other in terms of priority.\r\n\t\t// These \"on scroll\" updates have the lowest priority compared to\r\n\t\t// the state updates originating from `setItems()` and `onResize()` methods.\r\n\t\t//\r\n\t\tthis.updateState({\r\n\t\t\tfirstShownItemIndex,\r\n\t\t\tlastShownItemIndex,\r\n\t\t\tbeforeItemsHeight,\r\n\t\t\tafterItemsHeight,\r\n\t\t\t...stateUpdate\r\n\t\t})\r\n\t}\r\n\r\n\tfunction getVisibleArea() {\r\n\t\tconst visibleArea = this.scroll.getVisibleAreaBounds()\r\n\t\tthis.latestLayoutVisibleArea = visibleArea\r\n\r\n\t\t// Subtract the top offset of the list inside the scrollable container.\r\n\t\tconst listTopOffsetInsideScrollableContainer = this.getListTopOffsetInsideScrollableContainer()\r\n\t\treturn {\r\n\t\t\ttop: visibleArea.top - listTopOffsetInsideScrollableContainer,\r\n\t\t\tbottom: visibleArea.bottom - listTopOffsetInsideScrollableContainer\r\n\t\t}\r\n\t}\r\n\r\n\tfunction getShownItemIndexes() {\r\n\t\tconst itemsCount = this.getItemsCount()\r\n\r\n\t\tconst {\r\n\t\t\ttop: visibleAreaTop,\r\n\t\t\tbottom: visibleAreaBottom\r\n\t\t} = getVisibleArea.call(this)\r\n\r\n\t\tif (this.bypass) {\r\n\t\t\treturn {\r\n\t\t\t\tfirstShownItemIndex: 0,\r\n\t\t\t\tlastShownItemIndex: itemsCount - 1,\r\n\t\t\t\t// shownItemsHeight: this.getState().itemHeights.reduce((sum, itemHeight) => sum + itemHeight, 0)\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Find the indexes of the items that are currently visible\r\n\t\t// (or close to being visible) in the scrollable container.\r\n\t\t// For scrollable containers other than the main screen, it could also\r\n\t\t// check the visibility of such scrollable container itself, because it\r\n\t\t// might be not visible.\r\n\t\t// If such kind of an optimization would hypothetically be implemented,\r\n\t\t// then it would also require listening for \"scroll\" events on the screen.\r\n\t\t// Overall, I suppose that such \"actual visibility\" feature would be\r\n\t\t// a very minor optimization and not something I'd deal with.\r\n\t\tconst isVisible = visibleAreaTop < this.itemsContainer.getHeight() && visibleAreaBottom > 0\r\n\t\tif (!isVisible) {\r\n\t\t\tlog('The entire list is off-screen. No items are visible.')\r\n\t\t\treturn this.layout.getNonVisibleListShownItemIndexes()\r\n\t\t}\r\n\r\n\t\t// Get shown item indexes.\r\n\t\treturn this.layout.getShownItemIndexes({\r\n\t\t\titemsCount: this.getItemsCount(),\r\n\t\t\tvisibleAreaTop,\r\n\t\t\tvisibleAreaBottom\r\n\t\t})\r\n\t}\r\n\r\n\t/**\r\n\t * Validates the heights of items to be hidden on next render.\r\n\t * For example, a user could click a \"Show more\" button,\r\n\t * or an \"Expand YouTube video\" button, which would result\r\n\t * in the actual height of the list item being different\r\n\t * from what has been initially measured in `this.itemHeights[i]`,\r\n\t * if the developer didn't call `.setItemState(i, newState)` and `.onItemHeightDidChange(i)`.\r\n\t */\r\n\tfunction validateWillBeHiddenItemHeightsAreAccurate(firstShownItemIndex, lastShownItemIndex) {\r\n\t\tlet isValid = true\r\n\t\tlet i = this.getState().firstShownItemIndex\r\n\t\twhile (i <= this.getState().lastShownItemIndex) {\r\n\t\t\tif (i >= firstShownItemIndex && i <= lastShownItemIndex) {\r\n\t\t\t\t// The item's still visible.\r\n\t\t\t} else {\r\n\t\t\t\t// The item will be hidden. Re-measure its height.\r\n\t\t\t\t// The rationale is that there could be a situation when an item's\r\n\t\t\t\t// height has changed, and the developer has properly added an\r\n\t\t\t\t// `.onItemHeightDidChange(i)` call to notify `VirtualScroller`\r\n\t\t\t\t// about that change, but at the same time that wouldn't work.\r\n\t\t\t\t// For example, suppose there's a list of several items on a page,\r\n\t\t\t\t// and those items are in \"minimized\" state (having height 100px).\r\n\t\t\t\t// Then, a user clicks an \"Expand all items\" button, and all items\r\n\t\t\t\t// in the list are expanded (expanded item height is gonna be 700px).\r\n\t\t\t\t// `VirtualScroller` demands that `.onItemHeightDidChange(i)` is called\r\n\t\t\t\t// in such cases, and the developer has properly added the code to do that.\r\n\t\t\t\t// So, if there were 10 \"minimized\" items visible on a page, then there\r\n\t\t\t\t// will be 10 individual `.onItemHeightDidChange(i)` calls. No issues so far.\r\n\t\t\t\t// But, as the first `.onItemHeightDidChange(i)` call executes, it immediately\r\n\t\t\t\t// (\"synchronously\") triggers a re-layout, and that re-layout finds out\r\n\t\t\t\t// that now, because the first item is big, it occupies most of the screen\r\n\t\t\t\t// space, and only the first 3 items are visible on screen instead of 10,\r\n\t\t\t\t// and so it leaves the first 3 items mounted and unmounts the rest 7.\r\n\t\t\t\t// Then, after `VirtualScroller` has rerendered, the code returns to\r\n\t\t\t\t// where it was executing, and calls `.onItemHeightDidChange(i)` for the\r\n\t\t\t\t// second item. It also triggers an immediate re-layout that finds out\r\n\t\t\t\t// that only the first 2 items are visible on screen, and it unmounts\r\n\t\t\t\t// the third one too. After that, it calls `.onItemHeightDidChange(i)`\r\n\t\t\t\t// for the third item, but that item is no longer rendered, so its height\r\n\t\t\t\t// can't be measured, and the same's for all the rest of the original 10 items.\r\n\t\t\t\t// So, even though the developer has written their code properly, the\r\n\t\t\t\t// `VirtualScroller` still ends up having incorrect `itemHeights[]`:\r\n\t\t\t\t// `[700px, 700px, 100px, 100px, 100px, 100px, 100px, 100px, 100px, 100px]`\r\n\t\t\t\t// while it should have been `700px` for all of them.\r\n\t\t\t\t// To work around such issues, every item's height is re-measured before it\r\n\t\t\t\t// gets hidden.\r\n\t\t\t\tconst previouslyMeasuredItemHeight = this.getState().itemHeights[i]\r\n\t\t\t\tconst actualItemHeight = remeasureItemHeight.call(this, i)\r\n\t\t\t\tif (actualItemHeight !== previouslyMeasuredItemHeight) {\r\n\t\t\t\t\tif (isValid) {\r\n\t\t\t\t\t\tlog('~ Validate will-be-hidden item heights. ~')\r\n\t\t\t\t\t\t// Update or reset previously calculated layout.\r\n\t\t\t\t\t\tupdatePreviouslyCalculatedLayoutOnItemHeightChange.call(this, i, previouslyMeasuredItemHeight, actualItemHeight)\r\n\t\t\t\t\t}\r\n\t\t\t\t\tisValid = false\r\n\t\t\t\t\twarn('Item index', i, 'is no longer visible and will be unmounted. Its height has changed from', previouslyMeasuredItemHeight, 'to', actualItemHeight, 'since it was last measured. This is not necessarily a bug, and could happen, for example, on screen width change, or when there\\'re several `onItemHeightDidChange(i)` calls issued at the same time, and the first one triggers a re-layout before the rest of them have had a chance to be executed.')\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ti++\r\n\t\t}\r\n\t\treturn isValid\r\n\t}\r\n\r\n\tfunction remeasureItemHeight(i) {\r\n\t\tconst { firstShownItemIndex } = this.getState()\r\n\t\treturn this.itemHeights.remeasureItemHeight(i, firstShownItemIndex)\r\n\t}\r\n\r\n\t// Updates the snapshot of the current layout when an item's height changes.\r\n\t//\r\n\t// The \"previously calculated layout\" feature is not currently used.\r\n\t//\r\n\t// The current layout snapshot could be stored as a \"previously calculated layout\" variable\r\n\t// so that it could theoretically be used when calculating new layout incrementally\r\n\t// rather than from scratch, which would be an optimization.\r\n\t//\r\n\tfunction updatePreviouslyCalculatedLayoutOnItemHeightChange(i, previousHeight, newHeight) {\r\n\t\tconst prevLayout = this.previouslyCalculatedLayout\r\n\t\tif (prevLayout) {\r\n\t\t\tconst heightDifference = newHeight - previousHeight\r\n\t\t\tif (i < prevLayout.firstShownItemIndex) {\r\n\t\t\t\t// Patch `prevLayout`'s `.beforeItemsHeight`.\r\n\t\t\t\tprevLayout.beforeItemsHeight += heightDifference\r\n\t\t\t} else if (i > prevLayout.lastShownItemIndex) {\r\n\t\t\t\t// Could patch `.afterItemsHeight` of `prevLayout` here,\r\n\t\t\t\t// if `.afterItemsHeight` property existed in `prevLayout`.\r\n\t\t\t\tif (prevLayout.afterItemsHeight !== undefined) {\r\n\t\t\t\t\tprevLayout.afterItemsHeight += heightDifference\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t// Patch `prevLayout`'s shown items height.\r\n\t\t\t\tprevLayout.shownItemsHeight += newHeight - previousHeight\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the list's top offset relative to the scrollable container's top edge.\r\n\t * @return {number}\r\n\t */\r\n\tthis.getListTopOffsetInsideScrollableContainer = () => {\r\n\t\tconst listTopOffset = this.scrollableContainer.getItemsContainerTopOffset()\r\n\t\tif (this.listTopOffsetWatcher) {\r\n\t\t\tthis.listTopOffsetWatcher.onListTopOffset(listTopOffset)\r\n\t\t}\r\n\t\treturn listTopOffset\r\n\t}\r\n\r\n\tthis._onItemHeightDidChange = (i) => {\r\n\t\tlog('~ On Item Height Did Change was called ~')\r\n\t\tlog('Item index', i)\r\n\r\n\t\tconst {\r\n\t\t\titemHeights,\r\n\t\t\tfirstShownItemIndex,\r\n\t\t\tlastShownItemIndex\r\n\t\t} = this.getState()\r\n\r\n\t\t// Check if the item is still rendered.\r\n\t\tif (!(i >= firstShownItemIndex && i <= lastShownItemIndex)) {\r\n\t\t\t// There could be valid cases when an item is no longer rendered\r\n\t\t\t// by the time `.onItemHeightDidChange(i)` gets called.\r\n\t\t\t// For example, suppose there's a list of several items on a page,\r\n\t\t\t// and those items are in \"minimized\" state (having height 100px).\r\n\t\t\t// Then, a user clicks an \"Expand all items\" button, and all items\r\n\t\t\t// in the list are expanded (expanded item height is gonna be 700px).\r\n\t\t\t// `VirtualScroller` demands that `.onItemHeightDidChange(i)` is called\r\n\t\t\t// in such cases, and the developer has properly added the code to do that.\r\n\t\t\t// So, if there were 10 \"minimized\" items visible on a page, then there\r\n\t\t\t// will be 10 individual `.onItemHeightDidChange(i)` calls. No issues so far.\r\n\t\t\t// But, as the first `.onItemHeightDidChange(i)` call executes, it immediately\r\n\t\t\t// (\"synchronously\") triggers a re-layout, and that re-layout finds out\r\n\t\t\t// that now, because the first item is big, it occupies most of the screen\r\n\t\t\t// space, and only the first 3 items are visible on screen instead of 10,\r\n\t\t\t// and so it leaves the first 3 items mounted and unmounts the rest 7.\r\n\t\t\t// Then, after `VirtualScroller` has rerendered, the code returns to\r\n\t\t\t// where it was executing, and calls `.onItemHeightDidChange(i)` for the\r\n\t\t\t// second item. It also triggers an immediate re-layout that finds out\r\n\t\t\t// that only the first 2 items are visible on screen, and it unmounts\r\n\t\t\t// the third one too. After that, it calls `.onItemHeightDidChange(i)`\r\n\t\t\t// for the third item, but that item is no longer rendered, so its height\r\n\t\t\t// can't be measured, and the same's for all the rest of the original 10 items.\r\n\t\t\t// So, even though the developer has written their code properly, there're\r\n\t\t\t// still situations when the item could be no longer rendered by the time\r\n\t\t\t// `.onItemHeightDidChange(i)` gets called.\r\n\t\t\treturn warn('The item is no longer rendered. This is not necessarily a bug, and could happen, for example, when when a developer calls `onItemHeightDidChange(i)` while looping through a batch of items.')\r\n\t\t}\r\n\r\n\t\tconst previousHeight = itemHeights[i]\r\n\t\tif (previousHeight === undefined) {\r\n\t\t\treturn reportError(`\"onItemHeightDidChange()\" has been called for item index ${i} but the item hasn't been rendered before.`)\r\n\t\t}\r\n\r\n\t\tlog('~ Re-measure item height ~')\r\n\r\n\t\tlet newHeight\r\n\r\n\t\ttry {\r\n\t\t\tnewHeight = remeasureItemHeight.call(this, i)\r\n\t\t} catch (error) {\r\n\t\t\t// Successfully finishing an `onItemHeightDidChange(i)` call is not considered\r\n\t\t\t// critical for `VirtualScroller`'s operation, so such errors could be ignored.\r\n\t\t\tif (error instanceof ItemNotRenderedError) {\r\n\t\t\t\treturn reportError(`\"onItemHeightDidChange()\" has been called for item index ${i} but the item is not currently rendered and can\\'t be measured. The exact error was: ${error.message}`)\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlog('Previous height', previousHeight)\r\n\t\tlog('New height', newHeight)\r\n\r\n\t\tif (previousHeight !== newHeight) {\r\n\t\t\tlog('~ Item height has changed. Should update layout. ~')\r\n\r\n\t\t\t// Update or reset a previously calculated layout\r\n\t\t\t// so that the \"diff\"s based on that layout in the future\r\n\t\t\t// produce correct results.\r\n\t\t\tupdatePreviouslyCalculatedLayoutOnItemHeightChange.call(this, i, previousHeight, newHeight)\r\n\r\n\t\t\t// Recalculate layout.\r\n\t\t\t//\r\n\t\t\t// If the `VirtualScroller` is already waiting for a state update to be rendered,\r\n\t\t\t// delay `onItemHeightDidChange(i)`'s re-layout until that state update is rendered.\r\n\t\t\t// The reason is that React `<VirtualScroller/>`'s `onHeightDidChange()` is meant to\r\n\t\t\t// be called inside `useLayoutEffect()` hook. Due to how React is implemented internally,\r\n\t\t\t// that might happen in the middle of the currently pending `setState()` operation\r\n\t\t\t// being applied, resulting in weird \"race condition\" bugs.\r\n\t\t\t//\r\n\t\t\tif (this.waitingForRender) {\r\n\t\t\t\tlog('~ Another state update is already waiting to be rendered. Delay the layout update until then. ~')\r\n\t\t\t\tthis.updateLayoutAfterRenderBecauseItemHeightChanged = true\r\n\t\t\t} else {\r\n\t\t\t\tthis.onUpdateShownItemIndexes({ reason: LAYOUT_REASON.ITEM_HEIGHT_CHANGED })\r\n\t\t\t}\r\n\r\n\t\t\t// If there was a request for `setState()` with new `items`, then the changes\r\n\t\t\t// to `currentState.itemHeights[]` made above in a `remeasureItemHeight()` call\r\n\t\t\t// would be overwritten when that pending `setState()` call gets applied.\r\n\t\t\t// To fix that, the updates to current `itemHeights[]` are noted in\r\n\t\t\t// `this.itemHeightsThatChangedWhileNewItemsWereBeingRendered` variable.\r\n\t\t\t// That variable is then checked when the `setState()` call with the new `items`\r\n\t\t\t// has been updated.\r\n\t\t\tif (this.newItemsWillBeRendered) {\r\n\t\t\t\tif (!this.itemHeightsThatChangedWhileNewItemsWereBeingRendered) {\r\n\t\t\t\t\tthis.itemHeightsThatChangedWhileNewItemsWereBeingRendered = {}\r\n\t\t\t\t}\r\n\t\t\t\tthis.itemHeightsThatChangedWhileNewItemsWereBeingRendered[String(i)] = newHeight\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tthis.getPrerenderMargin = () => {\r\n\t\t// The list component renders not only the items that're currently visible\r\n\t\t// but also the items that lie within some extra vertical margin (called\r\n\t\t// \"prerender margin\") on top and bottom for future scrolling: this way,\r\n\t\t// there'll be significantly less layout recalculations as the user scrolls,\r\n\t\t// because now it doesn't have to recalculate layout on each scroll event.\r\n\t\t// By default, the \"prerender margin\" is equal to the screen height:\r\n\t\t// this seems to be the optimal value for \"Page Up\" / \"Page Down\" navigation\r\n\t\t// and optimized mouse wheel scrolling (a user is unlikely to continuously\r\n\t\t// scroll past the screen height, because they'd stop to read through\r\n\t\t// the newly visible items first, and when they do stop scrolling, that's\r\n\t\t// when layout gets recalculated).\r\n\t\tconst renderAheadMarginRatio = 1 // in scrollable container heights.\r\n\t\treturn this.scrollableContainer.getHeight() * renderAheadMarginRatio\r\n\t}\r\n\r\n\t/**\r\n\t * Calls `onItemFirstRender()` for items that haven't been\r\n\t * \"seen\" previously.\r\n\t * @param {any[]} items\r\n\t * @param {number[]} itemHeights\r\n\t * @param {number} firstShownItemIndex\r\n\t * @param {number} lastShownItemIndex\r\n\t */\r\n\tthis.onBeforeShowItems = (\r\n\t\titems,\r\n\t\titemHeights,\r\n\t\tfirstShownItemIndex,\r\n\t\tlastShownItemIndex\r\n\t) => {\r\n\t\tif (this.onItemInitialRender) {\r\n\t\t\tlet i = firstShownItemIndex\r\n\t\t\twhile (i <= lastShownItemIndex) {\r\n\t\t\t\tif (itemHeights[i] === undefined) {\r\n\t\t\t\t\tthis.onItemInitialRender(items[i])\r\n\t\t\t\t}\r\n\t\t\t\ti++\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tthis.measureItemHeightsAndSpacing = () => {\r\n\t\t// Measure \"newly shown\" item heights.\r\n\t\t// Also re-validate already measured items' heights.\r\n\t\tthis.itemHeights.measureItemHeights(\r\n\t\t\tthis.getState().firstShownItemIndex,\r\n\t\t\tthis.getState().lastShownItemIndex\r\n\t\t)\r\n\r\n\t\t// Measure item vertical spacing, if required.\r\n\t\tconst verticalSpacing = this.measureVerticalSpacingIfNotMeasured()\r\n\r\n\t\t// Return a state update if vertical spacing has been measured.\r\n\t\t// Doesn't set `verticalSpacing: 0` in `state` because it is effectively\r\n\t\t// same as `verticalSpacing: undefined` in terms code behavior and calculations.\r\n\t\t// Not having `verticalSpacing: 0` in `state` just makes the `state` object\r\n\t\t// a bit more cleaner and a bit less cluttered (easier for inspection).\r\n\t\tif (verticalSpacing && verticalSpacing !== 0) {\r\n\t\t\t// Return a state update.\r\n\t\t\t// Sets `verticalSpacing` property in `state`.\r\n\t\t\treturn {\r\n\t\t\t\tverticalSpacing\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tthis.cancelLayoutTimer = ({ stateUpdate }) => {\r\n\t\tif (this.layoutTimer) {\r\n\t\t\tclearTimeout(this.layoutTimer)\r\n\t\t\tthis.layoutTimer = undefined\r\n\t\t\t// Merge state updates.\r\n\t\t\tif (stateUpdate || this.layoutTimerStateUpdate) {\r\n\t\t\t\tstateUpdate = {\r\n\t\t\t\t\t...this.layoutTimerStateUpdate,\r\n\t\t\t\t\t...stateUpdate\r\n\t\t\t\t}\r\n\t\t\t\tthis.layoutTimerStateUpdate = undefined\r\n\t\t\t\treturn stateUpdate\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\treturn stateUpdate\r\n\t\t}\r\n\t}\r\n\r\n\tthis.scheduleLayoutTimer = ({ reason, stateUpdate }) => {\r\n\t\tthis.layoutTimerStateUpdate = stateUpdate\r\n\t\tthis.layoutTimer = setTimeout(() => {\r\n\t\t\tthis.layoutTimerStateUpdate = undefined\r\n\t\t\tthis.layoutTimer = undefined\r\n\t\t\tthis.onUpdateShownItemIndexes({\r\n\t\t\t\treason,\r\n\t\t\t\tstateUpdate\r\n\t\t\t})\r\n\t\t}, 0)\r\n\t}\r\n}\r\n\r\nconst SLOW_LAYOUT_DURATION = 15 // in milliseconds."],"mappings":"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"}
|