@embedpdf/plugin-redaction 2.15.0 → 3.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/LICENSE +192 -21
  2. package/README.md +109 -0
  3. package/dist/index.cjs +227 -2
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +89 -0
  6. package/dist/index.d.ts +89 -1
  7. package/dist/index.js +220 -1532
  8. package/dist/index.js.map +1 -1
  9. package/package.json +22 -67
  10. package/dist/lib/actions.d.ts +0 -113
  11. package/dist/lib/handlers/index.d.ts +0 -0
  12. package/dist/lib/index.d.ts +0 -11
  13. package/dist/lib/manifest.d.ts +0 -4
  14. package/dist/lib/redaction-plugin.d.ts +0 -153
  15. package/dist/lib/reducer.d.ts +0 -6
  16. package/dist/lib/selectors.d.ts +0 -5
  17. package/dist/lib/tools.d.ts +0 -64
  18. package/dist/lib/types.d.ts +0 -142
  19. package/dist/preact/adapter.d.ts +0 -10
  20. package/dist/preact/annotation.d.ts +0 -1
  21. package/dist/preact/core.d.ts +0 -1
  22. package/dist/preact/index.cjs +0 -2
  23. package/dist/preact/index.cjs.map +0 -1
  24. package/dist/preact/index.d.ts +0 -1
  25. package/dist/preact/index.js +0 -520
  26. package/dist/preact/index.js.map +0 -1
  27. package/dist/preact/utils.d.ts +0 -1
  28. package/dist/react/adapter.d.ts +0 -2
  29. package/dist/react/annotation.d.ts +0 -1
  30. package/dist/react/core.d.ts +0 -1
  31. package/dist/react/index.cjs +0 -2
  32. package/dist/react/index.cjs.map +0 -1
  33. package/dist/react/index.d.ts +0 -1
  34. package/dist/react/index.js +0 -519
  35. package/dist/react/index.js.map +0 -1
  36. package/dist/react/utils.d.ts +0 -1
  37. package/dist/shared/components/annotations/index.d.ts +0 -2
  38. package/dist/shared/components/annotations/redact-area.d.ts +0 -18
  39. package/dist/shared/components/annotations/redact-highlight.d.ts +0 -18
  40. package/dist/shared/components/highlight.d.ts +0 -14
  41. package/dist/shared/components/index.d.ts +0 -5
  42. package/dist/shared/components/marquee-redact.d.ts +0 -15
  43. package/dist/shared/components/pending-redactions.d.ts +0 -12
  44. package/dist/shared/components/redact-renderer-registration.d.ts +0 -5
  45. package/dist/shared/components/redact-renderers.d.ts +0 -7
  46. package/dist/shared/components/redaction-layer.d.ts +0 -16
  47. package/dist/shared/components/selection-redact.d.ts +0 -7
  48. package/dist/shared/components/types.d.ts +0 -9
  49. package/dist/shared/hooks/index.d.ts +0 -1
  50. package/dist/shared/hooks/use-redaction.d.ts +0 -15
  51. package/dist/shared/index.d.ts +0 -4
  52. package/dist/shared-preact/components/annotations/index.d.ts +0 -2
  53. package/dist/shared-preact/components/annotations/redact-area.d.ts +0 -18
  54. package/dist/shared-preact/components/annotations/redact-highlight.d.ts +0 -18
  55. package/dist/shared-preact/components/highlight.d.ts +0 -14
  56. package/dist/shared-preact/components/index.d.ts +0 -5
  57. package/dist/shared-preact/components/marquee-redact.d.ts +0 -15
  58. package/dist/shared-preact/components/pending-redactions.d.ts +0 -12
  59. package/dist/shared-preact/components/redact-renderer-registration.d.ts +0 -5
  60. package/dist/shared-preact/components/redact-renderers.d.ts +0 -7
  61. package/dist/shared-preact/components/redaction-layer.d.ts +0 -16
  62. package/dist/shared-preact/components/selection-redact.d.ts +0 -7
  63. package/dist/shared-preact/components/types.d.ts +0 -9
  64. package/dist/shared-preact/hooks/index.d.ts +0 -1
  65. package/dist/shared-preact/hooks/use-redaction.d.ts +0 -15
  66. package/dist/shared-preact/index.d.ts +0 -4
  67. package/dist/shared-react/components/annotations/index.d.ts +0 -2
  68. package/dist/shared-react/components/annotations/redact-area.d.ts +0 -18
  69. package/dist/shared-react/components/annotations/redact-highlight.d.ts +0 -18
  70. package/dist/shared-react/components/highlight.d.ts +0 -14
  71. package/dist/shared-react/components/index.d.ts +0 -5
  72. package/dist/shared-react/components/marquee-redact.d.ts +0 -15
  73. package/dist/shared-react/components/pending-redactions.d.ts +0 -12
  74. package/dist/shared-react/components/redact-renderer-registration.d.ts +0 -5
  75. package/dist/shared-react/components/redact-renderers.d.ts +0 -7
  76. package/dist/shared-react/components/redaction-layer.d.ts +0 -16
  77. package/dist/shared-react/components/selection-redact.d.ts +0 -7
  78. package/dist/shared-react/components/types.d.ts +0 -9
  79. package/dist/shared-react/hooks/index.d.ts +0 -1
  80. package/dist/shared-react/hooks/use-redaction.d.ts +0 -15
  81. package/dist/shared-react/index.d.ts +0 -4
  82. package/dist/svelte/components/RedactRendererRegistration.svelte.d.ts +0 -7
  83. package/dist/svelte/components/annotations/RedactArea.svelte.d.ts +0 -5
  84. package/dist/svelte/components/annotations/RedactHighlight.svelte.d.ts +0 -5
  85. package/dist/svelte/components/annotations/index.d.ts +0 -2
  86. package/dist/svelte/components/highlight.svelte.d.ts +0 -14
  87. package/dist/svelte/components/index.d.ts +0 -8
  88. package/dist/svelte/components/marquee-redact.svelte.d.ts +0 -16
  89. package/dist/svelte/components/pending-redactions.svelte.d.ts +0 -15
  90. package/dist/svelte/components/redact-renderers.d.ts +0 -7
  91. package/dist/svelte/components/redaction-layer.svelte.d.ts +0 -20
  92. package/dist/svelte/components/selection-redact.svelte.d.ts +0 -8
  93. package/dist/svelte/hooks/index.d.ts +0 -1
  94. package/dist/svelte/hooks/use-redaction.svelte.d.ts +0 -21
  95. package/dist/svelte/index.cjs +0 -2
  96. package/dist/svelte/index.cjs.map +0 -1
  97. package/dist/svelte/index.d.ts +0 -5
  98. package/dist/svelte/index.js +0 -801
  99. package/dist/svelte/index.js.map +0 -1
  100. package/dist/svelte/types.d.ts +0 -10
  101. package/dist/vue/components/annotations/index.d.ts +0 -2
  102. package/dist/vue/components/annotations/redact-area.vue.d.ts +0 -6
  103. package/dist/vue/components/annotations/redact-highlight.vue.d.ts +0 -6
  104. package/dist/vue/components/highlight.vue.d.ts +0 -17
  105. package/dist/vue/components/index.d.ts +0 -8
  106. package/dist/vue/components/marquee-redact.vue.d.ts +0 -19
  107. package/dist/vue/components/pending-redactions.vue.d.ts +0 -68
  108. package/dist/vue/components/redact-renderer-registration.vue.d.ts +0 -13
  109. package/dist/vue/components/redact-renderers.d.ts +0 -7
  110. package/dist/vue/components/redaction-layer.vue.d.ts +0 -50
  111. package/dist/vue/components/selection-redact.vue.d.ts +0 -8
  112. package/dist/vue/components/types.d.ts +0 -9
  113. package/dist/vue/hooks/index.d.ts +0 -1
  114. package/dist/vue/hooks/use-redaction.d.ts +0 -12
  115. package/dist/vue/index.cjs +0 -2
  116. package/dist/vue/index.cjs.map +0 -1
  117. package/dist/vue/index.d.ts +0 -5
  118. package/dist/vue/index.js +0 -638
  119. package/dist/vue/index.js.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/lib/types.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/tools.ts","../src/lib/redaction-plugin.ts","../src/lib/manifest.ts","../src/lib/selectors.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePluginConfig, EventHook } from '@embedpdf/core';\nimport { PdfErrorReason, Rect, Task } from '@embedpdf/models';\n\n// Redaction mode enum\nexport enum RedactionMode {\n /**\n * Unified redaction mode - supports both text selection and area marquee simultaneously.\n * Available when annotation plugin is present.\n */\n Redact = 'redact',\n /**\n * Area-based redactions only (marquee selection).\n * For backwards compatibility with existing code.\n */\n MarqueeRedact = 'marqueeRedact',\n /**\n * Text-based redactions only (text selection).\n * For backwards compatibility with existing code.\n */\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\n// Source mode for redaction items\nexport type RedactionSource = 'annotation' | 'legacy';\n\n// Common base for both kinds\ninterface RedactionItemBase {\n id: string;\n page: number;\n rect: Rect;\n source: RedactionSource;\n markColor: string; // Stroke/outline color (default: '#FF0000')\n redactionColor: string; // Fill color for redaction (transparent or #000000 in legacy, anno.color in annotation mode)\n}\n\nexport type RedactionItem =\n | (RedactionItemBase & {\n kind: 'text';\n rects: Rect[];\n text?: string; // The highlighted text (optional, async populated)\n })\n | (RedactionItemBase & {\n kind: 'area';\n });\n\nexport interface RedactionPluginConfig extends BasePluginConfig {\n drawBlackBoxes: boolean;\n /**\n * When true, use annotation-based redactions (requires annotation plugin).\n * When false (default), use legacy internal pending state.\n */\n useAnnotationMode?: 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 // Unified redact mode (recommended)\n enableRedact(): void;\n toggleRedact(): void;\n isRedactActive(): boolean;\n endRedact(): void;\n\n // Legacy marquee mode (area-based redactions)\n enableMarqueeRedact(): void;\n toggleMarqueeRedact(): void;\n isMarqueeRedactActive(): boolean;\n\n // Legacy selection mode (text-based redactions)\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 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 // Unified redact mode (recommended)\n enableRedact(): void;\n toggleRedact(): void;\n isRedactActive(): boolean;\n endRedact(): void;\n\n // Legacy marquee mode (area-based redactions)\n enableMarqueeRedact(): void;\n toggleMarqueeRedact(): void;\n isMarqueeRedactActive(): boolean;\n\n // Legacy selection mode (text-based redactions)\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 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 { Rect } from '@embedpdf/models';\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 UPDATE_PENDING = 'UPDATE_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 UpdatePendingAction extends Action {\n type: typeof UPDATE_PENDING;\n payload: {\n documentId: string;\n page: number;\n id: string;\n patch: {\n rect?: Rect;\n rects?: Rect[];\n markColor?: string;\n text?: string;\n redactionColor?: string;\n };\n };\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 | UpdatePendingAction\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 updatePending = (\n documentId: string,\n page: number,\n id: string,\n patch: {\n rect?: Rect;\n rects?: Rect[];\n markColor?: string;\n text?: string;\n redactionColor?: string;\n },\n): UpdatePendingAction => ({\n type: UPDATE_PENDING,\n payload: { documentId, page, id, patch },\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 UPDATE_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 const existing = next[item.page] ?? [];\n // Skip if item with same ID already exists\n if (existing.some((it) => it.id === item.id)) continue;\n next[item.page] = existing.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 UPDATE_PENDING: {\n const { documentId, page, id, patch } = action.payload;\n const docState = state.documents[documentId];\n if (!docState) return state;\n\n const list = docState.pending[page] ?? [];\n const updated = list.map((item) => (item.id === id ? { ...item, ...patch } : item));\n\n return {\n ...state,\n documents: {\n ...state.documents,\n [documentId]: {\n ...docState,\n pending: { ...docState.pending, [page]: updated },\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 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 { PdfAnnotationObject, PdfAnnotationSubtype } from '@embedpdf/models';\nimport { AnnotationTool, defineAnnotationTool } from '@embedpdf/plugin-annotation';\nimport { RedactionMode } from './types';\n\n/**\n * Unified Redact tool - handles both text-based and area-based redactions.\n * Dynamically determines isDraggable/isResizable based on whether it has segmentRects.\n */\nexport const redactTool = defineAnnotationTool({\n id: 'redact',\n name: 'Redact',\n categories: ['annotation', 'redaction'],\n matchScore: (a: PdfAnnotationObject) => (a.type === PdfAnnotationSubtype.REDACT ? 10 : 0),\n interaction: {\n mode: RedactionMode.Redact,\n exclusive: false,\n cursor: 'crosshair',\n textSelection: true,\n // Dynamic based on whether it's a text or area redaction\n isDraggable: (anno) => {\n if (anno.type !== PdfAnnotationSubtype.REDACT) return true;\n return !anno.segmentRects?.length;\n },\n isResizable: (anno) => {\n if (anno.type !== PdfAnnotationSubtype.REDACT) return true;\n return !anno.segmentRects?.length;\n },\n isRotatable: false,\n lockAspectRatio: false,\n isGroupDraggable: false,\n isGroupResizable: false,\n isGroupRotatable: false,\n },\n defaults: {\n type: PdfAnnotationSubtype.REDACT,\n color: '#000000',\n overlayColor: '#FFFFFF',\n strokeColor: '#E44234',\n opacity: 1,\n },\n behavior: {\n useAppearanceStream: false,\n },\n} satisfies AnnotationTool);\n\nexport const redactTools = [redactTool];\n","import {\n RedactionPluginConfig,\n RedactionCapability,\n RedactionState,\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 arePropsEqual,\n} from '@embedpdf/core';\nimport {\n PdfAnnotationSubtype,\n PdfDocumentObject,\n PdfErrorCode,\n PdfErrorReason,\n PdfPageObject,\n PdfPermissionFlag,\n PdfRedactAnnoObject,\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 AnnotationCapability,\n AnnotationCommandMetadata,\n AnnotationPlugin,\n AnnotationTool,\n AnnotationToolMap,\n} from '@embedpdf/plugin-annotation';\nimport { HistoryCapability, HistoryPlugin } from '@embedpdf/plugin-history';\nimport {\n addPending,\n clearPending,\n deselectPending,\n endRedaction,\n removePending,\n updatePending,\n selectPending,\n startRedaction,\n initRedactionState,\n cleanupRedactionState,\n RedactionAction,\n} from './actions';\nimport { initialDocumentState } from './reducer';\nimport { redactTool, redactTools } from './tools';\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 private annotationCapability: AnnotationCapability | undefined;\n private historyCapability: HistoryCapability | undefined;\n\n /**\n * Determines which mode to use:\n * - true: Annotation mode (new) - uses REDACT annotations as pending state\n * - false: Legacy mode (deprecated) - uses internal pending state\n */\n private readonly useAnnotationMode: boolean;\n\n // Per-document emitters\n private readonly redactionSelection$ = new Map<\n string,\n ReturnType<typeof createBehaviorEmitter<FormattedSelection[]>>\n >();\n private readonly redactionMarquee$ = new Map<\n string,\n ReturnType<\n typeof createBehaviorEmitter<{ pageIndex: number; rect: Rect | null; modeId: string }>\n >\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 this.annotationCapability = this.registry.getPlugin<AnnotationPlugin>('annotation')?.provides();\n this.historyCapability = this.registry.getPlugin<HistoryPlugin>('history')?.provides();\n\n // Determine mode based on config (default: false/legacy mode)\n if (this.config.useAnnotationMode) {\n if (this.annotationCapability) {\n this.useAnnotationMode = true;\n } else {\n this.logger.warn(\n 'RedactionPlugin',\n 'ConfigError',\n 'useAnnotationMode is enabled but annotation plugin is not available. Falling back to legacy mode.',\n );\n this.useAnnotationMode = false;\n }\n } else {\n this.useAnnotationMode = false;\n }\n\n // Register redact tools with annotation plugin if in annotation mode\n if (this.useAnnotationMode && this.annotationCapability) {\n for (const tool of redactTools) {\n this.annotationCapability.addTool(tool);\n }\n }\n\n // Register redaction modes (same for both annotation and legacy modes)\n this.setupRedactionModes();\n\n // Info log when annotation plugin is available but annotation mode is not enabled\n if (!this.useAnnotationMode && this.annotationCapability) {\n this.logger.info(\n 'RedactionPlugin',\n 'LegacyMode',\n 'Using legacy redaction mode. Set useAnnotationMode: true in config to use annotation-based redactions.',\n );\n }\n\n // Listen to mode changes per document\n this.setupModeChangeListener();\n }\n\n /**\n * Setup redaction modes - registers all interaction modes for redaction.\n * Works for both annotation mode and legacy mode.\n */\n private setupRedactionModes(): void {\n if (!this.interactionManagerCapability) return;\n\n // Register unified mode (recommended - supports both text and area)\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.Redact,\n scope: 'page',\n exclusive: false,\n cursor: 'crosshair',\n });\n\n // Also register legacy modes for backwards compatibility\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.MarqueeRedact,\n scope: 'page',\n exclusive: false,\n cursor: 'crosshair',\n });\n this.interactionManagerCapability.registerMode({\n id: RedactionMode.RedactSelection,\n scope: 'page',\n exclusive: false,\n });\n }\n\n /**\n * Setup mode change listener - handles all redaction modes\n */\n private setupModeChangeListener(): void {\n this.interactionManagerCapability?.onModeChange((modeState) => {\n const documentId = modeState.documentId;\n\n // Check if any redaction mode is active\n const isRedactionMode =\n modeState.activeMode === RedactionMode.Redact ||\n modeState.activeMode === RedactionMode.MarqueeRedact ||\n modeState.activeMode === RedactionMode.RedactSelection;\n\n if (isRedactionMode) {\n this.dispatch(startRedaction(documentId, modeState.activeMode as RedactionMode));\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 emitters\n this.redactionSelection$.set(documentId, createBehaviorEmitter<FormattedSelection[]>());\n this.redactionMarquee$.set(\n documentId,\n createBehaviorEmitter<{ pageIndex: number; rect: Rect | null; modeId: string }>(),\n );\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 if (!this.checkPermission(documentId, PdfPermissionFlag.ModifyContents)) return;\n\n const formattedSelection = selectionScope.getFormattedSelection();\n if (!formattedSelection.length) return;\n\n // Fetch selected text BEFORE clearing (async, but started now while selection exists)\n const textTask = selectionScope.getSelectedText();\n\n const emitter = this.redactionSelection$.get(documentId);\n emitter?.emit([]);\n selectionScope.clear();\n\n // Wait for text, then create redactions with text included\n textTask.wait(\n (textArr) => {\n const text = textArr.join(' ');\n this.createRedactionsFromSelection(documentId, formattedSelection, text);\n },\n () => {\n // On error, still create redactions but without text\n this.createRedactionsFromSelection(documentId, formattedSelection);\n },\n );\n });\n\n // Forward marquee preview rects (for MarqueeRedact component)\n const unsubMarqueeChange = selectionScope.onMarqueeChange((event) => {\n const docState = this.getDocumentState(documentId);\n if (!docState?.isRedacting) return;\n this.redactionMarquee$\n .get(documentId)\n ?.emit({ pageIndex: event.pageIndex, rect: event.rect, modeId: event.modeId });\n });\n\n // Create area redaction when marquee completes\n const unsubMarqueeEnd = selectionScope.onMarqueeEnd((event) => {\n const docState = this.getDocumentState(documentId);\n if (!docState?.isRedacting) return;\n if (!this.checkPermission(documentId, PdfPermissionFlag.ModifyContents)) return;\n\n if (this.useAnnotationMode) {\n this.createRedactAnnotationFromArea(documentId, event.pageIndex, event.rect);\n } else {\n // Legacy mode: create pending item\n const redactionColor = this.config.drawBlackBoxes ? '#000000' : 'transparent';\n const item: RedactionItem = {\n id: uuidV4(),\n kind: 'area',\n page: event.pageIndex,\n rect: event.rect,\n source: 'legacy',\n markColor: '#FF0000',\n redactionColor,\n };\n this.dispatch(addPending(documentId, [item]));\n this.selectPending(event.pageIndex, item.id, documentId);\n }\n });\n\n // Deselect pending redaction when clicking on empty page space\n const unsubEmptySpaceClick = selectionScope.onEmptySpaceClick(() => {\n this.deselectPending(documentId);\n });\n\n unsubscribers.push(\n unsubSelection,\n unsubEndSelection,\n unsubMarqueeChange,\n unsubMarqueeEnd,\n unsubEmptySpaceClick,\n );\n }\n\n // Setup annotation event forwarding AND state sync in annotation mode\n if (this.useAnnotationMode && this.annotationCapability) {\n const annoScope = this.annotationCapability.forDocument(documentId);\n\n const unsubEvents = annoScope.onAnnotationEvent((event) => {\n if (event.type === 'loaded') {\n // Sync existing REDACT annotations after initial load\n this.syncFromAnnotationLoad(documentId);\n return;\n }\n\n // Only process REDACT annotations\n if (event.annotation?.type !== PdfAnnotationSubtype.REDACT) return;\n const redactAnno = event.annotation as PdfRedactAnnoObject;\n\n if (event.type === 'create') {\n this.syncFromAnnotationCreate(documentId, redactAnno);\n this.events$.emit({\n type: 'add',\n documentId,\n items: [this.annotationToRedactionItem(redactAnno)],\n });\n } else if (event.type === 'update') {\n this.logger.debug('RedactionPlugin', 'AnnotationUpdated', {\n documentId,\n redactAnno,\n patch: event.patch as Partial<PdfRedactAnnoObject>,\n });\n this.syncFromAnnotationUpdate(\n documentId,\n redactAnno,\n event.patch as Partial<PdfRedactAnnoObject>,\n );\n } else if (event.type === 'delete') {\n this.syncFromAnnotationDelete(documentId, redactAnno);\n this.events$.emit({\n type: 'remove',\n documentId,\n page: redactAnno.pageIndex,\n id: redactAnno.id,\n });\n }\n });\n\n // Sync selection state when annotation selection changes\n const unsubState = annoScope.onStateChange(() => {\n this.syncSelectionFromAnnotation(documentId);\n });\n\n unsubscribers.push(unsubEvents, unsubState);\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 // Redaction plugin renders its own selection & marquee rects, so suppress selection layer rects.\n // Unified mode: both text selection and marquee\n this.selectionCapability?.enableForMode(\n RedactionMode.Redact,\n {\n enableSelection: true,\n showSelectionRects: false,\n enableMarquee: true,\n showMarqueeRects: false,\n },\n documentId,\n );\n // Legacy marquee-only mode\n this.selectionCapability?.enableForMode(\n RedactionMode.MarqueeRedact,\n {\n enableSelection: false,\n enableMarquee: true,\n showMarqueeRects: false,\n },\n documentId,\n );\n // Legacy selection-only mode\n this.selectionCapability?.enableForMode(\n RedactionMode.RedactSelection,\n {\n enableSelection: true,\n showSelectionRects: false,\n },\n documentId,\n );\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 const marqueeEmitter = this.redactionMarquee$.get(documentId);\n marqueeEmitter?.clear();\n this.redactionMarquee$.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 // Unified redact mode\n enableRedact: () => this.enableRedact(),\n toggleRedact: () => this.toggleRedact(),\n isRedactActive: () => this.isRedactActive(),\n endRedact: () => this.endRedact(),\n\n // Legacy marquee mode\n enableMarqueeRedact: () => this.enableMarqueeRedact(),\n toggleMarqueeRedact: () => this.toggleMarqueeRedact(),\n isMarqueeRedactActive: () => this.isMarqueeRedactActive(),\n\n // Legacy selection mode\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 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 // Unified redact mode\n enableRedact: () => this.enableRedact(documentId),\n toggleRedact: () => this.toggleRedact(documentId),\n isRedactActive: () => this.isRedactActive(documentId),\n endRedact: () => this.endRedact(documentId),\n\n // Legacy marquee mode\n enableMarqueeRedact: () => this.enableMarqueeRedact(documentId),\n toggleMarqueeRedact: () => this.toggleMarqueeRedact(documentId),\n isMarqueeRedactActive: () => this.isMarqueeRedactActive(documentId),\n\n // Legacy selection mode\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 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 /**\n * Get pending redactions derived from annotation plugin (annotation mode only)\n */\n private getPendingFromAnnotations(documentId: string): Record<number, RedactionItem[]> {\n if (!this.annotationCapability) return {};\n\n try {\n const annoState = this.annotationCapability.forDocument(documentId).getState();\n const result: Record<number, RedactionItem[]> = {};\n\n for (const ta of Object.values(annoState.byUid)) {\n if (ta.object.type === PdfAnnotationSubtype.REDACT) {\n const item = this.annotationToRedactionItem(ta.object);\n const page = ta.object.pageIndex;\n (result[page] ??= []).push(item);\n }\n }\n return result;\n } catch {\n // Annotation state not initialized yet\n return {};\n }\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 private isRedactTool(tool: AnnotationTool | undefined): tool is typeof redactTool {\n return tool?.id === redactTool.id && tool.defaults.type === PdfAnnotationSubtype.REDACT;\n }\n\n private getRedactTool(): typeof redactTool | undefined {\n const tool = this.annotationCapability?.getTool('redact');\n return this.isRedactTool(tool) ? tool : undefined;\n }\n\n // ─────────────────────────────────────────────────────────\n // Annotation Mode State Sync\n // ─────────────────────────────────────────────────────────\n\n /**\n * Sync internal state when REDACT annotation is created.\n * Called from annotation event listener in annotation mode.\n */\n private syncFromAnnotationCreate(documentId: string, annotation: PdfRedactAnnoObject): void {\n const item = this.annotationToRedactionItem(annotation);\n this.dispatch(addPending(documentId, [item]));\n }\n\n /**\n * Sync internal state when REDACT annotation is updated (moved/resized/color changed).\n * Called from annotation event listener in annotation mode.\n */\n private syncFromAnnotationUpdate(\n documentId: string,\n annotation: PdfRedactAnnoObject,\n patch: Partial<PdfRedactAnnoObject>,\n ): void {\n // Only sync if rect, segmentRects, strokeColor, or color changed\n if (\n !('rect' in patch) &&\n !('segmentRects' in patch) &&\n !('strokeColor' in patch) &&\n !('color' in patch)\n )\n return;\n\n const updatePatch: {\n rect?: Rect;\n rects?: Rect[];\n markColor?: string;\n redactionColor?: string;\n } = {};\n if (patch.rect) updatePatch.rect = patch.rect;\n if (patch.segmentRects) updatePatch.rects = patch.segmentRects;\n if (patch.strokeColor) updatePatch.markColor = patch.strokeColor;\n if (patch.color) updatePatch.redactionColor = patch.color;\n\n this.logger.debug('RedactionPlugin', 'AnnotationUpdated', {\n documentId,\n annotation,\n patch: updatePatch,\n });\n\n this.dispatch(updatePending(documentId, annotation.pageIndex, annotation.id, updatePatch));\n }\n\n /**\n * Sync internal state when REDACT annotation is deleted.\n * Called from annotation event listener in annotation mode.\n */\n private syncFromAnnotationDelete(documentId: string, annotation: PdfRedactAnnoObject): void {\n this.dispatch(removePending(documentId, annotation.pageIndex, annotation.id));\n }\n\n /**\n * Sync internal state from existing REDACT annotations after initial load.\n * Called when annotation plugin emits 'loaded' event.\n */\n private syncFromAnnotationLoad(documentId: string): void {\n const pending = this.getPendingFromAnnotations(documentId);\n\n // Clear and repopulate (in case of reload scenarios)\n this.dispatch(clearPending(documentId));\n\n for (const [, items] of Object.entries(pending)) {\n if (items.length > 0) {\n this.dispatch(addPending(documentId, items));\n }\n }\n }\n\n /**\n * Sync selection state from annotation plugin's selected REDACT annotation.\n * Called when annotation plugin state changes.\n */\n private syncSelectionFromAnnotation(documentId: string): void {\n const annoState = this.annotationCapability?.forDocument(documentId).getState();\n if (!annoState) return;\n\n // Find if a REDACT annotation is selected\n const selectedRedact = annoState.selectedUids\n .map((uid) => annoState.byUid[uid])\n .find((ta) => ta?.object.type === PdfAnnotationSubtype.REDACT);\n\n if (selectedRedact) {\n const obj = selectedRedact.object as PdfRedactAnnoObject;\n this.dispatch(selectPending(documentId, obj.pageIndex, obj.id));\n } else {\n // Check if currently selected in redaction state - if so, clear it\n const docState = this.getDocumentState(documentId);\n if (docState?.selected) {\n this.dispatch(deselectPending(documentId));\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Core Operations\n // ─────────────────────────────────────────────────────────\n\n private addPendingItems(items: RedactionItem[], documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n\n // Prevent adding redactions without permission\n if (!this.checkPermission(id, PdfPermissionFlag.ModifyContents)) {\n this.logger.debug(\n 'RedactionPlugin',\n 'AddPendingItems',\n `Cannot add redactions: document ${id} lacks ModifyContents permission`,\n );\n return;\n }\n\n if (this.useAnnotationMode) {\n // ANNOTATION MODE: Create REDACT annotations via annotation plugin\n if (!this.annotationCapability) return;\n const annoScope = this.annotationCapability.forDocument(id);\n for (const item of items) {\n const annotation = this.redactionItemToAnnotation(item);\n annoScope.createAnnotation(item.page, annotation);\n }\n // Select the last one\n if (items.length > 0) {\n const lastItem = items[items.length - 1];\n annoScope.selectAnnotation(lastItem.page, lastItem.id);\n }\n } else {\n // LEGACY MODE: Add to internal pending state\n this.dispatch(addPending(id, items));\n }\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\n if (this.useAnnotationMode) {\n // ANNOTATION MODE: Delete annotation via annotation plugin\n this.annotationCapability?.forDocument(id).deleteAnnotation(page, itemId);\n } else {\n // LEGACY MODE: Remove from internal state\n this.dispatch(removePending(id, page, itemId));\n }\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\n if (this.useAnnotationMode) {\n // ANNOTATION MODE: Delete all REDACT annotations\n const pending = this.getPendingFromAnnotations(id);\n const annoScope = this.annotationCapability?.forDocument(id);\n for (const [pageStr, items] of Object.entries(pending)) {\n const page = Number(pageStr);\n for (const item of items) {\n annoScope?.deleteAnnotation(page, item.id);\n }\n }\n } else {\n // LEGACY MODE: Clear internal state\n this.dispatch(clearPending(id));\n }\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\n if (this.useAnnotationMode) {\n // ANNOTATION MODE: Select annotation via annotation plugin\n // (annotation plugin handles 'annotation-selection' page activity)\n this.annotationCapability?.forDocument(id).selectAnnotation(page, itemId);\n } else {\n // LEGACY MODE: Update internal selection state\n this.dispatch(selectPending(id, page, itemId));\n // Claim page activity so the scroll plugin can elevate this page\n this.interactionManagerCapability?.claimPageActivity(id, 'redaction-selection', page);\n }\n this.selectionCapability?.forDocument(id).clear();\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\n if (this.useAnnotationMode) {\n // ANNOTATION MODE: Deselect via annotation plugin\n // (annotation plugin handles 'annotation-selection' page activity)\n this.annotationCapability?.forDocument(id).deselectAnnotation();\n } else {\n // LEGACY MODE: Update internal selection state\n this.dispatch(deselectPending(id));\n // Release page activity claim\n this.interactionManagerCapability?.releasePageActivity(id, 'redaction-selection');\n }\n }\n\n // ─────────────────────────────────────────────────────────\n // Legacy Selection Mode (text-based redactions)\n // ─────────────────────────────────────────────────────────\n\n private enableRedactSelection(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n\n // Prevent enabling redact selection without permission\n if (!this.checkPermission(id, PdfPermissionFlag.ModifyContents)) {\n this.logger.debug(\n 'RedactionPlugin',\n 'EnableRedactSelection',\n `Cannot enable redact selection: document ${id} lacks ModifyContents permission`,\n );\n return;\n }\n\n // Always activate RedactSelection mode (works in both annotation and legacy modes)\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 const activeMode = scope?.getActiveMode();\n\n if (activeMode === RedactionMode.RedactSelection) {\n scope?.activateDefaultMode();\n } else {\n // Prevent enabling without permission\n if (!this.checkPermission(id, PdfPermissionFlag.ModifyContents)) {\n return;\n }\n scope?.activate(RedactionMode.RedactSelection);\n }\n }\n\n private isRedactSelectionActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n const activeMode = this.interactionManagerCapability?.forDocument(id).getActiveMode();\n // Selection is available in both Redact and RedactSelection modes\n return activeMode === RedactionMode.Redact || activeMode === RedactionMode.RedactSelection;\n }\n\n // ─────────────────────────────────────────────────────────\n // Legacy Marquee Mode (area-based redactions)\n // ─────────────────────────────────────────────────────────\n\n private enableMarqueeRedact(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n\n // Prevent enabling marquee redact without permission\n if (!this.checkPermission(id, PdfPermissionFlag.ModifyContents)) {\n this.logger.debug(\n 'RedactionPlugin',\n 'EnableMarqueeRedact',\n `Cannot enable marquee redact: document ${id} lacks ModifyContents permission`,\n );\n return;\n }\n\n // Always activate MarqueeRedact mode (works in both annotation and legacy modes)\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 const activeMode = scope?.getActiveMode();\n\n if (activeMode === RedactionMode.MarqueeRedact) {\n scope?.activateDefaultMode();\n } else {\n // Prevent enabling without permission\n if (!this.checkPermission(id, PdfPermissionFlag.ModifyContents)) {\n return;\n }\n scope?.activate(RedactionMode.MarqueeRedact);\n }\n }\n\n private isMarqueeRedactActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n const activeMode = this.interactionManagerCapability?.forDocument(id).getActiveMode();\n // Marquee is available in both Redact and MarqueeRedact modes\n return activeMode === RedactionMode.Redact || activeMode === RedactionMode.MarqueeRedact;\n }\n\n // ─────────────────────────────────────────────────────────\n // Unified Redact Mode (recommended)\n // ─────────────────────────────────────────────────────────\n\n private enableRedact(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n\n // Prevent enabling redact mode without permission\n if (!this.checkPermission(id, PdfPermissionFlag.ModifyContents)) {\n this.logger.debug(\n 'RedactionPlugin',\n 'EnableRedact',\n `Cannot enable redact mode: document ${id} lacks ModifyContents permission`,\n );\n return;\n }\n\n this.interactionManagerCapability?.forDocument(id).activate(RedactionMode.Redact);\n }\n\n private toggleRedact(documentId?: string) {\n const id = documentId ?? this.getActiveDocumentId();\n const scope = this.interactionManagerCapability?.forDocument(id);\n const activeMode = scope?.getActiveMode();\n\n if (activeMode === RedactionMode.Redact) {\n scope?.activateDefaultMode();\n } else {\n // Prevent enabling redact mode without permission\n if (!this.checkPermission(id, PdfPermissionFlag.ModifyContents)) {\n return;\n }\n scope?.activate(RedactionMode.Redact);\n }\n }\n\n private isRedactActive(documentId?: string): boolean {\n const id = documentId ?? this.getActiveDocumentId();\n const activeMode = this.interactionManagerCapability?.forDocument(id).getActiveMode();\n return activeMode === RedactionMode.Redact;\n }\n\n private endRedact(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 onRedactionMarqueeChange(\n documentId: string,\n callback: (data: { pageIndex: number; rect: Rect | null; modeId: string }) => void,\n ) {\n const emitter = this.redactionMarquee$.get(documentId);\n return emitter?.on(callback) ?? (() => {});\n }\n\n /**\n * Get the stroke color for redaction previews.\n * In annotation mode: returns tool's defaults.strokeColor\n * In legacy mode: returns hardcoded red\n */\n public getPreviewStrokeColor(): string {\n if (this.useAnnotationMode) {\n return this.getRedactTool()?.defaults.strokeColor ?? '#FF0000';\n }\n return '#FF0000';\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\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\n const selectionScope = this.selectionCapability.forDocument(id);\n const formatted = selectionScope.getFormattedSelection();\n if (!formatted.length) return PdfTaskHelper.resolve(true);\n\n // Fetch selected text BEFORE clearing (async, but started now while selection exists)\n const textTask = selectionScope.getSelectedText();\n\n // Clear live UI selection\n const emitter = this.redactionSelection$.get(id);\n emitter?.emit([]);\n selectionScope.clear();\n\n // Enable redact selection mode for legacy mode\n if (!this.useAnnotationMode) {\n this.enableRedactSelection(id);\n }\n\n // Wait for text, then create redactions with text included\n const task = new Task<boolean, PdfErrorReason>();\n textTask.wait(\n (textArr) => {\n const text = textArr.join(' ');\n this.createRedactionsFromSelection(id, formatted, text);\n task.resolve(true);\n },\n () => {\n // On error, still create redactions but without text\n this.createRedactionsFromSelection(id, formatted);\n task.resolve(true);\n },\n );\n\n return task;\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\n // Prevent committing redactions without permission\n if (!this.checkPermission(docId, PdfPermissionFlag.ModifyContents)) {\n this.logger.debug(\n 'RedactionPlugin',\n 'CommitPendingOne',\n `Cannot commit redaction: document ${docId} lacks ModifyContents permission`,\n );\n return PdfTaskHelper.reject({\n code: PdfErrorCode.Security,\n message: 'Document lacks ModifyContents permission',\n });\n }\n\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 pdfPage = coreDoc.document.pages[page];\n if (!pdfPage)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Page not found' });\n\n if (this.useAnnotationMode) {\n // ANNOTATION MODE: Use applyRedaction engine method\n // In annotation mode, pending redactions are stored as REDACT annotations,\n // not in docState.pending, so we go directly to apply\n this.logger.debug(\n 'RedactionPlugin',\n 'CommitPendingOne',\n `Applying redaction in annotation mode: page ${page}, id ${id}`,\n );\n return this.applyRedactionAnnotationMode(docId, coreDoc.document, pdfPage, id);\n }\n\n // LEGACY MODE: Use internal pending state\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) {\n this.logger.debug(\n 'RedactionPlugin',\n 'CommitPendingOne',\n `No pending item found for page ${page}, id ${id}`,\n );\n return PdfTaskHelper.resolve(true);\n }\n\n return this.commitPendingOneLegacy(docId, coreDoc.document, pdfPage, page, item);\n }\n\n /**\n * Legacy commit single redaction using redactTextInRects\n */\n private commitPendingOneLegacy(\n docId: string,\n doc: PdfDocumentObject,\n pdfPage: PdfPageObject,\n page: number,\n item: RedactionItem,\n ): Task<boolean, PdfErrorReason> {\n const rects: Rect[] = item.kind === 'text' ? item.rects : [item.rect];\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(docId, page, item.id));\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 /**\n * Annotation mode: Apply single redaction using engine.applyRedaction\n */\n private applyRedactionAnnotationMode(\n docId: string,\n doc: PdfDocumentObject,\n pdfPage: PdfPageObject,\n annotationId: string,\n ): Task<boolean, PdfErrorReason> {\n const task = new Task<boolean, PdfErrorReason>();\n\n // Get the annotation from annotation plugin\n const anno = this.annotationCapability?.forDocument(docId).getAnnotationById(annotationId);\n this.logger.debug(\n 'RedactionPlugin',\n 'ApplyRedactionAnnotationMode',\n `Looking for annotation ${annotationId}, found: ${!!anno}, type: ${anno?.object.type}`,\n );\n\n if (!anno || anno.object.type !== PdfAnnotationSubtype.REDACT) {\n this.logger.warn(\n 'RedactionPlugin',\n 'ApplyRedactionAnnotationMode',\n `Redaction annotation not found or wrong type: ${annotationId}`,\n );\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Redaction annotation not found',\n });\n }\n\n this.logger.debug(\n 'RedactionPlugin',\n 'ApplyRedactionAnnotationMode',\n `Calling engine.applyRedaction for annotation ${annotationId} on page ${pdfPage.index}`,\n );\n\n this.engine.applyRedaction(doc, pdfPage, anno.object).wait(\n () => {\n this.logger.debug(\n 'RedactionPlugin',\n 'ApplyRedactionAnnotationMode',\n `Successfully applied redaction ${annotationId} on page ${pdfPage.index}`,\n );\n // Purge the annotation from state (engine already removed it from PDF)\n this.annotationCapability?.forDocument(docId).purgeAnnotation(pdfPage.index, annotationId);\n\n // Remove from internal pending state (purgeAnnotation doesn't emit events)\n this.dispatch(removePending(docId, pdfPage.index, annotationId));\n\n // Purge history entries for this committed redaction (permanent, irreversible operation)\n this.historyCapability\n ?.forDocument(docId)\n .purgeByMetadata<AnnotationCommandMetadata>(\n (meta) => meta?.annotationIds?.includes(annotationId) ?? false,\n 'annotations',\n );\n\n this.dispatchCoreAction(refreshPages(docId, [pdfPage.index]));\n this.events$.emit({ type: 'commit', documentId: docId, success: true });\n task.resolve(true);\n },\n (error) => {\n this.logger.error(\n 'RedactionPlugin',\n 'ApplyRedactionAnnotationMode',\n `Failed to apply redaction ${annotationId}: ${error.reason?.message ?? 'Unknown error'}`,\n );\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 apply redaction' });\n },\n );\n\n return task;\n }\n\n private commitAllPending(documentId?: string): Task<boolean, PdfErrorReason> {\n const docId = documentId ?? this.getActiveDocumentId();\n\n // Prevent committing redactions without permission\n if (!this.checkPermission(docId, PdfPermissionFlag.ModifyContents)) {\n this.logger.debug(\n 'RedactionPlugin',\n 'CommitAllPending',\n `Cannot commit redactions: document ${docId} lacks ModifyContents permission`,\n );\n return PdfTaskHelper.reject({\n code: PdfErrorCode.Security,\n message: 'Document lacks ModifyContents permission',\n });\n }\n\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 if (this.useAnnotationMode) {\n // ANNOTATION MODE: Use applyAllRedactions per page\n return this.applyAllRedactionsAnnotationMode(docId, coreDoc.document);\n } else {\n // LEGACY MODE: Use redactTextInRects\n return this.commitAllPendingLegacy(docId, coreDoc.document, docState);\n }\n }\n\n /**\n * Legacy commit all redactions using redactTextInRects\n */\n private commitAllPendingLegacy(\n docId: string,\n doc: PdfDocumentObject,\n docState: RedactionDocumentState,\n ): Task<boolean, PdfErrorReason> {\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 = 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(docId));\n this.dispatchCoreAction(refreshPages(docId, pagesToRefresh));\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 * Annotation mode: Apply all redactions using engine.applyAllRedactions per page\n */\n private applyAllRedactionsAnnotationMode(\n docId: string,\n doc: PdfDocumentObject,\n ): Task<boolean, PdfErrorReason> {\n const annotationCapability = this.annotationCapability;\n if (!annotationCapability) {\n return PdfTaskHelper.reject({\n code: PdfErrorCode.NotFound,\n message: 'Annotation capability not found',\n });\n }\n\n // Collect all REDACT annotation IDs per page (for purging after apply)\n const annoState = annotationCapability.forDocument(docId).getState();\n const redactAnnotationsByPage = new Map<number, string[]>();\n\n for (const ta of Object.values(annoState.byUid)) {\n if (ta.object.type === PdfAnnotationSubtype.REDACT) {\n const pageIds = redactAnnotationsByPage.get(ta.object.pageIndex) ?? [];\n pageIds.push(ta.object.id);\n redactAnnotationsByPage.set(ta.object.pageIndex, pageIds);\n }\n }\n\n const pagesToProcess = Array.from(redactAnnotationsByPage.keys());\n\n if (pagesToProcess.length === 0) {\n return PdfTaskHelper.resolve(true);\n }\n\n const tasks: PdfTask<boolean>[] = [];\n for (const pageIndex of pagesToProcess) {\n const page = doc.pages[pageIndex];\n if (!page) continue;\n tasks.push(this.engine.applyAllRedactions(doc, page));\n }\n\n const task = new Task<boolean, PdfErrorReason>();\n Task.all(tasks).wait(\n () => {\n // Purge all REDACT annotations from state (engine already removed them from PDF)\n const annoScope = annotationCapability.forDocument(docId);\n const allPurgedIds: string[] = [];\n\n for (const [pageIndex, ids] of redactAnnotationsByPage) {\n for (const id of ids) {\n annoScope.purgeAnnotation(pageIndex, id);\n // Remove from internal pending state (purgeAnnotation doesn't emit events)\n this.dispatch(removePending(docId, pageIndex, id));\n allPurgedIds.push(id);\n }\n }\n\n // Purge history entries for all committed redactions (permanent, irreversible operations)\n if (allPurgedIds.length > 0) {\n this.historyCapability\n ?.forDocument(docId)\n .purgeByMetadata<AnnotationCommandMetadata>(\n (meta) => meta?.annotationIds?.some((id) => allPurgedIds.includes(id)) ?? false,\n 'annotations',\n );\n }\n\n this.dispatchCoreAction(refreshPages(docId, pagesToProcess));\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 apply redactions' });\n },\n );\n\n return task;\n }\n\n // ─────────────────────────────────────────────────────────\n // Annotation Mode Helpers\n // ─────────────────────────────────────────────────────────\n\n /**\n * Create REDACT annotations from text selection (annotation mode only)\n * @returns Array of annotation IDs that were created\n */\n private createRedactAnnotationsFromSelection(\n documentId: string,\n formattedSelection: FormattedSelection[],\n text?: string,\n ): string[] {\n if (!this.annotationCapability) return [];\n\n const annoScope = this.annotationCapability.forDocument(documentId);\n const defaults = this.getRedactTool()?.defaults;\n const annotationIds: string[] = [];\n\n for (const selection of formattedSelection) {\n const annotationId = uuidV4();\n annotationIds.push(annotationId);\n\n const annotation: PdfRedactAnnoObject = {\n ...defaults,\n id: annotationId,\n type: PdfAnnotationSubtype.REDACT,\n pageIndex: selection.pageIndex,\n rect: selection.rect,\n segmentRects: selection.segmentRects,\n ...(text ? { custom: { text } } : {}),\n created: new Date(),\n };\n\n annoScope.createAnnotation(selection.pageIndex, annotation);\n\n // Select the last created annotation\n if (selection === formattedSelection[formattedSelection.length - 1]) {\n annoScope.selectAnnotation(selection.pageIndex, annotationId);\n }\n }\n\n // Update pending items with text if provided\n // (syncFromAnnotationCreate adds the items to pending state)\n if (text) {\n for (let i = 0; i < annotationIds.length; i++) {\n const pageIndex = formattedSelection[i].pageIndex;\n this.dispatch(updatePending(documentId, pageIndex, annotationIds[i], { text }));\n }\n }\n\n return annotationIds;\n }\n\n /**\n * Create legacy RedactionItems from text selection (legacy mode only)\n */\n private createLegacyRedactionsFromSelection(\n documentId: string,\n formattedSelection: FormattedSelection[],\n text?: string,\n ): void {\n const redactionColor = this.config.drawBlackBoxes ? '#000000' : 'transparent';\n const items: RedactionItem[] = formattedSelection.map((s) => ({\n id: uuidV4(),\n kind: 'text' as const,\n page: s.pageIndex,\n rect: s.rect,\n rects: s.segmentRects,\n source: 'legacy' as const,\n markColor: '#FF0000',\n redactionColor,\n text,\n }));\n\n this.dispatch(addPending(documentId, items));\n\n if (items.length) {\n this.selectPending(items[items.length - 1].page, items[items.length - 1].id, documentId);\n }\n }\n\n /**\n * Unified method to create redactions from text selection.\n * Delegates to annotation mode or legacy mode helper based on configuration.\n */\n private createRedactionsFromSelection(\n documentId: string,\n formattedSelection: FormattedSelection[],\n text?: string,\n ): void {\n if (this.useAnnotationMode) {\n this.createRedactAnnotationsFromSelection(documentId, formattedSelection, text);\n } else {\n this.createLegacyRedactionsFromSelection(documentId, formattedSelection, text);\n }\n }\n\n /**\n * Create a REDACT annotation from an area/marquee selection (annotation mode only)\n */\n private createRedactAnnotationFromArea(documentId: string, pageIndex: number, rect: Rect): void {\n if (!this.annotationCapability) return;\n\n const annoScope = this.annotationCapability.forDocument(documentId);\n const defaults = this.getRedactTool()?.defaults;\n const annotationId = uuidV4();\n\n const annotation: PdfRedactAnnoObject = {\n ...defaults,\n id: annotationId,\n type: PdfAnnotationSubtype.REDACT,\n pageIndex,\n rect,\n segmentRects: [], // No segment rects for area redaction\n created: new Date(),\n };\n\n annoScope.createAnnotation(pageIndex, annotation);\n annoScope.selectAnnotation(pageIndex, annotationId);\n }\n\n /**\n * Convert a RedactionItem to a PdfRedactAnnoObject\n */\n private redactionItemToAnnotation(item: RedactionItem): PdfRedactAnnoObject {\n const defaults = this.getRedactTool()?.defaults ?? {};\n\n return {\n ...defaults,\n id: item.id,\n type: PdfAnnotationSubtype.REDACT,\n pageIndex: item.page,\n rect: item.rect,\n segmentRects: item.kind === 'text' ? item.rects : [],\n created: new Date(),\n };\n }\n\n /**\n * Convert a PdfRedactAnnoObject to a RedactionItem\n */\n private annotationToRedactionItem(anno: PdfRedactAnnoObject): RedactionItem {\n const markColor = anno.strokeColor ?? '#FF0000';\n const redactionColor = anno.color ?? 'transparent';\n\n if (anno.segmentRects && anno.segmentRects.length > 0) {\n return {\n id: anno.id,\n kind: 'text',\n page: anno.pageIndex,\n rect: anno.rect,\n rects: anno.segmentRects,\n source: 'annotation',\n markColor,\n redactionColor,\n ...(anno.custom?.text ? { text: anno.custom.text } : {}),\n };\n } else {\n return {\n id: anno.id,\n kind: 'area',\n page: anno.pageIndex,\n rect: anno.rect,\n source: 'annotation',\n markColor,\n redactionColor,\n };\n }\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 this.redactionMarquee$.forEach((emitter) => emitter.clear());\n this.redactionMarquee$.clear();\n\n // Cleanup all unsubscribers\n this.documentUnsubscribers.forEach((unsubscribers) => {\n unsubscribers.forEach((unsub) => unsub());\n });\n this.documentUnsubscribers.clear();\n\n await super.destroy();\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { RedactionPluginConfig } from './types';\n\nexport const REDACTION_PLUGIN_ID = 'redaction';\n\nexport const manifest: PluginManifest<RedactionPluginConfig> = {\n id: REDACTION_PLUGIN_ID,\n name: 'Redaction Plugin',\n version: '1.0.0',\n provides: ['redaction'],\n requires: [],\n optional: ['interaction-manager', 'selection', 'annotation'],\n defaultConfig: {\n drawBlackBoxes: true,\n },\n};\n","import { RedactionState, RedactionDocumentState } from './types';\n\nexport const getPendingRedactionsCount = (s: RedactionDocumentState) => s.pendingCount;\n\nexport const hasPendingRedactions = (s: RedactionDocumentState) => s.pendingCount > 0;\n\nexport const getDocumentPendingCount = (state: RedactionState, documentId: string): number => {\n return state.documents[documentId]?.pendingCount ?? 0;\n};\n\nexport const getTotalPendingCount = (state: RedactionState): number => {\n return Object.values(state.documents).reduce((sum, doc) => sum + doc.pendingCount, 0);\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { RedactionPluginConfig, RedactionState } from './types';\nimport { RedactionPlugin } from './redaction-plugin';\nimport { manifest, REDACTION_PLUGIN_ID } from './manifest';\nimport { RedactionAction } from './actions';\nimport { initialState, redactionReducer } from './reducer';\n\nexport const RedactionPluginPackage: PluginPackage<\n RedactionPlugin,\n RedactionPluginConfig,\n RedactionState,\n RedactionAction\n> = {\n manifest,\n create: (registry, config) => new RedactionPlugin(REDACTION_PLUGIN_ID, registry, config),\n reducer: redactionReducer,\n initialState: initialState,\n};\n\nexport * from './redaction-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './selectors';\nexport * from './tools';\nexport { initialState, initialDocumentState } from './reducer';\n"],"names":["RedactionMode","_a"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/capability.ts","../src/reducer.ts","../src/types.ts","../src/redaction.plugin.ts"],"sourcesContent":["import type { DocCapability, PluginContext } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/internal';\nimport { InteractionToken } from '@embedpdf/plugin-interaction';\nimport { SelectionToken } from '@embedpdf/plugin-selection';\nimport type {\n AnnotationDTO,\n AnnotationRef,\n PdfRect,\n RedactionApplyResult,\n} from '@embedpdf/engine-core';\nimport type {\n RedactionAction,\n RedactionCapability,\n RedactionLabelPatch,\n RedactionPendingItem,\n RedactionState,\n} from './types';\n\n/** Applying destroys content — its own granted power, narrower than annotate. */\nconst REDACT_CAPABILITY: DocCapability = 'doc.redact';\n\n/** The annotation plugin's model-id convention for a durable ref. */\nconst idOf = (ref: AnnotationRef): string =>\n ref.kind === 'objectNumber'\n ? `obj:${ref.annotObjectNumber}`\n : ref.kind === 'nm'\n ? `nm:${ref.nm}`\n : `idx:${ref.pageObjectNumber}:${ref.index}`;\n\ntype RedactDTO = Extract<AnnotationDTO, { subtype: 'redact' }>;\n\n/** The PDF-space regions a redact mark targets: its quads' boxes, else `/Rect`. */\nfunction regionsOf(dto: RedactDTO): PdfRect[] {\n if (dto.quadPoints.length === 0) return [dto.rect];\n return dto.quadPoints.map((q) => {\n const xs = [q.p1.x, q.p2.x, q.p3.x, q.p4.x];\n const ys = [q.p1.y, q.p2.y, q.p3.y, q.p4.y];\n return {\n left: Math.min(...xs),\n right: Math.max(...xs),\n bottom: Math.min(...ys),\n top: Math.max(...ys),\n };\n });\n}\n\n/** Positive-area intersection — the engine's collateral rule. */\nconst intersects = (a: PdfRect, b: PdfRect): boolean =>\n Math.min(a.right, b.right) > Math.max(a.left, b.left) &&\n Math.min(a.top, b.top) > Math.max(a.bottom, b.bottom);\n\nexport function createRedactionCapability(\n ctx: PluginContext<RedactionState, RedactionAction>,\n): RedactionCapability {\n const anno = ctx.get(AnnotationToken);\n const appliedCallbacks = new Set<(result: RedactionApplyResult) => void>();\n\n const requireDoc = () => {\n const doc = ctx.doc;\n if (!doc) throw new Error('[redaction] no document bound');\n return doc;\n };\n const requireService = () => {\n const doc = requireDoc();\n if (!doc.redaction) throw new Error('[redaction] engine has no redaction service');\n return doc.redaction;\n };\n\n const pons = (): number[] => (ctx.document()?.pages ?? []).map((p) => p.pageObjectNumber);\n\n const pageIndexOf = (pon: number): number =>\n ctx.document()?.pages.find((p) => p.pageObjectNumber === pon)?.index ?? -1;\n\n const pendingOn = (pon: number): RedactDTO[] =>\n anno.list(pon).filter((a): a is RedactDTO => a.subtype === 'redact');\n\n const collectPending = (): RedactionPendingItem[] => {\n const items: RedactionPendingItem[] = [];\n for (const pon of pons()) {\n for (const dto of pendingOn(pon)) {\n items.push({\n id: idOf(dto.ref),\n ref: dto.ref,\n pageObjectNumber: pon,\n pageIndex: pageIndexOf(pon),\n kind: dto.quadPoints.length > 0 ? 'text' : 'area',\n overlayText: dto.overlayText,\n });\n }\n }\n return items;\n };\n\n const fireApplied = (result: RedactionApplyResult) => {\n for (const cb of appliedCallbacks) {\n try {\n cb(result);\n } catch (err) {\n console.error('[redaction] onApplied callback failed', err);\n }\n }\n };\n\n const runApply = async (\n scope: Parameters<ReturnType<typeof requireService>['apply']>[0],\n ): Promise<RedactionApplyResult> => {\n const service = requireService();\n ctx.dispatch({ type: 'APPLY_STARTED' });\n try {\n const result = await service.apply(scope);\n ctx.dispatch({ type: 'APPLY_FINISHED', result });\n fireApplied(result);\n return result;\n } catch (err) {\n ctx.dispatch({ type: 'APPLY_FINISHED', result: null });\n throw err;\n }\n };\n\n // A REMOTE collaborator's apply arrives only as a document event (own\n // applies flow through runApply above). Annotation state + raster\n // invalidation are handled by their own planes; here we only surface it.\n const doc = ctx.doc;\n if (doc) {\n ctx.cleanup(\n doc.events.subscribe((event) => {\n if (event.type !== 'redaction.applied') return;\n if (event.origin.kind !== 'remote') return;\n ctx.dispatch({ type: 'APPLY_FINISHED', result: event });\n fireApplied(event);\n }),\n );\n }\n\n return {\n canApply: () =>\n (ctx.doc?.redaction !== undefined && ctx.doc?.security.allows(REDACT_CAPABILITY)) ?? false,\n isApplying: () => ctx.getState().applying,\n lastResult: () => ctx.getState().lastResult,\n\n enableRedact: () => ctx.tryGet(InteractionToken)?.activateTool('redact'),\n toggleRedact: () => {\n const interaction = ctx.tryGet(InteractionToken);\n if (!interaction) return;\n interaction.activateTool(interaction.activeToolId() === 'redact' ? 'pointer' : 'redact');\n },\n isRedactActive: () => ctx.tryGet(InteractionToken)?.activeToolId() === 'redact',\n\n queueCurrentSelection: async () => {\n const selection = ctx.tryGet(SelectionToken);\n if (!selection || !selection.hasSelection()) return false;\n const snapshot = selection.snapshot();\n for (const page of snapshot.pages) {\n if (page.rects.length === 0) continue;\n anno.createMarkup('redact', page.pon, page.rects, 'redact');\n }\n selection.clear();\n return true;\n },\n\n preparePending: async () => {\n await Promise.all(pons().map((pon) => anno.ensurePage(pon)));\n },\n getPending: collectPending,\n pendingCount: () => collectPending().length,\n\n estimateCollateral: (ids) => {\n const wanted = ids ? new Set(ids) : null;\n let count = 0;\n for (const pon of pons()) {\n const all = anno.list(pon);\n const marks = all.filter(\n (a): a is RedactDTO => a.subtype === 'redact' && (!wanted || wanted.has(idOf(a.ref))),\n );\n if (marks.length === 0) continue;\n const regions = marks.flatMap(regionsOf);\n for (const other of all) {\n if (other.subtype === 'redact') continue;\n if (regions.some((r) => intersects(r, other.rect))) count++;\n }\n }\n return count;\n },\n\n setLabel: async (ref, patch: RedactionLabelPatch) => {\n const current = anno.get(ref);\n if (!current || current.subtype !== 'redact') {\n throw new Error('[redaction] setLabel target is not a redact annotation');\n }\n // Always carry the current /DA styling: the engine rewrites /DA whenever\n // a label field rides a patch, so a text-only edit must not let the\n // styling fall back to defaults.\n await anno.update(ref, {\n subtype: 'redact',\n ...(patch.overlayText !== undefined ? { overlayText: patch.overlayText } : {}),\n ...(patch.repeat !== undefined ? { repeat: patch.repeat } : {}),\n fontFamily: current.fontFamily,\n fontSize: current.fontSize,\n fontColor: current.fontColor,\n textAlign: current.textAlign,\n });\n },\n\n apply: async (ids) => {\n const wanted = new Set(ids);\n const refs = collectPending()\n .filter((p) => wanted.has(p.id))\n .map((p) => p.ref);\n if (refs.length === 0) throw new Error('[redaction] no matching pending redactions');\n return runApply({ kind: 'annotations', refs });\n },\n\n applyAll: async () => {\n // Pages scope: authoritative for the WHOLE document, including marks on\n // pages this client never loaded. Pages without marks report 'unchanged'.\n const pageObjectNumbers = pons();\n if (pageObjectNumbers.length === 0) throw new Error('[redaction] document has no pages');\n return runApply({ kind: 'pages', pageObjectNumbers });\n },\n\n onApplied: (cb) => {\n appliedCallbacks.add(cb);\n return () => appliedCallbacks.delete(cb);\n },\n };\n}\n","import type { RedactionAction, RedactionState } from './types';\n\nexport const initialRedactionState = (): RedactionState => ({\n applying: false,\n lastResult: null,\n});\n\nexport const redactionReducer = (\n state: RedactionState,\n action: RedactionAction,\n): RedactionState => {\n switch (action.type) {\n case 'APPLY_STARTED':\n return { ...state, applying: true };\n case 'APPLY_FINISHED':\n return { applying: false, lastResult: action.result ?? state.lastResult };\n default:\n return state;\n }\n};\n","import { createCapabilityToken } from '@embedpdf/core';\nimport type { AnnotationRef, RedactionApplyResult } from '@embedpdf/engine-core';\n\n/**\n * One pending redaction mark — a live projection of a `redact` annotation on\n * the annotation plane (the plugin owns NO mark state of its own; delete the\n * annotation and the pending item is gone).\n */\nexport interface RedactionPendingItem {\n /** Stable list key derived from the ref. */\n id: string;\n ref: AnnotationRef;\n pageObjectNumber: number;\n /** Display index (0-based) from the page registry — for \"page N\" labels. */\n pageIndex: number;\n /** `area` = rect-only mark (marquee); `text` = per-line quads (selection). */\n kind: 'area' | 'text';\n /** `/OverlayText` label, when set. */\n overlayText: string | null;\n}\n\nexport interface RedactionState {\n /** A destructive apply is in flight. */\n applying: boolean;\n /** The last apply result seen (own or remote), for status UI. */\n lastResult: RedactionApplyResult | null;\n}\n\nexport type RedactionAction =\n | { type: 'APPLY_STARTED' }\n | { type: 'APPLY_FINISHED'; result: RedactionApplyResult | null };\n\n/** A label edit: `overlayText: null` clears it; `repeat` tiles it. */\nexport interface RedactionLabelPatch {\n overlayText?: string | null;\n repeat?: boolean;\n}\n\nexport interface RedactionCapability {\n /** Engine support present AND this session holds `doc.redact`. The engine\n * enforces the same capability independently — this is the UI mirror. */\n canApply(): boolean;\n isApplying(): boolean;\n lastResult(): RedactionApplyResult | null;\n\n /** The composed marking tool (text-selection over text + area drag elsewhere). */\n enableRedact(): void;\n toggleRedact(): void;\n isRedactActive(): boolean;\n\n /** Mark the current text selection (per page) and clear it. False when\n * there is no selection plugin or no selection. */\n queueCurrentSelection(): Promise<boolean>;\n\n /** Load every page's annotations so the pending view is complete (the\n * annotation plane loads lazily per page). Call when opening a panel. */\n preparePending(): Promise<void>;\n /** Pending marks over the LOADED annotation state (see preparePending). */\n getPending(): RedactionPendingItem[];\n pendingCount(): number;\n /**\n * Client-side estimate of how many OTHER annotations the given pending\n * marks (default: all) would destroy — for confirm dialogs BEFORE the\n * apply. The authoritative count comes back on the result.\n */\n estimateCollateral(ids?: string[]): number;\n\n /** Edit a mark's label. Reads the mark's current `/DA` styling and writes\n * the full label set, so a text-only edit never resets the styling. */\n setLabel(ref: AnnotationRef, patch: RedactionLabelPatch): Promise<void>;\n\n /** Apply specific pending marks (refs scope). Irreversible. */\n apply(ids: string[]): Promise<RedactionApplyResult>;\n /** Apply every redaction in the document (pages scope — including marks on\n * pages this client never loaded). Irreversible. */\n applyAll(): Promise<RedactionApplyResult>;\n\n /** Fires after ANY confirmed apply — own or a remote collaborator's. */\n onApplied(cb: (result: RedactionApplyResult) => void): () => void;\n}\n\nexport const RedactionToken = createCapabilityToken<RedactionCapability>('redaction');\n","import { definePlugin } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/internal';\nimport { InteractionToken } from '@embedpdf/plugin-interaction';\nimport { SelectionToken } from '@embedpdf/plugin-selection';\nimport { createRedactionCapability } from './capability';\nimport { initialRedactionState, redactionReducer } from './reducer';\nimport { RedactionToken } from './types';\nimport type { RedactionAction, RedactionCapability, RedactionState } from './types';\n\n/**\n * Document-scoped redaction plugin — the DESTRUCTIVE half of the two-stage\n * model. Marking is annotation-plane work (the composed `redact` tool ships\n * with plugin-annotation); this plugin wraps `doc.redaction.apply`, projects\n * the pending queue out of annotation state, and estimates collateral for\n * confirm dialogs. It owns no mark state of its own.\n *\n * Trust boundary: on a layered document, applying rewrites the LAYER's bytes;\n * the immutable base keeps the original. See the package README.\n */\nexport const redactionPlugin = () =>\n definePlugin<RedactionState, RedactionAction, RedactionCapability>({\n id: 'redaction',\n token: RedactionToken,\n scope: 'document',\n requires: [AnnotationToken],\n optional: [InteractionToken, SelectionToken],\n initialState: initialRedactionState,\n reduce: redactionReducer,\n capability: createRedactionCapability,\n });\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,90 +1,45 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-redaction",
3
- "version": "2.15.0",
3
+ "version": "3.0.0-next.0",
4
+ "private": false,
5
+ "description": "Document-scoped redaction: the destructive apply stage over redact annotation marks — pending queue view, collateral estimation, and the doc.redaction.apply wrapper. Marking itself rides the annotation plane.",
4
6
  "type": "module",
5
- "license": "MIT",
6
- "main": "./dist/index.cjs",
7
+ "main": "./dist/index.js",
7
8
  "module": "./dist/index.js",
8
9
  "types": "./dist/index.d.ts",
9
10
  "exports": {
10
11
  ".": {
11
- "types": "./dist/index.d.ts",
12
12
  "import": "./dist/index.js",
13
13
  "require": "./dist/index.cjs"
14
14
  },
15
- "./preact": {
16
- "types": "./dist/preact/index.d.ts",
17
- "import": "./dist/preact/index.js",
18
- "require": "./dist/preact/index.cjs"
19
- },
20
- "./react": {
21
- "types": "./dist/react/index.d.ts",
22
- "import": "./dist/react/index.js",
23
- "require": "./dist/react/index.cjs"
24
- },
25
- "./vue": {
26
- "types": "./dist/vue/index.d.ts",
27
- "import": "./dist/vue/index.js",
28
- "require": "./dist/vue/index.cjs"
29
- },
30
- "./svelte": {
31
- "types": "./dist/svelte/index.d.ts",
32
- "svelte": "./dist/svelte/index.js",
33
- "import": "./dist/svelte/index.js",
34
- "require": "./dist/svelte/index.cjs"
35
- }
15
+ "./package.json": "./package.json"
36
16
  },
17
+ "files": [
18
+ "dist"
19
+ ],
37
20
  "dependencies": {
38
- "@embedpdf/models": "2.15.0",
39
- "@embedpdf/utils": "2.15.0"
21
+ "@embedpdf/core": "3.0.0-next.0",
22
+ "@embedpdf/plugin-annotation": "3.0.0-next.0",
23
+ "@embedpdf/plugin-interaction": "3.0.0-next.0",
24
+ "@embedpdf/plugin-selection": "3.0.0-next.0",
25
+ "@embedpdf/engine-core": "3.0.0-next.0"
40
26
  },
41
27
  "devDependencies": {
42
- "@types/react": "^18.2.0",
43
28
  "typescript": "^5.0.0",
44
- "@embedpdf/core": "2.15.0",
45
- "@embedpdf/plugin-selection": "2.15.0",
46
- "@embedpdf/plugin-annotation": "2.15.0",
47
- "@embedpdf/plugin-interaction-manager": "2.15.0",
48
- "@embedpdf/plugin-history": "2.15.0",
49
- "@embedpdf/build": "1.1.0"
29
+ "vitest": "^2.1.9",
30
+ "@embedpdf/tooling-build": "0.0.0"
50
31
  },
51
- "peerDependencies": {
52
- "preact": "^10.26.4",
53
- "react": ">=16.8.0",
54
- "react-dom": ">=16.8.0",
55
- "vue": ">=3.2.0",
56
- "svelte": ">=5 <6",
57
- "@embedpdf/core": "2.15.0",
58
- "@embedpdf/plugin-selection": "2.15.0",
59
- "@embedpdf/plugin-annotation": "2.15.0",
60
- "@embedpdf/plugin-interaction-manager": "2.15.0",
61
- "@embedpdf/plugin-history": "2.15.0"
62
- },
63
- "files": [
64
- "dist",
65
- "README.md"
66
- ],
32
+ "license": "Apache-2.0",
33
+ "sideEffects": false,
67
34
  "repository": {
68
35
  "type": "git",
69
- "url": "https://github.com/embedpdf/embed-pdf-viewer",
70
- "directory": "packages/plugin-redaction"
71
- },
72
- "homepage": "https://www.embedpdf.com/docs",
73
- "bugs": {
74
- "url": "https://github.com/embedpdf/embed-pdf-viewer/issues"
75
- },
76
- "publishConfig": {
77
- "access": "public"
36
+ "url": "git+https://github.com/embedpdf/embed-pdf-viewer.git",
37
+ "directory": "packages/plugin/redaction"
78
38
  },
79
39
  "scripts": {
80
- "build:base": "vite build --mode base",
81
- "build:react": "vite build --mode react",
82
- "build:preact": "vite build --mode preact",
83
- "build:vue": "vite build --mode vue",
84
- "build:svelte": "vite build --mode svelte",
85
- "build": "pnpm run clean && concurrently -c auto -n base,react,preact,vue,svelte \"vite build --mode base\" \"vite build --mode react\" \"vite build --mode preact\" \"vite build --mode vue\" \"vite build --mode svelte\"",
40
+ "build": "epdf-build",
86
41
  "clean": "rimraf dist",
87
- "lint": "eslint src --color",
88
- "lint:fix": "eslint src --color --fix"
42
+ "typecheck": "tsc -p tsconfig.json --noEmit",
43
+ "test": "vitest run --passWithNoTests"
89
44
  }
90
45
  }
@@ -1,113 +0,0 @@
1
- import { Action } from '@embedpdf/core';
2
- import { Rect } from '@embedpdf/models';
3
- import { RedactionItem, RedactionMode, RedactionDocumentState } from './types';
4
- export declare const INIT_REDACTION_STATE = "REDACTION/INIT_STATE";
5
- export declare const CLEANUP_REDACTION_STATE = "REDACTION/CLEANUP_STATE";
6
- export declare const SET_ACTIVE_DOCUMENT = "REDACTION/SET_ACTIVE_DOCUMENT";
7
- export declare const START_REDACTION = "START_REDACTION";
8
- export declare const END_REDACTION = "END_REDACTION";
9
- export declare const SET_ACTIVE_TYPE = "SET_ACTIVE_TYPE";
10
- export declare const ADD_PENDING = "ADD_PENDING";
11
- export declare const REMOVE_PENDING = "REMOVE_PENDING";
12
- export declare const UPDATE_PENDING = "UPDATE_PENDING";
13
- export declare const CLEAR_PENDING = "CLEAR_PENDING";
14
- export declare const SELECT_PENDING = "SELECT_PENDING";
15
- export declare const DESELECT_PENDING = "DESELECT_PENDING";
16
- export interface InitRedactionStateAction extends Action {
17
- type: typeof INIT_REDACTION_STATE;
18
- payload: {
19
- documentId: string;
20
- state: RedactionDocumentState;
21
- };
22
- }
23
- export interface CleanupRedactionStateAction extends Action {
24
- type: typeof CLEANUP_REDACTION_STATE;
25
- payload: string;
26
- }
27
- export interface SetActiveDocumentAction extends Action {
28
- type: typeof SET_ACTIVE_DOCUMENT;
29
- payload: string | null;
30
- }
31
- export interface StartRedactionAction extends Action {
32
- type: typeof START_REDACTION;
33
- payload: {
34
- documentId: string;
35
- mode: RedactionMode;
36
- };
37
- }
38
- export interface EndRedactionAction extends Action {
39
- type: typeof END_REDACTION;
40
- payload: string;
41
- }
42
- export interface SetActiveTypeAction extends Action {
43
- type: typeof SET_ACTIVE_TYPE;
44
- payload: {
45
- documentId: string;
46
- mode: RedactionMode | null;
47
- };
48
- }
49
- export interface AddPendingAction extends Action {
50
- type: typeof ADD_PENDING;
51
- payload: {
52
- documentId: string;
53
- items: RedactionItem[];
54
- };
55
- }
56
- export interface RemovePendingAction extends Action {
57
- type: typeof REMOVE_PENDING;
58
- payload: {
59
- documentId: string;
60
- page: number;
61
- id: string;
62
- };
63
- }
64
- export interface ClearPendingAction extends Action {
65
- type: typeof CLEAR_PENDING;
66
- payload: string;
67
- }
68
- export interface UpdatePendingAction extends Action {
69
- type: typeof UPDATE_PENDING;
70
- payload: {
71
- documentId: string;
72
- page: number;
73
- id: string;
74
- patch: {
75
- rect?: Rect;
76
- rects?: Rect[];
77
- markColor?: string;
78
- text?: string;
79
- redactionColor?: string;
80
- };
81
- };
82
- }
83
- export interface SelectPendingAction extends Action {
84
- type: typeof SELECT_PENDING;
85
- payload: {
86
- documentId: string;
87
- page: number;
88
- id: string;
89
- };
90
- }
91
- export interface DeselectPendingAction extends Action {
92
- type: typeof DESELECT_PENDING;
93
- payload: string;
94
- }
95
- export type RedactionAction = InitRedactionStateAction | CleanupRedactionStateAction | SetActiveDocumentAction | StartRedactionAction | EndRedactionAction | SetActiveTypeAction | AddPendingAction | RemovePendingAction | UpdatePendingAction | ClearPendingAction | SelectPendingAction | DeselectPendingAction;
96
- export declare function initRedactionState(documentId: string, state: RedactionDocumentState): InitRedactionStateAction;
97
- export declare function cleanupRedactionState(documentId: string): CleanupRedactionStateAction;
98
- export declare function setActiveDocument(documentId: string | null): SetActiveDocumentAction;
99
- export declare const addPending: (documentId: string, items: RedactionItem[]) => AddPendingAction;
100
- export declare const removePending: (documentId: string, page: number, id: string) => RemovePendingAction;
101
- export declare const clearPending: (documentId: string) => ClearPendingAction;
102
- export declare const updatePending: (documentId: string, page: number, id: string, patch: {
103
- rect?: Rect;
104
- rects?: Rect[];
105
- markColor?: string;
106
- text?: string;
107
- redactionColor?: string;
108
- }) => UpdatePendingAction;
109
- export declare const startRedaction: (documentId: string, mode: RedactionMode) => StartRedactionAction;
110
- export declare const endRedaction: (documentId: string) => EndRedactionAction;
111
- export declare const setActiveType: (documentId: string, mode: RedactionMode | null) => SetActiveTypeAction;
112
- export declare const selectPending: (documentId: string, page: number, id: string) => SelectPendingAction;
113
- export declare const deselectPending: (documentId: string) => DeselectPendingAction;
File without changes
@@ -1,11 +0,0 @@
1
- import { PluginPackage } from '@embedpdf/core';
2
- import { RedactionPluginConfig, RedactionState } from './types';
3
- import { RedactionPlugin } from './redaction-plugin';
4
- import { RedactionAction } from './actions';
5
- export declare const RedactionPluginPackage: PluginPackage<RedactionPlugin, RedactionPluginConfig, RedactionState, RedactionAction>;
6
- export * from './redaction-plugin';
7
- export * from './types';
8
- export * from './manifest';
9
- export * from './selectors';
10
- export * from './tools';
11
- export { initialState, initialDocumentState } from './reducer';
@@ -1,4 +0,0 @@
1
- import { PluginManifest } from '@embedpdf/core';
2
- import { RedactionPluginConfig } from './types';
3
- export declare const REDACTION_PLUGIN_ID = "redaction";
4
- export declare const manifest: PluginManifest<RedactionPluginConfig>;