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
|
@@ -4672,8 +4672,14 @@ var SmartComplySDK = (() => {
|
|
|
4672
4672
|
`;
|
|
4673
4673
|
document.head.appendChild(s2);
|
|
4674
4674
|
}
|
|
4675
|
+
var DEFAULT_COLORS = {
|
|
4676
|
+
primary: "#3b82f6",
|
|
4677
|
+
success: "#22c55e",
|
|
4678
|
+
error: "#ef4444",
|
|
4679
|
+
warning: "#fbbf24"
|
|
4680
|
+
};
|
|
4675
4681
|
var LivenessUI = class {
|
|
4676
|
-
constructor() {
|
|
4682
|
+
constructor(colors) {
|
|
4677
4683
|
this.root = null;
|
|
4678
4684
|
this.videoEl = null;
|
|
4679
4685
|
this.instructionEl = null;
|
|
@@ -4687,6 +4693,7 @@ var SmartComplySDK = (() => {
|
|
|
4687
4693
|
this.scanStartMs = 0;
|
|
4688
4694
|
this.scanDurationMs = 0;
|
|
4689
4695
|
this.faceTracked = false;
|
|
4696
|
+
this.colors = { ...DEFAULT_COLORS, ...colors };
|
|
4690
4697
|
}
|
|
4691
4698
|
mount(container, challenge) {
|
|
4692
4699
|
injectLivenessKeyframes();
|
|
@@ -4761,7 +4768,7 @@ var SmartComplySDK = (() => {
|
|
|
4761
4768
|
confOval.setAttribute("rx", "64");
|
|
4762
4769
|
confOval.setAttribute("ry", "86");
|
|
4763
4770
|
confOval.setAttribute("fill", "none");
|
|
4764
|
-
confOval.setAttribute("stroke",
|
|
4771
|
+
confOval.setAttribute("stroke", this.colors.primary);
|
|
4765
4772
|
confOval.setAttribute("stroke-width", "2.5");
|
|
4766
4773
|
confOval.setAttribute("stroke-linecap", "round");
|
|
4767
4774
|
const circ = 2 * Math.PI * Math.sqrt((64 * 64 + 86 * 86) / 2);
|
|
@@ -4770,7 +4777,7 @@ var SmartComplySDK = (() => {
|
|
|
4770
4777
|
confOval.style.cssText = "transition:stroke-dashoffset 0.2s linear,stroke 0.3s ease;transform:rotate(-90deg);transform-origin:70px 90px;";
|
|
4771
4778
|
this.confidenceRingEl = confOval;
|
|
4772
4779
|
const bracketGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
4773
|
-
bracketGroup.setAttribute("stroke",
|
|
4780
|
+
bracketGroup.setAttribute("stroke", this.colors.primary);
|
|
4774
4781
|
bracketGroup.setAttribute("stroke-width", "3");
|
|
4775
4782
|
bracketGroup.setAttribute("stroke-linecap", "round");
|
|
4776
4783
|
bracketGroup.setAttribute("fill", "none");
|
|
@@ -4831,7 +4838,7 @@ var SmartComplySDK = (() => {
|
|
|
4831
4838
|
for (let i2 = 0; i2 < 3; i2++) {
|
|
4832
4839
|
const dot = document.createElement("div");
|
|
4833
4840
|
dot.style.cssText = `
|
|
4834
|
-
width:6px;height:6px;border-radius:50%;background
|
|
4841
|
+
width:6px;height:6px;border-radius:50%;background:${this.colors.primary};
|
|
4835
4842
|
animation:sc-scan-dot 1.1s ease-in-out ${i2 * 0.18}s infinite;
|
|
4836
4843
|
`;
|
|
4837
4844
|
this.dotsEl.appendChild(dot);
|
|
@@ -4870,7 +4877,7 @@ var SmartComplySDK = (() => {
|
|
|
4870
4877
|
const pct = this.scanDurationMs > 0 ? Math.min(1, elapsed / this.scanDurationMs) : 0;
|
|
4871
4878
|
const circ = 2 * Math.PI * Math.sqrt((64 * 64 + 86 * 86) / 2);
|
|
4872
4879
|
this.confidenceRingEl.setAttribute("stroke-dashoffset", `${circ * (1 - pct)}`);
|
|
4873
|
-
this.confidenceRingEl.setAttribute("stroke", livenessConfirmed ?
|
|
4880
|
+
this.confidenceRingEl.setAttribute("stroke", livenessConfirmed ? this.colors.success : this.colors.primary);
|
|
4874
4881
|
}
|
|
4875
4882
|
/**
|
|
4876
4883
|
* Reflects whether a face is currently detected in-frame — brightens the
|
|
@@ -4906,7 +4913,7 @@ var SmartComplySDK = (() => {
|
|
|
4906
4913
|
<div style="text-align:center;color:#fff;animation:sc-pop-in 0.35s ease;padding:24px;">
|
|
4907
4914
|
<div style="width:72px;height:72px;border-radius:50%;margin:0 auto 16px;display:flex;align-items:center;justify-content:center;font-size:32px;
|
|
4908
4915
|
background:${ok ? "rgba(34,197,94,0.2)" : "rgba(239,68,68,0.2)"};
|
|
4909
|
-
border:3px solid ${ok ?
|
|
4916
|
+
border:3px solid ${ok ? this.colors.success : this.colors.error};">
|
|
4910
4917
|
${ok ? "✓" : "✕"}
|
|
4911
4918
|
</div>
|
|
4912
4919
|
<div style="font-size:17px;font-weight:700;margin-bottom:8px;">${ok ? "Verification submitted" : "Submission failed"}</div>
|
|
@@ -4924,10 +4931,10 @@ var SmartComplySDK = (() => {
|
|
|
4924
4931
|
this.overlayEl.style.display = "flex";
|
|
4925
4932
|
this.overlayEl.innerHTML = `
|
|
4926
4933
|
<div style="text-align:center;color:#fff;animation:sc-pop-in 0.35s ease;padding:24px;">
|
|
4927
|
-
<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
|
|
4934
|
+
<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 ${this.colors.warning};">⏱</div>
|
|
4928
4935
|
<div style="font-size:17px;font-weight:700;margin-bottom:8px;">Time's Up</div>
|
|
4929
4936
|
<div style="font-size:12px;opacity:0.6;margin-bottom:18px;">We couldn't confirm liveness in time. Please try again.</div>
|
|
4930
|
-
<button id="sc-retry-btn" style="padding:11px 28px;border-radius:10px;background
|
|
4937
|
+
<button id="sc-retry-btn" style="padding:11px 28px;border-radius:10px;background:${this.colors.primary};color:#fff;border:none;cursor:pointer;font-size:14px;font-weight:600;width:100%;max-width:180px;">Try Again</button>
|
|
4931
4938
|
</div>`;
|
|
4932
4939
|
const btn = this.overlayEl.querySelector("#sc-retry-btn");
|
|
4933
4940
|
if (btn) {
|
|
@@ -4961,13 +4968,13 @@ var SmartComplySDK = (() => {
|
|
|
4961
4968
|
docVideo.srcObject = stream;
|
|
4962
4969
|
const guideOverlay = document.createElement("div");
|
|
4963
4970
|
guideOverlay.style.cssText = "position:absolute;inset:0;pointer-events:none;display:flex;align-items:center;justify-content:center;";
|
|
4964
|
-
guideOverlay.innerHTML = `<div style="width:83%;height:53%;border:2px dashed rgba(255,255,255,0.55);border-radius:10px;box-shadow:0 0 0 2000px rgba(0,0,0,0.45);position:relative;"><div style="position:absolute;top:-2px;left:-2px;width:18px;height:18px;border-top:3px solid
|
|
4971
|
+
guideOverlay.innerHTML = `<div style="width:83%;height:53%;border:2px dashed rgba(255,255,255,0.55);border-radius:10px;box-shadow:0 0 0 2000px rgba(0,0,0,0.45);position:relative;"><div style="position:absolute;top:-2px;left:-2px;width:18px;height:18px;border-top:3px solid ${this.colors.primary};border-left:3px solid ${this.colors.primary};border-radius:4px 0 0 0;"></div><div style="position:absolute;top:-2px;right:-2px;width:18px;height:18px;border-top:3px solid ${this.colors.primary};border-right:3px solid ${this.colors.primary};border-radius:0 4px 0 0;"></div><div style="position:absolute;bottom:-2px;left:-2px;width:18px;height:18px;border-bottom:3px solid ${this.colors.primary};border-left:3px solid ${this.colors.primary};border-radius:0 0 0 4px;"></div><div style="position:absolute;bottom:-2px;right:-2px;width:18px;height:18px;border-bottom:3px solid ${this.colors.primary};border-right:3px solid ${this.colors.primary};border-radius:0 0 4px 0;"></div></div>`;
|
|
4965
4972
|
const header = document.createElement("div");
|
|
4966
4973
|
header.style.cssText = "position:absolute;top:0;left:0;right:0;background:linear-gradient(180deg,rgba(0,0,0,0.88) 0%,transparent 100%);padding:18px 16px 40px;text-align:center;";
|
|
4967
4974
|
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>`;
|
|
4968
4975
|
const bottomPanel = document.createElement("div");
|
|
4969
4976
|
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;";
|
|
4970
|
-
bottomPanel.innerHTML = `<div style="font-size:11px;color:rgba(255,255,255,0.4);text-align:center;margin-bottom:12px;"
|
|
4977
|
+
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:${this.colors.primary};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>`;
|
|
4971
4978
|
docRoot.appendChild(docVideo);
|
|
4972
4979
|
docRoot.appendChild(guideOverlay);
|
|
4973
4980
|
docRoot.appendChild(header);
|
|
@@ -5323,7 +5330,7 @@ var SmartComplySDK = (() => {
|
|
|
5323
5330
|
const camera = new CameraManager();
|
|
5324
5331
|
const recorder = new VideoRecorder();
|
|
5325
5332
|
const faceEngine = new FaceDetectorEngine();
|
|
5326
|
-
const ui2 = new LivenessUI();
|
|
5333
|
+
const ui2 = new LivenessUI(params.colors);
|
|
5327
5334
|
let cleanedUp = false;
|
|
5328
5335
|
const cleanup = () => {
|
|
5329
5336
|
if (cleanedUp) return;
|
|
@@ -5713,6 +5720,20 @@ var SmartComplySDK = (() => {
|
|
|
5713
5720
|
};
|
|
5714
5721
|
|
|
5715
5722
|
// src/flow/theme.ts
|
|
5723
|
+
var RADIUS = {
|
|
5724
|
+
sm: 8,
|
|
5725
|
+
md: 12,
|
|
5726
|
+
lg: 16,
|
|
5727
|
+
pill: 999
|
|
5728
|
+
};
|
|
5729
|
+
var TYPE = {
|
|
5730
|
+
xs: 12,
|
|
5731
|
+
sm: 13,
|
|
5732
|
+
base: 15,
|
|
5733
|
+
headingSm: 16,
|
|
5734
|
+
heading: 18,
|
|
5735
|
+
headingLg: 22
|
|
5736
|
+
};
|
|
5716
5737
|
var THEMES = {
|
|
5717
5738
|
default: {
|
|
5718
5739
|
primary: "#3b82f6",
|
|
@@ -5953,14 +5974,90 @@ var SmartComplySDK = (() => {
|
|
|
5953
5974
|
return Math.min(maxWidth / srcWidth, maxHeight / srcHeight, 1);
|
|
5954
5975
|
}
|
|
5955
5976
|
|
|
5977
|
+
// src/flow/icons.ts
|
|
5978
|
+
var PATHS = {
|
|
5979
|
+
shield: '<path d="M12 2l8 3v6c0 5-3.5 8.5-8 11-4.5-2.5-8-6-8-11V5l8-3z"/>',
|
|
5980
|
+
"id-card": '<rect x="2" y="5" width="20" height="14" rx="2"/><circle cx="8" cy="12" r="2"/><path d="M13 10h6M13 14h4"/>',
|
|
5981
|
+
document: '<path d="M6 2h9l5 5v15H6z"/><path d="M15 2v5h5"/><path d="M9 13h6M9 17h6"/>',
|
|
5982
|
+
check: '<path d="M4 12l6 6L20 6"/>',
|
|
5983
|
+
close: '<path d="M5 5l14 14M19 5L5 19"/>',
|
|
5984
|
+
camera: '<path d="M4 8h3l2-3h6l2 3h3v11H4z"/><circle cx="12" cy="13" r="3.5"/>',
|
|
5985
|
+
gallery: '<rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="8.5" cy="9.5" r="1.5"/><path d="M21 15l-5-5-9 9"/>',
|
|
5986
|
+
network: '<path d="M2 8.5a17 17 0 0120 0M5.5 12.5a12 12 0 0113 0M9 16.5a6 6 0 016 0"/><circle cx="12" cy="20" r="1"/>',
|
|
5987
|
+
clock: '<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3.5 2"/>',
|
|
5988
|
+
search: '<circle cx="10.5" cy="10.5" r="6.5"/><path d="M20 20l-4.8-4.8"/>',
|
|
5989
|
+
calendar: '<rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 10h18M8 3v4M16 3v4"/>',
|
|
5990
|
+
face: '<circle cx="12" cy="12" r="9"/><path d="M9 10h.01M15 10h.01M8.5 15c1 1.2 2.2 1.8 3.5 1.8s2.5-.6 3.5-1.8"/>',
|
|
5991
|
+
warning: '<path d="M12 3l10 18H2z"/><path d="M12 10v4"/><circle cx="12" cy="17" r="0.5" fill="currentColor"/>',
|
|
5992
|
+
passport: '<rect x="5" y="2" width="14" height="20" rx="2"/><circle cx="12" cy="9" r="2.5"/><path d="M9 15h6"/>',
|
|
5993
|
+
car: '<path d="M4 16V11l2-5h12l2 5v5"/><path d="M4 16h16M7 16v2M17 16v2"/><circle cx="7.5" cy="14" r="1"/><circle cx="16.5" cy="14" r="1"/>',
|
|
5994
|
+
ballot: '<rect x="4" y="8" width="16" height="12" rx="1"/><path d="M9 8V5a3 3 0 016 0v3"/><path d="M12 12v4"/>',
|
|
5995
|
+
refresh: '<path d="M4 4v6h6"/><path d="M20 20v-6h-6"/><path d="M20 10a8 8 0 00-14.6-4.6M4 14a8 8 0 0014.6 4.6"/>'
|
|
5996
|
+
};
|
|
5997
|
+
function icon(name, size = 24) {
|
|
5998
|
+
const d2 = PATHS[name];
|
|
5999
|
+
return `<svg width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${d2}</svg>`;
|
|
6000
|
+
}
|
|
6001
|
+
|
|
6002
|
+
// src/flow/spinner.ts
|
|
6003
|
+
var injected = false;
|
|
6004
|
+
function injectSpinnerKeyframes() {
|
|
6005
|
+
if (injected || document.getElementById("sc-spinner-kf")) {
|
|
6006
|
+
injected = true;
|
|
6007
|
+
return;
|
|
6008
|
+
}
|
|
6009
|
+
const style = document.createElement("style");
|
|
6010
|
+
style.id = "sc-spinner-kf";
|
|
6011
|
+
style.textContent = `
|
|
6012
|
+
@keyframes sc-spin { to { transform: rotate(360deg); } }
|
|
6013
|
+
@keyframes sc-spinner-pulse {
|
|
6014
|
+
0%, 100% { transform: scale(1); opacity: 1; }
|
|
6015
|
+
50% { transform: scale(1.1); opacity: 0.8; }
|
|
6016
|
+
}
|
|
6017
|
+
`;
|
|
6018
|
+
document.head.appendChild(style);
|
|
6019
|
+
injected = true;
|
|
6020
|
+
}
|
|
6021
|
+
function renderSpinner(theme, opts = {}) {
|
|
6022
|
+
injectSpinnerKeyframes();
|
|
6023
|
+
const size = opts.size ?? 44;
|
|
6024
|
+
const wrap = document.createElement("div");
|
|
6025
|
+
wrap.style.cssText = `position:relative;width:${size}px;height:${size}px;flex-shrink:0;`;
|
|
6026
|
+
const ring = document.createElement("div");
|
|
6027
|
+
ring.style.cssText = `
|
|
6028
|
+
position:absolute;inset:0;border-radius:50%;
|
|
6029
|
+
border:${Math.max(2, Math.round(size / 20))}px solid ${theme.border};
|
|
6030
|
+
border-top-color:${theme.primary};
|
|
6031
|
+
animation:sc-spin 0.9s linear infinite;
|
|
6032
|
+
`;
|
|
6033
|
+
wrap.appendChild(ring);
|
|
6034
|
+
if (opts.icon) {
|
|
6035
|
+
const center = document.createElement("div");
|
|
6036
|
+
center.style.cssText = `
|
|
6037
|
+
position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
|
|
6038
|
+
color:${theme.primary};animation:sc-spinner-pulse 2s ease-in-out infinite;
|
|
6039
|
+
`;
|
|
6040
|
+
center.innerHTML = opts.icon;
|
|
6041
|
+
wrap.appendChild(center);
|
|
6042
|
+
}
|
|
6043
|
+
return wrap;
|
|
6044
|
+
}
|
|
6045
|
+
function renderInlineSpinner(color = "#fff", size = 13) {
|
|
6046
|
+
injectSpinnerKeyframes();
|
|
6047
|
+
return `<span style="display:inline-block;width:${size}px;height:${size}px;border-radius:50%;border:2px solid rgba(255,255,255,0.3);border-top-color:${color};animation:sc-spin 0.6s linear infinite;flex-shrink:0;"></span>`;
|
|
6048
|
+
}
|
|
6049
|
+
|
|
5956
6050
|
// src/flow/DocumentCapture.ts
|
|
5957
6051
|
var DocumentCapture = class {
|
|
5958
6052
|
constructor() {
|
|
5959
6053
|
this.root = null;
|
|
5960
6054
|
this.videoEl = null;
|
|
6055
|
+
this.videoWrapEl = null;
|
|
5961
6056
|
this.cameraManager = new CameraManager();
|
|
6057
|
+
this.orientationHandler = null;
|
|
5962
6058
|
this.resolveCapture = null;
|
|
5963
6059
|
this.rejectCapture = null;
|
|
6060
|
+
this.frontViaCamera = false;
|
|
5964
6061
|
this.frontBlob = null;
|
|
5965
6062
|
this.backBlob = null;
|
|
5966
6063
|
this.currentSide = "front";
|
|
@@ -5992,6 +6089,7 @@ var SmartComplySDK = (() => {
|
|
|
5992
6089
|
this.rejectCapture = reject;
|
|
5993
6090
|
this.frontBlob = null;
|
|
5994
6091
|
this.backBlob = null;
|
|
6092
|
+
this.frontViaCamera = false;
|
|
5995
6093
|
this.currentSide = "front";
|
|
5996
6094
|
this.requiresBackOverride = requiresBack;
|
|
5997
6095
|
this.renderChoiceScreen(container, theme, documentType);
|
|
@@ -6034,14 +6132,14 @@ var SmartComplySDK = (() => {
|
|
|
6034
6132
|
iconBox.style.cssText = `
|
|
6035
6133
|
width:48px;height:48px;border-radius:14px;flex-shrink:0;
|
|
6036
6134
|
display:flex;align-items:center;justify-content:center;
|
|
6037
|
-
|
|
6135
|
+
color:${theme.primary};
|
|
6038
6136
|
background:${theme.primary}15;
|
|
6039
6137
|
border:1.5px solid ${theme.primary}30;
|
|
6040
6138
|
`;
|
|
6041
|
-
iconBox.
|
|
6139
|
+
iconBox.innerHTML = icon(this._docIcon(documentType), 22);
|
|
6042
6140
|
const titleBlock = document.createElement("div");
|
|
6043
6141
|
const titleEl = document.createElement("div");
|
|
6044
|
-
titleEl.style.cssText = `color:${theme.text};font-size
|
|
6142
|
+
titleEl.style.cssText = `color:${theme.text};font-size:${TYPE.headingSm}px;font-weight:700;line-height:1.3;`;
|
|
6045
6143
|
titleEl.textContent = `Capture your ${docLabel}`;
|
|
6046
6144
|
const subEl = document.createElement("div");
|
|
6047
6145
|
subEl.style.cssText = `color:${theme.textSecondary};font-size:12px;margin-top:2px;`;
|
|
@@ -6066,7 +6164,7 @@ var SmartComplySDK = (() => {
|
|
|
6066
6164
|
transition:all 0.15s ease;min-height:80px;
|
|
6067
6165
|
box-shadow:0 4px 14px ${theme.primary}30;
|
|
6068
6166
|
`;
|
|
6069
|
-
cameraBtn.innerHTML = `<span style="
|
|
6167
|
+
cameraBtn.innerHTML = `<span style="display:inline-flex;">${icon("camera", 24)}</span><span>Take Photo</span><span style="font-size:10px;opacity:0.8;font-weight:500;">Use camera</span>`;
|
|
6070
6168
|
cameraBtn.addEventListener("mouseenter", () => {
|
|
6071
6169
|
cameraBtn.style.opacity = "0.9";
|
|
6072
6170
|
cameraBtn.style.transform = "translateY(-1px)";
|
|
@@ -6088,7 +6186,7 @@ var SmartComplySDK = (() => {
|
|
|
6088
6186
|
font-size:13px;font-weight:600;font-family:inherit;
|
|
6089
6187
|
transition:all 0.15s ease;min-height:80px;
|
|
6090
6188
|
`;
|
|
6091
|
-
uploadBtn.innerHTML = `<span style="
|
|
6189
|
+
uploadBtn.innerHTML = `<span style="display:inline-flex;">${icon("gallery", 24)}</span><span>From Gallery</span><span style="font-size:10px;color:${theme.textMuted || theme.textSecondary};font-weight:500;">Upload file</span>`;
|
|
6092
6190
|
uploadBtn.addEventListener("mouseenter", () => {
|
|
6093
6191
|
uploadBtn.style.borderColor = theme.primary;
|
|
6094
6192
|
uploadBtn.style.transform = "translateY(-1px)";
|
|
@@ -6107,7 +6205,7 @@ var SmartComplySDK = (() => {
|
|
|
6107
6205
|
tips.style.cssText = `
|
|
6108
6206
|
margin:0 20px 16px;padding:12px 14px;
|
|
6109
6207
|
background:${theme.shimmer || theme.cardBg};
|
|
6110
|
-
border:1px solid ${theme.border};border-radius
|
|
6208
|
+
border:1px solid ${theme.border};border-radius:${RADIUS.md}px;
|
|
6111
6209
|
`;
|
|
6112
6210
|
const tipsGrid = document.createElement("div");
|
|
6113
6211
|
tipsGrid.style.cssText = `
|
|
@@ -6122,7 +6220,7 @@ var SmartComplySDK = (() => {
|
|
|
6122
6220
|
tipItems.forEach((t2) => {
|
|
6123
6221
|
const row = document.createElement("div");
|
|
6124
6222
|
row.style.cssText = `display:flex;align-items:center;gap:5px;font-size:11px;color:${theme.textSecondary};`;
|
|
6125
|
-
row.innerHTML = `<span style="color:${theme.primary};
|
|
6223
|
+
row.innerHTML = `<span style="color:${theme.primary};flex-shrink:0;display:inline-flex;">${icon("check", 12)}</span><span>${t2}</span>`;
|
|
6126
6224
|
tipsGrid.appendChild(row);
|
|
6127
6225
|
});
|
|
6128
6226
|
tips.appendChild(tipsGrid);
|
|
@@ -6159,45 +6257,84 @@ var SmartComplySDK = (() => {
|
|
|
6159
6257
|
this.root.appendChild(fileInput);
|
|
6160
6258
|
container.appendChild(this.root);
|
|
6161
6259
|
}
|
|
6162
|
-
/** Returns
|
|
6260
|
+
/** Returns the icon name matching the document type. */
|
|
6163
6261
|
_docIcon(documentType) {
|
|
6164
6262
|
const t2 = documentType.toLowerCase();
|
|
6165
|
-
if (t2.includes("passport")) return "
|
|
6166
|
-
if (t2.includes("driver") || t2.includes("licen")) return "
|
|
6167
|
-
if (t2.includes("voter") || t2.includes("pvc")) return "
|
|
6168
|
-
return "
|
|
6263
|
+
if (t2.includes("passport")) return "passport";
|
|
6264
|
+
if (t2.includes("driver") || t2.includes("licen")) return "car";
|
|
6265
|
+
if (t2.includes("voter") || t2.includes("pvc")) return "ballot";
|
|
6266
|
+
return "id-card";
|
|
6169
6267
|
}
|
|
6170
6268
|
renderCameraView(container, theme, documentType) {
|
|
6171
6269
|
const wrapper = document.createElement("div");
|
|
6172
|
-
wrapper.style.cssText =
|
|
6270
|
+
wrapper.style.cssText = `
|
|
6271
|
+
position:relative;width:100%;max-width:420px;margin:0 auto;
|
|
6272
|
+
background:#0a0a0a;border-radius:${RADIUS.lg}px;overflow:hidden;
|
|
6273
|
+
box-shadow:0 8px 32px rgba(0,0,0,0.4);
|
|
6274
|
+
`;
|
|
6275
|
+
this.videoWrapEl = wrapper;
|
|
6173
6276
|
this.videoEl = document.createElement("video");
|
|
6174
6277
|
this.videoEl.autoplay = true;
|
|
6175
6278
|
this.videoEl.playsInline = true;
|
|
6176
6279
|
this.videoEl.muted = true;
|
|
6177
6280
|
this.videoEl.style.cssText = "width:100%;display:block;aspect-ratio:4/3;object-fit:cover;";
|
|
6178
6281
|
wrapper.appendChild(this.videoEl);
|
|
6179
|
-
const
|
|
6180
|
-
|
|
6181
|
-
position:absolute;inset:0;
|
|
6182
|
-
|
|
6282
|
+
const vignette = document.createElement("div");
|
|
6283
|
+
vignette.style.cssText = `
|
|
6284
|
+
position:absolute;inset:0;pointer-events:none;
|
|
6285
|
+
box-shadow:inset 0 0 0 9999px rgba(0,0,0,0.38);
|
|
6286
|
+
-webkit-mask:radial-gradient(ellipse 46% 34% at 50% 50%, transparent 60%, #000 100%);
|
|
6287
|
+
mask:radial-gradient(ellipse 46% 34% at 50% 50%, transparent 60%, #000 100%);
|
|
6183
6288
|
`;
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6289
|
+
wrapper.appendChild(vignette);
|
|
6290
|
+
const guideWrap = document.createElement("div");
|
|
6291
|
+
guideWrap.style.cssText = `
|
|
6292
|
+
position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
|
|
6293
|
+
width:84%;aspect-ratio:16/10;pointer-events:none;
|
|
6188
6294
|
`;
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6295
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
6296
|
+
svg.setAttribute("viewBox", "0 0 160 100");
|
|
6297
|
+
svg.style.cssText = "width:100%;height:100%;overflow:visible;";
|
|
6298
|
+
const bracketGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
6299
|
+
bracketGroup.setAttribute("stroke", theme.primary);
|
|
6300
|
+
bracketGroup.setAttribute("stroke-width", "3");
|
|
6301
|
+
bracketGroup.setAttribute("stroke-linecap", "round");
|
|
6302
|
+
bracketGroup.setAttribute("fill", "none");
|
|
6303
|
+
const bLen = 16;
|
|
6304
|
+
const bx0 = 4, bx1 = 156, by0 = 4, by1 = 96;
|
|
6305
|
+
const brackets = [
|
|
6306
|
+
`M${bx0},${by0 + bLen} L${bx0},${by0} L${bx0 + bLen},${by0}`,
|
|
6307
|
+
`M${bx1 - bLen},${by0} L${bx1},${by0} L${bx1},${by0 + bLen}`,
|
|
6308
|
+
`M${bx0},${by1 - bLen} L${bx0},${by1} L${bx0 + bLen},${by1}`,
|
|
6309
|
+
`M${bx1 - bLen},${by1} L${bx1},${by1} L${bx1},${by1 - bLen}`
|
|
6310
|
+
];
|
|
6311
|
+
for (const d2 of brackets) {
|
|
6312
|
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
6313
|
+
path.setAttribute("d", d2);
|
|
6314
|
+
bracketGroup.appendChild(path);
|
|
6315
|
+
}
|
|
6316
|
+
svg.appendChild(bracketGroup);
|
|
6317
|
+
guideWrap.appendChild(svg);
|
|
6318
|
+
wrapper.appendChild(guideWrap);
|
|
6319
|
+
const header = document.createElement("div");
|
|
6320
|
+
header.style.cssText = `
|
|
6321
|
+
position:absolute;top:0;left:0;right:0;
|
|
6322
|
+
background:linear-gradient(180deg,rgba(0,0,0,0.8) 0%,transparent 100%);
|
|
6323
|
+
padding:14px 16px 32px;text-align:center;
|
|
6196
6324
|
`;
|
|
6197
|
-
|
|
6198
|
-
wrapper.appendChild(
|
|
6325
|
+
header.innerHTML = `<div style="color:#fff;font-size:${TYPE.sm}px;font-weight:600;">Align your ${this.getDocumentLabel(documentType)} within the frame</div>`;
|
|
6326
|
+
wrapper.appendChild(header);
|
|
6327
|
+
const footer = document.createElement("div");
|
|
6328
|
+
footer.style.cssText = `
|
|
6329
|
+
position:absolute;bottom:0;left:0;right:0;
|
|
6330
|
+
background:linear-gradient(0deg,rgba(0,0,0,0.7) 0%,transparent 100%);
|
|
6331
|
+
padding:28px 10px 18px;text-align:center;
|
|
6332
|
+
`;
|
|
6333
|
+
footer.innerHTML = `<div style="font-size:${TYPE.xs}px;color:rgba(255,255,255,0.55);">Good lighting · No glare · All 4 corners visible</div>`;
|
|
6334
|
+
wrapper.appendChild(footer);
|
|
6199
6335
|
container.appendChild(wrapper);
|
|
6200
6336
|
const captureBtn = document.createElement("button");
|
|
6337
|
+
captureBtn.setAttribute("aria-label", "Capture photo");
|
|
6201
6338
|
captureBtn.style.cssText = `
|
|
6202
6339
|
display:block;margin:16px auto 0;width:64px;height:64px;
|
|
6203
6340
|
border-radius:50%;border:4px solid ${theme.primary};
|
|
@@ -6223,6 +6360,39 @@ var SmartComplySDK = (() => {
|
|
|
6223
6360
|
container.appendChild(captureBtn);
|
|
6224
6361
|
this.openCamera();
|
|
6225
6362
|
}
|
|
6363
|
+
/**
|
|
6364
|
+
* Matches the video box's aspect-ratio CSS to the stream's actual
|
|
6365
|
+
* negotiated dimensions instead of a single hardcoded ratio — a stream
|
|
6366
|
+
* that's natively 16:9 no longer gets force-cropped into a 4:3 box.
|
|
6367
|
+
* Clamped to a sane document-shaped range so a degenerate/unusual stream
|
|
6368
|
+
* can't produce a sliver-thin or absurdly tall box.
|
|
6369
|
+
*/
|
|
6370
|
+
_fitToStream() {
|
|
6371
|
+
if (!this.videoEl) return;
|
|
6372
|
+
const { videoWidth: w2, videoHeight: h2 } = this.videoEl;
|
|
6373
|
+
if (!w2 || !h2) return;
|
|
6374
|
+
const ratio = Math.min(Math.max(w2 / h2, 1), 2);
|
|
6375
|
+
this.videoEl.style.aspectRatio = `${ratio}`;
|
|
6376
|
+
}
|
|
6377
|
+
/**
|
|
6378
|
+
* Re-fits the video box when the device rotates mid-capture. Does not
|
|
6379
|
+
* re-request getUserMedia (disruptive/slow) — the stream's dimensions
|
|
6380
|
+
* don't change on rotation, only the viewport does, so re-reading the
|
|
6381
|
+
* already-known videoWidth/videoHeight is enough to keep the box sane.
|
|
6382
|
+
*/
|
|
6383
|
+
_watchOrientation() {
|
|
6384
|
+
this._unwatchOrientation();
|
|
6385
|
+
this.orientationHandler = () => this._fitToStream();
|
|
6386
|
+
window.addEventListener("orientationchange", this.orientationHandler);
|
|
6387
|
+
window.addEventListener("resize", this.orientationHandler);
|
|
6388
|
+
}
|
|
6389
|
+
_unwatchOrientation() {
|
|
6390
|
+
if (this.orientationHandler) {
|
|
6391
|
+
window.removeEventListener("orientationchange", this.orientationHandler);
|
|
6392
|
+
window.removeEventListener("resize", this.orientationHandler);
|
|
6393
|
+
this.orientationHandler = null;
|
|
6394
|
+
}
|
|
6395
|
+
}
|
|
6226
6396
|
async openCamera() {
|
|
6227
6397
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
|
6228
6398
|
this.rejectCapture?.(new Error("Camera access is not supported in this browser. Please use a modern browser like Chrome, Firefox, or Safari."));
|
|
@@ -6269,6 +6439,8 @@ var SmartComplySDK = (() => {
|
|
|
6269
6439
|
});
|
|
6270
6440
|
if (this.videoEl) {
|
|
6271
6441
|
this.videoEl.srcObject = stream;
|
|
6442
|
+
this.videoEl.addEventListener("loadedmetadata", () => this._fitToStream(), { once: true });
|
|
6443
|
+
this._watchOrientation();
|
|
6272
6444
|
}
|
|
6273
6445
|
}
|
|
6274
6446
|
captureFrame(container, theme, documentType) {
|
|
@@ -6285,7 +6457,7 @@ var SmartComplySDK = (() => {
|
|
|
6285
6457
|
this.stopCamera();
|
|
6286
6458
|
this.showLoadingState("Analyzing photo...", theme);
|
|
6287
6459
|
const quality = await this._assessImageQuality(canvas, ctx);
|
|
6288
|
-
this.showPreview(container, theme, blob, documentType, quality);
|
|
6460
|
+
this.showPreview(container, theme, blob, documentType, quality, true);
|
|
6289
6461
|
}
|
|
6290
6462
|
},
|
|
6291
6463
|
"image/jpeg",
|
|
@@ -6327,28 +6499,37 @@ var SmartComplySDK = (() => {
|
|
|
6327
6499
|
return null;
|
|
6328
6500
|
}
|
|
6329
6501
|
}
|
|
6330
|
-
showPreview(container, theme, imageData, documentType, quality) {
|
|
6502
|
+
showPreview(container, theme, imageData, documentType, quality, viaCamera) {
|
|
6331
6503
|
if (this.root) this.root.innerHTML = "";
|
|
6332
6504
|
else {
|
|
6333
6505
|
this.root = document.createElement("div");
|
|
6334
6506
|
container.appendChild(this.root);
|
|
6335
6507
|
}
|
|
6336
6508
|
this.root.style.cssText = "display:flex;flex-direction:column;align-items:center;gap:16px;";
|
|
6509
|
+
const stepBadge = document.createElement("div");
|
|
6510
|
+
stepBadge.style.cssText = `
|
|
6511
|
+
display:inline-flex;align-items:center;gap:5px;
|
|
6512
|
+
padding:3px 11px;border-radius:${RADIUS.pill}px;
|
|
6513
|
+
font-size:10.5px;font-weight:600;letter-spacing:0.2px;
|
|
6514
|
+
color:${theme.primary};background:${theme.primary}15;border:1px solid ${theme.primary}30;
|
|
6515
|
+
`;
|
|
6516
|
+
stepBadge.textContent = "STEP 1 OF 2 · CHECK THE PHOTO";
|
|
6517
|
+
this.root.appendChild(stepBadge);
|
|
6337
6518
|
const img = document.createElement("img");
|
|
6338
6519
|
const imageUrl = URL.createObjectURL(imageData);
|
|
6339
6520
|
img.src = imageUrl;
|
|
6340
6521
|
img.style.cssText = `
|
|
6341
|
-
width:100%;max-height:300px;object-fit:contain;border-radius
|
|
6522
|
+
width:100%;max-height:300px;object-fit:contain;border-radius:${RADIUS.md}px;
|
|
6342
6523
|
border:2px solid ${theme.border};
|
|
6343
6524
|
`;
|
|
6344
6525
|
this.root.appendChild(img);
|
|
6345
6526
|
img._blobUrl = imageUrl;
|
|
6346
6527
|
const label = document.createElement("div");
|
|
6347
|
-
label.style.cssText = `color:${theme.
|
|
6528
|
+
label.style.cssText = `color:${theme.text};font-size:${TYPE.base}px;font-weight:700;text-align:center;`;
|
|
6348
6529
|
label.textContent = "Does the photo look clear?";
|
|
6349
6530
|
this.root.appendChild(label);
|
|
6350
6531
|
const sublabel = document.createElement("div");
|
|
6351
|
-
sublabel.style.cssText = `color:${theme.textMuted};font-size
|
|
6532
|
+
sublabel.style.cssText = `color:${theme.textMuted};font-size:${TYPE.xs}px;text-align:center;line-height:1.6;`;
|
|
6352
6533
|
sublabel.textContent = "All text must be readable and all four corners must be visible.";
|
|
6353
6534
|
this.root.appendChild(sublabel);
|
|
6354
6535
|
const qualityIsPoor = !!quality && !quality.isValid;
|
|
@@ -6388,7 +6569,7 @@ var SmartComplySDK = (() => {
|
|
|
6388
6569
|
}
|
|
6389
6570
|
useBtn.textContent = "Processing...";
|
|
6390
6571
|
useBtn.disabled = true;
|
|
6391
|
-
this.compressImage(imageData, 2e3, 1500, 0.92).then((compressed) => this.handleCaptureComplete(compressed, container, theme, documentType)).catch(() => this.handleCaptureComplete(imageData, container, theme, documentType));
|
|
6572
|
+
this.compressImage(imageData, 2e3, 1500, 0.92).then((compressed) => this.handleCaptureComplete(compressed, container, theme, documentType, viaCamera)).catch(() => this.handleCaptureComplete(imageData, container, theme, documentType, viaCamera));
|
|
6392
6573
|
};
|
|
6393
6574
|
const useBtn = this.createButton(qualityIsPoor ? "Use Anyway ⚠" : "Use Photo ✓", theme, !qualityIsPoor);
|
|
6394
6575
|
useBtn.style.flex = "1";
|
|
@@ -6409,11 +6590,12 @@ var SmartComplySDK = (() => {
|
|
|
6409
6590
|
btnRow.appendChild(useBtn);
|
|
6410
6591
|
this.root.appendChild(btnRow);
|
|
6411
6592
|
}
|
|
6412
|
-
handleCaptureComplete(imageData, container, theme, documentType) {
|
|
6593
|
+
handleCaptureComplete(imageData, container, theme, documentType, viaCamera) {
|
|
6413
6594
|
const requiresBack = this.shouldCaptureBackSide(documentType);
|
|
6414
6595
|
const wasCapturingFront = this.currentSide === "front";
|
|
6415
6596
|
if (wasCapturingFront) {
|
|
6416
6597
|
this.frontBlob = imageData;
|
|
6598
|
+
this.frontViaCamera = viaCamera;
|
|
6417
6599
|
} else {
|
|
6418
6600
|
this.backBlob = imageData;
|
|
6419
6601
|
}
|
|
@@ -6429,13 +6611,14 @@ var SmartComplySDK = (() => {
|
|
|
6429
6611
|
}
|
|
6430
6612
|
const result = {
|
|
6431
6613
|
front: this.frontBlob,
|
|
6432
|
-
back: this.backBlob || void 0
|
|
6614
|
+
back: this.backBlob || void 0,
|
|
6615
|
+
viaCamera: this.frontViaCamera
|
|
6433
6616
|
};
|
|
6434
6617
|
this.resolveCapture?.(result);
|
|
6435
6618
|
}
|
|
6436
6619
|
async handleFileUploadComplete(imageData, container, theme, documentType) {
|
|
6437
6620
|
const quality = await this._assessBlobQuality(imageData);
|
|
6438
|
-
this.showPreview(container, theme, imageData, documentType, quality);
|
|
6621
|
+
this.showPreview(container, theme, imageData, documentType, quality, false);
|
|
6439
6622
|
}
|
|
6440
6623
|
validateFile(file) {
|
|
6441
6624
|
const allowedTypes = ["image/jpeg", "image/jpg", "image/png"];
|
|
@@ -6456,63 +6639,30 @@ var SmartComplySDK = (() => {
|
|
|
6456
6639
|
if (input) input.click();
|
|
6457
6640
|
}
|
|
6458
6641
|
stopCamera() {
|
|
6642
|
+
this._unwatchOrientation();
|
|
6459
6643
|
this.cameraManager.stop();
|
|
6460
6644
|
if (this.videoEl) {
|
|
6461
6645
|
this.videoEl.srcObject = null;
|
|
6462
6646
|
this.videoEl = null;
|
|
6463
6647
|
}
|
|
6648
|
+
this.videoWrapEl = null;
|
|
6464
6649
|
}
|
|
6465
6650
|
showLoadingState(message, theme) {
|
|
6466
6651
|
if (!this.root) return;
|
|
6467
6652
|
this.root.innerHTML = "";
|
|
6468
6653
|
this.root.style.cssText = "display:flex;flex-direction:column;align-items:center;justify-content:center;gap:20px;padding:40px 20px;min-height:300px;";
|
|
6469
|
-
|
|
6470
|
-
spinnerContainer.style.cssText = "position:relative;width:80px;height:80px;";
|
|
6471
|
-
const spinner = document.createElement("div");
|
|
6472
|
-
spinner.style.cssText = `
|
|
6473
|
-
position:absolute;inset:0;border-radius:50%;
|
|
6474
|
-
border:4px solid ${theme.border};
|
|
6475
|
-
border-top-color:${theme.primary};
|
|
6476
|
-
animation:sc-spin 1s linear infinite;
|
|
6477
|
-
`;
|
|
6478
|
-
spinnerContainer.appendChild(spinner);
|
|
6479
|
-
const centerIcon = document.createElement("div");
|
|
6480
|
-
centerIcon.style.cssText = `
|
|
6481
|
-
position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
|
|
6482
|
-
font-size:28px;animation:pulse 2s ease-in-out infinite;
|
|
6483
|
-
`;
|
|
6484
|
-
centerIcon.textContent = "📄";
|
|
6485
|
-
spinnerContainer.appendChild(centerIcon);
|
|
6486
|
-
this.root.appendChild(spinnerContainer);
|
|
6654
|
+
this.root.appendChild(renderSpinner(theme, { size: 80, icon: icon("document", 28) }));
|
|
6487
6655
|
const loadingText = document.createElement("div");
|
|
6488
|
-
loadingText.style.cssText = `
|
|
6489
|
-
color:${theme.text};font-size:16px;font-weight:600;text-align:center;
|
|
6490
|
-
animation:fadeIn 0.5s ease-out;
|
|
6491
|
-
`;
|
|
6656
|
+
loadingText.style.cssText = `color:${theme.text};font-size:${TYPE.heading}px;font-weight:600;text-align:center;`;
|
|
6492
6657
|
loadingText.textContent = message;
|
|
6493
6658
|
this.root.appendChild(loadingText);
|
|
6494
|
-
if (!document.head.querySelector("style[data-pulse-animation]")) {
|
|
6495
|
-
const style2 = document.createElement("style");
|
|
6496
|
-
style2.setAttribute("data-pulse-animation", "true");
|
|
6497
|
-
style2.textContent = `
|
|
6498
|
-
@keyframes pulse {
|
|
6499
|
-
0%, 100% { transform: scale(1); opacity: 1; }
|
|
6500
|
-
50% { transform: scale(1.1); opacity: 0.8; }
|
|
6501
|
-
}
|
|
6502
|
-
@keyframes fadeIn {
|
|
6503
|
-
from { opacity: 0; transform: translateY(10px); }
|
|
6504
|
-
to { opacity: 1; transform: translateY(0); }
|
|
6505
|
-
}
|
|
6506
|
-
`;
|
|
6507
|
-
document.head.appendChild(style2);
|
|
6508
|
-
}
|
|
6509
6659
|
}
|
|
6510
6660
|
showError(message) {
|
|
6511
6661
|
if (!this.root) return;
|
|
6512
6662
|
const errorContainer = document.createElement("div");
|
|
6513
6663
|
errorContainer.style.cssText = `
|
|
6514
6664
|
display:flex;align-items:center;gap:12px;padding:16px;
|
|
6515
|
-
background:#ff444415;border:1px solid #ff444430;border-radius
|
|
6665
|
+
background:#ff444415;border:1px solid #ff444430;border-radius:${RADIUS.md}px;
|
|
6516
6666
|
color:#ff4444;font-size:14px;margin-top:16px;animation:shake 0.5s ease-in-out;
|
|
6517
6667
|
`;
|
|
6518
6668
|
errorContainer.innerHTML = `
|
|
@@ -6520,16 +6670,16 @@ var SmartComplySDK = (() => {
|
|
|
6520
6670
|
<span>${message}</span>
|
|
6521
6671
|
`;
|
|
6522
6672
|
if (!document.head.querySelector("style[data-shake-animation]")) {
|
|
6523
|
-
const
|
|
6524
|
-
|
|
6525
|
-
|
|
6673
|
+
const style = document.createElement("style");
|
|
6674
|
+
style.setAttribute("data-shake-animation", "true");
|
|
6675
|
+
style.textContent = `
|
|
6526
6676
|
@keyframes shake {
|
|
6527
6677
|
0%, 100% { transform: translateX(0); }
|
|
6528
6678
|
25% { transform: translateX(-5px); }
|
|
6529
6679
|
75% { transform: translateX(5px); }
|
|
6530
6680
|
}
|
|
6531
6681
|
`;
|
|
6532
|
-
document.head.appendChild(
|
|
6682
|
+
document.head.appendChild(style);
|
|
6533
6683
|
}
|
|
6534
6684
|
this.root.appendChild(errorContainer);
|
|
6535
6685
|
setTimeout(() => errorContainer.remove(), 5e3);
|
|
@@ -6538,7 +6688,7 @@ var SmartComplySDK = (() => {
|
|
|
6538
6688
|
const btn = document.createElement("button");
|
|
6539
6689
|
btn.textContent = label;
|
|
6540
6690
|
btn.style.cssText = `
|
|
6541
|
-
padding:16px 24px;border-radius
|
|
6691
|
+
padding:16px 24px;border-radius:${RADIUS.md}px;font-size:16px;font-weight:600;
|
|
6542
6692
|
cursor:pointer;transition:all 0.2s ease;border:none;width:100%;
|
|
6543
6693
|
min-height:52px;touch-action:manipulation;-webkit-tap-highlight-color:transparent;
|
|
6544
6694
|
${isPrimary ? `background:${theme.primary};color:#fff;box-shadow:0 4px 12px ${theme.primary}30;` : `background:${theme.inputBg};color:${theme.text};border:2px solid ${theme.border};`}
|
|
@@ -6865,17 +7015,6 @@ var SmartComplySDK = (() => {
|
|
|
6865
7015
|
if (map[key]) return map[key];
|
|
6866
7016
|
return code.replace(/_/g, " ").replace(/\b\w/g, (c2) => c2.toUpperCase());
|
|
6867
7017
|
}
|
|
6868
|
-
var style = document.createElement("style");
|
|
6869
|
-
style.textContent = `
|
|
6870
|
-
@keyframes sc-spin {
|
|
6871
|
-
0% { transform: rotate(0deg); }
|
|
6872
|
-
100% { transform: rotate(360deg); }
|
|
6873
|
-
}
|
|
6874
|
-
`;
|
|
6875
|
-
if (!document.head.querySelector("style[data-sc-animations]")) {
|
|
6876
|
-
style.setAttribute("data-sc-animations", "true");
|
|
6877
|
-
document.head.appendChild(style);
|
|
6878
|
-
}
|
|
6879
7018
|
var _SmartComplyFlow = class _SmartComplyFlow {
|
|
6880
7019
|
constructor(options) {
|
|
6881
7020
|
this.theme = getTheme("default");
|
|
@@ -6903,6 +7042,11 @@ var SmartComplySDK = (() => {
|
|
|
6903
7042
|
this.idNumber = "";
|
|
6904
7043
|
this.documentBlob = null;
|
|
6905
7044
|
this.documentBackBlob = null;
|
|
7045
|
+
// Whether the document's front image came from the live camera vs. a
|
|
7046
|
+
// gallery/file upload — gates whether pre-warming the liveness camera on
|
|
7047
|
+
// the confirm screens makes sense (reusing an already-open camera) or
|
|
7048
|
+
// would surprise a user who hasn't touched their camera yet this session.
|
|
7049
|
+
this._documentViaCamera = false;
|
|
6906
7050
|
this.identityCheckId = null;
|
|
6907
7051
|
this.verificationResult = null;
|
|
6908
7052
|
this.livenessEntryId = null;
|
|
@@ -7217,27 +7361,9 @@ var SmartComplySDK = (() => {
|
|
|
7217
7361
|
// ── Loading ─────────────────────────────────────────────────────
|
|
7218
7362
|
renderLoading(container) {
|
|
7219
7363
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:300px;gap:16px;";
|
|
7220
|
-
|
|
7221
|
-
spinnerWrap.style.cssText = "position:relative;width:60px;height:60px;flex-shrink:0;";
|
|
7222
|
-
const ring = document.createElement("div");
|
|
7223
|
-
ring.style.cssText = `
|
|
7224
|
-
position:absolute;inset:0;border-radius:50%;
|
|
7225
|
-
border:3px solid ${this.theme.border};
|
|
7226
|
-
border-top-color:${this.theme.primary};
|
|
7227
|
-
animation:sc-spin 0.9s linear infinite;
|
|
7228
|
-
`;
|
|
7229
|
-
const centre = document.createElement("div");
|
|
7230
|
-
centre.style.cssText = `
|
|
7231
|
-
position:absolute;inset:0;
|
|
7232
|
-
display:flex;align-items:center;justify-content:center;
|
|
7233
|
-
font-size:22px;
|
|
7234
|
-
`;
|
|
7235
|
-
centre.textContent = "🛡️";
|
|
7236
|
-
spinnerWrap.appendChild(ring);
|
|
7237
|
-
spinnerWrap.appendChild(centre);
|
|
7238
|
-
container.appendChild(spinnerWrap);
|
|
7364
|
+
container.appendChild(renderSpinner(this.theme, { size: 60, icon: icon("shield", 22) }));
|
|
7239
7365
|
const label = document.createElement("div");
|
|
7240
|
-
label.style.cssText = `color:${this.theme.text};font-size
|
|
7366
|
+
label.style.cssText = `color:${this.theme.text};font-size:${TYPE.base}px;font-weight:600;`;
|
|
7241
7367
|
label.textContent = "Setting up secure session";
|
|
7242
7368
|
container.appendChild(label);
|
|
7243
7369
|
const sub = document.createElement("div");
|
|
@@ -7255,11 +7381,11 @@ var SmartComplySDK = (() => {
|
|
|
7255
7381
|
iconWrap.style.cssText = `
|
|
7256
7382
|
width:50px;height:50px;border-radius:14px;
|
|
7257
7383
|
display:flex;align-items:center;justify-content:center;
|
|
7258
|
-
|
|
7384
|
+
color:${this.theme.primary};
|
|
7259
7385
|
background:linear-gradient(135deg,${this.theme.primary}22,${this.theme.primaryGlow});
|
|
7260
7386
|
border:1.5px solid ${this.theme.primary}33;
|
|
7261
7387
|
`;
|
|
7262
|
-
iconWrap.
|
|
7388
|
+
iconWrap.innerHTML = icon(isDocFlow ? "id-card" : "shield", 24);
|
|
7263
7389
|
topRow.appendChild(iconWrap);
|
|
7264
7390
|
const badge = document.createElement("div");
|
|
7265
7391
|
badge.style.cssText = `
|
|
@@ -7277,7 +7403,7 @@ var SmartComplySDK = (() => {
|
|
|
7277
7403
|
titleWrap.style.cssText = "display:flex;flex-direction:column;gap:5px;";
|
|
7278
7404
|
const title = document.createElement("h2");
|
|
7279
7405
|
title.style.cssText = `
|
|
7280
|
-
color:${this.theme.text};font-size
|
|
7406
|
+
color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;
|
|
7281
7407
|
margin:0;line-height:1.2;
|
|
7282
7408
|
`;
|
|
7283
7409
|
const brandName = this.sdkConfig?.brand_name;
|
|
@@ -7303,7 +7429,7 @@ var SmartComplySDK = (() => {
|
|
|
7303
7429
|
const stepsWrap = document.createElement("div");
|
|
7304
7430
|
stepsWrap.style.cssText = `
|
|
7305
7431
|
width:100%;display:flex;flex-direction:column;gap:0;
|
|
7306
|
-
border-radius
|
|
7432
|
+
border-radius:${RADIUS.md}px;overflow:hidden;
|
|
7307
7433
|
border:1.5px solid ${this.theme.border};
|
|
7308
7434
|
`;
|
|
7309
7435
|
steps.forEach((step, i2) => {
|
|
@@ -7316,7 +7442,7 @@ var SmartComplySDK = (() => {
|
|
|
7316
7442
|
`;
|
|
7317
7443
|
const iconEl = document.createElement("div");
|
|
7318
7444
|
iconEl.style.cssText = `
|
|
7319
|
-
width:28px;height:28px;border-radius
|
|
7445
|
+
width:28px;height:28px;border-radius:${RADIUS.sm}px;flex-shrink:0;
|
|
7320
7446
|
display:flex;align-items:center;justify-content:center;
|
|
7321
7447
|
font-size:13px;
|
|
7322
7448
|
background:${this.theme.primary}12;
|
|
@@ -7509,7 +7635,7 @@ var SmartComplySDK = (() => {
|
|
|
7509
7635
|
if (field.type === "dropdown" || field.type === "select") {
|
|
7510
7636
|
const select = document.createElement("select");
|
|
7511
7637
|
select.style.cssText = `
|
|
7512
|
-
width:100%;padding:13px 16px;border-radius
|
|
7638
|
+
width:100%;padding:13px 16px;border-radius:${RADIUS.md}px;
|
|
7513
7639
|
font-size:15px;
|
|
7514
7640
|
background:${this.theme.inputBg};
|
|
7515
7641
|
color:${this.theme.text};
|
|
@@ -7546,7 +7672,7 @@ var SmartComplySDK = (() => {
|
|
|
7546
7672
|
fileInput.type = "file";
|
|
7547
7673
|
fileInput.accept = "image/*";
|
|
7548
7674
|
fileInput.style.cssText = `
|
|
7549
|
-
width:100%;padding:12px 16px;border-radius
|
|
7675
|
+
width:100%;padding:12px 16px;border-radius:${RADIUS.md}px;
|
|
7550
7676
|
font-size:14px;font-weight:500;
|
|
7551
7677
|
background:${this.theme.inputBg};
|
|
7552
7678
|
color:${this.theme.text};
|
|
@@ -7587,7 +7713,7 @@ var SmartComplySDK = (() => {
|
|
|
7587
7713
|
input.maxLength = rule?.maxLen ? rule.maxLen + 2 : 50;
|
|
7588
7714
|
if (rule?.numeric) input.inputMode = "numeric";
|
|
7589
7715
|
input.style.cssText = `
|
|
7590
|
-
width:100%;padding:14px 16px;border-radius
|
|
7716
|
+
width:100%;padding:14px 16px;border-radius:${RADIUS.md}px;
|
|
7591
7717
|
font-size:16px;font-weight:500;
|
|
7592
7718
|
background:${this.theme.inputBg};
|
|
7593
7719
|
color:${this.theme.text};
|
|
@@ -7644,7 +7770,7 @@ var SmartComplySDK = (() => {
|
|
|
7644
7770
|
errorEl.id = "sc-id-error";
|
|
7645
7771
|
errorEl.style.cssText = `
|
|
7646
7772
|
color:${this.theme.error};font-size:13px;display:none;
|
|
7647
|
-
padding:8px 12px;border-radius
|
|
7773
|
+
padding:8px 12px;border-radius:${RADIUS.sm}px;background:${this.theme.errorBg};
|
|
7648
7774
|
`;
|
|
7649
7775
|
container.appendChild(errorEl);
|
|
7650
7776
|
const submitBtn = this.createPrimaryButton("Verify & Continue");
|
|
@@ -7662,7 +7788,7 @@ var SmartComplySDK = (() => {
|
|
|
7662
7788
|
};
|
|
7663
7789
|
submitBtn.addEventListener("click", async () => {
|
|
7664
7790
|
submitBtn.disabled = true;
|
|
7665
|
-
submitBtn.innerHTML = `<span style="display:inline-flex;align-items:center;justify-content:center;gap:8px;"
|
|
7791
|
+
submitBtn.innerHTML = `<span style="display:inline-flex;align-items:center;justify-content:center;gap:8px;">${renderInlineSpinner("#fff", 13)}Verifying...</span>`;
|
|
7666
7792
|
errorEl.style.display = "none";
|
|
7667
7793
|
try {
|
|
7668
7794
|
this.verificationResult = await this.sdk.onboarding.verify({
|
|
@@ -7760,11 +7886,11 @@ var SmartComplySDK = (() => {
|
|
|
7760
7886
|
}
|
|
7761
7887
|
this._prewarmCamera();
|
|
7762
7888
|
const iconWrap = document.createElement("div");
|
|
7763
|
-
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;
|
|
7764
|
-
iconWrap.
|
|
7889
|
+
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};`;
|
|
7890
|
+
iconWrap.innerHTML = icon("shield", 28);
|
|
7765
7891
|
container.appendChild(iconWrap);
|
|
7766
7892
|
const title = document.createElement("h2");
|
|
7767
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
7893
|
+
title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
7768
7894
|
title.textContent = this._ivsName ? `Is this you?` : "Identity Confirmed";
|
|
7769
7895
|
container.appendChild(title);
|
|
7770
7896
|
if (this._ivsName) {
|
|
@@ -7822,13 +7948,22 @@ var SmartComplySDK = (() => {
|
|
|
7822
7948
|
this._renderRetryLimitReached(container);
|
|
7823
7949
|
return;
|
|
7824
7950
|
}
|
|
7825
|
-
this._prewarmCamera();
|
|
7951
|
+
if (this._documentViaCamera) this._prewarmCamera();
|
|
7952
|
+
const stepBadge = document.createElement("div");
|
|
7953
|
+
stepBadge.style.cssText = `
|
|
7954
|
+
display:inline-flex;align-items:center;gap:5px;
|
|
7955
|
+
padding:3px 11px;border-radius:${RADIUS.pill}px;
|
|
7956
|
+
font-size:10.5px;font-weight:600;letter-spacing:0.2px;
|
|
7957
|
+
color:${this.theme.primary};background:${this.theme.primary}15;border:1px solid ${this.theme.primary}30;
|
|
7958
|
+
`;
|
|
7959
|
+
stepBadge.textContent = "STEP 2 OF 2 · CHECK WHAT WE READ";
|
|
7960
|
+
container.appendChild(stepBadge);
|
|
7826
7961
|
const iconWrap = document.createElement("div");
|
|
7827
|
-
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;
|
|
7828
|
-
iconWrap.
|
|
7962
|
+
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};`;
|
|
7963
|
+
iconWrap.innerHTML = icon("document", 28);
|
|
7829
7964
|
container.appendChild(iconWrap);
|
|
7830
7965
|
const title = document.createElement("h2");
|
|
7831
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
7966
|
+
title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
7832
7967
|
title.textContent = "Are these your details?";
|
|
7833
7968
|
container.appendChild(title);
|
|
7834
7969
|
const sub = document.createElement("p");
|
|
@@ -7906,19 +8041,10 @@ var SmartComplySDK = (() => {
|
|
|
7906
8041
|
// ── W6+W7+W8: OCR Gate (document verification) ───────────────────
|
|
7907
8042
|
renderOcrGate(container) {
|
|
7908
8043
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:14px;padding:20px 0;text-align:center;";
|
|
7909
|
-
|
|
7910
|
-
spinnerWrap.style.cssText = "position:relative;width:52px;height:52px;flex-shrink:0;";
|
|
7911
|
-
const ring = document.createElement("div");
|
|
7912
|
-
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;`;
|
|
7913
|
-
const centre = document.createElement("div");
|
|
7914
|
-
centre.style.cssText = "position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;";
|
|
7915
|
-
centre.textContent = "📄";
|
|
7916
|
-
spinnerWrap.appendChild(ring);
|
|
7917
|
-
spinnerWrap.appendChild(centre);
|
|
7918
|
-
container.appendChild(spinnerWrap);
|
|
8044
|
+
container.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("document", 20) }));
|
|
7919
8045
|
const statusEl = document.createElement("div");
|
|
7920
8046
|
statusEl.setAttribute("aria-live", "polite");
|
|
7921
|
-
statusEl.style.cssText = `color:${this.theme.text};font-size
|
|
8047
|
+
statusEl.style.cssText = `color:${this.theme.text};font-size:${TYPE.base}px;font-weight:600;`;
|
|
7922
8048
|
statusEl.textContent = "Reading your document…";
|
|
7923
8049
|
container.appendChild(statusEl);
|
|
7924
8050
|
const subEl = document.createElement("div");
|
|
@@ -7990,12 +8116,12 @@ var SmartComplySDK = (() => {
|
|
|
7990
8116
|
}
|
|
7991
8117
|
_renderExpiredDocument(container) {
|
|
7992
8118
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;padding:20px 0;";
|
|
7993
|
-
const
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
container.appendChild(
|
|
8119
|
+
const icon2 = document.createElement("div");
|
|
8120
|
+
icon2.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;`;
|
|
8121
|
+
icon2.textContent = "📅";
|
|
8122
|
+
container.appendChild(icon2);
|
|
7997
8123
|
const t2 = document.createElement("h2");
|
|
7998
|
-
t2.style.cssText = `color:${this.theme.text};font-size
|
|
8124
|
+
t2.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
7999
8125
|
t2.textContent = "Document Expired";
|
|
8000
8126
|
container.appendChild(t2);
|
|
8001
8127
|
const d2 = document.createElement("p");
|
|
@@ -8019,12 +8145,12 @@ var SmartComplySDK = (() => {
|
|
|
8019
8145
|
}
|
|
8020
8146
|
_renderOcrQualityFail(container, reason) {
|
|
8021
8147
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;padding:20px 0;";
|
|
8022
|
-
const
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
container.appendChild(
|
|
8148
|
+
const icon2 = document.createElement("div");
|
|
8149
|
+
icon2.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;`;
|
|
8150
|
+
icon2.textContent = "🔍";
|
|
8151
|
+
container.appendChild(icon2);
|
|
8026
8152
|
const t2 = document.createElement("h2");
|
|
8027
|
-
t2.style.cssText = `color:${this.theme.text};font-size
|
|
8153
|
+
t2.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
8028
8154
|
t2.textContent = "Document Photo Unclear";
|
|
8029
8155
|
container.appendChild(t2);
|
|
8030
8156
|
const msg = reason === "image_too_blurry" ? "Your document photo is too blurry. Please retake it in good lighting with a steady hand." : reason === "image_too_dark" ? "Your document photo is too dark. Please retake it in better lighting." : reason === "image_too_bright" ? "Your document photo has too much glare. Please reduce reflections and retake." : reason === "document_not_detected" ? "We could not detect a document in the photo. Please ensure the full ID is visible." : "We could not read your document clearly. Please retake the photo in good lighting with no glare.";
|
|
@@ -8053,11 +8179,11 @@ var SmartComplySDK = (() => {
|
|
|
8053
8179
|
verificationResult: this.verificationResult || void 0
|
|
8054
8180
|
});
|
|
8055
8181
|
const iconWrap = document.createElement("div");
|
|
8056
|
-
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;
|
|
8057
|
-
iconWrap.
|
|
8182
|
+
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;`;
|
|
8183
|
+
iconWrap.innerHTML = icon("check", 36);
|
|
8058
8184
|
container.appendChild(iconWrap);
|
|
8059
8185
|
const title = document.createElement("h2");
|
|
8060
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
8186
|
+
title.style.cssText = `color:${this.theme.text};font-size:${TYPE.headingLg}px;font-weight:700;margin:0;`;
|
|
8061
8187
|
title.textContent = "You're all done!";
|
|
8062
8188
|
container.appendChild(title);
|
|
8063
8189
|
const desc = document.createElement("p");
|
|
@@ -8077,12 +8203,12 @@ var SmartComplySDK = (() => {
|
|
|
8077
8203
|
// ── W14: Retry limit reached ─────────────────────────────────────
|
|
8078
8204
|
_renderRetryLimitReached(container) {
|
|
8079
8205
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;padding:24px 0;";
|
|
8080
|
-
const
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
container.appendChild(
|
|
8206
|
+
const icon2 = document.createElement("div");
|
|
8207
|
+
icon2.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;`;
|
|
8208
|
+
icon2.textContent = "⚠️";
|
|
8209
|
+
container.appendChild(icon2);
|
|
8084
8210
|
const t2 = document.createElement("h2");
|
|
8085
|
-
t2.style.cssText = `color:${this.theme.text};font-size
|
|
8211
|
+
t2.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
8086
8212
|
t2.textContent = "Unable to Complete Verification";
|
|
8087
8213
|
container.appendChild(t2);
|
|
8088
8214
|
const d2 = document.createElement("p");
|
|
@@ -8114,6 +8240,7 @@ var SmartComplySDK = (() => {
|
|
|
8114
8240
|
async processDocumentCaptureResult(result, captureContainer, container) {
|
|
8115
8241
|
this.documentBlob = await _compressImage(result.front, 1600, 0.85);
|
|
8116
8242
|
this.documentBackBlob = result.back ? await _compressImage(result.back, 1600, 0.85) : null;
|
|
8243
|
+
this._documentViaCamera = result.viaCamera;
|
|
8117
8244
|
await this.processDocumentBlob(this.documentBlob, captureContainer, container);
|
|
8118
8245
|
}
|
|
8119
8246
|
/**
|
|
@@ -8131,15 +8258,12 @@ var SmartComplySDK = (() => {
|
|
|
8131
8258
|
throw new Error("Document image is too large. Please retake in better lighting or use a clearer photo.");
|
|
8132
8259
|
}
|
|
8133
8260
|
this.documentBlob = blob;
|
|
8134
|
-
captureContainer.innerHTML =
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;">🔍</div>
|
|
8139
|
-
</div>
|
|
8261
|
+
captureContainer.innerHTML = "";
|
|
8262
|
+
captureContainer.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:14px;padding:28px 20px;";
|
|
8263
|
+
captureContainer.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("search", 20) }));
|
|
8264
|
+
captureContainer.insertAdjacentHTML("beforeend", `
|
|
8140
8265
|
<div style="color:${this.theme.text};font-size:14px;font-weight:600;">Scanning document...</div>
|
|
8141
|
-
<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
|
|
8142
|
-
</div>`;
|
|
8266
|
+
<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>`);
|
|
8143
8267
|
const identifier = Object.values(this.collectedFields)[0] || this.idNumber || this.selectedIdType || `DOC-${Date.now()}`;
|
|
8144
8268
|
const COUNTRY_CODES = {
|
|
8145
8269
|
nigeria: "NG",
|
|
@@ -8189,15 +8313,12 @@ var SmartComplySDK = (() => {
|
|
|
8189
8313
|
retryCount++;
|
|
8190
8314
|
console.log(`Retrying document processing (attempt ${retryCount}/${maxRetries})`);
|
|
8191
8315
|
if (captureContainer) {
|
|
8192
|
-
captureContainer.innerHTML =
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:20px;">🔄</div>
|
|
8197
|
-
</div>
|
|
8316
|
+
captureContainer.innerHTML = "";
|
|
8317
|
+
captureContainer.style.cssText += "display:flex;flex-direction:column;align-items:center;gap:16px;padding:28px 20px;text-align:center;";
|
|
8318
|
+
captureContainer.appendChild(renderSpinner(this.theme, { size: 52, icon: icon("refresh", 20) }));
|
|
8319
|
+
captureContainer.insertAdjacentHTML("beforeend", `
|
|
8198
8320
|
<div style="color:${this.theme.text};font-size:14px;font-weight:600;">Retrying...</div>
|
|
8199
|
-
<div style="color:${this.theme.textSecondary};font-size:12px;max-width:240px;line-height:1.5;">Attempt ${retryCount} of ${maxRetries}</div
|
|
8200
|
-
</div>`;
|
|
8321
|
+
<div style="color:${this.theme.textSecondary};font-size:12px;max-width:240px;line-height:1.5;">Attempt ${retryCount} of ${maxRetries}</div>`);
|
|
8201
8322
|
}
|
|
8202
8323
|
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
8203
8324
|
return attemptProcessing();
|
|
@@ -8232,10 +8353,10 @@ var SmartComplySDK = (() => {
|
|
|
8232
8353
|
const wrap = document.createElement("div");
|
|
8233
8354
|
wrap.style.cssText = "display:flex;flex-direction:column;align-items:center;gap:16px;padding:28px 20px;text-align:center;";
|
|
8234
8355
|
wrap.setAttribute("role", "alert");
|
|
8235
|
-
const
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
wrap.appendChild(
|
|
8356
|
+
const icon2 = document.createElement("div");
|
|
8357
|
+
icon2.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;`;
|
|
8358
|
+
icon2.textContent = "🔍";
|
|
8359
|
+
wrap.appendChild(icon2);
|
|
8239
8360
|
const titleEl = document.createElement("div");
|
|
8240
8361
|
titleEl.style.cssText = `color:${this.theme.text};font-size:14px;font-weight:700;`;
|
|
8241
8362
|
titleEl.textContent = "Document Could Not Be Verified";
|
|
@@ -8248,7 +8369,7 @@ var SmartComplySDK = (() => {
|
|
|
8248
8369
|
const retryBtn = document.createElement("button");
|
|
8249
8370
|
retryBtn.textContent = "Try Again";
|
|
8250
8371
|
retryBtn.setAttribute("aria-label", "Retake document photo");
|
|
8251
|
-
retryBtn.style.cssText = `margin-top:8px;padding:12px 24px;border-radius
|
|
8372
|
+
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;`;
|
|
8252
8373
|
retryBtn.addEventListener("click", () => this.showStep("document_capture"));
|
|
8253
8374
|
wrap.appendChild(retryBtn);
|
|
8254
8375
|
}
|
|
@@ -8298,7 +8419,13 @@ var SmartComplySDK = (() => {
|
|
|
8298
8419
|
identity_check: this.identityCheckId || void 0,
|
|
8299
8420
|
verification_type: this.identityCheckId ? "data_verification" : this.documentBlob ? "document_verification" : "liveness_only",
|
|
8300
8421
|
// B4: pass pre-warmed stream so camera.open() is skipped
|
|
8301
|
-
prewarmedStream: this._prewarmedStream || void 0
|
|
8422
|
+
prewarmedStream: this._prewarmedStream || void 0,
|
|
8423
|
+
colors: {
|
|
8424
|
+
primary: this.theme.primary,
|
|
8425
|
+
success: this.theme.success,
|
|
8426
|
+
error: this.theme.error,
|
|
8427
|
+
warning: this.theme.warning
|
|
8428
|
+
}
|
|
8302
8429
|
},
|
|
8303
8430
|
["BLINK"],
|
|
8304
8431
|
this.livenessEntryId || void 0
|
|
@@ -8333,21 +8460,21 @@ var SmartComplySDK = (() => {
|
|
|
8333
8460
|
const isExpiredDoc = /document.*expired|expired.*document/i.test(message);
|
|
8334
8461
|
const isFaceMatch = /face.*match|selfie.*match|does not match/i.test(message);
|
|
8335
8462
|
const isBillingErr = /wallet|balance|insufficient.*fund|payment.*required/i.test(message);
|
|
8336
|
-
const
|
|
8463
|
+
const errorIconName = isCameraErr ? "camera" : isNetworkErr ? "network" : isAuthErr ? "clock" : isDocQuality ? "search" : isExpiredDoc ? "calendar" : isFaceMatch ? "face" : isBillingErr ? "warning" : "close";
|
|
8337
8464
|
const errorTitle = isCameraErr ? "Camera Access Required" : isNetworkErr ? "Connection Problem" : isAuthErr ? "Session Expired" : isDocQuality ? "Document Photo Unclear" : isExpiredDoc ? "Document Expired" : isFaceMatch ? "Face Match Failed" : isBillingErr ? "Verification Unavailable" : "Verification Unsuccessful";
|
|
8338
8465
|
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." : isBillingErr ? "Verification is temporarily unavailable. Please contact support." : _sanitizeUserMessage(message) || "We were unable to complete your verification. Please try again.";
|
|
8339
8466
|
const iconWrap = document.createElement("div");
|
|
8340
8467
|
iconWrap.style.cssText = `
|
|
8341
8468
|
width:72px;height:72px;border-radius:50%;
|
|
8342
8469
|
display:flex;align-items:center;justify-content:center;
|
|
8343
|
-
|
|
8470
|
+
color:${this.theme.error};
|
|
8344
8471
|
background:${this.theme.errorBg};
|
|
8345
8472
|
border:3px solid ${this.theme.error};
|
|
8346
8473
|
`;
|
|
8347
|
-
iconWrap.
|
|
8474
|
+
iconWrap.innerHTML = icon(errorIconName, 28);
|
|
8348
8475
|
wrapper.appendChild(iconWrap);
|
|
8349
8476
|
const title = document.createElement("h2");
|
|
8350
|
-
title.style.cssText = `color:${this.theme.text};font-size
|
|
8477
|
+
title.style.cssText = `color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;margin:0;`;
|
|
8351
8478
|
title.textContent = errorTitle;
|
|
8352
8479
|
wrapper.appendChild(title);
|
|
8353
8480
|
const desc = document.createElement("p");
|
|
@@ -8385,7 +8512,7 @@ var SmartComplySDK = (() => {
|
|
|
8385
8512
|
this.headerBackBtn.innerHTML = "←";
|
|
8386
8513
|
this.headerBackBtn.setAttribute("aria-label", "Go back to previous step");
|
|
8387
8514
|
this.headerBackBtn.style.cssText = `
|
|
8388
|
-
width:30px;height:30px;border-radius
|
|
8515
|
+
width:30px;height:30px;border-radius:${RADIUS.sm}px;flex-shrink:0;
|
|
8389
8516
|
display:none;align-items:center;justify-content:center;
|
|
8390
8517
|
border:1.5px solid ${this.theme.border};cursor:pointer;
|
|
8391
8518
|
font-size:16px;line-height:1;
|
|
@@ -8441,7 +8568,7 @@ var SmartComplySDK = (() => {
|
|
|
8441
8568
|
closeBtn.innerHTML = "✕";
|
|
8442
8569
|
closeBtn.setAttribute("aria-label", "Close identity verification");
|
|
8443
8570
|
closeBtn.style.cssText = `
|
|
8444
|
-
width:32px;height:32px;border-radius
|
|
8571
|
+
width:32px;height:32px;border-radius:${RADIUS.sm}px;flex-shrink:0;
|
|
8445
8572
|
display:flex;align-items:center;justify-content:center;
|
|
8446
8573
|
border:none;cursor:pointer;font-size:16px;
|
|
8447
8574
|
background:${this.theme.shimmer};color:${this.theme.textMuted};
|
|
@@ -8478,7 +8605,7 @@ var SmartComplySDK = (() => {
|
|
|
8478
8605
|
createStepTitle(text) {
|
|
8479
8606
|
const el = document.createElement("h3");
|
|
8480
8607
|
el.style.cssText = `
|
|
8481
|
-
color:${this.theme.text};font-size
|
|
8608
|
+
color:${this.theme.text};font-size:${TYPE.heading}px;font-weight:700;
|
|
8482
8609
|
margin:0;
|
|
8483
8610
|
`;
|
|
8484
8611
|
el.textContent = text;
|
|
@@ -8488,7 +8615,7 @@ var SmartComplySDK = (() => {
|
|
|
8488
8615
|
const card = document.createElement("button");
|
|
8489
8616
|
card.setAttribute("aria-label", subtitle ? `${title}: ${subtitle}` : title);
|
|
8490
8617
|
card.style.cssText = `
|
|
8491
|
-
width:100%;padding:13px 16px;border-radius
|
|
8618
|
+
width:100%;padding:13px 16px;border-radius:${RADIUS.md}px;
|
|
8492
8619
|
background:${this.theme.cardBg};
|
|
8493
8620
|
border:2px solid ${this.theme.border};
|
|
8494
8621
|
cursor:pointer;text-align:left;
|
|
@@ -8528,7 +8655,7 @@ var SmartComplySDK = (() => {
|
|
|
8528
8655
|
const btn = document.createElement("button");
|
|
8529
8656
|
btn.textContent = text;
|
|
8530
8657
|
btn.style.cssText = `
|
|
8531
|
-
width:100%;padding:14px;border-radius
|
|
8658
|
+
width:100%;padding:14px;border-radius:${RADIUS.md}px;
|
|
8532
8659
|
font-size:15px;font-weight:600;
|
|
8533
8660
|
background:${this.theme.primary};color:#fff;
|
|
8534
8661
|
border:none;cursor:pointer;
|
|
@@ -8549,7 +8676,7 @@ var SmartComplySDK = (() => {
|
|
|
8549
8676
|
const btn = document.createElement("button");
|
|
8550
8677
|
btn.textContent = text;
|
|
8551
8678
|
btn.style.cssText = `
|
|
8552
|
-
width:100%;padding:12px;border-radius
|
|
8679
|
+
width:100%;padding:12px;border-radius:${RADIUS.md}px;
|
|
8553
8680
|
font-size:14px;font-weight:500;
|
|
8554
8681
|
background:transparent;color:${this.theme.textSecondary};
|
|
8555
8682
|
border:none;cursor:pointer;
|
|
@@ -8665,12 +8792,9 @@ var SmartComplySDK = (() => {
|
|
|
8665
8792
|
}
|
|
8666
8793
|
injectStyles() {
|
|
8667
8794
|
if (document.getElementById("sc-flow-styles")) return;
|
|
8668
|
-
const
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
@keyframes sc-spin {
|
|
8672
|
-
to { transform: rotate(360deg); }
|
|
8673
|
-
}
|
|
8795
|
+
const style = document.createElement("style");
|
|
8796
|
+
style.id = "sc-flow-styles";
|
|
8797
|
+
style.textContent = `
|
|
8674
8798
|
@keyframes sc-pop {
|
|
8675
8799
|
0% { transform: scale(0.8); opacity: 0; }
|
|
8676
8800
|
50% { transform: scale(1.05); }
|
|
@@ -8696,7 +8820,7 @@ var SmartComplySDK = (() => {
|
|
|
8696
8820
|
border-radius: 4px;
|
|
8697
8821
|
}
|
|
8698
8822
|
`;
|
|
8699
|
-
document.head.appendChild(
|
|
8823
|
+
document.head.appendChild(style);
|
|
8700
8824
|
}
|
|
8701
8825
|
};
|
|
8702
8826
|
_SmartComplyFlow.MAX_RETRIES = 3;
|