phanpy/src/components/lazy-shazam.jsx

60 lines
1.4 KiB
React
Raw Normal View History

2024-03-26 11:35:02 +03:00
/*
Rendered but hidden. Only show when visible
*/
2024-04-03 11:06:37 +03:00
import { useEffect, useRef, useState } from 'preact/hooks';
2024-03-26 11:35:02 +03:00
import { useInView } from 'react-intersection-observer';
// The sticky header, usually at the top
const TOP = 48;
2024-04-22 11:42:12 +03:00
const shazamIDs = {};
export default function LazyShazam({ id, children }) {
2024-03-26 11:35:02 +03:00
const containerRef = useRef();
2024-04-22 11:42:12 +03:00
const hasID = !!shazamIDs[id];
2024-03-26 11:35:02 +03:00
const [visible, setVisible] = useState(false);
2024-04-22 11:42:12 +03:00
const [visibleStart, setVisibleStart] = useState(hasID || false);
2024-03-26 11:35:02 +03:00
const { ref } = useInView({
root: null,
rootMargin: `-${TOP}px 0px 0px 0px`,
2024-03-26 11:35:02 +03:00
trackVisibility: true,
delay: 1000,
onChange: (inView) => {
if (inView) {
setVisible(true);
2024-04-22 11:42:12 +03:00
if (id) shazamIDs[id] = true;
2024-03-26 11:35:02 +03:00
}
},
triggerOnce: true,
skip: visibleStart || visible,
});
2024-04-03 11:06:37 +03:00
useEffect(() => {
2024-03-26 11:35:02 +03:00
if (!containerRef.current) return;
const rect = containerRef.current.getBoundingClientRect();
if (rect.bottom > TOP) {
2024-04-04 09:34:28 +03:00
if (rect.top < window.innerHeight) {
setVisible(true);
} else {
setVisibleStart(true);
}
2024-04-22 11:42:12 +03:00
if (id) shazamIDs[id] = true;
2024-03-26 11:35:02 +03:00
}
}, []);
if (visibleStart) return children;
return (
<div
ref={containerRef}
class="shazam-container no-animation"
hidden={!visible}
>
<div ref={ref} class="shazam-container-inner">
{children}
</div>
</div>
);
}