{"version":3,"file":"index.cjs","sources":["../../src/svelte/hooks/use-scroll.svelte.ts","../../src/svelte/components/Scroller.svelte"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/svelte';\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: ScrollScope | null;\n  state: {\n    currentPage: number;\n    totalPages: number;\n  };\n}\n\n/**\n * Hook for scroll state for a specific document\n * @param documentId Document ID.\n */\nexport const useScroll = (getDocumentId: () => string | null): UseScrollReturn => {\n  const capability = useScrollCapability();\n\n  let state = $state({\n    currentPage: 1,\n    totalPages: 1,\n  });\n\n  // Reactive documentId\n  const documentId = $derived(getDocumentId());\n\n  // Scoped capability for current docId\n  const scopedProvides = $derived(\n    capability.provides && documentId ? capability.provides.forDocument(documentId) : null,\n  );\n\n  $effect(() => {\n    const provides = capability.provides;\n    const docId = documentId;\n\n    if (!provides || !docId) {\n      state.currentPage = 1;\n      state.totalPages = 1;\n      return;\n    }\n\n    const scope = provides.forDocument(docId);\n\n    // Initial values\n    state.currentPage = scope.getCurrentPage();\n    state.totalPages = scope.getTotalPages();\n\n    // Subscribe to page changes for THIS docId\n    return provides.onPageChange((event) => {\n      if (event.documentId === docId) {\n        state.currentPage = event.pageNumber;\n        state.totalPages = event.totalPages;\n      }\n    });\n  });\n\n  return {\n    get provides() {\n      return scopedProvides;\n    },\n    get state() {\n      return state;\n    },\n  };\n};\n","<script lang=\"ts\">\n  import type { Snippet } from 'svelte';\n  import type { HTMLAttributes } from 'svelte/elements';\n  import { useScrollPlugin } from '../hooks';\n  import { type ScrollerLayout, ScrollStrategy } from '@embedpdf/plugin-scroll';\n  import type { PageLayout } from '@embedpdf/plugin-scroll';\n\n  type ScrollerProps = HTMLAttributes<HTMLDivElement> & {\n    documentId: string;\n    renderPage: Snippet<[PageLayout]>;\n  };\n\n  let { documentId, renderPage, ...restProps }: ScrollerProps = $props();\n\n  const { plugin: scrollPlugin } = useScrollPlugin();\n\n  let layoutData = $state<{\n    layout: ScrollerLayout | null;\n    docId: string | null;\n  }>({ layout: null, docId: null });\n\n  $effect(() => {\n    if (!scrollPlugin || !documentId) {\n      layoutData = { layout: null, docId: null };\n      return;\n    }\n\n    // When we get new data, store it along with the current documentId\n    const unsubscribe = scrollPlugin.onScrollerData(documentId, (newLayout) => {\n      layoutData = { layout: newLayout, docId: documentId };\n    });\n\n    // When the effect re-runs or component unmounts, clear the state\n    return () => {\n      unsubscribe();\n      layoutData = { layout: null, docId: null };\n      scrollPlugin.clearLayoutReady(documentId);\n    };\n  });\n\n  // Only use layout if it matches the current documentId (prevents stale data)\n  const scrollerLayout = $derived(layoutData.docId === documentId ? layoutData.layout : null);\n\n  // Call setLayoutReady after layout is rendered (Svelte's equivalent to useLayoutEffect)\n  $effect.pre(() => {\n    if (!scrollPlugin || !documentId || !scrollerLayout) return;\n\n    scrollPlugin.setLayoutReady(documentId);\n  });\n</script>\n\n{#if scrollerLayout}\n  <div\n    {...restProps}\n    style:width={`${scrollerLayout.totalWidth}px`}\n    style:height={`${scrollerLayout.totalHeight}px`}\n    style:position=\"relative\"\n    style:box-sizing=\"border-box\"\n    style:margin=\"0 auto\"\n    style:display={scrollerLayout.strategy === ScrollStrategy.Horizontal ? 'flex' : undefined}\n    style:flex-direction={scrollerLayout.strategy === ScrollStrategy.Horizontal ? 'row' : undefined}\n  >\n    <!-- Leading spacer -->\n    <div\n      style:width={scrollerLayout.strategy === ScrollStrategy.Horizontal\n        ? `${scrollerLayout.startSpacing}px`\n        : '100%'}\n      style:height={scrollerLayout.strategy === ScrollStrategy.Horizontal\n        ? '100%'\n        : `${scrollerLayout.startSpacing}px`}\n      style:flex-shrink={scrollerLayout.strategy === ScrollStrategy.Horizontal ? '0' : undefined}\n    ></div>\n\n    <!-- Page grid -->\n    <div\n      style:gap={`${scrollerLayout.pageGap}px`}\n      style:display=\"flex\"\n      style:align-items=\"center\"\n      style:position=\"relative\"\n      style:box-sizing=\"border-box\"\n      style:flex-direction={scrollerLayout.strategy === ScrollStrategy.Horizontal\n        ? 'row'\n        : 'column'}\n      style:min-height={scrollerLayout.strategy === ScrollStrategy.Horizontal ? '100%' : undefined}\n      style:min-width={scrollerLayout.strategy === ScrollStrategy.Horizontal\n        ? undefined\n        : 'fit-content'}\n    >\n      {#each scrollerLayout.items as item (item.pageNumbers[0])}\n        <div\n          style:display=\"flex\"\n          style:justify-content=\"center\"\n          style:gap={`${scrollerLayout.pageGap}px`}\n        >\n          {#each item.pageLayouts as layout (layout.pageNumber)}\n            <div\n              style:width={`${layout.rotatedWidth}px`}\n              style:height={`${layout.rotatedHeight}px`}\n              style:position=\"relative\"\n              style:z-index={layout.elevated ? '1' : undefined}\n            >\n              {@render renderPage(layout)}\n            </div>\n          {/each}\n        </div>\n      {/each}\n    </div>\n\n    <!-- Trailing spacer -->\n    <div\n      style:width={scrollerLayout.strategy === ScrollStrategy.Horizontal\n        ? `${scrollerLayout.endSpacing}px`\n        : '100%'}\n      style:height={scrollerLayout.strategy === ScrollStrategy.Horizontal\n        ? '100%'\n        : `${scrollerLayout.endSpacing}px`}\n      style:flex-shrink={scrollerLayout.strategy === ScrollStrategy.Horizontal ? '0' : undefined}\n    ></div>\n  </div>\n{/if}\n"],"names":["useScrollPlugin","usePlugin","ScrollPlugin","id","useScrollCapability","useCapability","restProps","$","rest_props","$$props","plugin","scrollPlugin","layoutData","proxy","layout","docId","user_effect","documentId","set","unsubscribe","onScrollerData","newLayout","clearLayoutReady","scrollerLayout","derived","get","user_pre_effect","setLayoutReady","div","root_1","width","totalWidth","height","totalHeight","strategy","ScrollStrategy","Horizontal","div_1","div_2","each","items","item","pageNumbers","div_3","root_2","pageLayouts","pageNumber","$$anchor","div_4","root_3","styles_3","rotatedWidth","rotatedHeight","elevated","styles_2","gap","pageGap","div_5","styles","startSpacing","styles_1","styles_4","endSpacing","consequent","getDocumentId","capability","state","currentPage","totalPages","scopedProvides","provides","forDocument","scope","getCurrentPage","getTotalPages","onPageChange","event"],"mappings":"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"}