{"version":3,"file":"useScrollContext.mjs","sources":["../../../../../src/lib/layouts/context-aware/hooks/useScrollContext.ts"],"sourcesContent":["/**\n * @fileoverview useScrollContext Hook\n *\n * Provides access to scroll container state and scroll control utilities.\n *\n * @module layouts/context-aware/hooks/useScrollContext\n * @author Agent 4 - PhD Context Systems Expert\n * @version 1.0.0\n */\n\nimport { useRef, useEffect, useState, useCallback, useMemo } from 'react';\n\nimport type { ScrollContainer, ScrollDirection, UseScrollContextReturn } from '../types';\nimport { useDOMContextValue } from '../DOMContextProvider';\nimport {\n  type ScrollTracker,\n  ScrollContainerRegistry,\n  type ScrollCallback,\n} from '../scroll-tracker';\nimport { useScrollContainerContext } from '../ScrollAwareContainer';\n\n// ============================================================================\n// useScrollContext Hook\n// ============================================================================\n\n/**\n * Hook to access scroll container context and utilities.\n *\n * @remarks\n * This hook provides information about the nearest scroll container\n * and utilities for programmatic scrolling.\n *\n * @returns Scroll container state and control functions\n *\n * @example\n * ```tsx\n * function ScrollableContent() {\n *   const {\n *     scrollContainer,\n *     isInScrollContainer,\n *     scrollTo,\n *     scrollBy,\n *     scrollDirection,\n *     scrollProgress,\n *   } = useScrollContext();\n *\n *   return (\n *     <div>\n *       {isInScrollContainer && (\n *         <>\n *           <p>Scroll progress: {(scrollProgress.y * 100).toFixed(0)}%</p>\n *           <button onClick={() => scrollTo({ y: 0, behavior: 'smooth' })}>\n *             Back to top\n *           </button>\n *         </>\n *       )}\n *     </div>\n *   );\n * }\n * ```\n */\nexport function useScrollContext(): UseScrollContextReturn {\n  // Try to get context from ScrollAwareContainer first\n  const containerContext = useScrollContainerContext();\n\n  // Fall back to DOM context\n  const domContext = useDOMContextValue();\n  const scrollContainer = containerContext ?? domContext.scrollContainer;\n\n  // Create scroll control functions\n  const scrollTo = useCallback(\n    (options: { x?: number; y?: number; behavior?: 'auto' | 'smooth' }) => {\n      if (scrollContainer?.element) {\n        scrollContainer.element.scrollTo({\n          left: options.x,\n          top: options.y,\n          behavior: options.behavior,\n        });\n      }\n    },\n    [scrollContainer]\n  );\n\n  const scrollBy = useCallback(\n    (options: { x?: number; y?: number; behavior?: 'auto' | 'smooth' }) => {\n      if (scrollContainer?.element) {\n        scrollContainer.element.scrollBy({\n          left: options.x,\n          top: options.y,\n          behavior: options.behavior,\n        });\n      }\n    },\n    [scrollContainer]\n  );\n\n  return {\n    scrollContainer,\n    isInScrollContainer: scrollContainer !== null,\n    scrollTo,\n    scrollBy,\n    scrollDirection: scrollContainer?.scrollDirection ?? 'none',\n    scrollProgress: scrollContainer?.scrollProgress ?? { x: 0, y: 0 },\n  };\n}\n\n// ============================================================================\n// Specialized Scroll Hooks\n// ============================================================================\n\n/**\n * Hook to find and track a specific scroll container.\n *\n * @param containerRef - Ref to the scroll container element\n * @returns Scroll container state\n *\n * @example\n * ```tsx\n * function CustomScrollContainer() {\n *   const containerRef = useRef<HTMLDivElement>(null);\n *   const scrollState = useScrollContainer(containerRef);\n *\n *   return (\n *     <div ref={containerRef} style={{ overflow: 'auto' }}>\n *       <p>Position: {scrollState?.scrollPosition.y}px</p>\n *       {children}\n *     </div>\n *   );\n * }\n * ```\n */\nexport function useScrollContainer(containerRef: {\n  readonly current: HTMLElement | null;\n}): ScrollContainer | null {\n  const [scrollState, setScrollState] = useState<ScrollContainer | null>(null);\n  const trackerRef = useRef<ScrollTracker | null>(null);\n\n  useEffect(() => {\n    if (containerRef.current === null) {\n      return;\n    }\n\n    const registry = ScrollContainerRegistry.getInstance();\n    const tracker = registry.getTracker(containerRef.current);\n    trackerRef.current = tracker;\n\n    const handleScroll: ScrollCallback = (state) => {\n      setScrollState(state);\n    };\n\n    // Set initial state\n    setScrollState(tracker.getState());\n\n    // Subscribe to updates\n    const unsubscribe = tracker.onScroll(handleScroll);\n\n    return () => {\n      unsubscribe();\n    };\n  }, [containerRef]);\n\n  return scrollState;\n}\n\n/**\n * Hook to get scroll direction.\n *\n * @returns Current scroll direction\n *\n * @example\n * ```tsx\n * function DirectionalHeader() {\n *   const direction = useScrollDirection();\n *\n *   return (\n *     <header\n *       className={direction === 'down' ? 'hidden' : 'visible'}\n *     >\n *       Header content\n *     </header>\n *   );\n * }\n * ```\n */\nexport function useScrollDirection(): ScrollDirection {\n  const { scrollDirection } = useScrollContext();\n  return scrollDirection;\n}\n\n/**\n * Hook to get scroll progress (0-1).\n *\n * @returns Scroll progress for x and y axes\n *\n * @example\n * ```tsx\n * function ProgressIndicator() {\n *   const progress = useScrollProgress();\n *\n *   return (\n *     <div\n *       className=\"progress-bar\"\n *       style={{ width: `${progress.y * 100}%` }}\n *     />\n *   );\n * }\n * ```\n */\nexport function useScrollProgress(): { x: number; y: number } {\n  const { scrollProgress } = useScrollContext();\n  return scrollProgress;\n}\n\n/**\n * Hook to detect if scrolling is currently happening.\n *\n * @returns Whether currently scrolling\n *\n * @example\n * ```tsx\n * function ScrollingIndicator() {\n *   const isScrolling = useIsScrolling();\n *\n *   return (\n *     <div className={isScrolling ? 'scrolling' : ''}>\n *       Content\n *     </div>\n *   );\n * }\n * ```\n */\nexport function useIsScrolling(): boolean {\n  const { scrollContainer } = useScrollContext();\n  return scrollContainer?.isScrolling ?? false;\n}\n\n/**\n * Hook to detect if scroll has reached edges.\n *\n * @returns Edge states\n *\n * @example\n * ```tsx\n * function InfiniteScroll() {\n *   const { atBottom } = useScrollEdges();\n *\n *   useEffect(() => {\n *     if (atBottom) {\n *       loadMoreItems();\n *     }\n *   }, [atBottom]);\n *\n *   return <List items={items} />;\n * }\n * ```\n */\nexport function useScrollEdges(): {\n  atTop: boolean;\n  atBottom: boolean;\n  atLeft: boolean;\n  atRight: boolean;\n} {\n  const { scrollContainer } = useScrollContext();\n\n  return useMemo(\n    () => ({\n      atTop: scrollContainer?.atEdge.top ?? true,\n      atBottom: scrollContainer?.atEdge.bottom ?? true,\n      atLeft: scrollContainer?.atEdge.left ?? true,\n      atRight: scrollContainer?.atEdge.right ?? true,\n    }),\n    [scrollContainer?.atEdge]\n  );\n}\n\n/**\n * Hook to get scroll position.\n *\n * @returns Scroll x and y positions\n *\n * @example\n * ```tsx\n * function ScrollDisplay() {\n *   const { x, y } = useScrollPosition();\n *\n *   return <span>Scroll: {x}, {y}</span>;\n * }\n * ```\n */\nexport function useScrollPosition(): { x: number; y: number } {\n  const { scrollContainer } = useScrollContext();\n\n  return useMemo(\n    () => ({\n      x: scrollContainer?.scrollPosition.x ?? 0,\n      y: scrollContainer?.scrollPosition.y ?? 0,\n    }),\n    [scrollContainer?.scrollPosition]\n  );\n}\n\n/**\n * Hook to get scroll velocity (for momentum detection).\n *\n * @returns Velocity in px/s for x and y axes\n *\n * @example\n * ```tsx\n * function MomentumIndicator() {\n *   const velocity = useScrollVelocity();\n *   const isFastScroll = Math.abs(velocity.y) > 1000;\n *\n *   return (\n *     <div className={isFastScroll ? 'fast-scroll' : ''}>\n *       Content\n *     </div>\n *   );\n * }\n * ```\n */\nexport function useScrollVelocity(): { x: number; y: number } {\n  const { scrollContainer } = useScrollContext();\n\n  return useMemo(\n    () => ({\n      x: scrollContainer?.scrollVelocity.x ?? 0,\n      y: scrollContainer?.scrollVelocity.y ?? 0,\n    }),\n    [scrollContainer?.scrollVelocity]\n  );\n}\n\n// ============================================================================\n// Scroll Actions\n// ============================================================================\n\n/**\n * Hook to get scroll-to-top functionality.\n *\n * @returns Scroll to top function and whether at top\n *\n * @example\n * ```tsx\n * function BackToTop() {\n *   const { scrollToTop, isAtTop } = useScrollToTop();\n *\n *   if (isAtTop) return null;\n *\n *   return <button onClick={scrollToTop}>Back to top</button>;\n * }\n * ```\n */\nexport function useScrollToTop(): {\n  scrollToTop: (behavior?: 'auto' | 'smooth') => void;\n  isAtTop: boolean;\n} {\n  const { scrollTo, scrollContainer } = useScrollContext();\n\n  const scrollToTop = useCallback(\n    (behavior: 'auto' | 'smooth' = 'smooth') => {\n      scrollTo({ y: 0, behavior });\n    },\n    [scrollTo]\n  );\n\n  const isAtTop = scrollContainer?.atEdge.top ?? true;\n\n  return { scrollToTop, isAtTop };\n}\n\n/**\n * Hook to get scroll-to-bottom functionality.\n *\n * @returns Scroll to bottom function and whether at bottom\n *\n * @example\n * ```tsx\n * function ChatContainer() {\n *   const { scrollToBottom, isAtBottom } = useScrollToBottom();\n *\n *   // Auto-scroll on new messages if already at bottom\n *   useEffect(() => {\n *     if (isAtBottom) {\n *       scrollToBottom();\n *     }\n *   }, [messages]);\n *\n *   return <MessageList messages={messages} />;\n * }\n * ```\n */\nexport function useScrollToBottom(): {\n  scrollToBottom: (behavior?: 'auto' | 'smooth') => void;\n  isAtBottom: boolean;\n} {\n  const { scrollTo, scrollContainer } = useScrollContext();\n\n  const scrollToBottom = useCallback(\n    (behavior: 'auto' | 'smooth' = 'smooth') => {\n      if (scrollContainer) {\n        scrollTo({\n          y: scrollContainer.scrollDimensions.height,\n          behavior,\n        });\n      }\n    },\n    [scrollTo, scrollContainer]\n  );\n\n  const isAtBottom = scrollContainer?.atEdge.bottom ?? true;\n\n  return { scrollToBottom, isAtBottom };\n}\n\n/**\n * Hook to scroll a specific element into view within the container.\n *\n * @returns Function to scroll element into view\n *\n * @example\n * ```tsx\n * function ListWithFocus() {\n *   const scrollIntoView = useScrollIntoView();\n *   const [activeId, setActiveId] = useState(null);\n *\n *   const handleSelect = (id) => {\n *     setActiveId(id);\n *     const element = document.getElementById(id);\n *     if (element) {\n *       scrollIntoView(element);\n *     }\n *   };\n *\n *   return <List onSelect={handleSelect} />;\n * }\n * ```\n */\nexport function useScrollIntoView(): (element: Element, options?: ScrollIntoViewOptions) => void {\n  return useCallback((element: Element, options?: ScrollIntoViewOptions) => {\n    element.scrollIntoView(options ?? { behavior: 'smooth', block: 'center' });\n  }, []);\n}\n"],"names":["useScrollContext","containerContext","useScrollContainerContext","domContext","useDOMContextValue","scrollContainer","scrollTo","useCallback","options","scrollBy","useScrollContainer","containerRef","scrollState","setScrollState","useState","trackerRef","useRef","useEffect","tracker","ScrollContainerRegistry","handleScroll","state","unsubscribe","useScrollDirection","scrollDirection","useScrollProgress","scrollProgress","useIsScrolling","useScrollEdges","useMemo","useScrollPosition","useScrollVelocity","useScrollToTop","scrollToTop","behavior","isAtTop","useScrollToBottom","scrollToBottom","isAtBottom","useScrollIntoView","element"],"mappings":"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"}