virtual-scroller 1.13.1 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/README.md +825 -578
- package/bundle/index-dom-bypass.html +198 -0
- package/bundle/index-dom-grid.html +204 -0
- package/bundle/index-dom-scrollableContainer.html +215 -0
- package/bundle/index-dom-tbody-scrollableContainer.html +81 -0
- package/bundle/index-dom-tbody.html +65 -0
- package/bundle/index-dom.html +116 -83
- package/bundle/{index-bypass.html → index-react-bypass.html} +83 -78
- package/bundle/{index-grid.html → index-react-grid.html} +78 -91
- package/bundle/{index-scrollableContainer.html → index-react-scrollableContainer.html} +96 -91
- package/bundle/index-react-strictMode.html +199 -0
- package/bundle/index-react-tbody-scrollableContainer.html +96 -0
- package/bundle/index-react-tbody.html +80 -0
- package/bundle/{messages.js → items.js} +1 -1
- package/bundle/lib/babel.min.js +25 -0
- package/bundle/lib/prop-types.min.js +1 -0
- package/bundle/lib/react-dom.development.js +29924 -0
- package/bundle/lib/react-dom.production.min.js +267 -0
- package/bundle/lib/react.development.js +3343 -0
- package/bundle/lib/react.production.min.js +31 -0
- package/bundle/style.base.css +33 -0
- package/{website/style.css → bundle/style.list.css} +10 -43
- package/bundle/style.list.grid.css +23 -0
- 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/BeforeResize.js +1 -2
- package/commonjs/BeforeResize.js.map +1 -1
- package/commonjs/DOM/VirtualScroller.js +67 -44
- package/commonjs/DOM/VirtualScroller.js.map +1 -1
- package/commonjs/DOM/tbody.js +15 -15
- package/commonjs/DOM/tbody.js.map +1 -1
- package/commonjs/ItemHeights.js +10 -13
- package/commonjs/ItemHeights.js.map +1 -1
- package/commonjs/Layout.defaults.js +21 -0
- package/commonjs/Layout.defaults.js.map +1 -0
- package/commonjs/Layout.js +78 -67
- package/commonjs/Layout.js.map +1 -1
- package/commonjs/Layout.test.js +8 -4
- package/commonjs/Layout.test.js.map +1 -1
- package/commonjs/Scroll.js +3 -3
- package/commonjs/Scroll.js.map +1 -1
- package/commonjs/ScrollableContainerResizeHandler.js +4 -5
- package/commonjs/ScrollableContainerResizeHandler.js.map +1 -1
- package/commonjs/VirtualScroller.constructor.js +53 -31
- package/commonjs/VirtualScroller.constructor.js.map +1 -1
- package/commonjs/VirtualScroller.items.js +50 -4
- package/commonjs/VirtualScroller.items.js.map +1 -1
- package/commonjs/VirtualScroller.js +44 -28
- package/commonjs/VirtualScroller.js.map +1 -1
- package/commonjs/VirtualScroller.layout.js +42 -31
- package/commonjs/VirtualScroller.layout.js.map +1 -1
- package/commonjs/VirtualScroller.onContainerResize.js +1 -2
- package/commonjs/VirtualScroller.onContainerResize.js.map +1 -1
- package/commonjs/VirtualScroller.onRender.js +1 -1
- package/commonjs/VirtualScroller.onRender.js.map +1 -1
- package/commonjs/VirtualScroller.state.js +18 -9
- package/commonjs/VirtualScroller.state.js.map +1 -1
- package/commonjs/VirtualScroller.verticalSpacing.js +39 -6
- package/commonjs/VirtualScroller.verticalSpacing.js.map +1 -1
- package/commonjs/react/VirtualScroller.js +98 -37
- package/commonjs/react/VirtualScroller.js.map +1 -1
- package/commonjs/react/useClassName.js +2 -2
- package/commonjs/react/useClassName.js.map +1 -1
- package/commonjs/react/useForwardedRef.js +50 -0
- package/commonjs/react/useForwardedRef.js.map +1 -0
- package/commonjs/react/useInstanceMethods.js +4 -4
- package/commonjs/react/useInstanceMethods.js.map +1 -1
- package/commonjs/react/useItemKeys.js +28 -5
- package/commonjs/react/useItemKeys.js.map +1 -1
- package/commonjs/react/useOnItemHeightDidChange.js +28 -12
- package/commonjs/react/useOnItemHeightDidChange.js.map +1 -1
- package/commonjs/react/useSetItemState.js +31 -12
- package/commonjs/react/useSetItemState.js.map +1 -1
- package/commonjs/react/useState.js +10 -11
- package/commonjs/react/useState.js.map +1 -1
- package/commonjs/react/{useStateNoStaleBug.js → useStateWithRepeatableRead.js} +3 -3
- package/commonjs/react/useStateWithRepeatableRead.js.map +1 -0
- package/commonjs/react/useStyle.js +10 -4
- package/commonjs/react/useStyle.js.map +1 -1
- package/commonjs/react/useValidateTableBodyItemsContainer.js +24 -0
- package/commonjs/react/useValidateTableBodyItemsContainer.js.map +1 -0
- package/commonjs/react/useVirtualScroller.js +12 -14
- package/commonjs/react/useVirtualScroller.js.map +1 -1
- package/commonjs/test/ItemsContainer.js +10 -10
- package/commonjs/test/ItemsContainer.js.map +1 -1
- package/commonjs/test/VirtualScroller.js +25 -10
- package/commonjs/test/VirtualScroller.js.map +1 -1
- package/dom/index.d.ts +11 -9
- package/index.d.ts +19 -9
- package/modules/BeforeResize.js +1 -2
- package/modules/BeforeResize.js.map +1 -1
- package/modules/DOM/VirtualScroller.js +67 -44
- package/modules/DOM/VirtualScroller.js.map +1 -1
- package/modules/DOM/tbody.js +14 -13
- package/modules/DOM/tbody.js.map +1 -1
- package/modules/ItemHeights.js +11 -14
- package/modules/ItemHeights.js.map +1 -1
- package/modules/Layout.defaults.js +11 -0
- package/modules/Layout.defaults.js.map +1 -0
- package/modules/Layout.js +77 -67
- package/modules/Layout.js.map +1 -1
- package/modules/Layout.test.js +8 -4
- package/modules/Layout.test.js.map +1 -1
- package/modules/Scroll.js +3 -3
- package/modules/Scroll.js.map +1 -1
- package/modules/ScrollableContainerResizeHandler.js +4 -5
- package/modules/ScrollableContainerResizeHandler.js.map +1 -1
- package/modules/VirtualScroller.constructor.js +53 -31
- package/modules/VirtualScroller.constructor.js.map +1 -1
- package/modules/VirtualScroller.items.js +51 -5
- package/modules/VirtualScroller.items.js.map +1 -1
- package/modules/VirtualScroller.js +44 -28
- package/modules/VirtualScroller.js.map +1 -1
- package/modules/VirtualScroller.layout.js +42 -31
- package/modules/VirtualScroller.layout.js.map +1 -1
- package/modules/VirtualScroller.onContainerResize.js +1 -2
- package/modules/VirtualScroller.onContainerResize.js.map +1 -1
- package/modules/VirtualScroller.onRender.js +1 -1
- package/modules/VirtualScroller.onRender.js.map +1 -1
- package/modules/VirtualScroller.state.js +18 -9
- package/modules/VirtualScroller.state.js.map +1 -1
- package/modules/VirtualScroller.verticalSpacing.js +38 -6
- package/modules/VirtualScroller.verticalSpacing.js.map +1 -1
- package/modules/react/VirtualScroller.js +97 -38
- package/modules/react/VirtualScroller.js.map +1 -1
- package/modules/react/useClassName.js +3 -3
- package/modules/react/useClassName.js.map +1 -1
- package/modules/react/useForwardedRef.js +42 -0
- package/modules/react/useForwardedRef.js.map +1 -0
- package/modules/react/useInstanceMethods.js +4 -4
- package/modules/react/useInstanceMethods.js.map +1 -1
- package/modules/react/useItemKeys.js +28 -5
- package/modules/react/useItemKeys.js.map +1 -1
- package/modules/react/useOnItemHeightDidChange.js +28 -12
- package/modules/react/useOnItemHeightDidChange.js.map +1 -1
- package/modules/react/useSetItemState.js +31 -12
- package/modules/react/useSetItemState.js.map +1 -1
- package/modules/react/useState.js +10 -11
- package/modules/react/useState.js.map +1 -1
- package/modules/react/{useStateNoStaleBug.js → useStateWithRepeatableRead.js} +2 -2
- package/modules/react/useStateWithRepeatableRead.js.map +1 -0
- package/modules/react/useStyle.js +10 -4
- package/modules/react/useStyle.js.map +1 -1
- package/modules/react/useValidateTableBodyItemsContainer.js +16 -0
- package/modules/react/useValidateTableBodyItemsContainer.js.map +1 -0
- package/modules/react/useVirtualScroller.js +10 -12
- package/modules/react/useVirtualScroller.js.map +1 -1
- package/modules/test/ItemsContainer.js +10 -10
- package/modules/test/ItemsContainer.js.map +1 -1
- package/modules/test/VirtualScroller.js +25 -10
- package/modules/test/VirtualScroller.js.map +1 -1
- package/package.json +1 -1
- package/react/as.d.ts +42 -0
- package/react/index.d.ts +204 -63
- package/source/BeforeResize.js +1 -2
- package/source/DOM/VirtualScroller.js +65 -40
- package/source/DOM/tbody.js +15 -14
- package/source/ItemHeights.js +11 -12
- package/source/Layout.defaults.js +8 -0
- package/source/Layout.js +69 -56
- package/source/Layout.test.js +7 -2
- package/source/Scroll.js +3 -3
- package/source/ScrollableContainerResizeHandler.js +4 -4
- package/source/VirtualScroller.constructor.js +40 -31
- package/source/VirtualScroller.items.js +47 -2
- package/source/VirtualScroller.js +49 -27
- package/source/VirtualScroller.layout.js +43 -30
- package/source/VirtualScroller.onContainerResize.js +1 -2
- package/source/VirtualScroller.onRender.js +1 -1
- package/source/VirtualScroller.state.js +18 -11
- package/source/VirtualScroller.verticalSpacing.js +32 -6
- package/source/react/VirtualScroller.js +111 -36
- package/source/react/useClassName.js +3 -3
- package/source/react/useForwardedRef.js +39 -0
- package/source/react/useInstanceMethods.js +12 -4
- package/source/react/useItemKeys.js +22 -4
- package/source/react/useOnItemHeightDidChange.js +29 -10
- package/source/react/useSetItemState.js +32 -10
- package/source/react/useState.js +7 -8
- package/source/react/{useStateNoStaleBug.js → useStateWithRepeatableRead.js} +1 -1
- package/source/react/useStyle.js +3 -2
- package/source/react/useValidateTableBodyItemsContainer.js +16 -0
- package/source/react/useVirtualScroller.js +4 -6
- package/source/test/ItemsContainer.js +10 -10
- package/source/test/VirtualScroller.js +16 -10
- package/website/index-dom-bypass.html +198 -0
- package/website/index-dom-grid.html +204 -0
- package/website/index-dom-scrollableContainer.html +215 -0
- package/website/index-dom-tbody-scrollableContainer.html +81 -0
- package/website/index-dom-tbody.html +65 -0
- package/website/index-dom.html +117 -84
- package/website/index-react-bypass.html +200 -0
- package/website/{index-grid.html → index-react-grid.html} +79 -92
- package/website/index-react-scrollableContainer.html +213 -0
- package/website/index-react-strictMode.html +199 -0
- package/website/index-react-tbody-scrollableContainer.html +96 -0
- package/website/index-react-tbody.html +80 -0
- package/website/{index-bypass.html → index-react.html} +84 -70
- package/website/index.html +84 -69
- package/website/{messages.js → items.js} +1 -1
- package/website/lib/babel.min.js +25 -0
- package/website/lib/prop-types.min.js +1 -0
- package/website/lib/react-dom.development.js +29924 -0
- package/website/lib/react-dom.production.min.js +267 -0
- package/website/lib/react.development.js +3343 -0
- package/website/lib/react.production.min.js +31 -0
- package/website/style.base.css +33 -0
- package/website/style.list.css +92 -0
- package/website/style.list.grid.css +23 -0
- package/bundle/index-tbody-scrollableContainer.html +0 -70
- package/bundle/index-tbody.html +0 -57
- package/bundle/on-scroll-to-dom.js +0 -2
- package/bundle/on-scroll-to-dom.js.map +0 -1
- package/bundle/on-scroll-to-react.js +0 -2
- package/bundle/on-scroll-to-react.js.map +0 -1
- package/bundle/on-scroll-to.js +0 -2
- package/bundle/on-scroll-to.js.map +0 -1
- package/commonjs/react/useStateNoStaleBug.js.map +0 -1
- package/modules/react/useStateNoStaleBug.js.map +0 -1
- package/website/index-scrollableContainer.html +0 -208
- package/website/index-tbody-scrollableContainer.html +0 -70
- package/website/index-tbody.html +0 -57
- package/website/lib/on-scroll-to-dom.js +0 -2
- package/website/lib/on-scroll-to-dom.js.map +0 -1
- package/website/lib/on-scroll-to-react.js +0 -2
- package/website/lib/on-scroll-to-react.js.map +0 -1
package/source/Layout.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import log, { warn } from './utility/debug.js'
|
|
2
2
|
import ScrollableContainerNotReadyError from './ScrollableContainerNotReadyError.js'
|
|
3
|
+
import { DEFAULT_VISIBLE_ITEM_ROWS_COUNT } from './Layout.defaults.js'
|
|
3
4
|
|
|
4
5
|
export default class Layout {
|
|
5
6
|
constructor({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
getInitialEstimatedVisibleItemRowsCount,
|
|
7
|
+
isInBypassMode,
|
|
8
|
+
getEstimatedVisibleItemRowsCountForInitialRender,
|
|
9
9
|
measureItemsBatchSize,
|
|
10
10
|
getPrerenderMargin,
|
|
11
|
+
getPrerenderMarginRatio,
|
|
11
12
|
getVerticalSpacing,
|
|
12
13
|
getVerticalSpacingBeforeResize,
|
|
13
14
|
getColumnsCount,
|
|
@@ -19,11 +20,11 @@ export default class Layout {
|
|
|
19
20
|
getMaxVisibleAreaHeight,
|
|
20
21
|
getPreviouslyCalculatedLayout
|
|
21
22
|
}) {
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
24
|
-
this.getInitialEstimatedVisibleItemRowsCount = getInitialEstimatedVisibleItemRowsCount
|
|
23
|
+
this.isInBypassMode = isInBypassMode
|
|
24
|
+
this.getEstimatedVisibleItemRowsCountForInitialRender = getEstimatedVisibleItemRowsCountForInitialRender
|
|
25
25
|
this.measureItemsBatchSize = measureItemsBatchSize
|
|
26
26
|
this.getPrerenderMargin = getPrerenderMargin
|
|
27
|
+
this.getPrerenderMarginRatio = getPrerenderMarginRatio
|
|
27
28
|
this.getVerticalSpacing = getVerticalSpacing
|
|
28
29
|
this.getVerticalSpacingBeforeResize = getVerticalSpacingBeforeResize
|
|
29
30
|
this.getColumnsCount = getColumnsCount
|
|
@@ -69,6 +70,10 @@ export default class Layout {
|
|
|
69
70
|
}) {
|
|
70
71
|
let firstShownItemIndex
|
|
71
72
|
let lastShownItemIndex
|
|
73
|
+
|
|
74
|
+
let beforeItemsHeight = 0
|
|
75
|
+
let afterItemsHeight = 0
|
|
76
|
+
|
|
72
77
|
// If there're no items then `firstShownItemIndex` stays `undefined`.
|
|
73
78
|
if (itemsCount > 0) {
|
|
74
79
|
const getLastShownItemIndex = () => {
|
|
@@ -78,18 +83,30 @@ export default class Layout {
|
|
|
78
83
|
firstShownItemIndex
|
|
79
84
|
})
|
|
80
85
|
}
|
|
86
|
+
|
|
81
87
|
firstShownItemIndex = 0
|
|
88
|
+
|
|
82
89
|
lastShownItemIndex = beforeStart
|
|
83
90
|
? this.getInitialLayoutValueWithFallback(
|
|
84
91
|
'lastShownItemIndex',
|
|
85
92
|
getLastShownItemIndex,
|
|
86
|
-
|
|
93
|
+
firstShownItemIndex
|
|
87
94
|
)
|
|
88
95
|
: getLastShownItemIndex()
|
|
96
|
+
|
|
97
|
+
const averageItemHeight = this.getAverageItemHeight()
|
|
98
|
+
const verticalSpacing = this.getVerticalSpacing()
|
|
99
|
+
|
|
100
|
+
const beforeItemsCount = firstShownItemIndex
|
|
101
|
+
const afterItemsCount = itemsCount - (lastShownItemIndex + 1)
|
|
102
|
+
|
|
103
|
+
beforeItemsHeight = Math.ceil(beforeItemsCount / columnsCount) * (verticalSpacing + averageItemHeight)
|
|
104
|
+
afterItemsHeight = Math.ceil(afterItemsCount / columnsCount) * (verticalSpacing + averageItemHeight)
|
|
89
105
|
}
|
|
106
|
+
|
|
90
107
|
return {
|
|
91
|
-
beforeItemsHeight
|
|
92
|
-
afterItemsHeight
|
|
108
|
+
beforeItemsHeight,
|
|
109
|
+
afterItemsHeight,
|
|
93
110
|
firstShownItemIndex,
|
|
94
111
|
lastShownItemIndex
|
|
95
112
|
}
|
|
@@ -100,57 +117,50 @@ export default class Layout {
|
|
|
100
117
|
columnsCount,
|
|
101
118
|
firstShownItemIndex
|
|
102
119
|
}) {
|
|
103
|
-
if (this.
|
|
120
|
+
if (this.isInBypassMode()) {
|
|
104
121
|
return itemsCount - 1
|
|
105
122
|
}
|
|
106
|
-
// On server side, at initialization time,
|
|
107
|
-
// `scrollableContainer` is `undefined`,
|
|
108
|
-
// so default to `1` estimated rows count.
|
|
109
|
-
let estimatedRowsCount = 1
|
|
110
|
-
if (this.getMaxVisibleAreaHeight()) {
|
|
111
|
-
estimatedRowsCount = this.getEstimatedRowsCountForHeight(this.getMaxVisibleAreaHeight() + this.getPrerenderMargin())
|
|
112
|
-
} else if (this.getInitialEstimatedVisibleItemRowsCount) {
|
|
113
|
-
estimatedRowsCount = this.getInitialEstimatedVisibleItemRowsCount()
|
|
114
|
-
if (isNaN(estimatedRowsCount)) {
|
|
115
|
-
throw new Error('[virtual-scroller] `getEstimatedVisibleItemRowsCount()` must return a number')
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
123
|
return Math.min(
|
|
119
|
-
firstShownItemIndex + (
|
|
124
|
+
firstShownItemIndex + (this.getInitialRenderedRowsCount() * columnsCount - 1),
|
|
120
125
|
itemsCount - 1
|
|
121
126
|
)
|
|
122
127
|
}
|
|
123
128
|
|
|
124
|
-
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return Math.ceil((height + verticalSpacing) / (estimatedItemHeight + verticalSpacing))
|
|
129
|
-
} else {
|
|
130
|
-
// If no items have been rendered yet, and no `estimatedItemHeight` option
|
|
131
|
-
// has been passed, then default to `1` estimated rows count in any `height`.
|
|
132
|
-
return 1
|
|
129
|
+
getInitialRenderedRowsCount() {
|
|
130
|
+
const estimatedVisibleItemRowsCount = this.getEstimatedVisibleItemRowsCount()
|
|
131
|
+
if (typeof estimatedVisibleItemRowsCount === 'number') {
|
|
132
|
+
return Math.ceil(estimatedVisibleItemRowsCount * (1 + this.getPrerenderMarginRatio()))
|
|
133
133
|
}
|
|
134
|
+
// `DEFAULT_VISIBLE_ITEM_ROWS_COUNT` will be used in server-side render
|
|
135
|
+
// unless `getEstimatedVisibleItemRowsCount()` parameter is specified.
|
|
136
|
+
return DEFAULT_VISIBLE_ITEM_ROWS_COUNT
|
|
134
137
|
}
|
|
135
138
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (averageItemHeight) {
|
|
144
|
-
return averageItemHeight
|
|
139
|
+
getEstimatedVisibleItemRowsCount() {
|
|
140
|
+
const maxVisibleAreaHeight = this.getMaxVisibleAreaHeight()
|
|
141
|
+
if (typeof maxVisibleAreaHeight === 'number') {
|
|
142
|
+
const estimatedRowsCount = this.getEstimatedRowsCountForHeight(maxVisibleAreaHeight)
|
|
143
|
+
if (typeof estimatedRowsCount === 'number') {
|
|
144
|
+
return estimatedRowsCount
|
|
145
|
+
}
|
|
145
146
|
}
|
|
146
|
-
if (this.
|
|
147
|
-
const
|
|
148
|
-
if (
|
|
149
|
-
|
|
147
|
+
if (this.getEstimatedVisibleItemRowsCountForInitialRender) {
|
|
148
|
+
const estimatedRowsCount = this.getEstimatedVisibleItemRowsCountForInitialRender()
|
|
149
|
+
if (typeof estimatedRowsCount === 'number') {
|
|
150
|
+
return estimatedRowsCount
|
|
150
151
|
}
|
|
151
|
-
return
|
|
152
|
+
throw new Error('[virtual-scroller] `getEstimatedVisibleItemRowsCount()` must return a number')
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
getEstimatedRowsCountForHeight(height) {
|
|
157
|
+
const averageItemHeight = this.getAverageItemHeight()
|
|
158
|
+
const verticalSpacing = this.getVerticalSpacing()
|
|
159
|
+
// `estimatedItemHeight` will most likely be `0` if it hasn't been specified explicitly.
|
|
160
|
+
// In that case, it can't divide by `0`.
|
|
161
|
+
if (averageItemHeight + verticalSpacing > 0) {
|
|
162
|
+
return Math.ceil((height + verticalSpacing) / (averageItemHeight + verticalSpacing))
|
|
152
163
|
}
|
|
153
|
-
return 0
|
|
154
164
|
}
|
|
155
165
|
|
|
156
166
|
getLayoutUpdateForItemsDiff({
|
|
@@ -328,8 +338,17 @@ export default class Layout {
|
|
|
328
338
|
|
|
329
339
|
const columnsCount = this.getColumnsCount()
|
|
330
340
|
|
|
341
|
+
const getNonMeasuredItemRowsCount = () => {
|
|
342
|
+
const estimatedRowsCount = this.getEstimatedRowsCountForHeight(nonMeasuredAreaHeight)
|
|
343
|
+
if (typeof estimatedRowsCount === 'number') {
|
|
344
|
+
return estimatedRowsCount
|
|
345
|
+
}
|
|
346
|
+
// Render all available item rows as a sensible fallback behavior.
|
|
347
|
+
return Math.ceil(itemsCount / columnsCount)
|
|
348
|
+
}
|
|
349
|
+
|
|
331
350
|
const itemsCountToRenderForMeasurement = Math.min(
|
|
332
|
-
|
|
351
|
+
getNonMeasuredItemRowsCount() * columnsCount,
|
|
333
352
|
this.measureItemsBatchSize || Infinity,
|
|
334
353
|
)
|
|
335
354
|
|
|
@@ -434,15 +453,12 @@ export default class Layout {
|
|
|
434
453
|
// then `shownItemsHeight` would also have to be returned from this function:
|
|
435
454
|
// the total height of all shown items including vertical spacing between them.
|
|
436
455
|
//
|
|
437
|
-
// If "previously calculated layout" would be used then it would first
|
|
438
|
-
// `firstShownItemIndex` and then
|
|
456
|
+
// If "previously calculated layout" would be used then it would first calculate
|
|
457
|
+
// `firstShownItemIndex` and then calculate `lastShownItemIndex` as part of two
|
|
439
458
|
// separate calls of this function, each with or without `backwards` flag,
|
|
440
459
|
// depending on whether `visibleAreaInsideTheList.top` and `visibleAreaInsideTheList.top`
|
|
441
460
|
// have shifted up or down.
|
|
442
461
|
|
|
443
|
-
let firstShownItemIndex
|
|
444
|
-
let lastShownItemIndex
|
|
445
|
-
|
|
446
462
|
// It's not always required to pass `beforeItemsHeight` parameter:
|
|
447
463
|
// when `fromIndex` is `0`, it's also assumed to be `0`.
|
|
448
464
|
if (fromIndex === 0) {
|
|
@@ -678,8 +694,6 @@ export default class Layout {
|
|
|
678
694
|
const verticalSpacing = beforeResize ? this.getVerticalSpacingBeforeResize() : this.getVerticalSpacing()
|
|
679
695
|
|
|
680
696
|
while (i < beforeItemsCount) {
|
|
681
|
-
const currentRowFirstItemIndex = i
|
|
682
|
-
|
|
683
697
|
let rowHeight = 0
|
|
684
698
|
let columnIndex = 0
|
|
685
699
|
// Not checking for `itemsCount` overflow here because `i = beforeItemsCount`
|
|
@@ -734,7 +748,6 @@ export default class Layout {
|
|
|
734
748
|
// Which becomes negligible in my project's use case (a couple thousands items max).
|
|
735
749
|
|
|
736
750
|
const columnsCount = this.getColumnsCount()
|
|
737
|
-
const lastShownRowIndex = Math.floor(lastShownItemIndex / columnsCount)
|
|
738
751
|
|
|
739
752
|
let afterItemsHeight = 0
|
|
740
753
|
|
package/source/Layout.test.js
CHANGED
|
@@ -158,9 +158,11 @@ describe('Layout', function() {
|
|
|
158
158
|
|
|
159
159
|
let shouldResetGridLayout
|
|
160
160
|
|
|
161
|
+
// Don't `throw` `VirtualScroller` errors but rather collect them in an array.
|
|
161
162
|
const errors = []
|
|
162
|
-
|
|
163
|
-
|
|
163
|
+
global.VirtualScrollerCatchError = (error) => {
|
|
164
|
+
errors.push(error)
|
|
165
|
+
}
|
|
164
166
|
|
|
165
167
|
layout.getLayoutUpdateForItemsDiff(
|
|
166
168
|
{
|
|
@@ -185,7 +187,10 @@ describe('Layout', function() {
|
|
|
185
187
|
afterItemsHeight: 5 * (ITEM_HEIGHT + VERTICAL_SPACING)
|
|
186
188
|
})
|
|
187
189
|
|
|
190
|
+
// Stop collecting `VirtualScroller` errors in the `errors` array.
|
|
191
|
+
// Use the default behavior of just `throw`-ing such errors.
|
|
188
192
|
global.VirtualScrollerCatchError = undefined
|
|
193
|
+
// Verify the errors that have been `throw`-n.
|
|
189
194
|
errors.length.should.equal(2)
|
|
190
195
|
errors[0].message.should.equal('[virtual-scroller] ~ Prepended items count 5 is not divisible by Columns Count 4 ~')
|
|
191
196
|
errors[1].message.should.equal('[virtual-scroller] Layout reset required')
|
package/source/Scroll.js
CHANGED
|
@@ -8,7 +8,7 @@ import log from './utility/debug.js'
|
|
|
8
8
|
|
|
9
9
|
export default class Scroll {
|
|
10
10
|
constructor({
|
|
11
|
-
|
|
11
|
+
isInBypassMode,
|
|
12
12
|
scrollableContainer,
|
|
13
13
|
itemsContainer,
|
|
14
14
|
onScroll,
|
|
@@ -23,7 +23,7 @@ export default class Scroll {
|
|
|
23
23
|
onScrolledToTop,
|
|
24
24
|
waitForScrollingToStop
|
|
25
25
|
}) {
|
|
26
|
-
this.
|
|
26
|
+
this.isInBypassMode = isInBypassMode
|
|
27
27
|
this.scrollableContainer = scrollableContainer
|
|
28
28
|
this.itemsContainer = itemsContainer
|
|
29
29
|
this.onScroll = onScroll
|
|
@@ -98,7 +98,7 @@ export default class Scroll {
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
if (this.
|
|
101
|
+
if (this.isInBypassMode()) {
|
|
102
102
|
return
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import debounce from './utility/debounce.js'
|
|
2
|
-
import log from './utility/debug.js'
|
|
2
|
+
// import log from './utility/debug.js'
|
|
3
3
|
|
|
4
4
|
export default class ScrollableContainerResizeHandler {
|
|
5
5
|
constructor({
|
|
6
|
-
|
|
6
|
+
isInBypassMode,
|
|
7
7
|
getWidth,
|
|
8
8
|
getHeight,
|
|
9
9
|
listenForResize,
|
|
@@ -13,7 +13,7 @@ export default class ScrollableContainerResizeHandler {
|
|
|
13
13
|
onWidthChange,
|
|
14
14
|
onNoChange
|
|
15
15
|
}) {
|
|
16
|
-
this.
|
|
16
|
+
this.isInBypassMode = isInBypassMode
|
|
17
17
|
|
|
18
18
|
this.onHeightChange = onHeightChange
|
|
19
19
|
this.onWidthChange = onWidthChange
|
|
@@ -35,7 +35,7 @@ export default class ScrollableContainerResizeHandler {
|
|
|
35
35
|
|
|
36
36
|
start() {
|
|
37
37
|
this.isActive = true
|
|
38
|
-
if (this.
|
|
38
|
+
if (this.isInBypassMode()) {
|
|
39
39
|
return
|
|
40
40
|
}
|
|
41
41
|
this.width = this.getWidth()
|
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
supportsTbody,
|
|
3
|
-
BROWSER_NOT_SUPPORTED_ERROR
|
|
4
|
-
} from './DOM/tbody.js'
|
|
5
|
-
|
|
6
1
|
import DOMEngine from './DOM/Engine.js'
|
|
7
2
|
|
|
8
3
|
import Layout, { LAYOUT_REASON } from './Layout.js'
|
|
4
|
+
import { DEFAULT_ITEM_HEIGHT } from './Layout.defaults.js'
|
|
9
5
|
import ScrollableContainerResizeHandler from './ScrollableContainerResizeHandler.js'
|
|
10
6
|
import BeforeResize from './BeforeResize.js'
|
|
11
7
|
import Scroll from './Scroll.js'
|
|
12
8
|
import ListHeightMeasurement from './ListHeightMeasurement.js'
|
|
13
9
|
import ItemHeights from './ItemHeights.js'
|
|
14
10
|
|
|
15
|
-
import log, { warn
|
|
11
|
+
import log, { warn } from './utility/debug.js'
|
|
16
12
|
|
|
17
13
|
import createStateHelpers from './VirtualScroller.state.js'
|
|
18
14
|
import createVerticalSpacingHelpers from './VirtualScroller.verticalSpacing.js'
|
|
@@ -34,6 +30,7 @@ export default function VirtualScrollerConstructor(
|
|
|
34
30
|
options = {}
|
|
35
31
|
) {
|
|
36
32
|
const {
|
|
33
|
+
bypass,
|
|
37
34
|
render,
|
|
38
35
|
state,
|
|
39
36
|
getInitialItemState = () => {},
|
|
@@ -46,10 +43,10 @@ export default function VirtualScrollerConstructor(
|
|
|
46
43
|
measureItemsBatchSize = 50,
|
|
47
44
|
getColumnsCount,
|
|
48
45
|
getItemId,
|
|
49
|
-
tbody,
|
|
50
46
|
// `estimatedItemHeight` is deprecated, use `getEstimatedItemHeight()` instead.
|
|
51
47
|
estimatedItemHeight,
|
|
52
48
|
getEstimatedVisibleItemRowsCount,
|
|
49
|
+
getEstimatedInterItemVerticalSpacing,
|
|
53
50
|
onItemInitialRender,
|
|
54
51
|
// `onItemFirstRender(i)` is deprecated, use `onItemInitialRender(item)` instead.
|
|
55
52
|
onItemFirstRender,
|
|
@@ -59,7 +56,6 @@ export default function VirtualScrollerConstructor(
|
|
|
59
56
|
} = options
|
|
60
57
|
|
|
61
58
|
let {
|
|
62
|
-
bypass,
|
|
63
59
|
getEstimatedItemHeight,
|
|
64
60
|
getScrollableContainer
|
|
65
61
|
} = options
|
|
@@ -104,21 +100,6 @@ export default function VirtualScrollerConstructor(
|
|
|
104
100
|
throw new Error('[virtual-scroller] `getState`/`setState` options usage has changed in the new version. See the readme for more details.')
|
|
105
101
|
}
|
|
106
102
|
|
|
107
|
-
// Work around `<tbody/>` not being able to have `padding`.
|
|
108
|
-
// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1
|
|
109
|
-
if (tbody) {
|
|
110
|
-
if (this.engine !== DOMEngine) {
|
|
111
|
-
throw new Error('[virtual-scroller] `tbody` option is only supported for DOM rendering engine')
|
|
112
|
-
}
|
|
113
|
-
log('~ <tbody/> detected ~')
|
|
114
|
-
this.tbody = true
|
|
115
|
-
if (!supportsTbody()) {
|
|
116
|
-
log('~ <tbody/> not supported ~')
|
|
117
|
-
reportError(BROWSER_NOT_SUPPORTED_ERROR)
|
|
118
|
-
bypass = true
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
103
|
if (bypass) {
|
|
123
104
|
log('~ "bypass" mode ~')
|
|
124
105
|
}
|
|
@@ -133,7 +114,7 @@ export default function VirtualScrollerConstructor(
|
|
|
133
114
|
// It turned out that unmounting large React component trees
|
|
134
115
|
// is a very long process, so `VirtualScroller` does seem to
|
|
135
116
|
// make sense when used in a React application.
|
|
136
|
-
this.
|
|
117
|
+
this._bypass = bypass
|
|
137
118
|
// this.bypassBatchSize = bypassBatchSize || 10
|
|
138
119
|
|
|
139
120
|
// Using `setTimeout()` in render loop is a workaround
|
|
@@ -188,7 +169,7 @@ export default function VirtualScrollerConstructor(
|
|
|
188
169
|
|
|
189
170
|
createStateHelpers.call(this, { state, getInitialItemState, onStateChange, render, items })
|
|
190
171
|
|
|
191
|
-
createVerticalSpacingHelpers.call(this)
|
|
172
|
+
createVerticalSpacingHelpers.call(this, { getEstimatedInterItemVerticalSpacing })
|
|
192
173
|
createColumnsHelpers.call(this, { getColumnsCount })
|
|
193
174
|
|
|
194
175
|
createLayoutHelpers.call(this)
|
|
@@ -238,6 +219,13 @@ function createHelpers({
|
|
|
238
219
|
this.itemsContainer.clear()
|
|
239
220
|
}
|
|
240
221
|
|
|
222
|
+
this.isItemsContainerElementTableBody = () => {
|
|
223
|
+
return this.engine === DOMEngine &&
|
|
224
|
+
this.getItemsContainerElement().tagName === 'TBODY'
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
this.isInBypassMode = () => this._bypass
|
|
228
|
+
|
|
241
229
|
this.scrollableContainer = this.engine.createScrollableContainer(
|
|
242
230
|
getScrollableContainer,
|
|
243
231
|
this.getItemsContainerElement
|
|
@@ -250,12 +238,33 @@ function createHelpers({
|
|
|
250
238
|
setItemHeight: (i, height) => this.getState().itemHeights[i] = height
|
|
251
239
|
})
|
|
252
240
|
|
|
241
|
+
this.getAverageItemHeight = () => {
|
|
242
|
+
const averageItemHeight = this.itemHeights.getAverageItemHeight()
|
|
243
|
+
if (typeof averageItemHeight === 'number') {
|
|
244
|
+
return averageItemHeight
|
|
245
|
+
}
|
|
246
|
+
return this.getEstimatedItemHeight()
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
this.getEstimatedItemHeight = () => {
|
|
250
|
+
if (getEstimatedItemHeight) {
|
|
251
|
+
const estimatedItemHeight = getEstimatedItemHeight()
|
|
252
|
+
if (typeof estimatedItemHeight === 'number') {
|
|
253
|
+
return estimatedItemHeight
|
|
254
|
+
}
|
|
255
|
+
throw new Error('[virtual-scroller] `getEstimatedItemHeight()` must return a number')
|
|
256
|
+
}
|
|
257
|
+
// `DEFAULT_ITEM_HEIGHT` will be used in server-side render
|
|
258
|
+
// unless `getEstimatedItemHeight()` parameter is specified.
|
|
259
|
+
return DEFAULT_ITEM_HEIGHT
|
|
260
|
+
}
|
|
261
|
+
|
|
253
262
|
this.layout = new Layout({
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
getInitialEstimatedVisibleItemRowsCount: getEstimatedVisibleItemRowsCount,
|
|
263
|
+
isInBypassMode: this.isInBypassMode,
|
|
264
|
+
getEstimatedVisibleItemRowsCountForInitialRender: getEstimatedVisibleItemRowsCount,
|
|
257
265
|
measureItemsBatchSize,
|
|
258
266
|
getPrerenderMargin: () => this.getPrerenderMargin(),
|
|
267
|
+
getPrerenderMarginRatio: () => this.getPrerenderMarginRatio(),
|
|
259
268
|
getVerticalSpacing: () => this.getVerticalSpacing(),
|
|
260
269
|
getVerticalSpacingBeforeResize: () => this.getVerticalSpacingBeforeResize(),
|
|
261
270
|
getColumnsCount: () => this.getColumnsCount(),
|
|
@@ -263,7 +272,7 @@ function createHelpers({
|
|
|
263
272
|
getItemHeight: (i) => this.getState().itemHeights[i],
|
|
264
273
|
getItemHeightBeforeResize: (i) => this.getState().beforeResize && this.getState().beforeResize.itemHeights[i],
|
|
265
274
|
getBeforeResizeItemsCount: () => this.getState().beforeResize ? this.getState().beforeResize.itemHeights.length : 0,
|
|
266
|
-
getAverageItemHeight: () => this.
|
|
275
|
+
getAverageItemHeight: () => this.getAverageItemHeight(),
|
|
267
276
|
// `this.scrollableContainer` is gonna be `undefined` during server-side rendering.
|
|
268
277
|
// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/30
|
|
269
278
|
getMaxVisibleAreaHeight: () => this.scrollableContainer && this.scrollableContainer.getHeight(),
|
|
@@ -278,7 +287,7 @@ function createHelpers({
|
|
|
278
287
|
})
|
|
279
288
|
|
|
280
289
|
this.scrollableContainerResizeHandler = new ScrollableContainerResizeHandler({
|
|
281
|
-
|
|
290
|
+
isInBypassMode: this.isInBypassMode,
|
|
282
291
|
getWidth: () => this.scrollableContainer.getWidth(),
|
|
283
292
|
getHeight: () => this.scrollableContainer.getHeight(),
|
|
284
293
|
listenForResize: (listener) => this.scrollableContainer.onResize(listener),
|
|
@@ -308,7 +317,7 @@ function createHelpers({
|
|
|
308
317
|
})
|
|
309
318
|
|
|
310
319
|
this.scroll = new Scroll({
|
|
311
|
-
|
|
320
|
+
isInBypassMode: this.isInBypassMode,
|
|
312
321
|
scrollableContainer: this.scrollableContainer,
|
|
313
322
|
itemsContainer: this.itemsContainer,
|
|
314
323
|
waitForScrollingToStop,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import log, {
|
|
1
|
+
import log, { reportError } from './utility/debug.js'
|
|
2
2
|
import getItemsDiff from './getItemsDiff.js'
|
|
3
3
|
import fillArray from './utility/fillArray.js'
|
|
4
4
|
|
|
@@ -7,6 +7,49 @@ export default function() {
|
|
|
7
7
|
return this.getState().items.length
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
this._getItemIndexByItemOrIndex = (itemOrIndex) => {
|
|
11
|
+
const item = itemOrIndex
|
|
12
|
+
const { items } = this.getState()
|
|
13
|
+
// Find the `item`'s index in the `items` array.
|
|
14
|
+
//
|
|
15
|
+
// Performance notes:
|
|
16
|
+
// Doing an `.indexOf()` operation on a very large array could be inefficient
|
|
17
|
+
// because it would have to check every element of the array.
|
|
18
|
+
// In case of any hypothetical performance-related issues,
|
|
19
|
+
// the code could use a `new Map()` as an "index" for finding individual items.
|
|
20
|
+
const i = items.indexOf(item)
|
|
21
|
+
// validate that the `item` exists in the `items` array.
|
|
22
|
+
if (i >= 0) {
|
|
23
|
+
return i
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Legacy behavior: some functions used to accept an `i: number` item index as an argument.
|
|
27
|
+
// Later the argument was changed to `item: Item`.
|
|
28
|
+
//
|
|
29
|
+
// The old way of passing an `i: number` argument would only result in weird application behavior
|
|
30
|
+
// when all of the below circumstances are true, which is assumed extremely unlikely:
|
|
31
|
+
//
|
|
32
|
+
// BOTH use a previous version of `virtual-scroller` (ones before December 2025, with downloads count that is not very high)
|
|
33
|
+
// AND to be used with an `items` array of type `number[]`
|
|
34
|
+
// AND to use any of the "advanced" functions:
|
|
35
|
+
// * `setItemState(i, newState)`
|
|
36
|
+
// * `onItemHeightDidChange(i)`
|
|
37
|
+
// * `getItemScrollPosition(i)`
|
|
38
|
+
//
|
|
39
|
+
// The code below handles the legacy compatibility aspect of the old type of argument
|
|
40
|
+
// except maybe for those "extremely unlikely" cases in which the app is still unlikely to crash.
|
|
41
|
+
//
|
|
42
|
+
if (typeof itemOrIndex === 'number') {
|
|
43
|
+
const i = itemOrIndex
|
|
44
|
+
// Validate the item index argument.
|
|
45
|
+
if (i >= 0 && i < items.length) {
|
|
46
|
+
return i
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
reportError(`Item not found: ${JSON.stringify(item)}`)
|
|
51
|
+
}
|
|
52
|
+
|
|
10
53
|
/**
|
|
11
54
|
* Updates `items`. For example, can prepend or append new items to the list.
|
|
12
55
|
* @param {any[]} newItems
|
|
@@ -81,7 +124,9 @@ export default function() {
|
|
|
81
124
|
if (prependedItemsCount > 0) {
|
|
82
125
|
log('Prepend', prependedItemsCount, 'items')
|
|
83
126
|
|
|
84
|
-
itemHeights = new Array(prependedItemsCount)
|
|
127
|
+
itemHeights = new Array(prependedItemsCount)
|
|
128
|
+
.concat(itemHeights)
|
|
129
|
+
|
|
85
130
|
itemStates = fillArray(
|
|
86
131
|
new Array(prependedItemsCount),
|
|
87
132
|
(i) => this.getInitialItemState(newItems[i])
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import VirtualScrollerConstructor from './VirtualScroller.constructor.js'
|
|
2
|
-
import { hasTbodyStyles, addTbodyStyles } from './DOM/tbody.js'
|
|
3
2
|
import { LAYOUT_REASON } from './Layout.js'
|
|
4
|
-
import log, { warn } from './utility/debug.js'
|
|
3
|
+
import log, { warn, reportError } from './utility/debug.js'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
supportsTbody,
|
|
7
|
+
hasTbodyStyles,
|
|
8
|
+
addTbodyStyles,
|
|
9
|
+
BROWSER_NOT_SUPPORTED_ERROR
|
|
10
|
+
} from './DOM/tbody.js'
|
|
5
11
|
|
|
6
12
|
export default class VirtualScroller {
|
|
7
13
|
/**
|
|
8
|
-
* @param {function} getItemsContainerElement — Returns the container DOM `Element`.
|
|
14
|
+
* @param {function} getItemsContainerElement — Returns the items container DOM `Element`.
|
|
9
15
|
* @param {any[]} items — The list of items.
|
|
10
16
|
* @param {Object} [options] — See README.md.
|
|
11
17
|
* @return {VirtualScroller}
|
|
@@ -35,13 +41,8 @@ export default class VirtualScroller {
|
|
|
35
41
|
const isRestart = this._isActive === false
|
|
36
42
|
|
|
37
43
|
if (!isRestart) {
|
|
44
|
+
this.setUpState()
|
|
38
45
|
this.waitingForRender = true
|
|
39
|
-
|
|
40
|
-
// If no custom state storage has been configured, use the default one.
|
|
41
|
-
// Also sets the initial state.
|
|
42
|
-
if (!this._usesCustomStateStorage) {
|
|
43
|
-
this.useDefaultStateStorage()
|
|
44
|
-
}
|
|
45
46
|
// If `render()` function parameter was passed,
|
|
46
47
|
// perform an initial render.
|
|
47
48
|
if (this._render) {
|
|
@@ -67,11 +68,23 @@ export default class VirtualScroller {
|
|
|
67
68
|
// Reset `_isSettingNewItems` flag just in case it has some "leftover" value.
|
|
68
69
|
this._isSettingNewItems = undefined
|
|
69
70
|
|
|
70
|
-
//
|
|
71
|
+
// When `<tbody/>` is used as an items container element,
|
|
72
|
+
// `virtual-scroller` has to work around the HTML bug of
|
|
73
|
+
// `padding` not working on a `<tbody/>` element.
|
|
71
74
|
// https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1
|
|
72
|
-
if (this.
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
+
if (!this.isInBypassMode()) {
|
|
76
|
+
if (this.isItemsContainerElementTableBody()) {
|
|
77
|
+
if (supportsTbody()) {
|
|
78
|
+
if (!hasTbodyStyles(this.getItemsContainerElement())) {
|
|
79
|
+
log('~ <tbody/> container ~')
|
|
80
|
+
addTbodyStyles(this.getItemsContainerElement())
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
log('~ <tbody/> container not supported ~')
|
|
84
|
+
reportError(BROWSER_NOT_SUPPORTED_ERROR)
|
|
85
|
+
log('~ enter "bypass" mode ~')
|
|
86
|
+
this._bypass = true
|
|
87
|
+
}
|
|
75
88
|
}
|
|
76
89
|
}
|
|
77
90
|
|
|
@@ -193,10 +206,19 @@ export default class VirtualScroller {
|
|
|
193
206
|
|
|
194
207
|
/**
|
|
195
208
|
* Returns the items's top offset relative to the scrollable container's top edge.
|
|
196
|
-
* @param {
|
|
209
|
+
* @param {any} item — Item
|
|
197
210
|
* @return {[number]} Returns the item's scroll Y position. Returns `undefined` if any of the previous items haven't been rendered yet.
|
|
198
211
|
*/
|
|
199
|
-
getItemScrollPosition(
|
|
212
|
+
getItemScrollPosition(itemOrIndex) {
|
|
213
|
+
// Item index.
|
|
214
|
+
const i = this._getItemIndexByItemOrIndex(itemOrIndex)
|
|
215
|
+
|
|
216
|
+
// If the item wasn't found, the error was already reported,
|
|
217
|
+
// so just return some "sensible" default value.
|
|
218
|
+
if (i === undefined) {
|
|
219
|
+
return
|
|
220
|
+
}
|
|
221
|
+
|
|
200
222
|
const itemTopOffsetInList = this.layout.getItemTopOffset(i)
|
|
201
223
|
if (itemTopOffsetInList === undefined) {
|
|
202
224
|
return
|
|
@@ -208,28 +230,28 @@ export default class VirtualScroller {
|
|
|
208
230
|
* @deprecated
|
|
209
231
|
* `.onItemHeightChange()` has been renamed to `.onItemHeightDidChange()`.
|
|
210
232
|
*/
|
|
211
|
-
onItemHeightChange(
|
|
212
|
-
warn('`.onItemHeightChange(
|
|
213
|
-
this.onItemHeightDidChange(
|
|
233
|
+
onItemHeightChange(item) {
|
|
234
|
+
warn('`.onItemHeightChange(item)` method was renamed to `.onItemHeightDidChange(item)`')
|
|
235
|
+
this.onItemHeightDidChange(item)
|
|
214
236
|
}
|
|
215
237
|
|
|
216
238
|
/**
|
|
217
239
|
* Forces a re-measure of an item's height.
|
|
218
|
-
* @param
|
|
240
|
+
* @param {any} item — Item. Legacy argument variant: Item index.
|
|
219
241
|
*/
|
|
220
|
-
onItemHeightDidChange(
|
|
242
|
+
onItemHeightDidChange(itemOrIndex) {
|
|
221
243
|
// See the comments in the `setItemState()` function below for the rationale
|
|
222
244
|
// on why the `hasToBeStarted()` check was commented out.
|
|
223
245
|
// this.hasToBeStarted()
|
|
224
|
-
this._onItemHeightDidChange(
|
|
246
|
+
this._onItemHeightDidChange(itemOrIndex)
|
|
225
247
|
}
|
|
226
248
|
|
|
227
249
|
/**
|
|
228
250
|
* Updates an item's state in `state.itemStates[]`.
|
|
229
|
-
* @param {
|
|
230
|
-
* @param {any}
|
|
251
|
+
* @param {any} item — Item. Legacy argument variant: Item index.
|
|
252
|
+
* @param {any} newItemState — Item's new state
|
|
231
253
|
*/
|
|
232
|
-
setItemState(
|
|
254
|
+
setItemState(itemOrIndex, newItemState) {
|
|
233
255
|
// There is an issue in React 18.2.0 when `useInsertionEffect()` doesn't run twice
|
|
234
256
|
// on mount unlike `useLayoutEffect()` in "strict" mode. That causes a bug in a React
|
|
235
257
|
// implementation of the `virtual-scroller`.
|
|
@@ -272,13 +294,13 @@ export default class VirtualScroller {
|
|
|
272
294
|
// Commenting it out wouldn't result in any potential bugs because the code would work correctly
|
|
273
295
|
// in both cases.
|
|
274
296
|
// this.hasToBeStarted()
|
|
275
|
-
this._setItemState(
|
|
297
|
+
this._setItemState(itemOrIndex, newItemState)
|
|
276
298
|
}
|
|
277
299
|
|
|
278
300
|
// (deprecated)
|
|
279
301
|
// Use `.setItemState()` method name instead.
|
|
280
|
-
onItemStateChange(
|
|
281
|
-
this.setItemState(
|
|
302
|
+
onItemStateChange(item, newItemState) {
|
|
303
|
+
this.setItemState(item, newItemState)
|
|
282
304
|
}
|
|
283
305
|
|
|
284
306
|
/**
|