@embedpdf/plugin-thumbnail 1.5.0 → 2.0.0-next.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 (36) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +316 -84
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/actions.d.ts +43 -0
  6. package/dist/lib/index.d.ts +5 -2
  7. package/dist/lib/reducer.d.ts +6 -0
  8. package/dist/lib/thumbnail-plugin.d.ts +19 -17
  9. package/dist/lib/types.d.ts +38 -2
  10. package/dist/preact/index.cjs +1 -1
  11. package/dist/preact/index.cjs.map +1 -1
  12. package/dist/preact/index.js +39 -18
  13. package/dist/preact/index.js.map +1 -1
  14. package/dist/react/index.cjs +1 -1
  15. package/dist/react/index.cjs.map +1 -1
  16. package/dist/react/index.js +39 -18
  17. package/dist/react/index.js.map +1 -1
  18. package/dist/shared/components/thumbnail-img.d.ts +5 -1
  19. package/dist/shared/components/thumbnails-pane.d.ts +6 -7
  20. package/dist/shared-preact/components/thumbnail-img.d.ts +5 -1
  21. package/dist/shared-preact/components/thumbnails-pane.d.ts +6 -7
  22. package/dist/shared-react/components/thumbnail-img.d.ts +5 -1
  23. package/dist/shared-react/components/thumbnails-pane.d.ts +6 -7
  24. package/dist/svelte/components/ThumbImg.svelte.d.ts +4 -0
  25. package/dist/svelte/components/ThumbnailsPane.svelte.d.ts +4 -0
  26. package/dist/svelte/index.cjs +1 -1
  27. package/dist/svelte/index.cjs.map +1 -1
  28. package/dist/svelte/index.js +44 -25
  29. package/dist/svelte/index.js.map +1 -1
  30. package/dist/vue/components/thumbnail-img.vue.d.ts +8 -3
  31. package/dist/vue/components/thumbnails-pane.vue.d.ts +9 -2
  32. package/dist/vue/index.cjs +1 -1
  33. package/dist/vue/index.cjs.map +1 -1
  34. package/dist/vue/index.js +135 -79
  35. package/dist/vue/index.js.map +1 -1
  36. package/package.json +7 -7
@@ -1,8 +1,12 @@
1
1
  import { HTMLAttributes, CSSProperties } from '../../react/adapter.ts';
2
2
  import { ThumbMeta } from '../../index.ts';
3
3
  type ThumbnailImgProps = Omit<HTMLAttributes<HTMLImageElement>, 'style'> & {
4
+ /**
5
+ * The ID of the document that this thumbnail belongs to
6
+ */
7
+ documentId: string;
4
8
  style?: CSSProperties;
5
9
  meta: ThumbMeta;
6
10
  };
7
- export declare function ThumbImg({ meta, style, ...props }: ThumbnailImgProps): import("react/jsx-runtime").JSX.Element | null;
11
+ export declare function ThumbImg({ documentId, meta, style, ...props }: ThumbnailImgProps): import("react/jsx-runtime").JSX.Element | null;
8
12
  export {};
@@ -1,12 +1,11 @@
1
1
  import { HTMLAttributes, CSSProperties, ReactNode } from '../../react/adapter.ts';
2
- import { ThumbMeta } from '../../index.ts';
3
2
  type ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {
3
+ /**
4
+ * The ID of the document that this thumbnail pane displays
5
+ */
6
+ documentId: string;
4
7
  style?: CSSProperties;
5
- children: (m: ThumbMeta) => ReactNode;
6
- /** @deprecated use scrollToThumb via capability or rely on autoScroll */
7
- selectedPage?: number;
8
- /** @deprecated behavior is now controlled by ThumbnailPluginConfig.scrollBehavior */
9
- scrollOptions?: ScrollIntoViewOptions;
8
+ children: (m: any) => ReactNode;
10
9
  };
11
- export declare function ThumbnailsPane({ style, scrollOptions, selectedPage, ...props }: ThumbnailsProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function ThumbnailsPane({ documentId, style, children, ...props }: ThumbnailsProps): import("react/jsx-runtime").JSX.Element;
12
11
  export {};
@@ -1,8 +1,12 @@
1
1
  import { HTMLAttributes, CSSProperties } from '../../preact/adapter.ts';
2
2
  import { ThumbMeta } from '../../lib/index.ts';
3
3
  type ThumbnailImgProps = Omit<HTMLAttributes<HTMLImageElement>, 'style'> & {
4
+ /**
5
+ * The ID of the document that this thumbnail belongs to
6
+ */
7
+ documentId: string;
4
8
  style?: CSSProperties;
5
9
  meta: ThumbMeta;
6
10
  };
7
- export declare function ThumbImg({ meta, style, ...props }: ThumbnailImgProps): import("preact").JSX.Element | null;
11
+ export declare function ThumbImg({ documentId, meta, style, ...props }: ThumbnailImgProps): import("preact").JSX.Element | null;
8
12
  export {};
@@ -1,12 +1,11 @@
1
1
  import { HTMLAttributes, CSSProperties, ReactNode } from '../../preact/adapter.ts';
2
- import { ThumbMeta } from '../../lib/index.ts';
3
2
  type ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {
3
+ /**
4
+ * The ID of the document that this thumbnail pane displays
5
+ */
6
+ documentId: string;
4
7
  style?: CSSProperties;
5
- children: (m: ThumbMeta) => ReactNode;
6
- /** @deprecated use scrollToThumb via capability or rely on autoScroll */
7
- selectedPage?: number;
8
- /** @deprecated behavior is now controlled by ThumbnailPluginConfig.scrollBehavior */
9
- scrollOptions?: ScrollIntoViewOptions;
8
+ children: (m: any) => ReactNode;
10
9
  };
11
- export declare function ThumbnailsPane({ style, scrollOptions, selectedPage, ...props }: ThumbnailsProps): import("preact").JSX.Element;
10
+ export declare function ThumbnailsPane({ documentId, style, children, ...props }: ThumbnailsProps): import("preact").JSX.Element;
12
11
  export {};
@@ -1,8 +1,12 @@
1
1
  import { HTMLAttributes, CSSProperties } from '../../react/adapter.ts';
2
2
  import { ThumbMeta } from '../../lib/index.ts';
3
3
  type ThumbnailImgProps = Omit<HTMLAttributes<HTMLImageElement>, 'style'> & {
4
+ /**
5
+ * The ID of the document that this thumbnail belongs to
6
+ */
7
+ documentId: string;
4
8
  style?: CSSProperties;
5
9
  meta: ThumbMeta;
6
10
  };
7
- export declare function ThumbImg({ meta, style, ...props }: ThumbnailImgProps): import("react/jsx-runtime").JSX.Element | null;
11
+ export declare function ThumbImg({ documentId, meta, style, ...props }: ThumbnailImgProps): import("react/jsx-runtime").JSX.Element | null;
8
12
  export {};
@@ -1,12 +1,11 @@
1
1
  import { HTMLAttributes, CSSProperties, ReactNode } from '../../react/adapter.ts';
2
- import { ThumbMeta } from '../../lib/index.ts';
3
2
  type ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {
3
+ /**
4
+ * The ID of the document that this thumbnail pane displays
5
+ */
6
+ documentId: string;
4
7
  style?: CSSProperties;
5
- children: (m: ThumbMeta) => ReactNode;
6
- /** @deprecated use scrollToThumb via capability or rely on autoScroll */
7
- selectedPage?: number;
8
- /** @deprecated behavior is now controlled by ThumbnailPluginConfig.scrollBehavior */
9
- scrollOptions?: ScrollIntoViewOptions;
8
+ children: (m: any) => ReactNode;
10
9
  };
11
- export declare function ThumbnailsPane({ style, scrollOptions, selectedPage, ...props }: ThumbnailsProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function ThumbnailsPane({ documentId, style, children, ...props }: ThumbnailsProps): import("react/jsx-runtime").JSX.Element;
12
11
  export {};
@@ -1,6 +1,10 @@
1
1
  import { ThumbMeta } from '../../lib/index.ts';
2
2
  import { HTMLImgAttributes } from 'svelte/elements';
3
3
  interface Props extends HTMLImgAttributes {
4
+ /**
5
+ * The ID of the document that this thumbnail belongs to
6
+ */
7
+ documentId: string;
4
8
  meta: ThumbMeta;
5
9
  }
6
10
  declare const ThumbImg: import('svelte', { with: { "resolution-mode": "import" } }).Component<Props, {}, "">;
@@ -2,6 +2,10 @@ import { Snippet } from 'svelte';
2
2
  import { ThumbMeta } from '../../lib/index.ts';
3
3
  import { HTMLAttributes } from 'svelte/elements';
4
4
  interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
5
+ /**
6
+ * The ID of the document that this thumbnail pane displays
7
+ */
8
+ documentId: string;
5
9
  children: Snippet<[ThumbMeta]>;
6
10
  }
7
11
  declare const ThumbnailsPane: import('svelte', { with: { "resolution-mode": "import" } }).Component<Props, {}, "">;
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("svelte/internal/client"),t=require("@embedpdf/core/svelte"),n=require("@embedpdf/plugin-thumbnail");require("svelte/internal/disclose-version");const r=require("@embedpdf/models");function i(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const n in e)if("default"!==n){const r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:()=>e[n]})}return t.default=e,Object.freeze(t)}const l=i(e),o=()=>t.usePlugin(n.ThumbnailPlugin.id),s=()=>t.useCapability(n.ThumbnailPlugin.id);var u=l.from_html("<img/>");var a=l.from_html("<div><div></div></div>");exports.ThumbImg=function(e,t){l.push(t,!0);const n=l.rest_props(t,["$$slots","$$events","$$legacy","meta"]),i=s(),a=o();let c=l.state(void 0),p=null,d=l.state(0);l.user_effect((()=>{if(a.plugin)return a.plugin.onRefreshPages((e=>{e.includes(t.meta.pageIndex)&&l.set(d,l.get(d)+1)}))})),l.user_effect((()=>{var e;const n=null==(e=i.provides)?void 0:e.renderThumb(t.meta.pageIndex,window.devicePixelRatio);return null==n||n.wait((e=>{const t=URL.createObjectURL(e);p=t,l.set(c,t,!0)}),r.ignore),()=>{p?(URL.revokeObjectURL(p),p=null):null==n||n.abort({code:r.PdfErrorCode.Cancelled,message:"canceled render task"})}}));const g=()=>{p&&(URL.revokeObjectURL(p),p=null)};var f=l.comment(),v=l.first_child(f),b=e=>{var t=u();l.attribute_effect(t,(()=>({src:l.get(c),onload:g,...n,alt:"PDF thumbnail"}))),l.replay_events(t),l.append(e,t)};l.if(v,(e=>{l.get(c)&&e(b)})),l.append(e,f),l.pop()},exports.ThumbnailsPane=function(e,t){l.push(t,!0);const n=l.rest_props(t,["$$slots","$$events","$$legacy","children"]),r=o();let i,s=l.state(null);l.user_effect((()=>{if(r.plugin)return r.plugin.onWindow((e=>{l.set(s,e,!0)}))})),l.user_effect((()=>{const e=i;if(!e||!r.plugin)return;const t=()=>{r.plugin.updateWindow(e.scrollTop,e.clientHeight)};return e.addEventListener("scroll",t),()=>e.removeEventListener("scroll",t)})),l.user_effect((()=>{const e=i;if(!e||!r.plugin)return;const t=new ResizeObserver((()=>{r.plugin.updateWindow(e.scrollTop,e.clientHeight)}));return t.observe(e),()=>t.disconnect()})),l.user_effect((()=>{const e=i;e&&r.plugin&&l.get(s)&&r.plugin.updateWindow(e.scrollTop,e.clientHeight)})),l.user_effect((()=>{const e=i;if(e&&r.plugin&&l.get(s))return r.plugin.onScrollTo((({top:t,behavior:n})=>{e.scrollTo({top:t,behavior:n})}))}));const u=l.derived((()=>{var e;return(null==(e=null==r?void 0:r.plugin)?void 0:e.cfg.paddingY)??0})),c=l.derived((()=>{var e;return(null==(e=l.get(s))?void 0:e.totalHeight)??0})),p=l.derived((()=>{var e;return(null==(e=l.get(s))?void 0:e.items)??[]}));var d=a();l.attribute_effect(d,(e=>({...n,[l.STYLE]:e})),[()=>({"overflow-y":"auto",position:"relative","padding-top":`${l.get(u)??""}px`,"padding-bottom":`${l.get(u)??""}px`,height:"100%"})]);var g=l.child(d);let f;l.each(g,21,(()=>l.get(p)),(e=>e.pageIndex),((e,n)=>{var r=l.comment(),i=l.first_child(r);l.snippet(i,(()=>t.children),(()=>l.get(n))),l.append(e,r)})),l.reset(g),l.reset(d),l.bind_this(d,(e=>i=e),(()=>i)),l.template_effect((e=>f=l.set_style(g,"",f,e)),[()=>({height:`${l.get(c)??""}px`,position:"relative"})]),l.append(e,d),l.pop()},exports.useThumbnailCapability=s,exports.useThumbnailPlugin=o,Object.keys(n).forEach((e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>n[e]})}));
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("svelte/internal/client"),t=require("@embedpdf/core/svelte"),n=require("@embedpdf/plugin-thumbnail");require("svelte/internal/disclose-version");const o=require("@embedpdf/models");function r(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const n in e)if("default"!==n){const o=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,o.get?o:{enumerable:!0,get:()=>e[n]})}return t.default=e,Object.freeze(t)}const i=r(e),d=()=>t.usePlugin(n.ThumbnailPlugin.id),l=()=>t.useCapability(n.ThumbnailPlugin.id);var u=i.from_html("<img/>");var s=i.from_html("<div><div></div></div>");exports.ThumbImg=function(e,t){i.push(t,!0);const n=i.rest_props(t,["$$slots","$$events","$$legacy","documentId","meta"]),r=l(),s=d();let c=i.state(void 0),p=null,a=i.state(0);i.user_effect(()=>{if(!s.plugin)return;return s.plugin.provides().forDocument(t.documentId).onRefreshPages(e=>{e.includes(t.meta.pageIndex)&&i.set(a,i.get(a)+1)})}),i.user_effect(()=>{if(i.get(a),!r.provides)return;const e=r.provides.forDocument(t.documentId).renderThumb(t.meta.pageIndex,window.devicePixelRatio);return e.wait(e=>{const t=URL.createObjectURL(e);p=t,i.set(c,t,!0)},o.ignore),()=>{p?(URL.revokeObjectURL(p),p=null):e.abort({code:o.PdfErrorCode.Cancelled,message:"canceled render task"})}});const g=()=>{p&&(URL.revokeObjectURL(p),p=null)};var f=i.comment(),m=i.first_child(f),v=e=>{var t=u();i.attribute_effect(t,()=>({src:i.get(c),onload:g,...n,alt:"PDF thumbnail"})),i.replay_events(t),i.append(e,t)};i.if(m,e=>{i.get(c)&&e(v)}),i.append(e,f),i.pop()},exports.ThumbnailsPane=function(e,t){i.push(t,!0);const n=i.rest_props(t,["$$slots","$$events","$$legacy","documentId","children"]),o=d();let r,l=i.state(i.proxy({window:null,docId:null}));const u=i.derived(()=>i.get(l).docId===t.documentId?i.get(l).window:null);i.user_effect(()=>{if(!o.plugin)return void i.set(l,{window:null,docId:null},!0);const e=o.plugin.provides().forDocument(t.documentId),n=e.getWindow();n&&i.set(l,{window:n,docId:t.documentId},!0);const r=e.onWindow(e=>{i.set(l,{window:e,docId:t.documentId},!0)});return()=>{r(),i.set(l,{window:null,docId:null},!0)}}),i.user_effect(()=>{const e=r;if(!e||!o.plugin)return;const n=o.plugin.provides().forDocument(t.documentId),i=()=>{n.updateWindow(e.scrollTop,e.clientHeight)};return e.addEventListener("scroll",i),()=>e.removeEventListener("scroll",i)}),i.user_effect(()=>{const e=r;if(!e||!o.plugin)return;const n=o.plugin.provides().forDocument(t.documentId),i=new ResizeObserver(()=>{n.updateWindow(e.scrollTop,e.clientHeight)});return i.observe(e),()=>i.disconnect()}),i.user_effect(()=>{const e=r;if(!e||!o.plugin||!i.get(u))return;o.plugin.provides().forDocument(t.documentId).updateWindow(e.scrollTop,e.clientHeight)}),i.user_effect(()=>{const e=r;if(!e||!o.plugin||!i.get(u))return;return o.plugin.provides().forDocument(t.documentId).onScrollTo(({top:t,behavior:n})=>{e.scrollTo({top:t,behavior:n})})});const c=i.derived(()=>{var e;return(null==(e=null==o?void 0:o.plugin)?void 0:e.cfg.paddingY)??0}),p=i.derived(()=>{var e;return(null==(e=i.get(u))?void 0:e.totalHeight)??0}),a=i.derived(()=>{var e;return(null==(e=i.get(u))?void 0:e.items)??[]});var g=s();i.attribute_effect(g,()=>({...n,[i.STYLE]:{"overflow-y":"auto",position:"relative","padding-top":`${i.get(c)??""}px`,"padding-bottom":`${i.get(c)??""}px`,height:"100%"}}));var f=i.child(g);let m;i.each(f,21,()=>i.get(a),e=>e.pageIndex,(e,n)=>{var o=i.comment(),r=i.first_child(o);i.snippet(r,()=>t.children,()=>i.get(n)),i.append(e,o)}),i.reset(f),i.reset(g),i.bind_this(g,e=>r=e,()=>r),i.template_effect(()=>m=i.set_style(f,"",m,{height:`${i.get(p)??""}px`,position:"relative"})),i.append(e,g),i.pop()},exports.useThumbnailCapability=l,exports.useThumbnailPlugin=d,Object.keys(n).forEach(e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>n[e]})});
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/svelte/hooks/use-thumbnail.svelte.ts","../../src/svelte/components/ThumbImg.svelte","../../src/svelte/components/ThumbnailsPane.svelte"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/svelte';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","<script lang=\"ts\">\n import type { ThumbMeta } from '@embedpdf/plugin-thumbnail';\n import { ignore, PdfErrorCode } from '@embedpdf/models';\n import { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\n import type { HTMLImgAttributes } from 'svelte/elements';\n\n interface Props extends HTMLImgAttributes {\n meta: ThumbMeta;\n }\n\n const { meta, ...imgProps }: Props = $props();\n\n const thumbnailCapability = useThumbnailCapability();\n const thumbnailPlugin = useThumbnailPlugin();\n\n let url = $state<string | undefined>(undefined);\n let urlRef: string | null = null;\n let refreshTick = $state(0);\n\n // Listen for refresh events\n $effect(() => {\n if (!thumbnailPlugin.plugin) return;\n return thumbnailPlugin.plugin.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n refreshTick = refreshTick + 1;\n }\n });\n });\n\n // Render thumbnail\n $effect(() => {\n const task = thumbnailCapability.provides?.renderThumb(meta.pageIndex, window.devicePixelRatio);\n task?.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef = objectUrl;\n url = objectUrl;\n }, ignore);\n\n return () => {\n if (urlRef) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n } else {\n task?.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n };\n });\n\n const handleImageLoad = () => {\n if (urlRef) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n }\n };\n</script>\n\n{#if url}\n <img src={url} onload={handleImageLoad} {...imgProps} alt=\"PDF thumbnail\" />\n{/if}\n","<script lang=\"ts\">\n import type { Snippet } from 'svelte';\n import type { ThumbMeta, WindowState } from '@embedpdf/plugin-thumbnail';\n import { useThumbnailPlugin } from '../hooks';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {\n children: Snippet<[ThumbMeta]>;\n }\n\n const { children, ...divProps }: Props = $props();\n\n const thumbnailPlugin = useThumbnailPlugin();\n\n let viewportRef: HTMLDivElement | undefined;\n let window = $state<WindowState | null>(null);\n\n // 1) subscribe once to window updates\n $effect(() => {\n if (!thumbnailPlugin.plugin) return;\n return thumbnailPlugin.plugin.onWindow((newWindow) => {\n window = newWindow;\n });\n });\n\n // 2) keep plugin in sync while the user scrolls\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin) return;\n\n const onScroll = () => {\n thumbnailPlugin.plugin.updateWindow(vp.scrollTop, vp.clientHeight);\n };\n\n vp.addEventListener('scroll', onScroll);\n return () => vp.removeEventListener('scroll', onScroll);\n });\n\n // 2.5) keep plugin in sync when viewport resizes (e.g., menu opens/closes)\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin) return;\n\n const resizeObserver = new ResizeObserver(() => {\n thumbnailPlugin.plugin.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n\n resizeObserver.observe(vp);\n return () => resizeObserver.disconnect();\n });\n\n // 3) kick-start after document change\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin || !window) return;\n\n // push initial metrics\n thumbnailPlugin.plugin.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n\n // 4) let plugin drive scroll – only after window is set, and only once\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin || !window) return;\n\n return thumbnailPlugin.plugin.onScrollTo(({ top, behavior }) => {\n vp.scrollTo({ top, behavior });\n });\n });\n\n const paddingY = $derived(thumbnailPlugin?.plugin?.cfg.paddingY ?? 0);\n const totalHeight = $derived(window?.totalHeight ?? 0);\n const items = $derived(window?.items ?? []);\n</script>\n\n<div\n bind:this={viewportRef}\n style:overflow-y=\"auto\"\n style:position=\"relative\"\n style:padding-top=\"{paddingY}px\"\n style:padding-bottom=\"{paddingY}px\"\n style:height=\"100%\"\n {...divProps}\n>\n <div style:height=\"{totalHeight}px\" style:position=\"relative\">\n {#each items as meta (meta.pageIndex)}\n {@render children(meta)}\n {/each}\n </div>\n</div>\n"],"names":["useThumbnailPlugin","usePlugin","ThumbnailPlugin","id","useThumbnailCapability","useCapability","imgProps","$","rest_props","$$props","thumbnailCapability","thumbnailPlugin","url","urlRef","refreshTick","user_effect","plugin","onRefreshPages","pages","includes","meta","pageIndex","get","task","_a","provides","renderThumb","window","devicePixelRatio","wait","blob","objectUrl","URL","createObjectURL","$__namespace","set","ignore","revokeObjectURL","abort","code","PdfErrorCode","Cancelled","message","handleImageLoad","consequent","divProps","viewportRef","onWindow","newWindow","vp","onScroll","updateWindow","scrollTop","clientHeight","addEventListener","removeEventListener","resizeObserver","ResizeObserver","observe","disconnect","onScrollTo","top","behavior","scrollTo","paddingY","derived","cfg","totalHeight","items","STYLE","$0","each","div_1","bind_this","div","$$value"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/svelte/hooks/use-thumbnail.svelte.ts","../../src/svelte/components/ThumbImg.svelte","../../src/svelte/components/ThumbnailsPane.svelte"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/svelte';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","<script lang=\"ts\">\n import type { ThumbMeta } from '@embedpdf/plugin-thumbnail';\n import { ignore, PdfErrorCode } from '@embedpdf/models';\n import { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\n import type { HTMLImgAttributes } from 'svelte/elements';\n\n interface Props extends HTMLImgAttributes {\n /**\n * The ID of the document that this thumbnail belongs to\n */\n documentId: string;\n meta: ThumbMeta;\n }\n\n const { documentId, meta, ...imgProps }: Props = $props();\n\n const thumbnailCapability = useThumbnailCapability();\n const thumbnailPlugin = useThumbnailPlugin();\n\n let url = $state<string | undefined>(undefined);\n let urlRef: string | null = null;\n let refreshTick = $state(0);\n\n // Listen for refresh events for this specific document\n $effect(() => {\n if (!thumbnailPlugin.plugin) return;\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n return scope.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n refreshTick = refreshTick + 1;\n }\n });\n });\n\n // Render thumbnail for this specific document\n $effect(() => {\n // Track refreshTick so effect re-runs on refresh\n const _tick = refreshTick;\n\n if (!thumbnailCapability.provides) return;\n\n const scope = thumbnailCapability.provides.forDocument(documentId);\n const task = scope.renderThumb(meta.pageIndex, window.devicePixelRatio);\n\n task.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef = objectUrl;\n url = objectUrl;\n }, ignore);\n\n return () => {\n if (urlRef) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n } else {\n task.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n };\n });\n\n const handleImageLoad = () => {\n if (urlRef) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n }\n };\n</script>\n\n{#if url}\n <img src={url} onload={handleImageLoad} {...imgProps} alt=\"PDF thumbnail\" />\n{/if}\n","<script lang=\"ts\">\n import type { Snippet } from 'svelte';\n import type { ThumbMeta, WindowState } from '@embedpdf/plugin-thumbnail';\n import { useThumbnailPlugin } from '../hooks';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {\n /**\n * The ID of the document that this thumbnail pane displays\n */\n documentId: string;\n children: Snippet<[ThumbMeta]>;\n }\n\n const { documentId, children, ...divProps }: Props = $props();\n\n const thumbnailPlugin = useThumbnailPlugin();\n\n let viewportRef: HTMLDivElement | undefined;\n\n // Store window data along with the documentId it came from\n let windowData = $state<{\n window: WindowState | null;\n docId: string | null;\n }>({ window: null, docId: null });\n\n // Only use the window if it matches the current documentId\n const window = $derived(windowData.docId === documentId ? windowData.window : null);\n\n // 1) subscribe to window updates for this document\n $effect(() => {\n if (!thumbnailPlugin.plugin) {\n windowData = { window: null, docId: null };\n return;\n }\n\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n\n // Get initial window state immediately on mount\n const initialWindow = scope.getWindow();\n if (initialWindow) {\n windowData = { window: initialWindow, docId: documentId };\n }\n\n // Subscribe to future updates\n const unsubscribe = scope.onWindow((newWindow) => {\n windowData = { window: newWindow, docId: documentId };\n });\n\n // Clear state when documentId changes or component unmounts\n return () => {\n unsubscribe();\n windowData = { window: null, docId: null };\n };\n });\n\n // 2) keep plugin in sync while the user scrolls\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin) return;\n\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n const onScroll = () => {\n scope.updateWindow(vp.scrollTop, vp.clientHeight);\n };\n\n vp.addEventListener('scroll', onScroll);\n return () => vp.removeEventListener('scroll', onScroll);\n });\n\n // 2.5) keep plugin in sync when viewport resizes (e.g., menu opens/closes)\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin) return;\n\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n const resizeObserver = new ResizeObserver(() => {\n scope.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n\n resizeObserver.observe(vp);\n return () => resizeObserver.disconnect();\n });\n\n // 3) kick-start after document change\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin || !window) return;\n\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n // push initial metrics\n scope.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n\n // 4) let plugin drive scroll – only after window is set, and only once\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin || !window) return;\n\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n return scope.onScrollTo(({ top, behavior }) => {\n vp.scrollTo({ top, behavior });\n });\n });\n\n const paddingY = $derived(thumbnailPlugin?.plugin?.cfg.paddingY ?? 0);\n const totalHeight = $derived(window?.totalHeight ?? 0);\n const items = $derived(window?.items ?? []);\n</script>\n\n<div\n bind:this={viewportRef}\n style:overflow-y=\"auto\"\n style:position=\"relative\"\n style:padding-top=\"{paddingY}px\"\n style:padding-bottom=\"{paddingY}px\"\n style:height=\"100%\"\n {...divProps}\n>\n <div style:height=\"{totalHeight}px\" style:position=\"relative\">\n {#each items as meta (meta.pageIndex)}\n {@render children(meta)}\n {/each}\n </div>\n</div>\n"],"names":["useThumbnailPlugin","usePlugin","ThumbnailPlugin","id","useThumbnailCapability","useCapability","imgProps","$","rest_props","$$props","thumbnailCapability","thumbnailPlugin","url","urlRef","refreshTick","user_effect","plugin","provides","forDocument","documentId","onRefreshPages","pages","includes","meta","pageIndex","get","task","renderThumb","window","devicePixelRatio","wait","blob","objectUrl","URL","createObjectURL","set","ignore","revokeObjectURL","abort","code","PdfErrorCode","Cancelled","message","handleImageLoad","consequent","divProps","viewportRef","windowData","docId","derived","scope","initialWindow","getWindow","unsubscribe","onWindow","newWindow","vp","onScroll","updateWindow","scrollTop","clientHeight","addEventListener","removeEventListener","resizeObserver","ResizeObserver","observe","disconnect","onScrollTo","top","behavior","scrollTo","paddingY","_a","cfg","totalHeight","items","each","div_1","bind_this","div","$$value"],"mappings":"6iBAGaA,EAAA,IAA2BC,YAA2BC,EAAAA,gBAAgBC,IACtEC,EAAA,IAA+BC,gBAA+BH,EAAAA,gBAAgBC,8HCU5DG,EAAQC,EAAAC,WAAAC,EAAA,CAAA,UAAA,WAAA,WAAA,aAAA,SAE/BC,EAAsBN,IACtBO,EAAkBX,IAEpB,IAAAY,eAAiC,GACjCC,EAAwB,KACxBC,UAAqB,GAGzBP,EAAAQ,YAAO,KACA,IAAAJ,EAAgBK,OAAM,OAEpB,OADOL,EAAgBK,OAAOC,WAAWC,YAAWT,EAAAU,YAC9CC,eAAgBC,IACvBA,EAAMC,SAAQb,EAAAc,KAAMC,kBACtBV,EAAWP,EAAAkB,IAAGX,GAAc,OAMlCP,EAAAQ,YAAO,KAIA,SAFSD,IAETJ,EAAoBO,SAAQ,OAE3B,MACAS,EADQhB,EAAoBO,SAASC,YAAWT,EAAAU,YACnCQ,mBAAiBH,UAAWI,OAAOC,kBAQzC,OANbH,EAAKI,KAAMC,IACH,MAAAC,EAAYC,IAAIC,gBAAgBH,GACtClB,EAASmB,EACTzB,EAAA4B,IAAAvB,EAAMoB,GAAS,IACdI,EAAAA,QAEU,KACPvB,GACFoB,IAAII,gBAAgBxB,GACpBA,EAAS,MAETa,EAAKY,MAAK,CACRC,KAAMC,EAAAA,aAAaC,UACnBC,QAAS,4BAMX,MAAAC,EAAe,KACf9B,IACFoB,IAAII,gBAAgBxB,GACpBA,EAAS,iGAMHD,UAAa+B,KAAqBrC,4EADzCM,MAAGgC,0BAFR,0DCvDmCC,EAAQtC,EAAAC,WAAAC,EAAA,CAAA,UAAA,WAAA,WAAA,aAAA,aAEnCE,EAAkBX,QAEpB8C,EAGAC,mBAGCnB,OAAQ,KAAMoB,MAAO,cAGpBpB,EAAMrB,EAAA0C,QAAA,IAAA1C,EAAAkB,IAAYsB,GAAWC,2BAAuBD,GAAWnB,OAAS,MAG9ErB,EAAAQ,YAAO,SACAJ,EAAgBK,mBACnBT,EAAA4B,IAAAY,GAAenB,OAAQ,KAAMoB,MAAO,OAAI,GAIpC,MAAAE,EAAQvC,EAAgBK,OAAOC,WAAWC,YAAWT,EAAAU,YAGrDgC,EAAgBD,EAAME,YACxBD,GACF5C,EAAA4B,IAAAY,EAAU,CAAKnB,OAAQuB,EAAeH,MAAKvC,EAAAU,aAAA,GAIvC,MAAAkC,EAAcH,EAAMI,SAAUC,IAClChD,EAAA4B,IAAAY,EAAU,CAAKnB,OAAQ2B,EAAWP,MAAKvC,EAAAU,aAAA,KAI5B,MAAA,KACXkC,IACA9C,EAAA4B,IAAAY,GAAenB,OAAQ,KAAMoB,MAAO,OAAI,MAK5CzC,EAAAQ,YAAO,KACC,MAAAyC,EAAKV,MACNU,IAAO7C,EAAgBK,OAAM,OAE5B,MAAAkC,EAAQvC,EAAgBK,OAAOC,WAAWC,YAAWT,EAAAU,YACrDsC,EAAQ,KACZP,EAAMQ,aAAaF,EAAGG,UAAWH,EAAGI,eAIzB,OADbJ,EAAGK,iBAAiB,SAAUJ,GACjB,IAAAD,EAAGM,oBAAoB,SAAUL,KAIhDlD,EAAAQ,YAAO,KACC,MAAAyC,EAAKV,MACNU,IAAO7C,EAAgBK,OAAM,OAE5B,MAAAkC,EAAQvC,EAAgBK,OAAOC,WAAWC,YAAWT,EAAAU,YACrD4C,EAAc,IAAOC,eAAc,KACvCd,EAAMQ,aAAaF,EAAGG,UAAWH,EAAGI,gBAIzB,OADbG,EAAeE,QAAQT,GACV,IAAAO,EAAeG,eAI9B3D,EAAAQ,YAAO,KACC,MAAAyC,EAAKV,EACN,IAAAU,IAAO7C,EAAgBK,eAAWY,GAAM,OAE/BjB,EAAgBK,OAAOC,WAAWC,YAAWT,EAAAU,YAErDuC,aAAaF,EAAGG,UAAWH,EAAGI,gBAItCrD,EAAAQ,YAAO,KACC,MAAAyC,EAAKV,EACN,IAAAU,IAAO7C,EAAgBK,eAAWY,GAAM,OAGtC,OADOjB,EAAgBK,OAAOC,WAAWC,YAAWT,EAAAU,YAC9CgD,WAAU,EAAIC,MAAKC,eAC9Bb,EAAGc,SAAQ,CAAGF,MAAKC,uBAIjBE,EAAQhE,EAAA0C,QAAA,WAAY,OAAA,OAAAuB,EAAA,MAAA7D,OAAA,EAAAA,EAAiBK,aAAjB,EAAAwD,EAAyBC,IAAIF,WAAY,IAC7DG,EAAWnE,EAAA0C,QAAA,WAAA1C,OAAAA,OAAAA,EAAAA,EAAAkB,IAAYG,SAAZrB,EAAAA,EAAoBmE,cAAe,IAC9CC,EAAKpE,EAAA0C,QAAA,WAAA1C,OAAAA,OAAAA,EAAAA,EAAAkB,IAAYG,SAAZrB,EAAAA,EAAoBoE,QAAK,6CAUhC9B,4EAHgB0B,IAAQ,iCACLA,IAAQ,gDAKtBhE,EAAAqE,KAAAC,EAAA,GAAA,IAAAtE,EAAAkB,IAAAkD,GAASpD,GAAMA,EAAKC,aAAXD,+EACIA,0CAVXhB,EAAAuE,UAAAC,EAAAC,GAAAlC,QAAAA,+DAQS4B,IAAW,mDAXjC"}
@@ -9,7 +9,7 @@ const useThumbnailCapability = () => useCapability(ThumbnailPlugin.id);
9
9
  var root_1 = $.from_html(`<img/>`);
10
10
  function ThumbImg($$anchor, $$props) {
11
11
  $.push($$props, true);
12
- const imgProps = $.rest_props($$props, ["$$slots", "$$events", "$$legacy", "meta"]);
12
+ const imgProps = $.rest_props($$props, ["$$slots", "$$events", "$$legacy", "documentId", "meta"]);
13
13
  const thumbnailCapability = useThumbnailCapability();
14
14
  const thumbnailPlugin = useThumbnailPlugin();
15
15
  let url = $.state(void 0);
@@ -17,16 +17,19 @@ function ThumbImg($$anchor, $$props) {
17
17
  let refreshTick = $.state(0);
18
18
  $.user_effect(() => {
19
19
  if (!thumbnailPlugin.plugin) return;
20
- return thumbnailPlugin.plugin.onRefreshPages((pages) => {
20
+ const scope = thumbnailPlugin.plugin.provides().forDocument($$props.documentId);
21
+ return scope.onRefreshPages((pages) => {
21
22
  if (pages.includes($$props.meta.pageIndex)) {
22
23
  $.set(refreshTick, $.get(refreshTick) + 1);
23
24
  }
24
25
  });
25
26
  });
26
27
  $.user_effect(() => {
27
- var _a;
28
- const task = (_a = thumbnailCapability.provides) == null ? void 0 : _a.renderThumb($$props.meta.pageIndex, window.devicePixelRatio);
29
- task == null ? void 0 : task.wait(
28
+ $.get(refreshTick);
29
+ if (!thumbnailCapability.provides) return;
30
+ const scope = thumbnailCapability.provides.forDocument($$props.documentId);
31
+ const task = scope.renderThumb($$props.meta.pageIndex, window.devicePixelRatio);
32
+ task.wait(
30
33
  (blob) => {
31
34
  const objectUrl = URL.createObjectURL(blob);
32
35
  urlRef = objectUrl;
@@ -39,7 +42,7 @@ function ThumbImg($$anchor, $$props) {
39
42
  URL.revokeObjectURL(urlRef);
40
43
  urlRef = null;
41
44
  } else {
42
- task == null ? void 0 : task.abort({
45
+ task.abort({
43
46
  code: PdfErrorCode.Cancelled,
44
47
  message: "canceled render task"
45
48
  });
@@ -76,21 +79,35 @@ function ThumbImg($$anchor, $$props) {
76
79
  var root = $.from_html(`<div><div></div></div>`);
77
80
  function ThumbnailsPane($$anchor, $$props) {
78
81
  $.push($$props, true);
79
- const divProps = $.rest_props($$props, ["$$slots", "$$events", "$$legacy", "children"]);
82
+ const divProps = $.rest_props($$props, ["$$slots", "$$events", "$$legacy", "documentId", "children"]);
80
83
  const thumbnailPlugin = useThumbnailPlugin();
81
84
  let viewportRef;
82
- let window2 = $.state(null);
85
+ let windowData = $.state($.proxy({ window: null, docId: null }));
86
+ const window2 = $.derived(() => $.get(windowData).docId === $$props.documentId ? $.get(windowData).window : null);
83
87
  $.user_effect(() => {
84
- if (!thumbnailPlugin.plugin) return;
85
- return thumbnailPlugin.plugin.onWindow((newWindow) => {
86
- $.set(window2, newWindow, true);
88
+ if (!thumbnailPlugin.plugin) {
89
+ $.set(windowData, { window: null, docId: null }, true);
90
+ return;
91
+ }
92
+ const scope = thumbnailPlugin.plugin.provides().forDocument($$props.documentId);
93
+ const initialWindow = scope.getWindow();
94
+ if (initialWindow) {
95
+ $.set(windowData, { window: initialWindow, docId: $$props.documentId }, true);
96
+ }
97
+ const unsubscribe = scope.onWindow((newWindow) => {
98
+ $.set(windowData, { window: newWindow, docId: $$props.documentId }, true);
87
99
  });
100
+ return () => {
101
+ unsubscribe();
102
+ $.set(windowData, { window: null, docId: null }, true);
103
+ };
88
104
  });
89
105
  $.user_effect(() => {
90
106
  const vp = viewportRef;
91
107
  if (!vp || !thumbnailPlugin.plugin) return;
108
+ const scope = thumbnailPlugin.plugin.provides().forDocument($$props.documentId);
92
109
  const onScroll = () => {
93
- thumbnailPlugin.plugin.updateWindow(vp.scrollTop, vp.clientHeight);
110
+ scope.updateWindow(vp.scrollTop, vp.clientHeight);
94
111
  };
95
112
  vp.addEventListener("scroll", onScroll);
96
113
  return () => vp.removeEventListener("scroll", onScroll);
@@ -98,8 +115,9 @@ function ThumbnailsPane($$anchor, $$props) {
98
115
  $.user_effect(() => {
99
116
  const vp = viewportRef;
100
117
  if (!vp || !thumbnailPlugin.plugin) return;
118
+ const scope = thumbnailPlugin.plugin.provides().forDocument($$props.documentId);
101
119
  const resizeObserver = new ResizeObserver(() => {
102
- thumbnailPlugin.plugin.updateWindow(vp.scrollTop, vp.clientHeight);
120
+ scope.updateWindow(vp.scrollTop, vp.clientHeight);
103
121
  });
104
122
  resizeObserver.observe(vp);
105
123
  return () => resizeObserver.disconnect();
@@ -107,12 +125,14 @@ function ThumbnailsPane($$anchor, $$props) {
107
125
  $.user_effect(() => {
108
126
  const vp = viewportRef;
109
127
  if (!vp || !thumbnailPlugin.plugin || !$.get(window2)) return;
110
- thumbnailPlugin.plugin.updateWindow(vp.scrollTop, vp.clientHeight);
128
+ const scope = thumbnailPlugin.plugin.provides().forDocument($$props.documentId);
129
+ scope.updateWindow(vp.scrollTop, vp.clientHeight);
111
130
  });
112
131
  $.user_effect(() => {
113
132
  const vp = viewportRef;
114
133
  if (!vp || !thumbnailPlugin.plugin || !$.get(window2)) return;
115
- return thumbnailPlugin.plugin.onScrollTo(({ top, behavior }) => {
134
+ const scope = thumbnailPlugin.plugin.provides().forDocument($$props.documentId);
135
+ return scope.onScrollTo(({ top, behavior }) => {
116
136
  vp.scrollTo({ top, behavior });
117
137
  });
118
138
  });
@@ -129,15 +149,16 @@ function ThumbnailsPane($$anchor, $$props) {
129
149
  return ((_a = $.get(window2)) == null ? void 0 : _a.items) ?? [];
130
150
  });
131
151
  var div = root();
132
- $.attribute_effect(div, ($0) => ({ ...divProps, [$.STYLE]: $0 }), [
133
- () => ({
152
+ $.attribute_effect(div, () => ({
153
+ ...divProps,
154
+ [$.STYLE]: {
134
155
  "overflow-y": "auto",
135
156
  position: "relative",
136
157
  "padding-top": `${$.get(paddingY) ?? ""}px`,
137
158
  "padding-bottom": `${$.get(paddingY) ?? ""}px`,
138
159
  height: "100%"
139
- })
140
- ]);
160
+ }
161
+ }));
141
162
  var div_1 = $.child(div);
142
163
  let styles;
143
164
  $.each(div_1, 21, () => $.get(items), (meta) => meta.pageIndex, ($$anchor2, meta) => {
@@ -149,12 +170,10 @@ function ThumbnailsPane($$anchor, $$props) {
149
170
  $.reset(div_1);
150
171
  $.reset(div);
151
172
  $.bind_this(div, ($$value) => viewportRef = $$value, () => viewportRef);
152
- $.template_effect(($0) => styles = $.set_style(div_1, "", styles, $0), [
153
- () => ({
154
- height: `${$.get(totalHeight) ?? ""}px`,
155
- position: "relative"
156
- })
157
- ]);
173
+ $.template_effect(() => styles = $.set_style(div_1, "", styles, {
174
+ height: `${$.get(totalHeight) ?? ""}px`,
175
+ position: "relative"
176
+ }));
158
177
  $.append($$anchor, div);
159
178
  $.pop();
160
179
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/svelte/hooks/use-thumbnail.svelte.ts","../../src/svelte/components/ThumbImg.svelte","../../src/svelte/components/ThumbnailsPane.svelte"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/svelte';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","<script lang=\"ts\">\n import type { ThumbMeta } from '@embedpdf/plugin-thumbnail';\n import { ignore, PdfErrorCode } from '@embedpdf/models';\n import { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\n import type { HTMLImgAttributes } from 'svelte/elements';\n\n interface Props extends HTMLImgAttributes {\n meta: ThumbMeta;\n }\n\n const { meta, ...imgProps }: Props = $props();\n\n const thumbnailCapability = useThumbnailCapability();\n const thumbnailPlugin = useThumbnailPlugin();\n\n let url = $state<string | undefined>(undefined);\n let urlRef: string | null = null;\n let refreshTick = $state(0);\n\n // Listen for refresh events\n $effect(() => {\n if (!thumbnailPlugin.plugin) return;\n return thumbnailPlugin.plugin.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n refreshTick = refreshTick + 1;\n }\n });\n });\n\n // Render thumbnail\n $effect(() => {\n const task = thumbnailCapability.provides?.renderThumb(meta.pageIndex, window.devicePixelRatio);\n task?.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef = objectUrl;\n url = objectUrl;\n }, ignore);\n\n return () => {\n if (urlRef) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n } else {\n task?.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n };\n });\n\n const handleImageLoad = () => {\n if (urlRef) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n }\n };\n</script>\n\n{#if url}\n <img src={url} onload={handleImageLoad} {...imgProps} alt=\"PDF thumbnail\" />\n{/if}\n","<script lang=\"ts\">\n import type { Snippet } from 'svelte';\n import type { ThumbMeta, WindowState } from '@embedpdf/plugin-thumbnail';\n import { useThumbnailPlugin } from '../hooks';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {\n children: Snippet<[ThumbMeta]>;\n }\n\n const { children, ...divProps }: Props = $props();\n\n const thumbnailPlugin = useThumbnailPlugin();\n\n let viewportRef: HTMLDivElement | undefined;\n let window = $state<WindowState | null>(null);\n\n // 1) subscribe once to window updates\n $effect(() => {\n if (!thumbnailPlugin.plugin) return;\n return thumbnailPlugin.plugin.onWindow((newWindow) => {\n window = newWindow;\n });\n });\n\n // 2) keep plugin in sync while the user scrolls\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin) return;\n\n const onScroll = () => {\n thumbnailPlugin.plugin.updateWindow(vp.scrollTop, vp.clientHeight);\n };\n\n vp.addEventListener('scroll', onScroll);\n return () => vp.removeEventListener('scroll', onScroll);\n });\n\n // 2.5) keep plugin in sync when viewport resizes (e.g., menu opens/closes)\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin) return;\n\n const resizeObserver = new ResizeObserver(() => {\n thumbnailPlugin.plugin.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n\n resizeObserver.observe(vp);\n return () => resizeObserver.disconnect();\n });\n\n // 3) kick-start after document change\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin || !window) return;\n\n // push initial metrics\n thumbnailPlugin.plugin.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n\n // 4) let plugin drive scroll – only after window is set, and only once\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin || !window) return;\n\n return thumbnailPlugin.plugin.onScrollTo(({ top, behavior }) => {\n vp.scrollTo({ top, behavior });\n });\n });\n\n const paddingY = $derived(thumbnailPlugin?.plugin?.cfg.paddingY ?? 0);\n const totalHeight = $derived(window?.totalHeight ?? 0);\n const items = $derived(window?.items ?? []);\n</script>\n\n<div\n bind:this={viewportRef}\n style:overflow-y=\"auto\"\n style:position=\"relative\"\n style:padding-top=\"{paddingY}px\"\n style:padding-bottom=\"{paddingY}px\"\n style:height=\"100%\"\n {...divProps}\n>\n <div style:height=\"{totalHeight}px\" style:position=\"relative\">\n {#each items as meta (meta.pageIndex)}\n {@render children(meta)}\n {/each}\n </div>\n</div>\n"],"names":["window"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/svelte/hooks/use-thumbnail.svelte.ts","../../src/svelte/components/ThumbImg.svelte","../../src/svelte/components/ThumbnailsPane.svelte"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/svelte';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","<script lang=\"ts\">\n import type { ThumbMeta } from '@embedpdf/plugin-thumbnail';\n import { ignore, PdfErrorCode } from '@embedpdf/models';\n import { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\n import type { HTMLImgAttributes } from 'svelte/elements';\n\n interface Props extends HTMLImgAttributes {\n /**\n * The ID of the document that this thumbnail belongs to\n */\n documentId: string;\n meta: ThumbMeta;\n }\n\n const { documentId, meta, ...imgProps }: Props = $props();\n\n const thumbnailCapability = useThumbnailCapability();\n const thumbnailPlugin = useThumbnailPlugin();\n\n let url = $state<string | undefined>(undefined);\n let urlRef: string | null = null;\n let refreshTick = $state(0);\n\n // Listen for refresh events for this specific document\n $effect(() => {\n if (!thumbnailPlugin.plugin) return;\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n return scope.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n refreshTick = refreshTick + 1;\n }\n });\n });\n\n // Render thumbnail for this specific document\n $effect(() => {\n // Track refreshTick so effect re-runs on refresh\n const _tick = refreshTick;\n\n if (!thumbnailCapability.provides) return;\n\n const scope = thumbnailCapability.provides.forDocument(documentId);\n const task = scope.renderThumb(meta.pageIndex, window.devicePixelRatio);\n\n task.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef = objectUrl;\n url = objectUrl;\n }, ignore);\n\n return () => {\n if (urlRef) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n } else {\n task.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n };\n });\n\n const handleImageLoad = () => {\n if (urlRef) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n }\n };\n</script>\n\n{#if url}\n <img src={url} onload={handleImageLoad} {...imgProps} alt=\"PDF thumbnail\" />\n{/if}\n","<script lang=\"ts\">\n import type { Snippet } from 'svelte';\n import type { ThumbMeta, WindowState } from '@embedpdf/plugin-thumbnail';\n import { useThumbnailPlugin } from '../hooks';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {\n /**\n * The ID of the document that this thumbnail pane displays\n */\n documentId: string;\n children: Snippet<[ThumbMeta]>;\n }\n\n const { documentId, children, ...divProps }: Props = $props();\n\n const thumbnailPlugin = useThumbnailPlugin();\n\n let viewportRef: HTMLDivElement | undefined;\n\n // Store window data along with the documentId it came from\n let windowData = $state<{\n window: WindowState | null;\n docId: string | null;\n }>({ window: null, docId: null });\n\n // Only use the window if it matches the current documentId\n const window = $derived(windowData.docId === documentId ? windowData.window : null);\n\n // 1) subscribe to window updates for this document\n $effect(() => {\n if (!thumbnailPlugin.plugin) {\n windowData = { window: null, docId: null };\n return;\n }\n\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n\n // Get initial window state immediately on mount\n const initialWindow = scope.getWindow();\n if (initialWindow) {\n windowData = { window: initialWindow, docId: documentId };\n }\n\n // Subscribe to future updates\n const unsubscribe = scope.onWindow((newWindow) => {\n windowData = { window: newWindow, docId: documentId };\n });\n\n // Clear state when documentId changes or component unmounts\n return () => {\n unsubscribe();\n windowData = { window: null, docId: null };\n };\n });\n\n // 2) keep plugin in sync while the user scrolls\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin) return;\n\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n const onScroll = () => {\n scope.updateWindow(vp.scrollTop, vp.clientHeight);\n };\n\n vp.addEventListener('scroll', onScroll);\n return () => vp.removeEventListener('scroll', onScroll);\n });\n\n // 2.5) keep plugin in sync when viewport resizes (e.g., menu opens/closes)\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin) return;\n\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n const resizeObserver = new ResizeObserver(() => {\n scope.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n\n resizeObserver.observe(vp);\n return () => resizeObserver.disconnect();\n });\n\n // 3) kick-start after document change\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin || !window) return;\n\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n // push initial metrics\n scope.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n\n // 4) let plugin drive scroll – only after window is set, and only once\n $effect(() => {\n const vp = viewportRef;\n if (!vp || !thumbnailPlugin.plugin || !window) return;\n\n const scope = thumbnailPlugin.plugin.provides().forDocument(documentId);\n return scope.onScrollTo(({ top, behavior }) => {\n vp.scrollTo({ top, behavior });\n });\n });\n\n const paddingY = $derived(thumbnailPlugin?.plugin?.cfg.paddingY ?? 0);\n const totalHeight = $derived(window?.totalHeight ?? 0);\n const items = $derived(window?.items ?? []);\n</script>\n\n<div\n bind:this={viewportRef}\n style:overflow-y=\"auto\"\n style:position=\"relative\"\n style:padding-top=\"{paddingY}px\"\n style:padding-bottom=\"{paddingY}px\"\n style:height=\"100%\"\n {...divProps}\n>\n <div style:height=\"{totalHeight}px\" style:position=\"relative\">\n {#each items as meta (meta.pageIndex)}\n {@render children(meta)}\n {/each}\n </div>\n</div>\n"],"names":["window"],"mappings":"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"}
@@ -1,6 +1,11 @@
1
1
  import { ThumbMeta } from '../../lib/index.ts';
2
- type __VLS_Props = {
2
+ interface ThumbImgProps {
3
+ /**
4
+ * The ID of the document that this thumbnail belongs to
5
+ */
6
+ documentId: string;
3
7
  meta: ThumbMeta;
4
- };
5
- declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
8
+ }
9
+ declare const __VLS_export: import('vue').DefineComponent<ThumbImgProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<ThumbImgProps> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
10
+ declare const _default: typeof __VLS_export;
6
11
  export default _default;
@@ -1,11 +1,18 @@
1
+ interface ThumbnailsPaneProps {
2
+ /**
3
+ * The ID of the document that this thumbnail pane displays
4
+ */
5
+ documentId: string;
6
+ }
1
7
  declare var __VLS_1: {
2
8
  meta: any;
3
9
  };
4
10
  type __VLS_Slots = {} & {
5
11
  default?: (props: typeof __VLS_1) => any;
6
12
  };
7
- declare const __VLS_component: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
8
- declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
13
+ declare const __VLS_base: import('vue').DefineComponent<ThumbnailsPaneProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<ThumbnailsPaneProps> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
14
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
15
+ declare const _default: typeof __VLS_export;
9
16
  export default _default;
10
17
  type __VLS_WithSlots<T, S> = T & {
11
18
  new (): {
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/vue"),l=require("@embedpdf/plugin-thumbnail"),n=require("vue"),t=require("@embedpdf/models"),o=()=>e.usePlugin(l.ThumbnailPlugin.id),u=()=>e.useCapability(l.ThumbnailPlugin.id),r=n.defineComponent({__name:"thumbnails-pane",setup(e){const l=n.useAttrs(),{plugin:t}=o(),u=n.ref(null),r=n.ref(null);let a=null,i=null;return n.watchEffect((e=>{t.value&&(null==a||a(),a=t.value.onWindow((e=>r.value=e)),e((()=>null==a?void 0:a())))})),n.onMounted((()=>{const e=u.value;if(!e||!t.value)return;const l=()=>t.value.updateWindow(e.scrollTop,e.clientHeight);e.addEventListener("scroll",l);const o=new ResizeObserver((()=>{t.value.updateWindow(e.scrollTop,e.clientHeight)}));o.observe(e),t.value.updateWindow(e.scrollTop,e.clientHeight),n.onBeforeUnmount((()=>{e.removeEventListener("scroll",l),o.disconnect()}))})),n.watchEffect((e=>{const l=u.value;l&&t.value&&r.value&&(i=t.value.onScrollTo((({top:e,behavior:t})=>{n.nextTick((()=>{l.scrollTo({top:e,behavior:t})}))})),e((()=>null==i?void 0:i())))})),n.onBeforeUnmount((()=>{null==a||a(),null==i||i()})),(e,o)=>{var a,i,d,s,c,p;return n.openBlock(),n.createElementBlock("div",n.mergeProps({ref_key:"viewportRef",ref:u,style:{overflowY:"auto",position:"relative",paddingTop:((null==(i=null==(a=n.unref(t))?void 0:a.cfg)?void 0:i.paddingY)??0)+"px",paddingBottom:((null==(s=null==(d=n.unref(t))?void 0:d.cfg)?void 0:s.paddingY)??0)+"px",height:"100%"}},n.unref(l)),[n.createElementVNode("div",{style:n.normalizeStyle({height:((null==(c=r.value)?void 0:c.totalHeight)??0)+"px",position:"relative"})},[(n.openBlock(!0),n.createElementBlock(n.Fragment,null,n.renderList((null==(p=r.value)?void 0:p.items)??[],(l=>n.renderSlot(e.$slots,"default",{key:l.pageIndex,meta:l}))),128))],4)],16)}}}),a=["src"],i=n.defineComponent({__name:"thumbnail-img",props:{meta:{}},setup(e){const l=e,r=n.useAttrs(),{provides:i}=u(),{plugin:d}=o(),s=n.ref(null);let c=null;const p=n.ref(0);let v=null;function m(){c&&(URL.revokeObjectURL(c),c=null)}n.watchEffect((e=>{d.value&&(null==v||v(),v=d.value.onRefreshPages((e=>{e.includes(l.meta.pageIndex)&&p.value++})),e((()=>null==v?void 0:v())))}));let f=null;return n.watch((()=>[l.meta.pageIndex,p.value,!!i.value]),(()=>{null==f||f(),function(){if(!i.value)return;const e=i.value.renderThumb(l.meta.pageIndex,window.devicePixelRatio);f=()=>e.abort({code:t.PdfErrorCode.Cancelled,message:"canceled render task"}),e.wait((e=>{m();const l=URL.createObjectURL(e);c=l,s.value=l}),t.ignore)}()}),{immediate:!0}),n.onBeforeUnmount((()=>{null==f||f(),m()})),(e,l)=>s.value?(n.openBlock(),n.createElementBlock("img",n.mergeProps({key:0,src:s.value},n.unref(r),{onLoad:m}),null,16,a)):n.createCommentVNode("",!0)}});exports.ThumbImg=i,exports.ThumbnailsPane=r,exports.useThumbnailCapability=u,exports.useThumbnailPlugin=o,Object.keys(l).forEach((e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>l[e]})}));
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/vue"),t=require("@embedpdf/plugin-thumbnail"),o=require("vue"),n=require("@embedpdf/models"),l=()=>e.usePlugin(t.ThumbnailPlugin.id),r=()=>e.useCapability(t.ThumbnailPlugin.id),i=o.defineComponent({__name:"thumbnails-pane",props:{documentId:{}},setup(e){const t=e,{plugin:n}=l(),r=o.ref(null),i=o.ref({window:null,docId:null}),u=o.ref(null);o.watch(i,e=>{u.value=e.docId===t.documentId?e.window:null},{deep:!0}),o.watch([()=>n.value,()=>t.documentId],([e,t],o,n)=>{if(!e)return void(i.value={window:null,docId:null});const l=e.provides().forDocument(t),r=l.getWindow();r&&(i.value={window:r,docId:t});const u=l.onWindow(e=>{i.value={window:e,docId:t}});n(()=>{u(),i.value={window:null,docId:null}})},{immediate:!0}),o.watch([r,()=>n.value,()=>t.documentId],([e,t,o],n,l)=>{if(!e||!t)return;const r=t.provides().forDocument(o),i=()=>r.updateWindow(e.scrollTop,e.clientHeight);e.addEventListener("scroll",i);const u=new ResizeObserver(()=>{r.updateWindow(e.scrollTop,e.clientHeight)});u.observe(e),r.updateWindow(e.scrollTop,e.clientHeight),l(()=>{e.removeEventListener("scroll",i),u.disconnect()})},{immediate:!0}),o.watch([r,()=>n.value,()=>t.documentId,u],([e,t,o])=>{if(!e||!t)return;t.provides().forDocument(o).updateWindow(e.scrollTop,e.clientHeight)}),o.watch([r,()=>n.value,()=>t.documentId,()=>!!u.value],([e,t,n,l],r,i)=>{if(!e||!t||!l)return;i(t.provides().forDocument(n).onScrollTo(({top:t,behavior:n})=>{o.nextTick(()=>{e.scrollTo({top:t,behavior:n})})}))},{immediate:!0});const d=o.ref(0);return o.watch(()=>n.value,e=>{d.value=(null==e?void 0:e.cfg.paddingY)??0},{immediate:!0}),(e,t)=>{var n,l;return o.openBlock(),o.createElementBlock("div",o.mergeProps({ref_key:"viewportRef",ref:r,style:{overflowY:"auto",position:"relative",paddingTop:`${d.value}px`,paddingBottom:`${d.value}px`,height:"100%"}},e.$attrs),[o.createElementVNode("div",{style:o.normalizeStyle({height:`${(null==(n=u.value)?void 0:n.totalHeight)??0}px`,position:"relative"})},[(o.openBlock(!0),o.createElementBlock(o.Fragment,null,o.renderList((null==(l=u.value)?void 0:l.items)??[],t=>o.renderSlot(e.$slots,"default",{key:t.pageIndex,meta:t})),128))],4)],16)}}}),u=["src"],d=o.defineComponent({__name:"thumbnail-img",props:{documentId:{},meta:{}},setup(e){const t=e,{provides:i}=r(),{plugin:d}=l(),a=o.ref(null);let c=null;const s=o.ref(0);function m(){c&&(URL.revokeObjectURL(c),c=null)}o.watch([()=>d.value,()=>t.documentId,()=>t.meta.pageIndex],([e,t,o],n,l)=>{if(!e)return;l(e.provides().forDocument(t).onRefreshPages(e=>{e.includes(o)&&s.value++}))},{immediate:!0});let p=null;return o.watch([()=>i.value,()=>t.documentId,()=>t.meta.pageIndex,s],([e,t,o],l,r)=>{if(p&&(p(),p=null),!e)return void(a.value=null);const i=e.forDocument(t).renderThumb(o,window.devicePixelRatio);p=()=>i.abort({code:n.PdfErrorCode.Cancelled,message:"canceled render task"}),i.wait(e=>{m();const t=URL.createObjectURL(e);c=t,a.value=t,p=null},n.ignore),r(()=>{p&&(p(),p=null),m()})},{immediate:!0}),(e,t)=>a.value?(o.openBlock(),o.createElementBlock("img",o.mergeProps({key:0,src:a.value},e.$attrs,{onLoad:m}),null,16,u)):o.createCommentVNode("",!0)}});exports.ThumbImg=d,exports.ThumbnailsPane=i,exports.useThumbnailCapability=r,exports.useThumbnailPlugin=l,Object.keys(t).forEach(e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})});
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/vue/hooks/use-thumbnail.ts","../../src/vue/components/thumbnails-pane.vue","../../src/vue/components/thumbnail-img.vue"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","<script setup lang=\"ts\">\nimport { onMounted, onBeforeUnmount, ref, watchEffect, nextTick, useAttrs } from 'vue';\nimport { useThumbnailPlugin } from '../hooks';\nimport type { WindowState } from '@embedpdf/plugin-thumbnail';\n\nconst attrs = useAttrs();\n\nconst { plugin: thumbnailPlugin } = useThumbnailPlugin();\nconst viewportRef = ref<HTMLDivElement | null>(null);\nconst windowState = ref<WindowState | null>(null);\n\nlet offWindow: (() => void) | null = null;\nlet offScrollTo: (() => void) | null = null;\n\nwatchEffect((onCleanup) => {\n if (!thumbnailPlugin.value) return;\n offWindow?.();\n offWindow = thumbnailPlugin.value.onWindow((w) => (windowState.value = w));\n onCleanup(() => offWindow?.());\n});\n\n// Setup scroll listener on mount\nonMounted(() => {\n const vp = viewportRef.value;\n if (!vp || !thumbnailPlugin.value) return;\n\n const onScroll = () => thumbnailPlugin.value!.updateWindow(vp.scrollTop, vp.clientHeight);\n vp.addEventListener('scroll', onScroll);\n\n // Setup resize observer for viewport changes\n const resizeObserver = new ResizeObserver(() => {\n thumbnailPlugin.value!.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n resizeObserver.observe(vp);\n\n // initial push\n thumbnailPlugin.value.updateWindow(vp.scrollTop, vp.clientHeight);\n\n onBeforeUnmount(() => {\n vp.removeEventListener('scroll', onScroll);\n resizeObserver.disconnect();\n });\n});\n\n// Setup scrollTo subscription only after window is ready\nwatchEffect((onCleanup) => {\n const vp = viewportRef.value;\n if (!vp || !thumbnailPlugin.value || !windowState.value) return;\n\n offScrollTo = thumbnailPlugin.value.onScrollTo(({ top, behavior }) => {\n // Wait for Vue to finish rendering the content before scrolling\n nextTick(() => {\n vp.scrollTo({ top, behavior });\n });\n });\n\n onCleanup(() => offScrollTo?.());\n});\n\nonBeforeUnmount(() => {\n offWindow?.();\n offScrollTo?.();\n});\n</script>\n\n<template>\n <div\n ref=\"viewportRef\"\n :style=\"{\n overflowY: 'auto',\n position: 'relative',\n paddingTop: (thumbnailPlugin?.cfg?.paddingY ?? 0) + 'px',\n paddingBottom: (thumbnailPlugin?.cfg?.paddingY ?? 0) + 'px',\n height: '100%',\n }\"\n v-bind=\"attrs\"\n >\n <div :style=\"{ height: (windowState?.totalHeight ?? 0) + 'px', position: 'relative' }\">\n <!-- ✅ Use a template v-for to render the default scoped slot -->\n <template v-for=\"m in windowState?.items ?? []\" :key=\"m.pageIndex\">\n <slot :meta=\"m\" />\n </template>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { onBeforeUnmount, ref, watch, watchEffect, useAttrs } from 'vue';\nimport { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\nimport type { ThumbMeta } from '@embedpdf/plugin-thumbnail';\nimport { ignore, PdfErrorCode } from '@embedpdf/models';\n\nconst props = defineProps<{ meta: ThumbMeta }>();\nconst attrs = useAttrs();\n\nconst { provides: thumbs } = useThumbnailCapability();\nconst { plugin: thumbnailPlugin } = useThumbnailPlugin();\n\nconst url = ref<string | null>(null);\nlet urlToRevoke: string | null = null;\nconst refreshTick = ref(0);\n\nlet offRefresh: (() => void) | null = null;\n\nwatchEffect((onCleanup) => {\n if (!thumbnailPlugin.value) return;\n offRefresh?.();\n offRefresh = thumbnailPlugin.value.onRefreshPages((pages) => {\n if (pages.includes(props.meta.pageIndex)) {\n refreshTick.value++;\n }\n });\n onCleanup(() => offRefresh?.());\n});\n\nfunction revoke() {\n if (urlToRevoke) {\n URL.revokeObjectURL(urlToRevoke);\n urlToRevoke = null;\n }\n}\n\nlet abortTask: (() => void) | null = null;\n\nfunction load() {\n if (!thumbs.value) return; // wait until capability exists\n\n const task = thumbs.value.renderThumb(props.meta.pageIndex, window.devicePixelRatio);\n abortTask = () =>\n task.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n\n task.wait((blob) => {\n revoke();\n const objectUrl = URL.createObjectURL(blob);\n urlToRevoke = objectUrl;\n url.value = objectUrl;\n }, ignore);\n}\n\n/* 🔧 Re-run when:\n - page changes,\n - the plugin tells us to refresh,\n - OR the capability becomes available later.\n*/\nwatch(\n () => [props.meta.pageIndex, refreshTick.value, !!thumbs.value],\n () => {\n abortTask?.();\n load();\n },\n { immediate: true },\n);\n\nonBeforeUnmount(() => {\n abortTask?.();\n revoke();\n});\n</script>\n\n<template>\n <img v-if=\"url\" :src=\"url\" v-bind=\"attrs\" @load=\"revoke\" />\n</template>\n"],"names":["useThumbnailPlugin","usePlugin","ThumbnailPlugin","id","useThumbnailCapability","useCapability","attrs","useAttrs","plugin","thumbnailPlugin","viewportRef","ref","windowState","offWindow","offScrollTo","vue$1","watchEffect","onCleanup","value","onWindow","w","onMounted","vp","onScroll","updateWindow","scrollTop","clientHeight","addEventListener","resizeObserver","ResizeObserver","observe","onBeforeUnmount","removeEventListener","disconnect","onScrollTo","top","behavior","nextTick","scrollTo","_openBlock","_createElementBlock","_mergeProps","style","_unref","_a","cfg","_b","paddingY","_c","_d","unref","_createElementVNode","_normalizeStyle","normalizeStyle","height","_e","totalHeight","position","createElementBlock","_Fragment","Fragment","_renderList","_f","items","m","_renderSlot","_ctx","$slots","key","pageIndex","meta","props","__props","provides","thumbs","url","urlToRevoke","refreshTick","offRefresh","revoke","URL","revokeObjectURL","onRefreshPages","pages","includes","abortTask","watch","task","renderThumb","window","devicePixelRatio","abort","code","PdfErrorCode","Cancelled","message","wait","blob","objectUrl","createObjectURL","ignore","load","immediate","src","onLoad","_hoisted_1"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/vue/hooks/use-thumbnail.ts","../../src/vue/components/thumbnails-pane.vue","../../src/vue/components/thumbnail-img.vue"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","<script setup lang=\"ts\">\nimport { ref, watch, nextTick } from 'vue';\nimport { useThumbnailPlugin } from '../hooks';\nimport type { WindowState } from '@embedpdf/plugin-thumbnail';\n\ninterface ThumbnailsPaneProps {\n /**\n * The ID of the document that this thumbnail pane displays\n */\n documentId: string;\n}\n\nconst props = defineProps<ThumbnailsPaneProps>();\n\nconst { plugin: thumbnailPlugin } = useThumbnailPlugin();\nconst viewportRef = ref<HTMLDivElement | null>(null);\n\n// Store window data along with the documentId it came from\nconst windowData = ref<{\n window: WindowState | null;\n docId: string | null;\n}>({ window: null, docId: null });\n\n// Only use the window if it matches the current documentId\nconst windowState = ref<WindowState | null>(null);\n\nwatch(\n windowData,\n (data) => {\n windowState.value = data.docId === props.documentId ? data.window : null;\n },\n { deep: true },\n);\n\n// Subscribe to window updates for this document\nwatch(\n [() => thumbnailPlugin.value, () => props.documentId],\n ([plugin, docId], _, onCleanup) => {\n if (!plugin) {\n windowData.value = { window: null, docId: null };\n return;\n }\n\n const scope = plugin.provides().forDocument(docId);\n\n // Get initial window state immediately\n const initialWindow = scope.getWindow();\n if (initialWindow) {\n windowData.value = { window: initialWindow, docId };\n }\n\n // Subscribe to future updates\n const unsubscribe = scope.onWindow((newWindow) => {\n windowData.value = { window: newWindow, docId };\n });\n\n // Clear state when documentId changes or component unmounts\n onCleanup(() => {\n unsubscribe();\n windowData.value = { window: null, docId: null };\n });\n },\n { immediate: true },\n);\n\n// Setup scroll listener\nwatch(\n [viewportRef, () => thumbnailPlugin.value, () => props.documentId],\n ([vp, plugin, docId], _, onCleanup) => {\n if (!vp || !plugin) return;\n\n const scope = plugin.provides().forDocument(docId);\n\n const onScroll = () => scope.updateWindow(vp.scrollTop, vp.clientHeight);\n vp.addEventListener('scroll', onScroll);\n\n // Setup resize observer for viewport changes\n const resizeObserver = new ResizeObserver(() => {\n scope.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n resizeObserver.observe(vp);\n\n // Initial update\n scope.updateWindow(vp.scrollTop, vp.clientHeight);\n\n onCleanup(() => {\n vp.removeEventListener('scroll', onScroll);\n resizeObserver.disconnect();\n });\n },\n { immediate: true },\n);\n\n// Kick-start after window state changes\nwatch(\n [viewportRef, () => thumbnailPlugin.value, () => props.documentId, windowState],\n ([vp, plugin, docId]) => {\n if (!vp || !plugin) return;\n\n const scope = plugin.provides().forDocument(docId);\n scope.updateWindow(vp.scrollTop, vp.clientHeight);\n },\n);\n\n// Setup scrollTo subscription\nwatch(\n [viewportRef, () => thumbnailPlugin.value, () => props.documentId, () => !!windowState.value],\n ([vp, plugin, docId, window], _, onCleanup) => {\n if (!vp || !plugin || !window) return;\n\n const scope = plugin.provides().forDocument(docId);\n const unsubscribe = scope.onScrollTo(({ top, behavior }) => {\n // Wait for Vue to finish rendering the content before scrolling\n nextTick(() => {\n vp.scrollTo({ top, behavior });\n });\n });\n\n onCleanup(unsubscribe);\n },\n { immediate: true },\n);\n\nconst paddingY = ref(0);\n\nwatch(\n () => thumbnailPlugin.value,\n (plugin) => {\n paddingY.value = plugin?.cfg.paddingY ?? 0;\n },\n { immediate: true },\n);\n</script>\n\n<template>\n <div\n ref=\"viewportRef\"\n :style=\"{\n overflowY: 'auto',\n position: 'relative',\n paddingTop: `${paddingY}px`,\n paddingBottom: `${paddingY}px`,\n height: '100%',\n }\"\n v-bind=\"$attrs\"\n >\n <div :style=\"{ height: `${windowState?.totalHeight ?? 0}px`, position: 'relative' }\">\n <template v-for=\"m in windowState?.items ?? []\" :key=\"m.pageIndex\">\n <slot :meta=\"m\" />\n </template>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ref, watch } from 'vue';\nimport { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\nimport type { ThumbMeta } from '@embedpdf/plugin-thumbnail';\nimport { ignore, PdfErrorCode } from '@embedpdf/models';\n\ninterface ThumbImgProps {\n /**\n * The ID of the document that this thumbnail belongs to\n */\n documentId: string;\n meta: ThumbMeta;\n}\n\nconst props = defineProps<ThumbImgProps>();\n\nconst { provides: thumbs } = useThumbnailCapability();\nconst { plugin: thumbnailPlugin } = useThumbnailPlugin();\n\nconst url = ref<string | null>(null);\nlet urlToRevoke: string | null = null;\nconst refreshTick = ref(0);\n\n// Watch for refresh events for this specific document\nwatch(\n [() => thumbnailPlugin.value, () => props.documentId, () => props.meta.pageIndex],\n ([plugin, docId, pageIdx], _, onCleanup) => {\n if (!plugin) return;\n\n const scope = plugin.provides().forDocument(docId);\n const unsubscribe = scope.onRefreshPages((pages) => {\n if (pages.includes(pageIdx)) {\n refreshTick.value++;\n }\n });\n\n onCleanup(unsubscribe);\n },\n { immediate: true },\n);\n\nfunction revoke() {\n if (urlToRevoke) {\n URL.revokeObjectURL(urlToRevoke);\n urlToRevoke = null;\n }\n}\n\nlet abortTask: (() => void) | null = null;\n\n// Render thumbnail when dependencies change\nwatch(\n [() => thumbs.value, () => props.documentId, () => props.meta.pageIndex, refreshTick],\n ([capability, docId, pageIdx], _, onCleanup) => {\n // Cancel previous task\n if (abortTask) {\n abortTask();\n abortTask = null;\n }\n\n if (!capability) {\n url.value = null;\n return;\n }\n\n const scope = capability.forDocument(docId);\n const task = scope.renderThumb(pageIdx, window.devicePixelRatio);\n\n abortTask = () =>\n task.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n\n task.wait((blob) => {\n revoke();\n const objectUrl = URL.createObjectURL(blob);\n urlToRevoke = objectUrl;\n url.value = objectUrl;\n abortTask = null;\n }, ignore);\n\n onCleanup(() => {\n if (abortTask) {\n abortTask();\n abortTask = null;\n }\n revoke();\n });\n },\n { immediate: true },\n);\n</script>\n\n<template>\n <img v-if=\"url\" :src=\"url\" v-bind=\"$attrs\" @load=\"revoke\" />\n</template>\n"],"names":["useThumbnailPlugin","usePlugin","ThumbnailPlugin","id","useThumbnailCapability","useCapability","props","__props","plugin","thumbnailPlugin","viewportRef","ref","windowData","window","docId","windowState","watch","data","value","documentId","deep","_","onCleanup","scope","provides","forDocument","initialWindow","getWindow","unsubscribe","onWindow","newWindow","immediate","vp","onScroll","updateWindow","scrollTop","clientHeight","addEventListener","resizeObserver","ResizeObserver","observe","removeEventListener","disconnect","onScrollTo","top","behavior","nextTick","scrollTo","paddingY","cfg","_openBlock","_createElementBlock","_mergeProps","style","$attrs","_createElementVNode","_normalizeStyle","height","_a","totalHeight","position","_Fragment","_renderList","_b","items","m","_renderSlot","_ctx","$slots","key","pageIndex","meta","thumbs","url","urlToRevoke","refreshTick","revoke","URL","revokeObjectURL","pageIdx","onRefreshPages","pages","includes","abortTask","capability","task","renderThumb","devicePixelRatio","abort","code","PdfErrorCode","Cancelled","message","wait","blob","objectUrl","createObjectURL","ignore","src","onLoad","_hoisted_1"],"mappings":"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"}