| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- import { frame, cancelFrame, frameData } from 'motion-dom';
- import { resize } from '../resize/index.mjs';
- import { createScrollInfo } from './info.mjs';
- import { createOnScrollHandler } from './on-scroll-handler.mjs';
- const scrollListeners = new WeakMap();
- const resizeListeners = new WeakMap();
- const onScrollHandlers = new WeakMap();
- const getEventTarget = (element) => element === document.documentElement ? window : element;
- function scrollInfo(onScroll, { container = document.documentElement, ...options } = {}) {
- let containerHandlers = onScrollHandlers.get(container);
- /**
- * Get the onScroll handlers for this container.
- * If one isn't found, create a new one.
- */
- if (!containerHandlers) {
- containerHandlers = new Set();
- onScrollHandlers.set(container, containerHandlers);
- }
- /**
- * Create a new onScroll handler for the provided callback.
- */
- const info = createScrollInfo();
- const containerHandler = createOnScrollHandler(container, onScroll, info, options);
- containerHandlers.add(containerHandler);
- /**
- * Check if there's a scroll event listener for this container.
- * If not, create one.
- */
- if (!scrollListeners.has(container)) {
- const measureAll = () => {
- for (const handler of containerHandlers)
- handler.measure();
- };
- const updateAll = () => {
- for (const handler of containerHandlers) {
- handler.update(frameData.timestamp);
- }
- };
- const notifyAll = () => {
- for (const handler of containerHandlers)
- handler.notify();
- };
- const listener = () => {
- frame.read(measureAll, false, true);
- frame.read(updateAll, false, true);
- frame.update(notifyAll, false, true);
- };
- scrollListeners.set(container, listener);
- const target = getEventTarget(container);
- window.addEventListener("resize", listener, { passive: true });
- if (container !== document.documentElement) {
- resizeListeners.set(container, resize(container, listener));
- }
- target.addEventListener("scroll", listener, { passive: true });
- }
- const listener = scrollListeners.get(container);
- frame.read(listener, false, true);
- return () => {
- cancelFrame(listener);
- /**
- * Check if we even have any handlers for this container.
- */
- const currentHandlers = onScrollHandlers.get(container);
- if (!currentHandlers)
- return;
- currentHandlers.delete(containerHandler);
- if (currentHandlers.size)
- return;
- /**
- * If no more handlers, remove the scroll listener too.
- */
- const scrollListener = scrollListeners.get(container);
- scrollListeners.delete(container);
- if (scrollListener) {
- getEventTarget(container).removeEventListener("scroll", scrollListener);
- resizeListeners.get(container)?.();
- window.removeEventListener("resize", scrollListener);
- }
- };
- }
- export { scrollInfo };
|