virtual-scroller 1.7.9 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/.gitlab-ci.yml +1 -1
  2. package/CHANGELOG.md +71 -1
  3. package/README.md +434 -151
  4. package/bundle/index-bypass.html +1 -1
  5. package/bundle/index-dom.html +1 -1
  6. package/bundle/index-grid.html +1 -2
  7. package/bundle/index-scrollableContainer.html +1 -1
  8. package/bundle/index-tbody-scrollableContainer.html +2 -0
  9. package/bundle/index-tbody.html +2 -0
  10. package/bundle/virtual-scroller-dom.js +1 -1
  11. package/bundle/virtual-scroller-dom.js.map +1 -1
  12. package/bundle/virtual-scroller-react.js +1 -1
  13. package/bundle/virtual-scroller-react.js.map +1 -1
  14. package/bundle/virtual-scroller.js +1 -1
  15. package/bundle/virtual-scroller.js.map +1 -1
  16. package/commonjs/BeforeResize.js +315 -0
  17. package/commonjs/BeforeResize.js.map +1 -0
  18. package/commonjs/DOM/Engine.js +46 -0
  19. package/commonjs/DOM/Engine.js.map +1 -0
  20. package/commonjs/DOM/ItemsContainer.js +78 -0
  21. package/commonjs/DOM/ItemsContainer.js.map +1 -0
  22. package/commonjs/DOM/{WaitForStylesToLoad.js → ListTopOffsetWatcher.js} +71 -44
  23. package/commonjs/DOM/ListTopOffsetWatcher.js.map +1 -0
  24. package/commonjs/DOM/ScrollableContainer.js +69 -101
  25. package/commonjs/DOM/ScrollableContainer.js.map +1 -1
  26. package/commonjs/DOM/VirtualScroller.js +37 -29
  27. package/commonjs/DOM/VirtualScroller.js.map +1 -1
  28. package/commonjs/DOM/tbody.js +17 -11
  29. package/commonjs/DOM/tbody.js.map +1 -1
  30. package/commonjs/ItemHeights.js +33 -34
  31. package/commonjs/ItemHeights.js.map +1 -1
  32. package/commonjs/Layout.js +591 -216
  33. package/commonjs/Layout.js.map +1 -1
  34. package/commonjs/Layout.test.js +196 -0
  35. package/commonjs/Layout.test.js.map +1 -0
  36. package/commonjs/ListHeightMeasurement.js +124 -0
  37. package/commonjs/ListHeightMeasurement.js.map +1 -0
  38. package/commonjs/Resize.js +50 -39
  39. package/commonjs/Resize.js.map +1 -1
  40. package/commonjs/Scroll.js +139 -95
  41. package/commonjs/Scroll.js.map +1 -1
  42. package/commonjs/VirtualScroller.columns.js +43 -0
  43. package/commonjs/VirtualScroller.columns.js.map +1 -0
  44. package/commonjs/VirtualScroller.constructor.js +408 -0
  45. package/commonjs/VirtualScroller.constructor.js.map +1 -0
  46. package/commonjs/VirtualScroller.items.js +305 -0
  47. package/commonjs/VirtualScroller.items.js.map +1 -0
  48. package/commonjs/VirtualScroller.js +160 -1021
  49. package/commonjs/VirtualScroller.js.map +1 -1
  50. package/commonjs/VirtualScroller.layout.js +562 -0
  51. package/commonjs/VirtualScroller.layout.js.map +1 -0
  52. package/commonjs/VirtualScroller.onRender.js +357 -0
  53. package/commonjs/VirtualScroller.onRender.js.map +1 -0
  54. package/commonjs/VirtualScroller.resize.js +186 -0
  55. package/commonjs/VirtualScroller.resize.js.map +1 -0
  56. package/commonjs/VirtualScroller.state.js +301 -0
  57. package/commonjs/VirtualScroller.state.js.map +1 -0
  58. package/commonjs/VirtualScroller.verticalSpacing.js +65 -0
  59. package/commonjs/VirtualScroller.verticalSpacing.js.map +1 -0
  60. package/commonjs/getItemCoordinates.js.map +1 -1
  61. package/commonjs/getItemsDiff.js.map +1 -1
  62. package/commonjs/getVerticalSpacing.js +8 -8
  63. package/commonjs/getVerticalSpacing.js.map +1 -1
  64. package/commonjs/package.json +5 -0
  65. package/commonjs/react/VirtualScroller.js +182 -628
  66. package/commonjs/react/VirtualScroller.js.map +1 -1
  67. package/commonjs/react/useClassName.js +26 -0
  68. package/commonjs/react/useClassName.js.map +1 -0
  69. package/commonjs/react/useHandleItemsChange.js +116 -0
  70. package/commonjs/react/useHandleItemsChange.js.map +1 -0
  71. package/commonjs/react/useInstanceMethods.js +37 -0
  72. package/commonjs/react/useInstanceMethods.js.map +1 -0
  73. package/commonjs/react/useItemKeys.js +60 -0
  74. package/commonjs/react/useItemKeys.js.map +1 -0
  75. package/commonjs/react/useOnItemHeightChange.js +32 -0
  76. package/commonjs/react/useOnItemHeightChange.js.map +1 -0
  77. package/commonjs/react/useOnItemStateChange.js +32 -0
  78. package/commonjs/react/useOnItemStateChange.js.map +1 -0
  79. package/commonjs/react/useState.js +140 -0
  80. package/commonjs/react/useState.js.map +1 -0
  81. package/commonjs/react/useStyle.js +29 -0
  82. package/commonjs/react/useStyle.js.map +1 -0
  83. package/commonjs/react/useVirtualScroller.js +62 -0
  84. package/commonjs/react/useVirtualScroller.js.map +1 -0
  85. package/commonjs/react/useVirtualScrollerStartStop.js +20 -0
  86. package/commonjs/react/useVirtualScrollerStartStop.js.map +1 -0
  87. package/commonjs/test/Engine.js +23 -0
  88. package/commonjs/test/Engine.js.map +1 -0
  89. package/commonjs/test/ItemsContainer.js +127 -0
  90. package/commonjs/test/ItemsContainer.js.map +1 -0
  91. package/commonjs/test/ScrollableContainer.js +130 -0
  92. package/commonjs/test/ScrollableContainer.js.map +1 -0
  93. package/commonjs/test/VirtualScroller.js +281 -0
  94. package/commonjs/test/VirtualScroller.js.map +1 -0
  95. package/commonjs/utility/debounce.js +28 -6
  96. package/commonjs/utility/debounce.js.map +1 -1
  97. package/commonjs/utility/debug.js +51 -12
  98. package/commonjs/utility/debug.js.map +1 -1
  99. package/commonjs/utility/getStateSnapshot.js +50 -0
  100. package/commonjs/utility/getStateSnapshot.js.map +1 -0
  101. package/commonjs/utility/px.js +1 -1
  102. package/commonjs/utility/px.js.map +1 -1
  103. package/commonjs/utility/px.test.js +14 -0
  104. package/commonjs/utility/px.test.js.map +1 -0
  105. package/commonjs/utility/shallowEqual.js +1 -1
  106. package/commonjs/utility/shallowEqual.js.map +1 -1
  107. package/commonjs/utility/throttle.js.map +1 -1
  108. package/dom/index.cjs +4 -0
  109. package/dom/index.cjs.js +9 -0
  110. package/dom/index.d.ts +25 -0
  111. package/dom/index.js +1 -1
  112. package/dom/package.json +10 -4
  113. package/index.cjs +4 -0
  114. package/index.cjs.js +9 -0
  115. package/index.d.ts +99 -0
  116. package/index.js +1 -1
  117. package/modules/BeforeResize.js +305 -0
  118. package/modules/BeforeResize.js.map +1 -0
  119. package/modules/DOM/Engine.js +27 -0
  120. package/modules/DOM/Engine.js.map +1 -0
  121. package/modules/DOM/ItemsContainer.js +71 -0
  122. package/modules/DOM/ItemsContainer.js.map +1 -0
  123. package/modules/DOM/{WaitForStylesToLoad.js → ListTopOffsetWatcher.js} +72 -44
  124. package/modules/DOM/ListTopOffsetWatcher.js.map +1 -0
  125. package/modules/DOM/ScrollableContainer.js +68 -100
  126. package/modules/DOM/ScrollableContainer.js.map +1 -1
  127. package/modules/DOM/VirtualScroller.js +32 -28
  128. package/modules/DOM/VirtualScroller.js.map +1 -1
  129. package/modules/DOM/tbody.js +11 -9
  130. package/modules/DOM/tbody.js.map +1 -1
  131. package/modules/ItemHeights.js +28 -33
  132. package/modules/ItemHeights.js.map +1 -1
  133. package/modules/Layout.js +585 -214
  134. package/modules/Layout.js.map +1 -1
  135. package/modules/Layout.test.js +190 -0
  136. package/modules/Layout.test.js.map +1 -0
  137. package/modules/ListHeightMeasurement.js +117 -0
  138. package/modules/ListHeightMeasurement.js.map +1 -0
  139. package/modules/Resize.js +50 -39
  140. package/modules/Resize.js.map +1 -1
  141. package/modules/Scroll.js +139 -94
  142. package/modules/Scroll.js.map +1 -1
  143. package/modules/VirtualScroller.columns.js +36 -0
  144. package/modules/VirtualScroller.columns.js.map +1 -0
  145. package/modules/VirtualScroller.constructor.js +371 -0
  146. package/modules/VirtualScroller.constructor.js.map +1 -0
  147. package/modules/VirtualScroller.items.js +288 -0
  148. package/modules/VirtualScroller.items.js.map +1 -0
  149. package/modules/VirtualScroller.js +159 -1014
  150. package/modules/VirtualScroller.js.map +1 -1
  151. package/modules/VirtualScroller.layout.js +549 -0
  152. package/modules/VirtualScroller.layout.js.map +1 -0
  153. package/modules/VirtualScroller.onRender.js +337 -0
  154. package/modules/VirtualScroller.onRender.js.map +1 -0
  155. package/modules/VirtualScroller.resize.js +176 -0
  156. package/modules/VirtualScroller.resize.js.map +1 -0
  157. package/modules/VirtualScroller.state.js +283 -0
  158. package/modules/VirtualScroller.state.js.map +1 -0
  159. package/modules/VirtualScroller.verticalSpacing.js +54 -0
  160. package/modules/VirtualScroller.verticalSpacing.js.map +1 -0
  161. package/modules/getItemCoordinates.js.map +1 -1
  162. package/modules/getItemsDiff.js.map +1 -1
  163. package/modules/getVerticalSpacing.js +8 -8
  164. package/modules/getVerticalSpacing.js.map +1 -1
  165. package/modules/react/VirtualScroller.js +179 -634
  166. package/modules/react/VirtualScroller.js.map +1 -1
  167. package/modules/react/useClassName.js +18 -0
  168. package/modules/react/useClassName.js.map +1 -0
  169. package/modules/react/useHandleItemsChange.js +108 -0
  170. package/modules/react/useHandleItemsChange.js.map +1 -0
  171. package/modules/react/useInstanceMethods.js +28 -0
  172. package/modules/react/useInstanceMethods.js.map +1 -0
  173. package/modules/react/useItemKeys.js +52 -0
  174. package/modules/react/useItemKeys.js.map +1 -0
  175. package/modules/react/useOnItemHeightChange.js +24 -0
  176. package/modules/react/useOnItemHeightChange.js.map +1 -0
  177. package/modules/react/useOnItemStateChange.js +24 -0
  178. package/modules/react/useOnItemStateChange.js.map +1 -0
  179. package/modules/react/useState.js +132 -0
  180. package/modules/react/useState.js.map +1 -0
  181. package/modules/react/useStyle.js +19 -0
  182. package/modules/react/useStyle.js.map +1 -0
  183. package/modules/react/useVirtualScroller.js +51 -0
  184. package/modules/react/useVirtualScroller.js.map +1 -0
  185. package/modules/react/useVirtualScrollerStartStop.js +12 -0
  186. package/modules/react/useVirtualScrollerStartStop.js.map +1 -0
  187. package/modules/test/Engine.js +11 -0
  188. package/modules/test/Engine.js.map +1 -0
  189. package/modules/test/ItemsContainer.js +120 -0
  190. package/modules/test/ItemsContainer.js.map +1 -0
  191. package/modules/test/ScrollableContainer.js +123 -0
  192. package/modules/test/ScrollableContainer.js.map +1 -0
  193. package/modules/test/VirtualScroller.js +270 -0
  194. package/modules/test/VirtualScroller.js.map +1 -0
  195. package/modules/utility/debounce.js +28 -6
  196. package/modules/utility/debounce.js.map +1 -1
  197. package/modules/utility/debug.js +47 -10
  198. package/modules/utility/debug.js.map +1 -1
  199. package/modules/utility/getStateSnapshot.js +43 -0
  200. package/modules/utility/getStateSnapshot.js.map +1 -0
  201. package/modules/utility/px.js +1 -1
  202. package/modules/utility/px.js.map +1 -1
  203. package/modules/utility/px.test.js +9 -0
  204. package/modules/utility/px.test.js.map +1 -0
  205. package/modules/utility/shallowEqual.js +1 -1
  206. package/modules/utility/shallowEqual.js.map +1 -1
  207. package/modules/utility/throttle.js.map +1 -1
  208. package/package.json +54 -29
  209. package/react/index.cjs +4 -0
  210. package/react/index.cjs.js +9 -0
  211. package/react/index.d.ts +28 -0
  212. package/react/index.js +1 -1
  213. package/react/package.json +10 -4
  214. package/rollup.config.mjs +62 -0
  215. package/runnable/create-commonjs-package-json.js +11 -0
  216. package/source/BeforeResize.js +312 -0
  217. package/source/DOM/Engine.js +30 -0
  218. package/source/DOM/ItemsContainer.js +48 -0
  219. package/source/DOM/{WaitForStylesToLoad.js → ListTopOffsetWatcher.js} +61 -30
  220. package/source/DOM/ScrollableContainer.js +51 -73
  221. package/source/DOM/VirtualScroller.js +33 -18
  222. package/source/DOM/tbody.js +30 -21
  223. package/source/ItemHeights.js +27 -27
  224. package/source/Layout.js +629 -252
  225. package/source/Layout.test.js +176 -0
  226. package/source/ListHeightMeasurement.js +95 -0
  227. package/source/Resize.js +56 -32
  228. package/source/Scroll.js +135 -82
  229. package/source/VirtualScroller.columns.js +26 -0
  230. package/source/VirtualScroller.constructor.js +336 -0
  231. package/source/VirtualScroller.items.js +302 -0
  232. package/source/VirtualScroller.js +162 -936
  233. package/source/VirtualScroller.layout.js +539 -0
  234. package/source/VirtualScroller.onRender.js +345 -0
  235. package/source/VirtualScroller.resize.js +189 -0
  236. package/source/VirtualScroller.state.js +284 -0
  237. package/source/VirtualScroller.verticalSpacing.js +51 -0
  238. package/source/getVerticalSpacing.js +7 -7
  239. package/source/react/VirtualScroller.js +243 -603
  240. package/source/react/useClassName.js +14 -0
  241. package/source/react/useHandleItemsChange.js +115 -0
  242. package/source/react/useInstanceMethods.js +25 -0
  243. package/source/react/useItemKeys.js +59 -0
  244. package/source/react/useOnItemHeightChange.js +28 -0
  245. package/source/react/useOnItemStateChange.js +28 -0
  246. package/source/react/useState.js +114 -0
  247. package/source/react/useStyle.js +20 -0
  248. package/source/react/useVirtualScroller.js +59 -0
  249. package/source/react/useVirtualScrollerStartStop.js +12 -0
  250. package/source/test/Engine.js +11 -0
  251. package/source/test/ItemsContainer.js +87 -0
  252. package/source/test/ScrollableContainer.js +88 -0
  253. package/source/test/VirtualScroller.js +232 -0
  254. package/source/utility/debounce.js +22 -5
  255. package/source/utility/debug.js +34 -3
  256. package/source/utility/getStateSnapshot.js +36 -0
  257. package/source/utility/px.js +1 -1
  258. package/source/utility/px.test.js +9 -0
  259. package/website/index-bypass.html +195 -0
  260. package/website/index-grid.html +0 -1
  261. package/website/index-scrollableContainer.html +208 -0
  262. package/website/index-tbody-scrollableContainer.html +68 -0
  263. package/website/index-tbody.html +55 -0
  264. package/commonjs/DOM/RenderingEngine.js +0 -33
  265. package/commonjs/DOM/RenderingEngine.js.map +0 -1
  266. package/commonjs/DOM/Screen.js +0 -87
  267. package/commonjs/DOM/Screen.js.map +0 -1
  268. package/commonjs/DOM/WaitForStylesToLoad.js.map +0 -1
  269. package/commonjs/RestoreScroll.js +0 -118
  270. package/commonjs/RestoreScroll.js.map +0 -1
  271. package/dom/index.commonjs.js +0 -4
  272. package/index.commonjs.js +0 -4
  273. package/modules/DOM/RenderingEngine.js +0 -19
  274. package/modules/DOM/RenderingEngine.js.map +0 -1
  275. package/modules/DOM/Screen.js +0 -80
  276. package/modules/DOM/Screen.js.map +0 -1
  277. package/modules/DOM/WaitForStylesToLoad.js.map +0 -1
  278. package/modules/RestoreScroll.js +0 -111
  279. package/modules/RestoreScroll.js.map +0 -1
  280. package/react/index.commonjs.js +0 -4
  281. package/source/DOM/RenderingEngine.js +0 -22
  282. package/source/DOM/Screen.js +0 -51
  283. package/source/RestoreScroll.js +0 -86
@@ -1,4 +1,8 @@
1
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
1
+ var _excluded = ["onMount", "onItemUnmount"];
2
+
3
+ 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; }
4
+
5
+ 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; }
2
6
 
3
7
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
4
8
 
@@ -8,33 +12,31 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
8
12
 
9
13
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
10
14
 
11
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
15
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
12
16
 
13
17
  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; }
14
18
 
15
- import VirtualScrollerCore from '../VirtualScroller';
16
- import log, { warn } from '../utility/debug';
17
- import px from '../utility/px';
19
+ import VirtualScrollerCore from '../VirtualScroller.js';
20
+ import log, { warn } from '../utility/debug.js';
21
+ import px from '../utility/px.js';
18
22
 
19
- var VirtualScroller =
20
- /*#__PURE__*/
21
- function () {
22
- function VirtualScroller(element, _items, renderItem) {
23
+ var VirtualScroller = /*#__PURE__*/function () {
24
+ function VirtualScroller(itemsContainerElement, _items, renderItem) {
23
25
  var _this = this;
24
26
 
25
27
  var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
26
28
 
27
29
  _classCallCheck(this, VirtualScroller);
28
30
 
29
- _defineProperty(this, "onStateChange", function (state, prevState) {
31
+ _defineProperty(this, "render", function (state, prevState) {
30
32
  var items = state.items,
31
33
  firstShownItemIndex = state.firstShownItemIndex,
32
34
  lastShownItemIndex = state.lastShownItemIndex,
33
35
  beforeItemsHeight = state.beforeItemsHeight,
34
- afterItemsHeight = state.afterItemsHeight;
35
- log('~ On state change ~');
36
- log('Previous state', prevState);
37
- log('New state', state); // Set container padding top and bottom.
36
+ afterItemsHeight = state.afterItemsHeight; // log('~ On state change ~')
37
+ // log('Previous state', prevState)
38
+ // log('New state', state)
39
+ // Set container padding top and bottom.
38
40
  // Work around `<tbody/>` not being able to have `padding`.
39
41
  // https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1
40
42
  // `this.virtualScroller` hasn't been initialized yet at this stage,
@@ -49,15 +51,14 @@ function () {
49
51
  var diffRender = prevState && items === prevState.items && items.length > 0; // Remove no longer visible items from the DOM.
50
52
 
51
53
  if (diffRender) {
52
- log('Incremental rerender'); // Decrement instead of increment here because
54
+ // Decrement instead of increment here because
53
55
  // `this.container.removeChild()` changes indexes.
54
-
55
56
  var _i = prevState.lastShownItemIndex;
56
57
 
57
58
  while (_i >= prevState.firstShownItemIndex) {
58
59
  if (_i >= firstShownItemIndex && _i <= lastShownItemIndex) {// The item is still visible.
59
60
  } else {
60
- log('Remove item index', _i); // The item is no longer visible. Remove it.
61
+ log('DOM: Remove element for item index', _i); // The item is no longer visible. Remove it.
61
62
 
62
63
  _this.unmountItem(_this.container.childNodes[_i - prevState.firstShownItemIndex]);
63
64
  }
@@ -65,7 +66,7 @@ function () {
65
66
  _i--;
66
67
  }
67
68
  } else {
68
- log('Rerender from scratch');
69
+ log('DOM: Rerender the list from scratch');
69
70
 
70
71
  while (_this.container.firstChild) {
71
72
  _this.unmountItem(_this.container.firstChild);
@@ -88,11 +89,11 @@ function () {
88
89
  var item = _this.renderItem(items[i]);
89
90
 
90
91
  if (shouldPrependItems) {
91
- log('Prepend item index', i); // Append `item` to `this.container` before the retained items.
92
+ log('DOM: Prepend element for item index', i); // Append `item` to `this.container` before the retained items.
92
93
 
93
94
  _this.container.insertBefore(item, prependBeforeItemElement);
94
95
  } else {
95
- log('Append item index', i); // Append `item` to `this.container`.
96
+ log('DOM: Append element for item index', i); // Append `item` to `this.container`.
96
97
 
97
98
  _this.container.appendChild(item);
98
99
  }
@@ -118,28 +119,31 @@ function () {
118
119
  _this.virtualScroller.stop();
119
120
  });
120
121
 
121
- this.container = element;
122
+ _defineProperty(this, "start", function () {
123
+ _this.virtualScroller.start();
124
+ });
125
+
126
+ this.container = itemsContainerElement;
122
127
  this.renderItem = renderItem;
123
128
 
124
129
  var onMount = options.onMount,
125
130
  onItemUnmount = options.onItemUnmount,
126
- restOptions = _objectWithoutProperties(options, ["onMount", "onItemUnmount"]);
131
+ restOptions = _objectWithoutProperties(options, _excluded);
127
132
 
128
133
  this.onItemUnmount = onItemUnmount;
129
134
  this.tbody = this.container.tagName === 'TBODY';
130
135
  this.virtualScroller = new VirtualScrollerCore(function () {
131
136
  return _this.container;
132
- }, _items, _objectSpread({}, restOptions, {
133
- tbody: this.tbody,
134
- onStateChange: this.onStateChange
135
- })); // `onMount()` option is deprecated due to no longer being used.
137
+ }, _items, _objectSpread(_objectSpread({}, restOptions), {}, {
138
+ render: this.render,
139
+ tbody: this.tbody
140
+ }));
141
+ this.start(); // `onMount()` option is deprecated due to no longer being used.
136
142
  // If someone thinks there's a valid use case for it, create an issue.
137
143
 
138
144
  if (onMount) {
139
145
  onMount();
140
146
  }
141
-
142
- this.virtualScroller.listen();
143
147
  }
144
148
 
145
149
  _createClass(VirtualScroller, [{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../source/DOM/VirtualScroller.js"],"names":["VirtualScrollerCore","log","warn","px","VirtualScroller","element","items","renderItem","options","state","prevState","firstShownItemIndex","lastShownItemIndex","beforeItemsHeight","afterItemsHeight","tbody","container","style","paddingTop","paddingBottom","diffRender","length","i","unmountItem","childNodes","firstChild","shouldPrependItems","prependBeforeItemElement","item","insertBefore","appendChild","stop","virtualScroller","onMount","onItemUnmount","restOptions","tagName","onStateChange","listen","itemElement","removeChild","onItemHeightChange","newItems","setItems"],"mappings":"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","sourcesContent":["import VirtualScrollerCore from '../VirtualScroller'\r\n\r\nimport log, { warn } from '../utility/debug'\r\nimport px from '../utility/px'\r\n\r\nexport default class VirtualScroller {\r\n constructor(element, items, renderItem, options = {}) {\r\n this.container = element\r\n this.renderItem = renderItem\r\n const {\r\n onMount,\r\n onItemUnmount,\r\n ...restOptions\r\n } = options\r\n this.onItemUnmount = onItemUnmount\r\n this.tbody = this.container.tagName === 'TBODY'\r\n this.virtualScroller = new VirtualScrollerCore(\r\n () => this.container,\r\n items,\r\n {\r\n ...restOptions,\r\n tbody: this.tbody,\r\n onStateChange: this.onStateChange\r\n }\r\n )\r\n // `onMount()` option is deprecated due to no longer being used.\r\n // If someone thinks there's a valid use case for it, create an issue.\r\n if (onMount) {\r\n onMount()\r\n }\r\n this.virtualScroller.listen()\r\n }\r\n\r\n onStateChange = (state, prevState) => {\r\n const {\r\n items,\r\n firstShownItemIndex,\r\n lastShownItemIndex,\r\n beforeItemsHeight,\r\n afterItemsHeight\r\n } = state\r\n log('~ On state change ~')\r\n log('Previous state', prevState)\r\n log('New state', state)\r\n // Set container padding top and bottom.\r\n // Work around `<tbody/>` not being able to have `padding`.\r\n // https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1\r\n // `this.virtualScroller` hasn't been initialized yet at this stage,\r\n // so using `this.tbody` instead of `this.virtualScroller.tbody`.\r\n if (!this.tbody) {\r\n this.container.style.paddingTop = px(beforeItemsHeight)\r\n this.container.style.paddingBottom = px(afterItemsHeight)\r\n }\r\n // Perform an intelligent \"diff\" re-render if the `items` are the same.\r\n const diffRender = prevState && items === prevState.items && items.length > 0\r\n // Remove no longer visible items from the DOM.\r\n if (diffRender) {\r\n log('Incremental rerender')\r\n // Decrement instead of increment here because\r\n // `this.container.removeChild()` changes indexes.\r\n let i = prevState.lastShownItemIndex\r\n while (i >= prevState.firstShownItemIndex) {\r\n if (i >= firstShownItemIndex && i <= lastShownItemIndex) {\r\n // The item is still visible.\r\n } else {\r\n log('Remove item index', i)\r\n // The item is no longer visible. Remove it.\r\n this.unmountItem(this.container.childNodes[i - prevState.firstShownItemIndex])\r\n }\r\n i--\r\n }\r\n } else {\r\n log('Rerender from scratch')\r\n while (this.container.firstChild) {\r\n this.unmountItem(this.container.firstChild)\r\n }\r\n }\r\n // Add newly visible items to the DOM.\r\n let shouldPrependItems = diffRender\r\n const prependBeforeItemElement = shouldPrependItems && this.container.firstChild\r\n let i = firstShownItemIndex\r\n while (i <= lastShownItemIndex) {\r\n if (diffRender && i >= prevState.firstShownItemIndex && i <= prevState.lastShownItemIndex) {\r\n // The item is already being rendered.\r\n // Next items will be appended rather than prepended.\r\n if (shouldPrependItems) {\r\n shouldPrependItems = false\r\n }\r\n } else {\r\n const item = this.renderItem(items[i])\r\n if (shouldPrependItems) {\r\n log('Prepend item index', i)\r\n // Append `item` to `this.container` before the retained items.\r\n this.container.insertBefore(item, prependBeforeItemElement)\r\n } else {\r\n log('Append item index', i)\r\n // Append `item` to `this.container`.\r\n this.container.appendChild(item)\r\n }\r\n }\r\n i++\r\n }\r\n }\r\n\r\n // Public API. Should be \"bound\" to `this`.\r\n onUnmount = () => {\r\n warn('`.onUnmount()` instance method name is deprecated, use `.stop()` instance method name instead.')\r\n this.stop()\r\n }\r\n\r\n // Public API. Should be \"bound\" to `this`.\r\n destroy = () => {\r\n warn('`.destroy()` instance method name is deprecated, use `.stop()` instance method name instead.')\r\n this.stop()\r\n }\r\n\r\n // Public API. Should be \"bound\" to `this`.\r\n stop = () => {\r\n this.virtualScroller.stop()\r\n }\r\n\r\n unmountItem(itemElement) {\r\n this.container.removeChild(itemElement)\r\n if (this.onItemUnmount) {\r\n this.onItemUnmount(itemElement)\r\n }\r\n }\r\n\r\n onItemHeightChange(i) {\r\n this.virtualScroller.onItemHeightChange(i)\r\n }\r\n\r\n /**\r\n * @deprecated\r\n * `.updateItems()` has been renamed to `.setItems()`.\r\n */\r\n updateItems(newItems, options) {\r\n this.setItems(newItems, options)\r\n }\r\n\r\n setItems(newItems, options) {\r\n this.virtualScroller.setItems(newItems, options)\r\n }\r\n\r\n /*\r\n getItemCoordinates(i) {\r\n return this.virtualScroller.getItemCoordinates(i)\r\n }\r\n */\r\n}"],"file":"VirtualScroller.js"}
1
+ {"version":3,"file":"VirtualScroller.js","names":["VirtualScrollerCore","log","warn","px","VirtualScroller","itemsContainerElement","items","renderItem","options","state","prevState","firstShownItemIndex","lastShownItemIndex","beforeItemsHeight","afterItemsHeight","tbody","container","style","paddingTop","paddingBottom","diffRender","length","i","unmountItem","childNodes","firstChild","shouldPrependItems","prependBeforeItemElement","item","insertBefore","appendChild","stop","virtualScroller","start","onMount","onItemUnmount","restOptions","tagName","render","itemElement","removeChild","onItemHeightChange","newItems","setItems"],"sources":["../../source/DOM/VirtualScroller.js"],"sourcesContent":["import VirtualScrollerCore from '../VirtualScroller.js'\r\n\r\nimport log, { warn } from '../utility/debug.js'\r\nimport px from '../utility/px.js'\r\n\r\nexport default class VirtualScroller {\r\n constructor(itemsContainerElement, items, renderItem, options = {}) {\r\n this.container = itemsContainerElement\r\n this.renderItem = renderItem\r\n\r\n const {\r\n onMount,\r\n onItemUnmount,\r\n ...restOptions\r\n } = options\r\n\r\n this.onItemUnmount = onItemUnmount\r\n this.tbody = this.container.tagName === 'TBODY'\r\n\r\n this.virtualScroller = new VirtualScrollerCore(\r\n () => this.container,\r\n items,\r\n {\r\n ...restOptions,\r\n render: this.render,\r\n tbody: this.tbody\r\n }\r\n )\r\n\r\n this.start()\r\n\r\n // `onMount()` option is deprecated due to no longer being used.\r\n // If someone thinks there's a valid use case for it, create an issue.\r\n if (onMount) {\r\n onMount()\r\n }\r\n }\r\n\r\n render = (state, prevState) => {\r\n const {\r\n items,\r\n firstShownItemIndex,\r\n lastShownItemIndex,\r\n beforeItemsHeight,\r\n afterItemsHeight\r\n } = state\r\n\r\n // log('~ On state change ~')\r\n // log('Previous state', prevState)\r\n // log('New state', state)\r\n\r\n // Set container padding top and bottom.\r\n // Work around `<tbody/>` not being able to have `padding`.\r\n // https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1\r\n // `this.virtualScroller` hasn't been initialized yet at this stage,\r\n // so using `this.tbody` instead of `this.virtualScroller.tbody`.\r\n if (!this.tbody) {\r\n this.container.style.paddingTop = px(beforeItemsHeight)\r\n this.container.style.paddingBottom = px(afterItemsHeight)\r\n }\r\n\r\n // Perform an intelligent \"diff\" re-render if the `items` are the same.\r\n const diffRender = prevState && items === prevState.items && items.length > 0\r\n // Remove no longer visible items from the DOM.\r\n if (diffRender) {\r\n // Decrement instead of increment here because\r\n // `this.container.removeChild()` changes indexes.\r\n let i = prevState.lastShownItemIndex\r\n while (i >= prevState.firstShownItemIndex) {\r\n if (i >= firstShownItemIndex && i <= lastShownItemIndex) {\r\n // The item is still visible.\r\n } else {\r\n log('DOM: Remove element for item index', i)\r\n // The item is no longer visible. Remove it.\r\n this.unmountItem(this.container.childNodes[i - prevState.firstShownItemIndex])\r\n }\r\n i--\r\n }\r\n } else {\r\n log('DOM: Rerender the list from scratch')\r\n while (this.container.firstChild) {\r\n this.unmountItem(this.container.firstChild)\r\n }\r\n }\r\n\r\n // Add newly visible items to the DOM.\r\n let shouldPrependItems = diffRender\r\n const prependBeforeItemElement = shouldPrependItems && this.container.firstChild\r\n let i = firstShownItemIndex\r\n while (i <= lastShownItemIndex) {\r\n if (diffRender && i >= prevState.firstShownItemIndex && i <= prevState.lastShownItemIndex) {\r\n // The item is already being rendered.\r\n // Next items will be appended rather than prepended.\r\n if (shouldPrependItems) {\r\n shouldPrependItems = false\r\n }\r\n } else {\r\n const item = this.renderItem(items[i])\r\n if (shouldPrependItems) {\r\n log('DOM: Prepend element for item index', i)\r\n // Append `item` to `this.container` before the retained items.\r\n this.container.insertBefore(item, prependBeforeItemElement)\r\n } else {\r\n log('DOM: Append element for item index', i)\r\n // Append `item` to `this.container`.\r\n this.container.appendChild(item)\r\n }\r\n }\r\n i++\r\n }\r\n }\r\n\r\n // Public API. Should be \"bound\" to `this`.\r\n onUnmount = () => {\r\n warn('`.onUnmount()` instance method name is deprecated, use `.stop()` instance method name instead.')\r\n this.stop()\r\n }\r\n\r\n // Public API. Should be \"bound\" to `this`.\r\n destroy = () => {\r\n warn('`.destroy()` instance method name is deprecated, use `.stop()` instance method name instead.')\r\n this.stop()\r\n }\r\n\r\n // Public API.\r\n // Should be \"bound\" to `this`.\r\n stop = () => {\r\n this.virtualScroller.stop()\r\n }\r\n\r\n // Potentially public API in some hypothetical scenario.\r\n // Should be \"bound\" to `this`.\r\n start = () => {\r\n this.virtualScroller.start()\r\n }\r\n\r\n unmountItem(itemElement) {\r\n this.container.removeChild(itemElement)\r\n if (this.onItemUnmount) {\r\n this.onItemUnmount(itemElement)\r\n }\r\n }\r\n\r\n onItemHeightChange(i) {\r\n this.virtualScroller.onItemHeightChange(i)\r\n }\r\n\r\n /**\r\n * @deprecated\r\n * `.updateItems()` has been renamed to `.setItems()`.\r\n */\r\n updateItems(newItems, options) {\r\n this.setItems(newItems, options)\r\n }\r\n\r\n setItems(newItems, options) {\r\n this.virtualScroller.setItems(newItems, options)\r\n }\r\n\r\n /*\r\n getItemCoordinates(i) {\r\n return this.virtualScroller.getItemCoordinates(i)\r\n }\r\n */\r\n}"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  // A workaround for `<tbody/>` not being able to have `padding`.
2
2
  // https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1
3
- import px from '../utility/px';
3
+ import px from '../utility/px.js';
4
4
  export var BROWSER_NOT_SUPPORTED_ERROR = 'It looks like you\'re using Internet Explorer which doesn\'t support CSS variables required for a <tbody/> container. VirtualScroller has been switched into "bypass" mode (render all items). See: https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1';
5
5
  export function supportsTbody() {
6
6
  // Detect Internet Explorer.
@@ -15,18 +15,20 @@ export function supportsTbody() {
15
15
 
16
16
  return true;
17
17
  }
18
+ export var TBODY_CLASS_NAME = 'VirtualScroller';
19
+ var STYLE_ELEMENT_ID = 'VirtualScrollerStyle';
20
+ export function hasTbodyStyles(tbody) {
21
+ return tbody.classList.contains(TBODY_CLASS_NAME) && Boolean(document.getElementById(STYLE_ELEMENT_ID));
22
+ }
18
23
  export function addTbodyStyles(tbody) {
19
24
  // `classList.add` is supported in Internet Explorer 10+.
20
- tbody.classList.add('VirtualScroller');
21
- var style = document.getElementById('VirtualScrollerStyle');
25
+ tbody.classList.add(TBODY_CLASS_NAME); // Create a `<style/>` element.
22
26
 
23
- if (!style) {
24
- style = document.createElement('style');
25
- style.id = 'VirtualScrollerStyle'; // CSS variables aren't supported in Internet Explorer.
27
+ var style = document.createElement('style');
28
+ style.id = STYLE_ELEMENT_ID; // CSS variables aren't supported in Internet Explorer.
26
29
 
27
- style.innerText = "\n\t\t\ttbody.VirtualScroller:before {\n\t\t\t\tcontent: '';\n\t\t\t\tdisplay: table-row;\n\t\t\t\theight: var(--VirtualScroller-paddingTop);\n\t\t\t}\n\t\t\ttbody.VirtualScroller:after {\n\t\t\t\tcontent: '';\n\t\t\t\tdisplay: table-row;\n\t\t\t\theight: var(--VirtualScroller-paddingBottom);\n\t\t\t}\n\t\t".replace(/[\n\t]/g, '');
28
- document.head.appendChild(style);
29
- }
30
+ style.innerText = "\n\t\ttbody.".concat(TBODY_CLASS_NAME, ":before {\n\t\t\tcontent: '';\n\t\t\tdisplay: table-row;\n\t\t\theight: var(--VirtualScroller-paddingTop);\n\t\t}\n\t\ttbody.").concat(TBODY_CLASS_NAME, ":after {\n\t\t\tcontent: '';\n\t\t\tdisplay: table-row;\n\t\t\theight: var(--VirtualScroller-paddingBottom);\n\t\t}\n\t").replace(/[\n\t]/g, '');
31
+ document.head.appendChild(style);
30
32
  }
31
33
  export function setTbodyPadding(tbody, beforeItemsHeight, afterItemsHeight) {
32
34
  // CSS variables aren't supported in Internet Explorer.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../source/DOM/tbody.js"],"names":["px","BROWSER_NOT_SUPPORTED_ERROR","supportsTbody","window","document","documentMode","addTbodyStyles","tbody","classList","add","style","getElementById","createElement","id","innerText","replace","head","appendChild","setTbodyPadding","beforeItemsHeight","afterItemsHeight","setProperty"],"mappings":"AAAA;AACA;AAEA,OAAOA,EAAP,MAAe,eAAf;AAEA,OAAO,IAAMC,2BAA2B,GAAG,mQAApC;AAEP,OAAO,SAASC,aAAT,GAAyB;AAC/B;AACA;AACA;AACA;AACA;AACA,MAAI,OAAOC,MAAP,KAAkB,WAAlB,IAAiCA,MAAM,CAACC,QAAP,CAAgBC,YAArD,EAAmE;AAClE;AACA,WAAO,KAAP;AACA;;AACD,SAAO,IAAP;AACA;AAED,OAAO,SAASC,cAAT,CAAwBC,KAAxB,EAA+B;AACrC;AACAA,EAAAA,KAAK,CAACC,SAAN,CAAgBC,GAAhB,CAAoB,iBAApB;AACA,MAAIC,KAAK,GAAGN,QAAQ,CAACO,cAAT,CAAwB,sBAAxB,CAAZ;;AACA,MAAI,CAACD,KAAL,EAAY;AACXA,IAAAA,KAAK,GAAGN,QAAQ,CAACQ,aAAT,CAAuB,OAAvB,CAAR;AACAF,IAAAA,KAAK,CAACG,EAAN,GAAW,sBAAX,CAFW,CAGX;;AACAH,IAAAA,KAAK,CAACI,SAAN,GAAkB,uTAWhBC,OAXgB,CAWR,SAXQ,EAWG,EAXH,CAAlB;AAYAX,IAAAA,QAAQ,CAACY,IAAT,CAAcC,WAAd,CAA0BP,KAA1B;AACA;AACD;AAED,OAAO,SAASQ,eAAT,CAAyBX,KAAzB,EAAgCY,iBAAhC,EAAmDC,gBAAnD,EAAqE;AAC3E;AACAb,EAAAA,KAAK,CAACG,KAAN,CAAYW,WAAZ,CAAwB,8BAAxB,EAAwDrB,EAAE,CAACmB,iBAAD,CAA1D;AACAZ,EAAAA,KAAK,CAACG,KAAN,CAAYW,WAAZ,CAAwB,iCAAxB,EAA2DrB,EAAE,CAACoB,gBAAD,CAA7D;AACA","sourcesContent":["// A workaround for `<tbody/>` not being able to have `padding`.\r\n// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1\r\n\r\nimport px from '../utility/px'\r\n\r\nexport const BROWSER_NOT_SUPPORTED_ERROR = 'It looks like you\\'re using Internet Explorer which doesn\\'t support CSS variables required for a <tbody/> container. VirtualScroller has been switched into \"bypass\" mode (render all items). See: https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1'\r\n\r\nexport function supportsTbody() {\r\n\t// Detect Internet Explorer.\r\n\t// https://stackoverflow.com/questions/19999388/check-if-user-is-using-ie\r\n\t// `documentMode` is an IE-only property.\r\n\t// Supports IE 9-11. Maybe even IE 8.\r\n\t// http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx\r\n\tif (typeof window !== 'undefined' && window.document.documentMode) {\r\n\t\t// CSS variables aren't supported in Internet Explorer.\r\n\t\treturn false\r\n\t}\r\n\treturn true\r\n}\r\n\r\nexport function addTbodyStyles(tbody) {\r\n\t// `classList.add` is supported in Internet Explorer 10+.\r\n\ttbody.classList.add('VirtualScroller')\r\n\tlet style = document.getElementById('VirtualScrollerStyle')\r\n\tif (!style) {\r\n\t\tstyle = document.createElement('style')\r\n\t\tstyle.id = 'VirtualScrollerStyle'\r\n\t\t// CSS variables aren't supported in Internet Explorer.\r\n\t\tstyle.innerText = `\r\n\t\t\ttbody.VirtualScroller:before {\r\n\t\t\t\tcontent: '';\r\n\t\t\t\tdisplay: table-row;\r\n\t\t\t\theight: var(--VirtualScroller-paddingTop);\r\n\t\t\t}\r\n\t\t\ttbody.VirtualScroller:after {\r\n\t\t\t\tcontent: '';\r\n\t\t\t\tdisplay: table-row;\r\n\t\t\t\theight: var(--VirtualScroller-paddingBottom);\r\n\t\t\t}\r\n\t\t`.replace(/[\\n\\t]/g, '')\r\n\t\tdocument.head.appendChild(style)\r\n\t}\r\n}\r\n\r\nexport function setTbodyPadding(tbody, beforeItemsHeight, afterItemsHeight) {\r\n\t// CSS variables aren't supported in Internet Explorer.\r\n\ttbody.style.setProperty('--VirtualScroller-paddingTop', px(beforeItemsHeight));\r\n\ttbody.style.setProperty('--VirtualScroller-paddingBottom', px(afterItemsHeight));\r\n}"],"file":"tbody.js"}
1
+ {"version":3,"file":"tbody.js","names":["px","BROWSER_NOT_SUPPORTED_ERROR","supportsTbody","window","document","documentMode","TBODY_CLASS_NAME","STYLE_ELEMENT_ID","hasTbodyStyles","tbody","classList","contains","Boolean","getElementById","addTbodyStyles","add","style","createElement","id","innerText","replace","head","appendChild","setTbodyPadding","beforeItemsHeight","afterItemsHeight","setProperty"],"sources":["../../source/DOM/tbody.js"],"sourcesContent":["// A workaround for `<tbody/>` not being able to have `padding`.\r\n// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1\r\n\r\nimport px from '../utility/px.js'\r\n\r\nexport const BROWSER_NOT_SUPPORTED_ERROR = 'It looks like you\\'re using Internet Explorer which doesn\\'t support CSS variables required for a <tbody/> container. VirtualScroller has been switched into \"bypass\" mode (render all items). See: https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1'\r\n\r\nexport function supportsTbody() {\r\n\t// Detect Internet Explorer.\r\n\t// https://stackoverflow.com/questions/19999388/check-if-user-is-using-ie\r\n\t// `documentMode` is an IE-only property.\r\n\t// Supports IE 9-11. Maybe even IE 8.\r\n\t// http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx\r\n\tif (typeof window !== 'undefined' && window.document.documentMode) {\r\n\t\t// CSS variables aren't supported in Internet Explorer.\r\n\t\treturn false\r\n\t}\r\n\treturn true\r\n}\r\n\r\nexport const TBODY_CLASS_NAME = 'VirtualScroller'\r\nconst STYLE_ELEMENT_ID = 'VirtualScrollerStyle'\r\n\r\nexport function hasTbodyStyles(tbody) {\r\n\treturn tbody.classList.contains(TBODY_CLASS_NAME) &&\r\n\t\tBoolean(document.getElementById(STYLE_ELEMENT_ID))\r\n}\r\n\r\nexport function addTbodyStyles(tbody) {\r\n\t// `classList.add` is supported in Internet Explorer 10+.\r\n\ttbody.classList.add(TBODY_CLASS_NAME)\r\n\r\n\t// Create a `<style/>` element.\r\n\tconst style = document.createElement('style')\r\n\tstyle.id = STYLE_ELEMENT_ID\r\n\r\n\t// CSS variables aren't supported in Internet Explorer.\r\n\tstyle.innerText = `\r\n\t\ttbody.${TBODY_CLASS_NAME}:before {\r\n\t\t\tcontent: '';\r\n\t\t\tdisplay: table-row;\r\n\t\t\theight: var(--VirtualScroller-paddingTop);\r\n\t\t}\r\n\t\ttbody.${TBODY_CLASS_NAME}:after {\r\n\t\t\tcontent: '';\r\n\t\t\tdisplay: table-row;\r\n\t\t\theight: var(--VirtualScroller-paddingBottom);\r\n\t\t}\r\n\t`.replace(/[\\n\\t]/g, '')\r\n\r\n\tdocument.head.appendChild(style)\r\n}\r\n\r\nexport function setTbodyPadding(tbody, beforeItemsHeight, afterItemsHeight) {\r\n\t// CSS variables aren't supported in Internet Explorer.\r\n\ttbody.style.setProperty('--VirtualScroller-paddingTop', px(beforeItemsHeight));\r\n\ttbody.style.setProperty('--VirtualScroller-paddingBottom', px(afterItemsHeight));\r\n}"],"mappings":"AAAA;AACA;AAEA,OAAOA,EAAP,MAAe,kBAAf;AAEA,OAAO,IAAMC,2BAA2B,GAAG,mQAApC;AAEP,OAAO,SAASC,aAAT,GAAyB;EAC/B;EACA;EACA;EACA;EACA;EACA,IAAI,OAAOC,MAAP,KAAkB,WAAlB,IAAiCA,MAAM,CAACC,QAAP,CAAgBC,YAArD,EAAmE;IAClE;IACA,OAAO,KAAP;EACA;;EACD,OAAO,IAAP;AACA;AAED,OAAO,IAAMC,gBAAgB,GAAG,iBAAzB;AACP,IAAMC,gBAAgB,GAAG,sBAAzB;AAEA,OAAO,SAASC,cAAT,CAAwBC,KAAxB,EAA+B;EACrC,OAAOA,KAAK,CAACC,SAAN,CAAgBC,QAAhB,CAAyBL,gBAAzB,KACNM,OAAO,CAACR,QAAQ,CAACS,cAAT,CAAwBN,gBAAxB,CAAD,CADR;AAEA;AAED,OAAO,SAASO,cAAT,CAAwBL,KAAxB,EAA+B;EACrC;EACAA,KAAK,CAACC,SAAN,CAAgBK,GAAhB,CAAoBT,gBAApB,EAFqC,CAIrC;;EACA,IAAMU,KAAK,GAAGZ,QAAQ,CAACa,aAAT,CAAuB,OAAvB,CAAd;EACAD,KAAK,CAACE,EAAN,GAAWX,gBAAX,CANqC,CAQrC;;EACAS,KAAK,CAACG,SAAN,GAAkB,sBACTb,gBADS,0IAMTA,gBANS,6HAWhBc,OAXgB,CAWR,SAXQ,EAWG,EAXH,CAAlB;EAaAhB,QAAQ,CAACiB,IAAT,CAAcC,WAAd,CAA0BN,KAA1B;AACA;AAED,OAAO,SAASO,eAAT,CAAyBd,KAAzB,EAAgCe,iBAAhC,EAAmDC,gBAAnD,EAAqE;EAC3E;EACAhB,KAAK,CAACO,KAAN,CAAYU,WAAZ,CAAwB,8BAAxB,EAAwD1B,EAAE,CAACwB,iBAAD,CAA1D;EACAf,KAAK,CAACO,KAAN,CAAYU,WAAZ,CAAwB,iCAAxB,EAA2D1B,EAAE,CAACyB,gBAAD,CAA7D;AACA"}
@@ -2,18 +2,20 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
2
2
 
3
3
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
4
4
 
5
- function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
5
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
6
6
 
7
- import log, { warn, isDebug, reportError } from './utility/debug';
7
+ import log, { warn, isDebug, reportError } from './utility/debug.js';
8
+
9
+ var ItemHeights = /*#__PURE__*/function () {
10
+ function ItemHeights(_ref) {
11
+ var container = _ref.container,
12
+ itemHeights = _ref.itemHeights,
13
+ getItemHeight = _ref.getItemHeight,
14
+ setItemHeight = _ref.setItemHeight;
8
15
 
9
- var ItemHeights =
10
- /*#__PURE__*/
11
- function () {
12
- function ItemHeights(screen, getContainerElement, getItemHeight, setItemHeight) {
13
16
  _classCallCheck(this, ItemHeights);
14
17
 
15
- this.screen = screen;
16
- this.getContainerElement = getContainerElement;
18
+ this.container = container;
17
19
  this._get = getItemHeight;
18
20
  this._set = setItemHeight;
19
21
  this.reset();
@@ -36,7 +38,7 @@ function () {
36
38
  this.lastMeasuredItemIndex = undefined;
37
39
  }
38
40
  /**
39
- * Is called after `.reset()`.
41
+ * Can only be called after a `.reset()` (including new instance creation).
40
42
  * Initializes `this.measuredItemsHeight`, `this.firstMeasuredItemIndex`
41
43
  * and `this.lastMeasuredItemIndex` instance variables from `VirtualScroller` `state`.
42
44
  * These instance variables are used when calculating "average" item height:
@@ -45,8 +47,9 @@ function () {
45
47
  */
46
48
 
47
49
  }, {
48
- key: "initialize",
49
- value: function initialize(itemHeights) {
50
+ key: "readItemHeightsFromState",
51
+ value: function readItemHeightsFromState(_ref2) {
52
+ var itemHeights = _ref2.itemHeights;
50
53
  var i = 0;
51
54
 
52
55
  while (i < itemHeights.length) {
@@ -81,15 +84,7 @@ function () {
81
84
  }, {
82
85
  key: "_measureItemHeight",
83
86
  value: function _measureItemHeight(i, firstShownItemIndex) {
84
- var container = this.getContainerElement();
85
-
86
- if (container) {
87
- var elementIndex = i - firstShownItemIndex;
88
-
89
- if (elementIndex >= 0 && elementIndex < this.screen.getChildElementsCount(container)) {
90
- return this.screen.getChildElementHeight(container, elementIndex);
91
- }
92
- }
87
+ return this.container.getNthRenderedItemHeight(i - firstShownItemIndex);
93
88
  }
94
89
  /**
95
90
  * Measures item heights:
@@ -113,7 +108,8 @@ function () {
113
108
  }, {
114
109
  key: "measureItemHeights",
115
110
  value: function measureItemHeights(firstShownItemIndex, lastShownItemIndex) {
116
- // If no items are rendered, don't measure anything.
111
+ log('~ Measure item heights ~'); // If no items are rendered, don't measure anything.
112
+
117
113
  if (firstShownItemIndex === undefined) {
118
114
  return;
119
115
  } // Reset `this.measuredItemsHeight` if it's not a "continuous" measured items list:
@@ -138,22 +134,18 @@ function () {
138
134
  var i = firstShownItemIndex;
139
135
 
140
136
  while (i <= lastShownItemIndex) {
137
+ // Measure item heights that haven't been measured previously.
141
138
  // Don't re-measure item heights that have been measured previously.
142
139
  // The rationale is that developers are supposed to manually call
143
140
  // `.onItemHeightChange()` every time an item's height changes.
144
- // If developers aren't neglecting that rule, item heights won't
141
+ // If developers don't neglect that rule, item heights won't
145
142
  // change unexpectedly.
146
- // // Re-measure all shown items' heights, because an item's height
147
- // // might have changed since it has been measured initially.
148
- // // For example, if an item is a long comment with a "Show more" button,
149
- // // then the user might have clicked that "Show more" button.
150
143
  if (this._get(i) === undefined) {
151
144
  nonPreviouslyMeasuredItemIndexes.push(i);
152
- log('Item', i, 'hasn\'t been previously measured');
153
145
 
154
146
  var height = this._measureItemHeight(i, firstShownItemIndex);
155
147
 
156
- log('Height', height);
148
+ log('Item index', i, 'height', height);
157
149
 
158
150
  this._set(i, height); // Update average item height calculation variables
159
151
  // related to the previously measured items
@@ -193,16 +185,19 @@ function () {
193
185
  this.lastMeasuredItemIndex = i;
194
186
  }
195
187
  } else {
196
- // Validate the item's height right after showing it after being hidden,
197
- // because, if the stored item's state isn't applied properly, the item's
198
- // height might be incorrect when it's rendered with that state not applied,
199
- // and so a developer could know that there's a bug in their code.
188
+ // Validate that the item's height didn't change since it was last measured.
189
+ // If it did, then display a warning and update the item's height
190
+ // as an attempt to fix things.
191
+ // If an item's height changes unexpectedly then it means that there'll
192
+ // likely be "content jumping".
200
193
  var previousHeight = this._get(i);
201
194
 
202
195
  var _height = this._measureItemHeight(i, firstShownItemIndex);
203
196
 
204
197
  if (previousHeight !== _height) {
205
- warn('Item', i, 'height was', previousHeight, 'before it was hidden, but, after showing it again, its height is', _height, '. Perhaps you forgot to persist the item\'s state by calling `onItemStateChange(i, newState)` when it changed, and that state got lost when the item element was unmounted, which resulted in a different height when the item was shown again, but with the missing state.');
198
+ warn('Item index', i, 'height changed unexpectedly: it was', previousHeight, 'before, but now it is', _height, '. An item\'s height is allowed to change only in two cases: when the item\'s "state" changes and the developer calls `onItemStateChange(i, newState)`, or when the item\'s height changes for some other reason and the developer calls `onItemHeightChange(i)`. Perhaps you forgot to persist the item\'s "state" by calling `onItemStateChange(i, newState)` when it changed, and that "state" got lost when the item element was unmounted, which resulted in a different height when the item was shown again having its "state" reset.'); // Update the item's height as an attempt to fix things.
199
+
200
+ this._set(i, _height);
206
201
  }
207
202
  }
208
203
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../source/ItemHeights.js"],"names":["log","warn","isDebug","reportError","ItemHeights","screen","getContainerElement","getItemHeight","setItemHeight","_get","_set","reset","measuredItemsHeight","firstMeasuredItemIndex","undefined","lastMeasuredItemIndex","itemHeights","i","length","firstShownItemIndex","container","elementIndex","getChildElementsCount","getChildElementHeight","lastShownItemIndex","nonPreviouslyMeasuredItemIndexes","previousFirstMeasuredItemIndex","previousLastMeasuredItemIndex","firstMeasuredItemIndexHasBeenUpdated","push","height","_measureItemHeight","previousHeight","count"],"mappings":"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","sourcesContent":["import log, { warn, isDebug, reportError } from './utility/debug'\r\n\r\nexport default class ItemHeights {\r\n\tconstructor(screen, getContainerElement, getItemHeight, setItemHeight) {\r\n\t\tthis.screen = screen\r\n\t\tthis.getContainerElement = getContainerElement\r\n\t\tthis._get = getItemHeight\r\n\t\tthis._set = setItemHeight\r\n\t\tthis.reset()\r\n\t}\r\n\r\n\treset() {\r\n\t\tthis.measuredItemsHeight = 0\r\n\t\t// \"First measured item index\" variable was introduced\r\n\t\t// because it's not always `0`: when `virtualScroller.setItems()`\r\n\t\t// is called, some items might get prepended, in which case\r\n\t\t// `this.lastMeasuredItemIndex` is updated. If there was no\r\n\t\t// `this.firstMeasuredItemIndex`, then the average item height\r\n\t\t// calculated in `.getAverage()` would be incorrect in the timeframe\r\n\t\t// between `.setItems()` is called and those changes have been rendered.\r\n\t\t// And in that timeframe, `.getAverage()` is used to calculate the \"layout\":\r\n\t\t// stuff like \"before/after items height\" and \"estimated items count on screen\".\r\n\t\tthis.firstMeasuredItemIndex = undefined\r\n\t\tthis.lastMeasuredItemIndex = undefined\r\n\t}\r\n\r\n\t/**\r\n\t * Is called after `.reset()`.\r\n\t * Initializes `this.measuredItemsHeight`, `this.firstMeasuredItemIndex`\r\n\t * and `this.lastMeasuredItemIndex` instance variables from `VirtualScroller` `state`.\r\n\t * These instance variables are used when calculating \"average\" item height:\r\n\t * the \"average\" item height is simply `this.measuredItemsHeight` divided by\r\n\t * `this.lastMeasuredItemIndex` minus `this.firstMeasuredItemIndex` plus 1.\r\n\t */\r\n\tinitialize(itemHeights) {\r\n\t\tlet i = 0\r\n\t\twhile (i < itemHeights.length) {\r\n\t\t\tif (itemHeights[i] === undefined) {\r\n\t\t\t\tif (this.firstMeasuredItemIndex !== undefined) {\r\n\t\t\t\t\tthis.lastMeasuredItemIndex = i - 1\r\n\t\t\t\t\tbreak\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tif (this.firstMeasuredItemIndex === undefined) {\r\n\t\t\t\t\tthis.firstMeasuredItemIndex = i\r\n\t\t\t\t}\r\n\t\t\t\tthis.measuredItemsHeight += itemHeights[i]\r\n\t\t\t}\r\n\t\t\ti++\r\n\t\t}\r\n\t}\r\n\r\n\t// Seems to be no longer used.\r\n\t// getItemHeight(i, firstShownItemIndex) {\r\n\t// \tif (this._get(i)) {\r\n\t// \t\treturn this._get(i)\r\n\t// \t}\r\n\t// \tconst itemHeight = this._measureItemHeight(i, firstShownItemIndex)\r\n\t// \tif (itemHeight) {\r\n\t// \t\tthis._set(i, itemHeight)\r\n\t// \t\treturn itemHeight\r\n\t// \t}\r\n\t// \treturn this.getAverage()\r\n\t// }\r\n\r\n\t_measureItemHeight(i, firstShownItemIndex) {\r\n\t\tconst container = this.getContainerElement()\r\n\t\tif (container) {\r\n\t\t\tconst elementIndex = i - firstShownItemIndex\r\n\t\t\tif (elementIndex >= 0 && elementIndex < this.screen.getChildElementsCount(container)) {\r\n\t\t\t\treturn this.screen.getChildElementHeight(container, elementIndex)\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Measures item heights:\r\n\t *\r\n\t * * For the items that haven't been previously measured,\r\n\t * measures them for the first time.\r\n\t *\r\n\t * * For the items that have been previoulsy measured,\r\n\t * validate that their previously measured height\r\n\t * is still equal to their current height.\r\n\t * The unequalness may not necessarily be caused by\r\n\t * incorrect use of `virtual-scroller`: there are\r\n\t * also some valid use cases when such unequalness\r\n\t * could happen (see the comments in the code).\r\n\t *\r\n\t * @param {number} firstShownItemIndex\r\n\t * @param {number} lastShownItemIndex\r\n\t * @return {number[]} The indexes of the items that have not previously been measured and have been measured now.\r\n\t */\r\n\tmeasureItemHeights(firstShownItemIndex, lastShownItemIndex) {\r\n\t\t// If no items are rendered, don't measure anything.\r\n\t\tif (firstShownItemIndex === undefined) {\r\n\t\t\treturn\r\n\t\t}\r\n\t\t// Reset `this.measuredItemsHeight` if it's not a \"continuous\" measured items list:\r\n\t\t// if a group of items has been measured previously, and now it has rendered a completely\r\n\t\t// different group of items, and there's a non-measured \"gap\" between those two groups,\r\n\t\t// then reset `this.measuredItemsHeight` and \"first measured\"/\"last measured\" item indexes.\r\n\t\t// For example, this could happen when `.setItems()` prepends a lot of new items.\r\n\t\tif (this.firstMeasuredItemIndex !== undefined) {\r\n\t\t\tif (firstShownItemIndex > this.lastMeasuredItemIndex + 1 ||\r\n\t\t\t\t\tlastShownItemIndex < this.firstMeasuredItemIndex - 1) {\r\n\t\t\t\t// Reset.\r\n\t\t\t\tlog('Non-measured items gap detected. Reset first and last measured item indexes.')\r\n\t\t\t\tthis.reset()\r\n\t\t\t}\r\n\t\t}\r\n\t\tconst nonPreviouslyMeasuredItemIndexes = []\r\n\t\tconst previousFirstMeasuredItemIndex = this.firstMeasuredItemIndex\r\n\t\tconst previousLastMeasuredItemIndex = this.lastMeasuredItemIndex\r\n\t\tlet firstMeasuredItemIndexHasBeenUpdated = false\r\n\t\tlet i = firstShownItemIndex\r\n\t\twhile (i <= lastShownItemIndex) {\r\n\t\t\t// Don't re-measure item heights that have been measured previously.\r\n\t\t\t// The rationale is that developers are supposed to manually call\r\n\t\t\t// `.onItemHeightChange()` every time an item's height changes.\r\n\t\t\t// If developers aren't neglecting that rule, item heights won't\r\n\t\t\t// change unexpectedly.\r\n\t\t\t// // Re-measure all shown items' heights, because an item's height\r\n\t\t\t// // might have changed since it has been measured initially.\r\n\t\t\t// // For example, if an item is a long comment with a \"Show more\" button,\r\n\t\t\t// // then the user might have clicked that \"Show more\" button.\r\n\t\t\tif (this._get(i) === undefined) {\r\n\t\t\t\tnonPreviouslyMeasuredItemIndexes.push(i)\r\n\t\t\t\tlog('Item', i, 'hasn\\'t been previously measured')\r\n\t\t\t\tconst height = this._measureItemHeight(i, firstShownItemIndex)\r\n\t\t\t\tlog('Height', height)\r\n\t\t\t\tthis._set(i, height)\r\n\t\t\t\t// Update average item height calculation variables\r\n\t\t\t\t// related to the previously measured items\r\n\t\t\t\t// that're above the items currently being shown.\r\n\t\t\t\t// It is known to be a \"continuous\" measured items list,\r\n\t\t\t\t// because the code at the start of this function checks that.\r\n\t\t\t\tif (previousFirstMeasuredItemIndex === undefined || i < previousFirstMeasuredItemIndex) {\r\n\t\t\t\t\tthis.measuredItemsHeight += height\r\n\t\t\t\t\t// Update first measured item index.\r\n\t\t\t\t\tif (!firstMeasuredItemIndexHasBeenUpdated) {\r\n\t\t\t\t\t\t// log('Set first measured item index', i)\r\n\t\t\t\t\t\tthis.firstMeasuredItemIndex = i\r\n\t\t\t\t\t\tfirstMeasuredItemIndexHasBeenUpdated = true\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t// Update average item height calculation variables\r\n\t\t\t\t// related to the previously measured items\r\n\t\t\t\t// that're below the items currently being shown.\r\n\t\t\t\t// It is known to be a \"continuous\" measured items list,\r\n\t\t\t\t// because the code at the start of this function checks that.\r\n\t\t\t\tif (previousLastMeasuredItemIndex === undefined || i > previousLastMeasuredItemIndex) {\r\n\t\t\t\t\t// If `previousLastMeasuredItemIndex` is `undefined`\r\n\t\t\t\t\t// then `previousFirstMeasuredItemIndex` is also `undefined`\r\n\t\t\t\t\t// which means that the item's `height` has already been added\r\n\t\t\t\t\t// to `this.measuredItemsHeight` in the code above,\r\n\t\t\t\t\t// so this condition guards against counting the item's `height`\r\n\t\t\t\t\t// twice in `this.measuredItemsHeight`.\r\n\t\t\t\t\tif (previousLastMeasuredItemIndex !== undefined) {\r\n\t\t\t\t\t\t// Add newly shown item height.\r\n\t\t\t\t\t\tthis.measuredItemsHeight += height\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// Update last measured item index.\r\n\t\t\t\t\tthis.lastMeasuredItemIndex = i\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t// Validate the item's height right after showing it after being hidden,\r\n\t\t\t\t// because, if the stored item's state isn't applied properly, the item's\r\n\t\t\t\t// height might be incorrect when it's rendered with that state not applied,\r\n\t\t\t\t// and so a developer could know that there's a bug in their code.\r\n\t\t\t\tconst previousHeight = this._get(i)\r\n\t\t\t\tconst height = this._measureItemHeight(i, firstShownItemIndex)\r\n\t\t\t\tif (previousHeight !== height) {\r\n\t\t\t\t\twarn('Item', i, 'height was', previousHeight, 'before it was hidden, but, after showing it again, its height is', height, '. Perhaps you forgot to persist the item\\'s state by calling `onItemStateChange(i, newState)` when it changed, and that state got lost when the item element was unmounted, which resulted in a different height when the item was shown again, but with the missing state.')\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ti++\r\n\t\t}\r\n\t\t// // Update average item height.\r\n\t\t// this.updateAverageItemHeight()\r\n\t\treturn nonPreviouslyMeasuredItemIndexes\r\n\t}\r\n\r\n\t/**\r\n\t * Re-measures item height.\r\n\t * @param {number} i — Item index.\r\n\t * @param {number} firstShownItemIndex\r\n\t */\r\n\tremeasureItemHeight(i, firstShownItemIndex) {\r\n\t\tconst previousHeight = this._get(i)\r\n\t\tconst height = this._measureItemHeight(i, firstShownItemIndex)\r\n\t\t// // Because this function is called from `.onItemHeightChange()`,\r\n\t\t// // there're no guarantees in which circumstances a developer calls it,\r\n\t\t// // and for which item indexes.\r\n\t\t// // Therefore, to guard against cases of incorrect usage,\r\n\t\t// // this function won't crash anything if the item isn't rendered\r\n\t\t// // or hasn't been previously rendered.\r\n\t\t// if (height !== undefined) {\r\n\t\t// \treportError(`\"onItemHeightChange()\" has been called for item ${i}, but that item isn't rendered.`)\r\n\t\t// \treturn\r\n\t\t// }\r\n\t\t// if (previousHeight === undefined) {\r\n\t\t// \treportError(`\"onItemHeightChange()\" has been called for item ${i}, but that item hasn't been rendered before.`)\r\n\t\t// \treturn\r\n\t\t// }\r\n\t\tthis._set(i, height)\r\n\t\tthis.measuredItemsHeight += height - previousHeight\r\n\t\treturn height\r\n\t}\r\n\r\n\t// /**\r\n\t// * \"Average\" item height is stored as an instance variable.\r\n\t// * For example, for caching, so that it isn't calculated every time it's requested.\r\n\t// * But that would be negligible performance gain, not really worth the extra code.\r\n\t// * Another thing it's stored for as an instance variable is\r\n\t// * keeping \"previous\" \"average\" item height, because it can be more precise\r\n\t// * than the newly calculated \"average\" item height, provided it had\r\n\t// * more \"samples\" (measured items). The newly calculated average item height\r\n\t// * could get less samples in a scenario when the scroll somehow jumps\r\n\t// * from one position to some other distant position: in that case previous\r\n\t// * \"total measured items height\" is discarded and the new one is initialized.\r\n\t// * Could such situation happen in real life? I guess, it's unlikely.\r\n\t// * So I'm commenting out this code, but still keeping it just in case.\r\n\t// */\r\n\t// updateAverageItemHeight() {\r\n\t// \tthis.averageItemHeightSamplesCount = this.lastMeasuredItemIndex - this.firstMeasuredItemIndex + 1\r\n\t// \tthis.averageItemHeight = this.measuredItemsHeight / this.averageItemHeightSamplesCount\r\n\t// }\r\n\t//\r\n\t// /**\r\n\t// * Public API: is called by `VirtualScroller`.\r\n\t// * @return {number}\r\n\t// */\r\n\t// getAverage() {\r\n\t// \t// Previously measured average item height might still be\r\n\t// \t// more precise if it contains more measured items (\"samples\").\r\n\t// \tif (this.previousAverageItemHeight) {\r\n\t// \t\tif (this.previousAverageItemHeightSamplesCount > this.averageItemHeightSamplesCount) {\r\n\t// \t\t\treturn this.previousAverageItemHeight\r\n\t// \t\t}\r\n\t// \t}\r\n\t// \treturn this.averageItemHeight || 0\r\n\t// }\r\n\r\n\t/**\r\n\t * Public API: is called by `VirtualScroller`.\r\n\t * @return {number}\r\n\t */\r\n\tgetAverage() {\r\n\t\tif (this.lastMeasuredItemIndex === undefined) {\r\n\t\t\treturn 0\r\n\t\t}\r\n\t\treturn this.measuredItemsHeight / (this.lastMeasuredItemIndex - this.firstMeasuredItemIndex + 1)\r\n\t}\r\n\r\n\tonPrepend(count) {\r\n\t\tif (this.firstMeasuredItemIndex !== undefined) {\r\n\t\t\tthis.firstMeasuredItemIndex += count\r\n\t\t\tthis.lastMeasuredItemIndex += count\r\n\t\t}\r\n\t}\r\n}"],"file":"ItemHeights.js"}
1
+ {"version":3,"file":"ItemHeights.js","names":["log","warn","isDebug","reportError","ItemHeights","container","itemHeights","getItemHeight","setItemHeight","_get","_set","reset","measuredItemsHeight","firstMeasuredItemIndex","undefined","lastMeasuredItemIndex","i","length","firstShownItemIndex","getNthRenderedItemHeight","lastShownItemIndex","nonPreviouslyMeasuredItemIndexes","previousFirstMeasuredItemIndex","previousLastMeasuredItemIndex","firstMeasuredItemIndexHasBeenUpdated","push","height","_measureItemHeight","previousHeight","count"],"sources":["../source/ItemHeights.js"],"sourcesContent":["import log, { warn, isDebug, reportError } from './utility/debug.js'\r\n\r\nexport default class ItemHeights {\r\n\tconstructor({\r\n\t\tcontainer,\r\n\t\titemHeights,\r\n\t\tgetItemHeight,\r\n\t\tsetItemHeight\r\n\t}) {\r\n\t\tthis.container = container\r\n\t\tthis._get = getItemHeight\r\n\t\tthis._set = setItemHeight\r\n\t\tthis.reset()\r\n\t}\r\n\r\n\treset() {\r\n\t\tthis.measuredItemsHeight = 0\r\n\t\t// \"First measured item index\" variable was introduced\r\n\t\t// because it's not always `0`: when `virtualScroller.setItems()`\r\n\t\t// is called, some items might get prepended, in which case\r\n\t\t// `this.lastMeasuredItemIndex` is updated. If there was no\r\n\t\t// `this.firstMeasuredItemIndex`, then the average item height\r\n\t\t// calculated in `.getAverage()` would be incorrect in the timeframe\r\n\t\t// between `.setItems()` is called and those changes have been rendered.\r\n\t\t// And in that timeframe, `.getAverage()` is used to calculate the \"layout\":\r\n\t\t// stuff like \"before/after items height\" and \"estimated items count on screen\".\r\n\t\tthis.firstMeasuredItemIndex = undefined\r\n\t\tthis.lastMeasuredItemIndex = undefined\r\n\t}\r\n\r\n\t/**\r\n\t * Can only be called after a `.reset()` (including new instance creation).\r\n\t * Initializes `this.measuredItemsHeight`, `this.firstMeasuredItemIndex`\r\n\t * and `this.lastMeasuredItemIndex` instance variables from `VirtualScroller` `state`.\r\n\t * These instance variables are used when calculating \"average\" item height:\r\n\t * the \"average\" item height is simply `this.measuredItemsHeight` divided by\r\n\t * `this.lastMeasuredItemIndex` minus `this.firstMeasuredItemIndex` plus 1.\r\n\t */\r\n\treadItemHeightsFromState({ itemHeights }) {\r\n\t\tlet i = 0\r\n\t\twhile (i < itemHeights.length) {\r\n\t\t\tif (itemHeights[i] === undefined) {\r\n\t\t\t\tif (this.firstMeasuredItemIndex !== undefined) {\r\n\t\t\t\t\tthis.lastMeasuredItemIndex = i - 1\r\n\t\t\t\t\tbreak\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tif (this.firstMeasuredItemIndex === undefined) {\r\n\t\t\t\t\tthis.firstMeasuredItemIndex = i\r\n\t\t\t\t}\r\n\t\t\t\tthis.measuredItemsHeight += itemHeights[i]\r\n\t\t\t}\r\n\t\t\ti++\r\n\t\t}\r\n\t}\r\n\r\n\t// Seems to be no longer used.\r\n\t// getItemHeight(i, firstShownItemIndex) {\r\n\t// \tif (this._get(i)) {\r\n\t// \t\treturn this._get(i)\r\n\t// \t}\r\n\t// \tconst itemHeight = this._measureItemHeight(i, firstShownItemIndex)\r\n\t// \tif (itemHeight) {\r\n\t// \t\tthis._set(i, itemHeight)\r\n\t// \t\treturn itemHeight\r\n\t// \t}\r\n\t// \treturn this.getAverage()\r\n\t// }\r\n\r\n\t_measureItemHeight(i, firstShownItemIndex) {\r\n\t\treturn this.container.getNthRenderedItemHeight(i - firstShownItemIndex)\r\n\t}\r\n\r\n\t/**\r\n\t * Measures item heights:\r\n\t *\r\n\t * * For the items that haven't been previously measured,\r\n\t * measures them for the first time.\r\n\t *\r\n\t * * For the items that have been previoulsy measured,\r\n\t * validate that their previously measured height\r\n\t * is still equal to their current height.\r\n\t * The unequalness may not necessarily be caused by\r\n\t * incorrect use of `virtual-scroller`: there are\r\n\t * also some valid use cases when such unequalness\r\n\t * could happen (see the comments in the code).\r\n\t *\r\n\t * @param {number} firstShownItemIndex\r\n\t * @param {number} lastShownItemIndex\r\n\t * @return {number[]} The indexes of the items that have not previously been measured and have been measured now.\r\n\t */\r\n\tmeasureItemHeights(firstShownItemIndex, lastShownItemIndex) {\r\n\t\tlog('~ Measure item heights ~')\r\n\t\t// If no items are rendered, don't measure anything.\r\n\t\tif (firstShownItemIndex === undefined) {\r\n\t\t\treturn\r\n\t\t}\r\n\t\t// Reset `this.measuredItemsHeight` if it's not a \"continuous\" measured items list:\r\n\t\t// if a group of items has been measured previously, and now it has rendered a completely\r\n\t\t// different group of items, and there's a non-measured \"gap\" between those two groups,\r\n\t\t// then reset `this.measuredItemsHeight` and \"first measured\"/\"last measured\" item indexes.\r\n\t\t// For example, this could happen when `.setItems()` prepends a lot of new items.\r\n\t\tif (this.firstMeasuredItemIndex !== undefined) {\r\n\t\t\tif (\r\n\t\t\t\tfirstShownItemIndex > this.lastMeasuredItemIndex + 1 ||\r\n\t\t\t\tlastShownItemIndex < this.firstMeasuredItemIndex - 1\r\n\t\t\t) {\r\n\t\t\t\t// Reset.\r\n\t\t\t\tlog('Non-measured items gap detected. Reset first and last measured item indexes.')\r\n\t\t\t\tthis.reset()\r\n\t\t\t}\r\n\t\t}\r\n\t\tconst nonPreviouslyMeasuredItemIndexes = []\r\n\t\tconst previousFirstMeasuredItemIndex = this.firstMeasuredItemIndex\r\n\t\tconst previousLastMeasuredItemIndex = this.lastMeasuredItemIndex\r\n\t\tlet firstMeasuredItemIndexHasBeenUpdated = false\r\n\t\tlet i = firstShownItemIndex\r\n\t\twhile (i <= lastShownItemIndex) {\r\n\t\t\t// Measure item heights that haven't been measured previously.\r\n\t\t\t// Don't re-measure item heights that have been measured previously.\r\n\t\t\t// The rationale is that developers are supposed to manually call\r\n\t\t\t// `.onItemHeightChange()` every time an item's height changes.\r\n\t\t\t// If developers don't neglect that rule, item heights won't\r\n\t\t\t// change unexpectedly.\r\n\t\t\tif (this._get(i) === undefined) {\r\n\t\t\t\tnonPreviouslyMeasuredItemIndexes.push(i)\r\n\t\t\t\tconst height = this._measureItemHeight(i, firstShownItemIndex)\r\n\t\t\t\tlog('Item index', i, 'height', height)\r\n\t\t\t\tthis._set(i, height)\r\n\t\t\t\t// Update average item height calculation variables\r\n\t\t\t\t// related to the previously measured items\r\n\t\t\t\t// that're above the items currently being shown.\r\n\t\t\t\t// It is known to be a \"continuous\" measured items list,\r\n\t\t\t\t// because the code at the start of this function checks that.\r\n\t\t\t\tif (previousFirstMeasuredItemIndex === undefined || i < previousFirstMeasuredItemIndex) {\r\n\t\t\t\t\tthis.measuredItemsHeight += height\r\n\t\t\t\t\t// Update first measured item index.\r\n\t\t\t\t\tif (!firstMeasuredItemIndexHasBeenUpdated) {\r\n\t\t\t\t\t\t// log('Set first measured item index', i)\r\n\t\t\t\t\t\tthis.firstMeasuredItemIndex = i\r\n\t\t\t\t\t\tfirstMeasuredItemIndexHasBeenUpdated = true\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t// Update average item height calculation variables\r\n\t\t\t\t// related to the previously measured items\r\n\t\t\t\t// that're below the items currently being shown.\r\n\t\t\t\t// It is known to be a \"continuous\" measured items list,\r\n\t\t\t\t// because the code at the start of this function checks that.\r\n\t\t\t\tif (previousLastMeasuredItemIndex === undefined || i > previousLastMeasuredItemIndex) {\r\n\t\t\t\t\t// If `previousLastMeasuredItemIndex` is `undefined`\r\n\t\t\t\t\t// then `previousFirstMeasuredItemIndex` is also `undefined`\r\n\t\t\t\t\t// which means that the item's `height` has already been added\r\n\t\t\t\t\t// to `this.measuredItemsHeight` in the code above,\r\n\t\t\t\t\t// so this condition guards against counting the item's `height`\r\n\t\t\t\t\t// twice in `this.measuredItemsHeight`.\r\n\t\t\t\t\tif (previousLastMeasuredItemIndex !== undefined) {\r\n\t\t\t\t\t\t// Add newly shown item height.\r\n\t\t\t\t\t\tthis.measuredItemsHeight += height\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// Update last measured item index.\r\n\t\t\t\t\tthis.lastMeasuredItemIndex = i\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t// Validate that the item's height didn't change since it was last measured.\r\n\t\t\t\t// If it did, then display a warning and update the item's height\r\n\t\t\t\t// as an attempt to fix things.\r\n\t\t\t\t// If an item's height changes unexpectedly then it means that there'll\r\n\t\t\t\t// likely be \"content jumping\".\r\n\t\t\t\tconst previousHeight = this._get(i)\r\n\t\t\t\tconst height = this._measureItemHeight(i, firstShownItemIndex)\r\n\t\t\t\tif (previousHeight !== height) {\r\n\t\t\t\t\twarn('Item index', i, 'height changed unexpectedly: it was', previousHeight, 'before, but now it is', height, '. An item\\'s height is allowed to change only in two cases: when the item\\'s \"state\" changes and the developer calls `onItemStateChange(i, newState)`, or when the item\\'s height changes for some other reason and the developer calls `onItemHeightChange(i)`. Perhaps you forgot to persist the item\\'s \"state\" by calling `onItemStateChange(i, newState)` when it changed, and that \"state\" got lost when the item element was unmounted, which resulted in a different height when the item was shown again having its \"state\" reset.')\r\n\t\t\t\t\t// Update the item's height as an attempt to fix things.\r\n\t\t\t\t\tthis._set(i, height)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ti++\r\n\t\t}\r\n\t\t// // Update average item height.\r\n\t\t// this.updateAverageItemHeight()\r\n\t\treturn nonPreviouslyMeasuredItemIndexes\r\n\t}\r\n\r\n\t/**\r\n\t * Re-measures item height.\r\n\t * @param {number} i — Item index.\r\n\t * @param {number} firstShownItemIndex\r\n\t */\r\n\tremeasureItemHeight(i, firstShownItemIndex) {\r\n\t\tconst previousHeight = this._get(i)\r\n\t\tconst height = this._measureItemHeight(i, firstShownItemIndex)\r\n\t\t// // Because this function is called from `.onItemHeightChange()`,\r\n\t\t// // there're no guarantees in which circumstances a developer calls it,\r\n\t\t// // and for which item indexes.\r\n\t\t// // Therefore, to guard against cases of incorrect usage,\r\n\t\t// // this function won't crash anything if the item isn't rendered\r\n\t\t// // or hasn't been previously rendered.\r\n\t\t// if (height !== undefined) {\r\n\t\t// \treportError(`\"onItemHeightChange()\" has been called for item ${i}, but that item isn't rendered.`)\r\n\t\t// \treturn\r\n\t\t// }\r\n\t\t// if (previousHeight === undefined) {\r\n\t\t// \treportError(`\"onItemHeightChange()\" has been called for item ${i}, but that item hasn't been rendered before.`)\r\n\t\t// \treturn\r\n\t\t// }\r\n\t\tthis._set(i, height)\r\n\t\tthis.measuredItemsHeight += height - previousHeight\r\n\t\treturn height\r\n\t}\r\n\r\n\t// /**\r\n\t// * \"Average\" item height is stored as an instance variable.\r\n\t// * For example, for caching, so that it isn't calculated every time it's requested.\r\n\t// * But that would be negligible performance gain, not really worth the extra code.\r\n\t// * Another thing it's stored for as an instance variable is\r\n\t// * keeping \"previous\" \"average\" item height, because it can be more precise\r\n\t// * than the newly calculated \"average\" item height, provided it had\r\n\t// * more \"samples\" (measured items). The newly calculated average item height\r\n\t// * could get less samples in a scenario when the scroll somehow jumps\r\n\t// * from one position to some other distant position: in that case previous\r\n\t// * \"total measured items height\" is discarded and the new one is initialized.\r\n\t// * Could such situation happen in real life? I guess, it's unlikely.\r\n\t// * So I'm commenting out this code, but still keeping it just in case.\r\n\t// */\r\n\t// updateAverageItemHeight() {\r\n\t// \tthis.averageItemHeightSamplesCount = this.lastMeasuredItemIndex - this.firstMeasuredItemIndex + 1\r\n\t// \tthis.averageItemHeight = this.measuredItemsHeight / this.averageItemHeightSamplesCount\r\n\t// }\r\n\t//\r\n\t// /**\r\n\t// * Public API: is called by `VirtualScroller`.\r\n\t// * @return {number}\r\n\t// */\r\n\t// getAverage() {\r\n\t// \t// Previously measured average item height might still be\r\n\t// \t// more precise if it contains more measured items (\"samples\").\r\n\t// \tif (this.previousAverageItemHeight) {\r\n\t// \t\tif (this.previousAverageItemHeightSamplesCount > this.averageItemHeightSamplesCount) {\r\n\t// \t\t\treturn this.previousAverageItemHeight\r\n\t// \t\t}\r\n\t// \t}\r\n\t// \treturn this.averageItemHeight || 0\r\n\t// }\r\n\r\n\t/**\r\n\t * Public API: is called by `VirtualScroller`.\r\n\t * @return {number}\r\n\t */\r\n\tgetAverage() {\r\n\t\tif (this.lastMeasuredItemIndex === undefined) {\r\n\t\t\treturn 0\r\n\t\t}\r\n\t\treturn this.measuredItemsHeight / (this.lastMeasuredItemIndex - this.firstMeasuredItemIndex + 1)\r\n\t}\r\n\r\n\tonPrepend(count) {\r\n\t\tif (this.firstMeasuredItemIndex !== undefined) {\r\n\t\t\tthis.firstMeasuredItemIndex += count\r\n\t\t\tthis.lastMeasuredItemIndex += count\r\n\t\t}\r\n\t}\r\n}"],"mappings":"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"}