Coves frontend - a photon fork
at main 76 lines 2.0 kB view raw
1<script lang="ts"> 2 import type { StrongRef } from '$lib/api/coves/types' 3 import type { DID } from '$lib/types/atproto' 4 import VirtualList from '$lib/app/render/VirtualList.svelte' 5 import { onMount } from 'svelte' 6 import { expoOut } from 'svelte/easing' 7 import { fly } from 'svelte/transition' 8 import type { CommentNodeI } from './comments.svelte' 9 import CommentTree from './CommentTree.svelte' 10 11 interface Props { 12 nodes: CommentNodeI[] 13 postRef: StrongRef 14 postAuthorDid?: DID 15 scrollTo?: string 16 } 17 18 onMount(() => { 19 if (scrollTo) { 20 const element = document?.getElementById(scrollTo) 21 setTimeout(() => { 22 element?.scrollIntoView({ behavior: 'smooth', block: 'start' }) 23 }, 100) 24 } 25 26 const observer = new ResizeObserver((entries) => { 27 entries.forEach((entry) => { 28 if (offsetEl) { 29 initialOffset = 30 entry.target.getBoundingClientRect().top + window.scrollY 31 } 32 }) 33 }) 34 35 if (offsetEl) observer.observe(offsetEl) 36 return () => observer.disconnect() 37 }) 38 39 let { nodes, postRef, postAuthorDid, scrollTo }: Props = $props() 40 41 let offsetEl = $state<HTMLElement>() 42 let initialOffset = $state<number | undefined>(undefined) 43 44 $effect(() => { 45 if (offsetEl) { 46 initialOffset = offsetEl.offsetTop 47 } 48 }) 49</script> 50 51<div bind:this={offsetEl}> 52 {#if offsetEl} 53 <VirtualList 54 class="divide-y-2 divide-slate-100 dark:divide-zinc-900 -mx-3 sm:-mx-6" 55 overscan={5} 56 estimatedHeight={500} 57 items={nodes} 58 {initialOffset} 59 > 60 {#snippet item(row)} 61 <div 62 in:fly={row < 7 63 ? { duration: 800, easing: expoOut, y: 12, delay: row * 50 } 64 : { opacity: 1, duration: 0 }} 65 class="px-3 sm:px-6" 66 > 67 <CommentTree 68 bind:nodes={() => [nodes[row]], (v) => (nodes[row] = v[0])} 69 {postRef} 70 {postAuthorDid} 71 /> 72 </div> 73 {/snippet} 74 </VirtualList> 75 {/if} 76</div>