@hubsync/esign-web-sdk 6.9.12 → 6.9.14

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.
@@ -458,11 +458,9 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
458
458
  }
459
459
  focusNextFieldAfter(field) {
460
460
  setTimeout(() => {
461
- const fields = this.getSortedFillableFields();
462
- const currentIndex = fields.findIndex(f => f.name === field.name);
463
- if (currentIndex >= 0 && currentIndex < fields.length - 1) {
464
- this.focusFieldElement(fields[currentIndex + 1]);
465
- }
461
+ const next = this.getNextUnfilledField(field);
462
+ if (next)
463
+ this.focusFieldElement(next);
466
464
  }, 100);
467
465
  }
468
466
  focusFieldElement(field) {
@@ -477,11 +475,6 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
477
475
  handleStartSigning() {
478
476
  this.markEnvelopeStarted();
479
477
  this.signingProgressMode = 'signing';
480
- const fields = this.getSortedFillableFields();
481
- const startField = fields.find(field => !this.isFieldActuallyFilled(field)) || fields[0];
482
- if (startField) {
483
- this.focusFieldElement(startField);
484
- }
485
478
  this.adoptingSignature = true;
486
479
  }
487
480
  async handleFieldChange(field, e) {
@@ -514,6 +507,7 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
514
507
  }
515
508
  if (e.detail === null) {
516
509
  console.log('[SIGN] Clearing initial');
510
+ this.initialId = null;
517
511
  const updateResult = await updateEnvelopeField(this.endpoint, this.envelopeId, this.roleId, field.name, null, false);
518
512
  return this.updateRecipientFieldValue(field.name, updateResult);
519
513
  }
@@ -559,6 +553,7 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
559
553
  }
560
554
  if (e.detail === null) {
561
555
  console.log('[SIGN] Clearing signature');
556
+ this.signatureId = null;
562
557
  const updateResult = await updateEnvelopeField(this.endpoint, this.envelopeId, this.roleId, field.name, null, false);
563
558
  return this.updateRecipientFieldValue(field.name, updateResult);
564
559
  }
@@ -624,6 +619,20 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
624
619
  async handleNext() {
625
620
  var _a;
626
621
  if (this.nextSubmits) {
622
+ // Re-verify required fields synchronously before submitting. nextSubmits can be stale if
623
+ // a text field was cleared but not yet blurred before the button was clicked — the focusout
624
+ // save is async, so the local value hasn't updated by the time onClick fires.
625
+ const allFields = this.getSortedFillableFields();
626
+ const requiredIncomplete = allFields.some(f => f.required && !this.isFieldActuallyFilled(f));
627
+ if (requiredIncomplete) {
628
+ this.nextSubmits = false;
629
+ this.nextButtonLabel = 'Next';
630
+ const currentField = allFields.find(f => f.name === this.focusedField);
631
+ const next = this.getNextUnfilledField(currentField);
632
+ if (next)
633
+ this.focusFieldElement(next);
634
+ return;
635
+ }
627
636
  try {
628
637
  // Patches the date picker to be forcibly removed if still showing during submission
629
638
  (_a = document.getElementById('air-datepicker-global-container')) === null || _a === void 0 ? void 0 : _a.remove();
@@ -642,12 +651,10 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
642
651
  }
643
652
  return;
644
653
  }
645
- // Find all unfilled fields and move to the next one in sequence
646
- const allUnfilled = this.getSortedFillableFields().filter(f => !this.isFieldActuallyFilled(f));
647
- const nextUnfilled = this.getNextFieldFromList(allUnfilled);
648
- if (nextUnfilled) {
649
- this.focusFieldElement(nextUnfilled);
650
- }
654
+ const currentField = this.getSortedFillableFields().find(f => f.name === this.focusedField);
655
+ const next = this.getNextUnfilledField(currentField);
656
+ if (next)
657
+ this.focusFieldElement(next);
651
658
  }
652
659
  handleNextOptional() {
653
660
  const unfilledOptional = this.getSortedFillableFields().filter(f => !f.required && !this.isFieldActuallyFilled(f));
@@ -671,8 +678,10 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
671
678
  }
672
679
  // See if everything that "needs to be" filled in is, and all "fillable fields" are valid
673
680
  checkRecipientFields() {
674
- const invalidFields = this.getRecipientFields().filter(field => !isFieldValid(field, this.getRecipientFields()));
675
- if (invalidFields.length < 1) {
681
+ const allFields = this.getSortedFillableFields();
682
+ const requiredIncomplete = allFields.some(f => f.required && !this.isFieldActuallyFilled(f));
683
+ const invalidFilled = allFields.some(f => this.isFieldActuallyFilled(f) && !isFieldValid(f, this.getRecipientFields()));
684
+ if (!requiredIncomplete && !invalidFilled) {
676
685
  this.nextButtonLabel = 'Finish';
677
686
  if (!this.nextSubmits) {
678
687
  this.nextSubmits = true;
@@ -716,20 +725,15 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
716
725
  (field.type !== 'radio' || field.value === 'true') &&
717
726
  (field.type !== 'checkbox' || field.value === 'true'));
718
727
  }
719
- getNextRequiredField() {
720
- // Find and focus the next incomplete field (that is fillable)
721
- const emptyFields = this.getSortedFillableFields().filter(field => field.required && !this.isFieldActuallyFilled(field));
722
- sortFields(emptyFields);
723
- if (emptyFields.length === 0) {
724
- const allUnfilled = this.getSortedFillableFields().filter(field => !this.isFieldActuallyFilled(field));
725
- sortFields(allUnfilled);
726
- if (allUnfilled.length > 0) {
727
- // If we are here, there are no required fields left, but there are optional ones.
728
- return this.getNextFieldFromList(allUnfilled);
729
- }
730
- return null;
731
- }
732
- return this.getNextFieldFromList(emptyFields);
728
+ getNextUnfilledField(after) {
729
+ const allFields = this.getSortedFillableFields();
730
+ const startIndex = after ? allFields.findIndex(f => f.name === after.name) + 1 : 0;
731
+ // Look forward from current position first
732
+ const nextAfter = allFields.slice(startIndex).find(f => !this.isFieldActuallyFilled(f));
733
+ if (nextAfter)
734
+ return nextAfter;
735
+ // Wrap to beginning if nothing unfilled ahead
736
+ return allFields.slice(0, startIndex).find(f => !this.isFieldActuallyFilled(f)) || null;
733
737
  }
734
738
  getNextFieldFromList(fields) {
735
739
  const focusedIndex = fields.findIndex(field => field.name === this.focusedField);
@@ -762,14 +766,16 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
762
766
  // Remove existing flags
763
767
  const existingFlags = controlsDiv.querySelectorAll('.verdocs-flag-instance');
764
768
  existingFlags.forEach(el => el.remove());
765
- let nextField = this.getNextRequiredField();
766
769
  const focusedFieldObj = this.getRecipientFields().find(f => f.name === this.focusedField);
767
- // If the currently focused field is unfilled, we should point the flag to IT, not the next one.
768
- // getNextRequiredField() is designed for the "Next" button (skipping current), but the visual flag
769
- // should guide the user to the current task if it's incomplete.
770
+ // If the currently focused field is unfilled, point the flag to it.
771
+ // Otherwise find the next unfilled field forward from the current position.
772
+ let nextField;
770
773
  if (focusedFieldObj && !this.isFieldActuallyFilled(focusedFieldObj)) {
771
774
  nextField = focusedFieldObj;
772
775
  }
776
+ else {
777
+ nextField = this.getNextUnfilledField(focusedFieldObj);
778
+ }
773
779
  if (nextField && nextField.page === pageInfo.pageNumber && nextField.document_id === pageInfo.documentId) {
774
780
  const variant = 'fill';
775
781
  let label = 'FILL';
@@ -1106,7 +1112,7 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
1106
1112
  return (h("span", { class: "remaining-count" }, remaining, " required field", remaining === 1 ? '' : 's', " left"));
1107
1113
  }
1108
1114
  return (h("span", { class: "remaining-count" }, h("span", { class: "check-icon", innerHTML: CheckCircleIcon }), "All required fields complete", optionalLeft > 0 && h("span", { class: "separator" }, "|"), optionalLeft > 0 && (h("span", { class: "review-optional", onClick: () => this.handleNextOptional() }, "Review ", optionalLeft, " optional"))));
1109
- })(), !this.finishLater && (h("verdocs-button", { size: "xsmall", label: this.nextButtonLabel === 'Next' ? 'Next Required' : this.nextButtonLabel, disabled: !this.agreed || this.submitting, onClick: () => this.handleNext() })), h("div", { class: { 'icon-button': true, 'minus': true, 'disabled': this.zoomLevel === 'normal' }, innerHTML: ToolbarMinusIcon, onClick: () => this.handleZoomOut() }), h("div", { class: { 'icon-button': true, 'plus': true, 'disabled': this.zoomLevel === 'zoom2' }, innerHTML: ToolbarPlusIcon, onClick: () => this.handleZoomIn() }), h("verdocs-dropdown", { options: !this.isDone && !this.finishLater ? inProgressMenuOptions : doneMenuOptions, onOptionSelected: e => this.handleOptionSelected(e) })))), this.toolbarStyle === 'controls' && (h("div", { class: "controls-toolbar" }, h("div", { class: "left-controls" }, h("div", { class: "title" }, this.envelope.name)), h("div", { class: "center-controls", style: { display: 'none' } }, h("span", { class: "label" }, "Page"), h("div", { class: "select-wrapper" }, h("verdocs-select-input", { options: pageOptions, value: this.pageNumber.toString(), onInput: e => this.handlePageSelect(e) })), h("span", { class: "count" }, "of ", totalPages)), h("div", { class: "right-controls" }, h("verdocs-button", { class: "mobile-next-button", label: this.nextButtonLabel, size: "xsmall", disabled: !this.agreed || this.submitting, onClick: () => this.handleNext() }), h("div", { class: { 'icon-button': true, 'minus': true, 'disabled': this.zoomLevel === 'normal' }, innerHTML: ToolbarMinusIcon, onClick: () => this.handleZoomOut() }), h("div", { class: { 'icon-button': true, 'plus': true, 'disabled': this.zoomLevel === 'zoom2' }, innerHTML: ToolbarPlusIcon, onClick: () => this.handleZoomIn() }), h("div", { class: "icon-button download", innerHTML: ToolbarDownloadIcon, onClick: () => this.handleOptionSelected({ detail: { id: 'download' } }) }), h("div", { class: "icon-button print", innerHTML: ToolbarPrintIcon, onClick: () => this.handleOptionSelected({ detail: { id: 'print' } }) })))), h("verdocs-signing-progress", { mode: this.signingProgressMode, focusedField: this.focusedField, fields: this.getSortedFillableFields(), recipientFields: this.getRecipientFields(), onStarted: () => {
1115
+ })(), !this.finishLater && (h("verdocs-button", { size: "xsmall", label: this.nextButtonLabel, disabled: !this.agreed || this.submitting, onClick: () => this.handleNext() })), h("div", { class: { 'icon-button': true, 'minus': true, 'disabled': this.zoomLevel === 'normal' }, innerHTML: ToolbarMinusIcon, onClick: () => this.handleZoomOut() }), h("div", { class: { 'icon-button': true, 'plus': true, 'disabled': this.zoomLevel === 'zoom2' }, innerHTML: ToolbarPlusIcon, onClick: () => this.handleZoomIn() }), h("verdocs-dropdown", { options: !this.isDone && !this.finishLater ? inProgressMenuOptions : doneMenuOptions, onOptionSelected: e => this.handleOptionSelected(e) })))), this.toolbarStyle === 'controls' && (h("div", { class: "controls-toolbar" }, h("div", { class: "left-controls" }, h("div", { class: "title" }, this.envelope.name)), h("div", { class: "center-controls", style: { display: 'none' } }, h("span", { class: "label" }, "Page"), h("div", { class: "select-wrapper" }, h("verdocs-select-input", { options: pageOptions, value: this.pageNumber.toString(), onInput: e => this.handlePageSelect(e) })), h("span", { class: "count" }, "of ", totalPages)), h("div", { class: "right-controls" }, h("verdocs-button", { class: "mobile-next-button", label: this.nextButtonLabel, size: "xsmall", disabled: !this.agreed || this.submitting, onClick: () => this.handleNext() }), h("div", { class: { 'icon-button': true, 'minus': true, 'disabled': this.zoomLevel === 'normal' }, innerHTML: ToolbarMinusIcon, onClick: () => this.handleZoomOut() }), h("div", { class: { 'icon-button': true, 'plus': true, 'disabled': this.zoomLevel === 'zoom2' }, innerHTML: ToolbarPlusIcon, onClick: () => this.handleZoomIn() }), h("div", { class: "icon-button download", innerHTML: ToolbarDownloadIcon, onClick: () => this.handleOptionSelected({ detail: { id: 'download' } }) }), h("div", { class: "icon-button print", innerHTML: ToolbarPrintIcon, onClick: () => this.handleOptionSelected({ detail: { id: 'print' } }) })))), h("verdocs-signing-progress", { mode: this.signingProgressMode, focusedField: this.focusedField, fields: this.getSortedFillableFields(), recipientFields: this.getRecipientFields(), onStarted: () => {
1110
1116
  this.handleStartSigning();
1111
1117
  }, onNext: () => this.handleNext(), onPrevious: () => this.handlePrev(), onExit: () => this.handleNext() }), h("div", { class: `document signed-document-container zoom-${this.zoomLevel}` }, (this.envelope.documents || []).map(envelopeDocument => {
1112
1118
  const pageNumbers = integerSequence(1, envelopeDocument.pages);
@@ -1147,7 +1153,10 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
1147
1153
  this.showSpinner = false;
1148
1154
  this.adoptingSignature = false;
1149
1155
  this.markEnvelopeStarted();
1150
- // Apply the new signature/initials to the field that triggered the dialog.
1156
+ // Apply the new signature/initials to the field that triggered the dialog (e.g. user
1157
+ // clicked an existing sig/initial field). Track which field was applied so we can
1158
+ // advance forward from it rather than jumping back to the start of the document.
1159
+ let appliedToField = null;
1151
1160
  if (this.focusedField) {
1152
1161
  const fieldObj = this.getRecipientFields().find(f => f.name === this.focusedField);
1153
1162
  if (fieldObj) {
@@ -1155,10 +1164,16 @@ const VerdocsSign$1 = /*@__PURE__*/ proxyCustomElement(class VerdocsSign extends
1155
1164
  if (id) {
1156
1165
  const updateResult = await updateEnvelopeField(this.endpoint, this.envelopeId, this.roleId, fieldObj.name, id, false);
1157
1166
  this.updateRecipientFieldValue(fieldObj.name, updateResult);
1167
+ appliedToField = fieldObj;
1158
1168
  }
1159
1169
  }
1160
1170
  this.focusedField = '';
1161
1171
  }
1172
+ // Navigate to the next unfilled field: forward from where we applied (or from the
1173
+ // beginning when adopting at session start with no pre-focused field).
1174
+ const nextField = this.getNextUnfilledField(appliedToField !== null && appliedToField !== void 0 ? appliedToField : undefined);
1175
+ if (nextField)
1176
+ this.focusFieldElement(nextField);
1162
1177
  // Update any existing field elements in the DOM with the new IDs. This prevents them from
1163
1178
  // needing to show the adoption dialog again if they are clicked.
1164
1179
  const sigFields = this.el.querySelectorAll('verdocs-field-signature');