{"version":3,"sources":["../../src/use-scroll/index.ts"],"sourcesContent":["import { useRef } from 'react'\nimport { useDebouncedFn } from '../use-debounced-fn'\nimport { useEventListener } from '../use-event-listener'\nimport { useLatest } from '../use-latest'\nimport { usePausable } from '../use-pausable'\nimport { useRafState } from '../use-raf-state'\nimport { useStableFn } from '../use-stable-fn'\nimport { useTargetElement } from '../use-target-element'\nimport { useThrottledFn } from '../use-throttled-fn'\n\nimport type { Pausable } from '../use-pausable'\nimport type { ElementTarget } from '../use-target-element'\n\nexport type Directions = {\n  left: boolean\n  right: boolean\n  top: boolean\n  bottom: boolean\n}\n\nexport type ArrivedState = Directions\nexport type Insets = { [K in keyof Directions]?: number }\nexport type UseScrollOptionsOffset = Insets\n\nexport interface UseScrollOptions {\n  /**\n   * The throttle time (ms) to update the scroll position\n   */\n  throttle?: number\n  /**\n   * The idle time (ms) to determine the scroll is stopped\n   */\n  idle?: number\n  /**\n   * The offset to determine the scroll has arrived at the edge\n   */\n  offset?: UseScrollOptionsOffset\n  /**\n   * The scroll event handler\n   */\n  onScroll?: (event: Event) => void\n  /**\n   * The scroll stop event handler\n   */\n  onStop?: (event: Event) => void\n  /**\n   * The event listener options\n   */\n  eventListenerOptions?: boolean | AddEventListenerOptions\n  /**\n   * The scroll behavior\n   */\n  behavior?: ScrollBehavior\n  /**\n   * Whether to trigger the first load immediately\n   */\n  immediate?: boolean\n}\n\nexport interface UseScrollReturns extends Pausable {\n  /**\n   * scroll x position\n   */\n  x: number\n  /**\n   * scroll y position\n   */\n  y: number\n  /**\n   * The scroll position\n   */\n  position: { x: number; y: number }\n  /**\n   * The scroll directions\n   */\n  directions: Directions\n  /**\n   * Whether the scroll is scrolling\n   */\n  isScrolling: boolean\n  /**\n   * The arrived state\n   */\n  arrivedState: ArrivedState\n  /**\n   * Scroll to the specified position\n   */\n  scrollTo: (x: number, y: number) => void\n  /**\n   * Scroll to the end of the specified direction\n   */\n  scrollToEnd: (direction: 'x' | 'y') => void\n  /**\n   * Measure the scroll position\n   */\n  measure(): void\n}\n\nconst INIT_DIRECTIONS = { left: false, right: false, top: false, bottom: false }\nconst ARRIVED_STATE_THRESHOLD_PIXELS = 1\n\n/**\n * A React Hook that track the scroll state of target element.\n */\nexport function useScroll<T extends HTMLElement>(\n  target: ElementTarget<T>,\n  options: UseScrollOptions = {},\n): UseScrollReturns {\n  const {\n    throttle = 0,\n    idle = 200,\n    offset = {},\n    onScroll,\n    onStop,\n    immediate = true,\n    eventListenerOptions = { capture: false, passive: true },\n    behavior = 'auto',\n  } = options\n\n  const isScrollingRef = useRef(false)\n  const el = useTargetElement<T>(target)\n  const pausable = usePausable(immediate)\n\n  const [state, setState] = useRafState({\n    position: { x: 0, y: 0 },\n    directions: { ...INIT_DIRECTIONS },\n    isScrolling: false,\n    arrivedState: { ...INIT_DIRECTIONS, left: true, top: true },\n  })\n\n  const latest = useLatest({ state, offset, onStop, onScroll, behavior })\n\n  const scrollTo = useStableFn((x: number, y: number) => {\n    const { behavior } = latest.current\n    el.current?.scrollTo({ left: x, top: y, behavior })\n  })\n\n  const onScrollEnd = useStableFn((e: Event) => {\n    const { state, onStop } = latest.current\n    if (!state.isScrolling || !pausable.isActive()) return\n\n    isScrollingRef.current = false\n\n    setState((pre) => ({\n      ...pre,\n      isScrolling: false,\n      directions: { ...INIT_DIRECTIONS },\n    }))\n\n    onStop?.(e)\n  })\n\n  const onScrollEndDebounced = useDebouncedFn(onScrollEnd, { wait: throttle + idle })\n\n  function calcAndSetArrivedState() {\n    const { offset, state } = latest.current\n\n    if (!el.current) return\n\n    const { display, flexDirection } = window.getComputedStyle(el.current)\n    const scrollLeft = el.current.scrollLeft\n\n    const left = Math.abs(scrollLeft) <= (offset.left || 0)\n    const right =\n      Math.abs(scrollLeft) + el.current.clientWidth >=\n      el.current.scrollWidth - (offset.right || 0) - ARRIVED_STATE_THRESHOLD_PIXELS\n\n    const scrollTop = el.current.scrollTop\n\n    const top = Math.abs(scrollTop) <= (offset.top || 0)\n    const bottom =\n      Math.abs(scrollTop) + el.current.clientHeight >=\n      el.current.scrollHeight - (offset.bottom || 0) - ARRIVED_STATE_THRESHOLD_PIXELS\n\n    const isFlexRowReverse = display === 'flex' && flexDirection === 'row-reverse'\n    const isFlexColumnReverse = display === 'flex' && flexDirection === 'column-reverse'\n\n    setState({\n      isScrolling: isScrollingRef.current,\n      position: { x: scrollLeft, y: scrollTop },\n      directions: {\n        left: scrollLeft < state.position.x,\n        right: scrollLeft > state.position.x,\n        top: scrollTop < state.position.y,\n        bottom: scrollTop > state.position.y,\n      },\n      arrivedState: {\n        left: isFlexRowReverse ? right : left,\n        right: isFlexRowReverse ? left : right,\n        top: isFlexColumnReverse ? bottom : top,\n        bottom: isFlexColumnReverse ? top : bottom,\n      },\n    })\n  }\n\n  const scrollToEnd = useStableFn((direction: 'x' | 'y') => {\n    if (!el.current) return\n\n    if (direction === 'x') {\n      scrollTo(el.current.scrollWidth, 0)\n    } else {\n      scrollTo(0, el.current.scrollHeight)\n    }\n  })\n\n  function onScrollHandler(event: Event) {\n    const { onScroll } = latest.current\n\n    if (!el.current || !pausable.isActive()) return\n\n    isScrollingRef.current = true\n\n    calcAndSetArrivedState()\n    onScrollEndDebounced(event)\n    onScroll?.(event)\n  }\n\n  const onScrollHandlerThrottled = useThrottledFn(onScrollHandler, { wait: throttle })\n  const measure = useStableFn(() => el.current && calcAndSetArrivedState())\n\n  useEventListener(el, 'scroll', throttle ? onScrollHandlerThrottled : onScrollHandler, eventListenerOptions)\n  useEventListener(el, 'scrollend', onScrollEnd, eventListenerOptions)\n\n  return {\n    ...state.position,\n    ...state,\n    ...pausable,\n    scrollTo,\n    scrollToEnd,\n    measure,\n  }\n}\n"],"names":["useScroll","INIT_DIRECTIONS","left","right","top","bottom","ARRIVED_STATE_THRESHOLD_PIXELS","target","options","throttle","idle","offset","onScroll","onStop","immediate","eventListenerOptions","capture","passive","behavior","isScrollingRef","useRef","el","useTargetElement","pausable","usePausable","useRafState","position","x","y","directions","isScrolling","arrivedState","state","setState","latest","useLatest","scrollTo","useStableFn","current","onScrollEnd","e","isActive","pre","onScrollEndDebounced","useDebouncedFn","wait","calcAndSetArrivedState","window","getComputedStyle","display","flexDirection","scrollLeft","Math","abs","clientWidth","scrollWidth","scrollTop","clientHeight","scrollHeight","isFlexRowReverse","isFlexColumnReverse","scrollToEnd","direction","onScrollHandler","event","onScrollHandlerThrottled","useThrottledFn","measure","useEventListener"],"mappings":"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"}