@signiphi/page-assembly 0.2.0-beta.16 → 0.2.0-beta.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -14,7 +14,7 @@ import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
14
14
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
15
15
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
16
16
  import * as pdfjsLib from 'pdfjs-dist';
17
- import { PDFDocument, PDFName, PDFTextField, PDFCheckBox, PDFDropdown, PDFRadioGroup, PDFHexString, StandardFonts, rgb, PDFString, PDFOperator, PDFOperatorNames, PDFDict, PDFArray, PDFInvalidObject, PDFObjectParser, PDFRawStream, PDFObjectStreamParser, PDFRef, PDFBool, PDFNumber } from 'pdf-lib';
17
+ import { PDFDocument, PDFTextField, PDFCheckBox, PDFDropdown, PDFRadioGroup, PDFHexString, PDFName, StandardFonts, rgb, PDFString, PDFOperator, PDFOperatorNames, PDFDict, PDFArray, PDFInvalidObject, PDFObjectParser, PDFRawStream, PDFObjectStreamParser, PDFRef, PDFBool, PDFNumber } from 'pdf-lib';
18
18
 
19
19
  // src/components/PageAssembler.tsx
20
20
  function cn(...inputs) {
@@ -220,8 +220,9 @@ var SelectContent = React7.forwardRef(({ className, children, position = "popper
220
220
  position,
221
221
  style: {
222
222
  zIndex: 99999,
223
- backgroundColor: "#ffffff",
224
- border: "1px solid #e2e8f0",
223
+ backgroundColor: "hsl(var(--xpa-popover))",
224
+ color: "hsl(var(--xpa-popover-foreground))",
225
+ border: "1px solid hsl(var(--xpa-border))",
225
226
  borderRadius: "0.5rem",
226
227
  boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)",
227
228
  marginTop: "4px"
@@ -315,16 +316,23 @@ var AlertDialogOverlay = React7.forwardRef(({ className, ...props }, ref) => /*
315
316
  }
316
317
  ));
317
318
  AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
318
- var AlertDialogContent = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs(AlertDialogPortal, { container: document.querySelector(".signiphi-page-assembly"), children: [
319
+ var CENTERED = {
320
+ position: "fixed",
321
+ left: "50%",
322
+ top: "50%",
323
+ transform: "translate(-50%, -50%)"
324
+ };
325
+ var AlertDialogContent = React7.forwardRef(({ className, style, ...props }, ref) => /* @__PURE__ */ jsxs(AlertDialogPortal, { container: document.querySelector(".signiphi-page-assembly"), children: [
319
326
  /* @__PURE__ */ jsx(AlertDialogOverlay, {}),
320
327
  /* @__PURE__ */ jsx(
321
328
  AlertDialogPrimitive.Content,
322
329
  {
323
330
  ref,
324
331
  className: cn(
325
- "fixed left-[50%] top-[50%] z-[9999] grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
332
+ "z-[9999] grid w-full max-w-lg gap-4 border bg-background p-6 shadow-lg sm:rounded-lg",
326
333
  className
327
334
  ),
335
+ style: { ...CENTERED, ...style },
328
336
  ...props
329
337
  }
330
338
  )
@@ -440,8 +448,9 @@ var DropdownMenuContent = React7.forwardRef(({ className, sideOffset = 4, ...pro
440
448
  ),
441
449
  style: {
442
450
  zIndex: 99999,
443
- backgroundColor: "#ffffff",
444
- border: "1px solid #e2e8f0",
451
+ backgroundColor: "hsl(var(--xpa-popover))",
452
+ color: "hsl(var(--xpa-popover-foreground))",
453
+ border: "1px solid hsl(var(--xpa-border))",
445
454
  borderRadius: "0.5rem",
446
455
  boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)",
447
456
  padding: "6px"
@@ -1372,6 +1381,46 @@ function downloadPdf(pdfBytes, filename) {
1372
1381
  a.click();
1373
1382
  URL.revokeObjectURL(url);
1374
1383
  }
1384
+ var KEY = "SigniphiMetadata";
1385
+ function readMetadata(doc, pdfLib) {
1386
+ let blockPresent = false;
1387
+ try {
1388
+ const infoRef = doc.context.trailerInfo.Info;
1389
+ if (!infoRef) return { metadata: null, blockPresent };
1390
+ const info = doc.context.lookup(infoRef);
1391
+ if (!info || typeof info.get !== "function") return { metadata: null, blockPresent };
1392
+ const value = info.get(pdfLib.PDFName.of(KEY));
1393
+ if (!value) return { metadata: null, blockPresent };
1394
+ blockPresent = true;
1395
+ const json = typeof value.decodeText === "function" ? value.decodeText() : stripDelimiters(value.toString());
1396
+ return { metadata: JSON.parse(json), blockPresent };
1397
+ } catch {
1398
+ return { metadata: null, blockPresent };
1399
+ }
1400
+ }
1401
+ function writeMetadata(doc, metadata, pdfLib) {
1402
+ const info = doc.context.lookup(doc.context.trailerInfo.Info);
1403
+ if (!info || typeof info.set !== "function") {
1404
+ throw new Error("Cannot write SigniphiMetadata: the PDF has no Info dictionary");
1405
+ }
1406
+ info.set(pdfLib.PDFName.of(KEY), pdfLib.PDFHexString.fromText(JSON.stringify(metadata)));
1407
+ }
1408
+ function stripDelimiters(raw) {
1409
+ const wrapped = raw.startsWith("(") && raw.endsWith(")") || raw.startsWith("<") && raw.endsWith(">");
1410
+ return wrapped ? raw.slice(1, -1) : raw;
1411
+ }
1412
+ function textLabelPlacements(source) {
1413
+ const fields = source.metadata?.fields;
1414
+ if (!fields || !source.pages?.length) return [];
1415
+ const out = [];
1416
+ for (const [name, entry] of Object.entries(fields)) {
1417
+ if (entry.type !== "text_label" || !entry.position) continue;
1418
+ for (const { source: page, combined } of source.pages) {
1419
+ if (page === entry.position.page) out.push({ name, page: combined });
1420
+ }
1421
+ }
1422
+ return out;
1423
+ }
1375
1424
  function toCombinedPage(entry, page) {
1376
1425
  if (!entry.position && !entry.radioPositions && !entry.radioOptions) return entry;
1377
1426
  const carried = { ...entry };
@@ -1382,78 +1431,55 @@ function toCombinedPage(entry, page) {
1382
1431
  }
1383
1432
  return carried;
1384
1433
  }
1385
- function mergeSourceMetadata(sources) {
1434
+ function assembleMetadata(sources) {
1386
1435
  const merged = { version: "1.0", fields: {}, fieldIdIndex: {} };
1387
1436
  let radioLabelsBaked;
1388
1437
  let textLabelsBaked;
1389
1438
  let checkboxLabelsBaked;
1439
+ let legacyRadioStripped;
1390
1440
  for (const source of sources) {
1391
1441
  const meta = source.metadata;
1392
- if (!meta || source.fields.length === 0) continue;
1442
+ if (!meta || source.fields.length === 0 && !source.pages?.length) continue;
1393
1443
  if (meta.radioLabelsBaked === false) radioLabelsBaked = false;
1394
1444
  else if (meta.radioLabelsBaked === true && radioLabelsBaked === void 0) radioLabelsBaked = true;
1395
1445
  if (meta.textLabelsBaked === false) textLabelsBaked = false;
1396
1446
  else if (meta.textLabelsBaked === true && textLabelsBaked === void 0) textLabelsBaked = true;
1397
1447
  if (meta.checkboxLabelsBaked === false) checkboxLabelsBaked = false;
1398
1448
  else if (meta.checkboxLabelsBaked === true && checkboxLabelsBaked === void 0) checkboxLabelsBaked = true;
1449
+ legacyRadioStripped = meta.legacyRadioStripped === true && legacyRadioStripped !== false;
1399
1450
  }
1400
1451
  for (const source of sources) {
1401
1452
  const meta = source.metadata;
1402
1453
  if (!meta) continue;
1403
1454
  const sourceTextLabelsBaked = meta.textLabelsBaked !== false;
1404
- for (const { name, page } of source.fields) {
1455
+ for (const { name, page } of [...source.fields, ...textLabelPlacements(source)]) {
1405
1456
  const key = `${name}_p${page}`;
1406
1457
  const entry = meta.fields?.[name];
1407
- if (entry) {
1408
- const carried = toCombinedPage(entry, page);
1409
- merged.fields[key] = textLabelsBaked === false && sourceTextLabelsBaked ? { ...carried, textLabelBaked: true } : carried;
1410
- }
1411
- const fieldId = meta.fieldIdIndex?.[name];
1412
- if (fieldId) merged.fieldIdIndex[key] = fieldId;
1458
+ if (!entry) continue;
1459
+ const carried = toCombinedPage(entry, page);
1460
+ merged.fields[key] = textLabelsBaked === false && sourceTextLabelsBaked ? { ...carried, textLabelBaked: true } : carried;
1461
+ if (entry.fieldId) merged.fieldIdIndex[entry.fieldId] = key;
1413
1462
  }
1414
1463
  }
1415
1464
  if (radioLabelsBaked !== void 0) merged.radioLabelsBaked = radioLabelsBaked;
1416
1465
  if (textLabelsBaked !== void 0) merged.textLabelsBaked = textLabelsBaked;
1417
1466
  if (checkboxLabelsBaked !== void 0) merged.checkboxLabelsBaked = checkboxLabelsBaked;
1467
+ if (legacyRadioStripped) merged.legacyRadioStripped = true;
1418
1468
  const hasEntries = Object.keys(merged.fields).length > 0;
1419
1469
  const hasMarkers = radioLabelsBaked !== void 0 || textLabelsBaked !== void 0 || checkboxLabelsBaked !== void 0;
1420
1470
  if (!hasEntries && !hasMarkers) return null;
1421
1471
  if (Object.keys(merged.fieldIdIndex).length === 0) delete merged.fieldIdIndex;
1422
1472
  return merged;
1423
1473
  }
1474
+ function mergeSourceMetadata(sources) {
1475
+ return assembleMetadata(sources);
1476
+ }
1424
1477
  function getSigniphiMetadata(pdfDoc) {
1425
- try {
1426
- const infoRef = pdfDoc.context.trailerInfo.Info;
1427
- if (!infoRef) {
1428
- return null;
1429
- }
1430
- const infoObj = pdfDoc.context.lookup(infoRef);
1431
- if (!infoObj || typeof infoObj.get !== "function") {
1432
- return null;
1433
- }
1434
- const infoDict = infoObj;
1435
- const metadataObj = infoDict.get(PDFName.of("SigniphiMetadata"));
1436
- if (!metadataObj) {
1437
- return null;
1438
- }
1439
- let jsonStr;
1440
- if (typeof metadataObj.decodeText === "function") {
1441
- jsonStr = metadataObj.decodeText();
1442
- } else {
1443
- const metadataStr = metadataObj.toString();
1444
- jsonStr = metadataStr;
1445
- if (metadataStr.startsWith("(") && metadataStr.endsWith(")")) {
1446
- jsonStr = metadataStr.slice(1, -1);
1447
- } else if (metadataStr.startsWith("<") && metadataStr.endsWith(">")) {
1448
- jsonStr = metadataStr.slice(1, -1);
1449
- }
1450
- }
1451
- const metadata = JSON.parse(jsonStr);
1452
- return metadata;
1453
- } catch (error) {
1454
- console.error("Failed to load Signiphi metadata:", error);
1455
- return null;
1478
+ const { metadata, blockPresent } = readMetadata(pdfDoc, { PDFName: PDFName });
1479
+ if (blockPresent && !metadata) {
1480
+ console.error("Failed to load Signiphi metadata: the block is present but will not parse");
1456
1481
  }
1482
+ return metadata;
1457
1483
  }
1458
1484
  function getBaseFieldName(encodedName) {
1459
1485
  let baseName = encodedName;
@@ -1512,6 +1538,10 @@ async function extractFieldsFromPdf(pdfBytes) {
1512
1538
  const metadata = getSigniphiMetadata(pdfDoc);
1513
1539
  const form = pdfDoc.getForm();
1514
1540
  const pdfFields = form.getFields();
1541
+ const pages = pdfDoc.getPages();
1542
+ const pageHeights = pages.map((p) => p.getHeight());
1543
+ const pageIndexByRef = new Map(pages.map((p, i) => [p.ref, i + 1]));
1544
+ const pageNumberOf = (ref) => ref && pageIndexByRef.get(ref) || 1;
1515
1545
  for (const field of pdfFields) {
1516
1546
  const fieldName = field.getName();
1517
1547
  const widgets = field.acroField.getWidgets();
@@ -1540,19 +1570,20 @@ async function extractFieldsFromPdf(pdfBytes) {
1540
1570
  } else {
1541
1571
  console.log(`[field-extraction] Unknown field type "${fieldName}" - defaulting required=false`);
1542
1572
  }
1573
+ const optionPositionsByPage = /* @__PURE__ */ new Map();
1574
+ if (widgetType === "radio") {
1575
+ for (const w of widgets) {
1576
+ const pageNumber = pageNumberOf(w.P());
1577
+ const r = w.getRectangle();
1578
+ const top = pageHeights[pageNumber - 1] - r.y - r.height;
1579
+ const bucket = optionPositionsByPage.get(pageNumber) ?? [];
1580
+ bucket.push({ x: r.x, y: top, width: r.width, height: r.height });
1581
+ optionPositionsByPage.set(pageNumber, bucket);
1582
+ }
1583
+ }
1543
1584
  for (const widget of widgets) {
1544
1585
  const rect = widget.getRectangle();
1545
- const pageRef = widget.P();
1546
- let pageNumber = 1;
1547
- if (pageRef) {
1548
- const pages = pdfDoc.getPages();
1549
- for (let i = 0; i < pages.length; i++) {
1550
- if (pages[i].ref === pageRef) {
1551
- pageNumber = i + 1;
1552
- break;
1553
- }
1554
- }
1555
- }
1586
+ const pageNumber = pageNumberOf(widget.P());
1556
1587
  const pageQualifiedKey = `${baseName}_p${pageNumber}`;
1557
1588
  let fieldMetadata = metadata?.fields?.[pageQualifiedKey];
1558
1589
  if (!fieldMetadata) {
@@ -1569,8 +1600,7 @@ async function extractFieldsFromPdf(pdfBytes) {
1569
1600
  if (fieldMetadata?.options?.length) {
1570
1601
  fieldOptions = fieldMetadata.options;
1571
1602
  }
1572
- const page = pdfDoc.getPage(pageNumber - 1);
1573
- const pageHeight = page.getHeight();
1603
+ const pageHeight = pageHeights[pageNumber - 1];
1574
1604
  const extractedField = {
1575
1605
  name: baseName,
1576
1606
  // Use clean base name without __SIGNER__ encoding (signer stored in signer property)
@@ -1587,6 +1617,9 @@ async function extractFieldsFromPdf(pdfBytes) {
1587
1617
  signer: signerFromName
1588
1618
  // Extract signer from encoded name
1589
1619
  };
1620
+ if (widgetType === "radio") {
1621
+ extractedField.optionPositions = optionPositionsByPage.get(pageNumber) ?? [];
1622
+ }
1590
1623
  if (fieldMetadata) {
1591
1624
  if (fieldMetadata.fieldId) {
1592
1625
  extractedField.fieldId = fieldMetadata.fieldId;
@@ -1632,20 +1665,14 @@ async function extractFieldsFromPdf(pdfBytes) {
1632
1665
  }
1633
1666
  function setSigniphiMetadata(pdfDoc, metadata) {
1634
1667
  try {
1635
- const infoRef = pdfDoc.context.trailerInfo.Info;
1636
- const infoObj = pdfDoc.context.lookup(infoRef);
1637
- if (!infoObj || typeof infoObj.set !== "function") {
1638
- throw new Error("Info object is not a PDFDict or does not have set method");
1639
- }
1640
- const infoDict = infoObj;
1641
- const metadataString = JSON.stringify(metadata);
1642
- infoDict.set(PDFName.of("SigniphiMetadata"), PDFHexString.fromText(metadataString));
1668
+ writeMetadata(pdfDoc, metadata, { PDFName: PDFName, PDFHexString: PDFHexString });
1643
1669
  } catch (error) {
1644
1670
  console.error("Failed to set Signiphi metadata:", error);
1645
1671
  throw error;
1646
1672
  }
1647
1673
  }
1648
1674
  var SIGNIPHI_CHECKBOX_LABEL_MARKER = "SiPL_Check";
1675
+ var RADIO_BORDER_WIDTH = 1;
1649
1676
  var FormFieldType = /* @__PURE__ */ ((FormFieldType2) => {
1650
1677
  FormFieldType2["TEXT"] = "text";
1651
1678
  FormFieldType2["SIGNATURE"] = "signature";
@@ -1942,7 +1969,24 @@ async function addFormFieldsToPdf(pdfBytes, formFields, options = {}) {
1942
1969
  case "radio" /* RADIO */: {
1943
1970
  const encodedName = encodeFieldNameWithSigner(uniqueFieldName, field.assignedSignerEmail);
1944
1971
  const radioGroup = form.createRadioGroup(encodedName);
1945
- if (field.options && field.options.length > 0) {
1972
+ if (field.options && field.options.length > 0 && field.optionPositions?.length === field.options.length) {
1973
+ const optionPositions = field.optionPositions;
1974
+ field.options.forEach((option, index) => {
1975
+ const at = optionPositions[index];
1976
+ radioGroup.addOptionToPage(option, page, {
1977
+ x: at.x + RADIO_BORDER_WIDTH / 2,
1978
+ y: pageHeight - at.y - at.height + RADIO_BORDER_WIDTH / 2,
1979
+ width: at.width - RADIO_BORDER_WIDTH,
1980
+ height: at.height - RADIO_BORDER_WIDTH,
1981
+ borderWidth: RADIO_BORDER_WIDTH,
1982
+ borderColor: rgb(0.5, 0.5, 0.5),
1983
+ backgroundColor: rgb(1, 1, 1)
1984
+ });
1985
+ });
1986
+ if (field.defaultValue && field.options.includes(field.defaultValue)) {
1987
+ radioGroup.select(field.defaultValue);
1988
+ }
1989
+ } else if (field.options && field.options.length > 0) {
1946
1990
  const optionHeight = Math.min(20, field.position.height / field.options.length);
1947
1991
  const spacing = field.position.height / field.options.length;
1948
1992
  field.options.forEach((option, index) => {
@@ -2282,7 +2326,7 @@ var DraggablePageThumbnail = ({
2282
2326
  ref,
2283
2327
  "data-handler-id": handlerId,
2284
2328
  className: cn(
2285
- "relative group cursor-pointer border-2 rounded-lg overflow-hidden bg-white transition-all",
2329
+ "relative group cursor-pointer border-2 rounded-lg overflow-hidden bg-card transition-all",
2286
2330
  isDragging && "opacity-50 scale-95",
2287
2331
  isSelected ? "border-primary shadow-md" : "border-gray-200 hover:border-gray-300"
2288
2332
  ),
@@ -2310,7 +2354,7 @@ var DraggablePageThumbnail = ({
2310
2354
  }
2311
2355
  },
2312
2356
  onContextMenu: handleContextMenu,
2313
- className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary focus:ring-2 bg-white/90 cursor-pointer"
2357
+ className: "h-4 w-4 rounded border-border text-primary focus:ring-primary focus:ring-2 bg-card/90 cursor-pointer"
2314
2358
  }
2315
2359
  )
2316
2360
  }
@@ -2638,7 +2682,7 @@ var BulkActionBar = ({
2638
2682
  /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: "Move selected pages to another file" }) })
2639
2683
  ] }) }),
2640
2684
  /* @__PURE__ */ jsxs(Select, { onValueChange: onMovePages, children: [
2641
- /* @__PURE__ */ jsx(SelectTrigger, { id: "move-select", className: "w-48 bg-white", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Choose file..." }) }),
2685
+ /* @__PURE__ */ jsx(SelectTrigger, { id: "move-select", className: "w-48 bg-card", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Choose file..." }) }),
2642
2686
  /* @__PURE__ */ jsx(SelectContent, { children: files.map((file) => /* @__PURE__ */ jsx(SelectItem, { value: file.id, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
2643
2687
  file.type === "pdf" ? /* @__PURE__ */ jsx(FileText, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Image$1, { className: "h-4 w-4" }),
2644
2688
  /* @__PURE__ */ jsx("span", { className: "truncate", children: file.name })
@@ -2667,7 +2711,7 @@ var BulkActionBar = ({
2667
2711
  variant: "outline",
2668
2712
  size: "sm",
2669
2713
  onClick: onClearSelection,
2670
- className: "bg-white",
2714
+ className: "bg-card",
2671
2715
  children: "Clear Selection"
2672
2716
  }
2673
2717
  )
@@ -3087,12 +3131,19 @@ var PageAssembler = forwardRef(
3087
3131
  if (sourcePdf && !sourceMetadata) {
3088
3132
  console.warn(`[PageAssembler] No readable SigniphiMetadata in "${fileName}"`);
3089
3133
  }
3134
+ const pageUsageForFile = filePageUsage.get(fileId) || /* @__PURE__ */ new Map();
3090
3135
  const placements = [];
3091
- metadataSources.push({ metadata: sourceMetadata, fields: placements });
3136
+ const pageLandings = [];
3137
+ for (const [srcIndex, pageInstances] of pageUsageForFile) {
3138
+ for (const pageInstance of pageInstances) {
3139
+ const combined = pageIdToNewPageNumber.get(pageInstance.id);
3140
+ if (combined !== void 0) pageLandings.push({ source: srcIndex + 1, combined });
3141
+ }
3142
+ }
3143
+ metadataSources.push({ metadata: sourceMetadata, fields: placements, pages: pageLandings });
3092
3144
  console.log(`[PageAssembler] Extracting fields from "${fileName}"`);
3093
3145
  const extractedFields = await extractFieldsFromPdf(pdfBytes2);
3094
3146
  console.log(`[PageAssembler] Found ${extractedFields.length} fields in "${fileName}"`);
3095
- const pageUsageForFile = filePageUsage.get(fileId) || /* @__PURE__ */ new Map();
3096
3147
  for (const field of extractedFields) {
3097
3148
  const originalPage = field.page;
3098
3149
  const srcIndex = originalPage - 1;
@@ -3116,6 +3167,7 @@ var PageAssembler = forwardRef(
3116
3167
  label: field.label,
3117
3168
  required: field.required,
3118
3169
  options: field.options,
3170
+ optionPositions: field.optionPositions,
3119
3171
  placeholder: field.placeholder,
3120
3172
  fieldId: field.fieldId,
3121
3173
  assignedSignerEmail: field.signer
@@ -3220,6 +3272,7 @@ var PageAssembler = forwardRef(
3220
3272
  label: field.label,
3221
3273
  required: field.required,
3222
3274
  options: field.options,
3275
+ optionPositions: field.optionPositions,
3223
3276
  placeholder: field.placeholder,
3224
3277
  assignedSignerEmail: field.assignedSignerEmail
3225
3278
  }));