@embedpdf/plugin-annotation 2.5.0 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +1061 -430
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/annotation-plugin.d.ts +24 -6
  6. package/dist/lib/geometry/index.d.ts +1 -0
  7. package/dist/lib/geometry/rotation.d.ts +32 -0
  8. package/dist/lib/handlers/types.d.ts +3 -1
  9. package/dist/lib/index.d.ts +1 -0
  10. package/dist/lib/patching/base-patch.d.ts +87 -0
  11. package/dist/lib/patching/index.d.ts +1 -0
  12. package/dist/lib/patching/insert-upright.d.ts +20 -0
  13. package/dist/lib/patching/patch-registry.d.ts +14 -1
  14. package/dist/lib/patching/patch-utils.d.ts +54 -1
  15. package/dist/lib/patching/patches/circle.patch.d.ts +3 -0
  16. package/dist/lib/patching/patches/freetext.patch.d.ts +3 -0
  17. package/dist/lib/patching/patches/index.d.ts +4 -0
  18. package/dist/lib/patching/patches/square.patch.d.ts +3 -0
  19. package/dist/lib/patching/patches/stamp.patch.d.ts +3 -0
  20. package/dist/lib/tools/default-tools.d.ts +32 -0
  21. package/dist/lib/tools/types.d.ts +20 -1
  22. package/dist/lib/types.d.ts +67 -3
  23. package/dist/preact/adapter.d.ts +3 -0
  24. package/dist/preact/index.cjs +1 -1
  25. package/dist/preact/index.cjs.map +1 -1
  26. package/dist/preact/index.js +793 -126
  27. package/dist/preact/index.js.map +1 -1
  28. package/dist/react/adapter.d.ts +2 -1
  29. package/dist/react/index.cjs +1 -1
  30. package/dist/react/index.cjs.map +1 -1
  31. package/dist/react/index.js +793 -126
  32. package/dist/react/index.js.map +1 -1
  33. package/dist/shared/components/annotation-container.d.ts +10 -2
  34. package/dist/shared/components/annotation-layer.d.ts +9 -3
  35. package/dist/shared/components/annotations.d.ts +4 -1
  36. package/dist/shared/components/group-selection-box.d.ts +12 -4
  37. package/dist/shared/components/render-annotation.d.ts +2 -1
  38. package/dist/shared/components/types.d.ts +51 -1
  39. package/dist/shared-preact/components/annotation-container.d.ts +10 -2
  40. package/dist/shared-preact/components/annotation-layer.d.ts +9 -3
  41. package/dist/shared-preact/components/annotations.d.ts +4 -1
  42. package/dist/shared-preact/components/group-selection-box.d.ts +12 -4
  43. package/dist/shared-preact/components/render-annotation.d.ts +2 -1
  44. package/dist/shared-preact/components/types.d.ts +51 -1
  45. package/dist/shared-react/components/annotation-container.d.ts +10 -2
  46. package/dist/shared-react/components/annotation-layer.d.ts +9 -3
  47. package/dist/shared-react/components/annotations.d.ts +4 -1
  48. package/dist/shared-react/components/group-selection-box.d.ts +12 -4
  49. package/dist/shared-react/components/render-annotation.d.ts +2 -1
  50. package/dist/shared-react/components/types.d.ts +51 -1
  51. package/dist/svelte/components/AnnotationLayer.svelte.d.ts +8 -2
  52. package/dist/svelte/components/Annotations.svelte.d.ts +7 -1
  53. package/dist/svelte/components/GroupSelectionBox.svelte.d.ts +11 -3
  54. package/dist/svelte/components/RenderAnnotation.svelte.d.ts +1 -0
  55. package/dist/svelte/components/types.d.ts +14 -1
  56. package/dist/svelte/index.cjs +1 -1
  57. package/dist/svelte/index.cjs.map +1 -1
  58. package/dist/svelte/index.js +1166 -330
  59. package/dist/svelte/index.js.map +1 -1
  60. package/dist/svelte/types.d.ts +53 -0
  61. package/dist/vue/components/annotation-container.vue.d.ts +35 -9
  62. package/dist/vue/components/annotation-layer.vue.d.ts +29 -5
  63. package/dist/vue/components/annotations.vue.d.ts +278 -134
  64. package/dist/vue/components/group-selection-box.vue.d.ts +35 -10
  65. package/dist/vue/components/render-annotation.vue.d.ts +2 -0
  66. package/dist/vue/index.cjs +1 -1
  67. package/dist/vue/index.cjs.map +1 -1
  68. package/dist/vue/index.js +945 -161
  69. package/dist/vue/index.js.map +1 -1
  70. package/dist/vue/types.d.ts +52 -0
  71. package/package.json +11 -10
package/dist/vue/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { createPluginPackage } from "@embedpdf/core";
2
- import { AnnotationPlugin, initialDocumentState, patching, getAnnotationsByPageIndex, getSelectedAnnotationIds, resolveInteractionProp, isInk, isSquare, isCircle, isLine, isPolyline, isPolygon, isFreeText, isStamp, isUnderline, isStrikeout, isSquiggly, isHighlight, isLink, AnnotationPluginPackage as AnnotationPluginPackage$1 } from "@embedpdf/plugin-annotation";
2
+ import { AnnotationPlugin, initialDocumentState, inferRotationCenterFromRects, patching, getAnnotationsByPageIndex, getSelectedAnnotationIds, resolveInteractionProp, isInk, isSquare, isCircle, isLine, isPolyline, isPolygon, isFreeText, isStamp, isUnderline, isStrikeout, isSquiggly, isHighlight, isLink, AnnotationPluginPackage as AnnotationPluginPackage$1 } from "@embedpdf/plugin-annotation";
3
3
  export * from "@embedpdf/plugin-annotation";
4
- import { ref, toValue, watch, computed, defineComponent, shallowRef, toRaw, useSlots, watchEffect, createElementBlock, openBlock, createElementVNode, createBlock, createCommentVNode, mergeProps, unref, renderSlot, Fragment, renderList, withCtx, resolveDynamicComponent, normalizeStyle, onMounted, toDisplayString, onUnmounted, createVNode, createSlots, normalizeProps, guardReactiveProps, provide, inject, markRaw } from "vue";
4
+ import { ref, toValue, watch, computed, defineComponent, shallowRef, toRaw, watchEffect, useSlots, openBlock, createElementBlock, createElementVNode, normalizeStyle, Fragment, createCommentVNode, unref, renderSlot, normalizeProps, mergeProps, renderList, createBlock, withCtx, resolveDynamicComponent, Teleport, toDisplayString, onMounted, onUnmounted, createVNode, createSlots, guardReactiveProps, provide, inject, markRaw } from "vue";
5
5
  import { useInteractionHandles, useDoublePressProps, CounterRotate, deepToRaw } from "@embedpdf/utils/vue";
6
6
  import { usePlugin, useCapability, useDocumentPermissions, useDocumentState } from "@embedpdf/core/vue";
7
- import { boundingRectOrEmpty, PdfAnnotationBorderStyle, textAlignmentToCss, standardFontCss, PdfVerticalAlignment, ignore, PdfErrorCode, blendModeToCss, PdfBlendMode, PdfAnnotationSubtype } from "@embedpdf/models";
7
+ import { boundingRectOrEmpty, PdfAnnotationBorderStyle, PdfVerticalAlignment, textAlignmentToCss, standardFontCssProperties, ignore, PdfErrorCode, PdfBlendMode, blendModeToCss, PdfAnnotationSubtype } from "@embedpdf/models";
8
8
  import { usePointerHandlers } from "@embedpdf/plugin-interaction-manager/vue";
9
9
  import { useSelectionCapability } from "@embedpdf/plugin-selection/vue";
10
10
  const useAnnotationPlugin = () => usePlugin(AnnotationPlugin.id);
@@ -37,10 +37,8 @@ const useAnnotation = (documentId) => {
37
37
  })
38
38
  };
39
39
  };
40
- const _hoisted_1$a = {
41
- "data-no-interaction": "",
42
- style: { display: "contents" }
43
- };
40
+ const _hoisted_1$a = ["width", "height", "stroke"];
41
+ const _hoisted_2$8 = ["width", "height", "stroke"];
44
42
  const __default__ = {
45
43
  inheritAttrs: false
46
44
  };
@@ -59,6 +57,7 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
59
57
  isMultiSelected: { type: Boolean, default: false },
60
58
  isDraggable: { type: Boolean },
61
59
  isResizable: { type: Boolean },
60
+ isRotatable: { type: Boolean, default: true },
62
61
  lockAspectRatio: { type: Boolean, default: false },
63
62
  vertexConfig: {},
64
63
  selectionMenu: {},
@@ -67,15 +66,88 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
67
66
  onSelect: {},
68
67
  zIndex: { default: 1 },
69
68
  selectionOutlineColor: { default: "#007ACC" },
69
+ selectionOutline: {},
70
+ resizeUi: {},
71
+ vertexUi: {},
72
+ rotationUi: {},
70
73
  style: {}
71
74
  },
72
75
  setup(__props) {
73
76
  const props = __props;
74
- const HANDLE_COLOR = "#007ACC";
75
- const VERTEX_COLOR = "#007ACC";
76
- const HANDLE_SIZE = 12;
77
- const VERTEX_SIZE = 12;
77
+ const HANDLE_COLOR = computed(() => {
78
+ var _a;
79
+ return ((_a = props.resizeUi) == null ? void 0 : _a.color) ?? "#007ACC";
80
+ });
81
+ const VERTEX_COLOR = computed(() => {
82
+ var _a;
83
+ return ((_a = props.vertexUi) == null ? void 0 : _a.color) ?? "#007ACC";
84
+ });
85
+ const HANDLE_SIZE = computed(() => {
86
+ var _a;
87
+ return ((_a = props.resizeUi) == null ? void 0 : _a.size) ?? 12;
88
+ });
89
+ const VERTEX_SIZE = computed(() => {
90
+ var _a;
91
+ return ((_a = props.vertexUi) == null ? void 0 : _a.size) ?? 12;
92
+ });
93
+ const ROTATION_SIZE = computed(() => {
94
+ var _a;
95
+ return ((_a = props.rotationUi) == null ? void 0 : _a.size) ?? 32;
96
+ });
97
+ const ROTATION_COLOR = computed(() => {
98
+ var _a;
99
+ return ((_a = props.rotationUi) == null ? void 0 : _a.color) ?? "white";
100
+ });
101
+ const ROTATION_CONNECTOR_COLOR = computed(() => {
102
+ var _a;
103
+ return ((_a = props.rotationUi) == null ? void 0 : _a.connectorColor) ?? "#007ACC";
104
+ });
105
+ const ROTATION_ICON_COLOR = computed(() => {
106
+ var _a;
107
+ return ((_a = props.rotationUi) == null ? void 0 : _a.iconColor) ?? "#007ACC";
108
+ });
109
+ const SHOW_CONNECTOR = computed(() => {
110
+ var _a;
111
+ return ((_a = props.rotationUi) == null ? void 0 : _a.showConnector) ?? false;
112
+ });
113
+ const ROTATION_MARGIN = computed(() => {
114
+ var _a;
115
+ return (_a = props.rotationUi) == null ? void 0 : _a.margin;
116
+ });
117
+ const ROTATION_BORDER_COLOR = computed(() => {
118
+ var _a, _b;
119
+ return ((_b = (_a = props.rotationUi) == null ? void 0 : _a.border) == null ? void 0 : _b.color) ?? "#007ACC";
120
+ });
121
+ const ROTATION_BORDER_WIDTH = computed(() => {
122
+ var _a, _b;
123
+ return ((_b = (_a = props.rotationUi) == null ? void 0 : _a.border) == null ? void 0 : _b.width) ?? 1;
124
+ });
125
+ const ROTATION_BORDER_STYLE = computed(() => {
126
+ var _a, _b;
127
+ return ((_b = (_a = props.rotationUi) == null ? void 0 : _a.border) == null ? void 0 : _b.style) ?? "solid";
128
+ });
129
+ const outlineColor = computed(
130
+ () => {
131
+ var _a;
132
+ return ((_a = props.selectionOutline) == null ? void 0 : _a.color) ?? props.selectionOutlineColor ?? "#007ACC";
133
+ }
134
+ );
135
+ const outlineStyle = computed(() => {
136
+ var _a;
137
+ return ((_a = props.selectionOutline) == null ? void 0 : _a.style) ?? "solid";
138
+ });
139
+ const outlineWidth = computed(() => {
140
+ var _a;
141
+ return ((_a = props.selectionOutline) == null ? void 0 : _a.width) ?? 1;
142
+ });
143
+ const outlineOff = computed(() => {
144
+ var _a;
145
+ return ((_a = props.selectionOutline) == null ? void 0 : _a.offset) ?? props.outlineOffset ?? 1;
146
+ });
78
147
  const preview = shallowRef(toRaw(props.trackedAnnotation.object));
148
+ const liveRotation = ref(null);
149
+ const cursorScreen = ref(null);
150
+ const isHandleHovered = ref(false);
79
151
  const { provides: annotationCapability } = useAnnotationCapability();
80
152
  const { plugin: annotationPlugin } = useAnnotationPlugin();
81
153
  const permissions = useDocumentPermissions(props.documentId);
@@ -87,6 +159,9 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
87
159
  const effectiveIsResizable = computed(
88
160
  () => permissions.value.canModifyAnnotations && props.isResizable && !props.isMultiSelected
89
161
  );
162
+ const effectiveIsRotatable = computed(
163
+ () => permissions.value.canModifyAnnotations && props.isRotatable && !props.isMultiSelected
164
+ );
90
165
  const guardedOnDoubleClick = props.onDoubleClick ? (e) => {
91
166
  var _a;
92
167
  if (permissions.value.canModifyAnnotations) {
@@ -99,6 +174,40 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
99
174
  const currentObject = computed(
100
175
  () => ({ ...toRaw(props.trackedAnnotation.object), ...toRaw(preview.value) })
101
176
  );
177
+ const annotationRotation = computed(
178
+ () => liveRotation.value ?? currentObject.value.rotation ?? 0
179
+ );
180
+ const rotationDisplay = computed(
181
+ () => liveRotation.value ?? currentObject.value.rotation ?? 0
182
+ );
183
+ const normalizedRotationDisplay = computed(() => {
184
+ const val = rotationDisplay.value;
185
+ return Number.isFinite(val) ? Math.round(val * 10) / 10 : 0;
186
+ });
187
+ const rotationActive = computed(() => liveRotation.value !== null);
188
+ const explicitUnrotatedRect = computed(
189
+ () => currentObject.value.unrotatedRect
190
+ );
191
+ const effectiveUnrotatedRect = computed(
192
+ () => explicitUnrotatedRect.value ?? currentObject.value.rect
193
+ );
194
+ const rotationPivot = computed(() => {
195
+ if (explicitUnrotatedRect.value && annotationRotation.value !== 0) {
196
+ return inferRotationCenterFromRects(
197
+ effectiveUnrotatedRect.value,
198
+ currentObject.value.rect,
199
+ annotationRotation.value
200
+ );
201
+ }
202
+ return void 0;
203
+ });
204
+ const controllerElement = computed(() => effectiveUnrotatedRect.value);
205
+ const childObject = computed(() => {
206
+ if (explicitUnrotatedRect.value) {
207
+ return { ...currentObject.value, rect: explicitUnrotatedRect.value };
208
+ }
209
+ return currentObject.value;
210
+ });
102
211
  const showOutline = computed(() => props.isSelected && !props.isMultiSelected);
103
212
  const shouldShowMenu = computed(() => {
104
213
  return props.isSelected && !props.isMultiSelected && (props.selectionMenu || slots["selection-menu"]);
@@ -118,12 +227,13 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
118
227
  annotation: props.trackedAnnotation,
119
228
  pageIndex: props.pageIndex
120
229
  }));
121
- const menuPlacement = computed(() => ({
122
- suggestTop: false,
123
- // Could calculate based on position in viewport
124
- spaceAbove: 0,
125
- spaceBelow: 0
126
- }));
230
+ const menuPlacement = computed(() => {
231
+ const effectiveAngle = ((annotationRotation.value + props.rotation * 90) % 360 + 360) % 360;
232
+ const handleNearMenuSide = effectiveIsRotatable.value && effectiveAngle > 90 && effectiveAngle < 270;
233
+ return {
234
+ suggestTop: handleNearMenuSide
235
+ };
236
+ });
127
237
  const renderSelectionMenu = (rect, menuWrapperProps) => {
128
238
  if (!props.selectionMenu) return null;
129
239
  return props.selectionMenu({
@@ -134,10 +244,6 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
134
244
  context: menuContext.value
135
245
  });
136
246
  };
137
- const elementSnapshot = computed(() => {
138
- const obj = toRaw(currentObject.value);
139
- return obj.rect;
140
- });
141
247
  const verticesSnapshot = computed(() => {
142
248
  var _a;
143
249
  const obj = toRaw(currentObject.value);
@@ -151,13 +257,21 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
151
257
  height: props.pageHeight
152
258
  }
153
259
  }));
154
- const { dragProps, vertices, resize } = useInteractionHandles({
260
+ const {
261
+ dragProps,
262
+ vertices,
263
+ resize,
264
+ rotation: rotationHandleData
265
+ } = useInteractionHandles({
155
266
  controller: {
156
- element: elementSnapshot,
267
+ element: controllerElement,
157
268
  vertices: verticesSnapshot,
158
269
  constraints: constraintsSnapshot,
159
270
  maintainAspectRatio: computed(() => props.lockAspectRatio),
160
271
  pageRotation: computed(() => props.rotation),
272
+ annotationRotation: computed(() => annotationRotation.value),
273
+ rotationCenter: computed(() => rotationPivot.value),
274
+ rotationElement: computed(() => currentObject.value.rect),
161
275
  scale: computed(() => props.scale),
162
276
  // Disable interaction handles when multi-selected
163
277
  enabled: computed(() => props.isSelected && !props.isMultiSelected),
@@ -170,7 +284,7 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
170
284
  const id = props.trackedAnnotation.object.id;
171
285
  const pageSize = { width: props.pageWidth, height: props.pageHeight };
172
286
  if (event.state === "start") {
173
- gestureBaseRectRef.value = props.trackedAnnotation.object.rect;
287
+ gestureBaseRectRef.value = props.trackedAnnotation.object.unrotatedRect ?? props.trackedAnnotation.object.rect;
174
288
  gestureBaseRef.value = currentObject.value;
175
289
  if (type === "move") {
176
290
  plugin.startDrag(props.documentId, { annotationIds: [id], pageSize });
@@ -208,6 +322,27 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
208
322
  }
209
323
  }
210
324
  }
325
+ if (type === "rotate") {
326
+ const cursorAngle = (metadata == null ? void 0 : metadata.rotationAngle) ?? annotationRotation.value;
327
+ const cursorPos = metadata == null ? void 0 : metadata.cursorPosition;
328
+ if (cursorPos) cursorScreen.value = { x: cursorPos.clientX, y: cursorPos.clientY };
329
+ if (event.state === "start") {
330
+ liveRotation.value = cursorAngle;
331
+ plugin.startRotation(props.documentId, {
332
+ annotationIds: [id],
333
+ cursorAngle,
334
+ rotationCenter: metadata == null ? void 0 : metadata.rotationCenter
335
+ });
336
+ } else if (event.state === "move") {
337
+ liveRotation.value = cursorAngle;
338
+ plugin.updateRotation(props.documentId, cursorAngle, metadata == null ? void 0 : metadata.rotationDelta);
339
+ } else if (event.state === "end") {
340
+ liveRotation.value = null;
341
+ cursorScreen.value = null;
342
+ plugin.commitRotation(props.documentId);
343
+ }
344
+ return;
345
+ }
211
346
  if (event.state === "end") {
212
347
  gestureBaseRectRef.value = null;
213
348
  gestureBaseRef.value = null;
@@ -217,19 +352,32 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
217
352
  }
218
353
  },
219
354
  resizeUI: {
220
- handleSize: HANDLE_SIZE,
221
- spacing: props.outlineOffset,
355
+ handleSize: HANDLE_SIZE.value,
356
+ spacing: outlineOff.value,
222
357
  offsetMode: "outside",
223
- includeSides: !props.lockAspectRatio,
358
+ includeSides: props.lockAspectRatio ? false : true,
224
359
  zIndex: props.zIndex + 1
225
360
  },
226
361
  vertexUI: {
227
- vertexSize: VERTEX_SIZE,
362
+ vertexSize: VERTEX_SIZE.value,
228
363
  zIndex: props.zIndex + 2
229
364
  },
230
- includeVertices: !!props.vertexConfig
365
+ rotationUI: {
366
+ handleSize: ROTATION_SIZE.value,
367
+ margin: ROTATION_MARGIN.value,
368
+ zIndex: props.zIndex + 3,
369
+ showConnector: SHOW_CONNECTOR.value
370
+ },
371
+ includeVertices: !!props.vertexConfig,
372
+ includeRotation: effectiveIsRotatable,
373
+ currentRotation: annotationRotation
231
374
  });
232
375
  const doubleProps = useDoublePressProps(guardedOnDoubleClick);
376
+ const onHandlePointerMove = (e) => {
377
+ if (!rotationActive.value) {
378
+ cursorScreen.value = { x: e.clientX, y: e.clientY };
379
+ }
380
+ };
233
381
  watchEffect(() => {
234
382
  if (props.trackedAnnotation.object) {
235
383
  preview.value = props.trackedAnnotation.object;
@@ -242,6 +390,9 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
242
390
  const handleEvent = (event) => {
243
391
  var _a;
244
392
  if (event.documentId !== props.documentId) return;
393
+ if (event.type === "end" || event.type === "cancel") {
394
+ liveRotation.value = null;
395
+ }
245
396
  const patch = (_a = event.previewPatches) == null ? void 0 : _a[id];
246
397
  if (event.type === "update" && patch) {
247
398
  preview.value = { ...toRaw(preview.value), ...patch };
@@ -249,67 +400,259 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
249
400
  preview.value = props.trackedAnnotation.object;
250
401
  }
251
402
  };
252
- const unsubs = [plugin.onDragChange(handleEvent), plugin.onResizeChange(handleEvent)];
403
+ const unsubs = [
404
+ plugin.onDragChange(handleEvent),
405
+ plugin.onResizeChange(handleEvent),
406
+ plugin.onRotateChange(handleEvent)
407
+ ];
253
408
  onCleanup(() => unsubs.forEach((u) => u()));
254
409
  });
255
- const containerStyle = computed(() => ({
410
+ const aabbWidth = computed(() => currentObject.value.rect.size.width * props.scale);
411
+ const aabbHeight = computed(() => currentObject.value.rect.size.height * props.scale);
412
+ const innerWidth = computed(() => effectiveUnrotatedRect.value.size.width * props.scale);
413
+ const innerHeight = computed(() => effectiveUnrotatedRect.value.size.height * props.scale);
414
+ const usesCustomPivot = computed(
415
+ () => Boolean(explicitUnrotatedRect.value) && annotationRotation.value !== 0
416
+ );
417
+ const innerLeft = computed(
418
+ () => usesCustomPivot.value ? (effectiveUnrotatedRect.value.origin.x - currentObject.value.rect.origin.x) * props.scale : (aabbWidth.value - innerWidth.value) / 2
419
+ );
420
+ const innerTop = computed(
421
+ () => usesCustomPivot.value ? (effectiveUnrotatedRect.value.origin.y - currentObject.value.rect.origin.y) * props.scale : (aabbHeight.value - innerHeight.value) / 2
422
+ );
423
+ const innerTransformOrigin = computed(() => {
424
+ if (usesCustomPivot.value && rotationPivot.value) {
425
+ return `${(rotationPivot.value.x - effectiveUnrotatedRect.value.origin.x) * props.scale}px ${(rotationPivot.value.y - effectiveUnrotatedRect.value.origin.y) * props.scale}px`;
426
+ }
427
+ return "center center";
428
+ });
429
+ const centerX = computed(
430
+ () => rotationPivot.value ? (rotationPivot.value.x - currentObject.value.rect.origin.x) * props.scale : aabbWidth.value / 2
431
+ );
432
+ const centerY = computed(
433
+ () => rotationPivot.value ? (rotationPivot.value.y - currentObject.value.rect.origin.y) * props.scale : aabbHeight.value / 2
434
+ );
435
+ const guideLength = computed(() => Math.max(300, Math.max(aabbWidth.value, aabbHeight.value) + 80));
436
+ const rotationIconSize = computed(() => Math.round(ROTATION_SIZE.value * 0.6));
437
+ const contentsStyle = { display: "contents" };
438
+ const outerAABBStyle = computed(() => ({
256
439
  position: "absolute",
257
440
  left: `${currentObject.value.rect.origin.x * props.scale}px`,
258
441
  top: `${currentObject.value.rect.origin.y * props.scale}px`,
259
- width: `${currentObject.value.rect.size.width * props.scale}px`,
260
- height: `${currentObject.value.rect.size.height * props.scale}px`,
261
- outline: showOutline.value ? `1px solid ${props.selectionOutlineColor}` : "none",
262
- outlineOffset: showOutline.value ? `${props.outlineOffset}px` : "0px",
442
+ width: `${aabbWidth.value}px`,
443
+ height: `${aabbHeight.value}px`,
444
+ pointerEvents: "none",
445
+ zIndex: props.zIndex,
446
+ ...props.style ?? {}
447
+ }));
448
+ const innerRotatedStyle = computed(() => ({
449
+ position: "absolute",
450
+ left: `${innerLeft.value}px`,
451
+ top: `${innerTop.value}px`,
452
+ width: `${innerWidth.value}px`,
453
+ height: `${innerHeight.value}px`,
454
+ transform: annotationRotation.value !== 0 ? `rotate(${annotationRotation.value}deg)` : void 0,
455
+ transformOrigin: innerTransformOrigin.value,
456
+ outline: showOutline.value ? `${outlineWidth.value}px ${outlineStyle.value} ${outlineColor.value}` : "none",
457
+ outlineOffset: showOutline.value ? `${outlineOff.value}px` : "0px",
263
458
  pointerEvents: props.isSelected && !props.isMultiSelected ? "auto" : "none",
264
459
  touchAction: "none",
265
- cursor: props.isSelected && effectiveIsDraggable.value ? "move" : "default",
266
- zIndex: props.zIndex
460
+ cursor: props.isSelected && effectiveIsDraggable.value ? "move" : "default"
267
461
  }));
268
- const mergedContainerStyle = computed(() => ({
269
- ...containerStyle.value,
270
- ...props.style ?? {}
462
+ const guideHorizontalStyle = computed(() => ({
463
+ position: "absolute",
464
+ left: `${centerX.value - guideLength.value / 2}px`,
465
+ top: `${centerY.value}px`,
466
+ width: `${guideLength.value}px`,
467
+ height: "1px",
468
+ backgroundColor: ROTATION_CONNECTOR_COLOR.value,
469
+ opacity: 0.35,
470
+ pointerEvents: "none"
471
+ }));
472
+ const guideVerticalStyle = computed(() => ({
473
+ position: "absolute",
474
+ left: `${centerX.value}px`,
475
+ top: `${centerY.value - guideLength.value / 2}px`,
476
+ width: "1px",
477
+ height: `${guideLength.value}px`,
478
+ backgroundColor: ROTATION_CONNECTOR_COLOR.value,
479
+ opacity: 0.35,
480
+ pointerEvents: "none"
481
+ }));
482
+ const guideAngleStyle = computed(() => ({
483
+ position: "absolute",
484
+ left: `${centerX.value - guideLength.value / 2}px`,
485
+ top: `${centerY.value}px`,
486
+ width: `${guideLength.value}px`,
487
+ height: "1px",
488
+ transformOrigin: "center center",
489
+ transform: `rotate(${annotationRotation.value}deg)`,
490
+ backgroundColor: ROTATION_CONNECTOR_COLOR.value,
491
+ opacity: 0.8,
492
+ pointerEvents: "none"
493
+ }));
494
+ const connectorLineStyle = computed(() => {
495
+ var _a;
496
+ return {
497
+ ...((_a = rotationHandleData.value) == null ? void 0 : _a.connector.style) ?? {},
498
+ backgroundColor: ROTATION_CONNECTOR_COLOR.value,
499
+ opacity: rotationActive.value ? 0 : 1
500
+ };
501
+ });
502
+ const rotationHandleStyle = computed(() => {
503
+ var _a;
504
+ return {
505
+ ...((_a = rotationHandleData.value) == null ? void 0 : _a.handle.style) ?? {},
506
+ backgroundColor: ROTATION_COLOR.value,
507
+ border: `${ROTATION_BORDER_WIDTH.value}px ${ROTATION_BORDER_STYLE.value} ${ROTATION_BORDER_COLOR.value}`,
508
+ boxSizing: "border-box",
509
+ display: "flex",
510
+ alignItems: "center",
511
+ justifyContent: "center",
512
+ pointerEvents: "auto",
513
+ opacity: rotationActive.value ? 0 : 1
514
+ };
515
+ });
516
+ const rotationHandleBindings = computed(() => {
517
+ if (!rotationHandleData.value) return {};
518
+ const { style: _s, ...rest } = rotationHandleData.value.handle;
519
+ return rest;
520
+ });
521
+ const rotationHandleSlotProps = computed(() => {
522
+ if (!rotationHandleData.value) return {};
523
+ return {
524
+ ...rotationHandleData.value.handle,
525
+ backgroundColor: ROTATION_COLOR.value,
526
+ iconColor: ROTATION_ICON_COLOR.value,
527
+ connectorStyle: connectorLineStyle.value,
528
+ showConnector: SHOW_CONNECTOR.value,
529
+ opacity: rotationActive.value ? 0 : 1,
530
+ border: {
531
+ color: ROTATION_BORDER_COLOR.value,
532
+ width: ROTATION_BORDER_WIDTH.value,
533
+ style: ROTATION_BORDER_STYLE.value
534
+ }
535
+ };
536
+ });
537
+ const tooltipStyle = computed(() => ({
538
+ position: "fixed",
539
+ left: cursorScreen.value ? `${cursorScreen.value.x + 16}px` : "0",
540
+ top: cursorScreen.value ? `${cursorScreen.value.y - 16}px` : "0",
541
+ background: "rgba(0,0,0,0.8)",
542
+ color: "#fff",
543
+ padding: "4px 8px",
544
+ borderRadius: "4px",
545
+ fontSize: "12px",
546
+ fontFamily: "monospace",
547
+ pointerEvents: "none",
548
+ zIndex: 1e4,
549
+ whiteSpace: "nowrap"
271
550
  }));
272
551
  const slots = useSlots();
273
552
  return (_ctx, _cache) => {
274
- return openBlock(), createElementBlock("div", _hoisted_1$a, [
275
- createElementVNode("div", mergeProps({ ...effectiveIsDraggable.value && __props.isSelected ? unref(dragProps) : {}, ...unref(doubleProps) }, { style: mergedContainerStyle.value }), [
276
- renderSlot(_ctx.$slots, "default", { annotation: currentObject.value }),
277
- __props.isSelected && effectiveIsResizable.value ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(unref(resize), ({ key, style, ...handle }) => {
278
- return openBlock(), createElementBlock(Fragment, { key }, [
279
- unref(slots)["resize-handle"] ? renderSlot(_ctx.$slots, "resize-handle", mergeProps({
280
- key: 0,
281
- ref_for: true
282
- }, { key, style, ...handle, backgroundColor: HANDLE_COLOR }), () => [
283
- createElementVNode("div", mergeProps({ ref_for: true }, handle, {
284
- style: [style, { backgroundColor: HANDLE_COLOR }]
285
- }), null, 16)
286
- ]) : (openBlock(), createElementBlock("div", mergeProps({
287
- key: 1,
288
- ref_for: true
289
- }, handle, {
290
- style: [style, { backgroundColor: HANDLE_COLOR }]
291
- }), null, 16))
292
- ], 64);
293
- }), 128)) : createCommentVNode("", true),
294
- __props.isSelected && unref(permissions).canModifyAnnotations && !__props.isMultiSelected && unref(vertices).length > 0 ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(unref(vertices), ({ key, style, ...vertex }) => {
295
- return openBlock(), createElementBlock(Fragment, { key }, [
296
- unref(slots)["vertex-handle"] ? renderSlot(_ctx.$slots, "vertex-handle", mergeProps({
297
- key: 0,
298
- ref_for: true
299
- }, { key, style, ...vertex, backgroundColor: VERTEX_COLOR }), () => [
300
- createElementVNode("div", mergeProps({ ref_for: true }, vertex, {
301
- style: [style, { backgroundColor: VERTEX_COLOR }]
302
- }), null, 16)
303
- ]) : (openBlock(), createElementBlock("div", mergeProps({
304
- key: 1,
305
- ref_for: true
306
- }, vertex, {
307
- style: [style, { backgroundColor: VERTEX_COLOR }]
308
- }), null, 16))
309
- ], 64);
310
- }), 128)) : createCommentVNode("", true)
311
- ], 16),
312
- shouldShowMenu.value ? (openBlock(), createBlock(unref(CounterRotate), {
553
+ return openBlock(), createElementBlock("div", {
554
+ "data-no-interaction": "",
555
+ style: contentsStyle
556
+ }, [
557
+ createElementVNode("div", {
558
+ style: normalizeStyle(outerAABBStyle.value)
559
+ }, [
560
+ rotationActive.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
561
+ createElementVNode("div", {
562
+ style: normalizeStyle(guideHorizontalStyle.value)
563
+ }, null, 4),
564
+ createElementVNode("div", {
565
+ style: normalizeStyle(guideVerticalStyle.value)
566
+ }, null, 4),
567
+ createElementVNode("div", {
568
+ style: normalizeStyle(guideAngleStyle.value)
569
+ }, null, 4)
570
+ ], 64)) : createCommentVNode("", true),
571
+ __props.isSelected && effectiveIsRotatable.value && unref(rotationHandleData) ? (openBlock(), createElementBlock("div", {
572
+ key: 1,
573
+ onPointerenter: _cache[0] || (_cache[0] = ($event) => isHandleHovered.value = true),
574
+ onPointerleave: _cache[1] || (_cache[1] = ($event) => {
575
+ isHandleHovered.value = false;
576
+ cursorScreen.value = null;
577
+ }),
578
+ onPointermove: onHandlePointerMove,
579
+ style: contentsStyle
580
+ }, [
581
+ SHOW_CONNECTOR.value ? (openBlock(), createElementBlock("div", {
582
+ key: 0,
583
+ style: normalizeStyle(connectorLineStyle.value)
584
+ }, null, 4)) : createCommentVNode("", true),
585
+ unref(slots)["rotation-handle"] ? renderSlot(_ctx.$slots, "rotation-handle", normalizeProps(mergeProps({ key: 1 }, rotationHandleSlotProps.value)), () => [
586
+ createElementVNode("div", mergeProps(rotationHandleBindings.value, { style: rotationHandleStyle.value }), [
587
+ (openBlock(), createElementBlock("svg", {
588
+ width: rotationIconSize.value,
589
+ height: rotationIconSize.value,
590
+ viewBox: "0 0 24 24",
591
+ fill: "none",
592
+ stroke: ROTATION_ICON_COLOR.value,
593
+ "stroke-width": "2",
594
+ "stroke-linecap": "round",
595
+ "stroke-linejoin": "round"
596
+ }, [..._cache[2] || (_cache[2] = [
597
+ createElementVNode("path", { d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8" }, null, -1),
598
+ createElementVNode("path", { d: "M21 3v5h-5" }, null, -1)
599
+ ])], 8, _hoisted_1$a))
600
+ ], 16)
601
+ ]) : (openBlock(), createElementBlock("div", mergeProps({ key: 2 }, rotationHandleBindings.value, { style: rotationHandleStyle.value }), [
602
+ (openBlock(), createElementBlock("svg", {
603
+ width: rotationIconSize.value,
604
+ height: rotationIconSize.value,
605
+ viewBox: "0 0 24 24",
606
+ fill: "none",
607
+ stroke: ROTATION_ICON_COLOR.value,
608
+ "stroke-width": "2",
609
+ "stroke-linecap": "round",
610
+ "stroke-linejoin": "round"
611
+ }, [..._cache[3] || (_cache[3] = [
612
+ createElementVNode("path", { d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8" }, null, -1),
613
+ createElementVNode("path", { d: "M21 3v5h-5" }, null, -1)
614
+ ])], 8, _hoisted_2$8))
615
+ ], 16))
616
+ ], 32)) : createCommentVNode("", true),
617
+ createElementVNode("div", mergeProps({ ...effectiveIsDraggable.value && __props.isSelected ? unref(dragProps) : {}, ...unref(doubleProps) }, { style: innerRotatedStyle.value }), [
618
+ renderSlot(_ctx.$slots, "default", { annotation: childObject.value }),
619
+ __props.isSelected && effectiveIsResizable.value && !rotationActive.value ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(unref(resize), ({ key, style, ...handle }) => {
620
+ return openBlock(), createElementBlock(Fragment, { key }, [
621
+ unref(slots)["resize-handle"] ? renderSlot(_ctx.$slots, "resize-handle", mergeProps({
622
+ key: 0,
623
+ ref_for: true
624
+ }, { key, style, ...handle, backgroundColor: HANDLE_COLOR.value }), () => [
625
+ createElementVNode("div", mergeProps({ ref_for: true }, handle, {
626
+ style: [style, { backgroundColor: HANDLE_COLOR.value }]
627
+ }), null, 16)
628
+ ]) : (openBlock(), createElementBlock("div", mergeProps({
629
+ key: 1,
630
+ ref_for: true
631
+ }, handle, {
632
+ style: [style, { backgroundColor: HANDLE_COLOR.value }]
633
+ }), null, 16))
634
+ ], 64);
635
+ }), 128)) : createCommentVNode("", true),
636
+ __props.isSelected && unref(permissions).canModifyAnnotations && !__props.isMultiSelected && !rotationActive.value && unref(vertices).length > 0 ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(unref(vertices), ({ key, style, ...vertex }) => {
637
+ return openBlock(), createElementBlock(Fragment, { key }, [
638
+ unref(slots)["vertex-handle"] ? renderSlot(_ctx.$slots, "vertex-handle", mergeProps({
639
+ key: 0,
640
+ ref_for: true
641
+ }, { key, style, ...vertex, backgroundColor: VERTEX_COLOR.value }), () => [
642
+ createElementVNode("div", mergeProps({ ref_for: true }, vertex, {
643
+ style: [style, { backgroundColor: VERTEX_COLOR.value }]
644
+ }), null, 16)
645
+ ]) : (openBlock(), createElementBlock("div", mergeProps({
646
+ key: 1,
647
+ ref_for: true
648
+ }, vertex, {
649
+ style: [style, { backgroundColor: VERTEX_COLOR.value }]
650
+ }), null, 16))
651
+ ], 64);
652
+ }), 128)) : createCommentVNode("", true)
653
+ ], 16)
654
+ ], 4),
655
+ shouldShowMenu.value && !rotationActive.value ? (openBlock(), createBlock(unref(CounterRotate), {
313
656
  key: 0,
314
657
  rect: menuRect.value,
315
658
  rotation: __props.rotation
@@ -325,7 +668,15 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
325
668
  })
326
669
  ]),
327
670
  _: 3
328
- }, 8, ["rect", "rotation"])) : createCommentVNode("", true)
671
+ }, 8, ["rect", "rotation"])) : createCommentVNode("", true),
672
+ (rotationActive.value || isHandleHovered.value) && cursorScreen.value ? (openBlock(), createBlock(Teleport, {
673
+ key: 1,
674
+ to: "body"
675
+ }, [
676
+ createElementVNode("div", {
677
+ style: normalizeStyle(tooltipStyle.value)
678
+ }, toDisplayString(normalizedRotationDisplay.value.toFixed(0)) + "°", 5)
679
+ ])) : createCommentVNode("", true)
329
680
  ]);
330
681
  };
331
682
  }
@@ -335,6 +686,8 @@ const _hoisted_1$9 = {
335
686
  "data-group-selection-box": "",
336
687
  "data-no-interaction": ""
337
688
  };
689
+ const _hoisted_2$7 = ["width", "height", "stroke"];
690
+ const _hoisted_3$4 = ["width", "height", "stroke"];
338
691
  const _sfc_main$k = /* @__PURE__ */ defineComponent({
339
692
  __name: "group-selection-box",
340
693
  props: {
@@ -347,9 +700,13 @@ const _sfc_main$k = /* @__PURE__ */ defineComponent({
347
700
  selectedAnnotations: {},
348
701
  isDraggable: { type: Boolean },
349
702
  isResizable: { type: Boolean },
350
- resizeUI: {},
703
+ isRotatable: { type: Boolean, default: true },
704
+ lockAspectRatio: { type: Boolean, default: false },
705
+ resizeUi: {},
706
+ rotationUi: {},
351
707
  selectionOutlineColor: { default: "#007ACC" },
352
708
  outlineOffset: { default: 2 },
709
+ selectionOutline: {},
353
710
  zIndex: { default: 100 },
354
711
  groupSelectionMenu: {}
355
712
  },
@@ -361,20 +718,87 @@ const _sfc_main$k = /* @__PURE__ */ defineComponent({
361
718
  const gestureBase = shallowRef(null);
362
719
  const isDraggingRef = ref(false);
363
720
  const isResizingRef = ref(false);
721
+ const liveRotation = ref(null);
722
+ const cursorScreen = ref(null);
723
+ const isHandleHovered = ref(false);
364
724
  const effectiveIsDraggable = computed(
365
725
  () => permissions.value.canModifyAnnotations && props.isDraggable
366
726
  );
367
727
  const effectiveIsResizable = computed(
368
728
  () => permissions.value.canModifyAnnotations && props.isResizable
369
729
  );
730
+ const effectiveIsRotatable = computed(
731
+ () => permissions.value.canModifyAnnotations && props.isRotatable
732
+ );
370
733
  const HANDLE_COLOR = computed(() => {
371
734
  var _a;
372
- return ((_a = props.resizeUI) == null ? void 0 : _a.color) ?? "#007ACC";
735
+ return ((_a = props.resizeUi) == null ? void 0 : _a.color) ?? "#007ACC";
373
736
  });
374
737
  const HANDLE_SIZE = computed(() => {
375
738
  var _a;
376
- return ((_a = props.resizeUI) == null ? void 0 : _a.size) ?? 12;
739
+ return ((_a = props.resizeUi) == null ? void 0 : _a.size) ?? 12;
740
+ });
741
+ const ROTATION_SIZE = computed(() => {
742
+ var _a;
743
+ return ((_a = props.rotationUi) == null ? void 0 : _a.size) ?? 32;
744
+ });
745
+ const ROTATION_COLOR = computed(() => {
746
+ var _a;
747
+ return ((_a = props.rotationUi) == null ? void 0 : _a.color) ?? "white";
748
+ });
749
+ const ROTATION_CONNECTOR_COLOR = computed(() => {
750
+ var _a;
751
+ return ((_a = props.rotationUi) == null ? void 0 : _a.connectorColor) ?? "#007ACC";
752
+ });
753
+ const ROTATION_ICON_COLOR = computed(() => {
754
+ var _a;
755
+ return ((_a = props.rotationUi) == null ? void 0 : _a.iconColor) ?? "#007ACC";
756
+ });
757
+ const SHOW_CONNECTOR = computed(() => {
758
+ var _a;
759
+ return ((_a = props.rotationUi) == null ? void 0 : _a.showConnector) ?? false;
760
+ });
761
+ const ROTATION_MARGIN = computed(() => {
762
+ var _a;
763
+ return (_a = props.rotationUi) == null ? void 0 : _a.margin;
764
+ });
765
+ const ROTATION_BORDER_COLOR = computed(() => {
766
+ var _a, _b;
767
+ return ((_b = (_a = props.rotationUi) == null ? void 0 : _a.border) == null ? void 0 : _b.color) ?? "#007ACC";
768
+ });
769
+ const ROTATION_BORDER_WIDTH = computed(() => {
770
+ var _a, _b;
771
+ return ((_b = (_a = props.rotationUi) == null ? void 0 : _a.border) == null ? void 0 : _b.width) ?? 1;
772
+ });
773
+ const ROTATION_BORDER_STYLE = computed(() => {
774
+ var _a, _b;
775
+ return ((_b = (_a = props.rotationUi) == null ? void 0 : _a.border) == null ? void 0 : _b.style) ?? "solid";
776
+ });
777
+ const outlineColor = computed(
778
+ () => {
779
+ var _a;
780
+ return ((_a = props.selectionOutline) == null ? void 0 : _a.color) ?? props.selectionOutlineColor ?? "#007ACC";
781
+ }
782
+ );
783
+ const outlineStyleVal = computed(() => {
784
+ var _a;
785
+ return ((_a = props.selectionOutline) == null ? void 0 : _a.style) ?? "dashed";
786
+ });
787
+ const outlineWidth = computed(() => {
788
+ var _a;
789
+ return ((_a = props.selectionOutline) == null ? void 0 : _a.width) ?? 2;
790
+ });
791
+ const outlineOff = computed(() => {
792
+ var _a;
793
+ return ((_a = props.selectionOutline) == null ? void 0 : _a.offset) ?? props.outlineOffset ?? 2;
794
+ });
795
+ const groupRotationDisplay = computed(() => liveRotation.value ?? 0);
796
+ const rotationActive = computed(() => liveRotation.value !== null);
797
+ const normalizedRotationDisplay = computed(() => {
798
+ const val = groupRotationDisplay.value;
799
+ return Number.isFinite(val) ? Math.round(val * 10) / 10 : 0;
377
800
  });
801
+ const rotationIconSize = computed(() => Math.round(ROTATION_SIZE.value * 0.6));
378
802
  const groupBox = computed(() => {
379
803
  const rects = props.selectedAnnotations.map((ta) => ta.object.rect);
380
804
  return boundingRectOrEmpty(rects);
@@ -389,17 +813,137 @@ const _sfc_main$k = /* @__PURE__ */ defineComponent({
389
813
  },
390
814
  { immediate: true }
391
815
  );
392
- const boxStyle = computed(() => ({
816
+ watch(
817
+ () => annotationPlugin.value,
818
+ (plugin, _old, onCleanup) => {
819
+ if (!plugin) return;
820
+ const unsub = plugin.onRotateChange((event) => {
821
+ if (event.documentId !== props.documentId) return;
822
+ if (event.type === "end" || event.type === "cancel") {
823
+ liveRotation.value = null;
824
+ }
825
+ });
826
+ onCleanup(unsub);
827
+ },
828
+ { immediate: true }
829
+ );
830
+ const groupBoxWidth = computed(() => previewGroupBox.value.size.width * props.scale);
831
+ const groupBoxHeight = computed(() => previewGroupBox.value.size.height * props.scale);
832
+ const groupCenterX = computed(() => groupBoxWidth.value / 2);
833
+ const groupCenterY = computed(() => groupBoxHeight.value / 2);
834
+ const groupGuideLength = computed(
835
+ () => Math.max(300, Math.max(groupBoxWidth.value, groupBoxHeight.value) + 80)
836
+ );
837
+ const contentsStyle = { display: "contents" };
838
+ const outerStyle = computed(() => ({
393
839
  position: "absolute",
394
840
  left: `${previewGroupBox.value.origin.x * props.scale}px`,
395
841
  top: `${previewGroupBox.value.origin.y * props.scale}px`,
396
- width: `${previewGroupBox.value.size.width * props.scale}px`,
397
- height: `${previewGroupBox.value.size.height * props.scale}px`,
398
- outline: `2px dashed ${props.selectionOutlineColor}`,
399
- outlineOffset: `${props.outlineOffset - 1}px`,
842
+ width: `${groupBoxWidth.value}px`,
843
+ height: `${groupBoxHeight.value}px`,
844
+ pointerEvents: "none",
845
+ zIndex: props.zIndex
846
+ }));
847
+ const boxStyle = computed(() => ({
848
+ position: "absolute",
849
+ left: 0,
850
+ top: 0,
851
+ width: `${groupBoxWidth.value}px`,
852
+ height: `${groupBoxHeight.value}px`,
853
+ outline: rotationActive.value ? "none" : `${outlineWidth.value}px ${outlineStyleVal.value} ${outlineColor.value}`,
854
+ outlineOffset: `${outlineOff.value - 1}px`,
400
855
  cursor: effectiveIsDraggable.value ? "move" : "default",
401
856
  touchAction: "none",
402
- zIndex: props.zIndex
857
+ pointerEvents: "auto"
858
+ }));
859
+ const guideHorizontalStyle = computed(() => ({
860
+ position: "absolute",
861
+ left: `${groupCenterX.value - groupGuideLength.value / 2}px`,
862
+ top: `${groupCenterY.value}px`,
863
+ width: `${groupGuideLength.value}px`,
864
+ height: "1px",
865
+ backgroundColor: HANDLE_COLOR.value,
866
+ opacity: 0.35,
867
+ pointerEvents: "none"
868
+ }));
869
+ const guideVerticalStyle = computed(() => ({
870
+ position: "absolute",
871
+ left: `${groupCenterX.value}px`,
872
+ top: `${groupCenterY.value - groupGuideLength.value / 2}px`,
873
+ width: "1px",
874
+ height: `${groupGuideLength.value}px`,
875
+ backgroundColor: HANDLE_COLOR.value,
876
+ opacity: 0.35,
877
+ pointerEvents: "none"
878
+ }));
879
+ const guideAngleStyle = computed(() => ({
880
+ position: "absolute",
881
+ left: `${groupCenterX.value - groupGuideLength.value / 2}px`,
882
+ top: `${groupCenterY.value}px`,
883
+ width: `${groupGuideLength.value}px`,
884
+ height: "1px",
885
+ transformOrigin: "center center",
886
+ transform: `rotate(${groupRotationDisplay.value}deg)`,
887
+ backgroundColor: HANDLE_COLOR.value,
888
+ opacity: 0.8,
889
+ pointerEvents: "none"
890
+ }));
891
+ const connectorLineStyle = computed(() => {
892
+ var _a;
893
+ return {
894
+ ...((_a = rotationHandleData.value) == null ? void 0 : _a.connector.style) ?? {},
895
+ backgroundColor: ROTATION_CONNECTOR_COLOR.value,
896
+ opacity: rotationActive.value ? 0 : 1
897
+ };
898
+ });
899
+ const rotationHandleStyle = computed(() => {
900
+ var _a;
901
+ return {
902
+ ...((_a = rotationHandleData.value) == null ? void 0 : _a.handle.style) ?? {},
903
+ backgroundColor: ROTATION_COLOR.value,
904
+ border: `${ROTATION_BORDER_WIDTH.value}px ${ROTATION_BORDER_STYLE.value} ${ROTATION_BORDER_COLOR.value}`,
905
+ boxSizing: "border-box",
906
+ display: "flex",
907
+ alignItems: "center",
908
+ justifyContent: "center",
909
+ pointerEvents: "auto",
910
+ opacity: rotationActive.value ? 0 : 1
911
+ };
912
+ });
913
+ const rotationHandleBindings = computed(() => {
914
+ if (!rotationHandleData.value) return {};
915
+ const { style: _s, ...rest } = rotationHandleData.value.handle;
916
+ return rest;
917
+ });
918
+ const rotationHandleSlotProps = computed(() => {
919
+ if (!rotationHandleData.value) return {};
920
+ return {
921
+ ...rotationHandleData.value.handle,
922
+ backgroundColor: ROTATION_COLOR.value,
923
+ iconColor: ROTATION_ICON_COLOR.value,
924
+ connectorStyle: connectorLineStyle.value,
925
+ showConnector: SHOW_CONNECTOR.value,
926
+ opacity: rotationActive.value ? 0 : 1,
927
+ border: {
928
+ color: ROTATION_BORDER_COLOR.value,
929
+ width: ROTATION_BORDER_WIDTH.value,
930
+ style: ROTATION_BORDER_STYLE.value
931
+ }
932
+ };
933
+ });
934
+ const tooltipStyle = computed(() => ({
935
+ position: "fixed",
936
+ left: cursorScreen.value ? `${cursorScreen.value.x + 16}px` : "0",
937
+ top: cursorScreen.value ? `${cursorScreen.value.y - 16}px` : "0",
938
+ background: "rgba(0,0,0,0.8)",
939
+ color: "#fff",
940
+ padding: "4px 8px",
941
+ borderRadius: "4px",
942
+ fontSize: "12px",
943
+ fontFamily: "monospace",
944
+ pointerEvents: "none",
945
+ zIndex: 1e4,
946
+ whiteSpace: "nowrap"
403
947
  }));
404
948
  const menuRect = computed(() => ({
405
949
  origin: {
@@ -416,9 +960,13 @@ const _sfc_main$k = /* @__PURE__ */ defineComponent({
416
960
  annotations: props.selectedAnnotations,
417
961
  pageIndex: props.pageIndex
418
962
  }));
419
- const menuPlacement = computed(() => ({
420
- suggestTop: false
421
- }));
963
+ const menuPlacement = computed(() => {
964
+ const effectiveAngle = ((groupRotationDisplay.value + props.rotation * 90) % 360 + 360) % 360;
965
+ const handleNearMenuSide = effectiveIsRotatable.value && effectiveAngle > 90 && effectiveAngle < 270;
966
+ return {
967
+ suggestTop: handleNearMenuSide
968
+ };
969
+ });
422
970
  const shouldShowMenu = computed(() => {
423
971
  return props.groupSelectionMenu || slots["group-selection-menu"];
424
972
  });
@@ -432,6 +980,11 @@ const _sfc_main$k = /* @__PURE__ */ defineComponent({
432
980
  context: menuContext.value
433
981
  });
434
982
  };
983
+ const onHandlePointerMove = (e) => {
984
+ if (!rotationActive.value) {
985
+ cursorScreen.value = { x: e.clientX, y: e.clientY };
986
+ }
987
+ };
435
988
  const elementSnapshot = computed(() => previewGroupBox.value);
436
989
  const constraintsSnapshot = computed(() => ({
437
990
  minWidth: 20,
@@ -441,17 +994,21 @@ const _sfc_main$k = /* @__PURE__ */ defineComponent({
441
994
  height: props.pageHeight
442
995
  }
443
996
  }));
444
- const { dragProps, resize } = useInteractionHandles({
997
+ const {
998
+ dragProps,
999
+ resize,
1000
+ rotation: rotationHandleData
1001
+ } = useInteractionHandles({
445
1002
  controller: {
446
1003
  element: elementSnapshot,
447
1004
  vertices: computed(() => []),
448
1005
  constraints: constraintsSnapshot,
449
- maintainAspectRatio: computed(() => false),
1006
+ maintainAspectRatio: computed(() => props.lockAspectRatio),
450
1007
  pageRotation: computed(() => props.rotation),
451
1008
  scale: computed(() => props.scale),
452
1009
  enabled: computed(() => true),
453
1010
  onUpdate: (event) => {
454
- var _a, _b;
1011
+ var _a, _b, _c, _d, _e, _f;
455
1012
  if (!((_a = event.transformData) == null ? void 0 : _a.type)) return;
456
1013
  if (!annotationPlugin.value) return;
457
1014
  const plugin = annotationPlugin.value;
@@ -476,6 +1033,33 @@ const _sfc_main$k = /* @__PURE__ */ defineComponent({
476
1033
  });
477
1034
  }
478
1035
  }
1036
+ if (transformType === "rotate") {
1037
+ if (!props.isRotatable) return;
1038
+ const ids = props.selectedAnnotations.map((ta) => ta.object.id);
1039
+ const cursorAngle = ((_c = event.transformData.metadata) == null ? void 0 : _c.rotationAngle) ?? 0;
1040
+ const cursorPos = (_d = event.transformData.metadata) == null ? void 0 : _d.cursorPosition;
1041
+ if (cursorPos) cursorScreen.value = { x: cursorPos.clientX, y: cursorPos.clientY };
1042
+ if (event.state === "start") {
1043
+ liveRotation.value = cursorAngle;
1044
+ plugin.startRotation(props.documentId, {
1045
+ annotationIds: ids,
1046
+ cursorAngle,
1047
+ rotationCenter: (_e = event.transformData.metadata) == null ? void 0 : _e.rotationCenter
1048
+ });
1049
+ } else if (event.state === "move") {
1050
+ liveRotation.value = cursorAngle;
1051
+ plugin.updateRotation(
1052
+ props.documentId,
1053
+ cursorAngle,
1054
+ (_f = event.transformData.metadata) == null ? void 0 : _f.rotationDelta
1055
+ );
1056
+ } else if (event.state === "end") {
1057
+ liveRotation.value = null;
1058
+ cursorScreen.value = null;
1059
+ plugin.commitRotation(props.documentId);
1060
+ }
1061
+ return;
1062
+ }
479
1063
  const base = gestureBase.value ?? groupBox.value;
480
1064
  if (isMove && event.transformData.changes.rect) {
481
1065
  const newRect = event.transformData.changes.rect;
@@ -510,41 +1094,110 @@ const _sfc_main$k = /* @__PURE__ */ defineComponent({
510
1094
  },
511
1095
  resizeUI: {
512
1096
  handleSize: HANDLE_SIZE.value,
513
- spacing: props.outlineOffset,
1097
+ spacing: outlineOff.value,
514
1098
  offsetMode: "outside",
515
- includeSides: true,
1099
+ includeSides: !props.lockAspectRatio,
516
1100
  zIndex: props.zIndex + 1
517
1101
  },
518
1102
  vertexUI: {
519
1103
  vertexSize: 0,
520
1104
  zIndex: props.zIndex
521
1105
  },
522
- includeVertices: false
1106
+ rotationUI: {
1107
+ handleSize: ROTATION_SIZE.value,
1108
+ margin: ROTATION_MARGIN.value,
1109
+ zIndex: props.zIndex + 2,
1110
+ showConnector: SHOW_CONNECTOR.value
1111
+ },
1112
+ includeVertices: false,
1113
+ includeRotation: effectiveIsRotatable,
1114
+ currentRotation: computed(() => liveRotation.value ?? 0)
523
1115
  });
524
1116
  return (_ctx, _cache) => {
525
1117
  return __props.selectedAnnotations.length >= 2 ? (openBlock(), createElementBlock("div", _hoisted_1$9, [
526
- createElementVNode("div", mergeProps(effectiveIsDraggable.value ? unref(dragProps) : {}, {
527
- style: boxStyle.value,
528
- onPointerdown: _cache[0] || (_cache[0] = ($event) => !effectiveIsDraggable.value ? $event.stopPropagation() : void 0)
529
- }), [
530
- effectiveIsResizable.value ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(unref(resize), ({ key, style, ...handle }) => {
531
- return openBlock(), createElementBlock(Fragment, { key }, [
532
- unref(slots)["resize-handle"] ? renderSlot(_ctx.$slots, "resize-handle", mergeProps({
533
- key: 0,
534
- ref_for: true
535
- }, { key, style, ...handle, backgroundColor: HANDLE_COLOR.value }), () => [
536
- createElementVNode("div", mergeProps({ ref_for: true }, handle, {
1118
+ createElementVNode("div", {
1119
+ style: normalizeStyle(outerStyle.value)
1120
+ }, [
1121
+ rotationActive.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
1122
+ createElementVNode("div", {
1123
+ style: normalizeStyle(guideHorizontalStyle.value)
1124
+ }, null, 4),
1125
+ createElementVNode("div", {
1126
+ style: normalizeStyle(guideVerticalStyle.value)
1127
+ }, null, 4),
1128
+ createElementVNode("div", {
1129
+ style: normalizeStyle(guideAngleStyle.value)
1130
+ }, null, 4)
1131
+ ], 64)) : createCommentVNode("", true),
1132
+ effectiveIsRotatable.value && unref(rotationHandleData) ? (openBlock(), createElementBlock("div", {
1133
+ key: 1,
1134
+ onPointerenter: _cache[0] || (_cache[0] = ($event) => isHandleHovered.value = true),
1135
+ onPointerleave: _cache[1] || (_cache[1] = ($event) => {
1136
+ isHandleHovered.value = false;
1137
+ cursorScreen.value = null;
1138
+ }),
1139
+ onPointermove: onHandlePointerMove,
1140
+ style: contentsStyle
1141
+ }, [
1142
+ SHOW_CONNECTOR.value ? (openBlock(), createElementBlock("div", {
1143
+ key: 0,
1144
+ style: normalizeStyle(connectorLineStyle.value)
1145
+ }, null, 4)) : createCommentVNode("", true),
1146
+ unref(slots)["rotation-handle"] ? renderSlot(_ctx.$slots, "rotation-handle", normalizeProps(mergeProps({ key: 1 }, rotationHandleSlotProps.value)), () => [
1147
+ createElementVNode("div", mergeProps(rotationHandleBindings.value, { style: rotationHandleStyle.value }), [
1148
+ (openBlock(), createElementBlock("svg", {
1149
+ width: rotationIconSize.value,
1150
+ height: rotationIconSize.value,
1151
+ viewBox: "0 0 24 24",
1152
+ fill: "none",
1153
+ stroke: ROTATION_ICON_COLOR.value,
1154
+ "stroke-width": "2",
1155
+ "stroke-linecap": "round",
1156
+ "stroke-linejoin": "round"
1157
+ }, [..._cache[2] || (_cache[2] = [
1158
+ createElementVNode("path", { d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8" }, null, -1),
1159
+ createElementVNode("path", { d: "M21 3v5h-5" }, null, -1)
1160
+ ])], 8, _hoisted_2$7))
1161
+ ], 16)
1162
+ ]) : (openBlock(), createElementBlock("div", mergeProps({ key: 2 }, rotationHandleBindings.value, { style: rotationHandleStyle.value }), [
1163
+ (openBlock(), createElementBlock("svg", {
1164
+ width: rotationIconSize.value,
1165
+ height: rotationIconSize.value,
1166
+ viewBox: "0 0 24 24",
1167
+ fill: "none",
1168
+ stroke: ROTATION_ICON_COLOR.value,
1169
+ "stroke-width": "2",
1170
+ "stroke-linecap": "round",
1171
+ "stroke-linejoin": "round"
1172
+ }, [..._cache[3] || (_cache[3] = [
1173
+ createElementVNode("path", { d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8" }, null, -1),
1174
+ createElementVNode("path", { d: "M21 3v5h-5" }, null, -1)
1175
+ ])], 8, _hoisted_3$4))
1176
+ ], 16))
1177
+ ], 32)) : createCommentVNode("", true),
1178
+ createElementVNode("div", mergeProps(
1179
+ effectiveIsDraggable.value ? unref(dragProps) : { onPointerdown: (e) => e.stopPropagation() },
1180
+ { style: boxStyle.value }
1181
+ ), [
1182
+ effectiveIsResizable.value && !rotationActive.value ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(unref(resize), ({ key, style, ...handle }) => {
1183
+ return openBlock(), createElementBlock(Fragment, { key }, [
1184
+ unref(slots)["resize-handle"] ? renderSlot(_ctx.$slots, "resize-handle", mergeProps({
1185
+ key: 0,
1186
+ ref_for: true
1187
+ }, { key, style, ...handle, backgroundColor: HANDLE_COLOR.value }), () => [
1188
+ createElementVNode("div", mergeProps({ ref_for: true }, handle, {
1189
+ style: [style, { backgroundColor: HANDLE_COLOR.value }]
1190
+ }), null, 16)
1191
+ ]) : (openBlock(), createElementBlock("div", mergeProps({
1192
+ key: 1,
1193
+ ref_for: true
1194
+ }, handle, {
537
1195
  style: [style, { backgroundColor: HANDLE_COLOR.value }]
538
- }), null, 16)
539
- ]) : (openBlock(), createElementBlock("div", mergeProps({
540
- key: 1,
541
- ref_for: true
542
- }, handle, {
543
- style: [style, { backgroundColor: HANDLE_COLOR.value }]
544
- }), null, 16))
545
- ], 64);
546
- }), 128)) : createCommentVNode("", true)
547
- ], 16),
1196
+ }), null, 16))
1197
+ ], 64);
1198
+ }), 128)) : createCommentVNode("", true)
1199
+ ], 16)
1200
+ ], 4),
548
1201
  shouldShowMenu.value ? (openBlock(), createBlock(unref(CounterRotate), {
549
1202
  key: 0,
550
1203
  rect: menuRect.value,
@@ -561,7 +1214,15 @@ const _sfc_main$k = /* @__PURE__ */ defineComponent({
561
1214
  })
562
1215
  ]),
563
1216
  _: 3
564
- }, 8, ["rect", "rotation"])) : createCommentVNode("", true)
1217
+ }, 8, ["rect", "rotation"])) : createCommentVNode("", true),
1218
+ (rotationActive.value || isHandleHovered.value) && cursorScreen.value ? (openBlock(), createBlock(Teleport, {
1219
+ key: 1,
1220
+ to: "body"
1221
+ }, [
1222
+ createElementVNode("div", {
1223
+ style: normalizeStyle(tooltipStyle.value)
1224
+ }, toDisplayString(normalizedRotationDisplay.value.toFixed(0)) + "°", 5)
1225
+ ])) : createCommentVNode("", true)
565
1226
  ])) : createCommentVNode("", true);
566
1227
  };
567
1228
  }
@@ -697,7 +1358,7 @@ const _sfc_main$i = /* @__PURE__ */ defineComponent({
697
1358
  return {
698
1359
  color: anno.fontColor,
699
1360
  fontSize: `${adjustedFontPx}px`,
700
- fontFamily: standardFontCss(anno.fontFamily),
1361
+ ...standardFontCssProperties(anno.fontFamily),
701
1362
  textAlign: textAlignmentToCss(anno.textAlign),
702
1363
  flexDirection: "column",
703
1364
  justifyContent: anno.verticalAlign === PdfVerticalAlignment.Top ? "flex-start" : anno.verticalAlign === PdfVerticalAlignment.Middle ? "center" : "flex-end",
@@ -1324,6 +1985,7 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1324
1985
  pageIndex: {},
1325
1986
  annotation: {},
1326
1987
  scaleFactor: { default: 1 },
1988
+ unrotated: { type: Boolean, default: false },
1327
1989
  style: {}
1328
1990
  },
1329
1991
  setup(__props) {
@@ -1339,6 +2001,7 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1339
2001
  () => [
1340
2002
  props.pageIndex,
1341
2003
  props.scaleFactor,
2004
+ props.unrotated,
1342
2005
  props.documentId,
1343
2006
  annotationId.value,
1344
2007
  rectWidth.value,
@@ -1356,7 +2019,8 @@ const _sfc_main$b = /* @__PURE__ */ defineComponent({
1356
2019
  annotation: deepToRaw(props.annotation),
1357
2020
  options: {
1358
2021
  scaleFactor: props.scaleFactor,
1359
- dpr: window.devicePixelRatio
2022
+ dpr: window.devicePixelRatio,
2023
+ unrotated: props.unrotated
1360
2024
  }
1361
2025
  });
1362
2026
  currentTask.value = task;
@@ -1424,6 +2088,10 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
1424
2088
  onClick: { type: Function }
1425
2089
  },
1426
2090
  setup(__props) {
2091
+ const props = __props;
2092
+ const unrotated = computed(
2093
+ () => !!props.annotation.object.rotation && !!props.annotation.object.unrotatedRect
2094
+ );
1427
2095
  return (_ctx, _cache) => {
1428
2096
  return openBlock(), createElementBlock("div", {
1429
2097
  style: normalizeStyle({
@@ -1443,8 +2111,9 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
1443
2111
  documentId: __props.documentId,
1444
2112
  pageIndex: __props.pageIndex,
1445
2113
  annotation: { ...__props.annotation.object, id: __props.annotation.object.id },
1446
- scaleFactor: __props.scale
1447
- }, null, 8, ["documentId", "pageIndex", "annotation", "scaleFactor"])
2114
+ scaleFactor: __props.scale,
2115
+ unrotated: unrotated.value
2116
+ }, null, 8, ["documentId", "pageIndex", "annotation", "scaleFactor", "unrotated"])
1448
2117
  ], 36);
1449
2118
  };
1450
2119
  }
@@ -1662,15 +2331,21 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1662
2331
  rotation: {},
1663
2332
  pageWidth: {},
1664
2333
  pageHeight: {},
1665
- resizeUI: {},
1666
- vertexUI: {},
2334
+ resizeUi: {},
2335
+ vertexUi: {},
2336
+ rotationUi: {},
1667
2337
  selectionOutlineColor: {},
2338
+ selectionOutline: {},
2339
+ groupSelectionOutline: {},
1668
2340
  selectionMenu: { type: Function },
1669
2341
  groupSelectionMenu: { type: Function },
1670
2342
  annotationRenderers: {}
1671
2343
  },
1672
2344
  setup(__props) {
1673
2345
  const props = __props;
2346
+ const blendStyle = (annotation, defaultBlend = PdfBlendMode.Normal) => ({
2347
+ mixBlendMode: blendModeToCss(annotation.object.blendMode ?? defaultBlend)
2348
+ });
1674
2349
  const findCustomRenderer = (annotation) => {
1675
2350
  var _a;
1676
2351
  return (_a = props.annotationRenderers) == null ? void 0 : _a.find((r) => r.matches(annotation.object));
@@ -1780,6 +2455,34 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1780
2455
  return (tool == null ? void 0 : tool.interaction.isGroupResizable) !== void 0 ? groupResizable : singleResizable;
1781
2456
  });
1782
2457
  });
2458
+ const areAllSelectedRotatable = computed(() => {
2459
+ if (selectedAnnotationsOnPage.value.length < 2) return false;
2460
+ return selectedAnnotationsOnPage.value.every((ta) => {
2461
+ var _a;
2462
+ const tool = (_a = annotationProvides.value) == null ? void 0 : _a.findToolForAnnotation(ta.object);
2463
+ const groupRotatable = resolveInteractionProp(
2464
+ tool == null ? void 0 : tool.interaction.isGroupRotatable,
2465
+ ta.object,
2466
+ true
2467
+ );
2468
+ const singleRotatable = resolveInteractionProp(tool == null ? void 0 : tool.interaction.isRotatable, ta.object, true);
2469
+ return (tool == null ? void 0 : tool.interaction.isGroupRotatable) !== void 0 ? groupRotatable : singleRotatable;
2470
+ });
2471
+ });
2472
+ const shouldLockGroupAspectRatio = computed(() => {
2473
+ if (selectedAnnotationsOnPage.value.length < 2) return false;
2474
+ return selectedAnnotationsOnPage.value.some((ta) => {
2475
+ var _a;
2476
+ const tool = (_a = annotationProvides.value) == null ? void 0 : _a.findToolForAnnotation(ta.object);
2477
+ const groupLock = resolveInteractionProp(
2478
+ tool == null ? void 0 : tool.interaction.lockGroupAspectRatio,
2479
+ ta.object,
2480
+ false
2481
+ );
2482
+ const singleLock = resolveInteractionProp(tool == null ? void 0 : tool.interaction.lockAspectRatio, ta.object, false);
2483
+ return (tool == null ? void 0 : tool.interaction.lockGroupAspectRatio) !== void 0 ? groupLock : singleLock;
2484
+ });
2485
+ });
1783
2486
  const allSelectedOnSamePage = computed(() => {
1784
2487
  if (!annotationProvides.value) return false;
1785
2488
  if (allSelectedIds.value.length < 2) return false;
@@ -1805,9 +2508,19 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1805
2508
  var _a;
1806
2509
  return resolveInteractionProp((_a = getTool(anno)) == null ? void 0 : _a.interaction.lockAspectRatio, anno.object, false);
1807
2510
  };
2511
+ const isRotatableFor = (anno, fallback) => {
2512
+ var _a;
2513
+ if (isMultiSelected.value) return false;
2514
+ return resolveInteractionProp((_a = getTool(anno)) == null ? void 0 : _a.interaction.isRotatable, anno.object, fallback);
2515
+ };
1808
2516
  const showIndividualSelection = (anno) => isSelected(anno) && !isMultiSelected.value;
1809
2517
  const containerProps = computed(() => {
1810
- const { selectionMenu: _sm, groupSelectionMenu: _gsm, ...rest } = props;
2518
+ const {
2519
+ selectionMenu: _sm,
2520
+ groupSelectionMenu: _gsm,
2521
+ groupSelectionOutline: _gso,
2522
+ ...rest
2523
+ } = props;
1811
2524
  return rest;
1812
2525
  });
1813
2526
  const getVertexConfig = (annotation) => {
@@ -1840,10 +2553,11 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1840
2553
  isSelected: showIndividualSelection(annotation),
1841
2554
  isDraggable: isDraggable(annotation),
1842
2555
  isResizable: isResizable(annotation),
2556
+ isRotatable: isRotatableFor(annotation, false),
1843
2557
  lockAspectRatio: lockAspectRatio(annotation),
1844
2558
  onSelect: (e) => handleClick(e, annotation),
1845
2559
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
1846
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2560
+ style: blendStyle(annotation)
1847
2561
  }, { ref_for: true }, containerProps.value), createSlots({
1848
2562
  default: withCtx(() => [
1849
2563
  (openBlock(), createBlock(resolveDynamicComponent(findCustomRenderer(annotation).component), {
@@ -1857,6 +2571,9 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1857
2571
  "resize-handle": withCtx((slotProps) => [
1858
2572
  renderSlot(_ctx.$slots, "resize-handle", mergeProps({ ref_for: true }, slotProps))
1859
2573
  ]),
2574
+ "rotation-handle": withCtx((slotProps) => [
2575
+ renderSlot(_ctx.$slots, "rotation-handle", mergeProps({ ref_for: true }, slotProps))
2576
+ ]),
1860
2577
  _: 2
1861
2578
  }, [
1862
2579
  !isMultiSelected.value ? {
@@ -1866,17 +2583,18 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1866
2583
  ]),
1867
2584
  key: "0"
1868
2585
  } : void 0
1869
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "selectionMenu", "style"])) : unref(isInk)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2586
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "selectionMenu", "style"])) : unref(isInk)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
1870
2587
  key: 1,
1871
2588
  trackedAnnotation: annotation,
1872
2589
  isSelected: showIndividualSelection(annotation),
1873
2590
  isDraggable: isDraggable(annotation),
1874
2591
  isResizable: isResizable(annotation),
2592
+ isRotatable: isRotatableFor(annotation, true),
1875
2593
  lockAspectRatio: lockAspectRatio(annotation),
1876
2594
  onSelect: (e) => handleClick(e, annotation),
1877
2595
  vertexConfig: getVertexConfig(annotation),
1878
2596
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
1879
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2597
+ style: blendStyle(annotation)
1880
2598
  }, { ref_for: true }, containerProps.value), createSlots({
1881
2599
  default: withCtx(({ annotation: currentObject }) => [
1882
2600
  createVNode(_sfc_main$h, mergeProps({ ref_for: true }, currentObject, {
@@ -1891,6 +2609,9 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1891
2609
  "vertex-handle": withCtx((slotProps) => [
1892
2610
  renderSlot(_ctx.$slots, "vertex-handle", mergeProps({ ref_for: true }, slotProps))
1893
2611
  ]),
2612
+ "rotation-handle": withCtx((slotProps) => [
2613
+ renderSlot(_ctx.$slots, "rotation-handle", mergeProps({ ref_for: true }, slotProps))
2614
+ ]),
1894
2615
  _: 2
1895
2616
  }, [
1896
2617
  !isMultiSelected.value ? {
@@ -1900,17 +2621,18 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1900
2621
  ]),
1901
2622
  key: "0"
1902
2623
  } : void 0
1903
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isSquare)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2624
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isSquare)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
1904
2625
  key: 2,
1905
2626
  trackedAnnotation: annotation,
1906
2627
  isSelected: showIndividualSelection(annotation),
1907
2628
  isDraggable: isDraggable(annotation),
1908
2629
  isResizable: isResizable(annotation),
2630
+ isRotatable: isRotatableFor(annotation, true),
1909
2631
  lockAspectRatio: lockAspectRatio(annotation),
1910
2632
  onSelect: (e) => handleClick(e, annotation),
1911
2633
  vertexConfig: getVertexConfig(annotation),
1912
2634
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
1913
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2635
+ style: blendStyle(annotation)
1914
2636
  }, { ref_for: true }, containerProps.value), createSlots({
1915
2637
  default: withCtx(({ annotation: currentObject }) => [
1916
2638
  createVNode(_sfc_main$c, mergeProps({ ref_for: true }, currentObject, {
@@ -1925,6 +2647,9 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1925
2647
  "vertex-handle": withCtx((slotProps) => [
1926
2648
  renderSlot(_ctx.$slots, "vertex-handle", mergeProps({ ref_for: true }, slotProps))
1927
2649
  ]),
2650
+ "rotation-handle": withCtx((slotProps) => [
2651
+ renderSlot(_ctx.$slots, "rotation-handle", mergeProps({ ref_for: true }, slotProps))
2652
+ ]),
1928
2653
  _: 2
1929
2654
  }, [
1930
2655
  !isMultiSelected.value ? {
@@ -1934,17 +2659,18 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1934
2659
  ]),
1935
2660
  key: "0"
1936
2661
  } : void 0
1937
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isCircle)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2662
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isCircle)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
1938
2663
  key: 3,
1939
2664
  trackedAnnotation: annotation,
1940
2665
  isSelected: showIndividualSelection(annotation),
1941
2666
  isDraggable: isDraggable(annotation),
1942
2667
  isResizable: isResizable(annotation),
2668
+ isRotatable: isRotatableFor(annotation, true),
1943
2669
  lockAspectRatio: lockAspectRatio(annotation),
1944
2670
  onSelect: (e) => handleClick(e, annotation),
1945
2671
  vertexConfig: getVertexConfig(annotation),
1946
2672
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
1947
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2673
+ style: blendStyle(annotation)
1948
2674
  }, { ref_for: true }, containerProps.value), createSlots({
1949
2675
  default: withCtx(({ annotation: currentObject }) => [
1950
2676
  createVNode(_sfc_main$j, mergeProps({ ref_for: true }, currentObject, {
@@ -1959,6 +2685,9 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1959
2685
  "vertex-handle": withCtx((slotProps) => [
1960
2686
  renderSlot(_ctx.$slots, "vertex-handle", mergeProps({ ref_for: true }, slotProps))
1961
2687
  ]),
2688
+ "rotation-handle": withCtx((slotProps) => [
2689
+ renderSlot(_ctx.$slots, "rotation-handle", mergeProps({ ref_for: true }, slotProps))
2690
+ ]),
1962
2691
  _: 2
1963
2692
  }, [
1964
2693
  !isMultiSelected.value ? {
@@ -1968,17 +2697,18 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1968
2697
  ]),
1969
2698
  key: "0"
1970
2699
  } : void 0
1971
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isLine)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2700
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isLine)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
1972
2701
  key: 4,
1973
2702
  trackedAnnotation: annotation,
1974
2703
  isSelected: showIndividualSelection(annotation),
1975
2704
  isDraggable: isDraggable(annotation),
1976
2705
  isResizable: isResizable(annotation),
2706
+ isRotatable: isRotatableFor(annotation, true),
1977
2707
  lockAspectRatio: lockAspectRatio(annotation),
1978
2708
  onSelect: (e) => handleClick(e, annotation),
1979
2709
  vertexConfig: getVertexConfig(annotation),
1980
2710
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
1981
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2711
+ style: blendStyle(annotation)
1982
2712
  }, { ref_for: true }, containerProps.value), createSlots({
1983
2713
  default: withCtx(({ annotation: currentObject }) => [
1984
2714
  createVNode(_sfc_main$g, mergeProps({ ref_for: true }, currentObject, {
@@ -1993,6 +2723,9 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
1993
2723
  "vertex-handle": withCtx((slotProps) => [
1994
2724
  renderSlot(_ctx.$slots, "vertex-handle", mergeProps({ ref_for: true }, slotProps))
1995
2725
  ]),
2726
+ "rotation-handle": withCtx((slotProps) => [
2727
+ renderSlot(_ctx.$slots, "rotation-handle", mergeProps({ ref_for: true }, slotProps))
2728
+ ]),
1996
2729
  _: 2
1997
2730
  }, [
1998
2731
  !isMultiSelected.value ? {
@@ -2002,17 +2735,18 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2002
2735
  ]),
2003
2736
  key: "0"
2004
2737
  } : void 0
2005
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isPolyline)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2738
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isPolyline)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2006
2739
  key: 5,
2007
2740
  trackedAnnotation: annotation,
2008
2741
  isSelected: showIndividualSelection(annotation),
2009
2742
  isDraggable: isDraggable(annotation),
2010
2743
  isResizable: isResizable(annotation),
2744
+ isRotatable: isRotatableFor(annotation, true),
2011
2745
  lockAspectRatio: lockAspectRatio(annotation),
2012
2746
  onSelect: (e) => handleClick(e, annotation),
2013
2747
  vertexConfig: getVertexConfig(annotation),
2014
2748
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
2015
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2749
+ style: blendStyle(annotation)
2016
2750
  }, { ref_for: true }, containerProps.value), createSlots({
2017
2751
  default: withCtx(({ annotation: currentObject }) => [
2018
2752
  createVNode(_sfc_main$d, mergeProps({ ref_for: true }, currentObject, {
@@ -2027,6 +2761,9 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2027
2761
  "vertex-handle": withCtx((slotProps) => [
2028
2762
  renderSlot(_ctx.$slots, "vertex-handle", mergeProps({ ref_for: true }, slotProps))
2029
2763
  ]),
2764
+ "rotation-handle": withCtx((slotProps) => [
2765
+ renderSlot(_ctx.$slots, "rotation-handle", mergeProps({ ref_for: true }, slotProps))
2766
+ ]),
2030
2767
  _: 2
2031
2768
  }, [
2032
2769
  !isMultiSelected.value ? {
@@ -2036,17 +2773,18 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2036
2773
  ]),
2037
2774
  key: "0"
2038
2775
  } : void 0
2039
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isPolygon)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2776
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isPolygon)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2040
2777
  key: 6,
2041
2778
  trackedAnnotation: annotation,
2042
2779
  isSelected: showIndividualSelection(annotation),
2043
2780
  isDraggable: isDraggable(annotation),
2044
2781
  isResizable: isResizable(annotation),
2782
+ isRotatable: isRotatableFor(annotation, true),
2045
2783
  lockAspectRatio: lockAspectRatio(annotation),
2046
2784
  onSelect: (e) => handleClick(e, annotation),
2047
2785
  vertexConfig: getVertexConfig(annotation),
2048
2786
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
2049
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2787
+ style: blendStyle(annotation)
2050
2788
  }, { ref_for: true }, containerProps.value), createSlots({
2051
2789
  default: withCtx(({ annotation: currentObject }) => [
2052
2790
  createVNode(_sfc_main$e, mergeProps({ ref_for: true }, currentObject, {
@@ -2061,6 +2799,9 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2061
2799
  "vertex-handle": withCtx((slotProps) => [
2062
2800
  renderSlot(_ctx.$slots, "vertex-handle", mergeProps({ ref_for: true }, slotProps))
2063
2801
  ]),
2802
+ "rotation-handle": withCtx((slotProps) => [
2803
+ renderSlot(_ctx.$slots, "rotation-handle", mergeProps({ ref_for: true }, slotProps))
2804
+ ]),
2064
2805
  _: 2
2065
2806
  }, [
2066
2807
  !isMultiSelected.value ? {
@@ -2070,18 +2811,19 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2070
2811
  ]),
2071
2812
  key: "0"
2072
2813
  } : void 0
2073
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isFreeText)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2814
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isFreeText)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2074
2815
  key: 7,
2075
2816
  trackedAnnotation: annotation,
2076
2817
  isSelected: showIndividualSelection(annotation),
2077
2818
  isDraggable: isDraggable(annotation),
2078
2819
  isResizable: isResizable(annotation),
2820
+ isRotatable: isRotatableFor(annotation, true),
2079
2821
  lockAspectRatio: lockAspectRatio(annotation),
2080
2822
  onSelect: (e) => handleClick(e, annotation),
2081
2823
  onDoubleClick: (e) => handleDoubleClick(e, annotation.object.id),
2082
2824
  vertexConfig: getVertexConfig(annotation),
2083
2825
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
2084
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2826
+ style: blendStyle(annotation)
2085
2827
  }, { ref_for: true }, containerProps.value), createSlots({
2086
2828
  default: withCtx(({ annotation: currentObject }) => [
2087
2829
  createVNode(_sfc_main$i, {
@@ -2099,6 +2841,9 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2099
2841
  "vertex-handle": withCtx((slotProps) => [
2100
2842
  renderSlot(_ctx.$slots, "vertex-handle", mergeProps({ ref_for: true }, slotProps))
2101
2843
  ]),
2844
+ "rotation-handle": withCtx((slotProps) => [
2845
+ renderSlot(_ctx.$slots, "rotation-handle", mergeProps({ ref_for: true }, slotProps))
2846
+ ]),
2102
2847
  _: 2
2103
2848
  }, [
2104
2849
  !isMultiSelected.value ? {
@@ -2108,17 +2853,18 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2108
2853
  ]),
2109
2854
  key: "0"
2110
2855
  } : void 0
2111
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "onDoubleClick", "vertexConfig", "selectionMenu", "style"])) : unref(isStamp)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2856
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "onDoubleClick", "vertexConfig", "selectionMenu", "style"])) : unref(isStamp)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2112
2857
  key: 8,
2113
2858
  trackedAnnotation: annotation,
2114
2859
  isSelected: showIndividualSelection(annotation),
2115
2860
  isDraggable: isDraggable(annotation),
2116
2861
  isResizable: isResizable(annotation),
2862
+ isRotatable: isRotatableFor(annotation, true),
2117
2863
  lockAspectRatio: lockAspectRatio(annotation),
2118
2864
  onSelect: (e) => handleClick(e, annotation),
2119
2865
  vertexConfig: getVertexConfig(annotation),
2120
2866
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
2121
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2867
+ style: blendStyle(annotation)
2122
2868
  }, { ref_for: true }, containerProps.value), createSlots({
2123
2869
  default: withCtx(() => [
2124
2870
  createVNode(_sfc_main$a, {
@@ -2136,6 +2882,9 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2136
2882
  "vertex-handle": withCtx((slotProps) => [
2137
2883
  renderSlot(_ctx.$slots, "vertex-handle", mergeProps({ ref_for: true }, slotProps))
2138
2884
  ]),
2885
+ "rotation-handle": withCtx((slotProps) => [
2886
+ renderSlot(_ctx.$slots, "rotation-handle", mergeProps({ ref_for: true }, slotProps))
2887
+ ]),
2139
2888
  _: 2
2140
2889
  }, [
2141
2890
  !isMultiSelected.value ? {
@@ -2145,18 +2894,19 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2145
2894
  ]),
2146
2895
  key: "0"
2147
2896
  } : void 0
2148
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isUnderline)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2897
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isUnderline)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2149
2898
  key: 9,
2150
2899
  trackedAnnotation: annotation,
2151
2900
  isSelected: showIndividualSelection(annotation),
2152
2901
  isDraggable: isDraggable(annotation),
2153
2902
  isResizable: isResizable(annotation),
2903
+ isRotatable: isRotatableFor(annotation, false),
2154
2904
  lockAspectRatio: lockAspectRatio(annotation),
2155
2905
  onSelect: (e) => handleClick(e, annotation),
2156
2906
  vertexConfig: getVertexConfig(annotation),
2157
2907
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
2158
2908
  zIndex: 0,
2159
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2909
+ style: blendStyle(annotation)
2160
2910
  }, { ref_for: true }, containerProps.value), createSlots({
2161
2911
  default: withCtx(({ annotation: currentObject }) => [
2162
2912
  createVNode(_sfc_main$6, mergeProps({ ref_for: true }, currentObject, {
@@ -2173,18 +2923,19 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2173
2923
  ]),
2174
2924
  key: "0"
2175
2925
  } : void 0
2176
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isStrikeout)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2926
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isStrikeout)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2177
2927
  key: 10,
2178
2928
  trackedAnnotation: annotation,
2179
2929
  isSelected: showIndividualSelection(annotation),
2180
2930
  isDraggable: isDraggable(annotation),
2181
2931
  isResizable: isResizable(annotation),
2932
+ isRotatable: isRotatableFor(annotation, false),
2182
2933
  lockAspectRatio: lockAspectRatio(annotation),
2183
2934
  onSelect: (e) => handleClick(e, annotation),
2184
2935
  vertexConfig: getVertexConfig(annotation),
2185
2936
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
2186
2937
  zIndex: 0,
2187
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2938
+ style: blendStyle(annotation)
2188
2939
  }, { ref_for: true }, containerProps.value), createSlots({
2189
2940
  default: withCtx(({ annotation: currentObject }) => [
2190
2941
  createVNode(_sfc_main$7, mergeProps({ ref_for: true }, currentObject, {
@@ -2201,18 +2952,19 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2201
2952
  ]),
2202
2953
  key: "0"
2203
2954
  } : void 0
2204
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isSquiggly)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2955
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isSquiggly)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2205
2956
  key: 11,
2206
2957
  trackedAnnotation: annotation,
2207
2958
  isSelected: showIndividualSelection(annotation),
2208
2959
  isDraggable: isDraggable(annotation),
2209
2960
  isResizable: isResizable(annotation),
2961
+ isRotatable: isRotatableFor(annotation, false),
2210
2962
  lockAspectRatio: lockAspectRatio(annotation),
2211
2963
  onSelect: (e) => handleClick(e, annotation),
2212
2964
  vertexConfig: getVertexConfig(annotation),
2213
2965
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
2214
2966
  zIndex: 0,
2215
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
2967
+ style: blendStyle(annotation)
2216
2968
  }, { ref_for: true }, containerProps.value), createSlots({
2217
2969
  default: withCtx(({ annotation: currentObject }) => [
2218
2970
  createVNode(_sfc_main$8, mergeProps({ ref_for: true }, currentObject, {
@@ -2229,20 +2981,19 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2229
2981
  ]),
2230
2982
  key: "0"
2231
2983
  } : void 0
2232
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isHighlight)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2984
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isHighlight)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2233
2985
  key: 12,
2234
2986
  trackedAnnotation: annotation,
2235
2987
  isSelected: showIndividualSelection(annotation),
2236
2988
  isDraggable: isDraggable(annotation),
2237
2989
  isResizable: isResizable(annotation),
2990
+ isRotatable: isRotatableFor(annotation, false),
2238
2991
  lockAspectRatio: lockAspectRatio(annotation),
2239
2992
  onSelect: (e) => handleClick(e, annotation),
2240
2993
  vertexConfig: getVertexConfig(annotation),
2241
2994
  selectionMenu: isMultiSelected.value ? void 0 : __props.selectionMenu,
2242
2995
  zIndex: 0,
2243
- style: {
2244
- mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Multiply)
2245
- }
2996
+ style: blendStyle(annotation, unref(PdfBlendMode).Multiply)
2246
2997
  }, { ref_for: true }, containerProps.value), createSlots({
2247
2998
  default: withCtx(({ annotation: currentObject }) => [
2248
2999
  createVNode(_sfc_main$9, mergeProps({ ref_for: true }, currentObject, {
@@ -2259,17 +3010,18 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2259
3010
  ]),
2260
3011
  key: "0"
2261
3012
  } : void 0
2262
- ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isLink)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
3013
+ ]), 1040, ["trackedAnnotation", "isSelected", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "onSelect", "vertexConfig", "selectionMenu", "style"])) : unref(isLink)(annotation) ? (openBlock(), createBlock(_sfc_main$l, mergeProps({
2263
3014
  key: 13,
2264
3015
  trackedAnnotation: annotation,
2265
3016
  isSelected: showIndividualSelection(annotation),
2266
3017
  isMultiSelected: isMultiSelected.value,
2267
3018
  isDraggable: false,
2268
3019
  isResizable: false,
3020
+ isRotatable: false,
2269
3021
  lockAspectRatio: false,
2270
3022
  onSelect: (e) => handleLinkClick(e, annotation),
2271
3023
  selectionMenu: annotation.object.inReplyToId ? void 0 : isMultiSelected.value ? void 0 : __props.selectionMenu,
2272
- style: { mixBlendMode: unref(blendModeToCss)(annotation.object.blendMode ?? unref(PdfBlendMode).Normal) }
3024
+ style: blendStyle(annotation)
2273
3025
  }, { ref_for: true }, containerProps.value), createSlots({
2274
3026
  default: withCtx(({ annotation: currentObject }) => [
2275
3027
  createVNode(_sfc_main$f, mergeProps({ ref_for: true }, currentObject, {
@@ -2305,8 +3057,12 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2305
3057
  selectedAnnotations: selectedAnnotationsOnPage.value,
2306
3058
  isDraggable: areAllSelectedDraggable.value,
2307
3059
  isResizable: areAllSelectedResizable.value,
2308
- resizeUI: __props.resizeUI,
3060
+ isRotatable: areAllSelectedRotatable.value,
3061
+ lockAspectRatio: shouldLockGroupAspectRatio.value,
3062
+ resizeUi: __props.resizeUi,
3063
+ rotationUi: __props.rotationUi,
2309
3064
  selectionOutlineColor: __props.selectionOutlineColor,
3065
+ selectionOutline: __props.groupSelectionOutline ?? __props.selectionOutline,
2310
3066
  groupSelectionMenu: __props.groupSelectionMenu
2311
3067
  }, {
2312
3068
  "group-selection-menu": withCtx((slotProps) => [
@@ -2315,8 +3071,11 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
2315
3071
  "resize-handle": withCtx((slotProps) => [
2316
3072
  renderSlot(_ctx.$slots, "resize-handle", normalizeProps(guardReactiveProps(slotProps)))
2317
3073
  ]),
3074
+ "rotation-handle": withCtx((slotProps) => [
3075
+ renderSlot(_ctx.$slots, "rotation-handle", normalizeProps(guardReactiveProps(slotProps)))
3076
+ ]),
2318
3077
  _: 3
2319
- }, 8, ["documentId", "pageIndex", "scale", "rotation", "pageWidth", "pageHeight", "selectedAnnotations", "isDraggable", "isResizable", "resizeUI", "selectionOutlineColor", "groupSelectionMenu"])) : createCommentVNode("", true)
3078
+ }, 8, ["documentId", "pageIndex", "scale", "rotation", "pageWidth", "pageHeight", "selectedAnnotations", "isDraggable", "isResizable", "isRotatable", "lockAspectRatio", "resizeUi", "rotationUi", "selectionOutlineColor", "selectionOutline", "groupSelectionMenu"])) : createCommentVNode("", true)
2320
3079
  ], 64);
2321
3080
  };
2322
3081
  }
@@ -2604,15 +3363,34 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
2604
3363
  pageIndex: {},
2605
3364
  scale: {},
2606
3365
  rotation: {},
3366
+ resizeUi: {},
2607
3367
  resizeUI: {},
3368
+ vertexUi: {},
2608
3369
  vertexUI: {},
3370
+ rotationUi: {},
2609
3371
  selectionOutlineColor: {},
3372
+ selectionOutline: {},
3373
+ groupSelectionOutline: {},
2610
3374
  selectionMenu: { type: Function },
2611
3375
  groupSelectionMenu: { type: Function },
2612
3376
  annotationRenderers: {}
2613
3377
  },
2614
3378
  setup(__props) {
2615
3379
  const props = __props;
3380
+ const resolvedResizeUi = computed(() => props.resizeUi ?? props.resizeUI);
3381
+ const resolvedVertexUi = computed(() => props.vertexUi ?? props.vertexUI);
3382
+ onMounted(() => {
3383
+ if (props.resizeUI) {
3384
+ console.warn(
3385
+ '[AnnotationLayer] The "resizeUI" prop is deprecated. Use :resize-ui in templates instead.'
3386
+ );
3387
+ }
3388
+ if (props.vertexUI) {
3389
+ console.warn(
3390
+ '[AnnotationLayer] The "vertexUI" prop is deprecated. Use :vertex-ui in templates instead.'
3391
+ );
3392
+ }
3393
+ });
2616
3394
  const registry = useRendererRegistry();
2617
3395
  const allRenderers = computed(() => {
2618
3396
  const fromRegistry = (registry == null ? void 0 : registry.getAll()) ?? [];
@@ -2659,9 +3437,12 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
2659
3437
  rotation: actualRotation.value,
2660
3438
  pageWidth: pageWidth.value,
2661
3439
  pageHeight: pageHeight.value,
2662
- resizeUI: __props.resizeUI,
2663
- vertexUI: __props.vertexUI,
3440
+ resizeUi: resolvedResizeUi.value,
3441
+ vertexUi: resolvedVertexUi.value,
3442
+ rotationUi: __props.rotationUi,
2664
3443
  selectionOutlineColor: __props.selectionOutlineColor,
3444
+ selectionOutline: __props.selectionOutline,
3445
+ groupSelectionOutline: __props.groupSelectionOutline,
2665
3446
  selectionMenu: __props.selectionMenu,
2666
3447
  groupSelectionMenu: __props.groupSelectionMenu,
2667
3448
  annotationRenderers: allRenderers.value
@@ -2678,8 +3459,11 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
2678
3459
  "vertex-handle": withCtx((slotProps) => [
2679
3460
  renderSlot(_ctx.$slots, "vertex-handle", normalizeProps(guardReactiveProps(slotProps)))
2680
3461
  ]),
3462
+ "rotation-handle": withCtx((slotProps) => [
3463
+ renderSlot(_ctx.$slots, "rotation-handle", normalizeProps(guardReactiveProps(slotProps)))
3464
+ ]),
2681
3465
  _: 3
2682
- }, 8, ["documentId", "pageIndex", "scale", "rotation", "pageWidth", "pageHeight", "resizeUI", "vertexUI", "selectionOutlineColor", "selectionMenu", "groupSelectionMenu", "annotationRenderers"]),
3466
+ }, 8, ["documentId", "pageIndex", "scale", "rotation", "pageWidth", "pageHeight", "resizeUi", "vertexUi", "rotationUi", "selectionOutlineColor", "selectionOutline", "groupSelectionOutline", "selectionMenu", "groupSelectionMenu", "annotationRenderers"]),
2683
3467
  createVNode(_sfc_main$4, {
2684
3468
  documentId: __props.documentId,
2685
3469
  pageIndex: __props.pageIndex,