{"version":3,"file":"index.cjs","sources":["../../src/shared/context/viewport-element-context.ts","../../src/shared/hooks/use-viewport.ts","../../src/shared/hooks/use-viewport-ref.ts","../../src/shared/components/viewport.tsx"],"sourcesContent":["import { createContext, RefObject } from '@framework';\n\n/**\n * Context to share the viewport DOM element reference with child components.\n * This allows child components (like ZoomGestureWrapper) to access the viewport\n * container element without DOM traversal.\n */\nexport const ViewportElementContext = createContext<RefObject<HTMLDivElement> | null>(null);\n","import { useEffect, useState, useContext, RefObject } from '@framework';\nimport { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { GateChangeEvent, ScrollActivity, ViewportPlugin } from '@embedpdf/plugin-viewport';\nimport { ViewportElementContext } from '../context';\n\nexport const useViewportPlugin = () => usePlugin<ViewportPlugin>(ViewportPlugin.id);\nexport const useViewportCapability = () => useCapability<ViewportPlugin>(ViewportPlugin.id);\n\n/**\n * Hook to get the viewport DOM element ref from context.\n * Must be used within a Viewport component.\n */\nexport const useViewportElement = (): RefObject<HTMLDivElement> | null => {\n  return useContext(ViewportElementContext);\n};\n\n/**\n * Hook to get the gated state of the viewport for a specific document.\n * The viewport children are not rendered when gated.\n * @param documentId Document ID.\n */\nexport const useIsViewportGated = (documentId: string) => {\n  const { provides } = useViewportCapability();\n  const [isGated, setIsGated] = useState(provides?.isGated(documentId) ?? false);\n\n  useEffect(() => {\n    if (!provides) return;\n\n    // Set initial state\n    setIsGated(provides.isGated(documentId));\n\n    // Subscribe to gate state changes\n    return provides.onGateChange((event: GateChangeEvent) => {\n      if (event.documentId === documentId) {\n        setIsGated(event.isGated);\n      }\n    });\n  }, [provides, documentId]);\n\n  return isGated;\n};\n\n/**\n * Hook to get scroll activity for a specific document\n * @param documentId Document ID.\n */\nexport const useViewportScrollActivity = (documentId: string) => {\n  const { provides } = useViewportCapability();\n  const [scrollActivity, setScrollActivity] = useState<ScrollActivity>({\n    isScrolling: false,\n    isSmoothScrolling: false,\n  });\n\n  useEffect(() => {\n    if (!provides) return;\n\n    // Subscribe to scroll activity events\n    return provides.onScrollActivity((event) => {\n      // Filter by documentId if provided\n      if (event.documentId === documentId) {\n        setScrollActivity(event.activity);\n      }\n    });\n  }, [provides, documentId]);\n\n  return scrollActivity;\n};\n","import { Rect } from '@embedpdf/models';\nimport { useLayoutEffect, useRef } from '@framework';\nimport { useViewportPlugin } from './use-viewport';\n\nexport function useViewportRef(documentId: string) {\n  const { plugin: viewportPlugin } = useViewportPlugin();\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  useLayoutEffect(() => {\n    if (!viewportPlugin) return;\n\n    const container = containerRef.current;\n    if (!container) return;\n\n    // Register this viewport for the document\n    try {\n      viewportPlugin.registerViewport(documentId);\n    } catch (error) {\n      console.error(`Failed to register viewport for document ${documentId}:`, error);\n      return;\n    }\n\n    // On scroll\n    const onScroll = () => {\n      viewportPlugin.setViewportScrollMetrics(documentId, {\n        scrollTop: container.scrollTop,\n        scrollLeft: container.scrollLeft,\n      });\n    };\n    container.addEventListener('scroll', onScroll);\n\n    // On resize\n    const resizeObserver = new ResizeObserver(() => {\n      viewportPlugin.setViewportResizeMetrics(documentId, {\n        width: container.offsetWidth,\n        height: container.offsetHeight,\n        clientWidth: container.clientWidth,\n        clientHeight: container.clientHeight,\n        scrollTop: container.scrollTop,\n        scrollLeft: container.scrollLeft,\n        scrollWidth: container.scrollWidth,\n        scrollHeight: container.scrollHeight,\n        clientLeft: container.clientLeft,\n        clientTop: container.clientTop,\n      });\n    });\n    resizeObserver.observe(container);\n\n    // Subscribe to scroll requests for this document\n    const unsubscribeScrollRequest = viewportPlugin.onScrollRequest(\n      documentId,\n      ({ x, y, behavior = 'auto' }) => {\n        requestAnimationFrame(() => {\n          container.scrollTo({ left: x, top: y, behavior });\n        });\n      },\n    );\n\n    // Cleanup\n    return () => {\n      viewportPlugin.unregisterViewport(documentId);\n      resizeObserver.disconnect();\n      container.removeEventListener('scroll', onScroll);\n      unsubscribeScrollRequest();\n    };\n  }, [viewportPlugin, documentId]);\n\n  return containerRef;\n}\n","import { ReactNode, useEffect, useState, HTMLAttributes } from '@framework';\nimport { useIsViewportGated, useViewportCapability } from '../hooks';\nimport { useViewportRef } from '../hooks/use-viewport-ref';\nimport { ViewportElementContext } from '../context';\n\ntype ViewportProps = HTMLAttributes<HTMLDivElement> & {\n  children: ReactNode;\n  /**\n   * The ID of the document that this viewport displays\n   */\n  documentId: string;\n};\n\nexport function Viewport({ children, documentId, ...props }: ViewportProps) {\n  const [viewportGap, setViewportGap] = useState(0);\n  const viewportRef = useViewportRef(documentId);\n  const { provides: viewportProvides } = useViewportCapability();\n  const isGated = useIsViewportGated(documentId);\n\n  useEffect(() => {\n    if (viewportProvides) {\n      setViewportGap(viewportProvides.getViewportGap());\n    }\n  }, [viewportProvides]);\n\n  const { style, ...restProps } = props;\n\n  return (\n    <ViewportElementContext.Provider value={viewportRef}>\n      <div\n        {...restProps}\n        ref={viewportRef}\n        style={{\n          width: '100%',\n          height: '100%',\n          overflow: 'auto',\n          ...(typeof style === 'object' ? style : {}),\n          padding: `${viewportGap}px`,\n        }}\n      >\n        {!isGated && children}\n      </div>\n    </ViewportElementContext.Provider>\n  );\n}\n"],"names":["ViewportElementContext","createContext","useViewportPlugin","usePlugin","ViewportPlugin","id","useViewportCapability","useCapability","useIsViewportGated","documentId","provides","isGated","setIsGated","useState","useEffect","onGateChange","event","useViewportRef","plugin","viewportPlugin","containerRef","useRef","useLayoutEffect","container","current","registerViewport","error","console","onScroll","setViewportScrollMetrics","scrollTop","scrollLeft","addEventListener","resizeObserver","ResizeObserver","setViewportResizeMetrics","width","offsetWidth","height","offsetHeight","clientWidth","clientHeight","scrollWidth","scrollHeight","clientLeft","clientTop","observe","unsubscribeScrollRequest","onScrollRequest","x","y","behavior","requestAnimationFrame","scrollTo","left","top","unregisterViewport","disconnect","removeEventListener","children","props","viewportGap","setViewportGap","viewportRef","viewportProvides","getViewportGap","style","restProps","jsx","Provider","value","ref","overflow","padding","useContext","scrollActivity","setScrollActivity","isScrolling","isSmoothScrolling","onScrollActivity","activity"],"mappings":"8OAOaA,EAAyBC,EAAAA,cAAgD,MCFzEC,EAAoB,IAAMC,YAA0BC,EAAAA,eAAeC,IACnEC,EAAwB,IAAMC,gBAA8BH,EAAAA,eAAeC,IAe3EG,EAAsBC,IACjC,MAAMC,SAAEA,GAAaJ,KACdK,EAASC,GAAcC,EAAAA,UAAS,MAAAH,OAAA,EAAAA,EAAUC,QAAQF,MAAe,GAgBxE,OAdAK,EAAAA,UAAU,KACR,GAAKJ,EAML,OAHAE,EAAWF,EAASC,QAAQF,IAGrBC,EAASK,aAAcC,IACxBA,EAAMP,aAAeA,GACvBG,EAAWI,EAAML,YAGpB,CAACD,EAAUD,IAEPE,GCnCF,SAASM,EAAeR,GAC7B,MAAQS,OAAQC,GAAmBjB,IAC7BkB,EAAeC,EAAAA,OAAuB,MA6D5C,OA3DAC,EAAAA,gBAAgB,KACd,IAAKH,EAAgB,OAErB,MAAMI,EAAYH,EAAaI,QAC/B,IAAKD,EAAW,OAGhB,IACEJ,EAAeM,iBAAiBhB,EAClC,OAASiB,GAEP,YADAC,QAAQD,MAAM,4CAA4CjB,KAAeiB,EAE3E,CAGA,MAAME,EAAW,KACfT,EAAeU,yBAAyBpB,EAAY,CAClDqB,UAAWP,EAAUO,UACrBC,WAAYR,EAAUQ,cAG1BR,EAAUS,iBAAiB,SAAUJ,GAGrC,MAAMK,EAAiB,IAAIC,eAAe,KACxCf,EAAegB,yBAAyB1B,EAAY,CAClD2B,MAAOb,EAAUc,YACjBC,OAAQf,EAAUgB,aAClBC,YAAajB,EAAUiB,YACvBC,aAAclB,EAAUkB,aACxBX,UAAWP,EAAUO,UACrBC,WAAYR,EAAUQ,WACtBW,YAAanB,EAAUmB,YACvBC,aAAcpB,EAAUoB,aACxBC,WAAYrB,EAAUqB,WACtBC,UAAWtB,EAAUsB,cAGzBZ,EAAea,QAAQvB,GAGvB,MAAMwB,EAA2B5B,EAAe6B,gBAC9CvC,EACA,EAAGwC,IAAGC,IAAGC,WAAW,WAClBC,sBAAsB,KACpB7B,EAAU8B,SAAS,CAAEC,KAAML,EAAGM,IAAKL,EAAGC,iBAM5C,MAAO,KACLhC,EAAeqC,mBAAmB/C,GAClCwB,EAAewB,aACflC,EAAUmC,oBAAoB,SAAU9B,GACxCmB,MAED,CAAC5B,EAAgBV,IAEbW,CACT,kBCvDO,UAAkBuC,SAAEA,EAAAlD,WAAUA,KAAemD,IAClD,MAAOC,EAAaC,GAAkBjD,EAAAA,SAAS,GACzCkD,EAAc9C,EAAeR,IAC3BC,SAAUsD,GAAqB1D,IACjCK,EAAUH,EAAmBC,GAEnCK,EAAAA,UAAU,KACJkD,GACFF,EAAeE,EAAiBC,mBAEjC,CAACD,IAEJ,MAAME,MAAEA,KAAUC,GAAcP,EAEhC,OACEQ,EAAAA,IAACpE,EAAuBqE,SAAvB,CAAgCC,MAAOP,EACtCJ,SAAAS,EAAAA,IAAC,MAAA,IACKD,EACJI,IAAKR,EACLG,MAAO,CACL9B,MAAO,OACPE,OAAQ,OACRkC,SAAU,UACW,iBAAVN,EAAqBA,EAAQ,CAAA,EACxCO,QAAS,GAAGZ,OAGbF,UAAChD,GAAWgD,KAIrB,2HFhCkC,IACzBe,EAAAA,WAAW1E,0FAiCsBS,IACxC,MAAMC,SAAEA,GAAaJ,KACdqE,EAAgBC,GAAqB/D,WAAyB,CACnEgE,aAAa,EACbC,mBAAmB,IAerB,OAZAhE,EAAAA,UAAU,KACR,GAAKJ,EAGL,OAAOA,EAASqE,iBAAkB/D,IAE5BA,EAAMP,aAAeA,GACvBmE,EAAkB5D,EAAMgE,aAG3B,CAACtE,EAAUD,IAEPkE"}