framer-motion
Version:
A simple and powerful JavaScript animation library
1 lines • 8.66 kB
Source Map (JSON)
{"version":3,"file":"track.mjs","sources":["../../../../../src/render/dom/scroll/track.ts"],"sourcesContent":["import { cancelFrame, frame, frameData, resize, Process } from \"motion-dom\"\nimport { noop } from \"motion-utils\"\nimport { createScrollInfo } from \"./info\"\nimport { createOnScrollHandler } from \"./on-scroll-handler\"\nimport { OnScrollHandler, OnScrollInfo, ScrollInfoOptions } from \"./types\"\n\nconst scrollListeners = new WeakMap<Element, VoidFunction>()\nconst resizeListeners = new WeakMap<Element, VoidFunction>()\nconst onScrollHandlers = new WeakMap<Element, Set<OnScrollHandler>>()\nconst scrollSize = new WeakMap<Element, { width: number; height: number }>()\nconst dimensionCheckProcesses = new WeakMap<Element, Process>()\n\nexport type ScrollTargets = Array<HTMLElement>\n\nconst getEventTarget = (element: Element) =>\n element === document.scrollingElement ? window : element\n\nexport function scrollInfo(\n onScroll: OnScrollInfo,\n {\n container = document.scrollingElement as Element,\n trackContentSize = false,\n ...options\n }: ScrollInfoOptions = {}\n) {\n if (!container) return noop as VoidFunction\n\n let containerHandlers = onScrollHandlers.get(container)\n\n /**\n * Get the onScroll handlers for this container.\n * If one isn't found, create a new one.\n */\n if (!containerHandlers) {\n containerHandlers = new Set()\n onScrollHandlers.set(container, containerHandlers)\n }\n\n /**\n * Create a new onScroll handler for the provided callback.\n */\n const info = createScrollInfo()\n const containerHandler = createOnScrollHandler(\n container,\n onScroll,\n info,\n options\n )\n containerHandlers.add(containerHandler)\n\n /**\n * Check if there's a scroll event listener for this container.\n * If not, create one.\n */\n if (!scrollListeners.has(container)) {\n const measureAll = () => {\n for (const handler of containerHandlers) {\n handler.measure(frameData.timestamp)\n }\n\n frame.preUpdate(notifyAll)\n }\n\n const notifyAll = () => {\n for (const handler of containerHandlers) {\n handler.notify()\n }\n }\n\n const listener = () => frame.read(measureAll)\n\n scrollListeners.set(container, listener)\n\n const target = getEventTarget(container)\n window.addEventListener(\"resize\", listener, { passive: true })\n if (container !== document.documentElement) {\n resizeListeners.set(container, resize(container, listener))\n }\n\n target.addEventListener(\"scroll\", listener, { passive: true })\n\n listener()\n }\n\n /**\n * Enable content size tracking if requested and not already enabled.\n */\n if (trackContentSize && !dimensionCheckProcesses.has(container)) {\n const listener = scrollListeners.get(container)!\n\n // Store initial scroll dimensions (object is reused to avoid allocation)\n const size = {\n width: container.scrollWidth,\n height: container.scrollHeight,\n }\n scrollSize.set(container, size)\n\n // Add frame-based scroll dimension checking to detect content changes\n const checkScrollDimensions: Process = () => {\n const newWidth = container.scrollWidth\n const newHeight = container.scrollHeight\n\n if (size.width !== newWidth || size.height !== newHeight) {\n listener()\n size.width = newWidth\n size.height = newHeight\n }\n }\n\n // Schedule with keepAlive=true to run every frame\n const dimensionCheckProcess = frame.read(checkScrollDimensions, true)\n dimensionCheckProcesses.set(container, dimensionCheckProcess)\n }\n\n const listener = scrollListeners.get(container)!\n frame.read(listener, false, true)\n\n return () => {\n cancelFrame(listener)\n\n /**\n * Check if we even have any handlers for this container.\n */\n const currentHandlers = onScrollHandlers.get(container)\n if (!currentHandlers) return\n\n currentHandlers.delete(containerHandler)\n\n if (currentHandlers.size) return\n\n /**\n * If no more handlers, remove the scroll listener too.\n */\n const scrollListener = scrollListeners.get(container)\n scrollListeners.delete(container)\n\n if (scrollListener) {\n getEventTarget(container).removeEventListener(\n \"scroll\",\n scrollListener\n )\n resizeListeners.get(container)?.()\n window.removeEventListener(\"resize\", scrollListener)\n }\n\n // Clean up scroll dimension checking\n const dimensionCheckProcess = dimensionCheckProcesses.get(container)\n if (dimensionCheckProcess) {\n cancelFrame(dimensionCheckProcess)\n dimensionCheckProcesses.delete(container)\n }\n scrollSize.delete(container)\n }\n}\n"],"names":[],"mappings":"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"}