@embedpdf/plugin-tiling 2.4.1 → 2.5.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.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/models"),i="tiling",s={id:i,name:"Tiling Plugin",version:"1.0.0",provides:["tiling"],requires:["render","scroll","viewport"],optional:[],defaultConfig:{tileSize:768,overlapPx:2.5,extraRings:0}},o="TILING/INIT_STATE",n="TILING/CLEANUP_STATE",r="TILING/UPDATE_VISIBLE_TILES",a="TILING/MARK_TILE_STATUS",l=(e,t)=>({type:r,payload:{documentId:e,tiles:t}}),c=(e,t,i,s)=>({type:a,payload:{documentId:e,pageIndex:t,tileId:i,status:s}}),d={visibleTiles:{}};function u({tileSize:e=768,overlapPx:i=2.5,extraRings:s=0,scale:o,rotation:n,page:r,metric:a}){const l=r.size.width*o,c=r.size.height*o,d=e-i,u=t.transformSize(r.size,n,o),h={origin:{x:a.scaled.pageX,y:a.scaled.pageY},size:{width:a.scaled.visibleWidth,height:a.scaled.visibleHeight}},g=t.restoreRect(u,h,n,1),p=g.origin.x,m=g.origin.y,f=p+g.size.width,b=m+g.size.height,y=Math.floor((l-1)/d),T=Math.floor((c-1)/d),I=Math.max(0,Math.floor(p/d)-s),v=Math.min(y,Math.floor((f-1)/d)+s),x=Math.max(0,Math.floor(m/d)-s),S=Math.min(T,Math.floor((b-1)/d)+s),R=[];for(let t=I;t<=v;t++){const i=t*d,s=Math.min(e,l-i),n=i/o,a=s/o;for(let l=x;l<=S;l++){const u=l*d,h=Math.min(e,c-u),g=u/o,p=h/o;R.push({id:`p${r.index}-${o}-x${i}-y${u}-w${s}-h${h}`,col:t,row:l,pageRect:{origin:{x:n,y:g},size:{width:a,height:p}},screenRect:{origin:{x:i,y:u},size:{width:s,height:h}},status:"queued",srcScale:o,isFallback:!1})}}return R}const h=class extends e.BasePlugin{constructor(t,i,s){super(t,i),this.tileRendering$=e.createBehaviorEmitter(),this.config=s,this.renderCapability=this.registry.getPlugin("render").provides(),this.scrollCapability=this.registry.getPlugin("scroll").provides(),this.viewportCapability=this.registry.getPlugin("viewport").provides(),this.scrollCapability.onScroll(e=>this.calculateVisibleTiles(e.documentId,e.metrics),{mode:"throttle",wait:50,throttleMode:"trailing"}),this.coreStore.onAction(e.REFRESH_PAGES,e=>this.recalculateTiles(e.payload))}onDocumentLoadingStarted(e){this.dispatch(((e,t)=>({type:o,payload:{documentId:e,state:t}}))(e,d))}onDocumentClosed(e){this.dispatch((e=>({type:n,payload:e}))(e))}onScaleChanged(e){this.recalculateTilesForDocument(e)}onRotationChanged(e){this.recalculateTilesForDocument(e)}recalculateTilesForDocument(e){const t=this.scrollCapability.forDocument(e),i=this.viewportCapability.forDocument(e),s=t.getMetrics(i.getMetrics());this.calculateVisibleTiles(e,s)}async recalculateTiles(e){const{documentId:t,pageIndexes:i}=e,s=this.getCoreDocument(t);if(!s||!s.document)return;const o=this.scrollCapability.forDocument(t),n=this.viewportCapability.forDocument(t),r=o.getMetrics(n.getMetrics()),a={},c=Date.now(),d=s.scale,h=s.rotation;for(const l of i){const e=r.pageVisibilityMetrics.find(e=>e.pageNumber===l+1);if(!e)continue;const t=s.document.pages[l];t&&(a[l]=u({page:t,metric:e,scale:d,rotation:h,tileSize:this.config.tileSize,overlapPx:this.config.overlapPx,extraRings:this.config.extraRings}).map(e=>({...e,id:`${e.id}-r${c}`})))}Object.keys(a).length>0&&this.dispatch(l(t,a))}async initialize(){}calculateVisibleTiles(e,t){const i=this.getCoreDocument(e);if(!i||!i.document)return;const s=i.scale,o=i.rotation,n={};for(const r of t.pageVisibilityMetrics){const e=r.pageNumber-1,t=i.document.pages[e];if(!t)continue;const a=u({page:t,metric:r,scale:s,rotation:o,tileSize:this.config.tileSize,overlapPx:this.config.overlapPx,extraRings:this.config.extraRings});n[e]=a}this.dispatch(l(e,n))}onStoreUpdated(e,t){for(const i in t.documents){const s=e.documents[i],o=t.documents[i];s!==o&&this.tileRendering$.emit({documentId:i,tiles:o.visibleTiles})}}buildCapability(){return{renderTile:this.renderTile.bind(this),forDocument:this.createTilingScope.bind(this),onTileRendering:this.tileRendering$.on}}createTilingScope(e){return{renderTile:t=>this.renderTile(t,e),onTileRendering:t=>this.tileRendering$.on(i=>{i.documentId===e&&t(i.tiles)})}}renderTile(e,i){const s=i??this.getActiveDocumentId();if(!this.renderCapability)throw new Error("Render capability not available.");this.dispatch(c(s,e.pageIndex,e.tile.id,"rendering"));const o=this.renderCapability.forDocument(s).renderPageRect({pageIndex:e.pageIndex,rect:e.tile.pageRect,options:{scaleFactor:e.tile.srcScale,dpr:e.dpr}});return o.wait(()=>{this.dispatch(c(s,e.pageIndex,e.tile.id,"ready"))},t.ignore),o}};h.id="tiling";let g=h;const p={manifest:s,create:(e,t)=>new g(i,e,t),reducer:(e,t)=>((e,t)=>{var i,s;switch(t.type){case o:{const{documentId:i,state:s}=t.payload;return{...e,documents:{...e.documents,[i]:s}}}case n:{const i=t.payload,{[i]:s,...o}=e.documents;return{...e,documents:o}}case r:{const{documentId:s,tiles:o}=t.payload,n=e.documents[s];if(!n)return e;const r={...n.visibleTiles};for(const e in o){const t=Number(e),s=o[t],n=r[t]??[],a=null==(i=n.find(e=>!e.isFallback))?void 0:i.srcScale,l=s.length>0?s[0].srcScale:a;if(void 0!==a&&a!==l){const e=n.filter(e=>!e.isFallback&&"ready"===e.status).map(e=>({...e,isFallback:!0})),i=e.length>0?[]:n.filter(e=>e.isFallback);r[t]=[...i,...e,...s]}else{const e=new Set(s.map(e=>e.id)),i=[],o=new Set;for(const t of n)(t.isFallback||e.has(t.id))&&(i.push(t),o.add(t.id));for(const t of s)o.has(t.id)||i.push(t);r[t]=i}}return{...e,documents:{...e.documents,[s]:{...n,visibleTiles:r}}}}case a:{const{documentId:i,pageIndex:o,tileId:n,status:r}=t.payload,a=e.documents[i];if(!a)return e;const l=(null==(s=a.visibleTiles[o])?void 0:s.map(e=>e.id===n?{...e,status:r}:e))??[],c=l.filter(e=>!e.isFallback),d=c.length>0&&c.every(e=>"ready"===e.status)?c:l;return{...e,documents:{...e.documents,[i]:{...a,visibleTiles:{...a.visibleTiles,[o]:d}}}}}default:return e}})(e,t),initialState:{documents:{}}};exports.TILING_PLUGIN_ID=i,exports.TilingPlugin=g,exports.TilingPluginPackage=p,exports.manifest=s;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/models"),i="tiling",s={id:i,name:"Tiling Plugin",version:"1.0.0",provides:["tiling"],requires:["render","scroll","viewport"],optional:[],defaultConfig:{tileSize:768,overlapPx:2.5,extraRings:0}},o="TILING/INIT_STATE",n="TILING/CLEANUP_STATE",r="TILING/UPDATE_VISIBLE_TILES",a="TILING/MARK_TILE_STATUS",l=(e,t)=>({type:r,payload:{documentId:e,tiles:t}}),c=(e,t,i,s)=>({type:a,payload:{documentId:e,pageIndex:t,tileId:i,status:s}}),d={visibleTiles:{}};function u({tileSize:e=768,overlapPx:i=2.5,extraRings:s=0,scale:o,rotation:n,page:r,metric:a}){const l=r.size.width*o,c=r.size.height*o,d=e-i,u=t.transformSize(r.size,n,o),h={origin:{x:a.scaled.pageX,y:a.scaled.pageY},size:{width:a.scaled.visibleWidth,height:a.scaled.visibleHeight}},g=t.restoreRect(u,h,n,1),p=g.origin.x,m=g.origin.y,f=p+g.size.width,b=m+g.size.height,y=Math.floor((l-1)/d),T=Math.floor((c-1)/d),I=Math.max(0,Math.floor(p/d)-s),v=Math.min(y,Math.floor((f-1)/d)+s),x=Math.max(0,Math.floor(m/d)-s),S=Math.min(T,Math.floor((b-1)/d)+s),R=[];for(let t=I;t<=v;t++){const i=t*d,s=Math.min(e,l-i),n=i/o,a=s/o;for(let l=x;l<=S;l++){const u=l*d,h=Math.min(e,c-u),g=u/o,p=h/o;R.push({id:`p${r.index}-${o}-x${i}-y${u}-w${s}-h${h}`,col:t,row:l,pageRect:{origin:{x:n,y:g},size:{width:a,height:p}},screenRect:{origin:{x:i,y:u},size:{width:s,height:h}},status:"queued",srcScale:o,isFallback:!1})}}return R}const h=class extends e.BasePlugin{constructor(t,i,s){super(t,i),this.tileRendering$=e.createBehaviorEmitter(),this.config=s,this.renderCapability=this.registry.getPlugin("render").provides(),this.scrollCapability=this.registry.getPlugin("scroll").provides(),this.viewportCapability=this.registry.getPlugin("viewport").provides(),this.scrollCapability.onScroll(e=>this.calculateVisibleTiles(e.documentId,e.metrics),{mode:"throttle",wait:50,throttleMode:"trailing"}),this.coreStore.onAction(e.REFRESH_PAGES,e=>this.recalculateTiles(e.payload))}onDocumentLoadingStarted(e){this.dispatch(((e,t)=>({type:o,payload:{documentId:e,state:t}}))(e,d))}onDocumentClosed(e){this.dispatch((e=>({type:n,payload:e}))(e))}onScaleChanged(e){this.recalculateTilesForDocument(e)}onRotationChanged(e){this.recalculateTilesForDocument(e)}recalculateTilesForDocument(e){const t=this.scrollCapability.forDocument(e),i=this.viewportCapability.forDocument(e),s=t.getMetrics(i.getMetrics());this.calculateVisibleTiles(e,s)}async recalculateTiles(e){const{documentId:t,pageIndexes:i}=e,s=this.getCoreDocument(t);if(!s||!s.document)return;const o=this.scrollCapability.forDocument(t),n=this.viewportCapability.forDocument(t),r=o.getMetrics(n.getMetrics()),a={},c=Date.now(),d=s.scale;for(const l of i){const e=r.pageVisibilityMetrics.find(e=>e.pageNumber===l+1);if(!e)continue;const t=s.document.pages[l];if(!t)continue;const i=((t.rotation??0)+s.rotation)%4;a[l]=u({page:t,metric:e,scale:d,rotation:i,tileSize:this.config.tileSize,overlapPx:this.config.overlapPx,extraRings:this.config.extraRings}).map(e=>({...e,id:`${e.id}-r${c}`}))}Object.keys(a).length>0&&this.dispatch(l(t,a))}async initialize(){}calculateVisibleTiles(e,t){const i=this.getCoreDocument(e);if(!i||!i.document)return;const s=i.scale,o={};for(const n of t.pageVisibilityMetrics){const e=n.pageNumber-1,t=i.document.pages[e];if(!t)continue;const r=u({page:t,metric:n,scale:s,rotation:((t.rotation??0)+i.rotation)%4,tileSize:this.config.tileSize,overlapPx:this.config.overlapPx,extraRings:this.config.extraRings});o[e]=r}this.dispatch(l(e,o))}onStoreUpdated(e,t){for(const i in t.documents){const s=e.documents[i],o=t.documents[i];s!==o&&this.tileRendering$.emit({documentId:i,tiles:o.visibleTiles})}}buildCapability(){return{renderTile:this.renderTile.bind(this),forDocument:this.createTilingScope.bind(this),onTileRendering:this.tileRendering$.on}}createTilingScope(e){return{renderTile:t=>this.renderTile(t,e),onTileRendering:t=>this.tileRendering$.on(i=>{i.documentId===e&&t(i.tiles)})}}renderTile(e,i){const s=i??this.getActiveDocumentId();if(!this.renderCapability)throw new Error("Render capability not available.");this.dispatch(c(s,e.pageIndex,e.tile.id,"rendering"));const o=this.renderCapability.forDocument(s).renderPageRect({pageIndex:e.pageIndex,rect:e.tile.pageRect,options:{scaleFactor:e.tile.srcScale,dpr:e.dpr}});return o.wait(()=>{this.dispatch(c(s,e.pageIndex,e.tile.id,"ready"))},t.ignore),o}};h.id="tiling";let g=h;const p={manifest:s,create:(e,t)=>new g(i,e,t),reducer:(e,t)=>((e,t)=>{var i,s;switch(t.type){case o:{const{documentId:i,state:s}=t.payload;return{...e,documents:{...e.documents,[i]:s}}}case n:{const i=t.payload,{[i]:s,...o}=e.documents;return{...e,documents:o}}case r:{const{documentId:s,tiles:o}=t.payload,n=e.documents[s];if(!n)return e;const r={...n.visibleTiles};for(const e in o){const t=Number(e),s=o[t],n=r[t]??[],a=null==(i=n.find(e=>!e.isFallback))?void 0:i.srcScale,l=s.length>0?s[0].srcScale:a;if(void 0!==a&&a!==l){const e=n.filter(e=>!e.isFallback&&"ready"===e.status).map(e=>({...e,isFallback:!0})),i=e.length>0?[]:n.filter(e=>e.isFallback);r[t]=[...i,...e,...s]}else{const e=new Set(s.map(e=>e.id)),i=[],o=new Set;for(const t of n)(t.isFallback||e.has(t.id))&&(i.push(t),o.add(t.id));for(const t of s)o.has(t.id)||i.push(t);r[t]=i}}return{...e,documents:{...e.documents,[s]:{...n,visibleTiles:r}}}}case a:{const{documentId:i,pageIndex:o,tileId:n,status:r}=t.payload,a=e.documents[i];if(!a)return e;const l=(null==(s=a.visibleTiles[o])?void 0:s.map(e=>e.id===n?{...e,status:r}:e))??[],c=l.filter(e=>!e.isFallback),d=c.length>0&&c.every(e=>"ready"===e.status)?c:l;return{...e,documents:{...e.documents,[i]:{...a,visibleTiles:{...a.visibleTiles,[o]:d}}}}}default:return e}})(e,t),initialState:{documents:{}}};exports.TILING_PLUGIN_ID=i,exports.TilingPlugin=g,exports.TilingPluginPackage=p,exports.manifest=s;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/utils.ts","../src/lib/tiling-plugin.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\n\nimport { TilingPluginConfig } from './types';\n\nexport const TILING_PLUGIN_ID = 'tiling';\n\nexport const manifest: PluginManifest<TilingPluginConfig> = {\n id: TILING_PLUGIN_ID,\n name: 'Tiling Plugin',\n version: '1.0.0',\n provides: ['tiling'],\n requires: ['render', 'scroll', 'viewport'],\n optional: [],\n defaultConfig: {\n tileSize: 768,\n overlapPx: 2.5,\n extraRings: 0,\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { Tile, TileStatus, TilingDocumentState } from './types';\n\nexport const INIT_TILING_STATE = 'TILING/INIT_STATE';\nexport const CLEANUP_TILING_STATE = 'TILING/CLEANUP_STATE';\nexport const UPDATE_VISIBLE_TILES = 'TILING/UPDATE_VISIBLE_TILES';\nexport const MARK_TILE_STATUS = 'TILING/MARK_TILE_STATUS';\n\nexport interface InitTilingStateAction extends Action {\n type: typeof INIT_TILING_STATE;\n payload: {\n documentId: string;\n state: TilingDocumentState;\n };\n}\n\nexport interface CleanupTilingStateAction extends Action {\n type: typeof CLEANUP_TILING_STATE;\n payload: string; // documentId\n}\n\nexport type UpdateVisibleTilesAction = {\n type: typeof UPDATE_VISIBLE_TILES;\n payload: {\n documentId: string;\n tiles: Record<number, Tile[]>;\n };\n};\n\nexport type MarkTileStatusAction = {\n type: typeof MARK_TILE_STATUS;\n payload: {\n documentId: string;\n pageIndex: number;\n tileId: string;\n status: TileStatus;\n };\n};\n\nexport type TilingAction =\n | InitTilingStateAction\n | CleanupTilingStateAction\n | UpdateVisibleTilesAction\n | MarkTileStatusAction;\n\nexport const initTilingState = (\n documentId: string,\n state: TilingDocumentState,\n): InitTilingStateAction => ({\n type: INIT_TILING_STATE,\n payload: { documentId, state },\n});\n\nexport const cleanupTilingState = (documentId: string): CleanupTilingStateAction => ({\n type: CLEANUP_TILING_STATE,\n payload: documentId,\n});\n\nexport const updateVisibleTiles = (\n documentId: string,\n tiles: Record<number, Tile[]>,\n): UpdateVisibleTilesAction => ({\n type: UPDATE_VISIBLE_TILES,\n payload: { documentId, tiles },\n});\n\nexport const markTileStatus = (\n documentId: string,\n pageIndex: number,\n tileId: string,\n status: TileStatus,\n): MarkTileStatusAction => ({\n type: MARK_TILE_STATUS,\n payload: { documentId, pageIndex, tileId, status },\n});\n","import { Reducer } from '@embedpdf/core';\n\nimport {\n UPDATE_VISIBLE_TILES,\n MARK_TILE_STATUS,\n TilingAction,\n INIT_TILING_STATE,\n CLEANUP_TILING_STATE,\n} from './actions';\nimport { Tile, TilingDocumentState, TilingState } from './types';\n\nexport const initialTilingDocumentState: TilingDocumentState = {\n visibleTiles: {},\n};\n\nexport const initialState: TilingState = {\n documents: {},\n};\n\nexport const tilingReducer: Reducer<TilingState, TilingAction> = (state, action) => {\n switch (action.type) {\n case INIT_TILING_STATE: {\n const { documentId, state: docState } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n };\n }\n\n case CLEANUP_TILING_STATE: {\n const documentId = action.payload;\n const { [documentId]: removed, ...remaining } = state.documents;\n return {\n ...state,\n documents: remaining,\n };\n }\n\n case UPDATE_VISIBLE_TILES: {\n const { documentId, tiles: incoming } = action.payload; // Record<number, Tile[]>\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const nextPages = { ...docState.visibleTiles };\n\n for (const key in incoming) {\n const pageIndex = Number(key);\n const newTiles = incoming[pageIndex]; // all isFallback=false\n const prevTiles = nextPages[pageIndex] ?? [];\n\n const prevScale = prevTiles.find((t) => !t.isFallback)?.srcScale;\n const newScale = newTiles.length > 0 ? newTiles[0].srcScale : prevScale;\n const zoomChanged = prevScale !== undefined && prevScale !== newScale;\n\n if (zoomChanged) {\n /* 1️⃣ ready tiles from the old zoom → new fallback */\n const promoted = prevTiles\n .filter((t) => !t.isFallback && t.status === 'ready')\n .map((t) => ({ ...t, isFallback: true }));\n\n /* 2️⃣ decide which fallback tiles to keep */\n const fallbackToCarry = promoted.length > 0 ? [] : prevTiles.filter((t) => t.isFallback);\n\n /* 3️⃣ final list = (maybe-kept fallback) + promoted + newTiles */\n nextPages[pageIndex] = [...fallbackToCarry, ...promoted, ...newTiles];\n } else {\n /* same zoom → keep current fallback, replace visible */\n const newIds = new Set(newTiles.map((t) => t.id));\n const keepers: Tile[] = []; // where we’ll collect surviving tiles\n const seenIds = new Set<string>();\n\n /* 2️⃣ loop prevTiles once */\n for (const t of prevTiles) {\n if (t.isFallback) {\n keepers.push(t); // always keep fallback\n seenIds.add(t.id);\n } else if (newIds.has(t.id)) {\n keepers.push(t); // keep old visible tile (preserves status)\n seenIds.add(t.id);\n }\n }\n\n /* 3️⃣ append *brand-new* tiles (not yet kept) */\n for (const t of newTiles) {\n if (!seenIds.has(t.id)) keepers.push(t);\n }\n\n /* 4️⃣ store result */\n nextPages[pageIndex] = keepers;\n }\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n visibleTiles: nextPages,\n },\n },\n };\n }\n\n case MARK_TILE_STATUS: {\n const { documentId, pageIndex, tileId, status } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const tiles =\n docState.visibleTiles[pageIndex]?.map((t) =>\n t.id === tileId ? ({ ...t, status } as Tile) : t,\n ) ?? [];\n\n const newTiles = tiles.filter((t) => !t.isFallback);\n const allReady = newTiles.length > 0 && newTiles.every((t) => t.status === 'ready');\n const finalTiles = allReady ? newTiles : tiles;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n visibleTiles: { ...docState.visibleTiles, [pageIndex]: finalTiles },\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import { Rect, restoreRect, transformSize } from '@embedpdf/models';\nimport { CalculateTilesForPageOptions, Tile } from './types';\n\n/**\n * Build a grid where neighbouring tiles overlap by `overlapPx`\n * (screen pixels). Inner tiles keep the full `tileSize`, edge\n * tiles are clipped to the page bounds. All screen-space values\n * are rounded to **integers** to avoid sub-pixel seams.\n */\nexport function calculateTilesForPage({\n tileSize = 768,\n overlapPx = 2.5,\n extraRings = 0,\n scale,\n rotation,\n page,\n metric,\n}: CalculateTilesForPageOptions): Tile[] {\n /* ---- work in screen-pixel space -------------------------------- */\n const pageW = page.size.width * scale; // px\n const pageH = page.size.height * scale; // px\n\n const step = tileSize - overlapPx; // shift between tiles\n\n const containerSize = transformSize(page.size, rotation, scale);\n const rotatedVisRect: Rect = {\n origin: { x: metric.scaled.pageX, y: metric.scaled.pageY },\n size: { width: metric.scaled.visibleWidth, height: metric.scaled.visibleHeight },\n };\n const unrotatedVisRect = restoreRect(containerSize, rotatedVisRect, rotation, 1);\n\n const visLeft = unrotatedVisRect.origin.x;\n const visTop = unrotatedVisRect.origin.y;\n const visRight = visLeft + unrotatedVisRect.size.width;\n const visBottom = visTop + unrotatedVisRect.size.height;\n\n const maxCol = Math.floor((pageW - 1) / step);\n const maxRow = Math.floor((pageH - 1) / step);\n\n const startCol = Math.max(0, Math.floor(visLeft / step) - extraRings);\n const endCol = Math.min(maxCol, Math.floor((visRight - 1) / step) + extraRings);\n const startRow = Math.max(0, Math.floor(visTop / step) - extraRings);\n const endRow = Math.min(maxRow, Math.floor((visBottom - 1) / step) + extraRings);\n\n /* ---- build tiles ---------------------------------------------- */\n const tiles: Tile[] = [];\n\n for (let col = startCol; col <= endCol; col++) {\n const xScreen = col * step; // px (integer)\n const wScreen = Math.min(tileSize, pageW - xScreen); // px (≤ tileSize)\n\n const xPage = xScreen / scale; // pt (may be frac.)\n const wPage = wScreen / scale; // pt\n\n for (let row = startRow; row <= endRow; row++) {\n const yScreen = row * step;\n const hScreen = Math.min(tileSize, pageH - yScreen);\n\n const yPage = yScreen / scale;\n const hPage = hScreen / scale;\n\n tiles.push({\n id: `p${page.index}-${scale}-x${xScreen}-y${yScreen}-w${wScreen}-h${hScreen}`,\n col,\n row,\n pageRect: { origin: { x: xPage, y: yPage }, size: { width: wPage, height: hPage } },\n screenRect: {\n origin: { x: xScreen, y: yScreen },\n size: { width: wScreen, height: hScreen },\n },\n status: 'queued',\n srcScale: scale,\n isFallback: false,\n });\n }\n }\n\n return tiles;\n}\n","import {\n BasePlugin,\n createBehaviorEmitter,\n Listener,\n PluginRegistry,\n REFRESH_PAGES,\n RefreshPagesAction,\n} from '@embedpdf/core';\nimport { ignore } from '@embedpdf/models';\nimport { RenderCapability, RenderPlugin } from '@embedpdf/plugin-render';\nimport {\n ScrollCapability,\n ScrollMetrics,\n ScrollPlugin,\n ScrollEvent,\n} from '@embedpdf/plugin-scroll';\nimport { ViewportCapability, ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { initTilingState, cleanupTilingState, markTileStatus, updateVisibleTiles } from './actions';\nimport { initialTilingDocumentState } from './reducer';\nimport {\n TilingPluginConfig,\n TilingCapability,\n Tile,\n RenderTileOptions,\n TilingState,\n TilingEvent,\n TilingScope,\n} from './types';\nimport { calculateTilesForPage } from './utils';\n\nexport class TilingPlugin extends BasePlugin<TilingPluginConfig, TilingCapability, TilingState> {\n static readonly id = 'tiling' as const;\n\n private readonly tileRendering$ = createBehaviorEmitter<TilingEvent>();\n\n private config: TilingPluginConfig;\n private renderCapability: RenderCapability;\n private scrollCapability: ScrollCapability;\n private viewportCapability: ViewportCapability;\n\n constructor(id: string, registry: PluginRegistry, config: TilingPluginConfig) {\n super(id, registry);\n\n this.config = config;\n\n this.renderCapability = this.registry.getPlugin<RenderPlugin>('render')!.provides();\n this.scrollCapability = this.registry.getPlugin<ScrollPlugin>('scroll')!.provides();\n this.viewportCapability = this.registry.getPlugin<ViewportPlugin>('viewport')!.provides();\n\n this.scrollCapability.onScroll(\n (event: ScrollEvent) => this.calculateVisibleTiles(event.documentId, event.metrics),\n {\n mode: 'throttle',\n wait: 50,\n throttleMode: 'trailing',\n },\n );\n\n this.coreStore.onAction(REFRESH_PAGES, (action) => this.recalculateTiles(action.payload));\n }\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n this.dispatch(initTilingState(documentId, initialTilingDocumentState));\n }\n\n protected override onDocumentClosed(documentId: string): void {\n this.dispatch(cleanupTilingState(documentId));\n }\n\n protected override onScaleChanged(documentId: string): void {\n this.recalculateTilesForDocument(documentId);\n }\n\n protected override onRotationChanged(documentId: string): void {\n this.recalculateTilesForDocument(documentId);\n }\n\n private recalculateTilesForDocument(documentId: string): void {\n const scrollScope = this.scrollCapability.forDocument(documentId);\n const viewportScope = this.viewportCapability.forDocument(documentId);\n const metrics = scrollScope.getMetrics(viewportScope.getMetrics());\n this.calculateVisibleTiles(documentId, metrics);\n }\n\n async recalculateTiles(payload: RefreshPagesAction['payload']): Promise<void> {\n const { documentId, pageIndexes } = payload;\n const coreDoc = this.getCoreDocument(documentId);\n if (!coreDoc || !coreDoc.document) return;\n\n const scrollScope = this.scrollCapability.forDocument(documentId);\n const viewportScope = this.viewportCapability.forDocument(documentId);\n const currentMetrics = scrollScope.getMetrics(viewportScope.getMetrics());\n\n // Recalculate tiles for refreshed pages with a new timestamp\n const refreshedTiles: Record<number, Tile[]> = {};\n const refreshTimestamp = Date.now();\n const scale = coreDoc.scale;\n const rotation = coreDoc.rotation;\n\n for (const pageIndex of pageIndexes) {\n const metric = currentMetrics.pageVisibilityMetrics.find(\n (m) => m.pageNumber === pageIndex + 1,\n );\n if (!metric) continue;\n\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n\n refreshedTiles[pageIndex] = calculateTilesForPage({\n page,\n metric,\n scale,\n rotation,\n tileSize: this.config.tileSize,\n overlapPx: this.config.overlapPx,\n extraRings: this.config.extraRings,\n }).map((tile) => ({\n ...tile,\n id: `${tile.id}-r${refreshTimestamp}`, // Add refresh token to force new render\n }));\n }\n\n if (Object.keys(refreshedTiles).length > 0) {\n this.dispatch(updateVisibleTiles(documentId, refreshedTiles));\n }\n }\n\n async initialize(): Promise<void> {\n // Fetch dependencies from the registry if needed\n }\n\n private calculateVisibleTiles(documentId: string, scrollMetrics: ScrollMetrics): void {\n const coreDoc = this.getCoreDocument(documentId);\n if (!coreDoc || !coreDoc.document) return;\n\n const scale = coreDoc.scale;\n const rotation = coreDoc.rotation;\n const visibleTiles: { [pageIndex: number]: Tile[] } = {};\n\n for (const scrollMetric of scrollMetrics.pageVisibilityMetrics) {\n const pageIndex = scrollMetric.pageNumber - 1; // Convert to 0-based index\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n\n // Calculate tiles for the page using the utility function\n const tiles = calculateTilesForPage({\n page,\n metric: scrollMetric,\n scale,\n rotation,\n tileSize: this.config.tileSize,\n overlapPx: this.config.overlapPx,\n extraRings: this.config.extraRings,\n });\n\n visibleTiles[pageIndex] = tiles;\n }\n\n this.dispatch(updateVisibleTiles(documentId, visibleTiles));\n }\n\n override onStoreUpdated(prevState: TilingState, newState: TilingState): void {\n for (const documentId in newState.documents) {\n const prevDoc = prevState.documents[documentId];\n const newDoc = newState.documents[documentId];\n if (prevDoc !== newDoc) {\n this.tileRendering$.emit({ documentId, tiles: newDoc.visibleTiles });\n }\n }\n }\n\n protected buildCapability(): TilingCapability {\n return {\n renderTile: this.renderTile.bind(this),\n forDocument: this.createTilingScope.bind(this),\n onTileRendering: this.tileRendering$.on,\n };\n }\n\n private createTilingScope(documentId: string): TilingScope {\n return {\n renderTile: (options) => this.renderTile(options, documentId),\n onTileRendering: (listener: Listener<Record<number, Tile[]>>) =>\n this.tileRendering$.on((event) => {\n if (event.documentId === documentId) listener(event.tiles);\n }),\n };\n }\n\n private renderTile(options: RenderTileOptions, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n if (!this.renderCapability) {\n throw new Error('Render capability not available.');\n }\n\n this.dispatch(markTileStatus(id, options.pageIndex, options.tile.id, 'rendering'));\n\n const task = this.renderCapability.forDocument(id).renderPageRect({\n pageIndex: options.pageIndex,\n rect: options.tile.pageRect,\n options: {\n scaleFactor: options.tile.srcScale,\n dpr: options.dpr,\n },\n });\n\n task.wait(() => {\n this.dispatch(markTileStatus(id, options.pageIndex, options.tile.id, 'ready'));\n }, ignore);\n\n return task;\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { TilingAction } from './actions';\nimport { manifest, TILING_PLUGIN_ID } from './manifest';\nimport { initialState, tilingReducer } from './reducer';\nimport { TilingPlugin } from './tiling-plugin';\nimport { TilingPluginConfig, TilingState } from './types';\n\nexport const TilingPluginPackage: PluginPackage<\n TilingPlugin,\n TilingPluginConfig,\n TilingState,\n TilingAction\n> = {\n manifest,\n create: (registry, config) => new TilingPlugin(TILING_PLUGIN_ID, registry, config),\n reducer: (state, action) => tilingReducer(state, action),\n initialState,\n};\n\nexport * from './tiling-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":["TILING_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","tileSize","overlapPx","extraRings","INIT_TILING_STATE","CLEANUP_TILING_STATE","UPDATE_VISIBLE_TILES","MARK_TILE_STATUS","updateVisibleTiles","documentId","tiles","type","payload","markTileStatus","pageIndex","tileId","status","initialTilingDocumentState","visibleTiles","calculateTilesForPage","scale","rotation","page","metric","pageW","size","width","pageH","height","step","containerSize","transformSize","rotatedVisRect","origin","x","scaled","pageX","y","pageY","visibleWidth","visibleHeight","unrotatedVisRect","restoreRect","visLeft","visTop","visRight","visBottom","maxCol","Math","floor","maxRow","startCol","max","endCol","min","startRow","endRow","col","xScreen","wScreen","xPage","wPage","row","yScreen","hScreen","yPage","hPage","push","index","pageRect","screenRect","srcScale","isFallback","_TilingPlugin","BasePlugin","constructor","registry","config","super","this","tileRendering$","createBehaviorEmitter","renderCapability","getPlugin","scrollCapability","viewportCapability","onScroll","event","calculateVisibleTiles","metrics","mode","wait","throttleMode","coreStore","onAction","REFRESH_PAGES","action","recalculateTiles","onDocumentLoadingStarted","dispatch","state","initTilingState","onDocumentClosed","cleanupTilingState","onScaleChanged","recalculateTilesForDocument","onRotationChanged","scrollScope","forDocument","viewportScope","getMetrics","pageIndexes","coreDoc","getCoreDocument","document","currentMetrics","refreshedTiles","refreshTimestamp","Date","now","pageVisibilityMetrics","find","m","pageNumber","pages","map","tile","Object","keys","length","initialize","scrollMetrics","scrollMetric","onStoreUpdated","prevState","newState","documents","prevDoc","newDoc","emit","buildCapability","renderTile","bind","createTilingScope","onTileRendering","on","options","listener","getActiveDocumentId","Error","task","renderPageRect","rect","scaleFactor","dpr","ignore","TilingPlugin","TilingPluginPackage","create","reducer","docState","removed","remaining","incoming","nextPages","key","Number","newTiles","prevTiles","prevScale","_a","t","newScale","promoted","filter","fallbackToCarry","newIds","Set","keepers","seenIds","has","add","_b","finalTiles","every","tilingReducer","initialState"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/utils.ts","../src/lib/tiling-plugin.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\n\nimport { TilingPluginConfig } from './types';\n\nexport const TILING_PLUGIN_ID = 'tiling';\n\nexport const manifest: PluginManifest<TilingPluginConfig> = {\n id: TILING_PLUGIN_ID,\n name: 'Tiling Plugin',\n version: '1.0.0',\n provides: ['tiling'],\n requires: ['render', 'scroll', 'viewport'],\n optional: [],\n defaultConfig: {\n tileSize: 768,\n overlapPx: 2.5,\n extraRings: 0,\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { Tile, TileStatus, TilingDocumentState } from './types';\n\nexport const INIT_TILING_STATE = 'TILING/INIT_STATE';\nexport const CLEANUP_TILING_STATE = 'TILING/CLEANUP_STATE';\nexport const UPDATE_VISIBLE_TILES = 'TILING/UPDATE_VISIBLE_TILES';\nexport const MARK_TILE_STATUS = 'TILING/MARK_TILE_STATUS';\n\nexport interface InitTilingStateAction extends Action {\n type: typeof INIT_TILING_STATE;\n payload: {\n documentId: string;\n state: TilingDocumentState;\n };\n}\n\nexport interface CleanupTilingStateAction extends Action {\n type: typeof CLEANUP_TILING_STATE;\n payload: string; // documentId\n}\n\nexport type UpdateVisibleTilesAction = {\n type: typeof UPDATE_VISIBLE_TILES;\n payload: {\n documentId: string;\n tiles: Record<number, Tile[]>;\n };\n};\n\nexport type MarkTileStatusAction = {\n type: typeof MARK_TILE_STATUS;\n payload: {\n documentId: string;\n pageIndex: number;\n tileId: string;\n status: TileStatus;\n };\n};\n\nexport type TilingAction =\n | InitTilingStateAction\n | CleanupTilingStateAction\n | UpdateVisibleTilesAction\n | MarkTileStatusAction;\n\nexport const initTilingState = (\n documentId: string,\n state: TilingDocumentState,\n): InitTilingStateAction => ({\n type: INIT_TILING_STATE,\n payload: { documentId, state },\n});\n\nexport const cleanupTilingState = (documentId: string): CleanupTilingStateAction => ({\n type: CLEANUP_TILING_STATE,\n payload: documentId,\n});\n\nexport const updateVisibleTiles = (\n documentId: string,\n tiles: Record<number, Tile[]>,\n): UpdateVisibleTilesAction => ({\n type: UPDATE_VISIBLE_TILES,\n payload: { documentId, tiles },\n});\n\nexport const markTileStatus = (\n documentId: string,\n pageIndex: number,\n tileId: string,\n status: TileStatus,\n): MarkTileStatusAction => ({\n type: MARK_TILE_STATUS,\n payload: { documentId, pageIndex, tileId, status },\n});\n","import { Reducer } from '@embedpdf/core';\n\nimport {\n UPDATE_VISIBLE_TILES,\n MARK_TILE_STATUS,\n TilingAction,\n INIT_TILING_STATE,\n CLEANUP_TILING_STATE,\n} from './actions';\nimport { Tile, TilingDocumentState, TilingState } from './types';\n\nexport const initialTilingDocumentState: TilingDocumentState = {\n visibleTiles: {},\n};\n\nexport const initialState: TilingState = {\n documents: {},\n};\n\nexport const tilingReducer: Reducer<TilingState, TilingAction> = (state, action) => {\n switch (action.type) {\n case INIT_TILING_STATE: {\n const { documentId, state: docState } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n };\n }\n\n case CLEANUP_TILING_STATE: {\n const documentId = action.payload;\n const { [documentId]: removed, ...remaining } = state.documents;\n return {\n ...state,\n documents: remaining,\n };\n }\n\n case UPDATE_VISIBLE_TILES: {\n const { documentId, tiles: incoming } = action.payload; // Record<number, Tile[]>\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const nextPages = { ...docState.visibleTiles };\n\n for (const key in incoming) {\n const pageIndex = Number(key);\n const newTiles = incoming[pageIndex]; // all isFallback=false\n const prevTiles = nextPages[pageIndex] ?? [];\n\n const prevScale = prevTiles.find((t) => !t.isFallback)?.srcScale;\n const newScale = newTiles.length > 0 ? newTiles[0].srcScale : prevScale;\n const zoomChanged = prevScale !== undefined && prevScale !== newScale;\n\n if (zoomChanged) {\n /* 1️⃣ ready tiles from the old zoom → new fallback */\n const promoted = prevTiles\n .filter((t) => !t.isFallback && t.status === 'ready')\n .map((t) => ({ ...t, isFallback: true }));\n\n /* 2️⃣ decide which fallback tiles to keep */\n const fallbackToCarry = promoted.length > 0 ? [] : prevTiles.filter((t) => t.isFallback);\n\n /* 3️⃣ final list = (maybe-kept fallback) + promoted + newTiles */\n nextPages[pageIndex] = [...fallbackToCarry, ...promoted, ...newTiles];\n } else {\n /* same zoom → keep current fallback, replace visible */\n const newIds = new Set(newTiles.map((t) => t.id));\n const keepers: Tile[] = []; // where we’ll collect surviving tiles\n const seenIds = new Set<string>();\n\n /* 2️⃣ loop prevTiles once */\n for (const t of prevTiles) {\n if (t.isFallback) {\n keepers.push(t); // always keep fallback\n seenIds.add(t.id);\n } else if (newIds.has(t.id)) {\n keepers.push(t); // keep old visible tile (preserves status)\n seenIds.add(t.id);\n }\n }\n\n /* 3️⃣ append *brand-new* tiles (not yet kept) */\n for (const t of newTiles) {\n if (!seenIds.has(t.id)) keepers.push(t);\n }\n\n /* 4️⃣ store result */\n nextPages[pageIndex] = keepers;\n }\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n visibleTiles: nextPages,\n },\n },\n };\n }\n\n case MARK_TILE_STATUS: {\n const { documentId, pageIndex, tileId, status } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const tiles =\n docState.visibleTiles[pageIndex]?.map((t) =>\n t.id === tileId ? ({ ...t, status } as Tile) : t,\n ) ?? [];\n\n const newTiles = tiles.filter((t) => !t.isFallback);\n const allReady = newTiles.length > 0 && newTiles.every((t) => t.status === 'ready');\n const finalTiles = allReady ? newTiles : tiles;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n visibleTiles: { ...docState.visibleTiles, [pageIndex]: finalTiles },\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import { Rect, restoreRect, transformSize } from '@embedpdf/models';\nimport { CalculateTilesForPageOptions, Tile } from './types';\n\n/**\n * Build a grid where neighbouring tiles overlap by `overlapPx`\n * (screen pixels). Inner tiles keep the full `tileSize`, edge\n * tiles are clipped to the page bounds. All screen-space values\n * are rounded to **integers** to avoid sub-pixel seams.\n */\nexport function calculateTilesForPage({\n tileSize = 768,\n overlapPx = 2.5,\n extraRings = 0,\n scale,\n rotation,\n page,\n metric,\n}: CalculateTilesForPageOptions): Tile[] {\n /* ---- work in screen-pixel space -------------------------------- */\n const pageW = page.size.width * scale; // px\n const pageH = page.size.height * scale; // px\n\n const step = tileSize - overlapPx; // shift between tiles\n\n const containerSize = transformSize(page.size, rotation, scale);\n const rotatedVisRect: Rect = {\n origin: { x: metric.scaled.pageX, y: metric.scaled.pageY },\n size: { width: metric.scaled.visibleWidth, height: metric.scaled.visibleHeight },\n };\n const unrotatedVisRect = restoreRect(containerSize, rotatedVisRect, rotation, 1);\n\n const visLeft = unrotatedVisRect.origin.x;\n const visTop = unrotatedVisRect.origin.y;\n const visRight = visLeft + unrotatedVisRect.size.width;\n const visBottom = visTop + unrotatedVisRect.size.height;\n\n const maxCol = Math.floor((pageW - 1) / step);\n const maxRow = Math.floor((pageH - 1) / step);\n\n const startCol = Math.max(0, Math.floor(visLeft / step) - extraRings);\n const endCol = Math.min(maxCol, Math.floor((visRight - 1) / step) + extraRings);\n const startRow = Math.max(0, Math.floor(visTop / step) - extraRings);\n const endRow = Math.min(maxRow, Math.floor((visBottom - 1) / step) + extraRings);\n\n /* ---- build tiles ---------------------------------------------- */\n const tiles: Tile[] = [];\n\n for (let col = startCol; col <= endCol; col++) {\n const xScreen = col * step; // px (integer)\n const wScreen = Math.min(tileSize, pageW - xScreen); // px (≤ tileSize)\n\n const xPage = xScreen / scale; // pt (may be frac.)\n const wPage = wScreen / scale; // pt\n\n for (let row = startRow; row <= endRow; row++) {\n const yScreen = row * step;\n const hScreen = Math.min(tileSize, pageH - yScreen);\n\n const yPage = yScreen / scale;\n const hPage = hScreen / scale;\n\n tiles.push({\n id: `p${page.index}-${scale}-x${xScreen}-y${yScreen}-w${wScreen}-h${hScreen}`,\n col,\n row,\n pageRect: { origin: { x: xPage, y: yPage }, size: { width: wPage, height: hPage } },\n screenRect: {\n origin: { x: xScreen, y: yScreen },\n size: { width: wScreen, height: hScreen },\n },\n status: 'queued',\n srcScale: scale,\n isFallback: false,\n });\n }\n }\n\n return tiles;\n}\n","import {\n BasePlugin,\n createBehaviorEmitter,\n Listener,\n PluginRegistry,\n REFRESH_PAGES,\n RefreshPagesAction,\n} from '@embedpdf/core';\nimport { ignore } from '@embedpdf/models';\nimport { RenderCapability, RenderPlugin } from '@embedpdf/plugin-render';\nimport {\n ScrollCapability,\n ScrollMetrics,\n ScrollPlugin,\n ScrollEvent,\n} from '@embedpdf/plugin-scroll';\nimport { ViewportCapability, ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { initTilingState, cleanupTilingState, markTileStatus, updateVisibleTiles } from './actions';\nimport { initialTilingDocumentState } from './reducer';\nimport {\n TilingPluginConfig,\n TilingCapability,\n Tile,\n RenderTileOptions,\n TilingState,\n TilingEvent,\n TilingScope,\n} from './types';\nimport { calculateTilesForPage } from './utils';\n\nexport class TilingPlugin extends BasePlugin<TilingPluginConfig, TilingCapability, TilingState> {\n static readonly id = 'tiling' as const;\n\n private readonly tileRendering$ = createBehaviorEmitter<TilingEvent>();\n\n private config: TilingPluginConfig;\n private renderCapability: RenderCapability;\n private scrollCapability: ScrollCapability;\n private viewportCapability: ViewportCapability;\n\n constructor(id: string, registry: PluginRegistry, config: TilingPluginConfig) {\n super(id, registry);\n\n this.config = config;\n\n this.renderCapability = this.registry.getPlugin<RenderPlugin>('render')!.provides();\n this.scrollCapability = this.registry.getPlugin<ScrollPlugin>('scroll')!.provides();\n this.viewportCapability = this.registry.getPlugin<ViewportPlugin>('viewport')!.provides();\n\n this.scrollCapability.onScroll(\n (event: ScrollEvent) => this.calculateVisibleTiles(event.documentId, event.metrics),\n {\n mode: 'throttle',\n wait: 50,\n throttleMode: 'trailing',\n },\n );\n\n this.coreStore.onAction(REFRESH_PAGES, (action) => this.recalculateTiles(action.payload));\n }\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n this.dispatch(initTilingState(documentId, initialTilingDocumentState));\n }\n\n protected override onDocumentClosed(documentId: string): void {\n this.dispatch(cleanupTilingState(documentId));\n }\n\n protected override onScaleChanged(documentId: string): void {\n this.recalculateTilesForDocument(documentId);\n }\n\n protected override onRotationChanged(documentId: string): void {\n this.recalculateTilesForDocument(documentId);\n }\n\n private recalculateTilesForDocument(documentId: string): void {\n const scrollScope = this.scrollCapability.forDocument(documentId);\n const viewportScope = this.viewportCapability.forDocument(documentId);\n const metrics = scrollScope.getMetrics(viewportScope.getMetrics());\n this.calculateVisibleTiles(documentId, metrics);\n }\n\n async recalculateTiles(payload: RefreshPagesAction['payload']): Promise<void> {\n const { documentId, pageIndexes } = payload;\n const coreDoc = this.getCoreDocument(documentId);\n if (!coreDoc || !coreDoc.document) return;\n\n const scrollScope = this.scrollCapability.forDocument(documentId);\n const viewportScope = this.viewportCapability.forDocument(documentId);\n const currentMetrics = scrollScope.getMetrics(viewportScope.getMetrics());\n\n // Recalculate tiles for refreshed pages with a new timestamp\n const refreshedTiles: Record<number, Tile[]> = {};\n const refreshTimestamp = Date.now();\n const scale = coreDoc.scale;\n\n for (const pageIndex of pageIndexes) {\n const metric = currentMetrics.pageVisibilityMetrics.find(\n (m) => m.pageNumber === pageIndex + 1,\n );\n if (!metric) continue;\n\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n\n // Calculate effective rotation for this page (page intrinsic + document rotation)\n const effectiveRotation = ((page.rotation ?? 0) + coreDoc.rotation) % 4;\n\n refreshedTiles[pageIndex] = calculateTilesForPage({\n page,\n metric,\n scale,\n rotation: effectiveRotation,\n tileSize: this.config.tileSize,\n overlapPx: this.config.overlapPx,\n extraRings: this.config.extraRings,\n }).map((tile) => ({\n ...tile,\n id: `${tile.id}-r${refreshTimestamp}`, // Add refresh token to force new render\n }));\n }\n\n if (Object.keys(refreshedTiles).length > 0) {\n this.dispatch(updateVisibleTiles(documentId, refreshedTiles));\n }\n }\n\n async initialize(): Promise<void> {\n // Fetch dependencies from the registry if needed\n }\n\n private calculateVisibleTiles(documentId: string, scrollMetrics: ScrollMetrics): void {\n const coreDoc = this.getCoreDocument(documentId);\n if (!coreDoc || !coreDoc.document) return;\n\n const scale = coreDoc.scale;\n const visibleTiles: { [pageIndex: number]: Tile[] } = {};\n\n for (const scrollMetric of scrollMetrics.pageVisibilityMetrics) {\n const pageIndex = scrollMetric.pageNumber - 1; // Convert to 0-based index\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n\n // Calculate effective rotation for this page (page intrinsic + document rotation)\n const effectiveRotation = ((page.rotation ?? 0) + coreDoc.rotation) % 4;\n\n // Calculate tiles for the page using the utility function\n const tiles = calculateTilesForPage({\n page,\n metric: scrollMetric,\n scale,\n rotation: effectiveRotation,\n tileSize: this.config.tileSize,\n overlapPx: this.config.overlapPx,\n extraRings: this.config.extraRings,\n });\n\n visibleTiles[pageIndex] = tiles;\n }\n\n this.dispatch(updateVisibleTiles(documentId, visibleTiles));\n }\n\n override onStoreUpdated(prevState: TilingState, newState: TilingState): void {\n for (const documentId in newState.documents) {\n const prevDoc = prevState.documents[documentId];\n const newDoc = newState.documents[documentId];\n if (prevDoc !== newDoc) {\n this.tileRendering$.emit({ documentId, tiles: newDoc.visibleTiles });\n }\n }\n }\n\n protected buildCapability(): TilingCapability {\n return {\n renderTile: this.renderTile.bind(this),\n forDocument: this.createTilingScope.bind(this),\n onTileRendering: this.tileRendering$.on,\n };\n }\n\n private createTilingScope(documentId: string): TilingScope {\n return {\n renderTile: (options) => this.renderTile(options, documentId),\n onTileRendering: (listener: Listener<Record<number, Tile[]>>) =>\n this.tileRendering$.on((event) => {\n if (event.documentId === documentId) listener(event.tiles);\n }),\n };\n }\n\n private renderTile(options: RenderTileOptions, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n if (!this.renderCapability) {\n throw new Error('Render capability not available.');\n }\n\n this.dispatch(markTileStatus(id, options.pageIndex, options.tile.id, 'rendering'));\n\n const task = this.renderCapability.forDocument(id).renderPageRect({\n pageIndex: options.pageIndex,\n rect: options.tile.pageRect,\n options: {\n scaleFactor: options.tile.srcScale,\n dpr: options.dpr,\n },\n });\n\n task.wait(() => {\n this.dispatch(markTileStatus(id, options.pageIndex, options.tile.id, 'ready'));\n }, ignore);\n\n return task;\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { TilingAction } from './actions';\nimport { manifest, TILING_PLUGIN_ID } from './manifest';\nimport { initialState, tilingReducer } from './reducer';\nimport { TilingPlugin } from './tiling-plugin';\nimport { TilingPluginConfig, TilingState } from './types';\n\nexport const TilingPluginPackage: PluginPackage<\n TilingPlugin,\n TilingPluginConfig,\n TilingState,\n TilingAction\n> = {\n manifest,\n create: (registry, config) => new TilingPlugin(TILING_PLUGIN_ID, registry, config),\n reducer: (state, action) => tilingReducer(state, action),\n initialState,\n};\n\nexport * from './tiling-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":["TILING_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","tileSize","overlapPx","extraRings","INIT_TILING_STATE","CLEANUP_TILING_STATE","UPDATE_VISIBLE_TILES","MARK_TILE_STATUS","updateVisibleTiles","documentId","tiles","type","payload","markTileStatus","pageIndex","tileId","status","initialTilingDocumentState","visibleTiles","calculateTilesForPage","scale","rotation","page","metric","pageW","size","width","pageH","height","step","containerSize","transformSize","rotatedVisRect","origin","x","scaled","pageX","y","pageY","visibleWidth","visibleHeight","unrotatedVisRect","restoreRect","visLeft","visTop","visRight","visBottom","maxCol","Math","floor","maxRow","startCol","max","endCol","min","startRow","endRow","col","xScreen","wScreen","xPage","wPage","row","yScreen","hScreen","yPage","hPage","push","index","pageRect","screenRect","srcScale","isFallback","_TilingPlugin","BasePlugin","constructor","registry","config","super","this","tileRendering$","createBehaviorEmitter","renderCapability","getPlugin","scrollCapability","viewportCapability","onScroll","event","calculateVisibleTiles","metrics","mode","wait","throttleMode","coreStore","onAction","REFRESH_PAGES","action","recalculateTiles","onDocumentLoadingStarted","dispatch","state","initTilingState","onDocumentClosed","cleanupTilingState","onScaleChanged","recalculateTilesForDocument","onRotationChanged","scrollScope","forDocument","viewportScope","getMetrics","pageIndexes","coreDoc","getCoreDocument","document","currentMetrics","refreshedTiles","refreshTimestamp","Date","now","pageVisibilityMetrics","find","m","pageNumber","pages","effectiveRotation","map","tile","Object","keys","length","initialize","scrollMetrics","scrollMetric","onStoreUpdated","prevState","newState","documents","prevDoc","newDoc","emit","buildCapability","renderTile","bind","createTilingScope","onTileRendering","on","options","listener","getActiveDocumentId","Error","task","renderPageRect","rect","scaleFactor","dpr","ignore","TilingPlugin","TilingPluginPackage","create","reducer","docState","removed","remaining","incoming","nextPages","key","Number","newTiles","prevTiles","prevScale","_a","t","newScale","promoted","filter","fallbackToCarry","newIds","Set","keepers","seenIds","has","add","_b","finalTiles","every","tilingReducer","initialState"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -234,7 +234,6 @@ const _TilingPlugin = class _TilingPlugin extends BasePlugin {
234
234
  const refreshedTiles = {};
235
235
  const refreshTimestamp = Date.now();
236
236
  const scale = coreDoc.scale;
237
- const rotation = coreDoc.rotation;
238
237
  for (const pageIndex of pageIndexes) {
239
238
  const metric = currentMetrics.pageVisibilityMetrics.find(
240
239
  (m) => m.pageNumber === pageIndex + 1
@@ -242,11 +241,12 @@ const _TilingPlugin = class _TilingPlugin extends BasePlugin {
242
241
  if (!metric) continue;
243
242
  const page = coreDoc.document.pages[pageIndex];
244
243
  if (!page) continue;
244
+ const effectiveRotation = ((page.rotation ?? 0) + coreDoc.rotation) % 4;
245
245
  refreshedTiles[pageIndex] = calculateTilesForPage({
246
246
  page,
247
247
  metric,
248
248
  scale,
249
- rotation,
249
+ rotation: effectiveRotation,
250
250
  tileSize: this.config.tileSize,
251
251
  overlapPx: this.config.overlapPx,
252
252
  extraRings: this.config.extraRings
@@ -266,17 +266,17 @@ const _TilingPlugin = class _TilingPlugin extends BasePlugin {
266
266
  const coreDoc = this.getCoreDocument(documentId);
267
267
  if (!coreDoc || !coreDoc.document) return;
268
268
  const scale = coreDoc.scale;
269
- const rotation = coreDoc.rotation;
270
269
  const visibleTiles = {};
271
270
  for (const scrollMetric of scrollMetrics.pageVisibilityMetrics) {
272
271
  const pageIndex = scrollMetric.pageNumber - 1;
273
272
  const page = coreDoc.document.pages[pageIndex];
274
273
  if (!page) continue;
274
+ const effectiveRotation = ((page.rotation ?? 0) + coreDoc.rotation) % 4;
275
275
  const tiles = calculateTilesForPage({
276
276
  page,
277
277
  metric: scrollMetric,
278
278
  scale,
279
- rotation,
279
+ rotation: effectiveRotation,
280
280
  tileSize: this.config.tileSize,
281
281
  overlapPx: this.config.overlapPx,
282
282
  extraRings: this.config.extraRings
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/utils.ts","../src/lib/tiling-plugin.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\n\nimport { TilingPluginConfig } from './types';\n\nexport const TILING_PLUGIN_ID = 'tiling';\n\nexport const manifest: PluginManifest<TilingPluginConfig> = {\n id: TILING_PLUGIN_ID,\n name: 'Tiling Plugin',\n version: '1.0.0',\n provides: ['tiling'],\n requires: ['render', 'scroll', 'viewport'],\n optional: [],\n defaultConfig: {\n tileSize: 768,\n overlapPx: 2.5,\n extraRings: 0,\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { Tile, TileStatus, TilingDocumentState } from './types';\n\nexport const INIT_TILING_STATE = 'TILING/INIT_STATE';\nexport const CLEANUP_TILING_STATE = 'TILING/CLEANUP_STATE';\nexport const UPDATE_VISIBLE_TILES = 'TILING/UPDATE_VISIBLE_TILES';\nexport const MARK_TILE_STATUS = 'TILING/MARK_TILE_STATUS';\n\nexport interface InitTilingStateAction extends Action {\n type: typeof INIT_TILING_STATE;\n payload: {\n documentId: string;\n state: TilingDocumentState;\n };\n}\n\nexport interface CleanupTilingStateAction extends Action {\n type: typeof CLEANUP_TILING_STATE;\n payload: string; // documentId\n}\n\nexport type UpdateVisibleTilesAction = {\n type: typeof UPDATE_VISIBLE_TILES;\n payload: {\n documentId: string;\n tiles: Record<number, Tile[]>;\n };\n};\n\nexport type MarkTileStatusAction = {\n type: typeof MARK_TILE_STATUS;\n payload: {\n documentId: string;\n pageIndex: number;\n tileId: string;\n status: TileStatus;\n };\n};\n\nexport type TilingAction =\n | InitTilingStateAction\n | CleanupTilingStateAction\n | UpdateVisibleTilesAction\n | MarkTileStatusAction;\n\nexport const initTilingState = (\n documentId: string,\n state: TilingDocumentState,\n): InitTilingStateAction => ({\n type: INIT_TILING_STATE,\n payload: { documentId, state },\n});\n\nexport const cleanupTilingState = (documentId: string): CleanupTilingStateAction => ({\n type: CLEANUP_TILING_STATE,\n payload: documentId,\n});\n\nexport const updateVisibleTiles = (\n documentId: string,\n tiles: Record<number, Tile[]>,\n): UpdateVisibleTilesAction => ({\n type: UPDATE_VISIBLE_TILES,\n payload: { documentId, tiles },\n});\n\nexport const markTileStatus = (\n documentId: string,\n pageIndex: number,\n tileId: string,\n status: TileStatus,\n): MarkTileStatusAction => ({\n type: MARK_TILE_STATUS,\n payload: { documentId, pageIndex, tileId, status },\n});\n","import { Reducer } from '@embedpdf/core';\n\nimport {\n UPDATE_VISIBLE_TILES,\n MARK_TILE_STATUS,\n TilingAction,\n INIT_TILING_STATE,\n CLEANUP_TILING_STATE,\n} from './actions';\nimport { Tile, TilingDocumentState, TilingState } from './types';\n\nexport const initialTilingDocumentState: TilingDocumentState = {\n visibleTiles: {},\n};\n\nexport const initialState: TilingState = {\n documents: {},\n};\n\nexport const tilingReducer: Reducer<TilingState, TilingAction> = (state, action) => {\n switch (action.type) {\n case INIT_TILING_STATE: {\n const { documentId, state: docState } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n };\n }\n\n case CLEANUP_TILING_STATE: {\n const documentId = action.payload;\n const { [documentId]: removed, ...remaining } = state.documents;\n return {\n ...state,\n documents: remaining,\n };\n }\n\n case UPDATE_VISIBLE_TILES: {\n const { documentId, tiles: incoming } = action.payload; // Record<number, Tile[]>\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const nextPages = { ...docState.visibleTiles };\n\n for (const key in incoming) {\n const pageIndex = Number(key);\n const newTiles = incoming[pageIndex]; // all isFallback=false\n const prevTiles = nextPages[pageIndex] ?? [];\n\n const prevScale = prevTiles.find((t) => !t.isFallback)?.srcScale;\n const newScale = newTiles.length > 0 ? newTiles[0].srcScale : prevScale;\n const zoomChanged = prevScale !== undefined && prevScale !== newScale;\n\n if (zoomChanged) {\n /* 1️⃣ ready tiles from the old zoom → new fallback */\n const promoted = prevTiles\n .filter((t) => !t.isFallback && t.status === 'ready')\n .map((t) => ({ ...t, isFallback: true }));\n\n /* 2️⃣ decide which fallback tiles to keep */\n const fallbackToCarry = promoted.length > 0 ? [] : prevTiles.filter((t) => t.isFallback);\n\n /* 3️⃣ final list = (maybe-kept fallback) + promoted + newTiles */\n nextPages[pageIndex] = [...fallbackToCarry, ...promoted, ...newTiles];\n } else {\n /* same zoom → keep current fallback, replace visible */\n const newIds = new Set(newTiles.map((t) => t.id));\n const keepers: Tile[] = []; // where we’ll collect surviving tiles\n const seenIds = new Set<string>();\n\n /* 2️⃣ loop prevTiles once */\n for (const t of prevTiles) {\n if (t.isFallback) {\n keepers.push(t); // always keep fallback\n seenIds.add(t.id);\n } else if (newIds.has(t.id)) {\n keepers.push(t); // keep old visible tile (preserves status)\n seenIds.add(t.id);\n }\n }\n\n /* 3️⃣ append *brand-new* tiles (not yet kept) */\n for (const t of newTiles) {\n if (!seenIds.has(t.id)) keepers.push(t);\n }\n\n /* 4️⃣ store result */\n nextPages[pageIndex] = keepers;\n }\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n visibleTiles: nextPages,\n },\n },\n };\n }\n\n case MARK_TILE_STATUS: {\n const { documentId, pageIndex, tileId, status } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const tiles =\n docState.visibleTiles[pageIndex]?.map((t) =>\n t.id === tileId ? ({ ...t, status } as Tile) : t,\n ) ?? [];\n\n const newTiles = tiles.filter((t) => !t.isFallback);\n const allReady = newTiles.length > 0 && newTiles.every((t) => t.status === 'ready');\n const finalTiles = allReady ? newTiles : tiles;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n visibleTiles: { ...docState.visibleTiles, [pageIndex]: finalTiles },\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import { Rect, restoreRect, transformSize } from '@embedpdf/models';\nimport { CalculateTilesForPageOptions, Tile } from './types';\n\n/**\n * Build a grid where neighbouring tiles overlap by `overlapPx`\n * (screen pixels). Inner tiles keep the full `tileSize`, edge\n * tiles are clipped to the page bounds. All screen-space values\n * are rounded to **integers** to avoid sub-pixel seams.\n */\nexport function calculateTilesForPage({\n tileSize = 768,\n overlapPx = 2.5,\n extraRings = 0,\n scale,\n rotation,\n page,\n metric,\n}: CalculateTilesForPageOptions): Tile[] {\n /* ---- work in screen-pixel space -------------------------------- */\n const pageW = page.size.width * scale; // px\n const pageH = page.size.height * scale; // px\n\n const step = tileSize - overlapPx; // shift between tiles\n\n const containerSize = transformSize(page.size, rotation, scale);\n const rotatedVisRect: Rect = {\n origin: { x: metric.scaled.pageX, y: metric.scaled.pageY },\n size: { width: metric.scaled.visibleWidth, height: metric.scaled.visibleHeight },\n };\n const unrotatedVisRect = restoreRect(containerSize, rotatedVisRect, rotation, 1);\n\n const visLeft = unrotatedVisRect.origin.x;\n const visTop = unrotatedVisRect.origin.y;\n const visRight = visLeft + unrotatedVisRect.size.width;\n const visBottom = visTop + unrotatedVisRect.size.height;\n\n const maxCol = Math.floor((pageW - 1) / step);\n const maxRow = Math.floor((pageH - 1) / step);\n\n const startCol = Math.max(0, Math.floor(visLeft / step) - extraRings);\n const endCol = Math.min(maxCol, Math.floor((visRight - 1) / step) + extraRings);\n const startRow = Math.max(0, Math.floor(visTop / step) - extraRings);\n const endRow = Math.min(maxRow, Math.floor((visBottom - 1) / step) + extraRings);\n\n /* ---- build tiles ---------------------------------------------- */\n const tiles: Tile[] = [];\n\n for (let col = startCol; col <= endCol; col++) {\n const xScreen = col * step; // px (integer)\n const wScreen = Math.min(tileSize, pageW - xScreen); // px (≤ tileSize)\n\n const xPage = xScreen / scale; // pt (may be frac.)\n const wPage = wScreen / scale; // pt\n\n for (let row = startRow; row <= endRow; row++) {\n const yScreen = row * step;\n const hScreen = Math.min(tileSize, pageH - yScreen);\n\n const yPage = yScreen / scale;\n const hPage = hScreen / scale;\n\n tiles.push({\n id: `p${page.index}-${scale}-x${xScreen}-y${yScreen}-w${wScreen}-h${hScreen}`,\n col,\n row,\n pageRect: { origin: { x: xPage, y: yPage }, size: { width: wPage, height: hPage } },\n screenRect: {\n origin: { x: xScreen, y: yScreen },\n size: { width: wScreen, height: hScreen },\n },\n status: 'queued',\n srcScale: scale,\n isFallback: false,\n });\n }\n }\n\n return tiles;\n}\n","import {\n BasePlugin,\n createBehaviorEmitter,\n Listener,\n PluginRegistry,\n REFRESH_PAGES,\n RefreshPagesAction,\n} from '@embedpdf/core';\nimport { ignore } from '@embedpdf/models';\nimport { RenderCapability, RenderPlugin } from '@embedpdf/plugin-render';\nimport {\n ScrollCapability,\n ScrollMetrics,\n ScrollPlugin,\n ScrollEvent,\n} from '@embedpdf/plugin-scroll';\nimport { ViewportCapability, ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { initTilingState, cleanupTilingState, markTileStatus, updateVisibleTiles } from './actions';\nimport { initialTilingDocumentState } from './reducer';\nimport {\n TilingPluginConfig,\n TilingCapability,\n Tile,\n RenderTileOptions,\n TilingState,\n TilingEvent,\n TilingScope,\n} from './types';\nimport { calculateTilesForPage } from './utils';\n\nexport class TilingPlugin extends BasePlugin<TilingPluginConfig, TilingCapability, TilingState> {\n static readonly id = 'tiling' as const;\n\n private readonly tileRendering$ = createBehaviorEmitter<TilingEvent>();\n\n private config: TilingPluginConfig;\n private renderCapability: RenderCapability;\n private scrollCapability: ScrollCapability;\n private viewportCapability: ViewportCapability;\n\n constructor(id: string, registry: PluginRegistry, config: TilingPluginConfig) {\n super(id, registry);\n\n this.config = config;\n\n this.renderCapability = this.registry.getPlugin<RenderPlugin>('render')!.provides();\n this.scrollCapability = this.registry.getPlugin<ScrollPlugin>('scroll')!.provides();\n this.viewportCapability = this.registry.getPlugin<ViewportPlugin>('viewport')!.provides();\n\n this.scrollCapability.onScroll(\n (event: ScrollEvent) => this.calculateVisibleTiles(event.documentId, event.metrics),\n {\n mode: 'throttle',\n wait: 50,\n throttleMode: 'trailing',\n },\n );\n\n this.coreStore.onAction(REFRESH_PAGES, (action) => this.recalculateTiles(action.payload));\n }\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n this.dispatch(initTilingState(documentId, initialTilingDocumentState));\n }\n\n protected override onDocumentClosed(documentId: string): void {\n this.dispatch(cleanupTilingState(documentId));\n }\n\n protected override onScaleChanged(documentId: string): void {\n this.recalculateTilesForDocument(documentId);\n }\n\n protected override onRotationChanged(documentId: string): void {\n this.recalculateTilesForDocument(documentId);\n }\n\n private recalculateTilesForDocument(documentId: string): void {\n const scrollScope = this.scrollCapability.forDocument(documentId);\n const viewportScope = this.viewportCapability.forDocument(documentId);\n const metrics = scrollScope.getMetrics(viewportScope.getMetrics());\n this.calculateVisibleTiles(documentId, metrics);\n }\n\n async recalculateTiles(payload: RefreshPagesAction['payload']): Promise<void> {\n const { documentId, pageIndexes } = payload;\n const coreDoc = this.getCoreDocument(documentId);\n if (!coreDoc || !coreDoc.document) return;\n\n const scrollScope = this.scrollCapability.forDocument(documentId);\n const viewportScope = this.viewportCapability.forDocument(documentId);\n const currentMetrics = scrollScope.getMetrics(viewportScope.getMetrics());\n\n // Recalculate tiles for refreshed pages with a new timestamp\n const refreshedTiles: Record<number, Tile[]> = {};\n const refreshTimestamp = Date.now();\n const scale = coreDoc.scale;\n const rotation = coreDoc.rotation;\n\n for (const pageIndex of pageIndexes) {\n const metric = currentMetrics.pageVisibilityMetrics.find(\n (m) => m.pageNumber === pageIndex + 1,\n );\n if (!metric) continue;\n\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n\n refreshedTiles[pageIndex] = calculateTilesForPage({\n page,\n metric,\n scale,\n rotation,\n tileSize: this.config.tileSize,\n overlapPx: this.config.overlapPx,\n extraRings: this.config.extraRings,\n }).map((tile) => ({\n ...tile,\n id: `${tile.id}-r${refreshTimestamp}`, // Add refresh token to force new render\n }));\n }\n\n if (Object.keys(refreshedTiles).length > 0) {\n this.dispatch(updateVisibleTiles(documentId, refreshedTiles));\n }\n }\n\n async initialize(): Promise<void> {\n // Fetch dependencies from the registry if needed\n }\n\n private calculateVisibleTiles(documentId: string, scrollMetrics: ScrollMetrics): void {\n const coreDoc = this.getCoreDocument(documentId);\n if (!coreDoc || !coreDoc.document) return;\n\n const scale = coreDoc.scale;\n const rotation = coreDoc.rotation;\n const visibleTiles: { [pageIndex: number]: Tile[] } = {};\n\n for (const scrollMetric of scrollMetrics.pageVisibilityMetrics) {\n const pageIndex = scrollMetric.pageNumber - 1; // Convert to 0-based index\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n\n // Calculate tiles for the page using the utility function\n const tiles = calculateTilesForPage({\n page,\n metric: scrollMetric,\n scale,\n rotation,\n tileSize: this.config.tileSize,\n overlapPx: this.config.overlapPx,\n extraRings: this.config.extraRings,\n });\n\n visibleTiles[pageIndex] = tiles;\n }\n\n this.dispatch(updateVisibleTiles(documentId, visibleTiles));\n }\n\n override onStoreUpdated(prevState: TilingState, newState: TilingState): void {\n for (const documentId in newState.documents) {\n const prevDoc = prevState.documents[documentId];\n const newDoc = newState.documents[documentId];\n if (prevDoc !== newDoc) {\n this.tileRendering$.emit({ documentId, tiles: newDoc.visibleTiles });\n }\n }\n }\n\n protected buildCapability(): TilingCapability {\n return {\n renderTile: this.renderTile.bind(this),\n forDocument: this.createTilingScope.bind(this),\n onTileRendering: this.tileRendering$.on,\n };\n }\n\n private createTilingScope(documentId: string): TilingScope {\n return {\n renderTile: (options) => this.renderTile(options, documentId),\n onTileRendering: (listener: Listener<Record<number, Tile[]>>) =>\n this.tileRendering$.on((event) => {\n if (event.documentId === documentId) listener(event.tiles);\n }),\n };\n }\n\n private renderTile(options: RenderTileOptions, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n if (!this.renderCapability) {\n throw new Error('Render capability not available.');\n }\n\n this.dispatch(markTileStatus(id, options.pageIndex, options.tile.id, 'rendering'));\n\n const task = this.renderCapability.forDocument(id).renderPageRect({\n pageIndex: options.pageIndex,\n rect: options.tile.pageRect,\n options: {\n scaleFactor: options.tile.srcScale,\n dpr: options.dpr,\n },\n });\n\n task.wait(() => {\n this.dispatch(markTileStatus(id, options.pageIndex, options.tile.id, 'ready'));\n }, ignore);\n\n return task;\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { TilingAction } from './actions';\nimport { manifest, TILING_PLUGIN_ID } from './manifest';\nimport { initialState, tilingReducer } from './reducer';\nimport { TilingPlugin } from './tiling-plugin';\nimport { TilingPluginConfig, TilingState } from './types';\n\nexport const TilingPluginPackage: PluginPackage<\n TilingPlugin,\n TilingPluginConfig,\n TilingState,\n TilingAction\n> = {\n manifest,\n create: (registry, config) => new TilingPlugin(TILING_PLUGIN_ID, registry, config),\n reducer: (state, action) => tilingReducer(state, action),\n initialState,\n};\n\nexport * from './tiling-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":[],"mappings":";;AAIO,MAAM,mBAAmB;AAEzB,MAAM,WAA+C;AAAA,EAC1D,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU,CAAC,QAAQ;AAAA,EACnB,UAAU,CAAC,UAAU,UAAU,UAAU;AAAA,EACzC,UAAU,CAAA;AAAA,EACV,eAAe;AAAA,IACb,UAAU;AAAA,IACV,WAAW;AAAA,IACX,YAAY;AAAA,EAAA;AAEhB;ACfO,MAAM,oBAAoB;AAC1B,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAC7B,MAAM,mBAAmB;AAuCzB,MAAM,kBAAkB,CAC7B,YACA,WAC2B;AAAA,EAC3B,MAAM;AAAA,EACN,SAAS,EAAE,YAAY,MAAA;AACzB;AAEO,MAAM,qBAAqB,CAAC,gBAAkD;AAAA,EACnF,MAAM;AAAA,EACN,SAAS;AACX;AAEO,MAAM,qBAAqB,CAChC,YACA,WAC8B;AAAA,EAC9B,MAAM;AAAA,EACN,SAAS,EAAE,YAAY,MAAA;AACzB;AAEO,MAAM,iBAAiB,CAC5B,YACA,WACA,QACA,YAC0B;AAAA,EAC1B,MAAM;AAAA,EACN,SAAS,EAAE,YAAY,WAAW,QAAQ,OAAA;AAC5C;AC/DO,MAAM,6BAAkD;AAAA,EAC7D,cAAc,CAAA;AAChB;AAEO,MAAM,eAA4B;AAAA,EACvC,WAAW,CAAA;AACb;AAEO,MAAM,gBAAoD,CAAC,OAAO,WAAW;;AAClF,UAAQ,OAAO,MAAA;AAAA,IACb,KAAK,mBAAmB;AACtB,YAAM,EAAE,YAAY,OAAO,SAAA,IAAa,OAAO;AAC/C,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW;AAAA,UACT,GAAG,MAAM;AAAA,UACT,CAAC,UAAU,GAAG;AAAA,QAAA;AAAA,MAChB;AAAA,IAEJ;AAAA,IAEA,KAAK,sBAAsB;AACzB,YAAM,aAAa,OAAO;AAC1B,YAAM,EAAE,CAAC,UAAU,GAAG,SAAS,GAAG,UAAA,IAAc,MAAM;AACtD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW;AAAA,MAAA;AAAA,IAEf;AAAA,IAEA,KAAK,sBAAsB;AACzB,YAAM,EAAE,YAAY,OAAO,SAAA,IAAa,OAAO;AAC/C,YAAM,WAAW,MAAM,UAAU,UAAU;AAC3C,UAAI,CAAC,SAAU,QAAO;AAEtB,YAAM,YAAY,EAAE,GAAG,SAAS,aAAA;AAEhC,iBAAW,OAAO,UAAU;AAC1B,cAAM,YAAY,OAAO,GAAG;AAC5B,cAAM,WAAW,SAAS,SAAS;AACnC,cAAM,YAAY,UAAU,SAAS,KAAK,CAAA;AAE1C,cAAM,aAAY,eAAU,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,MAAnC,mBAAsC;AACxD,cAAM,WAAW,SAAS,SAAS,IAAI,SAAS,CAAC,EAAE,WAAW;AAC9D,cAAM,cAAc,cAAc,UAAa,cAAc;AAE7D,YAAI,aAAa;AAEf,gBAAM,WAAW,UACd,OAAO,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,WAAW,OAAO,EACnD,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,YAAY,OAAO;AAG1C,gBAAM,kBAAkB,SAAS,SAAS,IAAI,CAAA,IAAK,UAAU,OAAO,CAAC,MAAM,EAAE,UAAU;AAGvF,oBAAU,SAAS,IAAI,CAAC,GAAG,iBAAiB,GAAG,UAAU,GAAG,QAAQ;AAAA,QACtE,OAAO;AAEL,gBAAM,SAAS,IAAI,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAChD,gBAAM,UAAkB,CAAA;AACxB,gBAAM,8BAAc,IAAA;AAGpB,qBAAW,KAAK,WAAW;AACzB,gBAAI,EAAE,YAAY;AAChB,sBAAQ,KAAK,CAAC;AACd,sBAAQ,IAAI,EAAE,EAAE;AAAA,YAClB,WAAW,OAAO,IAAI,EAAE,EAAE,GAAG;AAC3B,sBAAQ,KAAK,CAAC;AACd,sBAAQ,IAAI,EAAE,EAAE;AAAA,YAClB;AAAA,UACF;AAGA,qBAAW,KAAK,UAAU;AACxB,gBAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,EAAG,SAAQ,KAAK,CAAC;AAAA,UACxC;AAGA,oBAAU,SAAS,IAAI;AAAA,QACzB;AAAA,MACF;AAEA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW;AAAA,UACT,GAAG,MAAM;AAAA,UACT,CAAC,UAAU,GAAG;AAAA,YACZ,GAAG;AAAA,YACH,cAAc;AAAA,UAAA;AAAA,QAChB;AAAA,MACF;AAAA,IAEJ;AAAA,IAEA,KAAK,kBAAkB;AACrB,YAAM,EAAE,YAAY,WAAW,QAAQ,OAAA,IAAW,OAAO;AACzD,YAAM,WAAW,MAAM,UAAU,UAAU;AAC3C,UAAI,CAAC,SAAU,QAAO;AAEtB,YAAM,UACJ,cAAS,aAAa,SAAS,MAA/B,mBAAkC;AAAA,QAAI,CAAC,MACrC,EAAE,OAAO,SAAU,EAAE,GAAG,GAAG,WAAoB;AAAA,YAC5C,CAAA;AAEP,YAAM,WAAW,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,UAAU;AAClD,YAAM,WAAW,SAAS,SAAS,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,OAAO;AAClF,YAAM,aAAa,WAAW,WAAW;AAEzC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW;AAAA,UACT,GAAG,MAAM;AAAA,UACT,CAAC,UAAU,GAAG;AAAA,YACZ,GAAG;AAAA,YACH,cAAc,EAAE,GAAG,SAAS,cAAc,CAAC,SAAS,GAAG,WAAA;AAAA,UAAW;AAAA,QACpE;AAAA,MACF;AAAA,IAEJ;AAAA,IAEA;AACE,aAAO;AAAA,EAAA;AAEb;AC/HO,SAAS,sBAAsB;AAAA,EACpC,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyC;AAEvC,QAAM,QAAQ,KAAK,KAAK,QAAQ;AAChC,QAAM,QAAQ,KAAK,KAAK,SAAS;AAEjC,QAAM,OAAO,WAAW;AAExB,QAAM,gBAAgB,cAAc,KAAK,MAAM,UAAU,KAAK;AAC9D,QAAM,iBAAuB;AAAA,IAC3B,QAAQ,EAAE,GAAG,OAAO,OAAO,OAAO,GAAG,OAAO,OAAO,MAAA;AAAA,IACnD,MAAM,EAAE,OAAO,OAAO,OAAO,cAAc,QAAQ,OAAO,OAAO,cAAA;AAAA,EAAc;AAEjF,QAAM,mBAAmB,YAAY,eAAe,gBAAgB,UAAU,CAAC;AAE/E,QAAM,UAAU,iBAAiB,OAAO;AACxC,QAAM,SAAS,iBAAiB,OAAO;AACvC,QAAM,WAAW,UAAU,iBAAiB,KAAK;AACjD,QAAM,YAAY,SAAS,iBAAiB,KAAK;AAEjD,QAAM,SAAS,KAAK,OAAO,QAAQ,KAAK,IAAI;AAC5C,QAAM,SAAS,KAAK,OAAO,QAAQ,KAAK,IAAI;AAE5C,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,UAAU,IAAI,IAAI,UAAU;AACpE,QAAM,SAAS,KAAK,IAAI,QAAQ,KAAK,OAAO,WAAW,KAAK,IAAI,IAAI,UAAU;AAC9E,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,IAAI,IAAI,UAAU;AACnE,QAAM,SAAS,KAAK,IAAI,QAAQ,KAAK,OAAO,YAAY,KAAK,IAAI,IAAI,UAAU;AAG/E,QAAM,QAAgB,CAAA;AAEtB,WAAS,MAAM,UAAU,OAAO,QAAQ,OAAO;AAC7C,UAAM,UAAU,MAAM;AACtB,UAAM,UAAU,KAAK,IAAI,UAAU,QAAQ,OAAO;AAElD,UAAM,QAAQ,UAAU;AACxB,UAAM,QAAQ,UAAU;AAExB,aAAS,MAAM,UAAU,OAAO,QAAQ,OAAO;AAC7C,YAAM,UAAU,MAAM;AACtB,YAAM,UAAU,KAAK,IAAI,UAAU,QAAQ,OAAO;AAElD,YAAM,QAAQ,UAAU;AACxB,YAAM,QAAQ,UAAU;AAExB,YAAM,KAAK;AAAA,QACT,IAAI,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,OAAO,KAAK,OAAO,KAAK,OAAO,KAAK,OAAO;AAAA,QAC3E;AAAA,QACA;AAAA,QACA,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,GAAG,SAAS,MAAM,EAAE,OAAO,OAAO,QAAQ,QAAM;AAAA,QAChF,YAAY;AAAA,UACV,QAAQ,EAAE,GAAG,SAAS,GAAG,QAAA;AAAA,UACzB,MAAM,EAAE,OAAO,SAAS,QAAQ,QAAA;AAAA,QAAQ;AAAA,QAE1C,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,YAAY;AAAA,MAAA,CACb;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AC/CO,MAAM,gBAAN,MAAM,sBAAqB,WAA8D;AAAA,EAU9F,YAAY,IAAY,UAA0B,QAA4B;AAC5E,UAAM,IAAI,QAAQ;AARpB,SAAiB,iBAAiB,sBAAA;AAUhC,SAAK,SAAS;AAEd,SAAK,mBAAmB,KAAK,SAAS,UAAwB,QAAQ,EAAG,SAAA;AACzE,SAAK,mBAAmB,KAAK,SAAS,UAAwB,QAAQ,EAAG,SAAA;AACzE,SAAK,qBAAqB,KAAK,SAAS,UAA0B,UAAU,EAAG,SAAA;AAE/E,SAAK,iBAAiB;AAAA,MACpB,CAAC,UAAuB,KAAK,sBAAsB,MAAM,YAAY,MAAM,OAAO;AAAA,MAClF;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,cAAc;AAAA,MAAA;AAAA,IAChB;AAGF,SAAK,UAAU,SAAS,eAAe,CAAC,WAAW,KAAK,iBAAiB,OAAO,OAAO,CAAC;AAAA,EAC1F;AAAA,EAEmB,yBAAyB,YAA0B;AACpE,SAAK,SAAS,gBAAgB,YAAY,0BAA0B,CAAC;AAAA,EACvE;AAAA,EAEmB,iBAAiB,YAA0B;AAC5D,SAAK,SAAS,mBAAmB,UAAU,CAAC;AAAA,EAC9C;AAAA,EAEmB,eAAe,YAA0B;AAC1D,SAAK,4BAA4B,UAAU;AAAA,EAC7C;AAAA,EAEmB,kBAAkB,YAA0B;AAC7D,SAAK,4BAA4B,UAAU;AAAA,EAC7C;AAAA,EAEQ,4BAA4B,YAA0B;AAC5D,UAAM,cAAc,KAAK,iBAAiB,YAAY,UAAU;AAChE,UAAM,gBAAgB,KAAK,mBAAmB,YAAY,UAAU;AACpE,UAAM,UAAU,YAAY,WAAW,cAAc,YAAY;AACjE,SAAK,sBAAsB,YAAY,OAAO;AAAA,EAChD;AAAA,EAEA,MAAM,iBAAiB,SAAuD;AAC5E,UAAM,EAAE,YAAY,YAAA,IAAgB;AACpC,UAAM,UAAU,KAAK,gBAAgB,UAAU;AAC/C,QAAI,CAAC,WAAW,CAAC,QAAQ,SAAU;AAEnC,UAAM,cAAc,KAAK,iBAAiB,YAAY,UAAU;AAChE,UAAM,gBAAgB,KAAK,mBAAmB,YAAY,UAAU;AACpE,UAAM,iBAAiB,YAAY,WAAW,cAAc,YAAY;AAGxE,UAAM,iBAAyC,CAAA;AAC/C,UAAM,mBAAmB,KAAK,IAAA;AAC9B,UAAM,QAAQ,QAAQ;AACtB,UAAM,WAAW,QAAQ;AAEzB,eAAW,aAAa,aAAa;AACnC,YAAM,SAAS,eAAe,sBAAsB;AAAA,QAClD,CAAC,MAAM,EAAE,eAAe,YAAY;AAAA,MAAA;AAEtC,UAAI,CAAC,OAAQ;AAEb,YAAM,OAAO,QAAQ,SAAS,MAAM,SAAS;AAC7C,UAAI,CAAC,KAAM;AAEX,qBAAe,SAAS,IAAI,sBAAsB;AAAA,QAChD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,UAAU,KAAK,OAAO;AAAA,QACtB,WAAW,KAAK,OAAO;AAAA,QACvB,YAAY,KAAK,OAAO;AAAA,MAAA,CACzB,EAAE,IAAI,CAAC,UAAU;AAAA,QAChB,GAAG;AAAA,QACH,IAAI,GAAG,KAAK,EAAE,KAAK,gBAAgB;AAAA;AAAA,MAAA,EACnC;AAAA,IACJ;AAEA,QAAI,OAAO,KAAK,cAAc,EAAE,SAAS,GAAG;AAC1C,WAAK,SAAS,mBAAmB,YAAY,cAAc,CAAC;AAAA,IAC9D;AAAA,EACF;AAAA,EAEA,MAAM,aAA4B;AAAA,EAElC;AAAA,EAEQ,sBAAsB,YAAoB,eAAoC;AACpF,UAAM,UAAU,KAAK,gBAAgB,UAAU;AAC/C,QAAI,CAAC,WAAW,CAAC,QAAQ,SAAU;AAEnC,UAAM,QAAQ,QAAQ;AACtB,UAAM,WAAW,QAAQ;AACzB,UAAM,eAAgD,CAAA;AAEtD,eAAW,gBAAgB,cAAc,uBAAuB;AAC9D,YAAM,YAAY,aAAa,aAAa;AAC5C,YAAM,OAAO,QAAQ,SAAS,MAAM,SAAS;AAC7C,UAAI,CAAC,KAAM;AAGX,YAAM,QAAQ,sBAAsB;AAAA,QAClC;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,UAAU,KAAK,OAAO;AAAA,QACtB,WAAW,KAAK,OAAO;AAAA,QACvB,YAAY,KAAK,OAAO;AAAA,MAAA,CACzB;AAED,mBAAa,SAAS,IAAI;AAAA,IAC5B;AAEA,SAAK,SAAS,mBAAmB,YAAY,YAAY,CAAC;AAAA,EAC5D;AAAA,EAES,eAAe,WAAwB,UAA6B;AAC3E,eAAW,cAAc,SAAS,WAAW;AAC3C,YAAM,UAAU,UAAU,UAAU,UAAU;AAC9C,YAAM,SAAS,SAAS,UAAU,UAAU;AAC5C,UAAI,YAAY,QAAQ;AACtB,aAAK,eAAe,KAAK,EAAE,YAAY,OAAO,OAAO,cAAc;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AAAA,EAEU,kBAAoC;AAC5C,WAAO;AAAA,MACL,YAAY,KAAK,WAAW,KAAK,IAAI;AAAA,MACrC,aAAa,KAAK,kBAAkB,KAAK,IAAI;AAAA,MAC7C,iBAAiB,KAAK,eAAe;AAAA,IAAA;AAAA,EAEzC;AAAA,EAEQ,kBAAkB,YAAiC;AACzD,WAAO;AAAA,MACL,YAAY,CAAC,YAAY,KAAK,WAAW,SAAS,UAAU;AAAA,MAC5D,iBAAiB,CAAC,aAChB,KAAK,eAAe,GAAG,CAAC,UAAU;AAChC,YAAI,MAAM,eAAe,WAAY,UAAS,MAAM,KAAK;AAAA,MAC3D,CAAC;AAAA,IAAA;AAAA,EAEP;AAAA,EAEQ,WAAW,SAA4B,YAAqB;AAClE,UAAM,KAAK,cAAc,KAAK,oBAAA;AAC9B,QAAI,CAAC,KAAK,kBAAkB;AAC1B,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAEA,SAAK,SAAS,eAAe,IAAI,QAAQ,WAAW,QAAQ,KAAK,IAAI,WAAW,CAAC;AAEjF,UAAM,OAAO,KAAK,iBAAiB,YAAY,EAAE,EAAE,eAAe;AAAA,MAChE,WAAW,QAAQ;AAAA,MACnB,MAAM,QAAQ,KAAK;AAAA,MACnB,SAAS;AAAA,QACP,aAAa,QAAQ,KAAK;AAAA,QAC1B,KAAK,QAAQ;AAAA,MAAA;AAAA,IACf,CACD;AAED,SAAK,KAAK,MAAM;AACd,WAAK,SAAS,eAAe,IAAI,QAAQ,WAAW,QAAQ,KAAK,IAAI,OAAO,CAAC;AAAA,IAC/E,GAAG,MAAM;AAET,WAAO;AAAA,EACT;AACF;AArLE,cAAgB,KAAK;AADhB,IAAM,eAAN;ACvBA,MAAM,sBAKT;AAAA,EACF;AAAA,EACA,QAAQ,CAAC,UAAU,WAAW,IAAI,aAAa,kBAAkB,UAAU,MAAM;AAAA,EACjF,SAAS,CAAC,OAAO,WAAW,cAAc,OAAO,MAAM;AAAA,EACvD;AACF;"}
1
+ {"version":3,"file":"index.js","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/utils.ts","../src/lib/tiling-plugin.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\n\nimport { TilingPluginConfig } from './types';\n\nexport const TILING_PLUGIN_ID = 'tiling';\n\nexport const manifest: PluginManifest<TilingPluginConfig> = {\n id: TILING_PLUGIN_ID,\n name: 'Tiling Plugin',\n version: '1.0.0',\n provides: ['tiling'],\n requires: ['render', 'scroll', 'viewport'],\n optional: [],\n defaultConfig: {\n tileSize: 768,\n overlapPx: 2.5,\n extraRings: 0,\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { Tile, TileStatus, TilingDocumentState } from './types';\n\nexport const INIT_TILING_STATE = 'TILING/INIT_STATE';\nexport const CLEANUP_TILING_STATE = 'TILING/CLEANUP_STATE';\nexport const UPDATE_VISIBLE_TILES = 'TILING/UPDATE_VISIBLE_TILES';\nexport const MARK_TILE_STATUS = 'TILING/MARK_TILE_STATUS';\n\nexport interface InitTilingStateAction extends Action {\n type: typeof INIT_TILING_STATE;\n payload: {\n documentId: string;\n state: TilingDocumentState;\n };\n}\n\nexport interface CleanupTilingStateAction extends Action {\n type: typeof CLEANUP_TILING_STATE;\n payload: string; // documentId\n}\n\nexport type UpdateVisibleTilesAction = {\n type: typeof UPDATE_VISIBLE_TILES;\n payload: {\n documentId: string;\n tiles: Record<number, Tile[]>;\n };\n};\n\nexport type MarkTileStatusAction = {\n type: typeof MARK_TILE_STATUS;\n payload: {\n documentId: string;\n pageIndex: number;\n tileId: string;\n status: TileStatus;\n };\n};\n\nexport type TilingAction =\n | InitTilingStateAction\n | CleanupTilingStateAction\n | UpdateVisibleTilesAction\n | MarkTileStatusAction;\n\nexport const initTilingState = (\n documentId: string,\n state: TilingDocumentState,\n): InitTilingStateAction => ({\n type: INIT_TILING_STATE,\n payload: { documentId, state },\n});\n\nexport const cleanupTilingState = (documentId: string): CleanupTilingStateAction => ({\n type: CLEANUP_TILING_STATE,\n payload: documentId,\n});\n\nexport const updateVisibleTiles = (\n documentId: string,\n tiles: Record<number, Tile[]>,\n): UpdateVisibleTilesAction => ({\n type: UPDATE_VISIBLE_TILES,\n payload: { documentId, tiles },\n});\n\nexport const markTileStatus = (\n documentId: string,\n pageIndex: number,\n tileId: string,\n status: TileStatus,\n): MarkTileStatusAction => ({\n type: MARK_TILE_STATUS,\n payload: { documentId, pageIndex, tileId, status },\n});\n","import { Reducer } from '@embedpdf/core';\n\nimport {\n UPDATE_VISIBLE_TILES,\n MARK_TILE_STATUS,\n TilingAction,\n INIT_TILING_STATE,\n CLEANUP_TILING_STATE,\n} from './actions';\nimport { Tile, TilingDocumentState, TilingState } from './types';\n\nexport const initialTilingDocumentState: TilingDocumentState = {\n visibleTiles: {},\n};\n\nexport const initialState: TilingState = {\n documents: {},\n};\n\nexport const tilingReducer: Reducer<TilingState, TilingAction> = (state, action) => {\n switch (action.type) {\n case INIT_TILING_STATE: {\n const { documentId, state: docState } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n };\n }\n\n case CLEANUP_TILING_STATE: {\n const documentId = action.payload;\n const { [documentId]: removed, ...remaining } = state.documents;\n return {\n ...state,\n documents: remaining,\n };\n }\n\n case UPDATE_VISIBLE_TILES: {\n const { documentId, tiles: incoming } = action.payload; // Record<number, Tile[]>\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const nextPages = { ...docState.visibleTiles };\n\n for (const key in incoming) {\n const pageIndex = Number(key);\n const newTiles = incoming[pageIndex]; // all isFallback=false\n const prevTiles = nextPages[pageIndex] ?? [];\n\n const prevScale = prevTiles.find((t) => !t.isFallback)?.srcScale;\n const newScale = newTiles.length > 0 ? newTiles[0].srcScale : prevScale;\n const zoomChanged = prevScale !== undefined && prevScale !== newScale;\n\n if (zoomChanged) {\n /* 1️⃣ ready tiles from the old zoom → new fallback */\n const promoted = prevTiles\n .filter((t) => !t.isFallback && t.status === 'ready')\n .map((t) => ({ ...t, isFallback: true }));\n\n /* 2️⃣ decide which fallback tiles to keep */\n const fallbackToCarry = promoted.length > 0 ? [] : prevTiles.filter((t) => t.isFallback);\n\n /* 3️⃣ final list = (maybe-kept fallback) + promoted + newTiles */\n nextPages[pageIndex] = [...fallbackToCarry, ...promoted, ...newTiles];\n } else {\n /* same zoom → keep current fallback, replace visible */\n const newIds = new Set(newTiles.map((t) => t.id));\n const keepers: Tile[] = []; // where we’ll collect surviving tiles\n const seenIds = new Set<string>();\n\n /* 2️⃣ loop prevTiles once */\n for (const t of prevTiles) {\n if (t.isFallback) {\n keepers.push(t); // always keep fallback\n seenIds.add(t.id);\n } else if (newIds.has(t.id)) {\n keepers.push(t); // keep old visible tile (preserves status)\n seenIds.add(t.id);\n }\n }\n\n /* 3️⃣ append *brand-new* tiles (not yet kept) */\n for (const t of newTiles) {\n if (!seenIds.has(t.id)) keepers.push(t);\n }\n\n /* 4️⃣ store result */\n nextPages[pageIndex] = keepers;\n }\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n visibleTiles: nextPages,\n },\n },\n };\n }\n\n case MARK_TILE_STATUS: {\n const { documentId, pageIndex, tileId, status } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const tiles =\n docState.visibleTiles[pageIndex]?.map((t) =>\n t.id === tileId ? ({ ...t, status } as Tile) : t,\n ) ?? [];\n\n const newTiles = tiles.filter((t) => !t.isFallback);\n const allReady = newTiles.length > 0 && newTiles.every((t) => t.status === 'ready');\n const finalTiles = allReady ? newTiles : tiles;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n visibleTiles: { ...docState.visibleTiles, [pageIndex]: finalTiles },\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import { Rect, restoreRect, transformSize } from '@embedpdf/models';\nimport { CalculateTilesForPageOptions, Tile } from './types';\n\n/**\n * Build a grid where neighbouring tiles overlap by `overlapPx`\n * (screen pixels). Inner tiles keep the full `tileSize`, edge\n * tiles are clipped to the page bounds. All screen-space values\n * are rounded to **integers** to avoid sub-pixel seams.\n */\nexport function calculateTilesForPage({\n tileSize = 768,\n overlapPx = 2.5,\n extraRings = 0,\n scale,\n rotation,\n page,\n metric,\n}: CalculateTilesForPageOptions): Tile[] {\n /* ---- work in screen-pixel space -------------------------------- */\n const pageW = page.size.width * scale; // px\n const pageH = page.size.height * scale; // px\n\n const step = tileSize - overlapPx; // shift between tiles\n\n const containerSize = transformSize(page.size, rotation, scale);\n const rotatedVisRect: Rect = {\n origin: { x: metric.scaled.pageX, y: metric.scaled.pageY },\n size: { width: metric.scaled.visibleWidth, height: metric.scaled.visibleHeight },\n };\n const unrotatedVisRect = restoreRect(containerSize, rotatedVisRect, rotation, 1);\n\n const visLeft = unrotatedVisRect.origin.x;\n const visTop = unrotatedVisRect.origin.y;\n const visRight = visLeft + unrotatedVisRect.size.width;\n const visBottom = visTop + unrotatedVisRect.size.height;\n\n const maxCol = Math.floor((pageW - 1) / step);\n const maxRow = Math.floor((pageH - 1) / step);\n\n const startCol = Math.max(0, Math.floor(visLeft / step) - extraRings);\n const endCol = Math.min(maxCol, Math.floor((visRight - 1) / step) + extraRings);\n const startRow = Math.max(0, Math.floor(visTop / step) - extraRings);\n const endRow = Math.min(maxRow, Math.floor((visBottom - 1) / step) + extraRings);\n\n /* ---- build tiles ---------------------------------------------- */\n const tiles: Tile[] = [];\n\n for (let col = startCol; col <= endCol; col++) {\n const xScreen = col * step; // px (integer)\n const wScreen = Math.min(tileSize, pageW - xScreen); // px (≤ tileSize)\n\n const xPage = xScreen / scale; // pt (may be frac.)\n const wPage = wScreen / scale; // pt\n\n for (let row = startRow; row <= endRow; row++) {\n const yScreen = row * step;\n const hScreen = Math.min(tileSize, pageH - yScreen);\n\n const yPage = yScreen / scale;\n const hPage = hScreen / scale;\n\n tiles.push({\n id: `p${page.index}-${scale}-x${xScreen}-y${yScreen}-w${wScreen}-h${hScreen}`,\n col,\n row,\n pageRect: { origin: { x: xPage, y: yPage }, size: { width: wPage, height: hPage } },\n screenRect: {\n origin: { x: xScreen, y: yScreen },\n size: { width: wScreen, height: hScreen },\n },\n status: 'queued',\n srcScale: scale,\n isFallback: false,\n });\n }\n }\n\n return tiles;\n}\n","import {\n BasePlugin,\n createBehaviorEmitter,\n Listener,\n PluginRegistry,\n REFRESH_PAGES,\n RefreshPagesAction,\n} from '@embedpdf/core';\nimport { ignore } from '@embedpdf/models';\nimport { RenderCapability, RenderPlugin } from '@embedpdf/plugin-render';\nimport {\n ScrollCapability,\n ScrollMetrics,\n ScrollPlugin,\n ScrollEvent,\n} from '@embedpdf/plugin-scroll';\nimport { ViewportCapability, ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { initTilingState, cleanupTilingState, markTileStatus, updateVisibleTiles } from './actions';\nimport { initialTilingDocumentState } from './reducer';\nimport {\n TilingPluginConfig,\n TilingCapability,\n Tile,\n RenderTileOptions,\n TilingState,\n TilingEvent,\n TilingScope,\n} from './types';\nimport { calculateTilesForPage } from './utils';\n\nexport class TilingPlugin extends BasePlugin<TilingPluginConfig, TilingCapability, TilingState> {\n static readonly id = 'tiling' as const;\n\n private readonly tileRendering$ = createBehaviorEmitter<TilingEvent>();\n\n private config: TilingPluginConfig;\n private renderCapability: RenderCapability;\n private scrollCapability: ScrollCapability;\n private viewportCapability: ViewportCapability;\n\n constructor(id: string, registry: PluginRegistry, config: TilingPluginConfig) {\n super(id, registry);\n\n this.config = config;\n\n this.renderCapability = this.registry.getPlugin<RenderPlugin>('render')!.provides();\n this.scrollCapability = this.registry.getPlugin<ScrollPlugin>('scroll')!.provides();\n this.viewportCapability = this.registry.getPlugin<ViewportPlugin>('viewport')!.provides();\n\n this.scrollCapability.onScroll(\n (event: ScrollEvent) => this.calculateVisibleTiles(event.documentId, event.metrics),\n {\n mode: 'throttle',\n wait: 50,\n throttleMode: 'trailing',\n },\n );\n\n this.coreStore.onAction(REFRESH_PAGES, (action) => this.recalculateTiles(action.payload));\n }\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n this.dispatch(initTilingState(documentId, initialTilingDocumentState));\n }\n\n protected override onDocumentClosed(documentId: string): void {\n this.dispatch(cleanupTilingState(documentId));\n }\n\n protected override onScaleChanged(documentId: string): void {\n this.recalculateTilesForDocument(documentId);\n }\n\n protected override onRotationChanged(documentId: string): void {\n this.recalculateTilesForDocument(documentId);\n }\n\n private recalculateTilesForDocument(documentId: string): void {\n const scrollScope = this.scrollCapability.forDocument(documentId);\n const viewportScope = this.viewportCapability.forDocument(documentId);\n const metrics = scrollScope.getMetrics(viewportScope.getMetrics());\n this.calculateVisibleTiles(documentId, metrics);\n }\n\n async recalculateTiles(payload: RefreshPagesAction['payload']): Promise<void> {\n const { documentId, pageIndexes } = payload;\n const coreDoc = this.getCoreDocument(documentId);\n if (!coreDoc || !coreDoc.document) return;\n\n const scrollScope = this.scrollCapability.forDocument(documentId);\n const viewportScope = this.viewportCapability.forDocument(documentId);\n const currentMetrics = scrollScope.getMetrics(viewportScope.getMetrics());\n\n // Recalculate tiles for refreshed pages with a new timestamp\n const refreshedTiles: Record<number, Tile[]> = {};\n const refreshTimestamp = Date.now();\n const scale = coreDoc.scale;\n\n for (const pageIndex of pageIndexes) {\n const metric = currentMetrics.pageVisibilityMetrics.find(\n (m) => m.pageNumber === pageIndex + 1,\n );\n if (!metric) continue;\n\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n\n // Calculate effective rotation for this page (page intrinsic + document rotation)\n const effectiveRotation = ((page.rotation ?? 0) + coreDoc.rotation) % 4;\n\n refreshedTiles[pageIndex] = calculateTilesForPage({\n page,\n metric,\n scale,\n rotation: effectiveRotation,\n tileSize: this.config.tileSize,\n overlapPx: this.config.overlapPx,\n extraRings: this.config.extraRings,\n }).map((tile) => ({\n ...tile,\n id: `${tile.id}-r${refreshTimestamp}`, // Add refresh token to force new render\n }));\n }\n\n if (Object.keys(refreshedTiles).length > 0) {\n this.dispatch(updateVisibleTiles(documentId, refreshedTiles));\n }\n }\n\n async initialize(): Promise<void> {\n // Fetch dependencies from the registry if needed\n }\n\n private calculateVisibleTiles(documentId: string, scrollMetrics: ScrollMetrics): void {\n const coreDoc = this.getCoreDocument(documentId);\n if (!coreDoc || !coreDoc.document) return;\n\n const scale = coreDoc.scale;\n const visibleTiles: { [pageIndex: number]: Tile[] } = {};\n\n for (const scrollMetric of scrollMetrics.pageVisibilityMetrics) {\n const pageIndex = scrollMetric.pageNumber - 1; // Convert to 0-based index\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n\n // Calculate effective rotation for this page (page intrinsic + document rotation)\n const effectiveRotation = ((page.rotation ?? 0) + coreDoc.rotation) % 4;\n\n // Calculate tiles for the page using the utility function\n const tiles = calculateTilesForPage({\n page,\n metric: scrollMetric,\n scale,\n rotation: effectiveRotation,\n tileSize: this.config.tileSize,\n overlapPx: this.config.overlapPx,\n extraRings: this.config.extraRings,\n });\n\n visibleTiles[pageIndex] = tiles;\n }\n\n this.dispatch(updateVisibleTiles(documentId, visibleTiles));\n }\n\n override onStoreUpdated(prevState: TilingState, newState: TilingState): void {\n for (const documentId in newState.documents) {\n const prevDoc = prevState.documents[documentId];\n const newDoc = newState.documents[documentId];\n if (prevDoc !== newDoc) {\n this.tileRendering$.emit({ documentId, tiles: newDoc.visibleTiles });\n }\n }\n }\n\n protected buildCapability(): TilingCapability {\n return {\n renderTile: this.renderTile.bind(this),\n forDocument: this.createTilingScope.bind(this),\n onTileRendering: this.tileRendering$.on,\n };\n }\n\n private createTilingScope(documentId: string): TilingScope {\n return {\n renderTile: (options) => this.renderTile(options, documentId),\n onTileRendering: (listener: Listener<Record<number, Tile[]>>) =>\n this.tileRendering$.on((event) => {\n if (event.documentId === documentId) listener(event.tiles);\n }),\n };\n }\n\n private renderTile(options: RenderTileOptions, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n if (!this.renderCapability) {\n throw new Error('Render capability not available.');\n }\n\n this.dispatch(markTileStatus(id, options.pageIndex, options.tile.id, 'rendering'));\n\n const task = this.renderCapability.forDocument(id).renderPageRect({\n pageIndex: options.pageIndex,\n rect: options.tile.pageRect,\n options: {\n scaleFactor: options.tile.srcScale,\n dpr: options.dpr,\n },\n });\n\n task.wait(() => {\n this.dispatch(markTileStatus(id, options.pageIndex, options.tile.id, 'ready'));\n }, ignore);\n\n return task;\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { TilingAction } from './actions';\nimport { manifest, TILING_PLUGIN_ID } from './manifest';\nimport { initialState, tilingReducer } from './reducer';\nimport { TilingPlugin } from './tiling-plugin';\nimport { TilingPluginConfig, TilingState } from './types';\n\nexport const TilingPluginPackage: PluginPackage<\n TilingPlugin,\n TilingPluginConfig,\n TilingState,\n TilingAction\n> = {\n manifest,\n create: (registry, config) => new TilingPlugin(TILING_PLUGIN_ID, registry, config),\n reducer: (state, action) => tilingReducer(state, action),\n initialState,\n};\n\nexport * from './tiling-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-tiling",
3
- "version": "2.4.1",
3
+ "version": "2.5.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.cjs",
@@ -35,16 +35,16 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@embedpdf/models": "2.4.1"
38
+ "@embedpdf/models": "2.5.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/react": "^18.2.0",
42
42
  "typescript": "^5.0.0",
43
- "@embedpdf/core": "2.4.1",
43
+ "@embedpdf/core": "2.5.0",
44
+ "@embedpdf/plugin-render": "2.5.0",
44
45
  "@embedpdf/build": "1.1.0",
45
- "@embedpdf/plugin-render": "2.4.1",
46
- "@embedpdf/plugin-scroll": "2.4.1",
47
- "@embedpdf/plugin-viewport": "2.4.1"
46
+ "@embedpdf/plugin-viewport": "2.5.0",
47
+ "@embedpdf/plugin-scroll": "2.5.0"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "react": ">=16.8.0",
@@ -52,10 +52,10 @@
52
52
  "preact": "^10.26.4",
53
53
  "vue": ">=3.2.0",
54
54
  "svelte": ">=5 <6",
55
- "@embedpdf/core": "2.4.1",
56
- "@embedpdf/plugin-render": "2.4.1",
57
- "@embedpdf/plugin-viewport": "2.4.1",
58
- "@embedpdf/plugin-scroll": "2.4.1"
55
+ "@embedpdf/core": "2.5.0",
56
+ "@embedpdf/plugin-render": "2.5.0",
57
+ "@embedpdf/plugin-scroll": "2.5.0",
58
+ "@embedpdf/plugin-viewport": "2.5.0"
59
59
  },
60
60
  "files": [
61
61
  "dist",