@embedpdf/plugin-thumbnail 1.3.16 → 1.4.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.
@@ -0,0 +1,2 @@
1
+ export * from './thumbnails-pane';
2
+ export * from './thumbnail-img';
@@ -0,0 +1,8 @@
1
+ import { HTMLAttributes, CSSProperties } from '../../react/adapter.ts';
2
+ import { ThumbMeta } from '../../index.ts';
3
+ type ThumbnailImgProps = Omit<HTMLAttributes<HTMLImageElement>, 'style'> & {
4
+ style?: CSSProperties;
5
+ meta: ThumbMeta;
6
+ };
7
+ export declare function ThumbImg({ meta, style, ...props }: ThumbnailImgProps): import("react/jsx-runtime").JSX.Element | null;
8
+ export {};
@@ -0,0 +1,12 @@
1
+ import { HTMLAttributes, CSSProperties, ReactNode } from '../../react/adapter.ts';
2
+ import { ThumbMeta } from '../../index.ts';
3
+ type ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {
4
+ 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;
10
+ };
11
+ export declare function ThumbnailsPane({ style, scrollOptions, selectedPage, ...props }: ThumbnailsProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1 @@
1
+ export * from './use-thumbnail';
@@ -0,0 +1,11 @@
1
+ import { ThumbnailPlugin } from '../../index.ts';
2
+ export declare const useThumbnailPlugin: () => {
3
+ plugin: ThumbnailPlugin | null;
4
+ isLoading: boolean;
5
+ ready: Promise<void>;
6
+ };
7
+ export declare const useThumbnailCapability: () => {
8
+ provides: Readonly<import('../../index.ts').ThumbnailCapability> | null;
9
+ isLoading: boolean;
10
+ ready: Promise<void>;
11
+ };
@@ -0,0 +1,3 @@
1
+ export * from './hooks';
2
+ export * from './components';
3
+ export * from '../index.ts';
@@ -0,0 +1,8 @@
1
+ import { ThumbMeta } from '../../lib/index.ts';
2
+ import { HTMLImgAttributes } from 'svelte/elements';
3
+ interface Props extends HTMLImgAttributes {
4
+ meta: ThumbMeta;
5
+ }
6
+ declare const ThumbImg: import('svelte', { with: { "resolution-mode": "import" } }).Component<Props, {}, "">;
7
+ type ThumbImg = ReturnType<typeof ThumbImg>;
8
+ export default ThumbImg;
@@ -0,0 +1,9 @@
1
+ import { Snippet } from 'svelte';
2
+ import { ThumbMeta } from '../../lib/index.ts';
3
+ import { HTMLAttributes } from 'svelte/elements';
4
+ interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
5
+ children: Snippet<[ThumbMeta]>;
6
+ }
7
+ declare const ThumbnailsPane: import('svelte', { with: { "resolution-mode": "import" } }).Component<Props, {}, "">;
8
+ type ThumbnailsPane = ReturnType<typeof ThumbnailsPane>;
9
+ export default ThumbnailsPane;
@@ -0,0 +1,2 @@
1
+ export { default as ThumbImg } from './ThumbImg.svelte';
2
+ export { default as ThumbnailsPane } from './ThumbnailsPane.svelte';
@@ -0,0 +1 @@
1
+ export * from './use-thumbnail.svelte';
@@ -0,0 +1,11 @@
1
+ import { ThumbnailPlugin } from '../../lib/index.ts';
2
+ export declare const useThumbnailPlugin: () => {
3
+ plugin: ThumbnailPlugin | null;
4
+ isLoading: boolean;
5
+ ready: Promise<void>;
6
+ };
7
+ export declare const useThumbnailCapability: () => {
8
+ provides: Readonly<import('../../lib/index.ts').ThumbnailCapability> | null;
9
+ isLoading: boolean;
10
+ ready: Promise<void>;
11
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("svelte/internal/client"),t=require("@embedpdf/core/svelte"),r=require("@embedpdf/plugin-thumbnail");require("svelte/internal/disclose-version");const n=require("@embedpdf/models");function o(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const r in e)if("default"!==r){const n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:()=>e[r]})}return t.default=e,Object.freeze(t)}const i=o(e),l=()=>t.usePlugin(r.ThumbnailPlugin.id),s=()=>t.useCapability(r.ThumbnailPlugin.id);var c=i.from_html("<img/>");var a=i.from_html("<div><div></div></div>");exports.ThumbImg=function(e,t){i.push(t,!0);const r=i.rest_props(t,["$$slots","$$events","$$legacy","meta"]),{provides:o}=s(),{plugin:a}=l();let u=i.state(void 0),d=null,p=i.state(0);i.user_effect((()=>{if(a)return a.onRefreshPages((e=>{e.includes(t.meta.pageIndex)&&i.set(p,i.get(p)+1)}))})),i.user_effect((()=>{const e=null==o?void 0:o.renderThumb(t.meta.pageIndex,window.devicePixelRatio);return null==e||e.wait((e=>{const t=URL.createObjectURL(e);d=t,i.set(u,t,!0)}),n.ignore),()=>{d?(URL.revokeObjectURL(d),d=null):null==e||e.abort({code:n.PdfErrorCode.Cancelled,message:"canceled render task"})}}));const f=()=>{d&&(URL.revokeObjectURL(d),d=null)};var g=i.comment(),v=i.first_child(g),b=e=>{var t=c();i.attribute_effect(t,(()=>({src:i.get(u),onload:f,...r,alt:"PDF thumbnail"}))),i.replay_events(t),i.append(e,t)};i.if(v,(e=>{i.get(u)&&e(b)})),i.append(e,g),i.pop()},exports.ThumbnailsPane=function(e,t){i.push(t,!0);const r=i.rest_props(t,["$$slots","$$events","$$legacy","children"]),{plugin:n}=l();let o,s=i.state(null);i.user_effect((()=>{if(n)return n.onWindow((e=>{i.set(s,e,!0)}))})),i.user_effect((()=>{const e=o;if(!e||!n)return;const t=()=>{n.updateWindow(e.scrollTop,e.clientHeight)};return e.addEventListener("scroll",t),()=>e.removeEventListener("scroll",t)})),i.user_effect((()=>{const e=o;if(!e||!n)return;const t=new ResizeObserver((()=>{n.updateWindow(e.scrollTop,e.clientHeight)}));return t.observe(e),()=>t.disconnect()})),i.user_effect((()=>{const e=o;e&&n&&i.get(s)&&n.updateWindow(e.scrollTop,e.clientHeight)})),i.user_effect((()=>{const e=o;if(e&&n&&i.get(s))return n.onScrollTo((({top:t,behavior:r})=>{e.scrollTo({top:t,behavior:r})}))}));const c=i.derived((()=>(null==n?void 0:n.cfg.paddingY)??0)),u=i.derived((()=>{var e;return(null==(e=i.get(s))?void 0:e.totalHeight)??0})),d=i.derived((()=>{var e;return(null==(e=i.get(s))?void 0:e.items)??[]}));var p=a();i.attribute_effect(p,(e=>({...r,[i.STYLE]:e})),[()=>({"overflow-y":"auto",position:"relative","padding-top":`${i.get(c)??""}px`,"padding-bottom":`${i.get(c)??""}px`,height:"100%"})]);var f=i.child(p);let g;i.each(f,21,(()=>i.get(d)),(e=>e.pageIndex),((e,r)=>{var n=i.comment(),o=i.first_child(n);i.snippet(o,(()=>t.children),(()=>i.get(r))),i.append(e,n)})),i.reset(f),i.reset(p),i.bind_this(p,(e=>o=e),(()=>o)),i.template_effect((e=>g=i.set_style(f,"",g,e)),[()=>({height:`${i.get(u)??""}px`,position:"relative"})]),i.append(e,p),i.pop()},exports.useThumbnailCapability=s,exports.useThumbnailPlugin=l,Object.keys(r).forEach((e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>r[e]})}));
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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 { provides: thumbs } = useThumbnailCapability();\n const { plugin: 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) return;\n return thumbnailPlugin.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n refreshTick = refreshTick + 1;\n }\n });\n });\n\n // Render thumbnail\n $effect(() => {\n const task = thumbs?.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 { plugin: 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) return;\n return thumbnailPlugin.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) return;\n\n const onScroll = () => {\n thumbnailPlugin.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) return;\n\n const resizeObserver = new ResizeObserver(() => {\n thumbnailPlugin.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 || !window) return;\n\n // push initial metrics\n thumbnailPlugin.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 || !window) return;\n\n return thumbnailPlugin.onScrollTo(({ top, behavior }) => {\n vp.scrollTo({ top, behavior });\n });\n });\n\n const paddingY = $derived(thumbnailPlugin?.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","provides","thumbs","plugin","thumbnailPlugin","url","urlRef","refreshTick","user_effect","onRefreshPages","pages","includes","meta","pageIndex","get","task","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","cfg","totalHeight","derived","items","STYLE","$0","each","div_1","bind_this","div","$$value"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './hooks';
2
+ export * from './components';
3
+ export * from '../lib/index.ts';
@@ -0,0 +1,163 @@
1
+ import * as $ from "svelte/internal/client";
2
+ import { usePlugin, useCapability } from "@embedpdf/core/svelte";
3
+ import { ThumbnailPlugin } from "@embedpdf/plugin-thumbnail";
4
+ export * from "@embedpdf/plugin-thumbnail";
5
+ import "svelte/internal/disclose-version";
6
+ import { ignore, PdfErrorCode } from "@embedpdf/models";
7
+ const useThumbnailPlugin = () => usePlugin(ThumbnailPlugin.id);
8
+ const useThumbnailCapability = () => useCapability(ThumbnailPlugin.id);
9
+ var root_1 = $.from_html(`<img/>`);
10
+ function ThumbImg($$anchor, $$props) {
11
+ $.push($$props, true);
12
+ const imgProps = $.rest_props($$props, ["$$slots", "$$events", "$$legacy", "meta"]);
13
+ const { provides: thumbs } = useThumbnailCapability();
14
+ const { plugin: thumbnailPlugin } = useThumbnailPlugin();
15
+ let url = $.state(void 0);
16
+ let urlRef = null;
17
+ let refreshTick = $.state(0);
18
+ $.user_effect(() => {
19
+ if (!thumbnailPlugin) return;
20
+ return thumbnailPlugin.onRefreshPages((pages) => {
21
+ if (pages.includes($$props.meta.pageIndex)) {
22
+ $.set(refreshTick, $.get(refreshTick) + 1);
23
+ }
24
+ });
25
+ });
26
+ $.user_effect(() => {
27
+ const task = thumbs == null ? void 0 : thumbs.renderThumb($$props.meta.pageIndex, window.devicePixelRatio);
28
+ task == null ? void 0 : task.wait(
29
+ (blob) => {
30
+ const objectUrl = URL.createObjectURL(blob);
31
+ urlRef = objectUrl;
32
+ $.set(url, objectUrl, true);
33
+ },
34
+ ignore
35
+ );
36
+ return () => {
37
+ if (urlRef) {
38
+ URL.revokeObjectURL(urlRef);
39
+ urlRef = null;
40
+ } else {
41
+ task == null ? void 0 : task.abort({
42
+ code: PdfErrorCode.Cancelled,
43
+ message: "canceled render task"
44
+ });
45
+ }
46
+ };
47
+ });
48
+ const handleImageLoad = () => {
49
+ if (urlRef) {
50
+ URL.revokeObjectURL(urlRef);
51
+ urlRef = null;
52
+ }
53
+ };
54
+ var fragment = $.comment();
55
+ var node = $.first_child(fragment);
56
+ {
57
+ var consequent = ($$anchor2) => {
58
+ var img = root_1();
59
+ $.attribute_effect(img, () => ({
60
+ src: $.get(url),
61
+ onload: handleImageLoad,
62
+ ...imgProps,
63
+ alt: "PDF thumbnail"
64
+ }));
65
+ $.replay_events(img);
66
+ $.append($$anchor2, img);
67
+ };
68
+ $.if(node, ($$render) => {
69
+ if ($.get(url)) $$render(consequent);
70
+ });
71
+ }
72
+ $.append($$anchor, fragment);
73
+ $.pop();
74
+ }
75
+ var root = $.from_html(`<div><div></div></div>`);
76
+ function ThumbnailsPane($$anchor, $$props) {
77
+ $.push($$props, true);
78
+ const divProps = $.rest_props($$props, ["$$slots", "$$events", "$$legacy", "children"]);
79
+ const { plugin: thumbnailPlugin } = useThumbnailPlugin();
80
+ let viewportRef;
81
+ let window2 = $.state(null);
82
+ $.user_effect(() => {
83
+ if (!thumbnailPlugin) return;
84
+ return thumbnailPlugin.onWindow((newWindow) => {
85
+ $.set(window2, newWindow, true);
86
+ });
87
+ });
88
+ $.user_effect(() => {
89
+ const vp = viewportRef;
90
+ if (!vp || !thumbnailPlugin) return;
91
+ const onScroll = () => {
92
+ thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);
93
+ };
94
+ vp.addEventListener("scroll", onScroll);
95
+ return () => vp.removeEventListener("scroll", onScroll);
96
+ });
97
+ $.user_effect(() => {
98
+ const vp = viewportRef;
99
+ if (!vp || !thumbnailPlugin) return;
100
+ const resizeObserver = new ResizeObserver(() => {
101
+ thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);
102
+ });
103
+ resizeObserver.observe(vp);
104
+ return () => resizeObserver.disconnect();
105
+ });
106
+ $.user_effect(() => {
107
+ const vp = viewportRef;
108
+ if (!vp || !thumbnailPlugin || !$.get(window2)) return;
109
+ thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);
110
+ });
111
+ $.user_effect(() => {
112
+ const vp = viewportRef;
113
+ if (!vp || !thumbnailPlugin || !$.get(window2)) return;
114
+ return thumbnailPlugin.onScrollTo(({ top, behavior }) => {
115
+ vp.scrollTo({ top, behavior });
116
+ });
117
+ });
118
+ const paddingY = $.derived(() => (thumbnailPlugin == null ? void 0 : thumbnailPlugin.cfg.paddingY) ?? 0);
119
+ const totalHeight = $.derived(() => {
120
+ var _a;
121
+ return ((_a = $.get(window2)) == null ? void 0 : _a.totalHeight) ?? 0;
122
+ });
123
+ const items = $.derived(() => {
124
+ var _a;
125
+ return ((_a = $.get(window2)) == null ? void 0 : _a.items) ?? [];
126
+ });
127
+ var div = root();
128
+ $.attribute_effect(div, ($0) => ({ ...divProps, [$.STYLE]: $0 }), [
129
+ () => ({
130
+ "overflow-y": "auto",
131
+ position: "relative",
132
+ "padding-top": `${$.get(paddingY) ?? ""}px`,
133
+ "padding-bottom": `${$.get(paddingY) ?? ""}px`,
134
+ height: "100%"
135
+ })
136
+ ]);
137
+ var div_1 = $.child(div);
138
+ let styles;
139
+ $.each(div_1, 21, () => $.get(items), (meta) => meta.pageIndex, ($$anchor2, meta) => {
140
+ var fragment = $.comment();
141
+ var node = $.first_child(fragment);
142
+ $.snippet(node, () => $$props.children, () => $.get(meta));
143
+ $.append($$anchor2, fragment);
144
+ });
145
+ $.reset(div_1);
146
+ $.reset(div);
147
+ $.bind_this(div, ($$value) => viewportRef = $$value, () => viewportRef);
148
+ $.template_effect(($0) => styles = $.set_style(div_1, "", styles, $0), [
149
+ () => ({
150
+ height: `${$.get(totalHeight) ?? ""}px`,
151
+ position: "relative"
152
+ })
153
+ ]);
154
+ $.append($$anchor, div);
155
+ $.pop();
156
+ }
157
+ export {
158
+ ThumbImg,
159
+ ThumbnailsPane,
160
+ useThumbnailCapability,
161
+ useThumbnailPlugin
162
+ };
163
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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 { provides: thumbs } = useThumbnailCapability();\n const { plugin: 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) return;\n return thumbnailPlugin.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n refreshTick = refreshTick + 1;\n }\n });\n });\n\n // Render thumbnail\n $effect(() => {\n const task = thumbs?.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 { plugin: 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) return;\n return thumbnailPlugin.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) return;\n\n const onScroll = () => {\n thumbnailPlugin.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) return;\n\n const resizeObserver = new ResizeObserver(() => {\n thumbnailPlugin.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 || !window) return;\n\n // push initial metrics\n thumbnailPlugin.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 || !window) return;\n\n return thumbnailPlugin.onScrollTo(({ top, behavior }) => {\n vp.scrollTo({ top, behavior });\n });\n });\n\n const paddingY = $derived(thumbnailPlugin?.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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-thumbnail",
3
- "version": "1.3.16",
3
+ "version": "1.4.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.cjs",
@@ -26,26 +26,32 @@
26
26
  "types": "./dist/vue/index.d.ts",
27
27
  "import": "./dist/vue/index.js",
28
28
  "require": "./dist/vue/index.cjs"
29
+ },
30
+ "./svelte": {
31
+ "types": "./dist/svelte/index.d.ts",
32
+ "import": "./dist/svelte/index.js",
33
+ "require": "./dist/svelte/index.cjs"
29
34
  }
30
35
  },
31
36
  "dependencies": {
32
- "@embedpdf/models": "1.3.16"
37
+ "@embedpdf/models": "1.4.0"
33
38
  },
34
39
  "devDependencies": {
35
40
  "@types/react": "^18.2.0",
36
41
  "typescript": "^5.0.0",
37
- "@embedpdf/core": "1.3.16",
38
- "@embedpdf/plugin-render": "1.3.16",
39
- "@embedpdf/plugin-scroll": "1.3.16",
40
- "@embedpdf/build": "1.0.1"
42
+ "@embedpdf/plugin-render": "1.4.0",
43
+ "@embedpdf/core": "1.4.0",
44
+ "@embedpdf/build": "1.1.0",
45
+ "@embedpdf/plugin-scroll": "1.4.0"
41
46
  },
42
47
  "peerDependencies": {
43
48
  "react": ">=16.8.0",
44
49
  "react-dom": ">=16.8.0",
45
50
  "preact": "^10.26.4",
46
51
  "vue": ">=3.2.0",
47
- "@embedpdf/core": "1.3.16",
48
- "@embedpdf/plugin-render": "1.3.16"
52
+ "svelte": ">=5 <6",
53
+ "@embedpdf/core": "1.4.0",
54
+ "@embedpdf/plugin-render": "1.4.0"
49
55
  },
50
56
  "files": [
51
57
  "dist",
@@ -68,7 +74,8 @@
68
74
  "build:react": "vite build --mode react",
69
75
  "build:preact": "vite build --mode preact",
70
76
  "build:vue": "vite build --mode vue",
71
- "build": "pnpm run clean && concurrently -c auto -n base,react,preact,vue \"vite build --mode base\" \"vite build --mode react\" \"vite build --mode preact\" \"vite build --mode vue\"",
77
+ "build:svelte": "vite build --mode svelte",
78
+ "build": "pnpm run clean && concurrently -c auto -n base,react,preact,vue,svelte \"vite build --mode base\" \"vite build --mode react\" \"vite build --mode preact\" \"vite build --mode vue\" \"vite build --mode svelte\"",
72
79
  "clean": "rimraf dist",
73
80
  "lint": "eslint src --color",
74
81
  "lint:fix": "eslint src --color --fix"