import { BlogCard, BlogProps } from ':components/BlogBlocks.tsx' import Suspense from ':islands/Suspens.tsx' import { requestApiStream } from ':src/utils.ts' import { Signal, useSignal } from '@preact/signals' import type { JSX } from 'preact' import { useEffect } from 'preact/hooks' function fillList( list: Signal, { limit, ac }: { limit?: number; ac?: AbortController }, ) { ;(async () => { const newsList = requestApiStream( 'news/fetchAll', 'GET', ) for await (const news of newsList) { list.value = [ ...list.value, BlogCard({ ...news, lastUpdate: new Date(news.lastUpdate) }), ] if (limit && list.value.length >= limit) break } ac?.abort() })() } export default function BlogCardList( { limit, usePlaceholder }: { usePlaceholder?: boolean; limit?: number }, ) { const list = useSignal([]) const ac = new AbortController() useEffect(() => { fillList(list, { limit, ac }) }) if (limit && usePlaceholder) { const placeholders = Array .from({ length: limit }) .map((_, index) => ( } fallback={Fallback} signal={ac.signal} > {updateFromList(list, index)} )) return <>{placeholders} } return <>{list} } function Placeholder() { return (

Chargement ...

) } function Fallback() { return (

Pas de news disponible

) } function updateFromList( list: Signal, index: number, ): Promise { const { promise, resolve } = Promise.withResolvers() list.subscribe((value: JSX.Element[]) => { const selected = value.at(index) if (selected) { resolve(selected) } }) return promise }