virtual-scroller 1.8.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/.gitlab-ci.yml +1 -1
  2. package/CHANGELOG.md +57 -0
  3. package/README.md +337 -160
  4. package/bundle/virtual-scroller-dom.js +1 -1
  5. package/bundle/virtual-scroller-dom.js.map +1 -1
  6. package/bundle/virtual-scroller-react.js +1 -1
  7. package/bundle/virtual-scroller-react.js.map +1 -1
  8. package/bundle/virtual-scroller.js +1 -1
  9. package/bundle/virtual-scroller.js.map +1 -1
  10. package/commonjs/BeforeResize.js +23 -27
  11. package/commonjs/BeforeResize.js.map +1 -1
  12. package/commonjs/DOM/Engine.js +7 -7
  13. package/commonjs/DOM/Engine.js.map +1 -1
  14. package/commonjs/DOM/ItemsContainer.js +1 -1
  15. package/commonjs/DOM/ItemsContainer.js.map +1 -1
  16. package/commonjs/DOM/ListTopOffsetWatcher.js +15 -9
  17. package/commonjs/DOM/ListTopOffsetWatcher.js.map +1 -1
  18. package/commonjs/DOM/ScrollableContainer.js +28 -28
  19. package/commonjs/DOM/ScrollableContainer.js.map +1 -1
  20. package/commonjs/DOM/VirtualScroller.js +20 -17
  21. package/commonjs/DOM/VirtualScroller.js.map +1 -1
  22. package/commonjs/DOM/tbody.js +16 -10
  23. package/commonjs/DOM/tbody.js.map +1 -1
  24. package/commonjs/ItemHeights.js +23 -17
  25. package/commonjs/ItemHeights.js.map +1 -1
  26. package/commonjs/Layout.js +15 -13
  27. package/commonjs/Layout.js.map +1 -1
  28. package/commonjs/Layout.test.js +8 -3
  29. package/commonjs/Layout.test.js.map +1 -1
  30. package/commonjs/{ListHeightChangeWatcher.js → ListHeightMeasurement.js} +26 -28
  31. package/commonjs/ListHeightMeasurement.js.map +1 -0
  32. package/commonjs/Resize.js +38 -28
  33. package/commonjs/Resize.js.map +1 -1
  34. package/commonjs/Scroll.js +28 -44
  35. package/commonjs/Scroll.js.map +1 -1
  36. package/commonjs/VirtualScroller.columns.js +43 -0
  37. package/commonjs/VirtualScroller.columns.js.map +1 -0
  38. package/commonjs/VirtualScroller.constructor.js +408 -0
  39. package/commonjs/VirtualScroller.constructor.js.map +1 -0
  40. package/commonjs/VirtualScroller.items.js +305 -0
  41. package/commonjs/VirtualScroller.items.js.map +1 -0
  42. package/commonjs/VirtualScroller.js +132 -1872
  43. package/commonjs/VirtualScroller.js.map +1 -1
  44. package/commonjs/VirtualScroller.layout.js +562 -0
  45. package/commonjs/VirtualScroller.layout.js.map +1 -0
  46. package/commonjs/VirtualScroller.onRender.js +357 -0
  47. package/commonjs/VirtualScroller.onRender.js.map +1 -0
  48. package/commonjs/VirtualScroller.resize.js +186 -0
  49. package/commonjs/VirtualScroller.resize.js.map +1 -0
  50. package/commonjs/VirtualScroller.state.js +301 -0
  51. package/commonjs/VirtualScroller.state.js.map +1 -0
  52. package/commonjs/VirtualScroller.verticalSpacing.js +65 -0
  53. package/commonjs/VirtualScroller.verticalSpacing.js.map +1 -0
  54. package/commonjs/getItemCoordinates.js.map +1 -1
  55. package/commonjs/getItemsDiff.js.map +1 -1
  56. package/commonjs/getVerticalSpacing.js.map +1 -1
  57. package/commonjs/package.json +5 -0
  58. package/commonjs/react/VirtualScroller.js +184 -618
  59. package/commonjs/react/VirtualScroller.js.map +1 -1
  60. package/commonjs/react/useClassName.js +26 -0
  61. package/commonjs/react/useClassName.js.map +1 -0
  62. package/commonjs/react/useHandleItemsChange.js +116 -0
  63. package/commonjs/react/useHandleItemsChange.js.map +1 -0
  64. package/commonjs/react/useInstanceMethods.js +37 -0
  65. package/commonjs/react/useInstanceMethods.js.map +1 -0
  66. package/commonjs/react/useItemKeys.js +60 -0
  67. package/commonjs/react/useItemKeys.js.map +1 -0
  68. package/commonjs/react/useOnItemHeightChange.js +32 -0
  69. package/commonjs/react/useOnItemHeightChange.js.map +1 -0
  70. package/commonjs/react/useOnItemStateChange.js +32 -0
  71. package/commonjs/react/useOnItemStateChange.js.map +1 -0
  72. package/commonjs/react/useState.js +140 -0
  73. package/commonjs/react/useState.js.map +1 -0
  74. package/commonjs/react/useStyle.js +29 -0
  75. package/commonjs/react/useStyle.js.map +1 -0
  76. package/commonjs/react/useVirtualScroller.js +62 -0
  77. package/commonjs/react/useVirtualScroller.js.map +1 -0
  78. package/commonjs/react/useVirtualScrollerStartStop.js +20 -0
  79. package/commonjs/react/useVirtualScrollerStartStop.js.map +1 -0
  80. package/commonjs/test/Engine.js +23 -0
  81. package/commonjs/test/Engine.js.map +1 -0
  82. package/commonjs/test/ItemsContainer.js +127 -0
  83. package/commonjs/test/ItemsContainer.js.map +1 -0
  84. package/commonjs/test/ScrollableContainer.js +130 -0
  85. package/commonjs/test/ScrollableContainer.js.map +1 -0
  86. package/commonjs/test/VirtualScroller.js +281 -0
  87. package/commonjs/test/VirtualScroller.js.map +1 -0
  88. package/commonjs/utility/debounce.js +2 -2
  89. package/commonjs/utility/debounce.js.map +1 -1
  90. package/commonjs/utility/debug.js.map +1 -1
  91. package/commonjs/utility/getStateSnapshot.js +2 -2
  92. package/commonjs/utility/getStateSnapshot.js.map +1 -1
  93. package/commonjs/utility/px.js.map +1 -1
  94. package/commonjs/utility/px.test.js +1 -1
  95. package/commonjs/utility/px.test.js.map +1 -1
  96. package/commonjs/utility/shallowEqual.js +1 -1
  97. package/commonjs/utility/shallowEqual.js.map +1 -1
  98. package/commonjs/utility/throttle.js.map +1 -1
  99. package/dom/index.cjs +4 -0
  100. package/dom/index.cjs.js +9 -0
  101. package/dom/index.d.ts +6 -4
  102. package/dom/index.js +1 -1
  103. package/dom/package.json +10 -4
  104. package/index.cjs +4 -0
  105. package/index.cjs.js +9 -0
  106. package/index.d.ts +30 -15
  107. package/index.js +1 -1
  108. package/modules/BeforeResize.js +22 -27
  109. package/modules/BeforeResize.js.map +1 -1
  110. package/modules/DOM/Engine.js +6 -6
  111. package/modules/DOM/Engine.js.map +1 -1
  112. package/modules/DOM/ItemsContainer.js +1 -1
  113. package/modules/DOM/ItemsContainer.js.map +1 -1
  114. package/modules/DOM/ListTopOffsetWatcher.js +15 -9
  115. package/modules/DOM/ListTopOffsetWatcher.js.map +1 -1
  116. package/modules/DOM/ScrollableContainer.js +28 -28
  117. package/modules/DOM/ScrollableContainer.js.map +1 -1
  118. package/modules/DOM/VirtualScroller.js +19 -16
  119. package/modules/DOM/VirtualScroller.js.map +1 -1
  120. package/modules/DOM/tbody.js +11 -9
  121. package/modules/DOM/tbody.js.map +1 -1
  122. package/modules/ItemHeights.js +22 -16
  123. package/modules/ItemHeights.js.map +1 -1
  124. package/modules/Layout.js +14 -12
  125. package/modules/Layout.js.map +1 -1
  126. package/modules/Layout.test.js +8 -3
  127. package/modules/Layout.test.js.map +1 -1
  128. package/modules/{ListHeightChangeWatcher.js → ListHeightMeasurement.js} +25 -27
  129. package/modules/ListHeightMeasurement.js.map +1 -0
  130. package/modules/Resize.js +38 -28
  131. package/modules/Resize.js.map +1 -1
  132. package/modules/Scroll.js +28 -44
  133. package/modules/Scroll.js.map +1 -1
  134. package/modules/VirtualScroller.columns.js +36 -0
  135. package/modules/VirtualScroller.columns.js.map +1 -0
  136. package/modules/VirtualScroller.constructor.js +371 -0
  137. package/modules/VirtualScroller.constructor.js.map +1 -0
  138. package/modules/VirtualScroller.items.js +288 -0
  139. package/modules/VirtualScroller.items.js.map +1 -0
  140. package/modules/VirtualScroller.js +132 -1860
  141. package/modules/VirtualScroller.js.map +1 -1
  142. package/modules/VirtualScroller.layout.js +549 -0
  143. package/modules/VirtualScroller.layout.js.map +1 -0
  144. package/modules/VirtualScroller.onRender.js +337 -0
  145. package/modules/VirtualScroller.onRender.js.map +1 -0
  146. package/modules/VirtualScroller.resize.js +176 -0
  147. package/modules/VirtualScroller.resize.js.map +1 -0
  148. package/modules/VirtualScroller.state.js +283 -0
  149. package/modules/VirtualScroller.state.js.map +1 -0
  150. package/modules/VirtualScroller.verticalSpacing.js +54 -0
  151. package/modules/VirtualScroller.verticalSpacing.js.map +1 -0
  152. package/modules/getItemCoordinates.js.map +1 -1
  153. package/modules/getItemsDiff.js.map +1 -1
  154. package/modules/getVerticalSpacing.js.map +1 -1
  155. package/modules/react/VirtualScroller.js +176 -625
  156. package/modules/react/VirtualScroller.js.map +1 -1
  157. package/modules/react/useClassName.js +18 -0
  158. package/modules/react/useClassName.js.map +1 -0
  159. package/modules/react/useHandleItemsChange.js +108 -0
  160. package/modules/react/useHandleItemsChange.js.map +1 -0
  161. package/modules/react/useInstanceMethods.js +28 -0
  162. package/modules/react/useInstanceMethods.js.map +1 -0
  163. package/modules/react/useItemKeys.js +52 -0
  164. package/modules/react/useItemKeys.js.map +1 -0
  165. package/modules/react/useOnItemHeightChange.js +24 -0
  166. package/modules/react/useOnItemHeightChange.js.map +1 -0
  167. package/modules/react/useOnItemStateChange.js +24 -0
  168. package/modules/react/useOnItemStateChange.js.map +1 -0
  169. package/modules/react/useState.js +132 -0
  170. package/modules/react/useState.js.map +1 -0
  171. package/modules/react/useStyle.js +19 -0
  172. package/modules/react/useStyle.js.map +1 -0
  173. package/modules/react/useVirtualScroller.js +51 -0
  174. package/modules/react/useVirtualScroller.js.map +1 -0
  175. package/modules/react/useVirtualScrollerStartStop.js +12 -0
  176. package/modules/react/useVirtualScrollerStartStop.js.map +1 -0
  177. package/modules/test/Engine.js +11 -0
  178. package/modules/test/Engine.js.map +1 -0
  179. package/modules/test/ItemsContainer.js +120 -0
  180. package/modules/test/ItemsContainer.js.map +1 -0
  181. package/modules/test/ScrollableContainer.js +123 -0
  182. package/modules/test/ScrollableContainer.js.map +1 -0
  183. package/modules/test/VirtualScroller.js +270 -0
  184. package/modules/test/VirtualScroller.js.map +1 -0
  185. package/modules/utility/debounce.js +2 -2
  186. package/modules/utility/debounce.js.map +1 -1
  187. package/modules/utility/debug.js.map +1 -1
  188. package/modules/utility/getStateSnapshot.js +2 -2
  189. package/modules/utility/getStateSnapshot.js.map +1 -1
  190. package/modules/utility/px.js.map +1 -1
  191. package/modules/utility/px.test.js +1 -1
  192. package/modules/utility/px.test.js.map +1 -1
  193. package/modules/utility/shallowEqual.js +1 -1
  194. package/modules/utility/shallowEqual.js.map +1 -1
  195. package/modules/utility/throttle.js.map +1 -1
  196. package/package.json +46 -23
  197. package/react/index.cjs +4 -0
  198. package/react/index.cjs.js +9 -0
  199. package/react/index.d.ts +10 -9
  200. package/react/index.js +1 -1
  201. package/react/package.json +10 -4
  202. package/rollup.config.mjs +62 -0
  203. package/runnable/create-commonjs-package-json.js +11 -0
  204. package/source/BeforeResize.js +16 -21
  205. package/source/DOM/Engine.js +8 -10
  206. package/source/DOM/ListTopOffsetWatcher.js +13 -8
  207. package/source/DOM/ScrollableContainer.js +23 -21
  208. package/source/DOM/VirtualScroller.js +27 -11
  209. package/source/DOM/tbody.js +30 -21
  210. package/source/ItemHeights.js +19 -14
  211. package/source/Layout.js +12 -9
  212. package/source/Layout.test.js +8 -3
  213. package/source/{ListHeightChangeWatcher.js → ListHeightMeasurement.js} +21 -20
  214. package/source/Resize.js +41 -25
  215. package/source/Scroll.js +27 -35
  216. package/source/VirtualScroller.columns.js +26 -0
  217. package/source/VirtualScroller.constructor.js +336 -0
  218. package/source/VirtualScroller.items.js +302 -0
  219. package/source/VirtualScroller.js +144 -1872
  220. package/source/VirtualScroller.layout.js +539 -0
  221. package/source/VirtualScroller.onRender.js +345 -0
  222. package/source/VirtualScroller.resize.js +189 -0
  223. package/source/VirtualScroller.state.js +284 -0
  224. package/source/VirtualScroller.verticalSpacing.js +51 -0
  225. package/source/react/VirtualScroller.js +243 -587
  226. package/source/react/useClassName.js +14 -0
  227. package/source/react/useHandleItemsChange.js +115 -0
  228. package/source/react/useInstanceMethods.js +25 -0
  229. package/source/react/useItemKeys.js +59 -0
  230. package/source/react/useOnItemHeightChange.js +28 -0
  231. package/source/react/useOnItemStateChange.js +28 -0
  232. package/source/react/useState.js +114 -0
  233. package/source/react/useStyle.js +20 -0
  234. package/source/react/useVirtualScroller.js +59 -0
  235. package/source/react/useVirtualScrollerStartStop.js +12 -0
  236. package/source/test/Engine.js +11 -0
  237. package/source/test/ItemsContainer.js +87 -0
  238. package/source/test/ScrollableContainer.js +88 -0
  239. package/source/test/VirtualScroller.js +232 -0
  240. package/source/utility/debounce.js +2 -2
  241. package/source/utility/px.test.js +1 -1
  242. package/babel.config.js +0 -25
  243. package/babel.js +0 -5
  244. package/commonjs/ListHeightChangeWatcher.js.map +0 -1
  245. package/dom/index.commonjs.js +0 -4
  246. package/index.commonjs.js +0 -4
  247. package/modules/ListHeightChangeWatcher.js.map +0 -1
  248. package/react/index.commonjs.js +0 -4
@@ -0,0 +1,337 @@
1
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
2
+
3
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
4
+
5
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
+
7
+ import log, { warn, isDebug } from './utility/debug.js';
8
+ import getStateSnapshot from './utility/getStateSnapshot.js';
9
+ import shallowEqual from './utility/shallowEqual.js';
10
+ import { LAYOUT_REASON } from './Layout.js';
11
+ import { setTbodyPadding } from './DOM/tbody.js';
12
+ export default function () {
13
+ var _this = this;
14
+
15
+ /**
16
+ * Should be called right after updates to `state` have been rendered.
17
+ * @param {object} newState
18
+ * @param {object} [prevState]
19
+ */
20
+ this._onRender = function (newState, prevState) {
21
+ log('~ Rendered ~');
22
+
23
+ if (isDebug()) {
24
+ log('State', getStateSnapshot(newState));
25
+ }
26
+
27
+ if (_this.onStateChange) {
28
+ if (!shallowEqual(newState, prevState)) {
29
+ _this.onStateChange(newState);
30
+ }
31
+ } // Update `<tbody/>` `padding`.
32
+ // (`<tbody/>` is different in a way that it can't have `margin`, only `padding`).
33
+ // https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1
34
+
35
+
36
+ if (_this.tbody) {
37
+ setTbodyPadding(_this.getItemsContainerElement(), newState.beforeItemsHeight, newState.afterItemsHeight);
38
+ }
39
+
40
+ if (!prevState) {
41
+ return;
42
+ } // `this.resetStateUpdateFlags()` must be called before calling
43
+ // `this.measureItemHeightsAndSpacing()`.
44
+
45
+
46
+ var _resetStateUpdateFlag = resetStateUpdateFlags.call(_this),
47
+ nonMeasuredItemsHaveBeenRendered = _resetStateUpdateFlag.nonMeasuredItemsHaveBeenRendered,
48
+ widthHasChanged = _resetStateUpdateFlag.widthHasChanged;
49
+
50
+ var layoutUpdateReason; // If the `VirtualScroller`, while calculating layout parameters, encounters
51
+ // a not-shown item with a non-measured height, it calls `updateState()` just to
52
+ // render that item first, and then, after the list has been re-rendered, it measures
53
+ // the item's height and then proceeds with calculating the correct layout parameters.
54
+
55
+ if (nonMeasuredItemsHaveBeenRendered) {
56
+ layoutUpdateReason = LAYOUT_REASON.NON_MEASURED_ITEMS_HAVE_BEEN_MEASURED;
57
+ } // If scrollable container width has changed, and it has been re-rendered,
58
+ // then it's time to measure the new item heights and then perform a re-layout
59
+ // with the correctly calculated layout parameters.
60
+ //
61
+ // A re-layout is required because the layout parameters calculated on resize
62
+ // are approximate ones, and the exact item heights aren't known at that point.
63
+ // So on resize, it calls `updateState()` just to re-render the `VirtualScroller`.
64
+ // After it has been re-rendered, it will measure item heights and then calculate
65
+ // correct layout parameters.
66
+ //
67
+
68
+
69
+ if (widthHasChanged) {
70
+ layoutUpdateReason = LAYOUT_REASON.VIEWPORT_WIDTH_CHANGED; // Reset measured item heights on viewport width change.
71
+
72
+ _this.itemHeights.reset(); // Reset `verticalSpacing` (will be re-measured).
73
+
74
+
75
+ _this.verticalSpacing = undefined;
76
+ }
77
+
78
+ var previousItems = prevState.items;
79
+ var newItems = newState.items; // Even if `this.newItemsWillBeRendered` flag is `true`,
80
+ // `newItems` could still be equal to `previousItems`.
81
+ // For example, when `updateState()` calls don't update `state` immediately
82
+ // and a developer first calls `setItems(newItems)` and then calls `setItems(oldItems)`:
83
+ // in that case, `this.newItemsWillBeRendered` flag will be `true` but the actual `items`
84
+ // in state wouldn't have changed due to the first `updateState()` call being overwritten
85
+ // by the second `updateState()` call (that's called "batching state updates" in React).
86
+
87
+ if (newItems !== previousItems) {
88
+ var itemsDiff = _this.getItemsDiff(previousItems, newItems);
89
+
90
+ if (itemsDiff) {
91
+ // The call to `.onPrepend()` must precede the call to `.measureItemHeights()`
92
+ // which is called in `.onRender()`.
93
+ // `this.itemHeights.onPrepend()` updates `firstMeasuredItemIndex`
94
+ // and `lastMeasuredItemIndex` of `this.itemHeights`.
95
+ var prependedItemsCount = itemsDiff.prependedItemsCount;
96
+
97
+ _this.itemHeights.onPrepend(prependedItemsCount);
98
+ } else {
99
+ _this.itemHeights.reset();
100
+ }
101
+
102
+ if (!widthHasChanged) {
103
+ // The call to `this.onNewItemsRendered()` must precede the call to
104
+ // `.measureItemHeights()` which is called in `.onRender()` because
105
+ // `this.onNewItemsRendered()` updates `firstMeasuredItemIndex` and
106
+ // `lastMeasuredItemIndex` of `this.itemHeights` in case of a prepend.
107
+ //
108
+ // If after prepending items the scroll position
109
+ // should be "restored" so that there's no "jump" of content
110
+ // then it means that all previous items have just been rendered
111
+ // in a single pass, and there's no need to update layout again.
112
+ //
113
+ if (onNewItemsRendered.call(_this, itemsDiff, newState) !== 'SEAMLESS_PREPEND') {
114
+ layoutUpdateReason = LAYOUT_REASON.ITEMS_CHANGED;
115
+ }
116
+ }
117
+ }
118
+
119
+ var stateUpdate; // Re-measure item heights.
120
+ // Also, measure vertical spacing (if not measured) and fix `<table/>` padding.
121
+ //
122
+ // This block should go after `if (newItems !== previousItems) {}`
123
+ // because `this.itemHeights` can get `.reset()` there, which would
124
+ // discard all the measurements done here, and having currently shown
125
+ // item height measurements is required.
126
+ //
127
+
128
+ if (newState.firstShownItemIndex !== prevState.firstShownItemIndex || newState.lastShownItemIndex !== prevState.lastShownItemIndex || newState.items !== prevState.items || widthHasChanged) {
129
+ var verticalSpacingStateUpdate = _this.measureItemHeightsAndSpacing();
130
+
131
+ if (verticalSpacingStateUpdate) {
132
+ stateUpdate = _objectSpread(_objectSpread({}, stateUpdate), verticalSpacingStateUpdate);
133
+ }
134
+ } // Clean up "before resize" item heights and adjust the scroll position accordingly.
135
+ // Calling `this.beforeResize.cleanUpBeforeResizeItemHeights()` might trigger
136
+ // a `this.updateState()` call but that wouldn't matter because `beforeResize`
137
+ // properties have already been modified directly in `state` (a hacky technique)
138
+
139
+
140
+ var cleanedUpBeforeResize = _this.beforeResize.cleanUpBeforeResizeItemHeights();
141
+
142
+ if (cleanedUpBeforeResize !== undefined) {
143
+ var scrollBy = cleanedUpBeforeResize.scrollBy,
144
+ beforeResize = cleanedUpBeforeResize.beforeResize;
145
+ log('Correct scroll position by', scrollBy);
146
+
147
+ _this.scroll.scrollByY(scrollBy);
148
+
149
+ stateUpdate = _objectSpread(_objectSpread({}, stateUpdate), {}, {
150
+ beforeResize: beforeResize
151
+ });
152
+ }
153
+
154
+ if (!_this._isActive) {
155
+ _this._stoppedStateUpdate = stateUpdate;
156
+ return;
157
+ }
158
+
159
+ if (layoutUpdateReason) {
160
+ updateStateRightAfterRender.call(_this, {
161
+ stateUpdate: stateUpdate,
162
+ reason: layoutUpdateReason
163
+ });
164
+ } else if (stateUpdate) {
165
+ _this.updateState(stateUpdate);
166
+ } else {
167
+ log('~ Finished Layout ~');
168
+ }
169
+ }; // After a new set of items has been rendered:
170
+ //
171
+ // * Restores scroll position when using `preserveScrollPositionOnPrependItems`
172
+ // and items have been prepended.
173
+ //
174
+ // * Applies any "pending" `itemHeights` updates — those ones that happened
175
+ // while an asynchronous `updateState()` call in `setItems()` was pending.
176
+ //
177
+ // * Either creates or resets the snapshot of the current layout.
178
+ //
179
+ // The current layout snapshot could be stored as a "previously calculated layout" variable
180
+ // so that it could theoretically be used when calculating new layout incrementally
181
+ // rather than from scratch, which would be an optimization.
182
+ //
183
+ // The "previously calculated layout" feature is not currently used.
184
+ //
185
+
186
+
187
+ function onNewItemsRendered(itemsDiff, newLayout) {
188
+ // If it's an "incremental" update.
189
+ if (itemsDiff) {
190
+ var prependedItemsCount = itemsDiff.prependedItemsCount,
191
+ appendedItemsCount = itemsDiff.appendedItemsCount;
192
+
193
+ var _this$getState = this.getState(),
194
+ itemHeights = _this$getState.itemHeights,
195
+ itemStates = _this$getState.itemStates; // See if any items' heights changed while new items were being rendered.
196
+
197
+
198
+ if (this.itemHeightsThatChangedWhileNewItemsWereBeingRendered) {
199
+ for (var _i = 0, _Object$keys = Object.keys(this.itemHeightsThatChangedWhileNewItemsWereBeingRendered); _i < _Object$keys.length; _i++) {
200
+ var i = _Object$keys[_i];
201
+ itemHeights[prependedItemsCount + parseInt(i)] = this.itemHeightsThatChangedWhileNewItemsWereBeingRendered[i];
202
+ }
203
+ } // See if any items' states changed while new items were being rendered.
204
+
205
+
206
+ if (this.itemStatesThatChangedWhileNewItemsWereBeingRendered) {
207
+ for (var _i2 = 0, _Object$keys2 = Object.keys(this.itemStatesThatChangedWhileNewItemsWereBeingRendered); _i2 < _Object$keys2.length; _i2++) {
208
+ var _i3 = _Object$keys2[_i2];
209
+ itemStates[prependedItemsCount + parseInt(_i3)] = this.itemStatesThatChangedWhileNewItemsWereBeingRendered[_i3];
210
+ }
211
+ }
212
+
213
+ if (prependedItemsCount === 0) {
214
+ // Adjust `this.previouslyCalculatedLayout`.
215
+ if (this.previouslyCalculatedLayout) {
216
+ if (this.previouslyCalculatedLayout.firstShownItemIndex === newLayout.firstShownItemIndex && this.previouslyCalculatedLayout.lastShownItemIndex === newLayout.lastShownItemIndex) {// `this.previouslyCalculatedLayout` stays the same.
217
+ // `firstShownItemIndex` / `lastShownItemIndex` didn't get changed in `setItems()`,
218
+ // so `beforeItemsHeight` and `shownItemsHeight` also stayed the same.
219
+ } else {
220
+ warn('Unexpected (non-matching) "firstShownItemIndex" or "lastShownItemIndex" encountered in "onRender()" after appending items');
221
+ warn('Previously calculated layout', this.previouslyCalculatedLayout);
222
+ warn('New layout', newLayout);
223
+ this.previouslyCalculatedLayout = undefined;
224
+ }
225
+ }
226
+
227
+ return 'SEAMLESS_APPEND';
228
+ } else {
229
+ if (this.listHeightMeasurement.hasSnapshot()) {
230
+ if (newLayout.firstShownItemIndex === 0) {
231
+ // Restore (adjust) scroll position.
232
+ log('~ Restore Scroll Position ~');
233
+ var listBottomOffsetChange = this.listHeightMeasurement.getListBottomOffsetChange({
234
+ beforeItemsHeight: newLayout.beforeItemsHeight
235
+ });
236
+ this.listHeightMeasurement.reset();
237
+
238
+ if (listBottomOffsetChange) {
239
+ log('Scroll down by', listBottomOffsetChange);
240
+ this.scroll.scrollByY(listBottomOffsetChange);
241
+ } else {
242
+ log('Scroll position hasn\'t changed');
243
+ } // Create new `this.previouslyCalculatedLayout`.
244
+
245
+
246
+ if (this.previouslyCalculatedLayout) {
247
+ if (this.previouslyCalculatedLayout.firstShownItemIndex === 0 && this.previouslyCalculatedLayout.lastShownItemIndex === newLayout.lastShownItemIndex - prependedItemsCount) {
248
+ this.previouslyCalculatedLayout = {
249
+ beforeItemsHeight: 0,
250
+ shownItemsHeight: this.previouslyCalculatedLayout.shownItemsHeight + listBottomOffsetChange,
251
+ firstShownItemIndex: 0,
252
+ lastShownItemIndex: newLayout.lastShownItemIndex
253
+ };
254
+ } else {
255
+ warn('Unexpected (non-matching) "firstShownItemIndex" or "lastShownItemIndex" encountered in "onRender()" after prepending items');
256
+ warn('Previously calculated layout', this.previouslyCalculatedLayout);
257
+ warn('New layout', newLayout);
258
+ this.previouslyCalculatedLayout = undefined;
259
+ }
260
+ }
261
+
262
+ return 'SEAMLESS_PREPEND';
263
+ } else {
264
+ warn("Unexpected \"firstShownItemIndex\" ".concat(newLayout.firstShownItemIndex, " encountered in \"onRender()\" after prepending items. Expected 0."));
265
+ }
266
+ }
267
+ }
268
+ } // Reset `this.previouslyCalculatedLayout` in any case other than
269
+ // SEAMLESS_PREPEND or SEAMLESS_APPEND.
270
+
271
+
272
+ this.previouslyCalculatedLayout = undefined;
273
+ }
274
+
275
+ function updateStateRightAfterRender(_ref) {
276
+ var reason = _ref.reason,
277
+ stateUpdate = _ref.stateUpdate;
278
+
279
+ // In React, `setTimeout()` is used to prevent a React error:
280
+ // "Maximum update depth exceeded.
281
+ // This can happen when a component repeatedly calls
282
+ // `.updateState()` inside `componentWillUpdate()` or `componentDidUpdate()`.
283
+ // React limits the number of nested updates to prevent infinite loops."
284
+ if (this._useTimeoutInRenderLoop) {
285
+ // Cancel a previously scheduled re-layout.
286
+ stateUpdate = this.cancelLayoutTimer({
287
+ stateUpdate: stateUpdate
288
+ }); // Schedule a new re-layout.
289
+
290
+ this.scheduleLayoutTimer({
291
+ reason: reason,
292
+ stateUpdate: stateUpdate
293
+ });
294
+ } else {
295
+ this.onUpdateShownItemIndexes({
296
+ reason: reason,
297
+ stateUpdate: stateUpdate
298
+ });
299
+ }
300
+ }
301
+
302
+ function resetStateUpdateFlags() {
303
+ // Read and reset `this.widthHasChanged` flag.
304
+ //
305
+ // If `this.widthHasChanged` flag was reset after calling
306
+ // `this.measureWidthHeightsAndSpacingAndUpdateTablePadding()`
307
+ // then there would be a bug because
308
+ // `this.measureWidthHeightsAndSpacingAndUpdateTablePadding()`
309
+ // calls `this.updateState({ verticalSpacing })` which calls
310
+ // `this.onRender()` immediately, so `this.widthHasChanged`
311
+ // flag wouldn't be reset by that time and would trigger things
312
+ // like `this.itemHeights.reset()` a second time.
313
+ //
314
+ // So, instead read the value of `this.widthHasChanged` flag
315
+ // and reset it right away to prevent any such potential bugs.
316
+ //
317
+ var widthHasChanged = Boolean(this.widthHasChanged); //
318
+ // Reset `this.widthHasChanged` flag.
319
+
320
+ this.widthHasChanged = undefined; // Read `this.firstNonMeasuredItemIndex` flag.
321
+
322
+ var nonMeasuredItemsHaveBeenRendered = this.firstNonMeasuredItemIndex !== undefined; // Reset `this.firstNonMeasuredItemIndex` flag.
323
+
324
+ this.firstNonMeasuredItemIndex = undefined; // Reset `this.newItemsWillBeRendered` flag.
325
+
326
+ this.newItemsWillBeRendered = undefined; // Reset `this.itemHeightsThatChangedWhileNewItemsWereBeingRendered`.
327
+
328
+ this.itemHeightsThatChangedWhileNewItemsWereBeingRendered = undefined; // Reset `this.itemStatesThatChangedWhileNewItemsWereBeingRendered`.
329
+
330
+ this.itemStatesThatChangedWhileNewItemsWereBeingRendered = undefined;
331
+ return {
332
+ nonMeasuredItemsHaveBeenRendered: nonMeasuredItemsHaveBeenRendered,
333
+ widthHasChanged: widthHasChanged
334
+ };
335
+ }
336
+ }
337
+ //# sourceMappingURL=VirtualScroller.onRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VirtualScroller.onRender.js","names":["log","warn","isDebug","getStateSnapshot","shallowEqual","LAYOUT_REASON","setTbodyPadding","_onRender","newState","prevState","onStateChange","tbody","getItemsContainerElement","beforeItemsHeight","afterItemsHeight","resetStateUpdateFlags","call","nonMeasuredItemsHaveBeenRendered","widthHasChanged","layoutUpdateReason","NON_MEASURED_ITEMS_HAVE_BEEN_MEASURED","VIEWPORT_WIDTH_CHANGED","itemHeights","reset","verticalSpacing","undefined","previousItems","items","newItems","itemsDiff","getItemsDiff","prependedItemsCount","onPrepend","onNewItemsRendered","ITEMS_CHANGED","stateUpdate","firstShownItemIndex","lastShownItemIndex","verticalSpacingStateUpdate","measureItemHeightsAndSpacing","cleanedUpBeforeResize","beforeResize","cleanUpBeforeResizeItemHeights","scrollBy","scroll","scrollByY","_isActive","_stoppedStateUpdate","updateStateRightAfterRender","reason","updateState","newLayout","appendedItemsCount","getState","itemStates","itemHeightsThatChangedWhileNewItemsWereBeingRendered","Object","keys","i","parseInt","itemStatesThatChangedWhileNewItemsWereBeingRendered","previouslyCalculatedLayout","listHeightMeasurement","hasSnapshot","listBottomOffsetChange","getListBottomOffsetChange","shownItemsHeight","_useTimeoutInRenderLoop","cancelLayoutTimer","scheduleLayoutTimer","onUpdateShownItemIndexes","Boolean","firstNonMeasuredItemIndex","newItemsWillBeRendered"],"sources":["../source/VirtualScroller.onRender.js"],"sourcesContent":["import log, { warn, isDebug } from './utility/debug.js'\r\nimport getStateSnapshot from './utility/getStateSnapshot.js'\r\nimport shallowEqual from './utility/shallowEqual.js'\r\nimport { LAYOUT_REASON } from './Layout.js'\r\nimport { setTbodyPadding } from './DOM/tbody.js'\r\n\r\nexport default function() {\r\n\t/**\r\n\t * Should be called right after updates to `state` have been rendered.\r\n\t * @param {object} newState\r\n\t * @param {object} [prevState]\r\n\t */\r\n\tthis._onRender = (newState, prevState) => {\r\n\t\tlog('~ Rendered ~')\r\n\t\tif (isDebug()) {\r\n\t\t\tlog('State', getStateSnapshot(newState))\r\n\t\t}\r\n\r\n\t\tif (this.onStateChange) {\r\n\t\t\tif (!shallowEqual(newState, prevState)) {\r\n\t\t\t\tthis.onStateChange(newState)\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Update `<tbody/>` `padding`.\r\n\t\t// (`<tbody/>` is different in a way that it can't have `margin`, only `padding`).\r\n\t\t// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1\r\n\t\tif (this.tbody) {\r\n\t\t\tsetTbodyPadding(\r\n\t\t\t\tthis.getItemsContainerElement(),\r\n\t\t\t\tnewState.beforeItemsHeight,\r\n\t\t\t\tnewState.afterItemsHeight\r\n\t\t\t)\r\n\t\t}\r\n\r\n\t\tif (!prevState) {\r\n\t\t\treturn\r\n\t\t}\r\n\r\n\t\t// `this.resetStateUpdateFlags()` must be called before calling\r\n\t\t// `this.measureItemHeightsAndSpacing()`.\r\n\t\tconst {\r\n\t\t\tnonMeasuredItemsHaveBeenRendered,\r\n\t\t\twidthHasChanged\r\n\t\t} = resetStateUpdateFlags.call(this)\r\n\r\n\t\tlet layoutUpdateReason\r\n\r\n\t\t// If the `VirtualScroller`, while calculating layout parameters, encounters\r\n\t\t// a not-shown item with a non-measured height, it calls `updateState()` just to\r\n\t\t// render that item first, and then, after the list has been re-rendered, it measures\r\n\t\t// the item's height and then proceeds with calculating the correct layout parameters.\r\n\t\tif (nonMeasuredItemsHaveBeenRendered) {\r\n\t\t\tlayoutUpdateReason = LAYOUT_REASON.NON_MEASURED_ITEMS_HAVE_BEEN_MEASURED\r\n\t\t}\r\n\r\n\t\t// If scrollable container width has changed, and it has been re-rendered,\r\n\t\t// then it's time to measure the new item heights and then perform a re-layout\r\n\t\t// with the correctly calculated layout parameters.\r\n\t\t//\r\n\t\t// A re-layout is required because the layout parameters calculated on resize\r\n\t\t// are approximate ones, and the exact item heights aren't known at that point.\r\n\t\t// So on resize, it calls `updateState()` just to re-render the `VirtualScroller`.\r\n\t\t// After it has been re-rendered, it will measure item heights and then calculate\r\n\t\t// correct layout parameters.\r\n\t\t//\r\n\t\tif (widthHasChanged) {\r\n\t\t\tlayoutUpdateReason = LAYOUT_REASON.VIEWPORT_WIDTH_CHANGED\r\n\r\n\t\t\t// Reset measured item heights on viewport width change.\r\n\t\t\tthis.itemHeights.reset()\r\n\r\n\t\t\t// Reset `verticalSpacing` (will be re-measured).\r\n\t\t\tthis.verticalSpacing = undefined\r\n\t\t}\r\n\r\n\t\tconst { items: previousItems } = prevState\r\n\t\tconst { items: newItems } = newState\r\n\t\t// Even if `this.newItemsWillBeRendered` flag is `true`,\r\n\t\t// `newItems` could still be equal to `previousItems`.\r\n\t\t// For example, when `updateState()` calls don't update `state` immediately\r\n\t\t// and a developer first calls `setItems(newItems)` and then calls `setItems(oldItems)`:\r\n\t\t// in that case, `this.newItemsWillBeRendered` flag will be `true` but the actual `items`\r\n\t\t// in state wouldn't have changed due to the first `updateState()` call being overwritten\r\n\t\t// by the second `updateState()` call (that's called \"batching state updates\" in React).\r\n\t\tif (newItems !== previousItems) {\r\n\t\t\tconst itemsDiff = this.getItemsDiff(previousItems, newItems)\r\n\t\t\tif (itemsDiff) {\r\n\t\t\t\t// The call to `.onPrepend()` must precede the call to `.measureItemHeights()`\r\n\t\t\t\t// which is called in `.onRender()`.\r\n\t\t\t\t// `this.itemHeights.onPrepend()` updates `firstMeasuredItemIndex`\r\n\t\t\t\t// and `lastMeasuredItemIndex` of `this.itemHeights`.\r\n\t\t\t\tconst { prependedItemsCount } = itemsDiff\r\n\t\t\t\tthis.itemHeights.onPrepend(prependedItemsCount)\r\n\t\t\t} else {\r\n\t\t\t\tthis.itemHeights.reset()\r\n\t\t\t}\r\n\r\n\t\t\tif (!widthHasChanged) {\r\n\t\t\t\t// The call to `this.onNewItemsRendered()` must precede the call to\r\n\t\t\t\t// `.measureItemHeights()` which is called in `.onRender()` because\r\n\t\t\t\t// `this.onNewItemsRendered()` updates `firstMeasuredItemIndex` and\r\n\t\t\t\t// `lastMeasuredItemIndex` of `this.itemHeights` in case of a prepend.\r\n\t\t\t\t//\r\n\t\t\t\t// If after prepending items the scroll position\r\n\t\t\t\t// should be \"restored\" so that there's no \"jump\" of content\r\n\t\t\t\t// then it means that all previous items have just been rendered\r\n\t\t\t\t// in a single pass, and there's no need to update layout again.\r\n\t\t\t\t//\r\n\t\t\t\tif (onNewItemsRendered.call(this, itemsDiff, newState) !== 'SEAMLESS_PREPEND') {\r\n\t\t\t\t\tlayoutUpdateReason = LAYOUT_REASON.ITEMS_CHANGED\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlet stateUpdate\r\n\r\n\t\t// Re-measure item heights.\r\n\t\t// Also, measure vertical spacing (if not measured) and fix `<table/>` padding.\r\n\t\t//\r\n\t\t// This block should go after `if (newItems !== previousItems) {}`\r\n\t\t// because `this.itemHeights` can get `.reset()` there, which would\r\n\t\t// discard all the measurements done here, and having currently shown\r\n\t\t// item height measurements is required.\r\n\t\t//\r\n\t\tif (\r\n\t\t\tnewState.firstShownItemIndex !== prevState.firstShownItemIndex ||\r\n\t\t\tnewState.lastShownItemIndex !== prevState.lastShownItemIndex ||\r\n\t\t\tnewState.items !== prevState.items ||\r\n\t\t\twidthHasChanged\r\n\t\t) {\r\n\t\t\tconst verticalSpacingStateUpdate = this.measureItemHeightsAndSpacing()\r\n\t\t\tif (verticalSpacingStateUpdate) {\r\n\t\t\t\tstateUpdate = {\r\n\t\t\t\t\t...stateUpdate,\r\n\t\t\t\t\t...verticalSpacingStateUpdate\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Clean up \"before resize\" item heights and adjust the scroll position accordingly.\r\n\t\t// Calling `this.beforeResize.cleanUpBeforeResizeItemHeights()` might trigger\r\n\t\t// a `this.updateState()` call but that wouldn't matter because `beforeResize`\r\n\t\t// properties have already been modified directly in `state` (a hacky technique)\r\n\t\tconst cleanedUpBeforeResize = this.beforeResize.cleanUpBeforeResizeItemHeights()\r\n\t\tif (cleanedUpBeforeResize !== undefined) {\r\n\t\t\tconst { scrollBy, beforeResize } = cleanedUpBeforeResize\r\n\t\t\tlog('Correct scroll position by', scrollBy)\r\n\t\t\tthis.scroll.scrollByY(scrollBy)\r\n\t\t\tstateUpdate = {\r\n\t\t\t\t...stateUpdate,\r\n\t\t\t\tbeforeResize\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!this._isActive) {\r\n\t\t\tthis._stoppedStateUpdate = stateUpdate\r\n\t\t\treturn\r\n\t\t}\r\n\r\n\t\tif (layoutUpdateReason) {\r\n\t\t\tupdateStateRightAfterRender.call(this, {\r\n\t\t\t\tstateUpdate,\r\n\t\t\t\treason: layoutUpdateReason\r\n\t\t\t})\r\n\t\t} else if (stateUpdate) {\r\n\t\t\tthis.updateState(stateUpdate)\r\n\t\t} else {\r\n\t\t\tlog('~ Finished Layout ~')\r\n\t\t}\r\n\t}\r\n\r\n\t// After a new set of items has been rendered:\r\n\t//\r\n\t// * Restores scroll position when using `preserveScrollPositionOnPrependItems`\r\n\t// and items have been prepended.\r\n\t//\r\n\t// * Applies any \"pending\" `itemHeights` updates — those ones that happened\r\n\t// while an asynchronous `updateState()` call in `setItems()` was pending.\r\n\t//\r\n\t// * Either creates or resets the snapshot of the current layout.\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\t// The \"previously calculated layout\" feature is not currently used.\r\n\t//\r\n\tfunction onNewItemsRendered(itemsDiff, newLayout) {\r\n\t\t// If it's an \"incremental\" update.\r\n\t\tif (itemsDiff) {\r\n\t\t\tconst {\r\n\t\t\t\tprependedItemsCount,\r\n\t\t\t\tappendedItemsCount\r\n\t\t\t} = itemsDiff\r\n\r\n\t\t\tconst {\r\n\t\t\t\titemHeights,\r\n\t\t\t\titemStates\r\n\t\t\t} = this.getState()\r\n\r\n\t\t\t// See if any items' heights changed while new items were being rendered.\r\n\t\t\tif (this.itemHeightsThatChangedWhileNewItemsWereBeingRendered) {\r\n\t\t\t\tfor (const i of Object.keys(this.itemHeightsThatChangedWhileNewItemsWereBeingRendered)) {\r\n\t\t\t\t\titemHeights[prependedItemsCount + parseInt(i)] = this.itemHeightsThatChangedWhileNewItemsWereBeingRendered[i]\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// See if any items' states changed while new items were being rendered.\r\n\t\t\tif (this.itemStatesThatChangedWhileNewItemsWereBeingRendered) {\r\n\t\t\t\tfor (const i of Object.keys(this.itemStatesThatChangedWhileNewItemsWereBeingRendered)) {\r\n\t\t\t\t\titemStates[prependedItemsCount + parseInt(i)] = this.itemStatesThatChangedWhileNewItemsWereBeingRendered[i]\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (prependedItemsCount === 0) {\r\n\t\t\t\t// Adjust `this.previouslyCalculatedLayout`.\r\n\t\t\t\tif (this.previouslyCalculatedLayout) {\r\n\t\t\t\t\tif (\r\n\t\t\t\t\t\tthis.previouslyCalculatedLayout.firstShownItemIndex === newLayout.firstShownItemIndex &&\r\n\t\t\t\t\t\tthis.previouslyCalculatedLayout.lastShownItemIndex === newLayout.lastShownItemIndex\r\n\t\t\t\t\t) {\r\n\t\t\t\t\t\t// `this.previouslyCalculatedLayout` stays the same.\r\n\t\t\t\t\t\t// `firstShownItemIndex` / `lastShownItemIndex` didn't get changed in `setItems()`,\r\n\t\t\t\t\t\t// so `beforeItemsHeight` and `shownItemsHeight` also stayed the same.\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\twarn('Unexpected (non-matching) \"firstShownItemIndex\" or \"lastShownItemIndex\" encountered in \"onRender()\" after appending items')\r\n\t\t\t\t\t\twarn('Previously calculated layout', this.previouslyCalculatedLayout)\r\n\t\t\t\t\t\twarn('New layout', newLayout)\r\n\t\t\t\t\t\tthis.previouslyCalculatedLayout = undefined\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\treturn 'SEAMLESS_APPEND'\r\n\t\t\t} else {\r\n\t\t\t\tif (this.listHeightMeasurement.hasSnapshot()) {\r\n\t\t\t\t\tif (newLayout.firstShownItemIndex === 0) {\r\n\t\t\t\t\t\t// Restore (adjust) scroll position.\r\n\t\t\t\t\t\tlog('~ Restore Scroll Position ~')\r\n\t\t\t\t\t\tconst listBottomOffsetChange = this.listHeightMeasurement.getListBottomOffsetChange({\r\n\t\t\t\t\t\t\tbeforeItemsHeight: newLayout.beforeItemsHeight\r\n\t\t\t\t\t\t})\r\n\t\t\t\t\t\tthis.listHeightMeasurement.reset()\r\n\t\t\t\t\t\tif (listBottomOffsetChange) {\r\n\t\t\t\t\t\t\tlog('Scroll down by', listBottomOffsetChange)\r\n\t\t\t\t\t\t\tthis.scroll.scrollByY(listBottomOffsetChange)\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tlog('Scroll position hasn\\'t changed')\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t// Create new `this.previouslyCalculatedLayout`.\r\n\t\t\t\t\t\tif (this.previouslyCalculatedLayout) {\r\n\t\t\t\t\t\t\tif (\r\n\t\t\t\t\t\t\t\tthis.previouslyCalculatedLayout.firstShownItemIndex === 0 &&\r\n\t\t\t\t\t\t\t\tthis.previouslyCalculatedLayout.lastShownItemIndex === newLayout.lastShownItemIndex - prependedItemsCount\r\n\t\t\t\t\t\t\t) {\r\n\t\t\t\t\t\t\t\tthis.previouslyCalculatedLayout = {\r\n\t\t\t\t\t\t\t\t\tbeforeItemsHeight: 0,\r\n\t\t\t\t\t\t\t\t\tshownItemsHeight: this.previouslyCalculatedLayout.shownItemsHeight + listBottomOffsetChange,\r\n\t\t\t\t\t\t\t\t\tfirstShownItemIndex: 0,\r\n\t\t\t\t\t\t\t\t\tlastShownItemIndex: newLayout.lastShownItemIndex\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\twarn('Unexpected (non-matching) \"firstShownItemIndex\" or \"lastShownItemIndex\" encountered in \"onRender()\" after prepending items')\r\n\t\t\t\t\t\t\t\twarn('Previously calculated layout', this.previouslyCalculatedLayout)\r\n\t\t\t\t\t\t\t\twarn('New layout', newLayout)\r\n\t\t\t\t\t\t\t\tthis.previouslyCalculatedLayout = undefined\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\treturn 'SEAMLESS_PREPEND'\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\twarn(`Unexpected \"firstShownItemIndex\" ${newLayout.firstShownItemIndex} encountered in \"onRender()\" after prepending items. Expected 0.`)\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Reset `this.previouslyCalculatedLayout` in any case other than\r\n\t\t// SEAMLESS_PREPEND or SEAMLESS_APPEND.\r\n\t\tthis.previouslyCalculatedLayout = undefined\r\n\t}\r\n\r\n\tfunction updateStateRightAfterRender({\r\n\t\treason,\r\n\t\tstateUpdate\r\n\t}) {\r\n\t\t// In React, `setTimeout()` is used to prevent a React error:\r\n\t\t// \"Maximum update depth exceeded.\r\n\t\t// This can happen when a component repeatedly calls\r\n\t\t// `.updateState()` inside `componentWillUpdate()` or `componentDidUpdate()`.\r\n\t\t// React limits the number of nested updates to prevent infinite loops.\"\r\n\t\tif (this._useTimeoutInRenderLoop) {\r\n\t\t\t// Cancel a previously scheduled re-layout.\r\n\t\t\tstateUpdate = this.cancelLayoutTimer({ stateUpdate })\r\n\t\t\t// Schedule a new re-layout.\r\n\t\t\tthis.scheduleLayoutTimer({\r\n\t\t\t\treason,\r\n\t\t\t\tstateUpdate\r\n\t\t\t})\r\n\t\t} else {\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}\r\n\t}\r\n\r\n\tfunction resetStateUpdateFlags() {\r\n\t\t// Read and reset `this.widthHasChanged` flag.\r\n\t\t//\r\n\t\t// If `this.widthHasChanged` flag was reset after calling\r\n\t\t// `this.measureWidthHeightsAndSpacingAndUpdateTablePadding()`\r\n\t\t// then there would be a bug because\r\n\t\t// `this.measureWidthHeightsAndSpacingAndUpdateTablePadding()`\r\n\t\t// calls `this.updateState({ verticalSpacing })` which calls\r\n\t\t// `this.onRender()` immediately, so `this.widthHasChanged`\r\n\t\t// flag wouldn't be reset by that time and would trigger things\r\n\t\t// like `this.itemHeights.reset()` a second time.\r\n\t\t//\r\n\t\t// So, instead read the value of `this.widthHasChanged` flag\r\n\t\t// and reset it right away to prevent any such potential bugs.\r\n\t\t//\r\n\t\tconst widthHasChanged = Boolean(this.widthHasChanged)\r\n\t\t//\r\n\t\t// Reset `this.widthHasChanged` flag.\r\n\t\tthis.widthHasChanged = undefined\r\n\r\n\t\t// Read `this.firstNonMeasuredItemIndex` flag.\r\n\t\tconst nonMeasuredItemsHaveBeenRendered = this.firstNonMeasuredItemIndex !== undefined\r\n\t\t// Reset `this.firstNonMeasuredItemIndex` flag.\r\n\t\tthis.firstNonMeasuredItemIndex = undefined\r\n\r\n\t\t// Reset `this.newItemsWillBeRendered` flag.\r\n\t\tthis.newItemsWillBeRendered = undefined\r\n\r\n\t\t// Reset `this.itemHeightsThatChangedWhileNewItemsWereBeingRendered`.\r\n\t\tthis.itemHeightsThatChangedWhileNewItemsWereBeingRendered = undefined\r\n\r\n\t\t// Reset `this.itemStatesThatChangedWhileNewItemsWereBeingRendered`.\r\n\t\tthis.itemStatesThatChangedWhileNewItemsWereBeingRendered = undefined\r\n\r\n\t\treturn {\r\n\t\t\tnonMeasuredItemsHaveBeenRendered,\r\n\t\t\twidthHasChanged\r\n\t\t}\r\n\t}\r\n}"],"mappings":"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"}
@@ -0,0 +1,176 @@
1
+ import log from './utility/debug.js';
2
+ export default function () {
3
+ var _this = this;
4
+
5
+ this.onResize = function () {
6
+ // Reset "previously calculated layout".
7
+ //
8
+ // The "previously calculated layout" feature is not currently used.
9
+ //
10
+ // The current layout snapshot could be stored as a "previously calculated layout" variable
11
+ // so that it could theoretically be used when calculating new layout incrementally
12
+ // rather than from scratch, which would be an optimization.
13
+ //
14
+ _this.previouslyCalculatedLayout = undefined; // Cancel any potential scheduled scroll position restoration.
15
+
16
+ _this.listHeightMeasurement.reset(); // Get the most recent items count.
17
+ // If there're a "pending" `setItems()` call then use the items count from that call
18
+ // instead of using the count of currently shown `items` from `state`.
19
+ // A `setItems()` call is "pending" when `updateState()` operation is "asynchronous", that is
20
+ // when `updateState()` calls aren't applied immediately, like in React.
21
+
22
+
23
+ var itemsCount = _this.newItemsWillBeRendered ? _this.newItemsWillBeRendered.count : _this.getState().itemHeights.length; // If layout values have been calculated as a result of a "pending" `setItems()` call,
24
+ // then don't discard those new layout values and use them instead of the ones from `state`.
25
+ //
26
+ // A `setItems()` call is "pending" when `updateState()` operation is "asynchronous", that is
27
+ // when `updateState()` calls aren't applied immediately, like in React.
28
+ //
29
+
30
+ var layout = _this.newItemsWillBeRendered ? _this.newItemsWillBeRendered.layout : _this.getState(); // Update `VirtualScroller` state.
31
+
32
+ var newState = {
33
+ scrollableContainerWidth: _this.scrollableContainer.getWidth(),
34
+ // This state update should also overwrite all the `state` properties
35
+ // that are also updated in the "on scroll" handler (`getShownItemIndexes()`):
36
+ //
37
+ // * `firstShownItemIndex`
38
+ // * `lastShownItemIndex`
39
+ // * `beforeItemsHeight`
40
+ // * `afterItemsHeight`
41
+ //
42
+ // That's because this `updateState()` update has a higher priority
43
+ // than that of the "on scroll" handler, so it should overwrite
44
+ // any potential state changes dispatched by the "on scroll" handler.
45
+ //
46
+ // All these properties might have changed, but they're not
47
+ // recalculated here becase they'll be recalculated after
48
+ // this new state is applied (rendered).
49
+ //
50
+ firstShownItemIndex: layout.firstShownItemIndex,
51
+ lastShownItemIndex: layout.lastShownItemIndex,
52
+ beforeItemsHeight: layout.beforeItemsHeight,
53
+ afterItemsHeight: layout.afterItemsHeight,
54
+ // Reset item heights, because if scrollable container's width (or height)
55
+ // has changed, then the list width (or height) most likely also has changed,
56
+ // and also some CSS `@media()` rules might have been added or removed.
57
+ // So re-render the list entirely.
58
+ itemHeights: new Array(itemsCount),
59
+ columnsCount: _this.getActualColumnsCountForState(),
60
+ // Re-measure vertical spacing after render because new CSS styles
61
+ // might be applied for the new window width.
62
+ verticalSpacing: undefined
63
+ };
64
+ var firstShownItemIndex = layout.firstShownItemIndex,
65
+ lastShownItemIndex = layout.lastShownItemIndex; // Get the `columnsCount` for the new window width.
66
+
67
+ var newColumnsCount = _this.getActualColumnsCount(); // Re-calculate `firstShownItemIndex` and `lastShownItemIndex`
68
+ // based on the new `columnsCount` so that the whole row is visible.
69
+
70
+
71
+ var newFirstShownItemIndex = Math.floor(firstShownItemIndex / newColumnsCount) * newColumnsCount;
72
+ var newLastShownItemIndex = Math.min(Math.ceil((lastShownItemIndex + 1) / newColumnsCount) * newColumnsCount, itemsCount) - 1; // Potentially update `firstShownItemIndex` if it needs to be adjusted in order to
73
+ // correspond to the new `columnsCount`.
74
+
75
+ if (newFirstShownItemIndex !== firstShownItemIndex) {
76
+ log('Columns Count changed from', _this.getState().columnsCount || 1, 'to', newColumnsCount);
77
+ log('First Shown Item Index needs to change from', firstShownItemIndex, 'to', newFirstShownItemIndex);
78
+ } // Always rewrite `firstShownItemIndex` and `lastShownItemIndex`
79
+ // as part of the `state` update, even if it hasn't been modified.
80
+ //
81
+ // The reason is that there could be two subsequent `onResize()` calls:
82
+ // the first one could be user resizing the window to half of its width,
83
+ // resulting in an "asynchronous" `updateState()` call, and then, before that
84
+ // `updateState()` call is applied, a second resize event happens when the user
85
+ // has resized the window back to its original width, meaning that the
86
+ // `columnsCount` is back to its original value.
87
+ // In that case, the final `newFirstShownItemIndex` will be equal to the
88
+ // original `firstShownItemIndex` that was in `state` before the user
89
+ // has started resizing the window, so, in the end, `state.firstShownItemIndex`
90
+ // property wouldn't have changed, but it still has to be part of the final
91
+ // state update in order to overwrite the previous update of `firstShownItemIndex`
92
+ // property that has been scheduled to be applied in state after the first resize
93
+ // happened.
94
+ //
95
+
96
+
97
+ newState.firstShownItemIndex = newFirstShownItemIndex;
98
+ newState.lastShownItemIndex = newLastShownItemIndex;
99
+
100
+ var verticalSpacing = _this.getVerticalSpacing();
101
+
102
+ var columnsCount = _this.getColumnsCount(); // `beforeResize` is always overwritten in `state` here.
103
+ // (once it has started being tracked in `state`)
104
+
105
+
106
+ if (_this.shouldDiscardBeforeResizeItemHeights() || newFirstShownItemIndex === 0) {
107
+ if (_this.beforeResize.shouldIncludeBeforeResizeValuesInState()) {
108
+ newState.beforeResize = undefined;
109
+ }
110
+ } // Snapshot "before resize" values in order to preserve the currently
111
+ // shown items' vertical position on screen so that there's no "content jumping".
112
+ else {
113
+ // Keep "before resize" values in order to preserve the currently
114
+ // shown items' vertical position on screen so that there's no
115
+ // "content jumping". These "before resize" values will be discarded
116
+ // when (if) the user scrolls back to the top of the list.
117
+ newState.beforeResize = {
118
+ verticalSpacing: verticalSpacing,
119
+ columnsCount: columnsCount,
120
+ itemHeights: _this.beforeResize.snapshotBeforeResizeItemHeights({
121
+ firstShownItemIndex: firstShownItemIndex,
122
+ newFirstShownItemIndex: newFirstShownItemIndex,
123
+ newColumnsCount: newColumnsCount
124
+ })
125
+ };
126
+ } // `this.widthHasChanged` tells `VirtualScroller` that it should
127
+ // temporarily stop other updates (like "on scroll" updates) and wait
128
+ // for the new `state` to be applied, after which the `onRender()`
129
+ // function will clear this flag and perform a re-layout.
130
+ //
131
+ // A re-layout is required because the layout parameters calculated above
132
+ // are approximate ones, and the exact item heights aren't known at this point.
133
+ // So the `updateState()` call below is just to re-render the `VirtualScroller`.
134
+ // After it has been re-rendered, it will measure item heights and then calculate
135
+ // correct layout parameters.
136
+ //
137
+
138
+
139
+ _this.widthHasChanged = {
140
+ stateUpdate: newState
141
+ }; // Rerender.
142
+
143
+ _this.updateState(newState);
144
+ }; // Returns whether "before resize" item heights should be discarded
145
+ // as a result of calling `setItems()` with a new set of items
146
+ // when an asynchronous `updateState()` call inside that function
147
+ // hasn't been applied yet.
148
+ //
149
+ // If `setItems()` update was an "incremental" one and no items
150
+ // have been prepended, then `firstShownItemIndex` is preserved,
151
+ // and all items' heights before it should be kept in order to
152
+ // preserve the top offset of the first shown item so that there's
153
+ // no "content jumping".
154
+ //
155
+ // If `setItems()` update was an "incremental" one but there're
156
+ // some prepended items, then it means that now there're new items
157
+ // with unknown heights at the top, so the top offset of the first
158
+ // shown item won't be preserved because there're no "before resize"
159
+ // heights of those items.
160
+ //
161
+ // If `setItems()` update was not an "incremental" one, then don't
162
+ // attempt to restore previous item heights after a potential window
163
+ // width change because all item heights have been reset.
164
+ //
165
+
166
+
167
+ this.shouldDiscardBeforeResizeItemHeights = function () {
168
+ if (_this.newItemsWillBeRendered) {
169
+ var _this$newItemsWillBeR = _this.newItemsWillBeRendered,
170
+ prepend = _this$newItemsWillBeR.prepend,
171
+ replace = _this$newItemsWillBeR.replace;
172
+ return prepend || replace;
173
+ }
174
+ };
175
+ }
176
+ //# sourceMappingURL=VirtualScroller.resize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VirtualScroller.resize.js","names":["log","onResize","previouslyCalculatedLayout","undefined","listHeightMeasurement","reset","itemsCount","newItemsWillBeRendered","count","getState","itemHeights","length","layout","newState","scrollableContainerWidth","scrollableContainer","getWidth","firstShownItemIndex","lastShownItemIndex","beforeItemsHeight","afterItemsHeight","Array","columnsCount","getActualColumnsCountForState","verticalSpacing","newColumnsCount","getActualColumnsCount","newFirstShownItemIndex","Math","floor","newLastShownItemIndex","min","ceil","getVerticalSpacing","getColumnsCount","shouldDiscardBeforeResizeItemHeights","beforeResize","shouldIncludeBeforeResizeValuesInState","snapshotBeforeResizeItemHeights","widthHasChanged","stateUpdate","updateState","prepend","replace"],"sources":["../source/VirtualScroller.resize.js"],"sourcesContent":["import log from './utility/debug.js'\r\n\r\nexport default function() {\r\n\tthis.onResize = () => {\r\n\t\t// Reset \"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\tthis.previouslyCalculatedLayout = undefined\r\n\r\n\t\t// Cancel any potential scheduled scroll position restoration.\r\n\t\tthis.listHeightMeasurement.reset()\r\n\r\n\t\t// Get the most recent items count.\r\n\t\t// If there're a \"pending\" `setItems()` call then use the items count from that call\r\n\t\t// instead of using the count of currently shown `items` from `state`.\r\n\t\t// A `setItems()` call is \"pending\" when `updateState()` operation is \"asynchronous\", that is\r\n\t\t// when `updateState()` calls aren't applied immediately, like in React.\r\n\t\tconst itemsCount = this.newItemsWillBeRendered\r\n\t\t\t? this.newItemsWillBeRendered.count\r\n\t\t\t: this.getState().itemHeights.length\r\n\r\n\t\t// If layout values have been calculated as a result of a \"pending\" `setItems()` call,\r\n\t\t// then don't discard those new layout values and use them instead of the ones from `state`.\r\n\t\t//\r\n\t\t// A `setItems()` call is \"pending\" when `updateState()` operation is \"asynchronous\", that is\r\n\t\t// when `updateState()` calls aren't applied immediately, like in React.\r\n\t\t//\r\n\t\tconst layout = this.newItemsWillBeRendered\r\n\t\t\t? this.newItemsWillBeRendered.layout\r\n\t\t\t: this.getState()\r\n\r\n\t\t// Update `VirtualScroller` state.\r\n\t\tconst newState = {\r\n\t\t\tscrollableContainerWidth: this.scrollableContainer.getWidth(),\r\n\r\n\t\t\t// This state update should also overwrite all the `state` properties\r\n\t\t\t// that are also updated in the \"on scroll\" handler (`getShownItemIndexes()`):\r\n\t\t\t//\r\n\t\t\t// * `firstShownItemIndex`\r\n\t\t\t// * `lastShownItemIndex`\r\n\t\t\t// * `beforeItemsHeight`\r\n\t\t\t// * `afterItemsHeight`\r\n\t\t\t//\r\n\t\t\t// That's because this `updateState()` update has a higher priority\r\n\t\t\t// than that of the \"on scroll\" handler, so it should overwrite\r\n\t\t\t// any potential state changes dispatched by the \"on scroll\" handler.\r\n\t\t\t//\r\n\t\t\t// All these properties might have changed, but they're not\r\n\t\t\t// recalculated here becase they'll be recalculated after\r\n\t\t\t// this new state is applied (rendered).\r\n\t\t\t//\r\n\t\t\tfirstShownItemIndex: layout.firstShownItemIndex,\r\n\t\t\tlastShownItemIndex: layout.lastShownItemIndex,\r\n\t\t\tbeforeItemsHeight: layout.beforeItemsHeight,\r\n\t\t\tafterItemsHeight: layout.afterItemsHeight,\r\n\r\n\t\t\t// Reset item heights, because if scrollable container's width (or height)\r\n\t\t\t// has changed, then the list width (or height) most likely also has changed,\r\n\t\t\t// and also some CSS `@media()` rules might have been added or removed.\r\n\t\t\t// So re-render the list entirely.\r\n\t\t\titemHeights: new Array(itemsCount),\r\n\r\n\t\t\tcolumnsCount: this.getActualColumnsCountForState(),\r\n\r\n\t\t\t// Re-measure vertical spacing after render because new CSS styles\r\n\t\t\t// might be applied for the new window width.\r\n\t\t\tverticalSpacing: undefined\r\n\t\t}\r\n\r\n\t\tconst { firstShownItemIndex, lastShownItemIndex } = layout\r\n\r\n\t\t// Get the `columnsCount` for the new window width.\r\n\t\tconst newColumnsCount = this.getActualColumnsCount()\r\n\r\n\t\t// Re-calculate `firstShownItemIndex` and `lastShownItemIndex`\r\n\t\t// based on the new `columnsCount` so that the whole row is visible.\r\n\t\tconst newFirstShownItemIndex = Math.floor(firstShownItemIndex / newColumnsCount) * newColumnsCount\r\n\t\tconst newLastShownItemIndex = Math.min(\r\n\t\t\tMath.ceil((lastShownItemIndex + 1) / newColumnsCount) * newColumnsCount,\r\n\t\t\titemsCount\r\n\t\t) - 1\r\n\r\n\t\t// Potentially update `firstShownItemIndex` if it needs to be adjusted in order to\r\n\t\t// correspond to the new `columnsCount`.\r\n\t\tif (newFirstShownItemIndex !== firstShownItemIndex) {\r\n\t\t\tlog('Columns Count changed from', this.getState().columnsCount || 1, 'to', newColumnsCount)\r\n\t\t\tlog('First Shown Item Index needs to change from', firstShownItemIndex, 'to', newFirstShownItemIndex)\r\n\t\t}\r\n\r\n\t\t// Always rewrite `firstShownItemIndex` and `lastShownItemIndex`\r\n\t\t// as part of the `state` update, even if it hasn't been modified.\r\n\t\t//\r\n\t\t// The reason is that there could be two subsequent `onResize()` calls:\r\n\t\t// the first one could be user resizing the window to half of its width,\r\n\t\t// resulting in an \"asynchronous\" `updateState()` call, and then, before that\r\n\t\t// `updateState()` call is applied, a second resize event happens when the user\r\n\t\t// has resized the window back to its original width, meaning that the\r\n\t\t// `columnsCount` is back to its original value.\r\n\t\t// In that case, the final `newFirstShownItemIndex` will be equal to the\r\n\t\t// original `firstShownItemIndex` that was in `state` before the user\r\n\t\t// has started resizing the window, so, in the end, `state.firstShownItemIndex`\r\n\t\t// property wouldn't have changed, but it still has to be part of the final\r\n\t\t// state update in order to overwrite the previous update of `firstShownItemIndex`\r\n\t\t// property that has been scheduled to be applied in state after the first resize\r\n\t\t// happened.\r\n\t\t//\r\n\t\tnewState.firstShownItemIndex = newFirstShownItemIndex\r\n\t\tnewState.lastShownItemIndex = newLastShownItemIndex\r\n\r\n\t\tconst verticalSpacing = this.getVerticalSpacing()\r\n\t\tconst columnsCount = this.getColumnsCount()\r\n\r\n\t\t// `beforeResize` is always overwritten in `state` here.\r\n\t\t// (once it has started being tracked in `state`)\r\n\t\tif (this.shouldDiscardBeforeResizeItemHeights() || newFirstShownItemIndex === 0) {\r\n\t\t\tif (this.beforeResize.shouldIncludeBeforeResizeValuesInState()) {\r\n\t\t\t\tnewState.beforeResize = undefined\r\n\t\t\t}\r\n\t\t}\r\n\t\t// Snapshot \"before resize\" values in order to preserve the currently\r\n\t\t// shown items' vertical position on screen so that there's no \"content jumping\".\r\n\t\telse {\r\n\t\t\t// Keep \"before resize\" values in order to preserve the currently\r\n\t\t\t// shown items' vertical position on screen so that there's no\r\n\t\t\t// \"content jumping\". These \"before resize\" values will be discarded\r\n\t\t\t// when (if) the user scrolls back to the top of the list.\r\n\t\t\tnewState.beforeResize = {\r\n\t\t\t\tverticalSpacing,\r\n\t\t\t\tcolumnsCount,\r\n\t\t\t\titemHeights: this.beforeResize.snapshotBeforeResizeItemHeights({\r\n\t\t\t\t\tfirstShownItemIndex,\r\n\t\t\t\t\tnewFirstShownItemIndex,\r\n\t\t\t\t\tnewColumnsCount\r\n\t\t\t\t})\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// `this.widthHasChanged` tells `VirtualScroller` that it should\r\n\t\t// temporarily stop other updates (like \"on scroll\" updates) and wait\r\n\t\t// for the new `state` to be applied, after which the `onRender()`\r\n\t\t// function will clear this flag and perform a re-layout.\r\n\t\t//\r\n\t\t// A re-layout is required because the layout parameters calculated above\r\n\t\t// are approximate ones, and the exact item heights aren't known at this point.\r\n\t\t// So the `updateState()` call below is just to re-render the `VirtualScroller`.\r\n\t\t// After it has been re-rendered, it will measure item heights and then calculate\r\n\t\t// correct layout parameters.\r\n\t\t//\r\n\t\tthis.widthHasChanged = {\r\n\t\t\tstateUpdate: newState\r\n\t\t}\r\n\r\n\t\t// Rerender.\r\n\t\tthis.updateState(newState)\r\n\t}\r\n\r\n\t// Returns whether \"before resize\" item heights should be discarded\r\n\t// as a result of calling `setItems()` with a new set of items\r\n\t// when an asynchronous `updateState()` call inside that function\r\n\t// hasn't been applied yet.\r\n\t//\r\n\t// If `setItems()` update was an \"incremental\" one and no items\r\n\t// have been prepended, then `firstShownItemIndex` is preserved,\r\n\t// and all items' heights before it should be kept in order to\r\n\t// preserve the top offset of the first shown item so that there's\r\n\t// no \"content jumping\".\r\n\t//\r\n\t// If `setItems()` update was an \"incremental\" one but there're\r\n\t// some prepended items, then it means that now there're new items\r\n\t// with unknown heights at the top, so the top offset of the first\r\n\t// shown item won't be preserved because there're no \"before resize\"\r\n\t// heights of those items.\r\n\t//\r\n\t// If `setItems()` update was not an \"incremental\" one, then don't\r\n\t// attempt to restore previous item heights after a potential window\r\n\t// width change because all item heights have been reset.\r\n\t//\r\n\tthis.shouldDiscardBeforeResizeItemHeights = () => {\r\n\t\tif (this.newItemsWillBeRendered) {\r\n\t\t\tconst { prepend, replace } = this.newItemsWillBeRendered\r\n\t\t\treturn prepend || replace\r\n\t\t}\r\n\t}\r\n}"],"mappings":"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"}