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