@flonkid/kyc 1.7.0 → 1.8.0

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.d.cts CHANGED
@@ -80,10 +80,28 @@ interface VerificationResult {
80
80
  }
81
81
 
82
82
  declare class FlonkKYC {
83
- static readonly version = "1.7.0";
83
+ static readonly version = "1.8.0";
84
84
  private readonly widgetUrl;
85
85
  private readonly apiBase;
86
86
  constructor(options?: FlonkKYCOptions);
87
+ /**
88
+ * Warm the project's branding (colors) ahead of time so the widget paints the
89
+ * brand color on the first frame, with no branding round-trip at click time.
90
+ *
91
+ * Call it early — on page mount, route enter, or hover of the "verify" button
92
+ * — well before `init()`. The result is cached (module-level, 5-min TTL) and
93
+ * every subsequent `init()`/`open()` for the same key reads from it. Safe to
94
+ * call repeatedly; concurrent calls dedupe. Never throws.
95
+ *
96
+ * @example
97
+ * // in a layout effect, long before the user clicks "Verify"
98
+ * FlonkKYC.preloadBranding({ publishableKey: 'pk_live_...' });
99
+ */
100
+ static preloadBranding(opts: {
101
+ publishableKey?: string;
102
+ sessionId?: string;
103
+ apiBase?: string;
104
+ }): Promise<void>;
87
105
  /**
88
106
  * Open the KYC verification widget.
89
107
  *
@@ -160,6 +178,23 @@ interface FlonkKYCProps extends FlonkKYCOptions {
160
178
  autoOpen?: boolean;
161
179
  }
162
180
  declare function FlonkKYCWidget({ widgetUrl, apiBase, autoOpen, publishableKey, serverUrl, sessionId, embedToken, clientMetadata, lang, overlayColor, allowManualUpload, requestHeaders, onSuccess, onError, onCancel, onReady, }: FlonkKYCProps): react_jsx_runtime.JSX.Element;
181
+ interface FlonkKYCBrandingPreloaderProps {
182
+ publishableKey?: string;
183
+ sessionId?: string;
184
+ apiBase?: string;
185
+ }
186
+ /**
187
+ * Invisible helper that warms the project's branding cache on mount, so the
188
+ * widget paints the brand color on the first frame when the user later opens it.
189
+ *
190
+ * Mount it high in the tree (e.g. an authenticated layout) so branding is ready
191
+ * long before the user reaches the verification screen. Renders nothing.
192
+ *
193
+ * @example
194
+ * // app/(authed)/layout.tsx
195
+ * <FlonkKYCBrandingPreloader publishableKey={process.env.NEXT_PUBLIC_FLONK_PK} />
196
+ */
197
+ declare function FlonkKYCBrandingPreloader({ publishableKey, sessionId, apiBase, }: FlonkKYCBrandingPreloaderProps): null;
163
198
 
164
199
  declare class FlonkError extends Error {
165
200
  readonly code: string;
@@ -170,4 +205,4 @@ declare class FlonkValidationError extends FlonkError {
170
205
  constructor(message: string);
171
206
  }
172
207
 
173
- export { type DocumentType, type EmbedInstance, FlonkError, FlonkKYC, type FlonkKYCOptions, type FlonkKYCProps, FlonkKYCWidget, FlonkValidationError, type PreviewColors, type VerificationResult, type WidgetEmbedConfig, type WidgetInitConfig, type WidgetInstance, type WidgetLanguage, type WidgetPreviewConfig };
208
+ export { type DocumentType, type EmbedInstance, FlonkError, FlonkKYC, FlonkKYCBrandingPreloader, type FlonkKYCBrandingPreloaderProps, type FlonkKYCOptions, type FlonkKYCProps, FlonkKYCWidget, FlonkValidationError, type PreviewColors, type VerificationResult, type WidgetEmbedConfig, type WidgetInitConfig, type WidgetInstance, type WidgetLanguage, type WidgetPreviewConfig };
package/dist/index.d.ts CHANGED
@@ -80,10 +80,28 @@ interface VerificationResult {
80
80
  }
81
81
 
82
82
  declare class FlonkKYC {
83
- static readonly version = "1.7.0";
83
+ static readonly version = "1.8.0";
84
84
  private readonly widgetUrl;
85
85
  private readonly apiBase;
86
86
  constructor(options?: FlonkKYCOptions);
87
+ /**
88
+ * Warm the project's branding (colors) ahead of time so the widget paints the
89
+ * brand color on the first frame, with no branding round-trip at click time.
90
+ *
91
+ * Call it early — on page mount, route enter, or hover of the "verify" button
92
+ * — well before `init()`. The result is cached (module-level, 5-min TTL) and
93
+ * every subsequent `init()`/`open()` for the same key reads from it. Safe to
94
+ * call repeatedly; concurrent calls dedupe. Never throws.
95
+ *
96
+ * @example
97
+ * // in a layout effect, long before the user clicks "Verify"
98
+ * FlonkKYC.preloadBranding({ publishableKey: 'pk_live_...' });
99
+ */
100
+ static preloadBranding(opts: {
101
+ publishableKey?: string;
102
+ sessionId?: string;
103
+ apiBase?: string;
104
+ }): Promise<void>;
87
105
  /**
88
106
  * Open the KYC verification widget.
89
107
  *
@@ -160,6 +178,23 @@ interface FlonkKYCProps extends FlonkKYCOptions {
160
178
  autoOpen?: boolean;
161
179
  }
162
180
  declare function FlonkKYCWidget({ widgetUrl, apiBase, autoOpen, publishableKey, serverUrl, sessionId, embedToken, clientMetadata, lang, overlayColor, allowManualUpload, requestHeaders, onSuccess, onError, onCancel, onReady, }: FlonkKYCProps): react_jsx_runtime.JSX.Element;
181
+ interface FlonkKYCBrandingPreloaderProps {
182
+ publishableKey?: string;
183
+ sessionId?: string;
184
+ apiBase?: string;
185
+ }
186
+ /**
187
+ * Invisible helper that warms the project's branding cache on mount, so the
188
+ * widget paints the brand color on the first frame when the user later opens it.
189
+ *
190
+ * Mount it high in the tree (e.g. an authenticated layout) so branding is ready
191
+ * long before the user reaches the verification screen. Renders nothing.
192
+ *
193
+ * @example
194
+ * // app/(authed)/layout.tsx
195
+ * <FlonkKYCBrandingPreloader publishableKey={process.env.NEXT_PUBLIC_FLONK_PK} />
196
+ */
197
+ declare function FlonkKYCBrandingPreloader({ publishableKey, sessionId, apiBase, }: FlonkKYCBrandingPreloaderProps): null;
163
198
 
164
199
  declare class FlonkError extends Error {
165
200
  readonly code: string;
@@ -170,4 +205,4 @@ declare class FlonkValidationError extends FlonkError {
170
205
  constructor(message: string);
171
206
  }
172
207
 
173
- export { type DocumentType, type EmbedInstance, FlonkError, FlonkKYC, type FlonkKYCOptions, type FlonkKYCProps, FlonkKYCWidget, FlonkValidationError, type PreviewColors, type VerificationResult, type WidgetEmbedConfig, type WidgetInitConfig, type WidgetInstance, type WidgetLanguage, type WidgetPreviewConfig };
208
+ export { type DocumentType, type EmbedInstance, FlonkError, FlonkKYC, FlonkKYCBrandingPreloader, type FlonkKYCBrandingPreloaderProps, type FlonkKYCOptions, type FlonkKYCProps, FlonkKYCWidget, FlonkValidationError, type PreviewColors, type VerificationResult, type WidgetEmbedConfig, type WidgetInitConfig, type WidgetInstance, type WidgetLanguage, type WidgetPreviewConfig };
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { useRef, useMemo, useEffect } from 'react';
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
 
4
4
  // src/shared/constants.ts
5
- var SDK_VERSION = "1.7.0";
5
+ var SDK_VERSION = "1.8.0";
6
6
  var DEFAULT_WIDGET_URL = "https://widget.flonk.id";
7
7
  var DEFAULT_API_BASE = "https://api.flonk.id/v1";
8
8
  var WIDGET_EVENTS = {
@@ -104,21 +104,43 @@ async function fetchWidgetToken(pk, apiBase) {
104
104
  }
105
105
  return res.json();
106
106
  }
107
- async function fetchDesignTokens(apiBase, opts) {
107
+ var BRANDING_CACHE_TTL_MS = 5 * 60 * 1e3;
108
+ var brandingCache = /* @__PURE__ */ new Map();
109
+ function brandingCacheKey(opts) {
110
+ if (opts.pk) return `pk:${opts.pk}`;
111
+ if (opts.sessionId) return `sid:${opts.sessionId}`;
112
+ if (opts.clientId) return `cid:${opts.clientId}`;
113
+ return null;
114
+ }
115
+ async function requestDesignTokens(apiBase, opts) {
108
116
  const params = [];
109
117
  if (opts.sessionId) params.push(`sessionId=${encodeURIComponent(opts.sessionId)}`);
110
118
  else if (opts.clientId) params.push(`clientId=${encodeURIComponent(opts.clientId)}`);
111
119
  const url = `${apiBase}/public/design-tokens${params.length ? "?" + params.join("&") : ""}`;
112
- try {
113
- const res = await fetchWithTimeout(
114
- url,
115
- { headers: opts.pk ? { "x-kyc-pk": opts.pk } : {}, credentials: "omit" },
116
- 8e3
117
- );
118
- return res.ok ? res.json() : null;
119
- } catch {
120
- return null;
120
+ const res = await fetchWithTimeout(
121
+ url,
122
+ { headers: opts.pk ? { "x-kyc-pk": opts.pk } : {}, credentials: "omit" },
123
+ 8e3
124
+ );
125
+ return res.ok ? res.json() : null;
126
+ }
127
+ async function fetchDesignTokens(apiBase, opts) {
128
+ const key = brandingCacheKey(opts);
129
+ if (!key) return null;
130
+ const now = Date.now();
131
+ const cached = brandingCache.get(key);
132
+ if (cached && cached.expiresAt > now) {
133
+ return cached.promise;
121
134
  }
135
+ const promise = requestDesignTokens(apiBase, opts).catch(() => null);
136
+ brandingCache.set(key, { promise, expiresAt: now + BRANDING_CACHE_TTL_MS });
137
+ promise.then((tokens) => {
138
+ if (tokens == null) brandingCache.delete(key);
139
+ });
140
+ return promise;
141
+ }
142
+ function preloadDesignTokens(apiBase, opts) {
143
+ return fetchDesignTokens(apiBase, opts);
122
144
  }
123
145
  function validateServerUrl(url) {
124
146
  if (url.startsWith("/")) return;
@@ -703,6 +725,26 @@ var FlonkKYC = class {
703
725
  this.widgetUrl = (options.widgetUrl || DEFAULT_WIDGET_URL).replace(/\/$/, "");
704
726
  this.apiBase = (options.apiBase || DEFAULT_API_BASE).replace(/\/$/, "");
705
727
  }
728
+ /**
729
+ * Warm the project's branding (colors) ahead of time so the widget paints the
730
+ * brand color on the first frame, with no branding round-trip at click time.
731
+ *
732
+ * Call it early — on page mount, route enter, or hover of the "verify" button
733
+ * — well before `init()`. The result is cached (module-level, 5-min TTL) and
734
+ * every subsequent `init()`/`open()` for the same key reads from it. Safe to
735
+ * call repeatedly; concurrent calls dedupe. Never throws.
736
+ *
737
+ * @example
738
+ * // in a layout effect, long before the user clicks "Verify"
739
+ * FlonkKYC.preloadBranding({ publishableKey: 'pk_live_...' });
740
+ */
741
+ static preloadBranding(opts) {
742
+ const apiBase = (opts.apiBase || DEFAULT_API_BASE).replace(/\/$/, "");
743
+ return preloadDesignTokens(apiBase, {
744
+ pk: opts.publishableKey,
745
+ sessionId: opts.sessionId
746
+ }).then(() => void 0);
747
+ }
706
748
  // ── Public API ───────────────────────────────────────
707
749
  /**
708
750
  * Open the KYC verification widget.
@@ -1075,6 +1117,10 @@ function FlonkKYCWidget({
1075
1117
  const callbacksRef = useRef({ onSuccess, onError, onCancel, onReady });
1076
1118
  callbacksRef.current = { onSuccess, onError, onCancel, onReady };
1077
1119
  const sdk = useMemo(() => new FlonkKYC({ widgetUrl, apiBase }), [widgetUrl, apiBase]);
1120
+ useEffect(() => {
1121
+ if (!publishableKey && !sessionId) return;
1122
+ void FlonkKYC.preloadBranding({ publishableKey, sessionId, apiBase });
1123
+ }, [publishableKey, sessionId, apiBase]);
1078
1124
  const generationRef = useRef(0);
1079
1125
  useEffect(() => {
1080
1126
  if (!autoOpen) return;
@@ -1117,7 +1163,17 @@ function FlonkKYCWidget({
1117
1163
  }, [sdk, publishableKey, serverUrl, sessionId, embedToken, lang, overlayColor, allowManualUpload, autoOpen]);
1118
1164
  return /* @__PURE__ */ jsx("div", { ref: mountRef });
1119
1165
  }
1166
+ function FlonkKYCBrandingPreloader({
1167
+ publishableKey,
1168
+ sessionId,
1169
+ apiBase
1170
+ }) {
1171
+ useEffect(() => {
1172
+ void FlonkKYC.preloadBranding({ publishableKey, sessionId, apiBase });
1173
+ }, [publishableKey, sessionId, apiBase]);
1174
+ return null;
1175
+ }
1120
1176
 
1121
- export { FlonkError, FlonkKYC, FlonkKYCWidget, FlonkValidationError };
1177
+ export { FlonkError, FlonkKYC, FlonkKYCBrandingPreloader, FlonkKYCWidget, FlonkValidationError };
1122
1178
  //# sourceMappingURL=index.js.map
1123
1179
  //# sourceMappingURL=index.js.map