Path: blob/master/src/packages/frontend/editors/slate/scroll.ts
1691 views
import { delay } from "awaiting";1import type { SlateEditor } from "./editable-markdown";23export interface ScrollState {4index: number;5offset: number;6}78export function getScrollState(editor: SlateEditor): ScrollState | undefined {9const startIndex = editor.windowedListRef.current?.visibleRange?.startIndex;10if (startIndex == null) return;11const endIndex = editor.windowedListRef.current?.visibleRange?.endIndex;12if (endIndex == null) return;1314let index, offset;15if (endIndex > startIndex) {16index = startIndex + 1;17offset = editor.windowedListRef.current?.secondItemOffset ?? 0;18} else {19index = startIndex;20offset = editor.windowedListRef.current?.firstItemOffset ?? 0;21}2223return { index, offset };24}2526export async function setScrollState(editor: SlateEditor, scroll: ScrollState) {27const { index, offset } = scroll;28const f = async () => {29editor.windowedListRef.current?.virtuosoRef.current?.scrollToIndex?.(index);30// We have to set this twice, or it sometimes doesn't work. Setting it twice31// flickers a lot less than. This might be a bug in virtuoso. Also, we32// have to first set it above without the offset, then set it with!. Weird.33await new Promise(requestAnimationFrame);34editor.windowedListRef.current?.virtuosoRef.current?.scrollToIndex?.({35index,36offset,37});38};3940// Do it once:41await f();42// Then wait until next loop and try again.43// This combination seems pretty effective.44await delay(0);45await f();46}474849