pinafore/routes/_utils/virtualListStore.js

60 lines
1.4 KiB
JavaScript
Raw Normal View History

import { Store } from 'svelte/store.js'
class VirtualListStore extends Store {
}
const virtualListStore = new VirtualListStore({
items: [],
itemHeights: {},
})
2018-01-16 01:12:07 +01:00
virtualListStore.compute('visibleItems',
2018-01-17 06:43:31 +01:00
['items', 'scrollTop', 'itemHeights', 'offsetHeight'],
(items, scrollTop, itemHeights, offsetHeight) => {
2018-01-17 09:06:24 +01:00
let renderBuffer = 3 * offsetHeight
2018-01-16 01:12:07 +01:00
let visibleItems = []
2018-01-16 02:25:32 +01:00
let totalOffset = 0
let len = items.length
let i = -1
while (++i < len) {
let { props, key } = items[i]
2018-01-16 01:35:08 +01:00
let height = itemHeights[key] || 0
2018-01-16 02:25:32 +01:00
let currentOffset = totalOffset
totalOffset += height
let isBelowViewport = (currentOffset < scrollTop)
if (isBelowViewport) {
2018-01-16 03:29:28 +01:00
if (scrollTop - renderBuffer > currentOffset) {
2018-01-16 02:25:32 +01:00
continue // below the area we want to render
}
2018-01-16 01:12:07 +01:00
} else {
2018-01-17 08:16:15 +01:00
if (currentOffset > (scrollTop + height + renderBuffer)) {
2018-01-16 02:25:32 +01:00
break // above the area we want to render
}
2018-01-16 01:12:07 +01:00
}
2018-01-16 02:25:32 +01:00
visibleItems.push({
offset: currentOffset,
props: props,
key: key,
2018-01-17 08:16:15 +01:00
index: i
2018-01-16 02:25:32 +01:00
})
}
2018-01-16 01:12:07 +01:00
return visibleItems
})
2018-01-16 01:35:08 +01:00
virtualListStore.compute('height', ['items', 'itemHeights'], (items, itemHeights) => {
let sum = 0
2018-01-16 02:25:32 +01:00
let i = -1
let len = items.length
while (++i < len) {
sum += itemHeights[items[i].key] || 0
}
return sum
})
if (process.browser && process.env.NODE_ENV !== 'production') {
window.virtualListStore = virtualListStore
}
export {
virtualListStore
}