Skip to content

Commit 7e0343c

Browse files
author
dasathyakuma
committed
more fixes
1 parent f5f8539 commit 7e0343c

File tree

13 files changed

+386
-704
lines changed

13 files changed

+386
-704
lines changed
Lines changed: 54 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,55 @@
1-
/**
2-
* Dynamic-size virtualisation example
3-
*
4-
* Item sizes are unknown at render time — they depend on rendered content.
5-
* We use measureElement to let the virtualizer observe each item's actual
6-
* size via ResizeObserver after it renders into the DOM.
7-
*
8-
* This is the correct approach when content determines height (e.g. text
9-
* that wraps, images with unknown aspect ratios, or any dynamic content).
10-
*/
11-
12-
static const items = Array.from({ length: 1000 }, (_, i) => ({
13-
id: i,
14-
// Simulate content of varying length
15-
text: "Item " + i + "" + "lorem ipsum ".repeat(1 + (i % 5)),
16-
}))
17-
18-
<let/mounted = false/>
19-
<script() { mounted = true }/>
20-
21-
<div class="page">
22-
<h1>Dynamic Virtualisation</h1>
23-
<p>
24-
Item sizes are <strong>unknown</strong> at render time. Each rendered item
25-
is measured by the virtualizer via <code>measureElement</code>, and the
26-
scroll space is updated as real sizes are discovered.
27-
</p>
28-
<p class="note">
29-
Notice: provide a rough <code>estimateSize</code> so the initial scroll
30-
space is reasonable before measurement completes.
31-
</p>
32-
33-
<if=mounted>
34-
<div/$scrollEl class="scroll-container" style="height: 400px; overflow-y: auto">
35-
<virtualizer|{ virtualItems, totalSize, measureElement }|
36-
count=items.length
37-
estimateSize=() => 45
38-
getScrollElement=scrollEl
39-
>
40-
<div style=`height: ${totalSize}px; width: 100%; position: relative`>
41-
<for|item| of=virtualItems>
42-
<!--
43-
DOM ref pattern for dynamic measurement:
44-
1. /$el captures a ref to this DOM node
45-
2. <script> runs after render and calls measureElement(el())
46-
so the virtualizer learns the real height via ResizeObserver
47-
-->
48-
<div/$el
49-
class=item.index % 2 === 0 ? "item item-even" : "item item-odd"
50-
style=`
51-
position: absolute;
52-
top: 0;
53-
left: 0;
54-
width: 100%;
55-
transform: translateY(${item.start}px);
56-
padding: 10px 12px;
57-
box-sizing: border-box;
58-
`
59-
>
60-
<script() {
61-
const node = el()
62-
if (node && measureElement) measureElement(node)
63-
}/>
64-
<strong>${items[item.index]!.id}.</strong>
65-
${items[item.index]!.text}
66-
</div>
67-
</for>
68-
</div>
69-
</virtualizer>
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8"/>
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
6+
<title>Dynamic Virtualisation — @tanstack/marko-virtual</title>
7+
<style>
8+
* { box-sizing: border-box; margin: 0; padding: 0; }
9+
body { font-family: system-ui, sans-serif; padding: 24px; }
10+
h1 { font-size: 24px; margin-bottom: 8px; }
11+
p { color: #555; margin-bottom: 16px; font-size: 14px; line-height: 1.5; }
12+
.scroll-container { height: 400px; overflow-y: auto; border: 1px solid #e5e7eb; border-radius: 6px; }
13+
.item { padding: 10px 12px; font-size: 14px; border-bottom: 1px solid #f3f4f6; box-sizing: border-box; line-height: 1.5; }
14+
.item-even { background: #f9fafb; }
15+
.item-odd { background: #ffffff; }
16+
</style>
17+
</head>
18+
<body>
19+
<h1>Dynamic Virtualisation</h1>
20+
<p>Item sizes are unknown at render time. Each item is measured after render via measureElement.</p>
21+
22+
static const items = Array.from({ length: 1000 }, (_, i) => ({
23+
id: i,
24+
text: "Item " + i + " — " + "lorem ipsum ".repeat(1 + (i % 5)),
25+
}))
26+
27+
<let/mounted = false/>
28+
<script() { mounted = true }/>
29+
30+
<div/scrollEl class="scroll-container">
31+
<if=mounted>
32+
<virtualizer|{ virtualItems, totalSize, measureElement }|
33+
count=items.length
34+
estimateSize=() => 45
35+
getScrollElement=scrollEl
36+
>
37+
<div style=`height: ${totalSize}px; width: 100%; position: relative`>
38+
<for|item| of=virtualItems>
39+
<div/$el
40+
class=item.index % 2 === 0 ? "item item-even" : "item item-odd"
41+
style=`position: absolute; top: 0; left: 0; width: 100%; transform: translateY(${item.start}px)`
42+
>
43+
<script() {
44+
const node = el()
45+
if (node && measureElement) measureElement(node)
46+
}/>
47+
<strong>${items[item.index]!.id}.</strong> ${items[item.index]!.text}
48+
</div>
49+
</for>
50+
</div>
51+
</virtualizer>
52+
</if>
7053
</div>
71-
</if>
72-
</div>
73-
74-
<style>
75-
.page {
76-
font-family: system-ui, sans-serif;
77-
max-width: 600px;
78-
margin: 0 auto;
79-
padding: 24px;
80-
}
81-
82-
h1 { font-size: 24px; margin-bottom: 8px; }
83-
p { color: #555; margin-bottom: 12px; }
84-
.note { font-size: 13px; color: #888; font-style: italic; }
85-
code { background: #f3f4f6; padding: 1px 4px; border-radius: 3px; }
86-
87-
.scroll-container {
88-
border: 1px solid #e5e7eb;
89-
border-radius: 6px;
90-
}
91-
92-
.item {
93-
font-size: 14px;
94-
line-height: 1.5;
95-
border-bottom: 1px solid #f3f4f6;
96-
}
97-
98-
.item-even { background: #f9fafb; }
99-
.item-odd { background: #ffffff; }
100-
</style>
54+
</body>
55+
</html>

examples/marko/fixed/src/routes/+page.marko

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
<let/mounted = false/>
3030
<script() { mounted = true }/>
31-
<p>debug: mounted=${String(mounted)}</p>
3231

3332
<section>
3433
<h2>Rows</h2>
@@ -111,6 +110,5 @@
111110
</if>
112111
</div>
113112
</section>
114-
115113
</body>
116114
</html>

examples/marko/grid/marko.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ "taglib-imports": ["../../../packages/marko-virtual/marko.json"] }
Lines changed: 55 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,60 @@
1-
/**
2-
* Grid virtualisation example
3-
*
4-
* A 2D grid virtualised in both axes simultaneously.
5-
* Achieved by composing two <virtualizer> tags sharing the same scroll element:
6-
* - outer: vertical (rows)
7-
* - inner: horizontal (columns, horizontal=true)
8-
*
9-
* Only the cells visible in the current viewport are in the DOM.
10-
*/
11-
12-
static const ROW_COUNT = 1000
13-
static const COL_COUNT = 1000
14-
15-
static const rowSizes = Array.from({ length: ROW_COUNT }, () =>
16-
30 + Math.round(Math.random() * 20)
17-
)
18-
static const colSizes = Array.from({ length: COL_COUNT }, () =>
19-
80 + Math.round(Math.random() * 80)
20-
)
21-
22-
<let/mounted = false/>
23-
<script() { mounted = true }/>
24-
25-
<div class="page">
26-
<h1>Grid Virtualisation</h1>
27-
<p>
28-
A ${ROW_COUNT} × ${COL_COUNT} grid — ${(ROW_COUNT * COL_COUNT).toLocaleString()} cells total.
29-
Only those in the current viewport are rendered.
30-
</p>
31-
<p class="note">
32-
Pattern: compose two <code>&lt;virtualizer&gt;</code> tags sharing
33-
the same scroll element — one vertical, one horizontal.
34-
</p>
35-
36-
<if=mounted>
37-
<div/$gridScroll class="scroll-container" style="height: 500px; width: 100%; overflow: auto">
38-
<virtualizer|{ virtualItems: rowItems, totalSize: rowTotal }|
39-
count=ROW_COUNT
40-
estimateSize=(i) => rowSizes[i]!
41-
getScrollElement=gridScroll
42-
>
43-
<virtualizer|{ virtualItems: colItems, totalSize: colTotal }|
44-
count=COL_COUNT
45-
estimateSize=(i) => colSizes[i]!
46-
horizontal=true
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8"/>
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
6+
<title>Grid Virtualisation — @tanstack/marko-virtual</title>
7+
<style>
8+
* { box-sizing: border-box; margin: 0; padding: 0; }
9+
body { font-family: system-ui, sans-serif; padding: 24px; }
10+
h1 { font-size: 24px; margin-bottom: 8px; }
11+
p { color: #555; margin-bottom: 16px; }
12+
.scroll-grid { height: 500px; width: 100%; max-width: 700px; overflow: auto; border: 1px solid #e5e7eb; border-radius: 6px; }
13+
.cell { font-size: 11px; font-family: monospace; box-sizing: border-box; border-right: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb; display: flex; align-items: center; justify-content: center; }
14+
.cell-even { background: #f9fafb; }
15+
.cell-odd { background: #ffffff; }
16+
</style>
17+
</head>
18+
<body>
19+
<h1>Grid Virtualisation</h1>
20+
<p>A 1000 × 1000 grid — two &lt;virtualizer&gt; tags sharing the same scroll element.</p>
21+
22+
static const ROW_COUNT = 1000
23+
static const COL_COUNT = 1000
24+
static const rowSizes = Array.from({ length: ROW_COUNT }, () => 30 + Math.round(Math.random() * 20))
25+
static const colSizes = Array.from({ length: COL_COUNT }, () => 80 + Math.round(Math.random() * 80))
26+
27+
<let/mounted = false/>
28+
<script() { mounted = true }/>
29+
30+
<div/gridScroll class="scroll-grid">
31+
<if=mounted>
32+
<virtualizer|{ virtualItems: rowItems, totalSize: rowTotal }|
33+
count=ROW_COUNT
34+
estimateSize=(i) => rowSizes[i]!
4735
getScrollElement=gridScroll
4836
>
49-
<div style=`height: ${rowTotal}px; width: ${colTotal}px; position: relative`>
50-
<for|row| of=rowItems>
51-
<for|col| of=colItems>
52-
<div
53-
class=(col.index + row.index) % 2 === 0 ? "cell cell-even" : "cell cell-odd"
54-
style=`
55-
position: absolute;
56-
top: 0;
57-
left: 0;
58-
display: flex;
59-
align-items: center;
60-
justify-content: center;
61-
width: ${col.size}px;
62-
height: ${row.size}px;
63-
transform: translateX(${col.start}px) translateY(${row.start}px);
64-
font-size: 11px;
65-
box-sizing: border-box;
66-
border-right: 1px solid #e5e7eb;
67-
border-bottom: 1px solid #e5e7eb;
68-
`
69-
>
70-
${row.index},${col.index}
71-
</div>
37+
<virtualizer|{ virtualItems: colItems, totalSize: colTotal }|
38+
count=COL_COUNT
39+
estimateSize=(i) => colSizes[i]!
40+
horizontal=true
41+
getScrollElement=gridScroll
42+
>
43+
<div style=`height: ${rowTotal}px; width: ${colTotal}px; position: relative`>
44+
<for|row| of=rowItems>
45+
<for|col| of=colItems>
46+
<div
47+
class=(col.index + row.index) % 2 === 0 ? "cell cell-even" : "cell cell-odd"
48+
style=`position: absolute; top: 0; left: 0; width: ${col.size}px; height: ${row.size}px; transform: translateX(${col.start}px) translateY(${row.start}px)`
49+
>
50+
${row.index},${col.index}
51+
</div>
52+
</for>
7253
</for>
73-
</for>
74-
</div>
54+
</div>
55+
</virtualizer>
7556
</virtualizer>
76-
</virtualizer>
57+
</if>
7758
</div>
78-
</if>
79-
</div>
80-
81-
<style>
82-
.page {
83-
font-family: system-ui, sans-serif;
84-
max-width: 800px;
85-
margin: 0 auto;
86-
padding: 24px;
87-
}
88-
89-
h1 { font-size: 24px; margin-bottom: 8px; }
90-
p { color: #555; margin-bottom: 12px; }
91-
.note { font-size: 13px; color: #888; font-style: italic; }
92-
code { background: #f3f4f6; padding: 1px 4px; border-radius: 3px; }
93-
94-
.scroll-container {
95-
border: 1px solid #e5e7eb;
96-
border-radius: 6px;
97-
overflow: auto;
98-
}
99-
100-
.cell {
101-
font-family: monospace;
102-
color: #374151;
103-
}
104-
105-
.cell-even { background: #f9fafb; }
106-
.cell-odd { background: #ffffff; }
107-
</style>
59+
</body>
60+
</html>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ "taglib-imports": ["../../../packages/marko-virtual/marko.json"] }

0 commit comments

Comments
 (0)