mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-05 11:38:36 +09:00
67 lines
1.6 KiB
TypeScript
67 lines
1.6 KiB
TypeScript
import { createNanoEvents } from "nanoevents";
|
|
|
|
// Using a JS emitter to avoid overhead with subscribing scroll event directly on the DOM by many listeners
|
|
const emitter = createNanoEvents<{
|
|
scrollStart: () => void;
|
|
scroll: () => void;
|
|
scrollEnd: () => void;
|
|
}>();
|
|
|
|
if (typeof window === "object") {
|
|
const eventOptions = {
|
|
passive: true,
|
|
capture: true,
|
|
};
|
|
|
|
let timeoutId = 0;
|
|
let isScrolling = false;
|
|
|
|
window.addEventListener(
|
|
"scroll",
|
|
() => {
|
|
if (isScrolling === false) {
|
|
emitter.emit("scrollStart");
|
|
}
|
|
emitter.emit("scroll");
|
|
isScrolling = true;
|
|
clearTimeout(timeoutId);
|
|
timeoutId = window.setTimeout(() => {
|
|
if (isScrolling === false) {
|
|
return;
|
|
}
|
|
isScrolling = false;
|
|
emitter.emit("scrollEnd");
|
|
}, 150);
|
|
},
|
|
eventOptions
|
|
);
|
|
}
|
|
|
|
type UseScrollState = {
|
|
onScroll?: () => void;
|
|
onScrollStart?: () => void;
|
|
onScrollEnd?: () => void;
|
|
};
|
|
|
|
const noop = () => {};
|
|
|
|
/**
|
|
* Scroll state abstraction that can handle a lot of subscribers well.
|
|
* Potentially could add rate limiting and actual scroll top/left values.
|
|
*/
|
|
export const subscribeScrollState = ({
|
|
onScroll = noop,
|
|
onScrollStart = noop,
|
|
onScrollEnd = noop,
|
|
}: UseScrollState) => {
|
|
const unsubscribeScrollStart = emitter.on("scrollStart", onScrollStart);
|
|
const unsubscribeScroll = emitter.on("scroll", onScroll);
|
|
const unsubscribeScrollEnd = emitter.on("scrollEnd", onScrollEnd);
|
|
|
|
return () => {
|
|
unsubscribeScrollStart();
|
|
unsubscribeScroll();
|
|
unsubscribeScrollEnd();
|
|
};
|
|
};
|