@indielayer/ui
Version:
Indielayer UI Components with Tailwind CSS build for Vue 3
73 lines (61 loc) • 1.64 kB
text/typescript
import { assert } from '../utils/assert'
import type { Bounds, CachedBounds, SizeFunction } from './types'
export function createCachedBounds<Props extends object>({
itemCount,
itemProps,
itemSize,
}: {
itemCount: number;
itemProps: Props;
itemSize: number | SizeFunction<Props>;
}): CachedBounds {
const cache = new Map<number, Bounds>()
return {
get(index: number) {
assert(index < itemCount, `Invalid index ${index}`)
while (cache.size - 1 < index) {
const currentIndex = cache.size
let size: number
switch (typeof itemSize) {
case 'function': {
size = itemSize(currentIndex, itemProps)
break
}
case 'number': {
size = itemSize
break
}
}
if (currentIndex === 0) {
cache.set(currentIndex, {
size,
scrollOffset: 0,
})
} else {
const previousRowBounds = cache.get(currentIndex - 1)
assert(
previousRowBounds !== undefined,
`Unexpected bounds cache miss for index ${index}`,
)
cache.set(currentIndex, {
scrollOffset:
previousRowBounds.scrollOffset + previousRowBounds.size,
size,
})
}
}
const bounds = cache.get(index)
assert(
bounds !== undefined,
`Unexpected bounds cache miss for index ${index}`,
)
return bounds
},
set(index: number, bounds: Bounds) {
cache.set(index, bounds)
},
get size() {
return cache.size
},
}
}