phanpy/src/components/lazy-shazam.jsx

57 wiersze
1.4 KiB
React

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