UNPKG

@tanstack/svelte-virtual

Version:

Headless UI for virtualizing scrollable elements in Svelte

103 lines (93 loc) 3.1 kB
import { Virtualizer, elementScroll, observeElementOffset, observeElementRect, observeWindowOffset, observeWindowRect, windowScroll, } from '@tanstack/virtual-core' import { derived, writable } from 'svelte/store' import type { PartialKeys, VirtualizerOptions } from '@tanstack/virtual-core' import type { Readable, Writable } from 'svelte/store' export * from '@tanstack/virtual-core' export type SvelteVirtualizer< TScrollElement extends Element | Window, TItemElement extends Element, > = Omit<Virtualizer<TScrollElement, TItemElement>, 'setOptions'> & { setOptions: ( options: Partial<VirtualizerOptions<TScrollElement, TItemElement>>, ) => void } function createVirtualizerBase< TScrollElement extends Element | Window, TItemElement extends Element, >( initialOptions: VirtualizerOptions<TScrollElement, TItemElement>, ): Readable<SvelteVirtualizer<TScrollElement, TItemElement>> { const virtualizer = new Virtualizer(initialOptions) const originalSetOptions = virtualizer.setOptions // eslint-disable-next-line prefer-const let virtualizerWritable: Writable<Virtualizer<TScrollElement, TItemElement>> const setOptions = ( options: Partial<VirtualizerOptions<TScrollElement, TItemElement>>, ) => { const resolvedOptions = { ...virtualizer.options, ...options, onChange: options.onChange, } originalSetOptions({ ...resolvedOptions, onChange: ( instance: Virtualizer<TScrollElement, TItemElement>, sync: boolean, ) => { virtualizerWritable.set(instance) resolvedOptions.onChange?.(instance, sync) }, }) virtualizer._willUpdate() } virtualizerWritable = writable(virtualizer, () => { setOptions(initialOptions) return virtualizer._didMount() }) return derived(virtualizerWritable, (instance) => Object.assign(instance, { setOptions }), ) } export function createVirtualizer< TScrollElement extends Element, TItemElement extends Element, >( options: PartialKeys< VirtualizerOptions<TScrollElement, TItemElement>, 'observeElementRect' | 'observeElementOffset' | 'scrollToFn' >, ): Readable<SvelteVirtualizer<TScrollElement, TItemElement>> { return createVirtualizerBase<TScrollElement, TItemElement>({ observeElementRect: observeElementRect, observeElementOffset: observeElementOffset, scrollToFn: elementScroll, ...options, }) } export function createWindowVirtualizer<TItemElement extends Element>( options: PartialKeys< VirtualizerOptions<Window, TItemElement>, | 'getScrollElement' | 'observeElementRect' | 'observeElementOffset' | 'scrollToFn' >, ): Readable<SvelteVirtualizer<Window, TItemElement>> { return createVirtualizerBase<Window, TItemElement>({ getScrollElement: () => (typeof document !== 'undefined' ? window : null), observeElementRect: observeWindowRect, observeElementOffset: observeWindowOffset, scrollToFn: windowScroll, initialOffset: () => (typeof document !== 'undefined' ? window.scrollY : 0), ...options, }) }