@embedpdf/plugin-viewport 2.0.0-next.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +4 -21
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/types.d.ts +2 -3
  6. package/dist/lib/viewport-plugin.d.ts +0 -4
  7. package/dist/preact/adapter.d.ts +3 -3
  8. package/dist/preact/index.cjs +1 -1
  9. package/dist/preact/index.cjs.map +1 -1
  10. package/dist/preact/index.js +13 -14
  11. package/dist/preact/index.js.map +1 -1
  12. package/dist/react/adapter.d.ts +2 -2
  13. package/dist/react/index.cjs +1 -1
  14. package/dist/react/index.cjs.map +1 -1
  15. package/dist/react/index.js +12 -13
  16. package/dist/react/index.js.map +1 -1
  17. package/dist/shared/context/index.d.ts +1 -0
  18. package/dist/shared/context/viewport-element-context.d.ts +7 -0
  19. package/dist/shared/hooks/use-viewport.d.ts +6 -0
  20. package/dist/shared/index.d.ts +1 -0
  21. package/dist/shared-preact/context/index.d.ts +1 -0
  22. package/dist/shared-preact/context/viewport-element-context.d.ts +7 -0
  23. package/dist/shared-preact/hooks/use-viewport.d.ts +6 -0
  24. package/dist/shared-preact/index.d.ts +1 -0
  25. package/dist/shared-react/context/index.d.ts +1 -0
  26. package/dist/shared-react/context/viewport-element-context.d.ts +7 -0
  27. package/dist/shared-react/hooks/use-viewport.d.ts +6 -0
  28. package/dist/shared-react/index.d.ts +1 -0
  29. package/dist/svelte/index.cjs +1 -1
  30. package/dist/svelte/index.cjs.map +1 -1
  31. package/dist/svelte/index.js +9 -10
  32. package/dist/svelte/index.js.map +1 -1
  33. package/dist/vue/index.cjs +1 -1
  34. package/dist/vue/index.cjs.map +1 -1
  35. package/dist/vue/index.js +5 -11
  36. package/dist/vue/index.js.map +1 -1
  37. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/svelte/hooks/use-viewport.svelte.ts","../../src/svelte/hooks/use-viewport-ref.svelte.ts","../../src/svelte/components/Viewport.svelte"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/svelte';\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 getDocumentId Function that returns the document ID\n */\nexport const useIsViewportGated = (getDocumentId: () => string | null) => {\n const capability = useViewportCapability();\n\n let isGated = $state(false);\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect(() => {\n const provides = capability.provides;\n const docId = documentId;\n\n if (!provides || !docId) {\n isGated = false;\n return;\n }\n\n // Set initial state\n isGated = provides.isGated(docId);\n\n // Subscribe to gate state changes\n return provides.onGateChange((event: GateChangeEvent) => {\n if (event.documentId === docId) {\n isGated = event.isGated;\n }\n });\n });\n\n return {\n get current() {\n return isGated;\n },\n };\n};\n\n/**\n * Hook to get scroll activity for a specific document\n * @param getDocumentId Function that returns the document ID\n */\nexport const useViewportScrollActivity = (getDocumentId: () => string | null) => {\n const capability = useViewportCapability();\n\n let scrollActivity = $state<ScrollActivity>({\n isScrolling: false,\n isSmoothScrolling: false,\n });\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect(() => {\n const provides = capability.provides;\n const docId = documentId;\n\n if (!provides || !docId) {\n scrollActivity = {\n isScrolling: false,\n isSmoothScrolling: false,\n };\n return;\n }\n\n // Subscribe to scroll activity events\n return provides.onScrollActivity((event) => {\n // Filter by documentId\n if (event.documentId === docId) {\n scrollActivity = event.activity;\n }\n });\n });\n\n return {\n get current() {\n return scrollActivity;\n },\n };\n};\n","import { type Rect } from '@embedpdf/models';\nimport { useViewportPlugin } from './use-viewport.svelte';\n\n/**\n * Hook to get a ref for the viewport container element with automatic setup/teardown\n * @param getDocumentId Function that returns the document ID\n */\nexport function useViewportRef(getDocumentId: () => string | null) {\n const { plugin } = useViewportPlugin();\n\n let containerRef = $state<HTMLDivElement | null>(null);\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect.pre(() => {\n if (!plugin) return;\n\n const container = containerRef;\n const docId = documentId;\n if (!container || !docId) return;\n\n // Register this viewport for the document\n try {\n plugin.registerViewport(docId);\n } catch (error) {\n console.error(`Failed to register viewport for document ${docId}:`, error);\n return;\n }\n\n // Provide rect calculator\n const provideRect = (): Rect => {\n const r = container.getBoundingClientRect();\n return {\n origin: { x: r.left, y: r.top },\n size: { width: r.width, height: r.height },\n };\n };\n plugin.registerBoundingRectProvider(docId, provideRect);\n\n // On scroll\n const onScroll = () => {\n plugin.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 plugin.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 });\n });\n resizeObserver.observe(container);\n\n // Subscribe to scroll requests for this document\n const unsubscribeScrollRequest = plugin.onScrollRequest(\n docId,\n ({ x, y, behavior = 'auto' }) => {\n requestAnimationFrame(() => {\n container.scrollTo({ left: x, top: y, behavior });\n });\n },\n );\n\n // Store cleanup function\n return () => {\n plugin.unregisterViewport(docId);\n plugin.registerBoundingRectProvider(docId, null);\n container.removeEventListener('scroll', onScroll);\n resizeObserver.disconnect();\n unsubscribeScrollRequest();\n };\n });\n\n return {\n get containerRef() {\n return containerRef;\n },\n set containerRef(el: HTMLDivElement | null) {\n containerRef = el;\n },\n };\n}\n","<script lang=\"ts\">\n import { useIsViewportGated, useViewportCapability, useViewportRef } from '../hooks';\n import type { HTMLAttributes } from 'svelte/elements';\n import type { Snippet } from 'svelte';\n\n type ViewportProps = HTMLAttributes<HTMLDivElement> & {\n /**\n * The ID of the document that this viewport displays\n */\n documentId: string;\n children: Snippet;\n class?: string;\n };\n\n let { documentId, children, class: propsClass, ...restProps }: ViewportProps = $props();\n\n let viewportGap = $state(0);\n\n const viewportRef = useViewportRef(() => documentId);\n const viewportCapability = useViewportCapability();\n const isGated = useIsViewportGated(() => documentId);\n\n $effect(() => {\n if (viewportCapability.provides) {\n viewportGap = viewportCapability.provides.getViewportGap();\n }\n });\n</script>\n\n<div\n {...restProps}\n bind:this={viewportRef.containerRef}\n style:width=\"100%\"\n style:height=\"100%\"\n style:overflow=\"auto\"\n style:padding={`${viewportGap}px`}\n class={propsClass}\n>\n {#if !isGated.current}\n {@render children()}\n {/if}\n</div>\n"],"names":["useViewportPlugin","usePlugin","ViewportPlugin","id","useViewportCapability","useCapability","useIsViewportGated","getDocumentId","capability","isGated","documentId","$","user_effect","provides","docId","set","onGateChange","event","current","useViewportRef","plugin","containerRef","user_pre_effect","container","registerViewport","error","console","registerBoundingRectProvider","r","getBoundingClientRect","origin","x","left","y","top","size","width","height","onScroll","setViewportScrollMetrics","scrollTop","scrollLeft","addEventListener","resizeObserver","ResizeObserver","setViewportResizeMetrics","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollWidth","scrollHeight","observe","unsubscribeScrollRequest","onScrollRequest","behavior","requestAnimationFrame","scrollTo","unregisterViewport","removeEventListener","disconnect","el","restProps","rest_props","$$props","viewportGap","viewportRef","viewportCapability","getViewportGap","$$render","consequent","bind_this","div","$$value","scrollActivity","isScrolling","isSmoothScrolling","onScrollActivity","activity"],"mappings":"wgBAGaA,EAAA,IAA0BC,YAA0BC,EAAAA,eAAeC,IACnEC,EAAA,IAA8BC,gBAA8BH,EAAAA,eAAeC,IAO3EG,EAAsBC,IAC3B,MAAAC,EAAaJ,IAEf,IAAAK,WAAiB,GAGf,MAAAC,YAAsBH,UAE5BI,EAAAC,uBACQC,EAAWL,EAAWK,SACtBC,QAAQJ,MAETG,GAAaC,EASX,OAHPH,EAAAI,IAAAN,EAAUI,EAASJ,QAAQK,IAAK,GAGzBD,EAASG,aAAcC,IACxBA,EAAMP,aAAeI,SACvBL,EAAUQ,EAAMR,SAAA,KAVlBE,EAAAI,IAAAN,GAAU,MAgBR,WAAAS,gBACKT,EACT,aCnCYU,EAAeZ,GACrB,MAAAa,OAAAA,GAAWpB,IAEf,IAAAqB,UAA6C,MAG3C,MAAAX,YAAsBH,UAE5BI,EAAAW,yBACOF,EAAA,OAEC,MAAAG,QAAYF,GACZP,QAAQJ,GACT,IAAAa,IAAcT,EAAA,WAIjBM,EAAOI,iBAAiBV,EAC1B,OAASW,eACPC,QAAQD,MAAA,4CAAkDX,KAAUW,EAEtE,CAUAL,EAAOO,6BAA6Bb,aAN5Bc,EAAIL,EAAUM,+BAElBC,QAAUC,EAAGH,EAAEI,KAAMC,EAAGL,EAAEM,KAC1BC,MAAQC,MAAOR,EAAEQ,MAAOC,OAAQT,EAAES,WAMhC,MAAAC,OACJlB,EAAOmB,yBAAyBzB,EAAA,CAC9B0B,UAAWjB,EAAUiB,UACrBC,WAAYlB,EAAUkB,cAG1BlB,EAAUmB,iBAAiB,SAAUJ,SAG/BK,EAAA,IAAqBC,eAAA,KACzBxB,EAAOyB,yBAAyB/B,EAAA,CAC9BsB,MAAOb,EAAUuB,YACjBT,OAAQd,EAAUwB,aAClBC,YAAazB,EAAUyB,YACvBC,aAAc1B,EAAU0B,aACxBT,UAAWjB,EAAUiB,UACrBC,WAAYlB,EAAUkB,WACtBS,YAAa3B,EAAU2B,YACvBC,aAAc5B,EAAU4B,iBAG5BR,EAAeS,QAAQ7B,GAGjB,MAAA8B,EAA2BjC,EAAOkC,gBACtCxC,EAAA,EACGiB,IAAGE,IAAGsB,WAAW,WAClBC,2BACEjC,EAAUkC,UAAWzB,KAAMD,EAAGG,IAAKD,EAAGsB,4BAO1CnC,EAAOsC,mBAAmB5C,GAC1BM,EAAOO,6BAA6Bb,EAAO,MAC3CS,EAAUoC,oBAAoB,SAAUrB,GACxCK,EAAeiB,aACfP,QAKE,gBAAAhC,gBACKA,EACT,kBACIA,CAAawC,GACflD,EAAAI,IAAAM,EAAewC,GAAA,EACjB,EAEJ,qFC9EoDC,EAASnD,EAAAoD,WAAAC,EAAA,mEAEvDC,UAAqB,GAEnB,MAAAC,EAAc/C,EAAc,IAAA6C,EAAAtD,YAC5ByD,EAAqB/D,IACrBK,EAAUH,EAAkB,IAAA0D,EAAAtD,YAElCC,EAAAC,YAAO,KACDuD,EAAmBtD,UACrBF,EAAAI,IAAAkD,EAAcE,EAAmBtD,SAASuD,kBAAc,6CAMxDN,uFAKcG,6HAGZxD,EAAQS,SAAOmD,EAAAC,gBAPV3D,EAAA4D,UAAAC,EAAAC,GAAAP,EAAY7C,aAAYoD,EAAA,IAAxB,MAAAP,OAAA,EAAAA,EAAY7C,mCAJzB,sJFuB0Cd,IAClC,MAAAC,EAAaJ,IAEf,IAAAsE,mBACFC,aAAa,EACbC,mBAAmB,KAIf,MAAAlE,YAAsBH,UAE5BI,EAAAC,uBACQC,EAAWL,EAAWK,SACtBC,QAAQJ,MAETG,GAAaC,EASX,OAAAD,EAASgE,iBAAkB5D,IAE5BA,EAAMP,aAAeI,SACvB4D,EAAiBzD,EAAM6D,UAAA,KAXzBnE,EAAAI,IAAA2D,GACEC,aAAa,EACbC,mBAAmB,IAAA,MAenB,WAAA1D,gBACKwD,EACT"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/svelte/hooks/use-viewport.svelte.ts","../../src/svelte/hooks/use-viewport-ref.svelte.ts","../../src/svelte/components/Viewport.svelte"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/svelte';\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 getDocumentId Function that returns the document ID\n */\nexport const useIsViewportGated = (getDocumentId: () => string | null) => {\n const capability = useViewportCapability();\n\n let isGated = $state(false);\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect(() => {\n const provides = capability.provides;\n const docId = documentId;\n\n if (!provides || !docId) {\n isGated = false;\n return;\n }\n\n // Set initial state\n isGated = provides.isGated(docId);\n\n // Subscribe to gate state changes\n return provides.onGateChange((event: GateChangeEvent) => {\n if (event.documentId === docId) {\n isGated = event.isGated;\n }\n });\n });\n\n return {\n get current() {\n return isGated;\n },\n };\n};\n\n/**\n * Hook to get scroll activity for a specific document\n * @param getDocumentId Function that returns the document ID\n */\nexport const useViewportScrollActivity = (getDocumentId: () => string | null) => {\n const capability = useViewportCapability();\n\n let scrollActivity = $state<ScrollActivity>({\n isScrolling: false,\n isSmoothScrolling: false,\n });\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect(() => {\n const provides = capability.provides;\n const docId = documentId;\n\n if (!provides || !docId) {\n scrollActivity = {\n isScrolling: false,\n isSmoothScrolling: false,\n };\n return;\n }\n\n // Subscribe to scroll activity events\n return provides.onScrollActivity((event) => {\n // Filter by documentId\n if (event.documentId === docId) {\n scrollActivity = event.activity;\n }\n });\n });\n\n return {\n get current() {\n return scrollActivity;\n },\n };\n};\n","import { type Rect } from '@embedpdf/models';\nimport { useViewportPlugin } from './use-viewport.svelte';\n\n/**\n * Hook to get a ref for the viewport container element with automatic setup/teardown\n * @param getDocumentId Function that returns the document ID\n */\nexport function useViewportRef(getDocumentId: () => string | null) {\n const { plugin } = useViewportPlugin();\n\n let containerRef = $state<HTMLDivElement | null>(null);\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect.pre(() => {\n if (!plugin) return;\n\n const container = containerRef;\n const docId = documentId;\n if (!container || !docId) return;\n\n // Register this viewport for the document\n try {\n plugin.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 plugin.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 plugin.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 = plugin.onScrollRequest(\n docId,\n ({ x, y, behavior = 'auto' }) => {\n requestAnimationFrame(() => {\n container.scrollTo({ left: x, top: y, behavior });\n });\n },\n );\n\n // Store cleanup function\n return () => {\n plugin.unregisterViewport(docId);\n container.removeEventListener('scroll', onScroll);\n resizeObserver.disconnect();\n unsubscribeScrollRequest();\n };\n });\n\n return {\n get containerRef() {\n return containerRef;\n },\n set containerRef(el: HTMLDivElement | null) {\n containerRef = el;\n },\n };\n}\n","<script lang=\"ts\">\n import { setContext } from 'svelte';\n import { useIsViewportGated, useViewportCapability, useViewportRef } from '../hooks';\n import type { HTMLAttributes } from 'svelte/elements';\n import type { Snippet } from 'svelte';\n\n type ViewportProps = HTMLAttributes<HTMLDivElement> & {\n /**\n * The ID of the document that this viewport displays\n */\n documentId: string;\n children: Snippet;\n class?: string;\n };\n\n let { documentId, children, class: propsClass, ...restProps }: ViewportProps = $props();\n\n let viewportGap = $state(0);\n\n const viewportRef = useViewportRef(() => documentId);\n const viewportCapability = useViewportCapability();\n const isGated = useIsViewportGated(() => documentId);\n\n // Provide the viewport element to child components via context\n setContext('viewport-element', {\n get current() {\n return viewportRef.containerRef;\n },\n });\n\n $effect(() => {\n if (viewportCapability.provides) {\n viewportGap = viewportCapability.provides.getViewportGap();\n }\n });\n</script>\n\n<div\n {...restProps}\n bind:this={viewportRef.containerRef}\n style:width=\"100%\"\n style:height=\"100%\"\n style:overflow=\"auto\"\n style:padding={`${viewportGap}px`}\n class={propsClass}\n>\n {#if !isGated.current}\n {@render children()}\n {/if}\n</div>\n"],"names":["useViewportPlugin","usePlugin","ViewportPlugin","id","useViewportCapability","useCapability","useIsViewportGated","getDocumentId","capability","isGated","documentId","$","user_effect","provides","docId","set","onGateChange","event","current","useViewportRef","plugin","containerRef","user_pre_effect","container","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","removeEventListener","disconnect","el","restProps","rest_props","$$props","viewportGap","viewportRef","viewportCapability","setContext","getViewportGap","$$render","consequent","bind_this","div","$$value","scrollActivity","isScrolling","isSmoothScrolling","onScrollActivity","activity"],"mappings":"4hBAGaA,EAAA,IAA0BC,YAA0BC,EAAAA,eAAeC,IACnEC,EAAA,IAA8BC,gBAA8BH,EAAAA,eAAeC,IAO3EG,EAAsBC,IAC3B,MAAAC,EAAaJ,IAEf,IAAAK,WAAiB,GAGf,MAAAC,YAAsBH,UAE5BI,EAAAC,uBACQC,EAAWL,EAAWK,SACtBC,QAAQJ,MAETG,GAAaC,EASX,OAHPH,EAAAI,IAAAN,EAAUI,EAASJ,QAAQK,IAAK,GAGzBD,EAASG,aAAcC,IACxBA,EAAMP,aAAeI,SACvBL,EAAUQ,EAAMR,SAAA,KAVlBE,EAAAI,IAAAN,GAAU,MAgBR,WAAAS,gBACKT,EACT,aCnCYU,EAAeZ,GACrB,MAAAa,OAAAA,GAAWpB,IAEf,IAAAqB,UAA6C,MAG3C,MAAAX,YAAsBH,UAE5BI,EAAAW,yBACOF,EAAA,OAEC,MAAAG,QAAYF,GACZP,QAAQJ,GACT,IAAAa,IAAcT,EAAA,WAIjBM,EAAOI,iBAAiBV,EAC1B,OAASW,eACPC,QAAQD,MAAA,4CAAkDX,KAAUW,EAEtE,CAGM,MAAAE,OACJP,EAAOQ,yBAAyBd,EAAA,CAC9Be,UAAWN,EAAUM,UACrBC,WAAYP,EAAUO,cAG1BP,EAAUQ,iBAAiB,SAAUJ,SAG/BK,EAAA,IAAqBC,eAAA,KACzBb,EAAOc,yBAAyBpB,EAAA,CAC9BqB,MAAOZ,EAAUa,YACjBC,OAAQd,EAAUe,aAClBC,YAAahB,EAAUgB,YACvBC,aAAcjB,EAAUiB,aACxBX,UAAWN,EAAUM,UACrBC,WAAYP,EAAUO,WACtBW,YAAalB,EAAUkB,YACvBC,aAAcnB,EAAUmB,aACxBC,WAAYpB,EAAUoB,WACtBC,UAAWrB,EAAUqB,cAGzBZ,EAAea,QAAQtB,GAGjB,MAAAuB,EAA2B1B,EAAO2B,gBACtCjC,EAAA,EACGkC,IAAGC,IAAGC,WAAW,WAClBC,2BACE5B,EAAU6B,UAAWC,KAAML,EAAGM,IAAKL,EAAGC,4BAO1C9B,EAAOmC,mBAAmBzC,GAC1BS,EAAUiC,oBAAoB,SAAU7B,GACxCK,EAAeyB,aACfX,QAKE,gBAAAzB,gBACKA,EACT,kBACIA,CAAaqC,GACf/C,EAAAI,IAAAM,EAAeqC,GAAA,EACjB,EAEJ,qFCpEoDC,EAAShD,EAAAiD,WAAAC,EAAA,mEAEvDC,UAAqB,GAEnB,MAAAC,EAAc5C,EAAc,IAAA0C,EAAAnD,YAC5BsD,EAAqB5D,IACrBK,EAAUH,EAAkB,IAAAuD,EAAAnD,YAGlCuD,EAAAA,WAAW,mBAAkB,CACvB,WAAA/C,GACK,OAAA6C,EAAY1C,YACrB,IAGFV,EAAAC,YAAO,KACDoD,EAAmBnD,UACrBF,EAAAI,IAAA+C,EAAcE,EAAmBnD,SAASqD,kBAAc,6CAMxDP,uFAKcG,6HAGZrD,EAAQS,SAAOiD,EAAAC,gBAPVzD,EAAA0D,UAAAC,EAAAC,GAAAR,EAAY1C,aAAYkD,EAAA,IAAxB,MAAAR,OAAA,EAAAA,EAAY1C,mCAJzB,sJFe0Cd,IAClC,MAAAC,EAAaJ,IAEf,IAAAoE,mBACFC,aAAa,EACbC,mBAAmB,KAIf,MAAAhE,YAAsBH,UAE5BI,EAAAC,uBACQC,EAAWL,EAAWK,SACtBC,QAAQJ,MAETG,GAAaC,EASX,OAAAD,EAAS8D,iBAAkB1D,IAE5BA,EAAMP,aAAeI,SACvB0D,EAAiBvD,EAAM2D,UAAA,KAXzBjE,EAAAI,IAAAyD,GACEC,aAAa,EACbC,mBAAmB,IAAA,MAenB,WAAAxD,gBACKsD,EACT"}
@@ -1,5 +1,6 @@
1
1
  import "svelte/internal/disclose-version";
2
2
  import * as $ from "svelte/internal/client";
3
+ import { setContext } from "svelte";
3
4
  import { useCapability, usePlugin } from "@embedpdf/core/svelte";
4
5
  import { ViewportPlugin } from "@embedpdf/plugin-viewport";
5
6
  export * from "@embedpdf/plugin-viewport";
@@ -67,14 +68,6 @@ function useViewportRef(getDocumentId) {
67
68
  console.error(`Failed to register viewport for document ${docId}:`, error);
68
69
  return;
69
70
  }
70
- const provideRect = () => {
71
- const r = container.getBoundingClientRect();
72
- return {
73
- origin: { x: r.left, y: r.top },
74
- size: { width: r.width, height: r.height }
75
- };
76
- };
77
- plugin.registerBoundingRectProvider(docId, provideRect);
78
71
  const onScroll = () => {
79
72
  plugin.setViewportScrollMetrics(docId, {
80
73
  scrollTop: container.scrollTop,
@@ -91,7 +84,9 @@ function useViewportRef(getDocumentId) {
91
84
  scrollTop: container.scrollTop,
92
85
  scrollLeft: container.scrollLeft,
93
86
  scrollWidth: container.scrollWidth,
94
- scrollHeight: container.scrollHeight
87
+ scrollHeight: container.scrollHeight,
88
+ clientLeft: container.clientLeft,
89
+ clientTop: container.clientTop
95
90
  });
96
91
  });
97
92
  resizeObserver.observe(container);
@@ -102,7 +97,6 @@ function useViewportRef(getDocumentId) {
102
97
  });
103
98
  return () => {
104
99
  plugin.unregisterViewport(docId);
105
- plugin.registerBoundingRectProvider(docId, null);
106
100
  container.removeEventListener("scroll", onScroll);
107
101
  resizeObserver.disconnect();
108
102
  unsubscribeScrollRequest();
@@ -132,6 +126,11 @@ function Viewport($$anchor, $$props) {
132
126
  const viewportRef = useViewportRef(() => $$props.documentId);
133
127
  const viewportCapability = useViewportCapability();
134
128
  const isGated = useIsViewportGated(() => $$props.documentId);
129
+ setContext("viewport-element", {
130
+ get current() {
131
+ return viewportRef.containerRef;
132
+ }
133
+ });
135
134
  $.user_effect(() => {
136
135
  if (viewportCapability.provides) {
137
136
  $.set(viewportGap, viewportCapability.provides.getViewportGap(), true);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/svelte/hooks/use-viewport.svelte.ts","../../src/svelte/hooks/use-viewport-ref.svelte.ts","../../src/svelte/components/Viewport.svelte"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/svelte';\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 getDocumentId Function that returns the document ID\n */\nexport const useIsViewportGated = (getDocumentId: () => string | null) => {\n const capability = useViewportCapability();\n\n let isGated = $state(false);\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect(() => {\n const provides = capability.provides;\n const docId = documentId;\n\n if (!provides || !docId) {\n isGated = false;\n return;\n }\n\n // Set initial state\n isGated = provides.isGated(docId);\n\n // Subscribe to gate state changes\n return provides.onGateChange((event: GateChangeEvent) => {\n if (event.documentId === docId) {\n isGated = event.isGated;\n }\n });\n });\n\n return {\n get current() {\n return isGated;\n },\n };\n};\n\n/**\n * Hook to get scroll activity for a specific document\n * @param getDocumentId Function that returns the document ID\n */\nexport const useViewportScrollActivity = (getDocumentId: () => string | null) => {\n const capability = useViewportCapability();\n\n let scrollActivity = $state<ScrollActivity>({\n isScrolling: false,\n isSmoothScrolling: false,\n });\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect(() => {\n const provides = capability.provides;\n const docId = documentId;\n\n if (!provides || !docId) {\n scrollActivity = {\n isScrolling: false,\n isSmoothScrolling: false,\n };\n return;\n }\n\n // Subscribe to scroll activity events\n return provides.onScrollActivity((event) => {\n // Filter by documentId\n if (event.documentId === docId) {\n scrollActivity = event.activity;\n }\n });\n });\n\n return {\n get current() {\n return scrollActivity;\n },\n };\n};\n","import { type Rect } from '@embedpdf/models';\nimport { useViewportPlugin } from './use-viewport.svelte';\n\n/**\n * Hook to get a ref for the viewport container element with automatic setup/teardown\n * @param getDocumentId Function that returns the document ID\n */\nexport function useViewportRef(getDocumentId: () => string | null) {\n const { plugin } = useViewportPlugin();\n\n let containerRef = $state<HTMLDivElement | null>(null);\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect.pre(() => {\n if (!plugin) return;\n\n const container = containerRef;\n const docId = documentId;\n if (!container || !docId) return;\n\n // Register this viewport for the document\n try {\n plugin.registerViewport(docId);\n } catch (error) {\n console.error(`Failed to register viewport for document ${docId}:`, error);\n return;\n }\n\n // Provide rect calculator\n const provideRect = (): Rect => {\n const r = container.getBoundingClientRect();\n return {\n origin: { x: r.left, y: r.top },\n size: { width: r.width, height: r.height },\n };\n };\n plugin.registerBoundingRectProvider(docId, provideRect);\n\n // On scroll\n const onScroll = () => {\n plugin.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 plugin.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 });\n });\n resizeObserver.observe(container);\n\n // Subscribe to scroll requests for this document\n const unsubscribeScrollRequest = plugin.onScrollRequest(\n docId,\n ({ x, y, behavior = 'auto' }) => {\n requestAnimationFrame(() => {\n container.scrollTo({ left: x, top: y, behavior });\n });\n },\n );\n\n // Store cleanup function\n return () => {\n plugin.unregisterViewport(docId);\n plugin.registerBoundingRectProvider(docId, null);\n container.removeEventListener('scroll', onScroll);\n resizeObserver.disconnect();\n unsubscribeScrollRequest();\n };\n });\n\n return {\n get containerRef() {\n return containerRef;\n },\n set containerRef(el: HTMLDivElement | null) {\n containerRef = el;\n },\n };\n}\n","<script lang=\"ts\">\n import { useIsViewportGated, useViewportCapability, useViewportRef } from '../hooks';\n import type { HTMLAttributes } from 'svelte/elements';\n import type { Snippet } from 'svelte';\n\n type ViewportProps = HTMLAttributes<HTMLDivElement> & {\n /**\n * The ID of the document that this viewport displays\n */\n documentId: string;\n children: Snippet;\n class?: string;\n };\n\n let { documentId, children, class: propsClass, ...restProps }: ViewportProps = $props();\n\n let viewportGap = $state(0);\n\n const viewportRef = useViewportRef(() => documentId);\n const viewportCapability = useViewportCapability();\n const isGated = useIsViewportGated(() => documentId);\n\n $effect(() => {\n if (viewportCapability.provides) {\n viewportGap = viewportCapability.provides.getViewportGap();\n }\n });\n</script>\n\n<div\n {...restProps}\n bind:this={viewportRef.containerRef}\n style:width=\"100%\"\n style:height=\"100%\"\n style:overflow=\"auto\"\n style:padding={`${viewportGap}px`}\n class={propsClass}\n>\n {#if !isGated.current}\n {@render children()}\n {/if}\n</div>\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/svelte/hooks/use-viewport.svelte.ts","../../src/svelte/hooks/use-viewport-ref.svelte.ts","../../src/svelte/components/Viewport.svelte"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/svelte';\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 getDocumentId Function that returns the document ID\n */\nexport const useIsViewportGated = (getDocumentId: () => string | null) => {\n const capability = useViewportCapability();\n\n let isGated = $state(false);\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect(() => {\n const provides = capability.provides;\n const docId = documentId;\n\n if (!provides || !docId) {\n isGated = false;\n return;\n }\n\n // Set initial state\n isGated = provides.isGated(docId);\n\n // Subscribe to gate state changes\n return provides.onGateChange((event: GateChangeEvent) => {\n if (event.documentId === docId) {\n isGated = event.isGated;\n }\n });\n });\n\n return {\n get current() {\n return isGated;\n },\n };\n};\n\n/**\n * Hook to get scroll activity for a specific document\n * @param getDocumentId Function that returns the document ID\n */\nexport const useViewportScrollActivity = (getDocumentId: () => string | null) => {\n const capability = useViewportCapability();\n\n let scrollActivity = $state<ScrollActivity>({\n isScrolling: false,\n isSmoothScrolling: false,\n });\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect(() => {\n const provides = capability.provides;\n const docId = documentId;\n\n if (!provides || !docId) {\n scrollActivity = {\n isScrolling: false,\n isSmoothScrolling: false,\n };\n return;\n }\n\n // Subscribe to scroll activity events\n return provides.onScrollActivity((event) => {\n // Filter by documentId\n if (event.documentId === docId) {\n scrollActivity = event.activity;\n }\n });\n });\n\n return {\n get current() {\n return scrollActivity;\n },\n };\n};\n","import { type Rect } from '@embedpdf/models';\nimport { useViewportPlugin } from './use-viewport.svelte';\n\n/**\n * Hook to get a ref for the viewport container element with automatic setup/teardown\n * @param getDocumentId Function that returns the document ID\n */\nexport function useViewportRef(getDocumentId: () => string | null) {\n const { plugin } = useViewportPlugin();\n\n let containerRef = $state<HTMLDivElement | null>(null);\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n $effect.pre(() => {\n if (!plugin) return;\n\n const container = containerRef;\n const docId = documentId;\n if (!container || !docId) return;\n\n // Register this viewport for the document\n try {\n plugin.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 plugin.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 plugin.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 = plugin.onScrollRequest(\n docId,\n ({ x, y, behavior = 'auto' }) => {\n requestAnimationFrame(() => {\n container.scrollTo({ left: x, top: y, behavior });\n });\n },\n );\n\n // Store cleanup function\n return () => {\n plugin.unregisterViewport(docId);\n container.removeEventListener('scroll', onScroll);\n resizeObserver.disconnect();\n unsubscribeScrollRequest();\n };\n });\n\n return {\n get containerRef() {\n return containerRef;\n },\n set containerRef(el: HTMLDivElement | null) {\n containerRef = el;\n },\n };\n}\n","<script lang=\"ts\">\n import { setContext } from 'svelte';\n import { useIsViewportGated, useViewportCapability, useViewportRef } from '../hooks';\n import type { HTMLAttributes } from 'svelte/elements';\n import type { Snippet } from 'svelte';\n\n type ViewportProps = HTMLAttributes<HTMLDivElement> & {\n /**\n * The ID of the document that this viewport displays\n */\n documentId: string;\n children: Snippet;\n class?: string;\n };\n\n let { documentId, children, class: propsClass, ...restProps }: ViewportProps = $props();\n\n let viewportGap = $state(0);\n\n const viewportRef = useViewportRef(() => documentId);\n const viewportCapability = useViewportCapability();\n const isGated = useIsViewportGated(() => documentId);\n\n // Provide the viewport element to child components via context\n setContext('viewport-element', {\n get current() {\n return viewportRef.containerRef;\n },\n });\n\n $effect(() => {\n if (viewportCapability.provides) {\n viewportGap = viewportCapability.provides.getViewportGap();\n }\n });\n</script>\n\n<div\n {...restProps}\n bind:this={viewportRef.containerRef}\n style:width=\"100%\"\n style:height=\"100%\"\n style:overflow=\"auto\"\n style:padding={`${viewportGap}px`}\n class={propsClass}\n>\n {#if !isGated.current}\n {@render children()}\n {/if}\n</div>\n"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),t=require("@embedpdf/core/vue"),r=require("@embedpdf/plugin-viewport"),o=()=>t.usePlugin(r.ViewportPlugin.id),i=()=>t.useCapability(r.ViewportPlugin.id),l=t=>{const{provides:r}=i(),o=e.ref(!1);return e.watch([r,()=>e.toValue(t)],([e,t],r,i)=>{if(!e)return void(o.value=!1);o.value=e.isGated(t);i(e.onGateChange(e=>{e.documentId===t&&(o.value=e.isGated)}))},{immediate:!0}),o};function n(t){const{plugin:r}=o(),i=e.ref(null);let l=null;return e.watch([r,i,()=>e.toValue(t)],([,,e])=>{l&&(l(),l=null),l=(e=>{const t=r.value,o=i.value;if(!o||!t)return;try{t.registerViewport(e)}catch(s){return void console.error(`Failed to register viewport for document ${e}:`,s)}t.registerBoundingRectProvider(e,()=>{const e=o.getBoundingClientRect();return{origin:{x:e.left,y:e.top},size:{width:e.width,height:e.height}}});const l=()=>{t.setViewportScrollMetrics(e,{scrollTop:o.scrollTop,scrollLeft:o.scrollLeft})};o.addEventListener("scroll",l),new ResizeObserver(()=>{t.setViewportResizeMetrics(e,{width:o.offsetWidth,height:o.offsetHeight,clientWidth:o.clientWidth,clientHeight:o.clientHeight,scrollTop:o.scrollTop,scrollLeft:o.scrollLeft,scrollWidth:o.scrollWidth,scrollHeight:o.scrollHeight})}).observe(o);const n=t.onScrollRequest(e,({x:e,y:t,behavior:r="auto"})=>{requestAnimationFrame(()=>{o.scrollTo({left:e,top:t,behavior:r})})});return()=>{t.unregisterViewport(e),t.registerBoundingRectProvider(e,null),o.removeEventListener("scroll",l),n()}})(e)||null},{immediate:!0}),e.onBeforeUnmount(()=>{l&&(l(),l=null)}),i}const s=e.defineComponent({__name:"viewport",props:{documentId:{}},setup(t){const r=t,o=e.useAttrs(),{provides:s}=i(),c=e.ref(0);e.watch(s,e=>{e&&(c.value=e.getViewportGap())},{immediate:!0});const u=l(()=>r.documentId),d=n(()=>r.documentId);return(t,r)=>(e.openBlock(),e.createElementBlock("div",e.mergeProps({ref_key:"viewportRef",ref:d},e.unref(o),{style:{padding:`${c.value}px`,width:"100%",height:"100%",overflow:"auto"}}),[e.unref(u)?e.createCommentVNode("",!0):e.renderSlot(t.$slots,"default",{key:0})],16))}});exports.Viewport=s,exports.useIsViewportGated=l,exports.useViewportCapability=i,exports.useViewportPlugin=o,exports.useViewportRef=n,exports.useViewportScrollActivity=t=>{const{provides:r}=i(),o=e.ref({isSmoothScrolling:!1,isScrolling:!1});return e.watch([r,()=>e.toValue(t)],([e,t],r,i)=>{if(!e)return void(o.value={isSmoothScrolling:!1,isScrolling:!1});i(e.onScrollActivity(e=>{e.documentId===t&&(o.value=e.activity)}))},{immediate:!0}),o},Object.keys(r).forEach(e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>r[e]})});
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),t=require("@embedpdf/core/vue"),o=require("@embedpdf/plugin-viewport"),r=()=>t.usePlugin(o.ViewportPlugin.id),i=()=>t.useCapability(o.ViewportPlugin.id),l=t=>{const{provides:o}=i(),r=e.ref(!1);return e.watch([o,()=>e.toValue(t)],([e,t],o,i)=>{if(!e)return void(r.value=!1);r.value=e.isGated(t);i(e.onGateChange(e=>{e.documentId===t&&(r.value=e.isGated)}))},{immediate:!0}),r};function n(t){const{plugin:o}=r(),i=e.ref(null);let l=null;return e.watch([o,i,()=>e.toValue(t)],([,,e])=>{l&&(l(),l=null),l=(e=>{const t=o.value,r=i.value;if(!r||!t)return;try{t.registerViewport(e)}catch(s){return void console.error(`Failed to register viewport for document ${e}:`,s)}const l=()=>{t.setViewportScrollMetrics(e,{scrollTop:r.scrollTop,scrollLeft:r.scrollLeft})};r.addEventListener("scroll",l),new ResizeObserver(()=>{t.setViewportResizeMetrics(e,{width:r.offsetWidth,height:r.offsetHeight,clientWidth:r.clientWidth,clientHeight:r.clientHeight,scrollTop:r.scrollTop,scrollLeft:r.scrollLeft,scrollWidth:r.scrollWidth,scrollHeight:r.scrollHeight,clientLeft:r.clientLeft,clientTop:r.clientTop})}).observe(r);const n=t.onScrollRequest(e,({x:e,y:t,behavior:o="auto"})=>{requestAnimationFrame(()=>{r.scrollTo({left:e,top:t,behavior:o})})});return()=>{t.unregisterViewport(e),r.removeEventListener("scroll",l),n()}})(e)||null},{immediate:!0}),e.onBeforeUnmount(()=>{l&&(l(),l=null)}),i}const s=e.defineComponent({__name:"viewport",props:{documentId:{}},setup(t){const o=t,r=e.useAttrs(),{provides:s}=i(),c=e.ref(0);e.watch(s,e=>{e&&(c.value=e.getViewportGap())},{immediate:!0});const u=l(()=>o.documentId),p=n(()=>o.documentId);return e.provide("viewport-element",p),(t,o)=>(e.openBlock(),e.createElementBlock("div",e.mergeProps({ref_key:"viewportRef",ref:p},e.unref(r),{style:{padding:`${c.value}px`,width:"100%",height:"100%",overflow:"auto"}}),[e.unref(u)?e.createCommentVNode("",!0):e.renderSlot(t.$slots,"default",{key:0})],16))}});exports.Viewport=s,exports.useIsViewportGated=l,exports.useViewportCapability=i,exports.useViewportPlugin=r,exports.useViewportRef=n,exports.useViewportScrollActivity=t=>{const{provides:o}=i(),r=e.ref({isSmoothScrolling:!1,isScrolling:!1});return e.watch([o,()=>e.toValue(t)],([e,t],o,i)=>{if(!e)return void(r.value={isSmoothScrolling:!1,isScrolling:!1});i(e.onScrollActivity(e=>{e.documentId===t&&(r.value=e.activity)}))},{immediate:!0}),r},Object.keys(o).forEach(e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>o[e]})});
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"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 // Provide rect calculator\n const provideRect = (): Rect => {\n const r = container.getBoundingClientRect();\n return {\n origin: { x: r.left, y: r.top },\n size: { width: r.width, height: r.height },\n };\n };\n viewportPlugin.registerBoundingRectProvider(docId, provideRect);\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 });\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 viewportPlugin.registerBoundingRectProvider(docId, null);\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 } 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</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","registerBoundingRectProvider","r","getBoundingClientRect","origin","x","left","y","top","size","width","height","onScroll","setViewportScrollMetrics","scrollTop","scrollLeft","addEventListener","ResizeObserver","setViewportResizeMetrics","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollWidth","scrollHeight","observe","unsubscribeScrollRequest","onScrollRequest","behavior","requestAnimationFrame","scrollTo","unregisterViewport","removeEventListener","setupViewport","onBeforeUnmount","props","__props","attrs","useAttrs","viewportProvides","viewportGap","vp","getViewportGap","viewportRef","_openBlock","_createElementBlock","_mergeProps","_unref","style","overflow","_renderSlot","_ctx","$slots","key","scrollActivity","isSmoothScrolling","isScrolling","onScrollActivity","activity"],"mappings":"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"}
1
+ {"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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"}
package/dist/vue/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ref, watch, toValue, onBeforeUnmount, defineComponent, useAttrs, createElementBlock, openBlock, mergeProps, unref, renderSlot, createCommentVNode } from "vue";
1
+ import { ref, watch, toValue, onBeforeUnmount, defineComponent, useAttrs, provide, createElementBlock, openBlock, mergeProps, unref, renderSlot, createCommentVNode } from "vue";
2
2
  import { useCapability, usePlugin } from "@embedpdf/core/vue";
3
3
  import { ViewportPlugin } from "@embedpdf/plugin-viewport";
4
4
  export * from "@embedpdf/plugin-viewport";
@@ -67,14 +67,6 @@ function useViewportRef(documentId) {
67
67
  console.error(`Failed to register viewport for document ${docId}:`, error);
68
68
  return;
69
69
  }
70
- const provideRect = () => {
71
- const r = container.getBoundingClientRect();
72
- return {
73
- origin: { x: r.left, y: r.top },
74
- size: { width: r.width, height: r.height }
75
- };
76
- };
77
- viewportPlugin.registerBoundingRectProvider(docId, provideRect);
78
70
  const onScroll = () => {
79
71
  viewportPlugin.setViewportScrollMetrics(docId, {
80
72
  scrollTop: container.scrollTop,
@@ -91,7 +83,9 @@ function useViewportRef(documentId) {
91
83
  scrollTop: container.scrollTop,
92
84
  scrollLeft: container.scrollLeft,
93
85
  scrollWidth: container.scrollWidth,
94
- scrollHeight: container.scrollHeight
86
+ scrollHeight: container.scrollHeight,
87
+ clientLeft: container.clientLeft,
88
+ clientTop: container.clientTop
95
89
  });
96
90
  });
97
91
  resizeObserver.observe(container);
@@ -105,7 +99,6 @@ function useViewportRef(documentId) {
105
99
  );
106
100
  return () => {
107
101
  viewportPlugin.unregisterViewport(docId);
108
- viewportPlugin.registerBoundingRectProvider(docId, null);
109
102
  container.removeEventListener("scroll", onScroll);
110
103
  unsubscribeScrollRequest();
111
104
  };
@@ -148,6 +141,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
148
141
  );
149
142
  const isGated = useIsViewportGated(() => props.documentId);
150
143
  const viewportRef = useViewportRef(() => props.documentId);
144
+ provide("viewport-element", viewportRef);
151
145
  return (_ctx, _cache) => {
152
146
  return openBlock(), createElementBlock("div", mergeProps({
153
147
  ref_key: "viewportRef",
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","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 // Provide rect calculator\n const provideRect = (): Rect => {\n const r = container.getBoundingClientRect();\n return {\n origin: { x: r.left, y: r.top },\n size: { width: r.width, height: r.height },\n };\n };\n viewportPlugin.registerBoundingRectProvider(docId, provideRect);\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 });\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 viewportPlugin.registerBoundingRectProvider(docId, null);\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 } 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</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":["_openBlock","_createElementBlock","_mergeProps","_unref","_renderSlot"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","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":["_openBlock","_createElementBlock","_mergeProps","_unref","_renderSlot"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-viewport",
3
- "version": "2.0.0-next.3",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.cjs",
@@ -35,13 +35,13 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@embedpdf/models": "2.0.0-next.3"
38
+ "@embedpdf/models": "2.0.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/react": "^18.2.0",
42
42
  "typescript": "^5.0.0",
43
- "@embedpdf/core": "2.0.0-next.3",
44
- "@embedpdf/build": "1.1.0"
43
+ "@embedpdf/build": "1.1.0",
44
+ "@embedpdf/core": "2.0.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "react": ">=16.8.0",
@@ -49,7 +49,7 @@
49
49
  "preact": "^10.26.4",
50
50
  "vue": ">=3.2.0",
51
51
  "svelte": ">=5 <6",
52
- "@embedpdf/core": "2.0.0-next.3"
52
+ "@embedpdf/core": "2.0.0"
53
53
  },
54
54
  "files": [
55
55
  "dist",