@signiphi/pdf-signer 0.2.0-beta.2 → 0.2.0-beta.21

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 (197) hide show
  1. package/assets/viewer.html +1 -5
  2. package/dist/components/index.js +2746 -901
  3. package/dist/components/index.js.map +1 -1
  4. package/dist/components/index.mjs +2513 -669
  5. package/dist/components/index.mjs.map +1 -1
  6. package/dist/core/index.js +420 -20
  7. package/dist/core/index.js.map +1 -1
  8. package/dist/core/index.mjs +420 -20
  9. package/dist/core/index.mjs.map +1 -1
  10. package/dist/hooks/index.js +506 -211
  11. package/dist/hooks/index.js.map +1 -1
  12. package/dist/hooks/index.mjs +507 -212
  13. package/dist/hooks/index.mjs.map +1 -1
  14. package/dist/index.css +214 -191
  15. package/dist/index.css.map +1 -1
  16. package/dist/index.js +3019 -893
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +2762 -653
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/styles/index.css +202 -172
  21. package/dist/types/index.js.map +1 -1
  22. package/dist/types/index.mjs.map +1 -1
  23. package/dist/utils/index.js +792 -147
  24. package/dist/utils/index.js.map +1 -1
  25. package/dist/utils/index.mjs +777 -148
  26. package/dist/utils/index.mjs.map +1 -1
  27. package/package.json +2 -2
  28. package/scripts/copy-utils.js +14 -3
  29. package/src/styles/index.css +33 -3
  30. package/dist/__tests__/helpers/fixtures.d.ts +0 -43
  31. package/dist/__tests__/helpers/fixtures.d.ts.map +0 -1
  32. package/dist/__tests__/helpers/mocks.d.ts +0 -333
  33. package/dist/__tests__/helpers/mocks.d.ts.map +0 -1
  34. package/dist/__tests__/setup.d.ts +0 -6
  35. package/dist/__tests__/setup.d.ts.map +0 -1
  36. package/dist/components/AcknowledgementModal.d.ts +0 -21
  37. package/dist/components/AcknowledgementModal.d.ts.map +0 -1
  38. package/dist/components/AcknowledgementsSidebar.d.ts +0 -22
  39. package/dist/components/AcknowledgementsSidebar.d.ts.map +0 -1
  40. package/dist/components/AttachmentUpload.d.ts +0 -17
  41. package/dist/components/AttachmentUpload.d.ts.map +0 -1
  42. package/dist/components/EditableFieldsPanel.d.ts +0 -30
  43. package/dist/components/EditableFieldsPanel.d.ts.map +0 -1
  44. package/dist/components/ErrorBoundary.d.ts +0 -67
  45. package/dist/components/ErrorBoundary.d.ts.map +0 -1
  46. package/dist/components/FormFieldsView.d.ts +0 -46
  47. package/dist/components/FormFieldsView.d.ts.map +0 -1
  48. package/dist/components/InitialsModal.d.ts +0 -16
  49. package/dist/components/InitialsModal.d.ts.map +0 -1
  50. package/dist/components/PdfViewerStyled.d.ts +0 -16
  51. package/dist/components/PdfViewerStyled.d.ts.map +0 -1
  52. package/dist/components/PoweredBySigniphi.d.ts +0 -11
  53. package/dist/components/PoweredBySigniphi.d.ts.map +0 -1
  54. package/dist/components/RequiredFieldNavigation.d.ts +0 -18
  55. package/dist/components/RequiredFieldNavigation.d.ts.map +0 -1
  56. package/dist/components/SignatureCanvas.d.ts +0 -12
  57. package/dist/components/SignatureCanvas.d.ts.map +0 -1
  58. package/dist/components/SignatureInitialsBox.d.ts +0 -25
  59. package/dist/components/SignatureInitialsBox.d.ts.map +0 -1
  60. package/dist/components/SignatureModal.d.ts +0 -21
  61. package/dist/components/SignatureModal.d.ts.map +0 -1
  62. package/dist/components/SigningInstructions.d.ts +0 -12
  63. package/dist/components/SigningInstructions.d.ts.map +0 -1
  64. package/dist/components/SubmissionForm.d.ts +0 -52
  65. package/dist/components/SubmissionForm.d.ts.map +0 -1
  66. package/dist/components/UnacknowledgedFieldsModal.d.ts +0 -23
  67. package/dist/components/UnacknowledgedFieldsModal.d.ts.map +0 -1
  68. package/dist/components/ViewToggleToolbar.d.ts +0 -38
  69. package/dist/components/ViewToggleToolbar.d.ts.map +0 -1
  70. package/dist/components/form-fields/CheckboxRenderer.d.ts +0 -10
  71. package/dist/components/form-fields/CheckboxRenderer.d.ts.map +0 -1
  72. package/dist/components/form-fields/DateFieldRenderer.d.ts +0 -14
  73. package/dist/components/form-fields/DateFieldRenderer.d.ts.map +0 -1
  74. package/dist/components/form-fields/DropdownRenderer.d.ts +0 -14
  75. package/dist/components/form-fields/DropdownRenderer.d.ts.map +0 -1
  76. package/dist/components/form-fields/FormFieldRenderer.d.ts +0 -22
  77. package/dist/components/form-fields/FormFieldRenderer.d.ts.map +0 -1
  78. package/dist/components/form-fields/InitialsFieldRenderer.d.ts +0 -16
  79. package/dist/components/form-fields/InitialsFieldRenderer.d.ts.map +0 -1
  80. package/dist/components/form-fields/RadioGroupRenderer.d.ts +0 -10
  81. package/dist/components/form-fields/RadioGroupRenderer.d.ts.map +0 -1
  82. package/dist/components/form-fields/SignatureFieldRenderer.d.ts +0 -16
  83. package/dist/components/form-fields/SignatureFieldRenderer.d.ts.map +0 -1
  84. package/dist/components/form-fields/TextFieldRenderer.d.ts +0 -14
  85. package/dist/components/form-fields/TextFieldRenderer.d.ts.map +0 -1
  86. package/dist/components/form-fields/TextLabelRenderer.d.ts +0 -14
  87. package/dist/components/form-fields/TextLabelRenderer.d.ts.map +0 -1
  88. package/dist/components/form-fields/index.d.ts +0 -14
  89. package/dist/components/form-fields/index.d.ts.map +0 -1
  90. package/dist/components/index.d.ts +0 -17
  91. package/dist/components/index.d.ts.map +0 -1
  92. package/dist/core/PdfViewerCore.d.ts +0 -19
  93. package/dist/core/PdfViewerCore.d.ts.map +0 -1
  94. package/dist/core/SignatureCaptureCore.d.ts +0 -37
  95. package/dist/core/SignatureCaptureCore.d.ts.map +0 -1
  96. package/dist/core/index.d.ts +0 -3
  97. package/dist/core/index.d.ts.map +0 -1
  98. package/dist/hooks/index.d.ts +0 -9
  99. package/dist/hooks/index.d.ts.map +0 -1
  100. package/dist/hooks/useAcknowledgements.d.ts +0 -50
  101. package/dist/hooks/useAcknowledgements.d.ts.map +0 -1
  102. package/dist/hooks/useAttachments.d.ts +0 -25
  103. package/dist/hooks/useAttachments.d.ts.map +0 -1
  104. package/dist/hooks/useFieldFiltering.d.ts +0 -29
  105. package/dist/hooks/useFieldFiltering.d.ts.map +0 -1
  106. package/dist/hooks/useFormFields.d.ts +0 -23
  107. package/dist/hooks/useFormFields.d.ts.map +0 -1
  108. package/dist/hooks/useMultiSignerContext.d.ts +0 -25
  109. package/dist/hooks/useMultiSignerContext.d.ts.map +0 -1
  110. package/dist/hooks/usePdfViewer.d.ts +0 -52
  111. package/dist/hooks/usePdfViewer.d.ts.map +0 -1
  112. package/dist/hooks/useRequiredFieldNavigation.d.ts +0 -16
  113. package/dist/hooks/useRequiredFieldNavigation.d.ts.map +0 -1
  114. package/dist/hooks/useSignatureCapture.d.ts +0 -17
  115. package/dist/hooks/useSignatureCapture.d.ts.map +0 -1
  116. package/dist/hooks/useSignatures.d.ts +0 -29
  117. package/dist/hooks/useSignatures.d.ts.map +0 -1
  118. package/dist/index.d.ts +0 -17
  119. package/dist/index.d.ts.map +0 -1
  120. package/dist/integrations/index.d.ts +0 -6
  121. package/dist/integrations/index.d.ts.map +0 -1
  122. package/dist/integrations/next-config.d.ts +0 -46
  123. package/dist/integrations/next-config.d.ts.map +0 -1
  124. package/dist/integrations/vite-plugin.d.ts +0 -48
  125. package/dist/integrations/vite-plugin.d.ts.map +0 -1
  126. package/dist/lib/index.d.ts +0 -3
  127. package/dist/lib/index.d.ts.map +0 -1
  128. package/dist/lib/ui/accordion.d.ts +0 -8
  129. package/dist/lib/ui/accordion.d.ts.map +0 -1
  130. package/dist/lib/ui/alert.d.ts +0 -9
  131. package/dist/lib/ui/alert.d.ts.map +0 -1
  132. package/dist/lib/ui/button.d.ts +0 -12
  133. package/dist/lib/ui/button.d.ts.map +0 -1
  134. package/dist/lib/ui/calendar.d.ts +0 -10
  135. package/dist/lib/ui/calendar.d.ts.map +0 -1
  136. package/dist/lib/ui/card.d.ts +0 -9
  137. package/dist/lib/ui/card.d.ts.map +0 -1
  138. package/dist/lib/ui/checkbox.d.ts +0 -5
  139. package/dist/lib/ui/checkbox.d.ts.map +0 -1
  140. package/dist/lib/ui/dialog.d.ts +0 -20
  141. package/dist/lib/ui/dialog.d.ts.map +0 -1
  142. package/dist/lib/ui/index.d.ts +0 -13
  143. package/dist/lib/ui/index.d.ts.map +0 -1
  144. package/dist/lib/ui/input.d.ts +0 -6
  145. package/dist/lib/ui/input.d.ts.map +0 -1
  146. package/dist/lib/ui/label.d.ts +0 -6
  147. package/dist/lib/ui/label.d.ts.map +0 -1
  148. package/dist/lib/ui/popover.d.ts +0 -7
  149. package/dist/lib/ui/popover.d.ts.map +0 -1
  150. package/dist/lib/ui/radio-group.d.ts +0 -6
  151. package/dist/lib/ui/radio-group.d.ts.map +0 -1
  152. package/dist/lib/ui/select.d.ts +0 -14
  153. package/dist/lib/ui/select.d.ts.map +0 -1
  154. package/dist/lib/utils.d.ts +0 -7
  155. package/dist/lib/utils.d.ts.map +0 -1
  156. package/dist/types/index.d.ts +0 -278
  157. package/dist/types/index.d.ts.map +0 -1
  158. package/dist/utils/attachment-validators.d.ts +0 -118
  159. package/dist/utils/attachment-validators.d.ts.map +0 -1
  160. package/dist/utils/audit-trail.d.ts +0 -27
  161. package/dist/utils/audit-trail.d.ts.map +0 -1
  162. package/dist/utils/date-validation.d.ts +0 -30
  163. package/dist/utils/date-validation.d.ts.map +0 -1
  164. package/dist/utils/errors.d.ts +0 -106
  165. package/dist/utils/errors.d.ts.map +0 -1
  166. package/dist/utils/field-extraction.d.ts +0 -36
  167. package/dist/utils/field-extraction.d.ts.map +0 -1
  168. package/dist/utils/field-visibility.d.ts +0 -104
  169. package/dist/utils/field-visibility.d.ts.map +0 -1
  170. package/dist/utils/index.d.ts +0 -18
  171. package/dist/utils/index.d.ts.map +0 -1
  172. package/dist/utils/logger.d.ts +0 -16
  173. package/dist/utils/logger.d.ts.map +0 -1
  174. package/dist/utils/pdf-field-type-helpers.d.ts +0 -78
  175. package/dist/utils/pdf-field-type-helpers.d.ts.map +0 -1
  176. package/dist/utils/pdf-helpers.d.ts +0 -38
  177. package/dist/utils/pdf-helpers.d.ts.map +0 -1
  178. package/dist/utils/pdf-lib-loader.d.ts +0 -45
  179. package/dist/utils/pdf-lib-loader.d.ts.map +0 -1
  180. package/dist/utils/pdf-manipulation.d.ts +0 -93
  181. package/dist/utils/pdf-manipulation.d.ts.map +0 -1
  182. package/dist/utils/pdf-metadata.d.ts +0 -41
  183. package/dist/utils/pdf-metadata.d.ts.map +0 -1
  184. package/dist/utils/pdf-validators.d.ts +0 -149
  185. package/dist/utils/pdf-validators.d.ts.map +0 -1
  186. package/dist/utils/pdf-viewer-filter.d.ts +0 -35
  187. package/dist/utils/pdf-viewer-filter.d.ts.map +0 -1
  188. package/dist/utils/pdf-widget-helpers.d.ts +0 -98
  189. package/dist/utils/pdf-widget-helpers.d.ts.map +0 -1
  190. package/dist/utils/pdfjs-config.d.ts +0 -56
  191. package/dist/utils/pdfjs-config.d.ts.map +0 -1
  192. package/dist/utils/pdfjs-version-check.d.ts +0 -28
  193. package/dist/utils/pdfjs-version-check.d.ts.map +0 -1
  194. package/dist/utils/performance-monitor.d.ts +0 -172
  195. package/dist/utils/performance-monitor.d.ts.map +0 -1
  196. package/dist/utils/tracking.d.ts +0 -89
  197. package/dist/utils/tracking.d.ts.map +0 -1
@@ -78,6 +78,7 @@ function validatePdfBytes(pdfBytes) {
78
78
  }
79
79
  function isAutoGeneratedLabel(label) {
80
80
  if (!label || !label.trim()) return true;
81
+ const trimmed = label.trim();
81
82
  const autoLabels = [
82
83
  "Signature",
83
84
  "Initials",
@@ -88,7 +89,65 @@ function isAutoGeneratedLabel(label) {
88
89
  "Option",
89
90
  "Radio"
90
91
  ];
91
- return autoLabels.includes(label.trim());
92
+ if (autoLabels.includes(trimmed)) return true;
93
+ if (/^\d{10,}$/.test(trimmed)) return true;
94
+ const typeTimestampPattern = new RegExp(
95
+ `^(${autoLabels.join("|")})[\\s_-]?\\d{10,}$`,
96
+ "i"
97
+ );
98
+ if (typeTimestampPattern.test(trimmed)) return true;
99
+ const typeNumberPattern = new RegExp(
100
+ `^(${autoLabels.join("|")})[\\s_-]?\\d{1,3}$`,
101
+ "i"
102
+ );
103
+ if (typeNumberPattern.test(trimmed)) return true;
104
+ const typeWordsJoined = autoLabels.join("|");
105
+ const corruptedPattern = new RegExp(
106
+ `^(${typeWordsJoined})[\\s_-]?\\d{10,}[\\s_-]?(${typeWordsJoined})+`,
107
+ "i"
108
+ );
109
+ if (corruptedPattern.test(trimmed)) return true;
110
+ const repeatedTypePattern = new RegExp(
111
+ `^((${typeWordsJoined})[\\s_-]+)+(${typeWordsJoined})$`,
112
+ "i"
113
+ );
114
+ if (repeatedTypePattern.test(trimmed)) return true;
115
+ return false;
116
+ }
117
+ function hasDrawableLabel(field) {
118
+ if (!field.label || !field.label.trim()) return false;
119
+ if (field.isLabelAutoGenerated) return false;
120
+ if (isAutoGeneratedLabel(field.label)) return false;
121
+ return true;
122
+ }
123
+ function getFieldDisplayName(field) {
124
+ if (field.label && !isAutoGeneratedLabel(field.label)) {
125
+ return field.label;
126
+ }
127
+ const typeNames = {
128
+ "text": "Text field",
129
+ "signature": "Signature",
130
+ "initials": "Initials",
131
+ "date": "Date field",
132
+ "checkbox": "Checkbox",
133
+ "dropdown": "Dropdown",
134
+ "radio": "Radio selection",
135
+ "radiogroup": "Radio selection",
136
+ "text_label": "Text label"
137
+ };
138
+ if (field.type) {
139
+ const typeName = typeNames[field.type.toLowerCase()];
140
+ if (typeName) {
141
+ return typeName;
142
+ }
143
+ }
144
+ if (field.name) {
145
+ let cleaned = field.name.replace(/_?(signature|initials|date)$/i, "").replace(/[_-]\d{10,}$/, "").replace(/[_-]/g, " ").trim();
146
+ if (cleaned && !isAutoGeneratedLabel(cleaned)) {
147
+ return cleaned.replace(/\b\w/g, (l) => l.toUpperCase());
148
+ }
149
+ }
150
+ return "This field";
92
151
  }
93
152
  function validateFieldValues(values) {
94
153
  const errors = [];
@@ -324,6 +383,114 @@ function getSigniphiMetadata(pdfDoc) {
324
383
  }
325
384
  }
326
385
 
386
+ // src/utils/font-loader.ts
387
+ var SIGNATURE_FONTS = [
388
+ { name: "dancing-script", family: "Dancing Script", label: "Elegant" },
389
+ { name: "great-vibes", family: "Great Vibes", label: "Formal" },
390
+ { name: "caveat", family: "Caveat", label: "Casual" },
391
+ { name: "homemade-apple", family: "Homemade Apple", label: "Natural" },
392
+ { name: "sacramento", family: "Sacramento", label: "Flowing" }
393
+ ];
394
+ var DEFAULT_SIGNATURE_FONT = {
395
+ name: "dancing-script",
396
+ family: "Dancing Script",
397
+ label: "Elegant"
398
+ };
399
+ var GOOGLE_FONTS_URL = "https://fonts.googleapis.com/css2?family=Dancing+Script&family=Great+Vibes&family=Caveat&family=Homemade+Apple&family=Sacramento&display=swap";
400
+ var fontsLoaded = false;
401
+ var fontsLoadingPromise = null;
402
+ async function loadSignatureFonts() {
403
+ if (fontsLoaded) {
404
+ return;
405
+ }
406
+ if (fontsLoadingPromise) {
407
+ return fontsLoadingPromise;
408
+ }
409
+ fontsLoadingPromise = new Promise((resolve, reject) => {
410
+ const existingLink = document.querySelector(
411
+ `link[href="${GOOGLE_FONTS_URL}"]`
412
+ );
413
+ if (existingLink) {
414
+ fontsLoaded = true;
415
+ resolve();
416
+ return;
417
+ }
418
+ const link = document.createElement("link");
419
+ link.href = GOOGLE_FONTS_URL;
420
+ link.rel = "stylesheet";
421
+ link.onload = () => {
422
+ fontsLoaded = true;
423
+ resolve();
424
+ };
425
+ link.onerror = () => {
426
+ fontsLoadingPromise = null;
427
+ reject(new Error("Failed to load signature fonts from Google Fonts"));
428
+ };
429
+ document.head.appendChild(link);
430
+ });
431
+ return fontsLoadingPromise;
432
+ }
433
+ function isFontLoaded(fontFamily) {
434
+ if (typeof document === "undefined") {
435
+ return false;
436
+ }
437
+ return document.fonts.check(`48px "${fontFamily}"`);
438
+ }
439
+ async function waitForFont(fontFamily) {
440
+ if (typeof document === "undefined") {
441
+ return false;
442
+ }
443
+ try {
444
+ await document.fonts.load(`48px "${fontFamily}"`);
445
+ return true;
446
+ } catch {
447
+ return false;
448
+ }
449
+ }
450
+ function generateSignatureFromText(options) {
451
+ const {
452
+ text,
453
+ fontFamily,
454
+ width = 450,
455
+ height = 200,
456
+ fontSize = 48,
457
+ color = "#000000",
458
+ backgroundColor = null
459
+ } = options;
460
+ const canvas = document.createElement("canvas");
461
+ canvas.width = width;
462
+ canvas.height = height;
463
+ const ctx = canvas.getContext("2d");
464
+ if (!ctx) {
465
+ throw new Error("Failed to get canvas 2d context");
466
+ }
467
+ if (backgroundColor) {
468
+ ctx.fillStyle = backgroundColor;
469
+ ctx.fillRect(0, 0, width, height);
470
+ } else {
471
+ ctx.clearRect(0, 0, width, height);
472
+ }
473
+ ctx.font = `${fontSize}px "${fontFamily}"`;
474
+ ctx.fillStyle = color;
475
+ ctx.textAlign = "center";
476
+ ctx.textBaseline = "middle";
477
+ let adjustedFontSize = fontSize;
478
+ let textMetrics = ctx.measureText(text);
479
+ const maxWidth = width * 0.9;
480
+ while (textMetrics.width > maxWidth && adjustedFontSize > 16) {
481
+ adjustedFontSize -= 2;
482
+ ctx.font = `${adjustedFontSize}px "${fontFamily}"`;
483
+ textMetrics = ctx.measureText(text);
484
+ }
485
+ ctx.fillText(text, width / 2, height / 2);
486
+ return canvas.toDataURL("image/png");
487
+ }
488
+ async function generateSignatureFromTextAsync(options) {
489
+ await loadSignatureFonts();
490
+ await waitForFont(options.fontFamily);
491
+ return generateSignatureFromText(options);
492
+ }
493
+
327
494
  // src/utils/pdf-lib-loader.ts
328
495
  var pdfLibPromise = null;
329
496
  async function loadPdfLib() {
@@ -338,18 +505,15 @@ function isFieldVisibleToSigner(field, multiSignerContext) {
338
505
  if (!multiSignerContext.isMultiSigner) {
339
506
  return true;
340
507
  }
341
- const { currentSignerEmail, isPrimarySigner, isFinalSigner } = multiSignerContext;
508
+ const { currentSignerEmail } = multiSignerContext;
342
509
  if (!field.assignedSignerEmail) {
343
- return isFinalSigner;
510
+ return true;
344
511
  }
345
512
  if (field.assignedSignerEmail === currentSignerEmail) {
346
513
  return true;
347
514
  }
348
- if (field.assignedSignerEmail.includes("recipients")) {
349
- return isPrimarySigner;
350
- }
351
- if (field.assignedSignerEmail.includes("signers")) {
352
- return isFinalSigner;
515
+ if (field.assignedSignerEmail === "to-recipients" || field.assignedSignerEmail === "additional-signers") {
516
+ return true;
353
517
  }
354
518
  return false;
355
519
  }
@@ -363,18 +527,15 @@ function shouldFlattenField(field, multiSignerContext) {
363
527
  if (!multiSignerContext.isMultiSigner) {
364
528
  return true;
365
529
  }
366
- const { currentSignerEmail, isPrimarySigner, isFinalSigner } = multiSignerContext;
530
+ const { currentSignerEmail } = multiSignerContext;
367
531
  if (!field.assignedSignerEmail) {
368
- return isFinalSigner;
532
+ return true;
369
533
  }
370
534
  if (field.assignedSignerEmail === currentSignerEmail) {
371
535
  return true;
372
536
  }
373
- if (field.assignedSignerEmail.includes("recipients")) {
374
- return isPrimarySigner;
375
- }
376
- if (field.assignedSignerEmail.includes("signers")) {
377
- return isFinalSigner;
537
+ if (field.assignedSignerEmail === "to-recipients" || field.assignedSignerEmail === "additional-signers") {
538
+ return true;
378
539
  }
379
540
  return false;
380
541
  }
@@ -414,18 +575,23 @@ function findPageIndexWithFallback(pages, pageRef) {
414
575
 
415
576
  // src/utils/pdf-field-type-helpers.ts
416
577
  function detectFieldType(field) {
417
- const typeName = field.constructor.name;
418
- if (typeName === "PDFTextField") {
419
- return "text";
420
- } else if (typeName === "PDFCheckBox") {
578
+ const f = field;
579
+ if (typeof f.check === "function" && typeof f.uncheck === "function") {
421
580
  return "checkbox";
422
- } else if (typeName === "PDFDropdown") {
581
+ }
582
+ if (typeof f.select === "function" && typeof f.getOptions === "function" && typeof f.check !== "function" && typeof f.setOptions !== "function") {
583
+ return "radiogroup";
584
+ }
585
+ if (typeof f.select === "function" && typeof f.getOptions === "function" && (typeof f.setOptions === "function" || typeof f.addOptions === "function")) {
423
586
  return "dropdown";
424
- } else if (typeName === "PDFOptionList") {
587
+ }
588
+ if (typeof f.getOptions === "function" && typeof f.setOptions === "function" && typeof f.select !== "function") {
425
589
  return "optionlist";
426
- } else if (typeName === "PDFRadioGroup") {
427
- return "radiogroup";
428
- } else if (typeName === "PDFSignature") {
590
+ }
591
+ if (typeof f.getText === "function" && typeof f.setText === "function") {
592
+ return "text";
593
+ }
594
+ if (typeof f.getText !== "function" && typeof f.check !== "function" && typeof f.select !== "function") {
429
595
  return "signature";
430
596
  }
431
597
  return "unknown";
@@ -434,13 +600,20 @@ function extractFieldValue(field, fieldType) {
434
600
  try {
435
601
  switch (fieldType) {
436
602
  case "text":
603
+ case "date":
437
604
  return field.getText?.() || "";
438
605
  case "checkbox":
439
606
  return field.isChecked?.() ? "true" : "false";
440
607
  case "dropdown":
441
- case "optionlist":
608
+ case "optionlist": {
609
+ const selected = field.getSelected?.();
610
+ return Array.isArray(selected) ? selected[0] || "" : String(selected || "");
611
+ }
442
612
  case "radiogroup":
443
- return field.getSelected?.()?.[0] || "";
613
+ case "radio": {
614
+ const radioSelected = field.getSelected?.();
615
+ return radioSelected ? String(radioSelected) : "";
616
+ }
444
617
  default:
445
618
  return "";
446
619
  }
@@ -744,12 +917,16 @@ async function validatePdfFormFields(pdfBytes, fieldValues, signatures, extracte
744
917
  const errors = [];
745
918
  for (const field of pdfFormFields) {
746
919
  if (field.required) {
920
+ const extractedField = extractedFields?.find((f) => f.name === field.name);
747
921
  if (multiSignerContext?.isMultiSigner && extractedFields) {
748
- const extractedField = extractedFields.find((f) => f.name === field.name);
749
922
  if (!extractedField) {
750
923
  continue;
751
924
  }
752
925
  }
926
+ const logicalType = extractedField?.type || field.type;
927
+ if (logicalType === "date" || logicalType === "signature" || logicalType === "initials") {
928
+ continue;
929
+ }
753
930
  let hasValue = false;
754
931
  const fieldValue = fieldValues[field.name];
755
932
  const signatureValue = signatures[field.name];
@@ -759,16 +936,17 @@ async function validatePdfFormFields(pdfBytes, fieldValues, signatures, extracte
759
936
  hasValue = !!(signatureValue || fieldValue || mainSignature);
760
937
  } else if (field.name.includes("initials")) {
761
938
  hasValue = !!(signatureValue || fieldValue || mainInitials);
939
+ } else if (field.type === "checkbox" || logicalType === "checkbox") {
940
+ hasValue = fieldValue === "true" || field.value === "true";
762
941
  } else {
763
942
  hasValue = !!(fieldValue || field.value);
764
943
  }
765
944
  if (!hasValue) {
766
- let friendlyName = field.name.replace(/[_-]/g, " ").replace(/\b\w/g, (l) => l.toUpperCase());
767
- if (field.name.includes("signature")) {
768
- friendlyName = "Signature";
769
- } else if (field.name.includes("initials")) {
770
- friendlyName = "Initials";
771
- }
945
+ const friendlyName = getFieldDisplayName({
946
+ label: extractedField?.label,
947
+ name: field.name,
948
+ type: logicalType
949
+ });
772
950
  errors.push(`${friendlyName} is required`);
773
951
  }
774
952
  }
@@ -798,12 +976,10 @@ async function validateCurrentPdfState(pdfBytes, signatures, formFieldValues = {
798
976
  hasValue = currentValue.trim() !== "";
799
977
  }
800
978
  if (!hasValue) {
801
- let friendlyName = field.name.replace(/[_-]/g, " ").replace(/\b\w/g, (l) => l.toUpperCase());
802
- if (field.name.includes("signature")) {
803
- friendlyName = "Signature";
804
- } else if (field.name.includes("initials")) {
805
- friendlyName = "Initials";
806
- }
979
+ const friendlyName = getFieldDisplayName({
980
+ name: field.name,
981
+ type: field.type
982
+ });
807
983
  errors.push(`${friendlyName} is required`);
808
984
  }
809
985
  }
@@ -814,7 +990,80 @@ async function validateCurrentPdfState(pdfBytes, signatures, formFieldValues = {
814
990
  throw error;
815
991
  }
816
992
  }
817
- async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {}, currentSignerEmail, extractedFormFields, metadata, auditTrail, multiSignerContext) {
993
+ function extractFieldFontSize(fieldName, field, extractedFormFields) {
994
+ const DEFAULT_FONT_SIZE = 10;
995
+ const MIN_FONT_SIZE = 8;
996
+ const MAX_FONT_SIZE = 72;
997
+ const fieldInfo = extractedFormFields?.find((f) => f.name === fieldName);
998
+ if (fieldInfo?.fontSize && fieldInfo.fontSize >= MIN_FONT_SIZE && fieldInfo.fontSize <= MAX_FONT_SIZE) {
999
+ return fieldInfo.fontSize;
1000
+ }
1001
+ const daFontSize = extractFromDAField(field);
1002
+ if (daFontSize !== null) {
1003
+ return daFontSize;
1004
+ }
1005
+ const tuFontSize = extractFromTUField(field);
1006
+ if (tuFontSize !== null) {
1007
+ return tuFontSize;
1008
+ }
1009
+ return DEFAULT_FONT_SIZE;
1010
+ }
1011
+ function extractFromDAField(field) {
1012
+ try {
1013
+ const fieldWithAcro = field;
1014
+ const dict = fieldWithAcro.acroField?.dict;
1015
+ if (!dict) return null;
1016
+ const daKey = dict.context?.obj?.("DA") || "DA";
1017
+ const daEntry = dict.lookup?.(daKey) || dict.get?.(daKey);
1018
+ if (!daEntry) return null;
1019
+ let daValue = "";
1020
+ if (typeof daEntry.decodeText === "function") {
1021
+ daValue = daEntry.decodeText();
1022
+ } else if (typeof daEntry.asString === "function") {
1023
+ daValue = daEntry.asString();
1024
+ } else {
1025
+ daValue = String(daEntry);
1026
+ }
1027
+ const daMatch = daValue.match(/\s+(\d+)\s+Tf/i);
1028
+ if (daMatch?.[1]) {
1029
+ const fontSize = parseInt(daMatch[1], 10);
1030
+ if (fontSize >= 8 && fontSize <= 72) {
1031
+ return fontSize;
1032
+ }
1033
+ }
1034
+ } catch {
1035
+ }
1036
+ return null;
1037
+ }
1038
+ function extractFromTUField(field) {
1039
+ try {
1040
+ const fieldWithAcro = field;
1041
+ const dict = fieldWithAcro.acroField?.dict;
1042
+ if (!dict) return null;
1043
+ const tuKey = dict.context?.obj?.("TU") || "TU";
1044
+ const tuEntry = dict.lookup?.(tuKey) || dict.get?.(tuKey);
1045
+ if (!tuEntry) return null;
1046
+ let tuValue = "";
1047
+ if (typeof tuEntry.decodeText === "function") {
1048
+ tuValue = tuEntry.decodeText();
1049
+ } else if (typeof tuEntry.asString === "function") {
1050
+ tuValue = tuEntry.asString();
1051
+ } else {
1052
+ tuValue = String(tuEntry);
1053
+ }
1054
+ tuValue = tuValue.replace(/^\(|\)$|^<|>$/g, "");
1055
+ const match = tuValue.match(/\|fontSize:(\d+)$/);
1056
+ if (match?.[1]) {
1057
+ const fontSize = parseInt(match[1], 10);
1058
+ if (fontSize >= 8 && fontSize <= 72) {
1059
+ return fontSize;
1060
+ }
1061
+ }
1062
+ } catch {
1063
+ }
1064
+ return null;
1065
+ }
1066
+ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {}, _currentSignerEmail, extractedFormFields, metadata, auditTrail, multiSignerContext) {
818
1067
  try {
819
1068
  const { PDFDocument, rgb, StandardFonts } = await loadPdfLib();
820
1069
  const pdfDoc = await PDFDocument.load(pdfBytes);
@@ -831,39 +1080,39 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
831
1080
  continue;
832
1081
  }
833
1082
  try {
834
- const fieldTypeName = field.constructor.name;
835
- if (fieldTypeName === "PDFTextField" || fieldTypeName === "PDFTextField2") {
836
- const textField = field;
837
- textField.setText?.(fieldValue);
838
- } else if (fieldTypeName === "PDFCheckBox" || fieldTypeName === "PDFCheckBox2") {
839
- const checkBox = field;
1083
+ const f = field;
1084
+ const isTextField = typeof f.getText === "function" && typeof f.setText === "function";
1085
+ const isCheckbox = typeof f.check === "function" && typeof f.uncheck === "function";
1086
+ const isRadio = typeof f.select === "function" && typeof f.getOptions === "function" && typeof f.check !== "function" && typeof f.setOptions !== "function";
1087
+ const isDropdown = typeof f.select === "function" && (typeof f.setOptions === "function" || typeof f.addOptions === "function");
1088
+ if (isTextField) {
1089
+ f.setText?.(fieldValue);
1090
+ } else if (isCheckbox) {
840
1091
  if (fieldValue === "true" || fieldValue === "Yes" || fieldValue === "checked" || fieldValue === "On") {
841
- checkBox.check?.();
1092
+ f.check?.();
842
1093
  } else {
843
- checkBox.uncheck?.();
1094
+ f.uncheck?.();
844
1095
  }
845
- } else if (fieldTypeName === "PDFRadioGroup" || fieldTypeName === "PDFRadioGroup2") {
846
- const radioGroup = field;
1096
+ } else if (isRadio) {
847
1097
  if (fieldValue === "true" || fieldValue === "false") {
848
1098
  continue;
849
1099
  }
850
1100
  const idxMatch = fieldValue.match(/__RADIO_OPTION_INDEX_(\d+)__/);
851
1101
  if (idxMatch && idxMatch[1]) {
852
1102
  const selectedIndex = parseInt(idxMatch[1], 10);
853
- const options = radioGroup.getOptions?.() || [];
1103
+ const options = f.getOptions?.() || [];
854
1104
  if (selectedIndex >= 0 && selectedIndex < options.length) {
855
- radioGroup.select?.(options[selectedIndex]);
1105
+ f.select?.(options[selectedIndex]);
856
1106
  }
857
1107
  } else {
858
- const options = radioGroup.getOptions?.() || [];
1108
+ const options = f.getOptions?.() || [];
859
1109
  if (options.includes(fieldValue)) {
860
- radioGroup.select?.(fieldValue);
1110
+ f.select?.(fieldValue);
861
1111
  } else {
862
1112
  }
863
1113
  }
864
- } else if (fieldTypeName === "PDFDropdown" || fieldTypeName === "PDFDropdown2") {
865
- const dropdown = field;
866
- dropdown.select?.(fieldValue);
1114
+ } else if (isDropdown) {
1115
+ f.select?.(fieldValue);
867
1116
  }
868
1117
  } catch (fieldError) {
869
1118
  logger.error(`Error setting field "${fieldName}":`, fieldError);
@@ -871,11 +1120,6 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
871
1120
  }
872
1121
  try {
873
1122
  form.updateFieldAppearances();
874
- const PDFName3 = pdfLib.PDFName;
875
- const acroForm = pdfDoc.catalog.lookup(PDFName3.of("AcroForm"));
876
- if (acroForm && typeof acroForm === "object" && "set" in acroForm) {
877
- acroForm.set(PDFName3.of("NeedAppearances"), false);
878
- }
879
1123
  } catch (appearanceError) {
880
1124
  logger.warn("Could not update field appearances:", appearanceError);
881
1125
  }
@@ -944,6 +1188,20 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
944
1188
  const y = fieldPosition.y;
945
1189
  const width = Math.max(fieldPosition.width, 80);
946
1190
  const height = Math.max(fieldPosition.height, 30);
1191
+ const fieldInfo = extractedFormFields?.find((f) => f.name === fieldName);
1192
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1193
+ const labelFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
1194
+ const labelFontSize = Math.min(10, height * 0.4);
1195
+ const labelX = x;
1196
+ const labelY = y + height + 5;
1197
+ page.drawText(fieldInfo.label, {
1198
+ x: labelX,
1199
+ y: labelY,
1200
+ size: labelFontSize,
1201
+ font: labelFont,
1202
+ color: rgb(0, 0, 0)
1203
+ });
1204
+ }
947
1205
  const signatureDims = signatureImage.scaleToFit(width - 4, height - 4);
948
1206
  const finalX = x;
949
1207
  const finalY = y;
@@ -978,7 +1236,7 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
978
1236
  console.log("[FLATTEN] After pattern matching in fieldPageMap:", foundInitialsFields);
979
1237
  if (extractedFormFields && extractedFormFields.length > 0) {
980
1238
  foundInitialsFields = foundInitialsFields.filter((fieldName) => {
981
- const fieldInfo = extractedFormFields.find((f) => f.name === fieldName);
1239
+ const fieldInfo = extractedFormFields.find((f) => f.name === fieldName) || extractedFormFields.find((f) => f.name === fieldName.replace(/_initials$/i, "")) || extractedFormFields.find((f) => fieldName.startsWith(f.name));
982
1240
  if (!fieldInfo) return false;
983
1241
  const isActualInitialsField = fieldInfo.type === "initials" || fieldName.toLowerCase().includes("initials");
984
1242
  if (!isActualInitialsField) return false;
@@ -1007,6 +1265,19 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1007
1265
  const y = fieldPosition.y;
1008
1266
  const height = Math.max(fieldPosition.height, 20);
1009
1267
  const fontSize = Math.min(height * 0.7, 14);
1268
+ const fieldInfo = extractedFormFields?.find((f) => f.name === fieldName) || extractedFormFields?.find((f) => f.name === fieldName.replace(/_initials$/i, "")) || extractedFormFields?.find((f) => fieldName.startsWith(f.name)) || extractedFormFields?.find((f) => f.fieldId && fieldName.includes(f.fieldId)) || extractedFormFields?.find((f) => f.type === "initials" && f.name !== "initials_field_main");
1269
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1270
+ const labelFontSize = Math.min(10, height * 0.4);
1271
+ const labelX = x;
1272
+ const labelY = y + height + 5;
1273
+ page.drawText(fieldInfo.label, {
1274
+ x: labelX,
1275
+ y: labelY,
1276
+ size: labelFontSize,
1277
+ font,
1278
+ color: rgb(0, 0, 0)
1279
+ });
1280
+ }
1010
1281
  const finalX = x + 2;
1011
1282
  const finalY = y + (height - fontSize) / 2;
1012
1283
  console.log("[FLATTEN] \u2705 Drawing initials at:", { x: finalX, y: finalY, fontSize, text: mainInitialsData });
@@ -1049,11 +1320,16 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1049
1320
  let flattenedCount = 0;
1050
1321
  for (const field of fieldsToFlatten) {
1051
1322
  const fieldName = field.getName();
1052
- const fieldType = field.constructor.name;
1323
+ const f = field;
1324
+ const isCheckboxField = typeof f.check === "function" && typeof f.uncheck === "function";
1325
+ const isRadioField = typeof f.select === "function" && typeof f.getOptions === "function" && typeof f.check !== "function" && typeof f.setOptions !== "function";
1326
+ const isDropdownField = typeof f.select === "function" && (typeof f.setOptions === "function" || typeof f.addOptions === "function");
1327
+ const isTextField = typeof f.getText === "function" && typeof f.setText === "function";
1328
+ const isSignatureType = !isCheckboxField && !isRadioField && !isDropdownField && !isTextField;
1053
1329
  try {
1054
1330
  const userEnteredValue = formFieldValues[fieldName];
1055
- const isSignatureField2 = fieldName.toLowerCase().includes("signature") || fieldType.includes("Signature");
1056
- const isInitialsField2 = fieldName.toLowerCase().includes("initials") || fieldType.includes("Initials");
1331
+ const isSignatureField2 = fieldName.toLowerCase().includes("signature") || isSignatureType;
1332
+ const isInitialsField2 = fieldName.toLowerCase().includes("initials");
1057
1333
  if (isSignatureField2 || isInitialsField2) {
1058
1334
  form.removeField(field);
1059
1335
  flattenedCount++;
@@ -1061,15 +1337,29 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1061
1337
  }
1062
1338
  const fieldWithWidgets = field;
1063
1339
  const widgets = fieldWithWidgets.acroField?.getWidgets?.() || [];
1064
- if (fieldType === "PDFCheckBox" || fieldType === "PDFCheckBox2") {
1340
+ if (isCheckboxField) {
1065
1341
  const stringValue = String(userEnteredValue || "");
1066
1342
  const isChecked = stringValue === "true" || stringValue === "Yes" || stringValue === "On" || stringValue === "checked";
1343
+ const fieldInfo = extractedFormFields?.find((f2) => f2.name === fieldName);
1344
+ const labelFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
1067
1345
  if (isChecked) {
1068
1346
  for (const widget of widgets) {
1069
1347
  const result = getWidgetRectangleAndPage(widget, pages);
1070
1348
  if (!result) continue;
1071
1349
  const { rect, page } = result;
1072
- const checkboxSize = Math.min(rect.width, rect.height) * 0.6;
1350
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1351
+ const labelFontSize = Math.min(10, rect.height * 0.4);
1352
+ const labelX = rect.x + rect.width + 5;
1353
+ const labelY = rect.y + (rect.height - labelFontSize) / 2;
1354
+ page.drawText(fieldInfo.label, {
1355
+ x: labelX,
1356
+ y: labelY,
1357
+ size: labelFontSize,
1358
+ font: labelFont,
1359
+ color: rgb(0, 0, 0)
1360
+ });
1361
+ }
1362
+ const checkboxSize = Math.min(rect.width, rect.height);
1073
1363
  const checkboxX = rect.x + (rect.width - checkboxSize) / 2;
1074
1364
  const checkboxY = rect.y + (rect.height - checkboxSize) / 2;
1075
1365
  page.drawRectangle({
@@ -1080,21 +1370,51 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1080
1370
  borderColor: rgb(0, 0, 0),
1081
1371
  borderWidth: 1
1082
1372
  });
1083
- const checkSize = checkboxSize * 0.6;
1084
- const textWidth = checkSize * 0.6;
1085
- const textHeight = checkSize * 0.8;
1373
+ const checkFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
1374
+ const checkFontSize = checkboxSize * 0.7;
1375
+ const textWidth = checkFont.widthOfTextAtSize("X", checkFontSize);
1376
+ const textHeight = checkFont.heightAtSize(checkFontSize);
1086
1377
  page.drawText("X", {
1087
1378
  x: checkboxX + (checkboxSize - textWidth) / 2,
1088
- y: checkboxY + (checkboxSize - textHeight) / 2 + textHeight * 0.2,
1089
- size: checkSize,
1090
- font: await pdfDoc.embedFont(StandardFonts.HelveticaBold),
1379
+ y: checkboxY + (checkboxSize - textHeight) / 2 + textHeight * 0.15,
1380
+ size: checkFontSize,
1381
+ font: checkFont,
1091
1382
  color: rgb(0, 0, 0)
1092
1383
  });
1093
1384
  }
1385
+ } else {
1386
+ for (const widget of widgets) {
1387
+ const result = getWidgetRectangleAndPage(widget, pages);
1388
+ if (!result) continue;
1389
+ const { rect, page } = result;
1390
+ const checkboxSize = Math.min(rect.width, rect.height);
1391
+ const checkboxX = rect.x + (rect.width - checkboxSize) / 2;
1392
+ const checkboxY = rect.y + (rect.height - checkboxSize) / 2;
1393
+ page.drawRectangle({
1394
+ x: checkboxX,
1395
+ y: checkboxY,
1396
+ width: checkboxSize,
1397
+ height: checkboxSize,
1398
+ borderColor: rgb(0, 0, 0),
1399
+ borderWidth: 1
1400
+ });
1401
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1402
+ const labelFontSize = Math.min(12, rect.height * 0.6);
1403
+ const labelX = rect.x + rect.width + 5;
1404
+ const labelY = rect.y + (rect.height - labelFontSize) / 2;
1405
+ page.drawText(fieldInfo.label, {
1406
+ x: labelX,
1407
+ y: labelY,
1408
+ size: labelFontSize,
1409
+ font: labelFont,
1410
+ color: rgb(0, 0, 0)
1411
+ });
1412
+ }
1413
+ }
1094
1414
  }
1095
- } else if (fieldType === "PDFRadioGroup" || fieldType === "PDFRadioGroup2") {
1096
- const radioGroup = field;
1097
- const fieldInfo = extractedFormFields?.find((f) => f.name === fieldName);
1415
+ } else if (isRadioField) {
1416
+ const radioGroup = f;
1417
+ const fieldInfo = extractedFormFields?.find((f2) => f2.name === fieldName);
1098
1418
  let actualSelectedValue = "";
1099
1419
  try {
1100
1420
  actualSelectedValue = radioGroup.getSelected?.() || "";
@@ -1139,14 +1459,15 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1139
1459
  const result = getWidgetRectangleAndPage(widget, pages);
1140
1460
  if (!result) continue;
1141
1461
  const { rect, page, pageIndex } = result;
1142
- if (i === 0 && fieldInfo?.label && fieldInfo.label.trim() && !isAutoGeneratedLabel(fieldInfo.label)) {
1462
+ if (i === 0 && fieldInfo && hasDrawableLabel(fieldInfo)) {
1143
1463
  const groupLabelKey = `${pageIndex}-${fieldName}-grouplabel`;
1144
1464
  if (!drawnGroupLabels.has(groupLabelKey)) {
1465
+ const labelFontSize = Math.min(10, rect.height * 0.4);
1145
1466
  const labelY = rect.y + rect.height + 3;
1146
1467
  page.drawText(fieldInfo.label, {
1147
1468
  x: rect.x,
1148
1469
  y: labelY,
1149
- size: 8,
1470
+ size: labelFontSize,
1150
1471
  font: labelFont,
1151
1472
  color: rgb(0, 0, 0)
1152
1473
  });
@@ -1154,22 +1475,21 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1154
1475
  }
1155
1476
  } else if (i === 0 && isAutoGeneratedLabel(fieldInfo?.label || "")) {
1156
1477
  }
1157
- const radioSize = Math.min(rect.width, rect.height) * 0.5;
1158
- const radioX = rect.x + (rect.width - radioSize) / 2;
1159
- const radioY = rect.y + (rect.height - radioSize) / 2;
1478
+ const radioSize = Math.min(rect.width, rect.height);
1479
+ const centerX = rect.x + rect.width / 2;
1480
+ const centerY = rect.y + rect.height / 2;
1160
1481
  page.drawCircle({
1161
- x: radioX + radioSize / 2,
1162
- y: radioY + radioSize / 2,
1163
- size: radioSize,
1482
+ x: centerX,
1483
+ y: centerY,
1484
+ size: radioSize / 2,
1164
1485
  borderColor: rgb(0, 0, 0),
1165
1486
  borderWidth: 1
1166
1487
  });
1167
1488
  if (i === selectedIndex) {
1168
- const circleSize = radioSize * 0.5;
1169
1489
  page.drawCircle({
1170
- x: radioX + radioSize / 2,
1171
- y: radioY + radioSize / 2,
1172
- size: circleSize,
1490
+ x: centerX,
1491
+ y: centerY,
1492
+ size: radioSize / 4,
1173
1493
  color: rgb(0, 0, 0)
1174
1494
  });
1175
1495
  }
@@ -1179,8 +1499,8 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1179
1499
  if (optionText && !drawnOptionLabels.has(optionKey)) {
1180
1500
  page.drawText(optionText, {
1181
1501
  x: rect.x + rect.width + 4,
1182
- y: rect.y + (rect.height - 8) / 2,
1183
- size: 8,
1502
+ y: rect.y + (rect.height - 7) / 2,
1503
+ size: 7,
1184
1504
  font: labelFont,
1185
1505
  color: rgb(0, 0, 0)
1186
1506
  });
@@ -1190,17 +1510,31 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1190
1510
  }
1191
1511
  if (fieldInfo?.options) {
1192
1512
  }
1193
- } else if (fieldType === "PDFDropdown" || fieldType === "PDFDropdown2") {
1513
+ } else if (isDropdownField) {
1194
1514
  const selectedValue = userEnteredValue ? String(userEnteredValue) : "";
1195
- if (selectedValue && selectedValue.trim()) {
1196
- for (const widget of widgets) {
1197
- const result = getWidgetRectangleAndPage(widget, pages);
1198
- if (!result) continue;
1199
- const { rect, page } = result;
1515
+ const fieldInfo = extractedFormFields?.find((f2) => f2.name === fieldName);
1516
+ const labelFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
1517
+ for (const widget of widgets) {
1518
+ const result = getWidgetRectangleAndPage(widget, pages);
1519
+ if (!result) continue;
1520
+ const { rect, page } = result;
1521
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1522
+ const labelFontSize = Math.min(10, rect.height * 0.4);
1523
+ const labelX = rect.x;
1524
+ const labelY = rect.y + rect.height + 5;
1525
+ page.drawText(fieldInfo.label, {
1526
+ x: labelX,
1527
+ y: labelY,
1528
+ size: labelFontSize,
1529
+ font: labelFont,
1530
+ color: rgb(0, 0, 0)
1531
+ });
1532
+ }
1533
+ if (selectedValue && selectedValue.trim()) {
1200
1534
  page.drawText(selectedValue, {
1201
1535
  x: rect.x + 2,
1202
1536
  y: rect.y + 2,
1203
- size: 10,
1537
+ size: 14,
1204
1538
  font: await pdfDoc.embedFont(StandardFonts.Helvetica),
1205
1539
  color: rgb(0, 0, 0)
1206
1540
  });
@@ -1208,15 +1542,31 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1208
1542
  }
1209
1543
  } else {
1210
1544
  const fieldValue = userEnteredValue ? String(userEnteredValue) : "";
1211
- if (fieldValue && fieldValue.trim()) {
1212
- for (const widget of widgets) {
1213
- const result = getWidgetRectangleAndPage(widget, pages);
1214
- if (!result) continue;
1215
- const { rect, page } = result;
1545
+ const fieldInfo = extractedFormFields?.find((f2) => f2.name === fieldName);
1546
+ const labelFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
1547
+ const isDateField = fieldName.toLowerCase().includes("date") || fieldName.toLowerCase().includes("_date");
1548
+ const fontSize = isDateField ? 14 : extractFieldFontSize(fieldName, field, extractedFormFields);
1549
+ for (const widget of widgets) {
1550
+ const result = getWidgetRectangleAndPage(widget, pages);
1551
+ if (!result) continue;
1552
+ const { rect, page } = result;
1553
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1554
+ const labelFontSize = Math.min(10, rect.height * 0.4);
1555
+ const labelX = rect.x;
1556
+ const labelY = rect.y + rect.height + 5;
1557
+ page.drawText(fieldInfo.label, {
1558
+ x: labelX,
1559
+ y: labelY,
1560
+ size: labelFontSize,
1561
+ font: labelFont,
1562
+ color: rgb(0, 0, 0)
1563
+ });
1564
+ }
1565
+ if (fieldValue && fieldValue.trim()) {
1216
1566
  page.drawText(fieldValue, {
1217
1567
  x: rect.x + 2,
1218
1568
  y: rect.y + 2,
1219
- size: 10,
1569
+ size: fontSize,
1220
1570
  font: await pdfDoc.embedFont(StandardFonts.Helvetica),
1221
1571
  color: rgb(0, 0, 0)
1222
1572
  });
@@ -1339,24 +1689,45 @@ async function fillFormFieldsWithSignatures(pdfBytes, formFields, fieldValues, s
1339
1689
  switch (field.type) {
1340
1690
  case "text" /* TEXT */: {
1341
1691
  const value = fieldValues[field.id] || "";
1692
+ if (hasDrawableLabel(field)) {
1693
+ const labelFontSize = Math.min(10, field.position.height * 0.4);
1694
+ const labelX = pdfX;
1695
+ const labelY = pdfY + field.position.height + 5;
1696
+ page.drawText(field.label, {
1697
+ x: labelX,
1698
+ y: labelY,
1699
+ size: labelFontSize,
1700
+ font,
1701
+ color: rgb(0, 0, 0)
1702
+ });
1703
+ }
1342
1704
  if (value) {
1343
1705
  const fontSize = field.fontSize && field.fontSize >= 8 && field.fontSize <= 72 ? field.fontSize : Math.min(12, field.position.height * 0.6);
1344
1706
  page.drawText(value, {
1345
1707
  x: pdfX + 2,
1346
- // Small padding
1347
1708
  y: pdfY + (field.position.height - fontSize) / 2,
1348
- // Center vertically
1349
1709
  size: fontSize,
1350
1710
  font,
1351
1711
  color: rgb(0, 0, 0),
1352
1712
  maxWidth: field.position.width - 4
1353
- // Leave padding
1354
1713
  });
1355
1714
  }
1356
1715
  break;
1357
1716
  }
1358
1717
  case "date" /* DATE */: {
1359
1718
  const value = fieldValues[field.id] || "";
1719
+ if (hasDrawableLabel(field)) {
1720
+ const labelFontSize = Math.min(10, field.position.height * 0.4);
1721
+ const labelX = pdfX;
1722
+ const labelY = pdfY + field.position.height + 5;
1723
+ page.drawText(field.label, {
1724
+ x: labelX,
1725
+ y: labelY,
1726
+ size: labelFontSize,
1727
+ font,
1728
+ color: rgb(0, 0, 0)
1729
+ });
1730
+ }
1360
1731
  if (value) {
1361
1732
  const fontSize = field.fontSize && field.fontSize >= 8 && field.fontSize <= 72 ? field.fontSize : Math.min(12, field.position.height * 0.6);
1362
1733
  page.drawText(value, {
@@ -1372,10 +1743,22 @@ async function fillFormFieldsWithSignatures(pdfBytes, formFields, fieldValues, s
1372
1743
  }
1373
1744
  case "checkbox" /* CHECKBOX */: {
1374
1745
  const value = fieldValues[field.id] || "";
1746
+ const checkboxSize = Math.min(field.position.width, field.position.height) * 0.7;
1747
+ const checkboxX = pdfX + (field.position.width - checkboxSize) / 2;
1748
+ const checkboxY = pdfY + (field.position.height - checkboxSize) / 2;
1749
+ page.drawRectangle({
1750
+ x: checkboxX,
1751
+ y: checkboxY,
1752
+ width: checkboxSize,
1753
+ height: checkboxSize,
1754
+ borderColor: rgb(0, 0, 0),
1755
+ borderWidth: 1,
1756
+ color: rgb(1, 1, 1)
1757
+ });
1375
1758
  if (value === "true") {
1376
- const checkSize = Math.min(field.position.width, field.position.height) * 0.6;
1377
- const checkX = pdfX + (field.position.width - checkSize) / 2;
1378
- const checkY = pdfY + (field.position.height - checkSize) / 2;
1759
+ const checkSize = checkboxSize * 0.7;
1760
+ const checkX = checkboxX + (checkboxSize - checkSize) / 2;
1761
+ const checkY = checkboxY + (checkboxSize - checkSize) / 2;
1379
1762
  page.drawText("\u2713", {
1380
1763
  x: checkX,
1381
1764
  y: checkY,
@@ -1434,6 +1817,18 @@ async function fillFormFieldsWithSignatures(pdfBytes, formFields, fieldValues, s
1434
1817
  }
1435
1818
  case "dropdown" /* DROPDOWN */: {
1436
1819
  const value = fieldValues[field.id] || "";
1820
+ if (hasDrawableLabel(field)) {
1821
+ const labelFontSize = Math.min(10, field.position.height * 0.4);
1822
+ const labelX = pdfX;
1823
+ const labelY = pdfY + field.position.height + 5;
1824
+ page.drawText(field.label, {
1825
+ x: labelX,
1826
+ y: labelY,
1827
+ size: labelFontSize,
1828
+ font,
1829
+ color: rgb(0, 0, 0)
1830
+ });
1831
+ }
1437
1832
  if (value) {
1438
1833
  const fontSize = Math.min(12, field.position.height * 0.6);
1439
1834
  page.drawText(value, {
@@ -1501,6 +1896,203 @@ async function getFieldPageNumbers(pdfBytes) {
1501
1896
  }
1502
1897
  }
1503
1898
 
1899
+ // src/utils/pdf-signer-utils.ts
1900
+ function getFieldSignerEmail(field) {
1901
+ return field.assignedSignerEmail || null;
1902
+ }
1903
+ function isFieldAssignedToSigner(field, signerEmail, allSignerEmails = []) {
1904
+ const assignedTo = field.assignedSignerEmail;
1905
+ if (!assignedTo) return false;
1906
+ if (assignedTo === signerEmail) return true;
1907
+ if (assignedTo === "to-recipients" && allSignerEmails.includes(signerEmail)) {
1908
+ return true;
1909
+ }
1910
+ if (assignedTo === "additional-signers" && allSignerEmails.includes(signerEmail)) {
1911
+ return true;
1912
+ }
1913
+ return false;
1914
+ }
1915
+ async function preparePdfForSigner(inputPdfBytes, formFields, options) {
1916
+ const {
1917
+ activeSignerEmail,
1918
+ hideMode = "NoView",
1919
+ allSignerEmails = []
1920
+ } = options;
1921
+ logger.info(`\u{1F510} Preparing PDF for signer: ${activeSignerEmail}`);
1922
+ logger.info(`\u{1F510} Form fields to process: ${formFields.length}`);
1923
+ logger.info(`\u{1F510} Hide mode: ${hideMode}`);
1924
+ logger.info(`\u{1F510} All signer emails:`, allSignerEmails);
1925
+ logger.info(`\u{1F510} Form field assignments:`, formFields.map((f) => ({
1926
+ name: f.name,
1927
+ assignedTo: f.assignedSignerEmail
1928
+ })));
1929
+ const pdfLib = await loadPdfLib();
1930
+ const { PDFDocument, AnnotationFlags } = pdfLib;
1931
+ let pdfDoc;
1932
+ try {
1933
+ logger.info(`\u{1F510} Loading PDF document, bytes length: ${inputPdfBytes.byteLength || inputPdfBytes.length}`);
1934
+ const bytesArray = inputPdfBytes instanceof Uint8Array ? inputPdfBytes : new Uint8Array(inputPdfBytes);
1935
+ const header = new TextDecoder().decode(bytesArray.slice(0, 8));
1936
+ logger.info(`\u{1F510} PDF header: "${header}"`);
1937
+ if (!header.startsWith("%PDF-")) {
1938
+ throw new Error(`Invalid PDF header: "${header}". Expected "%PDF-"`);
1939
+ }
1940
+ pdfDoc = await PDFDocument.load(inputPdfBytes);
1941
+ logger.info(`\u2705 Successfully loaded PDF document`);
1942
+ } catch (loadError) {
1943
+ logger.error(`\u274C Failed to load PDF with pdf-lib:`, loadError);
1944
+ logger.info(`\u{1F50D} PDF bytes details:`, {
1945
+ type: inputPdfBytes.constructor.name,
1946
+ length: inputPdfBytes.byteLength || inputPdfBytes.length,
1947
+ isArrayBuffer: inputPdfBytes instanceof ArrayBuffer,
1948
+ isUint8Array: inputPdfBytes instanceof Uint8Array,
1949
+ first20Bytes: Array.from(new Uint8Array(inputPdfBytes instanceof ArrayBuffer ? inputPdfBytes : inputPdfBytes.buffer).slice(0, 20)).map((b) => b.toString(16).padStart(2, "0")).join(" ")
1950
+ });
1951
+ throw new Error(`PDF parsing failed for signer ${activeSignerEmail}: ${loadError instanceof Error ? loadError.message : "Unknown error"}`);
1952
+ }
1953
+ const form = pdfDoc.getForm();
1954
+ const pdfFields = form.getFields();
1955
+ logger.info(`\u{1F510} PDF contains ${pdfFields.length} form fields`);
1956
+ for (const pdfField of pdfFields) {
1957
+ const pdfFieldName = pdfField.getName();
1958
+ const matchingFormField = formFields.find(
1959
+ (f) => f.name === pdfFieldName || (f.type === "signature" /* SIGNATURE */ || f.type === "initials" /* INITIALS */) && `${f.name}_signature` === pdfFieldName
1960
+ );
1961
+ if (!matchingFormField) {
1962
+ logger.info(`\u{1F510} PDF field "${pdfFieldName}" not found in provided form fields - leaving unchanged`);
1963
+ continue;
1964
+ }
1965
+ logger.info(`\u{1F510} Matched PDF field "${pdfFieldName}" to FormField "${matchingFormField.name}". Assigned to: ${matchingFormField.assignedSignerEmail}`);
1966
+ const fieldSignerEmail = getFieldSignerEmail(matchingFormField);
1967
+ const isAssignedToActiveSigner = isFieldAssignedToSigner(
1968
+ matchingFormField,
1969
+ activeSignerEmail,
1970
+ allSignerEmails
1971
+ );
1972
+ const isAssignedToCompletedSigner = (options.completedSignerEmails || []).some(
1973
+ (completedEmail) => isFieldAssignedToSigner(matchingFormField, completedEmail, allSignerEmails)
1974
+ );
1975
+ const isUnassigned = !fieldSignerEmail;
1976
+ let isVisible = false;
1977
+ let reason = "";
1978
+ if (isAssignedToActiveSigner) {
1979
+ isVisible = true;
1980
+ reason = "Assigned to active signer";
1981
+ } else if (isUnassigned) {
1982
+ isVisible = true;
1983
+ reason = "Unassigned field (visible to all)";
1984
+ } else {
1985
+ isVisible = false;
1986
+ reason = `Assigned to different signer (${fieldSignerEmail})`;
1987
+ }
1988
+ const isLocked = (options.lockCompletedFields ?? true) && isAssignedToCompletedSigner;
1989
+ if (isLocked) {
1990
+ reason += " - Locked (completed)";
1991
+ }
1992
+ logger.info(`\u{1F510} Processing field "${pdfFieldName}": ${reason}`);
1993
+ if (isLocked) {
1994
+ try {
1995
+ const fieldWithExtensions = pdfField;
1996
+ if (typeof fieldWithExtensions.enableReadOnly === "function") {
1997
+ fieldWithExtensions.enableReadOnly();
1998
+ } else if (typeof fieldWithExtensions.setReadOnly === "function") {
1999
+ fieldWithExtensions.setReadOnly(true);
2000
+ }
2001
+ logger.info(`\u{1F512} Locked field "${pdfFieldName}"`);
2002
+ } catch (error) {
2003
+ logger.warn(`\u26A0\uFE0F Could not lock field "${pdfFieldName}":`, error);
2004
+ }
2005
+ }
2006
+ try {
2007
+ const fieldWithExtensions = pdfField;
2008
+ const widgets = fieldWithExtensions.acroField?.getWidgets?.() ?? [];
2009
+ for (const widget of widgets) {
2010
+ if (typeof widget.clearFlag === "function") {
2011
+ widget.clearFlag(AnnotationFlags.Hidden);
2012
+ widget.clearFlag(AnnotationFlags.NoView);
2013
+ }
2014
+ if (!isVisible) {
2015
+ const flag = hideMode === "Hidden" ? AnnotationFlags.Hidden : AnnotationFlags.NoView;
2016
+ if (typeof widget.setFlag === "function") {
2017
+ widget.setFlag(flag);
2018
+ }
2019
+ if (typeof widget.clearFlag === "function") {
2020
+ widget.clearFlag(AnnotationFlags.Print);
2021
+ }
2022
+ logger.info(`\u{1F648} Hidden field "${pdfFieldName}" using ${hideMode} flag`);
2023
+ } else {
2024
+ if (typeof widget.setFlag === "function") {
2025
+ widget.setFlag(AnnotationFlags.Print);
2026
+ }
2027
+ logger.info(`\u{1F441}\uFE0F Made field "${pdfFieldName}" visible`);
2028
+ }
2029
+ }
2030
+ } catch (error) {
2031
+ logger.warn(`\u26A0\uFE0F Could not set visibility for field "${pdfFieldName}":`, error);
2032
+ }
2033
+ }
2034
+ try {
2035
+ const currentSubject = pdfDoc.getSubject() || "";
2036
+ const signerInfo = `Prepared for: ${activeSignerEmail}`;
2037
+ const newSubject = currentSubject ? `${currentSubject} | ${signerInfo}` : signerInfo;
2038
+ pdfDoc.setSubject(newSubject);
2039
+ const currentKeywords = pdfDoc.getKeywords() || [];
2040
+ const updatedKeywords = [...currentKeywords, `ActiveSigner:${activeSignerEmail}`];
2041
+ pdfDoc.setKeywords(updatedKeywords);
2042
+ logger.info(`\u{1F4DD} Added signer metadata to PDF`);
2043
+ } catch (error) {
2044
+ logger.warn(`\u26A0\uFE0F Could not set PDF metadata:`, error);
2045
+ }
2046
+ const modifiedPdfBytes = await pdfDoc.save();
2047
+ logger.info(`\u2705 PDF prepared for ${activeSignerEmail}: ${modifiedPdfBytes.length} bytes`);
2048
+ return new Uint8Array(modifiedPdfBytes);
2049
+ }
2050
+ function areAllSignersComplete(signers, completedSignerEmails) {
2051
+ const requiredSigners = new Set(signers.map((s) => s.email));
2052
+ const completedSigners = new Set(completedSignerEmails);
2053
+ for (const signerEmail of requiredSigners) {
2054
+ if (!completedSigners.has(signerEmail)) {
2055
+ return false;
2056
+ }
2057
+ }
2058
+ return true;
2059
+ }
2060
+ function getNextSigner(signers, completedSignerEmails) {
2061
+ const completedSet = new Set(completedSignerEmails);
2062
+ const sortedSigners = [...signers].sort((a, b) => a.signOrder - b.signOrder);
2063
+ for (const signer of sortedSigners) {
2064
+ if (!completedSet.has(signer.email)) {
2065
+ return signer;
2066
+ }
2067
+ }
2068
+ return null;
2069
+ }
2070
+ function validateFieldAssignments(formFields, signers) {
2071
+ const errors = [];
2072
+ const signerEmailSet = new Set(signers.map((s) => s.email));
2073
+ const assignedEmails = new Set(
2074
+ formFields.map((field) => field.assignedSignerEmail).filter((email) => email)
2075
+ );
2076
+ for (const assignedEmail of assignedEmails) {
2077
+ if (assignedEmail === "to-recipients" || assignedEmail === "additional-signers") {
2078
+ continue;
2079
+ }
2080
+ if (!signerEmailSet.has(assignedEmail)) {
2081
+ errors.push(`Field assigned to unknown signer: ${assignedEmail}`);
2082
+ }
2083
+ }
2084
+ const requiredUnassignedFields = formFields.filter(
2085
+ (field) => field.required && !field.assignedSignerEmail
2086
+ );
2087
+ if (requiredUnassignedFields.length > 0) {
2088
+ errors.push(`${requiredUnassignedFields.length} required fields are not assigned to any signer`);
2089
+ }
2090
+ return {
2091
+ isValid: errors.length === 0,
2092
+ errors
2093
+ };
2094
+ }
2095
+
1504
2096
  // src/utils/field-extraction.ts
1505
2097
  var PDFName2;
1506
2098
  async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
@@ -1515,7 +2107,6 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1515
2107
  const fields = form.getFields();
1516
2108
  const visibleFields = [];
1517
2109
  let hasAnyInitialsFields = false;
1518
- let hasInitialsFieldsForCurrentSigner = false;
1519
2110
  for (const field of fields) {
1520
2111
  const fieldName = field.getName();
1521
2112
  const fieldWithExtensions = field;
@@ -1541,28 +2132,31 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1541
2132
  };
1542
2133
  })();
1543
2134
  let fieldType = "text" /* TEXT */;
1544
- const fieldTypeName = field.constructor.name;
2135
+ const f = field;
2136
+ const isCheckboxField = typeof f.check === "function" && typeof f.uncheck === "function";
2137
+ const isRadioField = typeof f.select === "function" && typeof f.getOptions === "function" && typeof f.check !== "function" && typeof f.setOptions !== "function";
2138
+ const isDropdownField = typeof f.select === "function" && (typeof f.setOptions === "function" || typeof f.addOptions === "function");
2139
+ const isTextField = typeof f.getText === "function" && typeof f.setText === "function";
2140
+ const isSignatureType = !isCheckboxField && !isRadioField && !isDropdownField && !isTextField;
1545
2141
  const cleanFieldName = fieldName.replace(/_signature$|_initials$|_date$/i, "");
1546
- const isActualSignatureField = fieldTypeName.includes("Signature") || cleanFieldName.toLowerCase().includes("signature") && !fieldTypeName.includes("CheckBox") && !fieldTypeName.includes("Radio");
1547
- const isActualInitialsField = cleanFieldName.toLowerCase().includes("initials") && !fieldTypeName.includes("CheckBox") && !fieldTypeName.includes("Radio");
2142
+ const isActualSignatureField = isSignatureType || cleanFieldName.toLowerCase().includes("signature") && !isCheckboxField && !isRadioField;
2143
+ const isActualInitialsField = cleanFieldName.toLowerCase().includes("initials") && !isCheckboxField && !isRadioField;
1548
2144
  if (isActualSignatureField) {
1549
2145
  fieldType = "signature" /* SIGNATURE */;
1550
2146
  } else if (isActualInitialsField) {
1551
2147
  fieldType = "initials" /* INITIALS */;
1552
2148
  hasAnyInitialsFields = true;
1553
- if (currentSignerEmail && fieldMetadata.signer === currentSignerEmail) {
1554
- hasInitialsFieldsForCurrentSigner = true;
1555
- }
1556
2149
  } else if (cleanFieldName.toLowerCase().includes("date")) {
1557
2150
  fieldType = "date" /* DATE */;
1558
- } else if (fieldTypeName.includes("CheckBox")) {
2151
+ } else if (isCheckboxField) {
1559
2152
  fieldType = "checkbox" /* CHECKBOX */;
1560
- } else if (fieldTypeName.toLowerCase().includes("dropdown")) {
2153
+ } else if (isDropdownField) {
1561
2154
  fieldType = "dropdown" /* DROPDOWN */;
1562
- } else if (fieldTypeName.includes("Radio")) {
2155
+ } else if (isRadioField) {
1563
2156
  fieldType = "radio" /* RADIO */;
1564
2157
  }
1565
2158
  let displayLabel = fieldMetadata.label || "";
2159
+ let isLabelAutoGenerated = false;
1566
2160
  if (!displayLabel || !displayLabel.trim()) {
1567
2161
  try {
1568
2162
  const tuLabel = extractTULabel(fieldWithExtensions);
@@ -1574,6 +2168,7 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1574
2168
  }
1575
2169
  if (!displayLabel || !displayLabel.trim()) {
1576
2170
  displayLabel = generateFallbackLabel(cleanFieldName, fieldType);
2171
+ isLabelAutoGenerated = true;
1577
2172
  }
1578
2173
  const esignField = {
1579
2174
  id: fieldName,
@@ -1585,6 +2180,8 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1585
2180
  type: fieldType,
1586
2181
  label: displayLabel,
1587
2182
  // Use friendly label for display
2183
+ isLabelAutoGenerated,
2184
+ // True when label was generated from field name (should not be drawn on PDF)
1588
2185
  position: { x: 0, y: 0, width: 100, height: 30, page: 1 },
1589
2186
  // Default position
1590
2187
  required: fieldWithExtensions.isRequired?.() ?? false,
@@ -1605,6 +2202,13 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1605
2202
  logger.warn("Error extracting options for field:", error);
1606
2203
  }
1607
2204
  }
2205
+ try {
2206
+ const currentValue = extractFieldValue(f, esignField.type);
2207
+ if (currentValue) {
2208
+ esignField.defaultValue = currentValue;
2209
+ }
2210
+ } catch {
2211
+ }
1608
2212
  visibleFields.push(esignField);
1609
2213
  }
1610
2214
  }
@@ -1621,11 +2225,8 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1621
2225
  placeholder: "Draw or upload your signature",
1622
2226
  assignedSignerEmail: currentSignerEmail
1623
2227
  });
1624
- const shouldCreateInitialsField = hasInitialsFieldsForCurrentSigner || hasAnyInitialsFields && !currentSignerEmail;
2228
+ const shouldCreateInitialsField = hasAnyInitialsFields;
1625
2229
  if (shouldCreateInitialsField) {
1626
- if (hasInitialsFieldsForCurrentSigner) {
1627
- } else {
1628
- }
1629
2230
  mainFields.push({
1630
2231
  id: "initials_field_main",
1631
2232
  fieldId: "initials_field_main",
@@ -1712,8 +2313,12 @@ function decodeFieldName(fieldName) {
1712
2313
  }
1713
2314
  function generateFallbackLabel(decodedFieldName, fieldType) {
1714
2315
  let displayLabel = decodedFieldName;
1715
- displayLabel = displayLabel.replace(/_signature$/i, "").replace(/_initials$/i, "").replace(/_date$/i, "");
1716
- if (/^(text|signature|initials|date)_\d+$/i.test(displayLabel)) {
2316
+ let prevLabel = "";
2317
+ while (displayLabel !== prevLabel) {
2318
+ prevLabel = displayLabel;
2319
+ displayLabel = displayLabel.replace(/_signature$/i, "").replace(/_initials$/i, "").replace(/_date$/i, "");
2320
+ }
2321
+ if (/^(text|signature|initials|date|checkbox|radio|dropdown)_\d+/i.test(displayLabel)) {
1717
2322
  if (fieldType === "signature" /* SIGNATURE */) return "Signature";
1718
2323
  if (fieldType === "initials" /* INITIALS */) return "Initials";
1719
2324
  if (fieldType === "date" /* DATE */) return "Date";
@@ -1721,9 +2326,9 @@ function generateFallbackLabel(decodedFieldName, fieldType) {
1721
2326
  if (fieldType === "checkbox" /* CHECKBOX */) return "Checkbox";
1722
2327
  if (fieldType === "dropdown" /* DROPDOWN */) return "Dropdown";
1723
2328
  if (fieldType === "radio" /* RADIO */) return "Option";
1724
- } else {
1725
- displayLabel = displayLabel.replace(/_/g, " ").replace(/\s+\d+$/g, "").trim().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
2329
+ if (fieldType === "text_label" /* TEXT_LABEL */) return "Text Label";
1726
2330
  }
2331
+ displayLabel = displayLabel.replace(/_/g, " ").replace(/\s+\d+$/g, "").trim().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
1727
2332
  return displayLabel;
1728
2333
  }
1729
2334
  function extractTULabel(field) {
@@ -1750,6 +2355,28 @@ function extractTULabel(field) {
1750
2355
  return "";
1751
2356
  }
1752
2357
  }
2358
+ function findFieldByUuid(fields, uuid) {
2359
+ return fields.find((f) => f.fieldId === uuid);
2360
+ }
2361
+ function resolveField(fields, identifier) {
2362
+ let field = findFieldByUuid(fields, identifier);
2363
+ if (field) {
2364
+ return field;
2365
+ }
2366
+ field = fields.find((f) => f.id === identifier);
2367
+ if (field) {
2368
+ return field;
2369
+ }
2370
+ field = fields.find((f) => f.name === identifier);
2371
+ if (field) {
2372
+ return field;
2373
+ }
2374
+ const cleanIdentifier = identifier.replace(/_signature$|_initials$|_date$/i, "");
2375
+ return fields.find((f) => f.fieldId === cleanIdentifier || f.id === cleanIdentifier || f.name === cleanIdentifier);
2376
+ }
2377
+ function getFieldUuidsForSigner(fields, signerEmail) {
2378
+ return fields.filter((f) => f.assignedSignerEmail === signerEmail && f.fieldId).map((f) => f.fieldId);
2379
+ }
1753
2380
  var CDN_WORKER = "https://cdn.jsdelivr.net/npm/pdfjs-dist@5.3.93/build/pdf.worker.mjs";
1754
2381
  var CDN_VIEWER = "https://mozilla.github.io/pdf.js";
1755
2382
  var _workerSrcComputed = false;
@@ -1823,7 +2450,7 @@ function initializePdfJs() {
1823
2450
  async function checkPdfJsVersion(viewerBasePath = "/pdfjs") {
1824
2451
  const workerVersion = pdfjsLib2__namespace.version;
1825
2452
  try {
1826
- const versionUrl = `${viewerBasePath}/.version`;
2453
+ const versionUrl = `${viewerBasePath}/version.txt`;
1827
2454
  const response = await fetch(versionUrl);
1828
2455
  if (!response.ok) {
1829
2456
  return {
@@ -2051,13 +2678,13 @@ function getErrorMessage(error, defaultMessage = "Unknown error") {
2051
2678
 
2052
2679
  // src/utils/attachment-validators.ts
2053
2680
  var DEFAULT_ATTACHMENT_CONSTRAINTS = {
2054
- maxFileSize: 10 * 1024 * 1024,
2055
- // 10MB
2681
+ maxFileSize: 25 * 1024 * 1024,
2682
+ // 25MB
2056
2683
  maxTotalSize: 50 * 1024 * 1024,
2057
2684
  // 50MB
2058
2685
  maxFiles: 10,
2059
2686
  allowedTypes: ["image/*", "application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"],
2060
- allowedExtensions: [".pdf", ".jpg", ".jpeg", ".png", ".gif", ".doc", ".docx"]
2687
+ allowedExtensions: [".pdf", ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".doc", ".docx"]
2061
2688
  };
2062
2689
  function validateFile(file, constraints = DEFAULT_ATTACHMENT_CONSTRAINTS) {
2063
2690
  const errors = [];
@@ -2349,6 +2976,23 @@ function withPerformanceMonitoring(label, fn, monitor = globalPerformanceMonitor
2349
2976
  }
2350
2977
  });
2351
2978
  }
2979
+ function isValidISODate(value) {
2980
+ if (!value || typeof value !== "string") {
2981
+ return false;
2982
+ }
2983
+ const isoPattern = /^\d{4}-\d{2}-\d{2}$/;
2984
+ if (!isoPattern.test(value)) {
2985
+ return false;
2986
+ }
2987
+ try {
2988
+ const date = dateFns.parseISO(value);
2989
+ return dateFns.isValid(date) && !isNaN(date.getTime());
2990
+ } catch {
2991
+ return false;
2992
+ }
2993
+ }
2994
+
2995
+ // src/utils/date-validation.ts
2352
2996
  function toIsoDateString(date) {
2353
2997
  const year = date.getFullYear();
2354
2998
  const month = String(date.getMonth() + 1).padStart(2, "0");
@@ -2472,21 +3116,6 @@ function parseAndValidateDate(value) {
2472
3116
  error: `Invalid date format: "${trimmedValue}". Please use a date picker or format like MM/DD/YYYY.`
2473
3117
  };
2474
3118
  }
2475
- function isValidISODate(value) {
2476
- if (!value || typeof value !== "string") {
2477
- return false;
2478
- }
2479
- const isoPattern = /^\d{4}-\d{2}-\d{2}$/;
2480
- if (!isoPattern.test(value)) {
2481
- return false;
2482
- }
2483
- try {
2484
- const date = dateFns.parseISO(value);
2485
- return dateFns.isValid(date) && !isNaN(date.getTime());
2486
- } catch {
2487
- return false;
2488
- }
2489
- }
2490
3119
 
2491
3120
  // src/utils/tracking.ts
2492
3121
  var DEFAULT_API_ENDPOINT = "https://api-dev.signiphi.ai";
@@ -2570,10 +3199,13 @@ exports.AttachmentValidationError = AttachmentValidationError;
2570
3199
  exports.CDN_VIEWER = CDN_VIEWER;
2571
3200
  exports.CDN_WORKER = CDN_WORKER;
2572
3201
  exports.DEFAULT_ATTACHMENT_CONSTRAINTS = DEFAULT_ATTACHMENT_CONSTRAINTS;
3202
+ exports.DEFAULT_SIGNATURE_FONT = DEFAULT_SIGNATURE_FONT;
2573
3203
  exports.FormFieldError = FormFieldError;
2574
3204
  exports.PdfProcessingError = PdfProcessingError;
2575
3205
  exports.PdfValidationError = PdfValidationError;
2576
3206
  exports.PerformanceMonitor = PerformanceMonitor;
3207
+ exports.SIGNATURE_FONTS = SIGNATURE_FONTS;
3208
+ exports.areAllSignersComplete = areAllSignersComplete;
2577
3209
  exports.captureAuditTrail = captureAuditTrail;
2578
3210
  exports.captureDeviceMetadata = captureDeviceMetadata;
2579
3211
  exports.captureGeolocation = captureGeolocation;
@@ -2591,22 +3223,30 @@ exports.extractVisibleFormFields = extractVisibleFormFields;
2591
3223
  exports.fillFormFieldsWithSignatures = fillFormFieldsWithSignatures;
2592
3224
  exports.fillPdfWithSignatures = fillPdfWithSignatures;
2593
3225
  exports.filterFieldsBySigner = filterFieldsBySigner;
3226
+ exports.findFieldByUuid = findFieldByUuid;
2594
3227
  exports.findPageIndexByRef = findPageIndexByRef;
2595
3228
  exports.findPageIndexWithFallback = findPageIndexWithFallback;
2596
3229
  exports.formatFieldName = formatFieldName;
2597
3230
  exports.formatFileSize = formatFileSize;
2598
3231
  exports.generateFallbackLabel = generateFallbackLabel;
3232
+ exports.generateSignatureFromText = generateSignatureFromText;
3233
+ exports.generateSignatureFromTextAsync = generateSignatureFromTextAsync;
2599
3234
  exports.getErrorMessage = getErrorMessage;
3235
+ exports.getFieldDisplayName = getFieldDisplayName;
2600
3236
  exports.getFieldPageNumbers = getFieldPageNumbers;
3237
+ exports.getFieldUuidsForSigner = getFieldUuidsForSigner;
3238
+ exports.getNextSigner = getNextSigner;
2601
3239
  exports.getPdfJsConfig = getPdfJsConfig;
2602
3240
  exports.getSigniphiMetadata = getSigniphiMetadata;
2603
3241
  exports.getWidgetRectangleAndPage = getWidgetRectangleAndPage;
2604
3242
  exports.globalPerformanceMonitor = globalPerformanceMonitor;
3243
+ exports.hasDrawableLabel = hasDrawableLabel;
2605
3244
  exports.initPdfMetadata = initPdfMetadata;
2606
3245
  exports.initializePdfJs = initializePdfJs;
2607
3246
  exports.isAttachmentValidationError = isAttachmentValidationError;
2608
3247
  exports.isAutoGeneratedLabel = isAutoGeneratedLabel;
2609
3248
  exports.isFieldVisibleToSigner = isFieldVisibleToSigner;
3249
+ exports.isFontLoaded = isFontLoaded;
2610
3250
  exports.isFormFieldError = isFormFieldError;
2611
3251
  exports.isImageType = isImageType;
2612
3252
  exports.isInitialsField = isInitialsField;
@@ -2616,15 +3256,18 @@ exports.isRequiredField = isRequiredField;
2616
3256
  exports.isSignatureField = isSignatureField;
2617
3257
  exports.isValidISODate = isValidISODate;
2618
3258
  exports.isValidPdf = isValidPdf;
3259
+ exports.loadSignatureFonts = loadSignatureFonts;
2619
3260
  exports.logVersionCheckWarning = logVersionCheckWarning;
2620
3261
  exports.logger = logger;
2621
3262
  exports.measurePerformance = measurePerformance;
2622
3263
  exports.parseAndValidateDate = parseAndValidateDate;
2623
3264
  exports.pdfToImages = pdfToImages;
3265
+ exports.preparePdfForSigner = preparePdfForSigner;
2624
3266
  exports.readCurrentPdfFormValues = readCurrentPdfFormValues;
2625
3267
  exports.readPdfFormFields = readPdfFormFields;
2626
3268
  exports.removeAllFormFields = removeAllFormFields;
2627
3269
  exports.resetPdfJsConfig = resetPdfJsConfig;
3270
+ exports.resolveField = resolveField;
2628
3271
  exports.setPdfJsConfig = setPdfJsConfig;
2629
3272
  exports.setSigniphiMetadata = setSigniphiMetadata;
2630
3273
  exports.shouldFlattenField = shouldFlattenField;
@@ -2634,6 +3277,7 @@ exports.trackDocumentSigned = trackDocumentSigned;
2634
3277
  exports.trackDocumentSignedSilent = trackDocumentSignedSilent;
2635
3278
  exports.urlToPdfBytes = urlToPdfBytes;
2636
3279
  exports.validateCurrentPdfState = validateCurrentPdfState;
3280
+ exports.validateFieldAssignments = validateFieldAssignments;
2637
3281
  exports.validateFieldValues = validateFieldValues;
2638
3282
  exports.validateFile = validateFile;
2639
3283
  exports.validateFileOrThrow = validateFileOrThrow;
@@ -2644,6 +3288,7 @@ exports.validatePdfBytes = validatePdfBytes;
2644
3288
  exports.validatePdfFormFields = validatePdfFormFields;
2645
3289
  exports.validatePdfUrl = validatePdfUrl;
2646
3290
  exports.validateSignatures = validateSignatures;
3291
+ exports.waitForFont = waitForFont;
2647
3292
  exports.withPerformanceMonitoring = withPerformanceMonitoring;
2648
3293
  //# sourceMappingURL=index.js.map
2649
3294
  //# sourceMappingURL=index.js.map