virtual-scroller 1.16.3 → 1.16.4
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 +7 -0
- package/README.md +72 -36
- 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/ListTopOffsetWatcher.js +2 -4
- package/commonjs/DOM/ListTopOffsetWatcher.js.map +1 -1
- package/commonjs/Scroll.js +8 -11
- package/commonjs/Scroll.js.map +1 -1
- package/commonjs/VirtualScroller.constructor.js +7 -8
- package/commonjs/VirtualScroller.constructor.js.map +1 -1
- package/commonjs/VirtualScroller.js +10 -1
- package/commonjs/VirtualScroller.js.map +1 -1
- package/commonjs/VirtualScroller.layout.js +62 -20
- package/commonjs/VirtualScroller.layout.js.map +1 -1
- package/commonjs/VirtualScroller.onRender.js +25 -2
- package/commonjs/VirtualScroller.onRender.js.map +1 -1
- package/commonjs/VirtualScroller.state.js +39 -0
- package/commonjs/VirtualScroller.state.js.map +1 -1
- package/commonjs/react/useCreateVirtualScroller.js +1 -1
- package/commonjs/react/useCreateVirtualScroller.js.map +1 -1
- package/commonjs/test/VirtualScroller.js +2 -1
- package/commonjs/test/VirtualScroller.js.map +1 -1
- package/commonjs/utility/scheduleOnNextTick.js +25 -0
- package/commonjs/utility/scheduleOnNextTick.js.map +1 -0
- package/index.d.ts +4 -0
- package/modules/DOM/ListTopOffsetWatcher.js +1 -6
- package/modules/DOM/ListTopOffsetWatcher.js.map +1 -1
- package/modules/Scroll.js +8 -11
- package/modules/Scroll.js.map +1 -1
- package/modules/VirtualScroller.constructor.js +7 -8
- package/modules/VirtualScroller.constructor.js.map +1 -1
- package/modules/VirtualScroller.js +9 -1
- package/modules/VirtualScroller.js.map +1 -1
- package/modules/VirtualScroller.layout.js +61 -23
- package/modules/VirtualScroller.layout.js.map +1 -1
- package/modules/VirtualScroller.onRender.js +24 -2
- package/modules/VirtualScroller.onRender.js.map +1 -1
- package/modules/VirtualScroller.state.js +39 -1
- package/modules/VirtualScroller.state.js.map +1 -1
- package/modules/react/useCreateVirtualScroller.js +1 -1
- package/modules/react/useCreateVirtualScroller.js.map +1 -1
- package/modules/test/VirtualScroller.js +2 -1
- package/modules/test/VirtualScroller.js.map +1 -1
- package/modules/utility/scheduleOnNextTick.js +15 -0
- package/modules/utility/scheduleOnNextTick.js.map +1 -0
- package/package.json +1 -1
- package/source/DOM/ListTopOffsetWatcher.js +0 -6
- package/source/Scroll.js +7 -9
- package/source/VirtualScroller.constructor.js +7 -7
- package/source/VirtualScroller.js +8 -0
- package/source/VirtualScroller.layout.js +61 -25
- package/source/VirtualScroller.onRender.js +29 -3
- package/source/VirtualScroller.state.js +38 -0
- package/source/react/useCreateVirtualScroller.js +1 -1
- package/source/test/VirtualScroller.js +2 -1
- package/source/utility/scheduleOnNextTick.js +16 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VirtualScroller.constructor.js","names":["DOMEngine","Layout","LAYOUT_REASON","DEFAULT_ITEM_HEIGHT","ScrollableContainerResizeHandler","BeforeResize","Scroll","ListHeightMeasurement","ItemHeights","log","warn","createStateHelpers","createVerticalSpacingHelpers","createColumnsHelpers","createLayoutHelpers","createOnRenderHelpers","createScrollableContainerResizeHelpers","createItemsHelpers","VirtualScrollerConstructor","getItemsContainerElement","items","options","bypass","render","state","getInitialItemState","onStateChange","initialScrollPosition","onScrollPositionChange","scrollableContainer","measureItemsBatchSize","getColumnsCount","getItemId","estimatedItemHeight","getEstimatedVisibleItemRowsCount","getEstimatedInterItemVerticalSpacing","onItemInitialRender","onItemFirstRender","_useTimeoutInRenderLoop","_waitForScrollingToStop","engine","getEstimatedItemHeight","getScrollableContainer","element","Error","getState","setState","_bypass","_getItemId","isItemEqual","a","b","item","i","indexOf","length","call","createHelpers","waitForScrollingToStop","itemHeights","readItemHeightsFromState","beforeResize","initializeFromState","itemsContainer","createItemsContainer","isItemsContainerElementTableBody","tagName","isInBypassMode","createScrollableContainer","container","getItemHeight","setItemHeight","height","getAverageItemHeight","averageItemHeight","layout","getEstimatedVisibleItemRowsCountForInitialRender","getPrerenderMargin","getPrerenderMarginRatio","getVerticalSpacing","getVerticalSpacingBeforeResize","getColumnsCountBeforeResize","columnsCount","getItemHeightBeforeResize","getBeforeResizeItemsCount","getMaxVisibleAreaHeight","getHeight","getPreviouslyCalculatedLayout","previouslyCalculatedLayout","scrollableContainerResizeHandler","getWidth","listenForResize","listener","onResize","onResizeStart","_isResizing","onResizeStop","undefined","onNoChange","onUpdateShownItemIndexes","reason","VIEWPORT_SIZE_UNCHANGED","onHeightChange","VIEWPORT_HEIGHT_CHANGED","onWidthChange","prevWidth","newWidth","onContainerResize","scroll","onScroll","delayed","STOPPED_SCROLLING","SCROLL","isImmediateLayoutScheduled","Boolean","layoutTimer","hasNonRenderedItemsAtTheTop","firstShownItemIndex","hasNonRenderedItemsAtTheBottom","lastShownItemIndex","getItemsCount","getLatestLayoutVisibleArea","latestLayoutVisibleArea","getListTopOffset","getListTopOffsetInsideScrollableContainer","listHeightMeasurement","watchListTopOffset","listTopOffsetWatcher","onListTopOffsetChange","TOP_OFFSET_CHANGED"],"sources":["../source/VirtualScroller.constructor.js"],"sourcesContent":["import DOMEngine from './DOM/Engine.js'\r\n\r\nimport Layout, { LAYOUT_REASON } from './Layout.js'\r\nimport { DEFAULT_ITEM_HEIGHT } from './Layout.defaults.js'\r\nimport ScrollableContainerResizeHandler from './ScrollableContainerResizeHandler.js'\r\nimport BeforeResize from './BeforeResize.js'\r\nimport Scroll from './Scroll.js'\r\nimport ListHeightMeasurement from './ListHeightMeasurement.js'\r\nimport ItemHeights from './ItemHeights.js'\r\n\r\nimport log, { warn } from './utility/debug.js'\r\n\r\nimport createStateHelpers from './VirtualScroller.state.js'\r\nimport createVerticalSpacingHelpers from './VirtualScroller.verticalSpacing.js'\r\nimport createColumnsHelpers from './VirtualScroller.columns.js'\r\nimport createLayoutHelpers from './VirtualScroller.layout.js'\r\nimport createOnRenderHelpers from './VirtualScroller.onRender.js'\r\nimport createScrollableContainerResizeHelpers from './VirtualScroller.onContainerResize.js'\r\nimport createItemsHelpers from './VirtualScroller.items.js'\r\n\r\n/**\r\n * @param {function} getItemsContainerElement — Returns the container DOM `Element` (or `null`).\r\n * @param {any[]} items — The list of items.\r\n * @param {Object} [options] — See README.md.\r\n * @return {VirtualScroller}\r\n */\r\nexport default function VirtualScrollerConstructor(\r\n\tgetItemsContainerElement,\r\n\titems,\r\n\toptions = {}\r\n) {\r\n\tconst {\r\n\t\tbypass,\r\n\t\trender,\r\n\t\tstate,\r\n\t\tgetInitialItemState = () => {},\r\n\t\tonStateChange,\r\n\t\tinitialScrollPosition,\r\n\t\tonScrollPositionChange,\r\n\t\t// `scrollableContainer` option is deprecated.\r\n\t\t// Use `getScrollableContainer()` option instead.\r\n\t\tscrollableContainer,\r\n\t\tmeasureItemsBatchSize = 50,\r\n\t\tgetColumnsCount,\r\n\t\tgetItemId,\r\n\t\t// `estimatedItemHeight` is deprecated, use `getEstimatedItemHeight()` instead.\r\n\t\testimatedItemHeight,\r\n\t\tgetEstimatedVisibleItemRowsCount,\r\n\t\tgetEstimatedInterItemVerticalSpacing,\r\n\t\tonItemInitialRender,\r\n\t\t// `onItemFirstRender(i)` is deprecated, use `onItemInitialRender(item)` instead.\r\n\t\tonItemFirstRender,\r\n\t\t_useTimeoutInRenderLoop,\r\n\t\t_waitForScrollingToStop,\r\n\t\tengine\r\n\t} = options\r\n\r\n\tlet {\r\n\t\tgetEstimatedItemHeight,\r\n\t\tgetScrollableContainer\r\n\t} = options\r\n\r\n\tlog('~ Initialize ~')\r\n\r\n\t// Could support non-DOM rendering engines.\r\n\t// For example, React Native, `<canvas/>`, etc.\r\n\tthis.engine = engine || DOMEngine\r\n\r\n\tif (!getEstimatedItemHeight && typeof estimatedItemHeight === 'number') {\r\n\t\tgetEstimatedItemHeight = () => estimatedItemHeight\r\n\t}\r\n\r\n\t// `scrollableContainer` option is deprecated.\r\n\t// Use `getScrollableContainer()` option instead.\r\n\tif (!getScrollableContainer && scrollableContainer) {\r\n\t\tgetScrollableContainer = () => scrollableContainer\r\n\t}\r\n\r\n\t// Sometimes, when `new VirtualScroller()` \"core\" instance is created,\r\n\t// `getItemsContainerElement()` function might not yet be ready to return the \"container\" DOM Element.\r\n\t// For example, because the \"container\" DOM Element not rendered yet.\r\n\t// That's the reason why it's a getter function rather than a simple variable.\r\n\t//\r\n\t// As an example, in React `<VirtualScroller/>` component, a \"core\" `VirtualScroller`\r\n\t// instance is created in the React component's `constructor()`, and at that time\r\n\t// the \"container\" DOM Element has not been rendered yet.\r\n\t// The \"container\" DOM Element is only guaranteed to have been rendered\r\n\t// by the time `useEffect()` callback function is called, but at the same time `useEffect()`\r\n\t// is only executed on client side and is not executed on server side at all.\r\n\t// Still, the code has to work both in a web browser and on the server during the initial\r\n\t// \"server-side render\", i.e. it still must render the list during the initial\r\n\t// \"server-side render\". So `VirtualScroller` can't simply be skipped during server-side render.\r\n\t// It has to render something, and that something has to be correct.\r\n\t// This means that the \"core\" `VirtualScroller` should at least correctly compute the state\r\n\t// regardless of whether the `itemsContainerElement` exists or not.\r\n\t//\r\n\tthis.getItemsContainerElement = () => {\r\n\t\tconst element = getItemsContainerElement()\r\n\t\tif (element === null) {\r\n\t\t\tthrow new Error('[virtual-scroller] Items container element is `null`')\r\n\t\t}\r\n\t\treturn element\r\n\t}\r\n\r\n\t// if (prerenderMargin === undefined) {\r\n\t// \t// Renders items which are outside of the screen by this \"prerender margin\".\r\n\t// \t// Is the screen height by default: seems to be the optimal value\r\n\t// \t// for \"Page Up\" / \"Page Down\" navigation and optimized mouse wheel scrolling.\r\n\t// \tprerenderMargin = this.scrollableContainer ? this.scrollableContainer.getHeight() : 0\r\n\t// }\r\n\r\n\tif (options.getState || options.setState) {\r\n\t\tthrow new Error('[virtual-scroller] `getState`/`setState` options usage has changed in the new version. See the readme for more details.')\r\n\t}\r\n\r\n\tif (bypass) {\r\n\t\tlog('~ \"bypass\" mode ~')\r\n\t}\r\n\r\n\t// In `bypass` mode, `VirtualScroller` doesn't wait\r\n\t// for the user to scroll down to render all items:\r\n\t// instead, it renders all items right away, as if\r\n\t// the list is rendered without using `VirtualScroller`.\r\n\t// It was added just to measure how much is the\r\n\t// performance difference between using a `VirtualScroller`\r\n\t// and not using a `VirtualScroller`.\r\n\t// It turned out that unmounting large React component trees\r\n\t// is a very long process, so `VirtualScroller` does seem to\r\n\t// make sense when used in a React application.\r\n\tthis._bypass = bypass\r\n\t// this.bypassBatchSize = bypassBatchSize || 10\r\n\r\n\t// Using `setTimeout()` in render loop is a workaround\r\n\t// for avoiding a React error message:\r\n\t// \"Maximum update depth exceeded.\r\n\t// This can happen when a component repeatedly calls\r\n\t// `.setState()` inside `componentWillUpdate()` or `componentDidUpdate()`.\r\n\t// React limits the number of nested updates to prevent infinite loops.\"\r\n\tthis._useTimeoutInRenderLoop = _useTimeoutInRenderLoop\r\n\r\n\t// `_getItemId()` function is used in `_getItemIndexByItemOrIndex()` function.\r\n\tthis._getItemId = getItemId\r\n\r\n\tif (getItemId) {\r\n\t\tthis.isItemEqual = (a, b) => getItemId(a) === getItemId(b)\r\n\t} else {\r\n\t\tthis.isItemEqual = (a, b) => a === b\r\n\t}\r\n\r\n\tif (onItemInitialRender) {\r\n\t\tthis.onItemInitialRender = onItemInitialRender\r\n\t}\r\n\t// `onItemFirstRender(i)` is deprecated, use `onItemInitialRender(item)` instead.\r\n\telse if (onItemFirstRender) {\r\n\t\tthis.onItemInitialRender = (item) => {\r\n\t\t\twarn('`onItemFirstRender(i)` is deprecated, use `onItemInitialRender(item)` instead.')\r\n\t\t\tconst { items } = this.getState()\r\n\t\t\tconst i = items.indexOf(item)\r\n\t\t\t// The `item` could also be non-found due to the inconsistency bug:\r\n\t\t\t// The reason is that `i` can be non-consistent with the `items`\r\n\t\t\t// passed to `<VirtualScroller/>` in React due to `updateState()` not being\r\n\t\t\t// instanteneous: when new `items` are passed to `<VirtualScroller/>`,\r\n\t\t\t// `VirtualScroller.updateState({ items })` is called, and if `onItemFirstRender(i)`\r\n\t\t\t// is called after the aforementioned `updateState()` is called but before it finishes,\r\n\t\t\t// `i` would point to an index in \"previous\" `items` while the application\r\n\t\t\t// would assume that `i` points to an index in the \"new\" `items`,\r\n\t\t\t// resulting in an incorrect item being assumed by the application\r\n\t\t\t// or even in an \"array index out of bounds\" error.\r\n\t\t\tif (i >= 0) {\r\n\t\t\t\tonItemFirstRender(i)\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// If initial `state` is passed then use `items` from `state`\r\n\t// instead of the `items` argument.\r\n\tif (state) {\r\n\t\titems = state.items\r\n\t}\r\n\r\n\tlog('Items count', items.length)\r\n\tif (getEstimatedItemHeight) {\r\n\t\tlog('Estimated item height', getEstimatedItemHeight())\r\n\t}\r\n\r\n\tcreateStateHelpers.call(this, { state, getInitialItemState, onStateChange, render, items })\r\n\r\n\tcreateVerticalSpacingHelpers.call(this, { getEstimatedInterItemVerticalSpacing })\r\n\tcreateColumnsHelpers.call(this, { getColumnsCount })\r\n\r\n\tcreateLayoutHelpers.call(this)\r\n\tcreateOnRenderHelpers.call(this)\r\n\tcreateScrollableContainerResizeHelpers.call(this)\r\n\tcreateItemsHelpers.call(this)\r\n\r\n\tcreateHelpers.call(this, {\r\n\t\tgetScrollableContainer,\r\n\t\tgetEstimatedItemHeight,\r\n\t\tgetEstimatedVisibleItemRowsCount,\r\n\t\tmeasureItemsBatchSize,\r\n\t\tinitialScrollPosition,\r\n\t\tonScrollPositionChange,\r\n\t\twaitForScrollingToStop: _waitForScrollingToStop\r\n\t})\r\n\r\n\tif (state) {\r\n\t\t// Initialize `ItemHeights` from previously measured `state.itemHeights`.\r\n\t\tthis.itemHeights.readItemHeightsFromState(state)\r\n\r\n\t\t// Initialize some `BeforeResize` internal flags from a previously saved state.\r\n\t\tthis.beforeResize.initializeFromState(state)\r\n\t}\r\n}\r\n\r\nfunction createHelpers({\r\n\tgetScrollableContainer,\r\n\tgetEstimatedItemHeight,\r\n\tgetEstimatedVisibleItemRowsCount,\r\n\tmeasureItemsBatchSize,\r\n\tinitialScrollPosition,\r\n\tonScrollPositionChange,\r\n\twaitForScrollingToStop\r\n}) {\r\n\tthis.itemsContainer = this.engine.createItemsContainer(\r\n\t\tthis.getItemsContainerElement\r\n\t)\r\n\r\n\tthis.isItemsContainerElementTableBody = () => {\r\n\t\treturn this.engine === DOMEngine &&\r\n\t\t\tthis.getItemsContainerElement().tagName === 'TBODY'\r\n\t}\r\n\r\n\tthis.isInBypassMode = () => this._bypass\r\n\r\n\tthis.scrollableContainer = this.engine.createScrollableContainer(\r\n\t\tgetScrollableContainer,\r\n\t\tthis.getItemsContainerElement\r\n\t)\r\n\r\n\t// Create `ItemHeights` instance.\r\n\tthis.itemHeights = new ItemHeights({\r\n\t\tcontainer: this.itemsContainer,\r\n\t\tgetItemHeight: (i) => this.getState().itemHeights[i],\r\n\t\tsetItemHeight: (i, height) => this.getState().itemHeights[i] = height\r\n\t})\r\n\r\n\tthis.getAverageItemHeight = () => {\r\n\t\tconst averageItemHeight = this.itemHeights.getAverageItemHeight()\r\n\t\tif (typeof averageItemHeight === 'number') {\r\n\t\t\treturn averageItemHeight\r\n\t\t}\r\n\t\treturn this.getEstimatedItemHeight()\r\n\t}\r\n\r\n\tthis.getEstimatedItemHeight = () => {\r\n\t\tif (getEstimatedItemHeight) {\r\n\t\t\tconst estimatedItemHeight = getEstimatedItemHeight()\r\n\t\t\tif (typeof estimatedItemHeight === 'number') {\r\n\t\t\t\treturn estimatedItemHeight\r\n\t\t\t}\r\n\t\t\tthrow new Error('[virtual-scroller] `getEstimatedItemHeight()` must return a number')\r\n\t\t}\r\n\t\t// `DEFAULT_ITEM_HEIGHT` will be used in server-side render\r\n\t\t// unless `getEstimatedItemHeight()` parameter is specified.\r\n\t\treturn DEFAULT_ITEM_HEIGHT\r\n\t}\r\n\r\n\tthis.layout = new Layout({\r\n\t\tisInBypassMode: this.isInBypassMode,\r\n\t\tgetEstimatedVisibleItemRowsCountForInitialRender: getEstimatedVisibleItemRowsCount,\r\n\t\tmeasureItemsBatchSize,\r\n\t\tgetPrerenderMargin: () => this.getPrerenderMargin(),\r\n\t\tgetPrerenderMarginRatio: () => this.getPrerenderMarginRatio(),\r\n\t\tgetVerticalSpacing: () => this.getVerticalSpacing(),\r\n\t\tgetVerticalSpacingBeforeResize: () => this.getVerticalSpacingBeforeResize(),\r\n\t\tgetColumnsCount: () => this.getColumnsCount(),\r\n\t\tgetColumnsCountBeforeResize: () => this.getState().beforeResize && this.getState().beforeResize.columnsCount,\r\n\t\tgetItemHeight: (i) => this.getState().itemHeights[i],\r\n\t\tgetItemHeightBeforeResize: (i) => this.getState().beforeResize && this.getState().beforeResize.itemHeights[i],\r\n\t\tgetBeforeResizeItemsCount: () => this.getState().beforeResize ? this.getState().beforeResize.itemHeights.length : 0,\r\n\t\tgetAverageItemHeight: () => this.getAverageItemHeight(),\r\n\t\t// `this.scrollableContainer` is gonna be `undefined` during server-side rendering.\r\n\t\t// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/30\r\n\t\tgetMaxVisibleAreaHeight: () => this.scrollableContainer && this.scrollableContainer.getHeight(),\r\n\t\t//\r\n\t\t// The \"previously calculated layout\" feature is not currently used.\r\n\t\t//\r\n\t\t// The current layout snapshot could be stored as a \"previously calculated layout\" variable\r\n\t\t// so that it could theoretically be used when calculating new layout incrementally\r\n\t\t// rather than from scratch, which would be an optimization.\r\n\t\t//\r\n\t\tgetPreviouslyCalculatedLayout: () => this.previouslyCalculatedLayout\r\n\t})\r\n\r\n\tthis.scrollableContainerResizeHandler = new ScrollableContainerResizeHandler({\r\n\t\tisInBypassMode: this.isInBypassMode,\r\n\t\tgetWidth: () => this.scrollableContainer.getWidth(),\r\n\t\tgetHeight: () => this.scrollableContainer.getHeight(),\r\n\t\tlistenForResize: (listener) => this.scrollableContainer.onResize(listener),\r\n\t\tonResizeStart: () => {\r\n\t\t\tlog('~ Scrollable container resize started ~')\r\n\t\t\tthis._isResizing = true\r\n\t\t},\r\n\t\tonResizeStop: () => {\r\n\t\t\tlog('~ Scrollable container resize finished ~')\r\n\t\t\tthis._isResizing = undefined\r\n\t\t},\r\n\t\tonNoChange: () => {\r\n\t\t\t// There might have been some missed `this.onUpdateShownItemIndexes()` calls\r\n\t\t\t// due to setting `this._isResizing` flag to `true` during the resize.\r\n\t\t\t// So, update shown item indexes just in case.\r\n\t\t\tthis.onUpdateShownItemIndexes({\r\n\t\t\t\treason: LAYOUT_REASON.VIEWPORT_SIZE_UNCHANGED\r\n\t\t\t})\r\n\t\t},\r\n\t\tonHeightChange: () => this.onUpdateShownItemIndexes({\r\n\t\t\treason: LAYOUT_REASON.VIEWPORT_HEIGHT_CHANGED\r\n\t\t}),\r\n\t\tonWidthChange: (prevWidth, newWidth) => {\r\n\t\t\tlog('~ Scrollable container width changed from', prevWidth, 'to', newWidth, '~')\r\n\t\t\tthis.onContainerResize()\r\n\t\t}\r\n\t})\r\n\r\n\tthis.scroll = new Scroll({\r\n\t\tisInBypassMode: this.isInBypassMode,\r\n\t\tscrollableContainer: this.scrollableContainer,\r\n\t\titemsContainer: this.itemsContainer,\r\n\t\twaitForScrollingToStop,\r\n\t\tonScroll: ({ delayed } = {}) => {\r\n\t\t\tthis.onUpdateShownItemIndexes({\r\n\t\t\t\treason: delayed ? LAYOUT_REASON.STOPPED_SCROLLING : LAYOUT_REASON.SCROLL\r\n\t\t\t})\r\n\t\t},\r\n\t\tinitialScrollPosition,\r\n\t\tonScrollPositionChange,\r\n\t\tisImmediateLayoutScheduled: () => Boolean(this.layoutTimer),\r\n\t\thasNonRenderedItemsAtTheTop: () => this.getState().firstShownItemIndex > 0,\r\n\t\thasNonRenderedItemsAtTheBottom: () => this.getState().lastShownItemIndex < this.getItemsCount() - 1,\r\n\t\tgetLatestLayoutVisibleArea: () => this.latestLayoutVisibleArea,\r\n\t\tgetListTopOffset: this.getListTopOffsetInsideScrollableContainer,\r\n\t\tgetPrerenderMargin: () => this.getPrerenderMargin()\r\n\t})\r\n\r\n\tthis.listHeightMeasurement = new ListHeightMeasurement({\r\n\t\titemsContainer: this.itemsContainer,\r\n\t\tgetListTopOffset: this.getListTopOffsetInsideScrollableContainer\r\n\t})\r\n\r\n\tif (this.engine.watchListTopOffset) {\r\n\t\tthis.listTopOffsetWatcher = this.engine.watchListTopOffset({\r\n\t\t\tgetListTopOffset: this.getListTopOffsetInsideScrollableContainer,\r\n\t\t\tonListTopOffsetChange: ({ reason }) => this.onUpdateShownItemIndexes({\r\n\t\t\t\treason: LAYOUT_REASON.TOP_OFFSET_CHANGED\r\n\t\t\t})\r\n\t\t})\r\n\t}\r\n\r\n\tthis.beforeResize = new BeforeResize({\r\n\t\tgetState: this.getState,\r\n\t\tgetVerticalSpacing: this.getVerticalSpacing,\r\n\t\tgetColumnsCount: this.getColumnsCount\r\n\t})\r\n}"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VirtualScroller.constructor.js","names":["DOMEngine","Layout","LAYOUT_REASON","DEFAULT_ITEM_HEIGHT","ScrollableContainerResizeHandler","BeforeResize","Scroll","ListHeightMeasurement","ItemHeights","log","warn","createStateHelpers","createVerticalSpacingHelpers","createColumnsHelpers","createLayoutHelpers","createOnRenderHelpers","createScrollableContainerResizeHelpers","createItemsHelpers","VirtualScrollerConstructor","getItemsContainerElement","items","options","bypass","render","state","getInitialItemState","onStateChange","initialScrollPosition","onScrollPositionChange","scrollableContainer","measureItemsBatchSize","getColumnsCount","getItemId","estimatedItemHeight","getEstimatedVisibleItemRowsCount","getEstimatedInterItemVerticalSpacing","onItemInitialRender","onItemFirstRender","delayRecursiveRenderUntilNextTick","_delayUnnecessaryRerenderUntilStopsScrolling","engine","getEstimatedItemHeight","getScrollableContainer","element","Error","getState","setState","_bypass","_delayRecursiveRenderUntilNextTick","_getItemId","isItemEqual","a","b","item","i","indexOf","length","call","createHelpers","delayUnnecessaryRerenderUntilStopsScrolling","itemHeights","readItemHeightsFromState","beforeResize","initializeFromState","itemsContainer","createItemsContainer","isItemsContainerElementTableBody","tagName","isInBypassMode","createScrollableContainer","container","getItemHeight","setItemHeight","height","getAverageItemHeight","averageItemHeight","layout","getEstimatedVisibleItemRowsCountForInitialRender","getPrerenderMargin","getPrerenderMarginRatio","getVerticalSpacing","getVerticalSpacingBeforeResize","getColumnsCountBeforeResize","columnsCount","getItemHeightBeforeResize","getBeforeResizeItemsCount","getMaxVisibleAreaHeight","getHeight","getPreviouslyCalculatedLayout","previouslyCalculatedLayout","scrollableContainerResizeHandler","getWidth","listenForResize","listener","onResize","onResizeStart","_isResizing","onResizeStop","undefined","onNoChange","onUpdateShownItemIndexes","reason","VIEWPORT_SIZE_UNCHANGED","onHeightChange","VIEWPORT_HEIGHT_CHANGED","onWidthChange","prevWidth","newWidth","onContainerResize","scroll","onScroll","delayed","STOPPED_SCROLLING","SCROLL","isImmediateLayoutScheduled","Boolean","layoutTimer","hasNonRenderedItemsAtTheTop","firstShownItemIndex","hasNonRenderedItemsAtTheBottom","lastShownItemIndex","getItemsCount","getLatestLayoutVisibleArea","latestLayoutVisibleArea","getListTopOffset","getListTopOffsetInsideScrollableContainer","listHeightMeasurement","watchListTopOffset","listTopOffsetWatcher","onListTopOffsetChange","TOP_OFFSET_CHANGED"],"sources":["../source/VirtualScroller.constructor.js"],"sourcesContent":["import DOMEngine from './DOM/Engine.js'\r\n\r\nimport Layout, { LAYOUT_REASON } from './Layout.js'\r\nimport { DEFAULT_ITEM_HEIGHT } from './Layout.defaults.js'\r\nimport ScrollableContainerResizeHandler from './ScrollableContainerResizeHandler.js'\r\nimport BeforeResize from './BeforeResize.js'\r\nimport Scroll from './Scroll.js'\r\nimport ListHeightMeasurement from './ListHeightMeasurement.js'\r\nimport ItemHeights from './ItemHeights.js'\r\n\r\nimport log, { warn } from './utility/debug.js'\r\n\r\nimport createStateHelpers from './VirtualScroller.state.js'\r\nimport createVerticalSpacingHelpers from './VirtualScroller.verticalSpacing.js'\r\nimport createColumnsHelpers from './VirtualScroller.columns.js'\r\nimport createLayoutHelpers from './VirtualScroller.layout.js'\r\nimport createOnRenderHelpers from './VirtualScroller.onRender.js'\r\nimport createScrollableContainerResizeHelpers from './VirtualScroller.onContainerResize.js'\r\nimport createItemsHelpers from './VirtualScroller.items.js'\r\n\r\n/**\r\n * @param {function} getItemsContainerElement — Returns the container DOM `Element` (or `null`).\r\n * @param {any[]} items — The list of items.\r\n * @param {Object} [options] — See README.md.\r\n * @return {VirtualScroller}\r\n */\r\nexport default function VirtualScrollerConstructor(\r\n\tgetItemsContainerElement,\r\n\titems,\r\n\toptions = {}\r\n) {\r\n\tconst {\r\n\t\tbypass,\r\n\t\trender,\r\n\t\tstate,\r\n\t\tgetInitialItemState = () => {},\r\n\t\tonStateChange,\r\n\t\tinitialScrollPosition,\r\n\t\tonScrollPositionChange,\r\n\t\t// `scrollableContainer` option is deprecated.\r\n\t\t// Use `getScrollableContainer()` option instead.\r\n\t\tscrollableContainer,\r\n\t\tmeasureItemsBatchSize = 50,\r\n\t\tgetColumnsCount,\r\n\t\tgetItemId,\r\n\t\t// `estimatedItemHeight` is deprecated, use `getEstimatedItemHeight()` instead.\r\n\t\testimatedItemHeight,\r\n\t\tgetEstimatedVisibleItemRowsCount,\r\n\t\tgetEstimatedInterItemVerticalSpacing,\r\n\t\tonItemInitialRender,\r\n\t\t// `onItemFirstRender(i)` is deprecated, use `onItemInitialRender(item)` instead.\r\n\t\tonItemFirstRender,\r\n\t\tdelayRecursiveRenderUntilNextTick,\r\n\t\t_delayUnnecessaryRerenderUntilStopsScrolling,\r\n\t\tengine\r\n\t} = options\r\n\r\n\tlet {\r\n\t\tgetEstimatedItemHeight,\r\n\t\tgetScrollableContainer\r\n\t} = options\r\n\r\n\tlog('~ Initialize ~')\r\n\r\n\t// Could support non-DOM rendering engines.\r\n\t// For example, React Native, `<canvas/>`, etc.\r\n\tthis.engine = engine || DOMEngine\r\n\r\n\tif (!getEstimatedItemHeight && typeof estimatedItemHeight === 'number') {\r\n\t\tgetEstimatedItemHeight = () => estimatedItemHeight\r\n\t}\r\n\r\n\t// `scrollableContainer` option is deprecated.\r\n\t// Use `getScrollableContainer()` option instead.\r\n\tif (!getScrollableContainer && scrollableContainer) {\r\n\t\tgetScrollableContainer = () => scrollableContainer\r\n\t}\r\n\r\n\t// Sometimes, when `new VirtualScroller()` \"core\" instance is created,\r\n\t// `getItemsContainerElement()` function might not yet be ready to return the \"container\" DOM Element.\r\n\t// For example, because the \"container\" DOM Element not rendered yet.\r\n\t// That's the reason why it's a getter function rather than a simple variable.\r\n\t//\r\n\t// As an example, in React `<VirtualScroller/>` component, a \"core\" `VirtualScroller`\r\n\t// instance is created in the React component's `constructor()`, and at that time\r\n\t// the \"container\" DOM Element has not been rendered yet.\r\n\t// The \"container\" DOM Element is only guaranteed to have been rendered\r\n\t// by the time `useEffect()` callback function is called, but at the same time `useEffect()`\r\n\t// is only executed on client side and is not executed on server side at all.\r\n\t// Still, the code has to work both in a web browser and on the server during the initial\r\n\t// \"server-side render\", i.e. it still must render the list during the initial\r\n\t// \"server-side render\". So `VirtualScroller` can't simply be skipped during server-side render.\r\n\t// It has to render something, and that something has to be correct.\r\n\t// This means that the \"core\" `VirtualScroller` should at least correctly compute the state\r\n\t// regardless of whether the `itemsContainerElement` exists or not.\r\n\t//\r\n\tthis.getItemsContainerElement = () => {\r\n\t\tconst element = getItemsContainerElement()\r\n\t\tif (element === null) {\r\n\t\t\tthrow new Error('[virtual-scroller] Items container element is `null`')\r\n\t\t}\r\n\t\treturn element\r\n\t}\r\n\r\n\t// if (prerenderMargin === undefined) {\r\n\t// \t// Renders items which are outside of the screen by this \"prerender margin\".\r\n\t// \t// Is the screen height by default: seems to be the optimal value\r\n\t// \t// for \"Page Up\" / \"Page Down\" navigation and optimized mouse wheel scrolling.\r\n\t// \tprerenderMargin = this.scrollableContainer ? this.scrollableContainer.getHeight() : 0\r\n\t// }\r\n\r\n\tif (options.getState || options.setState) {\r\n\t\tthrow new Error('[virtual-scroller] `getState`/`setState` options usage has changed in the new version. See the readme for more details.')\r\n\t}\r\n\r\n\tif (bypass) {\r\n\t\tlog('~ \"bypass\" mode ~')\r\n\t}\r\n\r\n\t// In `bypass` mode, `VirtualScroller` doesn't wait\r\n\t// for the user to scroll down to render all items:\r\n\t// instead, it renders all items right away, as if\r\n\t// the list is rendered without using `VirtualScroller`.\r\n\t// It was added just to measure how much is the\r\n\t// performance difference between using a `VirtualScroller`\r\n\t// and not using a `VirtualScroller`.\r\n\t// It turned out that unmounting large React component trees\r\n\t// is a very long process, so `VirtualScroller` does seem to\r\n\t// make sense when used in a React application.\r\n\tthis._bypass = bypass\r\n\t// this.bypassBatchSize = bypassBatchSize || 10\r\n\r\n\t// Using `setTimeout()` in render loop is a workaround\r\n\t// for avoiding a React error message:\r\n\t// \"Maximum update depth exceeded.\r\n\t// This can happen when a component repeatedly calls\r\n\t// `.setState()` inside `componentWillUpdate()` or `componentDidUpdate()`.\r\n\t// React limits the number of nested updates to prevent infinite loops.\"\r\n\tthis._delayRecursiveRenderUntilNextTick = delayRecursiveRenderUntilNextTick\r\n\r\n\t// `_getItemId()` function is used in `_getItemIndexByItemOrIndex()` function.\r\n\tthis._getItemId = getItemId\r\n\r\n\tif (getItemId) {\r\n\t\tthis.isItemEqual = (a, b) => getItemId(a) === getItemId(b)\r\n\t} else {\r\n\t\tthis.isItemEqual = (a, b) => a === b\r\n\t}\r\n\r\n\tif (onItemInitialRender) {\r\n\t\tthis.onItemInitialRender = onItemInitialRender\r\n\t}\r\n\t// `onItemFirstRender(i)` is deprecated, use `onItemInitialRender(item)` instead.\r\n\telse if (onItemFirstRender) {\r\n\t\tthis.onItemInitialRender = (item) => {\r\n\t\t\twarn('`onItemFirstRender(i)` is deprecated, use `onItemInitialRender(item)` instead.')\r\n\t\t\tconst { items } = this.getState()\r\n\t\t\tconst i = items.indexOf(item)\r\n\t\t\t// The `item` could also be non-found due to the inconsistency bug:\r\n\t\t\t// The reason is that `i` can be non-consistent with the `items`\r\n\t\t\t// passed to `<VirtualScroller/>` in React due to `updateState()` not being\r\n\t\t\t// instanteneous: when new `items` are passed to `<VirtualScroller/>`,\r\n\t\t\t// `VirtualScroller.updateState({ items })` is called, and if `onItemFirstRender(i)`\r\n\t\t\t// is called after the aforementioned `updateState()` is called but before it finishes,\r\n\t\t\t// `i` would point to an index in \"previous\" `items` while the application\r\n\t\t\t// would assume that `i` points to an index in the \"new\" `items`,\r\n\t\t\t// resulting in an incorrect item being assumed by the application\r\n\t\t\t// or even in an \"array index out of bounds\" error.\r\n\t\t\tif (i >= 0) {\r\n\t\t\t\tonItemFirstRender(i)\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// If initial `state` is passed then use `items` from `state`\r\n\t// instead of the `items` argument.\r\n\tif (state) {\r\n\t\titems = state.items\r\n\t}\r\n\r\n\tlog('Items count', items.length)\r\n\tif (getEstimatedItemHeight) {\r\n\t\tlog('Estimated item height', getEstimatedItemHeight())\r\n\t}\r\n\r\n\tcreateStateHelpers.call(this, { state, getInitialItemState, onStateChange, render, items })\r\n\r\n\tcreateVerticalSpacingHelpers.call(this, { getEstimatedInterItemVerticalSpacing })\r\n\tcreateColumnsHelpers.call(this, { getColumnsCount })\r\n\r\n\tcreateLayoutHelpers.call(this)\r\n\tcreateOnRenderHelpers.call(this)\r\n\tcreateScrollableContainerResizeHelpers.call(this)\r\n\tcreateItemsHelpers.call(this)\r\n\r\n\tcreateHelpers.call(this, {\r\n\t\tgetScrollableContainer,\r\n\t\tgetEstimatedItemHeight,\r\n\t\tgetEstimatedVisibleItemRowsCount,\r\n\t\tmeasureItemsBatchSize,\r\n\t\tinitialScrollPosition,\r\n\t\tonScrollPositionChange,\r\n\t\tdelayUnnecessaryRerenderUntilStopsScrolling: _delayUnnecessaryRerenderUntilStopsScrolling\r\n\t})\r\n\r\n\tif (state) {\r\n\t\t// Initialize `ItemHeights` from previously measured `state.itemHeights`.\r\n\t\tthis.itemHeights.readItemHeightsFromState(state)\r\n\r\n\t\t// Initialize some `BeforeResize` internal flags from a previously saved state.\r\n\t\tthis.beforeResize.initializeFromState(state)\r\n\t}\r\n}\r\n\r\nfunction createHelpers({\r\n\tgetScrollableContainer,\r\n\tgetEstimatedItemHeight,\r\n\tgetEstimatedVisibleItemRowsCount,\r\n\tmeasureItemsBatchSize,\r\n\tinitialScrollPosition,\r\n\tonScrollPositionChange,\r\n\tdelayUnnecessaryRerenderUntilStopsScrolling\r\n}) {\r\n\tthis.itemsContainer = this.engine.createItemsContainer(\r\n\t\tthis.getItemsContainerElement\r\n\t)\r\n\r\n\tthis.isItemsContainerElementTableBody = () => {\r\n\t\treturn this.engine === DOMEngine &&\r\n\t\t\tthis.getItemsContainerElement().tagName === 'TBODY'\r\n\t}\r\n\r\n\tthis.isInBypassMode = () => this._bypass\r\n\r\n\tthis.scrollableContainer = this.engine.createScrollableContainer(\r\n\t\tgetScrollableContainer,\r\n\t\tthis.getItemsContainerElement\r\n\t)\r\n\r\n\t// Create `ItemHeights` instance.\r\n\tthis.itemHeights = new ItemHeights({\r\n\t\tcontainer: this.itemsContainer,\r\n\t\tgetItemHeight: (i) => this.getState().itemHeights[i],\r\n\t\tsetItemHeight: (i, height) => this.getState().itemHeights[i] = height\r\n\t})\r\n\r\n\tthis.getAverageItemHeight = () => {\r\n\t\tconst averageItemHeight = this.itemHeights.getAverageItemHeight()\r\n\t\tif (typeof averageItemHeight === 'number') {\r\n\t\t\treturn averageItemHeight\r\n\t\t}\r\n\t\treturn this.getEstimatedItemHeight()\r\n\t}\r\n\r\n\tthis.getEstimatedItemHeight = () => {\r\n\t\tif (getEstimatedItemHeight) {\r\n\t\t\tconst estimatedItemHeight = getEstimatedItemHeight()\r\n\t\t\tif (typeof estimatedItemHeight === 'number') {\r\n\t\t\t\treturn estimatedItemHeight\r\n\t\t\t}\r\n\t\t\tthrow new Error('[virtual-scroller] `getEstimatedItemHeight()` must return a number')\r\n\t\t}\r\n\t\t// `DEFAULT_ITEM_HEIGHT` will be used in server-side render\r\n\t\t// unless `getEstimatedItemHeight()` parameter is specified.\r\n\t\treturn DEFAULT_ITEM_HEIGHT\r\n\t}\r\n\r\n\tthis.layout = new Layout({\r\n\t\tisInBypassMode: this.isInBypassMode,\r\n\t\tgetEstimatedVisibleItemRowsCountForInitialRender: getEstimatedVisibleItemRowsCount,\r\n\t\tmeasureItemsBatchSize,\r\n\t\tgetPrerenderMargin: () => this.getPrerenderMargin(),\r\n\t\tgetPrerenderMarginRatio: () => this.getPrerenderMarginRatio(),\r\n\t\tgetVerticalSpacing: () => this.getVerticalSpacing(),\r\n\t\tgetVerticalSpacingBeforeResize: () => this.getVerticalSpacingBeforeResize(),\r\n\t\tgetColumnsCount: () => this.getColumnsCount(),\r\n\t\tgetColumnsCountBeforeResize: () => this.getState().beforeResize && this.getState().beforeResize.columnsCount,\r\n\t\tgetItemHeight: (i) => this.getState().itemHeights[i],\r\n\t\tgetItemHeightBeforeResize: (i) => this.getState().beforeResize && this.getState().beforeResize.itemHeights[i],\r\n\t\tgetBeforeResizeItemsCount: () => this.getState().beforeResize ? this.getState().beforeResize.itemHeights.length : 0,\r\n\t\tgetAverageItemHeight: () => this.getAverageItemHeight(),\r\n\t\t// `this.scrollableContainer` is gonna be `undefined` during server-side rendering.\r\n\t\t// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/30\r\n\t\tgetMaxVisibleAreaHeight: () => this.scrollableContainer && this.scrollableContainer.getHeight(),\r\n\t\t//\r\n\t\t// The \"previously calculated layout\" feature is not currently used.\r\n\t\t//\r\n\t\t// The current layout snapshot could be stored as a \"previously calculated layout\" variable\r\n\t\t// so that it could theoretically be used when calculating new layout incrementally\r\n\t\t// rather than from scratch, which would be an optimization.\r\n\t\t//\r\n\t\tgetPreviouslyCalculatedLayout: () => this.previouslyCalculatedLayout\r\n\t})\r\n\r\n\tthis.scrollableContainerResizeHandler = new ScrollableContainerResizeHandler({\r\n\t\tisInBypassMode: this.isInBypassMode,\r\n\t\tgetWidth: () => this.scrollableContainer.getWidth(),\r\n\t\tgetHeight: () => this.scrollableContainer.getHeight(),\r\n\t\tlistenForResize: (listener) => this.scrollableContainer.onResize(listener),\r\n\t\tonResizeStart: () => {\r\n\t\t\tlog('~ Scrollable container resize started ~')\r\n\t\t\tthis._isResizing = true\r\n\t\t},\r\n\t\tonResizeStop: () => {\r\n\t\t\tlog('~ Scrollable container resize finished ~')\r\n\t\t\tthis._isResizing = undefined\r\n\t\t},\r\n\t\tonNoChange: () => {\r\n\t\t\t// There might have been some missed `this.onUpdateShownItemIndexes()` calls\r\n\t\t\t// due to setting `this._isResizing` flag to `true` during the resize.\r\n\t\t\t// So, update shown item indexes just in case.\r\n\t\t\tthis.onUpdateShownItemIndexes({\r\n\t\t\t\treason: LAYOUT_REASON.VIEWPORT_SIZE_UNCHANGED\r\n\t\t\t})\r\n\t\t},\r\n\t\tonHeightChange: () => this.onUpdateShownItemIndexes({\r\n\t\t\treason: LAYOUT_REASON.VIEWPORT_HEIGHT_CHANGED\r\n\t\t}),\r\n\t\tonWidthChange: (prevWidth, newWidth) => {\r\n\t\t\tlog('~ Scrollable container width changed from', prevWidth, 'to', newWidth, '~')\r\n\t\t\tthis.onContainerResize()\r\n\t\t}\r\n\t})\r\n\r\n\tthis.scroll = new Scroll({\r\n\t\tisInBypassMode: this.isInBypassMode,\r\n\t\tscrollableContainer: this.scrollableContainer,\r\n\t\titemsContainer: this.itemsContainer,\r\n\t\tdelayUnnecessaryRerenderUntilStopsScrolling,\r\n\t\tonScroll: ({ delayed } = {}) => {\r\n\t\t\tthis.onUpdateShownItemIndexes({\r\n\t\t\t\treason: delayed ? LAYOUT_REASON.STOPPED_SCROLLING : LAYOUT_REASON.SCROLL\r\n\t\t\t})\r\n\t\t},\r\n\t\tinitialScrollPosition,\r\n\t\tonScrollPositionChange,\r\n\t\tisImmediateLayoutScheduled: () => Boolean(this.layoutTimer),\r\n\t\thasNonRenderedItemsAtTheTop: () => this.getState().firstShownItemIndex > 0,\r\n\t\thasNonRenderedItemsAtTheBottom: () => this.getState().lastShownItemIndex < this.getItemsCount() - 1,\r\n\t\tgetLatestLayoutVisibleArea: () => this.latestLayoutVisibleArea,\r\n\t\tgetListTopOffset: this.getListTopOffsetInsideScrollableContainer,\r\n\t\tgetPrerenderMargin: () => this.getPrerenderMargin()\r\n\t})\r\n\r\n\tthis.listHeightMeasurement = new ListHeightMeasurement({\r\n\t\titemsContainer: this.itemsContainer,\r\n\t\tgetListTopOffset: this.getListTopOffsetInsideScrollableContainer\r\n\t})\r\n\r\n\tif (this.engine.watchListTopOffset) {\r\n\t\tthis.listTopOffsetWatcher = this.engine.watchListTopOffset({\r\n\t\t\tgetListTopOffset: this.getListTopOffsetInsideScrollableContainer,\r\n\t\t\tonListTopOffsetChange: () => this.onUpdateShownItemIndexes({\r\n\t\t\t\treason: LAYOUT_REASON.TOP_OFFSET_CHANGED\r\n\t\t\t})\r\n\t\t})\r\n\t}\r\n\r\n\tthis.beforeResize = new BeforeResize({\r\n\t\tgetState: this.getState,\r\n\t\tgetVerticalSpacing: this.getVerticalSpacing,\r\n\t\tgetColumnsCount: this.getColumnsCount\r\n\t})\r\n}"],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
|
|
12
12
|
|
|
13
13
|
import VirtualScrollerConstructor from './VirtualScroller.constructor.js';
|
|
14
14
|
import { LAYOUT_REASON } from './Layout.js';
|
|
15
|
+
import { unscheduleOnNextTick } from './utility/scheduleOnNextTick.js';
|
|
15
16
|
import log, { warn, reportError } from './utility/debug.js';
|
|
16
17
|
import { supportsTbody, hasTbodyStyles, addTbodyStyles, BROWSER_NOT_SUPPORTED_ERROR } from './DOM/tbody.js';
|
|
17
18
|
|
|
@@ -47,9 +48,16 @@ var VirtualScroller = /*#__PURE__*/function () {
|
|
|
47
48
|
if (_this.listTopOffsetWatcher && _this.listTopOffsetWatcher.isStarted()) {
|
|
48
49
|
_this.listTopOffsetWatcher.stop();
|
|
49
50
|
} // Cancel any scheduled layout.
|
|
51
|
+
// Any pending state update is discarded here.
|
|
50
52
|
|
|
51
53
|
|
|
52
|
-
_this.cancelLayoutTimer({});
|
|
54
|
+
_this.cancelLayoutTimer({}); // Cancel any scheduled "recursive re-render duration" timer.
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
if (_this._stateUpdateSequenceStartedAtResetTimer !== undefined) {
|
|
58
|
+
unscheduleOnNextTick(_this._stateUpdateSequenceStartedAtResetTimer);
|
|
59
|
+
_this._stateUpdateSequenceStartedAtResetTimer = undefined;
|
|
60
|
+
}
|
|
53
61
|
});
|
|
54
62
|
|
|
55
63
|
_defineProperty(this, "updateLayout", function () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VirtualScroller.js","names":["VirtualScrollerConstructor","LAYOUT_REASON","log","warn","reportError","supportsTbody","hasTbodyStyles","addTbodyStyles","BROWSER_NOT_SUPPORTED_ERROR","VirtualScroller","getItemsContainerElement","items","options","_isActive","Error","scrollableContainerResizeHandler","stop","scroll","listTopOffsetWatcher","isStarted","cancelLayoutTimer","hasToBeStarted","onUpdateShownItemIndexes","reason","MANUAL","_onRender","getState","previousState","call","isRestart","setUpState","waitingForRender","_render","listHeightMeasurement","reset","_isResizing","undefined","_isSettingNewItems","isInBypassMode","isItemsContainerElementTableBody","_bypass","stateUpdate","_afterRenderStateUpdateThatWasStopped","verticalSpacing","verticalSpacingStateUpdate","measureItemHeightsAndSpacing","start","scrollableContainerWidth","scrollableContainer","getWidth","newWidth","prevWidth","onContainerResize","_usesCustomStateStorage","columnsCount","getActualColumnsCount","columnsCountFromState","STARTED","itemOrIndex","i","_getItemIndexByItemOrIndex","itemTopOffsetInList","layout","getItemTopOffset","getListTopOffsetInsideScrollableContainer","item","onItemHeightDidChange","_onItemHeightDidChange","newItemState","_setItemState","setItemState","newItems","_setItems"],"sources":["../source/VirtualScroller.js"],"sourcesContent":["import VirtualScrollerConstructor from './VirtualScroller.constructor.js'\r\nimport { LAYOUT_REASON } from './Layout.js'\r\nimport log, { warn, reportError } from './utility/debug.js'\r\n\r\nimport {\r\n\tsupportsTbody,\r\n\thasTbodyStyles,\r\n\taddTbodyStyles,\r\n\tBROWSER_NOT_SUPPORTED_ERROR\r\n} from './DOM/tbody.js'\r\n\r\nexport default class VirtualScroller {\r\n\t/**\r\n\t * @param {function} getItemsContainerElement — Returns the items 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.setUpState()\r\n\t\t\tthis.waitingForRender = true\r\n\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\t// Perform the initial render of the list.\r\n\t\t\t\tthis._render(this.getState())\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (isRestart) {\r\n\t\t\tlog('~ Start (restart) ~')\r\n\t\t} else {\r\n\t\t\tlog('~ Start ~')\r\n\t\t}\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// When `<tbody/>` is used as an items container element,\r\n\t\t// `virtual-scroller` has to work around the HTML bug of\r\n\t\t// `padding` not working on a `<tbody/>` element.\r\n\t\t// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1\r\n\t\tif (!this.isInBypassMode()) {\r\n\t\t\tif (this.isItemsContainerElementTableBody()) {\r\n\t\t\t\tif (supportsTbody()) {\r\n\t\t\t\t\tif (!hasTbodyStyles(this.getItemsContainerElement())) {\r\n\t\t\t\t\t\tlog('~ <tbody/> container ~')\r\n\t\t\t\t\t\taddTbodyStyles(this.getItemsContainerElement())\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tlog('~ <tbody/> container not supported ~')\r\n\t\t\t\t\treportError(BROWSER_NOT_SUPPORTED_ERROR)\r\n\t\t\t\t\tlog('~ enter \"bypass\" mode ~')\r\n\t\t\t\t\tthis._bypass = true\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If there was a pending \"after render\" state update that didn't get applied\r\n\t\t// because the `VirtualScroller` got stopped, then apply that pending \"after render\"\r\n\t\t// state update now. Such state update could include properties like:\r\n\t\t// * A `verticalSpacing` that has been measured in `onRender()`.\r\n\t\t// * A cleaned-up `beforeResize` object that was cleaned-up in `onRender()`.\r\n\t\tlet stateUpdate = this._afterRenderStateUpdateThatWasStopped\r\n\t\tthis._afterRenderStateUpdateThatWasStopped = 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.scrollableContainerResizeHandler.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// The pending state update (if present) won't be applied in this case.\r\n\t\t\t\t// That's ok because such state update could currently only originate in\r\n\t\t\t\t// `this.onContainerResize()` function. Therefore, alling `this.onContainerResize()` again\r\n\t\t\t\t// would rewrite all those `stateUpdate` properties anyway, so they're not passed.\r\n\t\t\t\treturn this.onContainerResize()\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.onContainerResize()\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.scrollableContainerResizeHandler.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 {any} item — Item\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(itemOrIndex) {\r\n\t\t// Item index.\r\n\t\tconst i = this._getItemIndexByItemOrIndex(itemOrIndex)\r\n\r\n\t\t// If the item wasn't found, the error was already reported,\r\n\t\t// so just return some \"sensible\" default value.\r\n\t\tif (i === undefined) {\r\n\t\t\treturn\r\n\t\t}\r\n\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(item) {\r\n\t\twarn('`.onItemHeightChange(item)` method was renamed to `.onItemHeightDidChange(item)`')\r\n\t\tthis.onItemHeightDidChange(item)\r\n\t}\r\n\r\n\t/**\r\n\t * Forces a re-measure of an item's height.\r\n\t * @param {any} item — Item. Legacy argument variant: Item index.\r\n\t */\r\n\tonItemHeightDidChange(itemOrIndex) {\r\n\t\t// See the comments in the `setItemState()` function below for the rationale\r\n\t\t// on why the `hasToBeStarted()` check was commented out.\r\n\t\t// this.hasToBeStarted()\r\n\t\tthis._onItemHeightDidChange(itemOrIndex)\r\n\t}\r\n\r\n\t/**\r\n\t * Updates an item's state in `state.itemStates[]`.\r\n\t * @param {any} item — Item. Legacy argument variant: Item index.\r\n\t * @param {any} newItemState — Item's new state\r\n\t */\r\n\tsetItemState(itemOrIndex, newItemState) {\r\n\t\t// There is an issue in React 18.2.0 when `useInsertionEffect()` doesn't run twice\r\n\t\t// on mount unlike `useLayoutEffect()` in \"strict\" mode. That causes a bug in a React\r\n\t\t// implementation of the `virtual-scroller`.\r\n\t\t// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/33\r\n\t\t// https://github.com/facebook/react/issues/26320\r\n\t\t// A workaround for that bug is ignoring the second-initial run of the effects at mount.\r\n\t\t//\r\n\t\t// But in that case, if an `ItemComponent` calls `setItemState()` in `useLayoutEffect()`,\r\n\t\t// it could result in a bug.\r\n\t\t//\r\n\t\t// Consider a type of `useLayoutEffect()` that skips the initial mount:\r\n\t\t// `useLayoutEffectSkipInitialMount()`.\r\n\t\t// Suppose that effect is written in such a way that it only skips the first call of itself.\r\n\t\t// In that case, if React is run in \"strict\" mode, the effect will no longer work as expected\r\n\t\t// and it won't actually skip the initial mount and will be executed during the second initial run.\r\n\t\t// But the `VirtualScroller` itself has already implemented a workaround that prevents\r\n\t\t// its hooks from running twice on mount. This means that `useVirtualScrollerStartStop()`\r\n\t\t// of the React component would have already stopped the `VirtualScroller` by the time\r\n\t\t// `ItemComponent`'s incorrectly-behaving `useLayoutEffectSkipInitialMount()` effect is run,\r\n\t\t// resulting in an error: \"`VirtualScroller` hasn't been started\".\r\n\t\t//\r\n\t\t// The log when not in \"strict\" mode would be:\r\n\t\t//\r\n\t\t// * `useLayoutEffect()` is run in `ItemComponent` — skips the initial run.\r\n\t\t// * `useLayoutEffect()` is run in `useVirtualScrollerStartStop()`. It starts the `VirtualScroller`.\r\n\t\t// * Some dependency property gets updated inside `ItemComponent`.\r\n\t\t// * `useLayoutEffect()` is run in `ItemComponent` — no longer skips. Calls `setItemState()`.\r\n\t\t// * The `VirtualScroller` is started so it handles `setState()` correctly.\r\n\t\t//\r\n\t\t// The log when in \"strict\" mode would be:\r\n\t\t//\r\n\t\t// * `useLayoutEffect()` is run in `ItemComponent` — skips the initial run.\r\n\t\t// * `useLayoutEffect()` is run in `useVirtualScrollerStartStop()`. It starts the `VirtualScroller`.\r\n\t\t// * `useLayoutEffect()` is unmounted in `useVirtualScrollerStartStop()`. It stops the `VirtualScroller`.\r\n\t\t// * `useLayoutEffect()` is unmounted in `ItemComponent` — does nothing.\r\n\t\t// * `useLayoutEffect()` is run the second time in `ItemComponent` — no longer skips. Calls `setItemState()`.\r\n\t\t// * The `VirtualScroller` is stopped so it throws an error: \"`VirtualScroller` hasn't been started\".\r\n\t\t//\r\n\t\t// For that reason, the requirement of the `VirtualScroller` to be started was commented out.\r\n\t\t// Commenting it out wouldn't result in any potential bugs because the code would work correctly\r\n\t\t// in both cases.\r\n\t\t// this.hasToBeStarted()\r\n\t\tthis._setItemState(itemOrIndex, newItemState)\r\n\t}\r\n\r\n\t// (deprecated)\r\n\t// Use `.setItemState()` method name instead.\r\n\tonItemStateChange(item, newItemState) {\r\n\t\tthis.setItemState(item, 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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AA5B,EAAuC;QACtC;MACA;;MACD,OAAO,KAAK4B,yCAAL,KAAmDH,mBAA1D;IACA;IAED;AACD;AACA;AACA;;;;WACC,4BAAmBI,IAAnB,EAAyB;MACxB9D,IAAI,CAAC,kFAAD,CAAJ;MACA,KAAK+D,qBAAL,CAA2BD,IAA3B;IACA;IAED;AACD;AACA;AACA;;;;WACC,+BAAsBP,WAAtB,EAAmC;MAClC;MACA;MACA;MACA,KAAKS,sBAAL,CAA4BT,WAA5B;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,sBAAaA,WAAb,EAA0BU,YAA1B,EAAwC;MACvC;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,KAAKC,aAAL,CAAmBX,WAAnB,EAAgCU,YAAhC;IACA,C,CAED;IACA;;;;WACA,2BAAkBH,IAAlB,EAAwBG,YAAxB,EAAsC;MACrC,KAAKE,YAAL,CAAkBL,IAAlB,EAAwBG,YAAxB;IACA;IAED;AACD;AACA;AACA;AACA;;;;WACC,kBAASG,QAAT,EAAiC;MAAA,IAAd3D,OAAc,uEAAJ,EAAI;MAChC,KAAKS,cAAL;MACA,OAAO,KAAKmD,SAAL,CAAeD,QAAf,EAAyB3D,OAAzB,CAAP;IACA;;;;;;SAhTmBH,e"}
|
|
1
|
+
{"version":3,"file":"VirtualScroller.js","names":["VirtualScrollerConstructor","LAYOUT_REASON","unscheduleOnNextTick","log","warn","reportError","supportsTbody","hasTbodyStyles","addTbodyStyles","BROWSER_NOT_SUPPORTED_ERROR","VirtualScroller","getItemsContainerElement","items","options","_isActive","Error","scrollableContainerResizeHandler","stop","scroll","listTopOffsetWatcher","isStarted","cancelLayoutTimer","_stateUpdateSequenceStartedAtResetTimer","undefined","hasToBeStarted","onUpdateShownItemIndexes","reason","MANUAL","_onRender","getState","previousState","call","isRestart","setUpState","waitingForRender","_render","listHeightMeasurement","reset","_isResizing","_isSettingNewItems","isInBypassMode","isItemsContainerElementTableBody","_bypass","stateUpdate","_afterRenderStateUpdateThatWasStopped","verticalSpacing","verticalSpacingStateUpdate","measureItemHeightsAndSpacing","start","scrollableContainerWidth","scrollableContainer","getWidth","newWidth","prevWidth","onContainerResize","_usesCustomStateStorage","columnsCount","getActualColumnsCount","columnsCountFromState","STARTED","itemOrIndex","i","_getItemIndexByItemOrIndex","itemTopOffsetInList","layout","getItemTopOffset","getListTopOffsetInsideScrollableContainer","item","onItemHeightDidChange","_onItemHeightDidChange","newItemState","_setItemState","setItemState","newItems","_setItems"],"sources":["../source/VirtualScroller.js"],"sourcesContent":["import VirtualScrollerConstructor from './VirtualScroller.constructor.js'\r\nimport { LAYOUT_REASON } from './Layout.js'\r\nimport { unscheduleOnNextTick } from './utility/scheduleOnNextTick.js'\r\nimport log, { warn, reportError } from './utility/debug.js'\r\n\r\nimport {\r\n\tsupportsTbody,\r\n\thasTbodyStyles,\r\n\taddTbodyStyles,\r\n\tBROWSER_NOT_SUPPORTED_ERROR\r\n} from './DOM/tbody.js'\r\n\r\nexport default class VirtualScroller {\r\n\t/**\r\n\t * @param {function} getItemsContainerElement — Returns the items 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.setUpState()\r\n\t\t\tthis.waitingForRender = true\r\n\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\t// Perform the initial render of the list.\r\n\t\t\t\tthis._render(this.getState())\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (isRestart) {\r\n\t\t\tlog('~ Start (restart) ~')\r\n\t\t} else {\r\n\t\t\tlog('~ Start ~')\r\n\t\t}\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// When `<tbody/>` is used as an items container element,\r\n\t\t// `virtual-scroller` has to work around the HTML bug of\r\n\t\t// `padding` not working on a `<tbody/>` element.\r\n\t\t// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1\r\n\t\tif (!this.isInBypassMode()) {\r\n\t\t\tif (this.isItemsContainerElementTableBody()) {\r\n\t\t\t\tif (supportsTbody()) {\r\n\t\t\t\t\tif (!hasTbodyStyles(this.getItemsContainerElement())) {\r\n\t\t\t\t\t\tlog('~ <tbody/> container ~')\r\n\t\t\t\t\t\taddTbodyStyles(this.getItemsContainerElement())\r\n\t\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t\tlog('~ <tbody/> container not supported ~')\r\n\t\t\t\t\treportError(BROWSER_NOT_SUPPORTED_ERROR)\r\n\t\t\t\t\tlog('~ enter \"bypass\" mode ~')\r\n\t\t\t\t\tthis._bypass = true\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If there was a pending \"after render\" state update that didn't get applied\r\n\t\t// because the `VirtualScroller` got stopped, then apply that pending \"after render\"\r\n\t\t// state update now. Such state update could include properties like:\r\n\t\t// * A `verticalSpacing` that has been measured in `onRender()`.\r\n\t\t// * A cleaned-up `beforeResize` object that was cleaned-up in `onRender()`.\r\n\t\tlet stateUpdate = this._afterRenderStateUpdateThatWasStopped\r\n\t\tthis._afterRenderStateUpdateThatWasStopped = 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.scrollableContainerResizeHandler.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// The pending state update (if present) won't be applied in this case.\r\n\t\t\t\t// That's ok because such state update could currently only originate in\r\n\t\t\t\t// `this.onContainerResize()` function. Therefore, alling `this.onContainerResize()` again\r\n\t\t\t\t// would rewrite all those `stateUpdate` properties anyway, so they're not passed.\r\n\t\t\t\treturn this.onContainerResize()\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.onContainerResize()\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.scrollableContainerResizeHandler.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\t// Any pending state update is discarded here.\r\n\t\tthis.cancelLayoutTimer({})\r\n\r\n\t\t// Cancel any scheduled \"recursive re-render duration\" timer.\r\n\t\tif (this._stateUpdateSequenceStartedAtResetTimer !== undefined) {\r\n\t\t\tunscheduleOnNextTick(this._stateUpdateSequenceStartedAtResetTimer)\r\n\t\t\tthis._stateUpdateSequenceStartedAtResetTimer = undefined\r\n\t\t}\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 {any} item — Item\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(itemOrIndex) {\r\n\t\t// Item index.\r\n\t\tconst i = this._getItemIndexByItemOrIndex(itemOrIndex)\r\n\r\n\t\t// If the item wasn't found, the error was already reported,\r\n\t\t// so just return some \"sensible\" default value.\r\n\t\tif (i === undefined) {\r\n\t\t\treturn\r\n\t\t}\r\n\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(item) {\r\n\t\twarn('`.onItemHeightChange(item)` method was renamed to `.onItemHeightDidChange(item)`')\r\n\t\tthis.onItemHeightDidChange(item)\r\n\t}\r\n\r\n\t/**\r\n\t * Forces a re-measure of an item's height.\r\n\t * @param {any} item — Item. Legacy argument variant: Item index.\r\n\t */\r\n\tonItemHeightDidChange(itemOrIndex) {\r\n\t\t// See the comments in the `setItemState()` function below for the rationale\r\n\t\t// on why the `hasToBeStarted()` check was commented out.\r\n\t\t// this.hasToBeStarted()\r\n\t\tthis._onItemHeightDidChange(itemOrIndex)\r\n\t}\r\n\r\n\t/**\r\n\t * Updates an item's state in `state.itemStates[]`.\r\n\t * @param {any} item — Item. Legacy argument variant: Item index.\r\n\t * @param {any} newItemState — Item's new state\r\n\t */\r\n\tsetItemState(itemOrIndex, newItemState) {\r\n\t\t// There is an issue in React 18.2.0 when `useInsertionEffect()` doesn't run twice\r\n\t\t// on mount unlike `useLayoutEffect()` in \"strict\" mode. That causes a bug in a React\r\n\t\t// implementation of the `virtual-scroller`.\r\n\t\t// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/33\r\n\t\t// https://github.com/facebook/react/issues/26320\r\n\t\t// A workaround for that bug is ignoring the second-initial run of the effects at mount.\r\n\t\t//\r\n\t\t// But in that case, if an `ItemComponent` calls `setItemState()` in `useLayoutEffect()`,\r\n\t\t// it could result in a bug.\r\n\t\t//\r\n\t\t// Consider a type of `useLayoutEffect()` that skips the initial mount:\r\n\t\t// `useLayoutEffectSkipInitialMount()`.\r\n\t\t// Suppose that effect is written in such a way that it only skips the first call of itself.\r\n\t\t// In that case, if React is run in \"strict\" mode, the effect will no longer work as expected\r\n\t\t// and it won't actually skip the initial mount and will be executed during the second initial run.\r\n\t\t// But the `VirtualScroller` itself has already implemented a workaround that prevents\r\n\t\t// its hooks from running twice on mount. This means that `useVirtualScrollerStartStop()`\r\n\t\t// of the React component would have already stopped the `VirtualScroller` by the time\r\n\t\t// `ItemComponent`'s incorrectly-behaving `useLayoutEffectSkipInitialMount()` effect is run,\r\n\t\t// resulting in an error: \"`VirtualScroller` hasn't been started\".\r\n\t\t//\r\n\t\t// The log when not in \"strict\" mode would be:\r\n\t\t//\r\n\t\t// * `useLayoutEffect()` is run in `ItemComponent` — skips the initial run.\r\n\t\t// * `useLayoutEffect()` is run in `useVirtualScrollerStartStop()`. It starts the `VirtualScroller`.\r\n\t\t// * Some dependency property gets updated inside `ItemComponent`.\r\n\t\t// * `useLayoutEffect()` is run in `ItemComponent` — no longer skips. Calls `setItemState()`.\r\n\t\t// * The `VirtualScroller` is started so it handles `setState()` correctly.\r\n\t\t//\r\n\t\t// The log when in \"strict\" mode would be:\r\n\t\t//\r\n\t\t// * `useLayoutEffect()` is run in `ItemComponent` — skips the initial run.\r\n\t\t// * `useLayoutEffect()` is run in `useVirtualScrollerStartStop()`. It starts the `VirtualScroller`.\r\n\t\t// * `useLayoutEffect()` is unmounted in `useVirtualScrollerStartStop()`. It stops the `VirtualScroller`.\r\n\t\t// * `useLayoutEffect()` is unmounted in `ItemComponent` — does nothing.\r\n\t\t// * `useLayoutEffect()` is run the second time in `ItemComponent` — no longer skips. Calls `setItemState()`.\r\n\t\t// * The `VirtualScroller` is stopped so it throws an error: \"`VirtualScroller` hasn't been started\".\r\n\t\t//\r\n\t\t// For that reason, the requirement of the `VirtualScroller` to be started was commented out.\r\n\t\t// Commenting it out wouldn't result in any potential bugs because the code would work correctly\r\n\t\t// in both cases.\r\n\t\t// this.hasToBeStarted()\r\n\t\tthis._setItemState(itemOrIndex, newItemState)\r\n\t}\r\n\r\n\t// (deprecated)\r\n\t// Use `.setItemState()` method name instead.\r\n\tonItemStateChange(item, newItemState) {\r\n\t\tthis.setItemState(item, 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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"}
|
|
@@ -4,12 +4,8 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
|
|
|
4
4
|
|
|
5
5
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
6
|
|
|
7
|
-
// For some weird reason, in Chrome, `setTimeout()` would lag up to a second (or more) behind.
|
|
8
|
-
// Turns out, Chrome developers have deprecated `setTimeout()` API entirely without asking anyone.
|
|
9
|
-
// Replacing `setTimeout()` with `requestAnimationFrame()` can work around that Chrome bug.
|
|
10
|
-
// https://github.com/bvaughn/react-virtualized/issues/722
|
|
11
|
-
import { setTimeout, clearTimeout } from 'request-animation-frame-timeout';
|
|
12
7
|
import log, { warn, isDebug, reportError } from './utility/debug.js';
|
|
8
|
+
import { scheduleOnNextTick, unscheduleOnNextTick } from './utility/scheduleOnNextTick.js';
|
|
13
9
|
import { LAYOUT_REASON } from './Layout.js';
|
|
14
10
|
import ItemNotRenderedError from './ItemNotRenderedError.js';
|
|
15
11
|
export default function () {
|
|
@@ -19,21 +15,39 @@ export default function () {
|
|
|
19
15
|
var reason = _ref.reason,
|
|
20
16
|
stateUpdate = _ref.stateUpdate;
|
|
21
17
|
|
|
22
|
-
// In case of "don't
|
|
18
|
+
// In case of "don't perform this particular re-layout
|
|
19
|
+
// because a more-priority one is already scheduled".
|
|
23
20
|
var skip = function skip() {
|
|
24
21
|
if (stateUpdate) {
|
|
22
|
+
// Don't update layout. Just update some state.
|
|
23
|
+
// `stateUpdate` isn't supposed to affect the layout in any way
|
|
24
|
+
// because it doesn't contain any properties that affect the rendering of the list.
|
|
25
|
+
// I.e. it doesn't contain properties like `beforeItemsHeight` or `afterItemsHeight`, etc.
|
|
25
26
|
_this.updateState(stateUpdate);
|
|
26
27
|
}
|
|
27
28
|
}; // If new `items` have been set and are waiting to be applied,
|
|
28
29
|
// or if the viewport width has changed requiring a re-layout,
|
|
29
30
|
// then temporarily stop all other updates like "on scroll" updates.
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
// `
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
31
|
+
//
|
|
32
|
+
// This prevents `state` from becoming inconsistent, because several
|
|
33
|
+
// "contenders" (layout reasons) could be attempting to update
|
|
34
|
+
// `VirtualScroller` state in parallel between two successive renders.
|
|
35
|
+
//
|
|
36
|
+
// For example, both `VirtualScroller.setItems()` and `VirtualScroller.scroll.onScroll()`
|
|
37
|
+
// "contenders" could be attempting to update `VirtualScroller` state in parallel,
|
|
38
|
+
// and the layout calculated by one of them would overwrite the layout calculated by another.
|
|
39
|
+
//
|
|
40
|
+
// Which one should have the priority in such case then?
|
|
41
|
+
// In this specific example, `VirtualScroller.setItems()` should be the one
|
|
42
|
+
// because only it knows the correct new `items` whereas other "contenders"
|
|
43
|
+
// have the old stale `items`.
|
|
44
|
+
//
|
|
45
|
+
// Another example of a "contender" that should have a priority is
|
|
46
|
+
// "on list width has changed" handler because only it has access
|
|
47
|
+
// to the correct new width of the list rather than the old stale width.
|
|
48
|
+
//
|
|
49
|
+
// So in these two "priority" cases any other re-layout should be ignored.
|
|
50
|
+
//
|
|
37
51
|
|
|
38
52
|
|
|
39
53
|
if (_this.newItemsWillBeRendered || _this.widthHasChanged || _this._isResizing) {
|
|
@@ -43,11 +57,12 @@ export default function () {
|
|
|
43
57
|
|
|
44
58
|
if (_this.getItemsCount() === 0) {
|
|
45
59
|
return skip();
|
|
46
|
-
} // Cancel a "re-layout when user stops scrolling" timer
|
|
60
|
+
} // Cancel a scheduled "re-layout when user stops scrolling" timer
|
|
61
|
+
// because a re-layout will be performed here now.
|
|
47
62
|
|
|
48
63
|
|
|
49
|
-
_this.scroll.cancelScheduledLayout(); // Cancel a re-layout that is scheduled to run at the next "frame",
|
|
50
|
-
// because a re-layout will be performed
|
|
64
|
+
_this.scroll.cancelScheduledLayout(); // Cancel a scheduled re-layout that is scheduled to run at the next "frame",
|
|
65
|
+
// because a re-layout will be performed here now.
|
|
51
66
|
|
|
52
67
|
|
|
53
68
|
stateUpdate = _this.cancelLayoutTimer({
|
|
@@ -132,7 +147,24 @@ export default function () {
|
|
|
132
147
|
|
|
133
148
|
if (layoutDuration < SLOW_LAYOUT_DURATION) {// log('Calculated in', layoutDuration, 'ms')
|
|
134
149
|
} else {
|
|
135
|
-
|
|
150
|
+
// Getting this warning would mean that for a given (large) count of items,
|
|
151
|
+
// calculating `beforeItemsHeight` or `afterItemsHeight` requires too much time
|
|
152
|
+
// in order to iterate over all not-currently-visible items to add up their heights.
|
|
153
|
+
//
|
|
154
|
+
// Because layout calculation is a blocking procedure, it "freezes" the application
|
|
155
|
+
// for a given amount of milliseconds. If the amount of those milliseconds is longer
|
|
156
|
+
// than 16ms, frames are being dropped in a 60fps scenario.
|
|
157
|
+
// Modern phones even use 120fps as a baseline, so the timeframe requirement
|
|
158
|
+
// gets even more strict.
|
|
159
|
+
//
|
|
160
|
+
// What could be a way of dealing with this?
|
|
161
|
+
//
|
|
162
|
+
// * The code could cache clustered item heights in order to perform less add-up operations.
|
|
163
|
+
// For example, the code could cache the total height of items 1..100, 101..200, etc.
|
|
164
|
+
// Then 1..1000, 1001..2000, etc. Then 1..10000, 10001..20000, etc. So the clusters
|
|
165
|
+
// would just get progressively larger as more `items` are added.
|
|
166
|
+
//
|
|
167
|
+
warn('Layout calculation time too high:', layoutDuration, 'ms');
|
|
136
168
|
}
|
|
137
169
|
|
|
138
170
|
if (this.getColumnsCount()) {
|
|
@@ -143,7 +175,7 @@ export default function () {
|
|
|
143
175
|
log('Last shown item index', lastShownItemIndex);
|
|
144
176
|
log('Before items height', beforeItemsHeight);
|
|
145
177
|
log('After items height (actual or estimated)', afterItemsHeight);
|
|
146
|
-
log('Average item height (used
|
|
178
|
+
log('Average item height (will be used to calculate estimated "after items height")', this.getAverageItemHeight());
|
|
147
179
|
|
|
148
180
|
if (isDebug()) {
|
|
149
181
|
log('Item heights', this.getState().itemHeights.slice());
|
|
@@ -436,7 +468,7 @@ export default function () {
|
|
|
436
468
|
if (previousHeight === undefined) {
|
|
437
469
|
// There're valid cases when the item still hasn't been measured and `onItemHeightDidChange(item)`
|
|
438
470
|
// function was called for it. That's because measuring items is only done after the `VirtualScroller`
|
|
439
|
-
// has `start()`ed. But it's not
|
|
471
|
+
// has `start()`ed. But it's not necessarily `start()`ed by the time it has been rendered (mounted).
|
|
440
472
|
// For example, the React component `<VirtualScroller/>` provides an `readyToStart={false}` property
|
|
441
473
|
// in order to let the application finish initializing itself before starting the `VirtualScroller`.
|
|
442
474
|
// So there're legitimate cases when a `VirtualScroller` is already rendered but is not `start()`ed yet.
|
|
@@ -580,7 +612,7 @@ export default function () {
|
|
|
580
612
|
var stateUpdate = _ref3.stateUpdate;
|
|
581
613
|
|
|
582
614
|
if (_this.layoutTimer) {
|
|
583
|
-
|
|
615
|
+
unscheduleOnNextTick(_this.layoutTimer);
|
|
584
616
|
_this.layoutTimer = undefined; // Merge state updates.
|
|
585
617
|
|
|
586
618
|
if (stateUpdate || _this.layoutTimerStateUpdate) {
|
|
@@ -597,7 +629,7 @@ export default function () {
|
|
|
597
629
|
var reason = _ref4.reason,
|
|
598
630
|
stateUpdate = _ref4.stateUpdate;
|
|
599
631
|
_this.layoutTimerStateUpdate = stateUpdate;
|
|
600
|
-
_this.layoutTimer =
|
|
632
|
+
_this.layoutTimer = scheduleOnNextTick(function () {
|
|
601
633
|
_this.layoutTimerStateUpdate = undefined;
|
|
602
634
|
_this.layoutTimer = undefined;
|
|
603
635
|
|
|
@@ -605,8 +637,14 @@ export default function () {
|
|
|
605
637
|
reason: reason,
|
|
606
638
|
stateUpdate: stateUpdate
|
|
607
639
|
});
|
|
608
|
-
}
|
|
640
|
+
});
|
|
609
641
|
};
|
|
610
642
|
}
|
|
611
|
-
var
|
|
643
|
+
var FPS = 60; // though 120 fps is common on smartphones these days.
|
|
644
|
+
|
|
645
|
+
var FRAME_DURATION = 1000 / FPS; // in milliseconds
|
|
646
|
+
// Layout is considered "too slow" when it "blocks" the "main thread"
|
|
647
|
+
// for so long that it starts causing "frame drops".
|
|
648
|
+
|
|
649
|
+
var SLOW_LAYOUT_DURATION = FRAME_DURATION;
|
|
612
650
|
//# sourceMappingURL=VirtualScroller.layout.js.map
|