@snapdrag/plugins
Version:
Plugins for Snapdrag drag and drop library
1 lines • 8.75 kB
Source Map (JSON)
{"version":3,"sources":["../src/scroller.ts"],"names":["defaultAxisConfig","getAxisConfig","axisConfig","getContainerBoundingRect","container","scale","top","bottom","left","right","createScroller","config","configX","configY","isMouseDown","lastAnimationFrame","lastTimestamp","lastMouseX","lastMouseY","animationLoop","timestamp","deltaT","scrollDeltaX","scrollDeltaY","threshold","speed","distancePower","borderDistanceX","scrollDelta","onDragStart","onDragEnd","onDragMove","event","ratio","viewportScale","shouldRun","cleanup"],"mappings":"aAaA,IAAMA,CAAAA,CAAgC,CACpC,SAAW,CAAA,GAAA,CACX,MAAO,GACP,CAAA,aAAA,CAAe,GACjB,CAEA,CAAA,SAASC,EAAcC,CAAkC,CAAA,CACvD,OAAI,OAAOA,CAAAA,EAAe,UACjB,CAAE,GAAGF,CAAkB,CAGzB,CAAA,CAAE,GAAGA,CAAmB,CAAA,GAAGE,CAAW,CAC/C,CAEA,SAASC,CAAyBC,CAAAA,CAAAA,CAAiCC,EAAe,CAChF,GAAID,aAAqB,MACvB,CAAA,OAAO,CACL,GAAK,CAAA,CAAA,CACL,KAAM,CACN,CAAA,MAAA,CAAQA,EAAU,WAClB,CAAA,KAAA,CAAOA,EAAU,UACnB,CAAA,CACK,CACL,GAAI,CAAE,IAAAE,CAAK,CAAA,MAAA,CAAAC,EAAQ,IAAAC,CAAAA,CAAAA,CAAM,MAAAC,CAAM,CAAA,CAAIL,EAAU,qBAAsB,EAAA,CAEnE,OAAO,CACL,GAAA,CAAKE,EAAMD,CACX,CAAA,MAAA,CAAQE,EAASF,CACjB,CAAA,IAAA,CAAMG,EAAOH,CACb,CAAA,KAAA,CAAOI,EAAQJ,CACjB,CACF,CACF,CAEO,SAASK,EAAeC,CAAwB,CAAA,CACrD,OAAO,SAAkBP,CAAAA,CAAoD,CAC3E,GAAI,CAACA,CACH,CAAA,OAAO,EAAC,CAGV,IAAMQ,CAAUD,CAAAA,CAAAA,CAAO,EAAIV,CAAcU,CAAAA,CAAAA,CAAO,CAAC,CAAI,CAAA,IAAA,CAC/CE,EAAUF,CAAO,CAAA,CAAA,CAAIV,EAAcU,CAAO,CAAA,CAAC,EAAI,IAEjDG,CAAAA,CAAAA,CAAc,MACdC,CAAoC,CAAA,IAAA,CACpCC,EAAwB,CACxBC,CAAAA,CAAAA,CAAqB,EACrBC,CAAqB,CAAA,CAAA,CACrBb,EAAQ,CAEZ,CAAA,SAASc,EAAcC,CAAmB,CAAA,CACxC,GAAI,CAACN,CAAAA,CACH,OAGF,IAAMO,CAAAA,CAASD,EAAYJ,CAC3BA,CAAAA,CAAAA,CAAgBI,EAEhB,IAAIE,CAAAA,CAAe,EACfC,CAAe,CAAA,CAAA,CAEb,CAAE,GAAAjB,CAAAA,CAAAA,CAAK,OAAAC,CAAQ,CAAA,IAAA,CAAAC,EAAM,KAAAC,CAAAA,CAAM,EAAIN,CAAyBC,CAAAA,CAAAA,CAAYC,CAAK,CAE/E,CAAA,GAAIO,EAAS,CACX,GAAM,CAAE,SAAAY,CAAAA,CAAAA,CAAW,MAAAC,CAAO,CAAA,aAAA,CAAAC,CAAc,CAAId,CAAAA,CAAAA,CAEtCe,EAAkB,IAAK,CAAA,GAAA,CAC3BH,EAAYhB,CAAOS,CAAAA,CAAAA,CACnBO,EAAYf,CAAQQ,CAAAA,CACtB,EAKMW,CAFJ,CAAA,IAAA,CAAK,IAAI,IAAK,CAAA,GAAA,CAAID,EAAkBH,CAAW,CAAA,CAAG,CAAGE,CAAAA,CAAa,CAAID,CAAAA,CAAAA,CAErCJ,EAAU,GAEzCJ,CAAAA,CAAAA,CAAaO,EAAYhB,CAC3Bc,CAAAA,CAAAA,CAAe,CAACM,CACPX,CAAAA,CAAAA,CAAaR,EAAQe,CAC9BF,GAAAA,CAAAA,CAAeM,GAEnB,CAEA,GAAIf,EAAS,CACX,GAAM,CAAE,SAAAW,CAAAA,CAAAA,CAAW,MAAAC,CAAO,CAAA,aAAA,CAAAC,CAAc,CAAIb,CAAAA,CAAAA,CAEtCc,EAAkB,IAAK,CAAA,GAAA,CAC3BH,EAAYlB,CAAMY,CAAAA,CAAAA,CAClBM,EAAYjB,CAASW,CAAAA,CACvB,EAKMU,CAFJ,CAAA,IAAA,CAAK,IAAI,IAAK,CAAA,GAAA,CAAID,EAAkBH,CAAW,CAAA,CAAG,EAAGE,CAAa,CAAA,CAAID,EAErCJ,CAAU,CAAA,GAAA,CAEzCH,EAAaM,CAAYlB,CAAAA,CAAAA,CAC3BiB,EAAe,CAACK,CAAAA,CACPV,EAAaX,CAASiB,CAAAA,CAAAA,GAC/BD,EAAeK,CAEnB,EAAA,CAAA,CAIIN,IAAiB,CAAKC,EAAAA,CAAAA,GAAiB,IACzCnB,CAAW,EAAA,QAAA,CAASkB,EAAcC,CAAY,CAAA,CAGhDR,EAAqB,qBAAsBI,CAAAA,CAAa,EAC1D,CAEA,SAASU,GAAc,CACrBf,CAAAA,CAAc,KACdE,CAAgB,CAAA,WAAA,CAAY,MAC9B,CAEA,SAASc,CAAY,EAAA,CACnBhB,EAAc,KACdE,CAAAA,CAAAA,CAAgB,CAEZD,CAAAA,CAAAA,EACF,oBAAqBA,CAAAA,CAAkB,EAE3C,CAEA,SAASgB,EAAW,CAAE,KAAA,CAAAC,CAAM,CAAuB,CAAA,CACjD,IAAMC,CAAQ,CAAA,MAAA,CAAO,iBACfC,CAAgB,CAAA,MAAA,CAAO,eAAiB,MAAO,CAAA,cAAA,CAAe,MAAQ,CAE5E7B,CAAAA,CAAAA,CAAQ4B,EAAQC,CAEhBjB,CAAAA,CAAAA,CAAce,EAAqB,CAAI3B,CAAAA,CAAAA,CACvCa,EAAcc,CAAqB,CAAA,CAAA,CAAI3B,EAEvC,GAAM,CAAE,IAAAC,CAAK,CAAA,MAAA,CAAAC,EAAQ,IAAAC,CAAAA,CAAAA,CAAM,MAAAC,CAAM,CAAA,CAAIN,EAAyBC,CAAYC,CAAAA,CAAK,EAE3E8B,CAAY,CAAA,KAAA,CAEZvB,IACFuB,CACElB,GAAAA,CAAAA,CAAAA,CAAAA,CAAaL,EAAQ,SAAYJ,CAAAA,CAAAA,EAAQS,EAAaR,CAAQG,CAAAA,CAAAA,CAAQ,YAGtEC,CACFsB,GAAAA,CAAAA,GAAAA,CAAAA,CACEjB,EAAaL,CAAQ,CAAA,SAAA,CAAYP,GAAOY,CAAaX,CAAAA,CAAAA,CAASM,EAAQ,SAGtEE,CAAAA,CAAAA,CAAAA,CAAAA,EACF,qBAAqBA,CAAkB,CAAA,CAGrCoB,IACFpB,CAAqB,CAAA,qBAAA,CAAsBI,CAAa,CAE5D,EAAA,CAEA,SAASiB,CAAU,EAAA,CACjBN,IACF,CAEA,OAAO,CACL,WAAA,CAAAD,EACA,SAAAC,CAAAA,CAAAA,CACA,WAAAC,CACA,CAAA,OAAA,CAAAK,CACF,CACF,CACF","file":"index.cjs","sourcesContent":["import { PluginType } from \"@snapdrag/core\";\n\ntype AxisConfig = {\n threshold?: number;\n speed?: number;\n distancePower?: number;\n};\n\ntype ScrollerConfig = {\n x?: AxisConfig | boolean;\n y?: AxisConfig | boolean;\n};\n\nconst defaultAxisConfig: AxisConfig = {\n threshold: 100,\n speed: 2000,\n distancePower: 1.5,\n};\n\nfunction getAxisConfig(axisConfig: AxisConfig | boolean) {\n if (typeof axisConfig === \"boolean\") {\n return { ...defaultAxisConfig } as Required<AxisConfig>;\n }\n\n return { ...defaultAxisConfig, ...axisConfig } as Required<AxisConfig>;\n}\n\nfunction getContainerBoundingRect(container: HTMLElement | Window, scale: number) {\n if (container instanceof Window) {\n return {\n top: 0,\n left: 0,\n bottom: container.innerHeight,\n right: container.innerWidth,\n };\n } else {\n let { top, bottom, left, right } = container.getBoundingClientRect();\n\n return {\n top: top * scale,\n bottom: bottom * scale,\n left: left * scale,\n right: right * scale,\n };\n }\n}\n\nexport function createScroller(config: ScrollerConfig) {\n return function Scroller(container: HTMLElement | Window | null): PluginType {\n if (!container) {\n return {};\n }\n\n const configX = config.x ? getAxisConfig(config.x) : null;\n const configY = config.y ? getAxisConfig(config.y) : null;\n\n let isMouseDown = false;\n let lastAnimationFrame: number | null = null;\n let lastTimestamp: number = 0;\n let lastMouseX: number = 0;\n let lastMouseY: number = 0;\n let scale = 1.0;\n\n function animationLoop(timestamp: number) {\n if (!isMouseDown) {\n return;\n }\n\n const deltaT = timestamp - lastTimestamp;\n lastTimestamp = timestamp;\n\n let scrollDeltaX = 0;\n let scrollDeltaY = 0;\n\n const { top, bottom, left, right } = getContainerBoundingRect(container!, scale);\n\n if (configX) {\n const { threshold, speed, distancePower } = configX;\n\n const borderDistanceX = Math.max(\n threshold + left - lastMouseX,\n threshold - right + lastMouseX\n );\n\n const scrollSpeed =\n Math.pow(Math.min(borderDistanceX / threshold, 1.0), distancePower) * speed;\n\n const scrollDelta = (scrollSpeed * deltaT) / 1000;\n\n if (lastMouseX < threshold - left) {\n scrollDeltaX = -scrollDelta;\n } else if (lastMouseX > right - threshold) {\n scrollDeltaX = scrollDelta;\n }\n }\n\n if (configY) {\n const { threshold, speed, distancePower } = configY;\n\n const borderDistanceX = Math.max(\n threshold + top - lastMouseY,\n threshold - bottom + lastMouseY\n );\n\n const scrollSpeed =\n Math.pow(Math.min(borderDistanceX / threshold, 1.0), distancePower) * speed;\n\n const scrollDelta = (scrollSpeed * deltaT) / 1000;\n\n if (lastMouseY < threshold - top) {\n scrollDeltaY = -scrollDelta;\n } else if (lastMouseY > bottom - threshold) {\n scrollDeltaY = scrollDelta;\n }\n }\n\n // prevent scroll from firing every animation frame\n // if there is nothing to scroll\n if (scrollDeltaX !== 0 || scrollDeltaY !== 0) {\n container?.scrollBy(scrollDeltaX, scrollDeltaY);\n }\n\n lastAnimationFrame = requestAnimationFrame(animationLoop);\n }\n\n function onDragStart() {\n isMouseDown = true;\n lastTimestamp = performance.now();\n }\n\n function onDragEnd() {\n isMouseDown = false;\n lastTimestamp = 0;\n\n if (lastAnimationFrame) {\n cancelAnimationFrame(lastAnimationFrame);\n }\n }\n\n function onDragMove({ event }: { event: UIEvent }) {\n const ratio = window.devicePixelRatio;\n const viewportScale = window.visualViewport ? window.visualViewport.scale : 1;\n\n scale = ratio / viewportScale;\n\n lastMouseX = (event as MouseEvent).x * scale;\n lastMouseY = (event as MouseEvent).y * scale;\n\n const { top, bottom, left, right } = getContainerBoundingRect(container!, scale);\n\n let shouldRun = false;\n\n if (configX) {\n shouldRun ||=\n lastMouseX < configX.threshold + left || lastMouseX > right - configX.threshold;\n }\n\n if (configY) {\n shouldRun ||=\n lastMouseY < configY.threshold + top || lastMouseY > bottom - configY.threshold;\n }\n\n if (lastAnimationFrame) {\n cancelAnimationFrame(lastAnimationFrame);\n }\n\n if (shouldRun) {\n lastAnimationFrame = requestAnimationFrame(animationLoop);\n }\n }\n\n function cleanup() {\n onDragEnd();\n }\n\n return {\n onDragStart,\n onDragEnd,\n onDragMove,\n cleanup,\n };\n };\n}\n"]}