virtual-scroller 1.12.1 → 1.12.3
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 +9 -0
- package/CODE_OF_CONDUCT.md +78 -0
- package/README.md +75 -10
- 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/ItemHeights.js +1 -1
- package/commonjs/ItemHeights.js.map +1 -1
- package/commonjs/Layout.js +1 -1
- package/commonjs/Layout.js.map +1 -1
- package/commonjs/Scroll.js +2 -1
- package/commonjs/Scroll.js.map +1 -1
- package/commonjs/VirtualScroller.js +62 -23
- package/commonjs/VirtualScroller.js.map +1 -1
- package/commonjs/VirtualScroller.layout.js +16 -10
- package/commonjs/VirtualScroller.layout.js.map +1 -1
- package/commonjs/VirtualScroller.onRender.js +2 -2
- package/commonjs/VirtualScroller.onRender.js.map +1 -1
- package/commonjs/getVerticalSpacing.js +5 -2
- package/commonjs/getVerticalSpacing.js.map +1 -1
- package/commonjs/react/VirtualScroller.js +3 -0
- package/commonjs/react/VirtualScroller.js.map +1 -1
- package/commonjs/react/useEffectDontMountTwiceInStrictMode.js +83 -0
- package/commonjs/react/useEffectDontMountTwiceInStrictMode.js.map +1 -0
- package/commonjs/react/useInsertionEffectDontMountTwiceInStrictMode.js +20 -0
- package/commonjs/react/useInsertionEffectDontMountTwiceInStrictMode.js.map +1 -0
- package/commonjs/react/useLayoutEffectDontMountTwiceInStrictMode.js +20 -0
- package/commonjs/react/useLayoutEffectDontMountTwiceInStrictMode.js.map +1 -0
- package/commonjs/react/useState.js +13 -7
- package/commonjs/react/useState.js.map +1 -1
- package/commonjs/react/useStateNoStaleBug.js +59 -0
- package/commonjs/react/useStateNoStaleBug.js.map +1 -0
- package/modules/ItemHeights.js +1 -1
- package/modules/ItemHeights.js.map +1 -1
- package/modules/Layout.js +1 -1
- package/modules/Layout.js.map +1 -1
- package/modules/Scroll.js +2 -1
- package/modules/Scroll.js.map +1 -1
- package/modules/VirtualScroller.js +62 -23
- package/modules/VirtualScroller.js.map +1 -1
- package/modules/VirtualScroller.layout.js +16 -10
- package/modules/VirtualScroller.layout.js.map +1 -1
- package/modules/VirtualScroller.onRender.js +2 -2
- package/modules/VirtualScroller.onRender.js.map +1 -1
- package/modules/getVerticalSpacing.js +5 -2
- package/modules/getVerticalSpacing.js.map +1 -1
- package/modules/react/VirtualScroller.js +3 -1
- package/modules/react/VirtualScroller.js.map +1 -1
- package/modules/react/useEffectDontMountTwiceInStrictMode.js +75 -0
- package/modules/react/useEffectDontMountTwiceInStrictMode.js.map +1 -0
- package/modules/react/useInsertionEffectDontMountTwiceInStrictMode.js +9 -0
- package/modules/react/useInsertionEffectDontMountTwiceInStrictMode.js.map +1 -0
- package/modules/react/useLayoutEffectDontMountTwiceInStrictMode.js +9 -0
- package/modules/react/useLayoutEffectDontMountTwiceInStrictMode.js.map +1 -0
- package/modules/react/useState.js +11 -8
- package/modules/react/useState.js.map +1 -1
- package/modules/react/useStateNoStaleBug.js +51 -0
- package/modules/react/useStateNoStaleBug.js.map +1 -0
- package/package.json +1 -1
- package/source/ItemHeights.js +1 -1
- package/source/Layout.js +1 -1
- package/source/Scroll.js +1 -0
- package/source/VirtualScroller.js +61 -21
- package/source/VirtualScroller.layout.js +14 -8
- package/source/VirtualScroller.onRender.js +2 -2
- package/source/getVerticalSpacing.js +5 -2
- package/source/react/VirtualScroller.js +3 -0
- package/source/react/useEffectDontMountTwiceInStrictMode.js +68 -0
- package/source/react/useInsertionEffectDontMountTwiceInStrictMode.js +10 -0
- package/source/react/useLayoutEffectDontMountTwiceInStrictMode.js +10 -0
- package/source/react/useState.js +8 -5
- package/source/react/useStateNoStaleBug.js +35 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
<!-- `virtual-scroller`: in `.updateItems()` handle a case when `items.length` is the same, in which case find different items and if those items are rendered then maybe update them on screen and update their height, if the items are past rendered then maybe just discard all item heights past rendered, if the items are before rendered then maybe ignore and it will jump on scroll up which is kinda acceptable. -->
|
|
2
2
|
|
|
3
|
+
1.12.3 / 23.03.2023
|
|
4
|
+
==================
|
|
5
|
+
|
|
6
|
+
* [Fixed](https://gitlab.com/catamphetamine/virtual-scroller/-/issues/33) React `18.2.0` [bug](https://github.com/facebook/react/issues/26320) in ["strict" mode](https://hu.reactjs.org/docs/strict-mode.html) when `useInsertionEffect()` doesn't run twice on mount unlike `useEffect()` or `useLayoutEffect()`.
|
|
7
|
+
|
|
8
|
+
* Fixed React `18.2.0` [bug](https://github.com/facebook/react/issues/25023#issuecomment-1480463544) when out-of-sync (stale) state values are being rendered.
|
|
9
|
+
|
|
10
|
+
* `VirtualScroller` no longer restores the Y scroll position on mount: it was found out that this feature conflicted with the same feature of application "router" libraries.
|
|
11
|
+
|
|
3
12
|
1.11.3 / 05.02.2023
|
|
4
13
|
==================
|
|
5
14
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
In the interest of fostering an open and free environment, we as
|
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
|
7
|
+
our community a censorship-free experience for everyone, regardless of age, body
|
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
|
9
|
+
education, socio-economic status, nationality, personal appearance, race,
|
|
10
|
+
religion, or sexual identity and orientation.
|
|
11
|
+
|
|
12
|
+
## Our Standards
|
|
13
|
+
|
|
14
|
+
Examples of behavior that contributes to creating an open and free environment
|
|
15
|
+
include:
|
|
16
|
+
|
|
17
|
+
* Not constraining the language to be "welcoming" or "inclusive"
|
|
18
|
+
* Not demanding show of empathy towards other community members
|
|
19
|
+
* Not dictating anyone to be respectful of differing viewpoints and experiences
|
|
20
|
+
* Not forcing anyone to change their views or opinions regardless of those
|
|
21
|
+
* Not intimidating other people into accepting your own views or opinions
|
|
22
|
+
* Not blackmailing other people to disclose their personal views or opinions
|
|
23
|
+
* Not constraining other people from publishing their personal views or opinions in an unintrusive way
|
|
24
|
+
* Focusing on what is best for the ecosystem
|
|
25
|
+
|
|
26
|
+
Examples of acceptable behavior by participants include:
|
|
27
|
+
|
|
28
|
+
* The use of sexualized language
|
|
29
|
+
* Occasional trolling or insulting comments that are not completely off-topic
|
|
30
|
+
|
|
31
|
+
Examples of unacceptable behavior by participants include:
|
|
32
|
+
|
|
33
|
+
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
|
34
|
+
* Unwelcome sexual attention or advances
|
|
35
|
+
* Public harassment or personal attacks when carried out in an bold or intrusive way
|
|
36
|
+
* Private harassment
|
|
37
|
+
* Any actions that are in violation of the local laws or otherwise considered illegal
|
|
38
|
+
* Other conduct which could reasonably be considered inappropriate in an open and free setting
|
|
39
|
+
|
|
40
|
+
## Our Responsibilities
|
|
41
|
+
|
|
42
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
|
43
|
+
behavior and are free to take appropriate and fair corrective action in
|
|
44
|
+
response to any instances of unacceptable behavior.
|
|
45
|
+
|
|
46
|
+
Project maintainers have the right and authority to remove, edit, or
|
|
47
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
|
48
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
|
49
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
|
50
|
+
threatening, offensive, or harmful.
|
|
51
|
+
|
|
52
|
+
## Scope
|
|
53
|
+
|
|
54
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
|
55
|
+
when an individual is representing the project or its community. Examples of
|
|
56
|
+
representing a project or community include using an official project e-mail
|
|
57
|
+
address, posting via an official social media account, or acting as an appointed
|
|
58
|
+
representative at an online or offline event. Representation of a project may be
|
|
59
|
+
further defined and clarified by project maintainers.
|
|
60
|
+
|
|
61
|
+
## Enforcement
|
|
62
|
+
|
|
63
|
+
Instances of unacceptable behavior may be reported by contacting the project team.
|
|
64
|
+
The complaints will likely be reviewed and investigated and may result in a response that
|
|
65
|
+
is deemed necessary and appropriate to the circumstances. The project team should maintain confidentiality with regard to the reporter of an incident.
|
|
66
|
+
Further details of specific enforcement policies may be posted separately.
|
|
67
|
+
|
|
68
|
+
Project maintainers who do not follow the Code of Conduct in good
|
|
69
|
+
faith may face temporary or permanent repercussions as determined by other
|
|
70
|
+
members of the project's leadership.
|
|
71
|
+
|
|
72
|
+
## Attribution
|
|
73
|
+
|
|
74
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
|
75
|
+
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
|
76
|
+
|
|
77
|
+
[homepage]: https://www.contributor-covenant.org
|
|
78
|
+
|
package/README.md
CHANGED
|
@@ -86,9 +86,21 @@ The main `state` properties are:
|
|
|
86
86
|
|
|
87
87
|
The following `state` properties are only used for saving and restoring `VirtualScroller` `state`, and normally shouldn't be accessed:
|
|
88
88
|
|
|
89
|
-
* `itemStates: any[]` — The states of all items.
|
|
89
|
+
* `itemStates: any[]` — The "states" of all items. If an item's appearance is not "static" and could change, then every aspect of the item's appearance that could change should be represented in the item's "state", and that "state" must be preserved somewhere. That's because of the nature of how `VirtualScroller` works: no-longer-visible items get un-rendered, and when they later become visible again, they should precisely restore their latest-rendered appearance by re-rendering from a previously preserved "state".
|
|
90
90
|
|
|
91
|
-
*
|
|
91
|
+
* The item "state" could be preserved anywhere in the application, or the developer could use `VirtualScroller`'s built-in item "state" storage. To preserve an item's state in the built-in storage, call `.setItemState(i, itemState)` instance method (described below) immediately after an item's state has changed.
|
|
92
|
+
|
|
93
|
+
* An example would be an item representing a social media comment, with a "Show more"/"Show less" button that shows or hides the full text of the comment. Immediately after the full text of a comment has been shown or hidden, it should call `.setItemState(i, { showMore: true/false })` instance method along with `.onItemHeightDidChange(i)` instance method (described below), so that next time when the item is rendered, it could restore its appearance from `virtualScroller.getState().itemStates[i]`.
|
|
94
|
+
|
|
95
|
+
* For another similar example, consider a social network feed, where each post optionally has an attachment. Suppose there's a post in the feed having a YouTube video attachment. The attachment is initially shown as a small thumbnail that expands into a full-sized embedded YouTube video player when a user clicks on it. If the expanded/collapsed state of such attachment wasn't preserved, then the following "glitch" would be observed: the user expands the video, then scrolls down so that the post with the video is no longer visible, the post gets unmounted due to going off screen, then the user scrolls back up so that the post with the video is visible again, the post gets mounted again, but the video is not expanded and instead a small thumbnail is shown because there's no previous "state" to restore from.
|
|
96
|
+
|
|
97
|
+
* In this example, besides preserving the item state itself, one should also call `.onItemHeightDidChange(i)` instance method (described below) right after the YouTube video has been expanded/collapsed.
|
|
98
|
+
|
|
99
|
+
* `itemHeights: number[]` — The measured heights of all items. If an item's height hasn't been measured yet then it's `undefined`.
|
|
100
|
+
|
|
101
|
+
* By default, items are only measured once: when they're initially rendered. If an item's height changes afterwards, then `.onItemHeightDidChange(i)` instance method must be called right after it happens (described later in the document), otherwise `VirtualScroller`'s calculations will be off. For example, if an item is a social media comment, and there's a "Show more"/"Show less" button that shows the full text of the comment, then it must call `.onItemHeightDidChange(i)` immediately after the comment text has been expanded or collapsed.
|
|
102
|
+
|
|
103
|
+
* Besides the requirement of calling `.onItemHeightDidChange(i)`, every change in an item's height must also be reflected in the actual data: the change in height must be either a result of the item's internal properties changing or it could be a result of changing the item's "state". The reason is that when an item gets hidden, it's no longer rendered, so when it becomes visible again, it should precisely restore its last-rendered appearance based on the item's properties and any persisted "state".
|
|
92
104
|
|
|
93
105
|
* `verticalSpacing: number?` — Vertical item spacing. Is `undefined` until it has been measured. Is only measured once, when at least two rows of items have been rendered.
|
|
94
106
|
|
|
@@ -284,7 +296,12 @@ virtualScroller.start()
|
|
|
284
296
|
|
|
285
297
|
* `getItemId(item)` — (advanced) When `items` are dynamically updated via `.setItems()`, `VirtualScroller` detects an "incremental" update by comparing "new" and "old" item ["references"](https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0): this way, `VirtualScroller` can understand that the "new" `items` are (mostly) the same as the "old" `items` when some items get prepended or appended to the list, in which case it doesn't re-render the whole list from scratch, but rather just renders the "new" items that got prepended or appended. Sometimes though, some of the "old" items might get updated: for example, if `items` is a list of comments, then some of those comments might get edited in-between the refreshes. In that case, the edited comment object reference should change in order to indicate that the comment's content has changed and that the comment should be re-rendered (at least that's how it has to be done in React world). At the same time, changing the edited comment object reference would break `VirtualScroller`'s "incremental" update detection, and it would re-render the whole list of comments from scratch, which is not what it should be doing in such cases. So, in cases like this, `VirtualScroller` should have some way to understand that the updated item, even if its object reference has changed, is still the same as the old one, so that it doesn't break "incremental" update detection. For that, `getItemId(item)` parameter could be passed, which `VirtualScroller` would use to compare "old" and "new" items (instead of the default "reference equality" check), and that would fix the "re-rendering the whole list from scratch" issue. It can also be used when `items` are fetched from an external API, in which case all item object references change on every such fetch.
|
|
286
298
|
|
|
287
|
-
* `onItemInitialRender(item)` — (advanced)
|
|
299
|
+
* `onItemInitialRender(item)` — (advanced) Will be called for each `item` when it's about to be rendered for the first time. This function could be used to somehow "initialize" an item before it gets rendered for the first time. For example, consider a list of items that must be somehow "preprocessed" (parsed, enhanced, etc) before being rendered, and such "preprocessing" puts some load on the CPU (and therefore takes some time). In such case, instead of "preprocessing" the whole list of items up front, the application could "preprocess" only the items that're actually visible, preventing the unnecessary work and reducing the "time to first render".
|
|
300
|
+
* The function is guaranteed to be called at least once for each item that ever gets rendered.
|
|
301
|
+
* In more complex and non-trivial cases it could be called multiple times for a given item, so it should be written in such a way that calling it multiple times wouldn't do anything. For example, it could set a boolean flag on an item and then check that flag on each subsequent invocation.
|
|
302
|
+
|
|
303
|
+
* One example of the function being called multiple times would be when run in an "asynchronous" rendering framework like React. In such frameworks, "rendering" and "painting" are two separate actions separated in time, so one doesn't necessarily cause the other. For example, React could render a component multiple times before it actually gets painted on screen. In that example, the function would be called for a given item on each render until it finally gets painted on screen.
|
|
304
|
+
* Another example would be calling `VirtualScroller.setItems()` function with a "non-incremental" `items` update. An `items` update would be "non-incremental", for example, if some items got removed from the list, or some new items got inserted in the middle of the list, or the order of the items changed. In case of a "non-incremental" `items` update, `VirtualScroller` resets then previous state and basically "forgets" everything about the previous items, including the fact that the function has already been called for some of the items.
|
|
288
305
|
|
|
289
306
|
<!-- * `shouldUpdateLayoutOnScreenResize(event: Event): boolean` — By default, `VirtualScroller` always performs a re-layout on window `resize` event. The `resize` event is not only triggered when a user resizes the window itself: it's also [triggered](https://developer.mozilla.org/en-US/docs/Web/API/Window/fullScreen#Notes) when the user switches into (and out of) fullscreen mode. By default, `VirtualScroller` performs a re-layout on all window `resize` events, except for ones that don't result in actual window width or height change, and except for cases when, for example, a video somewhere in a list is maximized into fullscreen. There still can be other "custom" cases: for example, when an application uses a custom "slideshow" component (rendered outside of the list DOM element) that goes into fullscreen when a user clicks a picture or a video in the list. For such "custom" cases `shouldUpdateLayoutOnScreenResize(event)` option / property can be specified. -->
|
|
290
307
|
|
|
@@ -315,7 +332,7 @@ virtualScroller.start()
|
|
|
315
332
|
|
|
316
333
|
A developer might prefer to use custom (external) state management rather than the default one. That might be the case when a certain high-order `VirtualScroller` implementation comes with a specific state management paradigm, like in React. In such case, `VirtualScroller` provides the following instance methods:
|
|
317
334
|
|
|
318
|
-
* `onRender()` — When using custom (external) state management,
|
|
335
|
+
* `onRender()` — When using custom (external) state management, `.onRender()` function must be called every time right after the list has been "rendered" (including the initial render). The list should always "render" only with the "latest" state where the "latest" state is defined as the argument of the latest `setState()` call. Otherwise, the component may not work correctly.
|
|
319
336
|
|
|
320
337
|
* `getInitialState(): object` — Returns the initial `VirtualScroller` state for the cases when a developer configures `VirtualScroller` for custom (external) state management.
|
|
321
338
|
|
|
@@ -347,17 +364,15 @@ When using custom (external) state management, contrary to the default (internal
|
|
|
347
364
|
|
|
348
365
|
* `onItemHeightDidChange(i: number)` — (advanced) If an item's height could've changed, this function should be called immediately after the item's height has potentially changed. The function re-measures the item's height (the item must still be rendered) and re-calculates `VirtualScroller` layout. An example for using this function would be having an "Expand"/"Collapse" button in a list item.
|
|
349
366
|
|
|
350
|
-
* There's also a convention that every change in an item's height must come as a result of changing
|
|
367
|
+
* There's also a convention that every change in an item's height must come as a result of changing the item's "state". See the descripton of `itemStates` and `itemHeights` properties of the `VirtualScroller` [state](#state) for more details.
|
|
351
368
|
|
|
352
369
|
* Implementation-wise, calling `onItemHeightDidChange()` manually could be replaced with detecting item height changes automatically via [Resize Observer](https://caniuse.com/#search=Resize%20Observer) in some future version.
|
|
353
370
|
|
|
354
|
-
* `setItemState(i: number, itemState: any?)` — (advanced)
|
|
355
|
-
|
|
356
|
-
* Calling `setItemState()` doesn't trigger a re-layout of `VirtualScroller` because changing a list item's state doesn't necessarily mean a change of its height, so a re-layout might not be required. If an item's height did change as a result of changing its state, then `VirtualScroller` layout must be updated, and to do that, call `onItemHeightDidChange(i)` right after calling `setItemState()` has taken effect.
|
|
371
|
+
* `setItemState(i: number, itemState: any?)` — (advanced) Preserves a list item's "state" inside `VirtualScroller`'s built-in item "state" storage. See the descripton of `itemStates` property of the `VirtualScroller` [state](#state) for more details.
|
|
357
372
|
|
|
358
|
-
*
|
|
373
|
+
* A developer could use it to preserve an item's "state" if it could change. The reason is that offscreen items get unmounted and any unsaved state is lost in the process. If an item's state is correctly preserved, the item's latest-rendered appearance could be restored from that state when the item gets mounted again due to becoming visible again.
|
|
359
374
|
|
|
360
|
-
*
|
|
375
|
+
* Calling `setItemState()` doesn't trigger a re-layout of `VirtualScroller` because changing a list item's state doesn't necessarily mean a change of its height, so a re-layout might not be required. If an item's height did change as a result of changing its state, then `VirtualScroller` layout must be updated, and to do that, one should call `onItemHeightDidChange(i)` right after the change in the item's state has been reflected on screen.
|
|
361
376
|
|
|
362
377
|
* `getItemScrollPosition(i: number): number?` — (advanced) Returns an item's scroll position inside the scrollable container. Returns `undefined` if any of the items before this item haven't been rendered yet.
|
|
363
378
|
|
|
@@ -928,6 +943,56 @@ Due to the [inherent limitations](https://gitlab.com/catamphetamine/virtual-scro
|
|
|
928
943
|
|
|
929
944
|
Due to offscreen list items not being rendered native browser features like "Find on page", moving focus through items via `Tab` key, screen reader announcement and such won't work. A workaround for "search on page" is adding a custom "🔍 Search" input field that would filter items by their content and then call `VirtualScroller.setItems()`.
|
|
930
945
|
|
|
946
|
+
### "Item index N height changed unexpectedly" warning on page load in dev mode.
|
|
947
|
+
|
|
948
|
+
`VirtualScroller` assumes there'd be no "unexpected" (unannounced) changes in items' heights. If an item's height changes for whatever reason, a developer must announce it immediately by calling `.onItemHeightDidChange(i)` instance method.
|
|
949
|
+
|
|
950
|
+
There might still be cases outside of a developer's control when items' heights do change "unexpectedly". One such case is when running an application in "development" mode and the CSS styles or custom fonts haven't loaded yet, resulting in different item height measurements "before" and "after" the page has fully loaded.
|
|
951
|
+
|
|
952
|
+
<details>
|
|
953
|
+
|
|
954
|
+
<summary>To filter out such "false" warnings, one could temporarily override <code>console.warn</code> function in development mode.</summary>
|
|
955
|
+
|
|
956
|
+
######
|
|
957
|
+
|
|
958
|
+
```js
|
|
959
|
+
const PAGE_LOAD_TIMEOUT = 1000
|
|
960
|
+
|
|
961
|
+
let consoleWarnHasBeenInstrumented = false
|
|
962
|
+
|
|
963
|
+
export default function suppressVirtualScrollerDevModePageLoadWarnings() {
|
|
964
|
+
if (consoleWarnHasBeenInstrumented) {
|
|
965
|
+
return
|
|
966
|
+
}
|
|
967
|
+
// `virtual-scroller` might produce false warnings about items changing their height unexpectedly.
|
|
968
|
+
// https://gitlab.com/catamphetamine/virtual-scroller/#item-index-n-height-changed-unexpectedly-warning-on-page-load-in-dev-mode
|
|
969
|
+
// That might be the case because Webpack hasn't yet loaded the styles by the time `virtual-scroller`
|
|
970
|
+
// performs its initial items measurement.
|
|
971
|
+
// To clear the console from such false warnings, a "page load timeout" is introduced in development mode.
|
|
972
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
973
|
+
consoleWarnHasBeenInstrumented = true
|
|
974
|
+
const originalConsoleWarn = console.warn
|
|
975
|
+
const startedAt = Date.now()
|
|
976
|
+
let muteVirtualScrollerUnexpectedHeightChangeWarnings = true
|
|
977
|
+
console.warn = (...args) => {
|
|
978
|
+
if (muteVirtualScrollerUnexpectedHeightChangeWarnings) {
|
|
979
|
+
if (Date.now() - startedAt < PAGE_LOAD_TIMEOUT) {
|
|
980
|
+
if (args[0] === '[virtual-scroller]' && args[1] === 'Item index' && args[3] === 'height changed unexpectedly: it was') {
|
|
981
|
+
// Mute the warning.
|
|
982
|
+
console.log('(muted `virtual-scroller` warning because the page hasn\'t loaded yet)')
|
|
983
|
+
return
|
|
984
|
+
}
|
|
985
|
+
} else {
|
|
986
|
+
muteVirtualScrollerUnexpectedHeightChangeWarnings = false
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
return originalConsoleWarn(...args)
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
```
|
|
994
|
+
</details>
|
|
995
|
+
|
|
931
996
|
### If only the first item is rendered on page load in dev mode.
|
|
932
997
|
|
|
933
998
|
<details>
|