@embedpdf/plugin-pan 1.5.0 → 2.0.0-next.1

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/plugin-interaction-manager"),a=require("@embedpdf/plugin-viewport"),n=class extends e.BasePlugin{constructor(n,i,r){var o,s;super(n,i),this.panMode$=e.createBehaviorEmitter(),this.config=r,this.interactionManager=null==(o=i.getPlugin(t.InteractionManagerPlugin.id))?void 0:o.provides(),this.viewport=null==(s=i.getPlugin(a.ViewportPlugin.id))?void 0:s.provides(),this.interactionManager&&(this.interactionManager.registerMode({id:"panMode",scope:"global",exclusive:!1,cursor:"grab",wantsRawTouch:!1}),this.unsubscribePanModeChange=this.interactionManager.onStateChange((e=>{"panMode"===e.activeMode?this.panMode$.emit(!0):this.panMode$.emit(!1)})),this.registerPanHandlers()),"always"===r.defaultMode&&this.makePanDefault(!0)}async initialize(e){}async destroy(){var e,t;null==(e=this.unregisterHandlers)||e.call(this),null==(t=this.unsubscribePanModeChange)||t.call(this),await super.destroy()}registerPanHandlers(){let e=null;const t={onMouseDown:(t,a)=>{const n=this.viewport.getMetrics();e={startX:a.clientX,startY:a.clientY,startLeft:n.scrollLeft,startTop:n.scrollTop},this.interactionManager.setCursor("panMode","grabbing",10)},onMouseMove:(t,a)=>{if(!e)return;const n=a.clientX-e.startX,i=a.clientY-e.startY;this.viewport.scrollTo({x:e.startLeft-n,y:e.startTop-i})},onMouseUp:()=>{e&&(e=null,this.interactionManager.removeCursor("panMode"))},onMouseLeave:()=>{e&&(e=null,this.interactionManager.removeCursor("panMode"))},onMouseCancel:()=>{e&&(e=null,this.interactionManager.removeCursor("panMode"))}};this.unregisterHandlers=this.interactionManager.registerHandlers({modeId:"panMode",handlers:t})}makePanDefault(e=!0){this.interactionManager&&(this.interactionManager.setDefaultMode("panMode"),e&&this.interactionManager.activateDefaultMode())}buildCapability(){return{onPanModeChange:this.panMode$.on,makePanDefault:(e=!0)=>this.makePanDefault(e),enablePan:()=>{var e;return null==(e=this.interactionManager)?void 0:e.activate("panMode")},disablePan:()=>{var e;return null==(e=this.interactionManager)?void 0:e.activateDefaultMode()},togglePan:()=>{var e,t,a;"panMode"===(null==(e=this.interactionManager)?void 0:e.getActiveMode())?null==(t=this.interactionManager)||t.activateDefaultMode():null==(a=this.interactionManager)||a.activate("panMode")}}}};n.id="pan";let i=n;const r="pan",o={id:r,name:"Pan Plugin",version:"1.0.0",provides:["pan"],requires:["interaction-manager","viewport"],optional:[],defaultConfig:{enabled:!0,defaultMode:"mobile"}},s={manifest:o,create:(e,t)=>new i(r,e,t),reducer:()=>{},initialState:{}};exports.PAN_PLUGIN_ID=r,exports.PanPlugin=i,exports.PanPluginPackage=s,exports.manifest=o;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/plugin-interaction-manager"),n=require("@embedpdf/plugin-viewport"),a="PAN/INIT_STATE",o="PAN/CLEANUP_STATE",i="PAN/SET_ACTIVE_DOCUMENT",s="PAN/SET_PAN_MODE";function r(e,t){return{type:a,payload:{documentId:e,state:t}}}function d(e){return{type:o,payload:e}}function c(e,t){return{type:s,payload:{documentId:e,isPanMode:t}}}const u=class extends e.BasePlugin{constructor(a,o,i){var s,r,d;super(a,o),this.panMode$=e.createBehaviorEmitter(),this.documentHandlers=new Map,this.config=i,this.interactionManager=null==(s=o.getPlugin(t.InteractionManagerPlugin.id))?void 0:s.provides(),this.viewport=null==(r=o.getPlugin(n.ViewportPlugin.id))?void 0:r.provides(),this.interactionManager&&(this.interactionManager.registerMode({id:"panMode",scope:"global",exclusive:!1,cursor:"grab",wantsRawTouch:!1}),null==(d=this.interactionManager)||d.onModeChange(e=>{const t="panMode"===e.activeMode,n=this.getDocumentState(e.documentId);n&&n.isPanMode!==t&&this.dispatch(c(e.documentId,t))}))}onDocumentLoadingStarted(e){this.dispatch(r(e,{isPanMode:!1})),this.registerPanHandlersForDocument(e),"always"===this.config.defaultMode&&this.makePanDefault(!0),this.logger.debug("PanPlugin","DocumentOpened",`Initialized pan state for document: ${e}`)}onDocumentClosed(e){const t=this.documentHandlers.get(e);t&&(t(),this.documentHandlers.delete(e)),this.dispatch(d(e)),this.logger.debug("PanPlugin","DocumentClosed",`Cleaned up pan state for document: ${e}`)}buildCapability(){return{enablePan:()=>this.enablePan(),disablePan:()=>this.disablePan(),togglePan:()=>this.togglePan(),makePanDefault:e=>this.makePanDefault(e),isPanMode:()=>this.isPanMode(),forDocument:e=>this.createPanScope(e),onPanModeChange:this.panMode$.on}}createPanScope(e){return{enablePan:()=>this.enablePan(e),disablePan:()=>this.disablePan(e),togglePan:()=>this.togglePan(e),isPanMode:()=>this.isPanMode(e),onPanModeChange:t=>this.panMode$.on(n=>{n.documentId===e&&t(n.isPanMode)})}}getDocumentState(e){const t=e??this.getActiveDocumentId();return this.state.documents[t]??null}getDocumentStateOrThrow(e){const t=this.getDocumentState(e);if(!t)throw new Error(`Pan state not found for document: ${e??"active"}`);return t}enablePan(e){const t=e??this.getActiveDocumentId();this.interactionManager.forDocument(t).activate("panMode")}disablePan(e){const t=e??this.getActiveDocumentId();this.interactionManager.forDocument(t).activateDefaultMode()}togglePan(e){const t=e??this.getActiveDocumentId(),n=this.interactionManager.forDocument(t);"panMode"===n.getActiveMode()?n.activateDefaultMode():n.activate("panMode")}makePanDefault(e=!0){this.interactionManager&&(this.interactionManager.setDefaultMode("panMode"),e&&this.interactionManager.activateDefaultMode())}isPanMode(e){return this.getDocumentStateOrThrow(e).isPanMode}registerPanHandlersForDocument(e){if(!this.interactionManager||!this.viewport)return;let t=null;const n=this.interactionManager.forDocument(e),a=this.viewport.forDocument(e),o={onMouseDown:(e,o)=>{const i=a.getMetrics();t={startX:o.clientX,startY:o.clientY,startLeft:i.scrollLeft,startTop:i.scrollTop},n.setCursor("panMode","grabbing",10)},onMouseMove:(e,n)=>{if(!t)return;const o=n.clientX-t.startX,i=n.clientY-t.startY;a.scrollTo({x:t.startLeft-o,y:t.startTop-i})},onMouseUp:()=>{t&&(t=null,n.removeCursor("panMode"))},onMouseLeave:()=>{t&&(t=null,n.removeCursor("panMode"))},onMouseCancel:()=>{t&&(t=null,n.removeCursor("panMode"))}},i=this.interactionManager.registerHandlers({documentId:e,modeId:"panMode",handlers:o});this.documentHandlers.set(e,i)}onStoreUpdated(e,t){for(const n in t.documents){const a=e.documents[n],o=t.documents[n];(null==a?void 0:a.isPanMode)!==o.isPanMode&&(this.panMode$.emit({documentId:n,isPanMode:o.isPanMode}),this.logger.debug("PanPlugin","PanModeChanged",`Pan mode changed for document ${n}: ${(null==a?void 0:a.isPanMode)??!1} -> ${o.isPanMode}`))}}async initialize(e){this.logger.info("PanPlugin","Initialize","Pan plugin initialized")}async destroy(){this.documentHandlers.forEach(e=>e()),this.documentHandlers.clear(),this.panMode$.clear(),await super.destroy()}};u.id="pan";let l=u;const g="pan",p={id:g,name:"Pan Plugin",version:"1.0.0",provides:["pan"],requires:["interaction-manager","viewport"],optional:[],defaultConfig:{enabled:!0,defaultMode:"mobile"}},P={documents:{},activeDocumentId:null},m=(e=P,t)=>{switch(t.type){case a:{const{documentId:n,state:a}=t.payload;return{...e,documents:{...e.documents,[n]:a},activeDocumentId:e.activeDocumentId??n}}case o:{const n=t.payload,{[n]:a,...o}=e.documents;return{...e,documents:o,activeDocumentId:e.activeDocumentId===n?null:e.activeDocumentId}}case i:return{...e,activeDocumentId:t.payload};case s:{const{documentId:n,isPanMode:a}=t.payload,o=e.documents[n];return o?{...e,documents:{...e.documents,[n]:{...o,isPanMode:a}}}:e}default:return e}},M={manifest:p,create:(e,t)=>new l(g,e,t),reducer:m,initialState:P};exports.CLEANUP_PAN_STATE=o,exports.INIT_PAN_STATE=a,exports.PAN_PLUGIN_ID=g,exports.PanPlugin=l,exports.PanPluginPackage=M,exports.SET_ACTIVE_PAN_DOCUMENT=i,exports.SET_PAN_MODE=s,exports.cleanupPanState=d,exports.initPanState=r,exports.initialDocumentState={isPanMode:!1},exports.initialState=P,exports.manifest=p,exports.panReducer=m,exports.setActivePanDocument=function(e){return{type:i,payload:e}},exports.setPanMode=c;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/lib/pan-plugin.ts","../src/lib/manifest.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePlugin, createBehaviorEmitter, PluginRegistry, Unsubscribe } from '@embedpdf/core';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\n\nimport { PanCapability, PanPluginConfig } from './types';\nimport { ViewportCapability, ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nexport class PanPlugin extends BasePlugin<PanPluginConfig, PanCapability> {\n static readonly id = 'pan' as const;\n\n private readonly panMode$ = createBehaviorEmitter<boolean>();\n\n private interactionManager: InteractionManagerCapability;\n private viewport: ViewportCapability;\n public config: PanPluginConfig;\n\n private unregisterHandlers?: () => void;\n private unsubscribePanModeChange?: Unsubscribe;\n\n constructor(id: string, registry: PluginRegistry, config: PanPluginConfig) {\n super(id, registry);\n\n this.config = config;\n\n this.interactionManager = registry\n .getPlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id)\n ?.provides()!;\n this.viewport = registry.getPlugin<ViewportPlugin>(ViewportPlugin.id)?.provides()!;\n\n if (this.interactionManager) {\n this.interactionManager.registerMode({\n id: 'panMode',\n scope: 'global',\n exclusive: false,\n cursor: 'grab',\n wantsRawTouch: false,\n });\n\n this.unsubscribePanModeChange = this.interactionManager.onStateChange((state) => {\n if (state.activeMode === 'panMode') {\n this.panMode$.emit(true);\n } else {\n this.panMode$.emit(false);\n }\n });\n\n // Register pan handlers immediately\n this.registerPanHandlers();\n }\n\n // Handle 'always' mode - this is safe on server side\n if (config.defaultMode === 'always') {\n this.makePanDefault(true);\n }\n }\n\n async initialize(_: PanPluginConfig): Promise<void> {}\n\n async destroy(): Promise<void> {\n this.unregisterHandlers?.();\n this.unsubscribePanModeChange?.();\n await super.destroy();\n }\n\n private registerPanHandlers() {\n let dragState: {\n startX: number;\n startY: number;\n startLeft: number;\n startTop: number;\n } | null = null;\n\n const handlers = {\n onMouseDown: (_: any, pe: MouseEvent) => {\n const metrics = this.viewport.getMetrics();\n\n dragState = {\n startX: pe.clientX,\n startY: pe.clientY,\n startLeft: metrics.scrollLeft,\n startTop: metrics.scrollTop,\n };\n\n this.interactionManager.setCursor('panMode', 'grabbing', 10);\n },\n onMouseMove: (_: any, pe: MouseEvent) => {\n if (!dragState) return;\n\n /* delta between current pointer position and where the drag started */\n const dx = pe.clientX - dragState.startX;\n const dy = pe.clientY - dragState.startY;\n\n this.viewport.scrollTo({\n x: dragState.startLeft - dx,\n y: dragState.startTop - dy,\n });\n },\n onMouseUp: () => {\n if (!dragState) return;\n\n dragState = null;\n this.interactionManager.removeCursor('panMode');\n },\n onMouseLeave: () => {\n if (!dragState) return;\n\n dragState = null;\n this.interactionManager.removeCursor('panMode');\n },\n onMouseCancel: () => {\n if (!dragState) return;\n\n dragState = null;\n this.interactionManager.removeCursor('panMode');\n },\n };\n\n this.unregisterHandlers = this.interactionManager.registerHandlers({\n modeId: 'panMode',\n handlers,\n });\n }\n\n private makePanDefault(autoActivate: boolean = true) {\n if (!this.interactionManager) return;\n\n this.interactionManager.setDefaultMode('panMode');\n if (autoActivate) {\n this.interactionManager.activateDefaultMode();\n }\n }\n\n protected buildCapability(): PanCapability {\n return {\n onPanModeChange: this.panMode$.on,\n makePanDefault: (autoActivate: boolean = true) => this.makePanDefault(autoActivate),\n enablePan: () => this.interactionManager?.activate('panMode'),\n disablePan: () => this.interactionManager?.activateDefaultMode(),\n togglePan: () => {\n if (this.interactionManager?.getActiveMode() === 'panMode') {\n this.interactionManager?.activateDefaultMode();\n } else {\n this.interactionManager?.activate('panMode');\n }\n },\n };\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { PanPluginConfig } from './types';\n\nexport const PAN_PLUGIN_ID = 'pan';\n\nexport const manifest: PluginManifest<PanPluginConfig> = {\n id: PAN_PLUGIN_ID,\n name: 'Pan Plugin',\n version: '1.0.0',\n provides: ['pan'],\n requires: ['interaction-manager', 'viewport'],\n optional: [],\n defaultConfig: {\n enabled: true,\n defaultMode: 'mobile',\n },\n};\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { PanPlugin } from './pan-plugin';\nimport { manifest, PAN_PLUGIN_ID } from './manifest';\nimport { PanPluginConfig } from './types';\n\nexport const PanPluginPackage: PluginPackage<PanPlugin, PanPluginConfig> = {\n manifest,\n create: (registry, config) => new PanPlugin(PAN_PLUGIN_ID, registry, config),\n reducer: () => {},\n initialState: {},\n};\n\nexport * from './pan-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":["_PanPlugin","BasePlugin","constructor","id","registry","config","super","this","panMode$","createBehaviorEmitter","interactionManager","_a","getPlugin","InteractionManagerPlugin","provides","viewport","_b","ViewportPlugin","registerMode","scope","exclusive","cursor","wantsRawTouch","unsubscribePanModeChange","onStateChange","state","activeMode","emit","registerPanHandlers","defaultMode","makePanDefault","initialize","_","destroy","unregisterHandlers","call","dragState","handlers","onMouseDown","pe","metrics","getMetrics","startX","clientX","startY","clientY","startLeft","scrollLeft","startTop","scrollTop","setCursor","onMouseMove","dx","dy","scrollTo","x","y","onMouseUp","removeCursor","onMouseLeave","onMouseCancel","registerHandlers","modeId","autoActivate","setDefaultMode","activateDefaultMode","buildCapability","onPanModeChange","on","enablePan","activate","disablePan","togglePan","getActiveMode","_c","PanPlugin","PAN_PLUGIN_ID","manifest","name","version","requires","optional","defaultConfig","enabled","PanPluginPackage","create","reducer","initialState"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/lib/actions.ts","../src/lib/pan-plugin.ts","../src/lib/manifest.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { Action } from '@embedpdf/core';\nimport { PanDocumentState } from './types';\n\n// Document lifecycle\nexport const INIT_PAN_STATE = 'PAN/INIT_STATE';\nexport const CLEANUP_PAN_STATE = 'PAN/CLEANUP_STATE';\nexport const SET_ACTIVE_PAN_DOCUMENT = 'PAN/SET_ACTIVE_DOCUMENT';\n\n// Pan operations\nexport const SET_PAN_MODE = 'PAN/SET_PAN_MODE';\n\n// Document lifecycle actions\nexport interface InitPanStateAction extends Action {\n type: typeof INIT_PAN_STATE;\n payload: {\n documentId: string;\n state: PanDocumentState;\n };\n}\n\nexport interface CleanupPanStateAction extends Action {\n type: typeof CLEANUP_PAN_STATE;\n payload: string; // documentId\n}\n\nexport interface SetActivePanDocumentAction extends Action {\n type: typeof SET_ACTIVE_PAN_DOCUMENT;\n payload: string | null; // documentId\n}\n\nexport interface SetPanModeAction extends Action {\n type: typeof SET_PAN_MODE;\n payload: {\n documentId: string;\n isPanMode: boolean;\n };\n}\n\nexport type PanAction =\n | InitPanStateAction\n | CleanupPanStateAction\n | SetActivePanDocumentAction\n | SetPanModeAction;\n\n// Action Creators\nexport function initPanState(documentId: string, state: PanDocumentState): InitPanStateAction {\n return { type: INIT_PAN_STATE, payload: { documentId, state } };\n}\n\nexport function cleanupPanState(documentId: string): CleanupPanStateAction {\n return { type: CLEANUP_PAN_STATE, payload: documentId };\n}\n\nexport function setActivePanDocument(documentId: string | null): SetActivePanDocumentAction {\n return { type: SET_ACTIVE_PAN_DOCUMENT, payload: documentId };\n}\n\nexport function setPanMode(documentId: string, isPanMode: boolean): SetPanModeAction {\n return { type: SET_PAN_MODE, payload: { documentId, isPanMode } };\n}\n","import { BasePlugin, createBehaviorEmitter, Listener, PluginRegistry } from '@embedpdf/core';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { ViewportCapability, ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport {\n PanCapability,\n PanPluginConfig,\n PanScope,\n PanModeChangeEvent,\n PanState,\n PanDocumentState,\n} from './types';\nimport { initPanState, cleanupPanState, setPanMode, PanAction } from './actions';\n\nexport class PanPlugin extends BasePlugin<PanPluginConfig, PanCapability, PanState, PanAction> {\n static readonly id = 'pan' as const;\n\n private readonly panMode$ = createBehaviorEmitter<PanModeChangeEvent>();\n\n private interactionManager: InteractionManagerCapability;\n private viewport: ViewportCapability;\n public config: PanPluginConfig;\n\n // Track handler cleanup functions per document\n private documentHandlers = new Map<string, () => void>();\n\n constructor(id: string, registry: PluginRegistry, config: PanPluginConfig) {\n super(id, registry);\n\n this.config = config;\n\n this.interactionManager = registry\n .getPlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id)\n ?.provides()!;\n this.viewport = registry.getPlugin<ViewportPlugin>(ViewportPlugin.id)?.provides()!;\n\n if (this.interactionManager) {\n // Register pan mode globally (mode definition is global)\n this.interactionManager.registerMode({\n id: 'panMode',\n scope: 'global',\n exclusive: false,\n cursor: 'grab',\n wantsRawTouch: false,\n });\n\n this.interactionManager?.onModeChange((state) => {\n // Track pan mode state changes for this document\n const isPanMode = state.activeMode === 'panMode';\n const docState = this.getDocumentState(state.documentId);\n\n // Only dispatch if state actually changed\n if (docState && docState.isPanMode !== isPanMode) {\n this.dispatch(setPanMode(state.documentId, isPanMode));\n }\n });\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle Hooks (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n // Initialize pan state for this document\n const docState: PanDocumentState = {\n isPanMode: false,\n };\n\n this.dispatch(initPanState(documentId, docState));\n\n // Register pan handlers for this document\n this.registerPanHandlersForDocument(documentId);\n\n // Handle 'always' mode\n if (this.config.defaultMode === 'always') {\n this.makePanDefault(true);\n }\n\n this.logger.debug(\n 'PanPlugin',\n 'DocumentOpened',\n `Initialized pan state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup handlers\n const cleanup = this.documentHandlers.get(documentId);\n if (cleanup) {\n cleanup();\n this.documentHandlers.delete(documentId);\n }\n\n // Cleanup state\n this.dispatch(cleanupPanState(documentId));\n\n this.logger.debug(\n 'PanPlugin',\n 'DocumentClosed',\n `Cleaned up pan state for document: ${documentId}`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): PanCapability {\n return {\n // Active document operations\n enablePan: () => this.enablePan(),\n disablePan: () => this.disablePan(),\n togglePan: () => this.togglePan(),\n makePanDefault: (autoActivate?: boolean) => this.makePanDefault(autoActivate),\n isPanMode: () => this.isPanMode(),\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createPanScope(documentId),\n\n // Events\n onPanModeChange: this.panMode$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createPanScope(documentId: string): PanScope {\n return {\n enablePan: () => this.enablePan(documentId),\n disablePan: () => this.disablePan(documentId),\n togglePan: () => this.togglePan(documentId),\n isPanMode: () => this.isPanMode(documentId),\n onPanModeChange: (listener: Listener<boolean>) =>\n this.panMode$.on((event) => {\n if (event.documentId === documentId) listener(event.isPanMode);\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // State Helpers\n // ─────────────────────────────────────────────────────────\n private getDocumentState(documentId?: string): PanDocumentState | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.state.documents[id] ?? null;\n }\n\n private getDocumentStateOrThrow(documentId?: string): PanDocumentState {\n const state = this.getDocumentState(documentId);\n if (!state) {\n throw new Error(`Pan state not found for document: ${documentId ?? 'active'}`);\n }\n return state;\n }\n\n // ─────────────────────────────────────────────────────────\n // Core Operations\n // ─────────────────────────────────────────────────────────\n\n private enablePan(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager.forDocument(id).activate('panMode');\n }\n\n private disablePan(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager.forDocument(id).activateDefaultMode();\n }\n\n private togglePan(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManager.forDocument(id);\n if (scope.getActiveMode() === 'panMode') {\n scope.activateDefaultMode();\n } else {\n scope.activate('panMode');\n }\n }\n\n private makePanDefault(autoActivate: boolean = true): void {\n if (!this.interactionManager) return;\n\n this.interactionManager.setDefaultMode('panMode');\n if (autoActivate) {\n this.interactionManager.activateDefaultMode();\n }\n }\n\n private isPanMode(documentId?: string): boolean {\n return this.getDocumentStateOrThrow(documentId).isPanMode;\n }\n\n // ─────────────────────────────────────────────────────────\n // Pan Handlers Registration\n // ─────────────────────────────────────────────────────────\n\n private registerPanHandlersForDocument(documentId: string) {\n if (!this.interactionManager || !this.viewport) return;\n\n let dragState: {\n startX: number;\n startY: number;\n startLeft: number;\n startTop: number;\n } | null = null;\n\n const interactionScope = this.interactionManager.forDocument(documentId);\n const viewportScope = this.viewport.forDocument(documentId);\n\n const handlers = {\n onMouseDown: (_: any, pe: MouseEvent) => {\n const metrics = viewportScope.getMetrics();\n\n dragState = {\n startX: pe.clientX,\n startY: pe.clientY,\n startLeft: metrics.scrollLeft,\n startTop: metrics.scrollTop,\n };\n\n interactionScope.setCursor('panMode', 'grabbing', 10);\n },\n onMouseMove: (_: any, pe: MouseEvent) => {\n if (!dragState) return;\n\n /* delta between current pointer position and where the drag started */\n const dx = pe.clientX - dragState.startX;\n const dy = pe.clientY - dragState.startY;\n\n viewportScope.scrollTo({\n x: dragState.startLeft - dx,\n y: dragState.startTop - dy,\n });\n },\n onMouseUp: () => {\n if (!dragState) return;\n\n dragState = null;\n interactionScope.removeCursor('panMode');\n },\n onMouseLeave: () => {\n if (!dragState) return;\n\n dragState = null;\n interactionScope.removeCursor('panMode');\n },\n onMouseCancel: () => {\n if (!dragState) return;\n\n dragState = null;\n interactionScope.removeCursor('panMode');\n },\n };\n\n const unregister = this.interactionManager.registerHandlers({\n documentId,\n modeId: 'panMode',\n handlers,\n });\n\n this.documentHandlers.set(documentId, unregister);\n }\n\n // ─────────────────────────────────────────────────────────\n // Store Update Handlers\n // ─────────────────────────────────────────────────────────\n\n override onStoreUpdated(prevState: PanState, newState: PanState): void {\n // Emit pan mode change events for each changed document\n for (const documentId in newState.documents) {\n const prevDoc = prevState.documents[documentId];\n const newDoc = newState.documents[documentId];\n\n if (prevDoc?.isPanMode !== newDoc.isPanMode) {\n this.panMode$.emit({\n documentId,\n isPanMode: newDoc.isPanMode,\n });\n\n this.logger.debug(\n 'PanPlugin',\n 'PanModeChanged',\n `Pan mode changed for document ${documentId}: ${prevDoc?.isPanMode ?? false} -> ${newDoc.isPanMode}`,\n );\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async initialize(_: PanPluginConfig): Promise<void> {\n this.logger.info('PanPlugin', 'Initialize', 'Pan plugin initialized');\n }\n\n async destroy(): Promise<void> {\n // Cleanup all document handlers\n this.documentHandlers.forEach((cleanup) => cleanup());\n this.documentHandlers.clear();\n\n this.panMode$.clear();\n await super.destroy();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { PanPluginConfig } from './types';\n\nexport const PAN_PLUGIN_ID = 'pan';\n\nexport const manifest: PluginManifest<PanPluginConfig> = {\n id: PAN_PLUGIN_ID,\n name: 'Pan Plugin',\n version: '1.0.0',\n provides: ['pan'],\n requires: ['interaction-manager', 'viewport'],\n optional: [],\n defaultConfig: {\n enabled: true,\n defaultMode: 'mobile',\n },\n};\n","import { Reducer } from '@embedpdf/core';\nimport {\n PanAction,\n INIT_PAN_STATE,\n CLEANUP_PAN_STATE,\n SET_ACTIVE_PAN_DOCUMENT,\n SET_PAN_MODE,\n} from './actions';\nimport { PanState, PanDocumentState } from './types';\n\nexport const initialDocumentState: PanDocumentState = {\n isPanMode: false,\n};\n\nexport const initialState: PanState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const panReducer: Reducer<PanState, PanAction> = (state = initialState, action) => {\n switch (action.type) {\n case INIT_PAN_STATE: {\n const { documentId, state: docState } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n // Set as active if no active document\n activeDocumentId: state.activeDocumentId ?? documentId,\n };\n }\n\n case CLEANUP_PAN_STATE: {\n const documentId = action.payload;\n const { [documentId]: removed, ...remainingDocs } = state.documents;\n return {\n ...state,\n documents: remainingDocs,\n activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId,\n };\n }\n\n case SET_ACTIVE_PAN_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n case SET_PAN_MODE: {\n const { documentId, isPanMode } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n isPanMode,\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { PanPlugin } from './pan-plugin';\nimport { manifest, PAN_PLUGIN_ID } from './manifest';\nimport { PanPluginConfig, PanState } from './types';\nimport { panReducer, initialState } from './reducer';\nimport { PanAction } from './actions';\n\nexport const PanPluginPackage: PluginPackage<PanPlugin, PanPluginConfig, PanState, PanAction> = {\n manifest,\n create: (registry, config) => new PanPlugin(PAN_PLUGIN_ID, registry, config),\n reducer: panReducer,\n initialState,\n};\n\nexport * from './pan-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './actions';\nexport * from './reducer';\n"],"names":["INIT_PAN_STATE","CLEANUP_PAN_STATE","SET_ACTIVE_PAN_DOCUMENT","SET_PAN_MODE","initPanState","documentId","state","type","payload","cleanupPanState","setPanMode","isPanMode","_PanPlugin","BasePlugin","constructor","id","registry","config","super","this","panMode$","createBehaviorEmitter","documentHandlers","Map","interactionManager","_a","getPlugin","InteractionManagerPlugin","provides","viewport","_b","ViewportPlugin","registerMode","scope","exclusive","cursor","wantsRawTouch","_c","onModeChange","activeMode","docState","getDocumentState","dispatch","onDocumentLoadingStarted","registerPanHandlersForDocument","defaultMode","makePanDefault","logger","debug","onDocumentClosed","cleanup","get","delete","buildCapability","enablePan","disablePan","togglePan","autoActivate","forDocument","createPanScope","onPanModeChange","on","listener","event","getActiveDocumentId","documents","getDocumentStateOrThrow","Error","activate","activateDefaultMode","getActiveMode","setDefaultMode","dragState","interactionScope","viewportScope","handlers","onMouseDown","_","pe","metrics","getMetrics","startX","clientX","startY","clientY","startLeft","scrollLeft","startTop","scrollTop","setCursor","onMouseMove","dx","dy","scrollTo","x","y","onMouseUp","removeCursor","onMouseLeave","onMouseCancel","unregister","registerHandlers","modeId","set","onStoreUpdated","prevState","newState","prevDoc","newDoc","emit","initialize","info","destroy","forEach","clear","PanPlugin","PAN_PLUGIN_ID","manifest","name","version","requires","optional","defaultConfig","enabled","initialState","activeDocumentId","panReducer","action","removed","remainingDocs","PanPluginPackage","create","reducer"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,11 +1,28 @@
1
1
  import { BasePlugin, createBehaviorEmitter } from "@embedpdf/core";
2
2
  import { InteractionManagerPlugin } from "@embedpdf/plugin-interaction-manager";
3
3
  import { ViewportPlugin } from "@embedpdf/plugin-viewport";
4
+ const INIT_PAN_STATE = "PAN/INIT_STATE";
5
+ const CLEANUP_PAN_STATE = "PAN/CLEANUP_STATE";
6
+ const SET_ACTIVE_PAN_DOCUMENT = "PAN/SET_ACTIVE_DOCUMENT";
7
+ const SET_PAN_MODE = "PAN/SET_PAN_MODE";
8
+ function initPanState(documentId, state) {
9
+ return { type: INIT_PAN_STATE, payload: { documentId, state } };
10
+ }
11
+ function cleanupPanState(documentId) {
12
+ return { type: CLEANUP_PAN_STATE, payload: documentId };
13
+ }
14
+ function setActivePanDocument(documentId) {
15
+ return { type: SET_ACTIVE_PAN_DOCUMENT, payload: documentId };
16
+ }
17
+ function setPanMode(documentId, isPanMode) {
18
+ return { type: SET_PAN_MODE, payload: { documentId, isPanMode } };
19
+ }
4
20
  const _PanPlugin = class _PanPlugin extends BasePlugin {
5
21
  constructor(id, registry, config) {
6
- var _a, _b;
22
+ var _a, _b, _c;
7
23
  super(id, registry);
8
24
  this.panMode$ = createBehaviorEmitter();
25
+ this.documentHandlers = /* @__PURE__ */ new Map();
9
26
  this.config = config;
10
27
  this.interactionManager = (_a = registry.getPlugin(InteractionManagerPlugin.id)) == null ? void 0 : _a.provides();
11
28
  this.viewport = (_b = registry.getPlugin(ViewportPlugin.id)) == null ? void 0 : _b.provides();
@@ -17,45 +34,145 @@ const _PanPlugin = class _PanPlugin extends BasePlugin {
17
34
  cursor: "grab",
18
35
  wantsRawTouch: false
19
36
  });
20
- this.unsubscribePanModeChange = this.interactionManager.onStateChange((state) => {
21
- if (state.activeMode === "panMode") {
22
- this.panMode$.emit(true);
23
- } else {
24
- this.panMode$.emit(false);
37
+ (_c = this.interactionManager) == null ? void 0 : _c.onModeChange((state) => {
38
+ const isPanMode = state.activeMode === "panMode";
39
+ const docState = this.getDocumentState(state.documentId);
40
+ if (docState && docState.isPanMode !== isPanMode) {
41
+ this.dispatch(setPanMode(state.documentId, isPanMode));
25
42
  }
26
43
  });
27
- this.registerPanHandlers();
28
44
  }
29
- if (config.defaultMode === "always") {
45
+ }
46
+ // ─────────────────────────────────────────────────────────
47
+ // Document Lifecycle Hooks (from BasePlugin)
48
+ // ─────────────────────────────────────────────────────────
49
+ onDocumentLoadingStarted(documentId) {
50
+ const docState = {
51
+ isPanMode: false
52
+ };
53
+ this.dispatch(initPanState(documentId, docState));
54
+ this.registerPanHandlersForDocument(documentId);
55
+ if (this.config.defaultMode === "always") {
30
56
  this.makePanDefault(true);
31
57
  }
58
+ this.logger.debug(
59
+ "PanPlugin",
60
+ "DocumentOpened",
61
+ `Initialized pan state for document: ${documentId}`
62
+ );
32
63
  }
33
- async initialize(_) {
64
+ onDocumentClosed(documentId) {
65
+ const cleanup = this.documentHandlers.get(documentId);
66
+ if (cleanup) {
67
+ cleanup();
68
+ this.documentHandlers.delete(documentId);
69
+ }
70
+ this.dispatch(cleanupPanState(documentId));
71
+ this.logger.debug(
72
+ "PanPlugin",
73
+ "DocumentClosed",
74
+ `Cleaned up pan state for document: ${documentId}`
75
+ );
34
76
  }
35
- async destroy() {
36
- var _a, _b;
37
- (_a = this.unregisterHandlers) == null ? void 0 : _a.call(this);
38
- (_b = this.unsubscribePanModeChange) == null ? void 0 : _b.call(this);
39
- await super.destroy();
77
+ // ─────────────────────────────────────────────────────────
78
+ // Capability
79
+ // ─────────────────────────────────────────────────────────
80
+ buildCapability() {
81
+ return {
82
+ // Active document operations
83
+ enablePan: () => this.enablePan(),
84
+ disablePan: () => this.disablePan(),
85
+ togglePan: () => this.togglePan(),
86
+ makePanDefault: (autoActivate) => this.makePanDefault(autoActivate),
87
+ isPanMode: () => this.isPanMode(),
88
+ // Document-scoped operations
89
+ forDocument: (documentId) => this.createPanScope(documentId),
90
+ // Events
91
+ onPanModeChange: this.panMode$.on
92
+ };
93
+ }
94
+ // ─────────────────────────────────────────────────────────
95
+ // Document Scoping
96
+ // ─────────────────────────────────────────────────────────
97
+ createPanScope(documentId) {
98
+ return {
99
+ enablePan: () => this.enablePan(documentId),
100
+ disablePan: () => this.disablePan(documentId),
101
+ togglePan: () => this.togglePan(documentId),
102
+ isPanMode: () => this.isPanMode(documentId),
103
+ onPanModeChange: (listener) => this.panMode$.on((event) => {
104
+ if (event.documentId === documentId) listener(event.isPanMode);
105
+ })
106
+ };
107
+ }
108
+ // ─────────────────────────────────────────────────────────
109
+ // State Helpers
110
+ // ─────────────────────────────────────────────────────────
111
+ getDocumentState(documentId) {
112
+ const id = documentId ?? this.getActiveDocumentId();
113
+ return this.state.documents[id] ?? null;
114
+ }
115
+ getDocumentStateOrThrow(documentId) {
116
+ const state = this.getDocumentState(documentId);
117
+ if (!state) {
118
+ throw new Error(`Pan state not found for document: ${documentId ?? "active"}`);
119
+ }
120
+ return state;
121
+ }
122
+ // ─────────────────────────────────────────────────────────
123
+ // Core Operations
124
+ // ─────────────────────────────────────────────────────────
125
+ enablePan(documentId) {
126
+ const id = documentId ?? this.getActiveDocumentId();
127
+ this.interactionManager.forDocument(id).activate("panMode");
128
+ }
129
+ disablePan(documentId) {
130
+ const id = documentId ?? this.getActiveDocumentId();
131
+ this.interactionManager.forDocument(id).activateDefaultMode();
132
+ }
133
+ togglePan(documentId) {
134
+ const id = documentId ?? this.getActiveDocumentId();
135
+ const scope = this.interactionManager.forDocument(id);
136
+ if (scope.getActiveMode() === "panMode") {
137
+ scope.activateDefaultMode();
138
+ } else {
139
+ scope.activate("panMode");
140
+ }
141
+ }
142
+ makePanDefault(autoActivate = true) {
143
+ if (!this.interactionManager) return;
144
+ this.interactionManager.setDefaultMode("panMode");
145
+ if (autoActivate) {
146
+ this.interactionManager.activateDefaultMode();
147
+ }
148
+ }
149
+ isPanMode(documentId) {
150
+ return this.getDocumentStateOrThrow(documentId).isPanMode;
40
151
  }
41
- registerPanHandlers() {
152
+ // ─────────────────────────────────────────────────────────
153
+ // Pan Handlers Registration
154
+ // ─────────────────────────────────────────────────────────
155
+ registerPanHandlersForDocument(documentId) {
156
+ if (!this.interactionManager || !this.viewport) return;
42
157
  let dragState = null;
158
+ const interactionScope = this.interactionManager.forDocument(documentId);
159
+ const viewportScope = this.viewport.forDocument(documentId);
43
160
  const handlers = {
44
161
  onMouseDown: (_, pe) => {
45
- const metrics = this.viewport.getMetrics();
162
+ const metrics = viewportScope.getMetrics();
46
163
  dragState = {
47
164
  startX: pe.clientX,
48
165
  startY: pe.clientY,
49
166
  startLeft: metrics.scrollLeft,
50
167
  startTop: metrics.scrollTop
51
168
  };
52
- this.interactionManager.setCursor("panMode", "grabbing", 10);
169
+ interactionScope.setCursor("panMode", "grabbing", 10);
53
170
  },
54
171
  onMouseMove: (_, pe) => {
55
172
  if (!dragState) return;
56
173
  const dx = pe.clientX - dragState.startX;
57
174
  const dy = pe.clientY - dragState.startY;
58
- this.viewport.scrollTo({
175
+ viewportScope.scrollTo({
59
176
  x: dragState.startLeft - dx,
60
177
  y: dragState.startTop - dy
61
178
  });
@@ -63,52 +180,57 @@ const _PanPlugin = class _PanPlugin extends BasePlugin {
63
180
  onMouseUp: () => {
64
181
  if (!dragState) return;
65
182
  dragState = null;
66
- this.interactionManager.removeCursor("panMode");
183
+ interactionScope.removeCursor("panMode");
67
184
  },
68
185
  onMouseLeave: () => {
69
186
  if (!dragState) return;
70
187
  dragState = null;
71
- this.interactionManager.removeCursor("panMode");
188
+ interactionScope.removeCursor("panMode");
72
189
  },
73
190
  onMouseCancel: () => {
74
191
  if (!dragState) return;
75
192
  dragState = null;
76
- this.interactionManager.removeCursor("panMode");
193
+ interactionScope.removeCursor("panMode");
77
194
  }
78
195
  };
79
- this.unregisterHandlers = this.interactionManager.registerHandlers({
196
+ const unregister = this.interactionManager.registerHandlers({
197
+ documentId,
80
198
  modeId: "panMode",
81
199
  handlers
82
200
  });
201
+ this.documentHandlers.set(documentId, unregister);
83
202
  }
84
- makePanDefault(autoActivate = true) {
85
- if (!this.interactionManager) return;
86
- this.interactionManager.setDefaultMode("panMode");
87
- if (autoActivate) {
88
- this.interactionManager.activateDefaultMode();
203
+ // ─────────────────────────────────────────────────────────
204
+ // Store Update Handlers
205
+ // ─────────────────────────────────────────────────────────
206
+ onStoreUpdated(prevState, newState) {
207
+ for (const documentId in newState.documents) {
208
+ const prevDoc = prevState.documents[documentId];
209
+ const newDoc = newState.documents[documentId];
210
+ if ((prevDoc == null ? void 0 : prevDoc.isPanMode) !== newDoc.isPanMode) {
211
+ this.panMode$.emit({
212
+ documentId,
213
+ isPanMode: newDoc.isPanMode
214
+ });
215
+ this.logger.debug(
216
+ "PanPlugin",
217
+ "PanModeChanged",
218
+ `Pan mode changed for document ${documentId}: ${(prevDoc == null ? void 0 : prevDoc.isPanMode) ?? false} -> ${newDoc.isPanMode}`
219
+ );
220
+ }
89
221
  }
90
222
  }
91
- buildCapability() {
92
- return {
93
- onPanModeChange: this.panMode$.on,
94
- makePanDefault: (autoActivate = true) => this.makePanDefault(autoActivate),
95
- enablePan: () => {
96
- var _a;
97
- return (_a = this.interactionManager) == null ? void 0 : _a.activate("panMode");
98
- },
99
- disablePan: () => {
100
- var _a;
101
- return (_a = this.interactionManager) == null ? void 0 : _a.activateDefaultMode();
102
- },
103
- togglePan: () => {
104
- var _a, _b, _c;
105
- if (((_a = this.interactionManager) == null ? void 0 : _a.getActiveMode()) === "panMode") {
106
- (_b = this.interactionManager) == null ? void 0 : _b.activateDefaultMode();
107
- } else {
108
- (_c = this.interactionManager) == null ? void 0 : _c.activate("panMode");
109
- }
110
- }
111
- };
223
+ // ─────────────────────────────────────────────────────────
224
+ // Lifecycle
225
+ // ─────────────────────────────────────────────────────────
226
+ async initialize(_) {
227
+ this.logger.info("PanPlugin", "Initialize", "Pan plugin initialized");
228
+ }
229
+ async destroy() {
230
+ this.documentHandlers.forEach((cleanup) => cleanup());
231
+ this.documentHandlers.clear();
232
+ this.panMode$.clear();
233
+ await super.destroy();
112
234
  }
113
235
  };
114
236
  _PanPlugin.id = "pan";
@@ -126,17 +248,82 @@ const manifest = {
126
248
  defaultMode: "mobile"
127
249
  }
128
250
  };
251
+ const initialDocumentState = {
252
+ isPanMode: false
253
+ };
254
+ const initialState = {
255
+ documents: {},
256
+ activeDocumentId: null
257
+ };
258
+ const panReducer = (state = initialState, action) => {
259
+ switch (action.type) {
260
+ case INIT_PAN_STATE: {
261
+ const { documentId, state: docState } = action.payload;
262
+ return {
263
+ ...state,
264
+ documents: {
265
+ ...state.documents,
266
+ [documentId]: docState
267
+ },
268
+ // Set as active if no active document
269
+ activeDocumentId: state.activeDocumentId ?? documentId
270
+ };
271
+ }
272
+ case CLEANUP_PAN_STATE: {
273
+ const documentId = action.payload;
274
+ const { [documentId]: removed, ...remainingDocs } = state.documents;
275
+ return {
276
+ ...state,
277
+ documents: remainingDocs,
278
+ activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId
279
+ };
280
+ }
281
+ case SET_ACTIVE_PAN_DOCUMENT: {
282
+ return {
283
+ ...state,
284
+ activeDocumentId: action.payload
285
+ };
286
+ }
287
+ case SET_PAN_MODE: {
288
+ const { documentId, isPanMode } = action.payload;
289
+ const docState = state.documents[documentId];
290
+ if (!docState) return state;
291
+ return {
292
+ ...state,
293
+ documents: {
294
+ ...state.documents,
295
+ [documentId]: {
296
+ ...docState,
297
+ isPanMode
298
+ }
299
+ }
300
+ };
301
+ }
302
+ default:
303
+ return state;
304
+ }
305
+ };
129
306
  const PanPluginPackage = {
130
307
  manifest,
131
308
  create: (registry, config) => new PanPlugin(PAN_PLUGIN_ID, registry, config),
132
- reducer: () => {
133
- },
134
- initialState: {}
309
+ reducer: panReducer,
310
+ initialState
135
311
  };
136
312
  export {
313
+ CLEANUP_PAN_STATE,
314
+ INIT_PAN_STATE,
137
315
  PAN_PLUGIN_ID,
138
316
  PanPlugin,
139
317
  PanPluginPackage,
140
- manifest
318
+ SET_ACTIVE_PAN_DOCUMENT,
319
+ SET_PAN_MODE,
320
+ cleanupPanState,
321
+ initPanState,
322
+ initialDocumentState,
323
+ initialState,
324
+ manifest,
325
+ panReducer,
326
+ setActivePanDocument,
327
+ setPanMode
141
328
  };
142
329
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/lib/pan-plugin.ts","../src/lib/manifest.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePlugin, createBehaviorEmitter, PluginRegistry, Unsubscribe } from '@embedpdf/core';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\n\nimport { PanCapability, PanPluginConfig } from './types';\nimport { ViewportCapability, ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nexport class PanPlugin extends BasePlugin<PanPluginConfig, PanCapability> {\n static readonly id = 'pan' as const;\n\n private readonly panMode$ = createBehaviorEmitter<boolean>();\n\n private interactionManager: InteractionManagerCapability;\n private viewport: ViewportCapability;\n public config: PanPluginConfig;\n\n private unregisterHandlers?: () => void;\n private unsubscribePanModeChange?: Unsubscribe;\n\n constructor(id: string, registry: PluginRegistry, config: PanPluginConfig) {\n super(id, registry);\n\n this.config = config;\n\n this.interactionManager = registry\n .getPlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id)\n ?.provides()!;\n this.viewport = registry.getPlugin<ViewportPlugin>(ViewportPlugin.id)?.provides()!;\n\n if (this.interactionManager) {\n this.interactionManager.registerMode({\n id: 'panMode',\n scope: 'global',\n exclusive: false,\n cursor: 'grab',\n wantsRawTouch: false,\n });\n\n this.unsubscribePanModeChange = this.interactionManager.onStateChange((state) => {\n if (state.activeMode === 'panMode') {\n this.panMode$.emit(true);\n } else {\n this.panMode$.emit(false);\n }\n });\n\n // Register pan handlers immediately\n this.registerPanHandlers();\n }\n\n // Handle 'always' mode - this is safe on server side\n if (config.defaultMode === 'always') {\n this.makePanDefault(true);\n }\n }\n\n async initialize(_: PanPluginConfig): Promise<void> {}\n\n async destroy(): Promise<void> {\n this.unregisterHandlers?.();\n this.unsubscribePanModeChange?.();\n await super.destroy();\n }\n\n private registerPanHandlers() {\n let dragState: {\n startX: number;\n startY: number;\n startLeft: number;\n startTop: number;\n } | null = null;\n\n const handlers = {\n onMouseDown: (_: any, pe: MouseEvent) => {\n const metrics = this.viewport.getMetrics();\n\n dragState = {\n startX: pe.clientX,\n startY: pe.clientY,\n startLeft: metrics.scrollLeft,\n startTop: metrics.scrollTop,\n };\n\n this.interactionManager.setCursor('panMode', 'grabbing', 10);\n },\n onMouseMove: (_: any, pe: MouseEvent) => {\n if (!dragState) return;\n\n /* delta between current pointer position and where the drag started */\n const dx = pe.clientX - dragState.startX;\n const dy = pe.clientY - dragState.startY;\n\n this.viewport.scrollTo({\n x: dragState.startLeft - dx,\n y: dragState.startTop - dy,\n });\n },\n onMouseUp: () => {\n if (!dragState) return;\n\n dragState = null;\n this.interactionManager.removeCursor('panMode');\n },\n onMouseLeave: () => {\n if (!dragState) return;\n\n dragState = null;\n this.interactionManager.removeCursor('panMode');\n },\n onMouseCancel: () => {\n if (!dragState) return;\n\n dragState = null;\n this.interactionManager.removeCursor('panMode');\n },\n };\n\n this.unregisterHandlers = this.interactionManager.registerHandlers({\n modeId: 'panMode',\n handlers,\n });\n }\n\n private makePanDefault(autoActivate: boolean = true) {\n if (!this.interactionManager) return;\n\n this.interactionManager.setDefaultMode('panMode');\n if (autoActivate) {\n this.interactionManager.activateDefaultMode();\n }\n }\n\n protected buildCapability(): PanCapability {\n return {\n onPanModeChange: this.panMode$.on,\n makePanDefault: (autoActivate: boolean = true) => this.makePanDefault(autoActivate),\n enablePan: () => this.interactionManager?.activate('panMode'),\n disablePan: () => this.interactionManager?.activateDefaultMode(),\n togglePan: () => {\n if (this.interactionManager?.getActiveMode() === 'panMode') {\n this.interactionManager?.activateDefaultMode();\n } else {\n this.interactionManager?.activate('panMode');\n }\n },\n };\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { PanPluginConfig } from './types';\n\nexport const PAN_PLUGIN_ID = 'pan';\n\nexport const manifest: PluginManifest<PanPluginConfig> = {\n id: PAN_PLUGIN_ID,\n name: 'Pan Plugin',\n version: '1.0.0',\n provides: ['pan'],\n requires: ['interaction-manager', 'viewport'],\n optional: [],\n defaultConfig: {\n enabled: true,\n defaultMode: 'mobile',\n },\n};\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { PanPlugin } from './pan-plugin';\nimport { manifest, PAN_PLUGIN_ID } from './manifest';\nimport { PanPluginConfig } from './types';\n\nexport const PanPluginPackage: PluginPackage<PanPlugin, PanPluginConfig> = {\n manifest,\n create: (registry, config) => new PanPlugin(PAN_PLUGIN_ID, registry, config),\n reducer: () => {},\n initialState: {},\n};\n\nexport * from './pan-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/lib/actions.ts","../src/lib/pan-plugin.ts","../src/lib/manifest.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { Action } from '@embedpdf/core';\nimport { PanDocumentState } from './types';\n\n// Document lifecycle\nexport const INIT_PAN_STATE = 'PAN/INIT_STATE';\nexport const CLEANUP_PAN_STATE = 'PAN/CLEANUP_STATE';\nexport const SET_ACTIVE_PAN_DOCUMENT = 'PAN/SET_ACTIVE_DOCUMENT';\n\n// Pan operations\nexport const SET_PAN_MODE = 'PAN/SET_PAN_MODE';\n\n// Document lifecycle actions\nexport interface InitPanStateAction extends Action {\n type: typeof INIT_PAN_STATE;\n payload: {\n documentId: string;\n state: PanDocumentState;\n };\n}\n\nexport interface CleanupPanStateAction extends Action {\n type: typeof CLEANUP_PAN_STATE;\n payload: string; // documentId\n}\n\nexport interface SetActivePanDocumentAction extends Action {\n type: typeof SET_ACTIVE_PAN_DOCUMENT;\n payload: string | null; // documentId\n}\n\nexport interface SetPanModeAction extends Action {\n type: typeof SET_PAN_MODE;\n payload: {\n documentId: string;\n isPanMode: boolean;\n };\n}\n\nexport type PanAction =\n | InitPanStateAction\n | CleanupPanStateAction\n | SetActivePanDocumentAction\n | SetPanModeAction;\n\n// Action Creators\nexport function initPanState(documentId: string, state: PanDocumentState): InitPanStateAction {\n return { type: INIT_PAN_STATE, payload: { documentId, state } };\n}\n\nexport function cleanupPanState(documentId: string): CleanupPanStateAction {\n return { type: CLEANUP_PAN_STATE, payload: documentId };\n}\n\nexport function setActivePanDocument(documentId: string | null): SetActivePanDocumentAction {\n return { type: SET_ACTIVE_PAN_DOCUMENT, payload: documentId };\n}\n\nexport function setPanMode(documentId: string, isPanMode: boolean): SetPanModeAction {\n return { type: SET_PAN_MODE, payload: { documentId, isPanMode } };\n}\n","import { BasePlugin, createBehaviorEmitter, Listener, PluginRegistry } from '@embedpdf/core';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport { ViewportCapability, ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nimport {\n PanCapability,\n PanPluginConfig,\n PanScope,\n PanModeChangeEvent,\n PanState,\n PanDocumentState,\n} from './types';\nimport { initPanState, cleanupPanState, setPanMode, PanAction } from './actions';\n\nexport class PanPlugin extends BasePlugin<PanPluginConfig, PanCapability, PanState, PanAction> {\n static readonly id = 'pan' as const;\n\n private readonly panMode$ = createBehaviorEmitter<PanModeChangeEvent>();\n\n private interactionManager: InteractionManagerCapability;\n private viewport: ViewportCapability;\n public config: PanPluginConfig;\n\n // Track handler cleanup functions per document\n private documentHandlers = new Map<string, () => void>();\n\n constructor(id: string, registry: PluginRegistry, config: PanPluginConfig) {\n super(id, registry);\n\n this.config = config;\n\n this.interactionManager = registry\n .getPlugin<InteractionManagerPlugin>(InteractionManagerPlugin.id)\n ?.provides()!;\n this.viewport = registry.getPlugin<ViewportPlugin>(ViewportPlugin.id)?.provides()!;\n\n if (this.interactionManager) {\n // Register pan mode globally (mode definition is global)\n this.interactionManager.registerMode({\n id: 'panMode',\n scope: 'global',\n exclusive: false,\n cursor: 'grab',\n wantsRawTouch: false,\n });\n\n this.interactionManager?.onModeChange((state) => {\n // Track pan mode state changes for this document\n const isPanMode = state.activeMode === 'panMode';\n const docState = this.getDocumentState(state.documentId);\n\n // Only dispatch if state actually changed\n if (docState && docState.isPanMode !== isPanMode) {\n this.dispatch(setPanMode(state.documentId, isPanMode));\n }\n });\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle Hooks (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n // Initialize pan state for this document\n const docState: PanDocumentState = {\n isPanMode: false,\n };\n\n this.dispatch(initPanState(documentId, docState));\n\n // Register pan handlers for this document\n this.registerPanHandlersForDocument(documentId);\n\n // Handle 'always' mode\n if (this.config.defaultMode === 'always') {\n this.makePanDefault(true);\n }\n\n this.logger.debug(\n 'PanPlugin',\n 'DocumentOpened',\n `Initialized pan state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup handlers\n const cleanup = this.documentHandlers.get(documentId);\n if (cleanup) {\n cleanup();\n this.documentHandlers.delete(documentId);\n }\n\n // Cleanup state\n this.dispatch(cleanupPanState(documentId));\n\n this.logger.debug(\n 'PanPlugin',\n 'DocumentClosed',\n `Cleaned up pan state for document: ${documentId}`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): PanCapability {\n return {\n // Active document operations\n enablePan: () => this.enablePan(),\n disablePan: () => this.disablePan(),\n togglePan: () => this.togglePan(),\n makePanDefault: (autoActivate?: boolean) => this.makePanDefault(autoActivate),\n isPanMode: () => this.isPanMode(),\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createPanScope(documentId),\n\n // Events\n onPanModeChange: this.panMode$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createPanScope(documentId: string): PanScope {\n return {\n enablePan: () => this.enablePan(documentId),\n disablePan: () => this.disablePan(documentId),\n togglePan: () => this.togglePan(documentId),\n isPanMode: () => this.isPanMode(documentId),\n onPanModeChange: (listener: Listener<boolean>) =>\n this.panMode$.on((event) => {\n if (event.documentId === documentId) listener(event.isPanMode);\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // State Helpers\n // ─────────────────────────────────────────────────────────\n private getDocumentState(documentId?: string): PanDocumentState | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.state.documents[id] ?? null;\n }\n\n private getDocumentStateOrThrow(documentId?: string): PanDocumentState {\n const state = this.getDocumentState(documentId);\n if (!state) {\n throw new Error(`Pan state not found for document: ${documentId ?? 'active'}`);\n }\n return state;\n }\n\n // ─────────────────────────────────────────────────────────\n // Core Operations\n // ─────────────────────────────────────────────────────────\n\n private enablePan(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager.forDocument(id).activate('panMode');\n }\n\n private disablePan(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManager.forDocument(id).activateDefaultMode();\n }\n\n private togglePan(documentId?: string): void {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManager.forDocument(id);\n if (scope.getActiveMode() === 'panMode') {\n scope.activateDefaultMode();\n } else {\n scope.activate('panMode');\n }\n }\n\n private makePanDefault(autoActivate: boolean = true): void {\n if (!this.interactionManager) return;\n\n this.interactionManager.setDefaultMode('panMode');\n if (autoActivate) {\n this.interactionManager.activateDefaultMode();\n }\n }\n\n private isPanMode(documentId?: string): boolean {\n return this.getDocumentStateOrThrow(documentId).isPanMode;\n }\n\n // ─────────────────────────────────────────────────────────\n // Pan Handlers Registration\n // ─────────────────────────────────────────────────────────\n\n private registerPanHandlersForDocument(documentId: string) {\n if (!this.interactionManager || !this.viewport) return;\n\n let dragState: {\n startX: number;\n startY: number;\n startLeft: number;\n startTop: number;\n } | null = null;\n\n const interactionScope = this.interactionManager.forDocument(documentId);\n const viewportScope = this.viewport.forDocument(documentId);\n\n const handlers = {\n onMouseDown: (_: any, pe: MouseEvent) => {\n const metrics = viewportScope.getMetrics();\n\n dragState = {\n startX: pe.clientX,\n startY: pe.clientY,\n startLeft: metrics.scrollLeft,\n startTop: metrics.scrollTop,\n };\n\n interactionScope.setCursor('panMode', 'grabbing', 10);\n },\n onMouseMove: (_: any, pe: MouseEvent) => {\n if (!dragState) return;\n\n /* delta between current pointer position and where the drag started */\n const dx = pe.clientX - dragState.startX;\n const dy = pe.clientY - dragState.startY;\n\n viewportScope.scrollTo({\n x: dragState.startLeft - dx,\n y: dragState.startTop - dy,\n });\n },\n onMouseUp: () => {\n if (!dragState) return;\n\n dragState = null;\n interactionScope.removeCursor('panMode');\n },\n onMouseLeave: () => {\n if (!dragState) return;\n\n dragState = null;\n interactionScope.removeCursor('panMode');\n },\n onMouseCancel: () => {\n if (!dragState) return;\n\n dragState = null;\n interactionScope.removeCursor('panMode');\n },\n };\n\n const unregister = this.interactionManager.registerHandlers({\n documentId,\n modeId: 'panMode',\n handlers,\n });\n\n this.documentHandlers.set(documentId, unregister);\n }\n\n // ─────────────────────────────────────────────────────────\n // Store Update Handlers\n // ─────────────────────────────────────────────────────────\n\n override onStoreUpdated(prevState: PanState, newState: PanState): void {\n // Emit pan mode change events for each changed document\n for (const documentId in newState.documents) {\n const prevDoc = prevState.documents[documentId];\n const newDoc = newState.documents[documentId];\n\n if (prevDoc?.isPanMode !== newDoc.isPanMode) {\n this.panMode$.emit({\n documentId,\n isPanMode: newDoc.isPanMode,\n });\n\n this.logger.debug(\n 'PanPlugin',\n 'PanModeChanged',\n `Pan mode changed for document ${documentId}: ${prevDoc?.isPanMode ?? false} -> ${newDoc.isPanMode}`,\n );\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async initialize(_: PanPluginConfig): Promise<void> {\n this.logger.info('PanPlugin', 'Initialize', 'Pan plugin initialized');\n }\n\n async destroy(): Promise<void> {\n // Cleanup all document handlers\n this.documentHandlers.forEach((cleanup) => cleanup());\n this.documentHandlers.clear();\n\n this.panMode$.clear();\n await super.destroy();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { PanPluginConfig } from './types';\n\nexport const PAN_PLUGIN_ID = 'pan';\n\nexport const manifest: PluginManifest<PanPluginConfig> = {\n id: PAN_PLUGIN_ID,\n name: 'Pan Plugin',\n version: '1.0.0',\n provides: ['pan'],\n requires: ['interaction-manager', 'viewport'],\n optional: [],\n defaultConfig: {\n enabled: true,\n defaultMode: 'mobile',\n },\n};\n","import { Reducer } from '@embedpdf/core';\nimport {\n PanAction,\n INIT_PAN_STATE,\n CLEANUP_PAN_STATE,\n SET_ACTIVE_PAN_DOCUMENT,\n SET_PAN_MODE,\n} from './actions';\nimport { PanState, PanDocumentState } from './types';\n\nexport const initialDocumentState: PanDocumentState = {\n isPanMode: false,\n};\n\nexport const initialState: PanState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const panReducer: Reducer<PanState, PanAction> = (state = initialState, action) => {\n switch (action.type) {\n case INIT_PAN_STATE: {\n const { documentId, state: docState } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n // Set as active if no active document\n activeDocumentId: state.activeDocumentId ?? documentId,\n };\n }\n\n case CLEANUP_PAN_STATE: {\n const documentId = action.payload;\n const { [documentId]: removed, ...remainingDocs } = state.documents;\n return {\n ...state,\n documents: remainingDocs,\n activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId,\n };\n }\n\n case SET_ACTIVE_PAN_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n case SET_PAN_MODE: {\n const { documentId, isPanMode } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n isPanMode,\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\n\nimport { PanPlugin } from './pan-plugin';\nimport { manifest, PAN_PLUGIN_ID } from './manifest';\nimport { PanPluginConfig, PanState } from './types';\nimport { panReducer, initialState } from './reducer';\nimport { PanAction } from './actions';\n\nexport const PanPluginPackage: PluginPackage<PanPlugin, PanPluginConfig, PanState, PanAction> = {\n manifest,\n create: (registry, config) => new PanPlugin(PAN_PLUGIN_ID, registry, config),\n reducer: panReducer,\n initialState,\n};\n\nexport * from './pan-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './actions';\nexport * from './reducer';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { Action } from '@embedpdf/core';
2
+ import { PanDocumentState } from './types';
3
+ export declare const INIT_PAN_STATE = "PAN/INIT_STATE";
4
+ export declare const CLEANUP_PAN_STATE = "PAN/CLEANUP_STATE";
5
+ export declare const SET_ACTIVE_PAN_DOCUMENT = "PAN/SET_ACTIVE_DOCUMENT";
6
+ export declare const SET_PAN_MODE = "PAN/SET_PAN_MODE";
7
+ export interface InitPanStateAction extends Action {
8
+ type: typeof INIT_PAN_STATE;
9
+ payload: {
10
+ documentId: string;
11
+ state: PanDocumentState;
12
+ };
13
+ }
14
+ export interface CleanupPanStateAction extends Action {
15
+ type: typeof CLEANUP_PAN_STATE;
16
+ payload: string;
17
+ }
18
+ export interface SetActivePanDocumentAction extends Action {
19
+ type: typeof SET_ACTIVE_PAN_DOCUMENT;
20
+ payload: string | null;
21
+ }
22
+ export interface SetPanModeAction extends Action {
23
+ type: typeof SET_PAN_MODE;
24
+ payload: {
25
+ documentId: string;
26
+ isPanMode: boolean;
27
+ };
28
+ }
29
+ export type PanAction = InitPanStateAction | CleanupPanStateAction | SetActivePanDocumentAction | SetPanModeAction;
30
+ export declare function initPanState(documentId: string, state: PanDocumentState): InitPanStateAction;
31
+ export declare function cleanupPanState(documentId: string): CleanupPanStateAction;
32
+ export declare function setActivePanDocument(documentId: string | null): SetActivePanDocumentAction;
33
+ export declare function setPanMode(documentId: string, isPanMode: boolean): SetPanModeAction;
@@ -1,7 +1,10 @@
1
1
  import { PluginPackage } from '@embedpdf/core';
2
2
  import { PanPlugin } from './pan-plugin';
3
- import { PanPluginConfig } from './types';
4
- export declare const PanPluginPackage: PluginPackage<PanPlugin, PanPluginConfig>;
3
+ import { PanPluginConfig, PanState } from './types';
4
+ import { PanAction } from './actions';
5
+ export declare const PanPluginPackage: PluginPackage<PanPlugin, PanPluginConfig, PanState, PanAction>;
5
6
  export * from './pan-plugin';
6
7
  export * from './types';
7
8
  export * from './manifest';
9
+ export * from './actions';
10
+ export * from './reducer';
@@ -1,17 +1,27 @@
1
1
  import { BasePlugin, PluginRegistry } from '@embedpdf/core';
2
- import { PanCapability, PanPluginConfig } from './types';
3
- export declare class PanPlugin extends BasePlugin<PanPluginConfig, PanCapability> {
2
+ import { PanCapability, PanPluginConfig, PanState } from './types';
3
+ import { PanAction } from './actions';
4
+ export declare class PanPlugin extends BasePlugin<PanPluginConfig, PanCapability, PanState, PanAction> {
4
5
  static readonly id: "pan";
5
6
  private readonly panMode$;
6
7
  private interactionManager;
7
8
  private viewport;
8
9
  config: PanPluginConfig;
9
- private unregisterHandlers?;
10
- private unsubscribePanModeChange?;
10
+ private documentHandlers;
11
11
  constructor(id: string, registry: PluginRegistry, config: PanPluginConfig);
12
+ protected onDocumentLoadingStarted(documentId: string): void;
13
+ protected onDocumentClosed(documentId: string): void;
14
+ protected buildCapability(): PanCapability;
15
+ private createPanScope;
16
+ private getDocumentState;
17
+ private getDocumentStateOrThrow;
18
+ private enablePan;
19
+ private disablePan;
20
+ private togglePan;
21
+ private makePanDefault;
22
+ private isPanMode;
23
+ private registerPanHandlersForDocument;
24
+ onStoreUpdated(prevState: PanState, newState: PanState): void;
12
25
  initialize(_: PanPluginConfig): Promise<void>;
13
26
  destroy(): Promise<void>;
14
- private registerPanHandlers;
15
- private makePanDefault;
16
- protected buildCapability(): PanCapability;
17
27
  }