@embedpdf/plugin-thumbnail 1.3.4 → 1.3.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-thumbnail.ts","../../src/shared/components/thumbnails-pane.tsx","../../src/shared/components/thumbnail-img.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","import { useEffect, useRef, useState, HTMLAttributes, CSSProperties, ReactNode } from '@framework';\nimport { ThumbMeta, WindowState } from '@embedpdf/plugin-thumbnail';\nimport { useThumbnailCapability } from '../hooks';\n\ntype ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {\n style?: CSSProperties;\n children: (m: ThumbMeta) => ReactNode;\n selectedPage?: number;\n scrollOptions?: ScrollIntoViewOptions;\n};\n\nexport function ThumbnailsPane({\n style,\n selectedPage,\n scrollOptions = { behavior: 'smooth', block: 'nearest', inline: 'nearest' },\n ...props\n}: ThumbnailsProps) {\n const { provides: thumbs } = useThumbnailCapability();\n const viewportRef = useRef<HTMLDivElement>(null);\n\n const [window, setWindow] = useState<WindowState | null>(null);\n\n /* 1️⃣ subscribe once to window updates */\n useEffect(() => thumbs?.onWindow(setWindow), [thumbs]);\n\n /* 2️⃣ keep plugin in sync while the user scrolls */\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp) return;\n const onScroll = () => thumbs?.setViewport(vp.scrollTop, vp.clientHeight);\n vp.addEventListener('scroll', onScroll);\n return () => vp.removeEventListener('scroll', onScroll);\n }, [thumbs]);\n\n /* 3️⃣ kick-start (or re-kick) after document change */\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbs) return;\n\n if (window?.items.length === 0) {\n thumbs.setViewport(vp.scrollTop, vp.clientHeight);\n }\n }, [window, thumbs]);\n\n /* 4️⃣ whenever selectedPage or window changes, ensure it’s visible */\n useEffect(() => {\n if (!selectedPage || !window) return;\n\n const item = window.items.find((it) => it.pageIndex + 1 === selectedPage);\n if (!item) return; // not in current window yet wait for next update\n\n const vp = viewportRef.current;\n if (!vp) return;\n\n // Scroll only if the item is above or below the viewport “padding” zone\n const margin = 8; // px\n if (item.top < vp.scrollTop + margin) {\n vp.scrollTo({ top: item.top, ...scrollOptions });\n } else if (\n item.top + item.wrapperHeight + item.labelHeight >\n vp.scrollTop + vp.clientHeight - margin\n ) {\n vp.scrollTo({\n top: item.top + item.wrapperHeight + item.labelHeight - vp.clientHeight,\n ...scrollOptions,\n });\n }\n }, [selectedPage, window, scrollOptions]);\n\n return (\n <div ref={viewportRef} style={{ overflowY: 'auto', position: 'relative', ...style }} {...props}>\n {/* spacer keeps correct scroll height even before first window arrives */}\n <div style={{ height: window?.totalHeight ?? 0, position: 'relative' }}>\n {window?.items.map((m) => props.children(m))}\n </div>\n </div>\n );\n}\n","import { useEffect, useState, useRef, HTMLAttributes, CSSProperties, Fragment } from '@framework';\nimport { ThumbMeta } from '@embedpdf/plugin-thumbnail';\nimport { ignore, PdfErrorCode } from '@embedpdf/models';\nimport { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\n\ntype ThumbnailImgProps = Omit<HTMLAttributes<HTMLImageElement>, 'style'> & {\n style?: CSSProperties;\n meta: ThumbMeta;\n};\n\nexport function ThumbImg({ meta, style, ...props }: ThumbnailImgProps) {\n const { provides: thumbs } = useThumbnailCapability();\n const { plugin: thumbnailPlugin } = useThumbnailPlugin();\n const [url, setUrl] = useState<string>();\n const urlRef = useRef<string | null>(null);\n const [refreshTick, setRefreshTick] = useState(0);\n\n useEffect(() => {\n if (!thumbnailPlugin) return;\n return thumbnailPlugin.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n setRefreshTick((tick) => tick + 1);\n }\n });\n }, [thumbnailPlugin]);\n\n useEffect(() => {\n const task = thumbs?.renderThumb(meta.pageIndex, window.devicePixelRatio);\n task?.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef.current = objectUrl;\n setUrl(objectUrl);\n }, ignore);\n\n return () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n } else {\n task?.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n };\n }, [thumbs, meta.pageIndex, refreshTick]);\n\n const handleImageLoad = () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n }\n };\n\n return url ? <img src={url} onLoad={handleImageLoad} style={style} {...props} /> : null;\n}\n"],"names":["window"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-thumbnail.ts","../../src/shared/components/thumbnails-pane.tsx","../../src/shared/components/thumbnail-img.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","import { useEffect, useRef, useState, HTMLAttributes, CSSProperties, ReactNode } from '@framework';\nimport { ThumbMeta, WindowState } from '@embedpdf/plugin-thumbnail';\nimport { useThumbnailPlugin } from '../hooks';\n\ntype ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {\n style?: CSSProperties;\n children: (m: ThumbMeta) => ReactNode;\n /** @deprecated use scrollToThumb via capability or rely on autoScroll */\n selectedPage?: number;\n /** @deprecated behavior is now controlled by ThumbnailPluginConfig.scrollBehavior */\n scrollOptions?: ScrollIntoViewOptions;\n};\n\nexport function ThumbnailsPane({ style, scrollOptions, selectedPage, ...props }: ThumbnailsProps) {\n const { plugin: thumbnailPlugin } = useThumbnailPlugin();\n const viewportRef = useRef<HTMLDivElement>(null);\n\n const [window, setWindow] = useState<WindowState | null>(null);\n\n // 1) subscribe once to window updates\n useEffect(() => thumbnailPlugin?.onWindow(setWindow), [thumbnailPlugin]);\n\n // 2) keep plugin in sync while the user scrolls\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp) return;\n const onScroll = () => thumbnailPlugin?.updateWindow(vp.scrollTop, vp.clientHeight);\n vp.addEventListener('scroll', onScroll);\n return () => vp.removeEventListener('scroll', onScroll);\n }, [thumbnailPlugin]);\n\n // 2.5) keep plugin in sync when viewport resizes (e.g., menu opens/closes)\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbnailPlugin) return;\n\n const resizeObserver = new ResizeObserver(() => {\n thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n resizeObserver.observe(vp);\n\n return () => resizeObserver.disconnect();\n }, [thumbnailPlugin]);\n\n // 3) kick-start after document change\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbnailPlugin) return;\n\n // push initial metrics\n thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);\n }, [window, thumbnailPlugin]);\n\n // 4) let plugin drive scroll only after window is set, and only once\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbnailPlugin || !window) return;\n\n return thumbnailPlugin.onScrollTo(({ top, behavior }) => {\n vp.scrollTo({ top, behavior });\n });\n }, [thumbnailPlugin, !!window]); // Note: !!window to prevent re-subscription on window updates\n\n const paddingY = thumbnailPlugin?.cfg.paddingY ?? 0;\n\n return (\n <div\n ref={viewportRef}\n style={{\n overflowY: 'auto',\n position: 'relative',\n paddingTop: paddingY,\n paddingBottom: paddingY,\n height: '100%',\n ...style,\n }}\n {...props}\n >\n <div style={{ height: window?.totalHeight ?? 0, position: 'relative' }}>\n {window?.items.map((m) => props.children(m))}\n </div>\n </div>\n );\n}\n","import { useEffect, useState, useRef, HTMLAttributes, CSSProperties, Fragment } from '@framework';\nimport { ThumbMeta } from '@embedpdf/plugin-thumbnail';\nimport { ignore, PdfErrorCode } from '@embedpdf/models';\nimport { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\n\ntype ThumbnailImgProps = Omit<HTMLAttributes<HTMLImageElement>, 'style'> & {\n style?: CSSProperties;\n meta: ThumbMeta;\n};\n\nexport function ThumbImg({ meta, style, ...props }: ThumbnailImgProps) {\n const { provides: thumbs } = useThumbnailCapability();\n const { plugin: thumbnailPlugin } = useThumbnailPlugin();\n const [url, setUrl] = useState<string>();\n const urlRef = useRef<string | null>(null);\n const [refreshTick, setRefreshTick] = useState(0);\n\n useEffect(() => {\n if (!thumbnailPlugin) return;\n return thumbnailPlugin.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n setRefreshTick((tick) => tick + 1);\n }\n });\n }, [thumbnailPlugin]);\n\n useEffect(() => {\n const task = thumbs?.renderThumb(meta.pageIndex, window.devicePixelRatio);\n task?.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef.current = objectUrl;\n setUrl(objectUrl);\n }, ignore);\n\n return () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n } else {\n task?.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n };\n }, [thumbs, meta.pageIndex, refreshTick]);\n\n const handleImageLoad = () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n }\n };\n\n return url ? <img src={url} onLoad={handleImageLoad} style={style} {...props} /> : null;\n}\n"],"names":["window"],"mappings":";;;;;;;AAGO,MAAM,qBAAqB,MAAM,UAA2B,gBAAgB,EAAE;AAC9E,MAAM,yBAAyB,MAAM,cAA+B,gBAAgB,EAAE;ACStF,SAAS,eAAe,EAAE,OAAO,eAAe,cAAc,GAAG,SAA0B;AAChG,QAAM,EAAE,QAAQ,gBAAgB,IAAI,mBAAmB;AACjD,QAAA,cAAc,OAAuB,IAAI;AAE/C,QAAM,CAACA,SAAQ,SAAS,IAAI,SAA6B,IAAI;AAG7D,YAAU,MAAM,mDAAiB,SAAS,YAAY,CAAC,eAAe,CAAC;AAGvE,YAAU,MAAM;AACd,UAAM,KAAK,YAAY;AACvB,QAAI,CAAC,GAAI;AACT,UAAM,WAAW,MAAM,mDAAiB,aAAa,GAAG,WAAW,GAAG;AACnE,OAAA,iBAAiB,UAAU,QAAQ;AACtC,WAAO,MAAM,GAAG,oBAAoB,UAAU,QAAQ;AAAA,EAAA,GACrD,CAAC,eAAe,CAAC;AAGpB,YAAU,MAAM;AACd,UAAM,KAAK,YAAY;AACnB,QAAA,CAAC,MAAM,CAAC,gBAAiB;AAEvB,UAAA,iBAAiB,IAAI,eAAe,MAAM;AAC9C,sBAAgB,aAAa,GAAG,WAAW,GAAG,YAAY;AAAA,IAAA,CAC3D;AACD,mBAAe,QAAQ,EAAE;AAElB,WAAA,MAAM,eAAe,WAAW;AAAA,EAAA,GACtC,CAAC,eAAe,CAAC;AAGpB,YAAU,MAAM;AACd,UAAM,KAAK,YAAY;AACnB,QAAA,CAAC,MAAM,CAAC,gBAAiB;AAG7B,oBAAgB,aAAa,GAAG,WAAW,GAAG,YAAY;AAAA,EAAA,GACzD,CAACA,SAAQ,eAAe,CAAC;AAG5B,YAAU,MAAM;AACd,UAAM,KAAK,YAAY;AACvB,QAAI,CAAC,MAAM,CAAC,mBAAmB,CAACA,QAAQ;AAExC,WAAO,gBAAgB,WAAW,CAAC,EAAE,KAAK,eAAe;AACvD,SAAG,SAAS,EAAE,KAAK,SAAA,CAAU;AAAA,IAAA,CAC9B;AAAA,KACA,CAAC,iBAAiB,CAAC,CAACA,OAAM,CAAC;AAExB,QAAA,YAAW,mDAAiB,IAAI,aAAY;AAGhD,SAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK;AAAA,MACL,OAAO;AAAA,QACL,WAAW;AAAA,QACX,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,QAAQ;AAAA,QACR,GAAG;AAAA,MACL;AAAA,MACC,GAAG;AAAA,MAEJ,UAAA,oBAAC,SAAI,OAAO,EAAE,SAAQA,WAAA,gBAAAA,QAAQ,gBAAe,GAAG,UAAU,WAAA,GACvD,UAAQA,WAAA,gBAAAA,QAAA,MAAM,IAAI,CAAC,MAAM,MAAM,SAAS,CAAC,GAC5C,CAAA;AAAA,IAAA;AAAA,EACF;AAEJ;ACzEO,SAAS,SAAS,EAAE,MAAM,OAAO,GAAG,SAA4B;AACrE,QAAM,EAAE,UAAU,OAAO,IAAI,uBAAuB;AACpD,QAAM,EAAE,QAAQ,gBAAgB,IAAI,mBAAmB;AACvD,QAAM,CAAC,KAAK,MAAM,IAAI,SAAiB;AACjC,QAAA,SAAS,OAAsB,IAAI;AACzC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,CAAC;AAEhD,YAAU,MAAM;AACd,QAAI,CAAC,gBAAiB;AACf,WAAA,gBAAgB,eAAe,CAAC,UAAU;AAC/C,UAAI,MAAM,SAAS,KAAK,SAAS,GAAG;AACnB,uBAAA,CAAC,SAAS,OAAO,CAAC;AAAA,MAAA;AAAA,IACnC,CACD;AAAA,EAAA,GACA,CAAC,eAAe,CAAC;AAEpB,YAAU,MAAM;AACd,UAAM,OAAO,iCAAQ,YAAY,KAAK,WAAW,OAAO;AAClD,iCAAA,KAAK,CAAC,SAAS;AACb,YAAA,YAAY,IAAI,gBAAgB,IAAI;AAC1C,aAAO,UAAU;AACjB,aAAO,SAAS;AAAA,OACf;AAEH,WAAO,MAAM;AACX,UAAI,OAAO,SAAS;AACd,YAAA,gBAAgB,OAAO,OAAO;AAClC,eAAO,UAAU;AAAA,MAAA,OACZ;AACL,qCAAM,MAAM;AAAA,UACV,MAAM,aAAa;AAAA,UACnB,SAAS;AAAA,QAAA;AAAA,MACV;AAAA,IAEL;AAAA,KACC,CAAC,QAAQ,KAAK,WAAW,WAAW,CAAC;AAExC,QAAM,kBAAkB,MAAM;AAC5B,QAAI,OAAO,SAAS;AACd,UAAA,gBAAgB,OAAO,OAAO;AAClC,aAAO,UAAU;AAAA,IAAA;AAAA,EAErB;AAEO,SAAA,MAAO,oBAAA,OAAA,EAAI,KAAK,KAAK,QAAQ,iBAAiB,OAAe,GAAG,MAAA,CAAO,IAAK;AACrF;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/react"),t=require("@embedpdf/plugin-thumbnail"),r=require("react/jsx-runtime"),n=require("react"),l=require("@embedpdf/models"),i=()=>e.usePlugin(t.ThumbnailPlugin.id),o=()=>e.useCapability(t.ThumbnailPlugin.id);exports.ThumbImg=function({meta:e,style:t,...s}){const{provides:u}=o(),{plugin:c}=i(),[a,d]=n.useState(),p=n.useRef(null),[f,g]=n.useState(0);return n.useEffect((()=>{if(c)return c.onRefreshPages((t=>{t.includes(e.pageIndex)&&g((e=>e+1))}))}),[c]),n.useEffect((()=>{const t=null==u?void 0:u.renderThumb(e.pageIndex,window.devicePixelRatio);return null==t||t.wait((e=>{const t=URL.createObjectURL(e);p.current=t,d(t)}),l.ignore),()=>{p.current?(URL.revokeObjectURL(p.current),p.current=null):null==t||t.abort({code:l.PdfErrorCode.Cancelled,message:"canceled render task"})}}),[u,e.pageIndex,f]),a?r.jsx("img",{src:a,onLoad:()=>{p.current&&(URL.revokeObjectURL(p.current),p.current=null)},style:t,...s}):null},exports.ThumbnailsPane=function({style:e,selectedPage:t,scrollOptions:l={behavior:"smooth",block:"nearest",inline:"nearest"},...i}){const{provides:s}=o(),u=n.useRef(null),[c,a]=n.useState(null);return n.useEffect((()=>null==s?void 0:s.onWindow(a)),[s]),n.useEffect((()=>{const e=u.current;if(!e)return;const t=()=>null==s?void 0:s.setViewport(e.scrollTop,e.clientHeight);return e.addEventListener("scroll",t),()=>e.removeEventListener("scroll",t)}),[s]),n.useEffect((()=>{const e=u.current;e&&s&&0===(null==c?void 0:c.items.length)&&s.setViewport(e.scrollTop,e.clientHeight)}),[c,s]),n.useEffect((()=>{if(!t||!c)return;const e=c.items.find((e=>e.pageIndex+1===t));if(!e)return;const r=u.current;if(!r)return;e.top<r.scrollTop+8?r.scrollTo({top:e.top,...l}):e.top+e.wrapperHeight+e.labelHeight>r.scrollTop+r.clientHeight-8&&r.scrollTo({top:e.top+e.wrapperHeight+e.labelHeight-r.clientHeight,...l})}),[t,c,l]),r.jsx("div",{ref:u,style:{overflowY:"auto",position:"relative",...e},...i,children:r.jsx("div",{style:{height:(null==c?void 0:c.totalHeight)??0,position:"relative"},children:null==c?void 0:c.items.map((e=>i.children(e)))})})},exports.useThumbnailCapability=o,exports.useThumbnailPlugin=i,Object.keys(t).forEach((e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})}));
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/react"),t=require("@embedpdf/plugin-thumbnail"),r=require("react/jsx-runtime"),n=require("react"),o=require("@embedpdf/models"),l=()=>e.usePlugin(t.ThumbnailPlugin.id),i=()=>e.useCapability(t.ThumbnailPlugin.id);exports.ThumbImg=function({meta:e,style:t,...u}){const{provides:s}=i(),{plugin:c}=l(),[d,a]=n.useState(),p=n.useRef(null),[f,g]=n.useState(0);return n.useEffect((()=>{if(c)return c.onRefreshPages((t=>{t.includes(e.pageIndex)&&g((e=>e+1))}))}),[c]),n.useEffect((()=>{const t=null==s?void 0:s.renderThumb(e.pageIndex,window.devicePixelRatio);return null==t||t.wait((e=>{const t=URL.createObjectURL(e);p.current=t,a(t)}),o.ignore),()=>{p.current?(URL.revokeObjectURL(p.current),p.current=null):null==t||t.abort({code:o.PdfErrorCode.Cancelled,message:"canceled render task"})}}),[s,e.pageIndex,f]),d?r.jsx("img",{src:d,onLoad:()=>{p.current&&(URL.revokeObjectURL(p.current),p.current=null)},style:t,...u}):null},exports.ThumbnailsPane=function({style:e,scrollOptions:t,selectedPage:o,...i}){const{plugin:u}=l(),s=n.useRef(null),[c,d]=n.useState(null);n.useEffect((()=>null==u?void 0:u.onWindow(d)),[u]),n.useEffect((()=>{const e=s.current;if(!e)return;const t=()=>null==u?void 0:u.updateWindow(e.scrollTop,e.clientHeight);return e.addEventListener("scroll",t),()=>e.removeEventListener("scroll",t)}),[u]),n.useEffect((()=>{const e=s.current;if(!e||!u)return;const t=new ResizeObserver((()=>{u.updateWindow(e.scrollTop,e.clientHeight)}));return t.observe(e),()=>t.disconnect()}),[u]),n.useEffect((()=>{const e=s.current;e&&u&&u.updateWindow(e.scrollTop,e.clientHeight)}),[c,u]),n.useEffect((()=>{const e=s.current;if(e&&u&&c)return u.onScrollTo((({top:t,behavior:r})=>{e.scrollTo({top:t,behavior:r})}))}),[u,!!c]);const a=(null==u?void 0:u.cfg.paddingY)??0;return r.jsx("div",{ref:s,style:{overflowY:"auto",position:"relative",paddingTop:a,paddingBottom:a,height:"100%",...e},...i,children:r.jsx("div",{style:{height:(null==c?void 0:c.totalHeight)??0,position:"relative"},children:null==c?void 0:c.items.map((e=>i.children(e)))})})},exports.useThumbnailCapability=i,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/shared/hooks/use-thumbnail.ts","../../src/shared/components/thumbnail-img.tsx","../../src/shared/components/thumbnails-pane.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","import { useEffect, useState, useRef, HTMLAttributes, CSSProperties, Fragment } from '@framework';\nimport { ThumbMeta } from '@embedpdf/plugin-thumbnail';\nimport { ignore, PdfErrorCode } from '@embedpdf/models';\nimport { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\n\ntype ThumbnailImgProps = Omit<HTMLAttributes<HTMLImageElement>, 'style'> & {\n style?: CSSProperties;\n meta: ThumbMeta;\n};\n\nexport function ThumbImg({ meta, style, ...props }: ThumbnailImgProps) {\n const { provides: thumbs } = useThumbnailCapability();\n const { plugin: thumbnailPlugin } = useThumbnailPlugin();\n const [url, setUrl] = useState<string>();\n const urlRef = useRef<string | null>(null);\n const [refreshTick, setRefreshTick] = useState(0);\n\n useEffect(() => {\n if (!thumbnailPlugin) return;\n return thumbnailPlugin.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n setRefreshTick((tick) => tick + 1);\n }\n });\n }, [thumbnailPlugin]);\n\n useEffect(() => {\n const task = thumbs?.renderThumb(meta.pageIndex, window.devicePixelRatio);\n task?.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef.current = objectUrl;\n setUrl(objectUrl);\n }, ignore);\n\n return () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n } else {\n task?.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n };\n }, [thumbs, meta.pageIndex, refreshTick]);\n\n const handleImageLoad = () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n }\n };\n\n return url ? <img src={url} onLoad={handleImageLoad} style={style} {...props} /> : null;\n}\n","import { useEffect, useRef, useState, HTMLAttributes, CSSProperties, ReactNode } from '@framework';\nimport { ThumbMeta, WindowState } from '@embedpdf/plugin-thumbnail';\nimport { useThumbnailCapability } from '../hooks';\n\ntype ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {\n style?: CSSProperties;\n children: (m: ThumbMeta) => ReactNode;\n selectedPage?: number;\n scrollOptions?: ScrollIntoViewOptions;\n};\n\nexport function ThumbnailsPane({\n style,\n selectedPage,\n scrollOptions = { behavior: 'smooth', block: 'nearest', inline: 'nearest' },\n ...props\n}: ThumbnailsProps) {\n const { provides: thumbs } = useThumbnailCapability();\n const viewportRef = useRef<HTMLDivElement>(null);\n\n const [window, setWindow] = useState<WindowState | null>(null);\n\n /* 1️⃣ subscribe once to window updates */\n useEffect(() => thumbs?.onWindow(setWindow), [thumbs]);\n\n /* 2️⃣ keep plugin in sync while the user scrolls */\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp) return;\n const onScroll = () => thumbs?.setViewport(vp.scrollTop, vp.clientHeight);\n vp.addEventListener('scroll', onScroll);\n return () => vp.removeEventListener('scroll', onScroll);\n }, [thumbs]);\n\n /* 3️⃣ kick-start (or re-kick) after document change */\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbs) return;\n\n if (window?.items.length === 0) {\n thumbs.setViewport(vp.scrollTop, vp.clientHeight);\n }\n }, [window, thumbs]);\n\n /* 4️⃣ whenever selectedPage or window changes, ensure it’s visible */\n useEffect(() => {\n if (!selectedPage || !window) return;\n\n const item = window.items.find((it) => it.pageIndex + 1 === selectedPage);\n if (!item) return; // not in current window yet wait for next update\n\n const vp = viewportRef.current;\n if (!vp) return;\n\n // Scroll only if the item is above or below the viewport “padding” zone\n const margin = 8; // px\n if (item.top < vp.scrollTop + margin) {\n vp.scrollTo({ top: item.top, ...scrollOptions });\n } else if (\n item.top + item.wrapperHeight + item.labelHeight >\n vp.scrollTop + vp.clientHeight - margin\n ) {\n vp.scrollTo({\n top: item.top + item.wrapperHeight + item.labelHeight - vp.clientHeight,\n ...scrollOptions,\n });\n }\n }, [selectedPage, window, scrollOptions]);\n\n return (\n <div ref={viewportRef} style={{ overflowY: 'auto', position: 'relative', ...style }} {...props}>\n {/* spacer keeps correct scroll height even before first window arrives */}\n <div style={{ height: window?.totalHeight ?? 0, position: 'relative' }}>\n {window?.items.map((m) => props.children(m))}\n </div>\n </div>\n );\n}\n"],"names":["useThumbnailPlugin","usePlugin","ThumbnailPlugin","id","useThumbnailCapability","useCapability","meta","style","props","provides","thumbs","plugin","thumbnailPlugin","url","setUrl","useState","urlRef","useRef","refreshTick","setRefreshTick","useEffect","onRefreshPages","pages","includes","pageIndex","tick","task","renderThumb","window","devicePixelRatio","wait","blob","objectUrl","URL","createObjectURL","current","ignore","revokeObjectURL","abort","code","PdfErrorCode","Cancelled","message","jsx","src","onLoad","selectedPage","scrollOptions","behavior","block","inline","viewportRef","setWindow","onWindow","vp","onScroll","setViewport","scrollTop","clientHeight","addEventListener","removeEventListener","items","length","item","find","it","top","scrollTo","wrapperHeight","labelHeight","ref","overflowY","position","children","height","totalHeight","map","m"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-thumbnail.ts","../../src/shared/components/thumbnail-img.tsx","../../src/shared/components/thumbnails-pane.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","import { useEffect, useState, useRef, HTMLAttributes, CSSProperties, Fragment } from '@framework';\nimport { ThumbMeta } from '@embedpdf/plugin-thumbnail';\nimport { ignore, PdfErrorCode } from '@embedpdf/models';\nimport { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\n\ntype ThumbnailImgProps = Omit<HTMLAttributes<HTMLImageElement>, 'style'> & {\n style?: CSSProperties;\n meta: ThumbMeta;\n};\n\nexport function ThumbImg({ meta, style, ...props }: ThumbnailImgProps) {\n const { provides: thumbs } = useThumbnailCapability();\n const { plugin: thumbnailPlugin } = useThumbnailPlugin();\n const [url, setUrl] = useState<string>();\n const urlRef = useRef<string | null>(null);\n const [refreshTick, setRefreshTick] = useState(0);\n\n useEffect(() => {\n if (!thumbnailPlugin) return;\n return thumbnailPlugin.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n setRefreshTick((tick) => tick + 1);\n }\n });\n }, [thumbnailPlugin]);\n\n useEffect(() => {\n const task = thumbs?.renderThumb(meta.pageIndex, window.devicePixelRatio);\n task?.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef.current = objectUrl;\n setUrl(objectUrl);\n }, ignore);\n\n return () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n } else {\n task?.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n };\n }, [thumbs, meta.pageIndex, refreshTick]);\n\n const handleImageLoad = () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n }\n };\n\n return url ? <img src={url} onLoad={handleImageLoad} style={style} {...props} /> : null;\n}\n","import { useEffect, useRef, useState, HTMLAttributes, CSSProperties, ReactNode } from '@framework';\nimport { ThumbMeta, WindowState } from '@embedpdf/plugin-thumbnail';\nimport { useThumbnailPlugin } from '../hooks';\n\ntype ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {\n style?: CSSProperties;\n children: (m: ThumbMeta) => ReactNode;\n /** @deprecated use scrollToThumb via capability or rely on autoScroll */\n selectedPage?: number;\n /** @deprecated behavior is now controlled by ThumbnailPluginConfig.scrollBehavior */\n scrollOptions?: ScrollIntoViewOptions;\n};\n\nexport function ThumbnailsPane({ style, scrollOptions, selectedPage, ...props }: ThumbnailsProps) {\n const { plugin: thumbnailPlugin } = useThumbnailPlugin();\n const viewportRef = useRef<HTMLDivElement>(null);\n\n const [window, setWindow] = useState<WindowState | null>(null);\n\n // 1) subscribe once to window updates\n useEffect(() => thumbnailPlugin?.onWindow(setWindow), [thumbnailPlugin]);\n\n // 2) keep plugin in sync while the user scrolls\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp) return;\n const onScroll = () => thumbnailPlugin?.updateWindow(vp.scrollTop, vp.clientHeight);\n vp.addEventListener('scroll', onScroll);\n return () => vp.removeEventListener('scroll', onScroll);\n }, [thumbnailPlugin]);\n\n // 2.5) keep plugin in sync when viewport resizes (e.g., menu opens/closes)\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbnailPlugin) return;\n\n const resizeObserver = new ResizeObserver(() => {\n thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n resizeObserver.observe(vp);\n\n return () => resizeObserver.disconnect();\n }, [thumbnailPlugin]);\n\n // 3) kick-start after document change\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbnailPlugin) return;\n\n // push initial metrics\n thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);\n }, [window, thumbnailPlugin]);\n\n // 4) let plugin drive scroll only after window is set, and only once\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbnailPlugin || !window) return;\n\n return thumbnailPlugin.onScrollTo(({ top, behavior }) => {\n vp.scrollTo({ top, behavior });\n });\n }, [thumbnailPlugin, !!window]); // Note: !!window to prevent re-subscription on window updates\n\n const paddingY = thumbnailPlugin?.cfg.paddingY ?? 0;\n\n return (\n <div\n ref={viewportRef}\n style={{\n overflowY: 'auto',\n position: 'relative',\n paddingTop: paddingY,\n paddingBottom: paddingY,\n height: '100%',\n ...style,\n }}\n {...props}\n >\n <div style={{ height: window?.totalHeight ?? 0, position: 'relative' }}>\n {window?.items.map((m) => props.children(m))}\n </div>\n </div>\n );\n}\n"],"names":["useThumbnailPlugin","usePlugin","ThumbnailPlugin","id","useThumbnailCapability","useCapability","meta","style","props","provides","thumbs","plugin","thumbnailPlugin","url","setUrl","useState","urlRef","useRef","refreshTick","setRefreshTick","useEffect","onRefreshPages","pages","includes","pageIndex","tick","task","renderThumb","window","devicePixelRatio","wait","blob","objectUrl","URL","createObjectURL","current","ignore","revokeObjectURL","abort","code","PdfErrorCode","Cancelled","message","jsx","src","onLoad","scrollOptions","selectedPage","viewportRef","setWindow","onWindow","vp","onScroll","updateWindow","scrollTop","clientHeight","addEventListener","removeEventListener","resizeObserver","ResizeObserver","observe","disconnect","onScrollTo","top","behavior","scrollTo","paddingY","cfg","jsxRuntime","ref","overflowY","position","paddingTop","paddingBottom","height","children","totalHeight","items","map","m"],"mappings":"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"}
@@ -6,47 +6,56 @@ import { useRef, useState, useEffect } from "react";
6
6
  import { ignore, PdfErrorCode } from "@embedpdf/models";
7
7
  const useThumbnailPlugin = () => usePlugin(ThumbnailPlugin.id);
8
8
  const useThumbnailCapability = () => useCapability(ThumbnailPlugin.id);
9
- function ThumbnailsPane({
10
- style,
11
- selectedPage,
12
- scrollOptions = { behavior: "smooth", block: "nearest", inline: "nearest" },
13
- ...props
14
- }) {
15
- const { provides: thumbs } = useThumbnailCapability();
9
+ function ThumbnailsPane({ style, scrollOptions, selectedPage, ...props }) {
10
+ const { plugin: thumbnailPlugin } = useThumbnailPlugin();
16
11
  const viewportRef = useRef(null);
17
12
  const [window2, setWindow] = useState(null);
18
- useEffect(() => thumbs == null ? void 0 : thumbs.onWindow(setWindow), [thumbs]);
13
+ useEffect(() => thumbnailPlugin == null ? void 0 : thumbnailPlugin.onWindow(setWindow), [thumbnailPlugin]);
19
14
  useEffect(() => {
20
15
  const vp = viewportRef.current;
21
16
  if (!vp) return;
22
- const onScroll = () => thumbs == null ? void 0 : thumbs.setViewport(vp.scrollTop, vp.clientHeight);
17
+ const onScroll = () => thumbnailPlugin == null ? void 0 : thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);
23
18
  vp.addEventListener("scroll", onScroll);
24
19
  return () => vp.removeEventListener("scroll", onScroll);
25
- }, [thumbs]);
20
+ }, [thumbnailPlugin]);
26
21
  useEffect(() => {
27
22
  const vp = viewportRef.current;
28
- if (!vp || !thumbs) return;
29
- if ((window2 == null ? void 0 : window2.items.length) === 0) {
30
- thumbs.setViewport(vp.scrollTop, vp.clientHeight);
31
- }
32
- }, [window2, thumbs]);
23
+ if (!vp || !thumbnailPlugin) return;
24
+ const resizeObserver = new ResizeObserver(() => {
25
+ thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);
26
+ });
27
+ resizeObserver.observe(vp);
28
+ return () => resizeObserver.disconnect();
29
+ }, [thumbnailPlugin]);
33
30
  useEffect(() => {
34
- if (!selectedPage || !window2) return;
35
- const item = window2.items.find((it) => it.pageIndex + 1 === selectedPage);
36
- if (!item) return;
37
31
  const vp = viewportRef.current;
38
- if (!vp) return;
39
- const margin = 8;
40
- if (item.top < vp.scrollTop + margin) {
41
- vp.scrollTo({ top: item.top, ...scrollOptions });
42
- } else if (item.top + item.wrapperHeight + item.labelHeight > vp.scrollTop + vp.clientHeight - margin) {
43
- vp.scrollTo({
44
- top: item.top + item.wrapperHeight + item.labelHeight - vp.clientHeight,
45
- ...scrollOptions
46
- });
32
+ if (!vp || !thumbnailPlugin) return;
33
+ thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);
34
+ }, [window2, thumbnailPlugin]);
35
+ useEffect(() => {
36
+ const vp = viewportRef.current;
37
+ if (!vp || !thumbnailPlugin || !window2) return;
38
+ return thumbnailPlugin.onScrollTo(({ top, behavior }) => {
39
+ vp.scrollTo({ top, behavior });
40
+ });
41
+ }, [thumbnailPlugin, !!window2]);
42
+ const paddingY = (thumbnailPlugin == null ? void 0 : thumbnailPlugin.cfg.paddingY) ?? 0;
43
+ return /* @__PURE__ */ jsx(
44
+ "div",
45
+ {
46
+ ref: viewportRef,
47
+ style: {
48
+ overflowY: "auto",
49
+ position: "relative",
50
+ paddingTop: paddingY,
51
+ paddingBottom: paddingY,
52
+ height: "100%",
53
+ ...style
54
+ },
55
+ ...props,
56
+ children: /* @__PURE__ */ jsx("div", { style: { height: (window2 == null ? void 0 : window2.totalHeight) ?? 0, position: "relative" }, children: window2 == null ? void 0 : window2.items.map((m) => props.children(m)) })
47
57
  }
48
- }, [selectedPage, window2, scrollOptions]);
49
- return /* @__PURE__ */ jsx("div", { ref: viewportRef, style: { overflowY: "auto", position: "relative", ...style }, ...props, children: /* @__PURE__ */ jsx("div", { style: { height: (window2 == null ? void 0 : window2.totalHeight) ?? 0, position: "relative" }, children: window2 == null ? void 0 : window2.items.map((m) => props.children(m)) }) });
58
+ );
50
59
  }
51
60
  function ThumbImg({ meta, style, ...props }) {
52
61
  const { provides: thumbs } = useThumbnailCapability();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-thumbnail.ts","../../src/shared/components/thumbnails-pane.tsx","../../src/shared/components/thumbnail-img.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","import { useEffect, useRef, useState, HTMLAttributes, CSSProperties, ReactNode } from '@framework';\nimport { ThumbMeta, WindowState } from '@embedpdf/plugin-thumbnail';\nimport { useThumbnailCapability } from '../hooks';\n\ntype ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {\n style?: CSSProperties;\n children: (m: ThumbMeta) => ReactNode;\n selectedPage?: number;\n scrollOptions?: ScrollIntoViewOptions;\n};\n\nexport function ThumbnailsPane({\n style,\n selectedPage,\n scrollOptions = { behavior: 'smooth', block: 'nearest', inline: 'nearest' },\n ...props\n}: ThumbnailsProps) {\n const { provides: thumbs } = useThumbnailCapability();\n const viewportRef = useRef<HTMLDivElement>(null);\n\n const [window, setWindow] = useState<WindowState | null>(null);\n\n /* 1️⃣ subscribe once to window updates */\n useEffect(() => thumbs?.onWindow(setWindow), [thumbs]);\n\n /* 2️⃣ keep plugin in sync while the user scrolls */\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp) return;\n const onScroll = () => thumbs?.setViewport(vp.scrollTop, vp.clientHeight);\n vp.addEventListener('scroll', onScroll);\n return () => vp.removeEventListener('scroll', onScroll);\n }, [thumbs]);\n\n /* 3️⃣ kick-start (or re-kick) after document change */\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbs) return;\n\n if (window?.items.length === 0) {\n thumbs.setViewport(vp.scrollTop, vp.clientHeight);\n }\n }, [window, thumbs]);\n\n /* 4️⃣ whenever selectedPage or window changes, ensure it’s visible */\n useEffect(() => {\n if (!selectedPage || !window) return;\n\n const item = window.items.find((it) => it.pageIndex + 1 === selectedPage);\n if (!item) return; // not in current window yet wait for next update\n\n const vp = viewportRef.current;\n if (!vp) return;\n\n // Scroll only if the item is above or below the viewport “padding” zone\n const margin = 8; // px\n if (item.top < vp.scrollTop + margin) {\n vp.scrollTo({ top: item.top, ...scrollOptions });\n } else if (\n item.top + item.wrapperHeight + item.labelHeight >\n vp.scrollTop + vp.clientHeight - margin\n ) {\n vp.scrollTo({\n top: item.top + item.wrapperHeight + item.labelHeight - vp.clientHeight,\n ...scrollOptions,\n });\n }\n }, [selectedPage, window, scrollOptions]);\n\n return (\n <div ref={viewportRef} style={{ overflowY: 'auto', position: 'relative', ...style }} {...props}>\n {/* spacer keeps correct scroll height even before first window arrives */}\n <div style={{ height: window?.totalHeight ?? 0, position: 'relative' }}>\n {window?.items.map((m) => props.children(m))}\n </div>\n </div>\n );\n}\n","import { useEffect, useState, useRef, HTMLAttributes, CSSProperties, Fragment } from '@framework';\nimport { ThumbMeta } from '@embedpdf/plugin-thumbnail';\nimport { ignore, PdfErrorCode } from '@embedpdf/models';\nimport { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\n\ntype ThumbnailImgProps = Omit<HTMLAttributes<HTMLImageElement>, 'style'> & {\n style?: CSSProperties;\n meta: ThumbMeta;\n};\n\nexport function ThumbImg({ meta, style, ...props }: ThumbnailImgProps) {\n const { provides: thumbs } = useThumbnailCapability();\n const { plugin: thumbnailPlugin } = useThumbnailPlugin();\n const [url, setUrl] = useState<string>();\n const urlRef = useRef<string | null>(null);\n const [refreshTick, setRefreshTick] = useState(0);\n\n useEffect(() => {\n if (!thumbnailPlugin) return;\n return thumbnailPlugin.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n setRefreshTick((tick) => tick + 1);\n }\n });\n }, [thumbnailPlugin]);\n\n useEffect(() => {\n const task = thumbs?.renderThumb(meta.pageIndex, window.devicePixelRatio);\n task?.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef.current = objectUrl;\n setUrl(objectUrl);\n }, ignore);\n\n return () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n } else {\n task?.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n };\n }, [thumbs, meta.pageIndex, refreshTick]);\n\n const handleImageLoad = () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n }\n };\n\n return url ? <img src={url} onLoad={handleImageLoad} style={style} {...props} /> : null;\n}\n"],"names":["window"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-thumbnail.ts","../../src/shared/components/thumbnails-pane.tsx","../../src/shared/components/thumbnail-img.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { ThumbnailPlugin } from '@embedpdf/plugin-thumbnail';\n\nexport const useThumbnailPlugin = () => usePlugin<ThumbnailPlugin>(ThumbnailPlugin.id);\nexport const useThumbnailCapability = () => useCapability<ThumbnailPlugin>(ThumbnailPlugin.id);\n","import { useEffect, useRef, useState, HTMLAttributes, CSSProperties, ReactNode } from '@framework';\nimport { ThumbMeta, WindowState } from '@embedpdf/plugin-thumbnail';\nimport { useThumbnailPlugin } from '../hooks';\n\ntype ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {\n style?: CSSProperties;\n children: (m: ThumbMeta) => ReactNode;\n /** @deprecated use scrollToThumb via capability or rely on autoScroll */\n selectedPage?: number;\n /** @deprecated behavior is now controlled by ThumbnailPluginConfig.scrollBehavior */\n scrollOptions?: ScrollIntoViewOptions;\n};\n\nexport function ThumbnailsPane({ style, scrollOptions, selectedPage, ...props }: ThumbnailsProps) {\n const { plugin: thumbnailPlugin } = useThumbnailPlugin();\n const viewportRef = useRef<HTMLDivElement>(null);\n\n const [window, setWindow] = useState<WindowState | null>(null);\n\n // 1) subscribe once to window updates\n useEffect(() => thumbnailPlugin?.onWindow(setWindow), [thumbnailPlugin]);\n\n // 2) keep plugin in sync while the user scrolls\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp) return;\n const onScroll = () => thumbnailPlugin?.updateWindow(vp.scrollTop, vp.clientHeight);\n vp.addEventListener('scroll', onScroll);\n return () => vp.removeEventListener('scroll', onScroll);\n }, [thumbnailPlugin]);\n\n // 2.5) keep plugin in sync when viewport resizes (e.g., menu opens/closes)\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbnailPlugin) return;\n\n const resizeObserver = new ResizeObserver(() => {\n thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);\n });\n resizeObserver.observe(vp);\n\n return () => resizeObserver.disconnect();\n }, [thumbnailPlugin]);\n\n // 3) kick-start after document change\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbnailPlugin) return;\n\n // push initial metrics\n thumbnailPlugin.updateWindow(vp.scrollTop, vp.clientHeight);\n }, [window, thumbnailPlugin]);\n\n // 4) let plugin drive scroll only after window is set, and only once\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || !thumbnailPlugin || !window) return;\n\n return thumbnailPlugin.onScrollTo(({ top, behavior }) => {\n vp.scrollTo({ top, behavior });\n });\n }, [thumbnailPlugin, !!window]); // Note: !!window to prevent re-subscription on window updates\n\n const paddingY = thumbnailPlugin?.cfg.paddingY ?? 0;\n\n return (\n <div\n ref={viewportRef}\n style={{\n overflowY: 'auto',\n position: 'relative',\n paddingTop: paddingY,\n paddingBottom: paddingY,\n height: '100%',\n ...style,\n }}\n {...props}\n >\n <div style={{ height: window?.totalHeight ?? 0, position: 'relative' }}>\n {window?.items.map((m) => props.children(m))}\n </div>\n </div>\n );\n}\n","import { useEffect, useState, useRef, HTMLAttributes, CSSProperties, Fragment } from '@framework';\nimport { ThumbMeta } from '@embedpdf/plugin-thumbnail';\nimport { ignore, PdfErrorCode } from '@embedpdf/models';\nimport { useThumbnailCapability, useThumbnailPlugin } from '../hooks';\n\ntype ThumbnailImgProps = Omit<HTMLAttributes<HTMLImageElement>, 'style'> & {\n style?: CSSProperties;\n meta: ThumbMeta;\n};\n\nexport function ThumbImg({ meta, style, ...props }: ThumbnailImgProps) {\n const { provides: thumbs } = useThumbnailCapability();\n const { plugin: thumbnailPlugin } = useThumbnailPlugin();\n const [url, setUrl] = useState<string>();\n const urlRef = useRef<string | null>(null);\n const [refreshTick, setRefreshTick] = useState(0);\n\n useEffect(() => {\n if (!thumbnailPlugin) return;\n return thumbnailPlugin.onRefreshPages((pages) => {\n if (pages.includes(meta.pageIndex)) {\n setRefreshTick((tick) => tick + 1);\n }\n });\n }, [thumbnailPlugin]);\n\n useEffect(() => {\n const task = thumbs?.renderThumb(meta.pageIndex, window.devicePixelRatio);\n task?.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef.current = objectUrl;\n setUrl(objectUrl);\n }, ignore);\n\n return () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n } else {\n task?.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n };\n }, [thumbs, meta.pageIndex, refreshTick]);\n\n const handleImageLoad = () => {\n if (urlRef.current) {\n URL.revokeObjectURL(urlRef.current);\n urlRef.current = null;\n }\n };\n\n return url ? <img src={url} onLoad={handleImageLoad} style={style} {...props} /> : null;\n}\n"],"names":["window"],"mappings":"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"}
@@ -3,8 +3,10 @@ import { ThumbMeta } from '../../lib/index.ts';
3
3
  type ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {
4
4
  style?: CSSProperties;
5
5
  children: (m: ThumbMeta) => ReactNode;
6
+ /** @deprecated use scrollToThumb via capability or rely on autoScroll */
6
7
  selectedPage?: number;
8
+ /** @deprecated behavior is now controlled by ThumbnailPluginConfig.scrollBehavior */
7
9
  scrollOptions?: ScrollIntoViewOptions;
8
10
  };
9
- export declare function ThumbnailsPane({ style, selectedPage, scrollOptions, ...props }: ThumbnailsProps): import("preact").JSX.Element;
11
+ export declare function ThumbnailsPane({ style, scrollOptions, selectedPage, ...props }: ThumbnailsProps): import("preact").JSX.Element;
10
12
  export {};
@@ -3,8 +3,10 @@ import { ThumbMeta } from '../../lib/index.ts';
3
3
  type ThumbnailsProps = Omit<HTMLAttributes<HTMLDivElement>, 'style' | 'children'> & {
4
4
  style?: CSSProperties;
5
5
  children: (m: ThumbMeta) => ReactNode;
6
+ /** @deprecated use scrollToThumb via capability or rely on autoScroll */
6
7
  selectedPage?: number;
8
+ /** @deprecated behavior is now controlled by ThumbnailPluginConfig.scrollBehavior */
7
9
  scrollOptions?: ScrollIntoViewOptions;
8
10
  };
9
- export declare function ThumbnailsPane({ style, selectedPage, scrollOptions, ...props }: ThumbnailsProps): import("react/jsx-runtime").JSX.Element;
11
+ export declare function ThumbnailsPane({ style, scrollOptions, selectedPage, ...props }: ThumbnailsProps): import("react/jsx-runtime").JSX.Element;
10
12
  export {};
@@ -0,0 +1,2 @@
1
+ export { default as ThumbnailsPane } from './thumbnails-pane.vue';
2
+ export { default as ThumbImg } from './thumbnail-img.vue';
@@ -0,0 +1,6 @@
1
+ import { ThumbMeta } from '../../lib/index.ts';
2
+ type __VLS_Props = {
3
+ 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>;
6
+ export default _default;
@@ -0,0 +1,14 @@
1
+ declare var __VLS_1: {
2
+ meta: any;
3
+ };
4
+ type __VLS_Slots = {} & {
5
+ default?: (props: typeof __VLS_1) => any;
6
+ };
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>;
9
+ export default _default;
10
+ type __VLS_WithSlots<T, S> = T & {
11
+ new (): {
12
+ $slots: S;
13
+ };
14
+ };
@@ -0,0 +1 @@
1
+ export * from './use-thumbnail';
@@ -0,0 +1,3 @@
1
+ import { ThumbnailPlugin } from '../../lib/index.ts';
2
+ export declare const useThumbnailPlugin: () => import('@embedpdf/core/vue').PluginState<ThumbnailPlugin>;
3
+ export declare const useThumbnailCapability: () => import('@embedpdf/core/vue').CapabilityState<Readonly<import('../../lib/index.ts').ThumbnailCapability>>;
@@ -0,0 +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]})}));
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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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"}
@@ -0,0 +1,3 @@
1
+ export * from './hooks';
2
+ export * from './components';
3
+ export * from '../lib/index.ts';
@@ -0,0 +1,151 @@
1
+ import { usePlugin, useCapability } from "@embedpdf/core/vue";
2
+ import { ThumbnailPlugin } from "@embedpdf/plugin-thumbnail";
3
+ export * from "@embedpdf/plugin-thumbnail";
4
+ import { defineComponent, useAttrs, ref, watchEffect, onMounted, onBeforeUnmount, nextTick, createElementBlock, openBlock, mergeProps, unref, createElementVNode, normalizeStyle, Fragment, renderList, renderSlot, watch, createCommentVNode } from "vue";
5
+ import { ignore, PdfErrorCode } from "@embedpdf/models";
6
+ const useThumbnailPlugin = () => usePlugin(ThumbnailPlugin.id);
7
+ const useThumbnailCapability = () => useCapability(ThumbnailPlugin.id);
8
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
9
+ __name: "thumbnails-pane",
10
+ setup(__props) {
11
+ const attrs = useAttrs();
12
+ const { plugin: thumbnailPlugin } = useThumbnailPlugin();
13
+ const viewportRef = ref(null);
14
+ const windowState = ref(null);
15
+ let offWindow = null;
16
+ let offScrollTo = null;
17
+ watchEffect((onCleanup) => {
18
+ if (!thumbnailPlugin.value) return;
19
+ offWindow == null ? void 0 : offWindow();
20
+ offWindow = thumbnailPlugin.value.onWindow((w) => windowState.value = w);
21
+ onCleanup(() => offWindow == null ? void 0 : offWindow());
22
+ });
23
+ onMounted(() => {
24
+ const vp = viewportRef.value;
25
+ if (!vp || !thumbnailPlugin.value) return;
26
+ const onScroll = () => thumbnailPlugin.value.updateWindow(vp.scrollTop, vp.clientHeight);
27
+ vp.addEventListener("scroll", onScroll);
28
+ const resizeObserver = new ResizeObserver(() => {
29
+ thumbnailPlugin.value.updateWindow(vp.scrollTop, vp.clientHeight);
30
+ });
31
+ resizeObserver.observe(vp);
32
+ thumbnailPlugin.value.updateWindow(vp.scrollTop, vp.clientHeight);
33
+ onBeforeUnmount(() => {
34
+ vp.removeEventListener("scroll", onScroll);
35
+ resizeObserver.disconnect();
36
+ });
37
+ });
38
+ watchEffect((onCleanup) => {
39
+ const vp = viewportRef.value;
40
+ if (!vp || !thumbnailPlugin.value || !windowState.value) return;
41
+ offScrollTo = thumbnailPlugin.value.onScrollTo(({ top, behavior }) => {
42
+ nextTick(() => {
43
+ vp.scrollTo({ top, behavior });
44
+ });
45
+ });
46
+ onCleanup(() => offScrollTo == null ? void 0 : offScrollTo());
47
+ });
48
+ onBeforeUnmount(() => {
49
+ offWindow == null ? void 0 : offWindow();
50
+ offScrollTo == null ? void 0 : offScrollTo();
51
+ });
52
+ return (_ctx, _cache) => {
53
+ var _a, _b, _c, _d, _e, _f;
54
+ return openBlock(), createElementBlock("div", mergeProps({
55
+ ref_key: "viewportRef",
56
+ ref: viewportRef,
57
+ style: {
58
+ overflowY: "auto",
59
+ position: "relative",
60
+ paddingTop: (((_b = (_a = unref(thumbnailPlugin)) == null ? void 0 : _a.cfg) == null ? void 0 : _b.paddingY) ?? 0) + "px",
61
+ paddingBottom: (((_d = (_c = unref(thumbnailPlugin)) == null ? void 0 : _c.cfg) == null ? void 0 : _d.paddingY) ?? 0) + "px",
62
+ height: "100%"
63
+ }
64
+ }, unref(attrs)), [
65
+ createElementVNode("div", {
66
+ style: normalizeStyle({ height: (((_e = windowState.value) == null ? void 0 : _e.totalHeight) ?? 0) + "px", position: "relative" })
67
+ }, [
68
+ (openBlock(true), createElementBlock(Fragment, null, renderList(((_f = windowState.value) == null ? void 0 : _f.items) ?? [], (m) => {
69
+ return renderSlot(_ctx.$slots, "default", {
70
+ key: m.pageIndex,
71
+ meta: m
72
+ });
73
+ }), 128))
74
+ ], 4)
75
+ ], 16);
76
+ };
77
+ }
78
+ });
79
+ const _hoisted_1 = ["src"];
80
+ const _sfc_main = /* @__PURE__ */ defineComponent({
81
+ __name: "thumbnail-img",
82
+ props: {
83
+ meta: {}
84
+ },
85
+ setup(__props) {
86
+ const props = __props;
87
+ const attrs = useAttrs();
88
+ const { provides: thumbs } = useThumbnailCapability();
89
+ const { plugin: thumbnailPlugin } = useThumbnailPlugin();
90
+ const url = ref(null);
91
+ let urlToRevoke = null;
92
+ const refreshTick = ref(0);
93
+ let offRefresh = null;
94
+ watchEffect((onCleanup) => {
95
+ if (!thumbnailPlugin.value) return;
96
+ offRefresh == null ? void 0 : offRefresh();
97
+ offRefresh = thumbnailPlugin.value.onRefreshPages((pages) => {
98
+ if (pages.includes(props.meta.pageIndex)) {
99
+ refreshTick.value++;
100
+ }
101
+ });
102
+ onCleanup(() => offRefresh == null ? void 0 : offRefresh());
103
+ });
104
+ function revoke() {
105
+ if (urlToRevoke) {
106
+ URL.revokeObjectURL(urlToRevoke);
107
+ urlToRevoke = null;
108
+ }
109
+ }
110
+ let abortTask = null;
111
+ function load() {
112
+ if (!thumbs.value) return;
113
+ const task = thumbs.value.renderThumb(props.meta.pageIndex, window.devicePixelRatio);
114
+ abortTask = () => task.abort({
115
+ code: PdfErrorCode.Cancelled,
116
+ message: "canceled render task"
117
+ });
118
+ task.wait((blob) => {
119
+ revoke();
120
+ const objectUrl = URL.createObjectURL(blob);
121
+ urlToRevoke = objectUrl;
122
+ url.value = objectUrl;
123
+ }, ignore);
124
+ }
125
+ watch(
126
+ () => [props.meta.pageIndex, refreshTick.value, !!thumbs.value],
127
+ () => {
128
+ abortTask == null ? void 0 : abortTask();
129
+ load();
130
+ },
131
+ { immediate: true }
132
+ );
133
+ onBeforeUnmount(() => {
134
+ abortTask == null ? void 0 : abortTask();
135
+ revoke();
136
+ });
137
+ return (_ctx, _cache) => {
138
+ return url.value ? (openBlock(), createElementBlock("img", mergeProps({
139
+ key: 0,
140
+ src: url.value
141
+ }, unref(attrs), { onLoad: revoke }), null, 16, _hoisted_1)) : createCommentVNode("", true);
142
+ };
143
+ }
144
+ });
145
+ export {
146
+ _sfc_main as ThumbImg,
147
+ _sfc_main$1 as ThumbnailsPane,
148
+ useThumbnailCapability,
149
+ useThumbnailPlugin
150
+ };
151
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","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":["_openBlock","_createElementBlock","_mergeProps","_unref","_createElementVNode","_normalizeStyle","_Fragment","_renderList","_renderSlot"],"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.4",
3
+ "version": "1.3.6",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.cjs",
@@ -21,24 +21,31 @@
21
21
  "types": "./dist/react/index.d.ts",
22
22
  "import": "./dist/react/index.js",
23
23
  "require": "./dist/react/index.cjs"
24
+ },
25
+ "./vue": {
26
+ "types": "./dist/vue/index.d.ts",
27
+ "import": "./dist/vue/index.js",
28
+ "require": "./dist/vue/index.cjs"
24
29
  }
25
30
  },
26
31
  "dependencies": {
27
- "@embedpdf/models": "1.3.4"
32
+ "@embedpdf/models": "1.3.6"
28
33
  },
29
34
  "devDependencies": {
30
35
  "@types/react": "^18.2.0",
31
36
  "typescript": "^5.0.0",
32
37
  "@embedpdf/build": "1.0.1",
33
- "@embedpdf/core": "1.3.4",
34
- "@embedpdf/plugin-render": "1.3.4"
38
+ "@embedpdf/plugin-render": "1.3.6",
39
+ "@embedpdf/plugin-scroll": "1.3.6",
40
+ "@embedpdf/core": "1.3.6"
35
41
  },
36
42
  "peerDependencies": {
37
43
  "react": ">=16.8.0",
38
44
  "react-dom": ">=16.8.0",
39
45
  "preact": "^10.26.4",
40
- "@embedpdf/core": "1.3.4",
41
- "@embedpdf/plugin-render": "1.3.4"
46
+ "vue": ">=3.2.0",
47
+ "@embedpdf/core": "1.3.6",
48
+ "@embedpdf/plugin-render": "1.3.6"
42
49
  },
43
50
  "files": [
44
51
  "dist",
@@ -60,7 +67,8 @@
60
67
  "build:base": "vite build --mode base",
61
68
  "build:react": "vite build --mode react",
62
69
  "build:preact": "vite build --mode preact",
63
- "build": "pnpm run clean && concurrently -c auto -n base,react,preact \"vite build --mode base\" \"vite build --mode react\" \"vite build --mode preact\"",
70
+ "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\"",
64
72
  "clean": "rimraf dist",
65
73
  "lint": "eslint src --color",
66
74
  "lint:fix": "eslint src --color --fix"