MCPcopy Create free account
hub / github.com/artsy/force / scrollToAwaitable

Function scrollToAwaitable

src/Utils/scrollToAwaitable.ts:23–100  ·  view source on GitHub ↗
({
  target,
  container = window,
  offset = 0,
  behavior = "smooth",
  timeout = 15_000,
  onComplete,
}: ScrollToWithCallbackOptions)

Source from the content-addressed store, hash-verified

21 * @returns a Promise and a disposer you can call to cancel early.
22 */
23export const scrollToAwaitable = ({
24 target,
25 container = window,
26 offset = 0,
27 behavior = "smooth",
28 timeout = 15_000,
29 onComplete,
30}: ScrollToWithCallbackOptions): {
31 promise: Promise<void>
32 cancel: () => void
33} => {
34 const isWindow = container === window
35 const el = isWindow
36 ? document.scrollingElement || document.documentElement
37 : (container as HTMLElement)
38
39 // Calculate destination relative to the scrolling context
40 const baseDestination =
41 typeof target === "number"
42 ? target
43 : (() => {
44 const rect = target.getBoundingClientRect()
45
46 if (isWindow) {
47 // When scrolling the viewport, translate rect.top (viewport-relative) into document space
48 return rect.top + window.scrollY
49 }
50
51 // For an arbitrary scrolling container, translate rect.top into the container's scroll space
52 const containerRect = el.getBoundingClientRect()
53 return rect.top - containerRect.top + el.scrollTop
54 })()
55
56 const destination = baseDestination + offset
57
58 ;(isWindow ? window : el).scrollTo({ top: destination, behavior })
59
60 let frameId = 0
61 let resolved = false
62 const within = () =>
63 Math.abs((isWindow ? window.scrollY : el.scrollTop) - destination) <= 1
64
65 const finish = () => {
66 if (resolved) return
67 resolved = true
68 cancelAnimationFrame(frameId)
69 clearTimeout(timerId)
70 onComplete?.()
71 resolvePromise()
72 }
73
74 const step = () => {
75 if (within()) finish()
76 else frameId = requestAnimationFrame(step)
77 }
78
79 frameId = requestAnimationFrame(step)
80

Callers 2

useJumpFunction · 0.90
useArticleTocHistoryFunction · 0.90

Calls

no outgoing calls

Tested by

no test coverage detected