feat(VirtualList): incoroprate new logic related to window scroll and separation of isVisible flag
This commit is contained in:
@@ -76,6 +76,18 @@ interface Props {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
onNearBottom?: (lastVisibleIndex: number) => void;
|
onNearBottom?: (lastVisibleIndex: number) => void;
|
||||||
|
/**
|
||||||
|
* Snippet for rendering individual list items.
|
||||||
|
*
|
||||||
|
* The snippet receives an object containing:
|
||||||
|
* - `item`: The item from the items array (type T)
|
||||||
|
* - `index`: The current item's index in the array
|
||||||
|
*
|
||||||
|
* This pattern provides type safety and flexibility for
|
||||||
|
* rendering different item types without prop drilling.
|
||||||
|
*
|
||||||
|
* @template T - The type of items in the list
|
||||||
|
*/
|
||||||
/**
|
/**
|
||||||
* Snippet for rendering individual list items.
|
* Snippet for rendering individual list items.
|
||||||
*
|
*
|
||||||
@@ -89,8 +101,13 @@ interface Props {
|
|||||||
* @template T - The type of items in the list
|
* @template T - The type of items in the list
|
||||||
*/
|
*/
|
||||||
children: Snippet<
|
children: Snippet<
|
||||||
[{ item: T; index: number; isVisible: boolean; proximity: number }]
|
[{ item: T; index: number; isFullyVisible: boolean; isPartiallyVisible: boolean; proximity: number }]
|
||||||
>;
|
>;
|
||||||
|
/**
|
||||||
|
* Whether to use the window as the scroll container.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
useWindowScroll?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {
|
||||||
@@ -102,6 +119,7 @@ let {
|
|||||||
onVisibleItemsChange,
|
onVisibleItemsChange,
|
||||||
onNearBottom,
|
onNearBottom,
|
||||||
children,
|
children,
|
||||||
|
useWindowScroll = false,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
// Reference to the ScrollArea viewport element for attaching the virtualizer
|
// Reference to the ScrollArea viewport element for attaching the virtualizer
|
||||||
@@ -112,6 +130,7 @@ const virtualizer = createVirtualizer(() => ({
|
|||||||
data: items,
|
data: items,
|
||||||
estimateSize: typeof itemHeight === 'function' ? itemHeight : () => itemHeight,
|
estimateSize: typeof itemHeight === 'function' ? itemHeight : () => itemHeight,
|
||||||
overscan,
|
overscan,
|
||||||
|
useWindowScroll,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Attach virtualizer.container action to the viewport when it becomes available
|
// Attach virtualizer.container action to the viewport when it becomes available
|
||||||
@@ -139,9 +158,38 @@ $effect(() => {
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if useWindowScroll}
|
||||||
|
<div class={cn('relative w-full', className)} bind:this={viewportRef}>
|
||||||
|
<div style:height="{virtualizer.totalSize}px" class="relative w-full">
|
||||||
|
{#each virtualizer.items as item (item.key)}
|
||||||
|
<div
|
||||||
|
use:virtualizer.measureElement
|
||||||
|
data-index={item.index}
|
||||||
|
class="absolute top-0 left-0 w-full"
|
||||||
|
style:transform="translateY({item.start}px)"
|
||||||
|
>
|
||||||
|
{#if item.index < items.length}
|
||||||
|
{@render children({
|
||||||
|
// TODO: Fix indenation rule for this case
|
||||||
|
item: items[item.index],
|
||||||
|
index: item.index,
|
||||||
|
isFullyVisible: item.isFullyVisible,
|
||||||
|
isPartiallyVisible: item.isPartiallyVisible,
|
||||||
|
proximity: item.proximity,
|
||||||
|
})}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
<ScrollArea
|
<ScrollArea
|
||||||
bind:viewportRef
|
bind:viewportRef
|
||||||
class={cn('relative rounded-md bg-background', 'h-150 w-full', className)}
|
class={cn(
|
||||||
|
'relative rounded-md bg-background',
|
||||||
|
'h-150 w-full',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
orientation="vertical"
|
orientation="vertical"
|
||||||
>
|
>
|
||||||
<div style:height="{virtualizer.totalSize}px" class="relative w-full">
|
<div style:height="{virtualizer.totalSize}px" class="relative w-full">
|
||||||
@@ -158,7 +206,8 @@ $effect(() => {
|
|||||||
// TODO: Fix indenation rule for this case
|
// TODO: Fix indenation rule for this case
|
||||||
item: items[item.index],
|
item: items[item.index],
|
||||||
index: item.index,
|
index: item.index,
|
||||||
isVisible: item.isVisible,
|
isFullyVisible: item.isFullyVisible,
|
||||||
|
isPartiallyVisible: item.isPartiallyVisible,
|
||||||
proximity: item.proximity,
|
proximity: item.proximity,
|
||||||
})}
|
})}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -166,3 +215,4 @@ $effect(() => {
|
|||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user