Files
webstudio/apps/builder/app/canvas/shared/scroll-state.ts
T
Bogdan Chadkin 097d2922c3 build: remove unused eslint suppressions (#3876)
Looks like we forgot to enable the flag
2024-08-04 23:37:59 +02:00

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();
};
};