@libresign/pdf-elements 0.2.5 → 0.3.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@libresign/pdf-elements",
3
3
  "description": "PDF viewer with draggable and resizable element overlays for Vue 2",
4
- "version": "0.2.5",
4
+ "version": "0.3.0",
5
5
  "author": "LibreCode <contact@librecode.coop>",
6
6
  "private": false,
7
7
  "main": "dist/pdf-elements.umd.js",
@@ -10,7 +10,12 @@ SPDX-License-Identifier: AGPL-3.0-or-later
10
10
  class="actions-toolbar"
11
11
  :style="toolbarStyle"
12
12
  >
13
- <slot name="actions" :object="object" :onDelete="onDelete">
13
+ <slot name="actions" :object="object" :onDelete="onDelete" :onDuplicate="onDuplicate">
14
+ <button class="action-btn" type="button" title="Duplicate" @click.stop="onDuplicate">
15
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
16
+ <path d="M16 1H6a2 2 0 0 0-2 2v12h2V3h10V1zm3 4H10a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2zm0 16H10V7h9v14z"/>
17
+ </svg>
18
+ </button>
14
19
  <button class="action-btn" type="button" title="Delete" @click.stop="onDelete">
15
20
  <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
16
21
  <path d="M6.5 1h3a.5.5 0 0 1 .5.5v1H6v-1a.5.5 0 0 1 .5-.5ZM11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3A1.5 1.5 0 0 0 5 1.5v1H2.5a.5.5 0 0 0 0 1h.5v10.5A1.5 1.5 0 0 0 4.5 15h7a1.5 1.5 0 0 0 1.5-1.5V3.5h.5a.5.5 0 0 0 0-1H11Zm1 1v10.5a.5.5 0 0 1-.5.5h-7a.5.5 0 0 1-.5-.5V3.5h8Z"/>
@@ -77,6 +82,10 @@ export default {
77
82
  type: Function,
78
83
  default: () => {},
79
84
  },
85
+ onDuplicate: {
86
+ type: Function,
87
+ default: () => {},
88
+ },
80
89
  onDragStart: {
81
90
  type: Function,
82
91
  default: () => {},
@@ -124,7 +133,11 @@ export default {
124
133
  readOnly: {
125
134
  type: Boolean,
126
135
  default: false,
127
- }
136
+ },
137
+ ignoreClickOutsideSelectors: {
138
+ type: Array,
139
+ default: () => [],
140
+ },
128
141
  },
129
142
  data() {
130
143
  return {
@@ -237,6 +250,14 @@ export default {
237
250
  this.startDrag(event)
238
251
  },
239
252
  handleClickOutside(event) {
253
+ const selectors = Array.isArray(this.ignoreClickOutsideSelectors)
254
+ ? this.ignoreClickOutsideSelectors
255
+ : []
256
+ for (const selector of selectors) {
257
+ if (selector && event?.target?.closest?.(selector)) {
258
+ return
259
+ }
260
+ }
240
261
  if (this.$el && !this.$el.contains(event.target)) {
241
262
  this.isSelected = false
242
263
  }
@@ -60,6 +60,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
60
60
  :read-only="readOnly"
61
61
  :on-update="(payload) => updateObject(docIndex, object.id, payload)"
62
62
  :on-delete="() => deleteObject(docIndex, object.id)"
63
+ :on-duplicate="() => duplicateObject(docIndex, object.id)"
63
64
  :on-drag-start="(mouseX, mouseY, pointerOffset, dragShift) => startDraggingElement(docIndex, pIndex, object, mouseX, mouseY, pointerOffset, dragShift)"
64
65
  :on-drag-move="updateDraggingPosition"
65
66
  :on-drag-end="stopDraggingElement"
@@ -71,6 +72,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
71
72
  :global-drag-page-index="draggingPageIndex"
72
73
  :show-selection-ui="showSelectionHandles && !hideSelectionUI && object.resizable !== false"
73
74
  :show-default-actions="showElementActions && !hideSelectionUI"
75
+ :ignore-click-outside-selectors="ignoreClickOutsideSelectors"
74
76
  >
75
77
  <template #default="slotProps">
76
78
  <slot
@@ -92,6 +94,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
92
94
  name="actions"
93
95
  :object="slotProps.object"
94
96
  :onDelete="slotProps.onDelete"
97
+ :onDuplicate="slotProps.onDuplicate"
95
98
  />
96
99
  </template>
97
100
  </DraggableElement>
@@ -191,6 +194,10 @@ export default {
191
194
  type: Boolean,
192
195
  default: false,
193
196
  },
197
+ ignoreClickOutsideSelectors: {
198
+ type: Array,
199
+ default: () => [],
200
+ },
194
201
  pageCountFormat: {
195
202
  type: String,
196
203
  default: '{currentPage} of {totalPages}',
@@ -940,6 +947,64 @@ export default {
940
947
  })
941
948
  }
942
949
  },
950
+ duplicateObject(docIndex, objectId) {
951
+ if (docIndex < 0 || docIndex >= this.pdfDocuments.length) return
952
+ const doc = this.pdfDocuments[docIndex]
953
+
954
+ const cacheKey = `${docIndex}-${objectId}`
955
+ let pageIndex = this.objectIndexCache[cacheKey]
956
+
957
+ if (pageIndex === undefined) {
958
+ pageIndex = findObjectPageIndex(doc, objectId)
959
+ if (pageIndex !== undefined) {
960
+ this.objectIndexCache[cacheKey] = pageIndex
961
+ }
962
+ }
963
+
964
+ if (pageIndex === undefined) return
965
+
966
+ const sourceObject = doc.allObjects[pageIndex]?.find(o => o.id === objectId)
967
+ if (!sourceObject) return
968
+
969
+ const { width: pageWidth, height: pageHeight } = this.getPageSize(docIndex, pageIndex)
970
+ const offset = 12
971
+ const { x, y } = clampPosition(
972
+ sourceObject.x + offset,
973
+ sourceObject.y + offset,
974
+ sourceObject.width,
975
+ sourceObject.height,
976
+ pageWidth,
977
+ pageHeight,
978
+ )
979
+
980
+ let duplicatedSigner = sourceObject.signer
981
+ if (duplicatedSigner?.element && Object.prototype.hasOwnProperty.call(duplicatedSigner.element, 'elementId')) {
982
+ duplicatedSigner = {
983
+ ...duplicatedSigner,
984
+ element: { ...duplicatedSigner.element },
985
+ }
986
+ delete duplicatedSigner.element.elementId
987
+ }
988
+
989
+ const duplicatedObject = {
990
+ ...sourceObject,
991
+ id: this.generateObjectId(),
992
+ x,
993
+ y,
994
+ signer: duplicatedSigner,
995
+ }
996
+
997
+ doc.allObjects[pageIndex].push(duplicatedObject)
998
+ this.objectIndexCache[`${docIndex}-${duplicatedObject.id}`] = pageIndex
999
+
1000
+ this.$nextTick(() => {
1001
+ const refKey = `draggable${docIndex}-${pageIndex}-${duplicatedObject.id}`
1002
+ const draggableRefs = this.$refs[refKey]
1003
+ if (draggableRefs && Array.isArray(draggableRefs) && draggableRefs[0]) {
1004
+ draggableRefs[0].isSelected = true
1005
+ }
1006
+ })
1007
+ },
943
1008
 
944
1009
  checkAndMoveObjectPage(docIndex, objectId, mouseX, mouseY) {
945
1010
  if (docIndex < 0 || docIndex >= this.pdfDocuments.length) return undefined