virtual-scroller 1.11.3 → 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 (96) hide show
  1. package/README.md +6 -4
  2. package/bundle/virtual-scroller-dom.js +1 -1
  3. package/bundle/virtual-scroller-dom.js.map +1 -1
  4. package/bundle/virtual-scroller-react.js +1 -1
  5. package/bundle/virtual-scroller-react.js.map +1 -1
  6. package/bundle/virtual-scroller.js +1 -1
  7. package/bundle/virtual-scroller.js.map +1 -1
  8. package/commonjs/DOM/ItemsContainer.js +10 -3
  9. package/commonjs/DOM/ItemsContainer.js.map +1 -1
  10. package/commonjs/ItemNotRenderedError.js +64 -0
  11. package/commonjs/ItemNotRenderedError.js.map +1 -0
  12. package/commonjs/Layout.test.js +10 -0
  13. package/commonjs/Layout.test.js.map +1 -1
  14. package/commonjs/VirtualScroller.js +2 -1
  15. package/commonjs/VirtualScroller.js.map +1 -1
  16. package/commonjs/VirtualScroller.layout.js +61 -19
  17. package/commonjs/VirtualScroller.layout.js.map +1 -1
  18. package/commonjs/VirtualScroller.onRender.js +97 -45
  19. package/commonjs/VirtualScroller.onRender.js.map +1 -1
  20. package/commonjs/VirtualScroller.state.js +50 -18
  21. package/commonjs/VirtualScroller.state.js.map +1 -1
  22. package/commonjs/react/VirtualScroller.js +26 -42
  23. package/commonjs/react/VirtualScroller.js.map +1 -1
  24. package/commonjs/react/useItemKeys.js +11 -3
  25. package/commonjs/react/useItemKeys.js.map +1 -1
  26. package/commonjs/react/useOnChange.js +19 -0
  27. package/commonjs/react/useOnChange.js.map +1 -0
  28. package/commonjs/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +15 -14
  29. package/commonjs/react/useSetNewItemsOnItemsPropertyChange.js.map +1 -0
  30. package/commonjs/react/useState.js +162 -69
  31. package/commonjs/react/useState.js.map +1 -1
  32. package/commonjs/react/useStyle.js +3 -5
  33. package/commonjs/react/useStyle.js.map +1 -1
  34. package/commonjs/react/useUpdateItemKeysOnItemsChange.js +61 -0
  35. package/commonjs/react/useUpdateItemKeysOnItemsChange.js.map +1 -0
  36. package/commonjs/test/ItemsContainer.js +22 -1
  37. package/commonjs/test/ItemsContainer.js.map +1 -1
  38. package/commonjs/utility/debug.js +30 -6
  39. package/commonjs/utility/debug.js.map +1 -1
  40. package/index.cjs +2 -0
  41. package/index.d.ts +6 -0
  42. package/index.js +1 -0
  43. package/modules/DOM/ItemsContainer.js +8 -3
  44. package/modules/DOM/ItemsContainer.js.map +1 -1
  45. package/modules/ItemNotRenderedError.js +57 -0
  46. package/modules/ItemNotRenderedError.js.map +1 -0
  47. package/modules/Layout.test.js +10 -0
  48. package/modules/Layout.test.js.map +1 -1
  49. package/modules/VirtualScroller.js +2 -1
  50. package/modules/VirtualScroller.js.map +1 -1
  51. package/modules/VirtualScroller.layout.js +58 -19
  52. package/modules/VirtualScroller.layout.js.map +1 -1
  53. package/modules/VirtualScroller.onRender.js +98 -46
  54. package/modules/VirtualScroller.onRender.js.map +1 -1
  55. package/modules/VirtualScroller.state.js +50 -18
  56. package/modules/VirtualScroller.state.js.map +1 -1
  57. package/modules/react/VirtualScroller.js +26 -42
  58. package/modules/react/VirtualScroller.js.map +1 -1
  59. package/modules/react/useItemKeys.js +8 -3
  60. package/modules/react/useItemKeys.js.map +1 -1
  61. package/modules/react/useOnChange.js +11 -0
  62. package/modules/react/useOnChange.js.map +1 -0
  63. package/modules/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +11 -13
  64. package/modules/react/useSetNewItemsOnItemsPropertyChange.js.map +1 -0
  65. package/modules/react/useState.js +156 -73
  66. package/modules/react/useState.js.map +1 -1
  67. package/modules/react/useStyle.js +3 -5
  68. package/modules/react/useStyle.js.map +1 -1
  69. package/{commonjs/react/useHandleItemIndexesChange.js → modules/react/useUpdateItemKeysOnItemsChange.js} +18 -21
  70. package/modules/react/useUpdateItemKeysOnItemsChange.js.map +1 -0
  71. package/modules/test/ItemsContainer.js +20 -1
  72. package/modules/test/ItemsContainer.js.map +1 -1
  73. package/modules/utility/debug.js +31 -6
  74. package/modules/utility/debug.js.map +1 -1
  75. package/package.json +1 -1
  76. package/source/DOM/ItemsContainer.js +8 -3
  77. package/source/ItemNotRenderedError.js +16 -0
  78. package/source/Layout.test.js +9 -0
  79. package/source/VirtualScroller.js +2 -0
  80. package/source/VirtualScroller.layout.js +57 -18
  81. package/source/VirtualScroller.onRender.js +95 -42
  82. package/source/VirtualScroller.state.js +57 -20
  83. package/source/react/VirtualScroller.js +23 -35
  84. package/source/react/useItemKeys.js +9 -2
  85. package/source/react/useOnChange.js +11 -0
  86. package/source/react/{useHandleItemsPropertyChange.js → useSetNewItemsOnItemsPropertyChange.js} +11 -11
  87. package/source/react/useState.js +159 -71
  88. package/source/react/useStyle.js +2 -2
  89. package/source/react/{useHandleItemIndexesChange.js → useUpdateItemKeysOnItemsChange.js} +17 -9
  90. package/source/test/ItemsContainer.js +22 -1
  91. package/source/utility/debug.js +18 -4
  92. package/commonjs/react/useHandleItemIndexesChange.js.map +0 -1
  93. package/commonjs/react/useHandleItemsPropertyChange.js.map +0 -1
  94. package/modules/react/useHandleItemIndexesChange.js +0 -45
  95. package/modules/react/useHandleItemIndexesChange.js.map +0 -1
  96. package/modules/react/useHandleItemsPropertyChange.js.map +0 -1
package/index.d.ts CHANGED
@@ -99,3 +99,9 @@ export default class VirtualScroller<Element, Item, ItemState = NoItemState> {
99
99
  getInitialState(): State<Item, ItemState>;
100
100
  useState(options: UseStateOptions<Item, ItemState>): void;
101
101
  }
102
+
103
+ export class ItemNotRenderedError {
104
+ constructor(
105
+ message: string
106
+ );
107
+ }
package/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export { default } from './modules/VirtualScroller.js'
2
+ export { default as ItemNotRenderedError } from './modules/ItemNotRenderedError.js'
@@ -4,6 +4,8 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
4
4
 
5
5
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
6
6
 
7
+ import ItemNotRenderedError from '../ItemNotRenderedError.js';
8
+
7
9
  var ItemsContainer = /*#__PURE__*/function () {
8
10
  /**
9
11
  * Constructs a new "container" from an element.
@@ -21,9 +23,12 @@ var ItemsContainer = /*#__PURE__*/function () {
21
23
  var childNodes = this.getElement().childNodes;
22
24
 
23
25
  if (renderedElementIndex > childNodes.length - 1) {
24
- console.log('~ Items Container Contents ~');
25
- console.log(this.getElement().innerHTML);
26
- 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."));
26
+ // console.log('~ Items Container Contents ~')
27
+ // console.log(this.getElement().innerHTML)
28
+ throw new ItemNotRenderedError({
29
+ renderedElementIndex: renderedElementIndex,
30
+ renderedElementsCount: childNodes.length
31
+ });
27
32
  }
28
33
 
29
34
  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;;;;;;SAxDmBb,c"}
1
+ {"version":3,"file":"ItemsContainer.js","names":["ItemNotRenderedError","ItemsContainer","getElement","renderedElementIndex","childNodes","length","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,OAAOA,oBAAP,MAAiC,4BAAjC;;IAEqBC,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,IAAIL,oBAAJ,CAAyB;UAC9BG,oBAAoB,EAApBA,oBAD8B;UAE9BG,qBAAqB,EAAEF,UAAU,CAACC;QAFJ,CAAzB,CAAN;MAIA;;MACD,OAAOD,UAAU,CAACD,oBAAD,CAAjB;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,qCAA4BA,oBAA5B,EAAkD;MACjD,OAAO,KAAKI,0BAAL,CAAgCJ,oBAAhC,EAAsDK,qBAAtD,GAA8EC,GAA9E,GAAoF,KAAKP,UAAL,GAAkBM,qBAAlB,GAA0CC,GAArI;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,kCAAyBN,oBAAzB,EAA+C;MAC9C;MACA;MACA,OAAO,KAAKI,0BAAL,CAAgCJ,oBAAhC,EAAsDK,qBAAtD,GAA8EE,MAArF;IACA;IAED;AACD;AACA;AACA;;;;WACC,qBAAY;MACX;MACA;MACA,OAAO,KAAKR,UAAL,GAAkBM,qBAAlB,GAA0CE,MAAjD;IACA;IAED;AACD;AACA;;;;WACC,iBAAQ;MACP,OAAO,KAAKR,UAAL,GAAkBS,UAAzB,EAAqC;QACpC,KAAKT,UAAL,GAAkBU,WAAlB,CAA8B,KAAKV,UAAL,GAAkBS,UAAhD;MACA;IACD;;;;;;SA3DmBV,c"}
@@ -0,0 +1,57 @@
1
+ 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); }
2
+
3
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
4
+
5
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
6
+
7
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8
+
9
+ 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); }
10
+
11
+ 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); }; }
12
+
13
+ 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); }
14
+
15
+ function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
16
+
17
+ 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); }
18
+
19
+ 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); }
20
+
21
+ 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; } }
22
+
23
+ function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }
24
+
25
+ function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
26
+
27
+ function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
28
+
29
+ var ItemNotRenderedError = /*#__PURE__*/function (_Error) {
30
+ _inherits(ItemNotRenderedError, _Error);
31
+
32
+ var _super = _createSuper(ItemNotRenderedError);
33
+
34
+ function ItemNotRenderedError(_ref) {
35
+ var renderedElementIndex = _ref.renderedElementIndex,
36
+ renderedElementsCount = _ref.renderedElementsCount,
37
+ message = _ref.message;
38
+
39
+ _classCallCheck(this, ItemNotRenderedError);
40
+
41
+ return _super.call(this, message || getDefaultMessage({
42
+ renderedElementIndex: renderedElementIndex,
43
+ renderedElementsCount: renderedElementsCount
44
+ }));
45
+ }
46
+
47
+ return _createClass(ItemNotRenderedError);
48
+ }( /*#__PURE__*/_wrapNativeSuper(Error));
49
+
50
+ export { ItemNotRenderedError as default };
51
+
52
+ function getDefaultMessage(_ref2) {
53
+ var renderedElementIndex = _ref2.renderedElementIndex,
54
+ renderedElementsCount = _ref2.renderedElementsCount;
55
+ 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.");
56
+ }
57
+ //# 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;;SAA7BL,oB;;AAUrB,SAASI,iBAAT,QAGG;EAAA,IAFFH,oBAEE,SAFFA,oBAEE;EAAA,IADFC,qBACE,SADFA,qBACE;EACF,oCAA6BD,oBAA7B,4HAAmKC,qBAAnK;AACA"}
@@ -163,6 +163,12 @@ describe('Layout', function () {
163
163
  }
164
164
  });
165
165
  var shouldResetGridLayout;
166
+ var errors = [];
167
+
168
+ global.VirtualScrollerCatchError = function (error) {
169
+ return errors.push(error);
170
+ };
171
+
166
172
  layout.getLayoutUpdateForItemsDiff({
167
173
  firstShownItemIndex: 3,
168
174
  lastShownItemIndex: 5,
@@ -184,6 +190,10 @@ describe('Layout', function () {
184
190
  beforeItemsHeight: 0,
185
191
  afterItemsHeight: 5 * (ITEM_HEIGHT + VERTICAL_SPACING)
186
192
  });
193
+ global.VirtualScrollerCatchError = undefined;
194
+ errors.length.should.equal(2);
195
+ errors[0].message.should.equal('[virtual-scroller] ~ Prepended items count 5 is not divisible by Columns Count 4 ~');
196
+ errors[1].message.should.equal('[virtual-scroller] Layout reset required');
187
197
  shouldResetGridLayout.should.equal(true);
188
198
  });
189
199
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Layout.test.js","names":["Layout","Engine","describe","it","SCREEN_HEIGHT","scrollableContainer","width","height","ITEM_WIDTH","ITEM_HEIGHT","VERTICAL_SPACING","items","Array","fill","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":["Layout","Engine","describe","it","SCREEN_HEIGHT","scrollableContainer","width","height","ITEM_WIDTH","ITEM_HEIGHT","VERTICAL_SPACING","items","Array","fill","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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"}
@@ -82,8 +82,9 @@ var VirtualScroller = /*#__PURE__*/function () {
82
82
  var isRestart = this._isActive === false;
83
83
 
84
84
  if (!isRestart) {
85
- // If no custom state storage has been configured, use the default one.
85
+ this.waitingForRender = true; // If no custom state storage has been configured, use the default one.
86
86
  // Also sets the initial state.
87
+
87
88
  if (!this._usesCustomStateStorage) {
88
89
  this.useDefaultStateStorage();
89
90
  } // If `render()` function parameter was passed,
@@ -1 +1 @@
1
- {"version":3,"file":"VirtualScroller.js","names":["VirtualScrollerConstructor","hasTbodyStyles","addTbodyStyles","LAYOUT_REASON","log","warn","VirtualScroller","getItemsContainerElement","items","options","_isActive","Error","resize","stop","scroll","listTopOffsetWatcher","isStarted","cancelLayoutTimer","hasToBeStarted","onUpdateShownItemIndexes","reason","MANUAL","_onRender","getState","previousState","call","isRestart","_usesCustomStateStorage","useDefaultStateStorage","_render","listHeightMeasurement","reset","_isResizing","undefined","_isSettingNewItems","tbody","stateUpdate","_stoppedStateUpdate","verticalSpacing","verticalSpacingStateUpdate","measureItemHeightsAndSpacing","start","scrollableContainerWidth","scrollableContainer","getWidth","newWidth","prevWidth","onResize","columnsCount","getActualColumnsCount","columnsCountFromState","STARTED","i","itemTopOffsetInList","layout","getItemTopOffset","getListTopOffsetInsideScrollableContainer","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\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":"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"}
1
+ {"version":3,"file":"VirtualScroller.js","names":["VirtualScrollerConstructor","hasTbodyStyles","addTbodyStyles","LAYOUT_REASON","log","warn","VirtualScroller","getItemsContainerElement","items","options","_isActive","Error","resize","stop","scroll","listTopOffsetWatcher","isStarted","cancelLayoutTimer","hasToBeStarted","onUpdateShownItemIndexes","reason","MANUAL","_onRender","getState","previousState","call","isRestart","waitingForRender","_usesCustomStateStorage","useDefaultStateStorage","_render","listHeightMeasurement","reset","_isResizing","undefined","_isSettingNewItems","tbody","stateUpdate","_stoppedStateUpdate","verticalSpacing","verticalSpacingStateUpdate","measureItemHeightsAndSpacing","start","scrollableContainerWidth","scrollableContainer","getWidth","newWidth","prevWidth","onResize","columnsCount","getActualColumnsCount","columnsCountFromState","STARTED","i","itemTopOffsetInList","layout","getItemTopOffset","getListTopOffsetInsideScrollableContainer","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,OAAOA,0BAAP,MAAuC,kCAAvC;AACA,SAASC,cAAT,EAAyBC,cAAzB,QAA+C,gBAA/C;AACA,SAASC,aAAT,QAA8B,aAA9B;AACA,OAAOC,GAAP,IAAcC,IAAd,QAA0B,oBAA1B;;IAEqBC,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;MAEAN,GAAG,CAAC,UAAD,CAAH;;MAEA,KAAI,CAACQ,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,EAAEjB,aAAa,CAACkB;MAAxB,CAA9B;IACA,CA5KC;;IAAA,kCAgLS,YAAM;MAChB,KAAI,CAACC,SAAL,CAAe,KAAI,CAACC,QAAL,EAAf,EAAgC,KAAI,CAACC,aAArC;IACA,CAlLC;;IACDxB,0BAA0B,CAACyB,IAA3B,CACC,IADD,EAEClB,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,IAAMe,SAAS,GAAG,KAAKhB,SAAL,KAAmB,KAArC;;MAEA,IAAI,CAACgB,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,KAAKP,QAAL,EAAb;QACA;MACD;;MAEDnB,GAAG,CAAC,WAAD,CAAH,CAvBO,CAyBP;;MACA,KAAKM,SAAL,GAAiB,IAAjB,CA1BO,CA4BP;;MACA,KAAKqB,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,CAACnC,cAAc,CAAC,KAAKM,wBAAL,EAAD,CAAnB,EAAsD;UACrDL,cAAc,CAAC,KAAKK,wBAAL,EAAD,CAAd;QACA;MACD,CA3CM,CA6CP;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;;;MACA,IAAI8B,WAAW,GAAG,KAAKC,mBAAvB;MACA,KAAKA,mBAAL,GAA2BJ,SAA3B,CAxDO,CA0DP;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;;MACA,KAAKK,eAAL,GAAuBL,SAAvB;MAEA,IAAMM,0BAA0B,GAAG,KAAKC,4BAAL,EAAnC;;MACA,IAAID,0BAAJ,EAAgC;QAC/BH,WAAW,mCACPA,WADO,GAEPG,0BAFO,CAAX;MAIA;;MAED,KAAK5B,MAAL,CAAY8B,KAAZ;MACA,KAAK5B,MAAL,CAAY4B,KAAZ,GA9EO,CAgFP;MACA;;MACA,IAAI,KAAKnB,QAAL,GAAgBoB,wBAAhB,KAA6CT,SAAjD,EAA4D;QAC3D,IAAMS,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,KAAKxB,QAAL,GAAgBoB,wBAAlC;;QACA,IAAIG,QAAQ,KAAKC,SAAjB,EAA4B;UAC3B3C,GAAG,CAAC,2CAAD,EAA8C2C,SAA9C,EAAyD,IAAzD,EAA+DD,QAA/D,EAAyE,GAAzE,CAAH,CAD2B,CAE3B;UACA;UACA;UACA;UACA;UACA;;UACA,OAAO,KAAKE,QAAL,EAAP;QACA;MACD,CAxGM,CA0GP;MACA;MACA;;;MACA,IAAI,KAAKpB,uBAAT,EAAkC;QACjC,IAAMqB,YAAY,GAAG,KAAKC,qBAAL,EAArB;QACA,IAAMC,qBAAqB,GAAG,KAAK5B,QAAL,GAAgB0B,YAAhB,IAAgC,CAA9D;;QACA,IAAIA,YAAY,KAAKE,qBAArB,EAA4C;UAC3C,OAAO,KAAKH,QAAL,EAAP;QACA;MACD,CAnHM,CAqHP;MACA;MACA;MACA;MACA;;;MACA,KAAK7B,wBAAL,CAA8B;QAAEC,MAAM,EAAEjB,aAAa,CAACiD,OAAxB;QAAiCf,WAAW,EAAXA;MAAjC,CAA9B;IACA,C,CAED;;;;WAwBA,0BAAiB;MAChB,IAAI,CAAC,KAAK3B,SAAV,EAAqB;QACpB,MAAM,IAAIC,KAAJ,CAAU,2DAAV,CAAN;MACA;IACD,C,CAED;IACA;;;;;IAYA;AACD;AACA;AACA;AACA;IACC,+BAAsB0C,CAAtB,EAAyB;MACxB,IAAMC,mBAAmB,GAAG,KAAKC,MAAL,CAAYC,gBAAZ,CAA6BH,CAA7B,CAA5B;;MACA,IAAIC,mBAAmB,KAAKpB,SAA5B,EAAuC;QACtC;MACA;;MACD,OAAO,KAAKuB,yCAAL,KAAmDH,mBAA1D;IACA;IAED;AACD;AACA;AACA;;;;WACC,4BAAmBD,CAAnB,EAAsB;MACrBhD,IAAI,CAAC,4EAAD,CAAJ;MACA,KAAKqD,qBAAL,CAA2BL,CAA3B;IACA;IAED;AACD;AACA;AACA;;;;WACC,+BAAsBA,CAAtB,EAAyB;MACxB,KAAKnC,cAAL;;MACA,KAAKyC,sBAAL,CAA4BN,CAA5B;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,sBAAaA,CAAb,EAAgBO,YAAhB,EAA8B;MAC7B,KAAK1C,cAAL;;MACA,KAAK2C,aAAL,CAAmBR,CAAnB,EAAsBO,YAAtB;IACA,C,CAED;IACA;;;;WACA,2BAAkBP,CAAlB,EAAqBO,YAArB,EAAmC;MAClC,KAAKE,YAAL,CAAkBT,CAAlB,EAAqBO,YAArB;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,kBAASG,QAAT,EAAiC;MAAA,IAAdtD,OAAc,uEAAJ,EAAI;MAChC,KAAKS,cAAL;MACA,OAAO,KAAK8C,SAAL,CAAeD,QAAf,EAAyBtD,OAAzB,CAAP;IACA;;;;;;SAtPmBH,e"}
@@ -11,6 +11,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
11
11
  import { setTimeout, clearTimeout } from 'request-animation-frame-timeout';
12
12
  import log, { warn, isDebug, reportError } from './utility/debug.js';
13
13
  import { LAYOUT_REASON } from './Layout.js';
14
+ import ItemNotRenderedError from './ItemNotRenderedError.js';
14
15
  export default function () {
15
16
  var _this = this;
16
17
 
@@ -152,7 +153,10 @@ export default function () {
152
153
 
153
154
  this.onBeforeShowItems(this.getState().items, this.getState().itemHeights, firstShownItemIndex, lastShownItemIndex); // Set `this.firstNonMeasuredItemIndex`.
154
155
 
155
- this.firstNonMeasuredItemIndex = firstNonMeasuredItemIndex; // Set "previously calculated layout".
156
+ this.firstNonMeasuredItemIndex = firstNonMeasuredItemIndex; // if (firstNonMeasuredItemIndex !== undefined) {
157
+ // log('Non-measured item index that will be measured at next layout', firstNonMeasuredItemIndex)
158
+ // }
159
+ // Set "previously calculated layout".
156
160
  //
157
161
  // The "previously calculated layout" feature is not currently used.
158
162
  //
@@ -348,21 +352,23 @@ export default function () {
348
352
 
349
353
 
350
354
  function updatePreviouslyCalculatedLayoutOnItemHeightChange(i, previousHeight, newHeight) {
351
- if (this.previouslyCalculatedLayout) {
355
+ var prevLayout = this.previouslyCalculatedLayout;
356
+
357
+ if (prevLayout) {
352
358
  var heightDifference = newHeight - previousHeight;
353
359
 
354
- if (i < this.previouslyCalculatedLayout.firstShownItemIndex) {
355
- // Patch `this.previouslyCalculatedLayout`'s `.beforeItemsHeight`.
356
- this.previouslyCalculatedLayout.beforeItemsHeight += heightDifference;
357
- } else if (i > this.previouslyCalculatedLayout.lastShownItemIndex) {
358
- // Could patch `.afterItemsHeight` of `this.previouslyCalculatedLayout` here,
359
- // if `.afterItemsHeight` property existed in `this.previouslyCalculatedLayout`.
360
- if (this.previouslyCalculatedLayout.afterItemsHeight !== undefined) {
361
- this.previouslyCalculatedLayout.afterItemsHeight += heightDifference;
360
+ if (i < prevLayout.firstShownItemIndex) {
361
+ // Patch `prevLayout`'s `.beforeItemsHeight`.
362
+ prevLayout.beforeItemsHeight += heightDifference;
363
+ } else if (i > prevLayout.lastShownItemIndex) {
364
+ // Could patch `.afterItemsHeight` of `prevLayout` here,
365
+ // if `.afterItemsHeight` property existed in `prevLayout`.
366
+ if (prevLayout.afterItemsHeight !== undefined) {
367
+ prevLayout.afterItemsHeight += heightDifference;
362
368
  }
363
369
  } else {
364
- // Patch `this.previouslyCalculatedLayout`'s shown items height.
365
- this.previouslyCalculatedLayout.shownItemsHeight += newHeight - previousHeight;
370
+ // Patch `prevLayout`'s shown items height.
371
+ prevLayout.shownItemsHeight += newHeight - previousHeight;
366
372
  }
367
373
  }
368
374
  }
@@ -383,7 +389,7 @@ export default function () {
383
389
  };
384
390
 
385
391
  this._onItemHeightDidChange = function (i) {
386
- log('~ Re-measure item height ~');
392
+ log('~ On Item Height Did Change was called ~');
387
393
  log('Item index', i);
388
394
 
389
395
  var _this$getState2 = _this.getState(),
@@ -424,21 +430,54 @@ export default function () {
424
430
  var previousHeight = itemHeights[i];
425
431
 
426
432
  if (previousHeight === undefined) {
427
- return reportError("\"onItemHeightDidChange()\" has been called for item ".concat(i, ", but that item hasn't been rendered before."));
433
+ return reportError("\"onItemHeightDidChange()\" has been called for item index ".concat(i, " but the item hasn't been rendered before."));
434
+ }
435
+
436
+ log('~ Re-measure item height ~');
437
+ var newHeight;
438
+
439
+ try {
440
+ newHeight = remeasureItemHeight.call(_this, i);
441
+ } catch (error) {
442
+ // Successfully finishing an `onItemHeightDidChange(i)` call is not considered
443
+ // critical for `VirtualScroller`'s operation, so such errors could be ignored.
444
+ if (error instanceof ItemNotRenderedError) {
445
+ return reportError("\"onItemHeightDidChange()\" has been called for item index ".concat(i, " but the item is not currently rendered and can't be measured. The exact error was: ").concat(error.message));
446
+ }
428
447
  }
429
448
 
430
- var newHeight = remeasureItemHeight.call(_this, i);
431
449
  log('Previous height', previousHeight);
432
450
  log('New height', newHeight);
433
451
 
434
452
  if (previousHeight !== newHeight) {
435
- log('~ Item height has changed ~'); // Update or reset previously calculated layout.
453
+ log('~ Item height has changed. Should update layout. ~'); // Update or reset a previously calculated layout
454
+ // so that the "diff"s based on that layout in the future
455
+ // produce correct results.
436
456
 
437
457
  updatePreviouslyCalculatedLayoutOnItemHeightChange.call(_this, i, previousHeight, newHeight); // Recalculate layout.
458
+ //
459
+ // If the `VirtualScroller` is already waiting for a state update to be rendered,
460
+ // delay `onItemHeightDidChange(i)`'s re-layout until that state update is rendered.
461
+ // The reason is that React `<VirtualScroller/>`'s `onHeightDidChange()` is meant to
462
+ // be called inside `useLayoutEffect()` hook. Due to how React is implemented internally,
463
+ // that might happen in the middle of the currently pending `setState()` operation
464
+ // being applied, resulting in weird "race condition" bugs.
465
+ //
438
466
 
439
- _this.onUpdateShownItemIndexes({
440
- reason: LAYOUT_REASON.ITEM_HEIGHT_CHANGED
441
- }); // Schedule the item height update for after the new items have been rendered.
467
+ if (_this.waitingForRender) {
468
+ log('~ Another state update is already waiting to be rendered. Delay the layout update until then. ~');
469
+ _this.updateLayoutAfterRenderBecauseItemHeightChanged = true;
470
+ } else {
471
+ _this.onUpdateShownItemIndexes({
472
+ reason: LAYOUT_REASON.ITEM_HEIGHT_CHANGED
473
+ });
474
+ } // If there was a request for `setState()` with new `items`, then the changes
475
+ // to `currentState.itemHeights[]` made above in a `remeasureItemHeight()` call
476
+ // would be overwritten when that pending `setState()` call gets applied.
477
+ // To fix that, the updates to current `itemHeights[]` are noted in
478
+ // `this.itemHeightsThatChangedWhileNewItemsWereBeingRendered` variable.
479
+ // That variable is then checked when the `setState()` call with the new `items`
480
+ // has been updated.
442
481
 
443
482
 
444
483
  if (_this.newItemsWillBeRendered) {