@flonkid/kyc 1.5.1 → 1.6.1

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/index.js CHANGED
@@ -1,8 +1,12 @@
1
1
  import { useRef, useMemo, useEffect } from 'react';
2
- import { jsx } from 'react/jsx-runtime';
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
3
7
 
4
8
  // src/shared/constants.ts
5
- var SDK_VERSION = "1.5.1";
9
+ var SDK_VERSION = "1.6.0";
6
10
  var DEFAULT_WIDGET_URL = "https://widget.flonk.id";
7
11
  var DEFAULT_API_BASE = "https://api.flonk.id/v1";
8
12
  var WIDGET_EVENTS = {
@@ -13,20 +17,25 @@ var WIDGET_EVENTS = {
13
17
  };
14
18
 
15
19
  // src/shared/errors.ts
16
- var FlonkError = class extends Error {
20
+ var _FlonkError = class _FlonkError extends Error {
17
21
  constructor(message, code, statusCode) {
18
22
  super(message);
19
- this.code = code;
20
- this.statusCode = statusCode;
23
+ __publicField(this, "code");
24
+ __publicField(this, "statusCode");
25
+ this.code = code, this.statusCode = statusCode;
21
26
  this.name = "FlonkError";
22
27
  }
23
28
  };
24
- var FlonkValidationError = class extends FlonkError {
29
+ __name(_FlonkError, "FlonkError");
30
+ var FlonkError = _FlonkError;
31
+ var _FlonkValidationError = class _FlonkValidationError extends FlonkError {
25
32
  constructor(message) {
26
33
  super(message, "validation_error", 400);
27
34
  this.name = "FlonkValidationError";
28
35
  }
29
36
  };
37
+ __name(_FlonkValidationError, "FlonkValidationError");
38
+ var FlonkValidationError = _FlonkValidationError;
30
39
 
31
40
  // src/browser/utils.ts
32
41
  function getOrigin(url) {
@@ -36,12 +45,15 @@ function getOrigin(url) {
36
45
  return window.location.origin;
37
46
  }
38
47
  }
48
+ __name(getOrigin, "getOrigin");
39
49
  function isDesktop() {
40
50
  return window.innerWidth >= 1024 && !("ontouchstart" in window || navigator.maxTouchPoints > 0);
41
51
  }
52
+ __name(isDesktop, "isDesktop");
42
53
  function setStyles(el, styles) {
43
54
  Object.assign(el.style, styles);
44
55
  }
56
+ __name(setStyles, "setStyles");
45
57
  function createEl(tag, styles, attrs) {
46
58
  const el = document.createElement(tag);
47
59
  if (styles) setStyles(el, styles);
@@ -50,13 +62,15 @@ function createEl(tag, styles, attrs) {
50
62
  }
51
63
  return el;
52
64
  }
65
+ __name(createEl, "createEl");
53
66
  function debounce(fn, ms) {
54
67
  let timer;
55
- return ((...args) => {
68
+ return (...args) => {
56
69
  clearTimeout(timer);
57
70
  timer = setTimeout(() => fn(...args), ms);
58
- });
71
+ };
59
72
  }
73
+ __name(debounce, "debounce");
60
74
  function generateSecondaryColor(hex) {
61
75
  try {
62
76
  const h = hex.replace("#", "");
@@ -64,18 +78,21 @@ function generateSecondaryColor(hex) {
64
78
  const g = parseInt(h.substring(2, 4), 16);
65
79
  const b = parseInt(h.substring(4, 6), 16);
66
80
  const f = 0.6;
67
- const toHex = (n) => {
81
+ const toHex = /* @__PURE__ */ __name((n) => {
68
82
  const s = n.toString(16);
69
83
  return s.length === 1 ? "0" + s : s;
70
- };
84
+ }, "toHex");
71
85
  return "#" + toHex(Math.round(r + (255 - r) * f)) + toHex(Math.round(g + (255 - g) * f)) + toHex(Math.round(b + (255 - b) * f));
72
86
  } catch {
73
87
  return "#93c5fd";
74
88
  }
75
89
  }
90
+ __name(generateSecondaryColor, "generateSecondaryColor");
76
91
  async function fetchWidgetToken(pk, apiBase) {
77
92
  const res = await fetch(`${apiBase}/public/widget-token`, {
78
- headers: { "x-kyc-pk": pk },
93
+ headers: {
94
+ "x-kyc-pk": pk
95
+ },
79
96
  credentials: "include"
80
97
  });
81
98
  if (!res.ok) {
@@ -89,6 +106,7 @@ async function fetchWidgetToken(pk, apiBase) {
89
106
  }
90
107
  return res.json();
91
108
  }
109
+ __name(fetchWidgetToken, "fetchWidgetToken");
92
110
  async function fetchDesignTokens(apiBase, opts) {
93
111
  const params = [];
94
112
  if (opts.sessionId) params.push(`sessionId=${encodeURIComponent(opts.sessionId)}`);
@@ -96,7 +114,9 @@ async function fetchDesignTokens(apiBase, opts) {
96
114
  const url = `${apiBase}/public/design-tokens${params.length ? "?" + params.join("&") : ""}`;
97
115
  try {
98
116
  const res = await fetch(url, {
99
- headers: opts.pk ? { "x-kyc-pk": opts.pk } : {},
117
+ headers: opts.pk ? {
118
+ "x-kyc-pk": opts.pk
119
+ } : {},
100
120
  credentials: "omit"
101
121
  });
102
122
  return res.ok ? res.json() : null;
@@ -104,28 +124,33 @@ async function fetchDesignTokens(apiBase, opts) {
104
124
  return null;
105
125
  }
106
126
  }
127
+ __name(fetchDesignTokens, "fetchDesignTokens");
107
128
  function validateServerUrl(url) {
108
129
  if (url.startsWith("/")) return;
109
130
  try {
110
131
  const parsed = new URL(url);
111
132
  const isLocalhost = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1";
112
133
  if (parsed.protocol !== "https:" && !isLocalhost) {
113
- throw new Error(
114
- `serverUrl must use HTTPS in production. Got: ${parsed.protocol}//. Use HTTPS ('https://api.myapp.com/...') or a relative path ('/api/...')`
115
- );
134
+ throw new Error(`serverUrl must use HTTPS in production. Got: ${parsed.protocol}//. Use HTTPS ('https://api.myapp.com/...') or a relative path ('/api/...')`);
116
135
  }
117
136
  } catch (e) {
118
137
  if (e.message.includes("serverUrl must use HTTPS")) throw e;
119
138
  throw new Error(`Invalid serverUrl: ${url}`);
120
139
  }
121
140
  }
141
+ __name(validateServerUrl, "validateServerUrl");
122
142
  async function fetchSessionFromServer(serverUrl, clientMetadata, requestHeaders) {
123
143
  validateServerUrl(serverUrl);
124
144
  const res = await fetch(serverUrl, {
125
145
  method: "POST",
126
- headers: { "Content-Type": "application/json", ...requestHeaders },
146
+ headers: {
147
+ "Content-Type": "application/json",
148
+ ...requestHeaders
149
+ },
127
150
  credentials: "include",
128
- body: JSON.stringify({ clientMetadata })
151
+ body: JSON.stringify({
152
+ clientMetadata
153
+ })
129
154
  });
130
155
  if (!res.ok) {
131
156
  let message = `Session request failed (${res.status})`;
@@ -139,6 +164,7 @@ async function fetchSessionFromServer(serverUrl, clientMetadata, requestHeaders)
139
164
  }
140
165
  return res.json();
141
166
  }
167
+ __name(fetchSessionFromServer, "fetchSessionFromServer");
142
168
  async function fetchPublicSession(apiBase, sessionId, embedToken) {
143
169
  const res = await fetch(`${apiBase}/public/session/${sessionId}`, {
144
170
  headers: {
@@ -157,10 +183,13 @@ async function fetchPublicSession(apiBase, sessionId, embedToken) {
157
183
  }
158
184
  return res.json();
159
185
  }
186
+ __name(fetchPublicSession, "fetchPublicSession");
160
187
  async function exchangeSessionForToken(apiBase, sessionId) {
161
188
  const res = await fetch(`${apiBase}/public/session/${sessionId}/token`, {
162
189
  method: "POST",
163
- headers: { "Content-Type": "application/json" }
190
+ headers: {
191
+ "Content-Type": "application/json"
192
+ }
164
193
  });
165
194
  if (!res.ok) {
166
195
  let message = `Token exchange failed (${res.status})`;
@@ -173,36 +202,33 @@ async function exchangeSessionForToken(apiBase, sessionId) {
173
202
  }
174
203
  return res.json();
175
204
  }
205
+ __name(exchangeSessionForToken, "exchangeSessionForToken");
176
206
 
177
207
  // src/browser/iframe-manager.ts
178
208
  function createIframe(src) {
179
209
  const d = isDesktop();
180
- const iframe = createEl(
181
- "iframe",
182
- {
183
- border: "0",
184
- width: window.innerWidth + "px",
185
- height: window.innerHeight + "px",
186
- position: "fixed",
187
- top: "0",
188
- left: "0",
189
- zIndex: "9999",
190
- background: "transparent",
191
- backgroundColor: "transparent",
192
- opacity: "0",
193
- visibility: "hidden",
194
- borderRadius: d ? "0" : "",
195
- boxShadow: d ? "none" : "",
196
- colorScheme: "normal"
197
- },
198
- {
199
- src,
200
- allow: "camera;microphone;clipboard-read;clipboard-write",
201
- sandbox: "allow-scripts allow-forms allow-same-origin allow-popups",
202
- "aria-label": "KYC Verification",
203
- allowtransparency: "true"
204
- }
205
- );
210
+ const iframe = createEl("iframe", {
211
+ border: "0",
212
+ width: window.innerWidth + "px",
213
+ height: window.innerHeight + "px",
214
+ position: "fixed",
215
+ top: "0",
216
+ left: "0",
217
+ zIndex: "9999",
218
+ background: "transparent",
219
+ backgroundColor: "transparent",
220
+ opacity: "0",
221
+ visibility: "hidden",
222
+ borderRadius: d ? "0" : "",
223
+ boxShadow: d ? "none" : "",
224
+ colorScheme: "normal"
225
+ }, {
226
+ src,
227
+ allow: "camera;microphone;clipboard-read;clipboard-write",
228
+ sandbox: "allow-scripts allow-forms allow-same-origin allow-popups",
229
+ "aria-label": "KYC Verification",
230
+ allowtransparency: "true"
231
+ });
206
232
  try {
207
233
  iframe.style.setProperty("background", "transparent", "important");
208
234
  iframe.style.setProperty("background-color", "transparent", "important");
@@ -211,21 +237,24 @@ function createIframe(src) {
211
237
  }
212
238
  return iframe;
213
239
  }
240
+ __name(createIframe, "createIframe");
214
241
  function adjustZIndex(loader, iframe) {
215
242
  if (!isDesktop()) return;
216
243
  const all = Array.from(document.querySelectorAll("*"));
217
- const maxZ = Math.max(
218
- ...all.map((el) => parseInt(getComputedStyle(el).zIndex) || 0).filter((z) => z < 999999)
219
- );
244
+ const maxZ = Math.max(...all.map((el) => parseInt(getComputedStyle(el).zIndex) || 0).filter((z) => z < 999999));
220
245
  if (maxZ > 9998) {
221
246
  loader.style.zIndex = String(maxZ + 1);
222
247
  iframe.style.zIndex = String(maxZ + 2);
223
248
  }
224
249
  }
250
+ __name(adjustZIndex, "adjustZIndex");
225
251
  function transitionLoaderToIframe(loader, iframe, onDone) {
226
252
  const d = isDesktop();
227
253
  const dur = d ? 300 : 500;
228
- setStyles(iframe, { opacity: "0", visibility: "hidden" });
254
+ setStyles(iframe, {
255
+ opacity: "0",
256
+ visibility: "hidden"
257
+ });
229
258
  const card = loader.querySelector("div");
230
259
  if (card) {
231
260
  setStyles(card, {
@@ -243,12 +272,28 @@ function transitionLoaderToIframe(loader, iframe, onDone) {
243
272
  });
244
273
  }, dur);
245
274
  }
275
+ __name(transitionLoaderToIframe, "transitionLoaderToIframe");
246
276
 
247
277
  // src/browser/loader.ts
248
278
  var LOADER_I18N = {
249
- en: { title: "Initializing...", subtitle: "Loading KYC widget", errorTitle: "Something went wrong", close: "Close" },
250
- de: { title: "Initialisierung...", subtitle: "KYC-Widget wird geladen", errorTitle: "Ein Fehler ist aufgetreten", close: "Schlie\xDFen" },
251
- uk: { title: "\u0406\u043D\u0456\u0446\u0456\u0430\u043B\u0456\u0437\u0430\u0446\u0456\u044F...", subtitle: "\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F KYC-\u0432\u0456\u0434\u0436\u0435\u0442\u0430", errorTitle: "\u0429\u043E\u0441\u044C \u043F\u0456\u0448\u043B\u043E \u043D\u0435 \u0442\u0430\u043A", close: "\u0417\u0430\u043A\u0440\u0438\u0442\u0438" }
279
+ en: {
280
+ title: "Initializing...",
281
+ subtitle: "Loading KYC widget",
282
+ errorTitle: "Something went wrong",
283
+ close: "Close"
284
+ },
285
+ de: {
286
+ title: "Initialisierung...",
287
+ subtitle: "KYC-Widget wird geladen",
288
+ errorTitle: "Ein Fehler ist aufgetreten",
289
+ close: "Schlie\xDFen"
290
+ },
291
+ uk: {
292
+ title: "\u0406\u043D\u0456\u0446\u0456\u0430\u043B\u0456\u0437\u0430\u0446\u0456\u044F...",
293
+ subtitle: "\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F KYC-\u0432\u0456\u0434\u0436\u0435\u0442\u0430",
294
+ errorTitle: "\u0429\u043E\u0441\u044C \u043F\u0456\u0448\u043B\u043E \u043D\u0435 \u0442\u0430\u043A",
295
+ close: "\u0417\u0430\u043A\u0440\u0438\u0442\u0438"
296
+ }
252
297
  };
253
298
  var KEYFRAMES = `
254
299
  @keyframes kycspin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
@@ -256,11 +301,11 @@ var KEYFRAMES = `
256
301
  @keyframes kycprogress{0%{transform:translateX(-100%)}50%{transform:translateX(0%)}100%{transform:translateX(250%)}}
257
302
  `.trim();
258
303
  var styleInjected = false;
259
- var Loader = class {
304
+ var _Loader = class _Loader {
260
305
  constructor() {
261
- this.overlay = null;
262
- this.cleanup = null;
263
- this.origBodyStyles = null;
306
+ __publicField(this, "overlay", null);
307
+ __publicField(this, "cleanup", null);
308
+ __publicField(this, "origBodyStyles", null);
264
309
  }
265
310
  show(primaryColor, lang) {
266
311
  const color = primaryColor || "#15BA68";
@@ -339,23 +384,64 @@ var Loader = class {
339
384
  "stroke-dasharray": "62.8",
340
385
  "stroke-dashoffset": "15.7"
341
386
  })) fg.setAttribute(k, v);
342
- setStyles(fg, { transformOrigin: "center", animation: "kycdash 1.5s ease-in-out infinite" });
387
+ setStyles(fg, {
388
+ transformOrigin: "center",
389
+ animation: "kycdash 1.5s ease-in-out infinite"
390
+ });
343
391
  svg.append(bg, fg);
344
392
  wrap.appendChild(svg);
345
393
  const font = 'Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif';
346
- const textBox = createEl("div", { textAlign: "center" });
347
- const title = createEl("h3", { fontFamily: font, fontWeight: "600", fontSize: "18px", lineHeight: "1.3", color: "#1F2937", margin: "0 0 4px 0" });
394
+ const textBox = createEl("div", {
395
+ textAlign: "center"
396
+ });
397
+ const title = createEl("h3", {
398
+ fontFamily: font,
399
+ fontWeight: "600",
400
+ fontSize: "18px",
401
+ lineHeight: "1.3",
402
+ color: "#1F2937",
403
+ margin: "0 0 4px 0"
404
+ });
348
405
  title.textContent = strings.title;
349
- const subtitle = createEl("p", { fontFamily: font, fontWeight: "400", fontSize: "13px", lineHeight: "1.4", color: "rgba(31,41,55,0.7)", margin: "0" });
406
+ const subtitle = createEl("p", {
407
+ fontFamily: font,
408
+ fontWeight: "400",
409
+ fontSize: "13px",
410
+ lineHeight: "1.4",
411
+ color: "rgba(31,41,55,0.7)",
412
+ margin: "0"
413
+ });
350
414
  subtitle.textContent = strings.subtitle;
351
415
  textBox.append(title, subtitle);
352
- const track = createEl("div", { width: "100%", maxWidth: "240px", height: "3px", backgroundColor: color + "1A", borderRadius: "2px", overflow: "hidden" });
353
- const bar = createEl("div", { width: "40%", height: "100%", backgroundColor: color, borderRadius: "2px", transform: "translateX(-100%)", animation: "kycprogress 2000ms ease-in-out infinite" });
416
+ const track = createEl("div", {
417
+ width: "100%",
418
+ maxWidth: "240px",
419
+ height: "3px",
420
+ backgroundColor: color + "1A",
421
+ borderRadius: "2px",
422
+ overflow: "hidden"
423
+ });
424
+ const bar = createEl("div", {
425
+ width: "40%",
426
+ height: "100%",
427
+ backgroundColor: color,
428
+ borderRadius: "2px",
429
+ transform: "translateX(-100%)",
430
+ animation: "kycprogress 2000ms ease-in-out infinite"
431
+ });
354
432
  track.appendChild(bar);
355
433
  card.append(wrap, textBox, track);
356
434
  overlay.appendChild(card);
357
- this.origBodyStyles = { overflow: document.body.style.overflow, position: document.body.style.position };
358
- setStyles(document.body, { overflow: "hidden", position: "fixed", width: "100%", height: "100%" });
435
+ this.origBodyStyles = {
436
+ overflow: document.body.style.overflow,
437
+ position: document.body.style.position
438
+ };
439
+ setStyles(document.body, {
440
+ overflow: "hidden",
441
+ position: "fixed",
442
+ width: "100%",
443
+ height: "100%"
444
+ });
359
445
  document.body.appendChild(overlay);
360
446
  let prevW = window.innerWidth;
361
447
  let prevH = window.innerHeight;
@@ -363,7 +449,10 @@ var Loader = class {
363
449
  const w = window.innerWidth;
364
450
  const h = window.innerHeight;
365
451
  if (Math.abs(w - prevW) > 1 || Math.abs(h - prevH) > 1) {
366
- setStyles(overlay, { width: w + "px", height: h + "px" });
452
+ setStyles(overlay, {
453
+ width: w + "px",
454
+ height: h + "px"
455
+ });
367
456
  prevW = w;
368
457
  prevH = h;
369
458
  }
@@ -373,7 +462,11 @@ var Loader = class {
373
462
  this.cleanup = () => {
374
463
  window.removeEventListener("resize", onResize);
375
464
  if (this.origBodyStyles) {
376
- setStyles(document.body, { ...this.origBodyStyles, width: "", height: "" });
465
+ setStyles(document.body, {
466
+ ...this.origBodyStyles,
467
+ width: "",
468
+ height: ""
469
+ });
377
470
  }
378
471
  };
379
472
  return overlay;
@@ -381,6 +474,18 @@ var Loader = class {
381
474
  get element() {
382
475
  return this.overlay;
383
476
  }
477
+ updateColor(primaryColor) {
478
+ if (!this.overlay) return;
479
+ const color = primaryColor || "#15BA68";
480
+ const bgCircle = this.overlay.querySelector("circle:first-child");
481
+ const fgCircle = this.overlay.querySelector("circle:last-child");
482
+ const bar = this.overlay.querySelector('[style*="kycprogress"]');
483
+ if (bgCircle) bgCircle.setAttribute("stroke", color + "33");
484
+ if (fgCircle) fgCircle.setAttribute("stroke", color);
485
+ if (bar) bar.style.backgroundColor = color;
486
+ const track = bar?.parentElement;
487
+ if (track) track.style.backgroundColor = color + "1A";
488
+ }
384
489
  showError(message, lang) {
385
490
  if (!this.overlay) return;
386
491
  const strings = LOADER_I18N[lang || ""] || LOADER_I18N.en;
@@ -481,20 +586,25 @@ var Loader = class {
481
586
  this.cleanup = null;
482
587
  }
483
588
  };
589
+ __name(_Loader, "Loader");
590
+ var Loader = _Loader;
484
591
 
485
592
  // src/browser/message-handler.ts
486
- var MessageHandler = class {
593
+ var _MessageHandler = class _MessageHandler {
487
594
  constructor(iframeSrc, iframe, callbacks) {
595
+ __publicField(this, "iframeSrc");
596
+ __publicField(this, "iframe");
597
+ __publicField(this, "callbacks");
598
+ __publicField(this, "listener", null);
599
+ __publicField(this, "readyListener", null);
600
+ __publicField(this, "completionHandled", false);
488
601
  this.iframeSrc = iframeSrc;
489
602
  this.iframe = iframe;
490
603
  this.callbacks = callbacks;
491
- this.listener = null;
492
- this.readyListener = null;
493
- this.completionHandled = false;
494
604
  }
495
605
  /**
496
- * Start listening for postMessage events from the widget iframe.
497
- */
606
+ * Start listening for postMessage events from the widget iframe.
607
+ */
498
608
  listen() {
499
609
  const origin = getOrigin(this.iframeSrc);
500
610
  this.listener = (e) => {
@@ -524,8 +634,8 @@ var MessageHandler = class {
524
634
  window.addEventListener("message", this.listener);
525
635
  }
526
636
  /**
527
- * Listen for the first READY event, then call the callback once.
528
- */
637
+ * Listen for the first READY event, then call the callback once.
638
+ */
529
639
  onReadyOnce(callback) {
530
640
  const origin = getOrigin(this.iframeSrc);
531
641
  this.readyListener = (e) => {
@@ -547,6 +657,8 @@ var MessageHandler = class {
547
657
  }
548
658
  }
549
659
  };
660
+ __name(_MessageHandler, "MessageHandler");
661
+ var MessageHandler = _MessageHandler;
550
662
 
551
663
  // src/browser/viewport.ts
552
664
  function getVV() {
@@ -558,8 +670,14 @@ function getVV() {
558
670
  offsetLeft: window.visualViewport.offsetLeft || 0
559
671
  };
560
672
  }
561
- return { width: window.innerWidth, height: window.innerHeight, offsetTop: 0, offsetLeft: 0 };
673
+ return {
674
+ width: window.innerWidth,
675
+ height: window.innerHeight,
676
+ offsetTop: 0,
677
+ offsetLeft: 0
678
+ };
562
679
  }
680
+ __name(getVV, "getVV");
563
681
  function ensureViewportMeta() {
564
682
  try {
565
683
  const meta = document.querySelector('meta[name="viewport"]');
@@ -577,31 +695,42 @@ function ensureViewportMeta() {
577
695
  } catch {
578
696
  }
579
697
  }
698
+ __name(ensureViewportMeta, "ensureViewportMeta");
580
699
  function setupViewportSizing(overlay, iframe) {
581
700
  ensureViewportMeta();
582
701
  let baselineHeight = 0;
583
702
  let desktop = isDesktop();
584
703
  let rafId = null;
585
- const initBaseline = () => {
704
+ const initBaseline = /* @__PURE__ */ __name(() => {
586
705
  const vv = getVV();
587
706
  baselineHeight = window.innerHeight || vv.height || document.documentElement.clientHeight || 0;
588
707
  desktop = isDesktop();
589
708
  if (rafId) cancelAnimationFrame(rafId);
590
709
  rafId = requestAnimationFrame(applySize);
591
- };
592
- const applySize = () => {
710
+ }, "initBaseline");
711
+ const applySize = /* @__PURE__ */ __name(() => {
593
712
  try {
594
713
  const vv = getVV();
595
714
  const inner = window.innerHeight || vv.height;
596
715
  const kbThreshold = desktop ? 200 : 150;
597
716
  const isKeyboard = inner - vv.height > kbThreshold;
598
717
  const height = isKeyboard ? vv.height : baselineHeight || inner;
599
- const dims = desktop ? { top: "0", left: "0", width: window.innerWidth + "px", height: window.innerHeight + "px" } : { top: vv.offsetTop + "px", left: vv.offsetLeft + "px", width: vv.width + "px", height: height + "px" };
718
+ const dims = desktop ? {
719
+ top: "0",
720
+ left: "0",
721
+ width: window.innerWidth + "px",
722
+ height: window.innerHeight + "px"
723
+ } : {
724
+ top: vv.offsetTop + "px",
725
+ left: vv.offsetLeft + "px",
726
+ width: vv.width + "px",
727
+ height: height + "px"
728
+ };
600
729
  if (overlay) setStyles(overlay, dims);
601
730
  if (iframe) setStyles(iframe, dims);
602
731
  } catch {
603
732
  }
604
- };
733
+ }, "applySize");
605
734
  let prevW = window.innerWidth;
606
735
  let prevH = window.innerHeight;
607
736
  let prevX = 0;
@@ -610,7 +739,7 @@ function setupViewportSizing(overlay, iframe) {
610
739
  if (rafId) cancelAnimationFrame(rafId);
611
740
  rafId = requestAnimationFrame(applySize);
612
741
  }, desktop ? 50 : 150);
613
- const handleResize = () => {
742
+ const handleResize = /* @__PURE__ */ __name(() => {
614
743
  const vv = getVV();
615
744
  const w = vv.width;
616
745
  const h = vv.height;
@@ -629,12 +758,12 @@ function setupViewportSizing(overlay, iframe) {
629
758
  } else {
630
759
  debouncedApply();
631
760
  }
632
- };
633
- const handleOrientation = () => {
761
+ }, "handleResize");
762
+ const handleOrientation = /* @__PURE__ */ __name(() => {
634
763
  initBaseline();
635
764
  if (rafId) cancelAnimationFrame(rafId);
636
765
  rafId = requestAnimationFrame(applySize);
637
- };
766
+ }, "handleOrientation");
638
767
  initBaseline();
639
768
  applySize();
640
769
  window.addEventListener("resize", handleResize);
@@ -656,22 +785,26 @@ function setupViewportSizing(overlay, iframe) {
656
785
  }
657
786
  };
658
787
  }
788
+ __name(setupViewportSizing, "setupViewportSizing");
659
789
 
660
790
  // src/browser/index.ts
661
- var FlonkKYC = class {
791
+ var _FlonkKYC = class _FlonkKYC {
662
792
  constructor(options = {}) {
793
+ __publicField(this, "widgetUrl");
794
+ __publicField(this, "apiBase");
663
795
  this.widgetUrl = (options.widgetUrl || DEFAULT_WIDGET_URL).replace(/\/$/, "");
664
796
  this.apiBase = (options.apiBase || DEFAULT_API_BASE).replace(/\/$/, "");
665
797
  }
666
798
  // ── Public API ───────────────────────────────────────
667
799
  /**
668
- * Open the KYC verification widget.
669
- *
670
- * Flows (pick one):
671
- * 1. `{ serverUrl }` — auto-create session via your backend (recommended)
672
- * 2. `{ sessionId, embedToken }` server-to-server with pre-created session
673
- * 3. `{ publishableKey }` — client-side only
674
- */
800
+ * Open the KYC verification widget.
801
+ *
802
+ * Flows (pick one):
803
+ * 1. `{ serverUrl, publishableKey }` — auto-create session via your backend (recommended).
804
+ * `publishableKey` enables instant branded loader (~200-500ms faster).
805
+ * 2. `{ sessionId, embedToken }` — server-to-server with pre-created session
806
+ * 3. `{ publishableKey }` — client-side only (legacy)
807
+ */
675
808
  async init(config) {
676
809
  if (!config) throw new FlonkValidationError("config is required");
677
810
  if (config.serverUrl) {
@@ -685,17 +818,18 @@ var FlonkKYC = class {
685
818
  }
686
819
  const pk = config.publishableKey;
687
820
  if (!pk || !/^pk_/.test(pk)) {
688
- throw new FlonkValidationError(
689
- "Provide one of: serverUrl, sessionId + embedToken, or publishableKey (pk_*)"
690
- );
821
+ throw new FlonkValidationError("Provide one of: serverUrl, sessionId + embedToken, or publishableKey (pk_*)");
691
822
  }
692
823
  return this.initWithPublishableKey(config);
693
824
  }
694
825
  /**
695
- * Preview mode — no API calls, mock data.
696
- */
826
+ * Preview mode — no API calls, mock data.
827
+ */
697
828
  preview(config = {}) {
698
- const colors = config.colors || { primaryColor: "#3b82f6", secondaryColor: "#93c5fd" };
829
+ const colors = config.colors || {
830
+ primaryColor: "#3b82f6",
831
+ secondaryColor: "#93c5fd"
832
+ };
699
833
  return this.openWidget({
700
834
  mode: "preview",
701
835
  isPreview: "true",
@@ -713,17 +847,20 @@ var FlonkKYC = class {
713
847
  });
714
848
  }
715
849
  /**
716
- * Embed inline preview in a container (for dashboards).
717
- */
850
+ * Embed inline preview in a container (for dashboards).
851
+ */
718
852
  embed(config) {
719
853
  if (!config?.container) throw new FlonkValidationError("container is required");
720
854
  const container = typeof config.container === "string" ? document.querySelector(config.container) : config.container;
721
855
  if (!container) throw new FlonkValidationError("Container element not found");
722
- let colors = config.colors || { primaryColor: "#3b82f6", secondaryColor: "#93c5fd" };
856
+ let colors = config.colors || {
857
+ primaryColor: "#3b82f6",
858
+ secondaryColor: "#93c5fd"
859
+ };
723
860
  let device = config.device || "mobile";
724
861
  let scale = config.scale ?? 1;
725
862
  const lang = config.lang || "de";
726
- const buildSrc = (c, d) => {
863
+ const buildSrc = /* @__PURE__ */ __name((c, d) => {
727
864
  const p = new URLSearchParams({
728
865
  mode: "preview",
729
866
  isPreview: "true",
@@ -734,11 +871,11 @@ var FlonkKYC = class {
734
871
  lang
735
872
  });
736
873
  return `${this.widgetUrl}/?${p.toString()}`;
737
- };
738
- const applyScale = () => {
874
+ }, "buildSrc");
875
+ const applyScale = /* @__PURE__ */ __name(() => {
739
876
  iframe.style.transform = scale !== 1 ? `scale(${scale})` : "";
740
877
  iframe.style.transformOrigin = scale !== 1 ? "top left" : "";
741
- };
878
+ }, "applyScale");
742
879
  const iframe = document.createElement("iframe");
743
880
  iframe.style.cssText = "border:none;width:100%;height:100%;display:block";
744
881
  iframe.src = buildSrc(colors, device);
@@ -750,7 +887,10 @@ var FlonkKYC = class {
750
887
  return {
751
888
  iframe,
752
889
  setColors(newColors) {
753
- colors = { ...colors, ...newColors };
890
+ colors = {
891
+ ...colors,
892
+ ...newColors
893
+ };
754
894
  if (newColors.primaryColor && !newColors.secondaryColor) {
755
895
  colors.secondaryColor = generateSecondaryColor(newColors.primaryColor);
756
896
  }
@@ -760,39 +900,67 @@ var FlonkKYC = class {
760
900
  device = d;
761
901
  iframe.src = buildSrc(colors, device);
762
902
  },
763
- getColors: () => ({ ...colors }),
764
- destroy: () => iframe.remove()
903
+ getColors: /* @__PURE__ */ __name(() => ({
904
+ ...colors
905
+ }), "getColors"),
906
+ destroy: /* @__PURE__ */ __name(() => iframe.remove(), "destroy")
765
907
  };
766
908
  }
767
909
  // ── Private flows ────────────────────────────────────
768
910
  /**
769
- * Flow 1: serverUrl — POST to client's backend, get sessionId + embedToken.
770
- */
771
- /**
772
- * POST to serverUrl to get sessionId + embedToken, then same path as embed token flow.
773
- * No loader here avoids wrong brand color before design tokens exist; initWithEmbedToken
774
- * fetches tokens first, then shows loader with project primary color.
775
- */
911
+ * Flow 1: serverUrl — POST to client's backend, get sessionId + embedToken.
912
+ *
913
+ * When `publishableKey` is provided, design tokens are fetched in parallel
914
+ * with the session creation request. This shows the branded loader ~200-500ms
915
+ * faster because we don't have to wait for the session to be created first.
916
+ */
776
917
  async initWithServerUrl(config) {
918
+ const pk = config.publishableKey;
919
+ const designTokensPromise = pk ? fetchDesignTokens(this.apiBase, {
920
+ pk
921
+ }) : Promise.resolve(null);
922
+ const sessionPromise = fetchSessionFromServer(config.serverUrl, config.clientMetadata, config.requestHeaders);
923
+ const earlyTokens = await Promise.race([
924
+ designTokensPromise,
925
+ new Promise((resolve) => setTimeout(() => resolve(null), 800))
926
+ ]);
927
+ const primaryColor = earlyTokens?.colors?.primary?.cannabis || "#15BA68";
928
+ const loader = new Loader();
929
+ loader.show(primaryColor, config.lang);
777
930
  try {
778
- const { sessionId, embedToken } = await fetchSessionFromServer(
779
- config.serverUrl,
780
- config.clientMetadata,
781
- config.requestHeaders
782
- );
783
- return this.initWithEmbedToken({ ...config, sessionId, embedToken });
931
+ const [{ sessionId, embedToken }, designTokens] = await Promise.all([
932
+ sessionPromise,
933
+ designTokensPromise
934
+ ]);
935
+ const finalTokens = designTokens ?? await fetchDesignTokens(this.apiBase, {
936
+ sessionId
937
+ });
938
+ const finalColor = finalTokens?.colors?.primary?.cannabis || "#15BA68";
939
+ if (finalColor !== primaryColor) loader.updateColor(finalColor);
940
+ const sessionData = await fetchPublicSession(this.apiBase, sessionId, embedToken);
941
+ const session = {
942
+ id: sessionData.id,
943
+ allowManualUpload: sessionData.allowManualUpload ?? config.allowManualUpload ?? true,
944
+ clientMetadata: sessionData.clientMetadata || config.clientMetadata,
945
+ qrCodeUrl: sessionData.qrCodeUrl,
946
+ testMode: sessionData.testMode || false,
947
+ poaEnabled: sessionData.poaEnabled || false,
948
+ poaRequired: sessionData.poaRequired || false,
949
+ mlAutoCaptureEnabled: sessionData.mlAutoCaptureEnabled || false,
950
+ mlCropEnabled: sessionData.mlCropEnabled ?? true,
951
+ mlVerifyEnabled: sessionData.mlVerifyEnabled || false
952
+ };
953
+ return this.buildWidget(embedToken, session, config, loader, finalTokens);
784
954
  } catch (err) {
785
955
  const msg = err.message || "Failed to create session";
786
- const loader = new Loader();
787
- loader.show("#15BA68", config.lang);
788
956
  loader.showError(msg, config.lang);
789
957
  config.onError?.(msg);
790
958
  throw err;
791
959
  }
792
960
  }
793
961
  /**
794
- * Flow 2: sessionId + embedToken — fetch session data, open widget.
795
- */
962
+ * Flow 2: sessionId + embedToken — fetch session data, open widget.
963
+ */
796
964
  async initWithEmbedToken(config) {
797
965
  const designTokens = await fetchDesignTokens(this.apiBase, {
798
966
  sessionId: config.sessionId
@@ -801,11 +969,7 @@ var FlonkKYC = class {
801
969
  const loader = new Loader();
802
970
  loader.show(primaryColor, config.lang);
803
971
  try {
804
- const sessionData = await fetchPublicSession(
805
- this.apiBase,
806
- config.sessionId,
807
- config.embedToken
808
- );
972
+ const sessionData = await fetchPublicSession(this.apiBase, config.sessionId, config.embedToken);
809
973
  const session = {
810
974
  id: sessionData.id,
811
975
  allowManualUpload: sessionData.allowManualUpload ?? config.allowManualUpload ?? true,
@@ -813,7 +977,10 @@ var FlonkKYC = class {
813
977
  qrCodeUrl: sessionData.qrCodeUrl,
814
978
  testMode: sessionData.testMode || false,
815
979
  poaEnabled: sessionData.poaEnabled || false,
816
- poaRequired: sessionData.poaRequired || false
980
+ poaRequired: sessionData.poaRequired || false,
981
+ mlAutoCaptureEnabled: sessionData.mlAutoCaptureEnabled || false,
982
+ mlCropEnabled: sessionData.mlCropEnabled ?? true,
983
+ mlVerifyEnabled: sessionData.mlVerifyEnabled || false
817
984
  };
818
985
  return this.buildWidget(config.embedToken, session, config, loader, designTokens);
819
986
  } catch (err) {
@@ -824,8 +991,8 @@ var FlonkKYC = class {
824
991
  }
825
992
  }
826
993
  /**
827
- * Flow 3: sessionId only — exchange for embedToken, then init.
828
- */
994
+ * Flow 3: sessionId only — exchange for embedToken, then init.
995
+ */
829
996
  async initWithSession(config) {
830
997
  const designTokens = await fetchDesignTokens(this.apiBase, {
831
998
  sessionId: config.sessionId
@@ -834,10 +1001,7 @@ var FlonkKYC = class {
834
1001
  const loader = new Loader();
835
1002
  loader.show(primaryColor, config.lang);
836
1003
  try {
837
- const { embedToken, session } = await exchangeSessionForToken(
838
- this.apiBase,
839
- config.sessionId
840
- );
1004
+ const { embedToken, session } = await exchangeSessionForToken(this.apiBase, config.sessionId);
841
1005
  return this.buildWidget(embedToken, session, config, loader, designTokens);
842
1006
  } catch (err) {
843
1007
  const msg = err.message || "Failed to initialize verification";
@@ -847,11 +1011,13 @@ var FlonkKYC = class {
847
1011
  }
848
1012
  }
849
1013
  /**
850
- * Flow 4: publishableKey — fetch widget token, open widget.
851
- */
1014
+ * Flow 4: publishableKey — fetch widget token, open widget.
1015
+ */
852
1016
  async initWithPublishableKey(config) {
853
1017
  const pk = config.publishableKey;
854
- const designTokens = await fetchDesignTokens(this.apiBase, { pk });
1018
+ const designTokens = await fetchDesignTokens(this.apiBase, {
1019
+ pk
1020
+ });
855
1021
  const primaryColor = designTokens?.colors?.primary?.cannabis || "#15BA68";
856
1022
  const loader = new Loader();
857
1023
  loader.show(primaryColor, config.lang);
@@ -896,6 +1062,9 @@ var FlonkKYC = class {
896
1062
  if (session.testMode) params.testMode = "true";
897
1063
  if (session.poaEnabled) params.poaEnabled = "true";
898
1064
  if (session.poaRequired) params.poaRequired = "true";
1065
+ if (session.mlAutoCaptureEnabled) params.mlAutoCaptureEnabled = "true";
1066
+ if (session.mlCropEnabled !== false) params.mlCropEnabled = "true";
1067
+ if (session.mlVerifyEnabled) params.mlVerifyEnabled = "true";
899
1068
  if (designTokens?.colors) {
900
1069
  params.designTokens = JSON.stringify(designTokens);
901
1070
  }
@@ -919,12 +1088,10 @@ var FlonkKYC = class {
919
1088
  });
920
1089
  }
921
1090
  /**
922
- * Core: create iframe, attach listeners, return WidgetInstance.
923
- */
1091
+ * Core: create iframe, attach listeners, return WidgetInstance.
1092
+ */
924
1093
  openWidget(params, opts) {
925
- const filtered = Object.fromEntries(
926
- Object.entries(params).filter(([, v]) => v != null)
927
- );
1094
+ const filtered = Object.fromEntries(Object.entries(params).filter(([, v]) => v != null));
928
1095
  const search = new URLSearchParams(filtered);
929
1096
  const src = `${this.widgetUrl}/?${search.toString()}`;
930
1097
  const iframe = createIframe(src);
@@ -938,7 +1105,7 @@ var FlonkKYC = class {
938
1105
  mountTarget.appendChild(iframe);
939
1106
  const cleanupViewport = setupViewportSizing(loader.element, iframe);
940
1107
  let cleaned = false;
941
- const cleanupAll = () => {
1108
+ const cleanupAll = /* @__PURE__ */ __name(() => {
942
1109
  if (cleaned) return;
943
1110
  cleaned = true;
944
1111
  try {
@@ -948,8 +1115,8 @@ var FlonkKYC = class {
948
1115
  if (iframe.parentNode) iframe.remove();
949
1116
  } catch {
950
1117
  }
951
- };
952
- const afterCleanup = (delayMs) => () => setTimeout(cleanupAll, delayMs);
1118
+ }, "cleanupAll");
1119
+ const afterCleanup = /* @__PURE__ */ __name((delayMs) => () => setTimeout(cleanupAll, delayMs), "afterCleanup");
953
1120
  const handler = new MessageHandler(src, iframe, {
954
1121
  onSuccess: opts.onSuccess ? (r) => {
955
1122
  opts.onSuccess?.(r);
@@ -975,30 +1142,31 @@ var FlonkKYC = class {
975
1142
  };
976
1143
  }
977
1144
  };
978
- FlonkKYC.version = SDK_VERSION;
979
- function FlonkKYCWidget({
980
- widgetUrl,
981
- apiBase,
982
- autoOpen = true,
983
- publishableKey,
984
- serverUrl,
985
- sessionId,
986
- embedToken,
987
- clientMetadata,
988
- lang,
989
- overlayColor,
990
- allowManualUpload,
991
- requestHeaders,
992
- onSuccess,
993
- onError,
994
- onCancel,
995
- onReady
996
- }) {
1145
+ __name(_FlonkKYC, "FlonkKYC");
1146
+ __publicField(_FlonkKYC, "version", SDK_VERSION);
1147
+ var FlonkKYC = _FlonkKYC;
1148
+ function FlonkKYCWidget({ widgetUrl, apiBase, autoOpen = true, publishableKey, serverUrl, sessionId, embedToken, clientMetadata, lang, overlayColor, allowManualUpload, requestHeaders, onSuccess, onError, onCancel, onReady }) {
997
1149
  const mountRef = useRef(null);
998
1150
  const widgetRef = useRef(null);
999
- const callbacksRef = useRef({ onSuccess, onError, onCancel, onReady });
1000
- callbacksRef.current = { onSuccess, onError, onCancel, onReady };
1001
- const sdk = useMemo(() => new FlonkKYC({ widgetUrl, apiBase }), [widgetUrl, apiBase]);
1151
+ const callbacksRef = useRef({
1152
+ onSuccess,
1153
+ onError,
1154
+ onCancel,
1155
+ onReady
1156
+ });
1157
+ callbacksRef.current = {
1158
+ onSuccess,
1159
+ onError,
1160
+ onCancel,
1161
+ onReady
1162
+ };
1163
+ const sdk = useMemo(() => new FlonkKYC({
1164
+ widgetUrl,
1165
+ apiBase
1166
+ }), [
1167
+ widgetUrl,
1168
+ apiBase
1169
+ ]);
1002
1170
  const generationRef = useRef(0);
1003
1171
  useEffect(() => {
1004
1172
  if (!autoOpen) return;
@@ -1014,10 +1182,10 @@ function FlonkKYCWidget({
1014
1182
  allowManualUpload,
1015
1183
  requestHeaders,
1016
1184
  mount: mountRef.current || void 0,
1017
- onSuccess: (r) => callbacksRef.current.onSuccess?.(r),
1018
- onError: (e) => callbacksRef.current.onError?.(e),
1019
- onCancel: () => callbacksRef.current.onCancel?.(),
1020
- onReady: () => callbacksRef.current.onReady?.()
1185
+ onSuccess: /* @__PURE__ */ __name((r) => callbacksRef.current.onSuccess?.(r), "onSuccess"),
1186
+ onError: /* @__PURE__ */ __name((e) => callbacksRef.current.onError?.(e), "onError"),
1187
+ onCancel: /* @__PURE__ */ __name(() => callbacksRef.current.onCancel?.(), "onCancel"),
1188
+ onReady: /* @__PURE__ */ __name(() => callbacksRef.current.onReady?.(), "onReady")
1021
1189
  };
1022
1190
  const timer = setTimeout(() => {
1023
1191
  if (generationRef.current !== thisGeneration) return;
@@ -1038,9 +1206,18 @@ function FlonkKYCWidget({
1038
1206
  widgetRef.current?.destroy();
1039
1207
  widgetRef.current = null;
1040
1208
  };
1041
- }, [sdk, publishableKey, serverUrl, sessionId, autoOpen]);
1042
- return /* @__PURE__ */ jsx("div", { ref: mountRef });
1209
+ }, [
1210
+ sdk,
1211
+ publishableKey,
1212
+ serverUrl,
1213
+ sessionId,
1214
+ autoOpen
1215
+ ]);
1216
+ return /* @__PURE__ */ React.createElement("div", {
1217
+ ref: mountRef
1218
+ });
1043
1219
  }
1220
+ __name(FlonkKYCWidget, "FlonkKYCWidget");
1044
1221
 
1045
1222
  export { FlonkError, FlonkKYC, FlonkKYCWidget, FlonkValidationError };
1046
1223
  //# sourceMappingURL=index.js.map