smooth-scroll-into-view-if-needed
Version:
Ponyfill for smooth scrolling elements into view (if needed!)
1 lines • 7.55 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["import scrollIntoView, {\n Options,\n StandardBehaviorOptions,\n CustomBehaviorOptions,\n} from 'scroll-into-view-if-needed'\n\nexport interface CustomEasing {\n (t: number): number\n}\n\ntype OnScrollChangeCallback = (scrollState: {\n target: Element\n elapsed: number\n value: number\n left: number\n top: number\n}) => void\n\nexport type SmoothBehaviorOptions = Options & {\n behavior?: 'smooth'\n duration?: number\n ease?: CustomEasing\n onScrollChange?: OnScrollChangeCallback\n}\n\n// Memoize so we're much more friendly to non-dom envs\nlet memoizedNow: () => number\nconst now = () => {\n if (!memoizedNow) {\n memoizedNow =\n 'performance' in window ? performance.now.bind(performance) : Date.now\n }\n return memoizedNow()\n}\n\ntype SmoothScrollAction = {\n el: Element\n // [start, end] tuples of the distance animated\n left: [number, number]\n top: [number, number]\n}\n\ntype Context = {\n scrollable: Element\n method: (elapsed: number, value: number, x: number, y: number) => void\n startTime: number\n startX: number\n startY: number\n x: number\n y: number\n duration: number\n ease: CustomEasing\n cb: Function\n}\nfunction step(context: Context) {\n const time = now()\n const elapsed = Math.min((time - context.startTime) / context.duration, 1)\n // apply easing to elapsed time\n const value = context.ease(elapsed)\n\n const currentX = context.startX + (context.x - context.startX) * value\n const currentY = context.startY + (context.y - context.startY) * value\n\n context.method(currentX, currentY, elapsed, value)\n\n // scroll more if we have not reached our destination\n if (currentX !== context.x || currentY !== context.y) {\n requestAnimationFrame(() => step(context))\n } else {\n // If nothing left to scroll lets fire the callback\n context.cb()\n }\n}\n\nfunction smoothScroll(\n el: Element,\n x: number,\n y: number,\n duration = 600,\n ease: CustomEasing = (t) => 1 + --t * t * t * t * t,\n cb: Function,\n onScrollChange?: OnScrollChangeCallback\n) {\n // define scroll context\n const scrollable = el\n const startX = el.scrollLeft\n const startY = el.scrollTop\n const method = (x: number, y: number, elapsed: number, value: number) => {\n // @TODO use Element.scroll if it exists, as it is potentially better performing\n // use ceil to include the the fractional part of the number for the scrolling\n const left = Math.ceil(x)\n const top = Math.ceil(y)\n\n el.scrollLeft = left\n el.scrollTop = top\n\n onScrollChange?.({\n target: el,\n elapsed,\n value,\n left,\n top,\n })\n }\n\n // scroll looping over a frame if needed\n step({\n scrollable: scrollable,\n method: method,\n startTime: now(),\n startX: startX,\n startY: startY,\n x: x,\n y: y,\n duration,\n ease,\n cb,\n })\n}\n\nconst shouldSmoothScroll = <T>(options: any): options is T => {\n return (options && !options.behavior) || options.behavior === 'smooth'\n}\n\nfunction scroll(target: Element, options?: SmoothBehaviorOptions): Promise<any>\nfunction scroll<T>(target: Element, options: CustomBehaviorOptions<T>): T\nfunction scroll(target: Element, options: StandardBehaviorOptions): void\nfunction scroll<T>(target: Element, options?: any) {\n const overrides = options || {}\n if (shouldSmoothScroll<SmoothBehaviorOptions>(overrides)) {\n return scrollIntoView<Promise<SmoothScrollAction[]>>(target, {\n block: overrides.block,\n inline: overrides.inline,\n scrollMode: overrides.scrollMode,\n boundary: overrides.boundary,\n skipOverflowHiddenElements: overrides.skipOverflowHiddenElements,\n behavior: (actions) =>\n Promise.all(\n actions.reduce(\n (results: Promise<SmoothScrollAction>[], { el, left, top }) => {\n const startLeft = el.scrollLeft\n const startTop = el.scrollTop\n if (startLeft === left && startTop === top) {\n return results\n }\n\n return [\n ...results,\n new Promise((resolve) => {\n return smoothScroll(\n el,\n left,\n top,\n overrides.duration,\n overrides.ease,\n () =>\n resolve({\n el,\n left: [startLeft, left],\n top: [startTop, top],\n }),\n overrides.onScrollChange\n )\n }),\n ]\n },\n []\n )\n ),\n })\n }\n\n return Promise.resolve(scrollIntoView<T>(target, options))\n}\n\n// re-assign here makes the flowtype generation work\nconst smoothScrollIntoView = scroll\n\nexport default smoothScrollIntoView\n"],"names":["_interopDefaultCompat","e","default","scrollIntoView__default","require","memoizedNow","now","window","performance","bind","Date","step","context","time","elapsed","Math","min","startTime","duration","value","ease","currentX","startX","x","currentY","startY","y","method","requestAnimationFrame","cb","smoothScroll","el","arguments","length","undefined","t","onScrollChange","scrollable","scrollLeft","scrollTop","left","ceil","top","target","shouldSmoothScroll","options","behavior","smoothScrollIntoView","overrides","scrollIntoView","block","inline","scrollMode","boundary","skipOverflowHiddenElements","actions","Promise","all","reduce","results","_ref","startLeft","startTop","resolve","module","exports"],"mappings":"AA0BA,aAAA,SAAAA,EAAAC,GAAA,OAAAA,GAAA,iBAAAA,GAAA,YAAAA,EAAAA,EAAA,CAAAC,QAAAD,EAAA,CAAA,IAAAE,EAAAH,EAAAI,QAAA,+BAAA,IAAIC,EACJ,MAAMC,EAAMA,KACLD,IACHA,EACE,gBAAiBE,OAASC,YAAYF,IAAIG,KAAKD,aAAeE,KAAKJ,KAEhED,KAsBT,SAASM,EAAKC,GACZ,MAAMC,EAAOP,IACPQ,EAAUC,KAAKC,KAAKH,EAAOD,EAAQK,WAAaL,EAAQM,SAAU,GAElEC,EAAQP,EAAQQ,KAAKN,GAErBO,EAAWT,EAAQU,QAAUV,EAAQW,EAAIX,EAAQU,QAAUH,EAC3DK,EAAWZ,EAAQa,QAAUb,EAAQc,EAAId,EAAQa,QAAUN,EAEjEP,EAAQe,OAAON,EAAUG,EAAUV,EAASK,GAGxCE,IAAaT,EAAQW,GAAKC,IAAaZ,EAAQc,EAC3BE,uBAAA,IAAMjB,EAAKC,KAGjCA,EAAQiB,IAEZ,CAEA,SAASC,EACPC,EACAR,EACAG,GAKA,IAJAR,EAAAc,UAAAC,OAAA,QAAAC,IAAAF,UAAA,GAAAA,UAAA,GAAW,IACXZ,EAAqBY,UAAAC,eAAAC,IAAAF,UAAA,GAAAA,UAAA,GAACG,GAAM,IAAMA,EAAIA,EAAIA,EAAIA,EAAIA,EAClDN,yCACAO,EACAJ,UAAAC,OAAAD,EAAAA,kBAAAE,EAEA,MAAMG,EAAaN,EACbT,EAASS,EAAGO,WACZb,EAASM,EAAGQ,UAoBb5B,EAAA,CACH0B,aACAV,OArBaA,CAACJ,EAAWG,EAAWZ,EAAiBK,KAG/C,MAAAqB,EAAOzB,KAAK0B,KAAKlB,GACjBmB,EAAM3B,KAAK0B,KAAKf,GAEtBK,EAAGO,WAAaE,EAChBT,EAAGQ,UAAYG,EAEE,MAAAN,GAAAA,EAAA,CACfO,OAAQZ,EACRjB,UACAK,QACAqB,OACAE,OACF,EAOAzB,UAAWX,IACXgB,SACAG,SACAF,IACAG,IACAR,WACAE,OACAS,MAEJ,CAEA,MAAMe,EAAyBC,GACrBA,IAAYA,EAAQC,UAAkC,WAArBD,EAAQC,SAuDnD,MAAMC,EAjDN,SAAmBJ,EAAiBE,GAC5B,MAAAG,EAAYH,GAAW,GACzB,OAAAD,EAA0CI,GACrCC,EAAAA,QAA8CN,EAAQ,CAC3DO,MAAOF,EAAUE,MACjBC,OAAQH,EAAUG,OAClBC,WAAYJ,EAAUI,WACtBC,SAAUL,EAAUK,SACpBC,2BAA4BN,EAAUM,2BACtCR,SAAWS,GACTC,QAAQC,IACNF,EAAQG,QACN,CAACC,EAAwCC,KAAsB,IAAtB7B,GAAEA,EAAIS,KAAAA,EAAAE,IAAMA,GAAUkB,EAC7D,MAAMC,EAAY9B,EAAGO,WACfwB,EAAW/B,EAAGQ,UAChB,OAAAsB,IAAcrB,GAAQsB,IAAapB,EAC9BiB,EAGF,IACFA,EACH,IAAIH,SAASO,GACJjC,EACLC,EACAS,EACAE,EACAM,EAAU9B,SACV8B,EAAU5B,MACV,IACE2C,EAAQ,CACNhC,KACAS,KAAM,CAACqB,EAAWrB,GAClBE,IAAK,CAACoB,EAAUpB,MAEpBM,EAAUZ,kBAGhB,GAEF,OAMHoB,QAAQO,QAAQd,EAAAA,QAAkBN,EAAQE,GACnD,EAG6BmB,OAAAC,QAAAlB"}