Skip to content

Commit

Permalink
Remove internal adapter connecting Svelte to core
Browse files Browse the repository at this point in the history
  • Loading branch information
inokawa committed Nov 30, 2024
1 parent d739d69 commit d187e5d
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 322 deletions.
8 changes: 3 additions & 5 deletions rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ const terserPlugin = ({ vue } = {}) =>
},
});

const svelteDir = path.dirname(pkg.exports["./svelte"].default);

/** @type { import('rollup').RollupOptions[] } */
export default [
// react and type
Expand Down Expand Up @@ -136,10 +134,10 @@ export default [
},
// svelte
{
input: "src/svelte/core.ts",
input: "src/core/index.ts",
output: [
{
file: path.join(svelteDir, "core.js"),
file: "./lib/core/index.js",
format: "esm",
// sourcemap: true,
},
Expand All @@ -152,7 +150,7 @@ export default [
exclude: ["**/*.{spec,stories}.*"],
}),
terserPlugin(),
svelteCopy({ dir: svelteDir }),
svelteCopy({ dir: path.dirname(pkg.exports["./svelte"].default) }),
],
external,
},
Expand Down
2 changes: 1 addition & 1 deletion scripts/rollup-plugin-svelte-copy.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const svelteCopy = ({ dir }) => {

const svelteCodes = [];

for (const filename of globSync("./src/svelte/[!core.ts]*")) {
for (const filename of globSync("./src/svelte/*")) {
if (filename.endsWith(".svelte")) {
const code = readFileSync(filename, "utf8");
writeFileSync(join(dir, basename(filename)), code);
Expand Down
2 changes: 1 addition & 1 deletion src/svelte/ListItem.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts" generics="T">
import { type Snippet, onDestroy } from "svelte";
import { isRTLDocument, type ItemResizeObserver } from "./core";
import { isRTLDocument, type ItemResizeObserver } from "../core";
import { styleToString } from "./utils";
import type { SvelteHTMLElements } from "svelte/elements";
Expand Down
148 changes: 70 additions & 78 deletions src/svelte/Virtualizer.svelte
Original file line number Diff line number Diff line change
@@ -1,32 +1,17 @@
<script lang="ts" generics="T">
import { onMount, onDestroy } from "svelte";
import {
ACTION_ITEMS_LENGTH_CHANGE,
ACTION_START_OFFSET_CHANGE,
type StateVersion,
CHANGE_ITEM_LENGTH,
createVirtualizer,
FIX_SCROLL_JUMP,
GET_ITEM_OFFSET,
GET_JUMP_COUNT,
GET_RANGE,
GET_IS_SCROLLING,
GET_SCROLL_OFFSET,
GET_SCROLL_SIZE,
GET_TOTAL_SIZE,
GET_VIEWPORT_SIZE,
IS_ITEM_HIDDEN,
OBSERVE_ITEM_RESIZE,
ON_MOUNT,
ON_UN_MOUNT,
SCROLL_BY,
SCROLL_TO,
SCROLL_TO_INDEX,
CHANGE_START_MARGIN,
GET_START_SPACER_SIZE,
GET_ITEMS_LENGTH,
GET_ITEM_SIZE,
FIND_START_INDEX,
FIND_END_INDEX,
} from "./core";
UPDATE_SCROLL_END_EVENT,
UPDATE_SCROLL_EVENT,
UPDATE_VIRTUAL_STATE,
createResizer,
createScroller,
createVirtualStore,
getScrollSize as _getScrollSize,
} from "../core";
import { defaultGetKey, styleToString, iterRange } from "./utils";
import ListItem from "./ListItem.svelte";
import type { VirtualizerHandle, VirtualizerProps } from "./Virtualizer.type";
Expand All @@ -49,17 +34,24 @@
onscrollend,
}: Props = $props();
const virtualizer = createVirtualizer(
const store = createVirtualStore(
data.length,
itemSize,
overscan,
horizontal,
(v) => {
rerender = v;
},
(offset) => {
onscroll && onscroll(offset);
},
undefined,
undefined,
!itemSize
);
const resizer = createResizer(store, horizontal);
const scroller = createScroller(store, horizontal);
const unsubscribeStore = store._subscribe(UPDATE_VIRTUAL_STATE, () => {
rerender = store._getStateVersion();
});
const unsubscribeOnScroll = store._subscribe(UPDATE_SCROLL_EVENT, () => {
onscroll && onscroll(store._getScrollOffset());
});
const unsubscribeOnScrollEnd = store._subscribe(
UPDATE_SCROLL_END_EVENT,
() => {
onscrollend && onscrollend();
}
Expand All @@ -69,71 +61,71 @@
let rerender: StateVersion = $state([]);
let range = $derived(rerender && virtualizer[GET_RANGE]());
let isScrolling = $derived(rerender && virtualizer[GET_IS_SCROLLING]());
let totalSize = $derived(rerender && virtualizer[GET_TOTAL_SIZE]());
let jumpCount = $derived(rerender && virtualizer[GET_JUMP_COUNT]());
let range = $derived(rerender && store._getRange());
let isScrolling = $derived(rerender && store._isScrolling());
let totalSize = $derived(rerender && store._getTotalSize());
let jumpCount = $derived(rerender && store._getJumpCount());
onMount(() => {
const assignRef = (scrollable: HTMLElement) => {
resizer._observeRoot(scrollable);
scroller._observe(scrollable);
};
if (scrollRef) {
virtualizer[ON_MOUNT](scrollRef);
assignRef(scrollRef);
} else {
virtualizer[ON_MOUNT](containerRef!.parentElement!);
assignRef(containerRef!.parentElement!);
}
});
onDestroy(() => {
virtualizer[ON_UN_MOUNT]();
unsubscribeStore();
unsubscribeOnScroll();
unsubscribeOnScrollEnd();
resizer._dispose();
scroller._dispose();
});
$effect.pre(() => {
if (data.length !== virtualizer[GET_ITEMS_LENGTH]()) {
virtualizer[CHANGE_ITEM_LENGTH](data.length, shift);
if (data.length !== store._getItemsLength()) {
store._update(ACTION_ITEMS_LENGTH_CHANGE, [data.length, shift]);
}
});
$effect.pre(() => {
if (startMargin !== virtualizer[GET_START_SPACER_SIZE]()) {
virtualizer[CHANGE_START_MARGIN](startMargin);
if (startMargin !== store._getStartSpacerSize()) {
store._update(ACTION_START_OFFSET_CHANGE, startMargin);
}
});
let prevJumpCount: number | undefined;
$effect(() => {
if (prevJumpCount === jumpCount) return;
prevJumpCount = jumpCount;
virtualizer[FIX_SCROLL_JUMP]();
scroller._fixScrollJump();
});
export const getScrollOffset = virtualizer[
GET_SCROLL_OFFSET
] satisfies VirtualizerHandle["getScrollOffset"] as VirtualizerHandle["getScrollOffset"];
export const getScrollSize = virtualizer[
GET_SCROLL_SIZE
] satisfies VirtualizerHandle["getScrollSize"] as VirtualizerHandle["getScrollSize"];
export const getViewportSize = virtualizer[
GET_VIEWPORT_SIZE
] satisfies VirtualizerHandle["getViewportSize"] as VirtualizerHandle["getViewportSize"];
export const findStartIndex = virtualizer[
FIND_START_INDEX
] satisfies VirtualizerHandle["findStartIndex"] as VirtualizerHandle["findStartIndex"];
export const findEndIndex = virtualizer[
FIND_END_INDEX
] satisfies VirtualizerHandle["findEndIndex"] as VirtualizerHandle["findEndIndex"];
export const getItemOffset = virtualizer[
GET_ITEM_OFFSET
] satisfies VirtualizerHandle["getItemOffset"] as VirtualizerHandle["getItemOffset"];
export const getItemSize = virtualizer[
GET_ITEM_SIZE
] satisfies VirtualizerHandle["getItemSize"] as VirtualizerHandle["getItemSize"];
export const scrollToIndex = virtualizer[
SCROLL_TO_INDEX
] satisfies VirtualizerHandle["scrollToIndex"] as VirtualizerHandle["scrollToIndex"];
export const scrollTo = virtualizer[
SCROLL_TO
] satisfies VirtualizerHandle["scrollTo"] as VirtualizerHandle["scrollTo"];
export const scrollBy = virtualizer[
SCROLL_BY
] satisfies VirtualizerHandle["scrollBy"] as VirtualizerHandle["scrollBy"];
export const getScrollOffset =
store._getScrollOffset satisfies VirtualizerHandle["getScrollOffset"] as VirtualizerHandle["getScrollOffset"];
export const getScrollSize = (() =>
_getScrollSize(
store
)) satisfies VirtualizerHandle["getScrollSize"] as VirtualizerHandle["getScrollSize"];
export const getViewportSize =
store._getViewportSize satisfies VirtualizerHandle["getViewportSize"] as VirtualizerHandle["getViewportSize"];
export const findStartIndex =
store._findStartIndex satisfies VirtualizerHandle["findStartIndex"] as VirtualizerHandle["findStartIndex"];
export const findEndIndex =
store._findEndIndex satisfies VirtualizerHandle["findEndIndex"] as VirtualizerHandle["findEndIndex"];
export const getItemOffset =
store._getItemOffset satisfies VirtualizerHandle["getItemOffset"] as VirtualizerHandle["getItemOffset"];
export const getItemSize =
store._getItemSize satisfies VirtualizerHandle["getItemSize"] as VirtualizerHandle["getItemSize"];
export const scrollToIndex =
scroller._scrollToIndex satisfies VirtualizerHandle["scrollToIndex"] as VirtualizerHandle["scrollToIndex"];
export const scrollTo =
scroller._scrollTo satisfies VirtualizerHandle["scrollTo"] as VirtualizerHandle["scrollTo"];
export const scrollBy =
scroller._scrollBy satisfies VirtualizerHandle["scrollBy"] as VirtualizerHandle["scrollBy"];
let containerStyle = $derived(
styleToString({
Expand Down Expand Up @@ -161,10 +153,10 @@
{item}
{index}
as={itemAs}
offset={rerender && virtualizer[GET_ITEM_OFFSET](index)}
hide={rerender && virtualizer[IS_ITEM_HIDDEN](index)}
offset={rerender && store._getItemOffset(index)}
hide={rerender && store._isUnmeasuredItem(index)}
{horizontal}
resizer={virtualizer[OBSERVE_ITEM_RESIZE]}
resizer={resizer._observeItem}
/>
{/each}
</svelte:element>
94 changes: 48 additions & 46 deletions src/svelte/WindowVirtualizer.svelte
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
<script lang="ts" generics="T">
import { onMount, onDestroy } from "svelte";
import {
ACTION_ITEMS_LENGTH_CHANGE,
type StateVersion,
CHANGE_ITEM_LENGTH,
createWindowVirtualizer,
FIX_SCROLL_JUMP,
GET_ITEM_OFFSET,
GET_JUMP_COUNT,
GET_RANGE,
GET_IS_SCROLLING,
GET_TOTAL_SIZE,
IS_ITEM_HIDDEN,
OBSERVE_ITEM_RESIZE,
ON_MOUNT,
ON_UN_MOUNT,
GET_ITEMS_LENGTH,
FIND_START_INDEX,
FIND_END_INDEX,
SCROLL_TO_INDEX,
} from "./core";
UPDATE_SCROLL_END_EVENT,
UPDATE_SCROLL_EVENT,
UPDATE_VIRTUAL_STATE,
createVirtualStore,
getScrollSize as _getScrollSize,
createWindowResizer,
createWindowScroller,
} from "../core";
import { defaultGetKey, iterRange, styleToString } from "./utils";
import ListItem from "./ListItem.svelte";
import type {
Expand All @@ -40,17 +32,25 @@
onscrollend,
}: Props = $props();
const virtualizer = createWindowVirtualizer(
const store = createVirtualStore(
data.length,
itemSize,
overscan,
horizontal,
(v) => {
rerender = v;
},
(offset) => {
onscroll && onscroll(offset);
},
undefined,
undefined,
!itemSize
);
const resizer = createWindowResizer(store, horizontal);
const scroller = createWindowScroller(store, horizontal);
const unsubscribeStore = store._subscribe(UPDATE_VIRTUAL_STATE, () => {
rerender = store._getStateVersion();
});
const unsubscribeOnScroll = store._subscribe(UPDATE_SCROLL_EVENT, () => {
onscroll && onscroll(store._getScrollOffset());
});
const unsubscribeOnScrollEnd = store._subscribe(
UPDATE_SCROLL_END_EVENT,
() => {
onscrollend && onscrollend();
}
Expand All @@ -60,40 +60,42 @@
let rerender: StateVersion = $state([]);
let range = $derived(rerender && virtualizer[GET_RANGE]());
let isScrolling = $derived(rerender && virtualizer[GET_IS_SCROLLING]());
let totalSize = $derived(rerender && virtualizer[GET_TOTAL_SIZE]());
let jumpCount = $derived(rerender && virtualizer[GET_JUMP_COUNT]());
let range = $derived(rerender && store._getRange());
let isScrolling = $derived(rerender && store._isScrolling());
let totalSize = $derived(rerender && store._getTotalSize());
let jumpCount = $derived(rerender && store._getJumpCount());
onMount(() => {
virtualizer[ON_MOUNT](containerRef!);
resizer._observeRoot(containerRef!);
scroller._observe(containerRef!);
});
onDestroy(() => {
virtualizer[ON_UN_MOUNT]();
unsubscribeStore();
unsubscribeOnScroll();
unsubscribeOnScrollEnd();
resizer._dispose();
scroller._dispose();
});
$effect.pre(() => {
if (data.length !== virtualizer[GET_ITEMS_LENGTH]()) {
virtualizer[CHANGE_ITEM_LENGTH](data.length, shift);
if (data.length !== store._getItemsLength()) {
store._update(ACTION_ITEMS_LENGTH_CHANGE, [data.length, shift]);
}
});
let prevJumpCount: number | undefined;
$effect(() => {
if (prevJumpCount === jumpCount) return;
prevJumpCount = jumpCount;
virtualizer[FIX_SCROLL_JUMP]();
scroller._fixScrollJump();
});
export const findStartIndex = virtualizer[
FIND_START_INDEX
] satisfies WindowVirtualizerHandle["findStartIndex"] as WindowVirtualizerHandle["findStartIndex"];
export const findEndIndex = virtualizer[
FIND_END_INDEX
] satisfies WindowVirtualizerHandle["findEndIndex"] as WindowVirtualizerHandle["findEndIndex"];
export const scrollToIndex = virtualizer[
SCROLL_TO_INDEX
] satisfies WindowVirtualizerHandle["scrollToIndex"] as WindowVirtualizerHandle["scrollToIndex"];
export const findStartIndex =
store._findStartIndex satisfies WindowVirtualizerHandle["findStartIndex"] as WindowVirtualizerHandle["findStartIndex"];
export const findEndIndex =
store._findEndIndex satisfies WindowVirtualizerHandle["findEndIndex"] as WindowVirtualizerHandle["findEndIndex"];
export const scrollToIndex =
scroller._scrollToIndex satisfies WindowVirtualizerHandle["scrollToIndex"] as WindowVirtualizerHandle["scrollToIndex"];
let containerStyle = $derived(
styleToString({
Expand Down Expand Up @@ -121,10 +123,10 @@
{item}
{index}
as={"div"}
offset={rerender && virtualizer[GET_ITEM_OFFSET](index)}
hide={rerender && virtualizer[IS_ITEM_HIDDEN](index)}
offset={rerender && store._getItemOffset(index)}
hide={rerender && store._isUnmeasuredItem(index)}
{horizontal}
resizer={virtualizer[OBSERVE_ITEM_RESIZE]}
resizer={resizer._observeItem}
/>
{/each}
</div>
Loading

0 comments on commit d187e5d

Please sign in to comment.