virtual-scroller 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +712 -524
  3. package/bundle/index-dom.html +2 -0
  4. package/bundle/virtual-scroller-dom.js +1 -1
  5. package/bundle/virtual-scroller-dom.js.map +1 -1
  6. package/bundle/virtual-scroller-react.js +1 -1
  7. package/bundle/virtual-scroller-react.js.map +1 -1
  8. package/bundle/virtual-scroller.js +1 -1
  9. package/bundle/virtual-scroller.js.map +1 -1
  10. package/commonjs/DOM/VirtualScroller.js +60 -31
  11. package/commonjs/DOM/VirtualScroller.js.map +1 -1
  12. package/commonjs/DOM/tbody.js +9 -9
  13. package/commonjs/DOM/tbody.js.map +1 -1
  14. package/commonjs/Layout.js +3 -3
  15. package/commonjs/Layout.js.map +1 -1
  16. package/commonjs/Scroll.js +3 -3
  17. package/commonjs/Scroll.js.map +1 -1
  18. package/commonjs/ScrollableContainerResizeHandler.js +4 -5
  19. package/commonjs/ScrollableContainerResizeHandler.js.map +1 -1
  20. package/commonjs/VirtualScroller.constructor.js +15 -27
  21. package/commonjs/VirtualScroller.constructor.js.map +1 -1
  22. package/commonjs/VirtualScroller.js +21 -14
  23. package/commonjs/VirtualScroller.js.map +1 -1
  24. package/commonjs/VirtualScroller.layout.js +2 -2
  25. package/commonjs/VirtualScroller.layout.js.map +1 -1
  26. package/commonjs/VirtualScroller.onRender.js +1 -1
  27. package/commonjs/VirtualScroller.onRender.js.map +1 -1
  28. package/commonjs/VirtualScroller.state.js +8 -0
  29. package/commonjs/VirtualScroller.state.js.map +1 -1
  30. package/commonjs/react/VirtualScroller.js +15 -5
  31. package/commonjs/react/VirtualScroller.js.map +1 -1
  32. package/commonjs/react/useState.js +1 -2
  33. package/commonjs/react/useState.js.map +1 -1
  34. package/commonjs/react/useVirtualScroller.js +8 -11
  35. package/commonjs/react/useVirtualScroller.js.map +1 -1
  36. package/dom/index.d.ts +5 -4
  37. package/index.d.ts +0 -1
  38. package/modules/DOM/VirtualScroller.js +60 -31
  39. package/modules/DOM/VirtualScroller.js.map +1 -1
  40. package/modules/DOM/tbody.js +10 -9
  41. package/modules/DOM/tbody.js.map +1 -1
  42. package/modules/Layout.js +3 -3
  43. package/modules/Layout.js.map +1 -1
  44. package/modules/Scroll.js +3 -3
  45. package/modules/Scroll.js.map +1 -1
  46. package/modules/ScrollableContainerResizeHandler.js +4 -5
  47. package/modules/ScrollableContainerResizeHandler.js.map +1 -1
  48. package/modules/VirtualScroller.constructor.js +16 -27
  49. package/modules/VirtualScroller.constructor.js.map +1 -1
  50. package/modules/VirtualScroller.js +21 -14
  51. package/modules/VirtualScroller.js.map +1 -1
  52. package/modules/VirtualScroller.layout.js +2 -2
  53. package/modules/VirtualScroller.layout.js.map +1 -1
  54. package/modules/VirtualScroller.onRender.js +1 -1
  55. package/modules/VirtualScroller.onRender.js.map +1 -1
  56. package/modules/VirtualScroller.state.js +8 -0
  57. package/modules/VirtualScroller.state.js.map +1 -1
  58. package/modules/react/VirtualScroller.js +15 -5
  59. package/modules/react/VirtualScroller.js.map +1 -1
  60. package/modules/react/useState.js +1 -2
  61. package/modules/react/useState.js.map +1 -1
  62. package/modules/react/useVirtualScroller.js +6 -9
  63. package/modules/react/useVirtualScroller.js.map +1 -1
  64. package/package.json +2 -2
  65. package/source/DOM/VirtualScroller.js +58 -27
  66. package/source/DOM/tbody.js +10 -9
  67. package/source/Layout.js +3 -3
  68. package/source/Scroll.js +3 -3
  69. package/source/ScrollableContainerResizeHandler.js +4 -4
  70. package/source/VirtualScroller.constructor.js +13 -27
  71. package/source/VirtualScroller.js +26 -13
  72. package/source/VirtualScroller.layout.js +2 -2
  73. package/source/VirtualScroller.onRender.js +1 -1
  74. package/source/VirtualScroller.state.js +8 -0
  75. package/source/react/VirtualScroller.js +16 -4
  76. package/source/react/useState.js +1 -2
  77. package/source/react/useVirtualScroller.js +0 -3
@@ -5,34 +5,46 @@ import px from '../utility/px.js'
5
5
 
6
6
  export default class VirtualScroller {
7
7
  constructor(itemsContainerElement, items, renderItem, options = {}) {
8
- this.container = itemsContainerElement
8
+ this.getItemsContainerElement = typeof itemsContainerElement === 'function'
9
+ ? itemsContainerElement
10
+ : () => itemsContainerElement
11
+
9
12
  this.renderItem = renderItem
10
13
 
11
14
  const {
12
15
  onMount,
13
16
  onItemUnmount,
17
+ readyToStart,
18
+ readyToRender,
14
19
  ...restOptions
15
20
  } = options
16
21
 
22
+ // `onMount()` option is deprecated due to no longer being used.
23
+ // If someone thinks there's a valid use case for it, create an issue.
24
+ this._onMount = onMount
25
+
17
26
  this.onItemUnmount = onItemUnmount
18
- this.tbody = this.container.tagName === 'TBODY'
19
27
 
20
28
  this.virtualScroller = new VirtualScrollerCore(
21
- () => this.container,
29
+ this.getItemsContainerElement,
22
30
  items,
23
31
  {
24
32
  ...restOptions,
25
- render: this.render,
26
- tbody: this.tbody
33
+ render: this.render
27
34
  }
28
35
  )
29
36
 
30
- this.start()
31
-
32
- // `onMount()` option is deprecated due to no longer being used.
33
- // If someone thinks there's a valid use case for it, create an issue.
34
- if (onMount) {
35
- onMount()
37
+ if (readyToRender === false) {
38
+ // Don't automatically perform the initial render of the list.
39
+ // This means that neither `this.render()` nor `this.start()` methods should be called.
40
+ } else if (readyToStart === false) {
41
+ // Don't automatically call the `.start()` method of the "core" component.
42
+ // Still, perform the initial render of the list.
43
+ this.render(this.virtualScroller.getInitialState())
44
+ } else {
45
+ // Calls the `.start()` method of the "core" component.
46
+ // It performs the initial render of the list and starts listening to scroll events.
47
+ this.start()
36
48
  }
37
49
  }
38
50
 
@@ -45,18 +57,24 @@ export default class VirtualScroller {
45
57
  afterItemsHeight
46
58
  } = state
47
59
 
60
+ const itemsContainerElement = this.getItemsContainerElement()
61
+
48
62
  // log('~ On state change ~')
49
63
  // log('Previous state', prevState)
50
64
  // log('New state', state)
51
65
 
52
- // Set container padding top and bottom.
53
- // Work around `<tbody/>` not being able to have `padding`.
66
+ // Set items container's padding-top and padding-bottom.
67
+ // But only do that for a non-`<tbody/>` item container
68
+ // because, strangely, CSS `padding` doesn't work on a `<tbody/>` element.
54
69
  // https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1
70
+ //
55
71
  // `this.virtualScroller` hasn't been initialized yet at this stage,
56
- // so using `this.tbody` instead of `this.virtualScroller.tbody`.
57
- if (!this.tbody) {
58
- this.container.style.paddingTop = px(beforeItemsHeight)
59
- this.container.style.paddingBottom = px(afterItemsHeight)
72
+ // so this code can't use `this.virtualScroller.isItemsContainerElementTableBody()` function yet.
73
+ // Instead, it uses its own method of detecting the use of a `<tbody/>` container.
74
+ //
75
+ if (!this.virtualScroller.isItemsContainerElementTableBody()) {
76
+ itemsContainerElement.style.paddingTop = px(beforeItemsHeight)
77
+ itemsContainerElement.style.paddingBottom = px(afterItemsHeight)
60
78
  }
61
79
 
62
80
  // Perform an intelligent "diff" re-render if the `items` are the same.
@@ -64,7 +82,7 @@ export default class VirtualScroller {
64
82
  // Remove no longer visible items from the DOM.
65
83
  if (diffRender) {
66
84
  // Decrement instead of increment here because
67
- // `this.container.removeChild()` changes indexes.
85
+ // `itemsContainerElement.removeChild()` changes indexes.
68
86
  let i = prevState.lastShownItemIndex
69
87
  while (i >= prevState.firstShownItemIndex) {
70
88
  if (i >= firstShownItemIndex && i <= lastShownItemIndex) {
@@ -72,20 +90,20 @@ export default class VirtualScroller {
72
90
  } else {
73
91
  log('DOM: Remove element for item index', i)
74
92
  // The item is no longer visible. Remove it.
75
- this.unmountItem(this.container.childNodes[i - prevState.firstShownItemIndex])
93
+ this.unmountItem(itemsContainerElement.childNodes[i - prevState.firstShownItemIndex])
76
94
  }
77
95
  i--
78
96
  }
79
97
  } else {
80
98
  log('DOM: Rerender the list from scratch')
81
- while (this.container.firstChild) {
82
- this.unmountItem(this.container.firstChild)
99
+ while (itemsContainerElement.firstChild) {
100
+ this.unmountItem(itemsContainerElement.firstChild)
83
101
  }
84
102
  }
85
103
 
86
104
  // Add newly visible items to the DOM.
87
105
  let shouldPrependItems = diffRender
88
- const prependBeforeItemElement = shouldPrependItems && this.container.firstChild
106
+ const prependBeforeItemElement = shouldPrependItems && itemsContainerElement.firstChild
89
107
  let i = firstShownItemIndex
90
108
  while (i <= lastShownItemIndex) {
91
109
  if (diffRender && i >= prevState.firstShownItemIndex && i <= prevState.lastShownItemIndex) {
@@ -98,16 +116,28 @@ export default class VirtualScroller {
98
116
  const item = this.renderItem(items[i])
99
117
  if (shouldPrependItems) {
100
118
  log('DOM: Prepend element for item index', i)
101
- // Append `item` to `this.container` before the retained items.
102
- this.container.insertBefore(item, prependBeforeItemElement)
119
+ // Append `item` to `itemsContainerElement` before the retained items.
120
+ itemsContainerElement.insertBefore(item, prependBeforeItemElement)
103
121
  } else {
104
122
  log('DOM: Append element for item index', i)
105
- // Append `item` to `this.container`.
106
- this.container.appendChild(item)
123
+ // Append `item` to `itemsContainerElement`.
124
+ itemsContainerElement.appendChild(item)
107
125
  }
108
126
  }
109
127
  i++
110
128
  }
129
+
130
+ // Call `onMount()` function when the list has rendered for the first time.
131
+ //
132
+ // `onMount()` option is deprecated due to no longer being used.
133
+ // If someone thinks there's a valid use case for it, create an issue.
134
+ //
135
+ if (!this._isMounted) {
136
+ this._isMounted = true
137
+ if (this._onMount) {
138
+ this._onMount()
139
+ }
140
+ }
111
141
  }
112
142
 
113
143
  // Public API. Should be "bound" to `this`.
@@ -135,7 +165,8 @@ export default class VirtualScroller {
135
165
  }
136
166
 
137
167
  unmountItem(itemElement) {
138
- this.container.removeChild(itemElement)
168
+ this.getItemsContainerElement().removeChild(itemElement)
169
+
139
170
  if (this.onItemUnmount) {
140
171
  this.onItemUnmount(itemElement)
141
172
  }
@@ -5,17 +5,18 @@ import px from '../utility/px.js'
5
5
 
6
6
  export const BROWSER_NOT_SUPPORTED_ERROR = 'It looks like you\'re using Internet Explorer which doesn\'t support CSS variables required for a <tbody/> container. VirtualScroller has been switched into "bypass" mode (render all items). See: https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1'
7
7
 
8
- export function supportsTbody() {
9
- // Detect Internet Explorer.
8
+ function isInternetExplorer() {
9
+ // This function detects Internet Explorer using `documentMode` IE-only property.
10
10
  // https://stackoverflow.com/questions/19999388/check-if-user-is-using-ie
11
- // `documentMode` is an IE-only property.
12
- // Supports IE 9-11. Maybe even IE 8.
11
+ // The `documentMode` property exists in IE 9-11. Maybe even IE 8.
13
12
  // http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
14
- if (typeof window !== 'undefined' && window.document.documentMode) {
15
- // CSS variables aren't supported in Internet Explorer.
16
- return false
17
- }
18
- return true
13
+ return typeof window !== 'undefined' && Boolean(window.document.documentMode)
14
+ }
15
+
16
+ export function supportsTbody() {
17
+ // Internet Explorer doesn't support CSS Variables
18
+ // and therefore it will not be able to apply the `<tbody/>` workaround.
19
+ return !isInternetExplorer()
19
20
  }
20
21
 
21
22
  export const TBODY_CLASS_NAME = 'VirtualScroller'
package/source/Layout.js CHANGED
@@ -3,7 +3,7 @@ import ScrollableContainerNotReadyError from './ScrollableContainerNotReadyError
3
3
 
4
4
  export default class Layout {
5
5
  constructor({
6
- bypass,
6
+ isInBypassMode,
7
7
  getInitialEstimatedItemHeight,
8
8
  getInitialEstimatedVisibleItemRowsCount,
9
9
  measureItemsBatchSize,
@@ -19,7 +19,7 @@ export default class Layout {
19
19
  getMaxVisibleAreaHeight,
20
20
  getPreviouslyCalculatedLayout
21
21
  }) {
22
- this.bypass = bypass
22
+ this.isInBypassMode = isInBypassMode
23
23
  this.getInitialEstimatedItemHeight = getInitialEstimatedItemHeight
24
24
  this.getInitialEstimatedVisibleItemRowsCount = getInitialEstimatedVisibleItemRowsCount
25
25
  this.measureItemsBatchSize = measureItemsBatchSize
@@ -100,7 +100,7 @@ export default class Layout {
100
100
  columnsCount,
101
101
  firstShownItemIndex
102
102
  }) {
103
- if (this.bypass) {
103
+ if (this.isInBypassMode()) {
104
104
  return itemsCount - 1
105
105
  }
106
106
  // On server side, at initialization time,
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
- bypass,
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.bypass = bypass
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.bypass) {
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
- bypass,
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.bypass = bypass
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.bypass) {
38
+ if (this.isInBypassMode()) {
39
39
  return
40
40
  }
41
41
  this.width = this.getWidth()
@@ -1,8 +1,3 @@
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'
@@ -12,7 +7,7 @@ import Scroll from './Scroll.js'
12
7
  import ListHeightMeasurement from './ListHeightMeasurement.js'
13
8
  import ItemHeights from './ItemHeights.js'
14
9
 
15
- import log, { warn, isDebug, reportError } from './utility/debug.js'
10
+ import log, { warn } from './utility/debug.js'
16
11
 
17
12
  import createStateHelpers from './VirtualScroller.state.js'
18
13
  import createVerticalSpacingHelpers from './VirtualScroller.verticalSpacing.js'
@@ -34,6 +29,7 @@ export default function VirtualScrollerConstructor(
34
29
  options = {}
35
30
  ) {
36
31
  const {
32
+ bypass,
37
33
  render,
38
34
  state,
39
35
  getInitialItemState = () => {},
@@ -46,7 +42,6 @@ export default function VirtualScrollerConstructor(
46
42
  measureItemsBatchSize = 50,
47
43
  getColumnsCount,
48
44
  getItemId,
49
- tbody,
50
45
  // `estimatedItemHeight` is deprecated, use `getEstimatedItemHeight()` instead.
51
46
  estimatedItemHeight,
52
47
  getEstimatedVisibleItemRowsCount,
@@ -59,7 +54,6 @@ export default function VirtualScrollerConstructor(
59
54
  } = options
60
55
 
61
56
  let {
62
- bypass,
63
57
  getEstimatedItemHeight,
64
58
  getScrollableContainer
65
59
  } = options
@@ -104,21 +98,6 @@ export default function VirtualScrollerConstructor(
104
98
  throw new Error('[virtual-scroller] `getState`/`setState` options usage has changed in the new version. See the readme for more details.')
105
99
  }
106
100
 
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
101
  if (bypass) {
123
102
  log('~ "bypass" mode ~')
124
103
  }
@@ -133,7 +112,7 @@ export default function VirtualScrollerConstructor(
133
112
  // It turned out that unmounting large React component trees
134
113
  // is a very long process, so `VirtualScroller` does seem to
135
114
  // make sense when used in a React application.
136
- this.bypass = bypass
115
+ this._bypass = bypass
137
116
  // this.bypassBatchSize = bypassBatchSize || 10
138
117
 
139
118
  // Using `setTimeout()` in render loop is a workaround
@@ -238,6 +217,13 @@ function createHelpers({
238
217
  this.itemsContainer.clear()
239
218
  }
240
219
 
220
+ this.isItemsContainerElementTableBody = () => {
221
+ return this.engine === DOMEngine &&
222
+ this.getItemsContainerElement().tagName === 'TBODY'
223
+ }
224
+
225
+ this.isInBypassMode = () => this._bypass
226
+
241
227
  this.scrollableContainer = this.engine.createScrollableContainer(
242
228
  getScrollableContainer,
243
229
  this.getItemsContainerElement
@@ -251,7 +237,7 @@ function createHelpers({
251
237
  })
252
238
 
253
239
  this.layout = new Layout({
254
- bypass: this.bypass,
240
+ isInBypassMode: this.isInBypassMode,
255
241
  getInitialEstimatedItemHeight: getEstimatedItemHeight,
256
242
  getInitialEstimatedVisibleItemRowsCount: getEstimatedVisibleItemRowsCount,
257
243
  measureItemsBatchSize,
@@ -278,7 +264,7 @@ function createHelpers({
278
264
  })
279
265
 
280
266
  this.scrollableContainerResizeHandler = new ScrollableContainerResizeHandler({
281
- bypass: this.bypass,
267
+ isInBypassMode: this.isInBypassMode,
282
268
  getWidth: () => this.scrollableContainer.getWidth(),
283
269
  getHeight: () => this.scrollableContainer.getHeight(),
284
270
  listenForResize: (listener) => this.scrollableContainer.onResize(listener),
@@ -308,7 +294,7 @@ function createHelpers({
308
294
  })
309
295
 
310
296
  this.scroll = new Scroll({
311
- bypass: this.bypass,
297
+ isInBypassMode: this.isInBypassMode,
312
298
  scrollableContainer: this.scrollableContainer,
313
299
  itemsContainer: this.itemsContainer,
314
300
  waitForScrollingToStop,
@@ -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
- // Work around `<tbody/>` not being able to have `padding`.
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.tbody) {
73
- if (!hasTbodyStyles(this.getItemsContainerElement())) {
74
- addTbodyStyles(this.getItemsContainerElement())
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
 
@@ -122,7 +122,7 @@ export default function() {
122
122
  const layoutDuration = Date.now() - startedAt
123
123
 
124
124
  // Debugging.
125
- log('~ Calculated Layout' + (this.bypass ? ' (bypass)' : '') + ' ~')
125
+ log('~ Calculated Layout' + (this.isInBypassMode() ? ' (bypass)' : '') + ' ~')
126
126
  if (layoutDuration < SLOW_LAYOUT_DURATION) {
127
127
  // log('Calculated in', layoutDuration, 'ms')
128
128
  } else {
@@ -234,7 +234,7 @@ export default function() {
234
234
 
235
235
  const visibleAreaInsideTheList = getCoordinatesOfVisibleAreaInsideTheList.call(this)
236
236
 
237
- if (this.bypass) {
237
+ if (this.isInBypassMode()) {
238
238
  return {
239
239
  firstShownItemIndex: 0,
240
240
  lastShownItemIndex: itemsCount - 1,
@@ -27,7 +27,7 @@ export default function() {
27
27
  // Update `<tbody/>` `padding`.
28
28
  // (`<tbody/>` is different in a way that it can't have `margin`, only `padding`).
29
29
  // https://gitlab.com/catamphetamine/virtual-scroller/-/issues/1
30
- if (this.tbody) {
30
+ if (this.isItemsContainerElementTableBody()) {
31
31
  setTbodyPadding(
32
32
  this.getItemsContainerElement(),
33
33
  newState.beforeItemsHeight,
@@ -166,6 +166,14 @@ export default function createStateHelpers({
166
166
  setInitialState(this.getInitialState())
167
167
  }
168
168
 
169
+ this.setUpState = () => {
170
+ // If no custom state storage has been configured, use the default one.
171
+ // Also sets the initial state.
172
+ if (!this._usesCustomStateStorage) {
173
+ this.useDefaultStateStorage()
174
+ }
175
+ }
176
+
169
177
  function defaultGetState() {
170
178
  return this.state
171
179
  }
@@ -37,6 +37,8 @@ function VirtualScroller({
37
37
  getEstimatedItemHeight,
38
38
  getEstimatedVisibleItemRowsCount,
39
39
  bypass,
40
+ // `tbody` property is deprecated.
41
+ // Pass `as: "tbody"` property instead.
40
42
  tbody,
41
43
  // `preserveScrollPosition` property name is deprecated,
42
44
  // use `preserveScrollPositionOnPrependItems` property instead.
@@ -62,6 +64,16 @@ function VirtualScroller({
62
64
  getInitialItemState,
63
65
  ...rest
64
66
  }, ref) {
67
+ // It turns out that since May 2022, `useVirtualScroller()` hook completely ignored the `tbody` property.
68
+ // Instead, it always derived `tbody` property value from `as` property value by comparing it to `"tbody"` string.
69
+ // As a result, it seemed like the explicit passing of `tbody` property didn't really work as intended.
70
+ // In the end, it was decided that perhaps `tbody` property value should always be derived from `as` property
71
+ // without a developer having to manually specify it. So the `tbody` property was deprecated.
72
+ // It still exists though for backwards compatibility with the older versions of the package.
73
+ if (tbody === undefined) {
74
+ tbody = AsComponent === 'tbody'
75
+ }
76
+
65
77
  // List items "container" DOM Element reference.
66
78
  const container = useRef()
67
79
 
@@ -75,7 +87,6 @@ function VirtualScroller({
75
87
  getEstimatedVisibleItemRowsCount,
76
88
  bypass,
77
89
  // bypassBatchSize,
78
- tbody,
79
90
  onItemInitialRender,
80
91
  // `onItemFirstRender(i)` is deprecated, use `onItemInitialRender(item)` instead.
81
92
  onItemFirstRender,
@@ -109,8 +120,7 @@ function VirtualScroller({
109
120
  stateToRender
110
121
  } = useState({
111
122
  initialState: _initialState,
112
- onRender: virtualScroller.onRender,
113
- itemsProperty
123
+ onRender: virtualScroller.onRender
114
124
  })
115
125
 
116
126
  // Use custom (external) state storage in the `VirtualScroller`.
@@ -283,7 +293,9 @@ VirtualScroller.propTypes = {
283
293
  getEstimatedVisibleItemRowsCount: PropTypes.func,
284
294
  bypass: PropTypes.bool,
285
295
  // bypassBatchSize: PropTypes.number,
286
- tbody: PropTypes.bool,
296
+ // `tbody` property is deprecated.
297
+ // Pass `as: "tbody"` property instead.
298
+ // tbody: PropTypes.bool,
287
299
  preserveScrollPositionOnPrependItems: PropTypes.bool,
288
300
  // `preserveScrollPosition` property name is deprecated,
289
301
  // use `preserveScrollPositionOnPrependItems` instead.
@@ -9,8 +9,7 @@ import useLayoutEffectDontMountTwiceInStrictMode from './useLayoutEffectDontMoun
9
9
  // Creates state management functions.
10
10
  export default function _useState({
11
11
  initialState,
12
- onRender,
13
- itemsProperty
12
+ onRender
14
13
  }) {
15
14
  // This is a state variable that is used to re-render the component.
16
15
  // Right after the component has finished re-rendering,
@@ -11,7 +11,6 @@ export default function useVirtualScroller({
11
11
  getEstimatedVisibleItemRowsCount,
12
12
  bypass,
13
13
  // bypassBatchSize,
14
- tbody,
15
14
  onItemInitialRender,
16
15
  // `onItemFirstRender(i)` is deprecated, use `onItemInitialRender(item)` instead.
17
16
  onItemFirstRender,
@@ -44,7 +43,6 @@ export default function useVirtualScroller({
44
43
  getEstimatedVisibleItemRowsCount,
45
44
  bypass,
46
45
  // bypassBatchSize,
47
- tbody,
48
46
  onItemInitialRender,
49
47
  // `onItemFirstRender(i)` is deprecated, use `onItemInitialRender(item)` instead.
50
48
  onItemFirstRender,
@@ -57,7 +55,6 @@ export default function useVirtualScroller({
57
55
  getScrollableContainer,
58
56
  getColumnsCount,
59
57
  getItemId,
60
- tbody: AsComponent === 'tbody',
61
58
  state: initialState,
62
59
  getInitialItemState,
63
60
  onStateChange