@embedpdf/plugin-redaction 1.4.1 → 2.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 (63) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +573 -207
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/actions.d.ts +48 -13
  6. package/dist/lib/index.d.ts +1 -1
  7. package/dist/lib/redaction-plugin.d.ts +22 -8
  8. package/dist/lib/reducer.d.ts +4 -2
  9. package/dist/lib/selectors.d.ts +5 -3
  10. package/dist/lib/types.d.ts +68 -20
  11. package/dist/preact/index.cjs +1 -1
  12. package/dist/preact/index.cjs.map +1 -1
  13. package/dist/preact/index.js +86 -37
  14. package/dist/preact/index.js.map +1 -1
  15. package/dist/react/index.cjs +1 -1
  16. package/dist/react/index.cjs.map +1 -1
  17. package/dist/react/index.js +86 -37
  18. package/dist/react/index.js.map +1 -1
  19. package/dist/shared/components/marquee-redact.d.ts +4 -2
  20. package/dist/shared/components/pending-redactions.d.ts +4 -3
  21. package/dist/shared/components/redaction-layer.d.ts +11 -5
  22. package/dist/shared/components/selection-redact.d.ts +2 -1
  23. package/dist/shared/components/types.d.ts +6 -7
  24. package/dist/shared/hooks/use-redaction.d.ts +4 -4
  25. package/dist/shared-preact/components/marquee-redact.d.ts +4 -2
  26. package/dist/shared-preact/components/pending-redactions.d.ts +4 -3
  27. package/dist/shared-preact/components/redaction-layer.d.ts +11 -5
  28. package/dist/shared-preact/components/selection-redact.d.ts +2 -1
  29. package/dist/shared-preact/components/types.d.ts +6 -7
  30. package/dist/shared-preact/hooks/use-redaction.d.ts +4 -4
  31. package/dist/shared-react/components/marquee-redact.d.ts +4 -2
  32. package/dist/shared-react/components/pending-redactions.d.ts +4 -3
  33. package/dist/shared-react/components/redaction-layer.d.ts +11 -5
  34. package/dist/shared-react/components/selection-redact.d.ts +2 -1
  35. package/dist/shared-react/components/types.d.ts +6 -7
  36. package/dist/shared-react/hooks/use-redaction.d.ts +4 -4
  37. package/dist/svelte/components/highlight.svelte.d.ts +14 -0
  38. package/dist/svelte/components/index.d.ts +5 -0
  39. package/dist/svelte/components/marquee-redact.svelte.d.ts +16 -0
  40. package/dist/svelte/components/pending-redactions.svelte.d.ts +15 -0
  41. package/dist/svelte/components/redaction-layer.svelte.d.ts +20 -0
  42. package/dist/svelte/components/selection-redact.svelte.d.ts +8 -0
  43. package/dist/svelte/hooks/index.d.ts +1 -0
  44. package/dist/svelte/hooks/use-redaction.svelte.d.ts +21 -0
  45. package/dist/svelte/index.cjs +2 -0
  46. package/dist/svelte/index.cjs.map +1 -0
  47. package/dist/svelte/index.d.ts +4 -0
  48. package/dist/svelte/index.js +554 -0
  49. package/dist/svelte/index.js.map +1 -0
  50. package/dist/svelte/types.d.ts +10 -0
  51. package/dist/vue/components/highlight.vue.d.ts +2 -1
  52. package/dist/vue/components/marquee-redact.vue.d.ts +5 -2
  53. package/dist/vue/components/pending-redactions.vue.d.ts +18 -13
  54. package/dist/vue/components/redaction-layer.vue.d.ts +13 -4
  55. package/dist/vue/components/selection-redact.vue.d.ts +3 -1
  56. package/dist/vue/components/types.d.ts +9 -0
  57. package/dist/vue/hooks/use-redaction.d.ts +9 -102
  58. package/dist/vue/index.cjs +1 -1
  59. package/dist/vue/index.cjs.map +1 -1
  60. package/dist/vue/index.d.ts +1 -0
  61. package/dist/vue/index.js +219 -125
  62. package/dist/vue/index.js.map +1 -1
  63. package/package.json +18 -10
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-redaction.ts","../../src/shared/components/marquee-redact.tsx","../../src/shared/components/highlight.tsx","../../src/shared/components/selection-redact.tsx","../../src/shared/components/pending-redactions.tsx","../../src/shared/components/redaction-layer.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { initialState, RedactionPlugin, RedactionState } from '@embedpdf/plugin-redaction';\nimport { useState, useEffect } from '@framework';\n\nexport const useRedactionPlugin = () => usePlugin<RedactionPlugin>(RedactionPlugin.id);\nexport const useRedactionCapability = () => useCapability<RedactionPlugin>(RedactionPlugin.id);\n\nexport const useRedaction = () => {\n const { provides } = useRedactionCapability();\n const [state, setState] = useState<RedactionState>(initialState);\n\n useEffect(() => {\n return provides?.onStateChange((action) => {\n setState(action);\n });\n }, [provides]);\n\n return {\n state,\n provides,\n };\n};\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useRedactionPlugin } from '../hooks/use-redaction';\n\ninterface MarqueeRedactProps {\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page */\n scale: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeRedact = ({\n pageIndex,\n scale,\n className,\n stroke = 'red',\n fill = 'transparent',\n}: MarqueeRedactProps) => {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n\n const [rect, setRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!redactionPlugin) return;\n return redactionPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [redactionPlugin, pageIndex]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n","import { HTMLAttributes, CSSProperties, MouseEvent, TouchEvent } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\ntype HighlightProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n color?: string;\n opacity?: number;\n border?: string;\n rects: Rect[];\n rect?: Rect;\n scale: number;\n onClick?: (e: MouseEvent<HTMLDivElement> | TouchEvent<HTMLDivElement>) => void;\n style?: CSSProperties;\n};\n\nexport function Highlight({\n color = '#FFFF00',\n opacity = 1,\n border = '1px solid red',\n rects,\n rect,\n scale,\n onClick,\n style,\n ...props\n}: HighlightProps) {\n return (\n <>\n {rects.map((b, i) => (\n <div\n key={i}\n onPointerDown={onClick}\n onTouchStart={onClick}\n style={{\n position: 'absolute',\n border,\n left: (rect ? b.origin.x - rect.origin.x : b.origin.x) * scale,\n top: (rect ? b.origin.y - rect.origin.y : b.origin.y) * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: color,\n opacity: opacity,\n pointerEvents: onClick ? 'auto' : 'none',\n cursor: onClick ? 'pointer' : 'default',\n zIndex: onClick ? 1 : undefined,\n ...style,\n }}\n {...props}\n />\n ))}\n </>\n );\n}\n","import { Rect } from '@embedpdf/models';\n\nimport { useEffect, useState } from '@framework';\nimport { useRedactionPlugin } from '../hooks';\nimport { Highlight } from './highlight';\n\ninterface SelectionRedactProps {\n pageIndex: number;\n scale: number;\n}\n\nexport function SelectionRedact({ pageIndex, scale }: SelectionRedactProps) {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n const [rects, setRects] = useState<Array<Rect>>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!redactionPlugin) return;\n\n return redactionPlugin.onRedactionSelectionChange((formattedSelection) => {\n const selection = formattedSelection.find((s) => s.pageIndex === pageIndex);\n setRects(selection?.segmentRects ?? []);\n setBoundingRect(selection?.rect ?? null);\n });\n }, [redactionPlugin, pageIndex]);\n\n if (!boundingRect) return null;\n\n return (\n <div\n style={{\n mixBlendMode: 'normal',\n pointerEvents: 'none',\n position: 'absolute',\n inset: 0,\n }}\n >\n <Highlight\n color={'transparent'}\n opacity={1}\n rects={rects}\n scale={scale}\n border=\"1px solid red\"\n />\n </div>\n );\n}\n","import { Fragment, useEffect, useState, useCallback, MouseEvent, TouchEvent } from '@framework';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\nimport { useRedactionCapability } from '../hooks';\nimport { RedactionItem } from '@embedpdf/plugin-redaction';\nimport { Highlight } from './highlight';\nimport { SelectionMenuProps } from './types';\nimport { Rotation } from '@embedpdf/models';\n\ninterface PendingRedactionsProps {\n pageIndex: number;\n scale: number;\n rotation: Rotation;\n bboxStroke?: string;\n selectionMenu?: (props: SelectionMenuProps) => JSX.Element;\n}\n\nexport function PendingRedactions({\n pageIndex,\n scale,\n bboxStroke = 'rgba(0,0,0,0.8)',\n rotation = Rotation.Degree0,\n selectionMenu,\n}: PendingRedactionsProps) {\n const { provides: redaction } = useRedactionCapability();\n const [items, setItems] = useState<RedactionItem[]>([]);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n useEffect(() => {\n if (!redaction) return;\n const off1 = redaction.onPendingChange((map) => setItems(map[pageIndex] ?? []));\n const off2 = redaction.onSelectedChange((sel) => {\n setSelectedId(sel && sel.page === pageIndex ? sel.id : null);\n });\n return () => {\n off1?.();\n off2?.();\n };\n }, [redaction, pageIndex]);\n\n const select = useCallback(\n (e: MouseEvent | TouchEvent, id: string) => {\n e.stopPropagation();\n if (!redaction) return;\n redaction.selectPending(pageIndex, id);\n },\n [redaction, pageIndex],\n );\n\n if (!items.length) return null;\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {items.map((it) => {\n if (it.kind === 'area') {\n const r = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: r.origin.x * scale,\n top: r.origin.y * scale,\n width: r.size.width * scale,\n height: r.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n border: `1px solid red`,\n pointerEvents: 'auto',\n cursor: 'pointer',\n }}\n onPointerDown={(e) => select(e, it.id)}\n onTouchStart={(e) => select(e, it.id)}\n />\n <CounterRotate\n rect={{\n origin: { x: r.origin.x * scale, y: r.origin.y * scale },\n size: { width: r.size.width * scale, height: r.size.height * scale },\n }}\n rotation={rotation}\n >\n {({ rect, menuWrapperProps }) =>\n selectionMenu &&\n selectionMenu({\n item: it,\n selected: selectedId === it.id,\n pageIndex,\n menuWrapperProps,\n rect,\n })\n }\n </CounterRotate>\n </Fragment>\n );\n }\n // kind === 'text' → draw bounding box; inner rects are not drawn here to avoid clutter.\n const b = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: b.origin.x * scale,\n top: b.origin.y * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n pointerEvents: 'auto',\n cursor: selectedId === it.id ? 'pointer' : 'default',\n }}\n >\n <Highlight\n rect={b}\n rects={it.rects}\n color=\"transparent\"\n border=\"1px solid red\"\n scale={scale}\n onClick={(e) => select(e, it.id)}\n />\n </div>\n <CounterRotate\n rect={{\n origin: { x: b.origin.x * scale, y: b.origin.y * scale },\n size: { width: b.size.width * scale, height: b.size.height * scale },\n }}\n rotation={rotation}\n >\n {({ rect, menuWrapperProps }) =>\n selectionMenu &&\n selectionMenu({\n item: it,\n selected: selectedId === it.id,\n pageIndex,\n menuWrapperProps,\n rect,\n })\n }\n </CounterRotate>\n </Fragment>\n );\n })}\n </div>\n );\n}\n","import { Fragment } from '@framework';\nimport { MarqueeRedact } from './marquee-redact';\nimport { SelectionRedact } from './selection-redact';\nimport { PendingRedactions } from './pending-redactions';\nimport { Rotation } from '@embedpdf/models';\nimport { SelectionMenuProps } from './types';\n\ninterface RedactionLayerProps {\n pageIndex: number;\n scale: number;\n rotation: Rotation;\n selectionMenu?: (props: SelectionMenuProps) => JSX.Element;\n}\n\nexport const RedactionLayer = ({\n pageIndex,\n scale,\n rotation = Rotation.Degree0,\n selectionMenu,\n}: RedactionLayerProps) => {\n return (\n <Fragment>\n <PendingRedactions\n pageIndex={pageIndex}\n scale={scale}\n rotation={rotation}\n selectionMenu={selectionMenu}\n />\n <MarqueeRedact pageIndex={pageIndex} scale={scale} />\n <SelectionRedact pageIndex={pageIndex} scale={scale} />\n </Fragment>\n );\n};\n"],"names":["useRedactionPlugin","usePlugin","RedactionPlugin","id","useRedactionCapability","useCapability","MarqueeRedact","pageIndex","scale","className","stroke","fill","plugin","redactionPlugin","rect","setRect","useState","useEffect","registerMarqueeOnPage","callback","onPreview","jsxRuntime","jsx","style","position","pointerEvents","left","origin","x","top","y","width","size","height","border","background","boxSizing","Highlight","color","opacity","rects","onClick","props","Fragment","children","map","b","i","onPointerDown","onTouchStart","cursor","zIndex","SelectionRedact","setRects","boundingRect","setBoundingRect","onRedactionSelectionChange","formattedSelection","selection","find","s","segmentRects","mixBlendMode","inset","PendingRedactions","bboxStroke","rotation","Rotation","Degree0","selectionMenu","provides","redaction","items","setItems","selectedId","setSelectedId","off1","onPendingChange","off2","onSelectedChange","sel","page","select","useCallback","e","stopPropagation","selectPending","length","it","kind","r","outline","outlineOffset","CounterRotate","menuWrapperProps","item","selected","state","setState","initialState","onStateChange","action"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-redaction.ts","../../src/shared/components/marquee-redact.tsx","../../src/shared/components/highlight.tsx","../../src/shared/components/selection-redact.tsx","../../src/shared/components/pending-redactions.tsx","../../src/shared/components/redaction-layer.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport {\n initialDocumentState,\n RedactionPlugin,\n RedactionDocumentState,\n RedactionScope,\n} from '@embedpdf/plugin-redaction';\nimport { useState, useEffect, useMemo } from '@framework';\n\nexport const useRedactionPlugin = () => usePlugin<RedactionPlugin>(RedactionPlugin.id);\nexport const useRedactionCapability = () => useCapability<RedactionPlugin>(RedactionPlugin.id);\n\nexport const useRedaction = (\n documentId: string,\n): {\n state: RedactionDocumentState;\n provides: RedactionScope | null;\n} => {\n const { provides } = useRedactionCapability();\n const [state, setState] = useState<RedactionDocumentState>(initialDocumentState);\n\n const scope = useMemo(\n () => (provides ? provides.forDocument(documentId) : null),\n [provides, documentId],\n );\n\n useEffect(() => {\n if (!scope) {\n setState(initialDocumentState);\n return;\n }\n\n // Set initial state\n try {\n setState(scope.getState());\n } catch (e) {\n // Handle case where state might not be ready\n setState(initialDocumentState);\n }\n\n // Subscribe to changes\n const unsubscribe = scope.onStateChange((newState) => {\n setState(newState);\n });\n\n return unsubscribe;\n }, [scope]);\n\n return {\n state,\n provides: scope,\n };\n};\n","import { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useRedactionPlugin } from '../hooks/use-redaction';\n\ninterface MarqueeRedactProps {\n /** The ID of the document */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page */\n scale?: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeRedact = ({\n documentId,\n pageIndex,\n scale: scaleOverride,\n className,\n stroke = 'red',\n fill = 'transparent',\n}: MarqueeRedactProps) => {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n const documentState = useDocumentState(documentId);\n\n const [rect, setRect] = useState<Rect | null>(null);\n\n const scale = useMemo(() => {\n if (scaleOverride !== undefined) return scaleOverride;\n return documentState?.scale ?? 1;\n }, [scaleOverride, documentState?.scale]);\n\n useEffect(() => {\n if (!redactionPlugin || !documentId) return;\n return redactionPlugin.registerMarqueeOnPage({\n documentId,\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [redactionPlugin, documentId, pageIndex, scale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n","import { HTMLAttributes, CSSProperties, MouseEvent, TouchEvent } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\ntype HighlightProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n color?: string;\n opacity?: number;\n border?: string;\n rects: Rect[];\n rect?: Rect;\n scale: number;\n onClick?: (e: MouseEvent<HTMLDivElement> | TouchEvent<HTMLDivElement>) => void;\n style?: CSSProperties;\n};\n\nexport function Highlight({\n color = '#FFFF00',\n opacity = 1,\n border = '1px solid red',\n rects,\n rect,\n scale,\n onClick,\n style,\n ...props\n}: HighlightProps) {\n return (\n <>\n {rects.map((b, i) => (\n <div\n key={i}\n onPointerDown={onClick}\n onTouchStart={onClick}\n style={{\n position: 'absolute',\n border,\n left: (rect ? b.origin.x - rect.origin.x : b.origin.x) * scale,\n top: (rect ? b.origin.y - rect.origin.y : b.origin.y) * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: color,\n opacity: opacity,\n pointerEvents: onClick ? 'auto' : 'none',\n cursor: onClick ? 'pointer' : 'default',\n zIndex: onClick ? 1 : undefined,\n ...style,\n }}\n {...props}\n />\n ))}\n </>\n );\n}\n","import { Rect } from '@embedpdf/models';\nimport { useEffect, useState } from '@framework';\nimport { useRedactionPlugin } from '../hooks';\nimport { Highlight } from './highlight';\n\ninterface SelectionRedactProps {\n documentId: string;\n pageIndex: number;\n scale: number;\n}\n\nexport function SelectionRedact({ documentId, pageIndex, scale }: SelectionRedactProps) {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n const [rects, setRects] = useState<Array<Rect>>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!redactionPlugin) return;\n return redactionPlugin.onRedactionSelectionChange(documentId, (formattedSelection) => {\n const selection = formattedSelection.find((s) => s.pageIndex === pageIndex);\n setRects(selection?.segmentRects ?? []);\n setBoundingRect(selection?.rect ?? null);\n });\n }, [redactionPlugin, documentId, pageIndex]);\n\n if (!boundingRect) return null;\n\n return (\n <div\n style={{\n mixBlendMode: 'normal',\n pointerEvents: 'none',\n position: 'absolute',\n inset: 0,\n }}\n >\n <Highlight\n color={'transparent'}\n opacity={1}\n rects={rects}\n scale={scale}\n border=\"1px solid red\"\n />\n </div>\n );\n}\n","import { Fragment, useEffect, useState, useCallback, MouseEvent, TouchEvent } from '@framework';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\nimport { useRedactionCapability } from '../hooks';\nimport { RedactionItem } from '@embedpdf/plugin-redaction';\nimport { Highlight } from './highlight';\nimport { RedactionSelectionMenuRenderFn } from './types';\nimport { Rotation } from '@embedpdf/models';\n\ninterface PendingRedactionsProps {\n documentId: string;\n pageIndex: number;\n scale: number;\n rotation: Rotation;\n bboxStroke?: string;\n selectionMenu?: RedactionSelectionMenuRenderFn;\n}\n\nexport function PendingRedactions({\n documentId,\n pageIndex,\n scale,\n bboxStroke = 'rgba(0,0,0,0.8)',\n rotation = Rotation.Degree0,\n selectionMenu,\n}: PendingRedactionsProps) {\n const { provides: redaction } = useRedactionCapability();\n const [items, setItems] = useState<RedactionItem[]>([]);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n useEffect(() => {\n if (!redaction) return;\n\n // Use document-scoped hooks so we only receive events for this document\n const scoped = redaction.forDocument(documentId);\n\n // Initialize with current state\n const currentState = scoped.getState();\n setItems(currentState.pending[pageIndex] ?? []);\n setSelectedId(\n currentState.selected && currentState.selected.page === pageIndex\n ? currentState.selected.id\n : null,\n );\n\n // Subscribe to future changes\n const off1 = scoped.onPendingChange((map) => setItems(map[pageIndex] ?? []));\n const off2 = scoped.onSelectedChange((sel) => {\n setSelectedId(sel && sel.page === pageIndex ? sel.id : null);\n });\n\n return () => {\n off1?.();\n off2?.();\n };\n }, [redaction, documentId, pageIndex]);\n\n const select = useCallback(\n (e: MouseEvent | TouchEvent, id: string) => {\n e.stopPropagation();\n if (!redaction) return;\n redaction.forDocument(documentId).selectPending(pageIndex, id);\n },\n [redaction, documentId, pageIndex],\n );\n\n if (!items.length) return null;\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {items.map((it) => {\n if (it.kind === 'area') {\n const r = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: r.origin.x * scale,\n top: r.origin.y * scale,\n width: r.size.width * scale,\n height: r.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n border: `1px solid red`,\n pointerEvents: 'auto',\n cursor: 'pointer',\n }}\n onPointerDown={(e) => select(e, it.id)}\n onTouchStart={(e) => select(e, it.id)}\n />\n {selectionMenu && (\n <CounterRotate\n rect={{\n origin: { x: r.origin.x * scale, y: r.origin.y * scale },\n size: { width: r.size.width * scale, height: r.size.height * scale },\n }}\n rotation={rotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'redaction',\n item: it,\n pageIndex,\n },\n selected: selectedId === it.id,\n placement: {\n suggestTop: false,\n },\n })\n }\n </CounterRotate>\n )}\n </Fragment>\n );\n }\n\n const b = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: b.origin.x * scale,\n top: b.origin.y * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n pointerEvents: 'auto',\n cursor: selectedId === it.id ? 'pointer' : 'default',\n }}\n >\n <Highlight\n rect={b}\n rects={it.rects}\n color=\"transparent\"\n border=\"1px solid red\"\n scale={scale}\n onClick={(e) => select(e, it.id)}\n />\n </div>\n {selectionMenu && (\n <CounterRotate\n rect={{\n origin: { x: b.origin.x * scale, y: b.origin.y * scale },\n size: { width: b.size.width * scale, height: b.size.height * scale },\n }}\n rotation={rotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'redaction',\n item: it,\n pageIndex,\n },\n selected: selectedId === it.id,\n placement: {\n suggestTop: false,\n },\n })\n }\n </CounterRotate>\n )}\n </Fragment>\n );\n })}\n </div>\n );\n}\n","import { Fragment, useMemo } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { MarqueeRedact } from './marquee-redact';\nimport { SelectionRedact } from './selection-redact';\nimport { PendingRedactions } from './pending-redactions';\nimport { Rotation } from '@embedpdf/models';\nimport { RedactionSelectionMenuRenderFn } from './types';\n\ninterface RedactionLayerProps {\n /** The ID of the document this layer belongs to */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Current render scale for this page */\n scale?: number;\n /** Page rotation (for counter-rotating menus, etc.) */\n rotation?: Rotation;\n /** Optional menu renderer for a selected redaction */\n selectionMenu?: RedactionSelectionMenuRenderFn;\n}\n\nexport const RedactionLayer = ({\n documentId,\n pageIndex,\n scale,\n rotation,\n selectionMenu,\n}: RedactionLayerProps) => {\n const documentState = useDocumentState(documentId);\n\n const actualScale = useMemo(() => {\n if (scale !== undefined) return scale;\n return documentState?.scale ?? 1;\n }, [scale, documentState?.scale]);\n\n const actualRotation = useMemo(() => {\n if (rotation !== undefined) return rotation;\n return documentState?.rotation ?? Rotation.Degree0;\n }, [rotation, documentState?.rotation]);\n\n return (\n <Fragment>\n <PendingRedactions\n documentId={documentId}\n pageIndex={pageIndex}\n scale={actualScale}\n rotation={actualRotation}\n selectionMenu={selectionMenu}\n />\n <MarqueeRedact documentId={documentId} pageIndex={pageIndex} scale={actualScale} />\n <SelectionRedact documentId={documentId} pageIndex={pageIndex} scale={actualScale} />\n </Fragment>\n );\n};\n"],"names":["useRedactionPlugin","usePlugin","RedactionPlugin","id","useRedactionCapability","useCapability","MarqueeRedact","documentId","pageIndex","scale","scaleOverride","className","stroke","fill","plugin","redactionPlugin","documentState","useDocumentState","rect","setRect","useState","useMemo","useEffect","registerMarqueeOnPage","callback","onPreview","jsx","style","position","pointerEvents","left","origin","x","top","y","width","size","height","border","background","boxSizing","Highlight","color","opacity","rects","onClick","props","Fragment","children","map","b","i","onPointerDown","onTouchStart","cursor","zIndex","SelectionRedact","setRects","boundingRect","setBoundingRect","onRedactionSelectionChange","formattedSelection","selection","find","s","segmentRects","mixBlendMode","inset","PendingRedactions","bboxStroke","rotation","Rotation","Degree0","selectionMenu","provides","redaction","items","setItems","selectedId","setSelectedId","scoped","forDocument","currentState","getState","pending","selected","page","off1","onPendingChange","off2","onSelectedChange","sel","select","useCallback","e","stopPropagation","selectPending","length","it","kind","r","outline","outlineOffset","CounterRotate","context","type","item","placement","suggestTop","actualScale","actualRotation","state","setState","initialDocumentState","scope","onStateChange","newState"],"mappings":"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"}
@@ -1,45 +1,66 @@
1
- import { usePlugin, useCapability } from "@embedpdf/core/preact";
2
- import { RedactionPlugin, initialState } from "@embedpdf/plugin-redaction";
1
+ import { usePlugin, useCapability, useDocumentState } from "@embedpdf/core/preact";
2
+ import { RedactionPlugin, initialDocumentState } from "@embedpdf/plugin-redaction";
3
3
  export * from "@embedpdf/plugin-redaction";
4
4
  import { Fragment as Fragment$1 } from "preact";
5
- import { useState, useEffect, useCallback } from "preact/hooks";
5
+ import { useState, useMemo, useEffect, useCallback } from "preact/hooks";
6
6
  import { jsx, Fragment, jsxs } from "preact/jsx-runtime";
7
7
  import { CounterRotate } from "@embedpdf/utils/preact";
8
8
  import { Rotation } from "@embedpdf/models";
9
9
  const useRedactionPlugin = () => usePlugin(RedactionPlugin.id);
10
10
  const useRedactionCapability = () => useCapability(RedactionPlugin.id);
11
- const useRedaction = () => {
11
+ const useRedaction = (documentId) => {
12
12
  const { provides } = useRedactionCapability();
13
- const [state, setState] = useState(initialState);
13
+ const [state, setState] = useState(initialDocumentState);
14
+ const scope = useMemo(
15
+ () => provides ? provides.forDocument(documentId) : null,
16
+ [provides, documentId]
17
+ );
14
18
  useEffect(() => {
15
- return provides == null ? void 0 : provides.onStateChange((action) => {
16
- setState(action);
19
+ if (!scope) {
20
+ setState(initialDocumentState);
21
+ return;
22
+ }
23
+ try {
24
+ setState(scope.getState());
25
+ } catch (e) {
26
+ setState(initialDocumentState);
27
+ }
28
+ const unsubscribe = scope.onStateChange((newState) => {
29
+ setState(newState);
17
30
  });
18
- }, [provides]);
31
+ return unsubscribe;
32
+ }, [scope]);
19
33
  return {
20
34
  state,
21
- provides
35
+ provides: scope
22
36
  };
23
37
  };
24
38
  const MarqueeRedact = ({
39
+ documentId,
25
40
  pageIndex,
26
- scale,
41
+ scale: scaleOverride,
27
42
  className,
28
43
  stroke = "red",
29
44
  fill = "transparent"
30
45
  }) => {
31
46
  const { plugin: redactionPlugin } = useRedactionPlugin();
47
+ const documentState = useDocumentState(documentId);
32
48
  const [rect, setRect] = useState(null);
49
+ const scale = useMemo(() => {
50
+ if (scaleOverride !== void 0) return scaleOverride;
51
+ return (documentState == null ? void 0 : documentState.scale) ?? 1;
52
+ }, [scaleOverride, documentState == null ? void 0 : documentState.scale]);
33
53
  useEffect(() => {
34
- if (!redactionPlugin) return;
54
+ if (!redactionPlugin || !documentId) return;
35
55
  return redactionPlugin.registerMarqueeOnPage({
56
+ documentId,
36
57
  pageIndex,
37
58
  scale,
38
59
  callback: {
39
60
  onPreview: setRect
40
61
  }
41
62
  });
42
- }, [redactionPlugin, pageIndex]);
63
+ }, [redactionPlugin, documentId, pageIndex, scale]);
43
64
  if (!rect) return null;
44
65
  return /* @__PURE__ */ jsx(
45
66
  "div",
@@ -94,18 +115,18 @@ function Highlight({
94
115
  i
95
116
  )) });
96
117
  }
97
- function SelectionRedact({ pageIndex, scale }) {
118
+ function SelectionRedact({ documentId, pageIndex, scale }) {
98
119
  const { plugin: redactionPlugin } = useRedactionPlugin();
99
120
  const [rects, setRects] = useState([]);
100
121
  const [boundingRect, setBoundingRect] = useState(null);
101
122
  useEffect(() => {
102
123
  if (!redactionPlugin) return;
103
- return redactionPlugin.onRedactionSelectionChange((formattedSelection) => {
124
+ return redactionPlugin.onRedactionSelectionChange(documentId, (formattedSelection) => {
104
125
  const selection = formattedSelection.find((s) => s.pageIndex === pageIndex);
105
126
  setRects((selection == null ? void 0 : selection.segmentRects) ?? []);
106
127
  setBoundingRect((selection == null ? void 0 : selection.rect) ?? null);
107
128
  });
108
- }, [redactionPlugin, pageIndex]);
129
+ }, [redactionPlugin, documentId, pageIndex]);
109
130
  if (!boundingRect) return null;
110
131
  return /* @__PURE__ */ jsx(
111
132
  "div",
@@ -130,6 +151,7 @@ function SelectionRedact({ pageIndex, scale }) {
130
151
  );
131
152
  }
132
153
  function PendingRedactions({
154
+ documentId,
133
155
  pageIndex,
134
156
  scale,
135
157
  bboxStroke = "rgba(0,0,0,0.8)",
@@ -141,22 +163,28 @@ function PendingRedactions({
141
163
  const [selectedId, setSelectedId] = useState(null);
142
164
  useEffect(() => {
143
165
  if (!redaction) return;
144
- const off1 = redaction.onPendingChange((map) => setItems(map[pageIndex] ?? []));
145
- const off2 = redaction.onSelectedChange((sel) => {
166
+ const scoped = redaction.forDocument(documentId);
167
+ const currentState = scoped.getState();
168
+ setItems(currentState.pending[pageIndex] ?? []);
169
+ setSelectedId(
170
+ currentState.selected && currentState.selected.page === pageIndex ? currentState.selected.id : null
171
+ );
172
+ const off1 = scoped.onPendingChange((map) => setItems(map[pageIndex] ?? []));
173
+ const off2 = scoped.onSelectedChange((sel) => {
146
174
  setSelectedId(sel && sel.page === pageIndex ? sel.id : null);
147
175
  });
148
176
  return () => {
149
177
  off1 == null ? void 0 : off1();
150
178
  off2 == null ? void 0 : off2();
151
179
  };
152
- }, [redaction, pageIndex]);
180
+ }, [redaction, documentId, pageIndex]);
153
181
  const select = useCallback(
154
182
  (e, id) => {
155
183
  e.stopPropagation();
156
184
  if (!redaction) return;
157
- redaction.selectPending(pageIndex, id);
185
+ redaction.forDocument(documentId).selectPending(pageIndex, id);
158
186
  },
159
- [redaction, pageIndex]
187
+ [redaction, documentId, pageIndex]
160
188
  );
161
189
  if (!items.length) return null;
162
190
  return /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, pointerEvents: "none" }, children: items.map((it) => {
@@ -183,7 +211,7 @@ function PendingRedactions({
183
211
  onTouchStart: (e) => select(e, it.id)
184
212
  }
185
213
  ),
186
- /* @__PURE__ */ jsx(
214
+ selectionMenu && /* @__PURE__ */ jsx(
187
215
  CounterRotate,
188
216
  {
189
217
  rect: {
@@ -191,12 +219,17 @@ function PendingRedactions({
191
219
  size: { width: r.size.width * scale, height: r.size.height * scale }
192
220
  },
193
221
  rotation,
194
- children: ({ rect, menuWrapperProps }) => selectionMenu && selectionMenu({
195
- item: it,
222
+ children: (props) => selectionMenu({
223
+ ...props,
224
+ context: {
225
+ type: "redaction",
226
+ item: it,
227
+ pageIndex
228
+ },
196
229
  selected: selectedId === it.id,
197
- pageIndex,
198
- menuWrapperProps,
199
- rect
230
+ placement: {
231
+ suggestTop: false
232
+ }
200
233
  })
201
234
  }
202
235
  )
@@ -232,7 +265,7 @@ function PendingRedactions({
232
265
  )
233
266
  }
234
267
  ),
235
- /* @__PURE__ */ jsx(
268
+ selectionMenu && /* @__PURE__ */ jsx(
236
269
  CounterRotate,
237
270
  {
238
271
  rect: {
@@ -240,12 +273,17 @@ function PendingRedactions({
240
273
  size: { width: b.size.width * scale, height: b.size.height * scale }
241
274
  },
242
275
  rotation,
243
- children: ({ rect, menuWrapperProps }) => selectionMenu && selectionMenu({
244
- item: it,
276
+ children: (props) => selectionMenu({
277
+ ...props,
278
+ context: {
279
+ type: "redaction",
280
+ item: it,
281
+ pageIndex
282
+ },
245
283
  selected: selectedId === it.id,
246
- pageIndex,
247
- menuWrapperProps,
248
- rect
284
+ placement: {
285
+ suggestTop: false
286
+ }
249
287
  })
250
288
  }
251
289
  )
@@ -253,23 +291,34 @@ function PendingRedactions({
253
291
  }) });
254
292
  }
255
293
  const RedactionLayer = ({
294
+ documentId,
256
295
  pageIndex,
257
296
  scale,
258
- rotation = Rotation.Degree0,
297
+ rotation,
259
298
  selectionMenu
260
299
  }) => {
300
+ const documentState = useDocumentState(documentId);
301
+ const actualScale = useMemo(() => {
302
+ if (scale !== void 0) return scale;
303
+ return (documentState == null ? void 0 : documentState.scale) ?? 1;
304
+ }, [scale, documentState == null ? void 0 : documentState.scale]);
305
+ const actualRotation = useMemo(() => {
306
+ if (rotation !== void 0) return rotation;
307
+ return (documentState == null ? void 0 : documentState.rotation) ?? Rotation.Degree0;
308
+ }, [rotation, documentState == null ? void 0 : documentState.rotation]);
261
309
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
262
310
  /* @__PURE__ */ jsx(
263
311
  PendingRedactions,
264
312
  {
313
+ documentId,
265
314
  pageIndex,
266
- scale,
267
- rotation,
315
+ scale: actualScale,
316
+ rotation: actualRotation,
268
317
  selectionMenu
269
318
  }
270
319
  ),
271
- /* @__PURE__ */ jsx(MarqueeRedact, { pageIndex, scale }),
272
- /* @__PURE__ */ jsx(SelectionRedact, { pageIndex, scale })
320
+ /* @__PURE__ */ jsx(MarqueeRedact, { documentId, pageIndex, scale: actualScale }),
321
+ /* @__PURE__ */ jsx(SelectionRedact, { documentId, pageIndex, scale: actualScale })
273
322
  ] });
274
323
  };
275
324
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-redaction.ts","../../src/shared/components/marquee-redact.tsx","../../src/shared/components/highlight.tsx","../../src/shared/components/selection-redact.tsx","../../src/shared/components/pending-redactions.tsx","../../src/shared/components/redaction-layer.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { initialState, RedactionPlugin, RedactionState } from '@embedpdf/plugin-redaction';\nimport { useState, useEffect } from '@framework';\n\nexport const useRedactionPlugin = () => usePlugin<RedactionPlugin>(RedactionPlugin.id);\nexport const useRedactionCapability = () => useCapability<RedactionPlugin>(RedactionPlugin.id);\n\nexport const useRedaction = () => {\n const { provides } = useRedactionCapability();\n const [state, setState] = useState<RedactionState>(initialState);\n\n useEffect(() => {\n return provides?.onStateChange((action) => {\n setState(action);\n });\n }, [provides]);\n\n return {\n state,\n provides,\n };\n};\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useRedactionPlugin } from '../hooks/use-redaction';\n\ninterface MarqueeRedactProps {\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page */\n scale: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeRedact = ({\n pageIndex,\n scale,\n className,\n stroke = 'red',\n fill = 'transparent',\n}: MarqueeRedactProps) => {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n\n const [rect, setRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!redactionPlugin) return;\n return redactionPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [redactionPlugin, pageIndex]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n","import { HTMLAttributes, CSSProperties, MouseEvent, TouchEvent } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\ntype HighlightProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n color?: string;\n opacity?: number;\n border?: string;\n rects: Rect[];\n rect?: Rect;\n scale: number;\n onClick?: (e: MouseEvent<HTMLDivElement> | TouchEvent<HTMLDivElement>) => void;\n style?: CSSProperties;\n};\n\nexport function Highlight({\n color = '#FFFF00',\n opacity = 1,\n border = '1px solid red',\n rects,\n rect,\n scale,\n onClick,\n style,\n ...props\n}: HighlightProps) {\n return (\n <>\n {rects.map((b, i) => (\n <div\n key={i}\n onPointerDown={onClick}\n onTouchStart={onClick}\n style={{\n position: 'absolute',\n border,\n left: (rect ? b.origin.x - rect.origin.x : b.origin.x) * scale,\n top: (rect ? b.origin.y - rect.origin.y : b.origin.y) * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: color,\n opacity: opacity,\n pointerEvents: onClick ? 'auto' : 'none',\n cursor: onClick ? 'pointer' : 'default',\n zIndex: onClick ? 1 : undefined,\n ...style,\n }}\n {...props}\n />\n ))}\n </>\n );\n}\n","import { Rect } from '@embedpdf/models';\n\nimport { useEffect, useState } from '@framework';\nimport { useRedactionPlugin } from '../hooks';\nimport { Highlight } from './highlight';\n\ninterface SelectionRedactProps {\n pageIndex: number;\n scale: number;\n}\n\nexport function SelectionRedact({ pageIndex, scale }: SelectionRedactProps) {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n const [rects, setRects] = useState<Array<Rect>>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!redactionPlugin) return;\n\n return redactionPlugin.onRedactionSelectionChange((formattedSelection) => {\n const selection = formattedSelection.find((s) => s.pageIndex === pageIndex);\n setRects(selection?.segmentRects ?? []);\n setBoundingRect(selection?.rect ?? null);\n });\n }, [redactionPlugin, pageIndex]);\n\n if (!boundingRect) return null;\n\n return (\n <div\n style={{\n mixBlendMode: 'normal',\n pointerEvents: 'none',\n position: 'absolute',\n inset: 0,\n }}\n >\n <Highlight\n color={'transparent'}\n opacity={1}\n rects={rects}\n scale={scale}\n border=\"1px solid red\"\n />\n </div>\n );\n}\n","import { Fragment, useEffect, useState, useCallback, MouseEvent, TouchEvent } from '@framework';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\nimport { useRedactionCapability } from '../hooks';\nimport { RedactionItem } from '@embedpdf/plugin-redaction';\nimport { Highlight } from './highlight';\nimport { SelectionMenuProps } from './types';\nimport { Rotation } from '@embedpdf/models';\n\ninterface PendingRedactionsProps {\n pageIndex: number;\n scale: number;\n rotation: Rotation;\n bboxStroke?: string;\n selectionMenu?: (props: SelectionMenuProps) => JSX.Element;\n}\n\nexport function PendingRedactions({\n pageIndex,\n scale,\n bboxStroke = 'rgba(0,0,0,0.8)',\n rotation = Rotation.Degree0,\n selectionMenu,\n}: PendingRedactionsProps) {\n const { provides: redaction } = useRedactionCapability();\n const [items, setItems] = useState<RedactionItem[]>([]);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n useEffect(() => {\n if (!redaction) return;\n const off1 = redaction.onPendingChange((map) => setItems(map[pageIndex] ?? []));\n const off2 = redaction.onSelectedChange((sel) => {\n setSelectedId(sel && sel.page === pageIndex ? sel.id : null);\n });\n return () => {\n off1?.();\n off2?.();\n };\n }, [redaction, pageIndex]);\n\n const select = useCallback(\n (e: MouseEvent | TouchEvent, id: string) => {\n e.stopPropagation();\n if (!redaction) return;\n redaction.selectPending(pageIndex, id);\n },\n [redaction, pageIndex],\n );\n\n if (!items.length) return null;\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {items.map((it) => {\n if (it.kind === 'area') {\n const r = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: r.origin.x * scale,\n top: r.origin.y * scale,\n width: r.size.width * scale,\n height: r.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n border: `1px solid red`,\n pointerEvents: 'auto',\n cursor: 'pointer',\n }}\n onPointerDown={(e) => select(e, it.id)}\n onTouchStart={(e) => select(e, it.id)}\n />\n <CounterRotate\n rect={{\n origin: { x: r.origin.x * scale, y: r.origin.y * scale },\n size: { width: r.size.width * scale, height: r.size.height * scale },\n }}\n rotation={rotation}\n >\n {({ rect, menuWrapperProps }) =>\n selectionMenu &&\n selectionMenu({\n item: it,\n selected: selectedId === it.id,\n pageIndex,\n menuWrapperProps,\n rect,\n })\n }\n </CounterRotate>\n </Fragment>\n );\n }\n // kind === 'text' → draw bounding box; inner rects are not drawn here to avoid clutter.\n const b = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: b.origin.x * scale,\n top: b.origin.y * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n pointerEvents: 'auto',\n cursor: selectedId === it.id ? 'pointer' : 'default',\n }}\n >\n <Highlight\n rect={b}\n rects={it.rects}\n color=\"transparent\"\n border=\"1px solid red\"\n scale={scale}\n onClick={(e) => select(e, it.id)}\n />\n </div>\n <CounterRotate\n rect={{\n origin: { x: b.origin.x * scale, y: b.origin.y * scale },\n size: { width: b.size.width * scale, height: b.size.height * scale },\n }}\n rotation={rotation}\n >\n {({ rect, menuWrapperProps }) =>\n selectionMenu &&\n selectionMenu({\n item: it,\n selected: selectedId === it.id,\n pageIndex,\n menuWrapperProps,\n rect,\n })\n }\n </CounterRotate>\n </Fragment>\n );\n })}\n </div>\n );\n}\n","import { Fragment } from '@framework';\nimport { MarqueeRedact } from './marquee-redact';\nimport { SelectionRedact } from './selection-redact';\nimport { PendingRedactions } from './pending-redactions';\nimport { Rotation } from '@embedpdf/models';\nimport { SelectionMenuProps } from './types';\n\ninterface RedactionLayerProps {\n pageIndex: number;\n scale: number;\n rotation: Rotation;\n selectionMenu?: (props: SelectionMenuProps) => JSX.Element;\n}\n\nexport const RedactionLayer = ({\n pageIndex,\n scale,\n rotation = Rotation.Degree0,\n selectionMenu,\n}: RedactionLayerProps) => {\n return (\n <Fragment>\n <PendingRedactions\n pageIndex={pageIndex}\n scale={scale}\n rotation={rotation}\n selectionMenu={selectionMenu}\n />\n <MarqueeRedact pageIndex={pageIndex} scale={scale} />\n <SelectionRedact pageIndex={pageIndex} scale={scale} />\n </Fragment>\n );\n};\n"],"names":["Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-redaction.ts","../../src/shared/components/marquee-redact.tsx","../../src/shared/components/highlight.tsx","../../src/shared/components/selection-redact.tsx","../../src/shared/components/pending-redactions.tsx","../../src/shared/components/redaction-layer.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport {\n initialDocumentState,\n RedactionPlugin,\n RedactionDocumentState,\n RedactionScope,\n} from '@embedpdf/plugin-redaction';\nimport { useState, useEffect, useMemo } from '@framework';\n\nexport const useRedactionPlugin = () => usePlugin<RedactionPlugin>(RedactionPlugin.id);\nexport const useRedactionCapability = () => useCapability<RedactionPlugin>(RedactionPlugin.id);\n\nexport const useRedaction = (\n documentId: string,\n): {\n state: RedactionDocumentState;\n provides: RedactionScope | null;\n} => {\n const { provides } = useRedactionCapability();\n const [state, setState] = useState<RedactionDocumentState>(initialDocumentState);\n\n const scope = useMemo(\n () => (provides ? provides.forDocument(documentId) : null),\n [provides, documentId],\n );\n\n useEffect(() => {\n if (!scope) {\n setState(initialDocumentState);\n return;\n }\n\n // Set initial state\n try {\n setState(scope.getState());\n } catch (e) {\n // Handle case where state might not be ready\n setState(initialDocumentState);\n }\n\n // Subscribe to changes\n const unsubscribe = scope.onStateChange((newState) => {\n setState(newState);\n });\n\n return unsubscribe;\n }, [scope]);\n\n return {\n state,\n provides: scope,\n };\n};\n","import { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useRedactionPlugin } from '../hooks/use-redaction';\n\ninterface MarqueeRedactProps {\n /** The ID of the document */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page */\n scale?: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeRedact = ({\n documentId,\n pageIndex,\n scale: scaleOverride,\n className,\n stroke = 'red',\n fill = 'transparent',\n}: MarqueeRedactProps) => {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n const documentState = useDocumentState(documentId);\n\n const [rect, setRect] = useState<Rect | null>(null);\n\n const scale = useMemo(() => {\n if (scaleOverride !== undefined) return scaleOverride;\n return documentState?.scale ?? 1;\n }, [scaleOverride, documentState?.scale]);\n\n useEffect(() => {\n if (!redactionPlugin || !documentId) return;\n return redactionPlugin.registerMarqueeOnPage({\n documentId,\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [redactionPlugin, documentId, pageIndex, scale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n","import { HTMLAttributes, CSSProperties, MouseEvent, TouchEvent } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\ntype HighlightProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n color?: string;\n opacity?: number;\n border?: string;\n rects: Rect[];\n rect?: Rect;\n scale: number;\n onClick?: (e: MouseEvent<HTMLDivElement> | TouchEvent<HTMLDivElement>) => void;\n style?: CSSProperties;\n};\n\nexport function Highlight({\n color = '#FFFF00',\n opacity = 1,\n border = '1px solid red',\n rects,\n rect,\n scale,\n onClick,\n style,\n ...props\n}: HighlightProps) {\n return (\n <>\n {rects.map((b, i) => (\n <div\n key={i}\n onPointerDown={onClick}\n onTouchStart={onClick}\n style={{\n position: 'absolute',\n border,\n left: (rect ? b.origin.x - rect.origin.x : b.origin.x) * scale,\n top: (rect ? b.origin.y - rect.origin.y : b.origin.y) * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: color,\n opacity: opacity,\n pointerEvents: onClick ? 'auto' : 'none',\n cursor: onClick ? 'pointer' : 'default',\n zIndex: onClick ? 1 : undefined,\n ...style,\n }}\n {...props}\n />\n ))}\n </>\n );\n}\n","import { Rect } from '@embedpdf/models';\nimport { useEffect, useState } from '@framework';\nimport { useRedactionPlugin } from '../hooks';\nimport { Highlight } from './highlight';\n\ninterface SelectionRedactProps {\n documentId: string;\n pageIndex: number;\n scale: number;\n}\n\nexport function SelectionRedact({ documentId, pageIndex, scale }: SelectionRedactProps) {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n const [rects, setRects] = useState<Array<Rect>>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!redactionPlugin) return;\n return redactionPlugin.onRedactionSelectionChange(documentId, (formattedSelection) => {\n const selection = formattedSelection.find((s) => s.pageIndex === pageIndex);\n setRects(selection?.segmentRects ?? []);\n setBoundingRect(selection?.rect ?? null);\n });\n }, [redactionPlugin, documentId, pageIndex]);\n\n if (!boundingRect) return null;\n\n return (\n <div\n style={{\n mixBlendMode: 'normal',\n pointerEvents: 'none',\n position: 'absolute',\n inset: 0,\n }}\n >\n <Highlight\n color={'transparent'}\n opacity={1}\n rects={rects}\n scale={scale}\n border=\"1px solid red\"\n />\n </div>\n );\n}\n","import { Fragment, useEffect, useState, useCallback, MouseEvent, TouchEvent } from '@framework';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\nimport { useRedactionCapability } from '../hooks';\nimport { RedactionItem } from '@embedpdf/plugin-redaction';\nimport { Highlight } from './highlight';\nimport { RedactionSelectionMenuRenderFn } from './types';\nimport { Rotation } from '@embedpdf/models';\n\ninterface PendingRedactionsProps {\n documentId: string;\n pageIndex: number;\n scale: number;\n rotation: Rotation;\n bboxStroke?: string;\n selectionMenu?: RedactionSelectionMenuRenderFn;\n}\n\nexport function PendingRedactions({\n documentId,\n pageIndex,\n scale,\n bboxStroke = 'rgba(0,0,0,0.8)',\n rotation = Rotation.Degree0,\n selectionMenu,\n}: PendingRedactionsProps) {\n const { provides: redaction } = useRedactionCapability();\n const [items, setItems] = useState<RedactionItem[]>([]);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n useEffect(() => {\n if (!redaction) return;\n\n // Use document-scoped hooks so we only receive events for this document\n const scoped = redaction.forDocument(documentId);\n\n // Initialize with current state\n const currentState = scoped.getState();\n setItems(currentState.pending[pageIndex] ?? []);\n setSelectedId(\n currentState.selected && currentState.selected.page === pageIndex\n ? currentState.selected.id\n : null,\n );\n\n // Subscribe to future changes\n const off1 = scoped.onPendingChange((map) => setItems(map[pageIndex] ?? []));\n const off2 = scoped.onSelectedChange((sel) => {\n setSelectedId(sel && sel.page === pageIndex ? sel.id : null);\n });\n\n return () => {\n off1?.();\n off2?.();\n };\n }, [redaction, documentId, pageIndex]);\n\n const select = useCallback(\n (e: MouseEvent | TouchEvent, id: string) => {\n e.stopPropagation();\n if (!redaction) return;\n redaction.forDocument(documentId).selectPending(pageIndex, id);\n },\n [redaction, documentId, pageIndex],\n );\n\n if (!items.length) return null;\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {items.map((it) => {\n if (it.kind === 'area') {\n const r = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: r.origin.x * scale,\n top: r.origin.y * scale,\n width: r.size.width * scale,\n height: r.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n border: `1px solid red`,\n pointerEvents: 'auto',\n cursor: 'pointer',\n }}\n onPointerDown={(e) => select(e, it.id)}\n onTouchStart={(e) => select(e, it.id)}\n />\n {selectionMenu && (\n <CounterRotate\n rect={{\n origin: { x: r.origin.x * scale, y: r.origin.y * scale },\n size: { width: r.size.width * scale, height: r.size.height * scale },\n }}\n rotation={rotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'redaction',\n item: it,\n pageIndex,\n },\n selected: selectedId === it.id,\n placement: {\n suggestTop: false,\n },\n })\n }\n </CounterRotate>\n )}\n </Fragment>\n );\n }\n\n const b = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: b.origin.x * scale,\n top: b.origin.y * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n pointerEvents: 'auto',\n cursor: selectedId === it.id ? 'pointer' : 'default',\n }}\n >\n <Highlight\n rect={b}\n rects={it.rects}\n color=\"transparent\"\n border=\"1px solid red\"\n scale={scale}\n onClick={(e) => select(e, it.id)}\n />\n </div>\n {selectionMenu && (\n <CounterRotate\n rect={{\n origin: { x: b.origin.x * scale, y: b.origin.y * scale },\n size: { width: b.size.width * scale, height: b.size.height * scale },\n }}\n rotation={rotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'redaction',\n item: it,\n pageIndex,\n },\n selected: selectedId === it.id,\n placement: {\n suggestTop: false,\n },\n })\n }\n </CounterRotate>\n )}\n </Fragment>\n );\n })}\n </div>\n );\n}\n","import { Fragment, useMemo } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { MarqueeRedact } from './marquee-redact';\nimport { SelectionRedact } from './selection-redact';\nimport { PendingRedactions } from './pending-redactions';\nimport { Rotation } from '@embedpdf/models';\nimport { RedactionSelectionMenuRenderFn } from './types';\n\ninterface RedactionLayerProps {\n /** The ID of the document this layer belongs to */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Current render scale for this page */\n scale?: number;\n /** Page rotation (for counter-rotating menus, etc.) */\n rotation?: Rotation;\n /** Optional menu renderer for a selected redaction */\n selectionMenu?: RedactionSelectionMenuRenderFn;\n}\n\nexport const RedactionLayer = ({\n documentId,\n pageIndex,\n scale,\n rotation,\n selectionMenu,\n}: RedactionLayerProps) => {\n const documentState = useDocumentState(documentId);\n\n const actualScale = useMemo(() => {\n if (scale !== undefined) return scale;\n return documentState?.scale ?? 1;\n }, [scale, documentState?.scale]);\n\n const actualRotation = useMemo(() => {\n if (rotation !== undefined) return rotation;\n return documentState?.rotation ?? Rotation.Degree0;\n }, [rotation, documentState?.rotation]);\n\n return (\n <Fragment>\n <PendingRedactions\n documentId={documentId}\n pageIndex={pageIndex}\n scale={actualScale}\n rotation={actualRotation}\n selectionMenu={selectionMenu}\n />\n <MarqueeRedact documentId={documentId} pageIndex={pageIndex} scale={actualScale} />\n <SelectionRedact documentId={documentId} pageIndex={pageIndex} scale={actualScale} />\n </Fragment>\n );\n};\n"],"names":["Fragment"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/react"),t=require("@embedpdf/plugin-redaction"),i=require("react"),n=require("react/jsx-runtime"),r=require("@embedpdf/utils/react"),o=require("@embedpdf/models"),s=()=>e.usePlugin(t.RedactionPlugin.id),a=()=>e.useCapability(t.RedactionPlugin.id),l=({pageIndex:e,scale:t,className:r,stroke:o="red",fill:a="transparent"})=>{const{plugin:l}=s(),[d,c]=i.useState(null);return i.useEffect((()=>{if(l)return l.registerMarqueeOnPage({pageIndex:e,scale:t,callback:{onPreview:c}})}),[l,e]),d?n.jsx("div",{style:{position:"absolute",pointerEvents:"none",left:d.origin.x*t,top:d.origin.y*t,width:d.size.width*t,height:d.size.height*t,border:`1px solid ${o}`,background:a,boxSizing:"border-box"},className:r}):null};function d({color:e="#FFFF00",opacity:t=1,border:i="1px solid red",rects:r,rect:o,scale:s,onClick:a,style:l,...d}){return n.jsx(n.Fragment,{children:r.map(((r,c)=>n.jsx("div",{onPointerDown:a,onTouchStart:a,style:{position:"absolute",border:i,left:(o?r.origin.x-o.origin.x:r.origin.x)*s,top:(o?r.origin.y-o.origin.y:r.origin.y)*s,width:r.size.width*s,height:r.size.height*s,background:e,opacity:t,pointerEvents:a?"auto":"none",cursor:a?"pointer":"default",zIndex:a?1:void 0,...l},...d},c)))})}function c({pageIndex:e,scale:t}){const{plugin:r}=s(),[o,a]=i.useState([]),[l,c]=i.useState(null);return i.useEffect((()=>{if(r)return r.onRedactionSelectionChange((t=>{const i=t.find((t=>t.pageIndex===e));a((null==i?void 0:i.segmentRects)??[]),c((null==i?void 0:i.rect)??null)}))}),[r,e]),l?n.jsx("div",{style:{mixBlendMode:"normal",pointerEvents:"none",position:"absolute",inset:0},children:n.jsx(d,{color:"transparent",opacity:1,rects:o,scale:t,border:"1px solid red"})}):null}function u({pageIndex:e,scale:t,bboxStroke:s="rgba(0,0,0,0.8)",rotation:l=o.Rotation.Degree0,selectionMenu:c}){const{provides:u}=a(),[p,g]=i.useState([]),[x,h]=i.useState(null);i.useEffect((()=>{if(!u)return;const t=u.onPendingChange((t=>g(t[e]??[]))),i=u.onSelectedChange((t=>{h(t&&t.page===e?t.id:null)}));return()=>{null==t||t(),null==i||i()}}),[u,e]);const b=i.useCallback(((t,i)=>{t.stopPropagation(),u&&u.selectPending(e,i)}),[u,e]);return p.length?n.jsx("div",{style:{position:"absolute",inset:0,pointerEvents:"none"},children:p.map((o=>{if("area"===o.kind){const a=o.rect;return n.jsxs(i.Fragment,{children:[n.jsx("div",{style:{position:"absolute",left:a.origin.x*t,top:a.origin.y*t,width:a.size.width*t,height:a.size.height*t,background:"transparent",outline:x===o.id?`1px solid ${s}`:"none",outlineOffset:"2px",border:"1px solid red",pointerEvents:"auto",cursor:"pointer"},onPointerDown:e=>b(e,o.id),onTouchStart:e=>b(e,o.id)}),n.jsx(r.CounterRotate,{rect:{origin:{x:a.origin.x*t,y:a.origin.y*t},size:{width:a.size.width*t,height:a.size.height*t}},rotation:l,children:({rect:t,menuWrapperProps:i})=>c&&c({item:o,selected:x===o.id,pageIndex:e,menuWrapperProps:i,rect:t})})]},o.id)}const a=o.rect;return n.jsxs(i.Fragment,{children:[n.jsx("div",{style:{position:"absolute",left:a.origin.x*t,top:a.origin.y*t,width:a.size.width*t,height:a.size.height*t,background:"transparent",outline:x===o.id?`1px solid ${s}`:"none",outlineOffset:"2px",pointerEvents:"auto",cursor:x===o.id?"pointer":"default"},children:n.jsx(d,{rect:a,rects:o.rects,color:"transparent",border:"1px solid red",scale:t,onClick:e=>b(e,o.id)})}),n.jsx(r.CounterRotate,{rect:{origin:{x:a.origin.x*t,y:a.origin.y*t},size:{width:a.size.width*t,height:a.size.height*t}},rotation:l,children:({rect:t,menuWrapperProps:i})=>c&&c({item:o,selected:x===o.id,pageIndex:e,menuWrapperProps:i,rect:t})})]},o.id)}))}):null}exports.RedactionLayer=({pageIndex:e,scale:t,rotation:r=o.Rotation.Degree0,selectionMenu:s})=>n.jsxs(i.Fragment,{children:[n.jsx(u,{pageIndex:e,scale:t,rotation:r,selectionMenu:s}),n.jsx(l,{pageIndex:e,scale:t}),n.jsx(c,{pageIndex:e,scale:t})]}),exports.useRedaction=()=>{const{provides:e}=a(),[n,r]=i.useState(t.initialState);return i.useEffect((()=>null==e?void 0:e.onStateChange((e=>{r(e)}))),[e]),{state:n,provides:e}},exports.useRedactionCapability=a,exports.useRedactionPlugin=s,Object.keys(t).forEach((e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})}));
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/react"),t=require("@embedpdf/plugin-redaction"),n=require("react"),i=require("react/jsx-runtime"),o=require("@embedpdf/utils/react"),r=require("@embedpdf/models"),s=()=>e.usePlugin(t.RedactionPlugin.id),d=()=>e.useCapability(t.RedactionPlugin.id),l=({documentId:t,pageIndex:o,scale:r,className:d,stroke:l="red",fill:a="transparent"})=>{const{plugin:c}=s(),u=e.useDocumentState(t),[p,g]=n.useState(null),x=n.useMemo(()=>void 0!==r?r:(null==u?void 0:u.scale)??1,[r,null==u?void 0:u.scale]);return n.useEffect(()=>{if(c&&t)return c.registerMarqueeOnPage({documentId:t,pageIndex:o,scale:x,callback:{onPreview:g}})},[c,t,o,x]),p?i.jsx("div",{style:{position:"absolute",pointerEvents:"none",left:p.origin.x*x,top:p.origin.y*x,width:p.size.width*x,height:p.size.height*x,border:`1px solid ${l}`,background:a,boxSizing:"border-box"},className:d}):null};function a({color:e="#FFFF00",opacity:t=1,border:n="1px solid red",rects:o,rect:r,scale:s,onClick:d,style:l,...a}){return i.jsx(i.Fragment,{children:o.map((o,c)=>i.jsx("div",{onPointerDown:d,onTouchStart:d,style:{position:"absolute",border:n,left:(r?o.origin.x-r.origin.x:o.origin.x)*s,top:(r?o.origin.y-r.origin.y:o.origin.y)*s,width:o.size.width*s,height:o.size.height*s,background:e,opacity:t,pointerEvents:d?"auto":"none",cursor:d?"pointer":"default",zIndex:d?1:void 0,...l},...a},c))})}function c({documentId:e,pageIndex:t,scale:o}){const{plugin:r}=s(),[d,l]=n.useState([]),[c,u]=n.useState(null);return n.useEffect(()=>{if(r)return r.onRedactionSelectionChange(e,e=>{const n=e.find(e=>e.pageIndex===t);l((null==n?void 0:n.segmentRects)??[]),u((null==n?void 0:n.rect)??null)})},[r,e,t]),c?i.jsx("div",{style:{mixBlendMode:"normal",pointerEvents:"none",position:"absolute",inset:0},children:i.jsx(a,{color:"transparent",opacity:1,rects:d,scale:o,border:"1px solid red"})}):null}function u({documentId:e,pageIndex:t,scale:s,bboxStroke:l="rgba(0,0,0,0.8)",rotation:c=r.Rotation.Degree0,selectionMenu:u}){const{provides:p}=d(),[g,x]=n.useState([]),[h,m]=n.useState(null);n.useEffect(()=>{if(!p)return;const n=p.forDocument(e),i=n.getState();x(i.pending[t]??[]),m(i.selected&&i.selected.page===t?i.selected.id:null);const o=n.onPendingChange(e=>x(e[t]??[])),r=n.onSelectedChange(e=>{m(e&&e.page===t?e.id:null)});return()=>{null==o||o(),null==r||r()}},[p,e,t]);const f=n.useCallback((n,i)=>{n.stopPropagation(),p&&p.forDocument(e).selectPending(t,i)},[p,e,t]);return g.length?i.jsx("div",{style:{position:"absolute",inset:0,pointerEvents:"none"},children:g.map(e=>{if("area"===e.kind){const r=e.rect;return i.jsxs(n.Fragment,{children:[i.jsx("div",{style:{position:"absolute",left:r.origin.x*s,top:r.origin.y*s,width:r.size.width*s,height:r.size.height*s,background:"transparent",outline:h===e.id?`1px solid ${l}`:"none",outlineOffset:"2px",border:"1px solid red",pointerEvents:"auto",cursor:"pointer"},onPointerDown:t=>f(t,e.id),onTouchStart:t=>f(t,e.id)}),u&&i.jsx(o.CounterRotate,{rect:{origin:{x:r.origin.x*s,y:r.origin.y*s},size:{width:r.size.width*s,height:r.size.height*s}},rotation:c,children:n=>u({...n,context:{type:"redaction",item:e,pageIndex:t},selected:h===e.id,placement:{suggestTop:!1}})})]},e.id)}const r=e.rect;return i.jsxs(n.Fragment,{children:[i.jsx("div",{style:{position:"absolute",left:r.origin.x*s,top:r.origin.y*s,width:r.size.width*s,height:r.size.height*s,background:"transparent",outline:h===e.id?`1px solid ${l}`:"none",outlineOffset:"2px",pointerEvents:"auto",cursor:h===e.id?"pointer":"default"},children:i.jsx(a,{rect:r,rects:e.rects,color:"transparent",border:"1px solid red",scale:s,onClick:t=>f(t,e.id)})}),u&&i.jsx(o.CounterRotate,{rect:{origin:{x:r.origin.x*s,y:r.origin.y*s},size:{width:r.size.width*s,height:r.size.height*s}},rotation:c,children:n=>u({...n,context:{type:"redaction",item:e,pageIndex:t},selected:h===e.id,placement:{suggestTop:!1}})})]},e.id)})}):null}exports.RedactionLayer=({documentId:t,pageIndex:o,scale:s,rotation:d,selectionMenu:a})=>{const p=e.useDocumentState(t),g=n.useMemo(()=>void 0!==s?s:(null==p?void 0:p.scale)??1,[s,null==p?void 0:p.scale]),x=n.useMemo(()=>void 0!==d?d:(null==p?void 0:p.rotation)??r.Rotation.Degree0,[d,null==p?void 0:p.rotation]);return i.jsxs(n.Fragment,{children:[i.jsx(u,{documentId:t,pageIndex:o,scale:g,rotation:x,selectionMenu:a}),i.jsx(l,{documentId:t,pageIndex:o,scale:g}),i.jsx(c,{documentId:t,pageIndex:o,scale:g})]})},exports.useRedaction=e=>{const{provides:i}=d(),[o,r]=n.useState(t.initialDocumentState),s=n.useMemo(()=>i?i.forDocument(e):null,[i,e]);return n.useEffect(()=>{if(!s)return void r(t.initialDocumentState);try{r(s.getState())}catch(e){r(t.initialDocumentState)}return s.onStateChange(e=>{r(e)})},[s]),{state:o,provides:s}},exports.useRedactionCapability=d,exports.useRedactionPlugin=s,Object.keys(t).forEach(e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>t[e]})});
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-redaction.ts","../../src/shared/components/marquee-redact.tsx","../../src/shared/components/highlight.tsx","../../src/shared/components/selection-redact.tsx","../../src/shared/components/pending-redactions.tsx","../../src/shared/components/redaction-layer.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { initialState, RedactionPlugin, RedactionState } from '@embedpdf/plugin-redaction';\nimport { useState, useEffect } from '@framework';\n\nexport const useRedactionPlugin = () => usePlugin<RedactionPlugin>(RedactionPlugin.id);\nexport const useRedactionCapability = () => useCapability<RedactionPlugin>(RedactionPlugin.id);\n\nexport const useRedaction = () => {\n const { provides } = useRedactionCapability();\n const [state, setState] = useState<RedactionState>(initialState);\n\n useEffect(() => {\n return provides?.onStateChange((action) => {\n setState(action);\n });\n }, [provides]);\n\n return {\n state,\n provides,\n };\n};\n","import { useEffect, useState } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useRedactionPlugin } from '../hooks/use-redaction';\n\ninterface MarqueeRedactProps {\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page */\n scale: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeRedact = ({\n pageIndex,\n scale,\n className,\n stroke = 'red',\n fill = 'transparent',\n}: MarqueeRedactProps) => {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n\n const [rect, setRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!redactionPlugin) return;\n return redactionPlugin.registerMarqueeOnPage({\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [redactionPlugin, pageIndex]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n","import { HTMLAttributes, CSSProperties, MouseEvent, TouchEvent } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\ntype HighlightProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n color?: string;\n opacity?: number;\n border?: string;\n rects: Rect[];\n rect?: Rect;\n scale: number;\n onClick?: (e: MouseEvent<HTMLDivElement> | TouchEvent<HTMLDivElement>) => void;\n style?: CSSProperties;\n};\n\nexport function Highlight({\n color = '#FFFF00',\n opacity = 1,\n border = '1px solid red',\n rects,\n rect,\n scale,\n onClick,\n style,\n ...props\n}: HighlightProps) {\n return (\n <>\n {rects.map((b, i) => (\n <div\n key={i}\n onPointerDown={onClick}\n onTouchStart={onClick}\n style={{\n position: 'absolute',\n border,\n left: (rect ? b.origin.x - rect.origin.x : b.origin.x) * scale,\n top: (rect ? b.origin.y - rect.origin.y : b.origin.y) * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: color,\n opacity: opacity,\n pointerEvents: onClick ? 'auto' : 'none',\n cursor: onClick ? 'pointer' : 'default',\n zIndex: onClick ? 1 : undefined,\n ...style,\n }}\n {...props}\n />\n ))}\n </>\n );\n}\n","import { Rect } from '@embedpdf/models';\n\nimport { useEffect, useState } from '@framework';\nimport { useRedactionPlugin } from '../hooks';\nimport { Highlight } from './highlight';\n\ninterface SelectionRedactProps {\n pageIndex: number;\n scale: number;\n}\n\nexport function SelectionRedact({ pageIndex, scale }: SelectionRedactProps) {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n const [rects, setRects] = useState<Array<Rect>>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!redactionPlugin) return;\n\n return redactionPlugin.onRedactionSelectionChange((formattedSelection) => {\n const selection = formattedSelection.find((s) => s.pageIndex === pageIndex);\n setRects(selection?.segmentRects ?? []);\n setBoundingRect(selection?.rect ?? null);\n });\n }, [redactionPlugin, pageIndex]);\n\n if (!boundingRect) return null;\n\n return (\n <div\n style={{\n mixBlendMode: 'normal',\n pointerEvents: 'none',\n position: 'absolute',\n inset: 0,\n }}\n >\n <Highlight\n color={'transparent'}\n opacity={1}\n rects={rects}\n scale={scale}\n border=\"1px solid red\"\n />\n </div>\n );\n}\n","import { Fragment, useEffect, useState, useCallback, MouseEvent, TouchEvent } from '@framework';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\nimport { useRedactionCapability } from '../hooks';\nimport { RedactionItem } from '@embedpdf/plugin-redaction';\nimport { Highlight } from './highlight';\nimport { SelectionMenuProps } from './types';\nimport { Rotation } from '@embedpdf/models';\n\ninterface PendingRedactionsProps {\n pageIndex: number;\n scale: number;\n rotation: Rotation;\n bboxStroke?: string;\n selectionMenu?: (props: SelectionMenuProps) => JSX.Element;\n}\n\nexport function PendingRedactions({\n pageIndex,\n scale,\n bboxStroke = 'rgba(0,0,0,0.8)',\n rotation = Rotation.Degree0,\n selectionMenu,\n}: PendingRedactionsProps) {\n const { provides: redaction } = useRedactionCapability();\n const [items, setItems] = useState<RedactionItem[]>([]);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n useEffect(() => {\n if (!redaction) return;\n const off1 = redaction.onPendingChange((map) => setItems(map[pageIndex] ?? []));\n const off2 = redaction.onSelectedChange((sel) => {\n setSelectedId(sel && sel.page === pageIndex ? sel.id : null);\n });\n return () => {\n off1?.();\n off2?.();\n };\n }, [redaction, pageIndex]);\n\n const select = useCallback(\n (e: MouseEvent | TouchEvent, id: string) => {\n e.stopPropagation();\n if (!redaction) return;\n redaction.selectPending(pageIndex, id);\n },\n [redaction, pageIndex],\n );\n\n if (!items.length) return null;\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {items.map((it) => {\n if (it.kind === 'area') {\n const r = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: r.origin.x * scale,\n top: r.origin.y * scale,\n width: r.size.width * scale,\n height: r.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n border: `1px solid red`,\n pointerEvents: 'auto',\n cursor: 'pointer',\n }}\n onPointerDown={(e) => select(e, it.id)}\n onTouchStart={(e) => select(e, it.id)}\n />\n <CounterRotate\n rect={{\n origin: { x: r.origin.x * scale, y: r.origin.y * scale },\n size: { width: r.size.width * scale, height: r.size.height * scale },\n }}\n rotation={rotation}\n >\n {({ rect, menuWrapperProps }) =>\n selectionMenu &&\n selectionMenu({\n item: it,\n selected: selectedId === it.id,\n pageIndex,\n menuWrapperProps,\n rect,\n })\n }\n </CounterRotate>\n </Fragment>\n );\n }\n // kind === 'text' → draw bounding box; inner rects are not drawn here to avoid clutter.\n const b = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: b.origin.x * scale,\n top: b.origin.y * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n pointerEvents: 'auto',\n cursor: selectedId === it.id ? 'pointer' : 'default',\n }}\n >\n <Highlight\n rect={b}\n rects={it.rects}\n color=\"transparent\"\n border=\"1px solid red\"\n scale={scale}\n onClick={(e) => select(e, it.id)}\n />\n </div>\n <CounterRotate\n rect={{\n origin: { x: b.origin.x * scale, y: b.origin.y * scale },\n size: { width: b.size.width * scale, height: b.size.height * scale },\n }}\n rotation={rotation}\n >\n {({ rect, menuWrapperProps }) =>\n selectionMenu &&\n selectionMenu({\n item: it,\n selected: selectedId === it.id,\n pageIndex,\n menuWrapperProps,\n rect,\n })\n }\n </CounterRotate>\n </Fragment>\n );\n })}\n </div>\n );\n}\n","import { Fragment } from '@framework';\nimport { MarqueeRedact } from './marquee-redact';\nimport { SelectionRedact } from './selection-redact';\nimport { PendingRedactions } from './pending-redactions';\nimport { Rotation } from '@embedpdf/models';\nimport { SelectionMenuProps } from './types';\n\ninterface RedactionLayerProps {\n pageIndex: number;\n scale: number;\n rotation: Rotation;\n selectionMenu?: (props: SelectionMenuProps) => JSX.Element;\n}\n\nexport const RedactionLayer = ({\n pageIndex,\n scale,\n rotation = Rotation.Degree0,\n selectionMenu,\n}: RedactionLayerProps) => {\n return (\n <Fragment>\n <PendingRedactions\n pageIndex={pageIndex}\n scale={scale}\n rotation={rotation}\n selectionMenu={selectionMenu}\n />\n <MarqueeRedact pageIndex={pageIndex} scale={scale} />\n <SelectionRedact pageIndex={pageIndex} scale={scale} />\n </Fragment>\n );\n};\n"],"names":["useRedactionPlugin","usePlugin","RedactionPlugin","id","useRedactionCapability","useCapability","MarqueeRedact","pageIndex","scale","className","stroke","fill","plugin","redactionPlugin","rect","setRect","useState","useEffect","registerMarqueeOnPage","callback","onPreview","jsxRuntime","jsx","style","position","pointerEvents","left","origin","x","top","y","width","size","height","border","background","boxSizing","Highlight","color","opacity","rects","onClick","props","Fragment","children","map","b","i","onPointerDown","onTouchStart","cursor","zIndex","SelectionRedact","setRects","boundingRect","setBoundingRect","onRedactionSelectionChange","formattedSelection","selection","find","s","segmentRects","mixBlendMode","inset","PendingRedactions","bboxStroke","rotation","Rotation","Degree0","selectionMenu","provides","redaction","items","setItems","selectedId","setSelectedId","off1","onPendingChange","off2","onSelectedChange","sel","page","select","useCallback","e","stopPropagation","selectPending","length","it","kind","r","outline","outlineOffset","CounterRotate","menuWrapperProps","item","selected","state","setState","initialState","onStateChange","action"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-redaction.ts","../../src/shared/components/marquee-redact.tsx","../../src/shared/components/highlight.tsx","../../src/shared/components/selection-redact.tsx","../../src/shared/components/pending-redactions.tsx","../../src/shared/components/redaction-layer.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport {\n initialDocumentState,\n RedactionPlugin,\n RedactionDocumentState,\n RedactionScope,\n} from '@embedpdf/plugin-redaction';\nimport { useState, useEffect, useMemo } from '@framework';\n\nexport const useRedactionPlugin = () => usePlugin<RedactionPlugin>(RedactionPlugin.id);\nexport const useRedactionCapability = () => useCapability<RedactionPlugin>(RedactionPlugin.id);\n\nexport const useRedaction = (\n documentId: string,\n): {\n state: RedactionDocumentState;\n provides: RedactionScope | null;\n} => {\n const { provides } = useRedactionCapability();\n const [state, setState] = useState<RedactionDocumentState>(initialDocumentState);\n\n const scope = useMemo(\n () => (provides ? provides.forDocument(documentId) : null),\n [provides, documentId],\n );\n\n useEffect(() => {\n if (!scope) {\n setState(initialDocumentState);\n return;\n }\n\n // Set initial state\n try {\n setState(scope.getState());\n } catch (e) {\n // Handle case where state might not be ready\n setState(initialDocumentState);\n }\n\n // Subscribe to changes\n const unsubscribe = scope.onStateChange((newState) => {\n setState(newState);\n });\n\n return unsubscribe;\n }, [scope]);\n\n return {\n state,\n provides: scope,\n };\n};\n","import { useEffect, useMemo, useState } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { Rect } from '@embedpdf/models';\n\nimport { useRedactionPlugin } from '../hooks/use-redaction';\n\ninterface MarqueeRedactProps {\n /** The ID of the document */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Scale of the page */\n scale?: number;\n /** Optional CSS class applied to the marquee rectangle */\n className?: string;\n /** Stroke / fill colours (defaults below) */\n stroke?: string;\n fill?: string;\n}\n\nexport const MarqueeRedact = ({\n documentId,\n pageIndex,\n scale: scaleOverride,\n className,\n stroke = 'red',\n fill = 'transparent',\n}: MarqueeRedactProps) => {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n const documentState = useDocumentState(documentId);\n\n const [rect, setRect] = useState<Rect | null>(null);\n\n const scale = useMemo(() => {\n if (scaleOverride !== undefined) return scaleOverride;\n return documentState?.scale ?? 1;\n }, [scaleOverride, documentState?.scale]);\n\n useEffect(() => {\n if (!redactionPlugin || !documentId) return;\n return redactionPlugin.registerMarqueeOnPage({\n documentId,\n pageIndex,\n scale,\n callback: {\n onPreview: setRect,\n },\n });\n }, [redactionPlugin, documentId, pageIndex, scale]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'absolute',\n pointerEvents: 'none',\n left: rect.origin.x * scale,\n top: rect.origin.y * scale,\n width: rect.size.width * scale,\n height: rect.size.height * scale,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }}\n className={className}\n />\n );\n};\n","import { HTMLAttributes, CSSProperties, MouseEvent, TouchEvent } from '@framework';\nimport { Rect } from '@embedpdf/models';\n\ntype HighlightProps = Omit<HTMLAttributes<HTMLDivElement>, 'style'> & {\n color?: string;\n opacity?: number;\n border?: string;\n rects: Rect[];\n rect?: Rect;\n scale: number;\n onClick?: (e: MouseEvent<HTMLDivElement> | TouchEvent<HTMLDivElement>) => void;\n style?: CSSProperties;\n};\n\nexport function Highlight({\n color = '#FFFF00',\n opacity = 1,\n border = '1px solid red',\n rects,\n rect,\n scale,\n onClick,\n style,\n ...props\n}: HighlightProps) {\n return (\n <>\n {rects.map((b, i) => (\n <div\n key={i}\n onPointerDown={onClick}\n onTouchStart={onClick}\n style={{\n position: 'absolute',\n border,\n left: (rect ? b.origin.x - rect.origin.x : b.origin.x) * scale,\n top: (rect ? b.origin.y - rect.origin.y : b.origin.y) * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: color,\n opacity: opacity,\n pointerEvents: onClick ? 'auto' : 'none',\n cursor: onClick ? 'pointer' : 'default',\n zIndex: onClick ? 1 : undefined,\n ...style,\n }}\n {...props}\n />\n ))}\n </>\n );\n}\n","import { Rect } from '@embedpdf/models';\nimport { useEffect, useState } from '@framework';\nimport { useRedactionPlugin } from '../hooks';\nimport { Highlight } from './highlight';\n\ninterface SelectionRedactProps {\n documentId: string;\n pageIndex: number;\n scale: number;\n}\n\nexport function SelectionRedact({ documentId, pageIndex, scale }: SelectionRedactProps) {\n const { plugin: redactionPlugin } = useRedactionPlugin();\n const [rects, setRects] = useState<Array<Rect>>([]);\n const [boundingRect, setBoundingRect] = useState<Rect | null>(null);\n\n useEffect(() => {\n if (!redactionPlugin) return;\n return redactionPlugin.onRedactionSelectionChange(documentId, (formattedSelection) => {\n const selection = formattedSelection.find((s) => s.pageIndex === pageIndex);\n setRects(selection?.segmentRects ?? []);\n setBoundingRect(selection?.rect ?? null);\n });\n }, [redactionPlugin, documentId, pageIndex]);\n\n if (!boundingRect) return null;\n\n return (\n <div\n style={{\n mixBlendMode: 'normal',\n pointerEvents: 'none',\n position: 'absolute',\n inset: 0,\n }}\n >\n <Highlight\n color={'transparent'}\n opacity={1}\n rects={rects}\n scale={scale}\n border=\"1px solid red\"\n />\n </div>\n );\n}\n","import { Fragment, useEffect, useState, useCallback, MouseEvent, TouchEvent } from '@framework';\nimport { CounterRotate } from '@embedpdf/utils/@framework';\nimport { useRedactionCapability } from '../hooks';\nimport { RedactionItem } from '@embedpdf/plugin-redaction';\nimport { Highlight } from './highlight';\nimport { RedactionSelectionMenuRenderFn } from './types';\nimport { Rotation } from '@embedpdf/models';\n\ninterface PendingRedactionsProps {\n documentId: string;\n pageIndex: number;\n scale: number;\n rotation: Rotation;\n bboxStroke?: string;\n selectionMenu?: RedactionSelectionMenuRenderFn;\n}\n\nexport function PendingRedactions({\n documentId,\n pageIndex,\n scale,\n bboxStroke = 'rgba(0,0,0,0.8)',\n rotation = Rotation.Degree0,\n selectionMenu,\n}: PendingRedactionsProps) {\n const { provides: redaction } = useRedactionCapability();\n const [items, setItems] = useState<RedactionItem[]>([]);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n useEffect(() => {\n if (!redaction) return;\n\n // Use document-scoped hooks so we only receive events for this document\n const scoped = redaction.forDocument(documentId);\n\n // Initialize with current state\n const currentState = scoped.getState();\n setItems(currentState.pending[pageIndex] ?? []);\n setSelectedId(\n currentState.selected && currentState.selected.page === pageIndex\n ? currentState.selected.id\n : null,\n );\n\n // Subscribe to future changes\n const off1 = scoped.onPendingChange((map) => setItems(map[pageIndex] ?? []));\n const off2 = scoped.onSelectedChange((sel) => {\n setSelectedId(sel && sel.page === pageIndex ? sel.id : null);\n });\n\n return () => {\n off1?.();\n off2?.();\n };\n }, [redaction, documentId, pageIndex]);\n\n const select = useCallback(\n (e: MouseEvent | TouchEvent, id: string) => {\n e.stopPropagation();\n if (!redaction) return;\n redaction.forDocument(documentId).selectPending(pageIndex, id);\n },\n [redaction, documentId, pageIndex],\n );\n\n if (!items.length) return null;\n\n return (\n <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>\n {items.map((it) => {\n if (it.kind === 'area') {\n const r = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: r.origin.x * scale,\n top: r.origin.y * scale,\n width: r.size.width * scale,\n height: r.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n border: `1px solid red`,\n pointerEvents: 'auto',\n cursor: 'pointer',\n }}\n onPointerDown={(e) => select(e, it.id)}\n onTouchStart={(e) => select(e, it.id)}\n />\n {selectionMenu && (\n <CounterRotate\n rect={{\n origin: { x: r.origin.x * scale, y: r.origin.y * scale },\n size: { width: r.size.width * scale, height: r.size.height * scale },\n }}\n rotation={rotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'redaction',\n item: it,\n pageIndex,\n },\n selected: selectedId === it.id,\n placement: {\n suggestTop: false,\n },\n })\n }\n </CounterRotate>\n )}\n </Fragment>\n );\n }\n\n const b = it.rect;\n return (\n <Fragment key={it.id}>\n <div\n style={{\n position: 'absolute',\n left: b.origin.x * scale,\n top: b.origin.y * scale,\n width: b.size.width * scale,\n height: b.size.height * scale,\n background: 'transparent',\n outline: selectedId === it.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n pointerEvents: 'auto',\n cursor: selectedId === it.id ? 'pointer' : 'default',\n }}\n >\n <Highlight\n rect={b}\n rects={it.rects}\n color=\"transparent\"\n border=\"1px solid red\"\n scale={scale}\n onClick={(e) => select(e, it.id)}\n />\n </div>\n {selectionMenu && (\n <CounterRotate\n rect={{\n origin: { x: b.origin.x * scale, y: b.origin.y * scale },\n size: { width: b.size.width * scale, height: b.size.height * scale },\n }}\n rotation={rotation}\n >\n {(props) =>\n selectionMenu({\n ...props,\n context: {\n type: 'redaction',\n item: it,\n pageIndex,\n },\n selected: selectedId === it.id,\n placement: {\n suggestTop: false,\n },\n })\n }\n </CounterRotate>\n )}\n </Fragment>\n );\n })}\n </div>\n );\n}\n","import { Fragment, useMemo } from '@framework';\nimport { useDocumentState } from '@embedpdf/core/@framework';\nimport { MarqueeRedact } from './marquee-redact';\nimport { SelectionRedact } from './selection-redact';\nimport { PendingRedactions } from './pending-redactions';\nimport { Rotation } from '@embedpdf/models';\nimport { RedactionSelectionMenuRenderFn } from './types';\n\ninterface RedactionLayerProps {\n /** The ID of the document this layer belongs to */\n documentId: string;\n /** Index of the page this layer lives on */\n pageIndex: number;\n /** Current render scale for this page */\n scale?: number;\n /** Page rotation (for counter-rotating menus, etc.) */\n rotation?: Rotation;\n /** Optional menu renderer for a selected redaction */\n selectionMenu?: RedactionSelectionMenuRenderFn;\n}\n\nexport const RedactionLayer = ({\n documentId,\n pageIndex,\n scale,\n rotation,\n selectionMenu,\n}: RedactionLayerProps) => {\n const documentState = useDocumentState(documentId);\n\n const actualScale = useMemo(() => {\n if (scale !== undefined) return scale;\n return documentState?.scale ?? 1;\n }, [scale, documentState?.scale]);\n\n const actualRotation = useMemo(() => {\n if (rotation !== undefined) return rotation;\n return documentState?.rotation ?? Rotation.Degree0;\n }, [rotation, documentState?.rotation]);\n\n return (\n <Fragment>\n <PendingRedactions\n documentId={documentId}\n pageIndex={pageIndex}\n scale={actualScale}\n rotation={actualRotation}\n selectionMenu={selectionMenu}\n />\n <MarqueeRedact documentId={documentId} pageIndex={pageIndex} scale={actualScale} />\n <SelectionRedact documentId={documentId} pageIndex={pageIndex} scale={actualScale} />\n </Fragment>\n );\n};\n"],"names":["useRedactionPlugin","usePlugin","RedactionPlugin","id","useRedactionCapability","useCapability","MarqueeRedact","documentId","pageIndex","scale","scaleOverride","className","stroke","fill","plugin","redactionPlugin","documentState","useDocumentState","rect","setRect","useState","useMemo","useEffect","registerMarqueeOnPage","callback","onPreview","jsx","style","position","pointerEvents","left","origin","x","top","y","width","size","height","border","background","boxSizing","Highlight","color","opacity","rects","onClick","props","Fragment","children","map","b","i","onPointerDown","onTouchStart","cursor","zIndex","SelectionRedact","setRects","boundingRect","setBoundingRect","onRedactionSelectionChange","formattedSelection","selection","find","s","segmentRects","mixBlendMode","inset","PendingRedactions","bboxStroke","rotation","Rotation","Degree0","selectionMenu","provides","redaction","items","setItems","selectedId","setSelectedId","scoped","forDocument","currentState","getState","pending","selected","page","off1","onPendingChange","off2","onSelectedChange","sel","select","useCallback","e","stopPropagation","selectPending","length","it","kind","r","outline","outlineOffset","CounterRotate","context","type","item","placement","suggestTop","actualScale","actualRotation","state","setState","initialDocumentState","scope","onStateChange","newState"],"mappings":"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"}