virtual-scroller 1.11.2 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +13 -11
  3. package/bundle/virtual-scroller-dom.js +1 -1
  4. package/bundle/virtual-scroller-dom.js.map +1 -1
  5. package/bundle/virtual-scroller-react.js +1 -1
  6. package/bundle/virtual-scroller-react.js.map +1 -1
  7. package/bundle/virtual-scroller.js +1 -1
  8. package/bundle/virtual-scroller.js.map +1 -1
  9. package/commonjs/DOM/ItemsContainer.js +10 -3
  10. package/commonjs/DOM/ItemsContainer.js.map +1 -1
  11. package/commonjs/DOM/VirtualScroller.js +13 -1
  12. package/commonjs/DOM/VirtualScroller.js.map +1 -1
  13. package/commonjs/ItemHeights.js +5 -5
  14. package/commonjs/ItemHeights.js.map +1 -1
  15. package/commonjs/ItemNotRenderedError.js +64 -0
  16. package/commonjs/ItemNotRenderedError.js.map +1 -0
  17. package/commonjs/Layout.test.js +10 -0
  18. package/commonjs/Layout.test.js.map +1 -1
  19. package/commonjs/VirtualScroller.js +23 -5
  20. package/commonjs/VirtualScroller.js.map +1 -1
  21. package/commonjs/VirtualScroller.layout.js +81 -39
  22. package/commonjs/VirtualScroller.layout.js.map +1 -1
  23. package/commonjs/VirtualScroller.onRender.js +97 -45
  24. package/commonjs/VirtualScroller.onRender.js.map +1 -1
  25. package/commonjs/VirtualScroller.state.js +50 -18
  26. package/commonjs/VirtualScroller.state.js.map +1 -1
  27. package/commonjs/react/VirtualScroller.js +31 -46
  28. package/commonjs/react/VirtualScroller.js.map +1 -1
  29. package/commonjs/react/useItemKeys.js +11 -3
  30. package/commonjs/react/useItemKeys.js.map +1 -1
  31. package/commonjs/react/useOnChange.js +19 -0
  32. package/commonjs/react/useOnChange.js.map +1 -0
  33. package/commonjs/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +7 -7
  34. package/commonjs/react/useOnItemHeightDidChange.js.map +1 -0
  35. package/commonjs/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +15 -14
  36. package/commonjs/react/useSetNewItemsOnItemsPropertyChange.js.map +1 -0
  37. package/commonjs/react/useState.js +162 -69
  38. package/commonjs/react/useState.js.map +1 -1
  39. package/commonjs/react/useStyle.js +3 -5
  40. package/commonjs/react/useStyle.js.map +1 -1
  41. package/commonjs/react/useUpdateItemKeysOnItemsChange.js +61 -0
  42. package/commonjs/react/useUpdateItemKeysOnItemsChange.js.map +1 -0
  43. package/commonjs/test/ItemsContainer.js +22 -1
  44. package/commonjs/test/ItemsContainer.js.map +1 -1
  45. package/commonjs/utility/debug.js +30 -6
  46. package/commonjs/utility/debug.js.map +1 -1
  47. package/dom/index.d.ts +1 -1
  48. package/index.cjs +2 -0
  49. package/index.d.ts +7 -1
  50. package/index.js +1 -0
  51. package/modules/DOM/ItemsContainer.js +8 -3
  52. package/modules/DOM/ItemsContainer.js.map +1 -1
  53. package/modules/DOM/VirtualScroller.js +13 -1
  54. package/modules/DOM/VirtualScroller.js.map +1 -1
  55. package/modules/ItemHeights.js +5 -5
  56. package/modules/ItemHeights.js.map +1 -1
  57. package/modules/ItemNotRenderedError.js +57 -0
  58. package/modules/ItemNotRenderedError.js.map +1 -0
  59. package/modules/Layout.test.js +10 -0
  60. package/modules/Layout.test.js.map +1 -1
  61. package/modules/VirtualScroller.js +17 -5
  62. package/modules/VirtualScroller.js.map +1 -1
  63. package/modules/VirtualScroller.layout.js +78 -39
  64. package/modules/VirtualScroller.layout.js.map +1 -1
  65. package/modules/VirtualScroller.onRender.js +98 -46
  66. package/modules/VirtualScroller.onRender.js.map +1 -1
  67. package/modules/VirtualScroller.state.js +50 -18
  68. package/modules/VirtualScroller.state.js.map +1 -1
  69. package/modules/react/VirtualScroller.js +31 -46
  70. package/modules/react/VirtualScroller.js.map +1 -1
  71. package/modules/react/useItemKeys.js +8 -3
  72. package/modules/react/useItemKeys.js.map +1 -1
  73. package/modules/react/useOnChange.js +11 -0
  74. package/modules/react/useOnChange.js.map +1 -0
  75. package/modules/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +6 -6
  76. package/modules/react/useOnItemHeightDidChange.js.map +1 -0
  77. package/modules/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +11 -13
  78. package/modules/react/useSetNewItemsOnItemsPropertyChange.js.map +1 -0
  79. package/modules/react/useState.js +156 -73
  80. package/modules/react/useState.js.map +1 -1
  81. package/modules/react/useStyle.js +3 -5
  82. package/modules/react/useStyle.js.map +1 -1
  83. package/{commonjs/react/useHandleItemIndexesChange.js → modules/react/useUpdateItemKeysOnItemsChange.js} +18 -21
  84. package/modules/react/useUpdateItemKeysOnItemsChange.js.map +1 -0
  85. package/modules/test/ItemsContainer.js +20 -1
  86. package/modules/test/ItemsContainer.js.map +1 -1
  87. package/modules/utility/debug.js +31 -6
  88. package/modules/utility/debug.js.map +1 -1
  89. package/package.json +1 -1
  90. package/source/DOM/ItemsContainer.js +8 -3
  91. package/source/DOM/VirtualScroller.js +11 -1
  92. package/source/ItemHeights.js +5 -5
  93. package/source/ItemNotRenderedError.js +16 -0
  94. package/source/Layout.test.js +9 -0
  95. package/source/VirtualScroller.js +14 -3
  96. package/source/VirtualScroller.layout.js +77 -38
  97. package/source/VirtualScroller.onRender.js +95 -42
  98. package/source/VirtualScroller.state.js +57 -20
  99. package/source/react/VirtualScroller.js +28 -39
  100. package/source/react/useItemKeys.js +9 -2
  101. package/source/react/useOnChange.js +11 -0
  102. package/source/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +5 -5
  103. package/source/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +11 -11
  104. package/source/react/useState.js +159 -71
  105. package/source/react/useStyle.js +2 -2
  106. package/source/react/{useHandleItemIndexesChange.js → useUpdateItemKeysOnItemsChange.js} +17 -9
  107. package/source/test/ItemsContainer.js +22 -1
  108. package/source/utility/debug.js +18 -4
  109. package/commonjs/react/useHandleItemIndexesChange.js.map +0 -1
  110. package/commonjs/react/useHandleItemsPropertyChange.js.map +0 -1
  111. package/commonjs/react/useOnItemHeightChange.js.map +0 -1
  112. package/modules/react/useHandleItemIndexesChange.js +0 -45
  113. package/modules/react/useHandleItemIndexesChange.js.map +0 -1
  114. package/modules/react/useHandleItemsPropertyChange.js.map +0 -1
  115. package/modules/react/useOnItemHeightChange.js.map +0 -1
@@ -5,6 +5,10 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports["default"] = void 0;
7
7
 
8
+ var _ItemNotRenderedError = _interopRequireDefault(require("../ItemNotRenderedError.js"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
11
+
8
12
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
9
13
 
10
14
  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); } }
@@ -28,9 +32,12 @@ var ItemsContainer = /*#__PURE__*/function () {
28
32
  var childNodes = this.getElement().childNodes;
29
33
 
30
34
  if (renderedElementIndex > childNodes.length - 1) {
31
- console.log('~ Items Container Contents ~');
32
- console.log(this.getElement().innerHTML);
33
- throw new Error("Element with index ".concat(renderedElementIndex, " was not found in the list of Rendered Item Elements in the Items Container of Virtual Scroller. There're only ").concat(childNodes.length, " Elements there."));
35
+ // console.log('~ Items Container Contents ~')
36
+ // console.log(this.getElement().innerHTML)
37
+ throw new _ItemNotRenderedError["default"]({
38
+ renderedElementIndex: renderedElementIndex,
39
+ renderedElementsCount: childNodes.length
40
+ });
34
41
  }
35
42
 
36
43
  return childNodes[renderedElementIndex];
@@ -1 +1 @@
1
- {"version":3,"file":"ItemsContainer.js","names":["ItemsContainer","getElement","renderedElementIndex","childNodes","length","console","log","innerHTML","Error","_getNthRenderedItemElement","getBoundingClientRect","top","height","firstChild","removeChild"],"sources":["../../source/DOM/ItemsContainer.js"],"sourcesContent":["export default class ItemsContainer {\r\n\t/**\r\n\t * Constructs a new \"container\" from an element.\r\n\t * @param {function} getElement\r\n\t */\r\n\tconstructor(getElement) {\r\n\t\tthis.getElement = getElement\r\n\t}\r\n\r\n\t_getNthRenderedItemElement(renderedElementIndex) {\r\n\t\tconst childNodes = this.getElement().childNodes\r\n\t\tif (renderedElementIndex > childNodes.length - 1) {\r\n\t\t\tconsole.log('~ Items Container Contents ~')\r\n\t\t\tconsole.log(this.getElement().innerHTML)\r\n\t\t\tthrow new Error(`Element with index ${renderedElementIndex} was not found in the list of Rendered Item Elements in the Items Container of Virtual Scroller. There're only ${childNodes.length} Elements there.`)\r\n\t\t}\r\n\t\treturn childNodes[renderedElementIndex]\r\n\t}\r\n\r\n\t/**\r\n\t * Returns an item element's \"top offset\", relative to the items `container`'s top edge.\r\n\t * @param {number} renderedElementIndex — An index of an item relative to the \"first shown item index\". For example, if the list is showing items from index 8 to index 12 then `renderedElementIndex = 0` would mean the item at index `8`.\r\n\t * @return {number}\r\n\t */\r\n\tgetNthRenderedItemTopOffset(renderedElementIndex) {\r\n\t\treturn this._getNthRenderedItemElement(renderedElementIndex).getBoundingClientRect().top - this.getElement().getBoundingClientRect().top\r\n\t}\r\n\r\n\t/**\r\n\t * Returns an item element's height.\r\n\t * @param {number} renderedElementIndex — An index of an item relative to the \"first shown item index\". For example, if the list is showing items from index 8 to index 12 then `renderedElementIndex = 0` would mean the item at index `8`.\r\n\t * @return {number}\r\n\t */\r\n\tgetNthRenderedItemHeight(renderedElementIndex) {\r\n\t\t// `offsetHeight` is not precise enough (doesn't return fractional pixels).\r\n\t\t// return this._getNthRenderedItemElement(renderedElementIndex).offsetHeight\r\n\t\treturn this._getNthRenderedItemElement(renderedElementIndex).getBoundingClientRect().height\r\n\t}\r\n\r\n\t/**\r\n\t * Returns items container height.\r\n\t * @return {number}\r\n\t */\r\n\tgetHeight() {\r\n\t\t// `offsetHeight` is not precise enough (doesn't return fractional pixels).\r\n\t\t// return this.getElement().offsetHeight\r\n\t\treturn this.getElement().getBoundingClientRect().height\r\n\t}\r\n\r\n\t/**\r\n\t * Removes all item elements of an items container.\r\n\t */\r\n\tclear() {\r\n\t\twhile (this.getElement().firstChild) {\r\n\t\t\tthis.getElement().removeChild(this.getElement().firstChild)\r\n\t\t}\r\n\t}\r\n}"],"mappings":";;;;;;;;;;;;;IAAqBA,c;EACpB;AACD;AACA;AACA;EACC,wBAAYC,UAAZ,EAAwB;IAAA;;IACvB,KAAKA,UAAL,GAAkBA,UAAlB;EACA;;;;WAED,oCAA2BC,oBAA3B,EAAiD;MAChD,IAAMC,UAAU,GAAG,KAAKF,UAAL,GAAkBE,UAArC;;MACA,IAAID,oBAAoB,GAAGC,UAAU,CAACC,MAAX,GAAoB,CAA/C,EAAkD;QACjDC,OAAO,CAACC,GAAR,CAAY,8BAAZ;QACAD,OAAO,CAACC,GAAR,CAAY,KAAKL,UAAL,GAAkBM,SAA9B;QACA,MAAM,IAAIC,KAAJ,8BAAgCN,oBAAhC,4HAAsKC,UAAU,CAACC,MAAjL,sBAAN;MACA;;MACD,OAAOD,UAAU,CAACD,oBAAD,CAAjB;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,qCAA4BA,oBAA5B,EAAkD;MACjD,OAAO,KAAKO,0BAAL,CAAgCP,oBAAhC,EAAsDQ,qBAAtD,GAA8EC,GAA9E,GAAoF,KAAKV,UAAL,GAAkBS,qBAAlB,GAA0CC,GAArI;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,kCAAyBT,oBAAzB,EAA+C;MAC9C;MACA;MACA,OAAO,KAAKO,0BAAL,CAAgCP,oBAAhC,EAAsDQ,qBAAtD,GAA8EE,MAArF;IACA;IAED;AACD;AACA;AACA;;;;WACC,qBAAY;MACX;MACA;MACA,OAAO,KAAKX,UAAL,GAAkBS,qBAAlB,GAA0CE,MAAjD;IACA;IAED;AACD;AACA;;;;WACC,iBAAQ;MACP,OAAO,KAAKX,UAAL,GAAkBY,UAAzB,EAAqC;QACpC,KAAKZ,UAAL,GAAkBa,WAAlB,CAA8B,KAAKb,UAAL,GAAkBY,UAAhD;MACA;IACD"}
1
+ {"version":3,"file":"ItemsContainer.js","names":["ItemsContainer","getElement","renderedElementIndex","childNodes","length","ItemNotRenderedError","renderedElementsCount","_getNthRenderedItemElement","getBoundingClientRect","top","height","firstChild","removeChild"],"sources":["../../source/DOM/ItemsContainer.js"],"sourcesContent":["import ItemNotRenderedError from '../ItemNotRenderedError.js'\r\n\r\nexport default class ItemsContainer {\r\n\t/**\r\n\t * Constructs a new \"container\" from an element.\r\n\t * @param {function} getElement\r\n\t */\r\n\tconstructor(getElement) {\r\n\t\tthis.getElement = getElement\r\n\t}\r\n\r\n\t_getNthRenderedItemElement(renderedElementIndex) {\r\n\t\tconst childNodes = this.getElement().childNodes\r\n\t\tif (renderedElementIndex > childNodes.length - 1) {\r\n\t\t\t// console.log('~ Items Container Contents ~')\r\n\t\t\t// console.log(this.getElement().innerHTML)\r\n\t\t\tthrow new ItemNotRenderedError({\r\n\t\t\t\trenderedElementIndex,\r\n\t\t\t\trenderedElementsCount: childNodes.length\r\n\t\t\t})\r\n\t\t}\r\n\t\treturn childNodes[renderedElementIndex]\r\n\t}\r\n\r\n\t/**\r\n\t * Returns an item element's \"top offset\", relative to the items `container`'s top edge.\r\n\t * @param {number} renderedElementIndex — An index of an item relative to the \"first shown item index\". For example, if the list is showing items from index 8 to index 12 then `renderedElementIndex = 0` would mean the item at index `8`.\r\n\t * @return {number}\r\n\t */\r\n\tgetNthRenderedItemTopOffset(renderedElementIndex) {\r\n\t\treturn this._getNthRenderedItemElement(renderedElementIndex).getBoundingClientRect().top - this.getElement().getBoundingClientRect().top\r\n\t}\r\n\r\n\t/**\r\n\t * Returns an item element's height.\r\n\t * @param {number} renderedElementIndex — An index of an item relative to the \"first shown item index\". For example, if the list is showing items from index 8 to index 12 then `renderedElementIndex = 0` would mean the item at index `8`.\r\n\t * @return {number}\r\n\t */\r\n\tgetNthRenderedItemHeight(renderedElementIndex) {\r\n\t\t// `offsetHeight` is not precise enough (doesn't return fractional pixels).\r\n\t\t// return this._getNthRenderedItemElement(renderedElementIndex).offsetHeight\r\n\t\treturn this._getNthRenderedItemElement(renderedElementIndex).getBoundingClientRect().height\r\n\t}\r\n\r\n\t/**\r\n\t * Returns items container height.\r\n\t * @return {number}\r\n\t */\r\n\tgetHeight() {\r\n\t\t// `offsetHeight` is not precise enough (doesn't return fractional pixels).\r\n\t\t// return this.getElement().offsetHeight\r\n\t\treturn this.getElement().getBoundingClientRect().height\r\n\t}\r\n\r\n\t/**\r\n\t * Removes all item elements of an items container.\r\n\t */\r\n\tclear() {\r\n\t\twhile (this.getElement().firstChild) {\r\n\t\t\tthis.getElement().removeChild(this.getElement().firstChild)\r\n\t\t}\r\n\t}\r\n}"],"mappings":";;;;;;;AAAA;;;;;;;;;;IAEqBA,c;EACpB;AACD;AACA;AACA;EACC,wBAAYC,UAAZ,EAAwB;IAAA;;IACvB,KAAKA,UAAL,GAAkBA,UAAlB;EACA;;;;WAED,oCAA2BC,oBAA3B,EAAiD;MAChD,IAAMC,UAAU,GAAG,KAAKF,UAAL,GAAkBE,UAArC;;MACA,IAAID,oBAAoB,GAAGC,UAAU,CAACC,MAAX,GAAoB,CAA/C,EAAkD;QACjD;QACA;QACA,MAAM,IAAIC,gCAAJ,CAAyB;UAC9BH,oBAAoB,EAApBA,oBAD8B;UAE9BI,qBAAqB,EAAEH,UAAU,CAACC;QAFJ,CAAzB,CAAN;MAIA;;MACD,OAAOD,UAAU,CAACD,oBAAD,CAAjB;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,qCAA4BA,oBAA5B,EAAkD;MACjD,OAAO,KAAKK,0BAAL,CAAgCL,oBAAhC,EAAsDM,qBAAtD,GAA8EC,GAA9E,GAAoF,KAAKR,UAAL,GAAkBO,qBAAlB,GAA0CC,GAArI;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,kCAAyBP,oBAAzB,EAA+C;MAC9C;MACA;MACA,OAAO,KAAKK,0BAAL,CAAgCL,oBAAhC,EAAsDM,qBAAtD,GAA8EE,MAArF;IACA;IAED;AACD;AACA;AACA;;;;WACC,qBAAY;MACX;MACA;MACA,OAAO,KAAKT,UAAL,GAAkBO,qBAAlB,GAA0CE,MAAjD;IACA;IAED;AACD;AACA;;;;WACC,iBAAQ;MACP,OAAO,KAAKT,UAAL,GAAkBU,UAAzB,EAAqC;QACpC,KAAKV,UAAL,GAAkBW,WAAlB,CAA8B,KAAKX,UAAL,GAAkBU,UAAhD;MACA;IACD"}
@@ -172,10 +172,21 @@ var VirtualScroller = /*#__PURE__*/function () {
172
172
  this.onItemUnmount(itemElement);
173
173
  }
174
174
  }
175
+ /**
176
+ * @deprecated
177
+ * `.onItemHeightChange()` has been renamed to `.onItemHeightDidChange()`.
178
+ */
179
+
175
180
  }, {
176
181
  key: "onItemHeightChange",
177
182
  value: function onItemHeightChange(i) {
178
- this.virtualScroller.onItemHeightChange(i);
183
+ (0, _debug.warn)('`.onItemHeightChange(i)` method was renamed to `.onItemHeightDidChange(i)`');
184
+ this.onItemHeightDidChange(i);
185
+ }
186
+ }, {
187
+ key: "onItemHeightDidChange",
188
+ value: function onItemHeightDidChange(i) {
189
+ this.virtualScroller.onItemHeightDidChange(i);
179
190
  }
180
191
  }, {
181
192
  key: "setItemState",
@@ -190,6 +201,7 @@ var VirtualScroller = /*#__PURE__*/function () {
190
201
  }, {
191
202
  key: "updateItems",
192
203
  value: function updateItems(newItems, options) {
204
+ (0, _debug.warn)('`.updateItems()` method was renamed to `.setItems(i)`');
193
205
  this.setItems(newItems, options);
194
206
  }
195
207
  }, {
@@ -1 +1 @@
1
- {"version":3,"file":"VirtualScroller.js","names":["VirtualScroller","itemsContainerElement","items","renderItem","options","state","prevState","firstShownItemIndex","lastShownItemIndex","beforeItemsHeight","afterItemsHeight","tbody","container","style","paddingTop","px","paddingBottom","diffRender","length","i","log","unmountItem","childNodes","firstChild","shouldPrependItems","prependBeforeItemElement","item","insertBefore","appendChild","warn","stop","virtualScroller","start","onMount","onItemUnmount","restOptions","tagName","VirtualScrollerCore","render","itemElement","removeChild","onItemHeightChange","newState","setItemState","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 setItemState(i, newState) {\r\n this.virtualScroller.setItemState(i, newState)\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
+ {"version":3,"file":"VirtualScroller.js","names":["VirtualScroller","itemsContainerElement","items","renderItem","options","state","prevState","firstShownItemIndex","lastShownItemIndex","beforeItemsHeight","afterItemsHeight","tbody","container","style","paddingTop","px","paddingBottom","diffRender","length","i","log","unmountItem","childNodes","firstChild","shouldPrependItems","prependBeforeItemElement","item","insertBefore","appendChild","warn","stop","virtualScroller","start","onMount","onItemUnmount","restOptions","tagName","VirtualScrollerCore","render","itemElement","removeChild","onItemHeightDidChange","newState","setItemState","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 /**\r\n * @deprecated\r\n * `.onItemHeightChange()` has been renamed to `.onItemHeightDidChange()`.\r\n */\r\n onItemHeightChange(i) {\r\n warn('`.onItemHeightChange(i)` method was renamed to `.onItemHeightDidChange(i)`')\r\n this.onItemHeightDidChange(i)\r\n }\r\n\r\n onItemHeightDidChange(i) {\r\n this.virtualScroller.onItemHeightDidChange(i)\r\n }\r\n\r\n setItemState(i, newState) {\r\n this.virtualScroller.setItemState(i, newState)\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 warn('`.updateItems()` method was renamed to `.setItems(i)`')\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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"}
@@ -150,7 +150,7 @@ var ItemHeights = /*#__PURE__*/function () {
150
150
  // Measure item heights that haven't been measured previously.
151
151
  // Don't re-measure item heights that have been measured previously.
152
152
  // The rationale is that developers are supposed to manually call
153
- // `.onItemHeightChange()` every time an item's height changes.
153
+ // `.onItemHeightDidChange()` immediately every time an item's height has changed.
154
154
  // If developers don't neglect that rule, item heights won't
155
155
  // change unexpectedly.
156
156
  if (this._get(i) === undefined) {
@@ -208,7 +208,7 @@ var ItemHeights = /*#__PURE__*/function () {
208
208
  var _height = this._measureItemHeight(i, firstShownItemIndex);
209
209
 
210
210
  if (previousHeight !== _height) {
211
- (0, _debug.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 `setItemState(i, newState)`, or when the item\'s height changes for any reason and the developer calls `onItemHeightChange(i)`. Perhaps you forgot to persist the item\'s "state" by calling `setItemState(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.
211
+ (0, _debug.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 `setItemState(i, newState)`, or when the item\'s height changes for any reason and the developer calls `onItemHeightDidChange(i)` right after that happens. Perhaps you forgot to persist the item\'s "state" by calling `setItemState(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.
212
212
 
213
213
  this._set(i, _height);
214
214
  }
@@ -232,18 +232,18 @@ var ItemHeights = /*#__PURE__*/function () {
232
232
  value: function remeasureItemHeight(i, firstShownItemIndex) {
233
233
  var previousHeight = this._get(i);
234
234
 
235
- var height = this._measureItemHeight(i, firstShownItemIndex); // // Because this function is called from `.onItemHeightChange()`,
235
+ var height = this._measureItemHeight(i, firstShownItemIndex); // // Because this function is called from `.onItemHeightDidChange()`,
236
236
  // // there're no guarantees in which circumstances a developer calls it,
237
237
  // // and for which item indexes.
238
238
  // // Therefore, to guard against cases of incorrect usage,
239
239
  // // this function won't crash anything if the item isn't rendered
240
240
  // // or hasn't been previously rendered.
241
241
  // if (height !== undefined) {
242
- // reportError(`"onItemHeightChange()" has been called for item ${i}, but that item isn't rendered.`)
242
+ // reportError(`"onItemHeightDidChange()" has been called for item ${i}, but that item isn't currently rendered.`)
243
243
  // return
244
244
  // }
245
245
  // if (previousHeight === undefined) {
246
- // reportError(`"onItemHeightChange()" has been called for item ${i}, but that item hasn't been rendered before.`)
246
+ // reportError(`"onItemHeightDidChange()" has been called for item ${i}, but that item hasn't been rendered before.`)
247
247
  // return
248
248
  // }
249
249
 
@@ -1 +1 @@
1
- {"version":3,"file":"ItemHeights.js","names":["ItemHeights","container","itemHeights","getItemHeight","setItemHeight","_get","_set","reset","measuredItemsHeight","firstMeasuredItemIndex","undefined","lastMeasuredItemIndex","i","length","firstShownItemIndex","getNthRenderedItemHeight","lastShownItemIndex","log","nonPreviouslyMeasuredItemIndexes","previousFirstMeasuredItemIndex","previousLastMeasuredItemIndex","firstMeasuredItemIndexHasBeenUpdated","push","height","_measureItemHeight","previousHeight","warn","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 `setItemState(i, newState)`, or when the item\\'s height changes for any reason and the developer calls `onItemHeightChange(i)`. Perhaps you forgot to persist the item\\'s \"state\" by calling `setItemState(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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"}
1
+ {"version":3,"file":"ItemHeights.js","names":["ItemHeights","container","itemHeights","getItemHeight","setItemHeight","_get","_set","reset","measuredItemsHeight","firstMeasuredItemIndex","undefined","lastMeasuredItemIndex","i","length","firstShownItemIndex","getNthRenderedItemHeight","lastShownItemIndex","log","nonPreviouslyMeasuredItemIndexes","previousFirstMeasuredItemIndex","previousLastMeasuredItemIndex","firstMeasuredItemIndexHasBeenUpdated","push","height","_measureItemHeight","previousHeight","warn","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// `.onItemHeightDidChange()` immediately every time an item's height has changed.\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 `setItemState(i, newState)`, or when the item\\'s height changes for any reason and the developer calls `onItemHeightDidChange(i)` right after that happens. Perhaps you forgot to persist the item\\'s \"state\" by calling `setItemState(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 `.onItemHeightDidChange()`,\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(`\"onItemHeightDidChange()\" has been called for item ${i}, but that item isn't currently rendered.`)\r\n\t\t// \treturn\r\n\t\t// }\r\n\t\t// if (previousHeight === undefined) {\r\n\t\t// \treportError(`\"onItemHeightDidChange()\" 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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"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports["default"] = void 0;
9
+
10
+ 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); } }
11
+
12
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
13
+
14
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
15
+
16
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
17
+
18
+ function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
19
+
20
+ function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
21
+
22
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
23
+
24
+ function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }
25
+
26
+ function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
27
+
28
+ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
29
+
30
+ function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }
31
+
32
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
33
+
34
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
35
+
36
+ var ItemNotRenderedError = /*#__PURE__*/function (_Error) {
37
+ _inherits(ItemNotRenderedError, _Error);
38
+
39
+ var _super = _createSuper(ItemNotRenderedError);
40
+
41
+ function ItemNotRenderedError(_ref) {
42
+ var renderedElementIndex = _ref.renderedElementIndex,
43
+ renderedElementsCount = _ref.renderedElementsCount,
44
+ message = _ref.message;
45
+
46
+ _classCallCheck(this, ItemNotRenderedError);
47
+
48
+ return _super.call(this, message || getDefaultMessage({
49
+ renderedElementIndex: renderedElementIndex,
50
+ renderedElementsCount: renderedElementsCount
51
+ }));
52
+ }
53
+
54
+ return _createClass(ItemNotRenderedError);
55
+ }( /*#__PURE__*/_wrapNativeSuper(Error));
56
+
57
+ exports["default"] = ItemNotRenderedError;
58
+
59
+ function getDefaultMessage(_ref2) {
60
+ var renderedElementIndex = _ref2.renderedElementIndex,
61
+ renderedElementsCount = _ref2.renderedElementsCount;
62
+ return "Element with index ".concat(renderedElementIndex, " was not found in the list of Rendered Item Elements in the Items Container of Virtual Scroller. There're only ").concat(renderedElementsCount, " Elements there.");
63
+ }
64
+ //# sourceMappingURL=ItemNotRenderedError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ItemNotRenderedError.js","names":["ItemNotRenderedError","renderedElementIndex","renderedElementsCount","message","getDefaultMessage","Error"],"sources":["../source/ItemNotRenderedError.js"],"sourcesContent":["export default class ItemNotRenderedError extends Error {\r\n\tconstructor({\r\n\t\trenderedElementIndex,\r\n\t\trenderedElementsCount,\r\n\t\tmessage\r\n\t}) {\r\n\t\tsuper(message || getDefaultMessage({ renderedElementIndex, renderedElementsCount }))\r\n\t}\r\n}\r\n\r\nfunction getDefaultMessage({\r\n\trenderedElementIndex,\r\n\trenderedElementsCount\r\n}) {\r\n\treturn `Element with index ${renderedElementIndex} was not found in the list of Rendered Item Elements in the Items Container of Virtual Scroller. There're only ${renderedElementsCount} Elements there.`\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAAqBA,oB;;;;;EACpB,oCAIG;IAAA,IAHFC,oBAGE,QAHFA,oBAGE;IAAA,IAFFC,qBAEE,QAFFA,qBAEE;IAAA,IADFC,OACE,QADFA,OACE;;IAAA;;IAAA,yBACIA,OAAO,IAAIC,iBAAiB,CAAC;MAAEH,oBAAoB,EAApBA,oBAAF;MAAwBC,qBAAqB,EAArBA;IAAxB,CAAD,CADhC;EAEF;;;iCAPgDG,K;;;;AAUlD,SAASD,iBAAT,QAGG;EAAA,IAFFH,oBAEE,SAFFA,oBAEE;EAAA,IADFC,qBACE,SADFA,qBACE;EACF,oCAA6BD,oBAA7B,4HAAmKC,qBAAnK;AACA"}
@@ -169,6 +169,12 @@ describe('Layout', function () {
169
169
  }
170
170
  });
171
171
  var shouldResetGridLayout;
172
+ var errors = [];
173
+
174
+ global.VirtualScrollerCatchError = function (error) {
175
+ return errors.push(error);
176
+ };
177
+
172
178
  layout.getLayoutUpdateForItemsDiff({
173
179
  firstShownItemIndex: 3,
174
180
  lastShownItemIndex: 5,
@@ -190,6 +196,10 @@ describe('Layout', function () {
190
196
  beforeItemsHeight: 0,
191
197
  afterItemsHeight: 5 * (ITEM_HEIGHT + VERTICAL_SPACING)
192
198
  });
199
+ global.VirtualScrollerCatchError = undefined;
200
+ errors.length.should.equal(2);
201
+ errors[0].message.should.equal('[virtual-scroller] ~ Prepended items count 5 is not divisible by Columns Count 4 ~');
202
+ errors[1].message.should.equal('[virtual-scroller] Layout reset required');
193
203
  shouldResetGridLayout.should.equal(true);
194
204
  });
195
205
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Layout.test.js","names":["describe","it","SCREEN_HEIGHT","scrollableContainer","width","height","ITEM_WIDTH","ITEM_HEIGHT","VERTICAL_SPACING","items","Array","fill","layout","Layout","getPrerenderMargin","getVerticalSpacing","getColumnsCount","getItemHeight","i","getBeforeResizeItemsCount","getAverageItemHeight","getScrollableContainerHeight","getShownItemIndexes","itemsCount","length","visibleAreaTop","visibleAreaBottom","should","deep","equal","firstShownItemIndex","lastShownItemIndex","getLayoutUpdateForItemsDiff","beforeItemsHeight","afterItemsHeight","prependedItemsCount","appendedItemsCount","columnsCount","shouldResetGridLayout","shouldRestoreScrollPosition","onResetGridLayout"],"sources":["../source/Layout.test.js"],"sourcesContent":["import Layout from './Layout.js'\r\n\r\nimport Engine from './test/Engine.js'\r\n\r\ndescribe('Layout', function() {\r\n\tit('should work', function() {\r\n\t\tconst SCREEN_HEIGHT = 400\r\n\r\n\t\tconst scrollableContainer = {\r\n\t\t\twidth: 800,\r\n\t\t\theight: SCREEN_HEIGHT\r\n\t\t}\r\n\r\n\t\tconst ITEM_WIDTH = scrollableContainer.width\r\n\t\tconst ITEM_HEIGHT = 200\r\n\r\n\t\tconst VERTICAL_SPACING = 100\r\n\r\n\t\tconst items = new Array(9).fill(ITEM_WIDTH * ITEM_HEIGHT)\r\n\r\n\t\tconst layout = new Layout({\r\n\t\t\tgetPrerenderMargin: () => SCREEN_HEIGHT,\r\n\t\t\tgetVerticalSpacing: () => VERTICAL_SPACING,\r\n\t\t\tgetColumnsCount: () => 1,\r\n\t\t\tgetItemHeight: (i) => items[i] / scrollableContainer.width,\r\n\t\t\tgetBeforeResizeItemsCount: () => 0,\r\n\t\t\tgetAverageItemHeight: () => ITEM_HEIGHT,\r\n\t\t\tgetScrollableContainerHeight: () => scrollableContainer.height\r\n\t\t})\r\n\r\n\t\t// Initial render.\r\n\t\tlayout.getShownItemIndexes({\r\n\t\t\titemsCount: items.length,\r\n\t\t\tvisibleAreaTop: 0,\r\n\t\t\tvisibleAreaBottom: SCREEN_HEIGHT\r\n\t\t}).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 0,\r\n\t\t\tlastShownItemIndex: 2\r\n\t\t})\r\n\r\n\t\t// The first item is almost hidden.\r\n\t\tlayout.getShownItemIndexes({\r\n\t\t\titemsCount: items.length,\r\n\t\t\tvisibleAreaTop: SCREEN_HEIGHT + ITEM_HEIGHT - 1,\r\n\t\t\tvisibleAreaBottom: (SCREEN_HEIGHT + ITEM_HEIGHT - 1) + SCREEN_HEIGHT\r\n\t\t}).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 0,\r\n\t\t\tlastShownItemIndex: 4\r\n\t\t})\r\n\r\n\t\t// The first item is hidden.\r\n\t\tlayout.getShownItemIndexes({\r\n\t\t\titemsCount: items.length,\r\n\t\t\tvisibleAreaTop: SCREEN_HEIGHT + ITEM_HEIGHT,\r\n\t\t\tvisibleAreaBottom: (SCREEN_HEIGHT + ITEM_HEIGHT) + SCREEN_HEIGHT\r\n\t\t}).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 1,\r\n\t\t\tlastShownItemIndex: 4\r\n\t\t})\r\n\r\n\t\t// A new item at the bottom is almost visible.\r\n\t\tlayout.getShownItemIndexes({\r\n\t\t\titemsCount: items.length,\r\n\t\t\tvisibleAreaTop: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 - SCREEN_HEIGHT * 2,\r\n\t\t\tvisibleAreaBottom: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 - SCREEN_HEIGHT\r\n\t\t}).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 1,\r\n\t\t\tlastShownItemIndex: 4\r\n\t\t})\r\n\r\n\t\t// A new item at the bottom is visible.\r\n\t\tlayout.getShownItemIndexes({\r\n\t\t\titemsCount: items.length,\r\n\t\t\tvisibleAreaTop: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 + 1 - SCREEN_HEIGHT * 2,\r\n\t\t\tvisibleAreaBottom: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 + 1 - SCREEN_HEIGHT\r\n\t\t}).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 1,\r\n\t\t\tlastShownItemIndex: 5\r\n\t\t})\r\n\t})\r\n\r\n\tit('should update layout for items incremental change', function() {\r\n\t\tconst scrollableContainer = {\r\n\t\t\twidth: 800,\r\n\t\t\theight: 400\r\n\t\t}\r\n\r\n\t\tconst ITEM_WIDTH = scrollableContainer.width\r\n\t\tconst ITEM_HEIGHT = 200\r\n\r\n\t\tconst items = new Array(9).fill(ITEM_WIDTH * ITEM_HEIGHT)\r\n\r\n\t\tconst VERTICAL_SPACING = 100\r\n\r\n\t\tconst layout = new Layout({\r\n\t\t\tgetPrerenderMargin: () => scrollableContainer.height,\r\n\t\t\tgetVerticalSpacing: () => VERTICAL_SPACING,\r\n\t\t\tgetColumnsCount: () => 1,\r\n\t\t\tgetItemHeight: (i) => ITEM_HEIGHT,\r\n\t\t\tgetBeforeResizeItemsCount: () => 0,\r\n\t\t\tgetAverageItemHeight: () => ITEM_HEIGHT,\r\n\t\t\tgetScrollableContainerHeight: () => scrollableContainer.height\r\n\t\t})\r\n\r\n\t\tlayout.getLayoutUpdateForItemsDiff(\r\n\t\t\t{\r\n\t\t\t\tfirstShownItemIndex: 3,\r\n\t\t\t\tlastShownItemIndex: 5,\r\n\t\t\t\tbeforeItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING),\r\n\t\t\t\tafterItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING)\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tprependedItemsCount: 5,\r\n\t\t\t\tappendedItemsCount: 5\r\n\t\t\t}, {\r\n\t\t\t\titemsCount: 5 + 5 + items.length,\r\n\t\t\t\tcolumnsCount: 1\r\n\t\t\t}\r\n\t\t).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 5 + 3,\r\n\t\t\tlastShownItemIndex: 5 + 5,\r\n\t\t\tbeforeItemsHeight: (5 + 3) * (ITEM_HEIGHT + VERTICAL_SPACING),\r\n\t\t\tafterItemsHeight: (3 + 5) * (ITEM_HEIGHT + VERTICAL_SPACING)\r\n\t\t})\r\n\t})\r\n\r\n\tit('should update layout for items incremental change (rows get rebalanced)', function() {\r\n\t\tconst scrollableContainer = {\r\n\t\t\twidth: 800,\r\n\t\t\theight: 400\r\n\t\t}\r\n\t\tconst ITEM_WIDTH = scrollableContainer.width\r\n\t\tconst ITEM_HEIGHT = 400\r\n\r\n\t\tconst items = new Array(9).fill(ITEM_WIDTH * ITEM_HEIGHT)\r\n\r\n\t\tconst VERTICAL_SPACING = 100\r\n\r\n\t\tconst layout = new Layout({\r\n\t\t\tgetPrerenderMargin: () => scrollableContainer.height,\r\n\t\t\tgetVerticalSpacing: () => VERTICAL_SPACING,\r\n\t\t\tgetColumnsCount: () => 4,\r\n\t\t\tgetItemHeight: () => ITEM_HEIGHT,\r\n\t\t\tgetBeforeResizeItemsCount: () => 0,\r\n\t\t\tgetAverageItemHeight: () => ITEM_HEIGHT,\r\n\t\t\tgetScrollableContainerHeight: () => scrollableContainer.height\r\n\t\t})\r\n\r\n\t\tlet shouldResetGridLayout\r\n\r\n\t\tlayout.getLayoutUpdateForItemsDiff(\r\n\t\t\t{\r\n\t\t\t\tfirstShownItemIndex: 3,\r\n\t\t\t\tlastShownItemIndex: 5,\r\n\t\t\t\tbeforeItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING),\r\n\t\t\t\tafterItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING)\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tprependedItemsCount: 5,\r\n\t\t\t\tappendedItemsCount: 5\r\n\t\t\t}, {\r\n\t\t\t\titemsCount: 5 + 5 + items.length,\r\n\t\t\t\tcolumnsCount: 4,\r\n\t\t\t\tshouldRestoreScrollPosition: true,\r\n\t\t\t\tonResetGridLayout: () => shouldResetGridLayout = true\r\n\t\t\t}\r\n\t\t).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 0,\r\n\t\t\tlastShownItemIndex: 5 + 5,\r\n\t\t\tbeforeItemsHeight: 0,\r\n\t\t\tafterItemsHeight: 5 * (ITEM_HEIGHT + VERTICAL_SPACING)\r\n\t\t})\r\n\r\n\t\tshouldResetGridLayout.should.equal(true)\r\n\t})\r\n})"],"mappings":"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"}
1
+ {"version":3,"file":"Layout.test.js","names":["describe","it","SCREEN_HEIGHT","scrollableContainer","width","height","ITEM_WIDTH","ITEM_HEIGHT","VERTICAL_SPACING","items","Array","fill","layout","Layout","getPrerenderMargin","getVerticalSpacing","getColumnsCount","getItemHeight","i","getBeforeResizeItemsCount","getAverageItemHeight","getScrollableContainerHeight","getShownItemIndexes","itemsCount","length","visibleAreaTop","visibleAreaBottom","should","deep","equal","firstShownItemIndex","lastShownItemIndex","getLayoutUpdateForItemsDiff","beforeItemsHeight","afterItemsHeight","prependedItemsCount","appendedItemsCount","columnsCount","shouldResetGridLayout","errors","global","VirtualScrollerCatchError","error","push","shouldRestoreScrollPosition","onResetGridLayout","undefined","message"],"sources":["../source/Layout.test.js"],"sourcesContent":["import Layout from './Layout.js'\r\n\r\nimport Engine from './test/Engine.js'\r\n\r\ndescribe('Layout', function() {\r\n\tit('should work', function() {\r\n\t\tconst SCREEN_HEIGHT = 400\r\n\r\n\t\tconst scrollableContainer = {\r\n\t\t\twidth: 800,\r\n\t\t\theight: SCREEN_HEIGHT\r\n\t\t}\r\n\r\n\t\tconst ITEM_WIDTH = scrollableContainer.width\r\n\t\tconst ITEM_HEIGHT = 200\r\n\r\n\t\tconst VERTICAL_SPACING = 100\r\n\r\n\t\tconst items = new Array(9).fill(ITEM_WIDTH * ITEM_HEIGHT)\r\n\r\n\t\tconst layout = new Layout({\r\n\t\t\tgetPrerenderMargin: () => SCREEN_HEIGHT,\r\n\t\t\tgetVerticalSpacing: () => VERTICAL_SPACING,\r\n\t\t\tgetColumnsCount: () => 1,\r\n\t\t\tgetItemHeight: (i) => items[i] / scrollableContainer.width,\r\n\t\t\tgetBeforeResizeItemsCount: () => 0,\r\n\t\t\tgetAverageItemHeight: () => ITEM_HEIGHT,\r\n\t\t\tgetScrollableContainerHeight: () => scrollableContainer.height\r\n\t\t})\r\n\r\n\t\t// Initial render.\r\n\t\tlayout.getShownItemIndexes({\r\n\t\t\titemsCount: items.length,\r\n\t\t\tvisibleAreaTop: 0,\r\n\t\t\tvisibleAreaBottom: SCREEN_HEIGHT\r\n\t\t}).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 0,\r\n\t\t\tlastShownItemIndex: 2\r\n\t\t})\r\n\r\n\t\t// The first item is almost hidden.\r\n\t\tlayout.getShownItemIndexes({\r\n\t\t\titemsCount: items.length,\r\n\t\t\tvisibleAreaTop: SCREEN_HEIGHT + ITEM_HEIGHT - 1,\r\n\t\t\tvisibleAreaBottom: (SCREEN_HEIGHT + ITEM_HEIGHT - 1) + SCREEN_HEIGHT\r\n\t\t}).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 0,\r\n\t\t\tlastShownItemIndex: 4\r\n\t\t})\r\n\r\n\t\t// The first item is hidden.\r\n\t\tlayout.getShownItemIndexes({\r\n\t\t\titemsCount: items.length,\r\n\t\t\tvisibleAreaTop: SCREEN_HEIGHT + ITEM_HEIGHT,\r\n\t\t\tvisibleAreaBottom: (SCREEN_HEIGHT + ITEM_HEIGHT) + SCREEN_HEIGHT\r\n\t\t}).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 1,\r\n\t\t\tlastShownItemIndex: 4\r\n\t\t})\r\n\r\n\t\t// A new item at the bottom is almost visible.\r\n\t\tlayout.getShownItemIndexes({\r\n\t\t\titemsCount: items.length,\r\n\t\t\tvisibleAreaTop: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 - SCREEN_HEIGHT * 2,\r\n\t\t\tvisibleAreaBottom: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 - SCREEN_HEIGHT\r\n\t\t}).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 1,\r\n\t\t\tlastShownItemIndex: 4\r\n\t\t})\r\n\r\n\t\t// A new item at the bottom is visible.\r\n\t\tlayout.getShownItemIndexes({\r\n\t\t\titemsCount: items.length,\r\n\t\t\tvisibleAreaTop: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 + 1 - SCREEN_HEIGHT * 2,\r\n\t\t\tvisibleAreaBottom: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 + 1 - SCREEN_HEIGHT\r\n\t\t}).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 1,\r\n\t\t\tlastShownItemIndex: 5\r\n\t\t})\r\n\t})\r\n\r\n\tit('should update layout for items incremental change', function() {\r\n\t\tconst scrollableContainer = {\r\n\t\t\twidth: 800,\r\n\t\t\theight: 400\r\n\t\t}\r\n\r\n\t\tconst ITEM_WIDTH = scrollableContainer.width\r\n\t\tconst ITEM_HEIGHT = 200\r\n\r\n\t\tconst items = new Array(9).fill(ITEM_WIDTH * ITEM_HEIGHT)\r\n\r\n\t\tconst VERTICAL_SPACING = 100\r\n\r\n\t\tconst layout = new Layout({\r\n\t\t\tgetPrerenderMargin: () => scrollableContainer.height,\r\n\t\t\tgetVerticalSpacing: () => VERTICAL_SPACING,\r\n\t\t\tgetColumnsCount: () => 1,\r\n\t\t\tgetItemHeight: (i) => ITEM_HEIGHT,\r\n\t\t\tgetBeforeResizeItemsCount: () => 0,\r\n\t\t\tgetAverageItemHeight: () => ITEM_HEIGHT,\r\n\t\t\tgetScrollableContainerHeight: () => scrollableContainer.height\r\n\t\t})\r\n\r\n\t\tlayout.getLayoutUpdateForItemsDiff(\r\n\t\t\t{\r\n\t\t\t\tfirstShownItemIndex: 3,\r\n\t\t\t\tlastShownItemIndex: 5,\r\n\t\t\t\tbeforeItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING),\r\n\t\t\t\tafterItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING)\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tprependedItemsCount: 5,\r\n\t\t\t\tappendedItemsCount: 5\r\n\t\t\t}, {\r\n\t\t\t\titemsCount: 5 + 5 + items.length,\r\n\t\t\t\tcolumnsCount: 1\r\n\t\t\t}\r\n\t\t).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 5 + 3,\r\n\t\t\tlastShownItemIndex: 5 + 5,\r\n\t\t\tbeforeItemsHeight: (5 + 3) * (ITEM_HEIGHT + VERTICAL_SPACING),\r\n\t\t\tafterItemsHeight: (3 + 5) * (ITEM_HEIGHT + VERTICAL_SPACING)\r\n\t\t})\r\n\t})\r\n\r\n\tit('should update layout for items incremental change (rows get rebalanced)', function() {\r\n\t\tconst scrollableContainer = {\r\n\t\t\twidth: 800,\r\n\t\t\theight: 400\r\n\t\t}\r\n\t\tconst ITEM_WIDTH = scrollableContainer.width\r\n\t\tconst ITEM_HEIGHT = 400\r\n\r\n\t\tconst items = new Array(9).fill(ITEM_WIDTH * ITEM_HEIGHT)\r\n\r\n\t\tconst VERTICAL_SPACING = 100\r\n\r\n\t\tconst layout = new Layout({\r\n\t\t\tgetPrerenderMargin: () => scrollableContainer.height,\r\n\t\t\tgetVerticalSpacing: () => VERTICAL_SPACING,\r\n\t\t\tgetColumnsCount: () => 4,\r\n\t\t\tgetItemHeight: () => ITEM_HEIGHT,\r\n\t\t\tgetBeforeResizeItemsCount: () => 0,\r\n\t\t\tgetAverageItemHeight: () => ITEM_HEIGHT,\r\n\t\t\tgetScrollableContainerHeight: () => scrollableContainer.height\r\n\t\t})\r\n\r\n\t\tlet shouldResetGridLayout\r\n\r\n\t\tconst errors = []\r\n\r\n\t\tglobal.VirtualScrollerCatchError = (error) => errors.push(error)\r\n\r\n\t\tlayout.getLayoutUpdateForItemsDiff(\r\n\t\t\t{\r\n\t\t\t\tfirstShownItemIndex: 3,\r\n\t\t\t\tlastShownItemIndex: 5,\r\n\t\t\t\tbeforeItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING),\r\n\t\t\t\tafterItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING)\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tprependedItemsCount: 5,\r\n\t\t\t\tappendedItemsCount: 5\r\n\t\t\t}, {\r\n\t\t\t\titemsCount: 5 + 5 + items.length,\r\n\t\t\t\tcolumnsCount: 4,\r\n\t\t\t\tshouldRestoreScrollPosition: true,\r\n\t\t\t\tonResetGridLayout: () => shouldResetGridLayout = true\r\n\t\t\t}\r\n\t\t).should.deep.equal({\r\n\t\t\tfirstShownItemIndex: 0,\r\n\t\t\tlastShownItemIndex: 5 + 5,\r\n\t\t\tbeforeItemsHeight: 0,\r\n\t\t\tafterItemsHeight: 5 * (ITEM_HEIGHT + VERTICAL_SPACING)\r\n\t\t})\r\n\r\n\t\tglobal.VirtualScrollerCatchError = undefined\r\n\t\terrors.length.should.equal(2)\r\n\t\terrors[0].message.should.equal('[virtual-scroller] ~ Prepended items count 5 is not divisible by Columns Count 4 ~')\r\n\t\terrors[1].message.should.equal('[virtual-scroller] Layout reset required')\r\n\r\n\t\tshouldResetGridLayout.should.equal(true)\r\n\t})\r\n})"],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
 
3
+ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
4
+
3
5
  Object.defineProperty(exports, "__esModule", {
4
6
  value: true
5
7
  });
@@ -11,7 +13,11 @@ var _tbody = require("./DOM/tbody.js");
11
13
 
12
14
  var _Layout = require("./Layout.js");
13
15
 
14
- var _debug = _interopRequireDefault(require("./utility/debug.js"));
16
+ var _debug = _interopRequireWildcard(require("./utility/debug.js"));
17
+
18
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
+
20
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
15
21
 
16
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
17
23
 
@@ -94,8 +100,9 @@ var VirtualScroller = /*#__PURE__*/function () {
94
100
  var isRestart = this._isActive === false;
95
101
 
96
102
  if (!isRestart) {
97
- // If no custom state storage has been configured, use the default one.
103
+ this.waitingForRender = true; // If no custom state storage has been configured, use the default one.
98
104
  // Also sets the initial state.
105
+
99
106
  if (!this._usesCustomStateStorage) {
100
107
  this.useDefaultStateStorage();
101
108
  } // If `render()` function parameter was passed,
@@ -230,16 +237,27 @@ var VirtualScroller = /*#__PURE__*/function () {
230
237
  return this.getListTopOffsetInsideScrollableContainer() + itemTopOffsetInList;
231
238
  }
232
239
  /**
233
- * Forces a re-measure of an item's height.
234
- * @param {number} i Item index
240
+ * @deprecated
241
+ * `.onItemHeightChange()` has been renamed to `.onItemHeightDidChange()`.
235
242
  */
236
243
 
237
244
  }, {
238
245
  key: "onItemHeightChange",
239
246
  value: function onItemHeightChange(i) {
247
+ (0, _debug.warn)('`.onItemHeightChange(i)` method was renamed to `.onItemHeightDidChange(i)`');
248
+ this.onItemHeightDidChange(i);
249
+ }
250
+ /**
251
+ * Forces a re-measure of an item's height.
252
+ * @param {number} i — Item index
253
+ */
254
+
255
+ }, {
256
+ key: "onItemHeightDidChange",
257
+ value: function onItemHeightDidChange(i) {
240
258
  this.hasToBeStarted();
241
259
 
242
- this._onItemHeightChange(i);
260
+ this._onItemHeightDidChange(i);
243
261
  }
244
262
  /**
245
263
  * Updates an item's state in `state.itemStates[]`.
@@ -1 +1 @@
1
- {"version":3,"file":"VirtualScroller.js","names":["VirtualScroller","getItemsContainerElement","items","options","_isActive","Error","log","resize","stop","scroll","listTopOffsetWatcher","isStarted","cancelLayoutTimer","hasToBeStarted","onUpdateShownItemIndexes","reason","LAYOUT_REASON","MANUAL","_onRender","getState","previousState","VirtualScrollerConstructor","call","isRestart","_usesCustomStateStorage","useDefaultStateStorage","_render","listHeightMeasurement","reset","_isResizing","undefined","_isSettingNewItems","tbody","hasTbodyStyles","addTbodyStyles","stateUpdate","_stoppedStateUpdate","verticalSpacing","verticalSpacingStateUpdate","measureItemHeightsAndSpacing","start","scrollableContainerWidth","scrollableContainer","getWidth","newWidth","prevWidth","onResize","columnsCount","getActualColumnsCount","columnsCountFromState","STARTED","i","itemTopOffsetInList","layout","getItemTopOffset","getListTopOffsetInsideScrollableContainer","_onItemHeightChange","newItemState","_setItemState","setItemState","newItems","_setItems"],"sources":["../source/VirtualScroller.js"],"sourcesContent":["import VirtualScrollerConstructor from './VirtualScroller.constructor.js'\r\nimport { hasTbodyStyles, addTbodyStyles } from './DOM/tbody.js'\r\nimport { LAYOUT_REASON } from './Layout.js'\r\nimport log from './utility/debug.js'\r\n\r\nexport default class VirtualScroller {\r\n\t/**\r\n\t * @param {function} getItemsContainerElement — Returns the container DOM `Element`.\r\n\t * @param {any[]} items — The list of items.\r\n\t * @param {Object} [options] — See README.md.\r\n\t * @return {VirtualScroller}\r\n\t */\r\n\tconstructor(\r\n\t\tgetItemsContainerElement,\r\n\t\titems,\r\n\t\toptions = {}\r\n\t) {\r\n\t\tVirtualScrollerConstructor.call(\r\n\t\t\tthis,\r\n\t\t\tgetItemsContainerElement,\r\n\t\t\titems,\r\n\t\t\toptions\r\n\t\t)\r\n\t}\r\n\r\n\t/**\r\n\t * Should be invoked after a \"container\" DOM Element is mounted (inserted into the DOM tree).\r\n\t */\r\n\tstart() {\r\n\t\tif (this._isActive) {\r\n\t\t\tthrow new Error('[virtual-scroller] `VirtualScroller` has already been started')\r\n\t\t}\r\n\r\n\t\t// If has been stopped previously.\r\n\t\tconst isRestart = this._isActive === false\r\n\r\n\t\tif (!isRestart) {\r\n\t\t\t// If no custom state storage has been configured, use the default one.\r\n\t\t\t// Also sets the initial state.\r\n\t\t\tif (!this._usesCustomStateStorage) {\r\n\t\t\t\tthis.useDefaultStateStorage()\r\n\t\t\t}\r\n\t\t\t// If `render()` function parameter was passed,\r\n\t\t\t// perform an initial render.\r\n\t\t\tif (this._render) {\r\n\t\t\t\tthis._render(this.getState())\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlog('~ Start ~')\r\n\r\n\t\t// `this._isActive = true` should be placed somewhere at the start of this function.\r\n\t\tthis._isActive = true\r\n\r\n\t\t// Reset `ListHeightMeasurement` just in case it has some \"leftover\" state.\r\n\t\tthis.listHeightMeasurement.reset()\r\n\r\n\t\t// Reset `_isResizing` flag just in case it has some \"leftover\" value.\r\n\t\tthis._isResizing = undefined\r\n\r\n\t\t// Reset `_isSettingNewItems` flag just in case it has some \"leftover\" value.\r\n\t\tthis._isSettingNewItems = undefined\r\n\r\n\t\t// Work around `<tbody/>` not being able to have `padding`.\r\n\t\t// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1\r\n\t\tif (this.tbody) {\r\n\t\t\tif (!hasTbodyStyles(this.getItemsContainerElement())) {\r\n\t\t\t\taddTbodyStyles(this.getItemsContainerElement())\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If there was a pending state update that didn't get applied\r\n\t\t// because of stopping the `VirtualScroller`, apply that state update now.\r\n\t\t//\r\n\t\t// The pending state update won't get applied if the scrollable container width\r\n\t\t// has changed but that's ok because that state update currently could only contain:\r\n\t\t// * `scrollableContainerWidth`\r\n\t\t// * `verticalSpacing`\r\n\t\t// * `beforeResize`\r\n\t\t// All of those get rewritten in `onResize()` anyway.\r\n\t\t//\r\n\t\tlet stateUpdate = this._stoppedStateUpdate\r\n\t\tthis._stoppedStateUpdate = undefined\r\n\r\n\t\t// Reset `this.verticalSpacing` so that it re-measures it in cases when\r\n\t\t// the `VirtualScroller` was previously stopped and is now being restarted.\r\n\t\t// The rationale is that a previously captured inter-item vertical spacing\r\n\t\t// can't be \"trusted\" in a sense that the user might have resized the window\r\n\t\t// after the previous `state` has been snapshotted.\r\n\t\t// If the user has resized the window, then changing window width might have\r\n\t\t// activated different CSS `@media()` \"queries\" resulting in a potentially different\r\n\t\t// vertical spacing after the restart.\r\n\t\t// If it's not a restart then `this.verticalSpacing` is `undefined` anyway.\r\n\t\tthis.verticalSpacing = undefined\r\n\r\n\t\tconst verticalSpacingStateUpdate = this.measureItemHeightsAndSpacing()\r\n\t\tif (verticalSpacingStateUpdate) {\r\n\t\t\tstateUpdate = {\r\n\t\t\t\t...stateUpdate,\r\n\t\t\t\t...verticalSpacingStateUpdate\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.resize.start()\r\n\t\tthis.scroll.start()\r\n\r\n\t\t// If `scrollableContainerWidth` hasn't been measured yet,\r\n\t\t// measure it and write it to state.\r\n\t\tif (this.getState().scrollableContainerWidth === undefined) {\r\n\t\t\tconst scrollableContainerWidth = this.scrollableContainer.getWidth()\r\n\t\t\tstateUpdate = {\r\n\t\t\t\t...stateUpdate,\r\n\t\t\t\tscrollableContainerWidth\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\t// Reset layout:\r\n\t\t\t// * If the scrollable container width has changed while stopped.\r\n\t\t\t// * If the restored state was calculated for another scrollable container width.\r\n\t\t\tconst newWidth = this.scrollableContainer.getWidth()\r\n\t\t\tconst prevWidth = this.getState().scrollableContainerWidth\r\n\t\t\tif (newWidth !== prevWidth) {\r\n\t\t\t\tlog('~ Scrollable container width changed from', prevWidth, 'to', newWidth, '~')\r\n\t\t\t\t// `stateUpdate` doesn't get passed to `this.onResize()`, and, therefore,\r\n\t\t\t\t// won't be applied. But that's ok because currently it could only contain:\r\n\t\t\t\t// * `scrollableContainerWidth`\r\n\t\t\t\t// * `verticalSpacing`\r\n\t\t\t\t// * `beforeResize`\r\n\t\t\t\t// All of those get rewritten in `onResize()` anyway.\r\n\t\t\t\treturn this.onResize()\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If the `VirtualScroller` uses custom (external) state storage, then\r\n\t\t// check if the columns count has changed between calling `.getInitialState()`\r\n\t\t// and `.start()`. If it has, perform a re-layout \"from scratch\".\r\n\t\tif (this._usesCustomStateStorage) {\r\n\t\t\tconst columnsCount = this.getActualColumnsCount()\r\n\t\t\tconst columnsCountFromState = this.getState().columnsCount || 1\r\n\t\t\tif (columnsCount !== columnsCountFromState) {\r\n\t\t\t\treturn this.onResize()\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Re-calculate layout and re-render the list.\r\n\t\t// Do that even if when an initial `state` parameter, containing layout values,\r\n\t\t// has been passed. The reason is that the `state` parameter can't be \"trusted\"\r\n\t\t// in a way that it could have been snapshotted for another window width and\r\n\t\t// the user might have resized their window since then.\r\n\t\tthis.onUpdateShownItemIndexes({ reason: LAYOUT_REASON.STARTED, stateUpdate })\r\n\t}\r\n\r\n\t// Could be passed as a \"callback\" parameter, so bind it to `this`.\r\n\tstop = () => {\r\n\t\tif (!this._isActive) {\r\n\t\t\tthrow new Error('[virtual-scroller] Can\\'t stop a `VirtualScroller` that hasn\\'t been started')\r\n\t\t}\r\n\r\n\t\tthis._isActive = false\r\n\r\n\t\tlog('~ Stop ~')\r\n\r\n\t\tthis.resize.stop()\r\n\t\tthis.scroll.stop()\r\n\r\n\t\t// Stop `ListTopOffsetWatcher` if it has been started.\r\n\t\t// There seems to be no need to restart `ListTopOffsetWatcher`.\r\n\t\t// It's mainly a hacky workaround for development mode anyway.\r\n\t\tif (this.listTopOffsetWatcher && this.listTopOffsetWatcher.isStarted()) {\r\n\t\t\tthis.listTopOffsetWatcher.stop()\r\n\t\t}\r\n\r\n\t\t// Cancel any scheduled layout.\r\n\t\tthis.cancelLayoutTimer({})\r\n\t}\r\n\r\n\thasToBeStarted() {\r\n\t\tif (!this._isActive) {\r\n\t\t\tthrow new Error('[virtual-scroller] `VirtualScroller` hasn\\'t been started')\r\n\t\t}\r\n\t}\r\n\r\n\t// Bind it to `this` because this function could hypothetically be passed\r\n\t// as a \"callback\" parameter.\r\n\tupdateLayout = () => {\r\n\t\tthis.hasToBeStarted()\r\n\t\tthis.onUpdateShownItemIndexes({ reason: LAYOUT_REASON.MANUAL })\r\n\t}\r\n\r\n\t// Bind the function to `this` so that it could be passed as a callback\r\n\t// in a random application's code.\r\n\tonRender = () => {\r\n\t\tthis._onRender(this.getState(), this.previousState)\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the items's top offset relative to the scrollable container's top edge.\r\n\t * @param {number} i — Item index\r\n\t * @return {[number]} Returns the item's scroll Y position. Returns `undefined` if any of the previous items haven't been rendered yet.\r\n\t */\r\n\tgetItemScrollPosition(i) {\r\n\t\tconst itemTopOffsetInList = this.layout.getItemTopOffset(i)\r\n\t\tif (itemTopOffsetInList === undefined) {\r\n\t\t\treturn\r\n\t\t}\r\n\t\treturn this.getListTopOffsetInsideScrollableContainer() + itemTopOffsetInList\r\n\t}\r\n\r\n\t/**\r\n\t * Forces a re-measure of an item's height.\r\n\t * @param {number} i — Item index\r\n\t */\r\n\tonItemHeightChange(i) {\r\n\t\tthis.hasToBeStarted()\r\n\t\tthis._onItemHeightChange(i)\r\n\t}\r\n\r\n\t/**\r\n\t * Updates an item's state in `state.itemStates[]`.\r\n\t * @param {number} i — Item index\r\n\t * @param {any} i — Item's new state\r\n\t */\r\n\tsetItemState(i, newItemState) {\r\n\t\tthis.hasToBeStarted()\r\n\t\tthis._setItemState(i, newItemState)\r\n\t}\r\n\r\n\t// (deprecated)\r\n\t// Use `.setItemState()` method name instead.\r\n\tonItemStateChange(i, newItemState) {\r\n\t\tthis.setItemState(i, newItemState)\r\n\t}\r\n\r\n\t/**\r\n\t * Updates `items`. For example, can prepend or append new items to the list.\r\n\t * @param {any[]} newItems\r\n\t * @param {boolean} [options.preserveScrollPositionOnPrependItems] — Set to `true` to enable \"restore scroll position after prepending items\" feature (could be useful when implementing \"Show previous items\" button).\r\n\t */\r\n\tsetItems(newItems, options = {}) {\r\n\t\tthis.hasToBeStarted()\r\n\t\treturn this._setItems(newItems, options)\r\n\t}\r\n}"],"mappings":"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"}
1
+ {"version":3,"file":"VirtualScroller.js","names":["VirtualScroller","getItemsContainerElement","items","options","_isActive","Error","log","resize","stop","scroll","listTopOffsetWatcher","isStarted","cancelLayoutTimer","hasToBeStarted","onUpdateShownItemIndexes","reason","LAYOUT_REASON","MANUAL","_onRender","getState","previousState","VirtualScrollerConstructor","call","isRestart","waitingForRender","_usesCustomStateStorage","useDefaultStateStorage","_render","listHeightMeasurement","reset","_isResizing","undefined","_isSettingNewItems","tbody","hasTbodyStyles","addTbodyStyles","stateUpdate","_stoppedStateUpdate","verticalSpacing","verticalSpacingStateUpdate","measureItemHeightsAndSpacing","start","scrollableContainerWidth","scrollableContainer","getWidth","newWidth","prevWidth","onResize","columnsCount","getActualColumnsCount","columnsCountFromState","STARTED","i","itemTopOffsetInList","layout","getItemTopOffset","getListTopOffsetInsideScrollableContainer","warn","onItemHeightDidChange","_onItemHeightDidChange","newItemState","_setItemState","setItemState","newItems","_setItems"],"sources":["../source/VirtualScroller.js"],"sourcesContent":["import VirtualScrollerConstructor from './VirtualScroller.constructor.js'\r\nimport { hasTbodyStyles, addTbodyStyles } from './DOM/tbody.js'\r\nimport { LAYOUT_REASON } from './Layout.js'\r\nimport log, { warn } from './utility/debug.js'\r\n\r\nexport default class VirtualScroller {\r\n\t/**\r\n\t * @param {function} getItemsContainerElement — Returns the container DOM `Element`.\r\n\t * @param {any[]} items — The list of items.\r\n\t * @param {Object} [options] — See README.md.\r\n\t * @return {VirtualScroller}\r\n\t */\r\n\tconstructor(\r\n\t\tgetItemsContainerElement,\r\n\t\titems,\r\n\t\toptions = {}\r\n\t) {\r\n\t\tVirtualScrollerConstructor.call(\r\n\t\t\tthis,\r\n\t\t\tgetItemsContainerElement,\r\n\t\t\titems,\r\n\t\t\toptions\r\n\t\t)\r\n\t}\r\n\r\n\t/**\r\n\t * Should be invoked after a \"container\" DOM Element is mounted (inserted into the DOM tree).\r\n\t */\r\n\tstart() {\r\n\t\tif (this._isActive) {\r\n\t\t\tthrow new Error('[virtual-scroller] `VirtualScroller` has already been started')\r\n\t\t}\r\n\r\n\t\t// If has been stopped previously.\r\n\t\tconst isRestart = this._isActive === false\r\n\r\n\t\tif (!isRestart) {\r\n\t\t\tthis.waitingForRender = true\r\n\r\n\t\t\t// If no custom state storage has been configured, use the default one.\r\n\t\t\t// Also sets the initial state.\r\n\t\t\tif (!this._usesCustomStateStorage) {\r\n\t\t\t\tthis.useDefaultStateStorage()\r\n\t\t\t}\r\n\t\t\t// If `render()` function parameter was passed,\r\n\t\t\t// perform an initial render.\r\n\t\t\tif (this._render) {\r\n\t\t\t\tthis._render(this.getState())\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlog('~ Start ~')\r\n\r\n\t\t// `this._isActive = true` should be placed somewhere at the start of this function.\r\n\t\tthis._isActive = true\r\n\r\n\t\t// Reset `ListHeightMeasurement` just in case it has some \"leftover\" state.\r\n\t\tthis.listHeightMeasurement.reset()\r\n\r\n\t\t// Reset `_isResizing` flag just in case it has some \"leftover\" value.\r\n\t\tthis._isResizing = undefined\r\n\r\n\t\t// Reset `_isSettingNewItems` flag just in case it has some \"leftover\" value.\r\n\t\tthis._isSettingNewItems = undefined\r\n\r\n\t\t// Work around `<tbody/>` not being able to have `padding`.\r\n\t\t// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1\r\n\t\tif (this.tbody) {\r\n\t\t\tif (!hasTbodyStyles(this.getItemsContainerElement())) {\r\n\t\t\t\taddTbodyStyles(this.getItemsContainerElement())\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If there was a pending state update that didn't get applied\r\n\t\t// because of stopping the `VirtualScroller`, apply that state update now.\r\n\t\t//\r\n\t\t// The pending state update won't get applied if the scrollable container width\r\n\t\t// has changed but that's ok because that state update currently could only contain:\r\n\t\t// * `scrollableContainerWidth`\r\n\t\t// * `verticalSpacing`\r\n\t\t// * `beforeResize`\r\n\t\t// All of those get rewritten in `onResize()` anyway.\r\n\t\t//\r\n\t\tlet stateUpdate = this._stoppedStateUpdate\r\n\t\tthis._stoppedStateUpdate = undefined\r\n\r\n\t\t// Reset `this.verticalSpacing` so that it re-measures it in cases when\r\n\t\t// the `VirtualScroller` was previously stopped and is now being restarted.\r\n\t\t// The rationale is that a previously captured inter-item vertical spacing\r\n\t\t// can't be \"trusted\" in a sense that the user might have resized the window\r\n\t\t// after the previous `state` has been snapshotted.\r\n\t\t// If the user has resized the window, then changing window width might have\r\n\t\t// activated different CSS `@media()` \"queries\" resulting in a potentially different\r\n\t\t// vertical spacing after the restart.\r\n\t\t// If it's not a restart then `this.verticalSpacing` is `undefined` anyway.\r\n\t\tthis.verticalSpacing = undefined\r\n\r\n\t\tconst verticalSpacingStateUpdate = this.measureItemHeightsAndSpacing()\r\n\t\tif (verticalSpacingStateUpdate) {\r\n\t\t\tstateUpdate = {\r\n\t\t\t\t...stateUpdate,\r\n\t\t\t\t...verticalSpacingStateUpdate\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.resize.start()\r\n\t\tthis.scroll.start()\r\n\r\n\t\t// If `scrollableContainerWidth` hasn't been measured yet,\r\n\t\t// measure it and write it to state.\r\n\t\tif (this.getState().scrollableContainerWidth === undefined) {\r\n\t\t\tconst scrollableContainerWidth = this.scrollableContainer.getWidth()\r\n\t\t\tstateUpdate = {\r\n\t\t\t\t...stateUpdate,\r\n\t\t\t\tscrollableContainerWidth\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\t// Reset layout:\r\n\t\t\t// * If the scrollable container width has changed while stopped.\r\n\t\t\t// * If the restored state was calculated for another scrollable container width.\r\n\t\t\tconst newWidth = this.scrollableContainer.getWidth()\r\n\t\t\tconst prevWidth = this.getState().scrollableContainerWidth\r\n\t\t\tif (newWidth !== prevWidth) {\r\n\t\t\t\tlog('~ Scrollable container width changed from', prevWidth, 'to', newWidth, '~')\r\n\t\t\t\t// `stateUpdate` doesn't get passed to `this.onResize()`, and, therefore,\r\n\t\t\t\t// won't be applied. But that's ok because currently it could only contain:\r\n\t\t\t\t// * `scrollableContainerWidth`\r\n\t\t\t\t// * `verticalSpacing`\r\n\t\t\t\t// * `beforeResize`\r\n\t\t\t\t// All of those get rewritten in `onResize()` anyway.\r\n\t\t\t\treturn this.onResize()\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If the `VirtualScroller` uses custom (external) state storage, then\r\n\t\t// check if the columns count has changed between calling `.getInitialState()`\r\n\t\t// and `.start()`. If it has, perform a re-layout \"from scratch\".\r\n\t\tif (this._usesCustomStateStorage) {\r\n\t\t\tconst columnsCount = this.getActualColumnsCount()\r\n\t\t\tconst columnsCountFromState = this.getState().columnsCount || 1\r\n\t\t\tif (columnsCount !== columnsCountFromState) {\r\n\t\t\t\treturn this.onResize()\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Re-calculate layout and re-render the list.\r\n\t\t// Do that even if when an initial `state` parameter, containing layout values,\r\n\t\t// has been passed. The reason is that the `state` parameter can't be \"trusted\"\r\n\t\t// in a way that it could have been snapshotted for another window width and\r\n\t\t// the user might have resized their window since then.\r\n\t\tthis.onUpdateShownItemIndexes({ reason: LAYOUT_REASON.STARTED, stateUpdate })\r\n\t}\r\n\r\n\t// Could be passed as a \"callback\" parameter, so bind it to `this`.\r\n\tstop = () => {\r\n\t\tif (!this._isActive) {\r\n\t\t\tthrow new Error('[virtual-scroller] Can\\'t stop a `VirtualScroller` that hasn\\'t been started')\r\n\t\t}\r\n\r\n\t\tthis._isActive = false\r\n\r\n\t\tlog('~ Stop ~')\r\n\r\n\t\tthis.resize.stop()\r\n\t\tthis.scroll.stop()\r\n\r\n\t\t// Stop `ListTopOffsetWatcher` if it has been started.\r\n\t\t// There seems to be no need to restart `ListTopOffsetWatcher`.\r\n\t\t// It's mainly a hacky workaround for development mode anyway.\r\n\t\tif (this.listTopOffsetWatcher && this.listTopOffsetWatcher.isStarted()) {\r\n\t\t\tthis.listTopOffsetWatcher.stop()\r\n\t\t}\r\n\r\n\t\t// Cancel any scheduled layout.\r\n\t\tthis.cancelLayoutTimer({})\r\n\t}\r\n\r\n\thasToBeStarted() {\r\n\t\tif (!this._isActive) {\r\n\t\t\tthrow new Error('[virtual-scroller] `VirtualScroller` hasn\\'t been started')\r\n\t\t}\r\n\t}\r\n\r\n\t// Bind it to `this` because this function could hypothetically be passed\r\n\t// as a \"callback\" parameter.\r\n\tupdateLayout = () => {\r\n\t\tthis.hasToBeStarted()\r\n\t\tthis.onUpdateShownItemIndexes({ reason: LAYOUT_REASON.MANUAL })\r\n\t}\r\n\r\n\t// Bind the function to `this` so that it could be passed as a callback\r\n\t// in a random application's code.\r\n\tonRender = () => {\r\n\t\tthis._onRender(this.getState(), this.previousState)\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the items's top offset relative to the scrollable container's top edge.\r\n\t * @param {number} i — Item index\r\n\t * @return {[number]} Returns the item's scroll Y position. Returns `undefined` if any of the previous items haven't been rendered yet.\r\n\t */\r\n\tgetItemScrollPosition(i) {\r\n\t\tconst itemTopOffsetInList = this.layout.getItemTopOffset(i)\r\n\t\tif (itemTopOffsetInList === undefined) {\r\n\t\t\treturn\r\n\t\t}\r\n\t\treturn this.getListTopOffsetInsideScrollableContainer() + itemTopOffsetInList\r\n\t}\r\n\r\n\t/**\r\n\t * @deprecated\r\n\t * `.onItemHeightChange()` has been renamed to `.onItemHeightDidChange()`.\r\n\t */\r\n\tonItemHeightChange(i) {\r\n\t\twarn('`.onItemHeightChange(i)` method was renamed to `.onItemHeightDidChange(i)`')\r\n\t\tthis.onItemHeightDidChange(i)\r\n\t}\r\n\r\n\t/**\r\n\t * Forces a re-measure of an item's height.\r\n\t * @param {number} i — Item index\r\n\t */\r\n\tonItemHeightDidChange(i) {\r\n\t\tthis.hasToBeStarted()\r\n\t\tthis._onItemHeightDidChange(i)\r\n\t}\r\n\r\n\t/**\r\n\t * Updates an item's state in `state.itemStates[]`.\r\n\t * @param {number} i — Item index\r\n\t * @param {any} i — Item's new state\r\n\t */\r\n\tsetItemState(i, newItemState) {\r\n\t\tthis.hasToBeStarted()\r\n\t\tthis._setItemState(i, newItemState)\r\n\t}\r\n\r\n\t// (deprecated)\r\n\t// Use `.setItemState()` method name instead.\r\n\tonItemStateChange(i, newItemState) {\r\n\t\tthis.setItemState(i, newItemState)\r\n\t}\r\n\r\n\t/**\r\n\t * Updates `items`. For example, can prepend or append new items to the list.\r\n\t * @param {any[]} newItems\r\n\t * @param {boolean} [options.preserveScrollPositionOnPrependItems] — Set to `true` to enable \"restore scroll position after prepending items\" feature (could be useful when implementing \"Show previous items\" button).\r\n\t */\r\n\tsetItems(newItems, options = {}) {\r\n\t\tthis.hasToBeStarted()\r\n\t\treturn this._setItems(newItems, options)\r\n\t}\r\n}"],"mappings":";;;;;;;;;AAAA;;AACA;;AACA;;AACA;;;;;;;;;;;;;;;;;;;;IAEqBA,e;EACpB;AACD;AACA;AACA;AACA;AACA;EACC,yBACCC,wBADD,EAECC,KAFD,EAIE;IAAA;;IAAA,IADDC,OACC,uEADS,EACT;;IAAA;;IAAA,8BA0IK,YAAM;MACZ,IAAI,CAAC,KAAI,CAACC,SAAV,EAAqB;QACpB,MAAM,IAAIC,KAAJ,CAAU,8EAAV,CAAN;MACA;;MAED,KAAI,CAACD,SAAL,GAAiB,KAAjB;MAEA,IAAAE,iBAAA,EAAI,UAAJ;;MAEA,KAAI,CAACC,MAAL,CAAYC,IAAZ;;MACA,KAAI,CAACC,MAAL,CAAYD,IAAZ,GAVY,CAYZ;MACA;MACA;;;MACA,IAAI,KAAI,CAACE,oBAAL,IAA6B,KAAI,CAACA,oBAAL,CAA0BC,SAA1B,EAAjC,EAAwE;QACvE,KAAI,CAACD,oBAAL,CAA0BF,IAA1B;MACA,CAjBW,CAmBZ;;;MACA,KAAI,CAACI,iBAAL,CAAuB,EAAvB;IACA,CA/JC;;IAAA,sCAyKa,YAAM;MACpB,KAAI,CAACC,cAAL;;MACA,KAAI,CAACC,wBAAL,CAA8B;QAAEC,MAAM,EAAEC,qBAAA,CAAcC;MAAxB,CAA9B;IACA,CA5KC;;IAAA,kCAgLS,YAAM;MAChB,KAAI,CAACC,SAAL,CAAe,KAAI,CAACC,QAAL,EAAf,EAAgC,KAAI,CAACC,aAArC;IACA,CAlLC;;IACDC,sCAAA,CAA2BC,IAA3B,CACC,IADD,EAECrB,wBAFD,EAGCC,KAHD,EAICC,OAJD;EAMA;EAED;AACD;AACA;;;;;WACC,iBAAQ;MACP,IAAI,KAAKC,SAAT,EAAoB;QACnB,MAAM,IAAIC,KAAJ,CAAU,+DAAV,CAAN;MACA,CAHM,CAKP;;;MACA,IAAMkB,SAAS,GAAG,KAAKnB,SAAL,KAAmB,KAArC;;MAEA,IAAI,CAACmB,SAAL,EAAgB;QACf,KAAKC,gBAAL,GAAwB,IAAxB,CADe,CAGf;QACA;;QACA,IAAI,CAAC,KAAKC,uBAAV,EAAmC;UAClC,KAAKC,sBAAL;QACA,CAPc,CAQf;QACA;;;QACA,IAAI,KAAKC,OAAT,EAAkB;UACjB,KAAKA,OAAL,CAAa,KAAKR,QAAL,EAAb;QACA;MACD;;MAED,IAAAb,iBAAA,EAAI,WAAJ,EAvBO,CAyBP;;MACA,KAAKF,SAAL,GAAiB,IAAjB,CA1BO,CA4BP;;MACA,KAAKwB,qBAAL,CAA2BC,KAA3B,GA7BO,CA+BP;;MACA,KAAKC,WAAL,GAAmBC,SAAnB,CAhCO,CAkCP;;MACA,KAAKC,kBAAL,GAA0BD,SAA1B,CAnCO,CAqCP;MACA;;MACA,IAAI,KAAKE,KAAT,EAAgB;QACf,IAAI,CAAC,IAAAC,qBAAA,EAAe,KAAKjC,wBAAL,EAAf,CAAL,EAAsD;UACrD,IAAAkC,qBAAA,EAAe,KAAKlC,wBAAL,EAAf;QACA;MACD,CA3CM,CA6CP;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;;;MACA,IAAImC,WAAW,GAAG,KAAKC,mBAAvB;MACA,KAAKA,mBAAL,GAA2BN,SAA3B,CAxDO,CA0DP;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;;MACA,KAAKO,eAAL,GAAuBP,SAAvB;MAEA,IAAMQ,0BAA0B,GAAG,KAAKC,4BAAL,EAAnC;;MACA,IAAID,0BAAJ,EAAgC;QAC/BH,WAAW,mCACPA,WADO,GAEPG,0BAFO,CAAX;MAIA;;MAED,KAAKhC,MAAL,CAAYkC,KAAZ;MACA,KAAKhC,MAAL,CAAYgC,KAAZ,GA9EO,CAgFP;MACA;;MACA,IAAI,KAAKtB,QAAL,GAAgBuB,wBAAhB,KAA6CX,SAAjD,EAA4D;QAC3D,IAAMW,wBAAwB,GAAG,KAAKC,mBAAL,CAAyBC,QAAzB,EAAjC;QACAR,WAAW,mCACPA,WADO;UAEVM,wBAAwB,EAAxBA;QAFU,EAAX;MAIA,CAND,MAMO;QACN;QACA;QACA;QACA,IAAMG,QAAQ,GAAG,KAAKF,mBAAL,CAAyBC,QAAzB,EAAjB;QACA,IAAME,SAAS,GAAG,KAAK3B,QAAL,GAAgBuB,wBAAlC;;QACA,IAAIG,QAAQ,KAAKC,SAAjB,EAA4B;UAC3B,IAAAxC,iBAAA,EAAI,2CAAJ,EAAiDwC,SAAjD,EAA4D,IAA5D,EAAkED,QAAlE,EAA4E,GAA5E,EAD2B,CAE3B;UACA;UACA;UACA;UACA;UACA;;UACA,OAAO,KAAKE,QAAL,EAAP;QACA;MACD,CAxGM,CA0GP;MACA;MACA;;;MACA,IAAI,KAAKtB,uBAAT,EAAkC;QACjC,IAAMuB,YAAY,GAAG,KAAKC,qBAAL,EAArB;QACA,IAAMC,qBAAqB,GAAG,KAAK/B,QAAL,GAAgB6B,YAAhB,IAAgC,CAA9D;;QACA,IAAIA,YAAY,KAAKE,qBAArB,EAA4C;UAC3C,OAAO,KAAKH,QAAL,EAAP;QACA;MACD,CAnHM,CAqHP;MACA;MACA;MACA;MACA;;;MACA,KAAKjC,wBAAL,CAA8B;QAAEC,MAAM,EAAEC,qBAAA,CAAcmC,OAAxB;QAAiCf,WAAW,EAAXA;MAAjC,CAA9B;IACA,C,CAED;;;;WAwBA,0BAAiB;MAChB,IAAI,CAAC,KAAKhC,SAAV,EAAqB;QACpB,MAAM,IAAIC,KAAJ,CAAU,2DAAV,CAAN;MACA;IACD,C,CAED;IACA;;;;;IAYA;AACD;AACA;AACA;AACA;IACC,+BAAsB+C,CAAtB,EAAyB;MACxB,IAAMC,mBAAmB,GAAG,KAAKC,MAAL,CAAYC,gBAAZ,CAA6BH,CAA7B,CAA5B;;MACA,IAAIC,mBAAmB,KAAKtB,SAA5B,EAAuC;QACtC;MACA;;MACD,OAAO,KAAKyB,yCAAL,KAAmDH,mBAA1D;IACA;IAED;AACD;AACA;AACA;;;;WACC,4BAAmBD,CAAnB,EAAsB;MACrB,IAAAK,WAAA,EAAK,4EAAL;MACA,KAAKC,qBAAL,CAA2BN,CAA3B;IACA;IAED;AACD;AACA;AACA;;;;WACC,+BAAsBA,CAAtB,EAAyB;MACxB,KAAKvC,cAAL;;MACA,KAAK8C,sBAAL,CAA4BP,CAA5B;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,sBAAaA,CAAb,EAAgBQ,YAAhB,EAA8B;MAC7B,KAAK/C,cAAL;;MACA,KAAKgD,aAAL,CAAmBT,CAAnB,EAAsBQ,YAAtB;IACA,C,CAED;IACA;;;;WACA,2BAAkBR,CAAlB,EAAqBQ,YAArB,EAAmC;MAClC,KAAKE,YAAL,CAAkBV,CAAlB,EAAqBQ,YAArB;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,kBAASG,QAAT,EAAiC;MAAA,IAAd5D,OAAc,uEAAJ,EAAI;MAChC,KAAKU,cAAL;MACA,OAAO,KAAKmD,SAAL,CAAeD,QAAf,EAAyB5D,OAAzB,CAAP;IACA"}