mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: generalized intersection
This commit is contained in:
1 parent
33c67b9416
commit
555c94f3b1
3 files changed
+39
-19
No files matched your search
@@ -1,6 +1,7 @@
|
|||||||
import { Skeleton, Table } from '@radix-ui/themes';
|
import { Skeleton, Table } from '@radix-ui/themes';
|
||||||
import { times } from 'lodash';
|
import { times } from 'lodash';
|
||||||
import { useEffect, useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
|
import { useIntersection } from '../../../../hooks/useIntersection';
|
||||||
import { tankPerformanceSortTypeNamesArray } from '../../../../stores/tankPerformanceSort';
|
import { tankPerformanceSortTypeNamesArray } from '../../../../stores/tankPerformanceSort';
|
||||||
|
|
||||||
interface RowLoaderProps {
|
interface RowLoaderProps {
|
||||||
@@ -10,14 +11,9 @@ interface RowLoaderProps {
|
|||||||
export function RowLoader({ onIntersection }: RowLoaderProps) {
|
export function RowLoader({ onIntersection }: RowLoaderProps) {
|
||||||
const row = useRef<HTMLTableRowElement>(null);
|
const row = useRef<HTMLTableRowElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useIntersection(() => onIntersection?.(), row, {
|
||||||
if (!onIntersection || !row.current) return;
|
disabled: onIntersection === undefined,
|
||||||
|
});
|
||||||
const observer = new IntersectionObserver(onIntersection);
|
|
||||||
observer.observe(row.current);
|
|
||||||
|
|
||||||
return () => observer.disconnect();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table.Row ref={row}>
|
<Table.Row ref={row}>
|
||||||
|
|||||||
@@ -134,16 +134,9 @@ export function Tanks() {
|
|||||||
return (
|
return (
|
||||||
<RowLoader
|
<RowLoader
|
||||||
key={index}
|
key={index}
|
||||||
onIntersection={
|
onIntersection={() => {
|
||||||
index === 0
|
setLoadedRows((state) => Math.min(state + 2, tanks.length));
|
||||||
? () => {
|
}}
|
||||||
console.log('Intersected');
|
|
||||||
setLoadedRows((state) =>
|
|
||||||
Math.min(state + PREVIEW_COUNT, tanks.length),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { RefObject, useLayoutEffect, useRef } from 'react';
|
||||||
|
|
||||||
|
interface UseIntersectionOptions extends IntersectionObserverInit {
|
||||||
|
disabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useIntersection(
|
||||||
|
callback: () => void,
|
||||||
|
ref: RefObject<HTMLElement>,
|
||||||
|
options?: UseIntersectionOptions,
|
||||||
|
) {
|
||||||
|
const observer = useRef<IntersectionObserver>();
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (options?.disabled || !ref.current) return;
|
||||||
|
|
||||||
|
const rect = ref.current.getBoundingClientRect();
|
||||||
|
const visible = !(rect.bottom < 0 || rect.top - window.innerHeight >= 0);
|
||||||
|
|
||||||
|
if (visible) {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
observer.current = new IntersectionObserver(callback, options);
|
||||||
|
observer.current.observe(ref.current);
|
||||||
|
|
||||||
|
return () => observer.current!.disconnect();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return observer;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user