@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
package/dist/vue/index.js CHANGED
@@ -1,23 +1,42 @@
1
- import { ref, watchEffect, readonly, defineComponent, createElementBlock, openBlock, Fragment, renderList, mergeProps, unref, onMounted, onUnmounted, createCommentVNode, normalizeClass, normalizeStyle, createVNode, createElementVNode, withCtx, renderSlot, normalizeProps, guardReactiveProps } from "vue";
2
- import { usePlugin, useCapability } from "@embedpdf/core/vue";
3
- import { RedactionPlugin, initialState } from "@embedpdf/plugin-redaction";
1
+ import { ref, watch, toValue, computed, defineComponent, createElementBlock, openBlock, Fragment, renderList, mergeProps, unref, createCommentVNode, normalizeClass, normalizeStyle, createVNode, useSlots, createElementVNode, createBlock, withCtx, renderSlot, resolveDynamicComponent, normalizeProps, guardReactiveProps } from "vue";
2
+ import { useCapability, usePlugin, useDocumentState } from "@embedpdf/core/vue";
3
+ import { RedactionPlugin, initialDocumentState } from "@embedpdf/plugin-redaction";
4
4
  export * from "@embedpdf/plugin-redaction";
5
+ import { Rotation } from "@embedpdf/models";
5
6
  import { CounterRotate } from "@embedpdf/utils/vue";
6
7
  const useRedactionPlugin = () => usePlugin(RedactionPlugin.id);
7
8
  const useRedactionCapability = () => useCapability(RedactionPlugin.id);
8
- const useRedaction = () => {
9
+ const useRedaction = (documentId) => {
9
10
  const { provides } = useRedactionCapability();
10
- const state = ref(initialState);
11
- watchEffect((onCleanup) => {
12
- if (!provides.value) return;
13
- const unsubscribe = provides.value.onStateChange((newState) => {
14
- state.value = newState;
15
- });
16
- onCleanup(unsubscribe);
11
+ const state = ref(initialDocumentState);
12
+ watch(
13
+ [provides, () => toValue(documentId)],
14
+ ([providesValue, docId], _, onCleanup) => {
15
+ if (!providesValue) {
16
+ state.value = initialDocumentState;
17
+ return;
18
+ }
19
+ const scope = providesValue.forDocument(docId);
20
+ try {
21
+ state.value = scope.getState();
22
+ } catch (e) {
23
+ state.value = initialDocumentState;
24
+ }
25
+ const unsubscribe = scope.onStateChange((newState) => {
26
+ state.value = newState;
27
+ });
28
+ onCleanup(unsubscribe);
29
+ },
30
+ { immediate: true }
31
+ );
32
+ const scopedProvides = computed(() => {
33
+ var _a;
34
+ const docId = toValue(documentId);
35
+ return ((_a = provides.value) == null ? void 0 : _a.forDocument(docId)) ?? null;
17
36
  });
18
37
  return {
19
- state: readonly(state),
20
- provides
38
+ state,
39
+ provides: scopedProvides
21
40
  };
22
41
  };
23
42
  const _sfc_main$4 = /* @__PURE__ */ defineComponent({
@@ -35,25 +54,25 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
35
54
  const props = __props;
36
55
  const boundingRect = props.rect;
37
56
  return (_ctx, _cache) => {
38
- return openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.rects, (rect, i) => {
57
+ return openBlock(true), createElementBlock(Fragment, null, renderList(__props.rects, (rect, i) => {
39
58
  return openBlock(), createElementBlock("div", mergeProps({
40
59
  key: i,
41
60
  onPointerdown: _cache[0] || (_cache[0] = //@ts-ignore
42
- (...args) => _ctx.onClick && _ctx.onClick(...args)),
61
+ (...args) => __props.onClick && __props.onClick(...args)),
43
62
  onTouchstart: _cache[1] || (_cache[1] = //@ts-ignore
44
- (...args) => _ctx.onClick && _ctx.onClick(...args)),
63
+ (...args) => __props.onClick && __props.onClick(...args)),
45
64
  style: {
46
65
  position: "absolute",
47
- border: _ctx.border,
48
- left: `${(unref(boundingRect) ? rect.origin.x - unref(boundingRect).origin.x : rect.origin.x) * _ctx.scale}px`,
49
- top: `${(unref(boundingRect) ? rect.origin.y - unref(boundingRect).origin.y : rect.origin.y) * _ctx.scale}px`,
50
- width: `${rect.size.width * _ctx.scale}px`,
51
- height: `${rect.size.height * _ctx.scale}px`,
52
- background: _ctx.color,
53
- opacity: _ctx.opacity,
54
- pointerEvents: _ctx.onClick ? "auto" : "none",
55
- cursor: _ctx.onClick ? "pointer" : "default",
56
- zIndex: _ctx.onClick ? 1 : void 0
66
+ border: __props.border,
67
+ left: `${(unref(boundingRect) ? rect.origin.x - unref(boundingRect).origin.x : rect.origin.x) * __props.scale}px`,
68
+ top: `${(unref(boundingRect) ? rect.origin.y - unref(boundingRect).origin.y : rect.origin.y) * __props.scale}px`,
69
+ width: `${rect.size.width * __props.scale}px`,
70
+ height: `${rect.size.height * __props.scale}px`,
71
+ background: __props.color,
72
+ opacity: __props.opacity,
73
+ pointerEvents: __props.onClick ? "auto" : "none",
74
+ cursor: __props.onClick ? "pointer" : "default",
75
+ zIndex: __props.onClick ? 1 : void 0
57
76
  }
58
77
  }, { ref_for: true }, _ctx.$attrs), null, 16);
59
78
  }), 128);
@@ -63,6 +82,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
63
82
  const _sfc_main$3 = /* @__PURE__ */ defineComponent({
64
83
  __name: "marquee-redact",
65
84
  props: {
85
+ documentId: {},
66
86
  pageIndex: {},
67
87
  scale: {},
68
88
  className: {},
@@ -72,38 +92,46 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
72
92
  setup(__props) {
73
93
  const props = __props;
74
94
  const { plugin: redactionPlugin } = useRedactionPlugin();
95
+ const documentState = useDocumentState(() => props.documentId);
75
96
  const rect = ref(null);
76
- let unregister;
77
- onMounted(() => {
78
- if (!redactionPlugin.value) return;
79
- unregister = redactionPlugin.value.registerMarqueeOnPage({
80
- pageIndex: props.pageIndex,
81
- scale: props.scale,
82
- callback: {
83
- onPreview: (newRect) => {
84
- rect.value = newRect;
85
- }
86
- }
87
- });
88
- });
89
- onUnmounted(() => {
90
- unregister == null ? void 0 : unregister();
97
+ const actualScale = computed(() => {
98
+ var _a;
99
+ if (props.scale !== void 0) return props.scale;
100
+ return ((_a = documentState.value) == null ? void 0 : _a.scale) ?? 1;
91
101
  });
102
+ watch(
103
+ [redactionPlugin, () => props.documentId, () => props.pageIndex, actualScale],
104
+ ([plugin, docId, pageIdx, scale], _, onCleanup) => {
105
+ if (!plugin || !docId) return;
106
+ const unregister = plugin.registerMarqueeOnPage({
107
+ documentId: docId,
108
+ pageIndex: pageIdx,
109
+ scale,
110
+ callback: {
111
+ onPreview: (newRect) => {
112
+ rect.value = newRect;
113
+ }
114
+ }
115
+ });
116
+ onCleanup(unregister);
117
+ },
118
+ { immediate: true }
119
+ );
92
120
  return (_ctx, _cache) => {
93
121
  return rect.value ? (openBlock(), createElementBlock("div", {
94
122
  key: 0,
95
123
  style: normalizeStyle({
96
124
  position: "absolute",
97
125
  pointerEvents: "none",
98
- left: `${rect.value.origin.x * _ctx.scale}px`,
99
- top: `${rect.value.origin.y * _ctx.scale}px`,
100
- width: `${rect.value.size.width * _ctx.scale}px`,
101
- height: `${rect.value.size.height * _ctx.scale}px`,
102
- border: `1px solid ${_ctx.stroke}`,
103
- background: _ctx.fill,
126
+ left: `${rect.value.origin.x * actualScale.value}px`,
127
+ top: `${rect.value.origin.y * actualScale.value}px`,
128
+ width: `${rect.value.size.width * actualScale.value}px`,
129
+ height: `${rect.value.size.height * actualScale.value}px`,
130
+ border: `1px solid ${__props.stroke}`,
131
+ background: __props.fill,
104
132
  boxSizing: "border-box"
105
133
  }),
106
- class: normalizeClass(_ctx.className)
134
+ class: normalizeClass(__props.className)
107
135
  }, null, 6)) : createCommentVNode("", true);
108
136
  };
109
137
  }
@@ -120,6 +148,7 @@ const _hoisted_1$1 = {
120
148
  const _sfc_main$2 = /* @__PURE__ */ defineComponent({
121
149
  __name: "selection-redact",
122
150
  props: {
151
+ documentId: {},
123
152
  pageIndex: {},
124
153
  scale: {}
125
154
  },
@@ -128,25 +157,30 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
128
157
  const { plugin: redactionPlugin } = useRedactionPlugin();
129
158
  const rects = ref([]);
130
159
  const boundingRect = ref(null);
131
- let unsubscribe;
132
- onMounted(() => {
133
- if (!redactionPlugin.value) return;
134
- unsubscribe = redactionPlugin.value.onRedactionSelectionChange((formattedSelection) => {
135
- const selection = formattedSelection.find((s) => s.pageIndex === props.pageIndex);
136
- rects.value = (selection == null ? void 0 : selection.segmentRects) ?? [];
137
- boundingRect.value = (selection == null ? void 0 : selection.rect) ?? null;
138
- });
139
- });
140
- onUnmounted(() => {
141
- unsubscribe == null ? void 0 : unsubscribe();
142
- });
160
+ watch(
161
+ [redactionPlugin, () => props.documentId, () => props.pageIndex],
162
+ ([plugin, docId, pageIdx], _, onCleanup) => {
163
+ if (!plugin) {
164
+ rects.value = [];
165
+ boundingRect.value = null;
166
+ return;
167
+ }
168
+ const unsubscribe = plugin.onRedactionSelectionChange(docId, (formattedSelection) => {
169
+ const selection = formattedSelection.find((s) => s.pageIndex === pageIdx);
170
+ rects.value = (selection == null ? void 0 : selection.segmentRects) ?? [];
171
+ boundingRect.value = (selection == null ? void 0 : selection.rect) ?? null;
172
+ });
173
+ onCleanup(unsubscribe);
174
+ },
175
+ { immediate: true }
176
+ );
143
177
  return (_ctx, _cache) => {
144
178
  return boundingRect.value ? (openBlock(), createElementBlock("div", _hoisted_1$1, [
145
179
  createVNode(_sfc_main$4, {
146
180
  color: "transparent",
147
181
  opacity: 1,
148
182
  rects: rects.value,
149
- scale: _ctx.scale,
183
+ scale: __props.scale,
150
184
  border: "1px solid red"
151
185
  }, null, 8, ["rects", "scale"])
152
186
  ])) : createCommentVNode("", true);
@@ -161,36 +195,74 @@ const _hoisted_2 = ["onPointerdown", "onTouchstart"];
161
195
  const _sfc_main$1 = /* @__PURE__ */ defineComponent({
162
196
  __name: "pending-redactions",
163
197
  props: {
198
+ documentId: {},
164
199
  pageIndex: {},
165
200
  scale: {},
166
- rotation: { default: 0 },
167
- bboxStroke: { default: "rgba(0,0,0,0.8)" }
201
+ rotation: { default: Rotation.Degree0 },
202
+ bboxStroke: { default: "rgba(0,0,0,0.8)" },
203
+ selectionMenu: {}
168
204
  },
169
205
  setup(__props) {
170
206
  const props = __props;
207
+ const slots = useSlots();
171
208
  const { provides: redaction } = useRedactionCapability();
172
209
  const items = ref([]);
173
210
  const selectedId = ref(null);
211
+ watch(
212
+ [redaction, () => props.documentId, () => props.pageIndex],
213
+ ([redactionValue, docId, pageIdx], _, onCleanup) => {
214
+ if (!redactionValue) {
215
+ items.value = [];
216
+ selectedId.value = null;
217
+ return;
218
+ }
219
+ const scoped = redactionValue.forDocument(docId);
220
+ const currentState = scoped.getState();
221
+ items.value = currentState.pending[pageIdx] ?? [];
222
+ selectedId.value = currentState.selected && currentState.selected.page === pageIdx ? currentState.selected.id : null;
223
+ const off1 = scoped.onPendingChange((map) => {
224
+ items.value = map[pageIdx] ?? [];
225
+ });
226
+ const off2 = scoped.onSelectedChange((sel) => {
227
+ selectedId.value = sel && sel.page === pageIdx ? sel.id : null;
228
+ });
229
+ onCleanup(() => {
230
+ off1 == null ? void 0 : off1();
231
+ off2 == null ? void 0 : off2();
232
+ });
233
+ },
234
+ { immediate: true }
235
+ );
174
236
  const select = (e, id) => {
175
237
  e.stopPropagation();
176
- if (!redaction.value) return;
177
- redaction.value.selectPending(props.pageIndex, id);
238
+ const redactionValue = redaction.value;
239
+ if (!redactionValue) return;
240
+ redactionValue.forDocument(props.documentId).selectPending(props.pageIndex, id);
178
241
  };
179
- let unsubscribePending;
180
- let unsubscribeSelection;
181
- onMounted(() => {
182
- if (!redaction.value) return;
183
- unsubscribePending = redaction.value.onPendingChange((map) => {
184
- items.value = map[props.pageIndex] ?? [];
185
- });
186
- unsubscribeSelection = redaction.value.onSelectedChange((sel) => {
187
- selectedId.value = sel && sel.page === props.pageIndex ? sel.id : null;
188
- });
189
- });
190
- onUnmounted(() => {
191
- unsubscribePending == null ? void 0 : unsubscribePending();
192
- unsubscribeSelection == null ? void 0 : unsubscribeSelection();
242
+ const shouldShowMenu = (itemId) => {
243
+ const isSelected = selectedId.value === itemId;
244
+ return isSelected && (!!props.selectionMenu || !!slots["selection-menu"]);
245
+ };
246
+ const buildContext = (item) => ({
247
+ type: "redaction",
248
+ item,
249
+ pageIndex: props.pageIndex
193
250
  });
251
+ const menuPlacement = {
252
+ suggestTop: false,
253
+ spaceAbove: 0,
254
+ spaceBelow: 0
255
+ };
256
+ const renderSelectionMenu = (item, rect, menuWrapperProps) => {
257
+ if (!props.selectionMenu) return null;
258
+ return props.selectionMenu({
259
+ rect,
260
+ menuWrapperProps,
261
+ selected: selectedId.value === item.id,
262
+ placement: menuPlacement,
263
+ context: buildContext(item)
264
+ });
265
+ };
194
266
  return (_ctx, _cache) => {
195
267
  return items.value.length ? (openBlock(), createElementBlock("div", _hoisted_1, [
196
268
  (openBlock(true), createElementBlock(Fragment, null, renderList(items.value, (item) => {
@@ -201,12 +273,12 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
201
273
  createElementVNode("div", {
202
274
  style: normalizeStyle({
203
275
  position: "absolute",
204
- left: `${item.rect.origin.x * _ctx.scale}px`,
205
- top: `${item.rect.origin.y * _ctx.scale}px`,
206
- width: `${item.rect.size.width * _ctx.scale}px`,
207
- height: `${item.rect.size.height * _ctx.scale}px`,
276
+ left: `${item.rect.origin.x * __props.scale}px`,
277
+ top: `${item.rect.origin.y * __props.scale}px`,
278
+ width: `${item.rect.size.width * __props.scale}px`,
279
+ height: `${item.rect.size.height * __props.scale}px`,
208
280
  background: "transparent",
209
- outline: selectedId.value === item.id ? `1px solid ${_ctx.bboxStroke}` : "none",
281
+ outline: selectedId.value === item.id ? `1px solid ${__props.bboxStroke}` : "none",
210
282
  outlineOffset: "2px",
211
283
  border: `1px solid red`,
212
284
  pointerEvents: "auto",
@@ -215,34 +287,36 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
215
287
  onPointerdown: (e) => select(e, item.id),
216
288
  onTouchstart: (e) => select(e, item.id)
217
289
  }, null, 44, _hoisted_2),
218
- createVNode(unref(CounterRotate), {
290
+ shouldShowMenu(item.id) ? (openBlock(), createBlock(unref(CounterRotate), {
291
+ key: 0,
219
292
  rect: {
220
- origin: { x: item.rect.origin.x * _ctx.scale, y: item.rect.origin.y * _ctx.scale },
221
- size: { width: item.rect.size.width * _ctx.scale, height: item.rect.size.height * _ctx.scale }
293
+ origin: { x: item.rect.origin.x * __props.scale, y: item.rect.origin.y * __props.scale },
294
+ size: { width: item.rect.size.width * __props.scale, height: item.rect.size.height * __props.scale }
222
295
  },
223
- rotation: _ctx.rotation
296
+ rotation: __props.rotation
224
297
  }, {
225
298
  default: withCtx(({ rect, menuWrapperProps }) => [
226
- renderSlot(_ctx.$slots, "selection-menu", {
227
- item,
299
+ __props.selectionMenu ? (openBlock(), createBlock(resolveDynamicComponent(renderSelectionMenu(item, rect, menuWrapperProps)), { key: 0 })) : renderSlot(_ctx.$slots, "selection-menu", {
300
+ key: 1,
301
+ context: buildContext(item),
228
302
  selected: selectedId.value === item.id,
229
- pageIndex: _ctx.pageIndex,
230
- menuWrapperProps,
231
- rect
303
+ rect,
304
+ placement: menuPlacement,
305
+ menuWrapperProps
232
306
  })
233
307
  ]),
234
308
  _: 2
235
- }, 1032, ["rect", "rotation"])
309
+ }, 1032, ["rect", "rotation"])) : createCommentVNode("", true)
236
310
  ], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
237
311
  createElementVNode("div", {
238
312
  style: normalizeStyle({
239
313
  position: "absolute",
240
- left: `${item.rect.origin.x * _ctx.scale}px`,
241
- top: `${item.rect.origin.y * _ctx.scale}px`,
242
- width: `${item.rect.size.width * _ctx.scale}px`,
243
- height: `${item.rect.size.height * _ctx.scale}px`,
314
+ left: `${item.rect.origin.x * __props.scale}px`,
315
+ top: `${item.rect.origin.y * __props.scale}px`,
316
+ width: `${item.rect.size.width * __props.scale}px`,
317
+ height: `${item.rect.size.height * __props.scale}px`,
244
318
  background: "transparent",
245
- outline: selectedId.value === item.id ? `1px solid ${_ctx.bboxStroke}` : "none",
319
+ outline: selectedId.value === item.id ? `1px solid ${__props.bboxStroke}` : "none",
246
320
  outlineOffset: "2px",
247
321
  pointerEvents: "auto",
248
322
  cursor: selectedId.value === item.id ? "pointer" : "default"
@@ -253,34 +327,36 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
253
327
  rects: item.rects,
254
328
  color: "transparent",
255
329
  border: "1px solid red",
256
- scale: _ctx.scale,
330
+ scale: __props.scale,
257
331
  "on-click": (e) => select(e, item.id)
258
332
  }, null, 8, ["rect", "rects", "scale", "on-click"])
259
333
  ], 4),
260
- createVNode(unref(CounterRotate), {
334
+ shouldShowMenu(item.id) ? (openBlock(), createBlock(unref(CounterRotate), {
335
+ key: 0,
261
336
  rect: {
262
337
  origin: {
263
- x: item.rect.origin.x * _ctx.scale,
264
- y: item.rect.origin.y * _ctx.scale
338
+ x: item.rect.origin.x * __props.scale,
339
+ y: item.rect.origin.y * __props.scale
265
340
  },
266
341
  size: {
267
- width: item.rect.size.width * _ctx.scale,
268
- height: item.rect.size.height * _ctx.scale
342
+ width: item.rect.size.width * __props.scale,
343
+ height: item.rect.size.height * __props.scale
269
344
  }
270
345
  },
271
- rotation: _ctx.rotation
346
+ rotation: __props.rotation
272
347
  }, {
273
348
  default: withCtx(({ rect, menuWrapperProps }) => [
274
- renderSlot(_ctx.$slots, "selection-menu", {
275
- item,
349
+ __props.selectionMenu ? (openBlock(), createBlock(resolveDynamicComponent(renderSelectionMenu(item, rect, menuWrapperProps)), { key: 0 })) : renderSlot(_ctx.$slots, "selection-menu", {
350
+ key: 1,
351
+ context: buildContext(item),
276
352
  selected: selectedId.value === item.id,
277
- pageIndex: _ctx.pageIndex,
278
- menuWrapperProps,
279
- rect
353
+ rect,
354
+ placement: menuPlacement,
355
+ menuWrapperProps
280
356
  })
281
357
  ]),
282
358
  _: 2
283
- }, 1032, ["rect", "rotation"])
359
+ }, 1032, ["rect", "rotation"])) : createCommentVNode("", true)
284
360
  ], 64))
285
361
  ], 64);
286
362
  }), 128))
@@ -291,33 +367,51 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
291
367
  const _sfc_main = /* @__PURE__ */ defineComponent({
292
368
  __name: "redaction-layer",
293
369
  props: {
370
+ documentId: {},
294
371
  pageIndex: {},
295
372
  scale: {},
296
- rotation: { default: 0 },
297
- bboxStroke: { default: "rgba(0,0,0,0.8)" }
373
+ rotation: {},
374
+ bboxStroke: { default: "rgba(0,0,0,0.8)" },
375
+ selectionMenu: {}
298
376
  },
299
377
  setup(__props) {
378
+ const props = __props;
379
+ const documentState = useDocumentState(() => props.documentId);
380
+ const actualScale = computed(() => {
381
+ var _a;
382
+ if (props.scale !== void 0) return props.scale;
383
+ return ((_a = documentState.value) == null ? void 0 : _a.scale) ?? 1;
384
+ });
385
+ const actualRotation = computed(() => {
386
+ var _a;
387
+ if (props.rotation !== void 0) return props.rotation;
388
+ return ((_a = documentState.value) == null ? void 0 : _a.rotation) ?? Rotation.Degree0;
389
+ });
300
390
  return (_ctx, _cache) => {
301
391
  return openBlock(), createElementBlock(Fragment, null, [
302
392
  createVNode(_sfc_main$1, {
303
- "page-index": _ctx.pageIndex,
304
- scale: _ctx.scale,
305
- rotation: _ctx.rotation,
306
- "bbox-stroke": _ctx.bboxStroke
393
+ "document-id": __props.documentId,
394
+ "page-index": __props.pageIndex,
395
+ scale: actualScale.value,
396
+ rotation: actualRotation.value,
397
+ "bbox-stroke": __props.bboxStroke,
398
+ "selection-menu": __props.selectionMenu
307
399
  }, {
308
400
  "selection-menu": withCtx((slotProps) => [
309
401
  renderSlot(_ctx.$slots, "selection-menu", normalizeProps(guardReactiveProps(slotProps)))
310
402
  ]),
311
403
  _: 3
312
- }, 8, ["page-index", "scale", "rotation", "bbox-stroke"]),
404
+ }, 8, ["document-id", "page-index", "scale", "rotation", "bbox-stroke", "selection-menu"]),
313
405
  createVNode(_sfc_main$3, {
314
- "page-index": _ctx.pageIndex,
315
- scale: _ctx.scale
316
- }, null, 8, ["page-index", "scale"]),
406
+ "document-id": __props.documentId,
407
+ "page-index": __props.pageIndex,
408
+ scale: actualScale.value
409
+ }, null, 8, ["document-id", "page-index", "scale"]),
317
410
  createVNode(_sfc_main$2, {
318
- "page-index": _ctx.pageIndex,
319
- scale: _ctx.scale
320
- }, null, 8, ["page-index", "scale"])
411
+ "document-id": __props.documentId,
412
+ "page-index": __props.pageIndex,
413
+ scale: actualScale.value
414
+ }, null, 8, ["document-id", "page-index", "scale"])
321
415
  ], 64);
322
416
  };
323
417
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/vue/hooks/use-redaction.ts","../../src/vue/components/highlight.vue","../../src/vue/components/marquee-redact.vue","../../src/vue/components/selection-redact.vue","../../src/vue/components/pending-redactions.vue","../../src/vue/components/redaction-layer.vue"],"sourcesContent":["import { ref, watchEffect, readonly } from 'vue';\nimport { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { RedactionPlugin, initialState, RedactionState } from '@embedpdf/plugin-redaction';\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 = ref<RedactionState>(initialState);\n\n watchEffect((onCleanup) => {\n if (!provides.value) return;\n\n const unsubscribe = provides.value.onStateChange((newState) => {\n state.value = newState;\n });\n onCleanup(unsubscribe);\n });\n\n return {\n state: readonly(state),\n provides,\n };\n};\n","<template>\n <div\n v-for=\"(rect, i) in rects\"\n :key=\"i\"\n @pointerdown=\"onClick\"\n @touchstart=\"onClick\"\n :style=\"{\n position: 'absolute',\n border,\n left: `${(boundingRect ? rect.origin.x - boundingRect.origin.x : rect.origin.x) * scale}px`,\n top: `${(boundingRect ? rect.origin.y - boundingRect.origin.y : rect.origin.y) * scale}px`,\n width: `${rect.size.width * scale}px`,\n height: `${rect.size.height * scale}px`,\n background: color,\n opacity: opacity,\n pointerEvents: onClick ? 'auto' : 'none',\n cursor: onClick ? 'pointer' : 'default',\n zIndex: onClick ? 1 : undefined,\n }\"\n v-bind=\"$attrs\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport type { Rect } from '@embedpdf/models';\n\ninterface HighlightProps {\n color?: string;\n opacity?: number;\n border?: string;\n rects: Rect[];\n rect?: Rect;\n scale: number;\n onClick?: (e: PointerEvent | TouchEvent) => void;\n}\n\nconst props = withDefaults(defineProps<HighlightProps>(), {\n color: '#FFFF00',\n opacity: 1,\n border: '1px solid red',\n});\n\n// Rename rect to boundingRect for clarity in template\nconst boundingRect = props.rect;\n</script>\n","<template>\n <div\n v-if=\"rect\"\n :style=\"{\n position: 'absolute',\n pointerEvents: 'none',\n left: `${rect.origin.x * scale}px`,\n top: `${rect.origin.y * scale}px`,\n width: `${rect.size.width * scale}px`,\n height: `${rect.size.height * scale}px`,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }\"\n :class=\"className\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted } from 'vue';\nimport type { Rect } from '@embedpdf/models';\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\nconst props = withDefaults(defineProps<MarqueeRedactProps>(), {\n stroke: 'red',\n fill: 'transparent',\n});\n\nconst { plugin: redactionPlugin } = useRedactionPlugin();\nconst rect = ref<Rect | null>(null);\n\nlet unregister: (() => void) | undefined;\n\nonMounted(() => {\n if (!redactionPlugin.value) return;\n\n unregister = redactionPlugin.value.registerMarqueeOnPage({\n pageIndex: props.pageIndex,\n scale: props.scale,\n callback: {\n onPreview: (newRect) => {\n rect.value = newRect;\n },\n },\n });\n});\n\nonUnmounted(() => {\n unregister?.();\n});\n</script>\n","<template>\n <div\n v-if=\"boundingRect\"\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</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport { useRedactionPlugin } from '../hooks/use-redaction';\nimport Highlight from './highlight.vue';\n\ninterface SelectionRedactProps {\n pageIndex: number;\n scale: number;\n}\n\nconst props = defineProps<SelectionRedactProps>();\n\nconst { plugin: redactionPlugin } = useRedactionPlugin();\nconst rects = ref<Rect[]>([]);\nconst boundingRect = ref<Rect | null>(null);\n\nlet unsubscribe: (() => void) | undefined;\n\nonMounted(() => {\n if (!redactionPlugin.value) return;\n\n unsubscribe = redactionPlugin.value.onRedactionSelectionChange((formattedSelection) => {\n const selection = formattedSelection.find((s) => s.pageIndex === props.pageIndex);\n rects.value = selection?.segmentRects ?? [];\n boundingRect.value = selection?.rect ?? null;\n });\n});\n\nonUnmounted(() => {\n unsubscribe?.();\n});\n</script>\n","<template>\n <div v-if=\"items.length\" :style=\"{ position: 'absolute', inset: 0, pointerEvents: 'none' }\">\n <template v-for=\"item in items\" :key=\"item.id\">\n <!-- Area redaction -->\n <template v-if=\"item.kind === 'area'\">\n <div\n :style=\"{\n position: 'absolute',\n left: `${item.rect.origin.x * scale}px`,\n top: `${item.rect.origin.y * scale}px`,\n width: `${item.rect.size.width * scale}px`,\n height: `${item.rect.size.height * scale}px`,\n background: 'transparent',\n outline: selectedId === item.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n border: `1px solid red`,\n pointerEvents: 'auto',\n cursor: 'pointer',\n }\"\n @pointerdown=\"(e: PointerEvent) => select(e, item.id)\"\n @touchstart=\"(e: TouchEvent) => select(e, item.id)\"\n />\n <CounterRotate\n :rect=\"{\n origin: { x: item.rect.origin.x * scale, y: item.rect.origin.y * scale },\n size: { width: item.rect.size.width * scale, height: item.rect.size.height * scale },\n }\"\n :rotation=\"rotation\"\n >\n <template #default=\"{ rect, menuWrapperProps }\">\n <slot\n name=\"selection-menu\"\n :item=\"item\"\n :selected=\"selectedId === item.id\"\n :page-index=\"pageIndex\"\n :menu-wrapper-props=\"menuWrapperProps\"\n :rect=\"rect\"\n />\n </template>\n </CounterRotate>\n </template>\n\n <!-- Text redaction -->\n <template v-else>\n <div\n :style=\"{\n position: 'absolute',\n left: `${item.rect.origin.x * scale}px`,\n top: `${item.rect.origin.y * scale}px`,\n width: `${item.rect.size.width * scale}px`,\n height: `${item.rect.size.height * scale}px`,\n background: 'transparent',\n outline: selectedId === item.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n pointerEvents: 'auto',\n cursor: selectedId === item.id ? 'pointer' : 'default',\n }\"\n >\n <Highlight\n :rect=\"item.rect\"\n :rects=\"item.rects\"\n color=\"transparent\"\n border=\"1px solid red\"\n :scale=\"scale\"\n :on-click=\"(e: PointerEvent | TouchEvent) => select(e, item.id)\"\n />\n </div>\n <CounterRotate\n :rect=\"{\n origin: {\n x: item.rect.origin.x * scale,\n y: item.rect.origin.y * scale,\n },\n size: {\n width: item.rect.size.width * scale,\n height: item.rect.size.height * scale,\n },\n }\"\n :rotation=\"rotation\"\n >\n <template #default=\"{ rect, menuWrapperProps }\">\n <slot\n name=\"selection-menu\"\n :item=\"item\"\n :selected=\"selectedId === item.id\"\n :page-index=\"pageIndex\"\n :menu-wrapper-props=\"menuWrapperProps\"\n :rect=\"rect\"\n />\n </template>\n </CounterRotate>\n </template>\n </template>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted } from 'vue';\nimport { CounterRotate } from '@embedpdf/utils/vue';\nimport type { Rotation } from '@embedpdf/models';\nimport type { RedactionItem } from '@embedpdf/plugin-redaction';\nimport { useRedactionCapability } from '../hooks/use-redaction';\nimport Highlight from './highlight.vue';\n\ninterface PendingRedactionsProps {\n pageIndex: number;\n scale: number;\n rotation?: Rotation;\n bboxStroke?: string;\n}\n\nconst props = withDefaults(defineProps<PendingRedactionsProps>(), {\n rotation: 0,\n bboxStroke: 'rgba(0,0,0,0.8)',\n});\n\nconst { provides: redaction } = useRedactionCapability();\nconst items = ref<RedactionItem[]>([]);\nconst selectedId = ref<string | null>(null);\n\nconst select = (e: PointerEvent | TouchEvent, id: string) => {\n e.stopPropagation();\n if (!redaction.value) return;\n redaction.value.selectPending(props.pageIndex, id);\n};\n\nlet unsubscribePending: (() => void) | undefined;\nlet unsubscribeSelection: (() => void) | undefined;\n\nonMounted(() => {\n if (!redaction.value) return;\n\n unsubscribePending = redaction.value.onPendingChange((map) => {\n items.value = map[props.pageIndex] ?? [];\n });\n\n unsubscribeSelection = redaction.value.onSelectedChange((sel) => {\n selectedId.value = sel && sel.page === props.pageIndex ? sel.id : null;\n });\n});\n\nonUnmounted(() => {\n unsubscribePending?.();\n unsubscribeSelection?.();\n});\n</script>\n","<template>\n <PendingRedactions\n :page-index=\"pageIndex\"\n :scale=\"scale\"\n :rotation=\"rotation\"\n :bbox-stroke=\"bboxStroke\"\n >\n <template #selection-menu=\"slotProps\">\n <slot name=\"selection-menu\" v-bind=\"slotProps\" />\n </template>\n </PendingRedactions>\n <MarqueeRedact :page-index=\"pageIndex\" :scale=\"scale\" />\n <SelectionRedact :page-index=\"pageIndex\" :scale=\"scale\" />\n</template>\n\n<script setup lang=\"ts\">\nimport type { Rotation } from '@embedpdf/models';\nimport PendingRedactions from './pending-redactions.vue';\nimport MarqueeRedact from './marquee-redact.vue';\nimport SelectionRedact from './selection-redact.vue';\n\ninterface RedactionLayerProps {\n pageIndex: number;\n scale: number;\n rotation?: Rotation;\n bboxStroke?: string;\n}\n\nwithDefaults(defineProps<RedactionLayerProps>(), {\n rotation: 0,\n bboxStroke: 'rgba(0,0,0,0.8)',\n});\n</script>\n"],"names":["_openBlock","_createElementBlock","_Fragment","rects","_mergeProps","border","_unref","scale","color","opacity","onClick","$attrs","_normalizeStyle","stroke","fill","className","_hoisted_1","_createVNode","Highlight","_renderList","_createElementVNode","bboxStroke","rotation","_withCtx","_renderSlot","pageIndex","PendingRedactions","MarqueeRedact","SelectionRedact"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/vue/hooks/use-redaction.ts","../../src/vue/components/highlight.vue","../../src/vue/components/marquee-redact.vue","../../src/vue/components/selection-redact.vue","../../src/vue/components/pending-redactions.vue","../../src/vue/components/redaction-layer.vue"],"sourcesContent":["import { ref, watch, computed, toValue, type MaybeRefOrGetter, ComputedRef, Ref } from 'vue';\nimport { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport {\n RedactionPlugin,\n initialDocumentState,\n RedactionDocumentState,\n RedactionScope,\n} from '@embedpdf/plugin-redaction';\n\nexport const useRedactionPlugin = () => usePlugin<RedactionPlugin>(RedactionPlugin.id);\nexport const useRedactionCapability = () => useCapability<RedactionPlugin>(RedactionPlugin.id);\n\n/**\n * Hook for redaction state for a specific document\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n */\nexport const useRedaction = (\n documentId: MaybeRefOrGetter<string>,\n): {\n state: Readonly<Ref<RedactionDocumentState>>;\n provides: ComputedRef<RedactionScope | null>;\n} => {\n const { provides } = useRedactionCapability();\n const state = ref<RedactionDocumentState>(initialDocumentState);\n\n watch(\n [provides, () => toValue(documentId)],\n ([providesValue, docId], _, onCleanup) => {\n if (!providesValue) {\n state.value = initialDocumentState;\n return;\n }\n\n const scope = providesValue.forDocument(docId);\n\n // Set initial state\n try {\n state.value = scope.getState();\n } catch (e) {\n // Handle case where state might not be ready\n state.value = initialDocumentState;\n }\n\n // Subscribe to changes\n const unsubscribe = scope.onStateChange((newState) => {\n state.value = newState;\n });\n\n onCleanup(unsubscribe);\n },\n { immediate: true },\n );\n\n const scopedProvides = computed(() => {\n const docId = toValue(documentId);\n return provides.value?.forDocument(docId) ?? null;\n });\n\n return {\n state,\n provides: scopedProvides,\n };\n};\n","<template>\n <div\n v-for=\"(rect, i) in rects\"\n :key=\"i\"\n @pointerdown=\"onClick\"\n @touchstart=\"onClick\"\n :style=\"{\n position: 'absolute',\n border,\n left: `${(boundingRect ? rect.origin.x - boundingRect.origin.x : rect.origin.x) * scale}px`,\n top: `${(boundingRect ? rect.origin.y - boundingRect.origin.y : rect.origin.y) * scale}px`,\n width: `${rect.size.width * scale}px`,\n height: `${rect.size.height * scale}px`,\n background: color,\n opacity: opacity,\n pointerEvents: onClick ? 'auto' : 'none',\n cursor: onClick ? 'pointer' : 'default',\n zIndex: onClick ? 1 : undefined,\n }\"\n v-bind=\"$attrs\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport type { Rect } from '@embedpdf/models';\n\ninterface HighlightProps {\n color?: string;\n opacity?: number;\n border?: string;\n rects: Rect[];\n rect?: Rect;\n scale: number;\n onClick?: (e: PointerEvent | TouchEvent) => void;\n}\n\nconst props = withDefaults(defineProps<HighlightProps>(), {\n color: '#FFFF00',\n opacity: 1,\n border: '1px solid red',\n});\n\n// Rename rect to boundingRect for clarity in template\nconst boundingRect = props.rect;\n</script>\n","<template>\n <div\n v-if=\"rect\"\n :style=\"{\n position: 'absolute',\n pointerEvents: 'none',\n left: `${rect.origin.x * actualScale}px`,\n top: `${rect.origin.y * actualScale}px`,\n width: `${rect.size.width * actualScale}px`,\n height: `${rect.size.height * actualScale}px`,\n border: `1px solid ${stroke}`,\n background: fill,\n boxSizing: 'border-box',\n }\"\n :class=\"className\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch, computed } from 'vue';\nimport { useDocumentState } from '@embedpdf/core/vue';\nimport type { Rect } from '@embedpdf/models';\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\nconst props = withDefaults(defineProps<MarqueeRedactProps>(), {\n stroke: 'red',\n fill: 'transparent',\n});\n\nconst { plugin: redactionPlugin } = useRedactionPlugin();\nconst documentState = useDocumentState(() => props.documentId);\nconst rect = ref<Rect | null>(null);\n\nconst actualScale = computed(() => {\n if (props.scale !== undefined) return props.scale;\n return documentState.value?.scale ?? 1;\n});\n\nwatch(\n [redactionPlugin, () => props.documentId, () => props.pageIndex, actualScale],\n ([plugin, docId, pageIdx, scale], _, onCleanup) => {\n if (!plugin || !docId) return;\n\n const unregister = plugin.registerMarqueeOnPage({\n documentId: docId,\n pageIndex: pageIdx,\n scale,\n callback: {\n onPreview: (newRect) => {\n rect.value = newRect;\n },\n },\n });\n\n onCleanup(unregister);\n },\n { immediate: true },\n);\n</script>\n","<template>\n <div\n v-if=\"boundingRect\"\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</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport { useRedactionPlugin } from '../hooks/use-redaction';\nimport Highlight from './highlight.vue';\n\ninterface SelectionRedactProps {\n documentId: string;\n pageIndex: number;\n scale: number;\n}\n\nconst props = defineProps<SelectionRedactProps>();\n\nconst { plugin: redactionPlugin } = useRedactionPlugin();\nconst rects = ref<Rect[]>([]);\nconst boundingRect = ref<Rect | null>(null);\n\nwatch(\n [redactionPlugin, () => props.documentId, () => props.pageIndex],\n ([plugin, docId, pageIdx], _, onCleanup) => {\n if (!plugin) {\n rects.value = [];\n boundingRect.value = null;\n return;\n }\n\n const unsubscribe = plugin.onRedactionSelectionChange(docId, (formattedSelection) => {\n const selection = formattedSelection.find((s) => s.pageIndex === pageIdx);\n rects.value = selection?.segmentRects ?? [];\n boundingRect.value = selection?.rect ?? null;\n });\n\n onCleanup(unsubscribe);\n },\n { immediate: true },\n);\n</script>\n","<template>\n <div v-if=\"items.length\" :style=\"{ position: 'absolute', inset: 0, pointerEvents: 'none' }\">\n <template v-for=\"item in items\" :key=\"item.id\">\n <!-- Area redaction -->\n <template v-if=\"item.kind === 'area'\">\n <div\n :style=\"{\n position: 'absolute',\n left: `${item.rect.origin.x * scale}px`,\n top: `${item.rect.origin.y * scale}px`,\n width: `${item.rect.size.width * scale}px`,\n height: `${item.rect.size.height * scale}px`,\n background: 'transparent',\n outline: selectedId === item.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n border: `1px solid red`,\n pointerEvents: 'auto',\n cursor: 'pointer',\n }\"\n @pointerdown=\"(e: PointerEvent) => select(e, item.id)\"\n @touchstart=\"(e: TouchEvent) => select(e, item.id)\"\n />\n\n <!-- Selection Menu: Supports BOTH render function and slot -->\n <CounterRotate\n v-if=\"shouldShowMenu(item.id)\"\n :rect=\"{\n origin: { x: item.rect.origin.x * scale, y: item.rect.origin.y * scale },\n size: { width: item.rect.size.width * scale, height: item.rect.size.height * scale },\n }\"\n :rotation=\"rotation\"\n >\n <template #default=\"{ rect, menuWrapperProps }\">\n <!-- Priority 1: Render function prop (schema-driven) -->\n <component\n v-if=\"selectionMenu\"\n :is=\"renderSelectionMenu(item, rect, menuWrapperProps)\"\n />\n\n <!-- Priority 2: Slot (manual customization) -->\n <slot\n v-else\n name=\"selection-menu\"\n :context=\"buildContext(item)\"\n :selected=\"selectedId === item.id\"\n :rect=\"rect\"\n :placement=\"menuPlacement\"\n :menuWrapperProps=\"menuWrapperProps\"\n />\n </template>\n </CounterRotate>\n </template>\n\n <!-- Text redaction -->\n <template v-else>\n <div\n :style=\"{\n position: 'absolute',\n left: `${item.rect.origin.x * scale}px`,\n top: `${item.rect.origin.y * scale}px`,\n width: `${item.rect.size.width * scale}px`,\n height: `${item.rect.size.height * scale}px`,\n background: 'transparent',\n outline: selectedId === item.id ? `1px solid ${bboxStroke}` : 'none',\n outlineOffset: '2px',\n pointerEvents: 'auto',\n cursor: selectedId === item.id ? 'pointer' : 'default',\n }\"\n >\n <Highlight\n :rect=\"item.rect\"\n :rects=\"item.rects\"\n color=\"transparent\"\n border=\"1px solid red\"\n :scale=\"scale\"\n :on-click=\"(e: PointerEvent | TouchEvent) => select(e, item.id)\"\n />\n </div>\n\n <!-- Selection Menu: Supports BOTH render function and slot -->\n <CounterRotate\n v-if=\"shouldShowMenu(item.id)\"\n :rect=\"{\n origin: {\n x: item.rect.origin.x * scale,\n y: item.rect.origin.y * scale,\n },\n size: {\n width: item.rect.size.width * scale,\n height: item.rect.size.height * scale,\n },\n }\"\n :rotation=\"rotation\"\n >\n <template #default=\"{ rect, menuWrapperProps }\">\n <!-- Priority 1: Render function prop (schema-driven) -->\n <component\n v-if=\"selectionMenu\"\n :is=\"renderSelectionMenu(item, rect, menuWrapperProps)\"\n />\n\n <!-- Priority 2: Slot (manual customization) -->\n <slot\n v-else\n name=\"selection-menu\"\n :context=\"buildContext(item)\"\n :selected=\"selectedId === item.id\"\n :rect=\"rect\"\n :placement=\"menuPlacement\"\n :menuWrapperProps=\"menuWrapperProps\"\n />\n </template>\n </CounterRotate>\n </template>\n </template>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch, useSlots, type VNode } from 'vue';\nimport type { Rect } from '@embedpdf/models';\nimport { Rotation } from '@embedpdf/models';\nimport { CounterRotate } from '@embedpdf/utils/vue';\nimport type { MenuWrapperProps, SelectionMenuPlacement } from '@embedpdf/utils/vue';\nimport type { RedactionItem } from '@embedpdf/plugin-redaction';\nimport { useRedactionCapability } from '../hooks/use-redaction';\nimport Highlight from './highlight.vue';\nimport type { RedactionSelectionContext, RedactionSelectionMenuRenderFn } from './types';\n\ninterface PendingRedactionsProps {\n documentId: string;\n pageIndex: number;\n scale: number;\n rotation: Rotation;\n bboxStroke?: string;\n /** Render function for selection menu (schema-driven approach) */\n selectionMenu?: RedactionSelectionMenuRenderFn;\n}\n\nconst props = withDefaults(defineProps<PendingRedactionsProps>(), {\n rotation: Rotation.Degree0,\n bboxStroke: 'rgba(0,0,0,0.8)',\n});\n\nconst slots = useSlots();\nconst { provides: redaction } = useRedactionCapability();\nconst items = ref<RedactionItem[]>([]);\nconst selectedId = ref<string | null>(null);\n\nwatch(\n [redaction, () => props.documentId, () => props.pageIndex],\n ([redactionValue, docId, pageIdx], _, onCleanup) => {\n if (!redactionValue) {\n items.value = [];\n selectedId.value = null;\n return;\n }\n\n const scoped = redactionValue.forDocument(docId);\n\n // Initialize with current state\n const currentState = scoped.getState();\n items.value = currentState.pending[pageIdx] ?? [];\n selectedId.value =\n currentState.selected && currentState.selected.page === pageIdx\n ? currentState.selected.id\n : null;\n\n // Subscribe to future changes\n const off1 = scoped.onPendingChange((map) => {\n items.value = map[pageIdx] ?? [];\n });\n\n const off2 = scoped.onSelectedChange((sel) => {\n selectedId.value = sel && sel.page === pageIdx ? sel.id : null;\n });\n\n onCleanup(() => {\n off1?.();\n off2?.();\n });\n },\n { immediate: true },\n);\n\nconst select = (e: PointerEvent | TouchEvent, id: string) => {\n e.stopPropagation();\n const redactionValue = redaction.value;\n if (!redactionValue) return;\n redactionValue.forDocument(props.documentId).selectPending(props.pageIndex, id);\n};\n\n// --- Selection Menu Logic ---\n\n// Check if we should show menu for this item\nconst shouldShowMenu = (itemId: string): boolean => {\n const isSelected = selectedId.value === itemId;\n return isSelected && (!!props.selectionMenu || !!slots['selection-menu']);\n};\n\n// Build context object for selection menu\nconst buildContext = (item: RedactionItem): RedactionSelectionContext => ({\n type: 'redaction',\n item,\n pageIndex: props.pageIndex,\n});\n\n// Placement hints (could be computed based on position)\nconst menuPlacement: SelectionMenuPlacement = {\n suggestTop: false,\n spaceAbove: 0,\n spaceBelow: 0,\n};\n\n// Render via function (for schema-driven approach)\nconst renderSelectionMenu = (\n item: RedactionItem,\n rect: Rect,\n menuWrapperProps: MenuWrapperProps,\n): VNode | null => {\n if (!props.selectionMenu) return null;\n\n return props.selectionMenu({\n rect,\n menuWrapperProps,\n selected: selectedId.value === item.id,\n placement: menuPlacement,\n context: buildContext(item),\n });\n};\n</script>\n","<template>\n <PendingRedactions\n :document-id=\"documentId\"\n :page-index=\"pageIndex\"\n :scale=\"actualScale\"\n :rotation=\"actualRotation\"\n :bbox-stroke=\"bboxStroke\"\n :selection-menu=\"selectionMenu\"\n >\n <template #selection-menu=\"slotProps\">\n <slot name=\"selection-menu\" v-bind=\"slotProps\" />\n </template>\n </PendingRedactions>\n <MarqueeRedact :document-id=\"documentId\" :page-index=\"pageIndex\" :scale=\"actualScale\" />\n <SelectionRedact :document-id=\"documentId\" :page-index=\"pageIndex\" :scale=\"actualScale\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { useDocumentState } from '@embedpdf/core/vue';\nimport { Rotation } from '@embedpdf/models';\nimport PendingRedactions from './pending-redactions.vue';\nimport MarqueeRedact from './marquee-redact.vue';\nimport SelectionRedact from './selection-redact.vue';\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 bbox stroke color */\n bboxStroke?: string;\n /** Optional menu renderer for a selected redaction */\n selectionMenu?: RedactionSelectionMenuRenderFn;\n}\n\nconst props = withDefaults(defineProps<RedactionLayerProps>(), {\n bboxStroke: 'rgba(0,0,0,0.8)',\n});\n\nconst documentState = useDocumentState(() => props.documentId);\n\nconst actualScale = computed(() => {\n if (props.scale !== undefined) return props.scale;\n return documentState.value?.scale ?? 1;\n});\n\nconst actualRotation = computed(() => {\n if (props.rotation !== undefined) return props.rotation;\n return documentState.value?.rotation ?? Rotation.Degree0;\n});\n</script>\n"],"names":["_openBlock","_createElementBlock","_Fragment","_renderList","_mergeProps","_unref","$attrs","_normalizeStyle","_hoisted_1","_createVNode","Highlight","_createElementVNode","_createBlock","_withCtx","_resolveDynamicComponent","_renderSlot","PendingRedactions","MarqueeRedact","SelectionRedact"],"mappings":"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"}