smartcomply-web-sdk 1.0.62 → 1.0.63
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 +19 -1
- package/dist/esm/flow/DocumentCapture.d.ts.map +1 -1
- package/dist/esm/flow/DocumentCapture.js +144 -77
- package/dist/esm/flow/DocumentCapture.js.map +1 -1
- package/dist/esm/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/esm/flow/SmartComplyFlow.js +76 -103
- 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 +19 -1
- package/dist/flow/DocumentCapture.d.ts.map +1 -1
- package/dist/flow/DocumentCapture.js +144 -77
- package/dist/flow/DocumentCapture.js.map +1 -1
- package/dist/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/flow/SmartComplyFlow.js +75 -102
- 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 +316 -202
- package/dist/smartcomply.browser.js.map +4 -4
- package/package.json +1 -1
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { SmartComply } from "../client/Smartcomply";
|
|
2
|
-
import { getTheme } from "./theme";
|
|
2
|
+
import { getTheme, TYPE, RADIUS } from "./theme";
|
|
3
3
|
import { DocumentCapture } from "./DocumentCapture";
|
|
4
4
|
import { collectDeviceMetadata } from "../utils/device";
|
|
5
5
|
import { requiresBackSide } from "../utils/documentRules";
|
|
6
|
+
import { icon } from "./icons";
|
|
7
|
+
import { renderSpinner, renderInlineSpinner } from "./spinner";
|
|
6
8
|
const STEP_ORDER = [
|
|
7
9
|
"loading",
|
|
8
10
|
"welcome",
|
|
@@ -226,18 +228,6 @@ function _formatDocType(code) {
|
|
|
226
228
|
}
|
|
227
229
|
// SmartComplyFlow
|
|
228
230
|
// ─────────────────────────────────────────────────────────────────────
|
|
229
|
-
// Add CSS animation keyframes for spin animations
|
|
230
|
-
const style = document.createElement('style');
|
|
231
|
-
style.textContent = `
|
|
232
|
-
@keyframes sc-spin {
|
|
233
|
-
0% { transform: rotate(0deg); }
|
|
234
|
-
100% { transform: rotate(360deg); }
|
|
235
|
-
}
|
|
236
|
-
`;
|
|
237
|
-
if (!document.head.querySelector('style[data-sc-animations]')) {
|
|
238
|
-
style.setAttribute('data-sc-animations', 'true');
|
|
239
|
-
document.head.appendChild(style);
|
|
240
|
-
}
|
|
241
231
|
export class SmartComplyFlow {
|
|
242
232
|
constructor(options) {
|
|
243
233
|
this.theme = getTheme("default");
|
|
@@ -609,27 +599,9 @@ export class SmartComplyFlow {
|
|
|
609
599
|
// ── Loading ─────────────────────────────────────────────────────
|
|
610
600
|
renderLoading(container) {
|
|
611
601
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:300px;gap:16px;";
|
|
612
|
-
|
|
613
|
-
spinnerWrap.style.cssText = "position:relative;width:60px;height:60px;flex-shrink:0;";
|
|
614
|
-
const ring = document.createElement("div");
|
|
615
|
-
ring.style.cssText = `
|
|
616
|
-
position:absolute;inset:0;border-radius:50%;
|
|
617
|
-
border:3px solid ${this.theme.border};
|
|
618
|
-
border-top-color:${this.theme.primary};
|
|
619
|
-
animation:sc-spin 0.9s linear infinite;
|
|
620
|
-
`;
|
|
621
|
-
const centre = document.createElement("div");
|
|
622
|
-
centre.style.cssText = `
|
|
623
|
-
position:absolute;inset:0;
|
|
624
|
-
display:flex;align-items:center;justify-content:center;
|
|
625
|
-
font-size:22px;
|
|
626
|
-
`;
|
|
627
|
-
centre.textContent = "\uD83D\uDEE1\uFE0F";
|
|
628
|
-
spinnerWrap.appendChild(ring);
|
|
629
|
-
spinnerWrap.appendChild(centre);
|
|
630
|
-
container.appendChild(spinnerWrap);
|
|
602
|
+
container.appendChild(renderSpinner(this.theme, { size: 60, icon: icon("shield", 22) }));
|
|
631
603
|
const label = document.createElement("div");
|
|
632
|
-
label.style.cssText = `color:${this.theme.text};font-size
|
|
604
|
+
label.style.cssText = `color:${this.theme.text};font-size:${TYPE.base}px;font-weight:600;`;
|
|
633
605
|
label.textContent = "Setting up secure session";
|
|
634
606
|
container.appendChild(label);
|
|
635
607
|
const sub = document.createElement("div");
|
|
@@ -648,11 +620,11 @@ export class SmartComplyFlow {
|
|
|
648
620
|
iconWrap.style.cssText = `
|
|
649
621
|
width:50px;height:50px;border-radius:14px;
|
|
650
622
|
display:flex;align-items:center;justify-content:center;
|
|
651
|
-
|
|
623
|
+
color:${this.theme.primary};
|
|
652
624
|
background:linear-gradient(135deg,${this.theme.primary}22,${this.theme.primaryGlow});
|
|
653
625
|
border:1.5px solid ${this.theme.primary}33;
|
|
654
626
|
`;
|
|
655
|
-
iconWrap.
|
|
627
|
+
iconWrap.innerHTML = icon(isDocFlow ? "id-card" : "shield", 24);
|
|
656
628
|
topRow.appendChild(iconWrap);
|
|
657
629
|
const badge = document.createElement("div");
|
|
658
630
|
badge.style.cssText = `
|
|
@@ -671,7 +643,7 @@ export class SmartComplyFlow {
|
|
|
671
643
|
titleWrap.style.cssText = "display:flex;flex-direction:column;gap:5px;";
|
|
672
644
|
const title = document.createElement("h2");
|
|
673
645
|
title.style.cssText = `
|
|
674
|
-
color:${this.theme.text};font-size
|
|
646
|
+
color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;
|
|
675
647
|
margin:0;line-height:1.2;
|
|
676
648
|
`;
|
|
677
649
|
// W2: Use client brand name in title
|
|
@@ -705,7 +677,7 @@ export class SmartComplyFlow {
|
|
|
705
677
|
const stepsWrap = document.createElement("div");
|
|
706
678
|
stepsWrap.style.cssText = `
|
|
707
679
|
width:100%;display:flex;flex-direction:column;gap:0;
|
|
708
|
-
border-radius
|
|
680
|
+
border-radius:${RADIUS.md}px;overflow:hidden;
|
|
709
681
|
border:1.5px solid ${this.theme.border};
|
|
710
682
|
`;
|
|
711
683
|
steps.forEach((step, i) => {
|
|
@@ -718,7 +690,7 @@ export class SmartComplyFlow {
|
|
|
718
690
|
`;
|
|
719
691
|
const iconEl = document.createElement("div");
|
|
720
692
|
iconEl.style.cssText = `
|
|
721
|
-
width:28px;height:28px;border-radius
|
|
693
|
+
width:28px;height:28px;border-radius:${RADIUS.sm}px;flex-shrink:0;
|
|
722
694
|
display:flex;align-items:center;justify-content:center;
|
|
723
695
|
font-size:13px;
|
|
724
696
|
background:${this.theme.primary}12;
|
|
@@ -946,7 +918,7 @@ export class SmartComplyFlow {
|
|
|
946
918
|
// Dropdown field
|
|
947
919
|
const select = document.createElement("select");
|
|
948
920
|
select.style.cssText = `
|
|
949
|
-
width:100%;padding:13px 16px;border-radius
|
|
921
|
+
width:100%;padding:13px 16px;border-radius:${RADIUS.md}px;
|
|
950
922
|
font-size:15px;
|
|
951
923
|
background:${this.theme.inputBg};
|
|
952
924
|
color:${this.theme.text};
|
|
@@ -981,7 +953,7 @@ export class SmartComplyFlow {
|
|
|
981
953
|
fileInput.type = "file";
|
|
982
954
|
fileInput.accept = "image/*";
|
|
983
955
|
fileInput.style.cssText = `
|
|
984
|
-
width:100%;padding:12px 16px;border-radius
|
|
956
|
+
width:100%;padding:12px 16px;border-radius:${RADIUS.md}px;
|
|
985
957
|
font-size:14px;font-weight:500;
|
|
986
958
|
background:${this.theme.inputBg};
|
|
987
959
|
color:${this.theme.text};
|
|
@@ -1025,7 +997,7 @@ export class SmartComplyFlow {
|
|
|
1025
997
|
if (rule?.numeric)
|
|
1026
998
|
input.inputMode = "numeric";
|
|
1027
999
|
input.style.cssText = `
|
|
1028
|
-
width:100%;padding:14px 16px;border-radius
|
|
1000
|
+
width:100%;padding:14px 16px;border-radius:${RADIUS.md}px;
|
|
1029
1001
|
font-size:16px;font-weight:500;
|
|
1030
1002
|
background:${this.theme.inputBg};
|
|
1031
1003
|
color:${this.theme.text};
|
|
@@ -1087,7 +1059,7 @@ export class SmartComplyFlow {
|
|
|
1087
1059
|
errorEl.id = "sc-id-error";
|
|
1088
1060
|
errorEl.style.cssText = `
|
|
1089
1061
|
color:${this.theme.error};font-size:13px;display:none;
|
|
1090
|
-
padding:8px 12px;border-radius
|
|
1062
|
+
padding:8px 12px;border-radius:${RADIUS.sm}px;background:${this.theme.errorBg};
|
|
1091
1063
|
`;
|
|
1092
1064
|
container.appendChild(errorEl);
|
|
1093
1065
|
// Submit
|
|
@@ -1108,7 +1080,7 @@ export class SmartComplyFlow {
|
|
|
1108
1080
|
};
|
|
1109
1081
|
submitBtn.addEventListener("click", async () => {
|
|
1110
1082
|
submitBtn.disabled = true;
|
|
1111
|
-
submitBtn.innerHTML = `<span style="display:inline-flex;align-items:center;justify-content:center;gap:8px;"
|
|
1083
|
+
submitBtn.innerHTML = `<span style="display:inline-flex;align-items:center;justify-content:center;gap:8px;">${renderInlineSpinner("#fff", 13)}Verifying...</span>`;
|
|
1112
1084
|
errorEl.style.display = "none";
|
|
1113
1085
|
try {
|
|
1114
1086
|
this.verificationResult = await this.sdk.onboarding.verify({
|
|
@@ -1235,11 +1207,11 @@ export class SmartComplyFlow {
|
|
|
1235
1207
|
// W13: Pre-warm camera silently while user reads this screen
|
|
1236
1208
|
this._prewarmCamera();
|
|
1237
1209
|
const iconWrap = document.createElement("div");
|
|
1238
|
-
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;
|
|
1239
|
-
iconWrap.
|
|
1210
|
+
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};`;
|
|
1211
|
+
iconWrap.innerHTML = icon("shield", 28);
|
|
1240
1212
|
container.appendChild(iconWrap);
|
|
1241
1213
|
const title = document.createElement("h2");
|
|
1242
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
1214
|
+
title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1243
1215
|
title.textContent = this._ivsName ? `Is this you?` : "Identity Confirmed";
|
|
1244
1216
|
container.appendChild(title);
|
|
1245
1217
|
if (this._ivsName) {
|
|
@@ -1303,12 +1275,25 @@ export class SmartComplyFlow {
|
|
|
1303
1275
|
}
|
|
1304
1276
|
// W13: Pre-warm camera while user reads
|
|
1305
1277
|
this._prewarmCamera();
|
|
1278
|
+
// Step badge — pairs with DocumentCapture.showPreview's "Step 1 of 2"
|
|
1279
|
+
// badge shown right after capture, so this doesn't read as unexplained
|
|
1280
|
+
// repetition: that screen checked photo clarity, this one checks the
|
|
1281
|
+
// OCR-extracted data.
|
|
1282
|
+
const stepBadge = document.createElement("div");
|
|
1283
|
+
stepBadge.style.cssText = `
|
|
1284
|
+
display:inline-flex;align-items:center;gap:5px;
|
|
1285
|
+
padding:3px 11px;border-radius:${RADIUS.pill}px;
|
|
1286
|
+
font-size:10.5px;font-weight:600;letter-spacing:0.2px;
|
|
1287
|
+
color:${this.theme.primary};background:${this.theme.primary}15;border:1px solid ${this.theme.primary}30;
|
|
1288
|
+
`;
|
|
1289
|
+
stepBadge.textContent = "STEP 2 OF 2 · CHECK WHAT WE READ";
|
|
1290
|
+
container.appendChild(stepBadge);
|
|
1306
1291
|
const iconWrap = document.createElement("div");
|
|
1307
|
-
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;
|
|
1308
|
-
iconWrap.
|
|
1292
|
+
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};`;
|
|
1293
|
+
iconWrap.innerHTML = icon("document", 28);
|
|
1309
1294
|
container.appendChild(iconWrap);
|
|
1310
1295
|
const title = document.createElement("h2");
|
|
1311
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
1296
|
+
title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1312
1297
|
title.textContent = "Are these your details?";
|
|
1313
1298
|
container.appendChild(title);
|
|
1314
1299
|
const sub = document.createElement("p");
|
|
@@ -1400,19 +1385,10 @@ export class SmartComplyFlow {
|
|
|
1400
1385
|
// ── W6+W7+W8: OCR Gate (document verification) ───────────────────
|
|
1401
1386
|
renderOcrGate(container) {
|
|
1402
1387
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:14px;padding:20px 0;text-align:center;";
|
|
1403
|
-
|
|
1404
|
-
spinnerWrap.style.cssText = "position:relative;width:52px;height:52px;flex-shrink:0;";
|
|
1405
|
-
const ring = document.createElement("div");
|
|
1406
|
-
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;`;
|
|
1407
|
-
const centre = document.createElement("div");
|
|
1408
|
-
centre.style.cssText = "position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;";
|
|
1409
|
-
centre.textContent = "📄";
|
|
1410
|
-
spinnerWrap.appendChild(ring);
|
|
1411
|
-
spinnerWrap.appendChild(centre);
|
|
1412
|
-
container.appendChild(spinnerWrap);
|
|
1388
|
+
container.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("document", 20) }));
|
|
1413
1389
|
const statusEl = document.createElement("div");
|
|
1414
1390
|
statusEl.setAttribute("aria-live", "polite");
|
|
1415
|
-
statusEl.style.cssText = `color:${this.theme.text};font-size
|
|
1391
|
+
statusEl.style.cssText = `color:${this.theme.text};font-size:${TYPE.base}px;font-weight:600;`;
|
|
1416
1392
|
statusEl.textContent = "Reading your document…";
|
|
1417
1393
|
container.appendChild(statusEl);
|
|
1418
1394
|
const subEl = document.createElement("div");
|
|
@@ -1513,7 +1489,7 @@ export class SmartComplyFlow {
|
|
|
1513
1489
|
icon.textContent = "📅";
|
|
1514
1490
|
container.appendChild(icon);
|
|
1515
1491
|
const t = document.createElement("h2");
|
|
1516
|
-
t.style.cssText = `color:${this.theme.text};font-size
|
|
1492
|
+
t.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1517
1493
|
t.textContent = "Document Expired";
|
|
1518
1494
|
container.appendChild(t);
|
|
1519
1495
|
const d = document.createElement("p");
|
|
@@ -1539,7 +1515,7 @@ export class SmartComplyFlow {
|
|
|
1539
1515
|
icon.textContent = "🔍";
|
|
1540
1516
|
container.appendChild(icon);
|
|
1541
1517
|
const t = document.createElement("h2");
|
|
1542
|
-
t.style.cssText = `color:${this.theme.text};font-size
|
|
1518
|
+
t.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1543
1519
|
t.textContent = "Document Photo Unclear";
|
|
1544
1520
|
container.appendChild(t);
|
|
1545
1521
|
const msg = reason === "image_too_blurry" ? "Your document photo is too blurry. Please retake it in good lighting with a steady hand."
|
|
@@ -1576,11 +1552,11 @@ export class SmartComplyFlow {
|
|
|
1576
1552
|
verificationResult: this.verificationResult || undefined,
|
|
1577
1553
|
});
|
|
1578
1554
|
const iconWrap = document.createElement("div");
|
|
1579
|
-
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;
|
|
1580
|
-
iconWrap.
|
|
1555
|
+
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;`;
|
|
1556
|
+
iconWrap.innerHTML = icon("check", 36);
|
|
1581
1557
|
container.appendChild(iconWrap);
|
|
1582
1558
|
const title = document.createElement("h2");
|
|
1583
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
1559
|
+
title.style.cssText = `color:${this.theme.text};font-size:${TYPE.headingLg}px;font-weight:700;margin:0;`;
|
|
1584
1560
|
title.textContent = "You're all done!";
|
|
1585
1561
|
container.appendChild(title);
|
|
1586
1562
|
const desc = document.createElement("p");
|
|
@@ -1607,7 +1583,7 @@ export class SmartComplyFlow {
|
|
|
1607
1583
|
icon.textContent = "⚠️";
|
|
1608
1584
|
container.appendChild(icon);
|
|
1609
1585
|
const t = document.createElement("h2");
|
|
1610
|
-
t.style.cssText = `color:${this.theme.text};font-size
|
|
1586
|
+
t.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1611
1587
|
t.textContent = "Unable to Complete Verification";
|
|
1612
1588
|
container.appendChild(t);
|
|
1613
1589
|
const d = document.createElement("p");
|
|
@@ -1662,15 +1638,12 @@ export class SmartComplyFlow {
|
|
|
1662
1638
|
}
|
|
1663
1639
|
this.documentBlob = blob;
|
|
1664
1640
|
// Show scanning state
|
|
1665
|
-
captureContainer.innerHTML =
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;">🔍</div>
|
|
1670
|
-
</div>
|
|
1641
|
+
captureContainer.innerHTML = "";
|
|
1642
|
+
captureContainer.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:14px;padding:28px 20px;";
|
|
1643
|
+
captureContainer.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("search", 20) }));
|
|
1644
|
+
captureContainer.insertAdjacentHTML("beforeend", `
|
|
1671
1645
|
<div style="color:${this.theme.text};font-size:14px;font-weight:600;">Scanning document...</div>
|
|
1672
|
-
<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
|
|
1673
|
-
</div>`;
|
|
1646
|
+
<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>`);
|
|
1674
1647
|
// Create liveness entry with document.
|
|
1675
1648
|
// Use the first collected field value as identifier when available
|
|
1676
1649
|
// (document flow has no data-verification step, so collectedFields is
|
|
@@ -1734,15 +1707,12 @@ export class SmartComplyFlow {
|
|
|
1734
1707
|
console.log(`Retrying document processing (attempt ${retryCount}/${maxRetries})`);
|
|
1735
1708
|
// Show retry message
|
|
1736
1709
|
if (captureContainer) {
|
|
1737
|
-
captureContainer.innerHTML =
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;">🔄</div>
|
|
1742
|
-
</div>
|
|
1710
|
+
captureContainer.innerHTML = "";
|
|
1711
|
+
captureContainer.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:16px;padding:28px 20px;text-align:center;";
|
|
1712
|
+
captureContainer.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("refresh", 20) }));
|
|
1713
|
+
captureContainer.insertAdjacentHTML("beforeend", `
|
|
1743
1714
|
<div style="color:${this.theme.text};font-size:14px;font-weight:600;">Retrying...</div>
|
|
1744
|
-
<div style="color:${this.theme.textSecondary};font-size:12px;max-width:240px;line-height:1.5;">Attempt ${retryCount} of ${maxRetries}</div
|
|
1745
|
-
</div>`;
|
|
1715
|
+
<div style="color:${this.theme.textSecondary};font-size:12px;max-width:240px;line-height:1.5;">Attempt ${retryCount} of ${maxRetries}</div>`);
|
|
1746
1716
|
}
|
|
1747
1717
|
// Wait before retry
|
|
1748
1718
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
@@ -1804,7 +1774,7 @@ export class SmartComplyFlow {
|
|
|
1804
1774
|
const retryBtn = document.createElement("button");
|
|
1805
1775
|
retryBtn.textContent = "Try Again";
|
|
1806
1776
|
retryBtn.setAttribute("aria-label", "Retake document photo");
|
|
1807
|
-
retryBtn.style.cssText = `margin-top:8px;padding:12px 24px;border-radius
|
|
1777
|
+
retryBtn.style.cssText = `margin-top:8px;padding:12px 24px;border-radius:${RADIUS.sm}px;background:${this.theme.primary};color:#fff;border:none;font-size:14px;font-weight:600;cursor:pointer;`;
|
|
1808
1778
|
retryBtn.addEventListener("click", () => this.showStep("document_capture"));
|
|
1809
1779
|
wrap.appendChild(retryBtn);
|
|
1810
1780
|
}
|
|
@@ -1865,6 +1835,12 @@ export class SmartComplyFlow {
|
|
|
1865
1835
|
: "liveness_only",
|
|
1866
1836
|
// B4: pass pre-warmed stream so camera.open() is skipped
|
|
1867
1837
|
prewarmedStream: this._prewarmedStream || undefined,
|
|
1838
|
+
colors: {
|
|
1839
|
+
primary: this.theme.primary,
|
|
1840
|
+
success: this.theme.success,
|
|
1841
|
+
error: this.theme.error,
|
|
1842
|
+
warning: this.theme.warning,
|
|
1843
|
+
},
|
|
1868
1844
|
}, ["BLINK"], this.livenessEntryId || undefined)
|
|
1869
1845
|
.then((result) => {
|
|
1870
1846
|
// W11: After submit, end user is done — show "You're all done" screen.
|
|
@@ -1906,14 +1882,14 @@ export class SmartComplyFlow {
|
|
|
1906
1882
|
// /v1/sdk/liveness/submit/) are an operator-facing problem, not something
|
|
1907
1883
|
// the end user can act on — never show "wallet"/"balance" language to them.
|
|
1908
1884
|
const isBillingErr = /wallet|balance|insufficient.*fund|payment.*required/i.test(message);
|
|
1909
|
-
const
|
|
1910
|
-
: isNetworkErr ? "
|
|
1911
|
-
: isAuthErr ? "
|
|
1912
|
-
: isDocQuality ? "
|
|
1913
|
-
: isExpiredDoc ? "
|
|
1914
|
-
: isFaceMatch ? "
|
|
1915
|
-
: isBillingErr ? "
|
|
1916
|
-
: "
|
|
1885
|
+
const errorIconName = isCameraErr ? "camera"
|
|
1886
|
+
: isNetworkErr ? "network"
|
|
1887
|
+
: isAuthErr ? "clock"
|
|
1888
|
+
: isDocQuality ? "search"
|
|
1889
|
+
: isExpiredDoc ? "calendar"
|
|
1890
|
+
: isFaceMatch ? "face"
|
|
1891
|
+
: isBillingErr ? "warning"
|
|
1892
|
+
: "close";
|
|
1917
1893
|
const errorTitle = isCameraErr ? "Camera Access Required"
|
|
1918
1894
|
: isNetworkErr ? "Connection Problem"
|
|
1919
1895
|
: isAuthErr ? "Session Expired"
|
|
@@ -1942,14 +1918,14 @@ export class SmartComplyFlow {
|
|
|
1942
1918
|
iconWrap.style.cssText = `
|
|
1943
1919
|
width:72px;height:72px;border-radius:50%;
|
|
1944
1920
|
display:flex;align-items:center;justify-content:center;
|
|
1945
|
-
|
|
1921
|
+
color:${this.theme.error};
|
|
1946
1922
|
background:${this.theme.errorBg};
|
|
1947
1923
|
border:3px solid ${this.theme.error};
|
|
1948
1924
|
`;
|
|
1949
|
-
iconWrap.
|
|
1925
|
+
iconWrap.innerHTML = icon(errorIconName, 28);
|
|
1950
1926
|
wrapper.appendChild(iconWrap);
|
|
1951
1927
|
const title = document.createElement("h2");
|
|
1952
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
1928
|
+
title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
1953
1929
|
title.textContent = errorTitle;
|
|
1954
1930
|
wrapper.appendChild(title);
|
|
1955
1931
|
const desc = document.createElement("p");
|
|
@@ -1988,7 +1964,7 @@ export class SmartComplyFlow {
|
|
|
1988
1964
|
this.headerBackBtn.innerHTML = "←";
|
|
1989
1965
|
this.headerBackBtn.setAttribute("aria-label", "Go back to previous step");
|
|
1990
1966
|
this.headerBackBtn.style.cssText = `
|
|
1991
|
-
width:30px;height:30px;border-radius
|
|
1967
|
+
width:30px;height:30px;border-radius:${RADIUS.sm}px;flex-shrink:0;
|
|
1992
1968
|
display:none;align-items:center;justify-content:center;
|
|
1993
1969
|
border:1.5px solid ${this.theme.border};cursor:pointer;
|
|
1994
1970
|
font-size:16px;line-height:1;
|
|
@@ -2046,7 +2022,7 @@ export class SmartComplyFlow {
|
|
|
2046
2022
|
closeBtn.innerHTML = "✕";
|
|
2047
2023
|
closeBtn.setAttribute("aria-label", "Close identity verification");
|
|
2048
2024
|
closeBtn.style.cssText = `
|
|
2049
|
-
width:32px;height:32px;border-radius
|
|
2025
|
+
width:32px;height:32px;border-radius:${RADIUS.sm}px;flex-shrink:0;
|
|
2050
2026
|
display:flex;align-items:center;justify-content:center;
|
|
2051
2027
|
border:none;cursor:pointer;font-size:16px;
|
|
2052
2028
|
background:${this.theme.shimmer};color:${this.theme.textMuted};
|
|
@@ -2083,7 +2059,7 @@ export class SmartComplyFlow {
|
|
|
2083
2059
|
createStepTitle(text) {
|
|
2084
2060
|
const el = document.createElement("h3");
|
|
2085
2061
|
el.style.cssText = `
|
|
2086
|
-
color:${this.theme.text};font-size
|
|
2062
|
+
color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;
|
|
2087
2063
|
margin:0;
|
|
2088
2064
|
`;
|
|
2089
2065
|
el.textContent = text;
|
|
@@ -2093,7 +2069,7 @@ export class SmartComplyFlow {
|
|
|
2093
2069
|
const card = document.createElement("button");
|
|
2094
2070
|
card.setAttribute("aria-label", subtitle ? `${title}: ${subtitle}` : title);
|
|
2095
2071
|
card.style.cssText = `
|
|
2096
|
-
width:100%;padding:13px 16px;border-radius
|
|
2072
|
+
width:100%;padding:13px 16px;border-radius:${RADIUS.md}px;
|
|
2097
2073
|
background:${this.theme.cardBg};
|
|
2098
2074
|
border:2px solid ${this.theme.border};
|
|
2099
2075
|
cursor:pointer;text-align:left;
|
|
@@ -2133,7 +2109,7 @@ export class SmartComplyFlow {
|
|
|
2133
2109
|
const btn = document.createElement("button");
|
|
2134
2110
|
btn.textContent = text;
|
|
2135
2111
|
btn.style.cssText = `
|
|
2136
|
-
width:100%;padding:14px;border-radius
|
|
2112
|
+
width:100%;padding:14px;border-radius:${RADIUS.md}px;
|
|
2137
2113
|
font-size:15px;font-weight:600;
|
|
2138
2114
|
background:${this.theme.primary};color:#fff;
|
|
2139
2115
|
border:none;cursor:pointer;
|
|
@@ -2154,7 +2130,7 @@ export class SmartComplyFlow {
|
|
|
2154
2130
|
const btn = document.createElement("button");
|
|
2155
2131
|
btn.textContent = text;
|
|
2156
2132
|
btn.style.cssText = `
|
|
2157
|
-
width:100%;padding:12px;border-radius
|
|
2133
|
+
width:100%;padding:12px;border-radius:${RADIUS.md}px;
|
|
2158
2134
|
font-size:14px;font-weight:500;
|
|
2159
2135
|
background:transparent;color:${this.theme.textSecondary};
|
|
2160
2136
|
border:none;cursor:pointer;
|
|
@@ -2292,9 +2268,6 @@ export class SmartComplyFlow {
|
|
|
2292
2268
|
const style = document.createElement("style");
|
|
2293
2269
|
style.id = "sc-flow-styles";
|
|
2294
2270
|
style.textContent = `
|
|
2295
|
-
@keyframes sc-spin {
|
|
2296
|
-
to { transform: rotate(360deg); }
|
|
2297
|
-
}
|
|
2298
2271
|
@keyframes sc-pop {
|
|
2299
2272
|
0% { transform: scale(0.8); opacity: 0; }
|
|
2300
2273
|
50% { transform: scale(1.05); }
|