Skip to content

Commit de7d03c

Browse files
Begin work on list
1 parent 5c3eac0 commit de7d03c

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed

src/components/BetterList.svelte

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
<script lang="ts">
2+
import { onMount, tick } from "svelte"
3+
import View from "../ol/View.svelte"
4+
5+
export let items: any[]
6+
export let height = '100%'
7+
8+
export let scrollPos: number = 0
9+
10+
let heightMap = new WeakMap<any, {
11+
offset: number,
12+
height: number
13+
}>();
14+
15+
let viewport: HTMLElement
16+
let viewportHeight = 0
17+
18+
let contents: HTMLElement;
19+
20+
let top = 0
21+
let bottom = 0
22+
let averageHeight = 0
23+
24+
let startHeight = 0
25+
let start = 0
26+
let endHeight = 0
27+
let end = 0
28+
29+
let mounted = false
30+
31+
let rows: any
32+
$: visible = items.slice(start, end).map((data, i) => ({
33+
index: i + start,
34+
data
35+
}))
36+
37+
$: if(mounted) updateStartAndEnd(top, bottom, items)
38+
39+
async function updateStartAndEnd(top, bottom, items) {
40+
if (top === bottom) return
41+
42+
let y = 0
43+
for (let i = 0; i < items.length; ++i) {
44+
if (y >= bottom) break
45+
46+
if (!heightMap.has(items[i])) {
47+
// update start/end and render row
48+
if (y <= top) {
49+
start = i
50+
startHeight = y
51+
}
52+
end = i + 1
53+
54+
await tick()
55+
56+
console.log(`Rendered ${start} to ${end}`)
57+
58+
const row = contents.querySelector(`l-row[data-row="${i}"]`)
59+
if (!row) {
60+
console.log(contents.childNodes)
61+
console.log("Something went wrong!")
62+
break
63+
}
64+
heightMap.set(items[i], {
65+
offset: row['offsetHeight'],
66+
height: row.clientHeight
67+
})
68+
}
69+
70+
const info = heightMap.get(items[i])
71+
if (y <= top && y + info.height >= top) {
72+
start = i
73+
startHeight = y
74+
}
75+
76+
endHeight = y
77+
end = i + 1
78+
79+
if (y > bottom) {
80+
break
81+
}
82+
}
83+
84+
console.log(`Start: ${start}, End: ${end}, Top: ${top}, Bottom: ${bottom}`)
85+
}
86+
87+
function onScroll() {
88+
top = viewport.scrollTop
89+
bottom = top + viewport.clientHeight
90+
scrollPos = top
91+
}
92+
93+
onMount(() => {
94+
mounted = true
95+
rows = contents.getElementsByTagName('l-row')
96+
onScroll()
97+
})
98+
</script>
99+
100+
<style>
101+
l-viewport {
102+
position: relative;
103+
overflow-y: auto;
104+
-webkit-overflow-scrolling: touch;
105+
display: block;
106+
}
107+
108+
l-contents, l-row {
109+
display: block;
110+
}
111+
112+
l-row {
113+
overflow: hidden;
114+
}
115+
</style>
116+
117+
<l-viewport
118+
bind:this={viewport}
119+
bind:offsetHeight={viewportHeight}
120+
on:scroll={onScroll}
121+
style:height="{height}">
122+
<l-contents bind:this={contents}
123+
style:padding-top="{startHeight}px"
124+
style:padding-bottom="{bottom}px">
125+
{#each visible as row (row.index)}
126+
<l-row data-row={row.index}>
127+
<slot item={row.data}>No template</slot>
128+
</l-row>
129+
{/each}
130+
131+
</l-contents>
132+
</l-viewport>

0 commit comments

Comments
 (0)