smartcomply-web-sdk 1.0.48 → 1.0.50
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/client/HttpClient.d.ts +6 -1
- package/dist/client/HttpClient.d.ts.map +1 -1
- package/dist/client/HttpClient.js +11 -2
- package/dist/client/HttpClient.js.map +1 -1
- package/dist/esm/client/HttpClient.d.ts +6 -1
- package/dist/esm/client/HttpClient.d.ts.map +1 -1
- package/dist/esm/client/HttpClient.js +11 -2
- package/dist/esm/client/HttpClient.js.map +1 -1
- package/dist/esm/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/esm/flow/SmartComplyFlow.js +6 -8
- package/dist/esm/flow/SmartComplyFlow.js.map +1 -1
- package/dist/esm/modules/liveness/LivenessUI.d.ts +2 -0
- package/dist/esm/modules/liveness/LivenessUI.d.ts.map +1 -1
- package/dist/esm/modules/liveness/LivenessUI.js +26 -6
- package/dist/esm/modules/liveness/LivenessUI.js.map +1 -1
- package/dist/esm/modules/liveness/liveness.d.ts +12 -1
- package/dist/esm/modules/liveness/liveness.d.ts.map +1 -1
- package/dist/esm/modules/liveness/liveness.js +16 -10
- package/dist/esm/modules/liveness/liveness.js.map +1 -1
- package/dist/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/flow/SmartComplyFlow.js +6 -8
- package/dist/flow/SmartComplyFlow.js.map +1 -1
- package/dist/modules/liveness/LivenessUI.d.ts +2 -0
- package/dist/modules/liveness/LivenessUI.d.ts.map +1 -1
- package/dist/modules/liveness/LivenessUI.js +26 -6
- package/dist/modules/liveness/LivenessUI.js.map +1 -1
- package/dist/modules/liveness/liveness.d.ts +12 -1
- package/dist/modules/liveness/liveness.d.ts.map +1 -1
- package/dist/modules/liveness/liveness.js +16 -10
- package/dist/modules/liveness/liveness.js.map +1 -1
- package/dist/smartcomply.browser.js +143 -116
- package/dist/smartcomply.browser.js.map +2 -2
- package/package.json +2 -2
|
@@ -126,12 +126,21 @@ var SmartComplySDK = (() => {
|
|
|
126
126
|
});
|
|
127
127
|
}
|
|
128
128
|
/**
|
|
129
|
-
*
|
|
129
|
+
* GET for endpoints that work without auth (status polling still works after
|
|
130
|
+
* session revoke) but return additional fields when a live session token is
|
|
131
|
+
* presented — e.g. sdk-result/ only includes OCR/PII fields for the session
|
|
132
|
+
* that owns the entry. Attaches the token opportunistically when we still
|
|
133
|
+
* have one; the backend falls back to the public (non-PII) response if it's
|
|
134
|
+
* missing, invalid, or already revoked.
|
|
130
135
|
*/
|
|
131
136
|
async publicGet(path) {
|
|
137
|
+
const headers = { "Content-Type": "application/json" };
|
|
138
|
+
if (this.sessionToken) {
|
|
139
|
+
headers["x-access-token"] = this.sessionToken;
|
|
140
|
+
}
|
|
132
141
|
return this._fetch(path, {
|
|
133
142
|
method: "GET",
|
|
134
|
-
headers
|
|
143
|
+
headers
|
|
135
144
|
});
|
|
136
145
|
}
|
|
137
146
|
/**
|
|
@@ -3626,7 +3635,7 @@ var SmartComplySDK = (() => {
|
|
|
3626
3635
|
Pn(s2, 1, (i2.left + i2.right) / 2), Pn(s2, 2, (i2.top + i2.bottom) / 2), Pn(s2, 4, i2.right - i2.left), Pn(s2, 3, i2.bottom - i2.top);
|
|
3627
3636
|
} else Pn(s2, 1, 0.5), Pn(s2, 2, 0.5), Pn(s2, 4, 1), Pn(s2, 3, 1);
|
|
3628
3637
|
if (n2?.rotationDegrees) {
|
|
3629
|
-
if (n2?.rotationDegrees % 90 != 0) throw Error("Expected rotation to be a multiple of 90
|
|
3638
|
+
if (n2?.rotationDegrees % 90 != 0) throw Error("Expected rotation to be a multiple of 90°.");
|
|
3630
3639
|
if (Pn(s2, 5, -Math.PI * n2.rotationDegrees / 180), n2?.rotationDegrees % 180 != 0) {
|
|
3631
3640
|
const [t3, r3] = sa(e2);
|
|
3632
3641
|
n2 = Fn(s2, 3) * r3 / t3, i2 = Fn(s2, 4) * t3 / r3, Pn(s2, 4, n2), Pn(s2, 3, i2);
|
|
@@ -4555,22 +4564,22 @@ var SmartComplySDK = (() => {
|
|
|
4555
4564
|
|
|
4556
4565
|
// src/modules/liveness/LivenessUI.ts
|
|
4557
4566
|
var ICONS = {
|
|
4558
|
-
BLINK: "
|
|
4559
|
-
TURN_LEFT: "
|
|
4560
|
-
TURN_RIGHT: "
|
|
4561
|
-
TURN_HEAD: "
|
|
4562
|
-
OPEN_MOUTH: "
|
|
4567
|
+
BLINK: "👁",
|
|
4568
|
+
TURN_LEFT: "↔",
|
|
4569
|
+
TURN_RIGHT: "↔",
|
|
4570
|
+
TURN_HEAD: "↔",
|
|
4571
|
+
OPEN_MOUTH: "😮"
|
|
4563
4572
|
};
|
|
4564
4573
|
var ACTION_CUES = {
|
|
4565
|
-
BLINK: `<div style="font-size:52px;line-height:1;animation:sc-blink 1.2s ease-in-out infinite;"
|
|
4574
|
+
BLINK: `<div style="font-size:52px;line-height:1;animation:sc-blink 1.2s ease-in-out infinite;">👁️</div>
|
|
4566
4575
|
<div style="font-size:12px;font-weight:600;color:#fff;margin-top:6px;letter-spacing:0.5px;">BLINK YOUR EYES</div>`,
|
|
4567
|
-
TURN_LEFT: `<div style="font-size:52px;line-height:1;animation:sc-turn-head 1.4s ease-in-out infinite;"
|
|
4576
|
+
TURN_LEFT: `<div style="font-size:52px;line-height:1;animation:sc-turn-head 1.4s ease-in-out infinite;">↔️</div>
|
|
4568
4577
|
<div style="font-size:12px;font-weight:600;color:#fff;margin-top:6px;letter-spacing:0.5px;">TURN HEAD SIDEWAYS</div>`,
|
|
4569
|
-
TURN_RIGHT: `<div style="font-size:52px;line-height:1;animation:sc-turn-head 1.4s ease-in-out infinite;"
|
|
4578
|
+
TURN_RIGHT: `<div style="font-size:52px;line-height:1;animation:sc-turn-head 1.4s ease-in-out infinite;">↔️</div>
|
|
4570
4579
|
<div style="font-size:12px;font-weight:600;color:#fff;margin-top:6px;letter-spacing:0.5px;">TURN HEAD SIDEWAYS</div>`,
|
|
4571
|
-
TURN_HEAD: `<div style="font-size:52px;line-height:1;animation:sc-turn-head 1.4s ease-in-out infinite;"
|
|
4580
|
+
TURN_HEAD: `<div style="font-size:52px;line-height:1;animation:sc-turn-head 1.4s ease-in-out infinite;">↔️</div>
|
|
4572
4581
|
<div style="font-size:12px;font-weight:600;color:#fff;margin-top:6px;letter-spacing:0.5px;">TURN HEAD SIDE TO SIDE</div>`,
|
|
4573
|
-
OPEN_MOUTH: `<div style="font-size:52px;line-height:1;animation:sc-mouth 1.2s ease-in-out infinite;"
|
|
4582
|
+
OPEN_MOUTH: `<div style="font-size:52px;line-height:1;animation:sc-mouth 1.2s ease-in-out infinite;">😮</div>
|
|
4574
4583
|
<div style="font-size:12px;font-weight:600;color:#fff;margin-top:6px;letter-spacing:0.5px;">OPEN YOUR MOUTH</div>`
|
|
4575
4584
|
};
|
|
4576
4585
|
function injectLivenessKeyframes() {
|
|
@@ -4616,6 +4625,13 @@ var SmartComplySDK = (() => {
|
|
|
4616
4625
|
this.totalActions = 0;
|
|
4617
4626
|
this.currentCueAction = null;
|
|
4618
4627
|
this.docCaptureRoot = null;
|
|
4628
|
+
// updateActions() is called on every requestAnimationFrame tick (~60fps,
|
|
4629
|
+
// up to the challenge's ~45s time limit) — cache each action's step
|
|
4630
|
+
// element (avoids a querySelector per action per frame) and its last
|
|
4631
|
+
// rendered detected/active combination (avoids rewriting the same style
|
|
4632
|
+
// properties every frame when nothing about that action changed).
|
|
4633
|
+
this.stepEls = null;
|
|
4634
|
+
this.lastActionRender = /* @__PURE__ */ new Map();
|
|
4619
4635
|
}
|
|
4620
4636
|
mount(container, challenge) {
|
|
4621
4637
|
injectLivenessKeyframes();
|
|
@@ -4732,6 +4748,8 @@ var SmartComplySDK = (() => {
|
|
|
4732
4748
|
progressWrap.appendChild(this.progressBarEl);
|
|
4733
4749
|
this.stepsEl = document.createElement("div");
|
|
4734
4750
|
this.stepsEl.style.cssText = "display:flex;flex-direction:column;gap:6px;flex:1;";
|
|
4751
|
+
this.stepEls = /* @__PURE__ */ new Map();
|
|
4752
|
+
this.lastActionRender = /* @__PURE__ */ new Map();
|
|
4735
4753
|
for (let i2 = 0; i2 < challenge.actions.length; i2++) {
|
|
4736
4754
|
const action = challenge.actions[i2];
|
|
4737
4755
|
const step = document.createElement("div");
|
|
@@ -4765,6 +4783,7 @@ var SmartComplySDK = (() => {
|
|
|
4765
4783
|
step.appendChild(label);
|
|
4766
4784
|
step.appendChild(icon);
|
|
4767
4785
|
this.stepsEl.appendChild(step);
|
|
4786
|
+
this.stepEls.set(action, { step, num });
|
|
4768
4787
|
}
|
|
4769
4788
|
stepsCol.appendChild(progressWrap);
|
|
4770
4789
|
stepsCol.appendChild(this.stepsEl);
|
|
@@ -4782,24 +4801,24 @@ var SmartComplySDK = (() => {
|
|
|
4782
4801
|
return this.videoEl;
|
|
4783
4802
|
}
|
|
4784
4803
|
updateActions(states) {
|
|
4785
|
-
if (!this.stepsEl || !this.progressBarEl) return;
|
|
4804
|
+
if (!this.stepsEl || !this.progressBarEl || !this.stepEls) return;
|
|
4786
4805
|
let completed = 0;
|
|
4787
|
-
const activeState = states.find((s2) => s2.active && !s2.detected) ?? null;
|
|
4788
4806
|
for (const state of states) {
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
);
|
|
4792
|
-
|
|
4793
|
-
const
|
|
4807
|
+
if (state.detected) completed++;
|
|
4808
|
+
const renderKey = state.detected ? "detected" : state.active ? "active" : "idle";
|
|
4809
|
+
if (this.lastActionRender.get(state.action) === renderKey) continue;
|
|
4810
|
+
this.lastActionRender.set(state.action, renderKey);
|
|
4811
|
+
const cached = this.stepEls.get(state.action);
|
|
4812
|
+
if (!cached) continue;
|
|
4813
|
+
const { step, num } = cached;
|
|
4794
4814
|
if (state.detected) {
|
|
4795
|
-
completed++;
|
|
4796
4815
|
step.style.opacity = "1";
|
|
4797
4816
|
step.style.background = "rgba(34,197,94,0.12)";
|
|
4798
4817
|
step.style.borderColor = "rgba(34,197,94,0.3)";
|
|
4799
4818
|
if (num) {
|
|
4800
4819
|
num.style.background = "#22c55e";
|
|
4801
4820
|
num.style.borderColor = "#22c55e";
|
|
4802
|
-
num.textContent = "
|
|
4821
|
+
num.textContent = "✓";
|
|
4803
4822
|
}
|
|
4804
4823
|
} else if (state.active) {
|
|
4805
4824
|
step.style.opacity = "1";
|
|
@@ -4811,6 +4830,7 @@ var SmartComplySDK = (() => {
|
|
|
4811
4830
|
}
|
|
4812
4831
|
}
|
|
4813
4832
|
}
|
|
4833
|
+
const activeState = states.find((s2) => s2.active && !s2.detected) ?? null;
|
|
4814
4834
|
const pct = this.totalActions > 0 ? completed / this.totalActions * 100 : 0;
|
|
4815
4835
|
this.progressBarEl.style.width = `${pct}%`;
|
|
4816
4836
|
if (this.confidenceRingEl) {
|
|
@@ -4866,10 +4886,10 @@ var SmartComplySDK = (() => {
|
|
|
4866
4886
|
<div style="width:72px;height:72px;border-radius:50%;margin:0 auto 16px;display:flex;align-items:center;justify-content:center;font-size:32px;
|
|
4867
4887
|
background:${ok ? "rgba(34,197,94,0.2)" : "rgba(239,68,68,0.2)"};
|
|
4868
4888
|
border:3px solid ${ok ? "#22c55e" : "#ef4444"};">
|
|
4869
|
-
${ok ? "
|
|
4889
|
+
${ok ? "✓" : "✕"}
|
|
4870
4890
|
</div>
|
|
4871
4891
|
<div style="font-size:17px;font-weight:700;margin-bottom:8px;">${ok ? "Verification submitted" : "Submission failed"}</div>
|
|
4872
|
-
<div style="font-size:12px;opacity:0.6;line-height:1.6;">${ok ? "Hold on while we wrap up
|
|
4892
|
+
<div style="font-size:12px;opacity:0.6;line-height:1.6;">${ok ? "Hold on while we wrap up…" : "Something went wrong. Please try again."}</div>
|
|
4873
4893
|
</div>`;
|
|
4874
4894
|
setTimeout(resolve, 1800);
|
|
4875
4895
|
});
|
|
@@ -4885,7 +4905,7 @@ var SmartComplySDK = (() => {
|
|
|
4885
4905
|
this.overlayEl.style.display = "flex";
|
|
4886
4906
|
this.overlayEl.innerHTML = `
|
|
4887
4907
|
<div style="text-align:center;color:#fff;animation:sc-pop-in 0.35s ease;padding:24px;">
|
|
4888
|
-
<div style="width:72px;height:72px;border-radius:50%;margin:0 auto 14px;display:flex;align-items:center;justify-content:center;font-size:32px;background:rgba(251,191,36,0.15);border:3px solid #fbbf24;"
|
|
4908
|
+
<div style="width:72px;height:72px;border-radius:50%;margin:0 auto 14px;display:flex;align-items:center;justify-content:center;font-size:32px;background:rgba(251,191,36,0.15);border:3px solid #fbbf24;">⏱</div>
|
|
4889
4909
|
<div style="font-size:17px;font-weight:700;margin-bottom:8px;">Time's Up</div>
|
|
4890
4910
|
<div style="font-size:12px;opacity:0.6;margin-bottom:18px;">You ran out of time. Please try again.</div>
|
|
4891
4911
|
<button id="sc-retry-btn" style="padding:11px 28px;border-radius:10px;background:#3b82f6;color:#fff;border:none;cursor:pointer;font-size:14px;font-weight:600;width:100%;max-width:180px;">Try Again</button>
|
|
@@ -4924,7 +4944,7 @@ var SmartComplySDK = (() => {
|
|
|
4924
4944
|
header.innerHTML = `<div style="color:#fff;font-size:16px;font-weight:700;margin-bottom:6px;">Scan Your ID Document</div><div style="color:rgba(255,255,255,0.6);font-size:12px;line-height:1.6;">Fit your document inside the frame.<br>Make sure all text and corners are visible.</div>`;
|
|
4925
4945
|
const bottomPanel = document.createElement("div");
|
|
4926
4946
|
bottomPanel.style.cssText = "position:absolute;bottom:0;left:0;right:0;background:linear-gradient(0deg,rgba(0,0,0,0.92) 0%,rgba(0,0,0,0.6) 70%,transparent 100%);padding:16px;";
|
|
4927
|
-
bottomPanel.innerHTML = `<div style="font-size:11px;color:rgba(255,255,255,0.4);text-align:center;margin-bottom:12px;"
|
|
4947
|
+
bottomPanel.innerHTML = `<div style="font-size:11px;color:rgba(255,255,255,0.4);text-align:center;margin-bottom:12px;">💡 Good lighting · No glare · All 4 corners visible</div><button id="sc-capture-doc-btn" style="width:100%;padding:12px;border-radius:12px;background:#3b82f6;color:#fff;border:none;cursor:pointer;font-size:15px;font-weight:700;margin-bottom:8px;">Capture Document</button><label style="width:100%;display:flex;align-items:center;justify-content:center;gap:6px;padding:9px;border-radius:12px;border:1.5px solid rgba(255,255,255,0.18);cursor:pointer;color:rgba(255,255,255,0.6);font-size:13px;font-weight:500;"><span>📁</span><span>Upload from gallery instead</span><input id="sc-upload-doc-input" type="file" accept="image/*" style="display:none;" /></label>`;
|
|
4928
4948
|
docRoot.appendChild(docVideo);
|
|
4929
4949
|
docRoot.appendChild(guideOverlay);
|
|
4930
4950
|
docRoot.appendChild(header);
|
|
@@ -4997,6 +5017,8 @@ var SmartComplySDK = (() => {
|
|
|
4997
5017
|
this.timerEl = null;
|
|
4998
5018
|
this.overlayEl = null;
|
|
4999
5019
|
this.actionCueEl = null;
|
|
5020
|
+
this.stepEls = null;
|
|
5021
|
+
this.lastActionRender.clear();
|
|
5000
5022
|
}
|
|
5001
5023
|
startTimer(seconds) {
|
|
5002
5024
|
let remaining = seconds;
|
|
@@ -5042,10 +5064,12 @@ var SmartComplySDK = (() => {
|
|
|
5042
5064
|
*/
|
|
5043
5065
|
async create(params) {
|
|
5044
5066
|
const formData = new FormData();
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5067
|
+
if (!params.identity_check) {
|
|
5068
|
+
const rawIdentifier = params.identifier || `ID-${Date.now()}`;
|
|
5069
|
+
const safeIdentifier = rawIdentifier.length > 20 ? rawIdentifier.slice(0, 20) : rawIdentifier;
|
|
5070
|
+
formData.append("identifier", safeIdentifier);
|
|
5071
|
+
formData.append("identifier_type", params.identifier_type);
|
|
5072
|
+
}
|
|
5049
5073
|
formData.append("country", params.country);
|
|
5050
5074
|
formData.append(
|
|
5051
5075
|
"challenge_actions",
|
|
@@ -5121,7 +5145,10 @@ var SmartComplySDK = (() => {
|
|
|
5121
5145
|
}
|
|
5122
5146
|
/**
|
|
5123
5147
|
* Poll the public SDK status endpoint for the final verification result.
|
|
5124
|
-
* Safe to call after the session has been revoked (no auth required)
|
|
5148
|
+
* Safe to call after the session has been revoked (no auth required) —
|
|
5149
|
+
* the ocr_* fields below are only populated by the backend when a live
|
|
5150
|
+
* session token is still attached (see HttpClient.publicGet), since they
|
|
5151
|
+
* carry PII (name, document number, face thumbnail).
|
|
5125
5152
|
*
|
|
5126
5153
|
* GET /v1/sdk/liveness/<entryId>/sdk-result/
|
|
5127
5154
|
*/
|
|
@@ -5330,7 +5357,7 @@ var SmartComplySDK = (() => {
|
|
|
5330
5357
|
ui2.updateInstruction(getLabel(current));
|
|
5331
5358
|
}
|
|
5332
5359
|
} else {
|
|
5333
|
-
ui2.updateInstruction("All actions completed!
|
|
5360
|
+
ui2.updateInstruction("All actions completed! ✓");
|
|
5334
5361
|
}
|
|
5335
5362
|
if (actionDetector.allCompleted()) {
|
|
5336
5363
|
clearTimeout(timeout);
|
|
@@ -5362,7 +5389,7 @@ var SmartComplySDK = (() => {
|
|
|
5362
5389
|
});
|
|
5363
5390
|
});
|
|
5364
5391
|
}
|
|
5365
|
-
ui2.updateInstruction("Almost done
|
|
5392
|
+
ui2.updateInstruction("Almost done — hold still...");
|
|
5366
5393
|
await new Promise((r2) => setTimeout(r2, 800));
|
|
5367
5394
|
const autoshotBlob = await this.captureFrame(videoEl);
|
|
5368
5395
|
if (!autoshotBlob || autoshotBlob.size === 0) {
|
|
@@ -5881,7 +5908,7 @@ var SmartComplySDK = (() => {
|
|
|
5881
5908
|
const docLabel = this.getDocumentLabel(documentType);
|
|
5882
5909
|
const requiresBack = this.shouldCaptureBackSide(documentType);
|
|
5883
5910
|
const isCapturingFront = this.currentSide === "front";
|
|
5884
|
-
const sideLabel = requiresBack ? isCapturingFront ? "
|
|
5911
|
+
const sideLabel = requiresBack ? isCapturingFront ? " — Front side" : " — Back side" : "";
|
|
5885
5912
|
const headerRow = document.createElement("div");
|
|
5886
5913
|
headerRow.style.cssText = `
|
|
5887
5914
|
display:flex;align-items:center;gap:14px;
|
|
@@ -5902,7 +5929,7 @@ var SmartComplySDK = (() => {
|
|
|
5902
5929
|
titleEl.textContent = `Capture your ${docLabel}`;
|
|
5903
5930
|
const subEl = document.createElement("div");
|
|
5904
5931
|
subEl.style.cssText = `color:${theme.textSecondary};font-size:12px;margin-top:2px;`;
|
|
5905
|
-
subEl.textContent = requiresBack ? isCapturingFront ? "Step 1 of 2
|
|
5932
|
+
subEl.textContent = requiresBack ? isCapturingFront ? "Step 1 of 2 — front side" : "Step 2 of 2 — back side" : "Choose how to provide your document";
|
|
5906
5933
|
titleBlock.appendChild(titleEl);
|
|
5907
5934
|
titleBlock.appendChild(subEl);
|
|
5908
5935
|
headerRow.appendChild(iconBox);
|
|
@@ -5923,7 +5950,7 @@ var SmartComplySDK = (() => {
|
|
|
5923
5950
|
transition:all 0.15s ease;min-height:80px;
|
|
5924
5951
|
box-shadow:0 4px 14px ${theme.primary}30;
|
|
5925
5952
|
`;
|
|
5926
|
-
cameraBtn.innerHTML = `<span style="font-size:26px;"
|
|
5953
|
+
cameraBtn.innerHTML = `<span style="font-size:26px;">📷</span><span>Take Photo</span><span style="font-size:10px;opacity:0.8;font-weight:500;">Use camera</span>`;
|
|
5927
5954
|
cameraBtn.addEventListener("mouseenter", () => {
|
|
5928
5955
|
cameraBtn.style.opacity = "0.9";
|
|
5929
5956
|
cameraBtn.style.transform = "translateY(-1px)";
|
|
@@ -5945,7 +5972,7 @@ var SmartComplySDK = (() => {
|
|
|
5945
5972
|
font-size:13px;font-weight:600;font-family:inherit;
|
|
5946
5973
|
transition:all 0.15s ease;min-height:80px;
|
|
5947
5974
|
`;
|
|
5948
|
-
uploadBtn.innerHTML = `<span style="font-size:26px;"
|
|
5975
|
+
uploadBtn.innerHTML = `<span style="font-size:26px;">🖼️</span><span>From Gallery</span><span style="font-size:10px;color:${theme.textMuted || theme.textSecondary};font-weight:500;">Upload file</span>`;
|
|
5949
5976
|
uploadBtn.addEventListener("mouseenter", () => {
|
|
5950
5977
|
uploadBtn.style.borderColor = theme.primary;
|
|
5951
5978
|
uploadBtn.style.transform = "translateY(-1px)";
|
|
@@ -5979,7 +6006,7 @@ var SmartComplySDK = (() => {
|
|
|
5979
6006
|
tipItems.forEach((t2) => {
|
|
5980
6007
|
const row = document.createElement("div");
|
|
5981
6008
|
row.style.cssText = `display:flex;align-items:center;gap:5px;font-size:11px;color:${theme.textSecondary};`;
|
|
5982
|
-
row.innerHTML = `<span style="color:${theme.primary};font-weight:700;flex-shrink:0;"
|
|
6009
|
+
row.innerHTML = `<span style="color:${theme.primary};font-weight:700;flex-shrink:0;">✓</span><span>${t2}</span>`;
|
|
5983
6010
|
tipsGrid.appendChild(row);
|
|
5984
6011
|
});
|
|
5985
6012
|
tips.appendChild(tipsGrid);
|
|
@@ -5993,7 +6020,7 @@ var SmartComplySDK = (() => {
|
|
|
5993
6020
|
display:flex;align-items:center;gap:8px;
|
|
5994
6021
|
font-size:12px;color:${theme.textSecondary};line-height:1.5;
|
|
5995
6022
|
`;
|
|
5996
|
-
notice.innerHTML = `<span style="font-size:16px;flex-shrink:0;"
|
|
6023
|
+
notice.innerHTML = `<span style="font-size:16px;flex-shrink:0;">ℹ️</span><span>You'll capture both the <strong style="color:${theme.text}">front</strong> and <strong style="color:${theme.text}">back</strong> of this document.</span>`;
|
|
5997
6024
|
this.root.appendChild(notice);
|
|
5998
6025
|
}
|
|
5999
6026
|
const fileInput = document.createElement("input");
|
|
@@ -6019,10 +6046,10 @@ var SmartComplySDK = (() => {
|
|
|
6019
6046
|
/** Returns an appropriate emoji icon for the document type. */
|
|
6020
6047
|
_docIcon(documentType) {
|
|
6021
6048
|
const t2 = documentType.toLowerCase();
|
|
6022
|
-
if (t2.includes("passport")) return "
|
|
6023
|
-
if (t2.includes("driver") || t2.includes("licen")) return "
|
|
6024
|
-
if (t2.includes("voter") || t2.includes("pvc")) return "
|
|
6025
|
-
return "
|
|
6049
|
+
if (t2.includes("passport")) return "📘";
|
|
6050
|
+
if (t2.includes("driver") || t2.includes("licen")) return "🚗";
|
|
6051
|
+
if (t2.includes("voter") || t2.includes("pvc")) return "🗳️";
|
|
6052
|
+
return "🪪";
|
|
6026
6053
|
}
|
|
6027
6054
|
renderCameraView(container, theme, documentType) {
|
|
6028
6055
|
const wrapper = document.createElement("div");
|
|
@@ -6232,12 +6259,12 @@ var SmartComplySDK = (() => {
|
|
|
6232
6259
|
`;
|
|
6233
6260
|
const issueLine = document.createElement("div");
|
|
6234
6261
|
issueLine.style.cssText = "font-weight:700;color:#b8860b;";
|
|
6235
|
-
issueLine.textContent =
|
|
6262
|
+
issueLine.textContent = `⚠️ ${quality.message}`;
|
|
6236
6263
|
warn.appendChild(issueLine);
|
|
6237
6264
|
if (quality.recommendations.length > 0) {
|
|
6238
6265
|
const rec = document.createElement("div");
|
|
6239
6266
|
rec.style.cssText = "margin-top:4px;color:" + theme.textSecondary + ";";
|
|
6240
|
-
rec.textContent = quality.recommendations.join("
|
|
6267
|
+
rec.textContent = quality.recommendations.join(" · ");
|
|
6241
6268
|
warn.appendChild(rec);
|
|
6242
6269
|
}
|
|
6243
6270
|
this.root.appendChild(warn);
|
|
@@ -6253,7 +6280,7 @@ var SmartComplySDK = (() => {
|
|
|
6253
6280
|
this.root.innerHTML = "";
|
|
6254
6281
|
this.renderChoiceScreen(container, theme, documentType);
|
|
6255
6282
|
});
|
|
6256
|
-
const useBtn = this.createButton(qualityIsPoor ? "Use Anyway
|
|
6283
|
+
const useBtn = this.createButton(qualityIsPoor ? "Use Anyway ⚠" : "Use Photo ✓", theme, !qualityIsPoor);
|
|
6257
6284
|
useBtn.style.flex = "1";
|
|
6258
6285
|
useBtn.addEventListener("click", () => {
|
|
6259
6286
|
if (img._blobUrl) {
|
|
@@ -6399,7 +6426,7 @@ var SmartComplySDK = (() => {
|
|
|
6399
6426
|
position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
|
|
6400
6427
|
font-size:28px;animation:pulse 2s ease-in-out infinite;
|
|
6401
6428
|
`;
|
|
6402
|
-
centerIcon.textContent = "
|
|
6429
|
+
centerIcon.textContent = "📄";
|
|
6403
6430
|
spinnerContainer.appendChild(centerIcon);
|
|
6404
6431
|
this.root.appendChild(spinnerContainer);
|
|
6405
6432
|
const loadingText = document.createElement("div");
|
|
@@ -6434,7 +6461,7 @@ var SmartComplySDK = (() => {
|
|
|
6434
6461
|
color:#ff4444;font-size:14px;margin-top:16px;animation:shake 0.5s ease-in-out;
|
|
6435
6462
|
`;
|
|
6436
6463
|
errorContainer.innerHTML = `
|
|
6437
|
-
<span style="font-size:18px;"
|
|
6464
|
+
<span style="font-size:18px;">⚠️</span>
|
|
6438
6465
|
<span>${message}</span>
|
|
6439
6466
|
`;
|
|
6440
6467
|
if (!document.head.querySelector("style[data-shake-animation]")) {
|
|
@@ -6619,13 +6646,13 @@ var SmartComplySDK = (() => {
|
|
|
6619
6646
|
|
|
6620
6647
|
// src/flow/SmartComplyFlow.ts
|
|
6621
6648
|
var COUNTRY_LABELS = {
|
|
6622
|
-
nigeria: "
|
|
6623
|
-
global: "
|
|
6624
|
-
ghana: "
|
|
6625
|
-
kenya: "
|
|
6626
|
-
south_africa: "
|
|
6627
|
-
united_states: "
|
|
6628
|
-
united_kingdom: "
|
|
6649
|
+
nigeria: "🇳🇬 Nigeria",
|
|
6650
|
+
global: "🌠Other Countries",
|
|
6651
|
+
ghana: "🇬🇠Ghana",
|
|
6652
|
+
kenya: "🇰🇪 Kenya",
|
|
6653
|
+
south_africa: "🇿🇦 South Africa",
|
|
6654
|
+
united_states: "🇺🇸 United States",
|
|
6655
|
+
united_kingdom: "🇬🇧 United Kingdom"
|
|
6629
6656
|
};
|
|
6630
6657
|
function isUploadFieldType(type) {
|
|
6631
6658
|
return type === "upload" || type === "image" || type === "file";
|
|
@@ -6639,37 +6666,37 @@ var SmartComplySDK = (() => {
|
|
|
6639
6666
|
return t2.includes("voter") || t2.includes("driver") || t2.includes("license") || t2.includes("national id") || t2.includes("national id card");
|
|
6640
6667
|
};
|
|
6641
6668
|
if (u2.includes("BVN") || u2.includes("BANK VERIFICATION")) {
|
|
6642
|
-
return { icon: "
|
|
6669
|
+
return { icon: "ðŸ¦", desc: "Enter your 11-digit Bank Verification Number (BVN)", requiresBack: false };
|
|
6643
6670
|
}
|
|
6644
6671
|
if (u2.includes("NIN") || u2.includes("NATIONAL IDENTITY NUMBER")) {
|
|
6645
|
-
return { icon: "
|
|
6672
|
+
return { icon: "🆔", desc: "Enter your 11-digit National Identification Number (NIN)", requiresBack: false };
|
|
6646
6673
|
}
|
|
6647
6674
|
if (u2.includes("GHANA")) {
|
|
6648
|
-
if (isDocumentFlow) return { icon: "
|
|
6649
|
-
return { icon: "
|
|
6675
|
+
if (isDocumentFlow) return { icon: "🪪", desc: "Capture or upload your Ghana Card", requiresBack: true };
|
|
6676
|
+
return { icon: "🪪", desc: "Enter your Ghana Card number", requiresBack: false };
|
|
6650
6677
|
}
|
|
6651
6678
|
if (u2.includes("SSNIT"))
|
|
6652
|
-
return { icon: "
|
|
6679
|
+
return { icon: "ðŸ›ï¸", desc: "Enter your SSNIT number", requiresBack: false };
|
|
6653
6680
|
if (u2.includes("KENYA") || u2.includes("NATIONAL") && u2.includes("KENYA"))
|
|
6654
|
-
return { icon: "
|
|
6681
|
+
return { icon: "🆔", desc: "Enter your Kenya National ID number", requiresBack: false };
|
|
6655
6682
|
if (u2.includes("TIN") || u2.includes("TAX IDENTIFICATION"))
|
|
6656
|
-
return { icon: "
|
|
6683
|
+
return { icon: "🧾", desc: "Enter your Tax Identification Number (TIN)", requiresBack: false };
|
|
6657
6684
|
if (u2.includes("CAC") || u2.includes("CORPORATE AFFAIRS") || u2.includes("COMPANY"))
|
|
6658
|
-
return { icon: "
|
|
6685
|
+
return { icon: "ðŸ¢", desc: advanced ? "Enter RC number, company name & type" : "Enter your company registration number", requiresBack: false };
|
|
6659
6686
|
if (u2.includes("VOTER") || u2.includes("PVC")) {
|
|
6660
6687
|
const requiresBack = requiresBackSide(typeName);
|
|
6661
6688
|
return {
|
|
6662
|
-
icon: "
|
|
6689
|
+
icon: "🗳ï¸",
|
|
6663
6690
|
desc: isDocumentFlow ? `Capture or upload your voter's card${requiresBack ? " (front & back)" : ""}` : "Enter your voter ID number",
|
|
6664
6691
|
requiresBack: isDocumentFlow ? requiresBack : false
|
|
6665
6692
|
};
|
|
6666
6693
|
}
|
|
6667
6694
|
if (u2.includes("PASSPORT"))
|
|
6668
|
-
return { icon: "
|
|
6695
|
+
return { icon: "📘", desc: isDocumentFlow ? "Capture or upload your passport" : "Enter your passport number", requiresBack: false };
|
|
6669
6696
|
if (u2.includes("DRIVER") || u2.includes("LICENSE") || u2.includes("LICENCE")) {
|
|
6670
6697
|
const requiresBack = requiresBackSide(typeName);
|
|
6671
6698
|
return {
|
|
6672
|
-
icon: "
|
|
6699
|
+
icon: "🚗",
|
|
6673
6700
|
desc: isDocumentFlow ? `Capture or upload your driver's license${requiresBack ? " (front & back)" : ""}` : "Enter your driver's license number",
|
|
6674
6701
|
requiresBack: isDocumentFlow ? requiresBack : false
|
|
6675
6702
|
};
|
|
@@ -6677,15 +6704,15 @@ var SmartComplySDK = (() => {
|
|
|
6677
6704
|
if (u2.includes("NATIONAL ID") || u2.includes("NATIONAL") && u2.includes("CARD")) {
|
|
6678
6705
|
const requiresBack = requiresBackSide(typeName);
|
|
6679
6706
|
return {
|
|
6680
|
-
icon: "
|
|
6707
|
+
icon: "🪪",
|
|
6681
6708
|
desc: isDocumentFlow ? `Capture or upload your ID card${requiresBack ? " (front & back)" : ""}` : "Enter your National ID number",
|
|
6682
6709
|
requiresBack: isDocumentFlow ? requiresBack : false
|
|
6683
6710
|
};
|
|
6684
6711
|
}
|
|
6685
6712
|
if (u2.includes("LIVENESS") || u2.includes("FACE COMPARISON") || u2.includes("FACE MATCH"))
|
|
6686
|
-
return { icon: "
|
|
6713
|
+
return { icon: "🤳", desc: "We'll capture a short selfie video to verify you", requiresBack: false };
|
|
6687
6714
|
return {
|
|
6688
|
-
icon: isDocumentFlow ? "
|
|
6715
|
+
icon: isDocumentFlow ? "📄" : "🆔",
|
|
6689
6716
|
desc: isDocumentFlow ? "Capture or upload your document" : "Enter your ID number",
|
|
6690
6717
|
requiresBack: false
|
|
6691
6718
|
};
|
|
@@ -7097,7 +7124,7 @@ var SmartComplySDK = (() => {
|
|
|
7097
7124
|
display:flex;align-items:center;justify-content:center;
|
|
7098
7125
|
font-size:22px;
|
|
7099
7126
|
`;
|
|
7100
|
-
centre.textContent = "
|
|
7127
|
+
centre.textContent = "🛡️";
|
|
7101
7128
|
spinnerWrap.appendChild(ring);
|
|
7102
7129
|
spinnerWrap.appendChild(centre);
|
|
7103
7130
|
container.appendChild(spinnerWrap);
|
|
@@ -7124,7 +7151,7 @@ var SmartComplySDK = (() => {
|
|
|
7124
7151
|
background:linear-gradient(135deg,${this.theme.primary}22,${this.theme.primaryGlow});
|
|
7125
7152
|
border:1.5px solid ${this.theme.primary}33;
|
|
7126
7153
|
`;
|
|
7127
|
-
iconWrap.textContent = isDocFlow ? "
|
|
7154
|
+
iconWrap.textContent = isDocFlow ? "🪪" : "🛡ï¸";
|
|
7128
7155
|
topRow.appendChild(iconWrap);
|
|
7129
7156
|
const badge = document.createElement("div");
|
|
7130
7157
|
badge.style.cssText = `
|
|
@@ -7135,7 +7162,7 @@ var SmartComplySDK = (() => {
|
|
|
7135
7162
|
color:${this.theme.primary};
|
|
7136
7163
|
border:1px solid ${this.theme.primary}30;
|
|
7137
7164
|
`;
|
|
7138
|
-
badge.textContent = isDocFlow ? "
|
|
7165
|
+
badge.textContent = isDocFlow ? "📄 Document Verification" : "🔠Data Verification";
|
|
7139
7166
|
topRow.appendChild(badge);
|
|
7140
7167
|
container.appendChild(topRow);
|
|
7141
7168
|
const titleWrap = document.createElement("div");
|
|
@@ -7157,13 +7184,13 @@ var SmartComplySDK = (() => {
|
|
|
7157
7184
|
titleWrap.appendChild(desc);
|
|
7158
7185
|
container.appendChild(titleWrap);
|
|
7159
7186
|
const steps = isDocFlow ? [
|
|
7160
|
-
{ icon: "
|
|
7161
|
-
{ icon: "
|
|
7162
|
-
{ icon: "
|
|
7187
|
+
{ icon: "🪪", text: "Choose your document type", sub: "Passport, National ID, Driver License" },
|
|
7188
|
+
{ icon: "📷", text: "Scan your document", sub: "Upload or capture a photo of your ID" },
|
|
7189
|
+
{ icon: "🤳", text: "Face check", sub: "Quick selfie to confirm it's you" }
|
|
7163
7190
|
] : [
|
|
7164
|
-
{ icon: "
|
|
7165
|
-
{ icon: "
|
|
7166
|
-
{ icon: "
|
|
7191
|
+
{ icon: "🆔", text: "Choose your ID type", sub: "NIN, BVN, Voter's Card and more" },
|
|
7192
|
+
{ icon: "ðŸ“", text: "Enter your ID details", sub: "Exactly as shown on your ID" },
|
|
7193
|
+
{ icon: "🤳", text: "Face check", sub: "Quick selfie to confirm it's you" }
|
|
7167
7194
|
];
|
|
7168
7195
|
const stepsWrap = document.createElement("div");
|
|
7169
7196
|
stepsWrap.style.cssText = `
|
|
@@ -7203,7 +7230,7 @@ var SmartComplySDK = (() => {
|
|
|
7203
7230
|
stepsWrap.appendChild(row);
|
|
7204
7231
|
});
|
|
7205
7232
|
container.appendChild(stepsWrap);
|
|
7206
|
-
const btn = this.createPrimaryButton("Get Started
|
|
7233
|
+
const btn = this.createPrimaryButton("Get Started →");
|
|
7207
7234
|
btn.style.cssText += "margin-top:2px;";
|
|
7208
7235
|
btn.addEventListener("click", () => this.showStep("country"));
|
|
7209
7236
|
container.appendChild(btn);
|
|
@@ -7212,7 +7239,7 @@ var SmartComplySDK = (() => {
|
|
|
7212
7239
|
display:flex;align-items:center;gap:6px;
|
|
7213
7240
|
color:${this.theme.textMuted};font-size:10.5px;
|
|
7214
7241
|
`;
|
|
7215
|
-
trust.textContent = "
|
|
7242
|
+
trust.textContent = "🔒 End-to-end encrypted";
|
|
7216
7243
|
container.appendChild(trust);
|
|
7217
7244
|
}
|
|
7218
7245
|
// ── Country Select ──────────────────────────────────────────────
|
|
@@ -7265,7 +7292,7 @@ var SmartComplySDK = (() => {
|
|
|
7265
7292
|
const requiresBack = requiresBackFromBackend ?? info.requiresBack;
|
|
7266
7293
|
let subtitle2 = info.desc;
|
|
7267
7294
|
if (requiresBack && isThisDocFlow) {
|
|
7268
|
-
subtitle2 += "
|
|
7295
|
+
subtitle2 += " âš ï¸ Both sides required";
|
|
7269
7296
|
}
|
|
7270
7297
|
const displayName = typeName.replace(/\s*with\s+face\s*/gi, " ").replace(/\s*\(NIN\)\s*/gi, " ").replace(/\s*\(BVN\)\s*/gi, " ").replace(/\s{2,}/g, " ").trim();
|
|
7271
7298
|
const card = this.createOptionCard(
|
|
@@ -7328,13 +7355,13 @@ var SmartComplySDK = (() => {
|
|
|
7328
7355
|
{ match: "BVN", rule: { minLen: 11, maxLen: 11, numeric: true, hint: "BVN must be exactly 11 digits" } },
|
|
7329
7356
|
{ match: "NIN", rule: { minLen: 11, maxLen: 11, numeric: true, hint: "NIN must be exactly 11 digits" } },
|
|
7330
7357
|
{ match: "NATIONAL IDENTITY", rule: { minLen: 11, maxLen: 11, numeric: true, hint: "NIN must be exactly 11 digits" } },
|
|
7331
|
-
{ match: "PASSPORT", rule: { minLen: 6, maxLen: 20, alphanumeric: true, hint: "Passport number must be 6
|
|
7332
|
-
{ match: "DRIVER", rule: { minLen: 3, maxLen: 30, alphanumeric: true, hint: "Licence number must be 3
|
|
7333
|
-
{ match: "VOTER", rule: { minLen: 6, maxLen: 30, alphanumeric: true, hint: "Voter ID must be 6
|
|
7334
|
-
{ match: "GHANA", rule: { minLen: 8, maxLen: 20, alphanumeric: true, hint: "Ghana Card number must be 8
|
|
7335
|
-
{ match: "SSNIT", rule: { minLen: 7, maxLen: 15, alphanumeric: true, hint: "SSNIT number must be 7
|
|
7336
|
-
{ match: "TIN", rule: { minLen: 8, maxLen: 20, alphanumeric: true, hint: "TIN must be 8
|
|
7337
|
-
{ match: "KRA", rule: { minLen: 10, maxLen: 12, alphanumeric: true, hint: "KRA PIN must be 10
|
|
7358
|
+
{ match: "PASSPORT", rule: { minLen: 6, maxLen: 20, alphanumeric: true, hint: "Passport number must be 6–20 alphanumeric characters" } },
|
|
7359
|
+
{ match: "DRIVER", rule: { minLen: 3, maxLen: 30, alphanumeric: true, hint: "Licence number must be 3–30 alphanumeric characters" } },
|
|
7360
|
+
{ match: "VOTER", rule: { minLen: 6, maxLen: 30, alphanumeric: true, hint: "Voter ID must be 6–30 alphanumeric characters" } },
|
|
7361
|
+
{ match: "GHANA", rule: { minLen: 8, maxLen: 20, alphanumeric: true, hint: "Ghana Card number must be 8–20 alphanumeric characters" } },
|
|
7362
|
+
{ match: "SSNIT", rule: { minLen: 7, maxLen: 15, alphanumeric: true, hint: "SSNIT number must be 7–15 alphanumeric characters" } },
|
|
7363
|
+
{ match: "TIN", rule: { minLen: 8, maxLen: 20, alphanumeric: true, hint: "TIN must be 8–20 characters" } },
|
|
7364
|
+
{ match: "KRA", rule: { minLen: 10, maxLen: 12, alphanumeric: true, hint: "KRA PIN must be 10–12 characters" } }
|
|
7338
7365
|
];
|
|
7339
7366
|
function getFieldRule(label) {
|
|
7340
7367
|
const upper = label.toUpperCase();
|
|
@@ -7620,7 +7647,7 @@ var SmartComplySDK = (() => {
|
|
|
7620
7647
|
this._prewarmCamera();
|
|
7621
7648
|
const iconWrap = document.createElement("div");
|
|
7622
7649
|
iconWrap.style.cssText = `width:64px;height:64px;border-radius:50%;background:${this.theme.primary}15;border:2px solid ${this.theme.primary}30;display:flex;align-items:center;justify-content:center;font-size:28px;`;
|
|
7623
|
-
iconWrap.textContent = "
|
|
7650
|
+
iconWrap.textContent = "🛡ï¸";
|
|
7624
7651
|
container.appendChild(iconWrap);
|
|
7625
7652
|
const title = document.createElement("h2");
|
|
7626
7653
|
title.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
|
|
@@ -7657,7 +7684,7 @@ var SmartComplySDK = (() => {
|
|
|
7657
7684
|
sub.textContent = "Your details have been confirmed. Please continue to the face check.";
|
|
7658
7685
|
container.appendChild(sub);
|
|
7659
7686
|
}
|
|
7660
|
-
const yesBtn = this.createPrimaryButton("Yes, that's me
|
|
7687
|
+
const yesBtn = this.createPrimaryButton("Yes, that's me — continue");
|
|
7661
7688
|
yesBtn.addEventListener("click", () => {
|
|
7662
7689
|
this._confirmRetries = 0;
|
|
7663
7690
|
this.showStep("liveness");
|
|
@@ -7684,7 +7711,7 @@ var SmartComplySDK = (() => {
|
|
|
7684
7711
|
this._prewarmCamera();
|
|
7685
7712
|
const iconWrap = document.createElement("div");
|
|
7686
7713
|
iconWrap.style.cssText = `width:64px;height:64px;border-radius:50%;background:${this.theme.primary}15;border:2px solid ${this.theme.primary}30;display:flex;align-items:center;justify-content:center;font-size:28px;`;
|
|
7687
|
-
iconWrap.textContent = "
|
|
7714
|
+
iconWrap.textContent = "📄";
|
|
7688
7715
|
container.appendChild(iconWrap);
|
|
7689
7716
|
const title = document.createElement("h2");
|
|
7690
7717
|
title.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
|
|
@@ -7707,7 +7734,7 @@ var SmartComplySDK = (() => {
|
|
|
7707
7734
|
if (this._ocrExpirySoon && !this._ocrIsExpired) {
|
|
7708
7735
|
const warn = document.createElement("div");
|
|
7709
7736
|
warn.style.cssText = `width:100%;padding:10px 14px;border-radius:10px;background:${this.theme.warning}18;border:1px solid ${this.theme.warning}40;color:${this.theme.warning};font-size:12px;text-align:left;line-height:1.5;`;
|
|
7710
|
-
warn.textContent = "
|
|
7737
|
+
warn.textContent = "âš ï¸ Your document expires soon. Some services may not accept it, but you can still continue.";
|
|
7711
7738
|
container.appendChild(warn);
|
|
7712
7739
|
}
|
|
7713
7740
|
const card = document.createElement("div");
|
|
@@ -7770,18 +7797,18 @@ var SmartComplySDK = (() => {
|
|
|
7770
7797
|
ring.style.cssText = `position:absolute;inset:0;border-radius:50%;border:3px solid ${this.theme.border};border-top-color:${this.theme.primary};animation:sc-spin 0.9s linear infinite;`;
|
|
7771
7798
|
const centre = document.createElement("div");
|
|
7772
7799
|
centre.style.cssText = "position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;";
|
|
7773
|
-
centre.textContent = "
|
|
7800
|
+
centre.textContent = "📄";
|
|
7774
7801
|
spinnerWrap.appendChild(ring);
|
|
7775
7802
|
spinnerWrap.appendChild(centre);
|
|
7776
7803
|
container.appendChild(spinnerWrap);
|
|
7777
7804
|
const statusEl = document.createElement("div");
|
|
7778
7805
|
statusEl.setAttribute("aria-live", "polite");
|
|
7779
7806
|
statusEl.style.cssText = `color:${this.theme.text};font-size:15px;font-weight:600;`;
|
|
7780
|
-
statusEl.textContent = "Reading your document
|
|
7807
|
+
statusEl.textContent = "Reading your document…";
|
|
7781
7808
|
container.appendChild(statusEl);
|
|
7782
7809
|
const subEl = document.createElement("div");
|
|
7783
7810
|
subEl.style.cssText = `color:${this.theme.textSecondary};font-size:12px;max-width:260px;line-height:1.5;`;
|
|
7784
|
-
subEl.textContent = "This usually takes 5
|
|
7811
|
+
subEl.textContent = "This usually takes 5–15 seconds. Please wait.";
|
|
7785
7812
|
container.appendChild(subEl);
|
|
7786
7813
|
if (!this.livenessEntryId) {
|
|
7787
7814
|
this.showErrorStep("Document upload failed. Please try again.");
|
|
@@ -7826,8 +7853,8 @@ var SmartComplySDK = (() => {
|
|
|
7826
7853
|
if (polls < MAX_POLLS && !this.isDestroyed) {
|
|
7827
7854
|
this._ocrPollTimer = setTimeout(poll, 2e3);
|
|
7828
7855
|
} else if (!this.isDestroyed) {
|
|
7829
|
-
statusEl.textContent = "Taking longer than usual
|
|
7830
|
-
subEl.textContent = "We'll continue
|
|
7856
|
+
statusEl.textContent = "Taking longer than usual…";
|
|
7857
|
+
subEl.textContent = "We'll continue — you can confirm your details on the next screen.";
|
|
7831
7858
|
this._ocrPollTimer = setTimeout(() => {
|
|
7832
7859
|
if (!this.isDestroyed) this.showStep("document_confirm");
|
|
7833
7860
|
}, 2e3);
|
|
@@ -7846,7 +7873,7 @@ var SmartComplySDK = (() => {
|
|
|
7846
7873
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;padding:20px 0;";
|
|
7847
7874
|
const icon = document.createElement("div");
|
|
7848
7875
|
icon.style.cssText = `width:72px;height:72px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:28px;`;
|
|
7849
|
-
icon.textContent = "
|
|
7876
|
+
icon.textContent = "📅";
|
|
7850
7877
|
container.appendChild(icon);
|
|
7851
7878
|
const t2 = document.createElement("h2");
|
|
7852
7879
|
t2.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
|
|
@@ -7875,7 +7902,7 @@ var SmartComplySDK = (() => {
|
|
|
7875
7902
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;padding:20px 0;";
|
|
7876
7903
|
const icon = document.createElement("div");
|
|
7877
7904
|
icon.style.cssText = `width:72px;height:72px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:28px;`;
|
|
7878
|
-
icon.textContent = "
|
|
7905
|
+
icon.textContent = "ðŸ”";
|
|
7879
7906
|
container.appendChild(icon);
|
|
7880
7907
|
const t2 = document.createElement("h2");
|
|
7881
7908
|
t2.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
|
|
@@ -7908,7 +7935,7 @@ var SmartComplySDK = (() => {
|
|
|
7908
7935
|
});
|
|
7909
7936
|
const iconWrap = document.createElement("div");
|
|
7910
7937
|
iconWrap.style.cssText = `width:80px;height:80px;border-radius:50%;background:${this.theme.successBg};border:3px solid ${this.theme.success};display:flex;align-items:center;justify-content:center;font-size:36px;font-weight:700;color:${this.theme.success};animation:sc-pop 0.4s ease;`;
|
|
7911
|
-
iconWrap.textContent = "
|
|
7938
|
+
iconWrap.textContent = "✓";
|
|
7912
7939
|
container.appendChild(iconWrap);
|
|
7913
7940
|
const title = document.createElement("h2");
|
|
7914
7941
|
title.style.cssText = `color:${this.theme.text};font-size:22px;font-weight:700;margin:0;`;
|
|
@@ -7921,7 +7948,7 @@ var SmartComplySDK = (() => {
|
|
|
7921
7948
|
container.appendChild(desc);
|
|
7922
7949
|
const info = document.createElement("div");
|
|
7923
7950
|
info.style.cssText = `color:${this.theme.textMuted};font-size:11px;display:flex;align-items:center;gap:4px;`;
|
|
7924
|
-
info.textContent = "
|
|
7951
|
+
info.textContent = "🔒 Your data is encrypted and secure";
|
|
7925
7952
|
container.appendChild(info);
|
|
7926
7953
|
const doneBtn = this.createPrimaryButton("Close");
|
|
7927
7954
|
doneBtn.addEventListener("click", () => {
|
|
@@ -7934,7 +7961,7 @@ var SmartComplySDK = (() => {
|
|
|
7934
7961
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;padding:24px 0;";
|
|
7935
7962
|
const icon = document.createElement("div");
|
|
7936
7963
|
icon.style.cssText = `width:72px;height:72px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:28px;`;
|
|
7937
|
-
icon.textContent = "
|
|
7964
|
+
icon.textContent = "âš ï¸";
|
|
7938
7965
|
container.appendChild(icon);
|
|
7939
7966
|
const t2 = document.createElement("h2");
|
|
7940
7967
|
t2.style.cssText = `color:${this.theme.text};font-size:18px;font-weight:700;margin:0;`;
|
|
@@ -7990,7 +8017,7 @@ var SmartComplySDK = (() => {
|
|
|
7990
8017
|
<div style="display:flex;flex-direction:column;align-items:center;gap:14px;padding:28px 20px;">
|
|
7991
8018
|
<div style="position:relative;width:52px;height:52px;">
|
|
7992
8019
|
<div style="position:absolute;inset:0;border-radius:50%;border:3px solid ${this.theme.border};border-top-color:${this.theme.primary};animation:sc-spin 0.8s linear infinite;"></div>
|
|
7993
|
-
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;"
|
|
8020
|
+
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;">ðŸ”</div>
|
|
7994
8021
|
</div>
|
|
7995
8022
|
<div style="color:${this.theme.text};font-size:14px;font-weight:600;">Scanning document...</div>
|
|
7996
8023
|
<div style="color:${this.theme.textSecondary};font-size:12px;text-align:center;max-width:200px;line-height:1.5;">Running OCR and verifying your identity</div>
|
|
@@ -8048,7 +8075,7 @@ var SmartComplySDK = (() => {
|
|
|
8048
8075
|
<div style="display:flex;flex-direction:column;align-items:center;gap:16px;padding:28px 20px;text-align:center;">
|
|
8049
8076
|
<div style="position:relative;width:52px;height:52px;">
|
|
8050
8077
|
<div style="position:absolute;inset:0;border-radius:50%;border:3px solid ${this.theme.border};border-top-color:${this.theme.primary};animation:sc-spin 0.8s linear infinite;"></div>
|
|
8051
|
-
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;"
|
|
8078
|
+
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;">🔄</div>
|
|
8052
8079
|
</div>
|
|
8053
8080
|
<div style="color:${this.theme.text};font-size:14px;font-weight:600;">Retrying...</div>
|
|
8054
8081
|
<div style="color:${this.theme.textSecondary};font-size:12px;max-width:240px;line-height:1.5;">Attempt ${retryCount} of ${maxRetries}</div>
|
|
@@ -8089,7 +8116,7 @@ var SmartComplySDK = (() => {
|
|
|
8089
8116
|
wrap.setAttribute("role", "alert");
|
|
8090
8117
|
const icon = document.createElement("div");
|
|
8091
8118
|
icon.style.cssText = `width:56px;height:56px;border-radius:50%;background:${this.theme.errorBg};border:3px solid ${this.theme.error};display:flex;align-items:center;justify-content:center;font-size:26px;`;
|
|
8092
|
-
icon.textContent = "
|
|
8119
|
+
icon.textContent = "ðŸ”";
|
|
8093
8120
|
wrap.appendChild(icon);
|
|
8094
8121
|
const titleEl = document.createElement("div");
|
|
8095
8122
|
titleEl.style.cssText = `color:${this.theme.text};font-size:14px;font-weight:700;`;
|
|
@@ -8130,8 +8157,8 @@ var SmartComplySDK = (() => {
|
|
|
8130
8157
|
livenessContainer.style.cssText = "margin:8px 0;width:100%;";
|
|
8131
8158
|
container.appendChild(livenessContainer);
|
|
8132
8159
|
const isDataVerification = !!this.identityCheckId;
|
|
8133
|
-
const identifier = isDataVerification ?
|
|
8134
|
-
const identifierType = isDataVerification ? "
|
|
8160
|
+
const identifier = isDataVerification ? "" : this.idNumber || Object.values(this.collectedFields)[0] || this.selectedIdType || `DOC-${Date.now()}`;
|
|
8161
|
+
const identifierType = isDataVerification ? "" : this.selectedIdType;
|
|
8135
8162
|
const COUNTRY_CODES = {
|
|
8136
8163
|
nigeria: "NG",
|
|
8137
8164
|
ghana: "GH",
|
|
@@ -8189,7 +8216,7 @@ var SmartComplySDK = (() => {
|
|
|
8189
8216
|
const isDocQuality = /blurry|blur|quality|glare|dark|bright|lighting/i.test(message);
|
|
8190
8217
|
const isExpiredDoc = /document.*expired|expired.*document/i.test(message);
|
|
8191
8218
|
const isFaceMatch = /face.*match|selfie.*match|does not match/i.test(message);
|
|
8192
|
-
const errorIcon = isCameraErr ? "
|
|
8219
|
+
const errorIcon = isCameraErr ? "📷" : isNetworkErr ? "📡" : isAuthErr ? "â±" : isDocQuality ? "ðŸ”" : isExpiredDoc ? "📅" : isFaceMatch ? "🤳" : "✕";
|
|
8193
8220
|
const errorTitle = isCameraErr ? "Camera Access Required" : isNetworkErr ? "Connection Problem" : isAuthErr ? "Session Expired" : isDocQuality ? "Document Photo Unclear" : isExpiredDoc ? "Document Expired" : isFaceMatch ? "Face Match Failed" : "Verification Unsuccessful";
|
|
8194
8221
|
const userMessage = isCameraErr ? "Please allow camera access in your browser settings and try again." : isNetworkErr ? "Check your internet connection and try again." : isAuthErr ? "Your session has expired. Please start again." : isDocQuality ? _sanitizeUserMessage(message) || "Please retake your document photo in good lighting with no glare." : isExpiredDoc ? "The document you submitted has expired. Please use a valid, current ID." : isFaceMatch ? "Your selfie did not match the photo on your ID. Please ensure you are using your own valid document and face the camera directly." : _sanitizeUserMessage(message) || "We were unable to complete your verification. Please try again.";
|
|
8195
8222
|
const iconWrap = document.createElement("div");
|
|
@@ -8294,7 +8321,7 @@ var SmartComplySDK = (() => {
|
|
|
8294
8321
|
stepIndicator.appendChild(this.stepLabel);
|
|
8295
8322
|
header.appendChild(stepIndicator);
|
|
8296
8323
|
const closeBtn = document.createElement("button");
|
|
8297
|
-
closeBtn.innerHTML = "
|
|
8324
|
+
closeBtn.innerHTML = "✕";
|
|
8298
8325
|
closeBtn.setAttribute("aria-label", "Close identity verification");
|
|
8299
8326
|
closeBtn.style.cssText = `
|
|
8300
8327
|
width:32px;height:32px;border-radius:8px;flex-shrink:0;
|
|
@@ -8375,7 +8402,7 @@ var SmartComplySDK = (() => {
|
|
|
8375
8402
|
}
|
|
8376
8403
|
const arrow = document.createElement("span");
|
|
8377
8404
|
arrow.style.cssText = `color:${this.theme.textMuted};font-size:18px;flex-shrink:0;`;
|
|
8378
|
-
arrow.textContent = "
|
|
8405
|
+
arrow.textContent = "→";
|
|
8379
8406
|
card.appendChild(textWrap);
|
|
8380
8407
|
card.appendChild(arrow);
|
|
8381
8408
|
return card;
|
|
@@ -8447,7 +8474,7 @@ var SmartComplySDK = (() => {
|
|
|
8447
8474
|
if (this.currentStep === "loading" || this.currentStep === "welcome") {
|
|
8448
8475
|
this.stepLabel.textContent = "";
|
|
8449
8476
|
} else if (this.currentStep === "done" || this.currentStep === "result") {
|
|
8450
|
-
this.stepLabel.textContent = "Complete
|
|
8477
|
+
this.stepLabel.textContent = "Complete ✓";
|
|
8451
8478
|
} else if (stage2Steps.includes(this.currentStep)) {
|
|
8452
8479
|
this.stepLabel.textContent = "Stage 2 of 2: Face Check";
|
|
8453
8480
|
} else if (stage1Steps.includes(this.currentStep)) {
|
|
@@ -8561,20 +8588,20 @@ var SmartComplySDK = (() => {
|
|
|
8561
8588
|
/** Emit an informational message (debug mode only). */
|
|
8562
8589
|
info(message, ...args) {
|
|
8563
8590
|
if (!isDebugEnabled()) return;
|
|
8564
|
-
console.info(`${PREFIX}
|
|
8591
|
+
console.info(`${PREFIX} ℹ ${message}`, ...args);
|
|
8565
8592
|
},
|
|
8566
8593
|
/** Emit a warning (always visible). */
|
|
8567
8594
|
warn(message, ...args) {
|
|
8568
|
-
console.warn(`${PREFIX}
|
|
8595
|
+
console.warn(`${PREFIX} ⚠ ${message}`, ...args);
|
|
8569
8596
|
},
|
|
8570
8597
|
/** Emit an error (always visible). */
|
|
8571
8598
|
error(message, ...args) {
|
|
8572
|
-
console.error(`${PREFIX}
|
|
8599
|
+
console.error(`${PREFIX} ✖ ${message}`, ...args);
|
|
8573
8600
|
},
|
|
8574
8601
|
/** Emit a debug trace (debug mode only — lowest priority). */
|
|
8575
8602
|
debug(message, ...args) {
|
|
8576
8603
|
if (!isDebugEnabled()) return;
|
|
8577
|
-
console.debug(`${PREFIX}
|
|
8604
|
+
console.debug(`${PREFIX} ⬡ ${message}`, ...args);
|
|
8578
8605
|
},
|
|
8579
8606
|
/** Log a timed group of related messages (debug mode only). */
|
|
8580
8607
|
group(label, fn2) {
|
|
@@ -8732,7 +8759,7 @@ var SmartComplySDK = (() => {
|
|
|
8732
8759
|
}
|
|
8733
8760
|
};
|
|
8734
8761
|
xhr.onerror = async () => {
|
|
8735
|
-
SDKLogger.warn(`Upload to ${path} failed
|
|
8762
|
+
SDKLogger.warn(`Upload to ${path} failed — network error`, { retriesLeft });
|
|
8736
8763
|
if (retriesLeft > 0) {
|
|
8737
8764
|
await new Promise((r2) => setTimeout(r2, RETRY_DELAY_MS));
|
|
8738
8765
|
try {
|