@rhinestone/1auth 0.6.9 → 0.7.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/chunk-GUAI55LL.mjs +179 -0
- package/dist/chunk-GUAI55LL.mjs.map +1 -0
- package/dist/{chunk-VZYHCFEH.mjs → chunk-THKG3FAG.mjs} +4 -177
- package/dist/chunk-THKG3FAG.mjs.map +1 -0
- package/dist/{client-BNluVe4_.d.ts → client-B_CzDa_I.d.ts} +57 -10
- package/dist/{client-CLCdahyj.d.mts → client-F4DnFM8d.d.mts} +57 -10
- package/dist/headless.d.mts +24 -5
- package/dist/headless.d.ts +24 -5
- package/dist/headless.js +142 -2
- package/dist/headless.js.map +1 -1
- package/dist/headless.mjs +103 -1
- package/dist/headless.mjs.map +1 -1
- package/dist/index.d.mts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +314 -124
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +318 -126
- package/dist/index.mjs.map +1 -1
- package/dist/{provider-BgD9PeDX.d.ts → provider-Cd7Ip5L-.d.ts} +2 -2
- package/dist/{provider-hxHGb6SX.d.mts → provider-IvYXPMpk.d.mts} +2 -2
- package/dist/react.d.mts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/server.d.mts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/{types-1BMD1PSH.d.mts → types-U_dwxbtS.d.mts} +63 -0
- package/dist/{types-1BMD1PSH.d.ts → types-U_dwxbtS.d.ts} +63 -0
- package/dist/{verify-CZe-m_Vf.d.ts → verify-BLgZzwmJ.d.ts} +1 -1
- package/dist/{verify-D3FaLeAi.d.mts → verify-C8-a5c3K.d.mts} +1 -1
- package/dist/wagmi.d.mts +3 -3
- package/dist/wagmi.d.ts +3 -3
- package/dist/wagmi.mjs +2 -1
- package/dist/wagmi.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-VZYHCFEH.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -344,25 +344,19 @@ var SPINNER_RADIUS = (SPINNER_SIZE - SPINNER_STROKE) / 2;
|
|
|
344
344
|
var SPINNER_CIRCUMFERENCE = 2 * Math.PI * SPINNER_RADIUS;
|
|
345
345
|
var SPINNER_ARC_FRACTION = 0.17;
|
|
346
346
|
var SPINNER_ARC = SPINNER_CIRCUMFERENCE * SPINNER_ARC_FRACTION;
|
|
347
|
+
var SPINNER_SPIN_DURATION_MS = 800;
|
|
347
348
|
var LOADING_MODAL_WIDTH = 380;
|
|
348
349
|
var LOADING_MODAL_PADDING = 12;
|
|
349
350
|
var LOADING_MODAL_RADIUS = 16;
|
|
350
|
-
var LOADING_MOBILE_BREAKPOINT = 640;
|
|
351
|
-
var LOADING_CARD_GAP = 16;
|
|
352
351
|
var LOADING_BODY_GAP = 12;
|
|
353
352
|
var LOADING_ICON_PADDING = 12;
|
|
354
353
|
var LOADING_TITLE_BLOCK_GAP = 4;
|
|
355
|
-
var LOADING_FOOTER_GAP = 4;
|
|
356
354
|
var LOADING_TITLE_FONT_SIZE = 20;
|
|
357
355
|
var LOADING_TITLE_FONT_WEIGHT = 700;
|
|
358
356
|
var LOADING_SUBTITLE_FONT_SIZE = 12;
|
|
359
357
|
var LOADING_SUBTITLE_FONT_WEIGHT = 500;
|
|
360
|
-
var LOADING_FOOTER_FONT_SIZE = 11;
|
|
361
|
-
var LOADING_FOOTER_FONT_WEIGHT = 500;
|
|
362
358
|
var LOADING_LINE_HEIGHT = "normal";
|
|
363
359
|
var LOADING_FONT_FAMILY = "'Inter', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'";
|
|
364
|
-
var LOGO_WIDTH = 72;
|
|
365
|
-
var LOGO_HEIGHT = 16;
|
|
366
360
|
var BRAND_PURPLE = "#685bff";
|
|
367
361
|
var LIGHT_TOKENS = {
|
|
368
362
|
bgPrimary: "#ffffff",
|
|
@@ -376,7 +370,6 @@ var DARK_TOKENS = {
|
|
|
376
370
|
textPrimary: "#e4e4e7",
|
|
377
371
|
textSecondary: "#9f9fa9"
|
|
378
372
|
};
|
|
379
|
-
var FOOTER_TEXT_COLOR = "#71717b";
|
|
380
373
|
var LOADING_TITLE = "Loading...";
|
|
381
374
|
var LOADING_SUBTITLE = "This will only take a few moments, do not close the window.";
|
|
382
375
|
|
|
@@ -386,7 +379,36 @@ var POPUP_HEIGHT = 600;
|
|
|
386
379
|
var DEFAULT_EMBED_WIDTH = `${LOADING_MODAL_WIDTH}px`;
|
|
387
380
|
var DEFAULT_EMBED_HEIGHT = "500px";
|
|
388
381
|
var DEFAULT_PROVIDER_URL = "https://passkey.1auth.box";
|
|
382
|
+
function currentWindowOrigin() {
|
|
383
|
+
if (typeof window === "undefined") return null;
|
|
384
|
+
const origin = window.location?.origin;
|
|
385
|
+
return typeof origin === "string" && origin.length > 0 ? origin : null;
|
|
386
|
+
}
|
|
387
|
+
function appendParentOriginParam(params) {
|
|
388
|
+
const origin = currentWindowOrigin();
|
|
389
|
+
if (origin) params.set("parentOrigin", origin);
|
|
390
|
+
}
|
|
389
391
|
var MAX_LABEL_LEN = 20;
|
|
392
|
+
var DEFAULT_BACKDROP_COLOR = "#000000";
|
|
393
|
+
var DEFAULT_BACKDROP_OPACITY = 0.4;
|
|
394
|
+
var DEFAULT_BACKDROP_BLUR = 8;
|
|
395
|
+
var HEX_COLOR_RE = /^#[0-9a-fA-F]{6}$/;
|
|
396
|
+
function resolveBackdropStyle(params) {
|
|
397
|
+
const rawColor = params.get("backdropColor");
|
|
398
|
+
const hex = (rawColor && HEX_COLOR_RE.test(rawColor) ? rawColor : DEFAULT_BACKDROP_COLOR).slice(1);
|
|
399
|
+
const r = parseInt(hex.slice(0, 2), 16);
|
|
400
|
+
const g = parseInt(hex.slice(2, 4), 16);
|
|
401
|
+
const b = parseInt(hex.slice(4, 6), 16);
|
|
402
|
+
const clampNumber = (key, min, max, fallback) => {
|
|
403
|
+
const raw = params.get(key);
|
|
404
|
+
if (!raw) return fallback;
|
|
405
|
+
const n = Number(raw);
|
|
406
|
+
return Number.isFinite(n) ? Math.min(max, Math.max(min, n)) : fallback;
|
|
407
|
+
};
|
|
408
|
+
const opacity = clampNumber("backdropOpacity", 0, 1, DEFAULT_BACKDROP_OPACITY);
|
|
409
|
+
const blur = clampNumber("backdropBlur", 0, 40, DEFAULT_BACKDROP_BLUR);
|
|
410
|
+
return { background: `rgba(${r}, ${g}, ${b}, ${opacity})`, blur };
|
|
411
|
+
}
|
|
390
412
|
function generateModalNonce() {
|
|
391
413
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
392
414
|
return crypto.randomUUID();
|
|
@@ -510,6 +532,15 @@ var OneAuthClient = class {
|
|
|
510
532
|
// "Restore will override" warnings and "emitting session_request:N
|
|
511
533
|
// without any listeners" errors on the second and later txs.
|
|
512
534
|
this.eoaDialogState = null;
|
|
535
|
+
// Hidden iframe that warms the dialog ahead of the first real open (see
|
|
536
|
+
// `prewarm()`). The passkey app runs on a long-lived server (not serverless),
|
|
537
|
+
// so there is no backend cold-start to hide — what stays expensive is the
|
|
538
|
+
// *browser-side* cost of a freshly created cross-origin iframe: downloading
|
|
539
|
+
// the dialog HTML + JS bundle, parsing it, hydrating React, and loading the
|
|
540
|
+
// font. Loading that bundle once into a parked hidden iframe lets the real
|
|
541
|
+
// open hit the HTTP cache (Next.js chunks/fonts are immutable-cached) over an
|
|
542
|
+
// already-warm connection, so the SDK preload overlay is shown only briefly.
|
|
543
|
+
this.prewarmState = null;
|
|
513
544
|
// Serialises concurrent `requestWithWallet` calls — they would otherwise
|
|
514
545
|
// both try to drive the same iframe and cross-resolve each other.
|
|
515
546
|
this.eoaSerialQueue = Promise.resolve();
|
|
@@ -523,6 +554,15 @@ var OneAuthClient = class {
|
|
|
523
554
|
if (dialogUrl !== providerUrl) {
|
|
524
555
|
this.injectPreconnect(dialogUrl);
|
|
525
556
|
}
|
|
557
|
+
if (this.config.prewarm) {
|
|
558
|
+
const warm = () => void this.prewarm();
|
|
559
|
+
const ric = window.requestIdleCallback;
|
|
560
|
+
if (typeof ric === "function") {
|
|
561
|
+
ric(warm, { timeout: 2e3 });
|
|
562
|
+
} else {
|
|
563
|
+
setTimeout(warm, 200);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
526
566
|
}
|
|
527
567
|
const initOperation = this.createTelemetryOperation("client", {
|
|
528
568
|
hasClientId: !!this.config.clientId,
|
|
@@ -756,6 +796,18 @@ var OneAuthClient = class {
|
|
|
756
796
|
if (primary) {
|
|
757
797
|
params.set("accent", primary);
|
|
758
798
|
}
|
|
799
|
+
const backdrop = theme.backdrop;
|
|
800
|
+
if (backdrop) {
|
|
801
|
+
if (backdrop.color) {
|
|
802
|
+
params.set("backdropColor", backdrop.color);
|
|
803
|
+
}
|
|
804
|
+
if (backdrop.opacity !== void 0) {
|
|
805
|
+
params.set("backdropOpacity", String(backdrop.opacity));
|
|
806
|
+
}
|
|
807
|
+
if (backdrop.blur !== void 0) {
|
|
808
|
+
params.set("backdropBlur", String(backdrop.blur));
|
|
809
|
+
}
|
|
810
|
+
}
|
|
759
811
|
return params.toString();
|
|
760
812
|
}
|
|
761
813
|
/**
|
|
@@ -994,9 +1046,7 @@ var OneAuthClient = class {
|
|
|
994
1046
|
if (options?.flow === "create-account") {
|
|
995
1047
|
params.set("switch", "1");
|
|
996
1048
|
}
|
|
997
|
-
|
|
998
|
-
params.set("parentOrigin", window.location.origin);
|
|
999
|
-
}
|
|
1049
|
+
appendParentOriginParam(params);
|
|
1000
1050
|
this.appendTelemetryParams(params, telemetry);
|
|
1001
1051
|
const themeParams = this.getThemeParams(options?.theme);
|
|
1002
1052
|
if (themeParams) {
|
|
@@ -1077,9 +1127,7 @@ var OneAuthClient = class {
|
|
|
1077
1127
|
if (this.config.clientId) {
|
|
1078
1128
|
params.set("clientId", this.config.clientId);
|
|
1079
1129
|
}
|
|
1080
|
-
|
|
1081
|
-
params.set("parentOrigin", window.location.origin);
|
|
1082
|
-
}
|
|
1130
|
+
appendParentOriginParam(params);
|
|
1083
1131
|
this.appendTelemetryParams(params, telemetry);
|
|
1084
1132
|
const themeParams = this.getThemeParams(options?.theme);
|
|
1085
1133
|
if (themeParams) {
|
|
@@ -1210,10 +1258,13 @@ var OneAuthClient = class {
|
|
|
1210
1258
|
themeParsed.forEach((value, key) => params.set(key, value));
|
|
1211
1259
|
}
|
|
1212
1260
|
const url = `${dialogUrl}/dialog/account?${params.toString()}`;
|
|
1261
|
+
const accessTokenResult = await this.fetchAccessToken();
|
|
1262
|
+
const initMessage = { mode: "iframe" };
|
|
1263
|
+
if (accessTokenResult.ok) {
|
|
1264
|
+
initMessage.auth = { accessToken: accessTokenResult.accessToken };
|
|
1265
|
+
}
|
|
1213
1266
|
const { dialog, iframe, cleanup } = this.createModalDialog(url);
|
|
1214
|
-
const ready = await this.waitForDialogReady(dialog, iframe, cleanup,
|
|
1215
|
-
mode: "iframe"
|
|
1216
|
-
});
|
|
1267
|
+
const ready = await this.waitForDialogReady(dialog, iframe, cleanup, initMessage);
|
|
1217
1268
|
if (!ready) return;
|
|
1218
1269
|
const dialogOrigin = this.getDialogOrigin();
|
|
1219
1270
|
return new Promise((resolve) => {
|
|
@@ -1398,6 +1449,7 @@ var OneAuthClient = class {
|
|
|
1398
1449
|
}
|
|
1399
1450
|
const dialogUrl = this.getDialogUrl();
|
|
1400
1451
|
const params = new URLSearchParams({ mode: "iframe" });
|
|
1452
|
+
appendParentOriginParam(params);
|
|
1401
1453
|
this.appendTelemetryParams(params, telemetry);
|
|
1402
1454
|
const themeParams = this.getThemeParams(options.theme);
|
|
1403
1455
|
if (themeParams) {
|
|
@@ -1444,6 +1496,7 @@ var OneAuthClient = class {
|
|
|
1444
1496
|
targetChains,
|
|
1445
1497
|
status: result.status ? String(result.status) : void 0
|
|
1446
1498
|
});
|
|
1499
|
+
await this.waitForDialogClose(dialog, cleanup);
|
|
1447
1500
|
} else {
|
|
1448
1501
|
this.emitTelemetry(
|
|
1449
1502
|
result.error?.code === "USER_CANCELLED" ? "dialog.cancelled" : "grant_permission.failed",
|
|
@@ -1625,6 +1678,7 @@ var OneAuthClient = class {
|
|
|
1625
1678
|
});
|
|
1626
1679
|
const dialogUrl = this.getDialogUrl();
|
|
1627
1680
|
const params = new URLSearchParams({ mode: "iframe" });
|
|
1681
|
+
appendParentOriginParam(params);
|
|
1628
1682
|
this.appendTelemetryParams(params, telemetry);
|
|
1629
1683
|
const themeParams = this.getThemeParams(options?.theme);
|
|
1630
1684
|
if (themeParams) {
|
|
@@ -1795,6 +1849,7 @@ var OneAuthClient = class {
|
|
|
1795
1849
|
let prepareResponse;
|
|
1796
1850
|
const dialogUrl = this.getDialogUrl();
|
|
1797
1851
|
const params = new URLSearchParams({ mode: "iframe" });
|
|
1852
|
+
appendParentOriginParam(params);
|
|
1798
1853
|
this.appendTelemetryParams(params, telemetry);
|
|
1799
1854
|
const themeParams = this.getThemeParams();
|
|
1800
1855
|
if (themeParams) {
|
|
@@ -2071,6 +2126,10 @@ var OneAuthClient = class {
|
|
|
2071
2126
|
expiresAt: refreshedData.expiresAt,
|
|
2072
2127
|
intentOp: refreshedData.intentOp,
|
|
2073
2128
|
digestResult: refreshedData.digestResult,
|
|
2129
|
+
// A refreshed quote mints a fresh binding — it MUST replace the old
|
|
2130
|
+
// one, or execute would verify the new intentOp against a stale
|
|
2131
|
+
// binding and reject (once enforce mode is on).
|
|
2132
|
+
binding: refreshedData.binding,
|
|
2074
2133
|
auth: refreshedAuth
|
|
2075
2134
|
};
|
|
2076
2135
|
return {
|
|
@@ -2080,6 +2139,7 @@ var OneAuthClient = class {
|
|
|
2080
2139
|
originMessages: refreshedData.originMessages,
|
|
2081
2140
|
transaction: refreshedData.transaction,
|
|
2082
2141
|
digestResult: refreshedData.digestResult,
|
|
2142
|
+
binding: refreshedData.binding,
|
|
2083
2143
|
// Dialog-executed intents read auth from dialog state — ship the
|
|
2084
2144
|
// rebound bundle with the refresh so PASSKEY_REFRESH_COMPLETE
|
|
2085
2145
|
// updates it alongside the quote.
|
|
@@ -2144,6 +2204,7 @@ var OneAuthClient = class {
|
|
|
2144
2204
|
userId: prepareResponse.userId,
|
|
2145
2205
|
intentOp: prepareResponse.intentOp,
|
|
2146
2206
|
digestResult: prepareResponse.digestResult,
|
|
2207
|
+
binding: prepareResponse.binding,
|
|
2147
2208
|
tier: prepareResult.tier,
|
|
2148
2209
|
auth: sponsorshipTokens,
|
|
2149
2210
|
telemetry: this.telemetryPayload(telemetry)
|
|
@@ -2274,6 +2335,7 @@ var OneAuthClient = class {
|
|
|
2274
2335
|
userId: prepareResponse.userId,
|
|
2275
2336
|
intentOp: prepareResponse.intentOp,
|
|
2276
2337
|
digestResult: prepareResponse.digestResult,
|
|
2338
|
+
binding: prepareResponse.binding,
|
|
2277
2339
|
tier: prepareResult.tier,
|
|
2278
2340
|
...authReady && { auth: authReady },
|
|
2279
2341
|
telemetry: this.telemetryPayload(telemetry)
|
|
@@ -2447,6 +2509,8 @@ var OneAuthClient = class {
|
|
|
2447
2509
|
calls: prepareResponse.calls,
|
|
2448
2510
|
expiresAt: prepareResponse.expiresAt,
|
|
2449
2511
|
digestResult: prepareResponse.digestResult,
|
|
2512
|
+
// Opaque prepare->execute binding, forwarded unchanged.
|
|
2513
|
+
binding: prepareResponse.binding,
|
|
2450
2514
|
// Signature from dialog
|
|
2451
2515
|
signature: signingResult.signature,
|
|
2452
2516
|
passkey: signingResult.passkey,
|
|
@@ -2772,6 +2836,7 @@ var OneAuthClient = class {
|
|
|
2772
2836
|
};
|
|
2773
2837
|
const dialogUrl = this.getDialogUrl();
|
|
2774
2838
|
const params = new URLSearchParams({ mode: "iframe" });
|
|
2839
|
+
appendParentOriginParam(params);
|
|
2775
2840
|
this.appendTelemetryParams(params, telemetry);
|
|
2776
2841
|
const themeParams = this.getThemeParams();
|
|
2777
2842
|
if (themeParams) {
|
|
@@ -2888,6 +2953,7 @@ var OneAuthClient = class {
|
|
|
2888
2953
|
batchIntents: prepareResponse.intents,
|
|
2889
2954
|
batchFailedIntents: prepareResponse.failedIntents,
|
|
2890
2955
|
challenge: prepareResponse.challenge,
|
|
2956
|
+
binding: prepareResponse.binding,
|
|
2891
2957
|
username: options.username,
|
|
2892
2958
|
accountAddress: prepareResponse.accountAddress,
|
|
2893
2959
|
userId: prepareResponse.userId,
|
|
@@ -2931,6 +2997,7 @@ var OneAuthClient = class {
|
|
|
2931
2997
|
batchIntents: prepareResponse.intents,
|
|
2932
2998
|
batchFailedIntents: prepareResponse.failedIntents,
|
|
2933
2999
|
challenge: prepareResponse.challenge,
|
|
3000
|
+
binding: prepareResponse.binding,
|
|
2934
3001
|
username: options.username,
|
|
2935
3002
|
accountAddress: prepareResponse.accountAddress,
|
|
2936
3003
|
userId: prepareResponse.userId,
|
|
@@ -2998,6 +3065,7 @@ var OneAuthClient = class {
|
|
|
2998
3065
|
batchIntents: refreshed.intents,
|
|
2999
3066
|
batchFailedIntents: refreshed.failedIntents,
|
|
3000
3067
|
challenge: refreshed.challenge,
|
|
3068
|
+
binding: refreshed.binding,
|
|
3001
3069
|
expiresAt: refreshed.expiresAt,
|
|
3002
3070
|
auth: refreshedAuth
|
|
3003
3071
|
};
|
|
@@ -3005,6 +3073,7 @@ var OneAuthClient = class {
|
|
|
3005
3073
|
type: "PASSKEY_REFRESH_COMPLETE",
|
|
3006
3074
|
batchIntents: refreshed.intents,
|
|
3007
3075
|
challenge: refreshed.challenge,
|
|
3076
|
+
binding: refreshed.binding,
|
|
3008
3077
|
expiresAt: refreshed.expiresAt,
|
|
3009
3078
|
auth: refreshedAuth
|
|
3010
3079
|
}, dialogOrigin);
|
|
@@ -3433,6 +3502,82 @@ var OneAuthClient = class {
|
|
|
3433
3502
|
} catch {
|
|
3434
3503
|
}
|
|
3435
3504
|
}
|
|
3505
|
+
/**
|
|
3506
|
+
* Warm the dialog ahead of the first user interaction.
|
|
3507
|
+
*
|
|
3508
|
+
* `preconnect` (run in the constructor) only warms DNS/TLS. This goes
|
|
3509
|
+
* further: it loads the dialog into a hidden, off-screen iframe so the
|
|
3510
|
+
* browser downloads and parses the dialog HTML + JS bundle and the font, and
|
|
3511
|
+
* keeps the cross-origin connection alive. When the user later opens a real
|
|
3512
|
+
* auth/sign dialog, the fresh iframe serves those bytes from cache over the
|
|
3513
|
+
* warm connection and paints far sooner — so the SDK preload overlay is shown
|
|
3514
|
+
* only briefly (or imperceptibly) instead of covering a full cold load.
|
|
3515
|
+
*
|
|
3516
|
+
* It loads a dedicated `/dialog/warm` route, NOT a real flow route. That
|
|
3517
|
+
* matters for two reasons:
|
|
3518
|
+
* - **No side effects.** The real `/dialog/auth` route runs the signup
|
|
3519
|
+
* flow on mount (identity probe → `POST /api/auth/register?step=start`),
|
|
3520
|
+
* which writes an `AuthChallenge` row and counts against the register
|
|
3521
|
+
* rate limiter. Warming must never create backend auth state for a user
|
|
3522
|
+
* who hasn't acted, so the warm route renders nothing and runs no flow.
|
|
3523
|
+
* - **No message cross-talk.** The warm route posts no `PASSKEY_READY` /
|
|
3524
|
+
* `PASSKEY_RENDERED`, so a slow warm can never satisfy a visible modal's
|
|
3525
|
+
* readiness listener and drive it to `PASSKEY_INIT` at the wrong moment.
|
|
3526
|
+
* The warm route still pulls the shared Next.js framework + main + dialog
|
|
3527
|
+
* layout chunks (the bulk of every flow's bundle), so the real open is fast.
|
|
3528
|
+
*
|
|
3529
|
+
* Best called on a *likely-intent* signal — `pointerenter`/`focus` of your
|
|
3530
|
+
* "Sign in" / "Pay" button — rather than on page load, so visitors who never
|
|
3531
|
+
* authenticate don't pay for a cross-origin iframe. Pass `prewarm: true` in
|
|
3532
|
+
* the client config to have the SDK schedule this once on an idle callback.
|
|
3533
|
+
*
|
|
3534
|
+
* Idempotent: repeated calls return the same in-flight/settled promise.
|
|
3535
|
+
* Resolves `true` once the hidden iframe's document has loaded, `false` on
|
|
3536
|
+
* timeout or failure. Never throws and never blocks a real dialog open — a
|
|
3537
|
+
* failed prewarm just means the next open does a normal (cold) load.
|
|
3538
|
+
*
|
|
3539
|
+
* @returns Whether the dialog became warm.
|
|
3540
|
+
*/
|
|
3541
|
+
async prewarm() {
|
|
3542
|
+
if (typeof document === "undefined") return false;
|
|
3543
|
+
if (this.prewarmState) return this.prewarmState.ready;
|
|
3544
|
+
const warmUrl = `${this.getDialogUrl()}/dialog/warm`;
|
|
3545
|
+
const iframe = document.createElement("iframe");
|
|
3546
|
+
iframe.setAttribute("aria-hidden", "true");
|
|
3547
|
+
iframe.setAttribute("tabindex", "-1");
|
|
3548
|
+
iframe.title = "1auth dialog prewarm";
|
|
3549
|
+
iframe.style.cssText = "position:fixed;left:-9999px;top:0;width:1px;height:1px;opacity:0;border:0;pointer-events:none;";
|
|
3550
|
+
const ready = new Promise((resolve) => {
|
|
3551
|
+
let settled = false;
|
|
3552
|
+
const finish = (value) => {
|
|
3553
|
+
if (settled) return;
|
|
3554
|
+
settled = true;
|
|
3555
|
+
clearTimeout(timer);
|
|
3556
|
+
resolve(value);
|
|
3557
|
+
};
|
|
3558
|
+
iframe.onload = () => finish(true);
|
|
3559
|
+
iframe.onerror = () => finish(false);
|
|
3560
|
+
const timer = setTimeout(() => finish(false), 1e4);
|
|
3561
|
+
});
|
|
3562
|
+
iframe.src = warmUrl;
|
|
3563
|
+
document.body.appendChild(iframe);
|
|
3564
|
+
this.prewarmState = { iframe, ready };
|
|
3565
|
+
return ready;
|
|
3566
|
+
}
|
|
3567
|
+
/**
|
|
3568
|
+
* Tear down the hidden prewarm iframe created by {@link prewarm}.
|
|
3569
|
+
*
|
|
3570
|
+
* The HTTP cache that prewarm populated survives teardown, so a subsequent
|
|
3571
|
+
* open is still bundle-warm; this only releases the parked frame (and its
|
|
3572
|
+
* keep-alive connection). Call it when auth is no longer likely on the
|
|
3573
|
+
* current view. Safe to call when nothing is warmed.
|
|
3574
|
+
*/
|
|
3575
|
+
destroyPrewarm() {
|
|
3576
|
+
const state = this.prewarmState;
|
|
3577
|
+
if (!state) return;
|
|
3578
|
+
this.prewarmState = null;
|
|
3579
|
+
state.iframe.remove();
|
|
3580
|
+
}
|
|
3436
3581
|
/**
|
|
3437
3582
|
* Wait for the dialog iframe to signal ready, but defer sending `PASSKEY_INIT`
|
|
3438
3583
|
* until the caller decides the time is right.
|
|
@@ -3815,10 +3960,15 @@ var OneAuthClient = class {
|
|
|
3815
3960
|
return { ok: true, dialog: dialog2, iframe: iframe2 };
|
|
3816
3961
|
}
|
|
3817
3962
|
const dialogUrl = this.getDialogUrl();
|
|
3963
|
+
const params = new URLSearchParams({ mode: "iframe" });
|
|
3964
|
+
appendParentOriginParam(params);
|
|
3818
3965
|
const themeParams = this.getThemeParams(theme);
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3966
|
+
if (themeParams) {
|
|
3967
|
+
new URLSearchParams(themeParams).forEach((value, key) => {
|
|
3968
|
+
params.set(key, value);
|
|
3969
|
+
});
|
|
3970
|
+
}
|
|
3971
|
+
const signingUrl = `${dialogUrl}/dialog/sign-eoa?${params.toString()}`;
|
|
3822
3972
|
const { dialog, iframe, destroy } = this.createModalDialog(signingUrl, {
|
|
3823
3973
|
persistent: true
|
|
3824
3974
|
});
|
|
@@ -3923,6 +4073,7 @@ var OneAuthClient = class {
|
|
|
3923
4073
|
});
|
|
3924
4074
|
const dialogUrl = this.getDialogUrl();
|
|
3925
4075
|
const params = new URLSearchParams({ mode: "iframe" });
|
|
4076
|
+
appendParentOriginParam(params);
|
|
3926
4077
|
this.appendTelemetryParams(params, telemetry);
|
|
3927
4078
|
const themeParams = this.getThemeParams(options?.theme);
|
|
3928
4079
|
if (themeParams) {
|
|
@@ -4065,6 +4216,7 @@ var OneAuthClient = class {
|
|
|
4065
4216
|
});
|
|
4066
4217
|
const dialogUrl = this.getDialogUrl();
|
|
4067
4218
|
const params = new URLSearchParams({ mode: "iframe" });
|
|
4219
|
+
appendParentOriginParam(params);
|
|
4068
4220
|
this.appendTelemetryParams(params, telemetry);
|
|
4069
4221
|
const themeParams = this.getThemeParams(options?.theme);
|
|
4070
4222
|
if (themeParams) {
|
|
@@ -4518,17 +4670,17 @@ var OneAuthClient = class {
|
|
|
4518
4670
|
/**
|
|
4519
4671
|
* Create and open a full-viewport `<dialog>` containing a passkey iframe.
|
|
4520
4672
|
*
|
|
4521
|
-
* The SDK owns
|
|
4522
|
-
*
|
|
4523
|
-
*
|
|
4524
|
-
*
|
|
4673
|
+
* The SDK owns the browser `<dialog>` plus a minimal generic preload shell
|
|
4674
|
+
* that appears immediately on click. The passkey iframe owns all branded and
|
|
4675
|
+
* origin-specific UI (TitleBar, trust icon, action cards); the shell is
|
|
4676
|
+
* removed as soon as the iframe reports that its centered card has painted.
|
|
4525
4677
|
*
|
|
4526
4678
|
* Lifecycle:
|
|
4527
|
-
* 1. A themed
|
|
4528
|
-
* iframe loads
|
|
4529
|
-
*
|
|
4530
|
-
* 2. When the iframe sends `PASSKEY_RENDERED`, the overlay
|
|
4531
|
-
* the iframe becomes fully visible.
|
|
4679
|
+
* 1. A themed generic preload shell is injected and shown immediately
|
|
4680
|
+
* while the iframe loads. It intentionally contains no TitleBar or
|
|
4681
|
+
* origin chrome so that UI has a single implementation in apps/passkey.
|
|
4682
|
+
* 2. When the iframe sends `PASSKEY_RENDERED`, the overlay is removed and
|
|
4683
|
+
* the iframe becomes fully visible in the same frame.
|
|
4532
4684
|
* 3. The returned `cleanup` function tears down all event listeners,
|
|
4533
4685
|
* disconnects the MutationObserver, closes the `<dialog>`, and removes
|
|
4534
4686
|
* it from the DOM. It is idempotent — safe to call multiple times.
|
|
@@ -4550,12 +4702,10 @@ var OneAuthClient = class {
|
|
|
4550
4702
|
const dialogUrl = this.getDialogUrl();
|
|
4551
4703
|
const hostUrl = new URL(dialogUrl);
|
|
4552
4704
|
const urlParams = new URL(url, window.location.href).searchParams;
|
|
4705
|
+
const { background: backdropBackground, blur: backdropBlur } = resolveBackdropStyle(urlParams);
|
|
4553
4706
|
const themeMode = urlParams.get("theme") || "light";
|
|
4554
4707
|
const isDark = themeMode === "dark" || themeMode !== "light" && window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
4555
4708
|
const theme = isDark ? DARK_TOKENS : LIGHT_TOKENS;
|
|
4556
|
-
const { bgPrimary, borderColor, textPrimary, textSecondary } = theme;
|
|
4557
|
-
const textFooter = FOOTER_TEXT_COLOR;
|
|
4558
|
-
const spinnerColor = BRAND_PURPLE;
|
|
4559
4709
|
const dialog = document.createElement("dialog");
|
|
4560
4710
|
dialog.dataset.passkey = "";
|
|
4561
4711
|
if (options?.hidden) {
|
|
@@ -4566,16 +4716,6 @@ var OneAuthClient = class {
|
|
|
4566
4716
|
document.body.appendChild(dialog);
|
|
4567
4717
|
const style = document.createElement("style");
|
|
4568
4718
|
style.textContent = `
|
|
4569
|
-
/* Load Inter so the overlay's title/subtitle widths match the
|
|
4570
|
-
iframe (which loads Inter via next/font). Without this, host
|
|
4571
|
-
pages on Arial / system-ui produce wider text that wraps to two
|
|
4572
|
-
lines and breaks the visual match with the Figma. font-display:
|
|
4573
|
-
swap renders immediately with a fallback and swaps when Inter
|
|
4574
|
-
is ready \u2014 usually well before PASSKEY_RENDERED fires, but the
|
|
4575
|
-
overlay is short-lived either way so a single-frame swap is
|
|
4576
|
-
acceptable. */
|
|
4577
|
-
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@500;700&display=swap');
|
|
4578
|
-
|
|
4579
4719
|
dialog[data-passkey] {
|
|
4580
4720
|
position: fixed;
|
|
4581
4721
|
top: 0;
|
|
@@ -4613,103 +4753,143 @@ var OneAuthClient = class {
|
|
|
4613
4753
|
backdrop-filter: none;
|
|
4614
4754
|
-webkit-backdrop-filter: none;
|
|
4615
4755
|
}
|
|
4616
|
-
dialog[data-passkey] iframe {
|
|
4617
|
-
position: fixed;
|
|
4618
|
-
top: 0;
|
|
4619
|
-
left: 0;
|
|
4620
|
-
width: 100%;
|
|
4621
|
-
height: 100%;
|
|
4622
|
-
border: 0;
|
|
4623
|
-
background-color: transparent;
|
|
4624
|
-
color-scheme: normal;
|
|
4625
|
-
pointer-events: auto;
|
|
4626
|
-
backdrop-filter: blur(8px);
|
|
4627
|
-
-webkit-backdrop-filter: blur(8px);
|
|
4628
|
-
}
|
|
4629
4756
|
dialog[data-passkey] [data-passkey-overlay] {
|
|
4630
4757
|
position: fixed;
|
|
4631
|
-
|
|
4632
|
-
left: 0;
|
|
4633
|
-
width: 100%;
|
|
4634
|
-
height: 100%;
|
|
4758
|
+
inset: 0;
|
|
4635
4759
|
display: flex;
|
|
4636
4760
|
align-items: center;
|
|
4637
4761
|
justify-content: center;
|
|
4638
|
-
background:
|
|
4639
|
-
backdrop-filter: blur(
|
|
4640
|
-
-webkit-backdrop-filter: blur(
|
|
4762
|
+
background: ${backdropBackground};
|
|
4763
|
+
backdrop-filter: blur(${backdropBlur}px);
|
|
4764
|
+
-webkit-backdrop-filter: blur(${backdropBlur}px);
|
|
4641
4765
|
z-index: 1;
|
|
4642
|
-
/* Purely a visual loading screen \u2014 never intercept clicks.
|
|
4643
|
-
If the iframe's X button or backdrop-dismiss area happens to
|
|
4644
|
-
be reachable while the overlay is still painting (slow CI
|
|
4645
|
-
runners, redirect remounts), the click goes straight through
|
|
4646
|
-
instead of being trapped by the SDK preload. The previous
|
|
4647
|
-
rAF-deferred display:none lost this race in GitHub Actions
|
|
4648
|
-
\u2014 dialog-close.spec.ts repeatedly hit
|
|
4649
|
-
"<div data-passkey-overlay> intercepts pointer events". */
|
|
4650
4766
|
pointer-events: none;
|
|
4651
|
-
animation: _1auth-backdrop-in 0.2s ease-out;
|
|
4652
4767
|
}
|
|
4653
4768
|
dialog[data-passkey][data-passkey-hidden] [data-passkey-overlay] {
|
|
4654
4769
|
display: none;
|
|
4655
4770
|
}
|
|
4656
|
-
dialog[data-passkey] [data-passkey-card] {
|
|
4771
|
+
dialog[data-passkey] [data-passkey-preload-card] {
|
|
4657
4772
|
width: ${LOADING_MODAL_WIDTH}px;
|
|
4773
|
+
max-width: 100%;
|
|
4774
|
+
overflow: hidden;
|
|
4775
|
+
border-radius: ${LOADING_MODAL_RADIUS}px;
|
|
4776
|
+
background: ${theme.bgPrimary};
|
|
4777
|
+
box-shadow: 0 24px 80px rgba(0, 0, 0, 0.24), 0 2px 12px rgba(0, 0, 0, 0.12);
|
|
4778
|
+
font-family: ${LOADING_FONT_FAMILY};
|
|
4779
|
+
line-height: ${LOADING_LINE_HEIGHT};
|
|
4780
|
+
-webkit-font-smoothing: antialiased;
|
|
4781
|
+
-moz-osx-font-smoothing: grayscale;
|
|
4782
|
+
}
|
|
4783
|
+
dialog[data-passkey] [data-passkey-preload-body] {
|
|
4658
4784
|
box-sizing: border-box;
|
|
4785
|
+
display: flex;
|
|
4786
|
+
width: 100%;
|
|
4787
|
+
flex-direction: column;
|
|
4788
|
+
align-items: center;
|
|
4789
|
+
gap: ${LOADING_BODY_GAP}px;
|
|
4659
4790
|
padding: ${LOADING_MODAL_PADDING}px;
|
|
4660
4791
|
border-radius: ${LOADING_MODAL_RADIUS}px;
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4792
|
+
background: ${theme.bgPrimary};
|
|
4793
|
+
}
|
|
4794
|
+
dialog[data-passkey] [data-passkey-preload-spinner-wrap] {
|
|
4795
|
+
display: flex;
|
|
4796
|
+
align-items: center;
|
|
4797
|
+
padding: ${LOADING_ICON_PADDING}px;
|
|
4798
|
+
}
|
|
4799
|
+
dialog[data-passkey] [data-passkey-preload-spinner] {
|
|
4800
|
+
position: relative;
|
|
4801
|
+
width: ${SPINNER_SIZE}px;
|
|
4802
|
+
height: ${SPINNER_SIZE}px;
|
|
4803
|
+
}
|
|
4804
|
+
dialog[data-passkey] [data-passkey-preload-spinner] svg {
|
|
4805
|
+
position: absolute;
|
|
4806
|
+
inset: 0;
|
|
4807
|
+
width: 100%;
|
|
4808
|
+
height: 100%;
|
|
4809
|
+
color: ${BRAND_PURPLE};
|
|
4810
|
+
animation: _1auth-spin ${SPINNER_SPIN_DURATION_MS}ms linear infinite;
|
|
4811
|
+
}
|
|
4812
|
+
dialog[data-passkey] [data-passkey-preload-copy] {
|
|
4665
4813
|
display: flex;
|
|
4814
|
+
width: 100%;
|
|
4666
4815
|
flex-direction: column;
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4816
|
+
align-items: center;
|
|
4817
|
+
gap: ${LOADING_TITLE_BLOCK_GAP}px;
|
|
4818
|
+
text-align: center;
|
|
4819
|
+
}
|
|
4820
|
+
dialog[data-passkey] [data-passkey-preload-title] {
|
|
4821
|
+
margin: 0;
|
|
4822
|
+
color: ${theme.textPrimary};
|
|
4823
|
+
font-size: ${LOADING_TITLE_FONT_SIZE}px;
|
|
4824
|
+
font-weight: ${LOADING_TITLE_FONT_WEIGHT};
|
|
4673
4825
|
line-height: ${LOADING_LINE_HEIGHT};
|
|
4674
|
-
-webkit-font-smoothing: antialiased;
|
|
4675
|
-
-moz-osx-font-smoothing: grayscale;
|
|
4676
4826
|
}
|
|
4677
|
-
|
|
4827
|
+
dialog[data-passkey] [data-passkey-preload-subtitle] {
|
|
4828
|
+
margin: 0;
|
|
4829
|
+
color: ${theme.textSecondary};
|
|
4830
|
+
font-size: ${LOADING_SUBTITLE_FONT_SIZE}px;
|
|
4831
|
+
font-weight: ${LOADING_SUBTITLE_FONT_WEIGHT};
|
|
4832
|
+
line-height: ${LOADING_LINE_HEIGHT};
|
|
4833
|
+
}
|
|
4834
|
+
@media (max-width: 639px) {
|
|
4678
4835
|
dialog[data-passkey] [data-passkey-overlay] {
|
|
4679
4836
|
align-items: flex-end;
|
|
4680
4837
|
}
|
|
4681
|
-
dialog[data-passkey] [data-passkey-card] {
|
|
4838
|
+
dialog[data-passkey] [data-passkey-preload-card] {
|
|
4682
4839
|
width: 100%;
|
|
4683
|
-
border-bottom-left-radius: 0;
|
|
4684
4840
|
border-bottom-right-radius: 0;
|
|
4841
|
+
border-bottom-left-radius: 0;
|
|
4842
|
+
}
|
|
4843
|
+
dialog[data-passkey] [data-passkey-preload-body] {
|
|
4685
4844
|
padding-bottom: calc(${LOADING_MODAL_PADDING}px + env(safe-area-inset-bottom));
|
|
4686
|
-
animation: _1auth-card-slide 0.3s cubic-bezier(0.32, 0.72, 0, 1);
|
|
4687
4845
|
}
|
|
4688
4846
|
}
|
|
4689
|
-
@keyframes _1auth-backdrop-in {
|
|
4690
|
-
from { opacity: 0; } to { opacity: 1; }
|
|
4691
|
-
}
|
|
4692
|
-
@keyframes _1auth-card-in {
|
|
4693
|
-
from { opacity: 0; transform: scale(0.96) translateY(8px); }
|
|
4694
|
-
to { opacity: 1; transform: scale(1) translateY(0); }
|
|
4695
|
-
}
|
|
4696
|
-
@keyframes _1auth-card-slide {
|
|
4697
|
-
from { transform: translate3d(0, 100%, 0); }
|
|
4698
|
-
to { transform: translate3d(0, 0, 0); }
|
|
4699
|
-
}
|
|
4700
4847
|
@keyframes _1auth-spin {
|
|
4701
4848
|
from { transform: rotate(0deg); }
|
|
4702
4849
|
to { transform: rotate(360deg); }
|
|
4703
4850
|
}
|
|
4851
|
+
dialog[data-passkey] iframe {
|
|
4852
|
+
position: fixed;
|
|
4853
|
+
top: 0;
|
|
4854
|
+
left: 0;
|
|
4855
|
+
width: 100%;
|
|
4856
|
+
height: 100%;
|
|
4857
|
+
border: 0;
|
|
4858
|
+
background-color: transparent;
|
|
4859
|
+
color-scheme: normal;
|
|
4860
|
+
pointer-events: auto;
|
|
4861
|
+
backdrop-filter: blur(${backdropBlur}px);
|
|
4862
|
+
-webkit-backdrop-filter: blur(${backdropBlur}px);
|
|
4863
|
+
transition: none;
|
|
4864
|
+
}
|
|
4704
4865
|
`;
|
|
4705
4866
|
dialog.appendChild(style);
|
|
4706
4867
|
const overlay = document.createElement("div");
|
|
4707
4868
|
overlay.dataset.passkeyOverlay = "";
|
|
4869
|
+
const preloadCard = document.createElement("div");
|
|
4870
|
+
preloadCard.dataset.passkeyPreloadCard = "";
|
|
4871
|
+
const preloadBody = document.createElement("div");
|
|
4872
|
+
preloadBody.dataset.passkeyPreloadBody = "";
|
|
4873
|
+
const spinnerWrap = document.createElement("div");
|
|
4874
|
+
spinnerWrap.dataset.passkeyPreloadSpinnerWrap = "";
|
|
4875
|
+
const spinner = document.createElement("div");
|
|
4876
|
+
spinner.dataset.passkeyPreloadSpinner = "";
|
|
4708
4877
|
const spinnerCenter = SPINNER_SIZE / 2;
|
|
4709
4878
|
const spinnerGap = SPINNER_CIRCUMFERENCE - SPINNER_ARC;
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4879
|
+
spinner.innerHTML = `<svg viewBox="0 0 ${SPINNER_SIZE} ${SPINNER_SIZE}" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><circle cx="${spinnerCenter}" cy="${spinnerCenter}" r="${SPINNER_RADIUS}" stroke="currentColor" opacity="0.3" stroke-width="${SPINNER_STROKE}"/><circle cx="${spinnerCenter}" cy="${spinnerCenter}" r="${SPINNER_RADIUS}" stroke="currentColor" stroke-width="${SPINNER_STROKE}" stroke-linecap="round" stroke-dasharray="${SPINNER_ARC} ${spinnerGap}" transform="rotate(-90 ${spinnerCenter} ${spinnerCenter})"/></svg>`;
|
|
4880
|
+
spinnerWrap.appendChild(spinner);
|
|
4881
|
+
const preloadCopy = document.createElement("div");
|
|
4882
|
+
preloadCopy.dataset.passkeyPreloadCopy = "";
|
|
4883
|
+
const preloadTitle = document.createElement("p");
|
|
4884
|
+
preloadTitle.dataset.passkeyPreloadTitle = "";
|
|
4885
|
+
preloadTitle.textContent = LOADING_TITLE;
|
|
4886
|
+
const preloadSubtitle = document.createElement("p");
|
|
4887
|
+
preloadSubtitle.dataset.passkeyPreloadSubtitle = "";
|
|
4888
|
+
preloadSubtitle.textContent = LOADING_SUBTITLE;
|
|
4889
|
+
preloadCopy.append(preloadTitle, preloadSubtitle);
|
|
4890
|
+
preloadBody.append(spinnerWrap, preloadCopy);
|
|
4891
|
+
preloadCard.appendChild(preloadBody);
|
|
4892
|
+
overlay.appendChild(preloadCard);
|
|
4713
4893
|
dialog.appendChild(overlay);
|
|
4714
4894
|
const iframe = document.createElement("iframe");
|
|
4715
4895
|
iframe.setAttribute(
|
|
@@ -4729,21 +4909,23 @@ var OneAuthClient = class {
|
|
|
4729
4909
|
);
|
|
4730
4910
|
iframe.setAttribute("title", "Passkey");
|
|
4731
4911
|
iframe.style.opacity = "0";
|
|
4732
|
-
let
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4912
|
+
let revealed = false;
|
|
4913
|
+
let readyFailsafe;
|
|
4914
|
+
const revealIframe = () => {
|
|
4915
|
+
if (revealed) return;
|
|
4916
|
+
revealed = true;
|
|
4917
|
+
clearTimeout(readyFailsafe);
|
|
4736
4918
|
iframe.style.opacity = "1";
|
|
4737
|
-
overlay.style.
|
|
4738
|
-
requestAnimationFrame(() => {
|
|
4739
|
-
overlay.style.display = "none";
|
|
4740
|
-
});
|
|
4919
|
+
overlay.style.display = "none";
|
|
4741
4920
|
};
|
|
4742
|
-
const
|
|
4921
|
+
const revealFailsafe = setTimeout(revealIframe, 8e3);
|
|
4743
4922
|
const handleMessage = (event) => {
|
|
4744
4923
|
if (event.origin !== hostUrl.origin) return;
|
|
4745
|
-
if (event.
|
|
4746
|
-
|
|
4924
|
+
if (event.source !== iframe.contentWindow) return;
|
|
4925
|
+
if (event.data?.type === "PASSKEY_RENDERED") {
|
|
4926
|
+
revealIframe();
|
|
4927
|
+
} else if (event.data?.type === "PASSKEY_READY" && !revealed && readyFailsafe === void 0) {
|
|
4928
|
+
readyFailsafe = setTimeout(revealIframe, 1e3);
|
|
4747
4929
|
}
|
|
4748
4930
|
if (event.data?.type === "PASSKEY_DISCONNECT") {
|
|
4749
4931
|
localStorage.removeItem("1auth-user");
|
|
@@ -4771,7 +4953,13 @@ var OneAuthClient = class {
|
|
|
4771
4953
|
document.addEventListener("keydown", handleEscape);
|
|
4772
4954
|
const reveal = () => {
|
|
4773
4955
|
delete dialog.dataset.passkeyHidden;
|
|
4956
|
+
if (!revealed) {
|
|
4957
|
+
revealed = true;
|
|
4958
|
+
clearTimeout(readyFailsafe);
|
|
4959
|
+
clearTimeout(revealFailsafe);
|
|
4960
|
+
}
|
|
4774
4961
|
iframe.style.opacity = "1";
|
|
4962
|
+
overlay.style.display = "none";
|
|
4775
4963
|
};
|
|
4776
4964
|
if (options?.hidden) {
|
|
4777
4965
|
dialog.show();
|
|
@@ -4782,7 +4970,8 @@ var OneAuthClient = class {
|
|
|
4782
4970
|
const destroy = () => {
|
|
4783
4971
|
if (cleanedUp) return;
|
|
4784
4972
|
cleanedUp = true;
|
|
4785
|
-
clearTimeout(
|
|
4973
|
+
clearTimeout(revealFailsafe);
|
|
4974
|
+
clearTimeout(readyFailsafe);
|
|
4786
4975
|
inertObserver.disconnect();
|
|
4787
4976
|
viewportInfoCleanup();
|
|
4788
4977
|
window.removeEventListener("message", handleMessage);
|
|
@@ -5088,19 +5277,20 @@ var OneAuthClient = class {
|
|
|
5088
5277
|
return;
|
|
5089
5278
|
}
|
|
5090
5279
|
if (data?.type === "PASSKEY_GRANT_PERMISSION_RESULT") {
|
|
5091
|
-
teardown();
|
|
5092
|
-
cleanup();
|
|
5093
5280
|
if (data.success) {
|
|
5281
|
+
teardown();
|
|
5094
5282
|
resolve({ success: true, ...data.data ?? {} });
|
|
5095
|
-
|
|
5096
|
-
resolve({
|
|
5097
|
-
success: false,
|
|
5098
|
-
error: data.error ?? data.data?.error ?? {
|
|
5099
|
-
code: "GRANT_PERMISSION_FAILED",
|
|
5100
|
-
message: "Permission grant failed"
|
|
5101
|
-
}
|
|
5102
|
-
});
|
|
5283
|
+
return;
|
|
5103
5284
|
}
|
|
5285
|
+
teardown();
|
|
5286
|
+
cleanup();
|
|
5287
|
+
resolve({
|
|
5288
|
+
success: false,
|
|
5289
|
+
error: data.error ?? data.data?.error ?? {
|
|
5290
|
+
code: "GRANT_PERMISSION_FAILED",
|
|
5291
|
+
message: "Permission grant failed"
|
|
5292
|
+
}
|
|
5293
|
+
});
|
|
5104
5294
|
} else if (data?.type === "PASSKEY_CLOSE") {
|
|
5105
5295
|
teardown();
|
|
5106
5296
|
cleanup();
|