Files
wehub-resource-sync adf0d17497
publish / version_or_publish (push) Has been cancelled
storybook-build / changes (push) Has been cancelled
storybook-build / :storybook-build (push) Has been cancelled
Sync Gradio Skills to Hugging Face / sync-skills (push) Has been cancelled
functional / changes (push) Has been cancelled
functional / build-frontend (push) Has been cancelled
functional / functional-test-SSR=false (push) Has been cancelled
functional / functional-reload (push) Has been cancelled
js / changes (push) Has been cancelled
js / js-test (push) Has been cancelled
docs-build / changes (push) Has been cancelled
docs-build / docs-build (push) Has been cancelled
docs-build / website-build (push) Has been cancelled
functional / functional-test-SSR=true (push) Has been cancelled
hygiene / hygiene-test (push) Has been cancelled
python / changes (push) Has been cancelled
python / build (push) Has been cancelled
python / test-ubuntu-latest-flaky (push) Has been cancelled
python / test-ubuntu-latest-not-flaky (push) Has been cancelled
python / test-windows-latest-flaky (push) Has been cancelled
python / test-windows-latest-not-flaky (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:17:32 +08:00

106 lines
2.3 KiB
TypeScript

import {
Virtualizer,
elementScroll,
observeElementOffset,
observeElementRect,
type PartialKeys,
type VirtualizerOptions
} from "@tanstack/virtual-core";
import { untrack } from "svelte";
export type { VirtualItem } from "@tanstack/virtual-core";
/**
* Creates a reactive TanStack Virtualizer for Svelte 5.
*
* Returns a getter function that returns the virtualizer instance.
* Call the getter inside $derived or template expressions to create
* reactive dependencies on the virtualizer state.
*/
export function createSvelteVirtualizer<
TScrollElement extends Element,
TItemElement extends Element
>(
options: PartialKeys<
VirtualizerOptions<TScrollElement, TItemElement>,
"observeElementRect" | "observeElementOffset" | "scrollToFn"
>
): {
instance: Virtualizer<TScrollElement, TItemElement>;
virtualItems: () => ReturnType<
Virtualizer<TScrollElement, TItemElement>["getVirtualItems"]
>;
totalSize: () => number;
} {
let version = $state(0);
const virtualizer = new Virtualizer<TScrollElement, TItemElement>({
observeElementRect: observeElementRect,
observeElementOffset: observeElementOffset,
scrollToFn: elementScroll,
...options,
onChange: (instance, sync) => {
if (sync) {
version += 1;
} else {
queueMicrotask(() => {
version += 1;
});
}
options.onChange?.(instance, sync);
}
});
$effect(() => {
const cleanup = virtualizer._didMount();
untrack(() => {
version += 1;
});
return cleanup;
});
let prev_count = 0;
$effect(() => {
const current_count = options.count;
virtualizer.setOptions({
observeElementRect: observeElementRect,
observeElementOffset: observeElementOffset,
scrollToFn: elementScroll,
...options,
onChange: (instance, sync) => {
if (sync) {
version += 1;
} else {
queueMicrotask(() => {
version += 1;
});
}
options.onChange?.(instance, sync);
}
});
if (prev_count === 0 && current_count > 0) {
virtualizer.measure();
}
prev_count = current_count;
});
$effect.pre(() => {
void version;
virtualizer._willUpdate();
});
return {
instance: virtualizer,
virtualItems: () => {
void version;
return virtualizer.getVirtualItems();
},
totalSize: () => {
void version;
return virtualizer.getTotalSize();
}
};
}