@embedpdf/plugin-history 2.0.0-next.1 → 2.0.0-next.2
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 +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/core"),e="history",o={id:e,name:"History Plugin",version:"1.0.0",provides:["history"],requires:[],optional:[],defaultConfig:{
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/core"),e="history",o={id:e,name:"History Plugin",version:"1.0.0",provides:["history"],requires:[],optional:[],defaultConfig:{}},n="HISTORY/INIT_STATE",i="HISTORY/CLEANUP_STATE",s="HISTORY/SET_DOCUMENT_STATE",c=class extends t.BasePlugin{constructor(e,o){super(e,o),this.documentHistories=new Map,this.historyChange$=t.createEmitter()}async initialize(t){this.logger.info("HistoryPlugin","Initialize","History plugin initialized")}onDocumentLoadingStarted(t){this.dispatch((t=>({type:n,payload:{documentId:t}}))(t)),this.documentHistories.set(t,{topicHistories:new Map,globalTimeline:[],globalIndex:-1}),this.logger.debug("HistoryPlugin","DocumentOpened",`Initialized history state for document: ${t}`)}onDocumentClosed(t){this.dispatch((t=>({type:i,payload:{documentId:t}}))(t)),this.documentHistories.delete(t),this.logger.debug("HistoryPlugin","DocumentClosed",`Cleaned up history state for document: ${t}`)}getDocumentHistoryData(t){const e=t??this.getActiveDocumentId(),o=this.documentHistories.get(e);if(!o)throw new Error(`History data not found for document: ${e}`);return o}getDocumentHistoryState(t){const e=this.documentHistories.get(t);if(!e)throw new Error(`History data not found for document: ${t}`);const o={};return Array.from(e.topicHistories.entries()).forEach(([t,e])=>{o[t]={canUndo:e.currentIndex>-1,canRedo:e.currentIndex<e.commands.length-1}}),{global:{canUndo:e.globalIndex>-1,canRedo:e.globalIndex<e.globalTimeline.length-1},topics:o}}emitHistoryChange(t,e){const o=this.getDocumentHistoryState(t);this.dispatch(((t,e)=>({type:s,payload:{documentId:t,state:e}}))(t,o)),this.historyChange$.emit({documentId:t,topic:e,state:o})}register(t,e,o){const n=this.getDocumentHistoryData(o);n.topicHistories.has(e)||n.topicHistories.set(e,{commands:[],currentIndex:-1});const i=n.topicHistories.get(e);i.commands.splice(i.currentIndex+1),i.commands.push(t),i.currentIndex++;const s={command:t,topic:e};n.globalTimeline.splice(n.globalIndex+1),n.globalTimeline.push(s),n.globalIndex++,t.execute(),this.emitHistoryChange(o,e)}undo(t,e){const o=this.getDocumentHistoryData(e);let n;if(t){const e=o.topicHistories.get(t);e&&e.currentIndex>-1&&(e.commands[e.currentIndex].undo(),e.currentIndex--,n=t)}else if(o.globalIndex>-1){const t=o.globalTimeline[o.globalIndex];t.command.undo(),o.topicHistories.get(t.topic).currentIndex--,o.globalIndex--,n=t.topic}n&&this.emitHistoryChange(e,n)}redo(t,e){const o=this.getDocumentHistoryData(e);let n;if(t){const e=o.topicHistories.get(t);e&&e.currentIndex<e.commands.length-1&&(e.currentIndex++,e.commands[e.currentIndex].execute(),n=t)}else if(o.globalIndex<o.globalTimeline.length-1){o.globalIndex++;const t=o.globalTimeline[o.globalIndex];t.command.execute(),o.topicHistories.get(t.topic).currentIndex++,n=t.topic}n&&this.emitHistoryChange(e,n)}canUndo(t,e){const o=this.getDocumentHistoryData(e);if(t){const e=o.topicHistories.get(t);return!!e&&e.currentIndex>-1}return o.globalIndex>-1}canRedo(t,e){const o=this.getDocumentHistoryData(e);if(t){const e=o.topicHistories.get(t);return!!e&&e.currentIndex<e.commands.length-1}return o.globalIndex<o.globalTimeline.length-1}createHistoryScope(t){return{register:(e,o)=>this.register(e,o,t),undo:e=>this.undo(e,t),redo:e=>this.redo(e,t),canUndo:e=>this.canUndo(e,t),canRedo:e=>this.canRedo(e,t),getHistoryState:()=>this.getDocumentHistoryState(t),onHistoryChange:e=>this.historyChange$.on(o=>{o.documentId===t&&e(o.topic)})}}buildCapability(){return{register:(t,e)=>{const o=this.getActiveDocumentId();this.register(t,e,o)},undo:t=>{const e=this.getActiveDocumentId();this.undo(t,e)},redo:t=>{const e=this.getActiveDocumentId();this.redo(t,e)},canUndo:t=>{const e=this.getActiveDocumentId();return this.canUndo(t,e)},canRedo:t=>{const e=this.getActiveDocumentId();return this.canRedo(t,e)},getHistoryState:()=>{const t=this.getActiveDocumentId();return this.getDocumentHistoryState(t)},forDocument:t=>this.createHistoryScope(t),onHistoryChange:this.historyChange$.on}}async destroy(){this.historyChange$.clear(),this.documentHistories.clear(),super.destroy()}};c.id="history";let r=c;const d={global:{canUndo:!1,canRedo:!1},topics:{}},a={documents:{},activeDocumentId:null},u={manifest:o,create:t=>new r(e,t),reducer:(t=a,e)=>{switch(e.type){case n:{const{documentId:o}=e.payload;return{...t,documents:{...t.documents,[o]:{...d}}}}case i:{const{documentId:o}=e.payload,{[o]:n,...i}=t.documents;return{...t,documents:i,activeDocumentId:t.activeDocumentId===o?null:t.activeDocumentId}}case s:{const{documentId:o,state:n}=e.payload;return t.documents[o]?{...t,documents:{...t.documents,[o]:n}}:t}case"HISTORY/SET_ACTIVE_DOCUMENT":return{...t,activeDocumentId:e.payload};default:return t}},initialState:a};exports.HISTORY_PLUGIN_ID=e,exports.HistoryPlugin=r,exports.HistoryPluginPackage=u,exports.manifest=o;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/history-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { HistoryPluginConfig } from './types';\n\nexport const HISTORY_PLUGIN_ID = 'history';\n\nexport const manifest: PluginManifest<HistoryPluginConfig> = {\n id: HISTORY_PLUGIN_ID,\n name: 'History Plugin',\n version: '1.0.0',\n provides: ['history'],\n requires: [],\n optional: [],\n defaultConfig: {\n enabled: true,\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { HistoryDocumentState } from './types';\n\n// Document lifecycle actions\nexport const INIT_HISTORY_STATE = 'HISTORY/INIT_STATE';\nexport const CLEANUP_HISTORY_STATE = 'HISTORY/CLEANUP_STATE';\n\n// History state updates\nexport const SET_HISTORY_DOCUMENT_STATE = 'HISTORY/SET_DOCUMENT_STATE';\nexport const SET_ACTIVE_HISTORY_DOCUMENT = 'HISTORY/SET_ACTIVE_DOCUMENT';\n\n// Document lifecycle action interfaces\nexport interface InitHistoryStateAction extends Action {\n type: typeof INIT_HISTORY_STATE;\n payload: {\n documentId: string;\n };\n}\n\nexport interface CleanupHistoryStateAction extends Action {\n type: typeof CLEANUP_HISTORY_STATE;\n payload: {\n documentId: string;\n };\n}\n\n// State update action interfaces\nexport interface SetHistoryDocumentStateAction extends Action {\n type: typeof SET_HISTORY_DOCUMENT_STATE;\n payload: {\n documentId: string;\n state: HistoryDocumentState;\n };\n}\n\nexport interface SetActiveHistoryDocumentAction extends Action {\n type: typeof SET_ACTIVE_HISTORY_DOCUMENT;\n payload: string | null; // documentId\n}\n\nexport type HistoryAction =\n | InitHistoryStateAction\n | CleanupHistoryStateAction\n | SetHistoryDocumentStateAction\n | SetActiveHistoryDocumentAction;\n\n// Action creators\nexport const initHistoryState = (documentId: string): InitHistoryStateAction => ({\n type: INIT_HISTORY_STATE,\n payload: { documentId },\n});\n\nexport const cleanupHistoryState = (documentId: string): CleanupHistoryStateAction => ({\n type: CLEANUP_HISTORY_STATE,\n payload: { documentId },\n});\n\nexport const setHistoryDocumentState = (\n documentId: string,\n state: HistoryDocumentState,\n): SetHistoryDocumentStateAction => ({\n type: SET_HISTORY_DOCUMENT_STATE,\n payload: { documentId, state },\n});\n\nexport const setActiveHistoryDocument = (\n documentId: string | null,\n): SetActiveHistoryDocumentAction => ({\n type: SET_ACTIVE_HISTORY_DOCUMENT,\n payload: documentId,\n});\n","import { BasePlugin, createEmitter, Listener, PluginRegistry } from '@embedpdf/core';\nimport {\n Command,\n HistoryCapability,\n HistoryChangeEvent,\n HistoryDocumentState,\n HistoryEntry,\n HistoryPluginConfig,\n HistoryScope,\n HistoryState,\n} from './types';\nimport {\n HistoryAction,\n initHistoryState,\n cleanupHistoryState,\n setHistoryDocumentState,\n} from './actions';\n\ninterface DocumentHistoryData {\n topicHistories: Map<string, { commands: Command[]; currentIndex: number }>;\n globalTimeline: HistoryEntry[];\n globalIndex: number;\n}\n\nexport class HistoryPlugin extends BasePlugin<\n HistoryPluginConfig,\n HistoryCapability,\n HistoryState,\n HistoryAction\n> {\n static readonly id = 'history' as const;\n\n // Per-document history data (persisted with state)\n private readonly documentHistories = new Map<string, DocumentHistoryData>();\n\n // Event emitter for history changes\n private readonly historyChange$ = createEmitter<HistoryChangeEvent>();\n\n constructor(id: string, registry: PluginRegistry) {\n super(id, registry);\n }\n\n async initialize(_: HistoryPluginConfig): Promise<void> {\n this.logger.info('HistoryPlugin', 'Initialize', 'History plugin initialized');\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n // Initialize history state for this document\n this.dispatch(initHistoryState(documentId));\n\n // Create document history data\n this.documentHistories.set(documentId, {\n topicHistories: new Map(),\n globalTimeline: [],\n globalIndex: -1,\n });\n\n this.logger.debug(\n 'HistoryPlugin',\n 'DocumentOpened',\n `Initialized history state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup history state\n this.dispatch(cleanupHistoryState(documentId));\n\n // Cleanup document history data\n this.documentHistories.delete(documentId);\n\n this.logger.debug(\n 'HistoryPlugin',\n 'DocumentClosed',\n `Cleaned up history state for document: ${documentId}`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Helper Methods\n // ─────────────────────────────────────────────────────────\n\n private getDocumentHistoryData(documentId?: string): DocumentHistoryData {\n const id = documentId ?? this.getActiveDocumentId();\n const data = this.documentHistories.get(id);\n if (!data) {\n throw new Error(`History data not found for document: ${id}`);\n }\n return data;\n }\n\n private getDocumentHistoryState(documentId: string): HistoryDocumentState {\n const data = this.documentHistories.get(documentId);\n if (!data) {\n throw new Error(`History data not found for document: ${documentId}`);\n }\n\n const topics: HistoryDocumentState['topics'] = {};\n Array.from(data.topicHistories.entries()).forEach(([topic, history]) => {\n topics[topic] = {\n canUndo: history.currentIndex > -1,\n canRedo: history.currentIndex < history.commands.length - 1,\n };\n });\n\n return {\n global: {\n canUndo: data.globalIndex > -1,\n canRedo: data.globalIndex < data.globalTimeline.length - 1,\n },\n topics,\n };\n }\n\n private emitHistoryChange(documentId: string, topic: string | undefined) {\n // Update the state\n const state = this.getDocumentHistoryState(documentId);\n this.dispatch(setHistoryDocumentState(documentId, state));\n\n // Emit the event\n this.historyChange$.emit({\n documentId,\n topic,\n state,\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // History Operations (per document)\n // ─────────────────────────────────────────────────────────\n\n private register(command: Command, topic: string, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n\n // 1. Manage Topic History\n if (!data.topicHistories.has(topic)) {\n data.topicHistories.set(topic, { commands: [], currentIndex: -1 });\n }\n const topicHistory = data.topicHistories.get(topic)!;\n topicHistory.commands.splice(topicHistory.currentIndex + 1);\n topicHistory.commands.push(command);\n topicHistory.currentIndex++;\n\n // 2. Manage Global History\n const historyEntry: HistoryEntry = { command, topic };\n data.globalTimeline.splice(data.globalIndex + 1);\n data.globalTimeline.push(historyEntry);\n data.globalIndex++;\n\n // 3. Execute and notify with the specific topic\n command.execute();\n this.emitHistoryChange(documentId, topic);\n }\n\n private undo(topic: string | undefined, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n let affectedTopic: string | undefined;\n\n if (topic) {\n // Scoped Undo\n const topicHistory = data.topicHistories.get(topic);\n if (topicHistory && topicHistory.currentIndex > -1) {\n topicHistory.commands[topicHistory.currentIndex].undo();\n topicHistory.currentIndex--;\n affectedTopic = topic;\n }\n } else {\n // Global Undo\n if (data.globalIndex > -1) {\n const entry = data.globalTimeline[data.globalIndex];\n entry.command.undo();\n data.topicHistories.get(entry.topic)!.currentIndex--;\n data.globalIndex--;\n affectedTopic = entry.topic;\n }\n }\n\n if (affectedTopic) {\n this.emitHistoryChange(documentId, affectedTopic);\n }\n }\n\n private redo(topic: string | undefined, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n let affectedTopic: string | undefined;\n\n if (topic) {\n // Scoped Redo\n const topicHistory = data.topicHistories.get(topic);\n if (topicHistory && topicHistory.currentIndex < topicHistory.commands.length - 1) {\n topicHistory.currentIndex++;\n topicHistory.commands[topicHistory.currentIndex].execute();\n affectedTopic = topic;\n }\n } else {\n // Global Redo\n if (data.globalIndex < data.globalTimeline.length - 1) {\n data.globalIndex++;\n const entry = data.globalTimeline[data.globalIndex];\n entry.command.execute();\n data.topicHistories.get(entry.topic)!.currentIndex++;\n affectedTopic = entry.topic;\n }\n }\n\n if (affectedTopic) {\n this.emitHistoryChange(documentId, affectedTopic);\n }\n }\n\n private canUndo(topic: string | undefined, documentId: string): boolean {\n const data = this.getDocumentHistoryData(documentId);\n\n if (topic) {\n const history = data.topicHistories.get(topic);\n return !!history && history.currentIndex > -1;\n }\n return data.globalIndex > -1;\n }\n\n private canRedo(topic: string | undefined, documentId: string): boolean {\n const data = this.getDocumentHistoryData(documentId);\n\n if (topic) {\n const history = data.topicHistories.get(topic);\n return !!history && history.currentIndex < history.commands.length - 1;\n }\n return data.globalIndex < data.globalTimeline.length - 1;\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createHistoryScope(documentId: string): HistoryScope {\n return {\n register: (command: Command, topic: string) => this.register(command, topic, documentId),\n undo: (topic?: string) => this.undo(topic, documentId),\n redo: (topic?: string) => this.redo(topic, documentId),\n canUndo: (topic?: string) => this.canUndo(topic, documentId),\n canRedo: (topic?: string) => this.canRedo(topic, documentId),\n getHistoryState: () => this.getDocumentHistoryState(documentId),\n onHistoryChange: (listener: Listener<string | undefined>) =>\n this.historyChange$.on((event) => {\n if (event.documentId === documentId) {\n listener(event.topic);\n }\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): HistoryCapability {\n return {\n // Active document operations\n register: (command: Command, topic: string) => {\n const documentId = this.getActiveDocumentId();\n this.register(command, topic, documentId);\n },\n\n undo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n this.undo(topic, documentId);\n },\n\n redo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n this.redo(topic, documentId);\n },\n\n canUndo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n return this.canUndo(topic, documentId);\n },\n\n canRedo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n return this.canRedo(topic, documentId);\n },\n\n getHistoryState: () => {\n const documentId = this.getActiveDocumentId();\n return this.getDocumentHistoryState(documentId);\n },\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createHistoryScope(documentId),\n\n // Events\n onHistoryChange: this.historyChange$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async destroy(): Promise<void> {\n // Clear all emitters\n this.historyChange$.clear();\n\n // Clear document histories\n this.documentHistories.clear();\n\n super.destroy();\n }\n}\n","import { Reducer } from '@embedpdf/core';\nimport {\n HistoryAction,\n INIT_HISTORY_STATE,\n CLEANUP_HISTORY_STATE,\n SET_HISTORY_DOCUMENT_STATE,\n SET_ACTIVE_HISTORY_DOCUMENT,\n} from './actions';\nimport { HistoryState, HistoryDocumentState } from './types';\n\nconst initialDocumentState: HistoryDocumentState = {\n global: {\n canUndo: false,\n canRedo: false,\n },\n topics: {},\n};\n\nexport const initialState: HistoryState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const reducer: Reducer<HistoryState, HistoryAction> = (state = initialState, action) => {\n switch (action.type) {\n case INIT_HISTORY_STATE: {\n const { documentId } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: { ...initialDocumentState },\n },\n };\n }\n\n case CLEANUP_HISTORY_STATE: {\n const { documentId } = action.payload;\n const { [documentId]: removed, ...remainingDocs } = state.documents;\n\n return {\n ...state,\n documents: remainingDocs,\n activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId,\n };\n }\n\n case SET_HISTORY_DOCUMENT_STATE: {\n const { documentId, state: docState } = action.payload;\n if (!state.documents[documentId]) {\n return state;\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n };\n }\n\n case SET_ACTIVE_HISTORY_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, HISTORY_PLUGIN_ID } from './manifest';\nimport { HistoryPluginConfig, HistoryState } from './types';\nimport { HistoryPlugin } from './history-plugin';\nimport { initialState, reducer } from './reducer';\nimport { HistoryAction } from './actions';\n\nexport const HistoryPluginPackage: PluginPackage<\n HistoryPlugin,\n HistoryPluginConfig,\n HistoryState,\n HistoryAction\n> = {\n manifest,\n create: (registry) => new HistoryPlugin(HISTORY_PLUGIN_ID, registry),\n reducer,\n initialState,\n};\n\nexport * from './history-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":["HISTORY_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","enabled","INIT_HISTORY_STATE","CLEANUP_HISTORY_STATE","SET_HISTORY_DOCUMENT_STATE","_HistoryPlugin","BasePlugin","constructor","registry","super","this","documentHistories","Map","historyChange$","createEmitter","initialize","_","logger","info","onDocumentLoadingStarted","documentId","dispatch","type","payload","initHistoryState","set","topicHistories","globalTimeline","globalIndex","debug","onDocumentClosed","cleanupHistoryState","delete","getDocumentHistoryData","getActiveDocumentId","data","get","Error","getDocumentHistoryState","topics","Array","from","entries","forEach","topic","history","canUndo","currentIndex","canRedo","commands","length","global","emitHistoryChange","state","setHistoryDocumentState","emit","register","command","has","topicHistory","splice","push","historyEntry","execute","undo","affectedTopic","entry","redo","createHistoryScope","getHistoryState","onHistoryChange","listener","on","event","buildCapability","forDocument","destroy","clear","HistoryPlugin","initialDocumentState","initialState","documents","activeDocumentId","HistoryPluginPackage","create","reducer","action","removed","remainingDocs","docState"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/history-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { HistoryPluginConfig } from './types';\n\nexport const HISTORY_PLUGIN_ID = 'history';\n\nexport const manifest: PluginManifest<HistoryPluginConfig> = {\n id: HISTORY_PLUGIN_ID,\n name: 'History Plugin',\n version: '1.0.0',\n provides: ['history'],\n requires: [],\n optional: [],\n defaultConfig: {},\n};\n","import { Action } from '@embedpdf/core';\nimport { HistoryDocumentState } from './types';\n\n// Document lifecycle actions\nexport const INIT_HISTORY_STATE = 'HISTORY/INIT_STATE';\nexport const CLEANUP_HISTORY_STATE = 'HISTORY/CLEANUP_STATE';\n\n// History state updates\nexport const SET_HISTORY_DOCUMENT_STATE = 'HISTORY/SET_DOCUMENT_STATE';\nexport const SET_ACTIVE_HISTORY_DOCUMENT = 'HISTORY/SET_ACTIVE_DOCUMENT';\n\n// Document lifecycle action interfaces\nexport interface InitHistoryStateAction extends Action {\n type: typeof INIT_HISTORY_STATE;\n payload: {\n documentId: string;\n };\n}\n\nexport interface CleanupHistoryStateAction extends Action {\n type: typeof CLEANUP_HISTORY_STATE;\n payload: {\n documentId: string;\n };\n}\n\n// State update action interfaces\nexport interface SetHistoryDocumentStateAction extends Action {\n type: typeof SET_HISTORY_DOCUMENT_STATE;\n payload: {\n documentId: string;\n state: HistoryDocumentState;\n };\n}\n\nexport interface SetActiveHistoryDocumentAction extends Action {\n type: typeof SET_ACTIVE_HISTORY_DOCUMENT;\n payload: string | null; // documentId\n}\n\nexport type HistoryAction =\n | InitHistoryStateAction\n | CleanupHistoryStateAction\n | SetHistoryDocumentStateAction\n | SetActiveHistoryDocumentAction;\n\n// Action creators\nexport const initHistoryState = (documentId: string): InitHistoryStateAction => ({\n type: INIT_HISTORY_STATE,\n payload: { documentId },\n});\n\nexport const cleanupHistoryState = (documentId: string): CleanupHistoryStateAction => ({\n type: CLEANUP_HISTORY_STATE,\n payload: { documentId },\n});\n\nexport const setHistoryDocumentState = (\n documentId: string,\n state: HistoryDocumentState,\n): SetHistoryDocumentStateAction => ({\n type: SET_HISTORY_DOCUMENT_STATE,\n payload: { documentId, state },\n});\n\nexport const setActiveHistoryDocument = (\n documentId: string | null,\n): SetActiveHistoryDocumentAction => ({\n type: SET_ACTIVE_HISTORY_DOCUMENT,\n payload: documentId,\n});\n","import { BasePlugin, createEmitter, Listener, PluginRegistry } from '@embedpdf/core';\nimport {\n Command,\n HistoryCapability,\n HistoryChangeEvent,\n HistoryDocumentState,\n HistoryEntry,\n HistoryPluginConfig,\n HistoryScope,\n HistoryState,\n} from './types';\nimport {\n HistoryAction,\n initHistoryState,\n cleanupHistoryState,\n setHistoryDocumentState,\n} from './actions';\n\ninterface DocumentHistoryData {\n topicHistories: Map<string, { commands: Command[]; currentIndex: number }>;\n globalTimeline: HistoryEntry[];\n globalIndex: number;\n}\n\nexport class HistoryPlugin extends BasePlugin<\n HistoryPluginConfig,\n HistoryCapability,\n HistoryState,\n HistoryAction\n> {\n static readonly id = 'history' as const;\n\n // Per-document history data (persisted with state)\n private readonly documentHistories = new Map<string, DocumentHistoryData>();\n\n // Event emitter for history changes\n private readonly historyChange$ = createEmitter<HistoryChangeEvent>();\n\n constructor(id: string, registry: PluginRegistry) {\n super(id, registry);\n }\n\n async initialize(_: HistoryPluginConfig): Promise<void> {\n this.logger.info('HistoryPlugin', 'Initialize', 'History plugin initialized');\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n // Initialize history state for this document\n this.dispatch(initHistoryState(documentId));\n\n // Create document history data\n this.documentHistories.set(documentId, {\n topicHistories: new Map(),\n globalTimeline: [],\n globalIndex: -1,\n });\n\n this.logger.debug(\n 'HistoryPlugin',\n 'DocumentOpened',\n `Initialized history state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup history state\n this.dispatch(cleanupHistoryState(documentId));\n\n // Cleanup document history data\n this.documentHistories.delete(documentId);\n\n this.logger.debug(\n 'HistoryPlugin',\n 'DocumentClosed',\n `Cleaned up history state for document: ${documentId}`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Helper Methods\n // ─────────────────────────────────────────────────────────\n\n private getDocumentHistoryData(documentId?: string): DocumentHistoryData {\n const id = documentId ?? this.getActiveDocumentId();\n const data = this.documentHistories.get(id);\n if (!data) {\n throw new Error(`History data not found for document: ${id}`);\n }\n return data;\n }\n\n private getDocumentHistoryState(documentId: string): HistoryDocumentState {\n const data = this.documentHistories.get(documentId);\n if (!data) {\n throw new Error(`History data not found for document: ${documentId}`);\n }\n\n const topics: HistoryDocumentState['topics'] = {};\n Array.from(data.topicHistories.entries()).forEach(([topic, history]) => {\n topics[topic] = {\n canUndo: history.currentIndex > -1,\n canRedo: history.currentIndex < history.commands.length - 1,\n };\n });\n\n return {\n global: {\n canUndo: data.globalIndex > -1,\n canRedo: data.globalIndex < data.globalTimeline.length - 1,\n },\n topics,\n };\n }\n\n private emitHistoryChange(documentId: string, topic: string | undefined) {\n // Update the state\n const state = this.getDocumentHistoryState(documentId);\n this.dispatch(setHistoryDocumentState(documentId, state));\n\n // Emit the event\n this.historyChange$.emit({\n documentId,\n topic,\n state,\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // History Operations (per document)\n // ─────────────────────────────────────────────────────────\n\n private register(command: Command, topic: string, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n\n // 1. Manage Topic History\n if (!data.topicHistories.has(topic)) {\n data.topicHistories.set(topic, { commands: [], currentIndex: -1 });\n }\n const topicHistory = data.topicHistories.get(topic)!;\n topicHistory.commands.splice(topicHistory.currentIndex + 1);\n topicHistory.commands.push(command);\n topicHistory.currentIndex++;\n\n // 2. Manage Global History\n const historyEntry: HistoryEntry = { command, topic };\n data.globalTimeline.splice(data.globalIndex + 1);\n data.globalTimeline.push(historyEntry);\n data.globalIndex++;\n\n // 3. Execute and notify with the specific topic\n command.execute();\n this.emitHistoryChange(documentId, topic);\n }\n\n private undo(topic: string | undefined, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n let affectedTopic: string | undefined;\n\n if (topic) {\n // Scoped Undo\n const topicHistory = data.topicHistories.get(topic);\n if (topicHistory && topicHistory.currentIndex > -1) {\n topicHistory.commands[topicHistory.currentIndex].undo();\n topicHistory.currentIndex--;\n affectedTopic = topic;\n }\n } else {\n // Global Undo\n if (data.globalIndex > -1) {\n const entry = data.globalTimeline[data.globalIndex];\n entry.command.undo();\n data.topicHistories.get(entry.topic)!.currentIndex--;\n data.globalIndex--;\n affectedTopic = entry.topic;\n }\n }\n\n if (affectedTopic) {\n this.emitHistoryChange(documentId, affectedTopic);\n }\n }\n\n private redo(topic: string | undefined, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n let affectedTopic: string | undefined;\n\n if (topic) {\n // Scoped Redo\n const topicHistory = data.topicHistories.get(topic);\n if (topicHistory && topicHistory.currentIndex < topicHistory.commands.length - 1) {\n topicHistory.currentIndex++;\n topicHistory.commands[topicHistory.currentIndex].execute();\n affectedTopic = topic;\n }\n } else {\n // Global Redo\n if (data.globalIndex < data.globalTimeline.length - 1) {\n data.globalIndex++;\n const entry = data.globalTimeline[data.globalIndex];\n entry.command.execute();\n data.topicHistories.get(entry.topic)!.currentIndex++;\n affectedTopic = entry.topic;\n }\n }\n\n if (affectedTopic) {\n this.emitHistoryChange(documentId, affectedTopic);\n }\n }\n\n private canUndo(topic: string | undefined, documentId: string): boolean {\n const data = this.getDocumentHistoryData(documentId);\n\n if (topic) {\n const history = data.topicHistories.get(topic);\n return !!history && history.currentIndex > -1;\n }\n return data.globalIndex > -1;\n }\n\n private canRedo(topic: string | undefined, documentId: string): boolean {\n const data = this.getDocumentHistoryData(documentId);\n\n if (topic) {\n const history = data.topicHistories.get(topic);\n return !!history && history.currentIndex < history.commands.length - 1;\n }\n return data.globalIndex < data.globalTimeline.length - 1;\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createHistoryScope(documentId: string): HistoryScope {\n return {\n register: (command: Command, topic: string) => this.register(command, topic, documentId),\n undo: (topic?: string) => this.undo(topic, documentId),\n redo: (topic?: string) => this.redo(topic, documentId),\n canUndo: (topic?: string) => this.canUndo(topic, documentId),\n canRedo: (topic?: string) => this.canRedo(topic, documentId),\n getHistoryState: () => this.getDocumentHistoryState(documentId),\n onHistoryChange: (listener: Listener<string | undefined>) =>\n this.historyChange$.on((event) => {\n if (event.documentId === documentId) {\n listener(event.topic);\n }\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): HistoryCapability {\n return {\n // Active document operations\n register: (command: Command, topic: string) => {\n const documentId = this.getActiveDocumentId();\n this.register(command, topic, documentId);\n },\n\n undo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n this.undo(topic, documentId);\n },\n\n redo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n this.redo(topic, documentId);\n },\n\n canUndo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n return this.canUndo(topic, documentId);\n },\n\n canRedo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n return this.canRedo(topic, documentId);\n },\n\n getHistoryState: () => {\n const documentId = this.getActiveDocumentId();\n return this.getDocumentHistoryState(documentId);\n },\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createHistoryScope(documentId),\n\n // Events\n onHistoryChange: this.historyChange$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async destroy(): Promise<void> {\n // Clear all emitters\n this.historyChange$.clear();\n\n // Clear document histories\n this.documentHistories.clear();\n\n super.destroy();\n }\n}\n","import { Reducer } from '@embedpdf/core';\nimport {\n HistoryAction,\n INIT_HISTORY_STATE,\n CLEANUP_HISTORY_STATE,\n SET_HISTORY_DOCUMENT_STATE,\n SET_ACTIVE_HISTORY_DOCUMENT,\n} from './actions';\nimport { HistoryState, HistoryDocumentState } from './types';\n\nconst initialDocumentState: HistoryDocumentState = {\n global: {\n canUndo: false,\n canRedo: false,\n },\n topics: {},\n};\n\nexport const initialState: HistoryState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const reducer: Reducer<HistoryState, HistoryAction> = (state = initialState, action) => {\n switch (action.type) {\n case INIT_HISTORY_STATE: {\n const { documentId } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: { ...initialDocumentState },\n },\n };\n }\n\n case CLEANUP_HISTORY_STATE: {\n const { documentId } = action.payload;\n const { [documentId]: removed, ...remainingDocs } = state.documents;\n\n return {\n ...state,\n documents: remainingDocs,\n activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId,\n };\n }\n\n case SET_HISTORY_DOCUMENT_STATE: {\n const { documentId, state: docState } = action.payload;\n if (!state.documents[documentId]) {\n return state;\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n };\n }\n\n case SET_ACTIVE_HISTORY_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, HISTORY_PLUGIN_ID } from './manifest';\nimport { HistoryPluginConfig, HistoryState } from './types';\nimport { HistoryPlugin } from './history-plugin';\nimport { initialState, reducer } from './reducer';\nimport { HistoryAction } from './actions';\n\nexport const HistoryPluginPackage: PluginPackage<\n HistoryPlugin,\n HistoryPluginConfig,\n HistoryState,\n HistoryAction\n> = {\n manifest,\n create: (registry) => new HistoryPlugin(HISTORY_PLUGIN_ID, registry),\n reducer,\n initialState,\n};\n\nexport * from './history-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":["HISTORY_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","INIT_HISTORY_STATE","CLEANUP_HISTORY_STATE","SET_HISTORY_DOCUMENT_STATE","_HistoryPlugin","BasePlugin","constructor","registry","super","this","documentHistories","Map","historyChange$","createEmitter","initialize","_","logger","info","onDocumentLoadingStarted","documentId","dispatch","type","payload","initHistoryState","set","topicHistories","globalTimeline","globalIndex","debug","onDocumentClosed","cleanupHistoryState","delete","getDocumentHistoryData","getActiveDocumentId","data","get","Error","getDocumentHistoryState","topics","Array","from","entries","forEach","topic","history","canUndo","currentIndex","canRedo","commands","length","global","emitHistoryChange","state","setHistoryDocumentState","emit","register","command","has","topicHistory","splice","push","historyEntry","execute","undo","affectedTopic","entry","redo","createHistoryScope","getHistoryState","onHistoryChange","listener","on","event","buildCapability","forDocument","destroy","clear","HistoryPlugin","initialDocumentState","initialState","documents","activeDocumentId","HistoryPluginPackage","create","reducer","action","removed","remainingDocs","docState"],"mappings":"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"}
|
package/dist/index.js
CHANGED
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/history-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { HistoryPluginConfig } from './types';\n\nexport const HISTORY_PLUGIN_ID = 'history';\n\nexport const manifest: PluginManifest<HistoryPluginConfig> = {\n id: HISTORY_PLUGIN_ID,\n name: 'History Plugin',\n version: '1.0.0',\n provides: ['history'],\n requires: [],\n optional: [],\n defaultConfig: {\n enabled: true,\n },\n};\n","import { Action } from '@embedpdf/core';\nimport { HistoryDocumentState } from './types';\n\n// Document lifecycle actions\nexport const INIT_HISTORY_STATE = 'HISTORY/INIT_STATE';\nexport const CLEANUP_HISTORY_STATE = 'HISTORY/CLEANUP_STATE';\n\n// History state updates\nexport const SET_HISTORY_DOCUMENT_STATE = 'HISTORY/SET_DOCUMENT_STATE';\nexport const SET_ACTIVE_HISTORY_DOCUMENT = 'HISTORY/SET_ACTIVE_DOCUMENT';\n\n// Document lifecycle action interfaces\nexport interface InitHistoryStateAction extends Action {\n type: typeof INIT_HISTORY_STATE;\n payload: {\n documentId: string;\n };\n}\n\nexport interface CleanupHistoryStateAction extends Action {\n type: typeof CLEANUP_HISTORY_STATE;\n payload: {\n documentId: string;\n };\n}\n\n// State update action interfaces\nexport interface SetHistoryDocumentStateAction extends Action {\n type: typeof SET_HISTORY_DOCUMENT_STATE;\n payload: {\n documentId: string;\n state: HistoryDocumentState;\n };\n}\n\nexport interface SetActiveHistoryDocumentAction extends Action {\n type: typeof SET_ACTIVE_HISTORY_DOCUMENT;\n payload: string | null; // documentId\n}\n\nexport type HistoryAction =\n | InitHistoryStateAction\n | CleanupHistoryStateAction\n | SetHistoryDocumentStateAction\n | SetActiveHistoryDocumentAction;\n\n// Action creators\nexport const initHistoryState = (documentId: string): InitHistoryStateAction => ({\n type: INIT_HISTORY_STATE,\n payload: { documentId },\n});\n\nexport const cleanupHistoryState = (documentId: string): CleanupHistoryStateAction => ({\n type: CLEANUP_HISTORY_STATE,\n payload: { documentId },\n});\n\nexport const setHistoryDocumentState = (\n documentId: string,\n state: HistoryDocumentState,\n): SetHistoryDocumentStateAction => ({\n type: SET_HISTORY_DOCUMENT_STATE,\n payload: { documentId, state },\n});\n\nexport const setActiveHistoryDocument = (\n documentId: string | null,\n): SetActiveHistoryDocumentAction => ({\n type: SET_ACTIVE_HISTORY_DOCUMENT,\n payload: documentId,\n});\n","import { BasePlugin, createEmitter, Listener, PluginRegistry } from '@embedpdf/core';\nimport {\n Command,\n HistoryCapability,\n HistoryChangeEvent,\n HistoryDocumentState,\n HistoryEntry,\n HistoryPluginConfig,\n HistoryScope,\n HistoryState,\n} from './types';\nimport {\n HistoryAction,\n initHistoryState,\n cleanupHistoryState,\n setHistoryDocumentState,\n} from './actions';\n\ninterface DocumentHistoryData {\n topicHistories: Map<string, { commands: Command[]; currentIndex: number }>;\n globalTimeline: HistoryEntry[];\n globalIndex: number;\n}\n\nexport class HistoryPlugin extends BasePlugin<\n HistoryPluginConfig,\n HistoryCapability,\n HistoryState,\n HistoryAction\n> {\n static readonly id = 'history' as const;\n\n // Per-document history data (persisted with state)\n private readonly documentHistories = new Map<string, DocumentHistoryData>();\n\n // Event emitter for history changes\n private readonly historyChange$ = createEmitter<HistoryChangeEvent>();\n\n constructor(id: string, registry: PluginRegistry) {\n super(id, registry);\n }\n\n async initialize(_: HistoryPluginConfig): Promise<void> {\n this.logger.info('HistoryPlugin', 'Initialize', 'History plugin initialized');\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n // Initialize history state for this document\n this.dispatch(initHistoryState(documentId));\n\n // Create document history data\n this.documentHistories.set(documentId, {\n topicHistories: new Map(),\n globalTimeline: [],\n globalIndex: -1,\n });\n\n this.logger.debug(\n 'HistoryPlugin',\n 'DocumentOpened',\n `Initialized history state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup history state\n this.dispatch(cleanupHistoryState(documentId));\n\n // Cleanup document history data\n this.documentHistories.delete(documentId);\n\n this.logger.debug(\n 'HistoryPlugin',\n 'DocumentClosed',\n `Cleaned up history state for document: ${documentId}`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Helper Methods\n // ─────────────────────────────────────────────────────────\n\n private getDocumentHistoryData(documentId?: string): DocumentHistoryData {\n const id = documentId ?? this.getActiveDocumentId();\n const data = this.documentHistories.get(id);\n if (!data) {\n throw new Error(`History data not found for document: ${id}`);\n }\n return data;\n }\n\n private getDocumentHistoryState(documentId: string): HistoryDocumentState {\n const data = this.documentHistories.get(documentId);\n if (!data) {\n throw new Error(`History data not found for document: ${documentId}`);\n }\n\n const topics: HistoryDocumentState['topics'] = {};\n Array.from(data.topicHistories.entries()).forEach(([topic, history]) => {\n topics[topic] = {\n canUndo: history.currentIndex > -1,\n canRedo: history.currentIndex < history.commands.length - 1,\n };\n });\n\n return {\n global: {\n canUndo: data.globalIndex > -1,\n canRedo: data.globalIndex < data.globalTimeline.length - 1,\n },\n topics,\n };\n }\n\n private emitHistoryChange(documentId: string, topic: string | undefined) {\n // Update the state\n const state = this.getDocumentHistoryState(documentId);\n this.dispatch(setHistoryDocumentState(documentId, state));\n\n // Emit the event\n this.historyChange$.emit({\n documentId,\n topic,\n state,\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // History Operations (per document)\n // ─────────────────────────────────────────────────────────\n\n private register(command: Command, topic: string, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n\n // 1. Manage Topic History\n if (!data.topicHistories.has(topic)) {\n data.topicHistories.set(topic, { commands: [], currentIndex: -1 });\n }\n const topicHistory = data.topicHistories.get(topic)!;\n topicHistory.commands.splice(topicHistory.currentIndex + 1);\n topicHistory.commands.push(command);\n topicHistory.currentIndex++;\n\n // 2. Manage Global History\n const historyEntry: HistoryEntry = { command, topic };\n data.globalTimeline.splice(data.globalIndex + 1);\n data.globalTimeline.push(historyEntry);\n data.globalIndex++;\n\n // 3. Execute and notify with the specific topic\n command.execute();\n this.emitHistoryChange(documentId, topic);\n }\n\n private undo(topic: string | undefined, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n let affectedTopic: string | undefined;\n\n if (topic) {\n // Scoped Undo\n const topicHistory = data.topicHistories.get(topic);\n if (topicHistory && topicHistory.currentIndex > -1) {\n topicHistory.commands[topicHistory.currentIndex].undo();\n topicHistory.currentIndex--;\n affectedTopic = topic;\n }\n } else {\n // Global Undo\n if (data.globalIndex > -1) {\n const entry = data.globalTimeline[data.globalIndex];\n entry.command.undo();\n data.topicHistories.get(entry.topic)!.currentIndex--;\n data.globalIndex--;\n affectedTopic = entry.topic;\n }\n }\n\n if (affectedTopic) {\n this.emitHistoryChange(documentId, affectedTopic);\n }\n }\n\n private redo(topic: string | undefined, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n let affectedTopic: string | undefined;\n\n if (topic) {\n // Scoped Redo\n const topicHistory = data.topicHistories.get(topic);\n if (topicHistory && topicHistory.currentIndex < topicHistory.commands.length - 1) {\n topicHistory.currentIndex++;\n topicHistory.commands[topicHistory.currentIndex].execute();\n affectedTopic = topic;\n }\n } else {\n // Global Redo\n if (data.globalIndex < data.globalTimeline.length - 1) {\n data.globalIndex++;\n const entry = data.globalTimeline[data.globalIndex];\n entry.command.execute();\n data.topicHistories.get(entry.topic)!.currentIndex++;\n affectedTopic = entry.topic;\n }\n }\n\n if (affectedTopic) {\n this.emitHistoryChange(documentId, affectedTopic);\n }\n }\n\n private canUndo(topic: string | undefined, documentId: string): boolean {\n const data = this.getDocumentHistoryData(documentId);\n\n if (topic) {\n const history = data.topicHistories.get(topic);\n return !!history && history.currentIndex > -1;\n }\n return data.globalIndex > -1;\n }\n\n private canRedo(topic: string | undefined, documentId: string): boolean {\n const data = this.getDocumentHistoryData(documentId);\n\n if (topic) {\n const history = data.topicHistories.get(topic);\n return !!history && history.currentIndex < history.commands.length - 1;\n }\n return data.globalIndex < data.globalTimeline.length - 1;\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createHistoryScope(documentId: string): HistoryScope {\n return {\n register: (command: Command, topic: string) => this.register(command, topic, documentId),\n undo: (topic?: string) => this.undo(topic, documentId),\n redo: (topic?: string) => this.redo(topic, documentId),\n canUndo: (topic?: string) => this.canUndo(topic, documentId),\n canRedo: (topic?: string) => this.canRedo(topic, documentId),\n getHistoryState: () => this.getDocumentHistoryState(documentId),\n onHistoryChange: (listener: Listener<string | undefined>) =>\n this.historyChange$.on((event) => {\n if (event.documentId === documentId) {\n listener(event.topic);\n }\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): HistoryCapability {\n return {\n // Active document operations\n register: (command: Command, topic: string) => {\n const documentId = this.getActiveDocumentId();\n this.register(command, topic, documentId);\n },\n\n undo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n this.undo(topic, documentId);\n },\n\n redo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n this.redo(topic, documentId);\n },\n\n canUndo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n return this.canUndo(topic, documentId);\n },\n\n canRedo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n return this.canRedo(topic, documentId);\n },\n\n getHistoryState: () => {\n const documentId = this.getActiveDocumentId();\n return this.getDocumentHistoryState(documentId);\n },\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createHistoryScope(documentId),\n\n // Events\n onHistoryChange: this.historyChange$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async destroy(): Promise<void> {\n // Clear all emitters\n this.historyChange$.clear();\n\n // Clear document histories\n this.documentHistories.clear();\n\n super.destroy();\n }\n}\n","import { Reducer } from '@embedpdf/core';\nimport {\n HistoryAction,\n INIT_HISTORY_STATE,\n CLEANUP_HISTORY_STATE,\n SET_HISTORY_DOCUMENT_STATE,\n SET_ACTIVE_HISTORY_DOCUMENT,\n} from './actions';\nimport { HistoryState, HistoryDocumentState } from './types';\n\nconst initialDocumentState: HistoryDocumentState = {\n global: {\n canUndo: false,\n canRedo: false,\n },\n topics: {},\n};\n\nexport const initialState: HistoryState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const reducer: Reducer<HistoryState, HistoryAction> = (state = initialState, action) => {\n switch (action.type) {\n case INIT_HISTORY_STATE: {\n const { documentId } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: { ...initialDocumentState },\n },\n };\n }\n\n case CLEANUP_HISTORY_STATE: {\n const { documentId } = action.payload;\n const { [documentId]: removed, ...remainingDocs } = state.documents;\n\n return {\n ...state,\n documents: remainingDocs,\n activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId,\n };\n }\n\n case SET_HISTORY_DOCUMENT_STATE: {\n const { documentId, state: docState } = action.payload;\n if (!state.documents[documentId]) {\n return state;\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n };\n }\n\n case SET_ACTIVE_HISTORY_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, HISTORY_PLUGIN_ID } from './manifest';\nimport { HistoryPluginConfig, HistoryState } from './types';\nimport { HistoryPlugin } from './history-plugin';\nimport { initialState, reducer } from './reducer';\nimport { HistoryAction } from './actions';\n\nexport const HistoryPluginPackage: PluginPackage<\n HistoryPlugin,\n HistoryPluginConfig,\n HistoryState,\n HistoryAction\n> = {\n manifest,\n create: (registry) => new HistoryPlugin(HISTORY_PLUGIN_ID, registry),\n reducer,\n initialState,\n};\n\nexport * from './history-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/history-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { HistoryPluginConfig } from './types';\n\nexport const HISTORY_PLUGIN_ID = 'history';\n\nexport const manifest: PluginManifest<HistoryPluginConfig> = {\n id: HISTORY_PLUGIN_ID,\n name: 'History Plugin',\n version: '1.0.0',\n provides: ['history'],\n requires: [],\n optional: [],\n defaultConfig: {},\n};\n","import { Action } from '@embedpdf/core';\nimport { HistoryDocumentState } from './types';\n\n// Document lifecycle actions\nexport const INIT_HISTORY_STATE = 'HISTORY/INIT_STATE';\nexport const CLEANUP_HISTORY_STATE = 'HISTORY/CLEANUP_STATE';\n\n// History state updates\nexport const SET_HISTORY_DOCUMENT_STATE = 'HISTORY/SET_DOCUMENT_STATE';\nexport const SET_ACTIVE_HISTORY_DOCUMENT = 'HISTORY/SET_ACTIVE_DOCUMENT';\n\n// Document lifecycle action interfaces\nexport interface InitHistoryStateAction extends Action {\n type: typeof INIT_HISTORY_STATE;\n payload: {\n documentId: string;\n };\n}\n\nexport interface CleanupHistoryStateAction extends Action {\n type: typeof CLEANUP_HISTORY_STATE;\n payload: {\n documentId: string;\n };\n}\n\n// State update action interfaces\nexport interface SetHistoryDocumentStateAction extends Action {\n type: typeof SET_HISTORY_DOCUMENT_STATE;\n payload: {\n documentId: string;\n state: HistoryDocumentState;\n };\n}\n\nexport interface SetActiveHistoryDocumentAction extends Action {\n type: typeof SET_ACTIVE_HISTORY_DOCUMENT;\n payload: string | null; // documentId\n}\n\nexport type HistoryAction =\n | InitHistoryStateAction\n | CleanupHistoryStateAction\n | SetHistoryDocumentStateAction\n | SetActiveHistoryDocumentAction;\n\n// Action creators\nexport const initHistoryState = (documentId: string): InitHistoryStateAction => ({\n type: INIT_HISTORY_STATE,\n payload: { documentId },\n});\n\nexport const cleanupHistoryState = (documentId: string): CleanupHistoryStateAction => ({\n type: CLEANUP_HISTORY_STATE,\n payload: { documentId },\n});\n\nexport const setHistoryDocumentState = (\n documentId: string,\n state: HistoryDocumentState,\n): SetHistoryDocumentStateAction => ({\n type: SET_HISTORY_DOCUMENT_STATE,\n payload: { documentId, state },\n});\n\nexport const setActiveHistoryDocument = (\n documentId: string | null,\n): SetActiveHistoryDocumentAction => ({\n type: SET_ACTIVE_HISTORY_DOCUMENT,\n payload: documentId,\n});\n","import { BasePlugin, createEmitter, Listener, PluginRegistry } from '@embedpdf/core';\nimport {\n Command,\n HistoryCapability,\n HistoryChangeEvent,\n HistoryDocumentState,\n HistoryEntry,\n HistoryPluginConfig,\n HistoryScope,\n HistoryState,\n} from './types';\nimport {\n HistoryAction,\n initHistoryState,\n cleanupHistoryState,\n setHistoryDocumentState,\n} from './actions';\n\ninterface DocumentHistoryData {\n topicHistories: Map<string, { commands: Command[]; currentIndex: number }>;\n globalTimeline: HistoryEntry[];\n globalIndex: number;\n}\n\nexport class HistoryPlugin extends BasePlugin<\n HistoryPluginConfig,\n HistoryCapability,\n HistoryState,\n HistoryAction\n> {\n static readonly id = 'history' as const;\n\n // Per-document history data (persisted with state)\n private readonly documentHistories = new Map<string, DocumentHistoryData>();\n\n // Event emitter for history changes\n private readonly historyChange$ = createEmitter<HistoryChangeEvent>();\n\n constructor(id: string, registry: PluginRegistry) {\n super(id, registry);\n }\n\n async initialize(_: HistoryPluginConfig): Promise<void> {\n this.logger.info('HistoryPlugin', 'Initialize', 'History plugin initialized');\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n // Initialize history state for this document\n this.dispatch(initHistoryState(documentId));\n\n // Create document history data\n this.documentHistories.set(documentId, {\n topicHistories: new Map(),\n globalTimeline: [],\n globalIndex: -1,\n });\n\n this.logger.debug(\n 'HistoryPlugin',\n 'DocumentOpened',\n `Initialized history state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup history state\n this.dispatch(cleanupHistoryState(documentId));\n\n // Cleanup document history data\n this.documentHistories.delete(documentId);\n\n this.logger.debug(\n 'HistoryPlugin',\n 'DocumentClosed',\n `Cleaned up history state for document: ${documentId}`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Helper Methods\n // ─────────────────────────────────────────────────────────\n\n private getDocumentHistoryData(documentId?: string): DocumentHistoryData {\n const id = documentId ?? this.getActiveDocumentId();\n const data = this.documentHistories.get(id);\n if (!data) {\n throw new Error(`History data not found for document: ${id}`);\n }\n return data;\n }\n\n private getDocumentHistoryState(documentId: string): HistoryDocumentState {\n const data = this.documentHistories.get(documentId);\n if (!data) {\n throw new Error(`History data not found for document: ${documentId}`);\n }\n\n const topics: HistoryDocumentState['topics'] = {};\n Array.from(data.topicHistories.entries()).forEach(([topic, history]) => {\n topics[topic] = {\n canUndo: history.currentIndex > -1,\n canRedo: history.currentIndex < history.commands.length - 1,\n };\n });\n\n return {\n global: {\n canUndo: data.globalIndex > -1,\n canRedo: data.globalIndex < data.globalTimeline.length - 1,\n },\n topics,\n };\n }\n\n private emitHistoryChange(documentId: string, topic: string | undefined) {\n // Update the state\n const state = this.getDocumentHistoryState(documentId);\n this.dispatch(setHistoryDocumentState(documentId, state));\n\n // Emit the event\n this.historyChange$.emit({\n documentId,\n topic,\n state,\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // History Operations (per document)\n // ─────────────────────────────────────────────────────────\n\n private register(command: Command, topic: string, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n\n // 1. Manage Topic History\n if (!data.topicHistories.has(topic)) {\n data.topicHistories.set(topic, { commands: [], currentIndex: -1 });\n }\n const topicHistory = data.topicHistories.get(topic)!;\n topicHistory.commands.splice(topicHistory.currentIndex + 1);\n topicHistory.commands.push(command);\n topicHistory.currentIndex++;\n\n // 2. Manage Global History\n const historyEntry: HistoryEntry = { command, topic };\n data.globalTimeline.splice(data.globalIndex + 1);\n data.globalTimeline.push(historyEntry);\n data.globalIndex++;\n\n // 3. Execute and notify with the specific topic\n command.execute();\n this.emitHistoryChange(documentId, topic);\n }\n\n private undo(topic: string | undefined, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n let affectedTopic: string | undefined;\n\n if (topic) {\n // Scoped Undo\n const topicHistory = data.topicHistories.get(topic);\n if (topicHistory && topicHistory.currentIndex > -1) {\n topicHistory.commands[topicHistory.currentIndex].undo();\n topicHistory.currentIndex--;\n affectedTopic = topic;\n }\n } else {\n // Global Undo\n if (data.globalIndex > -1) {\n const entry = data.globalTimeline[data.globalIndex];\n entry.command.undo();\n data.topicHistories.get(entry.topic)!.currentIndex--;\n data.globalIndex--;\n affectedTopic = entry.topic;\n }\n }\n\n if (affectedTopic) {\n this.emitHistoryChange(documentId, affectedTopic);\n }\n }\n\n private redo(topic: string | undefined, documentId: string): void {\n const data = this.getDocumentHistoryData(documentId);\n let affectedTopic: string | undefined;\n\n if (topic) {\n // Scoped Redo\n const topicHistory = data.topicHistories.get(topic);\n if (topicHistory && topicHistory.currentIndex < topicHistory.commands.length - 1) {\n topicHistory.currentIndex++;\n topicHistory.commands[topicHistory.currentIndex].execute();\n affectedTopic = topic;\n }\n } else {\n // Global Redo\n if (data.globalIndex < data.globalTimeline.length - 1) {\n data.globalIndex++;\n const entry = data.globalTimeline[data.globalIndex];\n entry.command.execute();\n data.topicHistories.get(entry.topic)!.currentIndex++;\n affectedTopic = entry.topic;\n }\n }\n\n if (affectedTopic) {\n this.emitHistoryChange(documentId, affectedTopic);\n }\n }\n\n private canUndo(topic: string | undefined, documentId: string): boolean {\n const data = this.getDocumentHistoryData(documentId);\n\n if (topic) {\n const history = data.topicHistories.get(topic);\n return !!history && history.currentIndex > -1;\n }\n return data.globalIndex > -1;\n }\n\n private canRedo(topic: string | undefined, documentId: string): boolean {\n const data = this.getDocumentHistoryData(documentId);\n\n if (topic) {\n const history = data.topicHistories.get(topic);\n return !!history && history.currentIndex < history.commands.length - 1;\n }\n return data.globalIndex < data.globalTimeline.length - 1;\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createHistoryScope(documentId: string): HistoryScope {\n return {\n register: (command: Command, topic: string) => this.register(command, topic, documentId),\n undo: (topic?: string) => this.undo(topic, documentId),\n redo: (topic?: string) => this.redo(topic, documentId),\n canUndo: (topic?: string) => this.canUndo(topic, documentId),\n canRedo: (topic?: string) => this.canRedo(topic, documentId),\n getHistoryState: () => this.getDocumentHistoryState(documentId),\n onHistoryChange: (listener: Listener<string | undefined>) =>\n this.historyChange$.on((event) => {\n if (event.documentId === documentId) {\n listener(event.topic);\n }\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): HistoryCapability {\n return {\n // Active document operations\n register: (command: Command, topic: string) => {\n const documentId = this.getActiveDocumentId();\n this.register(command, topic, documentId);\n },\n\n undo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n this.undo(topic, documentId);\n },\n\n redo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n this.redo(topic, documentId);\n },\n\n canUndo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n return this.canUndo(topic, documentId);\n },\n\n canRedo: (topic?: string) => {\n const documentId = this.getActiveDocumentId();\n return this.canRedo(topic, documentId);\n },\n\n getHistoryState: () => {\n const documentId = this.getActiveDocumentId();\n return this.getDocumentHistoryState(documentId);\n },\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createHistoryScope(documentId),\n\n // Events\n onHistoryChange: this.historyChange$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async destroy(): Promise<void> {\n // Clear all emitters\n this.historyChange$.clear();\n\n // Clear document histories\n this.documentHistories.clear();\n\n super.destroy();\n }\n}\n","import { Reducer } from '@embedpdf/core';\nimport {\n HistoryAction,\n INIT_HISTORY_STATE,\n CLEANUP_HISTORY_STATE,\n SET_HISTORY_DOCUMENT_STATE,\n SET_ACTIVE_HISTORY_DOCUMENT,\n} from './actions';\nimport { HistoryState, HistoryDocumentState } from './types';\n\nconst initialDocumentState: HistoryDocumentState = {\n global: {\n canUndo: false,\n canRedo: false,\n },\n topics: {},\n};\n\nexport const initialState: HistoryState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const reducer: Reducer<HistoryState, HistoryAction> = (state = initialState, action) => {\n switch (action.type) {\n case INIT_HISTORY_STATE: {\n const { documentId } = action.payload;\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: { ...initialDocumentState },\n },\n };\n }\n\n case CLEANUP_HISTORY_STATE: {\n const { documentId } = action.payload;\n const { [documentId]: removed, ...remainingDocs } = state.documents;\n\n return {\n ...state,\n documents: remainingDocs,\n activeDocumentId: state.activeDocumentId === documentId ? null : state.activeDocumentId,\n };\n }\n\n case SET_HISTORY_DOCUMENT_STATE: {\n const { documentId, state: docState } = action.payload;\n if (!state.documents[documentId]) {\n return state;\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: docState,\n },\n };\n }\n\n case SET_ACTIVE_HISTORY_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, HISTORY_PLUGIN_ID } from './manifest';\nimport { HistoryPluginConfig, HistoryState } from './types';\nimport { HistoryPlugin } from './history-plugin';\nimport { initialState, reducer } from './reducer';\nimport { HistoryAction } from './actions';\n\nexport const HistoryPluginPackage: PluginPackage<\n HistoryPlugin,\n HistoryPluginConfig,\n HistoryState,\n HistoryAction\n> = {\n manifest,\n create: (registry) => new HistoryPlugin(HISTORY_PLUGIN_ID, registry),\n reducer,\n initialState,\n};\n\nexport * from './history-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-history",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -35,13 +35,13 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@embedpdf/models": "2.0.0-next.
|
|
38
|
+
"@embedpdf/models": "2.0.0-next.2"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/react": "^18.2.0",
|
|
42
42
|
"typescript": "^5.0.0",
|
|
43
|
-
"@embedpdf/
|
|
44
|
-
"@embedpdf/
|
|
43
|
+
"@embedpdf/core": "2.0.0-next.2",
|
|
44
|
+
"@embedpdf/build": "1.1.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"react": ">=16.8.0",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"preact": "^10.26.4",
|
|
50
50
|
"vue": ">=3.2.0",
|
|
51
51
|
"svelte": ">=5 <6",
|
|
52
|
-
"@embedpdf/core": "2.0.0-next.
|
|
52
|
+
"@embedpdf/core": "2.0.0-next.2"
|
|
53
53
|
},
|
|
54
54
|
"files": [
|
|
55
55
|
"dist",
|