{"version":3,"file":"overscroll.mjs","names":[],"sources":["../../../../package/common/overscroll/overscroll.tsx"],"sourcesContent":["import { useRef, useEffect, useCallback } from 'react';\nimport cx from 'classnames';\nimport type { UIEvent } from 'react';\nimport useWindowSize from '../../hooks/useWindowSize';\nimport styles from './overscroll.module.pcss';\nimport type { OverscrollProps } from './overscroll.types';\n\nexport default function Overscroll({\n  children = null,\n  overscrollContent = null,\n  overscrollContentDesktop = null,\n  centerHeader = true,\n  min = 10,\n  max = 80,\n  start = 30,\n  unit = '%',\n  mobileOnly = true,\n  onScrollChange = () => {},\n  scrollDisabled = false,\n}: OverscrollProps) {\n  const { isMobileSize, height } = useWindowSize();\n\n  const overscrollRef = useRef<HTMLDivElement>(null);\n  const overscrollHeaderRef = useRef<HTMLDivElement>(null);\n  const overscrollHeaderContainerRef = useRef<HTMLDivElement>(null);\n  const isScrollingRef = useRef(false);\n  const scrollTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n  const onScrollChangeRef = useRef(onScrollChange);\n  useEffect(() => {\n    onScrollChangeRef.current = onScrollChange;\n  });\n\n  const updateHeaderHeight = useCallback(\n    (scrollTop: number) => {\n      let h: number;\n      if (unit === '%') {\n        if (!overscrollHeaderContainerRef.current) return;\n        const containerH = overscrollHeaderContainerRef.current.clientHeight;\n        h = Math.max((containerH * min) / 100, containerH - scrollTop);\n      } else {\n        h = Math.max(min, max - scrollTop);\n      }\n      if (overscrollHeaderRef.current) {\n        overscrollHeaderRef.current.style.height = `${h}px`;\n      }\n    },\n    [min, max, unit],\n  );\n\n  const scrollToInitialPosition = useCallback(() => {\n    let toScroll: number;\n    if (unit === '%') {\n      if (!overscrollHeaderContainerRef.current) return;\n      const hundredPerc = (overscrollHeaderContainerRef.current.clientHeight / max) * 100;\n      toScroll = overscrollHeaderContainerRef.current.clientHeight - hundredPerc * (start / 100);\n    } else {\n      toScroll = max - start;\n    }\n    if (overscrollRef.current) {\n      overscrollRef.current.scrollTop = toScroll;\n      updateHeaderHeight(toScroll);\n    }\n  }, [max, start, unit, updateHeaderHeight]);\n\n  // Initial scroll position on mount (and if scroll-related props change)\n  useEffect(() => {\n    const id = setTimeout(scrollToInitialPosition, 100);\n    return () => clearTimeout(id);\n  }, [scrollToInitialPosition]);\n\n  // Toggle overflow when scrollDisabled changes\n  useEffect(() => {\n    if (overscrollRef.current) {\n      overscrollRef.current.style.overflow = scrollDisabled ? 'hidden' : 'auto';\n    }\n  }, [scrollDisabled]);\n\n  // Scroll to initial position when entering mobile view\n  const prevIsMobileRef = useRef(isMobileSize);\n  useEffect(() => {\n    if (isMobileSize && !prevIsMobileRef.current) scrollToInitialPosition();\n    prevIsMobileRef.current = isMobileSize;\n  }, [isMobileSize, scrollToInitialPosition]);\n\n  // Scroll to initial position when mobileOnly is turned off (full overscroll DOM just mounted)\n  const prevMobileOnlyRef = useRef(mobileOnly);\n  useEffect(() => {\n    if (!mobileOnly && prevMobileOnlyRef.current) scrollToInitialPosition();\n    prevMobileOnlyRef.current = mobileOnly;\n  }, [mobileOnly, scrollToInitialPosition]);\n\n  // Update header height on window resize while in mobile view\n  const prevHeightRef = useRef(height);\n  useEffect(() => {\n    if (isMobileSize && height !== prevHeightRef.current && overscrollRef.current) {\n      updateHeaderHeight(overscrollRef.current.scrollTop);\n    }\n    prevHeightRef.current = height;\n  }, [height, isMobileSize, updateHeaderHeight]);\n\n  function handleScroll(e: UIEvent<HTMLDivElement>) {\n    updateHeaderHeight(e.currentTarget.scrollTop);\n    if (!isScrollingRef.current) {\n      isScrollingRef.current = true;\n      onScrollChangeRef.current(true);\n    }\n    if (scrollTimeoutRef.current) clearTimeout(scrollTimeoutRef.current);\n    scrollTimeoutRef.current = setTimeout(() => {\n      scrollTimeoutRef.current = null;\n      isScrollingRef.current = false;\n      onScrollChangeRef.current(false);\n    }, 500);\n  }\n\n  if (mobileOnly && !isMobileSize) {\n    if (overscrollContentDesktop)\n      return (\n        <div>\n          {overscrollContentDesktop}\n          {children}\n        </div>\n      );\n    return <>{children}</>;\n  }\n\n  const contentMinHeight = unit === '%' ? `${100 - min}%` : `calc(100% - ${min}px)`;\n\n  return (\n    <div className={styles.overscroll} ref={overscrollRef} onScroll={handleScroll}>\n      <div\n        className={styles.overscrollHeaderContainer}\n        style={{ height: `${max}${unit}` }}\n        ref={overscrollHeaderContainerRef}\n      >\n        <div\n          className={cx(styles.overscrollHeader, centerHeader && styles.overscrollHeaderCentered)}\n          ref={overscrollHeaderRef}\n        >\n          {overscrollContent}\n        </div>\n      </div>\n      <div style={{ minHeight: contentMinHeight }}>{children}</div>\n    </div>\n  );\n}\n"],"mappings":"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"}