@embedpdf/plugin-tiling 1.5.0 → 2.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),i=require("@embedpdf/models"),t="tiling",s={id:t,name:"Tiling Plugin",version:"1.0.0",provides:["tiling"],requires:["render","scroll","viewport"],optional:[],defaultConfig:{enabled:!0,tileSize:768,overlapPx:2.5,extraRings:0}},a="UPDATE_VISIBLE_TILES",r="MARK_TILE_STATUS",l=e=>({type:a,payload:e}),o=(e,i,t)=>({type:r,payload:{pageIndex:e,tileId:i,status:t}});function n({tileSize:e=768,overlapPx:t=2.5,extraRings:s=0,scale:a,rotation:r,page:l,metric:o}){const n=l.size.width*a,c=l.size.height*a,d=e-t,h=i.transformSize(l.size,r,a),p={origin:{x:o.scaled.pageX,y:o.scaled.pageY},size:{width:o.scaled.visibleWidth,height:o.scaled.visibleHeight}},g=i.restoreRect(h,p,r,1),u=g.origin.x,b=g.origin.y,f=u+g.size.width,y=b+g.size.height,v=Math.floor((n-1)/d),x=Math.floor((c-1)/d),S=Math.max(0,Math.floor(u/d)-s),m=Math.min(v,Math.floor((f-1)/d)+s),T=Math.max(0,Math.floor(b/d)-s),w=Math.min(x,Math.floor((y-1)/d)+s),M=[];for(let i=S;i<=m;i++){const t=i*d,s=Math.min(e,n-t),r=t/a,o=s/a;for(let n=T;n<=w;n++){const h=n*d,p=Math.min(e,c-h),g=h/a,u=p/a;M.push({id:`p${l.index}-${a}-x${t}-y${h}-w${s}-h${p}`,col:i,row:n,pageRect:{origin:{x:r,y:g},size:{width:o,height:u}},screenRect:{origin:{x:t,y:h},size:{width:s,height:p}},status:"queued",srcScale:a,isFallback:!1})}}return M}const c=class extends e.BasePlugin{constructor(i,t,s){super(i,t),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)),{mode:"throttle",wait:50,throttleMode:"trailing"}),this.coreStore.onAction(e.REFRESH_PAGES,(e=>this.recalculateTiles(e.payload)))}async recalculateTiles(e){var i;const t=this.scrollCapability.getMetrics(this.viewportCapability.getMetrics()),s={},a=Date.now();for(const r of e){const e=t.pageVisibilityMetrics.find((e=>e.pageNumber===r+1));if(!e)continue;const l=null==(i=this.coreState.core.document)?void 0:i.pages[r];l&&(s[r]=n({page:l,metric:e,scale:this.coreState.core.scale,rotation:this.coreState.core.rotation,tileSize:this.config.tileSize,overlapPx:this.config.overlapPx,extraRings:this.config.extraRings}).map((e=>({...e,id:`${e.id}-r${a}`}))))}Object.keys(s).length>0&&this.dispatch(l(s))}async initialize(){}onCoreStoreUpdated(e,i){e.core.scale!==i.core.scale&&this.calculateVisibleTiles(this.scrollCapability.getMetrics(this.viewportCapability.getMetrics()))}calculateVisibleTiles(e){var i;if(!this.config.enabled)return void this.dispatch(l([]));const t=this.coreState.core.scale,s=this.coreState.core.rotation,a={};for(const r of e.pageVisibilityMetrics){const e=r.pageNumber-1,l=null==(i=this.coreState.core.document)?void 0:i.pages[e];if(!l)continue;const o=n({page:l,metric:r,scale:t,rotation:s,tileSize:this.config.tileSize,overlapPx:this.config.overlapPx,extraRings:this.config.extraRings});a[e]=o}this.dispatch(l(a))}onStoreUpdated(e,i){this.tileRendering$.emit(i.visibleTiles)}buildCapability(){return{renderTile:this.renderTile.bind(this),onTileRendering:this.tileRendering$.on}}renderTile(e){if(!this.renderCapability)throw new Error("Render capability not available.");this.dispatch(o(e.pageIndex,e.tile.id,"rendering"));const t=this.renderCapability.renderPageRect({pageIndex:e.pageIndex,rect:e.tile.pageRect,options:{scaleFactor:e.tile.srcScale,dpr:e.dpr}});return t.wait((()=>{this.dispatch(o(e.pageIndex,e.tile.id,"ready"))}),i.ignore),t}};c.id="tiling";let d=c;const h={manifest:s,create:(e,i)=>new d(t,e,i),reducer:(e,i)=>((e,i)=>{var t,s;switch(i.type){case a:{const s=i.payload,a={...e.visibleTiles};for(const e in s){const i=Number(e),r=s[i],l=a[i]??[],o=null==(t=l.find((e=>!e.isFallback)))?void 0:t.srcScale,n=r[0].srcScale;if(void 0!==o&&o!==n){const e=l.filter((e=>!e.isFallback&&"ready"===e.status)).map((e=>({...e,isFallback:!0}))),t=e.length>0?[]:l.filter((e=>e.isFallback));a[i]=[...t,...e,...r]}else{const e=new Set(r.map((e=>e.id))),t=[],s=new Set;for(const i of l)(i.isFallback||e.has(i.id))&&(t.push(i),s.add(i.id));for(const i of r)s.has(i.id)||t.push(i);a[i]=t}}return{...e,visibleTiles:a}}case r:{const{pageIndex:t,tileId:a,status:r}=i.payload,l=(null==(s=e.visibleTiles[t])?void 0:s.map((e=>e.id===a?{...e,status:r}:e)))??[],o=l.filter((e=>!e.isFallback)),n=o.every((e=>"ready"===e.status))?o:l;return{...e,visibleTiles:{...e.visibleTiles,[t]:n}}}default:return e}})(e,i),initialState:{visibleTiles:{}}};exports.TILING_PLUGIN_ID=t,exports.TilingPlugin=d,exports.TilingPluginPackage=h,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:{enabled:!0,tileSize:768,overlapPx:2.5,extraRings:0}},n="TILING/INIT_STATE",o="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:n,rotation:o,page:r,metric:a}){const l=r.size.width*n,c=r.size.height*n,d=e-i,u=t.transformSize(r.size,o,n),h={origin:{x:a.scaled.pageX,y:a.scaled.pageY},size:{width:a.scaled.visibleWidth,height:a.scaled.visibleHeight}},g=t.restoreRect(u,h,o,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),o=i/n,a=s/n;for(let l=x;l<=S;l++){const u=l*d,h=Math.min(e,c-u),g=u/n,p=h/n;R.push({id:`p${r.index}-${n}-x${i}-y${u}-w${s}-h${h}`,col:t,row:l,pageRect:{origin:{x:o,y:g},size:{width:a,height:p}},screenRect:{origin:{x:i,y:u},size:{width:s,height:h}},status:"queued",srcScale:n,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:n,payload:{documentId:e,state:t}}))(e,d))}onDocumentClosed(e){this.dispatch((e=>({type:o,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 n=this.scrollCapability.forDocument(t),o=this.viewportCapability.forDocument(t),r=n.getMetrics(o.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){if(!this.config.enabled)return void this.dispatch(l(e,{}));const i=this.getCoreDocument(e);if(!i||!i.document)return;const s=i.scale,n=i.rotation,o={};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:n,tileSize:this.config.tileSize,overlapPx:this.config.overlapPx,extraRings:this.config.extraRings});o[e]=a}this.dispatch(l(e,o))}onStoreUpdated(e,t){for(const i in t.documents){const s=e.documents[i],n=t.documents[i];s!==n&&this.tileRendering$.emit({documentId:i,tiles:n.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 n=this.renderCapability.forDocument(s).renderPageRect({pageIndex:e.pageIndex,rect:e.tile.pageRect,options:{scaleFactor:e.tile.srcScale,dpr:e.dpr}});return n.wait(()=>{this.dispatch(c(s,e.pageIndex,e.tile.id,"ready"))},t.ignore),n}};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 n:{const{documentId:i,state:s}=t.payload;return{...e,documents:{...e.documents,[i]:s}}}case o:{const i=t.payload,{[i]:s,...n}=e.documents;return{...e,documents:n}}case r:{const{documentId:s,tiles:n}=t.payload,o=e.documents[s];if(!o)return e;const r={...o.visibleTiles};for(const e in n){const t=Number(e),s=n[t],o=r[t]??[],a=null==(i=o.find(e=>!e.isFallback))?void 0:i.srcScale,l=s.length>0?s[0].srcScale:a;if(void 0!==a&&a!==l){const e=o.filter(e=>!e.isFallback&&"ready"===e.status).map(e=>({...e,isFallback:!0})),i=e.length>0?[]:o.filter(e=>e.isFallback);r[t]=[...i,...e,...s]}else{const e=new Set(s.map(e=>e.id)),i=[],n=new Set;for(const t of o)(t.isFallback||e.has(t.id))&&(i.push(t),n.add(t.id));for(const t of s)n.has(t.id)||i.push(t);r[t]=i}}return{...e,documents:{...e.documents,[s]:{...o,visibleTiles:r}}}}case a:{const{documentId:i,pageIndex:n,tileId:o,status:r}=t.payload,a=e.documents[i];if(!a)return e;const l=(null==(s=a.visibleTiles[n])?void 0:s.map(e=>e.id===o?{...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,[n]: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/utils.ts","../src/lib/tiling-plugin.ts","../src/lib/index.ts","../src/lib/reducer.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 enabled: true,\n tileSize: 768,\n overlapPx: 2.5,\n extraRings: 0,\n },\n};\n","import { Tile, TileStatus } from './types';\n\nexport const UPDATE_VISIBLE_TILES = 'UPDATE_VISIBLE_TILES';\nexport const MARK_TILE_STATUS = 'MARK_TILE_STATUS';\n\nexport type UpdateVisibleTilesAction = {\n type: typeof UPDATE_VISIBLE_TILES;\n payload: Record<number, Tile[]>;\n};\n\nexport type MarkTileStatusAction = {\n type: typeof MARK_TILE_STATUS;\n payload: { pageIndex: number; tileId: string; status: TileStatus };\n};\n\nexport type TilingAction = UpdateVisibleTilesAction | MarkTileStatusAction;\n\nexport const updateVisibleTiles = (tiles: Record<number, Tile[]>): UpdateVisibleTilesAction => ({\n type: UPDATE_VISIBLE_TILES,\n payload: tiles,\n});\n\nexport const markTileStatus = (\n pageIndex: number,\n tileId: string,\n status: TileStatus,\n): MarkTileStatusAction => ({ type: MARK_TILE_STATUS, payload: { pageIndex, tileId, status } });\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 CoreState,\n createBehaviorEmitter,\n PluginRegistry,\n REFRESH_PAGES,\n StoreState,\n} from '@embedpdf/core';\nimport { ignore } from '@embedpdf/models';\nimport { RenderCapability, RenderPlugin } from '@embedpdf/plugin-render';\nimport { ScrollCapability, ScrollMetrics, ScrollPlugin } from '@embedpdf/plugin-scroll';\nimport { ViewportCapability, ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { markTileStatus, updateVisibleTiles } from './actions';\nimport {\n TilingPluginConfig,\n TilingCapability,\n Tile,\n RenderTileOptions,\n TilingState,\n} from './types';\nimport { calculateTilesForPage } from './utils';\n\nexport class TilingPlugin extends BasePlugin<TilingPluginConfig, TilingCapability> {\n static readonly id = 'tiling' as const;\n\n private readonly tileRendering$ = createBehaviorEmitter<Record<number, Tile[]>>();\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((scrollMetrics) => this.calculateVisibleTiles(scrollMetrics), {\n mode: 'throttle',\n wait: 50,\n throttleMode: 'trailing',\n });\n\n this.coreStore.onAction(REFRESH_PAGES, (action) => this.recalculateTiles(action.payload));\n }\n\n async recalculateTiles(pagesToRefresh: number[]): Promise<void> {\n const currentMetrics = this.scrollCapability.getMetrics(this.viewportCapability.getMetrics());\n\n // Recalculate tiles for refreshed pages with a new timestamp\n const refreshedTiles: Record<number, Tile[]> = {};\n const refreshTimestamp = Date.now();\n\n for (const pageIndex of pagesToRefresh) {\n const metric = currentMetrics.pageVisibilityMetrics.find(\n (m) => m.pageNumber === pageIndex + 1,\n );\n if (!metric) continue;\n\n const page = this.coreState.core.document?.pages[pageIndex];\n if (!page) continue;\n\n refreshedTiles[pageIndex] = calculateTilesForPage({\n page,\n metric,\n scale: this.coreState.core.scale,\n rotation: this.coreState.core.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(refreshedTiles));\n }\n }\n\n async initialize(): Promise<void> {\n // Fetch dependencies from the registry if needed\n }\n\n protected onCoreStoreUpdated(\n oldState: StoreState<CoreState>,\n newState: StoreState<CoreState>,\n ): void {\n if (oldState.core.scale !== newState.core.scale) {\n this.calculateVisibleTiles(\n this.scrollCapability.getMetrics(this.viewportCapability.getMetrics()),\n );\n }\n }\n\n private calculateVisibleTiles(scrollMetrics: ScrollMetrics): void {\n if (!this.config.enabled) {\n this.dispatch(updateVisibleTiles([]));\n return;\n }\n\n const scale = this.coreState.core.scale;\n const rotation = this.coreState.core.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 = this.coreState.core.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(visibleTiles));\n }\n\n override onStoreUpdated(_prevState: TilingState, newState: TilingState): void {\n this.tileRendering$.emit(newState.visibleTiles);\n }\n\n protected buildCapability(): TilingCapability {\n return {\n renderTile: this.renderTile.bind(this),\n onTileRendering: this.tileRendering$.on,\n };\n }\n\n private renderTile(options: RenderTileOptions) {\n if (!this.renderCapability) {\n throw new Error('Render capability not available.');\n }\n\n this.dispatch(markTileStatus(options.pageIndex, options.tile.id, 'rendering'));\n\n const task = this.renderCapability.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(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","import { Reducer } from '@embedpdf/core';\n\nimport { UPDATE_VISIBLE_TILES, MARK_TILE_STATUS, TilingAction } from './actions';\nimport { Tile, TilingState } from './types';\n\nexport const initialState: TilingState = {\n visibleTiles: {},\n};\n\nexport const tilingReducer: Reducer<TilingState, TilingAction> = (state, action) => {\n switch (action.type) {\n case UPDATE_VISIBLE_TILES: {\n const incoming = action.payload; // Record<number, Tile[]>\n const nextPages = { ...state.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[0].srcScale;\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 { ...state, visibleTiles: nextPages };\n }\n\n case MARK_TILE_STATUS: {\n const { pageIndex, tileId, status } = action.payload;\n const tiles =\n state.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.every((t) => t.status === 'ready');\n const finalTiles = allReady ? newTiles : tiles;\n\n return {\n ...state,\n visibleTiles: { ...state.visibleTiles, [pageIndex]: finalTiles },\n };\n }\n\n default:\n return state;\n }\n};\n"],"names":["TILING_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","enabled","tileSize","overlapPx","extraRings","UPDATE_VISIBLE_TILES","MARK_TILE_STATUS","updateVisibleTiles","tiles","type","payload","markTileStatus","pageIndex","tileId","status","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","scrollMetrics","calculateVisibleTiles","mode","wait","throttleMode","coreStore","onAction","REFRESH_PAGES","action","recalculateTiles","pagesToRefresh","currentMetrics","getMetrics","refreshedTiles","refreshTimestamp","Date","now","pageVisibilityMetrics","find","m","pageNumber","_a","coreState","core","document","pages","map","tile","Object","keys","length","dispatch","initialize","onCoreStoreUpdated","oldState","newState","visibleTiles","scrollMetric","onStoreUpdated","_prevState","emit","buildCapability","renderTile","bind","onTileRendering","on","options","Error","task","renderPageRect","rect","scaleFactor","dpr","ignore","TilingPlugin","TilingPluginPackage","create","reducer","state","incoming","nextPages","key","Number","newTiles","prevTiles","prevScale","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 enabled: true,\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 if (!this.config.enabled) {\n this.dispatch(updateVisibleTiles(documentId, {}));\n return;\n }\n\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","enabled","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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"}
package/dist/index.js CHANGED
@@ -15,28 +15,64 @@ const manifest = {
15
15
  extraRings: 0
16
16
  }
17
17
  };
18
- const UPDATE_VISIBLE_TILES = "UPDATE_VISIBLE_TILES";
19
- const MARK_TILE_STATUS = "MARK_TILE_STATUS";
20
- const updateVisibleTiles = (tiles) => ({
18
+ const INIT_TILING_STATE = "TILING/INIT_STATE";
19
+ const CLEANUP_TILING_STATE = "TILING/CLEANUP_STATE";
20
+ const UPDATE_VISIBLE_TILES = "TILING/UPDATE_VISIBLE_TILES";
21
+ const MARK_TILE_STATUS = "TILING/MARK_TILE_STATUS";
22
+ const initTilingState = (documentId, state) => ({
23
+ type: INIT_TILING_STATE,
24
+ payload: { documentId, state }
25
+ });
26
+ const cleanupTilingState = (documentId) => ({
27
+ type: CLEANUP_TILING_STATE,
28
+ payload: documentId
29
+ });
30
+ const updateVisibleTiles = (documentId, tiles) => ({
21
31
  type: UPDATE_VISIBLE_TILES,
22
- payload: tiles
32
+ payload: { documentId, tiles }
23
33
  });
24
- const markTileStatus = (pageIndex, tileId, status) => ({ type: MARK_TILE_STATUS, payload: { pageIndex, tileId, status } });
25
- const initialState = {
34
+ const markTileStatus = (documentId, pageIndex, tileId, status) => ({
35
+ type: MARK_TILE_STATUS,
36
+ payload: { documentId, pageIndex, tileId, status }
37
+ });
38
+ const initialTilingDocumentState = {
26
39
  visibleTiles: {}
27
40
  };
41
+ const initialState = {
42
+ documents: {}
43
+ };
28
44
  const tilingReducer = (state, action) => {
29
45
  var _a, _b;
30
46
  switch (action.type) {
47
+ case INIT_TILING_STATE: {
48
+ const { documentId, state: docState } = action.payload;
49
+ return {
50
+ ...state,
51
+ documents: {
52
+ ...state.documents,
53
+ [documentId]: docState
54
+ }
55
+ };
56
+ }
57
+ case CLEANUP_TILING_STATE: {
58
+ const documentId = action.payload;
59
+ const { [documentId]: removed, ...remaining } = state.documents;
60
+ return {
61
+ ...state,
62
+ documents: remaining
63
+ };
64
+ }
31
65
  case UPDATE_VISIBLE_TILES: {
32
- const incoming = action.payload;
33
- const nextPages = { ...state.visibleTiles };
66
+ const { documentId, tiles: incoming } = action.payload;
67
+ const docState = state.documents[documentId];
68
+ if (!docState) return state;
69
+ const nextPages = { ...docState.visibleTiles };
34
70
  for (const key in incoming) {
35
71
  const pageIndex = Number(key);
36
72
  const newTiles = incoming[pageIndex];
37
73
  const prevTiles = nextPages[pageIndex] ?? [];
38
74
  const prevScale = (_a = prevTiles.find((t) => !t.isFallback)) == null ? void 0 : _a.srcScale;
39
- const newScale = newTiles[0].srcScale;
75
+ const newScale = newTiles.length > 0 ? newTiles[0].srcScale : prevScale;
40
76
  const zoomChanged = prevScale !== void 0 && prevScale !== newScale;
41
77
  if (zoomChanged) {
42
78
  const promoted = prevTiles.filter((t) => !t.isFallback && t.status === "ready").map((t) => ({ ...t, isFallback: true }));
@@ -61,19 +97,36 @@ const tilingReducer = (state, action) => {
61
97
  nextPages[pageIndex] = keepers;
62
98
  }
63
99
  }
64
- return { ...state, visibleTiles: nextPages };
100
+ return {
101
+ ...state,
102
+ documents: {
103
+ ...state.documents,
104
+ [documentId]: {
105
+ ...docState,
106
+ visibleTiles: nextPages
107
+ }
108
+ }
109
+ };
65
110
  }
66
111
  case MARK_TILE_STATUS: {
67
- const { pageIndex, tileId, status } = action.payload;
68
- const tiles = ((_b = state.visibleTiles[pageIndex]) == null ? void 0 : _b.map(
112
+ const { documentId, pageIndex, tileId, status } = action.payload;
113
+ const docState = state.documents[documentId];
114
+ if (!docState) return state;
115
+ const tiles = ((_b = docState.visibleTiles[pageIndex]) == null ? void 0 : _b.map(
69
116
  (t) => t.id === tileId ? { ...t, status } : t
70
117
  )) ?? [];
71
118
  const newTiles = tiles.filter((t) => !t.isFallback);
72
- const allReady = newTiles.every((t) => t.status === "ready");
119
+ const allReady = newTiles.length > 0 && newTiles.every((t) => t.status === "ready");
73
120
  const finalTiles = allReady ? newTiles : tiles;
74
121
  return {
75
122
  ...state,
76
- visibleTiles: { ...state.visibleTiles, [pageIndex]: finalTiles }
123
+ documents: {
124
+ ...state.documents,
125
+ [documentId]: {
126
+ ...docState,
127
+ visibleTiles: { ...docState.visibleTiles, [pageIndex]: finalTiles }
128
+ }
129
+ }
77
130
  };
78
131
  }
79
132
  default:
@@ -144,30 +197,57 @@ const _TilingPlugin = class _TilingPlugin extends BasePlugin {
144
197
  this.renderCapability = this.registry.getPlugin("render").provides();
145
198
  this.scrollCapability = this.registry.getPlugin("scroll").provides();
146
199
  this.viewportCapability = this.registry.getPlugin("viewport").provides();
147
- this.scrollCapability.onScroll((scrollMetrics) => this.calculateVisibleTiles(scrollMetrics), {
148
- mode: "throttle",
149
- wait: 50,
150
- throttleMode: "trailing"
151
- });
200
+ this.scrollCapability.onScroll(
201
+ (event) => this.calculateVisibleTiles(event.documentId, event.metrics),
202
+ {
203
+ mode: "throttle",
204
+ wait: 50,
205
+ throttleMode: "trailing"
206
+ }
207
+ );
152
208
  this.coreStore.onAction(REFRESH_PAGES, (action) => this.recalculateTiles(action.payload));
153
209
  }
154
- async recalculateTiles(pagesToRefresh) {
155
- var _a;
156
- const currentMetrics = this.scrollCapability.getMetrics(this.viewportCapability.getMetrics());
210
+ onDocumentLoadingStarted(documentId) {
211
+ this.dispatch(initTilingState(documentId, initialTilingDocumentState));
212
+ }
213
+ onDocumentClosed(documentId) {
214
+ this.dispatch(cleanupTilingState(documentId));
215
+ }
216
+ onScaleChanged(documentId) {
217
+ this.recalculateTilesForDocument(documentId);
218
+ }
219
+ onRotationChanged(documentId) {
220
+ this.recalculateTilesForDocument(documentId);
221
+ }
222
+ recalculateTilesForDocument(documentId) {
223
+ const scrollScope = this.scrollCapability.forDocument(documentId);
224
+ const viewportScope = this.viewportCapability.forDocument(documentId);
225
+ const metrics = scrollScope.getMetrics(viewportScope.getMetrics());
226
+ this.calculateVisibleTiles(documentId, metrics);
227
+ }
228
+ async recalculateTiles(payload) {
229
+ const { documentId, pageIndexes } = payload;
230
+ const coreDoc = this.getCoreDocument(documentId);
231
+ if (!coreDoc || !coreDoc.document) return;
232
+ const scrollScope = this.scrollCapability.forDocument(documentId);
233
+ const viewportScope = this.viewportCapability.forDocument(documentId);
234
+ const currentMetrics = scrollScope.getMetrics(viewportScope.getMetrics());
157
235
  const refreshedTiles = {};
158
236
  const refreshTimestamp = Date.now();
159
- for (const pageIndex of pagesToRefresh) {
237
+ const scale = coreDoc.scale;
238
+ const rotation = coreDoc.rotation;
239
+ for (const pageIndex of pageIndexes) {
160
240
  const metric = currentMetrics.pageVisibilityMetrics.find(
161
241
  (m) => m.pageNumber === pageIndex + 1
162
242
  );
163
243
  if (!metric) continue;
164
- const page = (_a = this.coreState.core.document) == null ? void 0 : _a.pages[pageIndex];
244
+ const page = coreDoc.document.pages[pageIndex];
165
245
  if (!page) continue;
166
246
  refreshedTiles[pageIndex] = calculateTilesForPage({
167
247
  page,
168
248
  metric,
169
- scale: this.coreState.core.scale,
170
- rotation: this.coreState.core.rotation,
249
+ scale,
250
+ rotation,
171
251
  tileSize: this.config.tileSize,
172
252
  overlapPx: this.config.overlapPx,
173
253
  extraRings: this.config.extraRings
@@ -178,30 +258,24 @@ const _TilingPlugin = class _TilingPlugin extends BasePlugin {
178
258
  }));
179
259
  }
180
260
  if (Object.keys(refreshedTiles).length > 0) {
181
- this.dispatch(updateVisibleTiles(refreshedTiles));
261
+ this.dispatch(updateVisibleTiles(documentId, refreshedTiles));
182
262
  }
183
263
  }
184
264
  async initialize() {
185
265
  }
186
- onCoreStoreUpdated(oldState, newState) {
187
- if (oldState.core.scale !== newState.core.scale) {
188
- this.calculateVisibleTiles(
189
- this.scrollCapability.getMetrics(this.viewportCapability.getMetrics())
190
- );
191
- }
192
- }
193
- calculateVisibleTiles(scrollMetrics) {
194
- var _a;
266
+ calculateVisibleTiles(documentId, scrollMetrics) {
195
267
  if (!this.config.enabled) {
196
- this.dispatch(updateVisibleTiles([]));
268
+ this.dispatch(updateVisibleTiles(documentId, {}));
197
269
  return;
198
270
  }
199
- const scale = this.coreState.core.scale;
200
- const rotation = this.coreState.core.rotation;
271
+ const coreDoc = this.getCoreDocument(documentId);
272
+ if (!coreDoc || !coreDoc.document) return;
273
+ const scale = coreDoc.scale;
274
+ const rotation = coreDoc.rotation;
201
275
  const visibleTiles = {};
202
276
  for (const scrollMetric of scrollMetrics.pageVisibilityMetrics) {
203
277
  const pageIndex = scrollMetric.pageNumber - 1;
204
- const page = (_a = this.coreState.core.document) == null ? void 0 : _a.pages[pageIndex];
278
+ const page = coreDoc.document.pages[pageIndex];
205
279
  if (!page) continue;
206
280
  const tiles = calculateTilesForPage({
207
281
  page,
@@ -214,23 +288,39 @@ const _TilingPlugin = class _TilingPlugin extends BasePlugin {
214
288
  });
215
289
  visibleTiles[pageIndex] = tiles;
216
290
  }
217
- this.dispatch(updateVisibleTiles(visibleTiles));
291
+ this.dispatch(updateVisibleTiles(documentId, visibleTiles));
218
292
  }
219
- onStoreUpdated(_prevState, newState) {
220
- this.tileRendering$.emit(newState.visibleTiles);
293
+ onStoreUpdated(prevState, newState) {
294
+ for (const documentId in newState.documents) {
295
+ const prevDoc = prevState.documents[documentId];
296
+ const newDoc = newState.documents[documentId];
297
+ if (prevDoc !== newDoc) {
298
+ this.tileRendering$.emit({ documentId, tiles: newDoc.visibleTiles });
299
+ }
300
+ }
221
301
  }
222
302
  buildCapability() {
223
303
  return {
224
304
  renderTile: this.renderTile.bind(this),
305
+ forDocument: this.createTilingScope.bind(this),
225
306
  onTileRendering: this.tileRendering$.on
226
307
  };
227
308
  }
228
- renderTile(options) {
309
+ createTilingScope(documentId) {
310
+ return {
311
+ renderTile: (options) => this.renderTile(options, documentId),
312
+ onTileRendering: (listener) => this.tileRendering$.on((event) => {
313
+ if (event.documentId === documentId) listener(event.tiles);
314
+ })
315
+ };
316
+ }
317
+ renderTile(options, documentId) {
318
+ const id = documentId ?? this.getActiveDocumentId();
229
319
  if (!this.renderCapability) {
230
320
  throw new Error("Render capability not available.");
231
321
  }
232
- this.dispatch(markTileStatus(options.pageIndex, options.tile.id, "rendering"));
233
- const task = this.renderCapability.renderPageRect({
322
+ this.dispatch(markTileStatus(id, options.pageIndex, options.tile.id, "rendering"));
323
+ const task = this.renderCapability.forDocument(id).renderPageRect({
234
324
  pageIndex: options.pageIndex,
235
325
  rect: options.tile.pageRect,
236
326
  options: {
@@ -239,7 +329,7 @@ const _TilingPlugin = class _TilingPlugin extends BasePlugin {
239
329
  }
240
330
  });
241
331
  task.wait(() => {
242
- this.dispatch(markTileStatus(options.pageIndex, options.tile.id, "ready"));
332
+ this.dispatch(markTileStatus(id, options.pageIndex, options.tile.id, "ready"));
243
333
  }, ignore);
244
334
  return task;
245
335
  }
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 enabled: true,\n tileSize: 768,\n overlapPx: 2.5,\n extraRings: 0,\n },\n};\n","import { Tile, TileStatus } from './types';\n\nexport const UPDATE_VISIBLE_TILES = 'UPDATE_VISIBLE_TILES';\nexport const MARK_TILE_STATUS = 'MARK_TILE_STATUS';\n\nexport type UpdateVisibleTilesAction = {\n type: typeof UPDATE_VISIBLE_TILES;\n payload: Record<number, Tile[]>;\n};\n\nexport type MarkTileStatusAction = {\n type: typeof MARK_TILE_STATUS;\n payload: { pageIndex: number; tileId: string; status: TileStatus };\n};\n\nexport type TilingAction = UpdateVisibleTilesAction | MarkTileStatusAction;\n\nexport const updateVisibleTiles = (tiles: Record<number, Tile[]>): UpdateVisibleTilesAction => ({\n type: UPDATE_VISIBLE_TILES,\n payload: tiles,\n});\n\nexport const markTileStatus = (\n pageIndex: number,\n tileId: string,\n status: TileStatus,\n): MarkTileStatusAction => ({ type: MARK_TILE_STATUS, payload: { pageIndex, tileId, status } });\n","import { Reducer } from '@embedpdf/core';\n\nimport { UPDATE_VISIBLE_TILES, MARK_TILE_STATUS, TilingAction } from './actions';\nimport { Tile, TilingState } from './types';\n\nexport const initialState: TilingState = {\n visibleTiles: {},\n};\n\nexport const tilingReducer: Reducer<TilingState, TilingAction> = (state, action) => {\n switch (action.type) {\n case UPDATE_VISIBLE_TILES: {\n const incoming = action.payload; // Record<number, Tile[]>\n const nextPages = { ...state.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[0].srcScale;\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 { ...state, visibleTiles: nextPages };\n }\n\n case MARK_TILE_STATUS: {\n const { pageIndex, tileId, status } = action.payload;\n const tiles =\n state.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.every((t) => t.status === 'ready');\n const finalTiles = allReady ? newTiles : tiles;\n\n return {\n ...state,\n visibleTiles: { ...state.visibleTiles, [pageIndex]: finalTiles },\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 CoreState,\n createBehaviorEmitter,\n PluginRegistry,\n REFRESH_PAGES,\n StoreState,\n} from '@embedpdf/core';\nimport { ignore } from '@embedpdf/models';\nimport { RenderCapability, RenderPlugin } from '@embedpdf/plugin-render';\nimport { ScrollCapability, ScrollMetrics, ScrollPlugin } from '@embedpdf/plugin-scroll';\nimport { ViewportCapability, ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport { markTileStatus, updateVisibleTiles } from './actions';\nimport {\n TilingPluginConfig,\n TilingCapability,\n Tile,\n RenderTileOptions,\n TilingState,\n} from './types';\nimport { calculateTilesForPage } from './utils';\n\nexport class TilingPlugin extends BasePlugin<TilingPluginConfig, TilingCapability> {\n static readonly id = 'tiling' as const;\n\n private readonly tileRendering$ = createBehaviorEmitter<Record<number, Tile[]>>();\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((scrollMetrics) => this.calculateVisibleTiles(scrollMetrics), {\n mode: 'throttle',\n wait: 50,\n throttleMode: 'trailing',\n });\n\n this.coreStore.onAction(REFRESH_PAGES, (action) => this.recalculateTiles(action.payload));\n }\n\n async recalculateTiles(pagesToRefresh: number[]): Promise<void> {\n const currentMetrics = this.scrollCapability.getMetrics(this.viewportCapability.getMetrics());\n\n // Recalculate tiles for refreshed pages with a new timestamp\n const refreshedTiles: Record<number, Tile[]> = {};\n const refreshTimestamp = Date.now();\n\n for (const pageIndex of pagesToRefresh) {\n const metric = currentMetrics.pageVisibilityMetrics.find(\n (m) => m.pageNumber === pageIndex + 1,\n );\n if (!metric) continue;\n\n const page = this.coreState.core.document?.pages[pageIndex];\n if (!page) continue;\n\n refreshedTiles[pageIndex] = calculateTilesForPage({\n page,\n metric,\n scale: this.coreState.core.scale,\n rotation: this.coreState.core.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(refreshedTiles));\n }\n }\n\n async initialize(): Promise<void> {\n // Fetch dependencies from the registry if needed\n }\n\n protected onCoreStoreUpdated(\n oldState: StoreState<CoreState>,\n newState: StoreState<CoreState>,\n ): void {\n if (oldState.core.scale !== newState.core.scale) {\n this.calculateVisibleTiles(\n this.scrollCapability.getMetrics(this.viewportCapability.getMetrics()),\n );\n }\n }\n\n private calculateVisibleTiles(scrollMetrics: ScrollMetrics): void {\n if (!this.config.enabled) {\n this.dispatch(updateVisibleTiles([]));\n return;\n }\n\n const scale = this.coreState.core.scale;\n const rotation = this.coreState.core.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 = this.coreState.core.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(visibleTiles));\n }\n\n override onStoreUpdated(_prevState: TilingState, newState: TilingState): void {\n this.tileRendering$.emit(newState.visibleTiles);\n }\n\n protected buildCapability(): TilingCapability {\n return {\n renderTile: this.renderTile.bind(this),\n onTileRendering: this.tileRendering$.on,\n };\n }\n\n private renderTile(options: RenderTileOptions) {\n if (!this.renderCapability) {\n throw new Error('Render capability not available.');\n }\n\n this.dispatch(markTileStatus(options.pageIndex, options.tile.id, 'rendering'));\n\n const task = this.renderCapability.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(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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"}
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 enabled: true,\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 if (!this.config.enabled) {\n this.dispatch(updateVisibleTiles(documentId, {}));\n return;\n }\n\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":"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"}
@@ -1,18 +1,38 @@
1
- import { Tile, TileStatus } from './types';
2
- export declare const UPDATE_VISIBLE_TILES = "UPDATE_VISIBLE_TILES";
3
- export declare const MARK_TILE_STATUS = "MARK_TILE_STATUS";
1
+ import { Action } from '@embedpdf/core';
2
+ import { Tile, TileStatus, TilingDocumentState } from './types';
3
+ export declare const INIT_TILING_STATE = "TILING/INIT_STATE";
4
+ export declare const CLEANUP_TILING_STATE = "TILING/CLEANUP_STATE";
5
+ export declare const UPDATE_VISIBLE_TILES = "TILING/UPDATE_VISIBLE_TILES";
6
+ export declare const MARK_TILE_STATUS = "TILING/MARK_TILE_STATUS";
7
+ export interface InitTilingStateAction extends Action {
8
+ type: typeof INIT_TILING_STATE;
9
+ payload: {
10
+ documentId: string;
11
+ state: TilingDocumentState;
12
+ };
13
+ }
14
+ export interface CleanupTilingStateAction extends Action {
15
+ type: typeof CLEANUP_TILING_STATE;
16
+ payload: string;
17
+ }
4
18
  export type UpdateVisibleTilesAction = {
5
19
  type: typeof UPDATE_VISIBLE_TILES;
6
- payload: Record<number, Tile[]>;
20
+ payload: {
21
+ documentId: string;
22
+ tiles: Record<number, Tile[]>;
23
+ };
7
24
  };
8
25
  export type MarkTileStatusAction = {
9
26
  type: typeof MARK_TILE_STATUS;
10
27
  payload: {
28
+ documentId: string;
11
29
  pageIndex: number;
12
30
  tileId: string;
13
31
  status: TileStatus;
14
32
  };
15
33
  };
16
- export type TilingAction = UpdateVisibleTilesAction | MarkTileStatusAction;
17
- export declare const updateVisibleTiles: (tiles: Record<number, Tile[]>) => UpdateVisibleTilesAction;
18
- export declare const markTileStatus: (pageIndex: number, tileId: string, status: TileStatus) => MarkTileStatusAction;
34
+ export type TilingAction = InitTilingStateAction | CleanupTilingStateAction | UpdateVisibleTilesAction | MarkTileStatusAction;
35
+ export declare const initTilingState: (documentId: string, state: TilingDocumentState) => InitTilingStateAction;
36
+ export declare const cleanupTilingState: (documentId: string) => CleanupTilingStateAction;
37
+ export declare const updateVisibleTiles: (documentId: string, tiles: Record<number, Tile[]>) => UpdateVisibleTilesAction;
38
+ export declare const markTileStatus: (documentId: string, pageIndex: number, tileId: string, status: TileStatus) => MarkTileStatusAction;
@@ -1,5 +1,6 @@
1
1
  import { Reducer } from '@embedpdf/core';
2
2
  import { TilingAction } from './actions';
3
- import { TilingState } from './types';
3
+ import { TilingDocumentState, TilingState } from './types';
4
+ export declare const initialTilingDocumentState: TilingDocumentState;
4
5
  export declare const initialState: TilingState;
5
6
  export declare const tilingReducer: Reducer<TilingState, TilingAction>;