Skip to content

Commit

Permalink
support string height in VirtualList
Browse files Browse the repository at this point in the history
  • Loading branch information
TutorLatin committed Mar 2, 2025
1 parent 7c449a7 commit 4846715
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 79 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ However, if you're passing a function to `itemSize`, that type of comparison is
}
</script>
<button on:click={handleClick}>Recompute Sizes</button>
<button onclick={handleClick}>Recompute Sizes</button>
<VirtualList
bind:this={virtualList}
Expand Down
36 changes: 18 additions & 18 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,23 @@
"@sveltejs/package": "^2.3.10",
"@sveltejs/vite-plugin-svelte": "^5.0.3",
"@types/eslint": "^9.6.1",
"beercss": "^3.8.0",
"eslint": "^9.17.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-svelte": "2.46.0",
"marked": "12.0.2",
"beercss": "^3.9.6",
"eslint": "^9.21.0",
"eslint-config-prettier": "10.0.2",
"eslint-plugin-svelte": "3.0.2",
"marked": "15.0.7",
"marked-base-url": "1.1.6",
"marked-gfm-heading-id": "3.2.0",
"prettier": "3.4.1",
"prettier-plugin-svelte": "3.2.8",
"publint": "0.2.12",
"svelte": "4.2.19",
"svelte-check": "3.8.6",
"svelte-infinite-loading": "1.3.8",
"tslib": "2.6.3",
"typescript": "5.3.3",
"vite": "5.1.8",
"vitest": "1.6.1"
"marked-gfm-heading-id": "4.1.1",
"prettier": "3.5.2",
"prettier-plugin-svelte": "3.3.3",
"publint": "0.3.7",
"svelte": "5.20.5",
"svelte-check": "4.1.4",
"svelte-infinite-loading": "1.4.0",
"tslib": "2.8.1",
"typescript": "5.8.2",
"vite": "6.2.0",
"vitest": "3.0.7"
},
"files": [
"dist",
Expand All @@ -66,7 +66,7 @@
"engines": {
"node": ">=18"
},
"packageManager": "pnpm@9.0.6",
"packageManager": "pnpm@10.5.2",
"keywords": [
"svelte",
"virtual",
Expand Down
15 changes: 10 additions & 5 deletions src/lib/VirtualList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
let wrapperStyle = $state.raw('');
let innerStyle = $state.raw('');
let wrapperHeight = $state(400);
let wrapperWidth = $state(400);
let items = $state.raw([]);
const _props = new ListProps(
Expand All @@ -43,8 +46,8 @@
itemCount,
itemSize,
estimatedItemSize,
height,
width,
Number.isFinite(height) ? height : 400,
Number.isFinite(width) ? width : 400,
stickyIndices
);
Expand All @@ -66,7 +69,7 @@
// Effect 1: Update props from user provided props
$effect(() => {
_props.listen(scrollToIndex, scrollToAlignment, scrollOffset, itemCount, itemSize, estimatedItemSize, height, width, stickyIndices);
_props.listen(scrollToIndex, scrollToAlignment, scrollOffset, itemCount, itemSize, estimatedItemSize, Number.isFinite(height) ? height : wrapperHeight, Number.isFinite(width) ? width : wrapperWidth, stickyIndices);
untrack(() => {
let doRecomputeSizes = false;
Expand Down Expand Up @@ -109,7 +112,7 @@
const refresh = () => {
const { start, stop } = sizeAndPositionManager.getVisibleRange({
containerSize: scrollDirection === DIRECTION.VERTICAL ? height : width,
containerSize: scrollDirection === DIRECTION.VERTICAL ? _props.height : _props.width,
offset: _state.offset,
overscanCount
});
Expand Down Expand Up @@ -179,7 +182,7 @@
return sizeAndPositionManager.getUpdatedOffsetForIndex({
align,
containerSize: scrollDirection === DIRECTION.VERTICAL ? height : width,
containerSize: scrollDirection === DIRECTION.VERTICAL ? _props.height : _props.width,
currentOffset: _state.offset || 0,
targetIndex: index
});
Expand Down Expand Up @@ -232,6 +235,8 @@

<div
bind:this={wrapper}
bind:offsetHeight={wrapperHeight}
bind:offsetWidth={wrapperWidth}
class="virtual-list-wrapper"
style={wrapperStyle}
>
Expand Down
14 changes: 7 additions & 7 deletions src/lib/utils/listProps.svelte.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ export class ListProps {
itemCount = $state(0);
itemSize = $state(0);
estimatedItemSize = $state(0);
height = $state(0);
width = $state(0);
height = $state(400);
width = $state(400);
stickyIndices = $state([]);

// Default values
Expand All @@ -18,8 +18,8 @@ export class ListProps {
itemCount: 0,
itemSize: 0,
estimatedItemSize: 50,
height: 600,
width: "100%",
height: 400,
width: 400,
stickyIndices: []
});

Expand Down Expand Up @@ -49,7 +49,7 @@ export class ListProps {
this.previous_state.stickyIndices.toString() !== $state.snapshot(this.stickyIndices).toString()
};

constructor (scrollToIndex = -1, scrollToAlignment = "start", scrollOffset = 0, itemCount = 0, itemSize = 0, estimatedItemSize = 50, height = 600, width = "100%", stickyIndices = []) {
constructor (scrollToIndex = -1, scrollToAlignment = "start", scrollOffset = 0, itemCount = 0, itemSize = 0, estimatedItemSize = 50, height = 400, width = 400, stickyIndices = []) {
this.scrollToIndex = scrollToIndex;
this.scrollToAlignment = scrollToAlignment;
this.scrollOffset = scrollOffset;
Expand Down Expand Up @@ -83,10 +83,10 @@ export class ListProps {
if (typeof estimatedItemSize === "number")
this.estimatedItemSize = estimatedItemSize || this.itemSize || 50;

if (typeof height === "number" || typeof height === "string")
if (typeof height === "number")
this.height = height;

if (typeof width === "number" || typeof width === "string")
if (typeof width === "number")
this.width = width;

if (Array.isArray(stickyIndices))
Expand Down
59 changes: 31 additions & 28 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<script>
import { base } from '$app/paths';
import { page } from '$app/stores';
import { page } from '$app/state';
import { browser } from '$app/environment';
if (browser) {
if (browser)
import('beercss');
}
let {
children
} = $props();
let darkMode = $state(true);
let mobileMenuOpen = $state(false);
Expand Down Expand Up @@ -42,7 +45,7 @@
</nav>
</header>

<a href="/" class:active={$page.route.id === '/'}>
<a href="/" class:active={page.route.id === '/'}>
<i aria-hidden="true">description</i>
<div>README</div>
</a>
Expand Down Expand Up @@ -71,57 +74,57 @@
<label for="">Examples</label>
<a
href="/examples/elements-of-equal-height"
class:active={$page.route.id === '/examples/elements-of-equal-height'}
class:active={page.route.id === '/examples/elements-of-equal-height'}
>
<i aria-hidden="true">view_headline</i>
<div>Elements of equal height</div>
</a>
<a
href="/examples/variable-heights"
class:active={$page.route.id === '/examples/variable-heights'}
class:active={page.route.id === '/examples/variable-heights'}
>
<i aria-hidden="true">view_day</i>
<div>Variable heights</div>
</a>
<a href="/examples/horizontal-list" class:active={$page.route.id === '/examples/horizontal-list'}>
<a href="/examples/horizontal-list" class:active={page.route.id === '/examples/horizontal-list'}>
<i aria-hidden="true">view_week</i>
<div>Horizontal list</div>
</a>
<a href="/examples/scroll-to-index" class:active={$page.route.id === '/examples/scroll-to-index'}>
<a href="/examples/scroll-to-index" class:active={page.route.id === '/examples/scroll-to-index'}>
<i aria-hidden="true">pin</i>
<div>Scroll to index</div>
</a>
<a
href="/examples/controlled-scroll-offset"
class:active={$page.route.id === '/examples/controlled-scroll-offset'}
class:active={page.route.id === '/examples/controlled-scroll-offset'}
>
<i aria-hidden="true">unfold_more</i>
<div>Controlled scroll offset</div>
</a>

<div class="small-divider"></div>
<label for="">Demos</label>
<a href="/demos/hacker-news" class:active={$page.route.id === '/demos/hacker-news'}>
<a href="/demos/hacker-news" class:active={page.route.id === '/demos/hacker-news'}>
<i aria-hidden="true">newspaper</i>
<div>Hacker News</div>
</a>

<div class="max"></div>
<button class="circle border" on:click={handleSwitchDarkMode}>
<button class="circle border" onclick={handleSwitchDarkMode}>
<i aria-hidden="true">{darkMode ? 'light_mode' : 'dark_mode'}</i>
</button>
</nav>

<nav class="top s m left-align">
<button class="circle transparent" on:click={() => (mobileMenuOpen = true)}>
<button class="circle transparent" onclick={() => (mobileMenuOpen = true)}>
<i aria-hidden="true">menu</i>
</button>
<i aria-hidden="true">
<img src="{base}/logo.svg" srcset="{base}/logo.svg 2x" alt="Logo" />
</i>
<h6 class="m">svelte-tiny-virtual-list</h6>
<div class="max"></div>
<button class="circle border" on:click={handleSwitchDarkMode}>
<button class="circle border" onclick={handleSwitchDarkMode}>
<i aria-hidden="true">{darkMode ? 'light_mode' : 'dark_mode'}</i>
</button>
</nav>
Expand All @@ -133,14 +136,14 @@
</i>
<h6 class="m">svelte-tiny-virtual-list</h6>
<div class="max"></div>
<button class="transparent circle" on:click={() => (mobileMenuOpen = false)}>
<button class="transparent circle" onclick={() => (mobileMenuOpen = false)}>
<i aria-hidden="true">close</i>
</button>
</nav>
</header>

<nav class="drawer no-padding no-margin">
<a href="/" class:active={$page.route.id === '/'} on:click={() => (mobileMenuOpen = false)}>
<a href="/" class:active={page.route.id === '/'} onclick={() => (mobileMenuOpen = false)}>
<i aria-hidden="true">description</i>
<div>README</div>
</a>
Expand Down Expand Up @@ -169,40 +172,40 @@
<label for="">Examples</label>
<a
href="/examples/elements-of-equal-height"
class:active={$page.route.id === '/examples/elements-of-equal-height'}
on:click={() => (mobileMenuOpen = false)}
class:active={page.route.id === '/examples/elements-of-equal-height'}
onclick={() => (mobileMenuOpen = false)}
>
<i aria-hidden="true">view_headline</i>
<div>Elements of equal height</div>
</a>
<a
href="/examples/variable-heights"
class:active={$page.route.id === '/examples/variable-heights'}
on:click={() => (mobileMenuOpen = false)}
class:active={page.route.id === '/examples/variable-heights'}
onclick={() => (mobileMenuOpen = false)}
>
<i aria-hidden="true">view_day</i>
<div>Variable heights</div>
</a>
<a
href="/examples/horizontal-list"
class:active={$page.route.id === '/examples/horizontal-list'}
on:click={() => (mobileMenuOpen = false)}
class:active={page.route.id === '/examples/horizontal-list'}
onclick={() => (mobileMenuOpen = false)}
>
<i aria-hidden="true">view_week</i>
<div>Horizontal list</div>
</a>
<a
href="/examples/scroll-to-index"
class:active={$page.route.id === '/examples/scroll-to-index'}
on:click={() => (mobileMenuOpen = false)}
class:active={page.route.id === '/examples/scroll-to-index'}
onclick={() => (mobileMenuOpen = false)}
>
<i aria-hidden="true">pin</i>
<div>Scroll to index</div>
</a>
<a
href="/examples/controlled-scroll-offset"
class:active={$page.route.id === '/examples/controlled-scroll-offset'}
on:click={() => (mobileMenuOpen = false)}
class:active={page.route.id === '/examples/controlled-scroll-offset'}
onclick={() => (mobileMenuOpen = false)}
>
<i aria-hidden="true">unfold_more</i>
<div>Controlled scroll offset</div>
Expand All @@ -212,8 +215,8 @@
<label for="">Demos</label>
<a
href="/demos/hacker-news"
class:active={$page.route.id === '/demos/hacker-news'}
on:click={() => (mobileMenuOpen = false)}
class:active={page.route.id === '/demos/hacker-news'}
onclick={() => (mobileMenuOpen = false)}
>
<i aria-hidden="true">newspaper</i>
<div>Hacker News</div>
Expand All @@ -222,7 +225,7 @@
</dialog>

<main id="content" class="responsive flex flex-column">
<slot />
{@render children()}
</main>

<style global>
Expand Down
2 changes: 1 addition & 1 deletion src/routes/examples/horizontal-list/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script>
import VirtualList from '$lib/VirtualList.svelte';
let width = $state(1);
let width = $state(500);// TODO no effect, width is always 100%
</script>

<svelte:head>
Expand Down
Loading

0 comments on commit 4846715

Please sign in to comment.