{"version":3,"file":"index.cjs","sources":["../../src/vue/hooks/use-scroll.ts","../../src/vue/components/scroller.vue"],"sourcesContent":["import { ref, watch, computed, toValue, type MaybeRefOrGetter, type ComputedRef } from 'vue';\nimport { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { ScrollPlugin, ScrollScope } from '@embedpdf/plugin-scroll';\n\nexport const useScrollPlugin = () => usePlugin<ScrollPlugin>(ScrollPlugin.id);\nexport const useScrollCapability = () => useCapability<ScrollPlugin>(ScrollPlugin.id);\n\n// Define the return type explicitly to maintain type safety\ninterface UseScrollReturn {\n  provides: ComputedRef<ScrollScope | null>;\n  state: ComputedRef<{\n    currentPage: number;\n    totalPages: number;\n  }>;\n}\n\n/**\n * Hook for scroll state for a specific document\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n */\nexport function useScroll(documentId: MaybeRefOrGetter<string>): UseScrollReturn {\n  const { provides } = useScrollCapability();\n\n  const currentPage = ref(1);\n  const totalPages = ref(1);\n\n  watch(\n    [provides, () => toValue(documentId)],\n    ([providesValue, docId], _, onCleanup) => {\n      if (!providesValue || !docId) {\n        currentPage.value = 1;\n        totalPages.value = 1;\n        return;\n      }\n\n      const scope = providesValue.forDocument(docId);\n\n      // Get initial state\n      currentPage.value = scope.getCurrentPage();\n      totalPages.value = scope.getTotalPages();\n\n      const unsubscribe = providesValue.onPageChange((event) => {\n        if (event.documentId === docId) {\n          currentPage.value = event.pageNumber;\n          totalPages.value = event.totalPages;\n        }\n      });\n\n      onCleanup(unsubscribe);\n    },\n    { immediate: true },\n  );\n\n  const state = computed(() => ({\n    currentPage: currentPage.value,\n    totalPages: totalPages.value,\n  }));\n\n  // Return a computed ref for the scoped capability\n  const scopedProvides = computed(() => {\n    const docId = toValue(documentId);\n    return provides.value?.forDocument(docId) ?? null;\n  });\n\n  return {\n    provides: scopedProvides,\n    state,\n  };\n}\n","<script setup lang=\"ts\">\nimport { ref, watch, computed } from 'vue';\nimport { useScrollPlugin } from '../hooks';\nimport { ScrollStrategy, type ScrollerLayout } from '@embedpdf/plugin-scroll';\n\ninterface ScrollerProps {\n  documentId: string;\n}\n\nconst props = defineProps<ScrollerProps>();\n\nconst { plugin: scrollPlugin } = useScrollPlugin();\n\nconst layoutData = ref<{\n  layout: ScrollerLayout | null;\n  docId: string | null;\n}>({ layout: null, docId: null });\n\nwatch(\n  [scrollPlugin, () => props.documentId],\n  ([plugin, docId], _, onCleanup) => {\n    if (!plugin || !docId) {\n      layoutData.value = { layout: null, docId: null };\n      return;\n    }\n\n    // Subscribe to the new document\n    const unsubscribe = plugin.onScrollerData(docId, (newLayout) => {\n      layoutData.value = { layout: newLayout, docId };\n    });\n\n    onCleanup(() => {\n      unsubscribe();\n      layoutData.value = { layout: null, docId: null };\n      plugin.clearLayoutReady(docId);\n    });\n  },\n  {\n    immediate: true,\n  },\n);\n\n// Only use layout if it matches the current documentId (prevents stale data)\nconst scrollerLayout = computed(() => {\n  return layoutData.value.docId === props.documentId ? layoutData.value.layout : null;\n});\n\n// Call setLayoutReady after layout is rendered (Vue's equivalent to useLayoutEffect)\nwatch(\n  [scrollPlugin, () => props.documentId, scrollerLayout],\n  ([plugin, docId, layout]) => {\n    if (!plugin || !docId || !layout) return;\n\n    plugin.setLayoutReady(docId);\n  },\n  { immediate: true },\n);\n</script>\n\n<template>\n  <div\n    v-if=\"scrollerLayout\"\n    :style=\"{\n      width: `${scrollerLayout.totalWidth}px`,\n      height: `${scrollerLayout.totalHeight}px`,\n      position: 'relative',\n      boxSizing: 'border-box',\n      margin: '0 auto',\n      ...(scrollerLayout.strategy === ScrollStrategy.Horizontal && {\n        display: 'flex',\n        flexDirection: 'row',\n      }),\n    }\"\n    v-bind=\"$attrs\"\n  >\n    <!-- Leading spacer -->\n    <div\n      :style=\"\n        scrollerLayout.strategy === ScrollStrategy.Horizontal\n          ? {\n              width: `${scrollerLayout.startSpacing}px`,\n              height: '100%',\n              flexShrink: 0,\n            }\n          : {\n              height: `${scrollerLayout.startSpacing}px`,\n              width: '100%',\n            }\n      \"\n    />\n\n    <!-- Page grid -->\n    <div\n      :style=\"{\n        gap: `${scrollerLayout.pageGap}px`,\n        display: 'flex',\n        alignItems: 'center',\n        position: 'relative',\n        boxSizing: 'border-box',\n        ...(scrollerLayout.strategy === ScrollStrategy.Horizontal\n          ? {\n              flexDirection: 'row',\n              minHeight: '100%',\n            }\n          : {\n              flexDirection: 'column',\n              minWidth: 'fit-content',\n            }),\n      }\"\n    >\n      <div\n        v-for=\"item in scrollerLayout.items\"\n        :key=\"item.pageNumbers[0]\"\n        :style=\"{\n          display: 'flex',\n          justifyContent: 'center',\n          gap: `${scrollerLayout.pageGap}px`,\n        }\"\n      >\n        <div\n          v-for=\"layout in item.pageLayouts\"\n          :key=\"layout.pageNumber\"\n          :style=\"{\n            width: `${layout.rotatedWidth}px`,\n            height: `${layout.rotatedHeight}px`,\n            position: 'relative',\n            zIndex: layout.elevated ? 1 : undefined,\n          }\"\n        >\n          <slot :page=\"layout\" />\n        </div>\n      </div>\n    </div>\n\n    <!-- Trailing spacer -->\n    <div\n      :style=\"\n        scrollerLayout.strategy === ScrollStrategy.Horizontal\n          ? {\n              width: `${scrollerLayout.endSpacing}px`,\n              height: '100%',\n              flexShrink: 0,\n            }\n          : {\n              height: `${scrollerLayout.endSpacing}px`,\n              width: '100%',\n            }\n      \"\n    />\n  </div>\n</template>\n"],"names":["useScrollPlugin","usePlugin","ScrollPlugin","id","useScrollCapability","useCapability","props","__props","plugin","scrollPlugin","layoutData","ref","layout","docId","watch","documentId","_","onCleanup","value","unsubscribe","onScrollerData","newLayout","clearLayoutReady","immediate","scrollerLayout","computed","setLayoutReady","_openBlock","_createElementBlock","_mergeProps","style","width","totalWidth","height","totalHeight","strategy","_unref","ScrollStrategy","Horizontal","$attrs","_createElementVNode","_normalizeStyle","startSpacing","gap","pageGap","_Fragment","_renderList","items","item","key","pageNumbers","pageLayouts","pageNumber","rotatedWidth","rotatedHeight","elevated","_renderSlot","_ctx","$slots","page","endSpacing","provides","currentPage","totalPages","toValue","providesValue","scope","forDocument","getCurrentPage","getTotalPages","onPageChange","event","state","_a"],"mappings":"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"}