@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
@@ -56,6 +56,7 @@ function validatePdfBytes(pdfBytes) {
56
56
  }
57
57
  function isAutoGeneratedLabel(label) {
58
58
  if (!label || !label.trim()) return true;
59
+ const trimmed = label.trim();
59
60
  const autoLabels = [
60
61
  "Signature",
61
62
  "Initials",
@@ -66,7 +67,65 @@ function isAutoGeneratedLabel(label) {
66
67
  "Option",
67
68
  "Radio"
68
69
  ];
69
- return autoLabels.includes(label.trim());
70
+ if (autoLabels.includes(trimmed)) return true;
71
+ if (/^\d{10,}$/.test(trimmed)) return true;
72
+ const typeTimestampPattern = new RegExp(
73
+ `^(${autoLabels.join("|")})[\\s_-]?\\d{10,}$`,
74
+ "i"
75
+ );
76
+ if (typeTimestampPattern.test(trimmed)) return true;
77
+ const typeNumberPattern = new RegExp(
78
+ `^(${autoLabels.join("|")})[\\s_-]?\\d{1,3}$`,
79
+ "i"
80
+ );
81
+ if (typeNumberPattern.test(trimmed)) return true;
82
+ const typeWordsJoined = autoLabels.join("|");
83
+ const corruptedPattern = new RegExp(
84
+ `^(${typeWordsJoined})[\\s_-]?\\d{10,}[\\s_-]?(${typeWordsJoined})+`,
85
+ "i"
86
+ );
87
+ if (corruptedPattern.test(trimmed)) return true;
88
+ const repeatedTypePattern = new RegExp(
89
+ `^((${typeWordsJoined})[\\s_-]+)+(${typeWordsJoined})$`,
90
+ "i"
91
+ );
92
+ if (repeatedTypePattern.test(trimmed)) return true;
93
+ return false;
94
+ }
95
+ function hasDrawableLabel(field) {
96
+ if (!field.label || !field.label.trim()) return false;
97
+ if (field.isLabelAutoGenerated) return false;
98
+ if (isAutoGeneratedLabel(field.label)) return false;
99
+ return true;
100
+ }
101
+ function getFieldDisplayName(field) {
102
+ if (field.label && !isAutoGeneratedLabel(field.label)) {
103
+ return field.label;
104
+ }
105
+ const typeNames = {
106
+ "text": "Text field",
107
+ "signature": "Signature",
108
+ "initials": "Initials",
109
+ "date": "Date field",
110
+ "checkbox": "Checkbox",
111
+ "dropdown": "Dropdown",
112
+ "radio": "Radio selection",
113
+ "radiogroup": "Radio selection",
114
+ "text_label": "Text label"
115
+ };
116
+ if (field.type) {
117
+ const typeName = typeNames[field.type.toLowerCase()];
118
+ if (typeName) {
119
+ return typeName;
120
+ }
121
+ }
122
+ if (field.name) {
123
+ let cleaned = field.name.replace(/_?(signature|initials|date)$/i, "").replace(/[_-]\d{10,}$/, "").replace(/[_-]/g, " ").trim();
124
+ if (cleaned && !isAutoGeneratedLabel(cleaned)) {
125
+ return cleaned.replace(/\b\w/g, (l) => l.toUpperCase());
126
+ }
127
+ }
128
+ return "This field";
70
129
  }
71
130
  function validateFieldValues(values) {
72
131
  const errors = [];
@@ -302,6 +361,114 @@ function getSigniphiMetadata(pdfDoc) {
302
361
  }
303
362
  }
304
363
 
364
+ // src/utils/font-loader.ts
365
+ var SIGNATURE_FONTS = [
366
+ { name: "dancing-script", family: "Dancing Script", label: "Elegant" },
367
+ { name: "great-vibes", family: "Great Vibes", label: "Formal" },
368
+ { name: "caveat", family: "Caveat", label: "Casual" },
369
+ { name: "homemade-apple", family: "Homemade Apple", label: "Natural" },
370
+ { name: "sacramento", family: "Sacramento", label: "Flowing" }
371
+ ];
372
+ var DEFAULT_SIGNATURE_FONT = {
373
+ name: "dancing-script",
374
+ family: "Dancing Script",
375
+ label: "Elegant"
376
+ };
377
+ var GOOGLE_FONTS_URL = "https://fonts.googleapis.com/css2?family=Dancing+Script&family=Great+Vibes&family=Caveat&family=Homemade+Apple&family=Sacramento&display=swap";
378
+ var fontsLoaded = false;
379
+ var fontsLoadingPromise = null;
380
+ async function loadSignatureFonts() {
381
+ if (fontsLoaded) {
382
+ return;
383
+ }
384
+ if (fontsLoadingPromise) {
385
+ return fontsLoadingPromise;
386
+ }
387
+ fontsLoadingPromise = new Promise((resolve, reject) => {
388
+ const existingLink = document.querySelector(
389
+ `link[href="${GOOGLE_FONTS_URL}"]`
390
+ );
391
+ if (existingLink) {
392
+ fontsLoaded = true;
393
+ resolve();
394
+ return;
395
+ }
396
+ const link = document.createElement("link");
397
+ link.href = GOOGLE_FONTS_URL;
398
+ link.rel = "stylesheet";
399
+ link.onload = () => {
400
+ fontsLoaded = true;
401
+ resolve();
402
+ };
403
+ link.onerror = () => {
404
+ fontsLoadingPromise = null;
405
+ reject(new Error("Failed to load signature fonts from Google Fonts"));
406
+ };
407
+ document.head.appendChild(link);
408
+ });
409
+ return fontsLoadingPromise;
410
+ }
411
+ function isFontLoaded(fontFamily) {
412
+ if (typeof document === "undefined") {
413
+ return false;
414
+ }
415
+ return document.fonts.check(`48px "${fontFamily}"`);
416
+ }
417
+ async function waitForFont(fontFamily) {
418
+ if (typeof document === "undefined") {
419
+ return false;
420
+ }
421
+ try {
422
+ await document.fonts.load(`48px "${fontFamily}"`);
423
+ return true;
424
+ } catch {
425
+ return false;
426
+ }
427
+ }
428
+ function generateSignatureFromText(options) {
429
+ const {
430
+ text,
431
+ fontFamily,
432
+ width = 450,
433
+ height = 200,
434
+ fontSize = 48,
435
+ color = "#000000",
436
+ backgroundColor = null
437
+ } = options;
438
+ const canvas = document.createElement("canvas");
439
+ canvas.width = width;
440
+ canvas.height = height;
441
+ const ctx = canvas.getContext("2d");
442
+ if (!ctx) {
443
+ throw new Error("Failed to get canvas 2d context");
444
+ }
445
+ if (backgroundColor) {
446
+ ctx.fillStyle = backgroundColor;
447
+ ctx.fillRect(0, 0, width, height);
448
+ } else {
449
+ ctx.clearRect(0, 0, width, height);
450
+ }
451
+ ctx.font = `${fontSize}px "${fontFamily}"`;
452
+ ctx.fillStyle = color;
453
+ ctx.textAlign = "center";
454
+ ctx.textBaseline = "middle";
455
+ let adjustedFontSize = fontSize;
456
+ let textMetrics = ctx.measureText(text);
457
+ const maxWidth = width * 0.9;
458
+ while (textMetrics.width > maxWidth && adjustedFontSize > 16) {
459
+ adjustedFontSize -= 2;
460
+ ctx.font = `${adjustedFontSize}px "${fontFamily}"`;
461
+ textMetrics = ctx.measureText(text);
462
+ }
463
+ ctx.fillText(text, width / 2, height / 2);
464
+ return canvas.toDataURL("image/png");
465
+ }
466
+ async function generateSignatureFromTextAsync(options) {
467
+ await loadSignatureFonts();
468
+ await waitForFont(options.fontFamily);
469
+ return generateSignatureFromText(options);
470
+ }
471
+
305
472
  // src/utils/pdf-lib-loader.ts
306
473
  var pdfLibPromise = null;
307
474
  async function loadPdfLib() {
@@ -316,18 +483,15 @@ function isFieldVisibleToSigner(field, multiSignerContext) {
316
483
  if (!multiSignerContext.isMultiSigner) {
317
484
  return true;
318
485
  }
319
- const { currentSignerEmail, isPrimarySigner, isFinalSigner } = multiSignerContext;
486
+ const { currentSignerEmail } = multiSignerContext;
320
487
  if (!field.assignedSignerEmail) {
321
- return isFinalSigner;
488
+ return true;
322
489
  }
323
490
  if (field.assignedSignerEmail === currentSignerEmail) {
324
491
  return true;
325
492
  }
326
- if (field.assignedSignerEmail.includes("recipients")) {
327
- return isPrimarySigner;
328
- }
329
- if (field.assignedSignerEmail.includes("signers")) {
330
- return isFinalSigner;
493
+ if (field.assignedSignerEmail === "to-recipients" || field.assignedSignerEmail === "additional-signers") {
494
+ return true;
331
495
  }
332
496
  return false;
333
497
  }
@@ -341,18 +505,15 @@ function shouldFlattenField(field, multiSignerContext) {
341
505
  if (!multiSignerContext.isMultiSigner) {
342
506
  return true;
343
507
  }
344
- const { currentSignerEmail, isPrimarySigner, isFinalSigner } = multiSignerContext;
508
+ const { currentSignerEmail } = multiSignerContext;
345
509
  if (!field.assignedSignerEmail) {
346
- return isFinalSigner;
510
+ return true;
347
511
  }
348
512
  if (field.assignedSignerEmail === currentSignerEmail) {
349
513
  return true;
350
514
  }
351
- if (field.assignedSignerEmail.includes("recipients")) {
352
- return isPrimarySigner;
353
- }
354
- if (field.assignedSignerEmail.includes("signers")) {
355
- return isFinalSigner;
515
+ if (field.assignedSignerEmail === "to-recipients" || field.assignedSignerEmail === "additional-signers") {
516
+ return true;
356
517
  }
357
518
  return false;
358
519
  }
@@ -392,18 +553,23 @@ function findPageIndexWithFallback(pages, pageRef) {
392
553
 
393
554
  // src/utils/pdf-field-type-helpers.ts
394
555
  function detectFieldType(field) {
395
- const typeName = field.constructor.name;
396
- if (typeName === "PDFTextField") {
397
- return "text";
398
- } else if (typeName === "PDFCheckBox") {
556
+ const f = field;
557
+ if (typeof f.check === "function" && typeof f.uncheck === "function") {
399
558
  return "checkbox";
400
- } else if (typeName === "PDFDropdown") {
559
+ }
560
+ if (typeof f.select === "function" && typeof f.getOptions === "function" && typeof f.check !== "function" && typeof f.setOptions !== "function") {
561
+ return "radiogroup";
562
+ }
563
+ if (typeof f.select === "function" && typeof f.getOptions === "function" && (typeof f.setOptions === "function" || typeof f.addOptions === "function")) {
401
564
  return "dropdown";
402
- } else if (typeName === "PDFOptionList") {
565
+ }
566
+ if (typeof f.getOptions === "function" && typeof f.setOptions === "function" && typeof f.select !== "function") {
403
567
  return "optionlist";
404
- } else if (typeName === "PDFRadioGroup") {
405
- return "radiogroup";
406
- } else if (typeName === "PDFSignature") {
568
+ }
569
+ if (typeof f.getText === "function" && typeof f.setText === "function") {
570
+ return "text";
571
+ }
572
+ if (typeof f.getText !== "function" && typeof f.check !== "function" && typeof f.select !== "function") {
407
573
  return "signature";
408
574
  }
409
575
  return "unknown";
@@ -412,13 +578,20 @@ function extractFieldValue(field, fieldType) {
412
578
  try {
413
579
  switch (fieldType) {
414
580
  case "text":
581
+ case "date":
415
582
  return field.getText?.() || "";
416
583
  case "checkbox":
417
584
  return field.isChecked?.() ? "true" : "false";
418
585
  case "dropdown":
419
- case "optionlist":
586
+ case "optionlist": {
587
+ const selected = field.getSelected?.();
588
+ return Array.isArray(selected) ? selected[0] || "" : String(selected || "");
589
+ }
420
590
  case "radiogroup":
421
- return field.getSelected?.()?.[0] || "";
591
+ case "radio": {
592
+ const radioSelected = field.getSelected?.();
593
+ return radioSelected ? String(radioSelected) : "";
594
+ }
422
595
  default:
423
596
  return "";
424
597
  }
@@ -722,12 +895,16 @@ async function validatePdfFormFields(pdfBytes, fieldValues, signatures, extracte
722
895
  const errors = [];
723
896
  for (const field of pdfFormFields) {
724
897
  if (field.required) {
898
+ const extractedField = extractedFields?.find((f) => f.name === field.name);
725
899
  if (multiSignerContext?.isMultiSigner && extractedFields) {
726
- const extractedField = extractedFields.find((f) => f.name === field.name);
727
900
  if (!extractedField) {
728
901
  continue;
729
902
  }
730
903
  }
904
+ const logicalType = extractedField?.type || field.type;
905
+ if (logicalType === "date" || logicalType === "signature" || logicalType === "initials") {
906
+ continue;
907
+ }
731
908
  let hasValue = false;
732
909
  const fieldValue = fieldValues[field.name];
733
910
  const signatureValue = signatures[field.name];
@@ -737,16 +914,17 @@ async function validatePdfFormFields(pdfBytes, fieldValues, signatures, extracte
737
914
  hasValue = !!(signatureValue || fieldValue || mainSignature);
738
915
  } else if (field.name.includes("initials")) {
739
916
  hasValue = !!(signatureValue || fieldValue || mainInitials);
917
+ } else if (field.type === "checkbox" || logicalType === "checkbox") {
918
+ hasValue = fieldValue === "true" || field.value === "true";
740
919
  } else {
741
920
  hasValue = !!(fieldValue || field.value);
742
921
  }
743
922
  if (!hasValue) {
744
- let friendlyName = field.name.replace(/[_-]/g, " ").replace(/\b\w/g, (l) => l.toUpperCase());
745
- if (field.name.includes("signature")) {
746
- friendlyName = "Signature";
747
- } else if (field.name.includes("initials")) {
748
- friendlyName = "Initials";
749
- }
923
+ const friendlyName = getFieldDisplayName({
924
+ label: extractedField?.label,
925
+ name: field.name,
926
+ type: logicalType
927
+ });
750
928
  errors.push(`${friendlyName} is required`);
751
929
  }
752
930
  }
@@ -776,12 +954,10 @@ async function validateCurrentPdfState(pdfBytes, signatures, formFieldValues = {
776
954
  hasValue = currentValue.trim() !== "";
777
955
  }
778
956
  if (!hasValue) {
779
- let friendlyName = field.name.replace(/[_-]/g, " ").replace(/\b\w/g, (l) => l.toUpperCase());
780
- if (field.name.includes("signature")) {
781
- friendlyName = "Signature";
782
- } else if (field.name.includes("initials")) {
783
- friendlyName = "Initials";
784
- }
957
+ const friendlyName = getFieldDisplayName({
958
+ name: field.name,
959
+ type: field.type
960
+ });
785
961
  errors.push(`${friendlyName} is required`);
786
962
  }
787
963
  }
@@ -792,7 +968,80 @@ async function validateCurrentPdfState(pdfBytes, signatures, formFieldValues = {
792
968
  throw error;
793
969
  }
794
970
  }
795
- async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {}, currentSignerEmail, extractedFormFields, metadata, auditTrail, multiSignerContext) {
971
+ function extractFieldFontSize(fieldName, field, extractedFormFields) {
972
+ const DEFAULT_FONT_SIZE = 10;
973
+ const MIN_FONT_SIZE = 8;
974
+ const MAX_FONT_SIZE = 72;
975
+ const fieldInfo = extractedFormFields?.find((f) => f.name === fieldName);
976
+ if (fieldInfo?.fontSize && fieldInfo.fontSize >= MIN_FONT_SIZE && fieldInfo.fontSize <= MAX_FONT_SIZE) {
977
+ return fieldInfo.fontSize;
978
+ }
979
+ const daFontSize = extractFromDAField(field);
980
+ if (daFontSize !== null) {
981
+ return daFontSize;
982
+ }
983
+ const tuFontSize = extractFromTUField(field);
984
+ if (tuFontSize !== null) {
985
+ return tuFontSize;
986
+ }
987
+ return DEFAULT_FONT_SIZE;
988
+ }
989
+ function extractFromDAField(field) {
990
+ try {
991
+ const fieldWithAcro = field;
992
+ const dict = fieldWithAcro.acroField?.dict;
993
+ if (!dict) return null;
994
+ const daKey = dict.context?.obj?.("DA") || "DA";
995
+ const daEntry = dict.lookup?.(daKey) || dict.get?.(daKey);
996
+ if (!daEntry) return null;
997
+ let daValue = "";
998
+ if (typeof daEntry.decodeText === "function") {
999
+ daValue = daEntry.decodeText();
1000
+ } else if (typeof daEntry.asString === "function") {
1001
+ daValue = daEntry.asString();
1002
+ } else {
1003
+ daValue = String(daEntry);
1004
+ }
1005
+ const daMatch = daValue.match(/\s+(\d+)\s+Tf/i);
1006
+ if (daMatch?.[1]) {
1007
+ const fontSize = parseInt(daMatch[1], 10);
1008
+ if (fontSize >= 8 && fontSize <= 72) {
1009
+ return fontSize;
1010
+ }
1011
+ }
1012
+ } catch {
1013
+ }
1014
+ return null;
1015
+ }
1016
+ function extractFromTUField(field) {
1017
+ try {
1018
+ const fieldWithAcro = field;
1019
+ const dict = fieldWithAcro.acroField?.dict;
1020
+ if (!dict) return null;
1021
+ const tuKey = dict.context?.obj?.("TU") || "TU";
1022
+ const tuEntry = dict.lookup?.(tuKey) || dict.get?.(tuKey);
1023
+ if (!tuEntry) return null;
1024
+ let tuValue = "";
1025
+ if (typeof tuEntry.decodeText === "function") {
1026
+ tuValue = tuEntry.decodeText();
1027
+ } else if (typeof tuEntry.asString === "function") {
1028
+ tuValue = tuEntry.asString();
1029
+ } else {
1030
+ tuValue = String(tuEntry);
1031
+ }
1032
+ tuValue = tuValue.replace(/^\(|\)$|^<|>$/g, "");
1033
+ const match = tuValue.match(/\|fontSize:(\d+)$/);
1034
+ if (match?.[1]) {
1035
+ const fontSize = parseInt(match[1], 10);
1036
+ if (fontSize >= 8 && fontSize <= 72) {
1037
+ return fontSize;
1038
+ }
1039
+ }
1040
+ } catch {
1041
+ }
1042
+ return null;
1043
+ }
1044
+ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {}, _currentSignerEmail, extractedFormFields, metadata, auditTrail, multiSignerContext) {
796
1045
  try {
797
1046
  const { PDFDocument, rgb, StandardFonts } = await loadPdfLib();
798
1047
  const pdfDoc = await PDFDocument.load(pdfBytes);
@@ -809,39 +1058,39 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
809
1058
  continue;
810
1059
  }
811
1060
  try {
812
- const fieldTypeName = field.constructor.name;
813
- if (fieldTypeName === "PDFTextField" || fieldTypeName === "PDFTextField2") {
814
- const textField = field;
815
- textField.setText?.(fieldValue);
816
- } else if (fieldTypeName === "PDFCheckBox" || fieldTypeName === "PDFCheckBox2") {
817
- const checkBox = field;
1061
+ const f = field;
1062
+ const isTextField = typeof f.getText === "function" && typeof f.setText === "function";
1063
+ const isCheckbox = typeof f.check === "function" && typeof f.uncheck === "function";
1064
+ const isRadio = typeof f.select === "function" && typeof f.getOptions === "function" && typeof f.check !== "function" && typeof f.setOptions !== "function";
1065
+ const isDropdown = typeof f.select === "function" && (typeof f.setOptions === "function" || typeof f.addOptions === "function");
1066
+ if (isTextField) {
1067
+ f.setText?.(fieldValue);
1068
+ } else if (isCheckbox) {
818
1069
  if (fieldValue === "true" || fieldValue === "Yes" || fieldValue === "checked" || fieldValue === "On") {
819
- checkBox.check?.();
1070
+ f.check?.();
820
1071
  } else {
821
- checkBox.uncheck?.();
1072
+ f.uncheck?.();
822
1073
  }
823
- } else if (fieldTypeName === "PDFRadioGroup" || fieldTypeName === "PDFRadioGroup2") {
824
- const radioGroup = field;
1074
+ } else if (isRadio) {
825
1075
  if (fieldValue === "true" || fieldValue === "false") {
826
1076
  continue;
827
1077
  }
828
1078
  const idxMatch = fieldValue.match(/__RADIO_OPTION_INDEX_(\d+)__/);
829
1079
  if (idxMatch && idxMatch[1]) {
830
1080
  const selectedIndex = parseInt(idxMatch[1], 10);
831
- const options = radioGroup.getOptions?.() || [];
1081
+ const options = f.getOptions?.() || [];
832
1082
  if (selectedIndex >= 0 && selectedIndex < options.length) {
833
- radioGroup.select?.(options[selectedIndex]);
1083
+ f.select?.(options[selectedIndex]);
834
1084
  }
835
1085
  } else {
836
- const options = radioGroup.getOptions?.() || [];
1086
+ const options = f.getOptions?.() || [];
837
1087
  if (options.includes(fieldValue)) {
838
- radioGroup.select?.(fieldValue);
1088
+ f.select?.(fieldValue);
839
1089
  } else {
840
1090
  }
841
1091
  }
842
- } else if (fieldTypeName === "PDFDropdown" || fieldTypeName === "PDFDropdown2") {
843
- const dropdown = field;
844
- dropdown.select?.(fieldValue);
1092
+ } else if (isDropdown) {
1093
+ f.select?.(fieldValue);
845
1094
  }
846
1095
  } catch (fieldError) {
847
1096
  logger.error(`Error setting field "${fieldName}":`, fieldError);
@@ -849,11 +1098,6 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
849
1098
  }
850
1099
  try {
851
1100
  form.updateFieldAppearances();
852
- const PDFName3 = pdfLib.PDFName;
853
- const acroForm = pdfDoc.catalog.lookup(PDFName3.of("AcroForm"));
854
- if (acroForm && typeof acroForm === "object" && "set" in acroForm) {
855
- acroForm.set(PDFName3.of("NeedAppearances"), false);
856
- }
857
1101
  } catch (appearanceError) {
858
1102
  logger.warn("Could not update field appearances:", appearanceError);
859
1103
  }
@@ -922,6 +1166,20 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
922
1166
  const y = fieldPosition.y;
923
1167
  const width = Math.max(fieldPosition.width, 80);
924
1168
  const height = Math.max(fieldPosition.height, 30);
1169
+ const fieldInfo = extractedFormFields?.find((f) => f.name === fieldName);
1170
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1171
+ const labelFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
1172
+ const labelFontSize = Math.min(10, height * 0.4);
1173
+ const labelX = x;
1174
+ const labelY = y + height + 5;
1175
+ page.drawText(fieldInfo.label, {
1176
+ x: labelX,
1177
+ y: labelY,
1178
+ size: labelFontSize,
1179
+ font: labelFont,
1180
+ color: rgb(0, 0, 0)
1181
+ });
1182
+ }
925
1183
  const signatureDims = signatureImage.scaleToFit(width - 4, height - 4);
926
1184
  const finalX = x;
927
1185
  const finalY = y;
@@ -956,7 +1214,7 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
956
1214
  console.log("[FLATTEN] After pattern matching in fieldPageMap:", foundInitialsFields);
957
1215
  if (extractedFormFields && extractedFormFields.length > 0) {
958
1216
  foundInitialsFields = foundInitialsFields.filter((fieldName) => {
959
- const fieldInfo = extractedFormFields.find((f) => f.name === fieldName);
1217
+ const fieldInfo = extractedFormFields.find((f) => f.name === fieldName) || extractedFormFields.find((f) => f.name === fieldName.replace(/_initials$/i, "")) || extractedFormFields.find((f) => fieldName.startsWith(f.name));
960
1218
  if (!fieldInfo) return false;
961
1219
  const isActualInitialsField = fieldInfo.type === "initials" || fieldName.toLowerCase().includes("initials");
962
1220
  if (!isActualInitialsField) return false;
@@ -985,6 +1243,19 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
985
1243
  const y = fieldPosition.y;
986
1244
  const height = Math.max(fieldPosition.height, 20);
987
1245
  const fontSize = Math.min(height * 0.7, 14);
1246
+ 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");
1247
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1248
+ const labelFontSize = Math.min(10, height * 0.4);
1249
+ const labelX = x;
1250
+ const labelY = y + height + 5;
1251
+ page.drawText(fieldInfo.label, {
1252
+ x: labelX,
1253
+ y: labelY,
1254
+ size: labelFontSize,
1255
+ font,
1256
+ color: rgb(0, 0, 0)
1257
+ });
1258
+ }
988
1259
  const finalX = x + 2;
989
1260
  const finalY = y + (height - fontSize) / 2;
990
1261
  console.log("[FLATTEN] \u2705 Drawing initials at:", { x: finalX, y: finalY, fontSize, text: mainInitialsData });
@@ -1027,11 +1298,16 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1027
1298
  let flattenedCount = 0;
1028
1299
  for (const field of fieldsToFlatten) {
1029
1300
  const fieldName = field.getName();
1030
- const fieldType = field.constructor.name;
1301
+ const f = field;
1302
+ const isCheckboxField = typeof f.check === "function" && typeof f.uncheck === "function";
1303
+ const isRadioField = typeof f.select === "function" && typeof f.getOptions === "function" && typeof f.check !== "function" && typeof f.setOptions !== "function";
1304
+ const isDropdownField = typeof f.select === "function" && (typeof f.setOptions === "function" || typeof f.addOptions === "function");
1305
+ const isTextField = typeof f.getText === "function" && typeof f.setText === "function";
1306
+ const isSignatureType = !isCheckboxField && !isRadioField && !isDropdownField && !isTextField;
1031
1307
  try {
1032
1308
  const userEnteredValue = formFieldValues[fieldName];
1033
- const isSignatureField2 = fieldName.toLowerCase().includes("signature") || fieldType.includes("Signature");
1034
- const isInitialsField2 = fieldName.toLowerCase().includes("initials") || fieldType.includes("Initials");
1309
+ const isSignatureField2 = fieldName.toLowerCase().includes("signature") || isSignatureType;
1310
+ const isInitialsField2 = fieldName.toLowerCase().includes("initials");
1035
1311
  if (isSignatureField2 || isInitialsField2) {
1036
1312
  form.removeField(field);
1037
1313
  flattenedCount++;
@@ -1039,15 +1315,29 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1039
1315
  }
1040
1316
  const fieldWithWidgets = field;
1041
1317
  const widgets = fieldWithWidgets.acroField?.getWidgets?.() || [];
1042
- if (fieldType === "PDFCheckBox" || fieldType === "PDFCheckBox2") {
1318
+ if (isCheckboxField) {
1043
1319
  const stringValue = String(userEnteredValue || "");
1044
1320
  const isChecked = stringValue === "true" || stringValue === "Yes" || stringValue === "On" || stringValue === "checked";
1321
+ const fieldInfo = extractedFormFields?.find((f2) => f2.name === fieldName);
1322
+ const labelFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
1045
1323
  if (isChecked) {
1046
1324
  for (const widget of widgets) {
1047
1325
  const result = getWidgetRectangleAndPage(widget, pages);
1048
1326
  if (!result) continue;
1049
1327
  const { rect, page } = result;
1050
- const checkboxSize = Math.min(rect.width, rect.height) * 0.6;
1328
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1329
+ const labelFontSize = Math.min(10, rect.height * 0.4);
1330
+ const labelX = rect.x + rect.width + 5;
1331
+ const labelY = rect.y + (rect.height - labelFontSize) / 2;
1332
+ page.drawText(fieldInfo.label, {
1333
+ x: labelX,
1334
+ y: labelY,
1335
+ size: labelFontSize,
1336
+ font: labelFont,
1337
+ color: rgb(0, 0, 0)
1338
+ });
1339
+ }
1340
+ const checkboxSize = Math.min(rect.width, rect.height);
1051
1341
  const checkboxX = rect.x + (rect.width - checkboxSize) / 2;
1052
1342
  const checkboxY = rect.y + (rect.height - checkboxSize) / 2;
1053
1343
  page.drawRectangle({
@@ -1058,21 +1348,51 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1058
1348
  borderColor: rgb(0, 0, 0),
1059
1349
  borderWidth: 1
1060
1350
  });
1061
- const checkSize = checkboxSize * 0.6;
1062
- const textWidth = checkSize * 0.6;
1063
- const textHeight = checkSize * 0.8;
1351
+ const checkFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
1352
+ const checkFontSize = checkboxSize * 0.7;
1353
+ const textWidth = checkFont.widthOfTextAtSize("X", checkFontSize);
1354
+ const textHeight = checkFont.heightAtSize(checkFontSize);
1064
1355
  page.drawText("X", {
1065
1356
  x: checkboxX + (checkboxSize - textWidth) / 2,
1066
- y: checkboxY + (checkboxSize - textHeight) / 2 + textHeight * 0.2,
1067
- size: checkSize,
1068
- font: await pdfDoc.embedFont(StandardFonts.HelveticaBold),
1357
+ y: checkboxY + (checkboxSize - textHeight) / 2 + textHeight * 0.15,
1358
+ size: checkFontSize,
1359
+ font: checkFont,
1069
1360
  color: rgb(0, 0, 0)
1070
1361
  });
1071
1362
  }
1363
+ } else {
1364
+ for (const widget of widgets) {
1365
+ const result = getWidgetRectangleAndPage(widget, pages);
1366
+ if (!result) continue;
1367
+ const { rect, page } = result;
1368
+ const checkboxSize = Math.min(rect.width, rect.height);
1369
+ const checkboxX = rect.x + (rect.width - checkboxSize) / 2;
1370
+ const checkboxY = rect.y + (rect.height - checkboxSize) / 2;
1371
+ page.drawRectangle({
1372
+ x: checkboxX,
1373
+ y: checkboxY,
1374
+ width: checkboxSize,
1375
+ height: checkboxSize,
1376
+ borderColor: rgb(0, 0, 0),
1377
+ borderWidth: 1
1378
+ });
1379
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1380
+ const labelFontSize = Math.min(12, rect.height * 0.6);
1381
+ const labelX = rect.x + rect.width + 5;
1382
+ const labelY = rect.y + (rect.height - labelFontSize) / 2;
1383
+ page.drawText(fieldInfo.label, {
1384
+ x: labelX,
1385
+ y: labelY,
1386
+ size: labelFontSize,
1387
+ font: labelFont,
1388
+ color: rgb(0, 0, 0)
1389
+ });
1390
+ }
1391
+ }
1072
1392
  }
1073
- } else if (fieldType === "PDFRadioGroup" || fieldType === "PDFRadioGroup2") {
1074
- const radioGroup = field;
1075
- const fieldInfo = extractedFormFields?.find((f) => f.name === fieldName);
1393
+ } else if (isRadioField) {
1394
+ const radioGroup = f;
1395
+ const fieldInfo = extractedFormFields?.find((f2) => f2.name === fieldName);
1076
1396
  let actualSelectedValue = "";
1077
1397
  try {
1078
1398
  actualSelectedValue = radioGroup.getSelected?.() || "";
@@ -1117,14 +1437,15 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1117
1437
  const result = getWidgetRectangleAndPage(widget, pages);
1118
1438
  if (!result) continue;
1119
1439
  const { rect, page, pageIndex } = result;
1120
- if (i === 0 && fieldInfo?.label && fieldInfo.label.trim() && !isAutoGeneratedLabel(fieldInfo.label)) {
1440
+ if (i === 0 && fieldInfo && hasDrawableLabel(fieldInfo)) {
1121
1441
  const groupLabelKey = `${pageIndex}-${fieldName}-grouplabel`;
1122
1442
  if (!drawnGroupLabels.has(groupLabelKey)) {
1443
+ const labelFontSize = Math.min(10, rect.height * 0.4);
1123
1444
  const labelY = rect.y + rect.height + 3;
1124
1445
  page.drawText(fieldInfo.label, {
1125
1446
  x: rect.x,
1126
1447
  y: labelY,
1127
- size: 8,
1448
+ size: labelFontSize,
1128
1449
  font: labelFont,
1129
1450
  color: rgb(0, 0, 0)
1130
1451
  });
@@ -1132,22 +1453,21 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1132
1453
  }
1133
1454
  } else if (i === 0 && isAutoGeneratedLabel(fieldInfo?.label || "")) {
1134
1455
  }
1135
- const radioSize = Math.min(rect.width, rect.height) * 0.5;
1136
- const radioX = rect.x + (rect.width - radioSize) / 2;
1137
- const radioY = rect.y + (rect.height - radioSize) / 2;
1456
+ const radioSize = Math.min(rect.width, rect.height);
1457
+ const centerX = rect.x + rect.width / 2;
1458
+ const centerY = rect.y + rect.height / 2;
1138
1459
  page.drawCircle({
1139
- x: radioX + radioSize / 2,
1140
- y: radioY + radioSize / 2,
1141
- size: radioSize,
1460
+ x: centerX,
1461
+ y: centerY,
1462
+ size: radioSize / 2,
1142
1463
  borderColor: rgb(0, 0, 0),
1143
1464
  borderWidth: 1
1144
1465
  });
1145
1466
  if (i === selectedIndex) {
1146
- const circleSize = radioSize * 0.5;
1147
1467
  page.drawCircle({
1148
- x: radioX + radioSize / 2,
1149
- y: radioY + radioSize / 2,
1150
- size: circleSize,
1468
+ x: centerX,
1469
+ y: centerY,
1470
+ size: radioSize / 4,
1151
1471
  color: rgb(0, 0, 0)
1152
1472
  });
1153
1473
  }
@@ -1157,8 +1477,8 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1157
1477
  if (optionText && !drawnOptionLabels.has(optionKey)) {
1158
1478
  page.drawText(optionText, {
1159
1479
  x: rect.x + rect.width + 4,
1160
- y: rect.y + (rect.height - 8) / 2,
1161
- size: 8,
1480
+ y: rect.y + (rect.height - 7) / 2,
1481
+ size: 7,
1162
1482
  font: labelFont,
1163
1483
  color: rgb(0, 0, 0)
1164
1484
  });
@@ -1168,17 +1488,31 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1168
1488
  }
1169
1489
  if (fieldInfo?.options) {
1170
1490
  }
1171
- } else if (fieldType === "PDFDropdown" || fieldType === "PDFDropdown2") {
1491
+ } else if (isDropdownField) {
1172
1492
  const selectedValue = userEnteredValue ? String(userEnteredValue) : "";
1173
- if (selectedValue && selectedValue.trim()) {
1174
- for (const widget of widgets) {
1175
- const result = getWidgetRectangleAndPage(widget, pages);
1176
- if (!result) continue;
1177
- const { rect, page } = result;
1493
+ const fieldInfo = extractedFormFields?.find((f2) => f2.name === fieldName);
1494
+ const labelFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
1495
+ for (const widget of widgets) {
1496
+ const result = getWidgetRectangleAndPage(widget, pages);
1497
+ if (!result) continue;
1498
+ const { rect, page } = result;
1499
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1500
+ const labelFontSize = Math.min(10, rect.height * 0.4);
1501
+ const labelX = rect.x;
1502
+ const labelY = rect.y + rect.height + 5;
1503
+ page.drawText(fieldInfo.label, {
1504
+ x: labelX,
1505
+ y: labelY,
1506
+ size: labelFontSize,
1507
+ font: labelFont,
1508
+ color: rgb(0, 0, 0)
1509
+ });
1510
+ }
1511
+ if (selectedValue && selectedValue.trim()) {
1178
1512
  page.drawText(selectedValue, {
1179
1513
  x: rect.x + 2,
1180
1514
  y: rect.y + 2,
1181
- size: 10,
1515
+ size: 14,
1182
1516
  font: await pdfDoc.embedFont(StandardFonts.Helvetica),
1183
1517
  color: rgb(0, 0, 0)
1184
1518
  });
@@ -1186,15 +1520,31 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1186
1520
  }
1187
1521
  } else {
1188
1522
  const fieldValue = userEnteredValue ? String(userEnteredValue) : "";
1189
- if (fieldValue && fieldValue.trim()) {
1190
- for (const widget of widgets) {
1191
- const result = getWidgetRectangleAndPage(widget, pages);
1192
- if (!result) continue;
1193
- const { rect, page } = result;
1523
+ const fieldInfo = extractedFormFields?.find((f2) => f2.name === fieldName);
1524
+ const labelFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
1525
+ const isDateField = fieldName.toLowerCase().includes("date") || fieldName.toLowerCase().includes("_date");
1526
+ const fontSize = isDateField ? 14 : extractFieldFontSize(fieldName, field, extractedFormFields);
1527
+ for (const widget of widgets) {
1528
+ const result = getWidgetRectangleAndPage(widget, pages);
1529
+ if (!result) continue;
1530
+ const { rect, page } = result;
1531
+ if (fieldInfo && hasDrawableLabel(fieldInfo)) {
1532
+ const labelFontSize = Math.min(10, rect.height * 0.4);
1533
+ const labelX = rect.x;
1534
+ const labelY = rect.y + rect.height + 5;
1535
+ page.drawText(fieldInfo.label, {
1536
+ x: labelX,
1537
+ y: labelY,
1538
+ size: labelFontSize,
1539
+ font: labelFont,
1540
+ color: rgb(0, 0, 0)
1541
+ });
1542
+ }
1543
+ if (fieldValue && fieldValue.trim()) {
1194
1544
  page.drawText(fieldValue, {
1195
1545
  x: rect.x + 2,
1196
1546
  y: rect.y + 2,
1197
- size: 10,
1547
+ size: fontSize,
1198
1548
  font: await pdfDoc.embedFont(StandardFonts.Helvetica),
1199
1549
  color: rgb(0, 0, 0)
1200
1550
  });
@@ -1317,24 +1667,45 @@ async function fillFormFieldsWithSignatures(pdfBytes, formFields, fieldValues, s
1317
1667
  switch (field.type) {
1318
1668
  case "text" /* TEXT */: {
1319
1669
  const value = fieldValues[field.id] || "";
1670
+ if (hasDrawableLabel(field)) {
1671
+ const labelFontSize = Math.min(10, field.position.height * 0.4);
1672
+ const labelX = pdfX;
1673
+ const labelY = pdfY + field.position.height + 5;
1674
+ page.drawText(field.label, {
1675
+ x: labelX,
1676
+ y: labelY,
1677
+ size: labelFontSize,
1678
+ font,
1679
+ color: rgb(0, 0, 0)
1680
+ });
1681
+ }
1320
1682
  if (value) {
1321
1683
  const fontSize = field.fontSize && field.fontSize >= 8 && field.fontSize <= 72 ? field.fontSize : Math.min(12, field.position.height * 0.6);
1322
1684
  page.drawText(value, {
1323
1685
  x: pdfX + 2,
1324
- // Small padding
1325
1686
  y: pdfY + (field.position.height - fontSize) / 2,
1326
- // Center vertically
1327
1687
  size: fontSize,
1328
1688
  font,
1329
1689
  color: rgb(0, 0, 0),
1330
1690
  maxWidth: field.position.width - 4
1331
- // Leave padding
1332
1691
  });
1333
1692
  }
1334
1693
  break;
1335
1694
  }
1336
1695
  case "date" /* DATE */: {
1337
1696
  const value = fieldValues[field.id] || "";
1697
+ if (hasDrawableLabel(field)) {
1698
+ const labelFontSize = Math.min(10, field.position.height * 0.4);
1699
+ const labelX = pdfX;
1700
+ const labelY = pdfY + field.position.height + 5;
1701
+ page.drawText(field.label, {
1702
+ x: labelX,
1703
+ y: labelY,
1704
+ size: labelFontSize,
1705
+ font,
1706
+ color: rgb(0, 0, 0)
1707
+ });
1708
+ }
1338
1709
  if (value) {
1339
1710
  const fontSize = field.fontSize && field.fontSize >= 8 && field.fontSize <= 72 ? field.fontSize : Math.min(12, field.position.height * 0.6);
1340
1711
  page.drawText(value, {
@@ -1350,10 +1721,22 @@ async function fillFormFieldsWithSignatures(pdfBytes, formFields, fieldValues, s
1350
1721
  }
1351
1722
  case "checkbox" /* CHECKBOX */: {
1352
1723
  const value = fieldValues[field.id] || "";
1724
+ const checkboxSize = Math.min(field.position.width, field.position.height) * 0.7;
1725
+ const checkboxX = pdfX + (field.position.width - checkboxSize) / 2;
1726
+ const checkboxY = pdfY + (field.position.height - checkboxSize) / 2;
1727
+ page.drawRectangle({
1728
+ x: checkboxX,
1729
+ y: checkboxY,
1730
+ width: checkboxSize,
1731
+ height: checkboxSize,
1732
+ borderColor: rgb(0, 0, 0),
1733
+ borderWidth: 1,
1734
+ color: rgb(1, 1, 1)
1735
+ });
1353
1736
  if (value === "true") {
1354
- const checkSize = Math.min(field.position.width, field.position.height) * 0.6;
1355
- const checkX = pdfX + (field.position.width - checkSize) / 2;
1356
- const checkY = pdfY + (field.position.height - checkSize) / 2;
1737
+ const checkSize = checkboxSize * 0.7;
1738
+ const checkX = checkboxX + (checkboxSize - checkSize) / 2;
1739
+ const checkY = checkboxY + (checkboxSize - checkSize) / 2;
1357
1740
  page.drawText("\u2713", {
1358
1741
  x: checkX,
1359
1742
  y: checkY,
@@ -1412,6 +1795,18 @@ async function fillFormFieldsWithSignatures(pdfBytes, formFields, fieldValues, s
1412
1795
  }
1413
1796
  case "dropdown" /* DROPDOWN */: {
1414
1797
  const value = fieldValues[field.id] || "";
1798
+ if (hasDrawableLabel(field)) {
1799
+ const labelFontSize = Math.min(10, field.position.height * 0.4);
1800
+ const labelX = pdfX;
1801
+ const labelY = pdfY + field.position.height + 5;
1802
+ page.drawText(field.label, {
1803
+ x: labelX,
1804
+ y: labelY,
1805
+ size: labelFontSize,
1806
+ font,
1807
+ color: rgb(0, 0, 0)
1808
+ });
1809
+ }
1415
1810
  if (value) {
1416
1811
  const fontSize = Math.min(12, field.position.height * 0.6);
1417
1812
  page.drawText(value, {
@@ -1479,6 +1874,203 @@ async function getFieldPageNumbers(pdfBytes) {
1479
1874
  }
1480
1875
  }
1481
1876
 
1877
+ // src/utils/pdf-signer-utils.ts
1878
+ function getFieldSignerEmail(field) {
1879
+ return field.assignedSignerEmail || null;
1880
+ }
1881
+ function isFieldAssignedToSigner(field, signerEmail, allSignerEmails = []) {
1882
+ const assignedTo = field.assignedSignerEmail;
1883
+ if (!assignedTo) return false;
1884
+ if (assignedTo === signerEmail) return true;
1885
+ if (assignedTo === "to-recipients" && allSignerEmails.includes(signerEmail)) {
1886
+ return true;
1887
+ }
1888
+ if (assignedTo === "additional-signers" && allSignerEmails.includes(signerEmail)) {
1889
+ return true;
1890
+ }
1891
+ return false;
1892
+ }
1893
+ async function preparePdfForSigner(inputPdfBytes, formFields, options) {
1894
+ const {
1895
+ activeSignerEmail,
1896
+ hideMode = "NoView",
1897
+ allSignerEmails = []
1898
+ } = options;
1899
+ logger.info(`\u{1F510} Preparing PDF for signer: ${activeSignerEmail}`);
1900
+ logger.info(`\u{1F510} Form fields to process: ${formFields.length}`);
1901
+ logger.info(`\u{1F510} Hide mode: ${hideMode}`);
1902
+ logger.info(`\u{1F510} All signer emails:`, allSignerEmails);
1903
+ logger.info(`\u{1F510} Form field assignments:`, formFields.map((f) => ({
1904
+ name: f.name,
1905
+ assignedTo: f.assignedSignerEmail
1906
+ })));
1907
+ const pdfLib = await loadPdfLib();
1908
+ const { PDFDocument, AnnotationFlags } = pdfLib;
1909
+ let pdfDoc;
1910
+ try {
1911
+ logger.info(`\u{1F510} Loading PDF document, bytes length: ${inputPdfBytes.byteLength || inputPdfBytes.length}`);
1912
+ const bytesArray = inputPdfBytes instanceof Uint8Array ? inputPdfBytes : new Uint8Array(inputPdfBytes);
1913
+ const header = new TextDecoder().decode(bytesArray.slice(0, 8));
1914
+ logger.info(`\u{1F510} PDF header: "${header}"`);
1915
+ if (!header.startsWith("%PDF-")) {
1916
+ throw new Error(`Invalid PDF header: "${header}". Expected "%PDF-"`);
1917
+ }
1918
+ pdfDoc = await PDFDocument.load(inputPdfBytes);
1919
+ logger.info(`\u2705 Successfully loaded PDF document`);
1920
+ } catch (loadError) {
1921
+ logger.error(`\u274C Failed to load PDF with pdf-lib:`, loadError);
1922
+ logger.info(`\u{1F50D} PDF bytes details:`, {
1923
+ type: inputPdfBytes.constructor.name,
1924
+ length: inputPdfBytes.byteLength || inputPdfBytes.length,
1925
+ isArrayBuffer: inputPdfBytes instanceof ArrayBuffer,
1926
+ isUint8Array: inputPdfBytes instanceof Uint8Array,
1927
+ first20Bytes: Array.from(new Uint8Array(inputPdfBytes instanceof ArrayBuffer ? inputPdfBytes : inputPdfBytes.buffer).slice(0, 20)).map((b) => b.toString(16).padStart(2, "0")).join(" ")
1928
+ });
1929
+ throw new Error(`PDF parsing failed for signer ${activeSignerEmail}: ${loadError instanceof Error ? loadError.message : "Unknown error"}`);
1930
+ }
1931
+ const form = pdfDoc.getForm();
1932
+ const pdfFields = form.getFields();
1933
+ logger.info(`\u{1F510} PDF contains ${pdfFields.length} form fields`);
1934
+ for (const pdfField of pdfFields) {
1935
+ const pdfFieldName = pdfField.getName();
1936
+ const matchingFormField = formFields.find(
1937
+ (f) => f.name === pdfFieldName || (f.type === "signature" /* SIGNATURE */ || f.type === "initials" /* INITIALS */) && `${f.name}_signature` === pdfFieldName
1938
+ );
1939
+ if (!matchingFormField) {
1940
+ logger.info(`\u{1F510} PDF field "${pdfFieldName}" not found in provided form fields - leaving unchanged`);
1941
+ continue;
1942
+ }
1943
+ logger.info(`\u{1F510} Matched PDF field "${pdfFieldName}" to FormField "${matchingFormField.name}". Assigned to: ${matchingFormField.assignedSignerEmail}`);
1944
+ const fieldSignerEmail = getFieldSignerEmail(matchingFormField);
1945
+ const isAssignedToActiveSigner = isFieldAssignedToSigner(
1946
+ matchingFormField,
1947
+ activeSignerEmail,
1948
+ allSignerEmails
1949
+ );
1950
+ const isAssignedToCompletedSigner = (options.completedSignerEmails || []).some(
1951
+ (completedEmail) => isFieldAssignedToSigner(matchingFormField, completedEmail, allSignerEmails)
1952
+ );
1953
+ const isUnassigned = !fieldSignerEmail;
1954
+ let isVisible = false;
1955
+ let reason = "";
1956
+ if (isAssignedToActiveSigner) {
1957
+ isVisible = true;
1958
+ reason = "Assigned to active signer";
1959
+ } else if (isUnassigned) {
1960
+ isVisible = true;
1961
+ reason = "Unassigned field (visible to all)";
1962
+ } else {
1963
+ isVisible = false;
1964
+ reason = `Assigned to different signer (${fieldSignerEmail})`;
1965
+ }
1966
+ const isLocked = (options.lockCompletedFields ?? true) && isAssignedToCompletedSigner;
1967
+ if (isLocked) {
1968
+ reason += " - Locked (completed)";
1969
+ }
1970
+ logger.info(`\u{1F510} Processing field "${pdfFieldName}": ${reason}`);
1971
+ if (isLocked) {
1972
+ try {
1973
+ const fieldWithExtensions = pdfField;
1974
+ if (typeof fieldWithExtensions.enableReadOnly === "function") {
1975
+ fieldWithExtensions.enableReadOnly();
1976
+ } else if (typeof fieldWithExtensions.setReadOnly === "function") {
1977
+ fieldWithExtensions.setReadOnly(true);
1978
+ }
1979
+ logger.info(`\u{1F512} Locked field "${pdfFieldName}"`);
1980
+ } catch (error) {
1981
+ logger.warn(`\u26A0\uFE0F Could not lock field "${pdfFieldName}":`, error);
1982
+ }
1983
+ }
1984
+ try {
1985
+ const fieldWithExtensions = pdfField;
1986
+ const widgets = fieldWithExtensions.acroField?.getWidgets?.() ?? [];
1987
+ for (const widget of widgets) {
1988
+ if (typeof widget.clearFlag === "function") {
1989
+ widget.clearFlag(AnnotationFlags.Hidden);
1990
+ widget.clearFlag(AnnotationFlags.NoView);
1991
+ }
1992
+ if (!isVisible) {
1993
+ const flag = hideMode === "Hidden" ? AnnotationFlags.Hidden : AnnotationFlags.NoView;
1994
+ if (typeof widget.setFlag === "function") {
1995
+ widget.setFlag(flag);
1996
+ }
1997
+ if (typeof widget.clearFlag === "function") {
1998
+ widget.clearFlag(AnnotationFlags.Print);
1999
+ }
2000
+ logger.info(`\u{1F648} Hidden field "${pdfFieldName}" using ${hideMode} flag`);
2001
+ } else {
2002
+ if (typeof widget.setFlag === "function") {
2003
+ widget.setFlag(AnnotationFlags.Print);
2004
+ }
2005
+ logger.info(`\u{1F441}\uFE0F Made field "${pdfFieldName}" visible`);
2006
+ }
2007
+ }
2008
+ } catch (error) {
2009
+ logger.warn(`\u26A0\uFE0F Could not set visibility for field "${pdfFieldName}":`, error);
2010
+ }
2011
+ }
2012
+ try {
2013
+ const currentSubject = pdfDoc.getSubject() || "";
2014
+ const signerInfo = `Prepared for: ${activeSignerEmail}`;
2015
+ const newSubject = currentSubject ? `${currentSubject} | ${signerInfo}` : signerInfo;
2016
+ pdfDoc.setSubject(newSubject);
2017
+ const currentKeywords = pdfDoc.getKeywords() || [];
2018
+ const updatedKeywords = [...currentKeywords, `ActiveSigner:${activeSignerEmail}`];
2019
+ pdfDoc.setKeywords(updatedKeywords);
2020
+ logger.info(`\u{1F4DD} Added signer metadata to PDF`);
2021
+ } catch (error) {
2022
+ logger.warn(`\u26A0\uFE0F Could not set PDF metadata:`, error);
2023
+ }
2024
+ const modifiedPdfBytes = await pdfDoc.save();
2025
+ logger.info(`\u2705 PDF prepared for ${activeSignerEmail}: ${modifiedPdfBytes.length} bytes`);
2026
+ return new Uint8Array(modifiedPdfBytes);
2027
+ }
2028
+ function areAllSignersComplete(signers, completedSignerEmails) {
2029
+ const requiredSigners = new Set(signers.map((s) => s.email));
2030
+ const completedSigners = new Set(completedSignerEmails);
2031
+ for (const signerEmail of requiredSigners) {
2032
+ if (!completedSigners.has(signerEmail)) {
2033
+ return false;
2034
+ }
2035
+ }
2036
+ return true;
2037
+ }
2038
+ function getNextSigner(signers, completedSignerEmails) {
2039
+ const completedSet = new Set(completedSignerEmails);
2040
+ const sortedSigners = [...signers].sort((a, b) => a.signOrder - b.signOrder);
2041
+ for (const signer of sortedSigners) {
2042
+ if (!completedSet.has(signer.email)) {
2043
+ return signer;
2044
+ }
2045
+ }
2046
+ return null;
2047
+ }
2048
+ function validateFieldAssignments(formFields, signers) {
2049
+ const errors = [];
2050
+ const signerEmailSet = new Set(signers.map((s) => s.email));
2051
+ const assignedEmails = new Set(
2052
+ formFields.map((field) => field.assignedSignerEmail).filter((email) => email)
2053
+ );
2054
+ for (const assignedEmail of assignedEmails) {
2055
+ if (assignedEmail === "to-recipients" || assignedEmail === "additional-signers") {
2056
+ continue;
2057
+ }
2058
+ if (!signerEmailSet.has(assignedEmail)) {
2059
+ errors.push(`Field assigned to unknown signer: ${assignedEmail}`);
2060
+ }
2061
+ }
2062
+ const requiredUnassignedFields = formFields.filter(
2063
+ (field) => field.required && !field.assignedSignerEmail
2064
+ );
2065
+ if (requiredUnassignedFields.length > 0) {
2066
+ errors.push(`${requiredUnassignedFields.length} required fields are not assigned to any signer`);
2067
+ }
2068
+ return {
2069
+ isValid: errors.length === 0,
2070
+ errors
2071
+ };
2072
+ }
2073
+
1482
2074
  // src/utils/field-extraction.ts
1483
2075
  var PDFName2;
1484
2076
  async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
@@ -1493,7 +2085,6 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1493
2085
  const fields = form.getFields();
1494
2086
  const visibleFields = [];
1495
2087
  let hasAnyInitialsFields = false;
1496
- let hasInitialsFieldsForCurrentSigner = false;
1497
2088
  for (const field of fields) {
1498
2089
  const fieldName = field.getName();
1499
2090
  const fieldWithExtensions = field;
@@ -1519,28 +2110,31 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1519
2110
  };
1520
2111
  })();
1521
2112
  let fieldType = "text" /* TEXT */;
1522
- const fieldTypeName = field.constructor.name;
2113
+ const f = field;
2114
+ const isCheckboxField = typeof f.check === "function" && typeof f.uncheck === "function";
2115
+ const isRadioField = typeof f.select === "function" && typeof f.getOptions === "function" && typeof f.check !== "function" && typeof f.setOptions !== "function";
2116
+ const isDropdownField = typeof f.select === "function" && (typeof f.setOptions === "function" || typeof f.addOptions === "function");
2117
+ const isTextField = typeof f.getText === "function" && typeof f.setText === "function";
2118
+ const isSignatureType = !isCheckboxField && !isRadioField && !isDropdownField && !isTextField;
1523
2119
  const cleanFieldName = fieldName.replace(/_signature$|_initials$|_date$/i, "");
1524
- const isActualSignatureField = fieldTypeName.includes("Signature") || cleanFieldName.toLowerCase().includes("signature") && !fieldTypeName.includes("CheckBox") && !fieldTypeName.includes("Radio");
1525
- const isActualInitialsField = cleanFieldName.toLowerCase().includes("initials") && !fieldTypeName.includes("CheckBox") && !fieldTypeName.includes("Radio");
2120
+ const isActualSignatureField = isSignatureType || cleanFieldName.toLowerCase().includes("signature") && !isCheckboxField && !isRadioField;
2121
+ const isActualInitialsField = cleanFieldName.toLowerCase().includes("initials") && !isCheckboxField && !isRadioField;
1526
2122
  if (isActualSignatureField) {
1527
2123
  fieldType = "signature" /* SIGNATURE */;
1528
2124
  } else if (isActualInitialsField) {
1529
2125
  fieldType = "initials" /* INITIALS */;
1530
2126
  hasAnyInitialsFields = true;
1531
- if (currentSignerEmail && fieldMetadata.signer === currentSignerEmail) {
1532
- hasInitialsFieldsForCurrentSigner = true;
1533
- }
1534
2127
  } else if (cleanFieldName.toLowerCase().includes("date")) {
1535
2128
  fieldType = "date" /* DATE */;
1536
- } else if (fieldTypeName.includes("CheckBox")) {
2129
+ } else if (isCheckboxField) {
1537
2130
  fieldType = "checkbox" /* CHECKBOX */;
1538
- } else if (fieldTypeName.toLowerCase().includes("dropdown")) {
2131
+ } else if (isDropdownField) {
1539
2132
  fieldType = "dropdown" /* DROPDOWN */;
1540
- } else if (fieldTypeName.includes("Radio")) {
2133
+ } else if (isRadioField) {
1541
2134
  fieldType = "radio" /* RADIO */;
1542
2135
  }
1543
2136
  let displayLabel = fieldMetadata.label || "";
2137
+ let isLabelAutoGenerated = false;
1544
2138
  if (!displayLabel || !displayLabel.trim()) {
1545
2139
  try {
1546
2140
  const tuLabel = extractTULabel(fieldWithExtensions);
@@ -1552,6 +2146,7 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1552
2146
  }
1553
2147
  if (!displayLabel || !displayLabel.trim()) {
1554
2148
  displayLabel = generateFallbackLabel(cleanFieldName, fieldType);
2149
+ isLabelAutoGenerated = true;
1555
2150
  }
1556
2151
  const esignField = {
1557
2152
  id: fieldName,
@@ -1563,6 +2158,8 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1563
2158
  type: fieldType,
1564
2159
  label: displayLabel,
1565
2160
  // Use friendly label for display
2161
+ isLabelAutoGenerated,
2162
+ // True when label was generated from field name (should not be drawn on PDF)
1566
2163
  position: { x: 0, y: 0, width: 100, height: 30, page: 1 },
1567
2164
  // Default position
1568
2165
  required: fieldWithExtensions.isRequired?.() ?? false,
@@ -1583,6 +2180,13 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1583
2180
  logger.warn("Error extracting options for field:", error);
1584
2181
  }
1585
2182
  }
2183
+ try {
2184
+ const currentValue = extractFieldValue(f, esignField.type);
2185
+ if (currentValue) {
2186
+ esignField.defaultValue = currentValue;
2187
+ }
2188
+ } catch {
2189
+ }
1586
2190
  visibleFields.push(esignField);
1587
2191
  }
1588
2192
  }
@@ -1599,11 +2203,8 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1599
2203
  placeholder: "Draw or upload your signature",
1600
2204
  assignedSignerEmail: currentSignerEmail
1601
2205
  });
1602
- const shouldCreateInitialsField = hasInitialsFieldsForCurrentSigner || hasAnyInitialsFields && !currentSignerEmail;
2206
+ const shouldCreateInitialsField = hasAnyInitialsFields;
1603
2207
  if (shouldCreateInitialsField) {
1604
- if (hasInitialsFieldsForCurrentSigner) {
1605
- } else {
1606
- }
1607
2208
  mainFields.push({
1608
2209
  id: "initials_field_main",
1609
2210
  fieldId: "initials_field_main",
@@ -1690,8 +2291,12 @@ function decodeFieldName(fieldName) {
1690
2291
  }
1691
2292
  function generateFallbackLabel(decodedFieldName, fieldType) {
1692
2293
  let displayLabel = decodedFieldName;
1693
- displayLabel = displayLabel.replace(/_signature$/i, "").replace(/_initials$/i, "").replace(/_date$/i, "");
1694
- if (/^(text|signature|initials|date)_\d+$/i.test(displayLabel)) {
2294
+ let prevLabel = "";
2295
+ while (displayLabel !== prevLabel) {
2296
+ prevLabel = displayLabel;
2297
+ displayLabel = displayLabel.replace(/_signature$/i, "").replace(/_initials$/i, "").replace(/_date$/i, "");
2298
+ }
2299
+ if (/^(text|signature|initials|date|checkbox|radio|dropdown)_\d+/i.test(displayLabel)) {
1695
2300
  if (fieldType === "signature" /* SIGNATURE */) return "Signature";
1696
2301
  if (fieldType === "initials" /* INITIALS */) return "Initials";
1697
2302
  if (fieldType === "date" /* DATE */) return "Date";
@@ -1699,9 +2304,9 @@ function generateFallbackLabel(decodedFieldName, fieldType) {
1699
2304
  if (fieldType === "checkbox" /* CHECKBOX */) return "Checkbox";
1700
2305
  if (fieldType === "dropdown" /* DROPDOWN */) return "Dropdown";
1701
2306
  if (fieldType === "radio" /* RADIO */) return "Option";
1702
- } else {
1703
- displayLabel = displayLabel.replace(/_/g, " ").replace(/\s+\d+$/g, "").trim().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
2307
+ if (fieldType === "text_label" /* TEXT_LABEL */) return "Text Label";
1704
2308
  }
2309
+ displayLabel = displayLabel.replace(/_/g, " ").replace(/\s+\d+$/g, "").trim().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
1705
2310
  return displayLabel;
1706
2311
  }
1707
2312
  function extractTULabel(field) {
@@ -1728,6 +2333,28 @@ function extractTULabel(field) {
1728
2333
  return "";
1729
2334
  }
1730
2335
  }
2336
+ function findFieldByUuid(fields, uuid) {
2337
+ return fields.find((f) => f.fieldId === uuid);
2338
+ }
2339
+ function resolveField(fields, identifier) {
2340
+ let field = findFieldByUuid(fields, identifier);
2341
+ if (field) {
2342
+ return field;
2343
+ }
2344
+ field = fields.find((f) => f.id === identifier);
2345
+ if (field) {
2346
+ return field;
2347
+ }
2348
+ field = fields.find((f) => f.name === identifier);
2349
+ if (field) {
2350
+ return field;
2351
+ }
2352
+ const cleanIdentifier = identifier.replace(/_signature$|_initials$|_date$/i, "");
2353
+ return fields.find((f) => f.fieldId === cleanIdentifier || f.id === cleanIdentifier || f.name === cleanIdentifier);
2354
+ }
2355
+ function getFieldUuidsForSigner(fields, signerEmail) {
2356
+ return fields.filter((f) => f.assignedSignerEmail === signerEmail && f.fieldId).map((f) => f.fieldId);
2357
+ }
1731
2358
  var CDN_WORKER = "https://cdn.jsdelivr.net/npm/pdfjs-dist@5.3.93/build/pdf.worker.mjs";
1732
2359
  var CDN_VIEWER = "https://mozilla.github.io/pdf.js";
1733
2360
  var _workerSrcComputed = false;
@@ -1801,7 +2428,7 @@ function initializePdfJs() {
1801
2428
  async function checkPdfJsVersion(viewerBasePath = "/pdfjs") {
1802
2429
  const workerVersion = pdfjsLib2.version;
1803
2430
  try {
1804
- const versionUrl = `${viewerBasePath}/.version`;
2431
+ const versionUrl = `${viewerBasePath}/version.txt`;
1805
2432
  const response = await fetch(versionUrl);
1806
2433
  if (!response.ok) {
1807
2434
  return {
@@ -2029,13 +2656,13 @@ function getErrorMessage(error, defaultMessage = "Unknown error") {
2029
2656
 
2030
2657
  // src/utils/attachment-validators.ts
2031
2658
  var DEFAULT_ATTACHMENT_CONSTRAINTS = {
2032
- maxFileSize: 10 * 1024 * 1024,
2033
- // 10MB
2659
+ maxFileSize: 25 * 1024 * 1024,
2660
+ // 25MB
2034
2661
  maxTotalSize: 50 * 1024 * 1024,
2035
2662
  // 50MB
2036
2663
  maxFiles: 10,
2037
2664
  allowedTypes: ["image/*", "application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"],
2038
- allowedExtensions: [".pdf", ".jpg", ".jpeg", ".png", ".gif", ".doc", ".docx"]
2665
+ allowedExtensions: [".pdf", ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".doc", ".docx"]
2039
2666
  };
2040
2667
  function validateFile(file, constraints = DEFAULT_ATTACHMENT_CONSTRAINTS) {
2041
2668
  const errors = [];
@@ -2327,6 +2954,23 @@ function withPerformanceMonitoring(label, fn, monitor = globalPerformanceMonitor
2327
2954
  }
2328
2955
  });
2329
2956
  }
2957
+ function isValidISODate(value) {
2958
+ if (!value || typeof value !== "string") {
2959
+ return false;
2960
+ }
2961
+ const isoPattern = /^\d{4}-\d{2}-\d{2}$/;
2962
+ if (!isoPattern.test(value)) {
2963
+ return false;
2964
+ }
2965
+ try {
2966
+ const date = parseISO(value);
2967
+ return isValid(date) && !isNaN(date.getTime());
2968
+ } catch {
2969
+ return false;
2970
+ }
2971
+ }
2972
+
2973
+ // src/utils/date-validation.ts
2330
2974
  function toIsoDateString(date) {
2331
2975
  const year = date.getFullYear();
2332
2976
  const month = String(date.getMonth() + 1).padStart(2, "0");
@@ -2450,21 +3094,6 @@ function parseAndValidateDate(value) {
2450
3094
  error: `Invalid date format: "${trimmedValue}". Please use a date picker or format like MM/DD/YYYY.`
2451
3095
  };
2452
3096
  }
2453
- function isValidISODate(value) {
2454
- if (!value || typeof value !== "string") {
2455
- return false;
2456
- }
2457
- const isoPattern = /^\d{4}-\d{2}-\d{2}$/;
2458
- if (!isoPattern.test(value)) {
2459
- return false;
2460
- }
2461
- try {
2462
- const date = parseISO(value);
2463
- return isValid(date) && !isNaN(date.getTime());
2464
- } catch {
2465
- return false;
2466
- }
2467
- }
2468
3097
 
2469
3098
  // src/utils/tracking.ts
2470
3099
  var DEFAULT_API_ENDPOINT = "https://api-dev.signiphi.ai";
@@ -2544,6 +3173,6 @@ async function trackDocumentSentSilent(config, data) {
2544
3173
  }
2545
3174
  }
2546
3175
 
2547
- export { AttachmentValidationError, CDN_VIEWER, CDN_WORKER, DEFAULT_ATTACHMENT_CONSTRAINTS, FormFieldError, PdfProcessingError, PdfValidationError, PerformanceMonitor, captureAuditTrail, captureDeviceMetadata, captureGeolocation, captureIpAddress, checkAndLogPdfJsVersion, checkPdfJsVersion, createPdfBlobUrl, createPerformanceMonitor, dataUrlToBytes, decodeFieldName, detectFieldType, downloadPdf, extractFieldValue, extractVisibleFormFields, fillFormFieldsWithSignatures, fillPdfWithSignatures, filterFieldsBySigner, findPageIndexByRef, findPageIndexWithFallback, formatFieldName, formatFileSize, generateFallbackLabel, getErrorMessage, getFieldPageNumbers, getPdfJsConfig, getSigniphiMetadata, getWidgetRectangleAndPage, globalPerformanceMonitor, initPdfMetadata, initializePdfJs, isAttachmentValidationError, isAutoGeneratedLabel, isFieldVisibleToSigner, isFormFieldError, isImageType, isInitialsField, isPdfProcessingError, isPdfValidationError, isRequiredField, isSignatureField, isValidISODate, isValidPdf, logVersionCheckWarning, logger, measurePerformance, parseAndValidateDate, pdfToImages, readCurrentPdfFormValues, readPdfFormFields, removeAllFormFields, resetPdfJsConfig, setPdfJsConfig, setSigniphiMetadata, shouldFlattenField, trackDocumentSent, trackDocumentSentSilent, trackDocumentSigned, trackDocumentSignedSilent, urlToPdfBytes, validateCurrentPdfState, validateFieldValues, validateFile, validateFileOrThrow, validateFiles, validateFilesOrThrow, validateFormField, validatePdfBytes, validatePdfFormFields, validatePdfUrl, validateSignatures, withPerformanceMonitoring };
3176
+ export { AttachmentValidationError, CDN_VIEWER, CDN_WORKER, DEFAULT_ATTACHMENT_CONSTRAINTS, DEFAULT_SIGNATURE_FONT, FormFieldError, PdfProcessingError, PdfValidationError, PerformanceMonitor, SIGNATURE_FONTS, areAllSignersComplete, captureAuditTrail, captureDeviceMetadata, captureGeolocation, captureIpAddress, checkAndLogPdfJsVersion, checkPdfJsVersion, createPdfBlobUrl, createPerformanceMonitor, dataUrlToBytes, decodeFieldName, detectFieldType, downloadPdf, extractFieldValue, extractVisibleFormFields, fillFormFieldsWithSignatures, fillPdfWithSignatures, filterFieldsBySigner, findFieldByUuid, findPageIndexByRef, findPageIndexWithFallback, formatFieldName, formatFileSize, generateFallbackLabel, generateSignatureFromText, generateSignatureFromTextAsync, getErrorMessage, getFieldDisplayName, getFieldPageNumbers, getFieldUuidsForSigner, getNextSigner, getPdfJsConfig, getSigniphiMetadata, getWidgetRectangleAndPage, globalPerformanceMonitor, hasDrawableLabel, initPdfMetadata, initializePdfJs, isAttachmentValidationError, isAutoGeneratedLabel, isFieldVisibleToSigner, isFontLoaded, isFormFieldError, isImageType, isInitialsField, isPdfProcessingError, isPdfValidationError, isRequiredField, isSignatureField, isValidISODate, isValidPdf, loadSignatureFonts, logVersionCheckWarning, logger, measurePerformance, parseAndValidateDate, pdfToImages, preparePdfForSigner, readCurrentPdfFormValues, readPdfFormFields, removeAllFormFields, resetPdfJsConfig, resolveField, setPdfJsConfig, setSigniphiMetadata, shouldFlattenField, trackDocumentSent, trackDocumentSentSilent, trackDocumentSigned, trackDocumentSignedSilent, urlToPdfBytes, validateCurrentPdfState, validateFieldAssignments, validateFieldValues, validateFile, validateFileOrThrow, validateFiles, validateFilesOrThrow, validateFormField, validatePdfBytes, validatePdfFormFields, validatePdfUrl, validateSignatures, waitForFont, withPerformanceMonitoring };
2548
3177
  //# sourceMappingURL=index.mjs.map
2549
3178
  //# sourceMappingURL=index.mjs.map