@signiphi/pdf-signer 0.2.0-beta.24 → 0.2.0-beta.26

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 (38) hide show
  1. package/dist/components/SubmissionForm.d.ts.map +1 -1
  2. package/dist/components/index.js +159 -27
  3. package/dist/components/index.js.map +1 -1
  4. package/dist/components/index.mjs +159 -27
  5. package/dist/components/index.mjs.map +1 -1
  6. package/dist/core/PdfViewerCore.d.ts.map +1 -1
  7. package/dist/core/index.js +6 -6
  8. package/dist/core/index.js.map +1 -1
  9. package/dist/core/index.mjs +6 -6
  10. package/dist/core/index.mjs.map +1 -1
  11. package/dist/hooks/index.js +140 -12
  12. package/dist/hooks/index.js.map +1 -1
  13. package/dist/hooks/index.mjs +140 -12
  14. package/dist/hooks/index.mjs.map +1 -1
  15. package/dist/index.js +166 -32
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +166 -32
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/styles/index.d.ts +1 -1
  20. package/dist/types/index.d.ts +1 -0
  21. package/dist/types/index.d.ts.map +1 -1
  22. package/dist/types/index.js.map +1 -1
  23. package/dist/types/index.mjs.map +1 -1
  24. package/dist/utils/date-validation.d.ts.map +1 -1
  25. package/dist/utils/field-extraction.d.ts.map +1 -1
  26. package/dist/utils/index.js +158 -25
  27. package/dist/utils/index.js.map +1 -1
  28. package/dist/utils/index.mjs +158 -25
  29. package/dist/utils/index.mjs.map +1 -1
  30. package/dist/utils/pdf-manipulation.d.ts.map +1 -1
  31. package/dist/utils/pdf-metadata.d.ts +1 -0
  32. package/dist/utils/pdf-metadata.d.ts.map +1 -1
  33. package/dist/utils/pdf-text-wrapping.d.ts +42 -0
  34. package/dist/utils/pdf-text-wrapping.d.ts.map +1 -0
  35. package/dist/utils/pdf-validators.d.ts +16 -14
  36. package/dist/utils/pdf-validators.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/src/styles/index.d.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"SubmissionForm.d.ts","sourceRoot":"","sources":["../../src/components/SubmissionForm.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAwC,MAAM,EAAE,MAAM,UAAU,CAAC;AA2B7G,MAAM,WAAW,mBAAmB;IAClC,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IAGf,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,uGAAuG;IACvG,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B,qDAAqD;IACrD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,0DAA0D;IAC1D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sCAAsC;IACtC,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,cAAc,EAAE,CAAC;IACpC,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qEAAqE;IACrE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,6FAA6F;IAC7F,qBAAqB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAClD,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAAE,yBAAyB;AAC7C,aAAa,EACb,mBAAmB,EACnB,aAAoB,EACpB,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,QAAgB,EAChB,SAAc,EACd,aAAoB,EACpB,gBAAgB,EAChB,kBAA0B,EAC1B,qBAA6B,EAC7B,qBAA6B,EAC7B,iBAAyB,EACzB,cAAmB,EACnB,MAAM,EACN,gBAAgB,EAChB,UAAU,GACX,EAAE,mBAAmB,2CA4wFrB"}
1
+ {"version":3,"file":"SubmissionForm.d.ts","sourceRoot":"","sources":["../../src/components/SubmissionForm.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAwC,MAAM,EAAE,MAAM,UAAU,CAAC;AA2B7G,MAAM,WAAW,mBAAmB;IAClC,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IAGf,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,uGAAuG;IACvG,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B,qDAAqD;IACrD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,0DAA0D;IAC1D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sCAAsC;IACtC,QAAQ,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,cAAc,EAAE,CAAC;IACpC,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qEAAqE;IACrE,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,6FAA6F;IAC7F,qBAAqB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAClD,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,aAAa,EACb,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAAE,yBAAyB;AAC7C,aAAa,EACb,mBAAmB,EACnB,aAAoB,EACpB,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,QAAgB,EAChB,SAAc,EACd,aAAoB,EACpB,gBAAgB,EAChB,kBAA0B,EAC1B,qBAA6B,EAC7B,qBAA6B,EAC7B,iBAAyB,EACzB,cAAmB,EACnB,MAAM,EACN,gBAAgB,EAChB,UAAU,GACX,EAAE,mBAAmB,2CA+wFrB"}
@@ -205,11 +205,6 @@ function isAutoGeneratedLabel(label) {
205
205
  "i"
206
206
  );
207
207
  if (typeTimestampPattern.test(trimmed)) return true;
208
- const typeNumberPattern = new RegExp(
209
- `^(${autoLabels.join("|")})[\\s_-]?\\d{1,3}$`,
210
- "i"
211
- );
212
- if (typeNumberPattern.test(trimmed)) return true;
213
208
  const typeWordsJoined = autoLabels.join("|");
214
209
  const corruptedPattern = new RegExp(
215
210
  `^(${typeWordsJoined})[\\s_-]?\\d{10,}[\\s_-]?(${typeWordsJoined})+`,
@@ -225,7 +220,8 @@ function isAutoGeneratedLabel(label) {
225
220
  }
226
221
  function hasDrawableLabel(field) {
227
222
  if (!field.label || !field.label.trim()) return false;
228
- if (field.isLabelAutoGenerated) return false;
223
+ if (field.isLabelAutoGenerated === true) return false;
224
+ if (field.isLabelAutoGenerated === false) return true;
229
225
  if (isAutoGeneratedLabel(field.label)) return false;
230
226
  return true;
231
227
  }
@@ -621,6 +617,118 @@ function isRequiredField(field, fieldName, fieldType) {
621
617
  return false;
622
618
  }
623
619
 
620
+ // src/utils/pdf-text-wrapping.ts
621
+ function wrapTextToLines(text, font, fontSize, maxWidth) {
622
+ if (!text) return [];
623
+ if (maxWidth <= 0) return [text];
624
+ const measure = (s) => {
625
+ try {
626
+ return font.widthOfTextAtSize(s, fontSize);
627
+ } catch {
628
+ return s.length * fontSize * 0.5;
629
+ }
630
+ };
631
+ const breakLongWord = (word) => {
632
+ const chunks = [];
633
+ let current = "";
634
+ for (const ch of word) {
635
+ const candidate = current + ch;
636
+ if (measure(candidate) > maxWidth && current.length > 0) {
637
+ chunks.push(current);
638
+ current = ch;
639
+ } else {
640
+ current = candidate;
641
+ }
642
+ }
643
+ if (current.length > 0) chunks.push(current);
644
+ return chunks;
645
+ };
646
+ const segments = text.split("\n");
647
+ const lines = [];
648
+ for (const segment of segments) {
649
+ if (segment.length === 0) {
650
+ lines.push("");
651
+ continue;
652
+ }
653
+ const words = segment.split(/(\s+)/).filter((token) => token.length > 0);
654
+ let current = "";
655
+ for (const token of words) {
656
+ const candidate = current + token;
657
+ if (measure(candidate) <= maxWidth) {
658
+ current = candidate;
659
+ continue;
660
+ }
661
+ if (current.trim().length > 0) {
662
+ lines.push(current.trimEnd());
663
+ current = "";
664
+ }
665
+ const trimmedToken = token.trimStart();
666
+ if (measure(trimmedToken) <= maxWidth) {
667
+ current = trimmedToken;
668
+ } else {
669
+ const broken = breakLongWord(trimmedToken);
670
+ for (let i = 0; i < broken.length - 1; i++) {
671
+ const piece = broken[i];
672
+ if (piece !== void 0) lines.push(piece);
673
+ }
674
+ current = broken[broken.length - 1] ?? "";
675
+ }
676
+ }
677
+ lines.push(current.trimEnd());
678
+ }
679
+ return lines;
680
+ }
681
+ var MIN_MULTILINE_FONT_SIZE = 8;
682
+ function findFittingFontSize(text, font, preferredSize, maxWidth, maxHeight) {
683
+ if (preferredSize <= MIN_MULTILINE_FONT_SIZE) return preferredSize;
684
+ for (let size = preferredSize; size >= MIN_MULTILINE_FONT_SIZE; size -= 1) {
685
+ const lines = wrapTextToLines(text, font, size, maxWidth);
686
+ if (lines.length * size * 1.2 <= maxHeight) return size;
687
+ }
688
+ return MIN_MULTILINE_FONT_SIZE;
689
+ }
690
+ function drawWrappedText(page, text, opts) {
691
+ if (!text) return;
692
+ const { x, y, width, height, fontSize, font, color, multiline } = opts;
693
+ const padding = opts.padding ?? 2;
694
+ const innerWidth = Math.max(0, width - padding * 2);
695
+ if (!multiline) {
696
+ let display = text.replace(/\n/g, " ");
697
+ if (font.widthOfTextAtSize(display, fontSize) > innerWidth) {
698
+ let truncated = "";
699
+ for (const ch of display) {
700
+ if (font.widthOfTextAtSize(truncated + ch, fontSize) > innerWidth) break;
701
+ truncated += ch;
702
+ }
703
+ display = truncated;
704
+ }
705
+ page.drawText(display, {
706
+ x: x + padding,
707
+ y: y + (height - fontSize) / 2,
708
+ size: fontSize,
709
+ font,
710
+ color
711
+ });
712
+ return;
713
+ }
714
+ const innerHeight = Math.max(0, height - padding * 2);
715
+ const fittedSize = findFittingFontSize(text, font, fontSize, innerWidth, innerHeight);
716
+ const lineHeight = fittedSize * 1.2;
717
+ const allLines = wrapTextToLines(text, font, fittedSize, innerWidth);
718
+ for (let i = 0; i < allLines.length; i++) {
719
+ const line = allLines[i];
720
+ if (!line) continue;
721
+ const lineY = y + height - padding - fittedSize - i * lineHeight;
722
+ page.drawText(line, {
723
+ x: x + padding,
724
+ y: lineY,
725
+ size: fittedSize,
726
+ font,
727
+ color
728
+ });
729
+ }
730
+ }
731
+
624
732
  // src/utils/pdf-manipulation.ts
625
733
  async function readPdfFormFields(pdfBytes) {
626
734
  try {
@@ -1265,6 +1373,21 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1265
1373
  const labelFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
1266
1374
  const isDateField = fieldName.toLowerCase().includes("date") || fieldName.toLowerCase().includes("_date");
1267
1375
  const fontSize = isDateField ? 14 : extractFieldFontSize(fieldName, field, extractedFormFields);
1376
+ let isMultiline = false;
1377
+ if (!isDateField) {
1378
+ try {
1379
+ const textFieldField = field;
1380
+ if (typeof textFieldField.isMultiline === "function") {
1381
+ isMultiline = textFieldField.isMultiline() === true;
1382
+ }
1383
+ } catch {
1384
+ isMultiline = false;
1385
+ }
1386
+ if (!isMultiline) {
1387
+ isMultiline = fieldInfo?.multiline === true;
1388
+ }
1389
+ }
1390
+ const valueFont = await pdfDoc.embedFont(StandardFonts.Helvetica);
1268
1391
  for (const widget of widgets) {
1269
1392
  const result = getWidgetRectangleAndPage(widget, pages);
1270
1393
  if (!result) continue;
@@ -1282,12 +1405,15 @@ async function fillPdfWithSignatures(pdfBytes, signatures, formFieldValues = {},
1282
1405
  });
1283
1406
  }
1284
1407
  if (fieldValue && fieldValue.trim()) {
1285
- page.drawText(fieldValue, {
1286
- x: rect.x + 2,
1287
- y: rect.y + 2,
1288
- size: fontSize,
1289
- font: await pdfDoc.embedFont(StandardFonts.Helvetica),
1290
- color: rgb(0, 0, 0)
1408
+ drawWrappedText(page, fieldValue, {
1409
+ x: rect.x,
1410
+ y: rect.y,
1411
+ width: rect.width,
1412
+ height: rect.height,
1413
+ fontSize,
1414
+ font: valueFont,
1415
+ color: rgb(0, 0, 0),
1416
+ multiline: isMultiline
1291
1417
  });
1292
1418
  }
1293
1419
  }
@@ -1513,6 +1639,8 @@ async function extractVisibleFormFields(pdfBytes, currentSignerEmail) {
1513
1639
  // Use fieldId from metadata, fallback to fieldName for backward compatibility
1514
1640
  name: fieldName,
1515
1641
  // Keep original for removal later
1642
+ mappableName: fieldMetadata.mappableName,
1643
+ // User-editable CSV-mapping identifier (undefined for legacy templates)
1516
1644
  type: fieldType,
1517
1645
  label: displayLabel,
1518
1646
  // Use friendly label for display
@@ -2045,14 +2173,17 @@ function parseAndValidateDate(value) {
2045
2173
  } catch {
2046
2174
  }
2047
2175
  }
2048
- const nativeParsed = new Date(sanitizedValue);
2049
- if (dateFns.isValid(nativeParsed) && !isNaN(nativeParsed.getTime())) {
2050
- return {
2051
- isValid: true,
2052
- date: nativeParsed,
2053
- isoString: toIsoDateString(nativeParsed),
2054
- originalValue
2055
- };
2176
+ const looksLikeNumericDate = /^\d{1,4}[\/.\-]\d{1,2}[\/.\-]\d{1,4}$/.test(sanitizedValue);
2177
+ if (!looksLikeNumericDate) {
2178
+ const nativeParsed = new Date(sanitizedValue);
2179
+ if (dateFns.isValid(nativeParsed) && !isNaN(nativeParsed.getTime())) {
2180
+ return {
2181
+ isValid: true,
2182
+ date: nativeParsed,
2183
+ isoString: toIsoDateString(nativeParsed),
2184
+ originalValue
2185
+ };
2186
+ }
2056
2187
  }
2057
2188
  return {
2058
2189
  isValid: false,
@@ -2312,11 +2443,10 @@ ${cssRules.join("\n")}`;
2312
2443
  for (const [id, data] of Object.entries(storedData)) {
2313
2444
  const fieldName = idToNameMap[id];
2314
2445
  if (!fieldName) continue;
2315
- const fieldType = fieldInfo[fieldName]?.type;
2316
- const isRadioButton = fieldType && (fieldType.toLowerCase().includes("radio") || fieldType.toLowerCase().includes("radiobutton") || fieldType === "radiobutton");
2446
+ const metaType = fieldMetadataRef.current.find((f) => f.name === fieldName)?.type;
2317
2447
  const widgetCount = fieldInfo[fieldName]?.widgets?.length || 0;
2318
- const isLikelyRadioGroup = widgetCount > 1 && fieldName.toLowerCase().includes("radio");
2319
- if (fieldName && (isRadioButton || isLikelyRadioGroup)) {
2448
+ const isRadioButton = metaType !== void 0 ? metaType === "radio" /* RADIO */ : widgetCount > 1;
2449
+ if (fieldName && isRadioButton) {
2320
2450
  if (!radioGroups[fieldName]) {
2321
2451
  radioGroups[fieldName] = [];
2322
2452
  }
@@ -2380,8 +2510,9 @@ ${cssRules.join("\n")}`;
2380
2510
  const field = fieldArray[0];
2381
2511
  if (field && field.value !== void 0 && field.value !== null) {
2382
2512
  const fieldValue = String(field.value);
2383
- const fieldType = fieldInfo[name]?.type;
2384
- const isRadioButton = fieldType && (fieldType.toLowerCase().includes("radio") || fieldType === "radiobutton");
2513
+ const metaType = fieldMetadataRef.current.find((f) => f.name === name)?.type;
2514
+ const widgetCount = fieldInfo[name]?.widgets?.length || 0;
2515
+ const isRadioButton = metaType !== void 0 ? metaType === "radio" /* RADIO */ : widgetCount > 1;
2385
2516
  if (isRadioButton && fieldValue !== "true" && fieldValue !== "false") {
2386
2517
  const widgets = fieldInfo[name]?.widgets || [];
2387
2518
  if (widgets.length > 0) {
@@ -9906,8 +10037,9 @@ function SubmissionForm({
9906
10037
  }
9907
10038
  }
9908
10039
  console.log("[SUBMIT] finalFieldValues after merge has", Object.keys(finalFieldValues).length, "entries");
10040
+ const radioFieldIds = new Set(filteredFields.filter((f) => f.type === "radio").map((f) => f.id));
9909
10041
  for (const [key, pdfValue] of Object.entries(pdfFieldValues)) {
9910
- if (key.includes("radio")) {
10042
+ if (radioFieldIds.has(key)) {
9911
10043
  const reactValue = currentFieldValues[key];
9912
10044
  if (pdfValue && pdfValue.includes("__RADIO_OPTION_INDEX_")) {
9913
10045
  finalFieldValues[key] = pdfValue;