virtual-scroller 1.11.2 → 1.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +9 -9
- package/bundle/virtual-scroller-dom.js +1 -1
- package/bundle/virtual-scroller-dom.js.map +1 -1
- package/bundle/virtual-scroller-react.js +1 -1
- package/bundle/virtual-scroller-react.js.map +1 -1
- package/bundle/virtual-scroller.js +1 -1
- package/bundle/virtual-scroller.js.map +1 -1
- package/commonjs/DOM/VirtualScroller.js +13 -1
- package/commonjs/DOM/VirtualScroller.js.map +1 -1
- package/commonjs/ItemHeights.js +5 -5
- package/commonjs/ItemHeights.js.map +1 -1
- package/commonjs/VirtualScroller.js +21 -4
- package/commonjs/VirtualScroller.js.map +1 -1
- package/commonjs/VirtualScroller.layout.js +21 -21
- package/commonjs/VirtualScroller.layout.js.map +1 -1
- package/commonjs/react/VirtualScroller.js +5 -4
- package/commonjs/react/VirtualScroller.js.map +1 -1
- package/commonjs/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +7 -7
- package/commonjs/react/useOnItemHeightDidChange.js.map +1 -0
- package/dom/index.d.ts +1 -1
- package/index.d.ts +1 -1
- package/modules/DOM/VirtualScroller.js +13 -1
- package/modules/DOM/VirtualScroller.js.map +1 -1
- package/modules/ItemHeights.js +5 -5
- package/modules/ItemHeights.js.map +1 -1
- package/modules/VirtualScroller.js +15 -4
- package/modules/VirtualScroller.js.map +1 -1
- package/modules/VirtualScroller.layout.js +21 -21
- package/modules/VirtualScroller.layout.js.map +1 -1
- package/modules/react/VirtualScroller.js +5 -4
- package/modules/react/VirtualScroller.js.map +1 -1
- package/modules/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +6 -6
- package/modules/react/useOnItemHeightDidChange.js.map +1 -0
- package/package.json +1 -1
- package/source/DOM/VirtualScroller.js +11 -1
- package/source/ItemHeights.js +5 -5
- package/source/VirtualScroller.js +12 -3
- package/source/VirtualScroller.layout.js +21 -21
- package/source/react/VirtualScroller.js +5 -4
- package/source/react/{useOnItemHeightChange.js → useOnItemHeightDidChange.js} +5 -5
- package/commonjs/react/useOnItemHeightChange.js.map +0 -1
- package/modules/react/useOnItemHeightChange.js.map +0 -1
|
@@ -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
|
-
|
|
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":";;;;;;;;;AAAA;;AAEA;;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;IAEqBA,e;EACnB,yBAAYC,qBAAZ,EAAmCC,MAAnC,EAA0CC,UAA1C,EAAoE;IAAA;;IAAA,IAAdC,OAAc,uEAAJ,EAAI;;IAAA;;IAAA,gCAgC3D,UAACC,KAAD,EAAQC,SAAR,EAAsB;MAC7B,IACEJ,KADF,GAMIG,KANJ,CACEH,KADF;MAAA,IAEEK,mBAFF,GAMIF,KANJ,CAEEE,mBAFF;MAAA,IAGEC,kBAHF,GAMIH,KANJ,CAGEG,kBAHF;MAAA,IAIEC,iBAJF,GAMIJ,KANJ,CAIEI,iBAJF;MAAA,IAKEC,gBALF,GAMIL,KANJ,CAKEK,gBALF,CAD6B,CAS7B;MACA;MACA;MAEA;MACA;MACA;MACA;MACA;;MACA,IAAI,CAAC,KAAI,CAACC,KAAV,EAAiB;QACf,KAAI,CAACC,SAAL,CAAeC,KAAf,CAAqBC,UAArB,GAAkC,IAAAC,cAAA,EAAGN,iBAAH,CAAlC;QACA,KAAI,CAACG,SAAL,CAAeC,KAAf,CAAqBG,aAArB,GAAqC,IAAAD,cAAA,EAAGL,gBAAH,CAArC;MACD,CArB4B,CAuB7B;;;MACA,IAAMO,UAAU,GAAGX,SAAS,IAAIJ,KAAK,KAAKI,SAAS,CAACJ,KAAjC,IAA0CA,KAAK,CAACgB,MAAN,GAAe,CAA5E,CAxB6B,CAyB7B;;MACA,IAAID,UAAJ,EAAgB;QACd;QACA;QACA,IAAIE,EAAC,GAAGb,SAAS,CAACE,kBAAlB;;QACA,OAAOW,EAAC,IAAIb,SAAS,CAACC,mBAAtB,EAA2C;UACzC,IAAIY,EAAC,IAAIZ,mBAAL,IAA4BY,EAAC,IAAIX,kBAArC,EAAyD,CACvD;UACD,CAFD,MAEO;YACL,IAAAY,iBAAA,EAAI,oCAAJ,EAA0CD,EAA1C,EADK,CAEL;;YACA,KAAI,CAACE,WAAL,CAAiB,KAAI,CAACT,SAAL,CAAeU,UAAf,CAA0BH,EAAC,GAAGb,SAAS,CAACC,mBAAxC,CAAjB;UACD;;UACDY,EAAC;QACF;MACF,CAdD,MAcO;QACL,IAAAC,iBAAA,EAAI,qCAAJ;;QACA,OAAO,KAAI,CAACR,SAAL,CAAeW,UAAtB,EAAkC;UAChC,KAAI,CAACF,WAAL,CAAiB,KAAI,CAACT,SAAL,CAAeW,UAAhC;QACD;MACF,CA7C4B,CA+C7B;;;MACA,IAAIC,kBAAkB,GAAGP,UAAzB;MACA,IAAMQ,wBAAwB,GAAGD,kBAAkB,IAAI,KAAI,CAACZ,SAAL,CAAeW,UAAtE;MACA,IAAIJ,CAAC,GAAGZ,mBAAR;;MACA,OAAOY,CAAC,IAAIX,kBAAZ,EAAgC;QAC9B,IAAIS,UAAU,IAAIE,CAAC,IAAIb,SAAS,CAACC,mBAA7B,IAAoDY,CAAC,IAAIb,SAAS,CAACE,kBAAvE,EAA2F;UACzF;UACA;UACA,IAAIgB,kBAAJ,EAAwB;YACtBA,kBAAkB,GAAG,KAArB;UACD;QACF,CAND,MAMO;UACL,IAAME,IAAI,GAAG,KAAI,CAACvB,UAAL,CAAgBD,KAAK,CAACiB,CAAD,CAArB,CAAb;;UACA,IAAIK,kBAAJ,EAAwB;YACtB,IAAAJ,iBAAA,EAAI,qCAAJ,EAA2CD,CAA3C,EADsB,CAEtB;;YACA,KAAI,CAACP,SAAL,CAAee,YAAf,CAA4BD,IAA5B,EAAkCD,wBAAlC;UACD,CAJD,MAIO;YACL,IAAAL,iBAAA,EAAI,oCAAJ,EAA0CD,CAA1C,EADK,CAEL;;YACA,KAAI,CAACP,SAAL,CAAegB,WAAf,CAA2BF,IAA3B;UACD;QACF;;QACDP,CAAC;MACF;IACF,CAxGmE;;IAAA,mCA2GxD,YAAM;MAChB,IAAAU,WAAA,EAAK,gGAAL;;MACA,KAAI,CAACC,IAAL;IACD,CA9GmE;;IAAA,iCAiH1D,YAAM;MACd,IAAAD,WAAA,EAAK,8FAAL;;MACA,KAAI,CAACC,IAAL;IACD,CApHmE;;IAAA,8BAwH7D,YAAM;MACX,KAAI,CAACC,eAAL,CAAqBD,IAArB;IACD,CA1HmE;;IAAA,+BA8H5D,YAAM;MACZ,KAAI,CAACC,eAAL,CAAqBC,KAArB;IACD,CAhImE;;IAClE,KAAKpB,SAAL,GAAiBX,qBAAjB;IACA,KAAKE,UAAL,GAAkBA,UAAlB;;IAEA,IACE8B,OADF,GAII7B,OAJJ,CACE6B,OADF;IAAA,IAEEC,aAFF,GAII9B,OAJJ,CAEE8B,aAFF;IAAA,IAGKC,WAHL,4BAII/B,OAJJ;;IAMA,KAAK8B,aAAL,GAAqBA,aAArB;IACA,KAAKvB,KAAL,GAAa,KAAKC,SAAL,CAAewB,OAAf,KAA2B,OAAxC;IAEA,KAAKL,eAAL,GAAuB,IAAIM,2BAAJ,CACrB;MAAA,OAAM,KAAI,CAACzB,SAAX;IAAA,CADqB,EAErBV,MAFqB,kCAIhBiC,WAJgB;MAKnBG,MAAM,EAAE,KAAKA,MALM;MAMnB3B,KAAK,EAAE,KAAKA;IANO,GAAvB;IAUA,KAAKqB,KAAL,GAvBkE,CAyBlE;IACA;;IACA,IAAIC,OAAJ,EAAa;MACXA,OAAO;IACR;EACF;;;;WAoGD,qBAAYM,WAAZ,EAAyB;MACvB,KAAK3B,SAAL,CAAe4B,WAAf,CAA2BD,WAA3B;;MACA,IAAI,KAAKL,aAAT,EAAwB;QACtB,KAAKA,aAAL,CAAmBK,WAAnB;MACD;IACF;IAED;AACF;AACA;AACA;;;;WACE,4BAAmBpB,CAAnB,EAAsB;MACpB,IAAAU,WAAA,EAAK,4EAAL;MACA,KAAKY,qBAAL,CAA2BtB,CAA3B;IACD;;;WAED,+BAAsBA,CAAtB,EAAyB;MACvB,KAAKY,eAAL,CAAqBU,qBAArB,CAA2CtB,CAA3C;IACD;;;WAED,sBAAaA,CAAb,EAAgBuB,QAAhB,EAA0B;MACxB,KAAKX,eAAL,CAAqBY,YAArB,CAAkCxB,CAAlC,EAAqCuB,QAArC;IACD;IAED;AACF;AACA;AACA;;;;WACE,qBAAYE,QAAZ,EAAsBxC,OAAtB,EAA+B;MAC7B,IAAAyB,WAAA,EAAK,uDAAL;MACA,KAAKgB,QAAL,CAAcD,QAAd,EAAwBxC,OAAxB;IACD;;;WAED,kBAASwC,QAAT,EAAmBxC,OAAnB,EAA4B;MAC1B,KAAK2B,eAAL,CAAqBc,QAArB,CAA8BD,QAA9B,EAAwCxC,OAAxC;IACD;IAED;AACF;AACA;AACA;AACA"}
|
package/commonjs/ItemHeights.js
CHANGED
|
@@ -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
|
-
// `.
|
|
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 `
|
|
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 `.
|
|
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(`"
|
|
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(`"
|
|
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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"}
|
|
@@ -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 =
|
|
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
|
|
|
@@ -230,16 +236,27 @@ var VirtualScroller = /*#__PURE__*/function () {
|
|
|
230
236
|
return this.getListTopOffsetInsideScrollableContainer() + itemTopOffsetInList;
|
|
231
237
|
}
|
|
232
238
|
/**
|
|
233
|
-
*
|
|
234
|
-
*
|
|
239
|
+
* @deprecated
|
|
240
|
+
* `.onItemHeightChange()` has been renamed to `.onItemHeightDidChange()`.
|
|
235
241
|
*/
|
|
236
242
|
|
|
237
243
|
}, {
|
|
238
244
|
key: "onItemHeightChange",
|
|
239
245
|
value: function onItemHeightChange(i) {
|
|
246
|
+
(0, _debug.warn)('`.onItemHeightChange(i)` method was renamed to `.onItemHeightDidChange(i)`');
|
|
247
|
+
this.onItemHeightDidChange(i);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Forces a re-measure of an item's height.
|
|
251
|
+
* @param {number} i — Item index
|
|
252
|
+
*/
|
|
253
|
+
|
|
254
|
+
}, {
|
|
255
|
+
key: "onItemHeightDidChange",
|
|
256
|
+
value: function onItemHeightDidChange(i) {
|
|
240
257
|
this.hasToBeStarted();
|
|
241
258
|
|
|
242
|
-
this.
|
|
259
|
+
this._onItemHeightDidChange(i);
|
|
243
260
|
}
|
|
244
261
|
/**
|
|
245
262
|
* 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","_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\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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"}
|
|
@@ -122,7 +122,7 @@ function _default() {
|
|
|
122
122
|
// or an "Expand YouTube video" button, which would result
|
|
123
123
|
// in the actual height of the list item being different
|
|
124
124
|
// from what has been initially measured in `this.itemHeights[i]`,
|
|
125
|
-
// if the developer didn't call `.setItemState(i, newState)` and `.
|
|
125
|
+
// if the developer didn't call `.setItemState(i, newState)` and `.onItemHeightDidChange(i)`.
|
|
126
126
|
|
|
127
127
|
|
|
128
128
|
if (!validateWillBeHiddenItemHeightsAreAccurate.call(this, firstShownItemIndex, lastShownItemIndex)) {
|
|
@@ -187,9 +187,9 @@ function _default() {
|
|
|
187
187
|
// Instead of using a `this.previouslyCalculatedLayout` instance variable,
|
|
188
188
|
// this code could use `this.getState()` because it reflects what's currently on screen,
|
|
189
189
|
// but there's a single edge case when it could go out of sync —
|
|
190
|
-
// updating item heights externally via `.
|
|
190
|
+
// updating item heights externally via `.onItemHeightDidChange(i)`.
|
|
191
191
|
//
|
|
192
|
-
// If, for example, an item height was updated externally via `.
|
|
192
|
+
// If, for example, an item height was updated externally via `.onItemHeightDidChange(i)`
|
|
193
193
|
// then `this.getState().itemHeights` would get updated immediately but
|
|
194
194
|
// `this.getState().beforeItemsHeight` or `this.getState().afterItemsHeight`
|
|
195
195
|
// would still correspond to the previous item height, so those would be "stale".
|
|
@@ -281,7 +281,7 @@ function _default() {
|
|
|
281
281
|
* or an "Expand YouTube video" button, which would result
|
|
282
282
|
* in the actual height of the list item being different
|
|
283
283
|
* from what has been initially measured in `this.itemHeights[i]`,
|
|
284
|
-
* if the developer didn't call `.setItemState(i, newState)` and `.
|
|
284
|
+
* if the developer didn't call `.setItemState(i, newState)` and `.onItemHeightDidChange(i)`.
|
|
285
285
|
*/
|
|
286
286
|
|
|
287
287
|
|
|
@@ -295,26 +295,26 @@ function _default() {
|
|
|
295
295
|
// The item will be hidden. Re-measure its height.
|
|
296
296
|
// The rationale is that there could be a situation when an item's
|
|
297
297
|
// height has changed, and the developer has properly added an
|
|
298
|
-
// `.
|
|
298
|
+
// `.onItemHeightDidChange(i)` call to notify `VirtualScroller`
|
|
299
299
|
// about that change, but at the same time that wouldn't work.
|
|
300
300
|
// For example, suppose there's a list of several items on a page,
|
|
301
301
|
// and those items are in "minimized" state (having height 100px).
|
|
302
302
|
// Then, a user clicks an "Expand all items" button, and all items
|
|
303
303
|
// in the list are expanded (expanded item height is gonna be 700px).
|
|
304
|
-
// `VirtualScroller` demands that `.
|
|
304
|
+
// `VirtualScroller` demands that `.onItemHeightDidChange(i)` is called
|
|
305
305
|
// in such cases, and the developer has properly added the code to do that.
|
|
306
306
|
// So, if there were 10 "minimized" items visible on a page, then there
|
|
307
|
-
// will be 10 individual `.
|
|
308
|
-
// But, as the first `.
|
|
307
|
+
// will be 10 individual `.onItemHeightDidChange(i)` calls. No issues so far.
|
|
308
|
+
// But, as the first `.onItemHeightDidChange(i)` call executes, it immediately
|
|
309
309
|
// ("synchronously") triggers a re-layout, and that re-layout finds out
|
|
310
310
|
// that now, because the first item is big, it occupies most of the screen
|
|
311
311
|
// space, and only the first 3 items are visible on screen instead of 10,
|
|
312
312
|
// and so it leaves the first 3 items mounted and unmounts the rest 7.
|
|
313
313
|
// Then, after `VirtualScroller` has rerendered, the code returns to
|
|
314
|
-
// where it was executing, and calls `.
|
|
314
|
+
// where it was executing, and calls `.onItemHeightDidChange(i)` for the
|
|
315
315
|
// second item. It also triggers an immediate re-layout that finds out
|
|
316
316
|
// that only the first 2 items are visible on screen, and it unmounts
|
|
317
|
-
// the third one too. After that, it calls `.
|
|
317
|
+
// the third one too. After that, it calls `.onItemHeightDidChange(i)`
|
|
318
318
|
// for the third item, but that item is no longer rendered, so its height
|
|
319
319
|
// can't be measured, and the same's for all the rest of the original 10 items.
|
|
320
320
|
// So, even though the developer has written their code properly, the
|
|
@@ -334,7 +334,7 @@ function _default() {
|
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
isValid = false;
|
|
337
|
-
(0, _debug.warn)('Item index', i, 'is no longer visible and will be unmounted. Its height has changed from', previouslyMeasuredItemHeight, 'to', actualItemHeight, 'since it was last measured. This is not necessarily a bug, and could happen, for example, on screen width change, or when there\'re several `
|
|
337
|
+
(0, _debug.warn)('Item index', i, 'is no longer visible and will be unmounted. Its height has changed from', previouslyMeasuredItemHeight, 'to', actualItemHeight, 'since it was last measured. This is not necessarily a bug, and could happen, for example, on screen width change, or when there\'re several `onItemHeightDidChange(i)` calls issued at the same time, and the first one triggers a re-layout before the rest of them have had a chance to be executed.');
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
|
|
@@ -394,7 +394,7 @@ function _default() {
|
|
|
394
394
|
return listTopOffset;
|
|
395
395
|
};
|
|
396
396
|
|
|
397
|
-
this.
|
|
397
|
+
this._onItemHeightDidChange = function (i) {
|
|
398
398
|
(0, _debug["default"])('~ Re-measure item height ~');
|
|
399
399
|
(0, _debug["default"])('Item index', i);
|
|
400
400
|
|
|
@@ -406,37 +406,37 @@ function _default() {
|
|
|
406
406
|
|
|
407
407
|
if (!(i >= firstShownItemIndex && i <= lastShownItemIndex)) {
|
|
408
408
|
// There could be valid cases when an item is no longer rendered
|
|
409
|
-
// by the time `.
|
|
409
|
+
// by the time `.onItemHeightDidChange(i)` gets called.
|
|
410
410
|
// For example, suppose there's a list of several items on a page,
|
|
411
411
|
// and those items are in "minimized" state (having height 100px).
|
|
412
412
|
// Then, a user clicks an "Expand all items" button, and all items
|
|
413
413
|
// in the list are expanded (expanded item height is gonna be 700px).
|
|
414
|
-
// `VirtualScroller` demands that `.
|
|
414
|
+
// `VirtualScroller` demands that `.onItemHeightDidChange(i)` is called
|
|
415
415
|
// in such cases, and the developer has properly added the code to do that.
|
|
416
416
|
// So, if there were 10 "minimized" items visible on a page, then there
|
|
417
|
-
// will be 10 individual `.
|
|
418
|
-
// But, as the first `.
|
|
417
|
+
// will be 10 individual `.onItemHeightDidChange(i)` calls. No issues so far.
|
|
418
|
+
// But, as the first `.onItemHeightDidChange(i)` call executes, it immediately
|
|
419
419
|
// ("synchronously") triggers a re-layout, and that re-layout finds out
|
|
420
420
|
// that now, because the first item is big, it occupies most of the screen
|
|
421
421
|
// space, and only the first 3 items are visible on screen instead of 10,
|
|
422
422
|
// and so it leaves the first 3 items mounted and unmounts the rest 7.
|
|
423
423
|
// Then, after `VirtualScroller` has rerendered, the code returns to
|
|
424
|
-
// where it was executing, and calls `.
|
|
424
|
+
// where it was executing, and calls `.onItemHeightDidChange(i)` for the
|
|
425
425
|
// second item. It also triggers an immediate re-layout that finds out
|
|
426
426
|
// that only the first 2 items are visible on screen, and it unmounts
|
|
427
|
-
// the third one too. After that, it calls `.
|
|
427
|
+
// the third one too. After that, it calls `.onItemHeightDidChange(i)`
|
|
428
428
|
// for the third item, but that item is no longer rendered, so its height
|
|
429
429
|
// can't be measured, and the same's for all the rest of the original 10 items.
|
|
430
430
|
// So, even though the developer has written their code properly, there're
|
|
431
431
|
// still situations when the item could be no longer rendered by the time
|
|
432
|
-
// `.
|
|
433
|
-
return (0, _debug.warn)('The item is no longer rendered. This is not necessarily a bug, and could happen, for example, when when a developer calls `
|
|
432
|
+
// `.onItemHeightDidChange(i)` gets called.
|
|
433
|
+
return (0, _debug.warn)('The item is no longer rendered. This is not necessarily a bug, and could happen, for example, when when a developer calls `onItemHeightDidChange(i)` while looping through a batch of items.');
|
|
434
434
|
}
|
|
435
435
|
|
|
436
436
|
var previousHeight = itemHeights[i];
|
|
437
437
|
|
|
438
438
|
if (previousHeight === undefined) {
|
|
439
|
-
return (0, _debug.reportError)("\"
|
|
439
|
+
return (0, _debug.reportError)("\"onItemHeightDidChange()\" has been called for item ".concat(i, ", but that item hasn't been rendered before."));
|
|
440
440
|
}
|
|
441
441
|
|
|
442
442
|
var newHeight = remeasureItemHeight.call(_this, i);
|