a simple web player for subsonic tinysub.devins.page
subsonic navidrome javascript
11
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 77 lines 1.8 kB view raw
1<script lang="ts"> 2 import type { Snippet } from "svelte"; 3 4 let { 5 items, 6 itemHeight, 7 children, 8 scrollToIndex = $bindable(), 9 } = $props<{ 10 items: any[]; 11 itemHeight: number; 12 children: Snippet<[any, number]>; 13 scrollToIndex?: (index: number) => void; 14 }>(); 15 16 let container: HTMLDivElement; 17 let scrollTop = $state(0); 18 let containerHeight = $state(0); 19 20 scrollToIndex = (index: number) => { 21 if (!container) return; 22 const targetTop = index * itemHeight; 23 const targetBottom = targetTop + itemHeight; 24 if (targetTop < container.scrollTop) { 25 container.scrollTop = targetTop; 26 } else if (targetBottom > container.scrollTop + containerHeight) { 27 container.scrollTop = targetBottom - containerHeight; 28 } 29 }; 30 31 let visibleStart = $derived( 32 Math.max(0, Math.floor(scrollTop / itemHeight) - 8), 33 ); 34 let visibleEnd = $derived( 35 Math.min( 36 items.length, 37 Math.ceil((scrollTop + containerHeight) / itemHeight) + 8, 38 ), 39 ); 40</script> 41 42<div 43 bind:this={container} 44 bind:clientHeight={containerHeight} 45 class="virtual-container" 46 onscroll={() => (scrollTop = container.scrollTop)} 47 tabindex="-1" 48> 49 <div class="virtual-spacer" style:block-size="{items.length * itemHeight}px"> 50 {#each items.slice(visibleStart, visibleEnd) as item, i (i + visibleStart)} 51 {@const index = i + visibleStart} 52 <div 53 class="virtual-item" 54 style:block-size="{itemHeight}px" 55 style:transform="translateY({index * itemHeight}px)" 56 > 57 {@render children(item, index)} 58 </div> 59 {/each} 60 </div> 61</div> 62 63<style> 64 .virtual-container { 65 block-size: 100%; 66 overflow-y: auto; 67 padding-inline: 1rem; 68 } 69 .virtual-spacer { 70 position: relative; 71 } 72 .virtual-item { 73 position: absolute; 74 inset-inline-start: 0; 75 inset-inline-end: 0; 76 } 77</style>