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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +573 -207
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/actions.d.ts +48 -13
  6. package/dist/lib/index.d.ts +1 -1
  7. package/dist/lib/redaction-plugin.d.ts +22 -8
  8. package/dist/lib/reducer.d.ts +4 -2
  9. package/dist/lib/selectors.d.ts +5 -3
  10. package/dist/lib/types.d.ts +68 -20
  11. package/dist/preact/index.cjs +1 -1
  12. package/dist/preact/index.cjs.map +1 -1
  13. package/dist/preact/index.js +86 -37
  14. package/dist/preact/index.js.map +1 -1
  15. package/dist/react/index.cjs +1 -1
  16. package/dist/react/index.cjs.map +1 -1
  17. package/dist/react/index.js +86 -37
  18. package/dist/react/index.js.map +1 -1
  19. package/dist/shared/components/marquee-redact.d.ts +4 -2
  20. package/dist/shared/components/pending-redactions.d.ts +4 -3
  21. package/dist/shared/components/redaction-layer.d.ts +11 -5
  22. package/dist/shared/components/selection-redact.d.ts +2 -1
  23. package/dist/shared/components/types.d.ts +6 -7
  24. package/dist/shared/hooks/use-redaction.d.ts +4 -4
  25. package/dist/shared-preact/components/marquee-redact.d.ts +4 -2
  26. package/dist/shared-preact/components/pending-redactions.d.ts +4 -3
  27. package/dist/shared-preact/components/redaction-layer.d.ts +11 -5
  28. package/dist/shared-preact/components/selection-redact.d.ts +2 -1
  29. package/dist/shared-preact/components/types.d.ts +6 -7
  30. package/dist/shared-preact/hooks/use-redaction.d.ts +4 -4
  31. package/dist/shared-react/components/marquee-redact.d.ts +4 -2
  32. package/dist/shared-react/components/pending-redactions.d.ts +4 -3
  33. package/dist/shared-react/components/redaction-layer.d.ts +11 -5
  34. package/dist/shared-react/components/selection-redact.d.ts +2 -1
  35. package/dist/shared-react/components/types.d.ts +6 -7
  36. package/dist/shared-react/hooks/use-redaction.d.ts +4 -4
  37. package/dist/svelte/components/highlight.svelte.d.ts +14 -0
  38. package/dist/svelte/components/index.d.ts +5 -0
  39. package/dist/svelte/components/marquee-redact.svelte.d.ts +16 -0
  40. package/dist/svelte/components/pending-redactions.svelte.d.ts +15 -0
  41. package/dist/svelte/components/redaction-layer.svelte.d.ts +20 -0
  42. package/dist/svelte/components/selection-redact.svelte.d.ts +8 -0
  43. package/dist/svelte/hooks/index.d.ts +1 -0
  44. package/dist/svelte/hooks/use-redaction.svelte.d.ts +21 -0
  45. package/dist/svelte/index.cjs +2 -0
  46. package/dist/svelte/index.cjs.map +1 -0
  47. package/dist/svelte/index.d.ts +4 -0
  48. package/dist/svelte/index.js +554 -0
  49. package/dist/svelte/index.js.map +1 -0
  50. package/dist/svelte/types.d.ts +10 -0
  51. package/dist/vue/components/highlight.vue.d.ts +2 -1
  52. package/dist/vue/components/marquee-redact.vue.d.ts +5 -2
  53. package/dist/vue/components/pending-redactions.vue.d.ts +18 -13
  54. package/dist/vue/components/redaction-layer.vue.d.ts +13 -4
  55. package/dist/vue/components/selection-redact.vue.d.ts +3 -1
  56. package/dist/vue/components/types.d.ts +9 -0
  57. package/dist/vue/hooks/use-redaction.d.ts +9 -102
  58. package/dist/vue/index.cjs +1 -1
  59. package/dist/vue/index.cjs.map +1 -1
  60. package/dist/vue/index.d.ts +1 -0
  61. package/dist/vue/index.js +219 -125
  62. package/dist/vue/index.js.map +1 -1
  63. package/package.json +18 -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 i=(e=>(e.MarqueeRedact="marqueeRedact",e.RedactSelection="redactSelection",e))(i||{});const n="START_REDACTION",a="END_REDACTION",s="ADD_PENDING",c="REMOVE_PENDING",o="CLEAR_PENDING",r="SELECT_PENDING",l="DESELECT_PENDING",d=e=>({type:s,payload:e}),g=(e,t)=>({type:c,payload:{page:e,id:t}}),h=()=>({type:o}),u=e=>({type:n,payload:e});const p=class extends e.BasePlugin{constructor(n,s,c){var o,r,l,g,h;super(n,s),this.redactionSelection$=e.createBehaviorEmitter(),this.pending$=e.createBehaviorEmitter(),this.selected$=e.createBehaviorEmitter(),this.state$=e.createBehaviorEmitter(),this.events$=e.createBehaviorEmitter(),this.config=c,this.selectionCapability=null==(o=this.registry.getPlugin("selection"))?void 0:o.provides(),this.interactionManagerCapability=null==(r=this.registry.getPlugin("interaction-manager"))?void 0:r.provides(),this.interactionManagerCapability&&this.interactionManagerCapability.registerMode({id:i.MarqueeRedact,scope:"page",exclusive:!0,cursor:"crosshair"}),this.interactionManagerCapability&&this.selectionCapability&&(this.interactionManagerCapability.registerMode({id:i.RedactSelection,scope:"page",exclusive:!1}),this.selectionCapability.enableForMode(i.RedactSelection)),this.unsubscribeModeChange=null==(l=this.interactionManagerCapability)?void 0:l.onModeChange((e=>{e.activeMode===i.RedactSelection?this.dispatch(u(i.RedactSelection)):e.activeMode===i.MarqueeRedact?this.dispatch(u(i.MarqueeRedact)):this.dispatch({type:a})})),this.unsubscribeSelectionChange=null==(g=this.selectionCapability)?void 0:g.onSelectionChange((()=>{if(!this.selectionCapability)return;if(!this.state.isRedacting)return;const e=this.selectionCapability.getFormattedSelection();this.redactionSelection$.emit(e)})),this.unsubscribeEndSelection=null==(h=this.selectionCapability)?void 0:h.onEndSelection((()=>{if(!this.selectionCapability)return;if(!this.state.isRedacting)return;const e=this.selectionCapability.getFormattedSelection().map((e=>({id:t.uuidV4(),kind:"text",page:e.pageIndex,rect:e.rect,rects:e.segmentRects})));this.dispatch(d(e)),this.redactionSelection$.emit([]),this.selectionCapability.clear(),this.pending$.emit(this.state.pending),e.length&&this.selectPending(e[e.length-1].page,e[e.length-1].id)}))}async initialize(e){}buildCapability(){return{queueCurrentSelectionAsPending:()=>this.queueCurrentSelectionAsPending(),enableMarqueeRedact:()=>this.enableMarqueeRedact(),toggleMarqueeRedact:()=>this.toggleMarqueeRedact(),isMarqueeRedactActive:()=>{var e;return(null==(e=this.interactionManagerCapability)?void 0:e.getActiveMode())===i.MarqueeRedact},enableRedactSelection:()=>this.enableRedactSelection(),toggleRedactSelection:()=>this.toggleRedactSelection(),isRedactSelectionActive:()=>{var e;return(null==(e=this.interactionManagerCapability)?void 0:e.getActiveMode())===i.RedactSelection},addPending:e=>{this.dispatch(d(e)),this.pending$.emit(this.state.pending),this.events$.emit({type:"add",items:e})},removePending:(e,t)=>{this.dispatch(g(e,t)),this.pending$.emit(this.state.pending),this.events$.emit({type:"remove",page:e,id:t})},clearPending:()=>{this.dispatch(h()),this.pending$.emit(this.state.pending),this.events$.emit({type:"clear"})},commitAllPending:()=>this.commitAllPending(),commitPending:(e,t)=>this.commitPendingOne(e,t),endRedaction:()=>this.endRedaction(),startRedaction:()=>this.startRedaction(),selectPending:(e,t)=>this.selectPending(e,t),deselectPending:()=>this.deselectPending(),onSelectedChange:this.selected$.on,onRedactionEvent:this.events$.on,onStateChange:this.state$.on,onPendingChange:this.pending$.on}}onRedactionSelectionChange(e){return this.redactionSelection$.on(e)}selectPending(e,t){var i;this.dispatch(((e,t)=>({type:r,payload:{page:e,id:t}}))(e,t)),null==(i=this.selectionCapability)||i.clear(),this.selected$.emit(this.state.selected)}deselectPending(){this.dispatch({type:l}),this.selected$.emit(this.state.selected)}enableRedactSelection(){var e;null==(e=this.interactionManagerCapability)||e.activate(i.RedactSelection)}toggleRedactSelection(){var e,t,n;(null==(e=this.interactionManagerCapability)?void 0:e.getActiveMode())===i.RedactSelection?null==(t=this.interactionManagerCapability)||t.activateDefaultMode():null==(n=this.interactionManagerCapability)||n.activate(i.RedactSelection)}enableMarqueeRedact(){var e;null==(e=this.interactionManagerCapability)||e.activate(i.MarqueeRedact)}toggleMarqueeRedact(){var e,t,n;(null==(e=this.interactionManagerCapability)?void 0:e.getActiveMode())===i.MarqueeRedact?null==(t=this.interactionManagerCapability)||t.activateDefaultMode():null==(n=this.interactionManagerCapability)||n.activate(i.MarqueeRedact)}startRedaction(){var e;null==(e=this.interactionManagerCapability)||e.activate(i.RedactSelection)}endRedaction(){var e;null==(e=this.interactionManagerCapability)||e.activateDefaultMode()}registerMarqueeOnPage(n){if(!this.interactionManagerCapability)return this.logger.warn("RedactionPlugin","MissingDependency","Interaction manager plugin not loaded, marquee redaction disabled"),()=>{};const a=this.coreState.core.document;if(!a)return this.logger.warn("RedactionPlugin","DocumentNotFound","Document not found"),()=>{};const s=a.pages[n.pageIndex];if(!s)return this.logger.warn("RedactionPlugin","PageNotFound",`Page ${n.pageIndex} not found`),()=>{};const c=function(t){const{pageSize:i,scale:n,minDragPx:a=5,onPreview:s,onCommit:c}=t;let o=null,r=null;return{onPointerDown:(e,t)=>{var i;o=e,r={origin:{x:e.x,y:e.y},size:{width:0,height:0}},null==s||s(r),null==(i=t.setPointerCapture)||i.call(t)},onPointerMove:t=>{if(!o)return;const n=e.clamp(t.x,0,i.width),a=e.clamp(t.y,0,i.height);r={origin:{x:Math.min(o.x,n),y:Math.min(o.y,a)},size:{width:Math.abs(n-o.x),height:Math.abs(a-o.y)}},null==s||s(r)},onPointerUp:(e,t)=>{var i;r&&Math.max(r.size.width,r.size.height)*n>a&&(null==c||c(r)),o=null,r=null,null==s||s(null),null==(i=t.releasePointerCapture)||i.call(t)},onPointerCancel:(e,t)=>{var i;o=null,r=null,null==s||s(null),null==(i=t.releasePointerCapture)||i.call(t)}}}({pageSize:s.size,scale:n.scale,onPreview:n.callback.onPreview,onCommit:e=>{var i,a;const s={id:t.uuidV4(),kind:"area",page:n.pageIndex,rect:e};this.dispatch(d([s])),this.pending$.emit(this.state.pending),null==(a=(i=n.callback).onCommit)||a.call(i,e),this.enableRedactSelection(),this.selectPending(n.pageIndex,s.id)}}),o=this.interactionManagerCapability.registerAlways({handlers:{onPointerDown:(e,t)=>{t.target===t.currentTarget&&this.deselectPending()}},scope:{type:"page",pageIndex:n.pageIndex}}),r=this.interactionManagerCapability.registerHandlers({modeId:i.MarqueeRedact,handlers:c,pageIndex:n.pageIndex});return()=>{o(),r()}}queueCurrentSelectionAsPending(){var e;if(!this.selectionCapability)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"[RedactionPlugin] selection plugin required"});if(!this.coreState.core.document)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document not found"});const i=this.selectionCapability.getFormattedSelection();if(!i.length)return t.PdfTaskHelper.resolve(!0);const n=t.uuidV4(),a=i.map((e=>({id:n,kind:"text",page:e.pageIndex,rect:e.rect,rects:e.segmentRects})));this.enableRedactSelection(),this.dispatch(d(a)),this.pending$.emit(this.state.pending);const s=a[a.length-1];return this.selectPending(s.page,s.id),this.redactionSelection$.emit([]),null==(e=this.selectionCapability)||e.clear(),t.PdfTaskHelper.resolve(!0)}commitPendingOne(i,n){const a=this.coreState.core.document;if(!a)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document not found"});const s=(this.state.pending[i]??[]).find((e=>e.id===n));if(!s)return t.PdfTaskHelper.resolve(!0);const c="text"===s.kind?s.rects:[s.rect],o=a.pages[i];if(!o)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Page not found"});const r=new t.Task;return this.engine.redactTextInRects(a,o,c,{drawBlackBoxes:this.config.drawBlackBoxes}).wait((()=>{this.dispatch(g(i,n)),this.pending$.emit(this.state.pending),this.dispatchCoreAction(e.refreshPages([i])),this.events$.emit({type:"commit",success:!0}),r.resolve(!0)}),(e=>{this.events$.emit({type:"commit",success:!1,error:e.reason}),r.reject({code:t.PdfErrorCode.Unknown,message:"Failed to commit redactions"})})),r}commitAllPending(){const i=this.coreState.core.document;if(!i)return t.PdfTaskHelper.reject({code:t.PdfErrorCode.NotFound,message:"Document not found"});const n=new Map;for(const[e,t]of Object.entries(this.state.pending)){const i=Number(e),a=n.get(i)??[];for(const e of t)"text"===e.kind?a.push(...e.rects):a.push(e.rect);n.set(i,a)}const a=Array.from(n.entries()).filter((([e,t])=>t.length>0)).map((([e])=>e)),s=[];for(const[e,t]of n){const n=i.pages[e];n&&(t.length&&s.push(this.engine.redactTextInRects(i,n,t,{drawBlackBoxes:this.config.drawBlackBoxes})))}const c=new t.Task;return t.Task.all(s).wait((()=>{this.dispatch(h()),this.dispatchCoreAction(e.refreshPages(a)),this.pending$.emit(this.state.pending),this.events$.emit({type:"commit",success:!0}),c.resolve(!0)}),(e=>{this.events$.emit({type:"commit",success:!1,error:e.reason}),c.reject({code:t.PdfErrorCode.Unknown,message:"Failed to commit redactions"})})),c}onStoreUpdated(e,t){this.pending$.emit(t.pending),this.selected$.emit(t.selected),this.state$.emit(t)}async destroy(){var e,t,i;this.redactionSelection$.clear(),this.pending$.clear(),this.state$.clear(),this.events$.clear(),null==(e=this.unsubscribeSelectionChange)||e.call(this),null==(t=this.unsubscribeEndSelection)||t.call(this),null==(i=this.unsubscribeModeChange)||i.call(this),await super.destroy()}};p.id="redaction";let m=p;const v="redaction",y={id:v,name:"Redaction Plugin",version:"1.0.0",provides:["redaction"],requires:[],optional:["interaction-manager","selection"],defaultConfig:{enabled:!0,drawBlackBoxes:!0}},C=e=>Object.values(e).reduce(((e,t)=>e+t.length),0),P={isRedacting:!1,activeType:null,pending:{},pendingCount:0,selected:null},b={manifest:y,create:(e,t)=>new m(v,e,t),reducer:(e=P,t)=>{switch(t.type){case s:{const i={...e.pending};for(const e of t.payload)i[e.page]=(i[e.page]??[]).concat(e);return{...e,pending:i,pendingCount:C(i)}}case c:{const{page:i,id:n}=t.payload,a=(e.pending[i]??[]).filter((e=>e.id!==n)),s={...e.pending,[i]:a},c=e.selected&&!(e.selected.page===i&&e.selected.id===n);return{...e,pending:s,pendingCount:C(s),selected:c?e.selected:null}}case o:return{...e,pending:{},pendingCount:0,selected:null};case r:return{...e,selected:{page:t.payload.page,id:t.payload.id}};case l:return{...e,selected:null};case n:return{...e,isRedacting:!0,activeType:t.payload};case a:return{...e,pending:{},pendingCount:0,selected:null,isRedacting:!1,activeType:null};case"SET_ACTIVE_TYPE":return{...e,activeType:t.payload};default:return e}},initialState:P};exports.REDACTION_PLUGIN_ID=v,exports.RedactionMode=i,exports.RedactionPlugin=m,exports.RedactionPluginPackage=b,exports.getPendingRedactionsCount=e=>Object.values(e.pending).reduce(((e,t)=>e+((null==t?void 0:t.length)??0)),0),exports.hasPendingRedactions=e=>Object.values(e.pending).some((e=>((null==e?void 0:e.length)??0)>0)),exports.initialState=P,exports.manifest=y;
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;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/lib/types.ts","../src/lib/actions.ts","../src/lib/redaction-plugin.ts","../src/lib/handlers/marquee-redact.handler.ts","../src/lib/manifest.ts","../src/lib/reducer.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 | null;\n}\n\nexport interface RedactionState {\n isRedacting: boolean;\n activeType: RedactionMode | null;\n pending: Record<number, RedactionItem[]>;\n pendingCount: number;\n selected: SelectedRedaction | 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 pageIndex: number;\n scale: number;\n callback: MarqueeRedactCallback;\n}\n\nexport interface RedactionPluginConfig extends BasePluginConfig {\n drawBlackBoxes: boolean;\n}\n\n// Add event types similar to annotation plugin\nexport type RedactionEvent =\n | {\n type: 'add';\n items: RedactionItem[];\n }\n | {\n type: 'remove';\n page: number;\n id: string;\n }\n | {\n type: 'clear';\n }\n | {\n type: 'commit';\n success: boolean;\n error?: PdfErrorReason;\n };\n\nexport interface RedactionCapability {\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 onPendingChange: EventHook<Record<number, RedactionItem[]>>;\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 deselectPending: () => void;\n\n // Event hook for redaction events\n onSelectedChange: EventHook<SelectedRedaction | null>;\n onRedactionEvent: EventHook<RedactionEvent>;\n onStateChange: EventHook<RedactionState>;\n}\n","import { Action } from '@embedpdf/core';\nimport { RedactionItem, RedactionMode } from './types';\n\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\nexport interface StartRedactionAction extends Action {\n type: typeof START_REDACTION;\n payload: RedactionMode;\n}\nexport interface EndRedactionAction extends Action {\n type: typeof END_REDACTION;\n}\nexport interface SetActiveTypeAction extends Action {\n type: typeof SET_ACTIVE_TYPE;\n payload: RedactionMode | null;\n}\n\nexport interface AddPendingAction extends Action {\n type: typeof ADD_PENDING;\n payload: RedactionItem[];\n}\nexport interface RemovePendingAction extends Action {\n type: typeof REMOVE_PENDING;\n payload: { page: number; id: string };\n}\nexport interface ClearPendingAction extends Action {\n type: typeof CLEAR_PENDING;\n}\n\nexport interface SelectPendingAction extends Action {\n type: typeof SELECT_PENDING;\n payload: { page: number; id: string };\n}\nexport interface DeselectPendingAction extends Action {\n type: typeof DESELECT_PENDING;\n}\n\nexport type RedactionAction =\n | StartRedactionAction\n | EndRedactionAction\n | SetActiveTypeAction\n | AddPendingAction\n | RemovePendingAction\n | ClearPendingAction\n | SelectPendingAction\n | DeselectPendingAction;\n\nexport const addPending = (items: RedactionItem[]): AddPendingAction => ({\n type: ADD_PENDING,\n payload: items,\n});\nexport const removePending = (page: number, id: string): RemovePendingAction => ({\n type: REMOVE_PENDING,\n payload: { page, id },\n});\nexport const clearPending = (): ClearPendingAction => ({ type: CLEAR_PENDING });\n\nexport const startRedaction = (mode: RedactionMode): StartRedactionAction => ({\n type: START_REDACTION,\n payload: mode,\n});\nexport const endRedaction = (): EndRedactionAction => ({ type: END_REDACTION });\nexport const setActiveType = (mode: RedactionMode | null): SetActiveTypeAction => ({\n type: SET_ACTIVE_TYPE,\n payload: mode,\n});\n\nexport const selectPending = (page: number, id: string): SelectPendingAction => ({\n type: SELECT_PENDING,\n payload: { page, id },\n});\nexport const deselectPending = (): DeselectPendingAction => ({ type: DESELECT_PENDING });\n","import {\n RedactionPluginConfig,\n RedactionCapability,\n RedactionState,\n RegisterMarqueeOnPageOptions,\n RedactionItem,\n SelectedRedaction,\n RedactionMode,\n RedactionEvent,\n} from './types';\nimport {\n BasePlugin,\n createBehaviorEmitter,\n PluginRegistry,\n refreshPages,\n Unsubscribe,\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} from './actions';\nimport { createMarqueeHandler } from './handlers';\n\nexport class RedactionPlugin extends BasePlugin<\n RedactionPluginConfig,\n RedactionCapability,\n RedactionState\n> {\n static readonly id = 'redaction' as const;\n private config: RedactionPluginConfig;\n\n private selectionCapability: SelectionCapability | undefined;\n private interactionManagerCapability: InteractionManagerCapability | undefined;\n\n private readonly redactionSelection$ = createBehaviorEmitter<FormattedSelection[]>();\n private readonly pending$ = createBehaviorEmitter<Record<number, RedactionItem[]>>();\n private readonly selected$ = createBehaviorEmitter<SelectedRedaction | null>();\n private readonly state$ = createBehaviorEmitter<RedactionState>();\n private readonly events$ = createBehaviorEmitter<RedactionEvent>();\n\n private readonly unsubscribeSelectionChange: Unsubscribe | undefined;\n private readonly unsubscribeEndSelection: Unsubscribe | undefined;\n private readonly unsubscribeModeChange: Unsubscribe | undefined;\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 }\n\n if (this.interactionManagerCapability && this.selectionCapability) {\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.RedactSelection,\n scope: 'page',\n exclusive: false,\n });\n this.selectionCapability.enableForMode(RedactionMode.RedactSelection);\n }\n\n this.unsubscribeModeChange = this.interactionManagerCapability?.onModeChange((state) => {\n if (state.activeMode === RedactionMode.RedactSelection) {\n this.dispatch(startRedaction(RedactionMode.RedactSelection));\n } else if (state.activeMode === RedactionMode.MarqueeRedact) {\n this.dispatch(startRedaction(RedactionMode.MarqueeRedact));\n } else {\n this.dispatch(endRedaction());\n }\n });\n\n this.unsubscribeSelectionChange = this.selectionCapability?.onSelectionChange(() => {\n if (!this.selectionCapability) return;\n if (!this.state.isRedacting) return;\n const formattedSelection = this.selectionCapability.getFormattedSelection();\n this.redactionSelection$.emit(formattedSelection);\n });\n\n this.unsubscribeEndSelection = this.selectionCapability?.onEndSelection(() => {\n if (!this.selectionCapability) return;\n if (!this.state.isRedacting) return;\n\n const formattedSelection = this.selectionCapability.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(items));\n this.redactionSelection$.emit([]);\n this.selectionCapability.clear();\n this.pending$.emit(this.state.pending);\n if (items.length) {\n this.selectPending(items[items.length - 1].page, items[items.length - 1].id);\n }\n });\n }\n\n async initialize(_config: RedactionPluginConfig): Promise<void> {}\n\n protected buildCapability(): RedactionCapability {\n return {\n queueCurrentSelectionAsPending: () => this.queueCurrentSelectionAsPending(),\n\n enableMarqueeRedact: () => this.enableMarqueeRedact(),\n toggleMarqueeRedact: () => this.toggleMarqueeRedact(),\n isMarqueeRedactActive: () =>\n this.interactionManagerCapability?.getActiveMode() === RedactionMode.MarqueeRedact,\n\n enableRedactSelection: () => this.enableRedactSelection(),\n toggleRedactSelection: () => this.toggleRedactSelection(),\n isRedactSelectionActive: () =>\n this.interactionManagerCapability?.getActiveMode() === RedactionMode.RedactSelection,\n\n addPending: (items) => {\n this.dispatch(addPending(items));\n this.pending$.emit(this.state.pending);\n this.events$.emit({ type: 'add', items });\n },\n removePending: (page, id) => {\n this.dispatch(removePending(page, id));\n this.pending$.emit(this.state.pending);\n this.events$.emit({ type: 'remove', page, id });\n },\n clearPending: () => {\n this.dispatch(clearPending());\n this.pending$.emit(this.state.pending);\n this.events$.emit({ type: 'clear' });\n },\n commitAllPending: () => this.commitAllPending(),\n commitPending: (page, id) => this.commitPendingOne(page, id),\n\n endRedaction: () => this.endRedaction(),\n startRedaction: () => this.startRedaction(),\n\n selectPending: (page, id) => this.selectPending(page, id),\n deselectPending: () => this.deselectPending(),\n\n onSelectedChange: this.selected$.on,\n onRedactionEvent: this.events$.on,\n onStateChange: this.state$.on,\n onPendingChange: this.pending$.on,\n };\n }\n\n public onRedactionSelectionChange(\n callback: (formattedSelection: FormattedSelection[]) => void,\n ): Unsubscribe {\n return this.redactionSelection$.on(callback);\n }\n\n private selectPending(page: number, id: string) {\n this.dispatch(selectPending(page, id));\n this.selectionCapability?.clear();\n this.selected$.emit(this.state.selected);\n }\n private deselectPending() {\n this.dispatch(deselectPending());\n this.selected$.emit(this.state.selected);\n }\n\n private enableRedactSelection() {\n this.interactionManagerCapability?.activate(RedactionMode.RedactSelection);\n }\n private toggleRedactSelection() {\n if (this.interactionManagerCapability?.getActiveMode() === RedactionMode.RedactSelection)\n this.interactionManagerCapability?.activateDefaultMode();\n else this.interactionManagerCapability?.activate(RedactionMode.RedactSelection);\n }\n\n private enableMarqueeRedact() {\n this.interactionManagerCapability?.activate(RedactionMode.MarqueeRedact);\n }\n private toggleMarqueeRedact() {\n if (this.interactionManagerCapability?.getActiveMode() === RedactionMode.MarqueeRedact)\n this.interactionManagerCapability?.activateDefaultMode();\n else this.interactionManagerCapability?.activate(RedactionMode.MarqueeRedact);\n }\n\n private startRedaction() {\n this.interactionManagerCapability?.activate(RedactionMode.RedactSelection);\n }\n private endRedaction() {\n this.interactionManagerCapability?.activateDefaultMode();\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 document = this.coreState.core.document;\n if (!document) {\n this.logger.warn('RedactionPlugin', 'DocumentNotFound', 'Document not found');\n return () => {};\n }\n\n const page = 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([item]));\n this.pending$.emit(this.state.pending);\n opts.callback.onCommit?.(r);\n this.enableRedactSelection();\n this.selectPending(opts.pageIndex, item.id);\n },\n });\n\n const off = this.interactionManagerCapability.registerAlways({\n handlers: {\n onPointerDown: (_, evt) => {\n if (evt.target === evt.currentTarget) {\n this.deselectPending();\n }\n },\n },\n scope: {\n type: 'page',\n pageIndex: opts.pageIndex,\n },\n });\n\n const off2 = this.interactionManagerCapability.registerHandlers({\n modeId: RedactionMode.MarqueeRedact,\n handlers,\n pageIndex: opts.pageIndex,\n });\n\n return () => {\n off();\n off2();\n };\n }\n\n private queueCurrentSelectionAsPending(): Task<boolean, PdfErrorReason> {\n if (!this.selectionCapability)\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: '[RedactionPlugin] selection plugin required',\n });\n\n const doc = this.coreState.core.document;\n if (!doc)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const formatted = this.selectionCapability.getFormattedSelection();\n if (!formatted.length) return PdfTaskHelper.resolve(true);\n\n const id = uuidV4();\n\n const items: RedactionItem[] = formatted.map((s) => ({\n id,\n kind: 'text',\n page: s.pageIndex,\n rect: s.rect,\n rects: s.segmentRects,\n }));\n\n this.enableRedactSelection();\n this.dispatch(addPending(items));\n this.pending$.emit(this.state.pending);\n // optional: auto-select the last one added\n const last = items[items.length - 1];\n this.selectPending(last.page, last.id);\n\n // clear live UI selection\n this.redactionSelection$.emit([]);\n this.selectionCapability?.clear();\n\n return PdfTaskHelper.resolve(true);\n }\n\n private commitPendingOne(page: number, id: string): Task<boolean, PdfErrorReason> {\n const doc = this.coreState.core.document;\n if (!doc)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const item = (this.state.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 = doc.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(doc, pdfPage, rects, {\n drawBlackBoxes: this.config.drawBlackBoxes,\n })\n .wait(\n () => {\n this.dispatch(removePending(page, id));\n this.pending$.emit(this.state.pending);\n this.dispatchCoreAction(refreshPages([page]));\n this.events$.emit({ type: 'commit', success: true });\n task.resolve(true);\n },\n (error) => {\n this.events$.emit({ type: 'commit', success: false, error: error.reason });\n task.reject({ code: PdfErrorCode.Unknown, message: 'Failed to commit redactions' });\n },\n );\n\n return task;\n }\n\n private commitAllPending(): Task<boolean, PdfErrorReason> {\n const doc = this.coreState.core.document;\n if (!doc)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n // group rects per page\n const perPage = new Map<number, Rect[]>();\n for (const [page, items] of Object.entries(this.state.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 = doc.pages[pageIndex];\n if (!page) continue;\n if (!rects.length) continue;\n tasks.push(\n this.engine.redactTextInRects(doc, 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());\n this.dispatchCoreAction(refreshPages(pagesToRefresh));\n this.pending$.emit(this.state.pending);\n this.events$.emit({ type: 'commit', success: true });\n task.resolve(true);\n },\n (error) => {\n this.events$.emit({ type: 'commit', success: false, error: error.reason });\n task.reject({ code: PdfErrorCode.Unknown, message: 'Failed to commit redactions' });\n },\n );\n\n return task;\n }\n\n override onStoreUpdated(_: RedactionState, newState: RedactionState): void {\n // keep external listeners in sync\n this.pending$.emit(newState.pending);\n this.selected$.emit(newState.selected);\n this.state$.emit(newState);\n }\n\n async destroy(): Promise<void> {\n this.redactionSelection$.clear();\n this.pending$.clear();\n this.state$.clear();\n this.events$.clear();\n\n this.unsubscribeSelectionChange?.();\n this.unsubscribeEndSelection?.();\n this.unsubscribeModeChange?.();\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 { RedactionItem, RedactionState } from './types';\nimport {\n RedactionAction,\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 initialState: RedactionState = {\n isRedacting: false,\n activeType: null,\n pending: {},\n pendingCount: 0,\n selected: null,\n};\n\nexport const redactionReducer = (state = initialState, action: RedactionAction): RedactionState => {\n switch (action.type) {\n case ADD_PENDING: {\n const next = { ...state.pending };\n for (const item of action.payload) {\n next[item.page] = (next[item.page] ?? []).concat(item);\n }\n return { ...state, pending: next, pendingCount: calculatePendingCount(next) };\n }\n\n case REMOVE_PENDING: {\n const { page, id } = action.payload;\n const list = state.pending[page] ?? [];\n const filtered = list.filter((it) => it.id !== id);\n const next = { ...state.pending, [page]: filtered };\n\n // if the removed one was selected → clear selection\n const stillSelected =\n state.selected && !(state.selected.page === page && state.selected.id === id);\n\n return {\n ...state,\n pending: next,\n pendingCount: calculatePendingCount(next),\n selected: stillSelected ? state.selected : null,\n };\n }\n\n case CLEAR_PENDING:\n return { ...state, pending: {}, pendingCount: 0, selected: null };\n\n case SELECT_PENDING:\n return { ...state, selected: { page: action.payload.page, id: action.payload.id } };\n\n case DESELECT_PENDING:\n return { ...state, selected: null };\n\n case START_REDACTION:\n return { ...state, isRedacting: true, activeType: action.payload };\n case END_REDACTION:\n return {\n ...state,\n pending: {},\n pendingCount: 0,\n selected: null,\n isRedacting: false,\n activeType: null,\n };\n case SET_ACTIVE_TYPE:\n return { ...state, activeType: action.payload };\n default:\n return state;\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 } from './reducer';\n","import { RedactionState } from './types';\n\nexport const getPendingRedactionsCount = (s: RedactionState) =>\n Object.values(s.pending).reduce((sum, list) => sum + (list?.length ?? 0), 0);\n\nexport const hasPendingRedactions = (s: RedactionState) =>\n Object.values(s.pending).some((list) => (list?.length ?? 0) > 0);\n"],"names":["RedactionMode","START_REDACTION","END_REDACTION","ADD_PENDING","REMOVE_PENDING","CLEAR_PENDING","SELECT_PENDING","DESELECT_PENDING","addPending","items","type","payload","removePending","page","id","clearPending","startRedaction","mode","_RedactionPlugin","BasePlugin","constructor","registry","config","super","this","redactionSelection$","createBehaviorEmitter","pending$","selected$","state$","events$","selectionCapability","_a","getPlugin","provides","interactionManagerCapability","_b","registerMode","MarqueeRedact","scope","exclusive","cursor","RedactSelection","enableForMode","unsubscribeModeChange","_c","onModeChange","state","activeMode","dispatch","unsubscribeSelectionChange","_d","onSelectionChange","isRedacting","formattedSelection","getFormattedSelection","emit","unsubscribeEndSelection","_e","onEndSelection","map","s","uuidV4","kind","pageIndex","rect","rects","segmentRects","clear","pending","length","selectPending","initialize","_config","buildCapability","queueCurrentSelectionAsPending","enableMarqueeRedact","toggleMarqueeRedact","isMarqueeRedactActive","getActiveMode","enableRedactSelection","toggleRedactSelection","isRedactSelectionActive","commitAllPending","commitPending","commitPendingOne","endRedaction","deselectPending","onSelectedChange","on","onRedactionEvent","onStateChange","onPendingChange","onRedactionSelectionChange","callback","selected","activate","activateDefaultMode","registerMarqueeOnPage","opts","logger","warn","document","coreState","core","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","doc","find","it","pdfPage","task","Task","engine","redactTextInRects","drawBlackBoxes","wait","dispatchCoreAction","refreshPages","success","error","reason","Unknown","perPage","Map","Object","entries","p","Number","list","get","push","set","pagesToRefresh","Array","from","filter","tasks","all","onStoreUpdated","newState","destroy","RedactionPlugin","REDACTION_PLUGIN_ID","manifest","name","version","requires","optional","defaultConfig","enabled","calculatePendingCount","values","reduce","total","initialState","activeType","pendingCount","RedactionPluginPackage","create","reducer","action","next","concat","filtered","stillSelected","sum","some"],"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 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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"}