smartcomply-web-sdk 1.0.62 → 1.0.64
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/esm/flow/DocumentCapture.d.ts +21 -1
- package/dist/esm/flow/DocumentCapture.d.ts.map +1 -1
- package/dist/esm/flow/DocumentCapture.js +155 -84
- package/dist/esm/flow/DocumentCapture.js.map +1 -1
- package/dist/esm/flow/SmartComplyFlow.d.ts +1 -0
- package/dist/esm/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/esm/flow/SmartComplyFlow.js +89 -105
- package/dist/esm/flow/SmartComplyFlow.js.map +1 -1
- package/dist/esm/flow/icons.d.ts +14 -0
- package/dist/esm/flow/icons.d.ts.map +1 -0
- package/dist/esm/flow/icons.js +34 -0
- package/dist/esm/flow/icons.js.map +1 -0
- package/dist/esm/flow/spinner.d.ts +15 -0
- package/dist/esm/flow/spinner.d.ts.map +1 -0
- package/dist/esm/flow/spinner.js +55 -0
- package/dist/esm/flow/spinner.js.map +1 -0
- package/dist/esm/flow/theme.d.ts +19 -0
- package/dist/esm/flow/theme.d.ts.map +1 -1
- package/dist/esm/flow/theme.js +19 -0
- package/dist/esm/flow/theme.js.map +1 -1
- package/dist/esm/modules/liveness/LivenessUI.d.ts +10 -0
- package/dist/esm/modules/liveness/LivenessUI.d.ts.map +1 -1
- package/dist/esm/modules/liveness/LivenessUI.js +17 -16
- package/dist/esm/modules/liveness/LivenessUI.js.map +1 -1
- package/dist/esm/modules/liveness/liveness.d.ts +2 -0
- package/dist/esm/modules/liveness/liveness.d.ts.map +1 -1
- package/dist/esm/modules/liveness/liveness.js +1 -1
- package/dist/esm/modules/liveness/liveness.js.map +1 -1
- package/dist/flow/DocumentCapture.d.ts +21 -1
- package/dist/flow/DocumentCapture.d.ts.map +1 -1
- package/dist/flow/DocumentCapture.js +155 -84
- package/dist/flow/DocumentCapture.js.map +1 -1
- package/dist/flow/SmartComplyFlow.d.ts +1 -0
- package/dist/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/flow/SmartComplyFlow.js +88 -104
- package/dist/flow/SmartComplyFlow.js.map +1 -1
- package/dist/flow/icons.d.ts +14 -0
- package/dist/flow/icons.d.ts.map +1 -0
- package/dist/flow/icons.js +37 -0
- package/dist/flow/icons.js.map +1 -0
- package/dist/flow/spinner.d.ts +15 -0
- package/dist/flow/spinner.d.ts.map +1 -0
- package/dist/flow/spinner.js +59 -0
- package/dist/flow/spinner.js.map +1 -0
- package/dist/flow/theme.d.ts +19 -0
- package/dist/flow/theme.d.ts.map +1 -1
- package/dist/flow/theme.js +20 -1
- package/dist/flow/theme.js.map +1 -1
- package/dist/modules/liveness/LivenessUI.d.ts +10 -0
- package/dist/modules/liveness/LivenessUI.d.ts.map +1 -1
- package/dist/modules/liveness/LivenessUI.js +17 -16
- package/dist/modules/liveness/LivenessUI.js.map +1 -1
- package/dist/modules/liveness/liveness.d.ts +2 -0
- package/dist/modules/liveness/liveness.d.ts.map +1 -1
- package/dist/modules/liveness/liveness.js +1 -1
- package/dist/modules/liveness/liveness.js.map +1 -1
- package/dist/smartcomply.browser.js +333 -209
- package/dist/smartcomply.browser.js.map +4 -4
- package/package.json +1 -1
|
@@ -6,6 +6,8 @@ const theme_1 = require("./theme");
|
|
|
6
6
|
const DocumentCapture_1 = require("./DocumentCapture");
|
|
7
7
|
const device_1 = require("../utils/device");
|
|
8
8
|
const documentRules_1 = require("../utils/documentRules");
|
|
9
|
+
const icons_1 = require("./icons");
|
|
10
|
+
const spinner_1 = require("./spinner");
|
|
9
11
|
const STEP_ORDER = [
|
|
10
12
|
"loading",
|
|
11
13
|
"welcome",
|
|
@@ -229,18 +231,6 @@ function _formatDocType(code) {
|
|
|
229
231
|
}
|
|
230
232
|
// SmartComplyFlow
|
|
231
233
|
// ─────────────────────────────────────────────────────────────────────
|
|
232
|
-
// Add CSS animation keyframes for spin animations
|
|
233
|
-
const style = document.createElement('style');
|
|
234
|
-
style.textContent = `
|
|
235
|
-
@keyframes sc-spin {
|
|
236
|
-
0% { transform: rotate(0deg); }
|
|
237
|
-
100% { transform: rotate(360deg); }
|
|
238
|
-
}
|
|
239
|
-
`;
|
|
240
|
-
if (!document.head.querySelector('style[data-sc-animations]')) {
|
|
241
|
-
style.setAttribute('data-sc-animations', 'true');
|
|
242
|
-
document.head.appendChild(style);
|
|
243
|
-
}
|
|
244
234
|
class SmartComplyFlow {
|
|
245
235
|
constructor(options) {
|
|
246
236
|
this.theme = (0, theme_1.getTheme)("default");
|
|
@@ -265,6 +255,11 @@ class SmartComplyFlow {
|
|
|
265
255
|
this.idNumber = "";
|
|
266
256
|
this.documentBlob = null;
|
|
267
257
|
this.documentBackBlob = null;
|
|
258
|
+
// Whether the document's front image came from the live camera vs. a
|
|
259
|
+
// gallery/file upload — gates whether pre-warming the liveness camera on
|
|
260
|
+
// the confirm screens makes sense (reusing an already-open camera) or
|
|
261
|
+
// would surprise a user who hasn't touched their camera yet this session.
|
|
262
|
+
this._documentViaCamera = false;
|
|
268
263
|
this.identityCheckId = null;
|
|
269
264
|
this.verificationResult = null;
|
|
270
265
|
this.livenessEntryId = null;
|
|
@@ -612,27 +607,9 @@ class SmartComplyFlow {
|
|
|
612
607
|
// ── Loading ─────────────────────────────────────────────────────
|
|
613
608
|
renderLoading(container) {
|
|
614
609
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:300px;gap:16px;";
|
|
615
|
-
|
|
616
|
-
spinnerWrap.style.cssText = "position:relative;width:60px;height:60px;flex-shrink:0;";
|
|
617
|
-
const ring = document.createElement("div");
|
|
618
|
-
ring.style.cssText = `
|
|
619
|
-
position:absolute;inset:0;border-radius:50%;
|
|
620
|
-
border:3px solid ${this.theme.border};
|
|
621
|
-
border-top-color:${this.theme.primary};
|
|
622
|
-
animation:sc-spin 0.9s linear infinite;
|
|
623
|
-
`;
|
|
624
|
-
const centre = document.createElement("div");
|
|
625
|
-
centre.style.cssText = `
|
|
626
|
-
position:absolute;inset:0;
|
|
627
|
-
display:flex;align-items:center;justify-content:center;
|
|
628
|
-
font-size:22px;
|
|
629
|
-
`;
|
|
630
|
-
centre.textContent = "\uD83D\uDEE1\uFE0F";
|
|
631
|
-
spinnerWrap.appendChild(ring);
|
|
632
|
-
spinnerWrap.appendChild(centre);
|
|
633
|
-
container.appendChild(spinnerWrap);
|
|
610
|
+
container.appendChild((0, spinner_1.renderSpinner)(this.theme, { size: 60, icon: (0, icons_1.icon)("shield", 22) }));
|
|
634
611
|
const label = document.createElement("div");
|
|
635
|
-
label.style.cssText = `color:${this.theme.text};font-size
|
|
612
|
+
label.style.cssText = `color:${this.theme.text};font-size:${theme_1.TYPE.base}px;font-weight:600;`;
|
|
636
613
|
label.textContent = "Setting up secure session";
|
|
637
614
|
container.appendChild(label);
|
|
638
615
|
const sub = document.createElement("div");
|
|
@@ -651,11 +628,11 @@ class SmartComplyFlow {
|
|
|
651
628
|
iconWrap.style.cssText = `
|
|
652
629
|
width:50px;height:50px;border-radius:14px;
|
|
653
630
|
display:flex;align-items:center;justify-content:center;
|
|
654
|
-
|
|
631
|
+
color:${this.theme.primary};
|
|
655
632
|
background:linear-gradient(135deg,${this.theme.primary}22,${this.theme.primaryGlow});
|
|
656
633
|
border:1.5px solid ${this.theme.primary}33;
|
|
657
634
|
`;
|
|
658
|
-
iconWrap.
|
|
635
|
+
iconWrap.innerHTML = (0, icons_1.icon)(isDocFlow ? "id-card" : "shield", 24);
|
|
659
636
|
topRow.appendChild(iconWrap);
|
|
660
637
|
const badge = document.createElement("div");
|
|
661
638
|
badge.style.cssText = `
|
|
@@ -674,7 +651,7 @@ class SmartComplyFlow {
|
|
|
674
651
|
titleWrap.style.cssText = "display:flex;flex-direction:column;gap:5px;";
|
|
675
652
|
const title = document.createElement("h2");
|
|
676
653
|
title.style.cssText = `
|
|
677
|
-
color:${this.theme.text};font-size
|
|
654
|
+
color:${this.theme.text};font-size:${theme_1.TYPE.heading}px;font-weight:700;
|
|
678
655
|
margin:0;line-height:1.2;
|
|
679
656
|
`;
|
|
680
657
|
// W2: Use client brand name in title
|
|
@@ -708,7 +685,7 @@ class SmartComplyFlow {
|
|
|
708
685
|
const stepsWrap = document.createElement("div");
|
|
709
686
|
stepsWrap.style.cssText = `
|
|
710
687
|
width:100%;display:flex;flex-direction:column;gap:0;
|
|
711
|
-
border-radius
|
|
688
|
+
border-radius:${theme_1.RADIUS.md}px;overflow:hidden;
|
|
712
689
|
border:1.5px solid ${this.theme.border};
|
|
713
690
|
`;
|
|
714
691
|
steps.forEach((step, i) => {
|
|
@@ -721,7 +698,7 @@ class SmartComplyFlow {
|
|
|
721
698
|
`;
|
|
722
699
|
const iconEl = document.createElement("div");
|
|
723
700
|
iconEl.style.cssText = `
|
|
724
|
-
width:28px;height:28px;border-radius
|
|
701
|
+
width:28px;height:28px;border-radius:${theme_1.RADIUS.sm}px;flex-shrink:0;
|
|
725
702
|
display:flex;align-items:center;justify-content:center;
|
|
726
703
|
font-size:13px;
|
|
727
704
|
background:${this.theme.primary}12;
|
|
@@ -949,7 +926,7 @@ class SmartComplyFlow {
|
|
|
949
926
|
// Dropdown field
|
|
950
927
|
const select = document.createElement("select");
|
|
951
928
|
select.style.cssText = `
|
|
952
|
-
width:100%;padding:13px 16px;border-radius
|
|
929
|
+
width:100%;padding:13px 16px;border-radius:${theme_1.RADIUS.md}px;
|
|
953
930
|
font-size:15px;
|
|
954
931
|
background:${this.theme.inputBg};
|
|
955
932
|
color:${this.theme.text};
|
|
@@ -984,7 +961,7 @@ class SmartComplyFlow {
|
|
|
984
961
|
fileInput.type = "file";
|
|
985
962
|
fileInput.accept = "image/*";
|
|
986
963
|
fileInput.style.cssText = `
|
|
987
|
-
width:100%;padding:12px 16px;border-radius
|
|
964
|
+
width:100%;padding:12px 16px;border-radius:${theme_1.RADIUS.md}px;
|
|
988
965
|
font-size:14px;font-weight:500;
|
|
989
966
|
background:${this.theme.inputBg};
|
|
990
967
|
color:${this.theme.text};
|
|
@@ -1028,7 +1005,7 @@ class SmartComplyFlow {
|
|
|
1028
1005
|
if (rule?.numeric)
|
|
1029
1006
|
input.inputMode = "numeric";
|
|
1030
1007
|
input.style.cssText = `
|
|
1031
|
-
width:100%;padding:14px 16px;border-radius
|
|
1008
|
+
width:100%;padding:14px 16px;border-radius:${theme_1.RADIUS.md}px;
|
|
1032
1009
|
font-size:16px;font-weight:500;
|
|
1033
1010
|
background:${this.theme.inputBg};
|
|
1034
1011
|
color:${this.theme.text};
|
|
@@ -1090,7 +1067,7 @@ class SmartComplyFlow {
|
|
|
1090
1067
|
errorEl.id = "sc-id-error";
|
|
1091
1068
|
errorEl.style.cssText = `
|
|
1092
1069
|
color:${this.theme.error};font-size:13px;display:none;
|
|
1093
|
-
padding:8px 12px;border-radius
|
|
1070
|
+
padding:8px 12px;border-radius:${theme_1.RADIUS.sm}px;background:${this.theme.errorBg};
|
|
1094
1071
|
`;
|
|
1095
1072
|
container.appendChild(errorEl);
|
|
1096
1073
|
// Submit
|
|
@@ -1111,7 +1088,7 @@ class SmartComplyFlow {
|
|
|
1111
1088
|
};
|
|
1112
1089
|
submitBtn.addEventListener("click", async () => {
|
|
1113
1090
|
submitBtn.disabled = true;
|
|
1114
|
-
submitBtn.innerHTML = `<span style="display:inline-flex;align-items:center;justify-content:center;gap:8px;"
|
|
1091
|
+
submitBtn.innerHTML = `<span style="display:inline-flex;align-items:center;justify-content:center;gap:8px;">${(0, spinner_1.renderInlineSpinner)("#fff", 13)}Verifying...</span>`;
|
|
1115
1092
|
errorEl.style.display = "none";
|
|
1116
1093
|
try {
|
|
1117
1094
|
this.verificationResult = await this.sdk.onboarding.verify({
|
|
@@ -1238,11 +1215,11 @@ class SmartComplyFlow {
|
|
|
1238
1215
|
// W13: Pre-warm camera silently while user reads this screen
|
|
1239
1216
|
this._prewarmCamera();
|
|
1240
1217
|
const iconWrap = document.createElement("div");
|
|
1241
|
-
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;
|
|
1242
|
-
iconWrap.
|
|
1218
|
+
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;color:${this.theme.primary};`;
|
|
1219
|
+
iconWrap.innerHTML = (0, icons_1.icon)("shield", 28);
|
|
1243
1220
|
container.appendChild(iconWrap);
|
|
1244
1221
|
const title = document.createElement("h2");
|
|
1245
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
1222
|
+
title.style.cssText = `color:${this.theme.text};font-size:${theme_1.TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1246
1223
|
title.textContent = this._ivsName ? `Is this you?` : "Identity Confirmed";
|
|
1247
1224
|
container.appendChild(title);
|
|
1248
1225
|
if (this._ivsName) {
|
|
@@ -1304,14 +1281,32 @@ class SmartComplyFlow {
|
|
|
1304
1281
|
this._renderRetryLimitReached(container);
|
|
1305
1282
|
return;
|
|
1306
1283
|
}
|
|
1307
|
-
// W13: Pre-warm camera while user reads
|
|
1308
|
-
|
|
1284
|
+
// W13: Pre-warm camera while user reads — but only if the document photo
|
|
1285
|
+
// itself came from the camera. Pre-warming here when the user uploaded
|
|
1286
|
+
// from gallery means requesting camera access before they've touched
|
|
1287
|
+
// their camera at all this session, which reads as an unexplained/
|
|
1288
|
+
// unexpected prompt rather than a seamless continuation.
|
|
1289
|
+
if (this._documentViaCamera)
|
|
1290
|
+
this._prewarmCamera();
|
|
1291
|
+
// Step badge — pairs with DocumentCapture.showPreview's "Step 1 of 2"
|
|
1292
|
+
// badge shown right after capture, so this doesn't read as unexplained
|
|
1293
|
+
// repetition: that screen checked photo clarity, this one checks the
|
|
1294
|
+
// OCR-extracted data.
|
|
1295
|
+
const stepBadge = document.createElement("div");
|
|
1296
|
+
stepBadge.style.cssText = `
|
|
1297
|
+
display:inline-flex;align-items:center;gap:5px;
|
|
1298
|
+
padding:3px 11px;border-radius:${theme_1.RADIUS.pill}px;
|
|
1299
|
+
font-size:10.5px;font-weight:600;letter-spacing:0.2px;
|
|
1300
|
+
color:${this.theme.primary};background:${this.theme.primary}15;border:1px solid ${this.theme.primary}30;
|
|
1301
|
+
`;
|
|
1302
|
+
stepBadge.textContent = "STEP 2 OF 2 · CHECK WHAT WE READ";
|
|
1303
|
+
container.appendChild(stepBadge);
|
|
1309
1304
|
const iconWrap = document.createElement("div");
|
|
1310
|
-
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;
|
|
1311
|
-
iconWrap.
|
|
1305
|
+
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;color:${this.theme.primary};`;
|
|
1306
|
+
iconWrap.innerHTML = (0, icons_1.icon)("document", 28);
|
|
1312
1307
|
container.appendChild(iconWrap);
|
|
1313
1308
|
const title = document.createElement("h2");
|
|
1314
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
1309
|
+
title.style.cssText = `color:${this.theme.text};font-size:${theme_1.TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1315
1310
|
title.textContent = "Are these your details?";
|
|
1316
1311
|
container.appendChild(title);
|
|
1317
1312
|
const sub = document.createElement("p");
|
|
@@ -1403,19 +1398,10 @@ class SmartComplyFlow {
|
|
|
1403
1398
|
// ── W6+W7+W8: OCR Gate (document verification) ───────────────────
|
|
1404
1399
|
renderOcrGate(container) {
|
|
1405
1400
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:14px;padding:20px 0;text-align:center;";
|
|
1406
|
-
|
|
1407
|
-
spinnerWrap.style.cssText = "position:relative;width:52px;height:52px;flex-shrink:0;";
|
|
1408
|
-
const ring = document.createElement("div");
|
|
1409
|
-
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;`;
|
|
1410
|
-
const centre = document.createElement("div");
|
|
1411
|
-
centre.style.cssText = "position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;";
|
|
1412
|
-
centre.textContent = "📄";
|
|
1413
|
-
spinnerWrap.appendChild(ring);
|
|
1414
|
-
spinnerWrap.appendChild(centre);
|
|
1415
|
-
container.appendChild(spinnerWrap);
|
|
1401
|
+
container.appendChild((0, spinner_1.renderSpinner)(this.theme, { size: 52, icon: (0, icons_1.icon)("document", 20) }));
|
|
1416
1402
|
const statusEl = document.createElement("div");
|
|
1417
1403
|
statusEl.setAttribute("aria-live", "polite");
|
|
1418
|
-
statusEl.style.cssText = `color:${this.theme.text};font-size
|
|
1404
|
+
statusEl.style.cssText = `color:${this.theme.text};font-size:${theme_1.TYPE.base}px;font-weight:600;`;
|
|
1419
1405
|
statusEl.textContent = "Reading your document…";
|
|
1420
1406
|
container.appendChild(statusEl);
|
|
1421
1407
|
const subEl = document.createElement("div");
|
|
@@ -1516,7 +1502,7 @@ class SmartComplyFlow {
|
|
|
1516
1502
|
icon.textContent = "📅";
|
|
1517
1503
|
container.appendChild(icon);
|
|
1518
1504
|
const t = document.createElement("h2");
|
|
1519
|
-
t.style.cssText = `color:${this.theme.text};font-size
|
|
1505
|
+
t.style.cssText = `color:${this.theme.text};font-size:${theme_1.TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1520
1506
|
t.textContent = "Document Expired";
|
|
1521
1507
|
container.appendChild(t);
|
|
1522
1508
|
const d = document.createElement("p");
|
|
@@ -1542,7 +1528,7 @@ class SmartComplyFlow {
|
|
|
1542
1528
|
icon.textContent = "🔍";
|
|
1543
1529
|
container.appendChild(icon);
|
|
1544
1530
|
const t = document.createElement("h2");
|
|
1545
|
-
t.style.cssText = `color:${this.theme.text};font-size
|
|
1531
|
+
t.style.cssText = `color:${this.theme.text};font-size:${theme_1.TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1546
1532
|
t.textContent = "Document Photo Unclear";
|
|
1547
1533
|
container.appendChild(t);
|
|
1548
1534
|
const msg = reason === "image_too_blurry" ? "Your document photo is too blurry. Please retake it in good lighting with a steady hand."
|
|
@@ -1579,11 +1565,11 @@ class SmartComplyFlow {
|
|
|
1579
1565
|
verificationResult: this.verificationResult || undefined,
|
|
1580
1566
|
});
|
|
1581
1567
|
const iconWrap = document.createElement("div");
|
|
1582
|
-
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;
|
|
1583
|
-
iconWrap.
|
|
1568
|
+
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;color:${this.theme.success};animation:sc-pop 0.4s ease;`;
|
|
1569
|
+
iconWrap.innerHTML = (0, icons_1.icon)("check", 36);
|
|
1584
1570
|
container.appendChild(iconWrap);
|
|
1585
1571
|
const title = document.createElement("h2");
|
|
1586
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
1572
|
+
title.style.cssText = `color:${this.theme.text};font-size:${theme_1.TYPE.headingLg}px;font-weight:700;margin:0;`;
|
|
1587
1573
|
title.textContent = "You're all done!";
|
|
1588
1574
|
container.appendChild(title);
|
|
1589
1575
|
const desc = document.createElement("p");
|
|
@@ -1610,7 +1596,7 @@ class SmartComplyFlow {
|
|
|
1610
1596
|
icon.textContent = "⚠️";
|
|
1611
1597
|
container.appendChild(icon);
|
|
1612
1598
|
const t = document.createElement("h2");
|
|
1613
|
-
t.style.cssText = `color:${this.theme.text};font-size
|
|
1599
|
+
t.style.cssText = `color:${this.theme.text};font-size:${theme_1.TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1614
1600
|
t.textContent = "Unable to Complete Verification";
|
|
1615
1601
|
container.appendChild(t);
|
|
1616
1602
|
const d = document.createElement("p");
|
|
@@ -1645,6 +1631,7 @@ class SmartComplyFlow {
|
|
|
1645
1631
|
// below so compression only happens once.
|
|
1646
1632
|
this.documentBlob = await _compressImage(result.front, 1600, 0.85);
|
|
1647
1633
|
this.documentBackBlob = result.back ? await _compressImage(result.back, 1600, 0.85) : null;
|
|
1634
|
+
this._documentViaCamera = result.viaCamera;
|
|
1648
1635
|
// Process the front image — pass the already-compressed blob
|
|
1649
1636
|
await this.processDocumentBlob(this.documentBlob, captureContainer, container);
|
|
1650
1637
|
}
|
|
@@ -1665,15 +1652,12 @@ class SmartComplyFlow {
|
|
|
1665
1652
|
}
|
|
1666
1653
|
this.documentBlob = blob;
|
|
1667
1654
|
// Show scanning state
|
|
1668
|
-
captureContainer.innerHTML =
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;">🔍</div>
|
|
1673
|
-
</div>
|
|
1655
|
+
captureContainer.innerHTML = "";
|
|
1656
|
+
captureContainer.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:14px;padding:28px 20px;";
|
|
1657
|
+
captureContainer.appendChild((0, spinner_1.renderSpinner)(this.theme, { size: 52, icon: (0, icons_1.icon)("search", 20) }));
|
|
1658
|
+
captureContainer.insertAdjacentHTML("beforeend", `
|
|
1674
1659
|
<div style="color:${this.theme.text};font-size:14px;font-weight:600;">Scanning document...</div>
|
|
1675
|
-
<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
|
|
1676
|
-
</div>`;
|
|
1660
|
+
<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>`);
|
|
1677
1661
|
// Create liveness entry with document.
|
|
1678
1662
|
// Use the first collected field value as identifier when available
|
|
1679
1663
|
// (document flow has no data-verification step, so collectedFields is
|
|
@@ -1737,15 +1721,12 @@ class SmartComplyFlow {
|
|
|
1737
1721
|
console.log(`Retrying document processing (attempt ${retryCount}/${maxRetries})`);
|
|
1738
1722
|
// Show retry message
|
|
1739
1723
|
if (captureContainer) {
|
|
1740
|
-
captureContainer.innerHTML =
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;">🔄</div>
|
|
1745
|
-
</div>
|
|
1724
|
+
captureContainer.innerHTML = "";
|
|
1725
|
+
captureContainer.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:16px;padding:28px 20px;text-align:center;";
|
|
1726
|
+
captureContainer.appendChild((0, spinner_1.renderSpinner)(this.theme, { size: 52, icon: (0, icons_1.icon)("refresh", 20) }));
|
|
1727
|
+
captureContainer.insertAdjacentHTML("beforeend", `
|
|
1746
1728
|
<div style="color:${this.theme.text};font-size:14px;font-weight:600;">Retrying...</div>
|
|
1747
|
-
<div style="color:${this.theme.textSecondary};font-size:12px;max-width:240px;line-height:1.5;">Attempt ${retryCount} of ${maxRetries}</div
|
|
1748
|
-
</div>`;
|
|
1729
|
+
<div style="color:${this.theme.textSecondary};font-size:12px;max-width:240px;line-height:1.5;">Attempt ${retryCount} of ${maxRetries}</div>`);
|
|
1749
1730
|
}
|
|
1750
1731
|
// Wait before retry
|
|
1751
1732
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
@@ -1807,7 +1788,7 @@ class SmartComplyFlow {
|
|
|
1807
1788
|
const retryBtn = document.createElement("button");
|
|
1808
1789
|
retryBtn.textContent = "Try Again";
|
|
1809
1790
|
retryBtn.setAttribute("aria-label", "Retake document photo");
|
|
1810
|
-
retryBtn.style.cssText = `margin-top:8px;padding:12px 24px;border-radius
|
|
1791
|
+
retryBtn.style.cssText = `margin-top:8px;padding:12px 24px;border-radius:${theme_1.RADIUS.sm}px;background:${this.theme.primary};color:#fff;border:none;font-size:14px;font-weight:600;cursor:pointer;`;
|
|
1811
1792
|
retryBtn.addEventListener("click", () => this.showStep("document_capture"));
|
|
1812
1793
|
wrap.appendChild(retryBtn);
|
|
1813
1794
|
}
|
|
@@ -1868,6 +1849,12 @@ class SmartComplyFlow {
|
|
|
1868
1849
|
: "liveness_only",
|
|
1869
1850
|
// B4: pass pre-warmed stream so camera.open() is skipped
|
|
1870
1851
|
prewarmedStream: this._prewarmedStream || undefined,
|
|
1852
|
+
colors: {
|
|
1853
|
+
primary: this.theme.primary,
|
|
1854
|
+
success: this.theme.success,
|
|
1855
|
+
error: this.theme.error,
|
|
1856
|
+
warning: this.theme.warning,
|
|
1857
|
+
},
|
|
1871
1858
|
}, ["BLINK"], this.livenessEntryId || undefined)
|
|
1872
1859
|
.then((result) => {
|
|
1873
1860
|
// W11: After submit, end user is done — show "You're all done" screen.
|
|
@@ -1909,14 +1896,14 @@ class SmartComplyFlow {
|
|
|
1909
1896
|
// /v1/sdk/liveness/submit/) are an operator-facing problem, not something
|
|
1910
1897
|
// the end user can act on — never show "wallet"/"balance" language to them.
|
|
1911
1898
|
const isBillingErr = /wallet|balance|insufficient.*fund|payment.*required/i.test(message);
|
|
1912
|
-
const
|
|
1913
|
-
: isNetworkErr ? "
|
|
1914
|
-
: isAuthErr ? "
|
|
1915
|
-
: isDocQuality ? "
|
|
1916
|
-
: isExpiredDoc ? "
|
|
1917
|
-
: isFaceMatch ? "
|
|
1918
|
-
: isBillingErr ? "
|
|
1919
|
-
: "
|
|
1899
|
+
const errorIconName = isCameraErr ? "camera"
|
|
1900
|
+
: isNetworkErr ? "network"
|
|
1901
|
+
: isAuthErr ? "clock"
|
|
1902
|
+
: isDocQuality ? "search"
|
|
1903
|
+
: isExpiredDoc ? "calendar"
|
|
1904
|
+
: isFaceMatch ? "face"
|
|
1905
|
+
: isBillingErr ? "warning"
|
|
1906
|
+
: "close";
|
|
1920
1907
|
const errorTitle = isCameraErr ? "Camera Access Required"
|
|
1921
1908
|
: isNetworkErr ? "Connection Problem"
|
|
1922
1909
|
: isAuthErr ? "Session Expired"
|
|
@@ -1945,14 +1932,14 @@ class SmartComplyFlow {
|
|
|
1945
1932
|
iconWrap.style.cssText = `
|
|
1946
1933
|
width:72px;height:72px;border-radius:50%;
|
|
1947
1934
|
display:flex;align-items:center;justify-content:center;
|
|
1948
|
-
|
|
1935
|
+
color:${this.theme.error};
|
|
1949
1936
|
background:${this.theme.errorBg};
|
|
1950
1937
|
border:3px solid ${this.theme.error};
|
|
1951
1938
|
`;
|
|
1952
|
-
iconWrap.
|
|
1939
|
+
iconWrap.innerHTML = (0, icons_1.icon)(errorIconName, 28);
|
|
1953
1940
|
wrapper.appendChild(iconWrap);
|
|
1954
1941
|
const title = document.createElement("h2");
|
|
1955
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
1942
|
+
title.style.cssText = `color:${this.theme.text};font-size:${theme_1.TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1956
1943
|
title.textContent = errorTitle;
|
|
1957
1944
|
wrapper.appendChild(title);
|
|
1958
1945
|
const desc = document.createElement("p");
|
|
@@ -1991,7 +1978,7 @@ class SmartComplyFlow {
|
|
|
1991
1978
|
this.headerBackBtn.innerHTML = "←";
|
|
1992
1979
|
this.headerBackBtn.setAttribute("aria-label", "Go back to previous step");
|
|
1993
1980
|
this.headerBackBtn.style.cssText = `
|
|
1994
|
-
width:30px;height:30px;border-radius
|
|
1981
|
+
width:30px;height:30px;border-radius:${theme_1.RADIUS.sm}px;flex-shrink:0;
|
|
1995
1982
|
display:none;align-items:center;justify-content:center;
|
|
1996
1983
|
border:1.5px solid ${this.theme.border};cursor:pointer;
|
|
1997
1984
|
font-size:16px;line-height:1;
|
|
@@ -2049,7 +2036,7 @@ class SmartComplyFlow {
|
|
|
2049
2036
|
closeBtn.innerHTML = "✕";
|
|
2050
2037
|
closeBtn.setAttribute("aria-label", "Close identity verification");
|
|
2051
2038
|
closeBtn.style.cssText = `
|
|
2052
|
-
width:32px;height:32px;border-radius
|
|
2039
|
+
width:32px;height:32px;border-radius:${theme_1.RADIUS.sm}px;flex-shrink:0;
|
|
2053
2040
|
display:flex;align-items:center;justify-content:center;
|
|
2054
2041
|
border:none;cursor:pointer;font-size:16px;
|
|
2055
2042
|
background:${this.theme.shimmer};color:${this.theme.textMuted};
|
|
@@ -2086,7 +2073,7 @@ class SmartComplyFlow {
|
|
|
2086
2073
|
createStepTitle(text) {
|
|
2087
2074
|
const el = document.createElement("h3");
|
|
2088
2075
|
el.style.cssText = `
|
|
2089
|
-
color:${this.theme.text};font-size
|
|
2076
|
+
color:${this.theme.text};font-size:${theme_1.TYPE.heading}px;font-weight:700;
|
|
2090
2077
|
margin:0;
|
|
2091
2078
|
`;
|
|
2092
2079
|
el.textContent = text;
|
|
@@ -2096,7 +2083,7 @@ class SmartComplyFlow {
|
|
|
2096
2083
|
const card = document.createElement("button");
|
|
2097
2084
|
card.setAttribute("aria-label", subtitle ? `${title}: ${subtitle}` : title);
|
|
2098
2085
|
card.style.cssText = `
|
|
2099
|
-
width:100%;padding:13px 16px;border-radius
|
|
2086
|
+
width:100%;padding:13px 16px;border-radius:${theme_1.RADIUS.md}px;
|
|
2100
2087
|
background:${this.theme.cardBg};
|
|
2101
2088
|
border:2px solid ${this.theme.border};
|
|
2102
2089
|
cursor:pointer;text-align:left;
|
|
@@ -2136,7 +2123,7 @@ class SmartComplyFlow {
|
|
|
2136
2123
|
const btn = document.createElement("button");
|
|
2137
2124
|
btn.textContent = text;
|
|
2138
2125
|
btn.style.cssText = `
|
|
2139
|
-
width:100%;padding:14px;border-radius
|
|
2126
|
+
width:100%;padding:14px;border-radius:${theme_1.RADIUS.md}px;
|
|
2140
2127
|
font-size:15px;font-weight:600;
|
|
2141
2128
|
background:${this.theme.primary};color:#fff;
|
|
2142
2129
|
border:none;cursor:pointer;
|
|
@@ -2157,7 +2144,7 @@ class SmartComplyFlow {
|
|
|
2157
2144
|
const btn = document.createElement("button");
|
|
2158
2145
|
btn.textContent = text;
|
|
2159
2146
|
btn.style.cssText = `
|
|
2160
|
-
width:100%;padding:12px;border-radius
|
|
2147
|
+
width:100%;padding:12px;border-radius:${theme_1.RADIUS.md}px;
|
|
2161
2148
|
font-size:14px;font-weight:500;
|
|
2162
2149
|
background:transparent;color:${this.theme.textSecondary};
|
|
2163
2150
|
border:none;cursor:pointer;
|
|
@@ -2295,9 +2282,6 @@ class SmartComplyFlow {
|
|
|
2295
2282
|
const style = document.createElement("style");
|
|
2296
2283
|
style.id = "sc-flow-styles";
|
|
2297
2284
|
style.textContent = `
|
|
2298
|
-
@keyframes sc-spin {
|
|
2299
|
-
to { transform: rotate(360deg); }
|
|
2300
|
-
}
|
|
2301
2285
|
@keyframes sc-pop {
|
|
2302
2286
|
0% { transform: scale(0.8); opacity: 0; }
|
|
2303
2287
|
50% { transform: scale(1.05); }
|