@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/README.md CHANGED
@@ -25,6 +25,7 @@ A Vue 2 component for rendering PDFs with draggable and resizable element overla
25
25
  | `showSelectionHandles` | Boolean | `true` | Show resize/move handles on selected elements |
26
26
  | `showElementActions` | Boolean | `true` | Show action buttons on selected elements |
27
27
  | `readOnly` | Boolean | `false` | Disable drag, resize, and actions for elements |
28
+ | `ignoreClickOutsideSelectors` | Array | `[]` | CSS selectors that keep the selection active when clicking outside the element |
28
29
  | `pageCountFormat` | String | `'{currentPage} of {totalPages}'` | Format string for page counter |
29
30
  | `autoFitZoom` | Boolean | `false` | Automatically adjust zoom to fit viewport on window resize |
30
31
 
@@ -37,4 +38,3 @@ A Vue 2 component for rendering PDFs with draggable and resizable element overla
37
38
  - `element-{type}` - Custom element rendering (e.g., `element-signature`)
38
39
  - `custom` - Fallback for elements without specific type
39
40
  - `actions` - Custom action buttons
40
-
@@ -2811,7 +2811,7 @@ if (typeof window !== 'undefined') {
2811
2811
  // Indicate to webpack that this file can be concatenated
2812
2812
  /* harmony default export */ const setPublicPath = (null);
2813
2813
 
2814
- ;// ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/PDFElements.vue?vue&type=template&id=ec3a4e5e&scoped=true
2814
+ ;// ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/PDFElements.vue?vue&type=template&id=46de43ea&scoped=true
2815
2815
  var render = function render() {
2816
2816
  var _vm = this,
2817
2817
  _c = _vm._self._c;
@@ -2892,6 +2892,7 @@ var render = function render() {
2892
2892
  "read-only": _vm.readOnly,
2893
2893
  "on-update": payload => _vm.updateObject(docIndex, object.id, payload),
2894
2894
  "on-delete": () => _vm.deleteObject(docIndex, object.id),
2895
+ "on-duplicate": () => _vm.duplicateObject(docIndex, object.id),
2895
2896
  "on-drag-start": (mouseX, mouseY, pointerOffset, dragShift) => _vm.startDraggingElement(docIndex, pIndex, object, mouseX, mouseY, pointerOffset, dragShift),
2896
2897
  "on-drag-move": _vm.updateDraggingPosition,
2897
2898
  "on-drag-end": _vm.stopDraggingElement,
@@ -2902,7 +2903,8 @@ var render = function render() {
2902
2903
  "global-drag-doc-index": _vm.draggingDocIndex,
2903
2904
  "global-drag-page-index": _vm.draggingPageIndex,
2904
2905
  "show-selection-ui": _vm.showSelectionHandles && !_vm.hideSelectionUI && object.resizable !== false,
2905
- "show-default-actions": _vm.showElementActions && !_vm.hideSelectionUI
2906
+ "show-default-actions": _vm.showElementActions && !_vm.hideSelectionUI,
2907
+ "ignore-click-outside-selectors": _vm.ignoreClickOutsideSelectors
2906
2908
  },
2907
2909
  scopedSlots: _vm._u([{
2908
2910
  key: "default",
@@ -2924,7 +2926,8 @@ var render = function render() {
2924
2926
  fn: function (slotProps) {
2925
2927
  return [_vm._t("actions", null, {
2926
2928
  "object": slotProps.object,
2927
- "onDelete": slotProps.onDelete
2929
+ "onDelete": slotProps.onDelete,
2930
+ "onDuplicate": slotProps.onDuplicate
2928
2931
  })];
2929
2932
  }
2930
2933
  }], null, true)
@@ -3201,8 +3204,8 @@ var component = normalizeComponent(
3201
3204
  )
3202
3205
 
3203
3206
  /* harmony default export */ const PDFPage = (component.exports);
3204
- ;// ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/DraggableElement.vue?vue&type=template&id=1fb13404&scoped=true
3205
- var DraggableElementvue_type_template_id_1fb13404_scoped_true_render = function render() {
3207
+ ;// ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/DraggableElement.vue?vue&type=template&id=9f1fd9e4&scoped=true
3208
+ var DraggableElementvue_type_template_id_9f1fd9e4_scoped_true_render = function render() {
3206
3209
  var _vm = this,
3207
3210
  _c = _vm._self._c;
3208
3211
  return _c('div', {
@@ -3212,6 +3215,29 @@ var DraggableElementvue_type_template_id_1fb13404_scoped_true_render = function
3212
3215
  style: _vm.toolbarStyle
3213
3216
  }, [_vm._t("actions", function () {
3214
3217
  return [_c('button', {
3218
+ staticClass: "action-btn",
3219
+ attrs: {
3220
+ "type": "button",
3221
+ "title": "Duplicate"
3222
+ },
3223
+ on: {
3224
+ "click": function ($event) {
3225
+ $event.stopPropagation();
3226
+ return _vm.onDuplicate.apply(null, arguments);
3227
+ }
3228
+ }
3229
+ }, [_c('svg', {
3230
+ attrs: {
3231
+ "width": "16",
3232
+ "height": "16",
3233
+ "viewBox": "0 0 24 24",
3234
+ "fill": "currentColor"
3235
+ }
3236
+ }, [_c('path', {
3237
+ attrs: {
3238
+ "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"
3239
+ }
3240
+ })])]), _c('button', {
3215
3241
  staticClass: "action-btn",
3216
3242
  attrs: {
3217
3243
  "type": "button",
@@ -3237,7 +3263,8 @@ var DraggableElementvue_type_template_id_1fb13404_scoped_true_render = function
3237
3263
  })])])];
3238
3264
  }, {
3239
3265
  "object": _vm.object,
3240
- "onDelete": _vm.onDelete
3266
+ "onDelete": _vm.onDelete,
3267
+ "onDuplicate": _vm.onDuplicate
3241
3268
  })], 2) : _vm._e(), _c('div', {
3242
3269
  staticClass: "draggable-element",
3243
3270
  class: {
@@ -3282,7 +3309,7 @@ var DraggableElementvue_type_template_id_1fb13404_scoped_true_render = function
3282
3309
  });
3283
3310
  }) : _vm._e()], 2)]);
3284
3311
  };
3285
- var DraggableElementvue_type_template_id_1fb13404_scoped_true_staticRenderFns = [];
3312
+ var DraggableElementvue_type_template_id_9f1fd9e4_scoped_true_staticRenderFns = [];
3286
3313
 
3287
3314
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/DraggableElement.vue?vue&type=script&lang=js
3288
3315
  /* harmony default export */ const DraggableElementvue_type_script_lang_js = ({
@@ -3312,6 +3339,10 @@ var DraggableElementvue_type_template_id_1fb13404_scoped_true_staticRenderFns =
3312
3339
  type: Function,
3313
3340
  default: () => {}
3314
3341
  },
3342
+ onDuplicate: {
3343
+ type: Function,
3344
+ default: () => {}
3345
+ },
3315
3346
  onDragStart: {
3316
3347
  type: Function,
3317
3348
  default: () => {}
@@ -3362,6 +3393,10 @@ var DraggableElementvue_type_template_id_1fb13404_scoped_true_staticRenderFns =
3362
3393
  readOnly: {
3363
3394
  type: Boolean,
3364
3395
  default: false
3396
+ },
3397
+ ignoreClickOutsideSelectors: {
3398
+ type: Array,
3399
+ default: () => []
3365
3400
  }
3366
3401
  },
3367
3402
  data() {
@@ -3478,6 +3513,12 @@ var DraggableElementvue_type_template_id_1fb13404_scoped_true_staticRenderFns =
3478
3513
  this.startDrag(event);
3479
3514
  },
3480
3515
  handleClickOutside(event) {
3516
+ const selectors = Array.isArray(this.ignoreClickOutsideSelectors) ? this.ignoreClickOutsideSelectors : [];
3517
+ for (const selector of selectors) {
3518
+ if (selector && event?.target?.closest?.(selector)) {
3519
+ return;
3520
+ }
3521
+ }
3481
3522
  if (this.$el && !this.$el.contains(event.target)) {
3482
3523
  this.isSelected = false;
3483
3524
  }
@@ -3692,10 +3733,10 @@ var DraggableElementvue_type_template_id_1fb13404_scoped_true_staticRenderFns =
3692
3733
  });
3693
3734
  ;// ./src/components/DraggableElement.vue?vue&type=script&lang=js
3694
3735
  /* harmony default export */ const components_DraggableElementvue_type_script_lang_js = (DraggableElementvue_type_script_lang_js);
3695
- ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/DraggableElement.vue?vue&type=style&index=0&id=1fb13404&prod&scoped=true&lang=css
3736
+ ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/DraggableElement.vue?vue&type=style&index=0&id=9f1fd9e4&prod&scoped=true&lang=css
3696
3737
  // extracted by mini-css-extract-plugin
3697
3738
 
3698
- ;// ./src/components/DraggableElement.vue?vue&type=style&index=0&id=1fb13404&prod&scoped=true&lang=css
3739
+ ;// ./src/components/DraggableElement.vue?vue&type=style&index=0&id=9f1fd9e4&prod&scoped=true&lang=css
3699
3740
 
3700
3741
  ;// ./src/components/DraggableElement.vue
3701
3742
 
@@ -3708,11 +3749,11 @@ var DraggableElementvue_type_template_id_1fb13404_scoped_true_staticRenderFns =
3708
3749
 
3709
3750
  var DraggableElement_component = normalizeComponent(
3710
3751
  components_DraggableElementvue_type_script_lang_js,
3711
- DraggableElementvue_type_template_id_1fb13404_scoped_true_render,
3712
- DraggableElementvue_type_template_id_1fb13404_scoped_true_staticRenderFns,
3752
+ DraggableElementvue_type_template_id_9f1fd9e4_scoped_true_render,
3753
+ DraggableElementvue_type_template_id_9f1fd9e4_scoped_true_staticRenderFns,
3713
3754
  false,
3714
3755
  null,
3715
- "1fb13404",
3756
+ "9f1fd9e4",
3716
3757
  null
3717
3758
 
3718
3759
  )
@@ -30297,6 +30338,10 @@ function getCachedMeasurement(cache, cacheKey, pageRef, pagesScale) {
30297
30338
  type: Boolean,
30298
30339
  default: false
30299
30340
  },
30341
+ ignoreClickOutsideSelectors: {
30342
+ type: Array,
30343
+ default: () => []
30344
+ },
30300
30345
  pageCountFormat: {
30301
30346
  type: String,
30302
30347
  default: '{currentPage} of {totalPages}'
@@ -31027,6 +31072,56 @@ function getCachedMeasurement(cache, cacheKey, pageRef, pagesScale) {
31027
31072
  });
31028
31073
  }
31029
31074
  },
31075
+ duplicateObject(docIndex, objectId) {
31076
+ if (docIndex < 0 || docIndex >= this.pdfDocuments.length) return;
31077
+ const doc = this.pdfDocuments[docIndex];
31078
+ const cacheKey = `${docIndex}-${objectId}`;
31079
+ let pageIndex = this.objectIndexCache[cacheKey];
31080
+ if (pageIndex === undefined) {
31081
+ pageIndex = findObjectPageIndex(doc, objectId);
31082
+ if (pageIndex !== undefined) {
31083
+ this.objectIndexCache[cacheKey] = pageIndex;
31084
+ }
31085
+ }
31086
+ if (pageIndex === undefined) return;
31087
+ const sourceObject = doc.allObjects[pageIndex]?.find(o => o.id === objectId);
31088
+ if (!sourceObject) return;
31089
+ const {
31090
+ width: pageWidth,
31091
+ height: pageHeight
31092
+ } = this.getPageSize(docIndex, pageIndex);
31093
+ const offset = 12;
31094
+ const {
31095
+ x,
31096
+ y
31097
+ } = clampPosition(sourceObject.x + offset, sourceObject.y + offset, sourceObject.width, sourceObject.height, pageWidth, pageHeight);
31098
+ let duplicatedSigner = sourceObject.signer;
31099
+ if (duplicatedSigner?.element && Object.prototype.hasOwnProperty.call(duplicatedSigner.element, 'elementId')) {
31100
+ duplicatedSigner = {
31101
+ ...duplicatedSigner,
31102
+ element: {
31103
+ ...duplicatedSigner.element
31104
+ }
31105
+ };
31106
+ delete duplicatedSigner.element.elementId;
31107
+ }
31108
+ const duplicatedObject = {
31109
+ ...sourceObject,
31110
+ id: this.generateObjectId(),
31111
+ x,
31112
+ y,
31113
+ signer: duplicatedSigner
31114
+ };
31115
+ doc.allObjects[pageIndex].push(duplicatedObject);
31116
+ this.objectIndexCache[`${docIndex}-${duplicatedObject.id}`] = pageIndex;
31117
+ this.$nextTick(() => {
31118
+ const refKey = `draggable${docIndex}-${pageIndex}-${duplicatedObject.id}`;
31119
+ const draggableRefs = this.$refs[refKey];
31120
+ if (draggableRefs && Array.isArray(draggableRefs) && draggableRefs[0]) {
31121
+ draggableRefs[0].isSelected = true;
31122
+ }
31123
+ });
31124
+ },
31030
31125
  checkAndMoveObjectPage(docIndex, objectId, mouseX, mouseY) {
31031
31126
  if (docIndex < 0 || docIndex >= this.pdfDocuments.length) return undefined;
31032
31127
  const doc = this.pdfDocuments[docIndex];
@@ -31162,10 +31257,10 @@ function getCachedMeasurement(cache, cacheKey, pageRef, pagesScale) {
31162
31257
  });
31163
31258
  ;// ./src/components/PDFElements.vue?vue&type=script&lang=js
31164
31259
  /* harmony default export */ const components_PDFElementsvue_type_script_lang_js = (PDFElementsvue_type_script_lang_js);
31165
- ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/PDFElements.vue?vue&type=style&index=0&id=ec3a4e5e&prod&scoped=true&lang=css
31260
+ ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/PDFElements.vue?vue&type=style&index=0&id=46de43ea&prod&scoped=true&lang=css
31166
31261
  // extracted by mini-css-extract-plugin
31167
31262
 
31168
- ;// ./src/components/PDFElements.vue?vue&type=style&index=0&id=ec3a4e5e&prod&scoped=true&lang=css
31263
+ ;// ./src/components/PDFElements.vue?vue&type=style&index=0&id=46de43ea&prod&scoped=true&lang=css
31169
31264
 
31170
31265
  ;// ./src/components/PDFElements.vue
31171
31266
 
@@ -31182,7 +31277,7 @@ var PDFElements_component = normalizeComponent(
31182
31277
  staticRenderFns,
31183
31278
  false,
31184
31279
  null,
31185
- "ec3a4e5e",
31280
+ "46de43ea",
31186
31281
  null
31187
31282
 
31188
31283
  )