{"version":3,"file":"index.cjs","sources":["../../src/vue/hooks/use-viewport.ts","../../src/vue/hooks/use-viewport-ref.ts","../../src/vue/components/viewport.vue"],"sourcesContent":["import { ref, watch, toValue, type MaybeRefOrGetter } from 'vue';\nimport { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { GateChangeEvent, ScrollActivity, ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nexport const useViewportPlugin = () => usePlugin<ViewportPlugin>(ViewportPlugin.id);\nexport const useViewportCapability = () => useCapability<ViewportPlugin>(ViewportPlugin.id);\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 (can be ref, computed, getter, or plain value).\n */\nexport const useIsViewportGated = (documentId: MaybeRefOrGetter<string>) => {\n  const { provides } = useViewportCapability();\n  const isGated = ref(false);\n\n  watch(\n    [provides, () => toValue(documentId)],\n    ([providesValue, docId], _, onCleanup) => {\n      if (!providesValue) {\n        isGated.value = false;\n        return;\n      }\n\n      // Set initial state\n      isGated.value = providesValue.isGated(docId);\n\n      const unsubscribe = providesValue.onGateChange((event: GateChangeEvent) => {\n        // Filter by documentId\n        if (event.documentId === docId) {\n          isGated.value = event.isGated;\n        }\n      });\n\n      onCleanup(unsubscribe);\n    },\n    { immediate: true },\n  );\n\n  return isGated;\n};\n\n/**\n * Hook to get scroll activity for a specific document\n * @param documentId Document ID (can be ref, computed, getter, or plain value).\n */\nexport const useViewportScrollActivity = (documentId: MaybeRefOrGetter<string>) => {\n  const { provides } = useViewportCapability();\n  const scrollActivity = ref<ScrollActivity>({\n    isSmoothScrolling: false,\n    isScrolling: false,\n  });\n\n  watch(\n    [provides, () => toValue(documentId)],\n    ([providesValue, docId], _, onCleanup) => {\n      if (!providesValue) {\n        scrollActivity.value = {\n          isSmoothScrolling: false,\n          isScrolling: false,\n        };\n        return;\n      }\n\n      const unsubscribe = providesValue.onScrollActivity((event) => {\n        // Filter by documentId\n        if (event.documentId === docId) {\n          scrollActivity.value = event.activity;\n        }\n      });\n\n      onCleanup(unsubscribe);\n    },\n    { immediate: true },\n  );\n\n  return scrollActivity;\n};\n","import { Rect } from '@embedpdf/models';\nimport { onBeforeUnmount, ref, watch, toValue, type MaybeRefOrGetter } from 'vue';\nimport { useViewportPlugin } from './use-viewport';\n\n/**\n * Hook to get a ref for the viewport container element with automatic setup/teardown\n * @param documentId Document ID (can be ref, computed, getter, or plain value).\n */\nexport function useViewportRef(documentId: MaybeRefOrGetter<string>) {\n  const { plugin: pluginRef } = useViewportPlugin();\n  const containerRef = ref<HTMLDivElement | null>(null);\n\n  let cleanup: (() => void) | null = null;\n\n  // Setup function that runs when both plugin and container are available\n  const setupViewport = (docId: string) => {\n    const viewportPlugin = pluginRef.value;\n    const container = containerRef.value;\n\n    if (!container || !viewportPlugin) return;\n\n    // Register this viewport for the document\n    try {\n      viewportPlugin.registerViewport(docId);\n    } catch (error) {\n      console.error(`Failed to register viewport for document ${docId}:`, error);\n      return;\n    }\n\n    // On scroll\n    const onScroll = () => {\n      viewportPlugin.setViewportScrollMetrics(docId, {\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(docId, {\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      docId,\n      ({ x, y, behavior = 'auto' }) => {\n        requestAnimationFrame(() => {\n          container.scrollTo({ left: x, top: y, behavior });\n        });\n      },\n    );\n\n    // Return cleanup function\n    return () => {\n      viewportPlugin.unregisterViewport(docId);\n      container.removeEventListener('scroll', onScroll);\n      unsubscribeScrollRequest();\n    };\n  };\n\n  // Watch for changes in plugin, container, or documentId\n  watch(\n    [pluginRef, containerRef, () => toValue(documentId)],\n    ([, , docId]) => {\n      // Clean up previous setup\n      if (cleanup) {\n        cleanup();\n        cleanup = null;\n      }\n\n      // Setup new viewport\n      cleanup = setupViewport(docId) || null;\n    },\n    { immediate: true },\n  );\n\n  onBeforeUnmount(() => {\n    if (cleanup) {\n      cleanup();\n      cleanup = null;\n    }\n  });\n\n  return containerRef;\n}\n","<script setup lang=\"ts\">\nimport { ref, watch, useAttrs, provide } from 'vue';\nimport { useIsViewportGated, useViewportCapability, useViewportRef } from '../hooks';\n\n/* -------------------------------------------------- */\n/* props & attrs                                      */\n/* -------------------------------------------------- */\ninterface Props {\n  /**\n   * The ID of the document that this viewport displays\n   */\n  documentId: string;\n}\n\nconst props = defineProps<Props>();\nconst attrs = useAttrs();\n\n/* -------------------------------------------------- */\n/* plugin + reactive viewport gap                     */\n/* -------------------------------------------------- */\nconst { provides: viewportProvides } = useViewportCapability();\nconst viewportGap = ref(0);\n\nwatch(\n  viewportProvides,\n  (vp) => {\n    if (vp) viewportGap.value = vp.getViewportGap();\n  },\n  { immediate: true },\n);\n\n/* -------------------------------------------------- */\n/* Gating logic                                    */\n/* -------------------------------------------------- */\nconst isGated = useIsViewportGated(() => props.documentId);\n\n/* -------------------------------------------------- */\n/* element ref that wires up scroll / resize logic    */\n/* -------------------------------------------------- */\nconst viewportRef = useViewportRef(() => props.documentId);\n\n/* -------------------------------------------------- */\n/* Provide viewport element to child components       */\n/* -------------------------------------------------- */\nprovide('viewport-element', viewportRef);\n</script>\n\n<template>\n  <div\n    ref=\"viewportRef\"\n    v-bind=\"attrs\"\n    :style=\"{ padding: `${viewportGap}px`, width: '100%', height: '100%', overflow: 'auto' }\"\n  >\n    <slot v-if=\"!isGated\" />\n  </div>\n</template>\n"],"names":["useViewportPlugin","usePlugin","ViewportPlugin","id","useViewportCapability","useCapability","useIsViewportGated","documentId","provides","isGated","ref","watch","toValue","providesValue","docId","_","onCleanup","value","onGateChange","event","immediate","useViewportRef","plugin","pluginRef","containerRef","cleanup","viewportPlugin","container","registerViewport","error","console","onScroll","setViewportScrollMetrics","scrollTop","scrollLeft","addEventListener","ResizeObserver","setViewportResizeMetrics","width","offsetWidth","height","offsetHeight","clientWidth","clientHeight","scrollWidth","scrollHeight","clientLeft","clientTop","observe","unsubscribeScrollRequest","onScrollRequest","x","y","behavior","requestAnimationFrame","scrollTo","left","top","unregisterViewport","removeEventListener","setupViewport","onBeforeUnmount","props","__props","attrs","useAttrs","viewportProvides","viewportGap","vp","getViewportGap","viewportRef","provide","_openBlock","_createElementBlock","_mergeProps","_unref","style","overflow","_renderSlot","_ctx","$slots","key","scrollActivity","isSmoothScrolling","isScrolling","onScrollActivity","activity"],"mappings":"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"}