virtual-scroller 1.7.9 → 1.9.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/.gitlab-ci.yml +1 -1
- package/CHANGELOG.md +71 -1
- package/README.md +434 -151
- package/bundle/index-bypass.html +1 -1
- package/bundle/index-dom.html +1 -1
- package/bundle/index-grid.html +1 -2
- package/bundle/index-scrollableContainer.html +1 -1
- package/bundle/index-tbody-scrollableContainer.html +2 -0
- package/bundle/index-tbody.html +2 -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 +315 -0
- package/commonjs/BeforeResize.js.map +1 -0
- package/commonjs/DOM/Engine.js +46 -0
- package/commonjs/DOM/Engine.js.map +1 -0
- package/commonjs/DOM/ItemsContainer.js +78 -0
- package/commonjs/DOM/ItemsContainer.js.map +1 -0
- package/commonjs/DOM/{WaitForStylesToLoad.js → ListTopOffsetWatcher.js} +71 -44
- package/commonjs/DOM/ListTopOffsetWatcher.js.map +1 -0
- package/commonjs/DOM/ScrollableContainer.js +69 -101
- package/commonjs/DOM/ScrollableContainer.js.map +1 -1
- package/commonjs/DOM/VirtualScroller.js +37 -29
- package/commonjs/DOM/VirtualScroller.js.map +1 -1
- package/commonjs/DOM/tbody.js +17 -11
- package/commonjs/DOM/tbody.js.map +1 -1
- package/commonjs/ItemHeights.js +33 -34
- package/commonjs/ItemHeights.js.map +1 -1
- package/commonjs/Layout.js +591 -216
- package/commonjs/Layout.js.map +1 -1
- package/commonjs/Layout.test.js +196 -0
- package/commonjs/Layout.test.js.map +1 -0
- package/commonjs/ListHeightMeasurement.js +124 -0
- package/commonjs/ListHeightMeasurement.js.map +1 -0
- package/commonjs/Resize.js +50 -39
- package/commonjs/Resize.js.map +1 -1
- package/commonjs/Scroll.js +139 -95
- package/commonjs/Scroll.js.map +1 -1
- package/commonjs/VirtualScroller.columns.js +43 -0
- package/commonjs/VirtualScroller.columns.js.map +1 -0
- package/commonjs/VirtualScroller.constructor.js +408 -0
- package/commonjs/VirtualScroller.constructor.js.map +1 -0
- package/commonjs/VirtualScroller.items.js +305 -0
- package/commonjs/VirtualScroller.items.js.map +1 -0
- package/commonjs/VirtualScroller.js +160 -1021
- package/commonjs/VirtualScroller.js.map +1 -1
- package/commonjs/VirtualScroller.layout.js +562 -0
- package/commonjs/VirtualScroller.layout.js.map +1 -0
- package/commonjs/VirtualScroller.onRender.js +357 -0
- package/commonjs/VirtualScroller.onRender.js.map +1 -0
- package/commonjs/VirtualScroller.resize.js +186 -0
- package/commonjs/VirtualScroller.resize.js.map +1 -0
- package/commonjs/VirtualScroller.state.js +301 -0
- package/commonjs/VirtualScroller.state.js.map +1 -0
- package/commonjs/VirtualScroller.verticalSpacing.js +65 -0
- package/commonjs/VirtualScroller.verticalSpacing.js.map +1 -0
- package/commonjs/getItemCoordinates.js.map +1 -1
- package/commonjs/getItemsDiff.js.map +1 -1
- package/commonjs/getVerticalSpacing.js +8 -8
- package/commonjs/getVerticalSpacing.js.map +1 -1
- package/commonjs/package.json +5 -0
- package/commonjs/react/VirtualScroller.js +182 -628
- package/commonjs/react/VirtualScroller.js.map +1 -1
- package/commonjs/react/useClassName.js +26 -0
- package/commonjs/react/useClassName.js.map +1 -0
- package/commonjs/react/useHandleItemsChange.js +116 -0
- package/commonjs/react/useHandleItemsChange.js.map +1 -0
- package/commonjs/react/useInstanceMethods.js +37 -0
- package/commonjs/react/useInstanceMethods.js.map +1 -0
- package/commonjs/react/useItemKeys.js +60 -0
- package/commonjs/react/useItemKeys.js.map +1 -0
- package/commonjs/react/useOnItemHeightChange.js +32 -0
- package/commonjs/react/useOnItemHeightChange.js.map +1 -0
- package/commonjs/react/useOnItemStateChange.js +32 -0
- package/commonjs/react/useOnItemStateChange.js.map +1 -0
- package/commonjs/react/useState.js +140 -0
- package/commonjs/react/useState.js.map +1 -0
- package/commonjs/react/useStyle.js +29 -0
- package/commonjs/react/useStyle.js.map +1 -0
- package/commonjs/react/useVirtualScroller.js +62 -0
- package/commonjs/react/useVirtualScroller.js.map +1 -0
- package/commonjs/react/useVirtualScrollerStartStop.js +20 -0
- package/commonjs/react/useVirtualScrollerStartStop.js.map +1 -0
- package/commonjs/test/Engine.js +23 -0
- package/commonjs/test/Engine.js.map +1 -0
- package/commonjs/test/ItemsContainer.js +127 -0
- package/commonjs/test/ItemsContainer.js.map +1 -0
- package/commonjs/test/ScrollableContainer.js +130 -0
- package/commonjs/test/ScrollableContainer.js.map +1 -0
- package/commonjs/test/VirtualScroller.js +281 -0
- package/commonjs/test/VirtualScroller.js.map +1 -0
- package/commonjs/utility/debounce.js +28 -6
- package/commonjs/utility/debounce.js.map +1 -1
- package/commonjs/utility/debug.js +51 -12
- package/commonjs/utility/debug.js.map +1 -1
- package/commonjs/utility/getStateSnapshot.js +50 -0
- package/commonjs/utility/getStateSnapshot.js.map +1 -0
- package/commonjs/utility/px.js +1 -1
- package/commonjs/utility/px.js.map +1 -1
- package/commonjs/utility/px.test.js +14 -0
- package/commonjs/utility/px.test.js.map +1 -0
- package/commonjs/utility/shallowEqual.js +1 -1
- package/commonjs/utility/shallowEqual.js.map +1 -1
- package/commonjs/utility/throttle.js.map +1 -1
- package/dom/index.cjs +4 -0
- package/dom/index.cjs.js +9 -0
- package/dom/index.d.ts +25 -0
- package/dom/index.js +1 -1
- package/dom/package.json +10 -4
- package/index.cjs +4 -0
- package/index.cjs.js +9 -0
- package/index.d.ts +99 -0
- package/index.js +1 -1
- package/modules/BeforeResize.js +305 -0
- package/modules/BeforeResize.js.map +1 -0
- package/modules/DOM/Engine.js +27 -0
- package/modules/DOM/Engine.js.map +1 -0
- package/modules/DOM/ItemsContainer.js +71 -0
- package/modules/DOM/ItemsContainer.js.map +1 -0
- package/modules/DOM/{WaitForStylesToLoad.js → ListTopOffsetWatcher.js} +72 -44
- package/modules/DOM/ListTopOffsetWatcher.js.map +1 -0
- package/modules/DOM/ScrollableContainer.js +68 -100
- package/modules/DOM/ScrollableContainer.js.map +1 -1
- package/modules/DOM/VirtualScroller.js +32 -28
- package/modules/DOM/VirtualScroller.js.map +1 -1
- package/modules/DOM/tbody.js +11 -9
- package/modules/DOM/tbody.js.map +1 -1
- package/modules/ItemHeights.js +28 -33
- package/modules/ItemHeights.js.map +1 -1
- package/modules/Layout.js +585 -214
- package/modules/Layout.js.map +1 -1
- package/modules/Layout.test.js +190 -0
- package/modules/Layout.test.js.map +1 -0
- package/modules/ListHeightMeasurement.js +117 -0
- package/modules/ListHeightMeasurement.js.map +1 -0
- package/modules/Resize.js +50 -39
- package/modules/Resize.js.map +1 -1
- package/modules/Scroll.js +139 -94
- package/modules/Scroll.js.map +1 -1
- package/modules/VirtualScroller.columns.js +36 -0
- package/modules/VirtualScroller.columns.js.map +1 -0
- package/modules/VirtualScroller.constructor.js +371 -0
- package/modules/VirtualScroller.constructor.js.map +1 -0
- package/modules/VirtualScroller.items.js +288 -0
- package/modules/VirtualScroller.items.js.map +1 -0
- package/modules/VirtualScroller.js +159 -1014
- package/modules/VirtualScroller.js.map +1 -1
- package/modules/VirtualScroller.layout.js +549 -0
- package/modules/VirtualScroller.layout.js.map +1 -0
- package/modules/VirtualScroller.onRender.js +337 -0
- package/modules/VirtualScroller.onRender.js.map +1 -0
- package/modules/VirtualScroller.resize.js +176 -0
- package/modules/VirtualScroller.resize.js.map +1 -0
- package/modules/VirtualScroller.state.js +283 -0
- package/modules/VirtualScroller.state.js.map +1 -0
- package/modules/VirtualScroller.verticalSpacing.js +54 -0
- package/modules/VirtualScroller.verticalSpacing.js.map +1 -0
- package/modules/getItemCoordinates.js.map +1 -1
- package/modules/getItemsDiff.js.map +1 -1
- package/modules/getVerticalSpacing.js +8 -8
- package/modules/getVerticalSpacing.js.map +1 -1
- package/modules/react/VirtualScroller.js +179 -634
- package/modules/react/VirtualScroller.js.map +1 -1
- package/modules/react/useClassName.js +18 -0
- package/modules/react/useClassName.js.map +1 -0
- package/modules/react/useHandleItemsChange.js +108 -0
- package/modules/react/useHandleItemsChange.js.map +1 -0
- package/modules/react/useInstanceMethods.js +28 -0
- package/modules/react/useInstanceMethods.js.map +1 -0
- package/modules/react/useItemKeys.js +52 -0
- package/modules/react/useItemKeys.js.map +1 -0
- package/modules/react/useOnItemHeightChange.js +24 -0
- package/modules/react/useOnItemHeightChange.js.map +1 -0
- package/modules/react/useOnItemStateChange.js +24 -0
- package/modules/react/useOnItemStateChange.js.map +1 -0
- package/modules/react/useState.js +132 -0
- package/modules/react/useState.js.map +1 -0
- package/modules/react/useStyle.js +19 -0
- package/modules/react/useStyle.js.map +1 -0
- package/modules/react/useVirtualScroller.js +51 -0
- package/modules/react/useVirtualScroller.js.map +1 -0
- package/modules/react/useVirtualScrollerStartStop.js +12 -0
- package/modules/react/useVirtualScrollerStartStop.js.map +1 -0
- package/modules/test/Engine.js +11 -0
- package/modules/test/Engine.js.map +1 -0
- package/modules/test/ItemsContainer.js +120 -0
- package/modules/test/ItemsContainer.js.map +1 -0
- package/modules/test/ScrollableContainer.js +123 -0
- package/modules/test/ScrollableContainer.js.map +1 -0
- package/modules/test/VirtualScroller.js +270 -0
- package/modules/test/VirtualScroller.js.map +1 -0
- package/modules/utility/debounce.js +28 -6
- package/modules/utility/debounce.js.map +1 -1
- package/modules/utility/debug.js +47 -10
- package/modules/utility/debug.js.map +1 -1
- package/modules/utility/getStateSnapshot.js +43 -0
- package/modules/utility/getStateSnapshot.js.map +1 -0
- package/modules/utility/px.js +1 -1
- package/modules/utility/px.js.map +1 -1
- package/modules/utility/px.test.js +9 -0
- package/modules/utility/px.test.js.map +1 -0
- package/modules/utility/shallowEqual.js +1 -1
- package/modules/utility/shallowEqual.js.map +1 -1
- package/modules/utility/throttle.js.map +1 -1
- package/package.json +54 -29
- package/react/index.cjs +4 -0
- package/react/index.cjs.js +9 -0
- package/react/index.d.ts +28 -0
- package/react/index.js +1 -1
- package/react/package.json +10 -4
- package/rollup.config.mjs +62 -0
- package/runnable/create-commonjs-package-json.js +11 -0
- package/source/BeforeResize.js +312 -0
- package/source/DOM/Engine.js +30 -0
- package/source/DOM/ItemsContainer.js +48 -0
- package/source/DOM/{WaitForStylesToLoad.js → ListTopOffsetWatcher.js} +61 -30
- package/source/DOM/ScrollableContainer.js +51 -73
- package/source/DOM/VirtualScroller.js +33 -18
- package/source/DOM/tbody.js +30 -21
- package/source/ItemHeights.js +27 -27
- package/source/Layout.js +629 -252
- package/source/Layout.test.js +176 -0
- package/source/ListHeightMeasurement.js +95 -0
- package/source/Resize.js +56 -32
- package/source/Scroll.js +135 -82
- package/source/VirtualScroller.columns.js +26 -0
- package/source/VirtualScroller.constructor.js +336 -0
- package/source/VirtualScroller.items.js +302 -0
- package/source/VirtualScroller.js +162 -936
- package/source/VirtualScroller.layout.js +539 -0
- package/source/VirtualScroller.onRender.js +345 -0
- package/source/VirtualScroller.resize.js +189 -0
- package/source/VirtualScroller.state.js +284 -0
- package/source/VirtualScroller.verticalSpacing.js +51 -0
- package/source/getVerticalSpacing.js +7 -7
- package/source/react/VirtualScroller.js +243 -603
- package/source/react/useClassName.js +14 -0
- package/source/react/useHandleItemsChange.js +115 -0
- package/source/react/useInstanceMethods.js +25 -0
- package/source/react/useItemKeys.js +59 -0
- package/source/react/useOnItemHeightChange.js +28 -0
- package/source/react/useOnItemStateChange.js +28 -0
- package/source/react/useState.js +114 -0
- package/source/react/useStyle.js +20 -0
- package/source/react/useVirtualScroller.js +59 -0
- package/source/react/useVirtualScrollerStartStop.js +12 -0
- package/source/test/Engine.js +11 -0
- package/source/test/ItemsContainer.js +87 -0
- package/source/test/ScrollableContainer.js +88 -0
- package/source/test/VirtualScroller.js +232 -0
- package/source/utility/debounce.js +22 -5
- package/source/utility/debug.js +34 -3
- package/source/utility/getStateSnapshot.js +36 -0
- package/source/utility/px.js +1 -1
- package/source/utility/px.test.js +9 -0
- package/website/index-bypass.html +195 -0
- package/website/index-grid.html +0 -1
- package/website/index-scrollableContainer.html +208 -0
- package/website/index-tbody-scrollableContainer.html +68 -0
- package/website/index-tbody.html +55 -0
- package/commonjs/DOM/RenderingEngine.js +0 -33
- package/commonjs/DOM/RenderingEngine.js.map +0 -1
- package/commonjs/DOM/Screen.js +0 -87
- package/commonjs/DOM/Screen.js.map +0 -1
- package/commonjs/DOM/WaitForStylesToLoad.js.map +0 -1
- package/commonjs/RestoreScroll.js +0 -118
- package/commonjs/RestoreScroll.js.map +0 -1
- package/dom/index.commonjs.js +0 -4
- package/index.commonjs.js +0 -4
- package/modules/DOM/RenderingEngine.js +0 -19
- package/modules/DOM/RenderingEngine.js.map +0 -1
- package/modules/DOM/Screen.js +0 -80
- package/modules/DOM/Screen.js.map +0 -1
- package/modules/DOM/WaitForStylesToLoad.js.map +0 -1
- package/modules/RestoreScroll.js +0 -111
- package/modules/RestoreScroll.js.map +0 -1
- package/react/index.commonjs.js +0 -4
- package/source/DOM/RenderingEngine.js +0 -22
- package/source/DOM/Screen.js +0 -51
- package/source/RestoreScroll.js +0 -86
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import Layout from './Layout.js'
|
|
2
|
+
|
|
3
|
+
import Engine from './test/Engine.js'
|
|
4
|
+
|
|
5
|
+
describe('Layout', function() {
|
|
6
|
+
it('should work', function() {
|
|
7
|
+
const SCREEN_HEIGHT = 400
|
|
8
|
+
|
|
9
|
+
const scrollableContainer = {
|
|
10
|
+
width: 800,
|
|
11
|
+
height: SCREEN_HEIGHT
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const ITEM_WIDTH = scrollableContainer.width
|
|
15
|
+
const ITEM_HEIGHT = 200
|
|
16
|
+
|
|
17
|
+
const VERTICAL_SPACING = 100
|
|
18
|
+
|
|
19
|
+
const items = new Array(9).fill(ITEM_WIDTH * ITEM_HEIGHT)
|
|
20
|
+
|
|
21
|
+
const layout = new Layout({
|
|
22
|
+
getPrerenderMargin: () => SCREEN_HEIGHT,
|
|
23
|
+
getVerticalSpacing: () => VERTICAL_SPACING,
|
|
24
|
+
getColumnsCount: () => 1,
|
|
25
|
+
getItemHeight: (i) => items[i] / scrollableContainer.width,
|
|
26
|
+
getBeforeResizeItemsCount: () => 0,
|
|
27
|
+
getAverageItemHeight: () => ITEM_HEIGHT,
|
|
28
|
+
getScrollableContainerHeight: () => scrollableContainer.height
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// Initial render.
|
|
32
|
+
layout.getShownItemIndexes({
|
|
33
|
+
itemsCount: items.length,
|
|
34
|
+
visibleAreaTop: 0,
|
|
35
|
+
visibleAreaBottom: SCREEN_HEIGHT
|
|
36
|
+
}).should.deep.equal({
|
|
37
|
+
firstShownItemIndex: 0,
|
|
38
|
+
lastShownItemIndex: 2
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
// The first item is almost hidden.
|
|
42
|
+
layout.getShownItemIndexes({
|
|
43
|
+
itemsCount: items.length,
|
|
44
|
+
visibleAreaTop: SCREEN_HEIGHT + ITEM_HEIGHT - 1,
|
|
45
|
+
visibleAreaBottom: (SCREEN_HEIGHT + ITEM_HEIGHT - 1) + SCREEN_HEIGHT
|
|
46
|
+
}).should.deep.equal({
|
|
47
|
+
firstShownItemIndex: 0,
|
|
48
|
+
lastShownItemIndex: 4
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// The first item is hidden.
|
|
52
|
+
layout.getShownItemIndexes({
|
|
53
|
+
itemsCount: items.length,
|
|
54
|
+
visibleAreaTop: SCREEN_HEIGHT + ITEM_HEIGHT,
|
|
55
|
+
visibleAreaBottom: (SCREEN_HEIGHT + ITEM_HEIGHT) + SCREEN_HEIGHT
|
|
56
|
+
}).should.deep.equal({
|
|
57
|
+
firstShownItemIndex: 1,
|
|
58
|
+
lastShownItemIndex: 4
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
// A new item at the bottom is almost visible.
|
|
62
|
+
layout.getShownItemIndexes({
|
|
63
|
+
itemsCount: items.length,
|
|
64
|
+
visibleAreaTop: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 - SCREEN_HEIGHT * 2,
|
|
65
|
+
visibleAreaBottom: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 - SCREEN_HEIGHT
|
|
66
|
+
}).should.deep.equal({
|
|
67
|
+
firstShownItemIndex: 1,
|
|
68
|
+
lastShownItemIndex: 4
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
// A new item at the bottom is visible.
|
|
72
|
+
layout.getShownItemIndexes({
|
|
73
|
+
itemsCount: items.length,
|
|
74
|
+
visibleAreaTop: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 + 1 - SCREEN_HEIGHT * 2,
|
|
75
|
+
visibleAreaBottom: (ITEM_HEIGHT + VERTICAL_SPACING) * 5 + 1 - SCREEN_HEIGHT
|
|
76
|
+
}).should.deep.equal({
|
|
77
|
+
firstShownItemIndex: 1,
|
|
78
|
+
lastShownItemIndex: 5
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('should update layout for items incremental change', function() {
|
|
83
|
+
const scrollableContainer = {
|
|
84
|
+
width: 800,
|
|
85
|
+
height: 400
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const ITEM_WIDTH = scrollableContainer.width
|
|
89
|
+
const ITEM_HEIGHT = 200
|
|
90
|
+
|
|
91
|
+
const items = new Array(9).fill(ITEM_WIDTH * ITEM_HEIGHT)
|
|
92
|
+
|
|
93
|
+
const VERTICAL_SPACING = 100
|
|
94
|
+
|
|
95
|
+
const layout = new Layout({
|
|
96
|
+
getPrerenderMargin: () => scrollableContainer.height,
|
|
97
|
+
getVerticalSpacing: () => VERTICAL_SPACING,
|
|
98
|
+
getColumnsCount: () => 1,
|
|
99
|
+
getItemHeight: (i) => ITEM_HEIGHT,
|
|
100
|
+
getBeforeResizeItemsCount: () => 0,
|
|
101
|
+
getAverageItemHeight: () => ITEM_HEIGHT,
|
|
102
|
+
getScrollableContainerHeight: () => scrollableContainer.height
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
layout.getLayoutUpdateForItemsDiff(
|
|
106
|
+
{
|
|
107
|
+
firstShownItemIndex: 3,
|
|
108
|
+
lastShownItemIndex: 5,
|
|
109
|
+
beforeItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING),
|
|
110
|
+
afterItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING)
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
prependedItemsCount: 5,
|
|
114
|
+
appendedItemsCount: 5
|
|
115
|
+
}, {
|
|
116
|
+
itemsCount: 5 + 5 + items.length,
|
|
117
|
+
columnsCount: 1
|
|
118
|
+
}
|
|
119
|
+
).should.deep.equal({
|
|
120
|
+
firstShownItemIndex: 5 + 3,
|
|
121
|
+
lastShownItemIndex: 5 + 5,
|
|
122
|
+
beforeItemsHeight: (5 + 3) * (ITEM_HEIGHT + VERTICAL_SPACING),
|
|
123
|
+
afterItemsHeight: (3 + 5) * (ITEM_HEIGHT + VERTICAL_SPACING)
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it('should update layout for items incremental change (rows get rebalanced)', function() {
|
|
128
|
+
const scrollableContainer = {
|
|
129
|
+
width: 800,
|
|
130
|
+
height: 400
|
|
131
|
+
}
|
|
132
|
+
const ITEM_WIDTH = scrollableContainer.width
|
|
133
|
+
const ITEM_HEIGHT = 400
|
|
134
|
+
|
|
135
|
+
const items = new Array(9).fill(ITEM_WIDTH * ITEM_HEIGHT)
|
|
136
|
+
|
|
137
|
+
const VERTICAL_SPACING = 100
|
|
138
|
+
|
|
139
|
+
const layout = new Layout({
|
|
140
|
+
getPrerenderMargin: () => scrollableContainer.height,
|
|
141
|
+
getVerticalSpacing: () => VERTICAL_SPACING,
|
|
142
|
+
getColumnsCount: () => 4,
|
|
143
|
+
getItemHeight: () => ITEM_HEIGHT,
|
|
144
|
+
getBeforeResizeItemsCount: () => 0,
|
|
145
|
+
getAverageItemHeight: () => ITEM_HEIGHT,
|
|
146
|
+
getScrollableContainerHeight: () => scrollableContainer.height
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
let shouldResetGridLayout
|
|
150
|
+
|
|
151
|
+
layout.getLayoutUpdateForItemsDiff(
|
|
152
|
+
{
|
|
153
|
+
firstShownItemIndex: 3,
|
|
154
|
+
lastShownItemIndex: 5,
|
|
155
|
+
beforeItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING),
|
|
156
|
+
afterItemsHeight: 3 * (ITEM_HEIGHT + VERTICAL_SPACING)
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
prependedItemsCount: 5,
|
|
160
|
+
appendedItemsCount: 5
|
|
161
|
+
}, {
|
|
162
|
+
itemsCount: 5 + 5 + items.length,
|
|
163
|
+
columnsCount: 4,
|
|
164
|
+
shouldRestoreScrollPosition: true,
|
|
165
|
+
onResetGridLayout: () => shouldResetGridLayout = true
|
|
166
|
+
}
|
|
167
|
+
).should.deep.equal({
|
|
168
|
+
firstShownItemIndex: 0,
|
|
169
|
+
lastShownItemIndex: 5 + 5,
|
|
170
|
+
beforeItemsHeight: 0,
|
|
171
|
+
afterItemsHeight: 5 * (ITEM_HEIGHT + VERTICAL_SPACING)
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
shouldResetGridLayout.should.equal(true)
|
|
175
|
+
})
|
|
176
|
+
})
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export default class ListHeightMeasurement {
|
|
2
|
+
constructor({
|
|
3
|
+
itemsContainer,
|
|
4
|
+
getListTopOffset
|
|
5
|
+
}) {
|
|
6
|
+
this.itemsContainer = itemsContainer
|
|
7
|
+
this.getListTopOffset = getListTopOffset
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Snapshots the list height while `previousItems` are still rendered,
|
|
12
|
+
* before rendering `newItems`. The list height will be re-measured
|
|
13
|
+
* after the new items have been rendered, yielding the list height difference
|
|
14
|
+
* which is gonna be the amount to scroll vertically in order to restore
|
|
15
|
+
* the previous scroll position. Is only used when prepending items.
|
|
16
|
+
* @param {any[]} previousItems
|
|
17
|
+
* @param {any[]} newItems
|
|
18
|
+
* @param {number} prependedItemsCount
|
|
19
|
+
*/
|
|
20
|
+
snapshotListHeightBeforeAddingNewItems({
|
|
21
|
+
previousItems,
|
|
22
|
+
newItems,
|
|
23
|
+
prependedItemsCount
|
|
24
|
+
}) {
|
|
25
|
+
// If there were no items in the list
|
|
26
|
+
// then there's no point in restoring scroll position.
|
|
27
|
+
if (previousItems.length === 0) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// If no items were prepended then no need to restore scroll position.
|
|
32
|
+
if (prependedItemsCount === 0) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// The first item is supposed to be shown when the user clicks
|
|
37
|
+
// "Show previous items" button. If it isn't shown though,
|
|
38
|
+
// could still calculate the first item's top position using
|
|
39
|
+
// the values from `itemHeights` and `verticalSpacing`.
|
|
40
|
+
// But that would be a weird non-realistic scenario.
|
|
41
|
+
// if (firstShownItemIndex > 0) {
|
|
42
|
+
// let i = firstShownItemIndex - 1
|
|
43
|
+
// while (i >= 0) {
|
|
44
|
+
// firstItemTopOffset += itemHeights[i] + verticalSpacing
|
|
45
|
+
// i--
|
|
46
|
+
// }
|
|
47
|
+
// }
|
|
48
|
+
|
|
49
|
+
// This part is longer relevant: <ReactVirtualScroller/> no longer calls
|
|
50
|
+
// this function two times consequtively.
|
|
51
|
+
//
|
|
52
|
+
// // If the scroll position has already been captured for restoration,
|
|
53
|
+
// // then don't capture it the second time.
|
|
54
|
+
// if (this._snapshot &&
|
|
55
|
+
// this._snapshot.previousItems === previousItems &&
|
|
56
|
+
// this._snapshot.newItems === newItems) {
|
|
57
|
+
// return
|
|
58
|
+
// }
|
|
59
|
+
|
|
60
|
+
this._snapshot = {
|
|
61
|
+
previousItems,
|
|
62
|
+
newItems,
|
|
63
|
+
itemIndex: prependedItemsCount,
|
|
64
|
+
itemTopOffset: this.itemsContainer.getNthRenderedItemTopOffset(0),
|
|
65
|
+
// Snapshot list top offset inside the scrollable container too
|
|
66
|
+
// because it's common to hide the "Show previous items" button
|
|
67
|
+
// when the user has browsed to the top of the list, which causes
|
|
68
|
+
// the list's top position to shift upwards due to the button
|
|
69
|
+
// no longer being rendered. Tracking list top offset doesn't
|
|
70
|
+
// fit here that well, but it makes sense in real-world applications.
|
|
71
|
+
listTopOffset: this.getListTopOffset()
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
getAnchorItemIndex() {
|
|
76
|
+
return this._snapshot.itemIndex
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
hasSnapshot() {
|
|
80
|
+
return this._snapshot !== undefined
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
getListBottomOffsetChange() {
|
|
84
|
+
const { itemIndex, itemTopOffset, listTopOffset } = this._snapshot
|
|
85
|
+
// `firstShownItemIndex` is supposed to be `0` at this point,
|
|
86
|
+
// so `renderedElementIndex` would be the same as the `itemIndex`.
|
|
87
|
+
const itemTopOffsetNew = this.itemsContainer.getNthRenderedItemTopOffset(itemIndex)
|
|
88
|
+
const listTopOffsetNew = this.getListTopOffset()
|
|
89
|
+
return (itemTopOffsetNew - itemTopOffset) + (listTopOffsetNew - listTopOffset)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
reset() {
|
|
93
|
+
this._snapshot = undefined
|
|
94
|
+
}
|
|
95
|
+
}
|
package/source/Resize.js
CHANGED
|
@@ -1,72 +1,96 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import debounce from './utility/debounce.js'
|
|
2
|
+
import log from './utility/debug.js'
|
|
3
3
|
|
|
4
4
|
export default class Resize {
|
|
5
5
|
constructor({
|
|
6
6
|
bypass,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
getWidth,
|
|
8
|
+
getHeight,
|
|
9
|
+
listenForResize,
|
|
10
|
+
onResizeStart,
|
|
11
|
+
onResizeStop,
|
|
12
|
+
onHeightChange,
|
|
13
|
+
onWidthChange,
|
|
14
|
+
onNoChange
|
|
11
15
|
}) {
|
|
12
16
|
this.bypass = bypass
|
|
13
|
-
|
|
14
|
-
this.
|
|
15
|
-
this.
|
|
16
|
-
this.
|
|
17
|
+
|
|
18
|
+
this.onHeightChange = onHeightChange
|
|
19
|
+
this.onWidthChange = onWidthChange
|
|
20
|
+
this.onNoChange = onNoChange
|
|
21
|
+
|
|
22
|
+
this.getWidth = getWidth
|
|
23
|
+
this.getHeight = getHeight
|
|
24
|
+
this.listenForResize = listenForResize
|
|
25
|
+
|
|
26
|
+
this.onResize = debounce(
|
|
27
|
+
this._onResize,
|
|
28
|
+
SCROLLABLE_CONTAINER_RESIZE_DEBOUNCE_INTERVAL,
|
|
29
|
+
{
|
|
30
|
+
onStart: onResizeStart,
|
|
31
|
+
onStop: onResizeStop
|
|
32
|
+
}
|
|
33
|
+
)
|
|
17
34
|
}
|
|
18
35
|
|
|
19
|
-
|
|
36
|
+
start() {
|
|
37
|
+
this.isActive = true
|
|
20
38
|
if (this.bypass) {
|
|
21
39
|
return
|
|
22
40
|
}
|
|
23
|
-
this.
|
|
24
|
-
this.
|
|
25
|
-
this.
|
|
26
|
-
this.scrollableContainerUnlistenResize = this.scrollableContainer.onResize(this.onResize, {
|
|
27
|
-
container: this.getContainerElement()
|
|
28
|
-
})
|
|
41
|
+
this.width = this.getWidth()
|
|
42
|
+
this.height = this.getHeight()
|
|
43
|
+
this.unlistenResize = this.listenForResize(this.onResize)
|
|
29
44
|
}
|
|
30
45
|
|
|
31
46
|
stop() {
|
|
32
|
-
this.
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
this.isActive = false
|
|
48
|
+
this.width = undefined
|
|
49
|
+
this.height = undefined
|
|
50
|
+
if (this.unlistenResize) {
|
|
51
|
+
this.unlistenResize()
|
|
52
|
+
this.unlistenResize = undefined
|
|
35
53
|
}
|
|
36
54
|
}
|
|
37
55
|
|
|
38
56
|
/**
|
|
39
57
|
* On scrollable container resize.
|
|
40
58
|
*/
|
|
41
|
-
|
|
59
|
+
_onResize = () => {
|
|
42
60
|
// If `VirtualScroller` has been unmounted
|
|
43
61
|
// while `debounce()`'s `setTimeout()` was waiting, then exit.
|
|
44
|
-
|
|
62
|
+
// If the `VirtualScroller` gets restarted later, it will detect
|
|
63
|
+
// that `state.scrollableContainerWidth` doesn't match the actual
|
|
64
|
+
// scrollable container width, and will call `this.onResize()`.
|
|
65
|
+
if (!this.isActive) {
|
|
45
66
|
return
|
|
46
67
|
}
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
68
|
+
|
|
69
|
+
const prevScrollableContainerWidth = this.width
|
|
70
|
+
const prevScrollableContainerHeight = this.height
|
|
71
|
+
|
|
72
|
+
this.width = this.getWidth()
|
|
73
|
+
this.height = this.getHeight()
|
|
74
|
+
|
|
75
|
+
if (this.width === prevScrollableContainerWidth) {
|
|
76
|
+
if (this.height === prevScrollableContainerHeight) {
|
|
53
77
|
// The dimensions of the container didn't change,
|
|
54
78
|
// so there's no need to re-layout anything.
|
|
55
|
-
|
|
79
|
+
this.onNoChange()
|
|
56
80
|
} else {
|
|
57
81
|
// Scrollable container height has changed,
|
|
58
82
|
// so just recalculate shown item indexes.
|
|
59
83
|
// No need to perform a re-layout from scratch.
|
|
60
|
-
this.
|
|
84
|
+
this.onHeightChange(prevScrollableContainerHeight, this.height)
|
|
61
85
|
}
|
|
62
86
|
} else {
|
|
63
87
|
// Reset item heights, because if scrollable container's width (or height)
|
|
64
88
|
// has changed, then the list width (or height) most likely also has changed,
|
|
65
89
|
// and also some CSS `@media()` rules might have been added or removed.
|
|
66
90
|
// So re-render the list entirely.
|
|
67
|
-
this.
|
|
91
|
+
this.onWidthChange(prevScrollableContainerWidth, this.width)
|
|
68
92
|
}
|
|
69
|
-
}
|
|
93
|
+
}
|
|
70
94
|
}
|
|
71
95
|
|
|
72
96
|
const SCROLLABLE_CONTAINER_RESIZE_DEBOUNCE_INTERVAL = 250
|