@embedpdf/plugin-redaction 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 +0 -1
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/models");var n=(e=>(e.MarqueeRedact="marqueeRedact",e.RedactSelection="redactSelection",e))(n||{});const i="REDACTION/INIT_STATE",o="REDACTION/CLEANUP_STATE",c="START_REDACTION",a="END_REDACTION",d="ADD_PENDING",s="REMOVE_PENDING",r="CLEAR_PENDING",l="SELECT_PENDING",u="DESELECT_PENDING";const g=(e,t)=>({type:d,payload:{documentId:e,items:t}}),m=(e,t,n)=>({type:s,payload:{documentId:e,page:t,id:n}}),h=e=>({type:r,payload:e}),p=(e,t)=>({type:c,payload:{documentId:e,mode:t}});const v=e=>Object.values(e).reduce((e,t)=>e+t.length,0),P={isRedacting:!1,activeType:null,pending:{},pendingCount:0,selected:null},I={documents:{},activeDocumentId:null},S=class extends e.BasePlugin{constructor(t,i,o){var c,d,s;super(t,i),this.redactionSelection$=new Map,this.pending$=e.createBehaviorEmitter(),this.selected$=e.createBehaviorEmitter(),this.state$=e.createBehaviorEmitter(),this.events$=e.createBehaviorEmitter(),this.documentUnsubscribers=new Map,this.config=o,this.selectionCapability=null==(c=this.registry.getPlugin("selection"))?void 0:c.provides(),this.interactionManagerCapability=null==(d=this.registry.getPlugin("interaction-manager"))?void 0:d.provides(),this.interactionManagerCapability&&(this.interactionManagerCapability.registerMode({id:n.MarqueeRedact,scope:"page",exclusive:!0,cursor:"crosshair"}),this.interactionManagerCapability.registerMode({id:n.RedactSelection,scope:"page",exclusive:!1})),null==(s=this.interactionManagerCapability)||s.onModeChange(e=>{const t=e.documentId;if(e.activeMode===n.RedactSelection)this.dispatch(p(t,n.RedactSelection));else if(e.activeMode===n.MarqueeRedact)this.dispatch(p(t,n.MarqueeRedact));else{const e=this.getDocumentState(t);(null==e?void 0:e.isRedacting)&&this.dispatch((e=>({type:a,payload:e}))(t))}})}onDocumentLoadingStarted(n){this.dispatch(function(e,t){return{type:i,payload:{documentId:e,state:t}}}(n,{...P})),this.redactionSelection$.set(n,e.createBehaviorEmitter());const o=[];if(this.selectionCapability){const e=this.selectionCapability.forDocument(n),i=e.onSelectionChange(()=>{const t=this.getDocumentState(n);if(!(null==t?void 0:t.isRedacting))return;const i=e.getFormattedSelection(),o=this.redactionSelection$.get(n);null==o||o.emit(i)}),c=e.onEndSelection(()=>{const i=this.getDocumentState(n);if(!(null==i?void 0:i.isRedacting))return;const o=e.getFormattedSelection().map(e=>({id:t.uuidV4(),kind:"text",page:e.pageIndex,rect:e.rect,rects:e.segmentRects}));this.dispatch(g(n,o));const c=this.redactionSelection$.get(n);null==c||c.emit([]),e.clear(),this.emitPendingChange(n),o.length&&this.selectPending(o[o.length-1].page,o[o.length-1].id,n)});o.push(i,c)}this.documentUnsubscribers.set(n,o),this.logger.debug("RedactionPlugin","DocumentOpened",`Initialized redaction state for document: ${n}`)}onDocumentLoaded(e){var t;null==(t=this.selectionCapability)||t.enableForMode(n.RedactSelection,e)}onDocumentClosed(e){this.dispatch(function(e){return{type:o,payload:e}}(e));const t=this.redactionSelection$.get(e);null==t||t.clear(),this.redactionSelection$.delete(e);const n=this.documentUnsubscribers.get(e);n&&(n.forEach(e=>e()),this.documentUnsubscribers.delete(e)),this.logger.debug("RedactionPlugin","DocumentClosed",`Cleaned up redaction state for document: ${e}`)}async initialize(e){this.logger.info("RedactionPlugin","Initialize","Redaction plugin initialized")}buildCapability(){return{queueCurrentSelectionAsPending:()=>this.queueCurrentSelectionAsPending(),enableMarqueeRedact:()=>this.enableMarqueeRedact(),toggleMarqueeRedact:()=>this.toggleMarqueeRedact(),isMarqueeRedactActive:()=>this.isMarqueeRedactActive(),enableRedactSelection:()=>this.enableRedactSelection(),toggleRedactSelection:()=>this.toggleRedactSelection(),isRedactSelectionActive:()=>this.isRedactSelectionActive(),addPending:e=>this.addPendingItems(e),removePending:(e,t)=>this.removePendingItem(e,t),clearPending:()=>this.clearPendingItems(),commitAllPending:()=>this.commitAllPending(),commitPending:(e,t)=>this.commitPendingOne(e,t),endRedaction:()=>this.endRedactionMode(),startRedaction:()=>this.startRedactionMode(),selectPending:(e,t)=>this.selectPending(e,t),getSelectedPending:()=>this.getSelectedPending(),deselectPending:()=>this.deselectPending(),getState:()=>this.getDocumentStateOrThrow(),forDocument:e=>this.createRedactionScope(e),onPendingChange:this.pending$.on,onSelectedChange:this.selected$.on,onRedactionEvent:this.events$.on,onStateChange:this.state$.on}}createRedactionScope(e){return{queueCurrentSelectionAsPending:()=>this.queueCurrentSelectionAsPending(e),enableMarqueeRedact:()=>this.enableMarqueeRedact(e),toggleMarqueeRedact:()=>this.toggleMarqueeRedact(e),isMarqueeRedactActive:()=>this.isMarqueeRedactActive(e),enableRedactSelection:()=>this.enableRedactSelection(e),toggleRedactSelection:()=>this.toggleRedactSelection(e),isRedactSelectionActive:()=>this.isRedactSelectionActive(e),addPending:t=>this.addPendingItems(t,e),removePending:(t,n)=>this.removePendingItem(t,n,e),clearPending:()=>this.clearPendingItems(e),commitAllPending:()=>this.commitAllPending(e),commitPending:(t,n)=>this.commitPendingOne(t,n,e),endRedaction:()=>this.endRedactionMode(e),startRedaction:()=>this.startRedactionMode(e),selectPending:(t,n)=>this.selectPending(t,n,e),getSelectedPending:()=>this.getSelectedPending(e),deselectPending:()=>this.deselectPending(e),getState:()=>this.getDocumentStateOrThrow(e),onPendingChange:t=>this.pending$.on(n=>{n.documentId===e&&t(n.pending)}),onSelectedChange:t=>this.selected$.on(n=>{n.documentId===e&&t(n.selected)}),onRedactionEvent:t=>this.events$.on(n=>{n.documentId===e&&t(n)}),onStateChange:t=>this.state$.on(n=>{n.documentId===e&&t(n.state)})}}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(`Redaction state not found for document: ${e??"active"}`);return t}addPendingItems(e,t){const n=t??this.getActiveDocumentId();this.dispatch(g(n,e)),this.emitPendingChange(n),this.events$.emit({type:"add",documentId:n,items:e})}removePendingItem(e,t,n){const i=n??this.getActiveDocumentId();this.dispatch(m(i,e,t)),this.emitPendingChange(i),this.events$.emit({type:"remove",documentId:i,page:e,id:t})}clearPendingItems(e){const t=e??this.getActiveDocumentId();this.dispatch(h(t)),this.emitPendingChange(t),this.events$.emit({type:"clear",documentId:t})}selectPending(e,t,n){var i;const o=n??this.getActiveDocumentId();this.dispatch(((e,t,n)=>({type:l,payload:{documentId:e,page:t,id:n}}))(o,e,t)),null==(i=this.selectionCapability)||i.forDocument(o).clear(),this.emitSelectedChange(o)}getSelectedPending(e){var t;const n=e??this.getActiveDocumentId();return(null==(t=this.getDocumentState(n))?void 0:t.selected)??null}deselectPending(e){const t=e??this.getActiveDocumentId();this.dispatch((e=>({type:u,payload:e}))(t)),this.emitSelectedChange(t)}enableRedactSelection(e){var t;const i=e??this.getActiveDocumentId();null==(t=this.interactionManagerCapability)||t.forDocument(i).activate(n.RedactSelection)}toggleRedactSelection(e){var t;const i=e??this.getActiveDocumentId(),o=null==(t=this.interactionManagerCapability)?void 0:t.forDocument(i);(null==o?void 0:o.getActiveMode())===n.RedactSelection?o.activateDefaultMode():null==o||o.activate(n.RedactSelection)}isRedactSelectionActive(e){var t;const i=e??this.getActiveDocumentId();return(null==(t=this.interactionManagerCapability)?void 0:t.forDocument(i).getActiveMode())===n.RedactSelection}enableMarqueeRedact(e){var t;const i=e??this.getActiveDocumentId();null==(t=this.interactionManagerCapability)||t.forDocument(i).activate(n.MarqueeRedact)}toggleMarqueeRedact(e){var t;const i=e??this.getActiveDocumentId(),o=null==(t=this.interactionManagerCapability)?void 0:t.forDocument(i);(null==o?void 0:o.getActiveMode())===n.MarqueeRedact?o.activateDefaultMode():null==o||o.activate(n.MarqueeRedact)}isMarqueeRedactActive(e){var t;const i=e??this.getActiveDocumentId();return(null==(t=this.interactionManagerCapability)?void 0:t.forDocument(i).getActiveMode())===n.MarqueeRedact}startRedactionMode(e){var t;const i=e??this.getActiveDocumentId();null==(t=this.interactionManagerCapability)||t.forDocument(i).activate(n.RedactSelection)}endRedactionMode(e){var t;const n=e??this.getActiveDocumentId();null==(t=this.interactionManagerCapability)||t.forDocument(n).activateDefaultMode()}onRedactionSelectionChange(e,t){const n=this.redactionSelection$.get(e);return(null==n?void 0:n.on(t))??(()=>{})}registerMarqueeOnPage(i){if(!this.interactionManagerCapability)return this.logger.warn("RedactionPlugin","MissingDependency","Interaction manager plugin not loaded, marquee redaction disabled"),()=>{};const o=this.coreState.core.documents[i.documentId];if(!(null==o?void 0:o.document))return this.logger.warn("RedactionPlugin","DocumentNotFound","Document not found"),()=>{};const c=o.document.pages[i.pageIndex];if(!c)return this.logger.warn("RedactionPlugin","PageNotFound",`Page ${i.pageIndex} not found`),()=>{};const a=function(t){const{pageSize:n,scale:i,minDragPx:o=5,onPreview:c,onCommit:a}=t;let d=null,s=null;return{onPointerDown:(e,t)=>{var n;d=e,s={origin:{x:e.x,y:e.y},size:{width:0,height:0}},null==c||c(s),null==(n=t.setPointerCapture)||n.call(t)},onPointerMove:t=>{if(!d)return;const i=e.clamp(t.x,0,n.width),o=e.clamp(t.y,0,n.height);s={origin:{x:Math.min(d.x,i),y:Math.min(d.y,o)},size:{width:Math.abs(i-d.x),height:Math.abs(o-d.y)}},null==c||c(s)},onPointerUp:(e,t)=>{var n;s&&Math.max(s.size.width,s.size.height)*i>o&&(null==a||a(s)),d=null,s=null,null==c||c(null),null==(n=t.releasePointerCapture)||n.call(t)},onPointerCancel:(e,t)=>{var n;d=null,s=null,null==c||c(null),null==(n=t.releasePointerCapture)||n.call(t)}}}({pageSize:c.size,scale:i.scale,onPreview:i.callback.onPreview,onCommit:e=>{var n,o;const c={id:t.uuidV4(),kind:"area",page:i.pageIndex,rect:e};this.dispatch(g(i.documentId,[c])),this.emitPendingChange(i.documentId),null==(o=(n=i.callback).onCommit)||o.call(n,e),this.enableRedactSelection(i.documentId),this.selectPending(i.pageIndex,c.id,i.documentId)}}),d=this.interactionManagerCapability.registerAlways({handlers:{onPointerDown:(e,t)=>{t.target===t.currentTarget&&this.deselectPending(i.documentId)}},scope:{type:"page",documentId:i.documentId,pageIndex:i.pageIndex}}),s=this.interactionManagerCapability.registerHandlers({documentId:i.documentId,modeId:n.MarqueeRedact,handlers:a,pageIndex:i.pageIndex});return()=>{d(),s()}}queueCurrentSelectionAsPending(e){const n=e??this.getActiveDocumentId();if(!this.selectionCapability)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"[RedactionPlugin] selection plugin required"});const i=this.coreState.core.documents[n];if(!(null==i?void 0:i.document))return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document not found"});const o=this.selectionCapability.forDocument(n),c=o.getFormattedSelection();if(!c.length)return t.PdfTaskHelper.resolve(!0);const a=t.uuidV4(),d=c.map(e=>({id:a,kind:"text",page:e.pageIndex,rect:e.rect,rects:e.segmentRects}));this.enableRedactSelection(n),this.dispatch(g(n,d)),this.emitPendingChange(n);const s=d[d.length-1];this.selectPending(s.page,s.id,n);const r=this.redactionSelection$.get(n);return null==r||r.emit([]),o.clear(),t.PdfTaskHelper.resolve(!0)}commitPendingOne(n,i,o){const c=o??this.getActiveDocumentId(),a=this.coreState.core.documents[c];if(!(null==a?void 0:a.document))return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document not found"});const d=this.getDocumentState(c);if(!d)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document state not found"});const s=(d.pending[n]??[]).find(e=>e.id===i);if(!s)return t.PdfTaskHelper.resolve(!0);const r="text"===s.kind?s.rects:[s.rect],l=a.document.pages[n];if(!l)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Page not found"});const u=new t.Task;return this.engine.redactTextInRects(a.document,l,r,{drawBlackBoxes:this.config.drawBlackBoxes}).wait(()=>{this.dispatch(m(c,n,i)),this.emitPendingChange(c),this.dispatchCoreAction(e.refreshPages(c,[n])),this.events$.emit({type:"commit",documentId:c,success:!0}),u.resolve(!0)},e=>{this.events$.emit({type:"commit",documentId:c,success:!1,error:e.reason}),u.reject({code:t.PdfErrorCode.Unknown,message:"Failed to commit redactions"})}),u}commitAllPending(n){const i=n??this.getActiveDocumentId(),o=this.coreState.core.documents[i];if(!(null==o?void 0:o.document))return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document not found"});const c=this.getDocumentState(i);if(!c)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document state not found"});const a=new Map;for(const[e,t]of Object.entries(c.pending)){const n=Number(e),i=a.get(n)??[];for(const e of t)"text"===e.kind?i.push(...e.rects):i.push(e.rect);a.set(n,i)}const d=Array.from(a.entries()).filter(([e,t])=>t.length>0).map(([e])=>e),s=[];for(const[e,t]of a){const n=o.document.pages[e];n&&(t.length&&s.push(this.engine.redactTextInRects(o.document,n,t,{drawBlackBoxes:this.config.drawBlackBoxes})))}const r=new t.Task;return t.Task.all(s).wait(()=>{this.dispatch(h(i)),this.dispatchCoreAction(e.refreshPages(i,d)),this.emitPendingChange(i),this.events$.emit({type:"commit",documentId:i,success:!0}),r.resolve(!0)},e=>{this.events$.emit({type:"commit",documentId:i,success:!1,error:e.reason}),r.reject({code:t.PdfErrorCode.Unknown,message:"Failed to commit redactions"})}),r}emitPendingChange(e){const t=this.getDocumentState(e);t&&this.pending$.emit({documentId:e,pending:t.pending})}emitSelectedChange(e){const t=this.getDocumentState(e);t&&this.selected$.emit({documentId:e,selected:t.selected})}emitStateChange(e){const t=this.getDocumentState(e);t&&this.state$.emit({documentId:e,state:t})}onStoreUpdated(e,t){for(const n in t.documents){t.documents[n]&&(this.emitPendingChange(n),this.emitSelectedChange(n),this.emitStateChange(n))}}async destroy(){this.pending$.clear(),this.selected$.clear(),this.state$.clear(),this.events$.clear(),this.redactionSelection$.forEach(e=>e.clear()),this.redactionSelection$.clear(),this.documentUnsubscribers.forEach(e=>{e.forEach(e=>e())}),this.documentUnsubscribers.clear(),await super.destroy()}};S.id="redaction";let f=S;const C="redaction",R={id:C,name:"Redaction Plugin",version:"1.0.0",provides:["redaction"],requires:[],optional:["interaction-manager","selection"],defaultConfig:{enabled:!0,drawBlackBoxes:!0}},D={manifest:R,create:(e,t)=>new f(C,e,t),reducer:(e=I,t)=>{switch(t.type){case i:{const{documentId:n,state:i}=t.payload;return{...e,documents:{...e.documents,[n]:i},activeDocumentId:e.activeDocumentId??n}}case o:{const n=t.payload,{[n]:i,...o}=e.documents;return{...e,documents:o,activeDocumentId:e.activeDocumentId===n?null:e.activeDocumentId}}case"REDACTION/SET_ACTIVE_DOCUMENT":return{...e,activeDocumentId:t.payload};case d:{const{documentId:n,items:i}=t.payload,o=e.documents[n];if(!o)return e;const c={...o.pending};for(const e of i)c[e.page]=(c[e.page]??[]).concat(e);return{...e,documents:{...e.documents,[n]:{...o,pending:c,pendingCount:v(c)}}}}case s:{const{documentId:n,page:i,id:o}=t.payload,c=e.documents[n];if(!c)return e;const a=(c.pending[i]??[]).filter(e=>e.id!==o),d={...c.pending,[i]:a},s=c.selected&&!(c.selected.page===i&&c.selected.id===o);return{...e,documents:{...e.documents,[n]:{...c,pending:d,pendingCount:v(d),selected:s?c.selected:null}}}}case r:{const n=t.payload,i=e.documents[n];return i?{...e,documents:{...e.documents,[n]:{...i,pending:{},pendingCount:0,selected:null}}}:e}case l:{const{documentId:n,page:i,id:o}=t.payload,c=e.documents[n];return c?{...e,documents:{...e.documents,[n]:{...c,selected:{page:i,id:o}}}}:e}case u:{const n=t.payload,i=e.documents[n];return i?{...e,documents:{...e.documents,[n]:{...i,selected:null}}}:e}case c:{const{documentId:n,mode:i}=t.payload,o=e.documents[n];return o?{...e,documents:{...e.documents,[n]:{...o,isRedacting:!0,activeType:i}}}:e}case a:{const n=t.payload,i=e.documents[n];return i?{...e,documents:{...e.documents,[n]:{...i,pending:{},pendingCount:0,selected:null,isRedacting:!1,activeType:null}}}:e}case"SET_ACTIVE_TYPE":{const{documentId:n,mode:i}=t.payload,o=e.documents[n];return o?{...e,documents:{...e.documents,[n]:{...o,activeType:i}}}:e}default:return e}},initialState:I};exports.REDACTION_PLUGIN_ID=C,exports.RedactionMode=n,exports.RedactionPlugin=f,exports.RedactionPluginPackage=D,exports.getDocumentPendingCount=(e,t)=>{var n;return(null==(n=e.documents[t])?void 0:n.pendingCount)??0},exports.getPendingRedactionsCount=e=>e.pendingCount,exports.getTotalPendingCount=e=>Object.values(e.documents).reduce((e,t)=>e+t.pendingCount,0),exports.hasPendingRedactions=e=>e.pendingCount>0,exports.initialDocumentState=P,exports.initialState=I,exports.manifest=R;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t=require("@embedpdf/models");var n=(e=>(e.MarqueeRedact="marqueeRedact",e.RedactSelection="redactSelection",e))(n||{});const i="REDACTION/INIT_STATE",o="REDACTION/CLEANUP_STATE",c="START_REDACTION",a="END_REDACTION",d="ADD_PENDING",s="REMOVE_PENDING",r="CLEAR_PENDING",l="SELECT_PENDING",u="DESELECT_PENDING";const g=(e,t)=>({type:d,payload:{documentId:e,items:t}}),m=(e,t,n)=>({type:s,payload:{documentId:e,page:t,id:n}}),h=e=>({type:r,payload:e}),p=(e,t)=>({type:c,payload:{documentId:e,mode:t}});const v=e=>Object.values(e).reduce((e,t)=>e+t.length,0),P={isRedacting:!1,activeType:null,pending:{},pendingCount:0,selected:null},I={documents:{},activeDocumentId:null},S=class extends e.BasePlugin{constructor(t,i,o){var c,d,s;super(t,i),this.redactionSelection$=new Map,this.pending$=e.createBehaviorEmitter(),this.selected$=e.createBehaviorEmitter(),this.state$=e.createBehaviorEmitter(),this.events$=e.createBehaviorEmitter(),this.documentUnsubscribers=new Map,this.config=o,this.selectionCapability=null==(c=this.registry.getPlugin("selection"))?void 0:c.provides(),this.interactionManagerCapability=null==(d=this.registry.getPlugin("interaction-manager"))?void 0:d.provides(),this.interactionManagerCapability&&(this.interactionManagerCapability.registerMode({id:n.MarqueeRedact,scope:"page",exclusive:!0,cursor:"crosshair"}),this.interactionManagerCapability.registerMode({id:n.RedactSelection,scope:"page",exclusive:!1})),null==(s=this.interactionManagerCapability)||s.onModeChange(e=>{const t=e.documentId;if(e.activeMode===n.RedactSelection)this.dispatch(p(t,n.RedactSelection));else if(e.activeMode===n.MarqueeRedact)this.dispatch(p(t,n.MarqueeRedact));else{const e=this.getDocumentState(t);(null==e?void 0:e.isRedacting)&&this.dispatch((e=>({type:a,payload:e}))(t))}})}onDocumentLoadingStarted(n){this.dispatch(function(e,t){return{type:i,payload:{documentId:e,state:t}}}(n,{...P})),this.redactionSelection$.set(n,e.createBehaviorEmitter());const o=[];if(this.selectionCapability){const e=this.selectionCapability.forDocument(n),i=e.onSelectionChange(()=>{const t=this.getDocumentState(n);if(!(null==t?void 0:t.isRedacting))return;const i=e.getFormattedSelection(),o=this.redactionSelection$.get(n);null==o||o.emit(i)}),c=e.onEndSelection(()=>{const i=this.getDocumentState(n);if(!(null==i?void 0:i.isRedacting))return;const o=e.getFormattedSelection().map(e=>({id:t.uuidV4(),kind:"text",page:e.pageIndex,rect:e.rect,rects:e.segmentRects}));this.dispatch(g(n,o));const c=this.redactionSelection$.get(n);null==c||c.emit([]),e.clear(),this.emitPendingChange(n),o.length&&this.selectPending(o[o.length-1].page,o[o.length-1].id,n)});o.push(i,c)}this.documentUnsubscribers.set(n,o),this.logger.debug("RedactionPlugin","DocumentOpened",`Initialized redaction state for document: ${n}`)}onDocumentLoaded(e){var t;null==(t=this.selectionCapability)||t.enableForMode(n.RedactSelection,e)}onDocumentClosed(e){this.dispatch(function(e){return{type:o,payload:e}}(e));const t=this.redactionSelection$.get(e);null==t||t.clear(),this.redactionSelection$.delete(e);const n=this.documentUnsubscribers.get(e);n&&(n.forEach(e=>e()),this.documentUnsubscribers.delete(e)),this.logger.debug("RedactionPlugin","DocumentClosed",`Cleaned up redaction state for document: ${e}`)}async initialize(e){this.logger.info("RedactionPlugin","Initialize","Redaction plugin initialized")}buildCapability(){return{queueCurrentSelectionAsPending:()=>this.queueCurrentSelectionAsPending(),enableMarqueeRedact:()=>this.enableMarqueeRedact(),toggleMarqueeRedact:()=>this.toggleMarqueeRedact(),isMarqueeRedactActive:()=>this.isMarqueeRedactActive(),enableRedactSelection:()=>this.enableRedactSelection(),toggleRedactSelection:()=>this.toggleRedactSelection(),isRedactSelectionActive:()=>this.isRedactSelectionActive(),addPending:e=>this.addPendingItems(e),removePending:(e,t)=>this.removePendingItem(e,t),clearPending:()=>this.clearPendingItems(),commitAllPending:()=>this.commitAllPending(),commitPending:(e,t)=>this.commitPendingOne(e,t),endRedaction:()=>this.endRedactionMode(),startRedaction:()=>this.startRedactionMode(),selectPending:(e,t)=>this.selectPending(e,t),getSelectedPending:()=>this.getSelectedPending(),deselectPending:()=>this.deselectPending(),getState:()=>this.getDocumentStateOrThrow(),forDocument:e=>this.createRedactionScope(e),onPendingChange:this.pending$.on,onSelectedChange:this.selected$.on,onRedactionEvent:this.events$.on,onStateChange:this.state$.on}}createRedactionScope(e){return{queueCurrentSelectionAsPending:()=>this.queueCurrentSelectionAsPending(e),enableMarqueeRedact:()=>this.enableMarqueeRedact(e),toggleMarqueeRedact:()=>this.toggleMarqueeRedact(e),isMarqueeRedactActive:()=>this.isMarqueeRedactActive(e),enableRedactSelection:()=>this.enableRedactSelection(e),toggleRedactSelection:()=>this.toggleRedactSelection(e),isRedactSelectionActive:()=>this.isRedactSelectionActive(e),addPending:t=>this.addPendingItems(t,e),removePending:(t,n)=>this.removePendingItem(t,n,e),clearPending:()=>this.clearPendingItems(e),commitAllPending:()=>this.commitAllPending(e),commitPending:(t,n)=>this.commitPendingOne(t,n,e),endRedaction:()=>this.endRedactionMode(e),startRedaction:()=>this.startRedactionMode(e),selectPending:(t,n)=>this.selectPending(t,n,e),getSelectedPending:()=>this.getSelectedPending(e),deselectPending:()=>this.deselectPending(e),getState:()=>this.getDocumentStateOrThrow(e),onPendingChange:t=>this.pending$.on(n=>{n.documentId===e&&t(n.pending)}),onSelectedChange:t=>this.selected$.on(n=>{n.documentId===e&&t(n.selected)}),onRedactionEvent:t=>this.events$.on(n=>{n.documentId===e&&t(n)}),onStateChange:t=>this.state$.on(n=>{n.documentId===e&&t(n.state)})}}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(`Redaction state not found for document: ${e??"active"}`);return t}addPendingItems(e,t){const n=t??this.getActiveDocumentId();this.dispatch(g(n,e)),this.emitPendingChange(n),this.events$.emit({type:"add",documentId:n,items:e})}removePendingItem(e,t,n){const i=n??this.getActiveDocumentId();this.dispatch(m(i,e,t)),this.emitPendingChange(i),this.events$.emit({type:"remove",documentId:i,page:e,id:t})}clearPendingItems(e){const t=e??this.getActiveDocumentId();this.dispatch(h(t)),this.emitPendingChange(t),this.events$.emit({type:"clear",documentId:t})}selectPending(e,t,n){var i;const o=n??this.getActiveDocumentId();this.dispatch(((e,t,n)=>({type:l,payload:{documentId:e,page:t,id:n}}))(o,e,t)),null==(i=this.selectionCapability)||i.forDocument(o).clear(),this.emitSelectedChange(o)}getSelectedPending(e){var t;const n=e??this.getActiveDocumentId();return(null==(t=this.getDocumentState(n))?void 0:t.selected)??null}deselectPending(e){const t=e??this.getActiveDocumentId();this.dispatch((e=>({type:u,payload:e}))(t)),this.emitSelectedChange(t)}enableRedactSelection(e){var t;const i=e??this.getActiveDocumentId();null==(t=this.interactionManagerCapability)||t.forDocument(i).activate(n.RedactSelection)}toggleRedactSelection(e){var t;const i=e??this.getActiveDocumentId(),o=null==(t=this.interactionManagerCapability)?void 0:t.forDocument(i);(null==o?void 0:o.getActiveMode())===n.RedactSelection?o.activateDefaultMode():null==o||o.activate(n.RedactSelection)}isRedactSelectionActive(e){var t;const i=e??this.getActiveDocumentId();return(null==(t=this.interactionManagerCapability)?void 0:t.forDocument(i).getActiveMode())===n.RedactSelection}enableMarqueeRedact(e){var t;const i=e??this.getActiveDocumentId();null==(t=this.interactionManagerCapability)||t.forDocument(i).activate(n.MarqueeRedact)}toggleMarqueeRedact(e){var t;const i=e??this.getActiveDocumentId(),o=null==(t=this.interactionManagerCapability)?void 0:t.forDocument(i);(null==o?void 0:o.getActiveMode())===n.MarqueeRedact?o.activateDefaultMode():null==o||o.activate(n.MarqueeRedact)}isMarqueeRedactActive(e){var t;const i=e??this.getActiveDocumentId();return(null==(t=this.interactionManagerCapability)?void 0:t.forDocument(i).getActiveMode())===n.MarqueeRedact}startRedactionMode(e){var t;const i=e??this.getActiveDocumentId();null==(t=this.interactionManagerCapability)||t.forDocument(i).activate(n.RedactSelection)}endRedactionMode(e){var t;const n=e??this.getActiveDocumentId();null==(t=this.interactionManagerCapability)||t.forDocument(n).activateDefaultMode()}onRedactionSelectionChange(e,t){const n=this.redactionSelection$.get(e);return(null==n?void 0:n.on(t))??(()=>{})}registerMarqueeOnPage(i){if(!this.interactionManagerCapability)return this.logger.warn("RedactionPlugin","MissingDependency","Interaction manager plugin not loaded, marquee redaction disabled"),()=>{};const o=this.coreState.core.documents[i.documentId];if(!(null==o?void 0:o.document))return this.logger.warn("RedactionPlugin","DocumentNotFound","Document not found"),()=>{};const c=o.document.pages[i.pageIndex];if(!c)return this.logger.warn("RedactionPlugin","PageNotFound",`Page ${i.pageIndex} not found`),()=>{};const a=function(t){const{pageSize:n,scale:i,minDragPx:o=5,onPreview:c,onCommit:a}=t;let d=null,s=null;return{onPointerDown:(e,t)=>{var n;d=e,s={origin:{x:e.x,y:e.y},size:{width:0,height:0}},null==c||c(s),null==(n=t.setPointerCapture)||n.call(t)},onPointerMove:t=>{if(!d)return;const i=e.clamp(t.x,0,n.width),o=e.clamp(t.y,0,n.height);s={origin:{x:Math.min(d.x,i),y:Math.min(d.y,o)},size:{width:Math.abs(i-d.x),height:Math.abs(o-d.y)}},null==c||c(s)},onPointerUp:(e,t)=>{var n;s&&Math.max(s.size.width,s.size.height)*i>o&&(null==a||a(s)),d=null,s=null,null==c||c(null),null==(n=t.releasePointerCapture)||n.call(t)},onPointerCancel:(e,t)=>{var n;d=null,s=null,null==c||c(null),null==(n=t.releasePointerCapture)||n.call(t)}}}({pageSize:c.size,scale:i.scale,onPreview:i.callback.onPreview,onCommit:e=>{var n,o;const c={id:t.uuidV4(),kind:"area",page:i.pageIndex,rect:e};this.dispatch(g(i.documentId,[c])),this.emitPendingChange(i.documentId),null==(o=(n=i.callback).onCommit)||o.call(n,e),this.enableRedactSelection(i.documentId),this.selectPending(i.pageIndex,c.id,i.documentId)}}),d=this.interactionManagerCapability.registerAlways({handlers:{onPointerDown:(e,t)=>{t.target===t.currentTarget&&this.deselectPending(i.documentId)}},scope:{type:"page",documentId:i.documentId,pageIndex:i.pageIndex}}),s=this.interactionManagerCapability.registerHandlers({documentId:i.documentId,modeId:n.MarqueeRedact,handlers:a,pageIndex:i.pageIndex});return()=>{d(),s()}}queueCurrentSelectionAsPending(e){const n=e??this.getActiveDocumentId();if(!this.selectionCapability)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"[RedactionPlugin] selection plugin required"});const i=this.coreState.core.documents[n];if(!(null==i?void 0:i.document))return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document not found"});const o=this.selectionCapability.forDocument(n),c=o.getFormattedSelection();if(!c.length)return t.PdfTaskHelper.resolve(!0);const a=t.uuidV4(),d=c.map(e=>({id:a,kind:"text",page:e.pageIndex,rect:e.rect,rects:e.segmentRects}));this.enableRedactSelection(n),this.dispatch(g(n,d)),this.emitPendingChange(n);const s=d[d.length-1];this.selectPending(s.page,s.id,n);const r=this.redactionSelection$.get(n);return null==r||r.emit([]),o.clear(),t.PdfTaskHelper.resolve(!0)}commitPendingOne(n,i,o){const c=o??this.getActiveDocumentId(),a=this.coreState.core.documents[c];if(!(null==a?void 0:a.document))return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document not found"});const d=this.getDocumentState(c);if(!d)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document state not found"});const s=(d.pending[n]??[]).find(e=>e.id===i);if(!s)return t.PdfTaskHelper.resolve(!0);const r="text"===s.kind?s.rects:[s.rect],l=a.document.pages[n];if(!l)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Page not found"});const u=new t.Task;return this.engine.redactTextInRects(a.document,l,r,{drawBlackBoxes:this.config.drawBlackBoxes}).wait(()=>{this.dispatch(m(c,n,i)),this.emitPendingChange(c),this.dispatchCoreAction(e.refreshPages(c,[n])),this.events$.emit({type:"commit",documentId:c,success:!0}),u.resolve(!0)},e=>{this.events$.emit({type:"commit",documentId:c,success:!1,error:e.reason}),u.reject({code:t.PdfErrorCode.Unknown,message:"Failed to commit redactions"})}),u}commitAllPending(n){const i=n??this.getActiveDocumentId(),o=this.coreState.core.documents[i];if(!(null==o?void 0:o.document))return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document not found"});const c=this.getDocumentState(i);if(!c)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document state not found"});const a=new Map;for(const[e,t]of Object.entries(c.pending)){const n=Number(e),i=a.get(n)??[];for(const e of t)"text"===e.kind?i.push(...e.rects):i.push(e.rect);a.set(n,i)}const d=Array.from(a.entries()).filter(([e,t])=>t.length>0).map(([e])=>e),s=[];for(const[e,t]of a){const n=o.document.pages[e];n&&(t.length&&s.push(this.engine.redactTextInRects(o.document,n,t,{drawBlackBoxes:this.config.drawBlackBoxes})))}const r=new t.Task;return t.Task.all(s).wait(()=>{this.dispatch(h(i)),this.dispatchCoreAction(e.refreshPages(i,d)),this.emitPendingChange(i),this.events$.emit({type:"commit",documentId:i,success:!0}),r.resolve(!0)},e=>{this.events$.emit({type:"commit",documentId:i,success:!1,error:e.reason}),r.reject({code:t.PdfErrorCode.Unknown,message:"Failed to commit redactions"})}),r}emitPendingChange(e){const t=this.getDocumentState(e);t&&this.pending$.emit({documentId:e,pending:t.pending})}emitSelectedChange(e){const t=this.getDocumentState(e);t&&this.selected$.emit({documentId:e,selected:t.selected})}emitStateChange(e){const t=this.getDocumentState(e);t&&this.state$.emit({documentId:e,state:t})}onStoreUpdated(e,t){for(const n in t.documents){t.documents[n]&&(this.emitPendingChange(n),this.emitSelectedChange(n),this.emitStateChange(n))}}async destroy(){this.pending$.clear(),this.selected$.clear(),this.state$.clear(),this.events$.clear(),this.redactionSelection$.forEach(e=>e.clear()),this.redactionSelection$.clear(),this.documentUnsubscribers.forEach(e=>{e.forEach(e=>e())}),this.documentUnsubscribers.clear(),await super.destroy()}};S.id="redaction";let f=S;const C="redaction",R={id:C,name:"Redaction Plugin",version:"1.0.0",provides:["redaction"],requires:[],optional:["interaction-manager","selection"],defaultConfig:{drawBlackBoxes:!0}},D={manifest:R,create:(e,t)=>new f(C,e,t),reducer:(e=I,t)=>{switch(t.type){case i:{const{documentId:n,state:i}=t.payload;return{...e,documents:{...e.documents,[n]:i},activeDocumentId:e.activeDocumentId??n}}case o:{const n=t.payload,{[n]:i,...o}=e.documents;return{...e,documents:o,activeDocumentId:e.activeDocumentId===n?null:e.activeDocumentId}}case"REDACTION/SET_ACTIVE_DOCUMENT":return{...e,activeDocumentId:t.payload};case d:{const{documentId:n,items:i}=t.payload,o=e.documents[n];if(!o)return e;const c={...o.pending};for(const e of i)c[e.page]=(c[e.page]??[]).concat(e);return{...e,documents:{...e.documents,[n]:{...o,pending:c,pendingCount:v(c)}}}}case s:{const{documentId:n,page:i,id:o}=t.payload,c=e.documents[n];if(!c)return e;const a=(c.pending[i]??[]).filter(e=>e.id!==o),d={...c.pending,[i]:a},s=c.selected&&!(c.selected.page===i&&c.selected.id===o);return{...e,documents:{...e.documents,[n]:{...c,pending:d,pendingCount:v(d),selected:s?c.selected:null}}}}case r:{const n=t.payload,i=e.documents[n];return i?{...e,documents:{...e.documents,[n]:{...i,pending:{},pendingCount:0,selected:null}}}:e}case l:{const{documentId:n,page:i,id:o}=t.payload,c=e.documents[n];return c?{...e,documents:{...e.documents,[n]:{...c,selected:{page:i,id:o}}}}:e}case u:{const n=t.payload,i=e.documents[n];return i?{...e,documents:{...e.documents,[n]:{...i,selected:null}}}:e}case c:{const{documentId:n,mode:i}=t.payload,o=e.documents[n];return o?{...e,documents:{...e.documents,[n]:{...o,isRedacting:!0,activeType:i}}}:e}case a:{const n=t.payload,i=e.documents[n];return i?{...e,documents:{...e.documents,[n]:{...i,pending:{},pendingCount:0,selected:null,isRedacting:!1,activeType:null}}}:e}case"SET_ACTIVE_TYPE":{const{documentId:n,mode:i}=t.payload,o=e.documents[n];return o?{...e,documents:{...e.documents,[n]:{...o,activeType:i}}}:e}default:return e}},initialState:I};exports.REDACTION_PLUGIN_ID=C,exports.RedactionMode=n,exports.RedactionPlugin=f,exports.RedactionPluginPackage=D,exports.getDocumentPendingCount=(e,t)=>{var n;return(null==(n=e.documents[t])?void 0:n.pendingCount)??0},exports.getPendingRedactionsCount=e=>e.pendingCount,exports.getTotalPendingCount=e=>Object.values(e.documents).reduce((e,t)=>e+t.pendingCount,0),exports.hasPendingRedactions=e=>e.pendingCount>0,exports.initialDocumentState=P,exports.initialState=I,exports.manifest=R;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/lib/types.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/redaction-plugin.ts","../src/lib/handlers/marquee-redact.handler.ts","../src/lib/manifest.ts","../src/lib/index.ts","../src/lib/selectors.ts"],"sourcesContent":["import { BasePluginConfig, EventHook } from '@embedpdf/core';\nimport { PdfErrorReason, Rect, Task } from '@embedpdf/models';\n\n// Redaction mode enum\nexport enum RedactionMode {\n MarqueeRedact = 'marqueeRedact',\n RedactSelection = 'redactSelection',\n}\n\nexport interface SelectedRedaction {\n page: number;\n id: string;\n}\n\n// Per-document redaction state\nexport interface RedactionDocumentState {\n isRedacting: boolean;\n activeType: RedactionMode | null;\n pending: Record<number, RedactionItem[]>;\n pendingCount: number;\n selected: SelectedRedaction | null;\n}\n\n// Plugin state\nexport interface RedactionState {\n documents: Record<string, RedactionDocumentState>;\n activeDocumentId: string | null;\n}\n\nexport type RedactionItem =\n | {\n id: string;\n kind: 'text';\n page: number;\n rect: Rect;\n rects: Rect[];\n }\n | {\n id: string;\n kind: 'area';\n page: number;\n rect: Rect;\n };\n\nexport interface MarqueeRedactCallback {\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n}\n\nexport interface RegisterMarqueeOnPageOptions {\n documentId: string;\n pageIndex: number;\n scale: number;\n callback: MarqueeRedactCallback;\n}\n\nexport interface RedactionPluginConfig extends BasePluginConfig {\n drawBlackBoxes: boolean;\n}\n\n// Events include documentId\nexport type RedactionEvent =\n | {\n type: 'add';\n documentId: string;\n items: RedactionItem[];\n }\n | {\n type: 'remove';\n documentId: string;\n page: number;\n id: string;\n }\n | {\n type: 'clear';\n documentId: string;\n }\n | {\n type: 'commit';\n documentId: string;\n success: boolean;\n error?: PdfErrorReason;\n };\n\nexport interface PendingChangeEvent {\n documentId: string;\n pending: Record<number, RedactionItem[]>;\n}\n\nexport interface SelectedChangeEvent {\n documentId: string;\n selected: SelectedRedaction | null;\n}\n\nexport interface StateChangeEvent {\n documentId: string;\n state: RedactionDocumentState;\n}\n\n// Scoped redaction capability\nexport interface RedactionScope {\n queueCurrentSelectionAsPending(): Task<boolean, PdfErrorReason>;\n\n enableMarqueeRedact(): void;\n toggleMarqueeRedact(): void;\n isMarqueeRedactActive(): boolean;\n\n enableRedactSelection(): void;\n toggleRedactSelection(): void;\n isRedactSelectionActive(): boolean;\n\n addPending(items: RedactionItem[]): void;\n removePending(page: number, id: string): void;\n clearPending(): void;\n commitAllPending(): Task<boolean, PdfErrorReason>;\n commitPending(page: number, id: string): Task<boolean, PdfErrorReason>;\n\n endRedaction(): void;\n startRedaction(): void;\n\n selectPending(page: number, id: string): void;\n getSelectedPending(): SelectedRedaction | null;\n deselectPending(): void;\n\n getState(): RedactionDocumentState;\n\n onPendingChange: EventHook<Record<number, RedactionItem[]>>;\n onSelectedChange: EventHook<SelectedRedaction | null>;\n onRedactionEvent: EventHook<RedactionEvent>;\n onStateChange: EventHook<RedactionDocumentState>;\n}\n\nexport interface RedactionCapability {\n // Active document operations\n queueCurrentSelectionAsPending(): Task<boolean, PdfErrorReason>;\n\n enableMarqueeRedact(): void;\n toggleMarqueeRedact(): void;\n isMarqueeRedactActive(): boolean;\n\n enableRedactSelection(): void;\n toggleRedactSelection(): void;\n isRedactSelectionActive(): boolean;\n\n addPending(items: RedactionItem[]): void;\n removePending(page: number, id: string): void;\n clearPending(): void;\n commitAllPending(): Task<boolean, PdfErrorReason>;\n commitPending(page: number, id: string): Task<boolean, PdfErrorReason>;\n\n endRedaction(): void;\n startRedaction(): void;\n\n selectPending(page: number, id: string): void;\n getSelectedPending(): SelectedRedaction | null;\n deselectPending(): void;\n\n getState(): RedactionDocumentState;\n\n // Document-scoped operations\n forDocument(documentId: string): RedactionScope;\n\n // Events (include documentId)\n onPendingChange: EventHook<PendingChangeEvent>;\n onSelectedChange: EventHook<SelectedChangeEvent>;\n onRedactionEvent: EventHook<RedactionEvent>;\n onStateChange: EventHook<StateChangeEvent>;\n}\n","import { Action } from '@embedpdf/core';\nimport { RedactionItem, RedactionMode, RedactionDocumentState } from './types';\n\n// Document lifecycle\nexport const INIT_REDACTION_STATE = 'REDACTION/INIT_STATE';\nexport const CLEANUP_REDACTION_STATE = 'REDACTION/CLEANUP_STATE';\nexport const SET_ACTIVE_DOCUMENT = 'REDACTION/SET_ACTIVE_DOCUMENT';\n\n// Per-document redaction operations\nexport const START_REDACTION = 'START_REDACTION';\nexport const END_REDACTION = 'END_REDACTION';\nexport const SET_ACTIVE_TYPE = 'SET_ACTIVE_TYPE';\n\nexport const ADD_PENDING = 'ADD_PENDING';\nexport const REMOVE_PENDING = 'REMOVE_PENDING';\nexport const CLEAR_PENDING = 'CLEAR_PENDING';\n\nexport const SELECT_PENDING = 'SELECT_PENDING';\nexport const DESELECT_PENDING = 'DESELECT_PENDING';\n\n// Document lifecycle actions\nexport interface InitRedactionStateAction extends Action {\n type: typeof INIT_REDACTION_STATE;\n payload: {\n documentId: string;\n state: RedactionDocumentState;\n };\n}\n\nexport interface CleanupRedactionStateAction extends Action {\n type: typeof CLEANUP_REDACTION_STATE;\n payload: string; // documentId\n}\n\nexport interface SetActiveDocumentAction extends Action {\n type: typeof SET_ACTIVE_DOCUMENT;\n payload: string | null; // documentId\n}\n\n// Per-document operation actions\nexport interface StartRedactionAction extends Action {\n type: typeof START_REDACTION;\n payload: {\n documentId: string;\n mode: RedactionMode;\n };\n}\n\nexport interface EndRedactionAction extends Action {\n type: typeof END_REDACTION;\n payload: string; // documentId\n}\n\nexport interface SetActiveTypeAction extends Action {\n type: typeof SET_ACTIVE_TYPE;\n payload: {\n documentId: string;\n mode: RedactionMode | null;\n };\n}\n\nexport interface AddPendingAction extends Action {\n type: typeof ADD_PENDING;\n payload: {\n documentId: string;\n items: RedactionItem[];\n };\n}\n\nexport interface RemovePendingAction extends Action {\n type: typeof REMOVE_PENDING;\n payload: {\n documentId: string;\n page: number;\n id: string;\n };\n}\n\nexport interface ClearPendingAction extends Action {\n type: typeof CLEAR_PENDING;\n payload: string; // documentId\n}\n\nexport interface SelectPendingAction extends Action {\n type: typeof SELECT_PENDING;\n payload: {\n documentId: string;\n page: number;\n id: string;\n };\n}\n\nexport interface DeselectPendingAction extends Action {\n type: typeof DESELECT_PENDING;\n payload: string; // documentId\n}\n\nexport type RedactionAction =\n | InitRedactionStateAction\n | CleanupRedactionStateAction\n | SetActiveDocumentAction\n | StartRedactionAction\n | EndRedactionAction\n | SetActiveTypeAction\n | AddPendingAction\n | RemovePendingAction\n | ClearPendingAction\n | SelectPendingAction\n | DeselectPendingAction;\n\n// Action Creators\n\nexport function initRedactionState(\n documentId: string,\n state: RedactionDocumentState,\n): InitRedactionStateAction {\n return { type: INIT_REDACTION_STATE, payload: { documentId, state } };\n}\n\nexport function cleanupRedactionState(documentId: string): CleanupRedactionStateAction {\n return { type: CLEANUP_REDACTION_STATE, payload: documentId };\n}\n\nexport function setActiveDocument(documentId: string | null): SetActiveDocumentAction {\n return { type: SET_ACTIVE_DOCUMENT, payload: documentId };\n}\n\nexport const addPending = (documentId: string, items: RedactionItem[]): AddPendingAction => ({\n type: ADD_PENDING,\n payload: { documentId, items },\n});\n\nexport const removePending = (\n documentId: string,\n page: number,\n id: string,\n): RemovePendingAction => ({\n type: REMOVE_PENDING,\n payload: { documentId, page, id },\n});\n\nexport const clearPending = (documentId: string): ClearPendingAction => ({\n type: CLEAR_PENDING,\n payload: documentId,\n});\n\nexport const startRedaction = (documentId: string, mode: RedactionMode): StartRedactionAction => ({\n type: START_REDACTION,\n payload: { documentId, mode },\n});\n\nexport const endRedaction = (documentId: string): EndRedactionAction => ({\n type: END_REDACTION,\n payload: documentId,\n});\n\nexport const setActiveType = (\n documentId: string,\n mode: RedactionMode | null,\n): SetActiveTypeAction => ({\n type: SET_ACTIVE_TYPE,\n payload: { documentId, mode },\n});\n\nexport const selectPending = (\n documentId: string,\n page: number,\n id: string,\n): SelectPendingAction => ({\n type: SELECT_PENDING,\n payload: { documentId, page, id },\n});\n\nexport const deselectPending = (documentId: string): DeselectPendingAction => ({\n type: DESELECT_PENDING,\n payload: documentId,\n});\n","import { Reducer } from '@embedpdf/core';\nimport { RedactionItem, RedactionState, RedactionDocumentState } from './types';\nimport {\n RedactionAction,\n INIT_REDACTION_STATE,\n CLEANUP_REDACTION_STATE,\n SET_ACTIVE_DOCUMENT,\n ADD_PENDING,\n CLEAR_PENDING,\n END_REDACTION,\n REMOVE_PENDING,\n START_REDACTION,\n SET_ACTIVE_TYPE,\n SELECT_PENDING,\n DESELECT_PENDING,\n} from './actions';\n\n// Helper function to calculate total pending count\nconst calculatePendingCount = (pending: Record<number, RedactionItem[]>): number => {\n return Object.values(pending).reduce((total, items) => total + items.length, 0);\n};\n\nexport const initialDocumentState: RedactionDocumentState = {\n isRedacting: false,\n activeType: null,\n pending: {},\n pendingCount: 0,\n selected: null,\n};\n\nexport const initialState: RedactionState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const redactionReducer: Reducer<RedactionState, RedactionAction> = (\n state = initialState,\n action,\n) => {\n switch (action.type) {\n case INIT_REDACTION_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_REDACTION_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_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n case ADD_PENDING: {\n const { documentId, items } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const next = { ...docState.pending };\n for (const item of items) {\n next[item.page] = (next[item.page] ?? []).concat(item);\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n pending: next,\n pendingCount: calculatePendingCount(next),\n },\n },\n };\n }\n\n case REMOVE_PENDING: {\n const { documentId, page, id } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const list = docState.pending[page] ?? [];\n const filtered = list.filter((it) => it.id !== id);\n const next = { ...docState.pending, [page]: filtered };\n\n // if the removed one was selected → clear selection\n const stillSelected =\n docState.selected && !(docState.selected.page === page && docState.selected.id === id);\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n pending: next,\n pendingCount: calculatePendingCount(next),\n selected: stillSelected ? docState.selected : null,\n },\n },\n };\n }\n\n case CLEAR_PENDING: {\n const documentId = 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 pending: {},\n pendingCount: 0,\n selected: null,\n },\n },\n };\n }\n\n case SELECT_PENDING: {\n const { documentId, page, id } = 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 selected: { page, id },\n },\n },\n };\n }\n\n case DESELECT_PENDING: {\n const documentId = 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 selected: null,\n },\n },\n };\n }\n\n case START_REDACTION: {\n const { documentId, mode } = 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 isRedacting: true,\n activeType: mode,\n },\n },\n };\n }\n\n case END_REDACTION: {\n const documentId = 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 pending: {},\n pendingCount: 0,\n selected: null,\n isRedacting: false,\n activeType: null,\n },\n },\n };\n }\n\n case SET_ACTIVE_TYPE: {\n const { documentId, mode } = 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 activeType: mode,\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import {\n RedactionPluginConfig,\n RedactionCapability,\n RedactionState,\n RegisterMarqueeOnPageOptions,\n RedactionItem,\n SelectedRedaction,\n RedactionMode,\n RedactionEvent,\n RedactionScope,\n StateChangeEvent,\n PendingChangeEvent,\n SelectedChangeEvent,\n RedactionDocumentState,\n} from './types';\nimport {\n BasePlugin,\n createBehaviorEmitter,\n PluginRegistry,\n refreshPages,\n Listener,\n} from '@embedpdf/core';\nimport {\n PdfErrorCode,\n PdfErrorReason,\n PdfTask,\n PdfTaskHelper,\n Rect,\n Task,\n uuidV4,\n} from '@embedpdf/models';\nimport {\n FormattedSelection,\n SelectionCapability,\n SelectionPlugin,\n} from '@embedpdf/plugin-selection';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport {\n addPending,\n clearPending,\n deselectPending,\n endRedaction,\n removePending,\n selectPending,\n startRedaction,\n initRedactionState,\n cleanupRedactionState,\n RedactionAction,\n} from './actions';\nimport { createMarqueeHandler } from './handlers';\nimport { initialDocumentState } from './reducer';\n\nexport class RedactionPlugin extends BasePlugin<\n RedactionPluginConfig,\n RedactionCapability,\n RedactionState,\n RedactionAction\n> {\n static readonly id = 'redaction' as const;\n\n private config: RedactionPluginConfig;\n private selectionCapability: SelectionCapability | undefined;\n private interactionManagerCapability: InteractionManagerCapability | undefined;\n\n // Per-document emitters\n private readonly redactionSelection$ = new Map<\n string,\n ReturnType<typeof createBehaviorEmitter<FormattedSelection[]>>\n >();\n\n // Global emitters with documentId\n private readonly pending$ = createBehaviorEmitter<PendingChangeEvent>();\n private readonly selected$ = createBehaviorEmitter<SelectedChangeEvent>();\n private readonly state$ = createBehaviorEmitter<StateChangeEvent>();\n private readonly events$ = createBehaviorEmitter<RedactionEvent>();\n\n // Per-document unsubscribe functions\n private readonly documentUnsubscribers = new Map<string, Array<() => void>>();\n\n constructor(id: string, registry: PluginRegistry, config: RedactionPluginConfig) {\n super(id, registry);\n this.config = config;\n\n this.selectionCapability = this.registry.getPlugin<SelectionPlugin>('selection')?.provides();\n this.interactionManagerCapability = this.registry\n .getPlugin<InteractionManagerPlugin>('interaction-manager')\n ?.provides();\n\n if (this.interactionManagerCapability) {\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.MarqueeRedact,\n scope: 'page',\n exclusive: true,\n cursor: 'crosshair',\n });\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.RedactSelection,\n scope: 'page',\n exclusive: false,\n });\n }\n\n // Listen to mode changes per document\n this.interactionManagerCapability?.onModeChange((modeState) => {\n const documentId = modeState.documentId;\n\n if (modeState.activeMode === RedactionMode.RedactSelection) {\n this.dispatch(startRedaction(documentId, RedactionMode.RedactSelection));\n } else if (modeState.activeMode === RedactionMode.MarqueeRedact) {\n this.dispatch(startRedaction(documentId, RedactionMode.MarqueeRedact));\n } else {\n const docState = this.getDocumentState(documentId);\n if (docState?.isRedacting) {\n this.dispatch(endRedaction(documentId));\n }\n }\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle Hooks (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n // Initialize state for this document\n this.dispatch(\n initRedactionState(documentId, {\n ...initialDocumentState,\n }),\n );\n\n // Create per-document emitter\n this.redactionSelection$.set(documentId, createBehaviorEmitter<FormattedSelection[]>());\n // Setup selection listeners for this document\n const unsubscribers: Array<() => void> = [];\n\n if (this.selectionCapability) {\n const selectionScope = this.selectionCapability.forDocument(documentId);\n\n // Listen to selection changes\n const unsubSelection = selectionScope.onSelectionChange(() => {\n const docState = this.getDocumentState(documentId);\n if (!docState?.isRedacting) return;\n\n const formattedSelection = selectionScope.getFormattedSelection();\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.emit(formattedSelection);\n });\n\n // Listen to end selection\n const unsubEndSelection = selectionScope.onEndSelection(() => {\n const docState = this.getDocumentState(documentId);\n if (!docState?.isRedacting) return;\n\n const formattedSelection = selectionScope.getFormattedSelection();\n\n const items: RedactionItem[] = formattedSelection.map((s) => ({\n id: uuidV4(),\n kind: 'text',\n page: s.pageIndex,\n rect: s.rect,\n rects: s.segmentRects,\n }));\n\n this.dispatch(addPending(documentId, items));\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.emit([]);\n selectionScope.clear();\n\n this.emitPendingChange(documentId);\n\n if (items.length) {\n this.selectPending(items[items.length - 1].page, items[items.length - 1].id, documentId);\n }\n });\n\n unsubscribers.push(unsubSelection, unsubEndSelection);\n }\n\n this.documentUnsubscribers.set(documentId, unsubscribers);\n\n this.logger.debug(\n 'RedactionPlugin',\n 'DocumentOpened',\n `Initialized redaction state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentLoaded(documentId: string): void {\n this.selectionCapability?.enableForMode(RedactionMode.RedactSelection, documentId);\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup state\n this.dispatch(cleanupRedactionState(documentId));\n\n // Cleanup emitters\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.clear();\n this.redactionSelection$.delete(documentId);\n\n // Cleanup unsubscribers\n const unsubscribers = this.documentUnsubscribers.get(documentId);\n if (unsubscribers) {\n unsubscribers.forEach((unsub) => unsub());\n this.documentUnsubscribers.delete(documentId);\n }\n\n this.logger.debug(\n 'RedactionPlugin',\n 'DocumentClosed',\n `Cleaned up redaction state for document: ${documentId}`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n async initialize(_config: RedactionPluginConfig): Promise<void> {\n this.logger.info('RedactionPlugin', 'Initialize', 'Redaction plugin initialized');\n }\n\n protected buildCapability(): RedactionCapability {\n return {\n // Active document operations\n queueCurrentSelectionAsPending: () => this.queueCurrentSelectionAsPending(),\n\n enableMarqueeRedact: () => this.enableMarqueeRedact(),\n toggleMarqueeRedact: () => this.toggleMarqueeRedact(),\n isMarqueeRedactActive: () => this.isMarqueeRedactActive(),\n\n enableRedactSelection: () => this.enableRedactSelection(),\n toggleRedactSelection: () => this.toggleRedactSelection(),\n isRedactSelectionActive: () => this.isRedactSelectionActive(),\n\n addPending: (items) => this.addPendingItems(items),\n removePending: (page, id) => this.removePendingItem(page, id),\n clearPending: () => this.clearPendingItems(),\n commitAllPending: () => this.commitAllPending(),\n commitPending: (page, id) => this.commitPendingOne(page, id),\n\n endRedaction: () => this.endRedactionMode(),\n startRedaction: () => this.startRedactionMode(),\n\n selectPending: (page, id) => this.selectPending(page, id),\n getSelectedPending: () => this.getSelectedPending(),\n deselectPending: () => this.deselectPending(),\n\n getState: () => this.getDocumentStateOrThrow(),\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createRedactionScope(documentId),\n\n // Events\n onPendingChange: this.pending$.on,\n onSelectedChange: this.selected$.on,\n onRedactionEvent: this.events$.on,\n onStateChange: this.state$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createRedactionScope(documentId: string): RedactionScope {\n return {\n queueCurrentSelectionAsPending: () => this.queueCurrentSelectionAsPending(documentId),\n\n enableMarqueeRedact: () => this.enableMarqueeRedact(documentId),\n toggleMarqueeRedact: () => this.toggleMarqueeRedact(documentId),\n isMarqueeRedactActive: () => this.isMarqueeRedactActive(documentId),\n\n enableRedactSelection: () => this.enableRedactSelection(documentId),\n toggleRedactSelection: () => this.toggleRedactSelection(documentId),\n isRedactSelectionActive: () => this.isRedactSelectionActive(documentId),\n\n addPending: (items) => this.addPendingItems(items, documentId),\n removePending: (page, id) => this.removePendingItem(page, id, documentId),\n clearPending: () => this.clearPendingItems(documentId),\n commitAllPending: () => this.commitAllPending(documentId),\n commitPending: (page, id) => this.commitPendingOne(page, id, documentId),\n\n endRedaction: () => this.endRedactionMode(documentId),\n startRedaction: () => this.startRedactionMode(documentId),\n\n selectPending: (page, id) => this.selectPending(page, id, documentId),\n getSelectedPending: () => this.getSelectedPending(documentId),\n deselectPending: () => this.deselectPending(documentId),\n\n getState: () => this.getDocumentStateOrThrow(documentId),\n\n onPendingChange: (listener: Listener<Record<number, RedactionItem[]>>) =>\n this.pending$.on((event) => {\n if (event.documentId === documentId) listener(event.pending);\n }),\n onSelectedChange: (listener: Listener<SelectedRedaction | null>) =>\n this.selected$.on((event) => {\n if (event.documentId === documentId) listener(event.selected);\n }),\n onRedactionEvent: (listener: Listener<RedactionEvent>) =>\n this.events$.on((event) => {\n if (event.documentId === documentId) listener(event);\n }),\n onStateChange: (listener: Listener<RedactionDocumentState>) =>\n this.state$.on((event) => {\n if (event.documentId === documentId) listener(event.state);\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // State Helpers\n // ─────────────────────────────────────────────────────────\n\n private getDocumentState(documentId?: string): RedactionDocumentState | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.state.documents[id] ?? null;\n }\n\n private getDocumentStateOrThrow(documentId?: string): RedactionDocumentState {\n const state = this.getDocumentState(documentId);\n if (!state) {\n throw new Error(`Redaction state not found for document: ${documentId ?? 'active'}`);\n }\n return state;\n }\n\n // ─────────────────────────────────────────────────────────\n // Core Operations\n // ─────────────────────────────────────────────────────────\n\n private addPendingItems(items: RedactionItem[], documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(addPending(id, items));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'add', documentId: id, items });\n }\n\n private removePendingItem(page: number, itemId: string, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(removePending(id, page, itemId));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'remove', documentId: id, page, id: itemId });\n }\n\n private clearPendingItems(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(clearPending(id));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'clear', documentId: id });\n }\n\n private selectPending(page: number, itemId: string, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(selectPending(id, page, itemId));\n this.selectionCapability?.forDocument(id).clear();\n this.emitSelectedChange(id);\n }\n\n private getSelectedPending(documentId?: string): SelectedRedaction | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.getDocumentState(id)?.selected ?? null;\n }\n\n private deselectPending(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(deselectPending(id));\n this.emitSelectedChange(id);\n }\n\n private enableRedactSelection(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.RedactSelection);\n }\n\n private toggleRedactSelection(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManagerCapability?.forDocument(id);\n if (scope?.getActiveMode() === RedactionMode.RedactSelection) {\n scope.activateDefaultMode();\n } else {\n scope?.activate(RedactionMode.RedactSelection);\n }\n }\n\n private isRedactSelectionActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return (\n this.interactionManagerCapability?.forDocument(id).getActiveMode() ===\n RedactionMode.RedactSelection\n );\n }\n\n private enableMarqueeRedact(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.MarqueeRedact);\n }\n\n private toggleMarqueeRedact(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManagerCapability?.forDocument(id);\n if (scope?.getActiveMode() === RedactionMode.MarqueeRedact) {\n scope.activateDefaultMode();\n } else {\n scope?.activate(RedactionMode.MarqueeRedact);\n }\n }\n\n private isMarqueeRedactActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return (\n this.interactionManagerCapability?.forDocument(id).getActiveMode() ===\n RedactionMode.MarqueeRedact\n );\n }\n\n private startRedactionMode(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.RedactSelection);\n }\n\n private endRedactionMode(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activateDefaultMode();\n }\n\n // ─────────────────────────────────────────────────────────\n // Public Methods\n // ─────────────────────────────────────────────────────────\n\n public onRedactionSelectionChange(\n documentId: string,\n callback: (formattedSelection: FormattedSelection[]) => void,\n ) {\n const emitter = this.redactionSelection$.get(documentId);\n return emitter?.on(callback) ?? (() => {});\n }\n\n public registerMarqueeOnPage(opts: RegisterMarqueeOnPageOptions) {\n if (!this.interactionManagerCapability) {\n this.logger.warn(\n 'RedactionPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, marquee redaction disabled',\n );\n return () => {};\n }\n\n const coreDoc = this.coreState.core.documents[opts.documentId];\n if (!coreDoc?.document) {\n this.logger.warn('RedactionPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = coreDoc.document.pages[opts.pageIndex];\n if (!page) {\n this.logger.warn('RedactionPlugin', 'PageNotFound', `Page ${opts.pageIndex} not found`);\n return () => {};\n }\n\n const handlers = createMarqueeHandler({\n pageSize: page.size,\n scale: opts.scale,\n onPreview: opts.callback.onPreview,\n onCommit: (r) => {\n const item: RedactionItem = {\n id: uuidV4(),\n kind: 'area',\n page: opts.pageIndex,\n rect: r,\n };\n this.dispatch(addPending(opts.documentId, [item]));\n this.emitPendingChange(opts.documentId);\n opts.callback.onCommit?.(r);\n this.enableRedactSelection(opts.documentId);\n this.selectPending(opts.pageIndex, item.id, opts.documentId);\n },\n });\n\n const off = this.interactionManagerCapability.registerAlways({\n handlers: {\n onPointerDown: (_, evt) => {\n if (evt.target === evt.currentTarget) {\n this.deselectPending(opts.documentId);\n }\n },\n },\n scope: {\n type: 'page',\n documentId: opts.documentId,\n pageIndex: opts.pageIndex,\n },\n });\n\n const off2 = this.interactionManagerCapability.registerHandlers({\n documentId: opts.documentId,\n modeId: RedactionMode.MarqueeRedact,\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return () => {\n off();\n off2();\n };\n }\n\n private queueCurrentSelectionAsPending(documentId?: string): Task<boolean, PdfErrorReason> {\n const id = documentId ?? this.getActiveDocumentId();\n\n if (!this.selectionCapability)\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: '[RedactionPlugin] selection plugin required',\n });\n\n const coreDoc = this.coreState.core.documents[id];\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const selectionScope = this.selectionCapability.forDocument(id);\n const formatted = selectionScope.getFormattedSelection();\n if (!formatted.length) return PdfTaskHelper.resolve(true);\n\n const uniqueId = uuidV4();\n\n const items: RedactionItem[] = formatted.map((s) => ({\n id: uniqueId,\n kind: 'text',\n page: s.pageIndex,\n rect: s.rect,\n rects: s.segmentRects,\n }));\n\n this.enableRedactSelection(id);\n this.dispatch(addPending(id, items));\n this.emitPendingChange(id);\n\n // Auto-select the last one added\n const last = items[items.length - 1];\n this.selectPending(last.page, last.id, id);\n\n // Clear live UI selection\n const emitter = this.redactionSelection$.get(id);\n emitter?.emit([]);\n selectionScope.clear();\n\n return PdfTaskHelper.resolve(true);\n }\n\n private commitPendingOne(\n page: number,\n id: string,\n documentId?: string,\n ): Task<boolean, PdfErrorReason> {\n const docId = documentId ?? this.getActiveDocumentId();\n const coreDoc = this.coreState.core.documents[docId];\n\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const docState = this.getDocumentState(docId);\n if (!docState) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Document state not found',\n });\n }\n\n const item = (docState.pending[page] ?? []).find((it) => it.id === id);\n if (!item) return PdfTaskHelper.resolve(true);\n\n const rects: Rect[] = item.kind === 'text' ? item.rects : [item.rect];\n const pdfPage = coreDoc.document.pages[page];\n if (!pdfPage)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Page not found' });\n\n const task = new Task<boolean, PdfErrorReason>();\n this.engine\n .redactTextInRects(coreDoc.document, pdfPage, rects, {\n drawBlackBoxes: this.config.drawBlackBoxes,\n })\n .wait(\n () => {\n this.dispatch(removePending(docId, page, id));\n this.emitPendingChange(docId);\n this.dispatchCoreAction(refreshPages(docId, [page]));\n this.events$.emit({ type: 'commit', documentId: docId, success: true });\n task.resolve(true);\n },\n (error) => {\n this.events$.emit({\n type: 'commit',\n documentId: docId,\n success: false,\n error: error.reason,\n });\n task.reject({ code: PdfErrorCode.Unknown, message: 'Failed to commit redactions' });\n },\n );\n\n return task;\n }\n\n private commitAllPending(documentId?: string): Task<boolean, PdfErrorReason> {\n const docId = documentId ?? this.getActiveDocumentId();\n const coreDoc = this.coreState.core.documents[docId];\n\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const docState = this.getDocumentState(docId);\n if (!docState) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Document state not found',\n });\n }\n\n // Group rects per page\n const perPage = new Map<number, Rect[]>();\n for (const [page, items] of Object.entries(docState.pending)) {\n const p = Number(page);\n const list = perPage.get(p) ?? [];\n for (const it of items) {\n if (it.kind === 'text') list.push(...it.rects);\n else list.push(it.rect);\n }\n perPage.set(p, list);\n }\n\n const pagesToRefresh = Array.from(perPage.entries())\n .filter(([_, rects]) => rects.length > 0)\n .map(([pageIndex]) => pageIndex);\n\n const tasks: PdfTask<boolean>[] = [];\n for (const [pageIndex, rects] of perPage) {\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n if (!rects.length) continue;\n tasks.push(\n this.engine.redactTextInRects(coreDoc.document, page, rects, {\n drawBlackBoxes: this.config.drawBlackBoxes,\n }),\n );\n }\n\n const task = new Task<boolean, PdfErrorReason>();\n Task.all(tasks).wait(\n () => {\n this.dispatch(clearPending(docId));\n this.dispatchCoreAction(refreshPages(docId, pagesToRefresh));\n this.emitPendingChange(docId);\n this.events$.emit({ type: 'commit', documentId: docId, success: true });\n task.resolve(true);\n },\n (error) => {\n this.events$.emit({\n type: 'commit',\n documentId: docId,\n success: false,\n error: error.reason,\n });\n task.reject({ code: PdfErrorCode.Unknown, message: 'Failed to commit redactions' });\n },\n );\n\n return task;\n }\n\n // ─────────────────────────────────────────────────────────\n // Event Emission Helpers\n // ─────────────────────────────────────────────────────────\n\n private emitPendingChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.pending$.emit({ documentId, pending: docState.pending });\n }\n }\n\n private emitSelectedChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.selected$.emit({ documentId, selected: docState.selected });\n }\n }\n\n private emitStateChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.state$.emit({ documentId, state: docState });\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Store Update Handlers\n // ─────────────────────────────────────────────────────────\n\n override onStoreUpdated(_: RedactionState, newState: RedactionState): void {\n // Emit state changes for each changed document\n for (const documentId in newState.documents) {\n const docState = newState.documents[documentId];\n if (docState) {\n this.emitPendingChange(documentId);\n this.emitSelectedChange(documentId);\n this.emitStateChange(documentId);\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async destroy(): Promise<void> {\n this.pending$.clear();\n this.selected$.clear();\n this.state$.clear();\n this.events$.clear();\n\n // Cleanup all per-document emitters\n this.redactionSelection$.forEach((emitter) => emitter.clear());\n this.redactionSelection$.clear();\n\n // Cleanup all unsubscribers\n this.documentUnsubscribers.forEach((unsubscribers) => {\n unsubscribers.forEach((unsub) => unsub());\n });\n this.documentUnsubscribers.clear();\n\n await super.destroy();\n }\n}\n","import { Position, Rect, Size } from '@embedpdf/models';\nimport { clamp } from '@embedpdf/core';\nimport {\n EmbedPdfPointerEvent,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nexport function createMarqueeHandler(opts: {\n pageSize: Size;\n scale: number;\n minDragPx?: number;\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n}): PointerEventHandlersWithLifecycle<EmbedPdfPointerEvent> {\n const { pageSize, scale, minDragPx = 5, onPreview, onCommit } = opts;\n\n let start: Position | null = null;\n let last: Rect | null = null;\n\n return {\n onPointerDown: (pos, evt) => {\n start = pos;\n last = { origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } };\n onPreview?.(last);\n evt.setPointerCapture?.();\n },\n onPointerMove: (pos) => {\n if (!start) return;\n const x = clamp(pos.x, 0, pageSize.width);\n const y = clamp(pos.y, 0, pageSize.height);\n last = {\n origin: { x: Math.min(start.x, x), y: Math.min(start.y, y) },\n size: { width: Math.abs(x - start.x), height: Math.abs(y - start.y) },\n };\n onPreview?.(last);\n },\n onPointerUp: (_pos, evt) => {\n if (last) {\n const dragPx = Math.max(last.size.width, last.size.height) * scale;\n if (dragPx > minDragPx) onCommit?.(last);\n }\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n onPointerCancel: (_pos, evt) => {\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n };\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { RedactionPluginConfig } from './types';\n\nexport const REDACTION_PLUGIN_ID = 'redaction';\n\nexport const manifest: PluginManifest<RedactionPluginConfig> = {\n id: REDACTION_PLUGIN_ID,\n name: 'Redaction Plugin',\n version: '1.0.0',\n provides: ['redaction'],\n requires: [],\n optional: ['interaction-manager', 'selection'],\n defaultConfig: {\n enabled: true,\n drawBlackBoxes: true,\n },\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { RedactionPluginConfig, RedactionState } from './types';\nimport { RedactionPlugin } from './redaction-plugin';\nimport { manifest, REDACTION_PLUGIN_ID } from './manifest';\nimport { RedactionAction } from './actions';\nimport { initialState, redactionReducer } from './reducer';\n\nexport const RedactionPluginPackage: PluginPackage<\n RedactionPlugin,\n RedactionPluginConfig,\n RedactionState,\n RedactionAction\n> = {\n manifest,\n create: (registry, config) => new RedactionPlugin(REDACTION_PLUGIN_ID, registry, config),\n reducer: redactionReducer,\n initialState: initialState,\n};\n\nexport * from './redaction-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './selectors';\nexport { initialState, initialDocumentState } from './reducer';\n","import { RedactionState, RedactionDocumentState } from './types';\n\nexport const getPendingRedactionsCount = (s: RedactionDocumentState) => s.pendingCount;\n\nexport const hasPendingRedactions = (s: RedactionDocumentState) => s.pendingCount > 0;\n\nexport const getDocumentPendingCount = (state: RedactionState, documentId: string): number => {\n return state.documents[documentId]?.pendingCount ?? 0;\n};\n\nexport const getTotalPendingCount = (state: RedactionState): number => {\n return Object.values(state.documents).reduce((sum, doc) => sum + doc.pendingCount, 0);\n};\n"],"names":["RedactionMode","INIT_REDACTION_STATE","CLEANUP_REDACTION_STATE","START_REDACTION","END_REDACTION","ADD_PENDING","REMOVE_PENDING","CLEAR_PENDING","SELECT_PENDING","DESELECT_PENDING","addPending","documentId","items","type","payload","removePending","page","id","clearPending","startRedaction","mode","calculatePendingCount","pending","Object","values","reduce","total","length","initialDocumentState","isRedacting","activeType","pendingCount","selected","initialState","documents","activeDocumentId","_RedactionPlugin","BasePlugin","constructor","registry","config","super","this","redactionSelection$","Map","pending$","createBehaviorEmitter","selected$","state$","events$","documentUnsubscribers","selectionCapability","_a","getPlugin","provides","interactionManagerCapability","_b","registerMode","MarqueeRedact","scope","exclusive","cursor","RedactSelection","_c","onModeChange","modeState","activeMode","dispatch","docState","getDocumentState","endRedaction","onDocumentLoadingStarted","state","initRedactionState","set","unsubscribers","selectionScope","forDocument","unsubSelection","onSelectionChange","formattedSelection","getFormattedSelection","emitter","get","emit","unsubEndSelection","onEndSelection","map","s","uuidV4","kind","pageIndex","rect","rects","segmentRects","clear","emitPendingChange","selectPending","push","logger","debug","onDocumentLoaded","enableForMode","onDocumentClosed","cleanupRedactionState","delete","forEach","unsub","initialize","_config","info","buildCapability","queueCurrentSelectionAsPending","enableMarqueeRedact","toggleMarqueeRedact","isMarqueeRedactActive","enableRedactSelection","toggleRedactSelection","isRedactSelectionActive","addPendingItems","removePendingItem","clearPendingItems","commitAllPending","commitPending","commitPendingOne","endRedactionMode","startRedactionMode","getSelectedPending","deselectPending","getState","getDocumentStateOrThrow","createRedactionScope","onPendingChange","on","onSelectedChange","onRedactionEvent","onStateChange","listener","event","getActiveDocumentId","Error","itemId","emitSelectedChange","activate","getActiveMode","activateDefaultMode","onRedactionSelectionChange","callback","registerMarqueeOnPage","opts","warn","coreDoc","coreState","core","document","pages","handlers","pageSize","scale","minDragPx","onPreview","onCommit","start","last","onPointerDown","pos","evt","origin","x","y","size","width","height","setPointerCapture","call","onPointerMove","clamp","Math","min","abs","onPointerUp","_pos","max","releasePointerCapture","onPointerCancel","createMarqueeHandler","r","item","off","registerAlways","_","target","currentTarget","off2","registerHandlers","modeId","PdfTaskHelper","reject","code","PdfErrorCode","NotFound","message","formatted","resolve","uniqueId","docId","find","it","pdfPage","task","Task","engine","redactTextInRects","drawBlackBoxes","wait","dispatchCoreAction","refreshPages","success","error","reason","Unknown","perPage","entries","p","Number","list","pagesToRefresh","Array","from","filter","tasks","all","emitStateChange","onStoreUpdated","newState","destroy","RedactionPlugin","REDACTION_PLUGIN_ID","manifest","name","version","requires","optional","defaultConfig","enabled","RedactionPluginPackage","create","reducer","action","removed","remainingDocs","next","concat","filtered","stillSelected","sum","doc"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/lib/types.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/redaction-plugin.ts","../src/lib/handlers/marquee-redact.handler.ts","../src/lib/manifest.ts","../src/lib/index.ts","../src/lib/selectors.ts"],"sourcesContent":["import { BasePluginConfig, EventHook } from '@embedpdf/core';\nimport { PdfErrorReason, Rect, Task } from '@embedpdf/models';\n\n// Redaction mode enum\nexport enum RedactionMode {\n MarqueeRedact = 'marqueeRedact',\n RedactSelection = 'redactSelection',\n}\n\nexport interface SelectedRedaction {\n page: number;\n id: string;\n}\n\n// Per-document redaction state\nexport interface RedactionDocumentState {\n isRedacting: boolean;\n activeType: RedactionMode | null;\n pending: Record<number, RedactionItem[]>;\n pendingCount: number;\n selected: SelectedRedaction | null;\n}\n\n// Plugin state\nexport interface RedactionState {\n documents: Record<string, RedactionDocumentState>;\n activeDocumentId: string | null;\n}\n\nexport type RedactionItem =\n | {\n id: string;\n kind: 'text';\n page: number;\n rect: Rect;\n rects: Rect[];\n }\n | {\n id: string;\n kind: 'area';\n page: number;\n rect: Rect;\n };\n\nexport interface MarqueeRedactCallback {\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n}\n\nexport interface RegisterMarqueeOnPageOptions {\n documentId: string;\n pageIndex: number;\n scale: number;\n callback: MarqueeRedactCallback;\n}\n\nexport interface RedactionPluginConfig extends BasePluginConfig {\n drawBlackBoxes: boolean;\n}\n\n// Events include documentId\nexport type RedactionEvent =\n | {\n type: 'add';\n documentId: string;\n items: RedactionItem[];\n }\n | {\n type: 'remove';\n documentId: string;\n page: number;\n id: string;\n }\n | {\n type: 'clear';\n documentId: string;\n }\n | {\n type: 'commit';\n documentId: string;\n success: boolean;\n error?: PdfErrorReason;\n };\n\nexport interface PendingChangeEvent {\n documentId: string;\n pending: Record<number, RedactionItem[]>;\n}\n\nexport interface SelectedChangeEvent {\n documentId: string;\n selected: SelectedRedaction | null;\n}\n\nexport interface StateChangeEvent {\n documentId: string;\n state: RedactionDocumentState;\n}\n\n// Scoped redaction capability\nexport interface RedactionScope {\n queueCurrentSelectionAsPending(): Task<boolean, PdfErrorReason>;\n\n enableMarqueeRedact(): void;\n toggleMarqueeRedact(): void;\n isMarqueeRedactActive(): boolean;\n\n enableRedactSelection(): void;\n toggleRedactSelection(): void;\n isRedactSelectionActive(): boolean;\n\n addPending(items: RedactionItem[]): void;\n removePending(page: number, id: string): void;\n clearPending(): void;\n commitAllPending(): Task<boolean, PdfErrorReason>;\n commitPending(page: number, id: string): Task<boolean, PdfErrorReason>;\n\n endRedaction(): void;\n startRedaction(): void;\n\n selectPending(page: number, id: string): void;\n getSelectedPending(): SelectedRedaction | null;\n deselectPending(): void;\n\n getState(): RedactionDocumentState;\n\n onPendingChange: EventHook<Record<number, RedactionItem[]>>;\n onSelectedChange: EventHook<SelectedRedaction | null>;\n onRedactionEvent: EventHook<RedactionEvent>;\n onStateChange: EventHook<RedactionDocumentState>;\n}\n\nexport interface RedactionCapability {\n // Active document operations\n queueCurrentSelectionAsPending(): Task<boolean, PdfErrorReason>;\n\n enableMarqueeRedact(): void;\n toggleMarqueeRedact(): void;\n isMarqueeRedactActive(): boolean;\n\n enableRedactSelection(): void;\n toggleRedactSelection(): void;\n isRedactSelectionActive(): boolean;\n\n addPending(items: RedactionItem[]): void;\n removePending(page: number, id: string): void;\n clearPending(): void;\n commitAllPending(): Task<boolean, PdfErrorReason>;\n commitPending(page: number, id: string): Task<boolean, PdfErrorReason>;\n\n endRedaction(): void;\n startRedaction(): void;\n\n selectPending(page: number, id: string): void;\n getSelectedPending(): SelectedRedaction | null;\n deselectPending(): void;\n\n getState(): RedactionDocumentState;\n\n // Document-scoped operations\n forDocument(documentId: string): RedactionScope;\n\n // Events (include documentId)\n onPendingChange: EventHook<PendingChangeEvent>;\n onSelectedChange: EventHook<SelectedChangeEvent>;\n onRedactionEvent: EventHook<RedactionEvent>;\n onStateChange: EventHook<StateChangeEvent>;\n}\n","import { Action } from '@embedpdf/core';\nimport { RedactionItem, RedactionMode, RedactionDocumentState } from './types';\n\n// Document lifecycle\nexport const INIT_REDACTION_STATE = 'REDACTION/INIT_STATE';\nexport const CLEANUP_REDACTION_STATE = 'REDACTION/CLEANUP_STATE';\nexport const SET_ACTIVE_DOCUMENT = 'REDACTION/SET_ACTIVE_DOCUMENT';\n\n// Per-document redaction operations\nexport const START_REDACTION = 'START_REDACTION';\nexport const END_REDACTION = 'END_REDACTION';\nexport const SET_ACTIVE_TYPE = 'SET_ACTIVE_TYPE';\n\nexport const ADD_PENDING = 'ADD_PENDING';\nexport const REMOVE_PENDING = 'REMOVE_PENDING';\nexport const CLEAR_PENDING = 'CLEAR_PENDING';\n\nexport const SELECT_PENDING = 'SELECT_PENDING';\nexport const DESELECT_PENDING = 'DESELECT_PENDING';\n\n// Document lifecycle actions\nexport interface InitRedactionStateAction extends Action {\n type: typeof INIT_REDACTION_STATE;\n payload: {\n documentId: string;\n state: RedactionDocumentState;\n };\n}\n\nexport interface CleanupRedactionStateAction extends Action {\n type: typeof CLEANUP_REDACTION_STATE;\n payload: string; // documentId\n}\n\nexport interface SetActiveDocumentAction extends Action {\n type: typeof SET_ACTIVE_DOCUMENT;\n payload: string | null; // documentId\n}\n\n// Per-document operation actions\nexport interface StartRedactionAction extends Action {\n type: typeof START_REDACTION;\n payload: {\n documentId: string;\n mode: RedactionMode;\n };\n}\n\nexport interface EndRedactionAction extends Action {\n type: typeof END_REDACTION;\n payload: string; // documentId\n}\n\nexport interface SetActiveTypeAction extends Action {\n type: typeof SET_ACTIVE_TYPE;\n payload: {\n documentId: string;\n mode: RedactionMode | null;\n };\n}\n\nexport interface AddPendingAction extends Action {\n type: typeof ADD_PENDING;\n payload: {\n documentId: string;\n items: RedactionItem[];\n };\n}\n\nexport interface RemovePendingAction extends Action {\n type: typeof REMOVE_PENDING;\n payload: {\n documentId: string;\n page: number;\n id: string;\n };\n}\n\nexport interface ClearPendingAction extends Action {\n type: typeof CLEAR_PENDING;\n payload: string; // documentId\n}\n\nexport interface SelectPendingAction extends Action {\n type: typeof SELECT_PENDING;\n payload: {\n documentId: string;\n page: number;\n id: string;\n };\n}\n\nexport interface DeselectPendingAction extends Action {\n type: typeof DESELECT_PENDING;\n payload: string; // documentId\n}\n\nexport type RedactionAction =\n | InitRedactionStateAction\n | CleanupRedactionStateAction\n | SetActiveDocumentAction\n | StartRedactionAction\n | EndRedactionAction\n | SetActiveTypeAction\n | AddPendingAction\n | RemovePendingAction\n | ClearPendingAction\n | SelectPendingAction\n | DeselectPendingAction;\n\n// Action Creators\n\nexport function initRedactionState(\n documentId: string,\n state: RedactionDocumentState,\n): InitRedactionStateAction {\n return { type: INIT_REDACTION_STATE, payload: { documentId, state } };\n}\n\nexport function cleanupRedactionState(documentId: string): CleanupRedactionStateAction {\n return { type: CLEANUP_REDACTION_STATE, payload: documentId };\n}\n\nexport function setActiveDocument(documentId: string | null): SetActiveDocumentAction {\n return { type: SET_ACTIVE_DOCUMENT, payload: documentId };\n}\n\nexport const addPending = (documentId: string, items: RedactionItem[]): AddPendingAction => ({\n type: ADD_PENDING,\n payload: { documentId, items },\n});\n\nexport const removePending = (\n documentId: string,\n page: number,\n id: string,\n): RemovePendingAction => ({\n type: REMOVE_PENDING,\n payload: { documentId, page, id },\n});\n\nexport const clearPending = (documentId: string): ClearPendingAction => ({\n type: CLEAR_PENDING,\n payload: documentId,\n});\n\nexport const startRedaction = (documentId: string, mode: RedactionMode): StartRedactionAction => ({\n type: START_REDACTION,\n payload: { documentId, mode },\n});\n\nexport const endRedaction = (documentId: string): EndRedactionAction => ({\n type: END_REDACTION,\n payload: documentId,\n});\n\nexport const setActiveType = (\n documentId: string,\n mode: RedactionMode | null,\n): SetActiveTypeAction => ({\n type: SET_ACTIVE_TYPE,\n payload: { documentId, mode },\n});\n\nexport const selectPending = (\n documentId: string,\n page: number,\n id: string,\n): SelectPendingAction => ({\n type: SELECT_PENDING,\n payload: { documentId, page, id },\n});\n\nexport const deselectPending = (documentId: string): DeselectPendingAction => ({\n type: DESELECT_PENDING,\n payload: documentId,\n});\n","import { Reducer } from '@embedpdf/core';\nimport { RedactionItem, RedactionState, RedactionDocumentState } from './types';\nimport {\n RedactionAction,\n INIT_REDACTION_STATE,\n CLEANUP_REDACTION_STATE,\n SET_ACTIVE_DOCUMENT,\n ADD_PENDING,\n CLEAR_PENDING,\n END_REDACTION,\n REMOVE_PENDING,\n START_REDACTION,\n SET_ACTIVE_TYPE,\n SELECT_PENDING,\n DESELECT_PENDING,\n} from './actions';\n\n// Helper function to calculate total pending count\nconst calculatePendingCount = (pending: Record<number, RedactionItem[]>): number => {\n return Object.values(pending).reduce((total, items) => total + items.length, 0);\n};\n\nexport const initialDocumentState: RedactionDocumentState = {\n isRedacting: false,\n activeType: null,\n pending: {},\n pendingCount: 0,\n selected: null,\n};\n\nexport const initialState: RedactionState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const redactionReducer: Reducer<RedactionState, RedactionAction> = (\n state = initialState,\n action,\n) => {\n switch (action.type) {\n case INIT_REDACTION_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_REDACTION_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_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n case ADD_PENDING: {\n const { documentId, items } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const next = { ...docState.pending };\n for (const item of items) {\n next[item.page] = (next[item.page] ?? []).concat(item);\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n pending: next,\n pendingCount: calculatePendingCount(next),\n },\n },\n };\n }\n\n case REMOVE_PENDING: {\n const { documentId, page, id } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const list = docState.pending[page] ?? [];\n const filtered = list.filter((it) => it.id !== id);\n const next = { ...docState.pending, [page]: filtered };\n\n // if the removed one was selected → clear selection\n const stillSelected =\n docState.selected && !(docState.selected.page === page && docState.selected.id === id);\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n pending: next,\n pendingCount: calculatePendingCount(next),\n selected: stillSelected ? docState.selected : null,\n },\n },\n };\n }\n\n case CLEAR_PENDING: {\n const documentId = 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 pending: {},\n pendingCount: 0,\n selected: null,\n },\n },\n };\n }\n\n case SELECT_PENDING: {\n const { documentId, page, id } = 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 selected: { page, id },\n },\n },\n };\n }\n\n case DESELECT_PENDING: {\n const documentId = 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 selected: null,\n },\n },\n };\n }\n\n case START_REDACTION: {\n const { documentId, mode } = 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 isRedacting: true,\n activeType: mode,\n },\n },\n };\n }\n\n case END_REDACTION: {\n const documentId = 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 pending: {},\n pendingCount: 0,\n selected: null,\n isRedacting: false,\n activeType: null,\n },\n },\n };\n }\n\n case SET_ACTIVE_TYPE: {\n const { documentId, mode } = 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 activeType: mode,\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import {\n RedactionPluginConfig,\n RedactionCapability,\n RedactionState,\n RegisterMarqueeOnPageOptions,\n RedactionItem,\n SelectedRedaction,\n RedactionMode,\n RedactionEvent,\n RedactionScope,\n StateChangeEvent,\n PendingChangeEvent,\n SelectedChangeEvent,\n RedactionDocumentState,\n} from './types';\nimport {\n BasePlugin,\n createBehaviorEmitter,\n PluginRegistry,\n refreshPages,\n Listener,\n} from '@embedpdf/core';\nimport {\n PdfErrorCode,\n PdfErrorReason,\n PdfTask,\n PdfTaskHelper,\n Rect,\n Task,\n uuidV4,\n} from '@embedpdf/models';\nimport {\n FormattedSelection,\n SelectionCapability,\n SelectionPlugin,\n} from '@embedpdf/plugin-selection';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport {\n addPending,\n clearPending,\n deselectPending,\n endRedaction,\n removePending,\n selectPending,\n startRedaction,\n initRedactionState,\n cleanupRedactionState,\n RedactionAction,\n} from './actions';\nimport { createMarqueeHandler } from './handlers';\nimport { initialDocumentState } from './reducer';\n\nexport class RedactionPlugin extends BasePlugin<\n RedactionPluginConfig,\n RedactionCapability,\n RedactionState,\n RedactionAction\n> {\n static readonly id = 'redaction' as const;\n\n private config: RedactionPluginConfig;\n private selectionCapability: SelectionCapability | undefined;\n private interactionManagerCapability: InteractionManagerCapability | undefined;\n\n // Per-document emitters\n private readonly redactionSelection$ = new Map<\n string,\n ReturnType<typeof createBehaviorEmitter<FormattedSelection[]>>\n >();\n\n // Global emitters with documentId\n private readonly pending$ = createBehaviorEmitter<PendingChangeEvent>();\n private readonly selected$ = createBehaviorEmitter<SelectedChangeEvent>();\n private readonly state$ = createBehaviorEmitter<StateChangeEvent>();\n private readonly events$ = createBehaviorEmitter<RedactionEvent>();\n\n // Per-document unsubscribe functions\n private readonly documentUnsubscribers = new Map<string, Array<() => void>>();\n\n constructor(id: string, registry: PluginRegistry, config: RedactionPluginConfig) {\n super(id, registry);\n this.config = config;\n\n this.selectionCapability = this.registry.getPlugin<SelectionPlugin>('selection')?.provides();\n this.interactionManagerCapability = this.registry\n .getPlugin<InteractionManagerPlugin>('interaction-manager')\n ?.provides();\n\n if (this.interactionManagerCapability) {\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.MarqueeRedact,\n scope: 'page',\n exclusive: true,\n cursor: 'crosshair',\n });\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.RedactSelection,\n scope: 'page',\n exclusive: false,\n });\n }\n\n // Listen to mode changes per document\n this.interactionManagerCapability?.onModeChange((modeState) => {\n const documentId = modeState.documentId;\n\n if (modeState.activeMode === RedactionMode.RedactSelection) {\n this.dispatch(startRedaction(documentId, RedactionMode.RedactSelection));\n } else if (modeState.activeMode === RedactionMode.MarqueeRedact) {\n this.dispatch(startRedaction(documentId, RedactionMode.MarqueeRedact));\n } else {\n const docState = this.getDocumentState(documentId);\n if (docState?.isRedacting) {\n this.dispatch(endRedaction(documentId));\n }\n }\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle Hooks (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n // Initialize state for this document\n this.dispatch(\n initRedactionState(documentId, {\n ...initialDocumentState,\n }),\n );\n\n // Create per-document emitter\n this.redactionSelection$.set(documentId, createBehaviorEmitter<FormattedSelection[]>());\n // Setup selection listeners for this document\n const unsubscribers: Array<() => void> = [];\n\n if (this.selectionCapability) {\n const selectionScope = this.selectionCapability.forDocument(documentId);\n\n // Listen to selection changes\n const unsubSelection = selectionScope.onSelectionChange(() => {\n const docState = this.getDocumentState(documentId);\n if (!docState?.isRedacting) return;\n\n const formattedSelection = selectionScope.getFormattedSelection();\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.emit(formattedSelection);\n });\n\n // Listen to end selection\n const unsubEndSelection = selectionScope.onEndSelection(() => {\n const docState = this.getDocumentState(documentId);\n if (!docState?.isRedacting) return;\n\n const formattedSelection = selectionScope.getFormattedSelection();\n\n const items: RedactionItem[] = formattedSelection.map((s) => ({\n id: uuidV4(),\n kind: 'text',\n page: s.pageIndex,\n rect: s.rect,\n rects: s.segmentRects,\n }));\n\n this.dispatch(addPending(documentId, items));\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.emit([]);\n selectionScope.clear();\n\n this.emitPendingChange(documentId);\n\n if (items.length) {\n this.selectPending(items[items.length - 1].page, items[items.length - 1].id, documentId);\n }\n });\n\n unsubscribers.push(unsubSelection, unsubEndSelection);\n }\n\n this.documentUnsubscribers.set(documentId, unsubscribers);\n\n this.logger.debug(\n 'RedactionPlugin',\n 'DocumentOpened',\n `Initialized redaction state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentLoaded(documentId: string): void {\n this.selectionCapability?.enableForMode(RedactionMode.RedactSelection, documentId);\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup state\n this.dispatch(cleanupRedactionState(documentId));\n\n // Cleanup emitters\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.clear();\n this.redactionSelection$.delete(documentId);\n\n // Cleanup unsubscribers\n const unsubscribers = this.documentUnsubscribers.get(documentId);\n if (unsubscribers) {\n unsubscribers.forEach((unsub) => unsub());\n this.documentUnsubscribers.delete(documentId);\n }\n\n this.logger.debug(\n 'RedactionPlugin',\n 'DocumentClosed',\n `Cleaned up redaction state for document: ${documentId}`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n async initialize(_config: RedactionPluginConfig): Promise<void> {\n this.logger.info('RedactionPlugin', 'Initialize', 'Redaction plugin initialized');\n }\n\n protected buildCapability(): RedactionCapability {\n return {\n // Active document operations\n queueCurrentSelectionAsPending: () => this.queueCurrentSelectionAsPending(),\n\n enableMarqueeRedact: () => this.enableMarqueeRedact(),\n toggleMarqueeRedact: () => this.toggleMarqueeRedact(),\n isMarqueeRedactActive: () => this.isMarqueeRedactActive(),\n\n enableRedactSelection: () => this.enableRedactSelection(),\n toggleRedactSelection: () => this.toggleRedactSelection(),\n isRedactSelectionActive: () => this.isRedactSelectionActive(),\n\n addPending: (items) => this.addPendingItems(items),\n removePending: (page, id) => this.removePendingItem(page, id),\n clearPending: () => this.clearPendingItems(),\n commitAllPending: () => this.commitAllPending(),\n commitPending: (page, id) => this.commitPendingOne(page, id),\n\n endRedaction: () => this.endRedactionMode(),\n startRedaction: () => this.startRedactionMode(),\n\n selectPending: (page, id) => this.selectPending(page, id),\n getSelectedPending: () => this.getSelectedPending(),\n deselectPending: () => this.deselectPending(),\n\n getState: () => this.getDocumentStateOrThrow(),\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createRedactionScope(documentId),\n\n // Events\n onPendingChange: this.pending$.on,\n onSelectedChange: this.selected$.on,\n onRedactionEvent: this.events$.on,\n onStateChange: this.state$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createRedactionScope(documentId: string): RedactionScope {\n return {\n queueCurrentSelectionAsPending: () => this.queueCurrentSelectionAsPending(documentId),\n\n enableMarqueeRedact: () => this.enableMarqueeRedact(documentId),\n toggleMarqueeRedact: () => this.toggleMarqueeRedact(documentId),\n isMarqueeRedactActive: () => this.isMarqueeRedactActive(documentId),\n\n enableRedactSelection: () => this.enableRedactSelection(documentId),\n toggleRedactSelection: () => this.toggleRedactSelection(documentId),\n isRedactSelectionActive: () => this.isRedactSelectionActive(documentId),\n\n addPending: (items) => this.addPendingItems(items, documentId),\n removePending: (page, id) => this.removePendingItem(page, id, documentId),\n clearPending: () => this.clearPendingItems(documentId),\n commitAllPending: () => this.commitAllPending(documentId),\n commitPending: (page, id) => this.commitPendingOne(page, id, documentId),\n\n endRedaction: () => this.endRedactionMode(documentId),\n startRedaction: () => this.startRedactionMode(documentId),\n\n selectPending: (page, id) => this.selectPending(page, id, documentId),\n getSelectedPending: () => this.getSelectedPending(documentId),\n deselectPending: () => this.deselectPending(documentId),\n\n getState: () => this.getDocumentStateOrThrow(documentId),\n\n onPendingChange: (listener: Listener<Record<number, RedactionItem[]>>) =>\n this.pending$.on((event) => {\n if (event.documentId === documentId) listener(event.pending);\n }),\n onSelectedChange: (listener: Listener<SelectedRedaction | null>) =>\n this.selected$.on((event) => {\n if (event.documentId === documentId) listener(event.selected);\n }),\n onRedactionEvent: (listener: Listener<RedactionEvent>) =>\n this.events$.on((event) => {\n if (event.documentId === documentId) listener(event);\n }),\n onStateChange: (listener: Listener<RedactionDocumentState>) =>\n this.state$.on((event) => {\n if (event.documentId === documentId) listener(event.state);\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // State Helpers\n // ─────────────────────────────────────────────────────────\n\n private getDocumentState(documentId?: string): RedactionDocumentState | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.state.documents[id] ?? null;\n }\n\n private getDocumentStateOrThrow(documentId?: string): RedactionDocumentState {\n const state = this.getDocumentState(documentId);\n if (!state) {\n throw new Error(`Redaction state not found for document: ${documentId ?? 'active'}`);\n }\n return state;\n }\n\n // ─────────────────────────────────────────────────────────\n // Core Operations\n // ─────────────────────────────────────────────────────────\n\n private addPendingItems(items: RedactionItem[], documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(addPending(id, items));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'add', documentId: id, items });\n }\n\n private removePendingItem(page: number, itemId: string, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(removePending(id, page, itemId));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'remove', documentId: id, page, id: itemId });\n }\n\n private clearPendingItems(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(clearPending(id));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'clear', documentId: id });\n }\n\n private selectPending(page: number, itemId: string, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(selectPending(id, page, itemId));\n this.selectionCapability?.forDocument(id).clear();\n this.emitSelectedChange(id);\n }\n\n private getSelectedPending(documentId?: string): SelectedRedaction | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.getDocumentState(id)?.selected ?? null;\n }\n\n private deselectPending(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(deselectPending(id));\n this.emitSelectedChange(id);\n }\n\n private enableRedactSelection(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.RedactSelection);\n }\n\n private toggleRedactSelection(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManagerCapability?.forDocument(id);\n if (scope?.getActiveMode() === RedactionMode.RedactSelection) {\n scope.activateDefaultMode();\n } else {\n scope?.activate(RedactionMode.RedactSelection);\n }\n }\n\n private isRedactSelectionActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return (\n this.interactionManagerCapability?.forDocument(id).getActiveMode() ===\n RedactionMode.RedactSelection\n );\n }\n\n private enableMarqueeRedact(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.MarqueeRedact);\n }\n\n private toggleMarqueeRedact(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManagerCapability?.forDocument(id);\n if (scope?.getActiveMode() === RedactionMode.MarqueeRedact) {\n scope.activateDefaultMode();\n } else {\n scope?.activate(RedactionMode.MarqueeRedact);\n }\n }\n\n private isMarqueeRedactActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return (\n this.interactionManagerCapability?.forDocument(id).getActiveMode() ===\n RedactionMode.MarqueeRedact\n );\n }\n\n private startRedactionMode(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.RedactSelection);\n }\n\n private endRedactionMode(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activateDefaultMode();\n }\n\n // ─────────────────────────────────────────────────────────\n // Public Methods\n // ─────────────────────────────────────────────────────────\n\n public onRedactionSelectionChange(\n documentId: string,\n callback: (formattedSelection: FormattedSelection[]) => void,\n ) {\n const emitter = this.redactionSelection$.get(documentId);\n return emitter?.on(callback) ?? (() => {});\n }\n\n public registerMarqueeOnPage(opts: RegisterMarqueeOnPageOptions) {\n if (!this.interactionManagerCapability) {\n this.logger.warn(\n 'RedactionPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, marquee redaction disabled',\n );\n return () => {};\n }\n\n const coreDoc = this.coreState.core.documents[opts.documentId];\n if (!coreDoc?.document) {\n this.logger.warn('RedactionPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = coreDoc.document.pages[opts.pageIndex];\n if (!page) {\n this.logger.warn('RedactionPlugin', 'PageNotFound', `Page ${opts.pageIndex} not found`);\n return () => {};\n }\n\n const handlers = createMarqueeHandler({\n pageSize: page.size,\n scale: opts.scale,\n onPreview: opts.callback.onPreview,\n onCommit: (r) => {\n const item: RedactionItem = {\n id: uuidV4(),\n kind: 'area',\n page: opts.pageIndex,\n rect: r,\n };\n this.dispatch(addPending(opts.documentId, [item]));\n this.emitPendingChange(opts.documentId);\n opts.callback.onCommit?.(r);\n this.enableRedactSelection(opts.documentId);\n this.selectPending(opts.pageIndex, item.id, opts.documentId);\n },\n });\n\n const off = this.interactionManagerCapability.registerAlways({\n handlers: {\n onPointerDown: (_, evt) => {\n if (evt.target === evt.currentTarget) {\n this.deselectPending(opts.documentId);\n }\n },\n },\n scope: {\n type: 'page',\n documentId: opts.documentId,\n pageIndex: opts.pageIndex,\n },\n });\n\n const off2 = this.interactionManagerCapability.registerHandlers({\n documentId: opts.documentId,\n modeId: RedactionMode.MarqueeRedact,\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return () => {\n off();\n off2();\n };\n }\n\n private queueCurrentSelectionAsPending(documentId?: string): Task<boolean, PdfErrorReason> {\n const id = documentId ?? this.getActiveDocumentId();\n\n if (!this.selectionCapability)\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: '[RedactionPlugin] selection plugin required',\n });\n\n const coreDoc = this.coreState.core.documents[id];\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const selectionScope = this.selectionCapability.forDocument(id);\n const formatted = selectionScope.getFormattedSelection();\n if (!formatted.length) return PdfTaskHelper.resolve(true);\n\n const uniqueId = uuidV4();\n\n const items: RedactionItem[] = formatted.map((s) => ({\n id: uniqueId,\n kind: 'text',\n page: s.pageIndex,\n rect: s.rect,\n rects: s.segmentRects,\n }));\n\n this.enableRedactSelection(id);\n this.dispatch(addPending(id, items));\n this.emitPendingChange(id);\n\n // Auto-select the last one added\n const last = items[items.length - 1];\n this.selectPending(last.page, last.id, id);\n\n // Clear live UI selection\n const emitter = this.redactionSelection$.get(id);\n emitter?.emit([]);\n selectionScope.clear();\n\n return PdfTaskHelper.resolve(true);\n }\n\n private commitPendingOne(\n page: number,\n id: string,\n documentId?: string,\n ): Task<boolean, PdfErrorReason> {\n const docId = documentId ?? this.getActiveDocumentId();\n const coreDoc = this.coreState.core.documents[docId];\n\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const docState = this.getDocumentState(docId);\n if (!docState) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Document state not found',\n });\n }\n\n const item = (docState.pending[page] ?? []).find((it) => it.id === id);\n if (!item) return PdfTaskHelper.resolve(true);\n\n const rects: Rect[] = item.kind === 'text' ? item.rects : [item.rect];\n const pdfPage = coreDoc.document.pages[page];\n if (!pdfPage)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Page not found' });\n\n const task = new Task<boolean, PdfErrorReason>();\n this.engine\n .redactTextInRects(coreDoc.document, pdfPage, rects, {\n drawBlackBoxes: this.config.drawBlackBoxes,\n })\n .wait(\n () => {\n this.dispatch(removePending(docId, page, id));\n this.emitPendingChange(docId);\n this.dispatchCoreAction(refreshPages(docId, [page]));\n this.events$.emit({ type: 'commit', documentId: docId, success: true });\n task.resolve(true);\n },\n (error) => {\n this.events$.emit({\n type: 'commit',\n documentId: docId,\n success: false,\n error: error.reason,\n });\n task.reject({ code: PdfErrorCode.Unknown, message: 'Failed to commit redactions' });\n },\n );\n\n return task;\n }\n\n private commitAllPending(documentId?: string): Task<boolean, PdfErrorReason> {\n const docId = documentId ?? this.getActiveDocumentId();\n const coreDoc = this.coreState.core.documents[docId];\n\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const docState = this.getDocumentState(docId);\n if (!docState) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Document state not found',\n });\n }\n\n // Group rects per page\n const perPage = new Map<number, Rect[]>();\n for (const [page, items] of Object.entries(docState.pending)) {\n const p = Number(page);\n const list = perPage.get(p) ?? [];\n for (const it of items) {\n if (it.kind === 'text') list.push(...it.rects);\n else list.push(it.rect);\n }\n perPage.set(p, list);\n }\n\n const pagesToRefresh = Array.from(perPage.entries())\n .filter(([_, rects]) => rects.length > 0)\n .map(([pageIndex]) => pageIndex);\n\n const tasks: PdfTask<boolean>[] = [];\n for (const [pageIndex, rects] of perPage) {\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n if (!rects.length) continue;\n tasks.push(\n this.engine.redactTextInRects(coreDoc.document, page, rects, {\n drawBlackBoxes: this.config.drawBlackBoxes,\n }),\n );\n }\n\n const task = new Task<boolean, PdfErrorReason>();\n Task.all(tasks).wait(\n () => {\n this.dispatch(clearPending(docId));\n this.dispatchCoreAction(refreshPages(docId, pagesToRefresh));\n this.emitPendingChange(docId);\n this.events$.emit({ type: 'commit', documentId: docId, success: true });\n task.resolve(true);\n },\n (error) => {\n this.events$.emit({\n type: 'commit',\n documentId: docId,\n success: false,\n error: error.reason,\n });\n task.reject({ code: PdfErrorCode.Unknown, message: 'Failed to commit redactions' });\n },\n );\n\n return task;\n }\n\n // ─────────────────────────────────────────────────────────\n // Event Emission Helpers\n // ─────────────────────────────────────────────────────────\n\n private emitPendingChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.pending$.emit({ documentId, pending: docState.pending });\n }\n }\n\n private emitSelectedChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.selected$.emit({ documentId, selected: docState.selected });\n }\n }\n\n private emitStateChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.state$.emit({ documentId, state: docState });\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Store Update Handlers\n // ─────────────────────────────────────────────────────────\n\n override onStoreUpdated(_: RedactionState, newState: RedactionState): void {\n // Emit state changes for each changed document\n for (const documentId in newState.documents) {\n const docState = newState.documents[documentId];\n if (docState) {\n this.emitPendingChange(documentId);\n this.emitSelectedChange(documentId);\n this.emitStateChange(documentId);\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async destroy(): Promise<void> {\n this.pending$.clear();\n this.selected$.clear();\n this.state$.clear();\n this.events$.clear();\n\n // Cleanup all per-document emitters\n this.redactionSelection$.forEach((emitter) => emitter.clear());\n this.redactionSelection$.clear();\n\n // Cleanup all unsubscribers\n this.documentUnsubscribers.forEach((unsubscribers) => {\n unsubscribers.forEach((unsub) => unsub());\n });\n this.documentUnsubscribers.clear();\n\n await super.destroy();\n }\n}\n","import { Position, Rect, Size } from '@embedpdf/models';\nimport { clamp } from '@embedpdf/core';\nimport {\n EmbedPdfPointerEvent,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nexport function createMarqueeHandler(opts: {\n pageSize: Size;\n scale: number;\n minDragPx?: number;\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n}): PointerEventHandlersWithLifecycle<EmbedPdfPointerEvent> {\n const { pageSize, scale, minDragPx = 5, onPreview, onCommit } = opts;\n\n let start: Position | null = null;\n let last: Rect | null = null;\n\n return {\n onPointerDown: (pos, evt) => {\n start = pos;\n last = { origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } };\n onPreview?.(last);\n evt.setPointerCapture?.();\n },\n onPointerMove: (pos) => {\n if (!start) return;\n const x = clamp(pos.x, 0, pageSize.width);\n const y = clamp(pos.y, 0, pageSize.height);\n last = {\n origin: { x: Math.min(start.x, x), y: Math.min(start.y, y) },\n size: { width: Math.abs(x - start.x), height: Math.abs(y - start.y) },\n };\n onPreview?.(last);\n },\n onPointerUp: (_pos, evt) => {\n if (last) {\n const dragPx = Math.max(last.size.width, last.size.height) * scale;\n if (dragPx > minDragPx) onCommit?.(last);\n }\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n onPointerCancel: (_pos, evt) => {\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n };\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { RedactionPluginConfig } from './types';\n\nexport const REDACTION_PLUGIN_ID = 'redaction';\n\nexport const manifest: PluginManifest<RedactionPluginConfig> = {\n id: REDACTION_PLUGIN_ID,\n name: 'Redaction Plugin',\n version: '1.0.0',\n provides: ['redaction'],\n requires: [],\n optional: ['interaction-manager', 'selection'],\n defaultConfig: {\n drawBlackBoxes: true,\n },\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { RedactionPluginConfig, RedactionState } from './types';\nimport { RedactionPlugin } from './redaction-plugin';\nimport { manifest, REDACTION_PLUGIN_ID } from './manifest';\nimport { RedactionAction } from './actions';\nimport { initialState, redactionReducer } from './reducer';\n\nexport const RedactionPluginPackage: PluginPackage<\n RedactionPlugin,\n RedactionPluginConfig,\n RedactionState,\n RedactionAction\n> = {\n manifest,\n create: (registry, config) => new RedactionPlugin(REDACTION_PLUGIN_ID, registry, config),\n reducer: redactionReducer,\n initialState: initialState,\n};\n\nexport * from './redaction-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './selectors';\nexport { initialState, initialDocumentState } from './reducer';\n","import { RedactionState, RedactionDocumentState } from './types';\n\nexport const getPendingRedactionsCount = (s: RedactionDocumentState) => s.pendingCount;\n\nexport const hasPendingRedactions = (s: RedactionDocumentState) => s.pendingCount > 0;\n\nexport const getDocumentPendingCount = (state: RedactionState, documentId: string): number => {\n return state.documents[documentId]?.pendingCount ?? 0;\n};\n\nexport const getTotalPendingCount = (state: RedactionState): number => {\n return Object.values(state.documents).reduce((sum, doc) => sum + doc.pendingCount, 0);\n};\n"],"names":["RedactionMode","INIT_REDACTION_STATE","CLEANUP_REDACTION_STATE","START_REDACTION","END_REDACTION","ADD_PENDING","REMOVE_PENDING","CLEAR_PENDING","SELECT_PENDING","DESELECT_PENDING","addPending","documentId","items","type","payload","removePending","page","id","clearPending","startRedaction","mode","calculatePendingCount","pending","Object","values","reduce","total","length","initialDocumentState","isRedacting","activeType","pendingCount","selected","initialState","documents","activeDocumentId","_RedactionPlugin","BasePlugin","constructor","registry","config","super","this","redactionSelection$","Map","pending$","createBehaviorEmitter","selected$","state$","events$","documentUnsubscribers","selectionCapability","_a","getPlugin","provides","interactionManagerCapability","_b","registerMode","MarqueeRedact","scope","exclusive","cursor","RedactSelection","_c","onModeChange","modeState","activeMode","dispatch","docState","getDocumentState","endRedaction","onDocumentLoadingStarted","state","initRedactionState","set","unsubscribers","selectionScope","forDocument","unsubSelection","onSelectionChange","formattedSelection","getFormattedSelection","emitter","get","emit","unsubEndSelection","onEndSelection","map","s","uuidV4","kind","pageIndex","rect","rects","segmentRects","clear","emitPendingChange","selectPending","push","logger","debug","onDocumentLoaded","enableForMode","onDocumentClosed","cleanupRedactionState","delete","forEach","unsub","initialize","_config","info","buildCapability","queueCurrentSelectionAsPending","enableMarqueeRedact","toggleMarqueeRedact","isMarqueeRedactActive","enableRedactSelection","toggleRedactSelection","isRedactSelectionActive","addPendingItems","removePendingItem","clearPendingItems","commitAllPending","commitPending","commitPendingOne","endRedactionMode","startRedactionMode","getSelectedPending","deselectPending","getState","getDocumentStateOrThrow","createRedactionScope","onPendingChange","on","onSelectedChange","onRedactionEvent","onStateChange","listener","event","getActiveDocumentId","Error","itemId","emitSelectedChange","activate","getActiveMode","activateDefaultMode","onRedactionSelectionChange","callback","registerMarqueeOnPage","opts","warn","coreDoc","coreState","core","document","pages","handlers","pageSize","scale","minDragPx","onPreview","onCommit","start","last","onPointerDown","pos","evt","origin","x","y","size","width","height","setPointerCapture","call","onPointerMove","clamp","Math","min","abs","onPointerUp","_pos","max","releasePointerCapture","onPointerCancel","createMarqueeHandler","r","item","off","registerAlways","_","target","currentTarget","off2","registerHandlers","modeId","PdfTaskHelper","reject","code","PdfErrorCode","NotFound","message","formatted","resolve","uniqueId","docId","find","it","pdfPage","task","Task","engine","redactTextInRects","drawBlackBoxes","wait","dispatchCoreAction","refreshPages","success","error","reason","Unknown","perPage","entries","p","Number","list","pagesToRefresh","Array","from","filter","tasks","all","emitStateChange","onStoreUpdated","newState","destroy","RedactionPlugin","REDACTION_PLUGIN_ID","manifest","name","version","requires","optional","defaultConfig","RedactionPluginPackage","create","reducer","action","removed","remainingDocs","next","concat","filtered","stillSelected","sum","doc"],"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/types.ts","../src/lib/actions.ts","../src/lib/handlers/marquee-redact.handler.ts","../src/lib/reducer.ts","../src/lib/redaction-plugin.ts","../src/lib/manifest.ts","../src/lib/selectors.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, EventHook } from '@embedpdf/core';\nimport { PdfErrorReason, Rect, Task } from '@embedpdf/models';\n\n// Redaction mode enum\nexport enum RedactionMode {\n MarqueeRedact = 'marqueeRedact',\n RedactSelection = 'redactSelection',\n}\n\nexport interface SelectedRedaction {\n page: number;\n id: string;\n}\n\n// Per-document redaction state\nexport interface RedactionDocumentState {\n isRedacting: boolean;\n activeType: RedactionMode | null;\n pending: Record<number, RedactionItem[]>;\n pendingCount: number;\n selected: SelectedRedaction | null;\n}\n\n// Plugin state\nexport interface RedactionState {\n documents: Record<string, RedactionDocumentState>;\n activeDocumentId: string | null;\n}\n\nexport type RedactionItem =\n | {\n id: string;\n kind: 'text';\n page: number;\n rect: Rect;\n rects: Rect[];\n }\n | {\n id: string;\n kind: 'area';\n page: number;\n rect: Rect;\n };\n\nexport interface MarqueeRedactCallback {\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n}\n\nexport interface RegisterMarqueeOnPageOptions {\n documentId: string;\n pageIndex: number;\n scale: number;\n callback: MarqueeRedactCallback;\n}\n\nexport interface RedactionPluginConfig extends BasePluginConfig {\n drawBlackBoxes: boolean;\n}\n\n// Events include documentId\nexport type RedactionEvent =\n | {\n type: 'add';\n documentId: string;\n items: RedactionItem[];\n }\n | {\n type: 'remove';\n documentId: string;\n page: number;\n id: string;\n }\n | {\n type: 'clear';\n documentId: string;\n }\n | {\n type: 'commit';\n documentId: string;\n success: boolean;\n error?: PdfErrorReason;\n };\n\nexport interface PendingChangeEvent {\n documentId: string;\n pending: Record<number, RedactionItem[]>;\n}\n\nexport interface SelectedChangeEvent {\n documentId: string;\n selected: SelectedRedaction | null;\n}\n\nexport interface StateChangeEvent {\n documentId: string;\n state: RedactionDocumentState;\n}\n\n// Scoped redaction capability\nexport interface RedactionScope {\n queueCurrentSelectionAsPending(): Task<boolean, PdfErrorReason>;\n\n enableMarqueeRedact(): void;\n toggleMarqueeRedact(): void;\n isMarqueeRedactActive(): boolean;\n\n enableRedactSelection(): void;\n toggleRedactSelection(): void;\n isRedactSelectionActive(): boolean;\n\n addPending(items: RedactionItem[]): void;\n removePending(page: number, id: string): void;\n clearPending(): void;\n commitAllPending(): Task<boolean, PdfErrorReason>;\n commitPending(page: number, id: string): Task<boolean, PdfErrorReason>;\n\n endRedaction(): void;\n startRedaction(): void;\n\n selectPending(page: number, id: string): void;\n getSelectedPending(): SelectedRedaction | null;\n deselectPending(): void;\n\n getState(): RedactionDocumentState;\n\n onPendingChange: EventHook<Record<number, RedactionItem[]>>;\n onSelectedChange: EventHook<SelectedRedaction | null>;\n onRedactionEvent: EventHook<RedactionEvent>;\n onStateChange: EventHook<RedactionDocumentState>;\n}\n\nexport interface RedactionCapability {\n // Active document operations\n queueCurrentSelectionAsPending(): Task<boolean, PdfErrorReason>;\n\n enableMarqueeRedact(): void;\n toggleMarqueeRedact(): void;\n isMarqueeRedactActive(): boolean;\n\n enableRedactSelection(): void;\n toggleRedactSelection(): void;\n isRedactSelectionActive(): boolean;\n\n addPending(items: RedactionItem[]): void;\n removePending(page: number, id: string): void;\n clearPending(): void;\n commitAllPending(): Task<boolean, PdfErrorReason>;\n commitPending(page: number, id: string): Task<boolean, PdfErrorReason>;\n\n endRedaction(): void;\n startRedaction(): void;\n\n selectPending(page: number, id: string): void;\n getSelectedPending(): SelectedRedaction | null;\n deselectPending(): void;\n\n getState(): RedactionDocumentState;\n\n // Document-scoped operations\n forDocument(documentId: string): RedactionScope;\n\n // Events (include documentId)\n onPendingChange: EventHook<PendingChangeEvent>;\n onSelectedChange: EventHook<SelectedChangeEvent>;\n onRedactionEvent: EventHook<RedactionEvent>;\n onStateChange: EventHook<StateChangeEvent>;\n}\n","import { Action } from '@embedpdf/core';\nimport { RedactionItem, RedactionMode, RedactionDocumentState } from './types';\n\n// Document lifecycle\nexport const INIT_REDACTION_STATE = 'REDACTION/INIT_STATE';\nexport const CLEANUP_REDACTION_STATE = 'REDACTION/CLEANUP_STATE';\nexport const SET_ACTIVE_DOCUMENT = 'REDACTION/SET_ACTIVE_DOCUMENT';\n\n// Per-document redaction operations\nexport const START_REDACTION = 'START_REDACTION';\nexport const END_REDACTION = 'END_REDACTION';\nexport const SET_ACTIVE_TYPE = 'SET_ACTIVE_TYPE';\n\nexport const ADD_PENDING = 'ADD_PENDING';\nexport const REMOVE_PENDING = 'REMOVE_PENDING';\nexport const CLEAR_PENDING = 'CLEAR_PENDING';\n\nexport const SELECT_PENDING = 'SELECT_PENDING';\nexport const DESELECT_PENDING = 'DESELECT_PENDING';\n\n// Document lifecycle actions\nexport interface InitRedactionStateAction extends Action {\n type: typeof INIT_REDACTION_STATE;\n payload: {\n documentId: string;\n state: RedactionDocumentState;\n };\n}\n\nexport interface CleanupRedactionStateAction extends Action {\n type: typeof CLEANUP_REDACTION_STATE;\n payload: string; // documentId\n}\n\nexport interface SetActiveDocumentAction extends Action {\n type: typeof SET_ACTIVE_DOCUMENT;\n payload: string | null; // documentId\n}\n\n// Per-document operation actions\nexport interface StartRedactionAction extends Action {\n type: typeof START_REDACTION;\n payload: {\n documentId: string;\n mode: RedactionMode;\n };\n}\n\nexport interface EndRedactionAction extends Action {\n type: typeof END_REDACTION;\n payload: string; // documentId\n}\n\nexport interface SetActiveTypeAction extends Action {\n type: typeof SET_ACTIVE_TYPE;\n payload: {\n documentId: string;\n mode: RedactionMode | null;\n };\n}\n\nexport interface AddPendingAction extends Action {\n type: typeof ADD_PENDING;\n payload: {\n documentId: string;\n items: RedactionItem[];\n };\n}\n\nexport interface RemovePendingAction extends Action {\n type: typeof REMOVE_PENDING;\n payload: {\n documentId: string;\n page: number;\n id: string;\n };\n}\n\nexport interface ClearPendingAction extends Action {\n type: typeof CLEAR_PENDING;\n payload: string; // documentId\n}\n\nexport interface SelectPendingAction extends Action {\n type: typeof SELECT_PENDING;\n payload: {\n documentId: string;\n page: number;\n id: string;\n };\n}\n\nexport interface DeselectPendingAction extends Action {\n type: typeof DESELECT_PENDING;\n payload: string; // documentId\n}\n\nexport type RedactionAction =\n | InitRedactionStateAction\n | CleanupRedactionStateAction\n | SetActiveDocumentAction\n | StartRedactionAction\n | EndRedactionAction\n | SetActiveTypeAction\n | AddPendingAction\n | RemovePendingAction\n | ClearPendingAction\n | SelectPendingAction\n | DeselectPendingAction;\n\n// Action Creators\n\nexport function initRedactionState(\n documentId: string,\n state: RedactionDocumentState,\n): InitRedactionStateAction {\n return { type: INIT_REDACTION_STATE, payload: { documentId, state } };\n}\n\nexport function cleanupRedactionState(documentId: string): CleanupRedactionStateAction {\n return { type: CLEANUP_REDACTION_STATE, payload: documentId };\n}\n\nexport function setActiveDocument(documentId: string | null): SetActiveDocumentAction {\n return { type: SET_ACTIVE_DOCUMENT, payload: documentId };\n}\n\nexport const addPending = (documentId: string, items: RedactionItem[]): AddPendingAction => ({\n type: ADD_PENDING,\n payload: { documentId, items },\n});\n\nexport const removePending = (\n documentId: string,\n page: number,\n id: string,\n): RemovePendingAction => ({\n type: REMOVE_PENDING,\n payload: { documentId, page, id },\n});\n\nexport const clearPending = (documentId: string): ClearPendingAction => ({\n type: CLEAR_PENDING,\n payload: documentId,\n});\n\nexport const startRedaction = (documentId: string, mode: RedactionMode): StartRedactionAction => ({\n type: START_REDACTION,\n payload: { documentId, mode },\n});\n\nexport const endRedaction = (documentId: string): EndRedactionAction => ({\n type: END_REDACTION,\n payload: documentId,\n});\n\nexport const setActiveType = (\n documentId: string,\n mode: RedactionMode | null,\n): SetActiveTypeAction => ({\n type: SET_ACTIVE_TYPE,\n payload: { documentId, mode },\n});\n\nexport const selectPending = (\n documentId: string,\n page: number,\n id: string,\n): SelectPendingAction => ({\n type: SELECT_PENDING,\n payload: { documentId, page, id },\n});\n\nexport const deselectPending = (documentId: string): DeselectPendingAction => ({\n type: DESELECT_PENDING,\n payload: documentId,\n});\n","import { Position, Rect, Size } from '@embedpdf/models';\nimport { clamp } from '@embedpdf/core';\nimport {\n EmbedPdfPointerEvent,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nexport function createMarqueeHandler(opts: {\n pageSize: Size;\n scale: number;\n minDragPx?: number;\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n}): PointerEventHandlersWithLifecycle<EmbedPdfPointerEvent> {\n const { pageSize, scale, minDragPx = 5, onPreview, onCommit } = opts;\n\n let start: Position | null = null;\n let last: Rect | null = null;\n\n return {\n onPointerDown: (pos, evt) => {\n start = pos;\n last = { origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } };\n onPreview?.(last);\n evt.setPointerCapture?.();\n },\n onPointerMove: (pos) => {\n if (!start) return;\n const x = clamp(pos.x, 0, pageSize.width);\n const y = clamp(pos.y, 0, pageSize.height);\n last = {\n origin: { x: Math.min(start.x, x), y: Math.min(start.y, y) },\n size: { width: Math.abs(x - start.x), height: Math.abs(y - start.y) },\n };\n onPreview?.(last);\n },\n onPointerUp: (_pos, evt) => {\n if (last) {\n const dragPx = Math.max(last.size.width, last.size.height) * scale;\n if (dragPx > minDragPx) onCommit?.(last);\n }\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n onPointerCancel: (_pos, evt) => {\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n };\n}\n","import { Reducer } from '@embedpdf/core';\nimport { RedactionItem, RedactionState, RedactionDocumentState } from './types';\nimport {\n RedactionAction,\n INIT_REDACTION_STATE,\n CLEANUP_REDACTION_STATE,\n SET_ACTIVE_DOCUMENT,\n ADD_PENDING,\n CLEAR_PENDING,\n END_REDACTION,\n REMOVE_PENDING,\n START_REDACTION,\n SET_ACTIVE_TYPE,\n SELECT_PENDING,\n DESELECT_PENDING,\n} from './actions';\n\n// Helper function to calculate total pending count\nconst calculatePendingCount = (pending: Record<number, RedactionItem[]>): number => {\n return Object.values(pending).reduce((total, items) => total + items.length, 0);\n};\n\nexport const initialDocumentState: RedactionDocumentState = {\n isRedacting: false,\n activeType: null,\n pending: {},\n pendingCount: 0,\n selected: null,\n};\n\nexport const initialState: RedactionState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const redactionReducer: Reducer<RedactionState, RedactionAction> = (\n state = initialState,\n action,\n) => {\n switch (action.type) {\n case INIT_REDACTION_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_REDACTION_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_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n case ADD_PENDING: {\n const { documentId, items } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const next = { ...docState.pending };\n for (const item of items) {\n next[item.page] = (next[item.page] ?? []).concat(item);\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n pending: next,\n pendingCount: calculatePendingCount(next),\n },\n },\n };\n }\n\n case REMOVE_PENDING: {\n const { documentId, page, id } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const list = docState.pending[page] ?? [];\n const filtered = list.filter((it) => it.id !== id);\n const next = { ...docState.pending, [page]: filtered };\n\n // if the removed one was selected → clear selection\n const stillSelected =\n docState.selected && !(docState.selected.page === page && docState.selected.id === id);\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n pending: next,\n pendingCount: calculatePendingCount(next),\n selected: stillSelected ? docState.selected : null,\n },\n },\n };\n }\n\n case CLEAR_PENDING: {\n const documentId = 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 pending: {},\n pendingCount: 0,\n selected: null,\n },\n },\n };\n }\n\n case SELECT_PENDING: {\n const { documentId, page, id } = 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 selected: { page, id },\n },\n },\n };\n }\n\n case DESELECT_PENDING: {\n const documentId = 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 selected: null,\n },\n },\n };\n }\n\n case START_REDACTION: {\n const { documentId, mode } = 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 isRedacting: true,\n activeType: mode,\n },\n },\n };\n }\n\n case END_REDACTION: {\n const documentId = 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 pending: {},\n pendingCount: 0,\n selected: null,\n isRedacting: false,\n activeType: null,\n },\n },\n };\n }\n\n case SET_ACTIVE_TYPE: {\n const { documentId, mode } = 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 activeType: mode,\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import {\n RedactionPluginConfig,\n RedactionCapability,\n RedactionState,\n RegisterMarqueeOnPageOptions,\n RedactionItem,\n SelectedRedaction,\n RedactionMode,\n RedactionEvent,\n RedactionScope,\n StateChangeEvent,\n PendingChangeEvent,\n SelectedChangeEvent,\n RedactionDocumentState,\n} from './types';\nimport {\n BasePlugin,\n createBehaviorEmitter,\n PluginRegistry,\n refreshPages,\n Listener,\n} from '@embedpdf/core';\nimport {\n PdfErrorCode,\n PdfErrorReason,\n PdfTask,\n PdfTaskHelper,\n Rect,\n Task,\n uuidV4,\n} from '@embedpdf/models';\nimport {\n FormattedSelection,\n SelectionCapability,\n SelectionPlugin,\n} from '@embedpdf/plugin-selection';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport {\n addPending,\n clearPending,\n deselectPending,\n endRedaction,\n removePending,\n selectPending,\n startRedaction,\n initRedactionState,\n cleanupRedactionState,\n RedactionAction,\n} from './actions';\nimport { createMarqueeHandler } from './handlers';\nimport { initialDocumentState } from './reducer';\n\nexport class RedactionPlugin extends BasePlugin<\n RedactionPluginConfig,\n RedactionCapability,\n RedactionState,\n RedactionAction\n> {\n static readonly id = 'redaction' as const;\n\n private config: RedactionPluginConfig;\n private selectionCapability: SelectionCapability | undefined;\n private interactionManagerCapability: InteractionManagerCapability | undefined;\n\n // Per-document emitters\n private readonly redactionSelection$ = new Map<\n string,\n ReturnType<typeof createBehaviorEmitter<FormattedSelection[]>>\n >();\n\n // Global emitters with documentId\n private readonly pending$ = createBehaviorEmitter<PendingChangeEvent>();\n private readonly selected$ = createBehaviorEmitter<SelectedChangeEvent>();\n private readonly state$ = createBehaviorEmitter<StateChangeEvent>();\n private readonly events$ = createBehaviorEmitter<RedactionEvent>();\n\n // Per-document unsubscribe functions\n private readonly documentUnsubscribers = new Map<string, Array<() => void>>();\n\n constructor(id: string, registry: PluginRegistry, config: RedactionPluginConfig) {\n super(id, registry);\n this.config = config;\n\n this.selectionCapability = this.registry.getPlugin<SelectionPlugin>('selection')?.provides();\n this.interactionManagerCapability = this.registry\n .getPlugin<InteractionManagerPlugin>('interaction-manager')\n ?.provides();\n\n if (this.interactionManagerCapability) {\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.MarqueeRedact,\n scope: 'page',\n exclusive: true,\n cursor: 'crosshair',\n });\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.RedactSelection,\n scope: 'page',\n exclusive: false,\n });\n }\n\n // Listen to mode changes per document\n this.interactionManagerCapability?.onModeChange((modeState) => {\n const documentId = modeState.documentId;\n\n if (modeState.activeMode === RedactionMode.RedactSelection) {\n this.dispatch(startRedaction(documentId, RedactionMode.RedactSelection));\n } else if (modeState.activeMode === RedactionMode.MarqueeRedact) {\n this.dispatch(startRedaction(documentId, RedactionMode.MarqueeRedact));\n } else {\n const docState = this.getDocumentState(documentId);\n if (docState?.isRedacting) {\n this.dispatch(endRedaction(documentId));\n }\n }\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle Hooks (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n // Initialize state for this document\n this.dispatch(\n initRedactionState(documentId, {\n ...initialDocumentState,\n }),\n );\n\n // Create per-document emitter\n this.redactionSelection$.set(documentId, createBehaviorEmitter<FormattedSelection[]>());\n // Setup selection listeners for this document\n const unsubscribers: Array<() => void> = [];\n\n if (this.selectionCapability) {\n const selectionScope = this.selectionCapability.forDocument(documentId);\n\n // Listen to selection changes\n const unsubSelection = selectionScope.onSelectionChange(() => {\n const docState = this.getDocumentState(documentId);\n if (!docState?.isRedacting) return;\n\n const formattedSelection = selectionScope.getFormattedSelection();\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.emit(formattedSelection);\n });\n\n // Listen to end selection\n const unsubEndSelection = selectionScope.onEndSelection(() => {\n const docState = this.getDocumentState(documentId);\n if (!docState?.isRedacting) return;\n\n const formattedSelection = selectionScope.getFormattedSelection();\n\n const items: RedactionItem[] = formattedSelection.map((s) => ({\n id: uuidV4(),\n kind: 'text',\n page: s.pageIndex,\n rect: s.rect,\n rects: s.segmentRects,\n }));\n\n this.dispatch(addPending(documentId, items));\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.emit([]);\n selectionScope.clear();\n\n this.emitPendingChange(documentId);\n\n if (items.length) {\n this.selectPending(items[items.length - 1].page, items[items.length - 1].id, documentId);\n }\n });\n\n unsubscribers.push(unsubSelection, unsubEndSelection);\n }\n\n this.documentUnsubscribers.set(documentId, unsubscribers);\n\n this.logger.debug(\n 'RedactionPlugin',\n 'DocumentOpened',\n `Initialized redaction state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentLoaded(documentId: string): void {\n this.selectionCapability?.enableForMode(RedactionMode.RedactSelection, documentId);\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup state\n this.dispatch(cleanupRedactionState(documentId));\n\n // Cleanup emitters\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.clear();\n this.redactionSelection$.delete(documentId);\n\n // Cleanup unsubscribers\n const unsubscribers = this.documentUnsubscribers.get(documentId);\n if (unsubscribers) {\n unsubscribers.forEach((unsub) => unsub());\n this.documentUnsubscribers.delete(documentId);\n }\n\n this.logger.debug(\n 'RedactionPlugin',\n 'DocumentClosed',\n `Cleaned up redaction state for document: ${documentId}`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n async initialize(_config: RedactionPluginConfig): Promise<void> {\n this.logger.info('RedactionPlugin', 'Initialize', 'Redaction plugin initialized');\n }\n\n protected buildCapability(): RedactionCapability {\n return {\n // Active document operations\n queueCurrentSelectionAsPending: () => this.queueCurrentSelectionAsPending(),\n\n enableMarqueeRedact: () => this.enableMarqueeRedact(),\n toggleMarqueeRedact: () => this.toggleMarqueeRedact(),\n isMarqueeRedactActive: () => this.isMarqueeRedactActive(),\n\n enableRedactSelection: () => this.enableRedactSelection(),\n toggleRedactSelection: () => this.toggleRedactSelection(),\n isRedactSelectionActive: () => this.isRedactSelectionActive(),\n\n addPending: (items) => this.addPendingItems(items),\n removePending: (page, id) => this.removePendingItem(page, id),\n clearPending: () => this.clearPendingItems(),\n commitAllPending: () => this.commitAllPending(),\n commitPending: (page, id) => this.commitPendingOne(page, id),\n\n endRedaction: () => this.endRedactionMode(),\n startRedaction: () => this.startRedactionMode(),\n\n selectPending: (page, id) => this.selectPending(page, id),\n getSelectedPending: () => this.getSelectedPending(),\n deselectPending: () => this.deselectPending(),\n\n getState: () => this.getDocumentStateOrThrow(),\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createRedactionScope(documentId),\n\n // Events\n onPendingChange: this.pending$.on,\n onSelectedChange: this.selected$.on,\n onRedactionEvent: this.events$.on,\n onStateChange: this.state$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createRedactionScope(documentId: string): RedactionScope {\n return {\n queueCurrentSelectionAsPending: () => this.queueCurrentSelectionAsPending(documentId),\n\n enableMarqueeRedact: () => this.enableMarqueeRedact(documentId),\n toggleMarqueeRedact: () => this.toggleMarqueeRedact(documentId),\n isMarqueeRedactActive: () => this.isMarqueeRedactActive(documentId),\n\n enableRedactSelection: () => this.enableRedactSelection(documentId),\n toggleRedactSelection: () => this.toggleRedactSelection(documentId),\n isRedactSelectionActive: () => this.isRedactSelectionActive(documentId),\n\n addPending: (items) => this.addPendingItems(items, documentId),\n removePending: (page, id) => this.removePendingItem(page, id, documentId),\n clearPending: () => this.clearPendingItems(documentId),\n commitAllPending: () => this.commitAllPending(documentId),\n commitPending: (page, id) => this.commitPendingOne(page, id, documentId),\n\n endRedaction: () => this.endRedactionMode(documentId),\n startRedaction: () => this.startRedactionMode(documentId),\n\n selectPending: (page, id) => this.selectPending(page, id, documentId),\n getSelectedPending: () => this.getSelectedPending(documentId),\n deselectPending: () => this.deselectPending(documentId),\n\n getState: () => this.getDocumentStateOrThrow(documentId),\n\n onPendingChange: (listener: Listener<Record<number, RedactionItem[]>>) =>\n this.pending$.on((event) => {\n if (event.documentId === documentId) listener(event.pending);\n }),\n onSelectedChange: (listener: Listener<SelectedRedaction | null>) =>\n this.selected$.on((event) => {\n if (event.documentId === documentId) listener(event.selected);\n }),\n onRedactionEvent: (listener: Listener<RedactionEvent>) =>\n this.events$.on((event) => {\n if (event.documentId === documentId) listener(event);\n }),\n onStateChange: (listener: Listener<RedactionDocumentState>) =>\n this.state$.on((event) => {\n if (event.documentId === documentId) listener(event.state);\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // State Helpers\n // ─────────────────────────────────────────────────────────\n\n private getDocumentState(documentId?: string): RedactionDocumentState | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.state.documents[id] ?? null;\n }\n\n private getDocumentStateOrThrow(documentId?: string): RedactionDocumentState {\n const state = this.getDocumentState(documentId);\n if (!state) {\n throw new Error(`Redaction state not found for document: ${documentId ?? 'active'}`);\n }\n return state;\n }\n\n // ─────────────────────────────────────────────────────────\n // Core Operations\n // ─────────────────────────────────────────────────────────\n\n private addPendingItems(items: RedactionItem[], documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(addPending(id, items));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'add', documentId: id, items });\n }\n\n private removePendingItem(page: number, itemId: string, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(removePending(id, page, itemId));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'remove', documentId: id, page, id: itemId });\n }\n\n private clearPendingItems(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(clearPending(id));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'clear', documentId: id });\n }\n\n private selectPending(page: number, itemId: string, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(selectPending(id, page, itemId));\n this.selectionCapability?.forDocument(id).clear();\n this.emitSelectedChange(id);\n }\n\n private getSelectedPending(documentId?: string): SelectedRedaction | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.getDocumentState(id)?.selected ?? null;\n }\n\n private deselectPending(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(deselectPending(id));\n this.emitSelectedChange(id);\n }\n\n private enableRedactSelection(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.RedactSelection);\n }\n\n private toggleRedactSelection(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManagerCapability?.forDocument(id);\n if (scope?.getActiveMode() === RedactionMode.RedactSelection) {\n scope.activateDefaultMode();\n } else {\n scope?.activate(RedactionMode.RedactSelection);\n }\n }\n\n private isRedactSelectionActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return (\n this.interactionManagerCapability?.forDocument(id).getActiveMode() ===\n RedactionMode.RedactSelection\n );\n }\n\n private enableMarqueeRedact(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.MarqueeRedact);\n }\n\n private toggleMarqueeRedact(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManagerCapability?.forDocument(id);\n if (scope?.getActiveMode() === RedactionMode.MarqueeRedact) {\n scope.activateDefaultMode();\n } else {\n scope?.activate(RedactionMode.MarqueeRedact);\n }\n }\n\n private isMarqueeRedactActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return (\n this.interactionManagerCapability?.forDocument(id).getActiveMode() ===\n RedactionMode.MarqueeRedact\n );\n }\n\n private startRedactionMode(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.RedactSelection);\n }\n\n private endRedactionMode(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activateDefaultMode();\n }\n\n // ─────────────────────────────────────────────────────────\n // Public Methods\n // ─────────────────────────────────────────────────────────\n\n public onRedactionSelectionChange(\n documentId: string,\n callback: (formattedSelection: FormattedSelection[]) => void,\n ) {\n const emitter = this.redactionSelection$.get(documentId);\n return emitter?.on(callback) ?? (() => {});\n }\n\n public registerMarqueeOnPage(opts: RegisterMarqueeOnPageOptions) {\n if (!this.interactionManagerCapability) {\n this.logger.warn(\n 'RedactionPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, marquee redaction disabled',\n );\n return () => {};\n }\n\n const coreDoc = this.coreState.core.documents[opts.documentId];\n if (!coreDoc?.document) {\n this.logger.warn('RedactionPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = coreDoc.document.pages[opts.pageIndex];\n if (!page) {\n this.logger.warn('RedactionPlugin', 'PageNotFound', `Page ${opts.pageIndex} not found`);\n return () => {};\n }\n\n const handlers = createMarqueeHandler({\n pageSize: page.size,\n scale: opts.scale,\n onPreview: opts.callback.onPreview,\n onCommit: (r) => {\n const item: RedactionItem = {\n id: uuidV4(),\n kind: 'area',\n page: opts.pageIndex,\n rect: r,\n };\n this.dispatch(addPending(opts.documentId, [item]));\n this.emitPendingChange(opts.documentId);\n opts.callback.onCommit?.(r);\n this.enableRedactSelection(opts.documentId);\n this.selectPending(opts.pageIndex, item.id, opts.documentId);\n },\n });\n\n const off = this.interactionManagerCapability.registerAlways({\n handlers: {\n onPointerDown: (_, evt) => {\n if (evt.target === evt.currentTarget) {\n this.deselectPending(opts.documentId);\n }\n },\n },\n scope: {\n type: 'page',\n documentId: opts.documentId,\n pageIndex: opts.pageIndex,\n },\n });\n\n const off2 = this.interactionManagerCapability.registerHandlers({\n documentId: opts.documentId,\n modeId: RedactionMode.MarqueeRedact,\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return () => {\n off();\n off2();\n };\n }\n\n private queueCurrentSelectionAsPending(documentId?: string): Task<boolean, PdfErrorReason> {\n const id = documentId ?? this.getActiveDocumentId();\n\n if (!this.selectionCapability)\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: '[RedactionPlugin] selection plugin required',\n });\n\n const coreDoc = this.coreState.core.documents[id];\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const selectionScope = this.selectionCapability.forDocument(id);\n const formatted = selectionScope.getFormattedSelection();\n if (!formatted.length) return PdfTaskHelper.resolve(true);\n\n const uniqueId = uuidV4();\n\n const items: RedactionItem[] = formatted.map((s) => ({\n id: uniqueId,\n kind: 'text',\n page: s.pageIndex,\n rect: s.rect,\n rects: s.segmentRects,\n }));\n\n this.enableRedactSelection(id);\n this.dispatch(addPending(id, items));\n this.emitPendingChange(id);\n\n // Auto-select the last one added\n const last = items[items.length - 1];\n this.selectPending(last.page, last.id, id);\n\n // Clear live UI selection\n const emitter = this.redactionSelection$.get(id);\n emitter?.emit([]);\n selectionScope.clear();\n\n return PdfTaskHelper.resolve(true);\n }\n\n private commitPendingOne(\n page: number,\n id: string,\n documentId?: string,\n ): Task<boolean, PdfErrorReason> {\n const docId = documentId ?? this.getActiveDocumentId();\n const coreDoc = this.coreState.core.documents[docId];\n\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const docState = this.getDocumentState(docId);\n if (!docState) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Document state not found',\n });\n }\n\n const item = (docState.pending[page] ?? []).find((it) => it.id === id);\n if (!item) return PdfTaskHelper.resolve(true);\n\n const rects: Rect[] = item.kind === 'text' ? item.rects : [item.rect];\n const pdfPage = coreDoc.document.pages[page];\n if (!pdfPage)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Page not found' });\n\n const task = new Task<boolean, PdfErrorReason>();\n this.engine\n .redactTextInRects(coreDoc.document, pdfPage, rects, {\n drawBlackBoxes: this.config.drawBlackBoxes,\n })\n .wait(\n () => {\n this.dispatch(removePending(docId, page, id));\n this.emitPendingChange(docId);\n this.dispatchCoreAction(refreshPages(docId, [page]));\n this.events$.emit({ type: 'commit', documentId: docId, success: true });\n task.resolve(true);\n },\n (error) => {\n this.events$.emit({\n type: 'commit',\n documentId: docId,\n success: false,\n error: error.reason,\n });\n task.reject({ code: PdfErrorCode.Unknown, message: 'Failed to commit redactions' });\n },\n );\n\n return task;\n }\n\n private commitAllPending(documentId?: string): Task<boolean, PdfErrorReason> {\n const docId = documentId ?? this.getActiveDocumentId();\n const coreDoc = this.coreState.core.documents[docId];\n\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const docState = this.getDocumentState(docId);\n if (!docState) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Document state not found',\n });\n }\n\n // Group rects per page\n const perPage = new Map<number, Rect[]>();\n for (const [page, items] of Object.entries(docState.pending)) {\n const p = Number(page);\n const list = perPage.get(p) ?? [];\n for (const it of items) {\n if (it.kind === 'text') list.push(...it.rects);\n else list.push(it.rect);\n }\n perPage.set(p, list);\n }\n\n const pagesToRefresh = Array.from(perPage.entries())\n .filter(([_, rects]) => rects.length > 0)\n .map(([pageIndex]) => pageIndex);\n\n const tasks: PdfTask<boolean>[] = [];\n for (const [pageIndex, rects] of perPage) {\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n if (!rects.length) continue;\n tasks.push(\n this.engine.redactTextInRects(coreDoc.document, page, rects, {\n drawBlackBoxes: this.config.drawBlackBoxes,\n }),\n );\n }\n\n const task = new Task<boolean, PdfErrorReason>();\n Task.all(tasks).wait(\n () => {\n this.dispatch(clearPending(docId));\n this.dispatchCoreAction(refreshPages(docId, pagesToRefresh));\n this.emitPendingChange(docId);\n this.events$.emit({ type: 'commit', documentId: docId, success: true });\n task.resolve(true);\n },\n (error) => {\n this.events$.emit({\n type: 'commit',\n documentId: docId,\n success: false,\n error: error.reason,\n });\n task.reject({ code: PdfErrorCode.Unknown, message: 'Failed to commit redactions' });\n },\n );\n\n return task;\n }\n\n // ─────────────────────────────────────────────────────────\n // Event Emission Helpers\n // ─────────────────────────────────────────────────────────\n\n private emitPendingChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.pending$.emit({ documentId, pending: docState.pending });\n }\n }\n\n private emitSelectedChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.selected$.emit({ documentId, selected: docState.selected });\n }\n }\n\n private emitStateChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.state$.emit({ documentId, state: docState });\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Store Update Handlers\n // ─────────────────────────────────────────────────────────\n\n override onStoreUpdated(_: RedactionState, newState: RedactionState): void {\n // Emit state changes for each changed document\n for (const documentId in newState.documents) {\n const docState = newState.documents[documentId];\n if (docState) {\n this.emitPendingChange(documentId);\n this.emitSelectedChange(documentId);\n this.emitStateChange(documentId);\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async destroy(): Promise<void> {\n this.pending$.clear();\n this.selected$.clear();\n this.state$.clear();\n this.events$.clear();\n\n // Cleanup all per-document emitters\n this.redactionSelection$.forEach((emitter) => emitter.clear());\n this.redactionSelection$.clear();\n\n // Cleanup all unsubscribers\n this.documentUnsubscribers.forEach((unsubscribers) => {\n unsubscribers.forEach((unsub) => unsub());\n });\n this.documentUnsubscribers.clear();\n\n await super.destroy();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { RedactionPluginConfig } from './types';\n\nexport const REDACTION_PLUGIN_ID = 'redaction';\n\nexport const manifest: PluginManifest<RedactionPluginConfig> = {\n id: REDACTION_PLUGIN_ID,\n name: 'Redaction Plugin',\n version: '1.0.0',\n provides: ['redaction'],\n requires: [],\n optional: ['interaction-manager', 'selection'],\n defaultConfig: {\n enabled: true,\n drawBlackBoxes: true,\n },\n};\n","import { RedactionState, RedactionDocumentState } from './types';\n\nexport const getPendingRedactionsCount = (s: RedactionDocumentState) => s.pendingCount;\n\nexport const hasPendingRedactions = (s: RedactionDocumentState) => s.pendingCount > 0;\n\nexport const getDocumentPendingCount = (state: RedactionState, documentId: string): number => {\n return state.documents[documentId]?.pendingCount ?? 0;\n};\n\nexport const getTotalPendingCount = (state: RedactionState): number => {\n return Object.values(state.documents).reduce((sum, doc) => sum + doc.pendingCount, 0);\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { RedactionPluginConfig, RedactionState } from './types';\nimport { RedactionPlugin } from './redaction-plugin';\nimport { manifest, REDACTION_PLUGIN_ID } from './manifest';\nimport { RedactionAction } from './actions';\nimport { initialState, redactionReducer } from './reducer';\n\nexport const RedactionPluginPackage: PluginPackage<\n RedactionPlugin,\n RedactionPluginConfig,\n RedactionState,\n RedactionAction\n> = {\n manifest,\n create: (registry, config) => new RedactionPlugin(REDACTION_PLUGIN_ID, registry, config),\n reducer: redactionReducer,\n initialState: initialState,\n};\n\nexport * from './redaction-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './selectors';\nexport { initialState, initialDocumentState } from './reducer';\n"],"names":["RedactionMode"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/lib/types.ts","../src/lib/actions.ts","../src/lib/handlers/marquee-redact.handler.ts","../src/lib/reducer.ts","../src/lib/redaction-plugin.ts","../src/lib/manifest.ts","../src/lib/selectors.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, EventHook } from '@embedpdf/core';\nimport { PdfErrorReason, Rect, Task } from '@embedpdf/models';\n\n// Redaction mode enum\nexport enum RedactionMode {\n MarqueeRedact = 'marqueeRedact',\n RedactSelection = 'redactSelection',\n}\n\nexport interface SelectedRedaction {\n page: number;\n id: string;\n}\n\n// Per-document redaction state\nexport interface RedactionDocumentState {\n isRedacting: boolean;\n activeType: RedactionMode | null;\n pending: Record<number, RedactionItem[]>;\n pendingCount: number;\n selected: SelectedRedaction | null;\n}\n\n// Plugin state\nexport interface RedactionState {\n documents: Record<string, RedactionDocumentState>;\n activeDocumentId: string | null;\n}\n\nexport type RedactionItem =\n | {\n id: string;\n kind: 'text';\n page: number;\n rect: Rect;\n rects: Rect[];\n }\n | {\n id: string;\n kind: 'area';\n page: number;\n rect: Rect;\n };\n\nexport interface MarqueeRedactCallback {\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n}\n\nexport interface RegisterMarqueeOnPageOptions {\n documentId: string;\n pageIndex: number;\n scale: number;\n callback: MarqueeRedactCallback;\n}\n\nexport interface RedactionPluginConfig extends BasePluginConfig {\n drawBlackBoxes: boolean;\n}\n\n// Events include documentId\nexport type RedactionEvent =\n | {\n type: 'add';\n documentId: string;\n items: RedactionItem[];\n }\n | {\n type: 'remove';\n documentId: string;\n page: number;\n id: string;\n }\n | {\n type: 'clear';\n documentId: string;\n }\n | {\n type: 'commit';\n documentId: string;\n success: boolean;\n error?: PdfErrorReason;\n };\n\nexport interface PendingChangeEvent {\n documentId: string;\n pending: Record<number, RedactionItem[]>;\n}\n\nexport interface SelectedChangeEvent {\n documentId: string;\n selected: SelectedRedaction | null;\n}\n\nexport interface StateChangeEvent {\n documentId: string;\n state: RedactionDocumentState;\n}\n\n// Scoped redaction capability\nexport interface RedactionScope {\n queueCurrentSelectionAsPending(): Task<boolean, PdfErrorReason>;\n\n enableMarqueeRedact(): void;\n toggleMarqueeRedact(): void;\n isMarqueeRedactActive(): boolean;\n\n enableRedactSelection(): void;\n toggleRedactSelection(): void;\n isRedactSelectionActive(): boolean;\n\n addPending(items: RedactionItem[]): void;\n removePending(page: number, id: string): void;\n clearPending(): void;\n commitAllPending(): Task<boolean, PdfErrorReason>;\n commitPending(page: number, id: string): Task<boolean, PdfErrorReason>;\n\n endRedaction(): void;\n startRedaction(): void;\n\n selectPending(page: number, id: string): void;\n getSelectedPending(): SelectedRedaction | null;\n deselectPending(): void;\n\n getState(): RedactionDocumentState;\n\n onPendingChange: EventHook<Record<number, RedactionItem[]>>;\n onSelectedChange: EventHook<SelectedRedaction | null>;\n onRedactionEvent: EventHook<RedactionEvent>;\n onStateChange: EventHook<RedactionDocumentState>;\n}\n\nexport interface RedactionCapability {\n // Active document operations\n queueCurrentSelectionAsPending(): Task<boolean, PdfErrorReason>;\n\n enableMarqueeRedact(): void;\n toggleMarqueeRedact(): void;\n isMarqueeRedactActive(): boolean;\n\n enableRedactSelection(): void;\n toggleRedactSelection(): void;\n isRedactSelectionActive(): boolean;\n\n addPending(items: RedactionItem[]): void;\n removePending(page: number, id: string): void;\n clearPending(): void;\n commitAllPending(): Task<boolean, PdfErrorReason>;\n commitPending(page: number, id: string): Task<boolean, PdfErrorReason>;\n\n endRedaction(): void;\n startRedaction(): void;\n\n selectPending(page: number, id: string): void;\n getSelectedPending(): SelectedRedaction | null;\n deselectPending(): void;\n\n getState(): RedactionDocumentState;\n\n // Document-scoped operations\n forDocument(documentId: string): RedactionScope;\n\n // Events (include documentId)\n onPendingChange: EventHook<PendingChangeEvent>;\n onSelectedChange: EventHook<SelectedChangeEvent>;\n onRedactionEvent: EventHook<RedactionEvent>;\n onStateChange: EventHook<StateChangeEvent>;\n}\n","import { Action } from '@embedpdf/core';\nimport { RedactionItem, RedactionMode, RedactionDocumentState } from './types';\n\n// Document lifecycle\nexport const INIT_REDACTION_STATE = 'REDACTION/INIT_STATE';\nexport const CLEANUP_REDACTION_STATE = 'REDACTION/CLEANUP_STATE';\nexport const SET_ACTIVE_DOCUMENT = 'REDACTION/SET_ACTIVE_DOCUMENT';\n\n// Per-document redaction operations\nexport const START_REDACTION = 'START_REDACTION';\nexport const END_REDACTION = 'END_REDACTION';\nexport const SET_ACTIVE_TYPE = 'SET_ACTIVE_TYPE';\n\nexport const ADD_PENDING = 'ADD_PENDING';\nexport const REMOVE_PENDING = 'REMOVE_PENDING';\nexport const CLEAR_PENDING = 'CLEAR_PENDING';\n\nexport const SELECT_PENDING = 'SELECT_PENDING';\nexport const DESELECT_PENDING = 'DESELECT_PENDING';\n\n// Document lifecycle actions\nexport interface InitRedactionStateAction extends Action {\n type: typeof INIT_REDACTION_STATE;\n payload: {\n documentId: string;\n state: RedactionDocumentState;\n };\n}\n\nexport interface CleanupRedactionStateAction extends Action {\n type: typeof CLEANUP_REDACTION_STATE;\n payload: string; // documentId\n}\n\nexport interface SetActiveDocumentAction extends Action {\n type: typeof SET_ACTIVE_DOCUMENT;\n payload: string | null; // documentId\n}\n\n// Per-document operation actions\nexport interface StartRedactionAction extends Action {\n type: typeof START_REDACTION;\n payload: {\n documentId: string;\n mode: RedactionMode;\n };\n}\n\nexport interface EndRedactionAction extends Action {\n type: typeof END_REDACTION;\n payload: string; // documentId\n}\n\nexport interface SetActiveTypeAction extends Action {\n type: typeof SET_ACTIVE_TYPE;\n payload: {\n documentId: string;\n mode: RedactionMode | null;\n };\n}\n\nexport interface AddPendingAction extends Action {\n type: typeof ADD_PENDING;\n payload: {\n documentId: string;\n items: RedactionItem[];\n };\n}\n\nexport interface RemovePendingAction extends Action {\n type: typeof REMOVE_PENDING;\n payload: {\n documentId: string;\n page: number;\n id: string;\n };\n}\n\nexport interface ClearPendingAction extends Action {\n type: typeof CLEAR_PENDING;\n payload: string; // documentId\n}\n\nexport interface SelectPendingAction extends Action {\n type: typeof SELECT_PENDING;\n payload: {\n documentId: string;\n page: number;\n id: string;\n };\n}\n\nexport interface DeselectPendingAction extends Action {\n type: typeof DESELECT_PENDING;\n payload: string; // documentId\n}\n\nexport type RedactionAction =\n | InitRedactionStateAction\n | CleanupRedactionStateAction\n | SetActiveDocumentAction\n | StartRedactionAction\n | EndRedactionAction\n | SetActiveTypeAction\n | AddPendingAction\n | RemovePendingAction\n | ClearPendingAction\n | SelectPendingAction\n | DeselectPendingAction;\n\n// Action Creators\n\nexport function initRedactionState(\n documentId: string,\n state: RedactionDocumentState,\n): InitRedactionStateAction {\n return { type: INIT_REDACTION_STATE, payload: { documentId, state } };\n}\n\nexport function cleanupRedactionState(documentId: string): CleanupRedactionStateAction {\n return { type: CLEANUP_REDACTION_STATE, payload: documentId };\n}\n\nexport function setActiveDocument(documentId: string | null): SetActiveDocumentAction {\n return { type: SET_ACTIVE_DOCUMENT, payload: documentId };\n}\n\nexport const addPending = (documentId: string, items: RedactionItem[]): AddPendingAction => ({\n type: ADD_PENDING,\n payload: { documentId, items },\n});\n\nexport const removePending = (\n documentId: string,\n page: number,\n id: string,\n): RemovePendingAction => ({\n type: REMOVE_PENDING,\n payload: { documentId, page, id },\n});\n\nexport const clearPending = (documentId: string): ClearPendingAction => ({\n type: CLEAR_PENDING,\n payload: documentId,\n});\n\nexport const startRedaction = (documentId: string, mode: RedactionMode): StartRedactionAction => ({\n type: START_REDACTION,\n payload: { documentId, mode },\n});\n\nexport const endRedaction = (documentId: string): EndRedactionAction => ({\n type: END_REDACTION,\n payload: documentId,\n});\n\nexport const setActiveType = (\n documentId: string,\n mode: RedactionMode | null,\n): SetActiveTypeAction => ({\n type: SET_ACTIVE_TYPE,\n payload: { documentId, mode },\n});\n\nexport const selectPending = (\n documentId: string,\n page: number,\n id: string,\n): SelectPendingAction => ({\n type: SELECT_PENDING,\n payload: { documentId, page, id },\n});\n\nexport const deselectPending = (documentId: string): DeselectPendingAction => ({\n type: DESELECT_PENDING,\n payload: documentId,\n});\n","import { Position, Rect, Size } from '@embedpdf/models';\nimport { clamp } from '@embedpdf/core';\nimport {\n EmbedPdfPointerEvent,\n PointerEventHandlersWithLifecycle,\n} from '@embedpdf/plugin-interaction-manager';\n\nexport function createMarqueeHandler(opts: {\n pageSize: Size;\n scale: number;\n minDragPx?: number;\n onPreview?: (rect: Rect | null) => void;\n onCommit?: (rect: Rect) => void;\n}): PointerEventHandlersWithLifecycle<EmbedPdfPointerEvent> {\n const { pageSize, scale, minDragPx = 5, onPreview, onCommit } = opts;\n\n let start: Position | null = null;\n let last: Rect | null = null;\n\n return {\n onPointerDown: (pos, evt) => {\n start = pos;\n last = { origin: { x: pos.x, y: pos.y }, size: { width: 0, height: 0 } };\n onPreview?.(last);\n evt.setPointerCapture?.();\n },\n onPointerMove: (pos) => {\n if (!start) return;\n const x = clamp(pos.x, 0, pageSize.width);\n const y = clamp(pos.y, 0, pageSize.height);\n last = {\n origin: { x: Math.min(start.x, x), y: Math.min(start.y, y) },\n size: { width: Math.abs(x - start.x), height: Math.abs(y - start.y) },\n };\n onPreview?.(last);\n },\n onPointerUp: (_pos, evt) => {\n if (last) {\n const dragPx = Math.max(last.size.width, last.size.height) * scale;\n if (dragPx > minDragPx) onCommit?.(last);\n }\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n onPointerCancel: (_pos, evt) => {\n start = null;\n last = null;\n onPreview?.(null);\n evt.releasePointerCapture?.();\n },\n };\n}\n","import { Reducer } from '@embedpdf/core';\nimport { RedactionItem, RedactionState, RedactionDocumentState } from './types';\nimport {\n RedactionAction,\n INIT_REDACTION_STATE,\n CLEANUP_REDACTION_STATE,\n SET_ACTIVE_DOCUMENT,\n ADD_PENDING,\n CLEAR_PENDING,\n END_REDACTION,\n REMOVE_PENDING,\n START_REDACTION,\n SET_ACTIVE_TYPE,\n SELECT_PENDING,\n DESELECT_PENDING,\n} from './actions';\n\n// Helper function to calculate total pending count\nconst calculatePendingCount = (pending: Record<number, RedactionItem[]>): number => {\n return Object.values(pending).reduce((total, items) => total + items.length, 0);\n};\n\nexport const initialDocumentState: RedactionDocumentState = {\n isRedacting: false,\n activeType: null,\n pending: {},\n pendingCount: 0,\n selected: null,\n};\n\nexport const initialState: RedactionState = {\n documents: {},\n activeDocumentId: null,\n};\n\nexport const redactionReducer: Reducer<RedactionState, RedactionAction> = (\n state = initialState,\n action,\n) => {\n switch (action.type) {\n case INIT_REDACTION_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_REDACTION_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_DOCUMENT: {\n return {\n ...state,\n activeDocumentId: action.payload,\n };\n }\n\n case ADD_PENDING: {\n const { documentId, items } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const next = { ...docState.pending };\n for (const item of items) {\n next[item.page] = (next[item.page] ?? []).concat(item);\n }\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n pending: next,\n pendingCount: calculatePendingCount(next),\n },\n },\n };\n }\n\n case REMOVE_PENDING: {\n const { documentId, page, id } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const list = docState.pending[page] ?? [];\n const filtered = list.filter((it) => it.id !== id);\n const next = { ...docState.pending, [page]: filtered };\n\n // if the removed one was selected → clear selection\n const stillSelected =\n docState.selected && !(docState.selected.page === page && docState.selected.id === id);\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n pending: next,\n pendingCount: calculatePendingCount(next),\n selected: stillSelected ? docState.selected : null,\n },\n },\n };\n }\n\n case CLEAR_PENDING: {\n const documentId = 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 pending: {},\n pendingCount: 0,\n selected: null,\n },\n },\n };\n }\n\n case SELECT_PENDING: {\n const { documentId, page, id } = 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 selected: { page, id },\n },\n },\n };\n }\n\n case DESELECT_PENDING: {\n const documentId = 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 selected: null,\n },\n },\n };\n }\n\n case START_REDACTION: {\n const { documentId, mode } = 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 isRedacting: true,\n activeType: mode,\n },\n },\n };\n }\n\n case END_REDACTION: {\n const documentId = 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 pending: {},\n pendingCount: 0,\n selected: null,\n isRedacting: false,\n activeType: null,\n },\n },\n };\n }\n\n case SET_ACTIVE_TYPE: {\n const { documentId, mode } = 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 activeType: mode,\n },\n },\n };\n }\n\n default:\n return state;\n }\n};\n","import {\n RedactionPluginConfig,\n RedactionCapability,\n RedactionState,\n RegisterMarqueeOnPageOptions,\n RedactionItem,\n SelectedRedaction,\n RedactionMode,\n RedactionEvent,\n RedactionScope,\n StateChangeEvent,\n PendingChangeEvent,\n SelectedChangeEvent,\n RedactionDocumentState,\n} from './types';\nimport {\n BasePlugin,\n createBehaviorEmitter,\n PluginRegistry,\n refreshPages,\n Listener,\n} from '@embedpdf/core';\nimport {\n PdfErrorCode,\n PdfErrorReason,\n PdfTask,\n PdfTaskHelper,\n Rect,\n Task,\n uuidV4,\n} from '@embedpdf/models';\nimport {\n FormattedSelection,\n SelectionCapability,\n SelectionPlugin,\n} from '@embedpdf/plugin-selection';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n} from '@embedpdf/plugin-interaction-manager';\nimport {\n addPending,\n clearPending,\n deselectPending,\n endRedaction,\n removePending,\n selectPending,\n startRedaction,\n initRedactionState,\n cleanupRedactionState,\n RedactionAction,\n} from './actions';\nimport { createMarqueeHandler } from './handlers';\nimport { initialDocumentState } from './reducer';\n\nexport class RedactionPlugin extends BasePlugin<\n RedactionPluginConfig,\n RedactionCapability,\n RedactionState,\n RedactionAction\n> {\n static readonly id = 'redaction' as const;\n\n private config: RedactionPluginConfig;\n private selectionCapability: SelectionCapability | undefined;\n private interactionManagerCapability: InteractionManagerCapability | undefined;\n\n // Per-document emitters\n private readonly redactionSelection$ = new Map<\n string,\n ReturnType<typeof createBehaviorEmitter<FormattedSelection[]>>\n >();\n\n // Global emitters with documentId\n private readonly pending$ = createBehaviorEmitter<PendingChangeEvent>();\n private readonly selected$ = createBehaviorEmitter<SelectedChangeEvent>();\n private readonly state$ = createBehaviorEmitter<StateChangeEvent>();\n private readonly events$ = createBehaviorEmitter<RedactionEvent>();\n\n // Per-document unsubscribe functions\n private readonly documentUnsubscribers = new Map<string, Array<() => void>>();\n\n constructor(id: string, registry: PluginRegistry, config: RedactionPluginConfig) {\n super(id, registry);\n this.config = config;\n\n this.selectionCapability = this.registry.getPlugin<SelectionPlugin>('selection')?.provides();\n this.interactionManagerCapability = this.registry\n .getPlugin<InteractionManagerPlugin>('interaction-manager')\n ?.provides();\n\n if (this.interactionManagerCapability) {\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.MarqueeRedact,\n scope: 'page',\n exclusive: true,\n cursor: 'crosshair',\n });\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.RedactSelection,\n scope: 'page',\n exclusive: false,\n });\n }\n\n // Listen to mode changes per document\n this.interactionManagerCapability?.onModeChange((modeState) => {\n const documentId = modeState.documentId;\n\n if (modeState.activeMode === RedactionMode.RedactSelection) {\n this.dispatch(startRedaction(documentId, RedactionMode.RedactSelection));\n } else if (modeState.activeMode === RedactionMode.MarqueeRedact) {\n this.dispatch(startRedaction(documentId, RedactionMode.MarqueeRedact));\n } else {\n const docState = this.getDocumentState(documentId);\n if (docState?.isRedacting) {\n this.dispatch(endRedaction(documentId));\n }\n }\n });\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Lifecycle Hooks (from BasePlugin)\n // ─────────────────────────────────────────────────────────\n\n protected override onDocumentLoadingStarted(documentId: string): void {\n // Initialize state for this document\n this.dispatch(\n initRedactionState(documentId, {\n ...initialDocumentState,\n }),\n );\n\n // Create per-document emitter\n this.redactionSelection$.set(documentId, createBehaviorEmitter<FormattedSelection[]>());\n // Setup selection listeners for this document\n const unsubscribers: Array<() => void> = [];\n\n if (this.selectionCapability) {\n const selectionScope = this.selectionCapability.forDocument(documentId);\n\n // Listen to selection changes\n const unsubSelection = selectionScope.onSelectionChange(() => {\n const docState = this.getDocumentState(documentId);\n if (!docState?.isRedacting) return;\n\n const formattedSelection = selectionScope.getFormattedSelection();\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.emit(formattedSelection);\n });\n\n // Listen to end selection\n const unsubEndSelection = selectionScope.onEndSelection(() => {\n const docState = this.getDocumentState(documentId);\n if (!docState?.isRedacting) return;\n\n const formattedSelection = selectionScope.getFormattedSelection();\n\n const items: RedactionItem[] = formattedSelection.map((s) => ({\n id: uuidV4(),\n kind: 'text',\n page: s.pageIndex,\n rect: s.rect,\n rects: s.segmentRects,\n }));\n\n this.dispatch(addPending(documentId, items));\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.emit([]);\n selectionScope.clear();\n\n this.emitPendingChange(documentId);\n\n if (items.length) {\n this.selectPending(items[items.length - 1].page, items[items.length - 1].id, documentId);\n }\n });\n\n unsubscribers.push(unsubSelection, unsubEndSelection);\n }\n\n this.documentUnsubscribers.set(documentId, unsubscribers);\n\n this.logger.debug(\n 'RedactionPlugin',\n 'DocumentOpened',\n `Initialized redaction state for document: ${documentId}`,\n );\n }\n\n protected override onDocumentLoaded(documentId: string): void {\n this.selectionCapability?.enableForMode(RedactionMode.RedactSelection, documentId);\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup state\n this.dispatch(cleanupRedactionState(documentId));\n\n // Cleanup emitters\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.clear();\n this.redactionSelection$.delete(documentId);\n\n // Cleanup unsubscribers\n const unsubscribers = this.documentUnsubscribers.get(documentId);\n if (unsubscribers) {\n unsubscribers.forEach((unsub) => unsub());\n this.documentUnsubscribers.delete(documentId);\n }\n\n this.logger.debug(\n 'RedactionPlugin',\n 'DocumentClosed',\n `Cleaned up redaction state for document: ${documentId}`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n async initialize(_config: RedactionPluginConfig): Promise<void> {\n this.logger.info('RedactionPlugin', 'Initialize', 'Redaction plugin initialized');\n }\n\n protected buildCapability(): RedactionCapability {\n return {\n // Active document operations\n queueCurrentSelectionAsPending: () => this.queueCurrentSelectionAsPending(),\n\n enableMarqueeRedact: () => this.enableMarqueeRedact(),\n toggleMarqueeRedact: () => this.toggleMarqueeRedact(),\n isMarqueeRedactActive: () => this.isMarqueeRedactActive(),\n\n enableRedactSelection: () => this.enableRedactSelection(),\n toggleRedactSelection: () => this.toggleRedactSelection(),\n isRedactSelectionActive: () => this.isRedactSelectionActive(),\n\n addPending: (items) => this.addPendingItems(items),\n removePending: (page, id) => this.removePendingItem(page, id),\n clearPending: () => this.clearPendingItems(),\n commitAllPending: () => this.commitAllPending(),\n commitPending: (page, id) => this.commitPendingOne(page, id),\n\n endRedaction: () => this.endRedactionMode(),\n startRedaction: () => this.startRedactionMode(),\n\n selectPending: (page, id) => this.selectPending(page, id),\n getSelectedPending: () => this.getSelectedPending(),\n deselectPending: () => this.deselectPending(),\n\n getState: () => this.getDocumentStateOrThrow(),\n\n // Document-scoped operations\n forDocument: (documentId: string) => this.createRedactionScope(documentId),\n\n // Events\n onPendingChange: this.pending$.on,\n onSelectedChange: this.selected$.on,\n onRedactionEvent: this.events$.on,\n onStateChange: this.state$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createRedactionScope(documentId: string): RedactionScope {\n return {\n queueCurrentSelectionAsPending: () => this.queueCurrentSelectionAsPending(documentId),\n\n enableMarqueeRedact: () => this.enableMarqueeRedact(documentId),\n toggleMarqueeRedact: () => this.toggleMarqueeRedact(documentId),\n isMarqueeRedactActive: () => this.isMarqueeRedactActive(documentId),\n\n enableRedactSelection: () => this.enableRedactSelection(documentId),\n toggleRedactSelection: () => this.toggleRedactSelection(documentId),\n isRedactSelectionActive: () => this.isRedactSelectionActive(documentId),\n\n addPending: (items) => this.addPendingItems(items, documentId),\n removePending: (page, id) => this.removePendingItem(page, id, documentId),\n clearPending: () => this.clearPendingItems(documentId),\n commitAllPending: () => this.commitAllPending(documentId),\n commitPending: (page, id) => this.commitPendingOne(page, id, documentId),\n\n endRedaction: () => this.endRedactionMode(documentId),\n startRedaction: () => this.startRedactionMode(documentId),\n\n selectPending: (page, id) => this.selectPending(page, id, documentId),\n getSelectedPending: () => this.getSelectedPending(documentId),\n deselectPending: () => this.deselectPending(documentId),\n\n getState: () => this.getDocumentStateOrThrow(documentId),\n\n onPendingChange: (listener: Listener<Record<number, RedactionItem[]>>) =>\n this.pending$.on((event) => {\n if (event.documentId === documentId) listener(event.pending);\n }),\n onSelectedChange: (listener: Listener<SelectedRedaction | null>) =>\n this.selected$.on((event) => {\n if (event.documentId === documentId) listener(event.selected);\n }),\n onRedactionEvent: (listener: Listener<RedactionEvent>) =>\n this.events$.on((event) => {\n if (event.documentId === documentId) listener(event);\n }),\n onStateChange: (listener: Listener<RedactionDocumentState>) =>\n this.state$.on((event) => {\n if (event.documentId === documentId) listener(event.state);\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // State Helpers\n // ─────────────────────────────────────────────────────────\n\n private getDocumentState(documentId?: string): RedactionDocumentState | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.state.documents[id] ?? null;\n }\n\n private getDocumentStateOrThrow(documentId?: string): RedactionDocumentState {\n const state = this.getDocumentState(documentId);\n if (!state) {\n throw new Error(`Redaction state not found for document: ${documentId ?? 'active'}`);\n }\n return state;\n }\n\n // ─────────────────────────────────────────────────────────\n // Core Operations\n // ─────────────────────────────────────────────────────────\n\n private addPendingItems(items: RedactionItem[], documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(addPending(id, items));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'add', documentId: id, items });\n }\n\n private removePendingItem(page: number, itemId: string, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(removePending(id, page, itemId));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'remove', documentId: id, page, id: itemId });\n }\n\n private clearPendingItems(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(clearPending(id));\n this.emitPendingChange(id);\n this.events$.emit({ type: 'clear', documentId: id });\n }\n\n private selectPending(page: number, itemId: string, documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(selectPending(id, page, itemId));\n this.selectionCapability?.forDocument(id).clear();\n this.emitSelectedChange(id);\n }\n\n private getSelectedPending(documentId?: string): SelectedRedaction | null {\n const id = documentId ?? this.getActiveDocumentId();\n return this.getDocumentState(id)?.selected ?? null;\n }\n\n private deselectPending(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.dispatch(deselectPending(id));\n this.emitSelectedChange(id);\n }\n\n private enableRedactSelection(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.RedactSelection);\n }\n\n private toggleRedactSelection(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManagerCapability?.forDocument(id);\n if (scope?.getActiveMode() === RedactionMode.RedactSelection) {\n scope.activateDefaultMode();\n } else {\n scope?.activate(RedactionMode.RedactSelection);\n }\n }\n\n private isRedactSelectionActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return (\n this.interactionManagerCapability?.forDocument(id).getActiveMode() ===\n RedactionMode.RedactSelection\n );\n }\n\n private enableMarqueeRedact(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.MarqueeRedact);\n }\n\n private toggleMarqueeRedact(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManagerCapability?.forDocument(id);\n if (scope?.getActiveMode() === RedactionMode.MarqueeRedact) {\n scope.activateDefaultMode();\n } else {\n scope?.activate(RedactionMode.MarqueeRedact);\n }\n }\n\n private isMarqueeRedactActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n return (\n this.interactionManagerCapability?.forDocument(id).getActiveMode() ===\n RedactionMode.MarqueeRedact\n );\n }\n\n private startRedactionMode(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.RedactSelection);\n }\n\n private endRedactionMode(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n this.interactionManagerCapability?.forDocument(id).activateDefaultMode();\n }\n\n // ─────────────────────────────────────────────────────────\n // Public Methods\n // ─────────────────────────────────────────────────────────\n\n public onRedactionSelectionChange(\n documentId: string,\n callback: (formattedSelection: FormattedSelection[]) => void,\n ) {\n const emitter = this.redactionSelection$.get(documentId);\n return emitter?.on(callback) ?? (() => {});\n }\n\n public registerMarqueeOnPage(opts: RegisterMarqueeOnPageOptions) {\n if (!this.interactionManagerCapability) {\n this.logger.warn(\n 'RedactionPlugin',\n 'MissingDependency',\n 'Interaction manager plugin not loaded, marquee redaction disabled',\n );\n return () => {};\n }\n\n const coreDoc = this.coreState.core.documents[opts.documentId];\n if (!coreDoc?.document) {\n this.logger.warn('RedactionPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = coreDoc.document.pages[opts.pageIndex];\n if (!page) {\n this.logger.warn('RedactionPlugin', 'PageNotFound', `Page ${opts.pageIndex} not found`);\n return () => {};\n }\n\n const handlers = createMarqueeHandler({\n pageSize: page.size,\n scale: opts.scale,\n onPreview: opts.callback.onPreview,\n onCommit: (r) => {\n const item: RedactionItem = {\n id: uuidV4(),\n kind: 'area',\n page: opts.pageIndex,\n rect: r,\n };\n this.dispatch(addPending(opts.documentId, [item]));\n this.emitPendingChange(opts.documentId);\n opts.callback.onCommit?.(r);\n this.enableRedactSelection(opts.documentId);\n this.selectPending(opts.pageIndex, item.id, opts.documentId);\n },\n });\n\n const off = this.interactionManagerCapability.registerAlways({\n handlers: {\n onPointerDown: (_, evt) => {\n if (evt.target === evt.currentTarget) {\n this.deselectPending(opts.documentId);\n }\n },\n },\n scope: {\n type: 'page',\n documentId: opts.documentId,\n pageIndex: opts.pageIndex,\n },\n });\n\n const off2 = this.interactionManagerCapability.registerHandlers({\n documentId: opts.documentId,\n modeId: RedactionMode.MarqueeRedact,\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return () => {\n off();\n off2();\n };\n }\n\n private queueCurrentSelectionAsPending(documentId?: string): Task<boolean, PdfErrorReason> {\n const id = documentId ?? this.getActiveDocumentId();\n\n if (!this.selectionCapability)\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: '[RedactionPlugin] selection plugin required',\n });\n\n const coreDoc = this.coreState.core.documents[id];\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const selectionScope = this.selectionCapability.forDocument(id);\n const formatted = selectionScope.getFormattedSelection();\n if (!formatted.length) return PdfTaskHelper.resolve(true);\n\n const uniqueId = uuidV4();\n\n const items: RedactionItem[] = formatted.map((s) => ({\n id: uniqueId,\n kind: 'text',\n page: s.pageIndex,\n rect: s.rect,\n rects: s.segmentRects,\n }));\n\n this.enableRedactSelection(id);\n this.dispatch(addPending(id, items));\n this.emitPendingChange(id);\n\n // Auto-select the last one added\n const last = items[items.length - 1];\n this.selectPending(last.page, last.id, id);\n\n // Clear live UI selection\n const emitter = this.redactionSelection$.get(id);\n emitter?.emit([]);\n selectionScope.clear();\n\n return PdfTaskHelper.resolve(true);\n }\n\n private commitPendingOne(\n page: number,\n id: string,\n documentId?: string,\n ): Task<boolean, PdfErrorReason> {\n const docId = documentId ?? this.getActiveDocumentId();\n const coreDoc = this.coreState.core.documents[docId];\n\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const docState = this.getDocumentState(docId);\n if (!docState) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Document state not found',\n });\n }\n\n const item = (docState.pending[page] ?? []).find((it) => it.id === id);\n if (!item) return PdfTaskHelper.resolve(true);\n\n const rects: Rect[] = item.kind === 'text' ? item.rects : [item.rect];\n const pdfPage = coreDoc.document.pages[page];\n if (!pdfPage)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Page not found' });\n\n const task = new Task<boolean, PdfErrorReason>();\n this.engine\n .redactTextInRects(coreDoc.document, pdfPage, rects, {\n drawBlackBoxes: this.config.drawBlackBoxes,\n })\n .wait(\n () => {\n this.dispatch(removePending(docId, page, id));\n this.emitPendingChange(docId);\n this.dispatchCoreAction(refreshPages(docId, [page]));\n this.events$.emit({ type: 'commit', documentId: docId, success: true });\n task.resolve(true);\n },\n (error) => {\n this.events$.emit({\n type: 'commit',\n documentId: docId,\n success: false,\n error: error.reason,\n });\n task.reject({ code: PdfErrorCode.Unknown, message: 'Failed to commit redactions' });\n },\n );\n\n return task;\n }\n\n private commitAllPending(documentId?: string): Task<boolean, PdfErrorReason> {\n const docId = documentId ?? this.getActiveDocumentId();\n const coreDoc = this.coreState.core.documents[docId];\n\n if (!coreDoc?.document)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const docState = this.getDocumentState(docId);\n if (!docState) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Document state not found',\n });\n }\n\n // Group rects per page\n const perPage = new Map<number, Rect[]>();\n for (const [page, items] of Object.entries(docState.pending)) {\n const p = Number(page);\n const list = perPage.get(p) ?? [];\n for (const it of items) {\n if (it.kind === 'text') list.push(...it.rects);\n else list.push(it.rect);\n }\n perPage.set(p, list);\n }\n\n const pagesToRefresh = Array.from(perPage.entries())\n .filter(([_, rects]) => rects.length > 0)\n .map(([pageIndex]) => pageIndex);\n\n const tasks: PdfTask<boolean>[] = [];\n for (const [pageIndex, rects] of perPage) {\n const page = coreDoc.document.pages[pageIndex];\n if (!page) continue;\n if (!rects.length) continue;\n tasks.push(\n this.engine.redactTextInRects(coreDoc.document, page, rects, {\n drawBlackBoxes: this.config.drawBlackBoxes,\n }),\n );\n }\n\n const task = new Task<boolean, PdfErrorReason>();\n Task.all(tasks).wait(\n () => {\n this.dispatch(clearPending(docId));\n this.dispatchCoreAction(refreshPages(docId, pagesToRefresh));\n this.emitPendingChange(docId);\n this.events$.emit({ type: 'commit', documentId: docId, success: true });\n task.resolve(true);\n },\n (error) => {\n this.events$.emit({\n type: 'commit',\n documentId: docId,\n success: false,\n error: error.reason,\n });\n task.reject({ code: PdfErrorCode.Unknown, message: 'Failed to commit redactions' });\n },\n );\n\n return task;\n }\n\n // ─────────────────────────────────────────────────────────\n // Event Emission Helpers\n // ─────────────────────────────────────────────────────────\n\n private emitPendingChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.pending$.emit({ documentId, pending: docState.pending });\n }\n }\n\n private emitSelectedChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.selected$.emit({ documentId, selected: docState.selected });\n }\n }\n\n private emitStateChange(documentId: string) {\n const docState = this.getDocumentState(documentId);\n if (docState) {\n this.state$.emit({ documentId, state: docState });\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Store Update Handlers\n // ─────────────────────────────────────────────────────────\n\n override onStoreUpdated(_: RedactionState, newState: RedactionState): void {\n // Emit state changes for each changed document\n for (const documentId in newState.documents) {\n const docState = newState.documents[documentId];\n if (docState) {\n this.emitPendingChange(documentId);\n this.emitSelectedChange(documentId);\n this.emitStateChange(documentId);\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Lifecycle\n // ─────────────────────────────────────────────────────────\n\n async destroy(): Promise<void> {\n this.pending$.clear();\n this.selected$.clear();\n this.state$.clear();\n this.events$.clear();\n\n // Cleanup all per-document emitters\n this.redactionSelection$.forEach((emitter) => emitter.clear());\n this.redactionSelection$.clear();\n\n // Cleanup all unsubscribers\n this.documentUnsubscribers.forEach((unsubscribers) => {\n unsubscribers.forEach((unsub) => unsub());\n });\n this.documentUnsubscribers.clear();\n\n await super.destroy();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { RedactionPluginConfig } from './types';\n\nexport const REDACTION_PLUGIN_ID = 'redaction';\n\nexport const manifest: PluginManifest<RedactionPluginConfig> = {\n id: REDACTION_PLUGIN_ID,\n name: 'Redaction Plugin',\n version: '1.0.0',\n provides: ['redaction'],\n requires: [],\n optional: ['interaction-manager', 'selection'],\n defaultConfig: {\n drawBlackBoxes: true,\n },\n};\n","import { RedactionState, RedactionDocumentState } from './types';\n\nexport const getPendingRedactionsCount = (s: RedactionDocumentState) => s.pendingCount;\n\nexport const hasPendingRedactions = (s: RedactionDocumentState) => s.pendingCount > 0;\n\nexport const getDocumentPendingCount = (state: RedactionState, documentId: string): number => {\n return state.documents[documentId]?.pendingCount ?? 0;\n};\n\nexport const getTotalPendingCount = (state: RedactionState): number => {\n return Object.values(state.documents).reduce((sum, doc) => sum + doc.pendingCount, 0);\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { RedactionPluginConfig, RedactionState } from './types';\nimport { RedactionPlugin } from './redaction-plugin';\nimport { manifest, REDACTION_PLUGIN_ID } from './manifest';\nimport { RedactionAction } from './actions';\nimport { initialState, redactionReducer } from './reducer';\n\nexport const RedactionPluginPackage: PluginPackage<\n RedactionPlugin,\n RedactionPluginConfig,\n RedactionState,\n RedactionAction\n> = {\n manifest,\n create: (registry, config) => new RedactionPlugin(REDACTION_PLUGIN_ID, registry, config),\n reducer: redactionReducer,\n initialState: initialState,\n};\n\nexport * from './redaction-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './selectors';\nexport { initialState, initialDocumentState } from './reducer';\n"],"names":["RedactionMode"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-redaction",
|
|
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,16 +35,16 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@embedpdf/models": "2.0.0-next.
|
|
39
|
-
"@embedpdf/utils": "2.0.0-next.
|
|
38
|
+
"@embedpdf/models": "2.0.0-next.2",
|
|
39
|
+
"@embedpdf/utils": "2.0.0-next.2"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/react": "^18.2.0",
|
|
43
43
|
"typescript": "^5.0.0",
|
|
44
|
-
"@embedpdf/
|
|
45
|
-
"@embedpdf/core": "2.0.0-next.
|
|
46
|
-
"@embedpdf/plugin-interaction-manager": "2.0.0-next.
|
|
47
|
-
"@embedpdf/
|
|
44
|
+
"@embedpdf/plugin-selection": "2.0.0-next.2",
|
|
45
|
+
"@embedpdf/core": "2.0.0-next.2",
|
|
46
|
+
"@embedpdf/plugin-interaction-manager": "2.0.0-next.2",
|
|
47
|
+
"@embedpdf/build": "1.1.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"preact": "^10.26.4",
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
"react-dom": ">=16.8.0",
|
|
53
53
|
"vue": ">=3.2.0",
|
|
54
54
|
"svelte": ">=5 <6",
|
|
55
|
-
"@embedpdf/plugin-
|
|
56
|
-
"@embedpdf/
|
|
57
|
-
"@embedpdf/
|
|
55
|
+
"@embedpdf/plugin-interaction-manager": "2.0.0-next.2",
|
|
56
|
+
"@embedpdf/plugin-selection": "2.0.0-next.2",
|
|
57
|
+
"@embedpdf/core": "2.0.0-next.2"
|
|
58
58
|
},
|
|
59
59
|
"files": [
|
|
60
60
|
"dist",
|