export function createInfiniteScroll<T extends Data<E>, E>( fetcher: (page: number) => Promise<T>): [ pages: Accessor<E[]>, loader: Directive, options: { page: Accessor<number> setPage: Setter<number> setPages: Setter<E[]> end: Accessor<boolean> setEnd: Setter<boolean> refetch: (info?: unknown) => T | Promise<T | undefined> | null | undefined newestData: Resource<T> }] { const [pages, setPages] = createSignal<E[]>([]) const [page, setPage] = createSignal(0) const [end, setEnd] = createSignal(false) const [contents, { refetch }] = createResource(page, fetcher) let add: (el: Element) => void = noop if (!isServer) { const io = new IntersectionObserver((e) => { if (e.length > 0 && e[0]?.isIntersecting && !end() && !contents.loading) { setPage((p) => { return p + 1 }) } }) onCleanup(() => io.disconnect()) add = (el: Element) => { io.observe(el) tryOnCleanup(() => io.unobserve(el)) } } createComputed(() => { const content = contents() if (!content) return batch(() => { if (content.results.length === 0) setEnd(true) else { setEnd(false) } setPages((p) => [...p, ...content.results]) }) }) return [ pages, add, { page, setPage, setPages, end, setEnd, refetch, newestData: contents, }, ]}