@tatchi-xyz/sdk 0.18.0 → 0.20.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/cjs/core/EmailRecovery/index.js +25 -0
- package/dist/cjs/core/EmailRecovery/index.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/emailRecovery.js +80 -60
- package/dist/cjs/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/index.js +23 -0
- package/dist/cjs/core/WebAuthnManager/index.js.map +1 -1
- package/dist/cjs/core/types/emailRecovery.js +33 -0
- package/dist/cjs/core/types/emailRecovery.js.map +1 -0
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BCrFe5p3.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → cjs/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-CRJrtxDb.css} +1 -1
- package/dist/{esm/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → cjs/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-DXFRw8ND.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-DXFRw8ND.css.map} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-DNgbAK_i.css} +1 -1
- package/dist/cjs/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-DNgbAK_i.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DRwSoF8q.css} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DRwSoF8q.css.map} +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +107 -21
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CL4gsszN.css} +1 -1
- package/dist/cjs/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CL4gsszN.css.map} +1 -1
- package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js +25 -0
- package/dist/cjs/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js +80 -60
- package/dist/cjs/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.js +23 -0
- package/dist/cjs/react/sdk/src/core/WebAuthnManager/index.js.map +1 -1
- package/dist/cjs/react/sdk/src/core/types/emailRecovery.js +33 -0
- package/dist/cjs/react/sdk/src/core/types/emailRecovery.js.map +1 -0
- package/dist/esm/core/EmailRecovery/index.js +25 -1
- package/dist/esm/core/EmailRecovery/index.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/emailRecovery.js +81 -61
- package/dist/esm/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/index.js +23 -0
- package/dist/esm/core/WebAuthnManager/index.js.map +1 -1
- package/dist/esm/core/types/emailRecovery.js +26 -0
- package/dist/esm/core/types/emailRecovery.js.map +1 -0
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react/components/AccountMenuButton/{LinkedDevicesModal-CSSowiHP.css → LinkedDevicesModal-BCrFe5p3.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/LinkedDevicesModal-CSSowiHP.css.map → esm/react/components/AccountMenuButton/LinkedDevicesModal-BCrFe5p3.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{ProfileDropdown-CEPMZ1gY.css → ProfileDropdown-CRJrtxDb.css} +1 -1
- package/dist/{cjs/react/components/AccountMenuButton/ProfileDropdown-CEPMZ1gY.css.map → esm/react/components/AccountMenuButton/ProfileDropdown-CRJrtxDb.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css → Web3AuthProfileButton-DXFRw8ND.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/{Web3AuthProfileButton-DopOg7Xc.css.map → Web3AuthProfileButton-DXFRw8ND.css.map} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css → TouchIcon-DNgbAK_i.css} +1 -1
- package/dist/esm/react/components/AccountMenuButton/icons/{TouchIcon-BQWentvJ.css.map → TouchIcon-DNgbAK_i.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css → PasskeyAuthMenu-DRwSoF8q.css} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-DwrzWMYx.css.map → PasskeyAuthMenu-DRwSoF8q.css.map} +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +107 -21
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css → ShowQRCode-CL4gsszN.css} +1 -1
- package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CL4gsszN.css.map} +1 -1
- package/dist/esm/react/sdk/src/core/EmailRecovery/index.js +25 -1
- package/dist/esm/react/sdk/src/core/EmailRecovery/index.js.map +1 -1
- package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js +81 -61
- package/dist/esm/react/sdk/src/core/TatchiPasskey/emailRecovery.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/localOnly.js.map +1 -1
- package/dist/esm/react/sdk/src/core/WebAuthnManager/index.js +23 -0
- package/dist/esm/react/sdk/src/core/WebAuthnManager/index.js.map +1 -1
- package/dist/esm/react/sdk/src/core/types/emailRecovery.js +26 -0
- package/dist/esm/react/sdk/src/core/types/emailRecovery.js.map +1 -0
- package/dist/esm/sdk/{createAdapters-qVGD6i0g.js → createAdapters-DIRR8_Z9.js} +1 -1
- package/dist/esm/sdk/{createAdapters-BumKM2ft.js → createAdapters-Yga6W0en.js} +2 -2
- package/dist/esm/sdk/{createAdapters-BumKM2ft.js.map → createAdapters-Yga6W0en.js.map} +1 -1
- package/dist/esm/sdk/{localOnly-pXMTqh1m.js → localOnly-BHScJasw.js} +2 -2
- package/dist/esm/sdk/{localOnly-Byi3AK7A.js → localOnly-VevCI7H0.js} +3 -3
- package/dist/esm/sdk/{localOnly-Byi3AK7A.js.map → localOnly-VevCI7H0.js.map} +1 -1
- package/dist/esm/sdk/offline-export-app.js +29 -6
- package/dist/esm/sdk/offline-export-app.js.map +1 -1
- package/dist/esm/sdk/{registration-CBiS4Ua_.js → registration-bKEg9Zr2.js} +2 -2
- package/dist/esm/sdk/{registration-CBiS4Ua_.js.map → registration-bKEg9Zr2.js.map} +1 -1
- package/dist/esm/sdk/{registration-DLPLsGCz.js → registration-lDD60Ytt.js} +1 -1
- package/dist/esm/sdk/{transactions-Bk-VavcV.js → transactions-BalIhtJ9.js} +1 -1
- package/dist/esm/sdk/{transactions-BIqKZeR0.js → transactions-bqaAwL4k.js} +2 -2
- package/dist/esm/sdk/{transactions-BIqKZeR0.js.map → transactions-bqaAwL4k.js.map} +1 -1
- package/dist/esm/sdk/wallet-iframe-host.js +150 -65
- package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
- package/dist/types/src/core/EmailRecovery/index.d.ts +8 -0
- package/dist/types/src/core/EmailRecovery/index.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts +7 -2
- package/dist/types/src/core/TatchiPasskey/emailRecovery.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/webauthn.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/index.d.ts +7 -0
- package/dist/types/src/core/WebAuthnManager/index.d.ts.map +1 -1
- package/dist/types/src/core/types/emailRecovery.d.ts +10 -0
- package/dist/types/src/core/types/emailRecovery.d.ts.map +1 -0
- package/dist/types/src/core/types/index.d.ts +1 -0
- package/dist/types/src/core/types/index.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
- package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Web3AuthProfileButton-
|
|
1
|
+
{"version":3,"file":"Web3AuthProfileButton-DXFRw8ND.css","names":[],"sources":["../../../../../src/react/components/AccountMenuButton/Web3AuthProfileButton.css"],"sourcesContent":["* {\n box-sizing: border-box;\n}\n\n.w3a-profile-button-morphable {\n position: relative;\n background-color: var(--w3a-colors-colorBackground);\n border: 1px solid var(--w3a-colors-borderPrimary);\n border-radius: 2rem;\n box-shadow: var(--w3a-shadows-sm);\n font-size: 14px;\n font-weight: 500;\n color: var(--w3a-colors-textPrimary);\n cursor: pointer;\n outline: none;\n overflow: visible;\n width: fit-content;\n transition: none;\n}\n\n.w3a-profile-button-morphable:hover {\n border-color: var(--w3a-colors-borderHover);\n}\n\n.w3a-profile-button-icon {\n flex-shrink: 0;\n}\n\n.w3a-profile-button-icon svg {\n overflow: visible;\n}\n\n.w3a-profile-button-username {\n white-space: nowrap;\n overflow: hidden;\n display: inline-block;\n}\n\n.w3a-profile-button-icon {\n color: var(--w3a-colors-textSecondary);\n}\n\n.w3a-profile-button-username {\n display: block; color: var(--w3a-colors-textSecondary);\n}\n\n.w3a-profile-button-username.hidden {\n display: none;\n}\n\n.w3a-user-account--toggle-content {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: space-between;\n transition: opacity 0.15s ease-in-out;\n}\n\n.w3a-user-account--toggle-text {\n flex: 1;\n}\n\n.w3a-user-account--toggle-title {\n font-weight: 500;\n color: var(--w3a-colors-textPrimary);\n font-size: 14px;\n margin: 0;\n}\n\n.w3a-user-account--toggle-description {\n font-size: 14px;\n color: var(--w3a-colors-textMuted);\n margin: 0;\n}\n"],"mappings":"AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TouchIcon-
|
|
1
|
+
{"version":3,"file":"TouchIcon-DNgbAK_i.css","names":[],"sources":["../../../../../../src/react/components/AccountMenuButton/icons/TouchIcon.css"],"sourcesContent":["/* TouchIcon specific styles and animations */\n\n.w3a-fingerprint-icon {\n transition: transform 400ms ease;\n}\n\n.w3a-fingerprint-icon path {\n /* Normalize path length so dash animations are simple */\n stroke: currentColor;\n}\n\n.w3a-fingerprint-icon.open path {\n /* Draw the fingerprint when expanding/opening */\n stroke-dasharray: 1;\n stroke-dashoffset: 1;\n animation: w3a-fp-open 1.6s ease-out 0.1s both;\n}\n\n/* Animate when closing the menu */\n.w3a-fingerprint-icon.closed path {\n stroke-dasharray: 1;\n stroke-dashoffset: 1;\n animation: w3a-fp-close 1.6s ease-out 0.1s both;\n}\n\n@keyframes w3a-fp-open {\n from { stroke-dashoffset: 1; }\n to { stroke-dashoffset: 0; }\n}\n\n@keyframes w3a-fp-close {\n from { stroke-dashoffset: 1; }\n to { stroke-dashoffset: 0; }\n}\n\n.w3a-fingerprint-icon:hover {\n transform: rotate(180deg) scale(1.2);\n}\n"],"mappings":"AAAA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PasskeyAuthMenu-DwrzWMYx.css","names":[],"sources":["../../../../../src/react/components/PasskeyAuthMenu/PasskeyAuthMenu.css"],"sourcesContent":["/* Root container */\n.w3a-signup-menu-root {\n position: relative; /* relative position to anchor back button */\n width: min(100dvw, 420px);\n max-width: 100dvw;\n min-width: 330px;\n min-height: 250px;\n color: var(--w3a-colors-textPrimary);\n background: var(--w3a-colors-colorBackground);\n border: 1px solid var(--w3a-colors-borderPrimary);\n border-radius: 3rem;\n box-shadow: var(--w3a-shadows-lg);\n padding: var(--w3a-spacing-lg);\n padding-top: calc(var(--w3a-spacing-lg) + 4px);\n position: relative;\n display: flex;\n flex-direction: column;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1), min-height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n will-change: height, min-height;\n}\n\n/* Back button */\n.w3a-back-button {\n position: absolute;\n top: 1rem;\n left: 1rem;\n width: 48px;\n height: 48px;\n padding: 0;\n aspect-ratio: 1 / 1;\n display: grid;\n place-items: center;\n line-height: 0;\n border-radius: 50%;\n color: var(--w3a-colors-textPrimary);\n background: transparent;\n cursor: pointer;\n border: none;\n z-index: 3;\n transition: transform 120ms ease, background-color 160ms ease, opacity 220ms ease;\n opacity: 0;\n pointer-events: none;\n filter: blur(0.2px);\n}\n.w3a-back-button.is-visible {\n opacity: 1;\n pointer-events: auto;\n filter: none;\n}\n.w3a-back-button:hover {\n transform: scale(1.02);\n background: var(--w3a-colors-surface);\n}\n.w3a-back-button:active {\n transform: scale(0.96);\n}\n\n/* Header */\n.w3a-header {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n opacity: 1;\n height: auto;\n overflow: hidden;\n transition: opacity 240ms ease-out, height 260ms cubic-bezier(0.2, 0.8, 0.2, 1), padding 260ms cubic-bezier(0.2, 0.8, 0.2, 1), margin 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n pointer-events: auto;\n position: relative;\n will-change: height, opacity;\n}\n\n/* Hide header when waiting or scan device is active */\n.w3a-signup-menu-root[data-waiting=\"true\"] .w3a-header,\n.w3a-signup-menu-root[data-scan-device=\"true\"] .w3a-header {\n opacity: 0;\n height: 0px;\n padding-top: 0px;\n padding-bottom: 0px;\n margin-top: 0px;\n margin-bottom: 0px;\n pointer-events: none;\n}\n\n/* Hide header when email recovery is active */\n.w3a-signup-menu-root[data-email-recovery=\"true\"] .w3a-header {\n opacity: 0;\n height: 0px;\n padding-top: 0px;\n padding-bottom: 0px;\n margin-top: 0px;\n margin-bottom: 0px;\n pointer-events: none;\n}\n\n/* Adjust content area when header is hidden */\n.w3a-signup-menu-root[data-waiting=\"true\"] .w3a-content-area,\n.w3a-signup-menu-root[data-scan-device=\"true\"] .w3a-content-area {\n flex: 1 1 auto;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Adjust content area when email recovery is active */\n.w3a-signup-menu-root[data-email-recovery=\"true\"] .w3a-content-area {\n flex: 1 1 auto;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Specific height adjustments for different states */\n.w3a-signup-menu-root[data-waiting=\"true\"] {\n min-height: 200px;\n}\n\n.w3a-signup-menu-root[data-scan-device=\"true\"] {\n min-height: 300px;\n}\n\n.w3a-signup-menu-root[data-email-recovery=\"true\"] {\n min-height: 320px;\n}\n\n.w3a-title {\n font-size: 24px;\n font-weight: 700;\n margin: 0.5rem 0.75rem;\n}\n\n.w3a-subhead {\n font-size: 1rem;\n font-weight: 500;\n line-height: 1;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n margin: 0;\n margin-bottom: 1rem;\n margin-left: 0.75rem;\n}\n\n/* Content switcher container */\n.w3a-content-switcher {\n display: flex;\n flex-direction: column;\n overflow: hidden; /* ensure smooth height animations without spillover */\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n will-change: height;\n}\n\n/* Content area container */\n.w3a-content-area {\n position: relative;\n /* do not force-stretch; let content define intrinsic height */\n flex: 0 1 auto;\n display: flex;\n flex-direction: column;\n animation: fade-in 240ms ease-out;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Intrinsic sizer wrapper inside content area used for height measurement */\n.w3a-content-sizer {\n display: block;\n width: 100%;\n}\n\n/* Default content */\n.w3a-signin-menu {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 0px;\n min-height: 250px;\n width: 100%;\n animation: content-enter 240ms ease-in-out;\n}\n\n@keyframes content-enter {\n from {\n opacity: 0;\n transform: scale(0.98) translateY(6px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n@keyframes fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* Social providers row */\n.w3a-social-row {\n display: flex;\n gap: 8px;\n margin-bottom: var(--w3a-spacing-sm);\n}\n.w3a-social-btn {\n height: 48px;\n flex: 1 1 0;\n min-width: 0;\n display: grid;\n place-items: center;\n cursor: pointer;\n color: var(--w3a-colors-textSecondary, #64748b);\n overflow: hidden;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n border-radius: var(--w3a-border-radius-xl);\n /* no shadow requested */\n box-shadow: none;\n}\n.w3a-social-btn svg {\n color: var(--w3a-colors-textSecondary, #64748b);\n}\n.w3a-social-btn:hover {\n background: var(--w3a-colors-surface2);\n box-shadow: var(--w3a-shadows-sm);\n}\n.w3a-social-btn:hover svg {\n color: var(--w3a-colors-textPrimary, #1e293b);\n}\n\n/* Passkey row */\n.w3a-passkey-row {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.w3a-input-pill {\n position: relative;\n display: flex;\n flex: 1;\n align-items: center;\n padding: 0rem 1rem;\n height: 54px;\n gap: 8px;\n border: none;\n background: var(--w3a-colors-surface);\n border-radius: 2rem 2rem 2rem 2rem;\n box-shadow: none;\n overflow-x: hidden;\n transition: border-radius 150ms ease-in-out;\n}\n.w3a-input-pill.is-enabled {\n border-radius: 2rem 0.25rem 0.25rem 2rem;\n transition: border-radius 150ms ease-in-out;\n}\n\n.w3a-input-wrap {\n position: relative;\n flex: 1;\n height: 32px;\n display: flex;\n align-items: center;\n min-width: 0; /* allow input to shrink inside flex container without clipping */\n}\n.w3a-input {\n width: 100%;\n height: 32px;\n border: none;\n outline: none;\n background: transparent;\n color: var(--w3a-colors-textPrimary);\n font-size: 16px;\n padding: 0;\n min-width: 0; /* prevent overflow clipping in flex layouts */\n}\n\n/* Absolute status message anchored to bottom-right of the input area */\n.w3a-input::placeholder {\n /* Improve contrast for placeholders on dark */\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 35%);\n opacity: 0.95;\n}\n\n.w3a-postfix {\n position: absolute;\n top: 50%;\n left: 0;\n transform: translateY(-50%);\n color: var(--w3a-colors-textSecondary);\n font-size: 16px;\n white-space: nowrap;\n pointer-events: none;\n visibility: hidden; /* React enables once measured */\n will-change: left;\n transition: left 32ms ease;\n}\n.w3a-postfix.is-existing {\n color: var(--w3a-colors-success);\n}\n/* On focus, keep postfix subtle for readability */\n.w3a-input:focus ~ .w3a-postfix {\n color: var(--w3a-colors-textMuted);\n}\n\n.w3a-arrow-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 0; /* hidden footprint by default */\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: 2rem 0.25rem 0.25rem 2rem;\n color: #fff;\n line-height: 0;\n cursor: pointer;\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n margin-left: -1rem;\n z-index: 1;\n border: 6px solid var(--w3a-colors-colorBackground, #fff);\n height: 64px;\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn.is-enabled {\n width: 100px; /* expand when enabled */\n /* Prefer themed primary; fall back to legacy then a sane default */\n background: var(--w3a-colors-primary, #2563eb);\n border-radius: 2rem;\n /* border-radius: 2rem; */\n opacity: 1;\n visibility: visible;\n pointer-events: auto;\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn.no-transition,\n.w3a-arrow-btn.no-transition.is-enabled {\n transition: none;\n}\n.w3a-arrow-btn .w3a-arrow-icon {\n color: #fff;\n}\n.w3a-arrow-btn.is-enabled:hover {\n /* transform: scale(1.02); */\n background: var(--w3a-colors-primaryHover, #1d4ed8);\n}\n.w3a-arrow-btn.is-enabled:active {\n transform: scale(0.96);\n}\n.w3a-arrow-btn:disabled {\n width: 0;\n cursor: not-allowed;\n opacity: 0.5;\n background: var(--w3a-colors-borderSecondary);\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn .w3a-arrow-label {\n margin-left: 8px;\n font-weight: 600;\n line-height: 1;\n}\n\n/* Animated arrow inside the continue button */\n.w3a-arrow-btn .stripe-arrow {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.w3a-arrow-btn .stripe-arrow > .HoverArrow {\n position: relative;\n margin-top: 0.1rem;\n margin-left: 8px;\n stroke-width: 2;\n fill: none;\n stroke: currentColor;\n}\n\n/* Horizontal line: fades in on hover of the button */\n.w3a-arrow-btn .stripe-arrow > .HoverArrow .HoverArrow__linePath {\n opacity: 0;\n transition: opacity 120ms cubic-bezier(0.215, 0.61, 0.355, 1);\n}\n\n/* Chevron: nudges right and slightly scales on hover */\n.w3a-arrow-btn .stripe-arrow > .HoverArrow .HoverArrow__tipPath {\n transition: transform 120ms cubic-bezier(0.215, 0.61, 0.355, 1);\n}\n\n.w3a-arrow-btn.is-enabled:hover .stripe-arrow > .HoverArrow .HoverArrow__linePath,\n.w3a-arrow-btn.is-enabled:focus-visible .stripe-arrow > .HoverArrow .HoverArrow__linePath {\n opacity: 1;\n}\n\n.w3a-arrow-btn.is-enabled:hover .stripe-arrow > .HoverArrow .HoverArrow__tipPath,\n.w3a-arrow-btn.is-enabled:focus-visible .stripe-arrow > .HoverArrow .HoverArrow__tipPath {\n transform: translateX(3px);\n}\n\n/* Segmented control */\n.w3a-seg {\n position: relative;\n min-height: 54px;\n overflow: hidden;\n padding: 5px;\n border: none;\n background: var(--w3a-colors-surface2);\n border-radius: var(--w3a-border-radius-xl);\n}\n.w3a-seg-active {\n position: absolute;\n top: 5px;\n bottom: 5px;\n left: 0;\n border-radius: var(--w3a-border-radius-xl);\n transition:\n transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1),\n width 220ms ease,\n opacity 150ms ease;\n will-change: transform, width;\n pointer-events: none;\n}\n.w3a-seg-grid {\n display: flex;\n gap: 4px;\n height: 100%;\n position: relative;\n z-index: 1;\n}\n.w3a-seg-btn {\n flex: 1 1 0;\n min-width: 0;\n min-height: 44px;\n border-radius: 12px;\n background: transparent;\n /* Make inactive tabs more legible and clearly tappable */\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 45%);\n font-weight: 600;\n cursor: pointer;\n border: none;\n /* Immediate taps on mobile; opt-out of double-tap zoom heuristics */\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n transition: color 200ms ease, transform 120ms ease;\n display: flex;\n align-items: center;\n justify-content: center;\n text-align: center;\n white-space: normal;\n padding: 0 14px;\n font-size: clamp(13px, 3.6vw, 15px);\n}\n.w3a-seg-btn:hover {\n transform: scale(1.02);\n}\n.w3a-seg-btn:active {\n transform: scale(0.98);\n}\n.w3a-seg-btn.is-active {\n color: var(--w3a-colors-textPrimary);\n}\n.w3a-seg-btn:focus-visible {\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--w3a-colors-focus), transparent 60%);\n}\n\n@media (max-width: 420px) {\n .w3a-signup-menu-root {\n padding: 1rem;\n padding-top: calc(1rem + 4px);\n border-radius: 2rem;\n max-width: calc(100dvw - 0.25rem);\n }\n\n @supports (width: 1dvw) {\n .w3a-signup-menu-root { max-width: calc(100dvw - 0.25rem); }\n }\n\n .w3a-title {\n font-size: 20px;\n }\n\n .w3a-subhead {\n font-size: 0.9rem;\n margin-bottom: 0.75rem;\n }\n\n .w3a-input-pill {\n height: 48px;\n }\n\n .w3a-arrow-btn {\n height: 60px;\n }\n\n .w3a-arrow-btn.is-enabled {\n width: 60px;\n }\n\n .w3a-seg {\n min-height: 48px;\n padding: 4px;\n }\n\n .w3a-seg-grid {\n gap: 3px;\n }\n\n .w3a-seg-active {\n top: 4px;\n bottom: 4px;\n }\n\n .w3a-seg-btn {\n min-height: 42px;\n padding: 0 12px;\n font-size: clamp(12px, 3.4vw, 14px);\n }\n\n .w3a-back-button {\n top: -0.5rem;\n left: -0.5rem;\n }\n}\n\n/* Waiting state */\n.w3a-waiting {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n background: transparent;\n text-align: center;\n min-height: 200px;\n /* Quick fade with configurable delay for smoother handoff */\n animation: content-enter 200ms ease-out;\n animation-delay: var(--w3a-waiting-delay, 0ms);\n animation-fill-mode: both;\n}\n.w3a-waiting-text { font-size: 18px; font-weight: 600; }\n.w3a-spinner {\n width: 36px;\n height: 36px;\n border-radius: 999px;\n border: 3px solid rgba(255,255,255,0.15);\n border-top-color: var(--w3a-colors-primary);\n animation: w3a-spin 0.9s linear infinite;\n}\n\n/* Scan device content wrapper */\n.w3a-scan-device-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n background: transparent;\n text-align: center;\n min-height: 300px;\n width: 100%;\n overflow: hidden;\n animation: content-enter 240ms ease-out;\n}\n\n/* Ensure QR code content stays within bounds */\n.w3a-scan-device-content .qr-code-container,\n.w3a-scan-device-content .qr-modal-backdrop,\n.w3a-scan-device-content .qr-modal-content {\n max-width: 100%;\n max-height: 100%;\n overflow: hidden;\n}\n\n.w3a-scan-device-content .qr-code-display {\n max-width: 280px;\n width: 100%;\n}\n\n/* Status message row */\n.w3a-status-row {\n position: absolute;\n font-size: 0.75rem;\n bottom: -10px;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n}\n.w3a-status-message {\n font-size: 11px;\n font-weight: 500;\n}\n\n/* Section divider */\n.w3a-section-divider {\n display: flex;\n align-items: center;\n margin: var(--w3a-spacing-md) 0;\n position: relative;\n}\n\n.w3a-section-divider::before,\n.w3a-section-divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: var(--w3a-colors-borderSecondary);\n}\n\n.w3a-section-divider-text {\n padding: 0 var(--w3a-spacing-sm);\n font-size: 12px;\n color: var(--w3a-colors-textSecondary);\n font-weight: 500;\n background: var(--w3a-colors-colorBackground);\n}\n\n/* Labels and helper text */\n.w3a-field-label {\n font-size: 12px;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 35%);\n margin: 6px 2px 6px;\n font-weight: 600;\n}\n.w3a-seg-help {\n font-size: 12px;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 25%);\n margin: 0;\n margin-left: 0.75rem;\n}\n.w3a-seg-help-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-top: 8px;\n}\n/* Tooltip for account existence status */\n.w3a-input-wrap .w3a-tooltip {\n position: absolute;\n right: 0;\n padding: 4px 8px;\n border-radius: 1rem;\n font-size: 0.7rem;\n background: var(--w3a-colors-surface2);\n color: var(--w3a-colors-textPrimary);\n opacity: 0;\n transform: translateX(50px) scale(0.9);\n pointer-events: none;\n transition: opacity 180ms ease, transform 200ms ease;\n z-index: 2;\n}\n.w3a-input-wrap .w3a-tooltip.is-visible {\n opacity: 0.8;\n transform: translateX(0px) scale(1);\n}\n.w3a-input-wrap .w3a-tooltip.is-error {\n color: var(--w3a-colors-error);\n background: var(--w3a-colors-colorBackground);\n /* background: color-mix(in srgb, var(--w3a-colors-error), transparent 90%); */\n}\n.w3a-input-wrap .w3a-tooltip.is-success {\n color: var(--w3a-colors-blue400);\n background: var(--w3a-colors-colorBackground);\n /* background: color-mix(in srgb, var(--w3a-colors-blue400), transparent 90%); */\n}\n\n@keyframes w3a-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Pop/bounce-in animation (kept for legacy classes) */\n@keyframes w3a-input-msg-pop {\n 0% { opacity: 0; transform: translateY(8px) scale(0.98); }\n 60% { opacity: 1; transform: translateY(-2px) scale(1.02); }\n 100% { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .w3a-input-msg.is-error { animation: none; }\n}\n\n/* Button System */\n.w3a-scan-device-row {\n}\n\n.w3a-secondary-actions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.w3a-link-device-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n overflow: hidden;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n height: 48px;\n width: 100%;\n max-width: 100%;\n background: var(--w3a-colors-surface) !important;\n border: 1px solid var(--w3a-colors-borderPrimary);\n border-radius: 2rem;\n cursor: pointer;\n color: var(--w3a-colors-textPrimary);\n font-family: var(--w3a-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);\n font-weight: 500;\n font-size: 0.875rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Hover/focus elevated state (theme-reactive via CSS vars) */\n.w3a-link-device-btn:hover:not(:disabled),\n.w3a-link-device-btn:focus-visible {\n background: var(--w3a-colors-surface2) !important;\n}\n\n.w3a-link-device-btn-primary {\n background: var(--w3a-colors-buttonBackground, var(--w3a-colors-primary, #3b82f6)) !important;\n border-color: transparent;\n border-radius: 2rem;\n color: var(--w3a-colors-textButton, white);\n}\n\n.w3a-link-device-btn-primary:hover:not(:disabled),\n.w3a-link-device-btn-primary:focus-visible {\n background: var(--w3a-colors-buttonHoverBackground, var(--w3a-colors-primaryHover, #2563eb)) !important;\n color: var(--w3a-colors-textButton, white);\n}\n\n.w3a-link-device-btn-primary:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* Button-local spinner: match text size inside buttons */\n.w3a-link-device-btn .w3a-spinner {\n width: 1em;\n height: 1em;\n border-width: 2px;\n}\n\n.w3a-link-device-btn-primary .w3a-spinner {\n border-color: rgba(255, 255, 255, 0.35);\n border-top-color: #ffffff;\n}\n\n/* Email recovery slide */\n.w3a-email-recovery-content {\n width: 100%;\n padding-top: 1rem;\n}\n\n.w3a-email-recovery-slide {\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-height: 260px;\n animation: content-enter 240ms ease-out;\n}\n\n.w3a-email-recovery-title {\n font-size: 20px;\n font-weight: 700;\n margin: 0.5rem 0.5rem;\n display: flex;\n justify-content: center;\n}\n\n.w3a-email-recovery-help {\n font-size: 0.95rem;\n line-height: 1.2;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n margin: 0 0.25rem;\n}\n\n.w3a-email-recovery-meta {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n padding: 0 0.25rem;\n font-size: 0.85rem;\n}\n\n.w3a-email-recovery-meta-label {\n opacity: 0.85;\n}\n\n.w3a-email-recovery-meta-value {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 0.85rem;\n opacity: 0.9;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 70%;\n text-align: right;\n}\n\n.w3a-email-recovery-input-pill {\n height: 54px;\n padding: 0 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n transition: box-shadow 160ms ease, border-color 160ms ease;\n}\n\n.w3a-email-recovery-input-pill:focus-within {\n border-color: var(--w3a-colors-primary, #3b82f6);\n}\n\n.w3a-email-recovery-actions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n.w3a-email-recovery-summary {\n font-size: 0.875rem;\n line-height: 1.2;\n padding: 0 0.25rem;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.w3a-email-recovery-warning {\n color: color-mix(in srgb, var(--w3a-colors-error), var(--w3a-colors-textPrimary) 30%);\n}\n\n.w3a-email-recovery-link {\n font-size: 0.875rem;\n color: var(--w3a-colors-primary, #3b82f6);\n text-decoration: none;\n padding: 0 0.25rem;\n}\n\n.w3a-email-recovery-link:hover {\n text-decoration: underline;\n}\n\n.w3a-email-recovery-status {\n font-size: 0.875rem;\n padding: 0.75rem 0.875rem;\n border-radius: 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n color: var(--w3a-colors-textPrimary);\n margin-bottom: 0.5rem;\n}\n\n.w3a-email-recovery-status.is-error {\n border-color: color-mix(in srgb, var(--w3a-colors-error), var(--w3a-colors-borderPrimary) 60%);\n color: var(--w3a-colors-error);\n}\n\n.w3a-email-recovery-elapsed {\n margin-left: 6px;\n opacity: 0.75;\n}\n\n.w3a-email-recovery-saved-emails {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.w3a-email-recovery-email-chip {\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n color: var(--w3a-colors-textPrimary);\n padding: 6px 10px;\n border-radius: 999px;\n font-size: 0.85rem;\n cursor: pointer;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.w3a-email-recovery-email-chip:hover:not(:disabled) {\n background: var(--w3a-colors-surface2);\n}\n\n.w3a-email-recovery-email-chip:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.w3a-email-recovery-toast {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0.75rem 0.875rem;\n border-radius: 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n font-size: 0.875rem;\n color: var(--w3a-colors-textPrimary);\n}\n\n.w3a-email-recovery-toast a {\n color: var(--w3a-colors-primary, #3b82f6);\n text-decoration: none;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 100%;\n}\n\n.w3a-email-recovery-toast a:hover {\n text-decoration: underline;\n}\n\n.w3a-email-recovery-toast-close {\n margin-left: auto;\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: none;\n background: transparent;\n color: var(--w3a-colors-textSecondary);\n cursor: pointer;\n display: grid;\n place-items: center;\n}\n\n.w3a-email-recovery-toast-close:hover {\n background: var(--w3a-colors-surface2);\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA"}
|
|
1
|
+
{"version":3,"file":"PasskeyAuthMenu-DRwSoF8q.css","names":[],"sources":["../../../../../src/react/components/PasskeyAuthMenu/PasskeyAuthMenu.css"],"sourcesContent":["/* Root container */\n.w3a-signup-menu-root {\n position: relative; /* relative position to anchor back button */\n width: min(100dvw, 420px);\n max-width: 100dvw;\n min-width: 330px;\n min-height: 250px;\n color: var(--w3a-colors-textPrimary);\n background: var(--w3a-colors-colorBackground);\n border: 1px solid var(--w3a-colors-borderPrimary);\n border-radius: 3rem;\n box-shadow: var(--w3a-shadows-lg);\n padding: var(--w3a-spacing-lg);\n padding-top: calc(var(--w3a-spacing-lg) + 4px);\n position: relative;\n display: flex;\n flex-direction: column;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1), min-height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n will-change: height, min-height;\n}\n\n/* Back button */\n.w3a-back-button {\n position: absolute;\n top: 1rem;\n left: 1rem;\n width: 48px;\n height: 48px;\n padding: 0;\n aspect-ratio: 1 / 1;\n display: grid;\n place-items: center;\n line-height: 0;\n border-radius: 50%;\n color: var(--w3a-colors-textPrimary);\n background: transparent;\n cursor: pointer;\n border: none;\n z-index: 3;\n transition: transform 120ms ease, background-color 160ms ease, opacity 220ms ease;\n opacity: 0;\n pointer-events: none;\n filter: blur(0.2px);\n}\n.w3a-back-button.is-visible {\n opacity: 1;\n pointer-events: auto;\n filter: none;\n}\n.w3a-back-button:hover {\n transform: scale(1.02);\n background: var(--w3a-colors-surface);\n}\n.w3a-back-button:active {\n transform: scale(0.96);\n}\n\n/* Header */\n.w3a-header {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n opacity: 1;\n height: auto;\n overflow: hidden;\n transition: opacity 240ms ease-out, height 260ms cubic-bezier(0.2, 0.8, 0.2, 1), padding 260ms cubic-bezier(0.2, 0.8, 0.2, 1), margin 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n pointer-events: auto;\n position: relative;\n will-change: height, opacity;\n}\n\n/* Hide header when waiting or scan device is active */\n.w3a-signup-menu-root[data-waiting=\"true\"] .w3a-header,\n.w3a-signup-menu-root[data-scan-device=\"true\"] .w3a-header {\n opacity: 0;\n height: 0px;\n padding-top: 0px;\n padding-bottom: 0px;\n margin-top: 0px;\n margin-bottom: 0px;\n pointer-events: none;\n}\n\n/* Hide header when email recovery is active */\n.w3a-signup-menu-root[data-email-recovery=\"true\"] .w3a-header {\n opacity: 0;\n height: 0px;\n padding-top: 0px;\n padding-bottom: 0px;\n margin-top: 0px;\n margin-bottom: 0px;\n pointer-events: none;\n}\n\n/* Adjust content area when header is hidden */\n.w3a-signup-menu-root[data-waiting=\"true\"] .w3a-content-area,\n.w3a-signup-menu-root[data-scan-device=\"true\"] .w3a-content-area {\n flex: 1 1 auto;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Adjust content area when email recovery is active */\n.w3a-signup-menu-root[data-email-recovery=\"true\"] .w3a-content-area {\n flex: 1 1 auto;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Specific height adjustments for different states */\n.w3a-signup-menu-root[data-waiting=\"true\"] {\n min-height: 200px;\n}\n\n.w3a-signup-menu-root[data-scan-device=\"true\"] {\n min-height: 300px;\n}\n\n.w3a-signup-menu-root[data-email-recovery=\"true\"] {\n min-height: 320px;\n}\n\n.w3a-title {\n font-size: 24px;\n font-weight: 700;\n margin: 0.5rem 0.75rem;\n}\n\n.w3a-subhead {\n font-size: 1rem;\n font-weight: 500;\n line-height: 1;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n margin: 0;\n margin-bottom: 1rem;\n margin-left: 0.75rem;\n}\n\n/* Content switcher container */\n.w3a-content-switcher {\n display: flex;\n flex-direction: column;\n overflow: hidden; /* ensure smooth height animations without spillover */\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n will-change: height;\n}\n\n/* Content area container */\n.w3a-content-area {\n position: relative;\n /* do not force-stretch; let content define intrinsic height */\n flex: 0 1 auto;\n display: flex;\n flex-direction: column;\n animation: fade-in 240ms ease-out;\n transition: height 260ms cubic-bezier(0.2, 0.8, 0.2, 1);\n}\n\n/* Intrinsic sizer wrapper inside content area used for height measurement */\n.w3a-content-sizer {\n display: block;\n width: 100%;\n}\n\n/* Default content */\n.w3a-signin-menu {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 0px;\n min-height: 250px;\n width: 100%;\n animation: content-enter 240ms ease-in-out;\n}\n\n@keyframes content-enter {\n from {\n opacity: 0;\n transform: scale(0.98) translateY(6px);\n }\n to {\n opacity: 1;\n transform: scale(1) translateY(0);\n }\n}\n\n@keyframes fade-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n\n/* Social providers row */\n.w3a-social-row {\n display: flex;\n gap: 8px;\n margin-bottom: var(--w3a-spacing-sm);\n}\n.w3a-social-btn {\n height: 48px;\n flex: 1 1 0;\n min-width: 0;\n display: grid;\n place-items: center;\n cursor: pointer;\n color: var(--w3a-colors-textSecondary, #64748b);\n overflow: hidden;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n border-radius: var(--w3a-border-radius-xl);\n /* no shadow requested */\n box-shadow: none;\n}\n.w3a-social-btn svg {\n color: var(--w3a-colors-textSecondary, #64748b);\n}\n.w3a-social-btn:hover {\n background: var(--w3a-colors-surface2);\n box-shadow: var(--w3a-shadows-sm);\n}\n.w3a-social-btn:hover svg {\n color: var(--w3a-colors-textPrimary, #1e293b);\n}\n\n/* Passkey row */\n.w3a-passkey-row {\n position: relative;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.w3a-input-pill {\n position: relative;\n display: flex;\n flex: 1;\n align-items: center;\n padding: 0rem 1rem;\n height: 54px;\n gap: 8px;\n border: none;\n background: var(--w3a-colors-surface);\n border-radius: 2rem 2rem 2rem 2rem;\n box-shadow: none;\n overflow-x: hidden;\n transition: border-radius 150ms ease-in-out;\n}\n.w3a-input-pill.is-enabled {\n border-radius: 2rem 0.25rem 0.25rem 2rem;\n transition: border-radius 150ms ease-in-out;\n}\n\n.w3a-input-wrap {\n position: relative;\n flex: 1;\n height: 32px;\n display: flex;\n align-items: center;\n min-width: 0; /* allow input to shrink inside flex container without clipping */\n}\n.w3a-input {\n width: 100%;\n height: 32px;\n border: none;\n outline: none;\n background: transparent;\n color: var(--w3a-colors-textPrimary);\n font-size: 16px;\n padding: 0;\n min-width: 0; /* prevent overflow clipping in flex layouts */\n}\n\n/* Absolute status message anchored to bottom-right of the input area */\n.w3a-input::placeholder {\n /* Improve contrast for placeholders on dark */\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 35%);\n opacity: 0.95;\n}\n\n.w3a-postfix {\n position: absolute;\n top: 50%;\n left: 0;\n transform: translateY(-50%);\n color: var(--w3a-colors-textSecondary);\n font-size: 16px;\n white-space: nowrap;\n pointer-events: none;\n visibility: hidden; /* React enables once measured */\n will-change: left;\n transition: left 32ms ease;\n}\n.w3a-postfix.is-existing {\n color: var(--w3a-colors-success);\n}\n/* On focus, keep postfix subtle for readability */\n.w3a-input:focus ~ .w3a-postfix {\n color: var(--w3a-colors-textMuted);\n}\n\n.w3a-arrow-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 0; /* hidden footprint by default */\n padding: 0;\n background: transparent;\n border: 0;\n border-radius: 2rem 0.25rem 0.25rem 2rem;\n color: #fff;\n line-height: 0;\n cursor: pointer;\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n margin-left: -1rem;\n z-index: 1;\n border: 6px solid var(--w3a-colors-colorBackground, #fff);\n height: 64px;\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn.is-enabled {\n width: 100px; /* expand when enabled */\n /* Prefer themed primary; fall back to legacy then a sane default */\n background: var(--w3a-colors-primary, #2563eb);\n border-radius: 2rem;\n /* border-radius: 2rem; */\n opacity: 1;\n visibility: visible;\n pointer-events: auto;\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn.no-transition,\n.w3a-arrow-btn.no-transition.is-enabled {\n transition: none;\n}\n.w3a-arrow-btn .w3a-arrow-icon {\n color: #fff;\n}\n.w3a-arrow-btn.is-enabled:hover {\n /* transform: scale(1.02); */\n background: var(--w3a-colors-primaryHover, #1d4ed8);\n}\n.w3a-arrow-btn.is-enabled:active {\n transform: scale(0.96);\n}\n.w3a-arrow-btn:disabled {\n width: 0;\n cursor: not-allowed;\n opacity: 0.5;\n background: var(--w3a-colors-borderSecondary);\n transition: transform 150ms ease,\n background-color 150ms ease,\n border-radius 150ms ease,\n opacity 150ms ease,\n width 150ms ease-in-out;\n}\n.w3a-arrow-btn .w3a-arrow-label {\n margin-left: 8px;\n font-weight: 600;\n line-height: 1;\n}\n\n/* Animated arrow inside the continue button */\n.w3a-arrow-btn .stripe-arrow {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.w3a-arrow-btn .stripe-arrow > .HoverArrow {\n position: relative;\n margin-top: 0.1rem;\n margin-left: 8px;\n stroke-width: 2;\n fill: none;\n stroke: currentColor;\n}\n\n/* Horizontal line: fades in on hover of the button */\n.w3a-arrow-btn .stripe-arrow > .HoverArrow .HoverArrow__linePath {\n opacity: 0;\n transition: opacity 120ms cubic-bezier(0.215, 0.61, 0.355, 1);\n}\n\n/* Chevron: nudges right and slightly scales on hover */\n.w3a-arrow-btn .stripe-arrow > .HoverArrow .HoverArrow__tipPath {\n transition: transform 120ms cubic-bezier(0.215, 0.61, 0.355, 1);\n}\n\n.w3a-arrow-btn.is-enabled:hover .stripe-arrow > .HoverArrow .HoverArrow__linePath,\n.w3a-arrow-btn.is-enabled:focus-visible .stripe-arrow > .HoverArrow .HoverArrow__linePath {\n opacity: 1;\n}\n\n.w3a-arrow-btn.is-enabled:hover .stripe-arrow > .HoverArrow .HoverArrow__tipPath,\n.w3a-arrow-btn.is-enabled:focus-visible .stripe-arrow > .HoverArrow .HoverArrow__tipPath {\n transform: translateX(3px);\n}\n\n/* Segmented control */\n.w3a-seg {\n position: relative;\n min-height: 54px;\n overflow: hidden;\n padding: 5px;\n border: none;\n background: var(--w3a-colors-surface2);\n border-radius: var(--w3a-border-radius-xl);\n}\n.w3a-seg-active {\n position: absolute;\n top: 5px;\n bottom: 5px;\n left: 0;\n border-radius: var(--w3a-border-radius-xl);\n transition:\n transform 320ms cubic-bezier(0.2, 0.8, 0.2, 1),\n width 220ms ease,\n opacity 150ms ease;\n will-change: transform, width;\n pointer-events: none;\n}\n.w3a-seg-grid {\n display: flex;\n gap: 4px;\n height: 100%;\n position: relative;\n z-index: 1;\n}\n.w3a-seg-btn {\n flex: 1 1 0;\n min-width: 0;\n min-height: 44px;\n border-radius: 12px;\n background: transparent;\n /* Make inactive tabs more legible and clearly tappable */\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 45%);\n font-weight: 600;\n cursor: pointer;\n border: none;\n /* Immediate taps on mobile; opt-out of double-tap zoom heuristics */\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n transition: color 200ms ease, transform 120ms ease;\n display: flex;\n align-items: center;\n justify-content: center;\n text-align: center;\n white-space: normal;\n padding: 0 14px;\n font-size: clamp(13px, 3.6vw, 15px);\n}\n.w3a-seg-btn:hover {\n transform: scale(1.02);\n}\n.w3a-seg-btn:active {\n transform: scale(0.98);\n}\n.w3a-seg-btn.is-active {\n color: var(--w3a-colors-textPrimary);\n}\n.w3a-seg-btn:focus-visible {\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--w3a-colors-focus), transparent 60%);\n}\n\n@media (max-width: 420px) {\n .w3a-signup-menu-root {\n padding: 1rem;\n padding-top: calc(1rem + 4px);\n border-radius: 2rem;\n max-width: calc(100dvw - 0.25rem);\n }\n\n @supports (width: 1dvw) {\n .w3a-signup-menu-root { max-width: calc(100dvw - 0.25rem); }\n }\n\n .w3a-title {\n font-size: 20px;\n }\n\n .w3a-subhead {\n font-size: 0.9rem;\n margin-bottom: 0.75rem;\n }\n\n .w3a-input-pill {\n height: 48px;\n }\n\n .w3a-arrow-btn {\n height: 60px;\n }\n\n .w3a-arrow-btn.is-enabled {\n width: 60px;\n }\n\n .w3a-seg {\n min-height: 48px;\n padding: 4px;\n }\n\n .w3a-seg-grid {\n gap: 3px;\n }\n\n .w3a-seg-active {\n top: 4px;\n bottom: 4px;\n }\n\n .w3a-seg-btn {\n min-height: 42px;\n padding: 0 12px;\n font-size: clamp(12px, 3.4vw, 14px);\n }\n\n .w3a-back-button {\n top: -0.5rem;\n left: -0.5rem;\n }\n}\n\n/* Waiting state */\n.w3a-waiting {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n background: transparent;\n text-align: center;\n min-height: 200px;\n /* Quick fade with configurable delay for smoother handoff */\n animation: content-enter 200ms ease-out;\n animation-delay: var(--w3a-waiting-delay, 0ms);\n animation-fill-mode: both;\n}\n.w3a-waiting-text { font-size: 18px; font-weight: 600; }\n.w3a-spinner {\n width: 36px;\n height: 36px;\n border-radius: 999px;\n border: 3px solid rgba(255,255,255,0.15);\n border-top-color: var(--w3a-colors-primary);\n animation: w3a-spin 0.9s linear infinite;\n}\n\n/* Scan device content wrapper */\n.w3a-scan-device-content {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 16px;\n background: transparent;\n text-align: center;\n min-height: 300px;\n width: 100%;\n overflow: hidden;\n animation: content-enter 240ms ease-out;\n}\n\n/* Ensure QR code content stays within bounds */\n.w3a-scan-device-content .qr-code-container,\n.w3a-scan-device-content .qr-modal-backdrop,\n.w3a-scan-device-content .qr-modal-content {\n max-width: 100%;\n max-height: 100%;\n overflow: hidden;\n}\n\n.w3a-scan-device-content .qr-code-display {\n max-width: 280px;\n width: 100%;\n}\n\n/* Status message row */\n.w3a-status-row {\n position: absolute;\n font-size: 0.75rem;\n bottom: -10px;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n}\n.w3a-status-message {\n font-size: 11px;\n font-weight: 500;\n}\n\n/* Section divider */\n.w3a-section-divider {\n display: flex;\n align-items: center;\n margin: var(--w3a-spacing-md) 0;\n position: relative;\n}\n\n.w3a-section-divider::before,\n.w3a-section-divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: var(--w3a-colors-borderSecondary);\n}\n\n.w3a-section-divider-text {\n padding: 0 var(--w3a-spacing-sm);\n font-size: 12px;\n color: var(--w3a-colors-textSecondary);\n font-weight: 500;\n background: var(--w3a-colors-colorBackground);\n}\n\n/* Labels and helper text */\n.w3a-field-label {\n font-size: 12px;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 35%);\n margin: 6px 2px 6px;\n font-weight: 600;\n}\n.w3a-seg-help {\n font-size: 12px;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 25%);\n margin: 0;\n margin-left: 0.75rem;\n}\n.w3a-seg-help-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-top: 8px;\n}\n/* Tooltip for account existence status */\n.w3a-input-wrap .w3a-tooltip {\n position: absolute;\n right: 0;\n padding: 4px 8px;\n border-radius: 1rem;\n font-size: 0.7rem;\n background: var(--w3a-colors-surface2);\n color: var(--w3a-colors-textPrimary);\n opacity: 0;\n transform: translateX(50px) scale(0.9);\n pointer-events: none;\n transition: opacity 180ms ease, transform 200ms ease;\n z-index: 2;\n}\n.w3a-input-wrap .w3a-tooltip.is-visible {\n opacity: 0.8;\n transform: translateX(0px) scale(1);\n}\n.w3a-input-wrap .w3a-tooltip.is-error {\n color: var(--w3a-colors-error);\n background: var(--w3a-colors-colorBackground);\n /* background: color-mix(in srgb, var(--w3a-colors-error), transparent 90%); */\n}\n.w3a-input-wrap .w3a-tooltip.is-success {\n color: var(--w3a-colors-blue400);\n background: var(--w3a-colors-colorBackground);\n /* background: color-mix(in srgb, var(--w3a-colors-blue400), transparent 90%); */\n}\n\n@keyframes w3a-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n/* Pop/bounce-in animation (kept for legacy classes) */\n@keyframes w3a-input-msg-pop {\n 0% { opacity: 0; transform: translateY(8px) scale(0.98); }\n 60% { opacity: 1; transform: translateY(-2px) scale(1.02); }\n 100% { opacity: 1; transform: translateY(0) scale(1); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .w3a-input-msg.is-error { animation: none; }\n}\n\n/* Button System */\n.w3a-scan-device-row {\n}\n\n.w3a-secondary-actions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.w3a-link-device-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n overflow: hidden;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n height: 48px;\n width: 100%;\n max-width: 100%;\n background: var(--w3a-colors-surface) !important;\n border: 1px solid var(--w3a-colors-borderPrimary);\n border-radius: 2rem;\n cursor: pointer;\n color: var(--w3a-colors-textPrimary);\n font-family: var(--w3a-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);\n font-weight: 500;\n font-size: 0.875rem;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* Hover/focus elevated state (theme-reactive via CSS vars) */\n.w3a-link-device-btn:hover:not(:disabled),\n.w3a-link-device-btn:focus-visible {\n background: var(--w3a-colors-surface2) !important;\n}\n\n.w3a-link-device-btn-primary {\n background: var(--w3a-colors-buttonBackground, var(--w3a-colors-primary, #3b82f6)) !important;\n border-color: transparent;\n border-radius: 2rem;\n color: var(--w3a-colors-textButton, white);\n}\n\n.w3a-link-device-btn-primary:hover:not(:disabled),\n.w3a-link-device-btn-primary:focus-visible {\n background: var(--w3a-colors-buttonHoverBackground, var(--w3a-colors-primaryHover, #2563eb)) !important;\n color: var(--w3a-colors-textButton, white);\n}\n\n.w3a-link-device-btn-primary:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* Button-local spinner: match text size inside buttons */\n.w3a-link-device-btn .w3a-spinner {\n width: 1em;\n height: 1em;\n border-width: 2px;\n}\n\n.w3a-link-device-btn-primary .w3a-spinner {\n border-color: rgba(255, 255, 255, 0.35);\n border-top-color: #ffffff;\n}\n\n/* Email recovery slide */\n.w3a-email-recovery-content {\n width: 100%;\n padding-top: 1rem;\n}\n\n.w3a-email-recovery-slide {\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-height: 260px;\n animation: content-enter 240ms ease-out;\n}\n\n.w3a-email-recovery-title {\n font-size: 20px;\n font-weight: 700;\n margin: 0.5rem 0.5rem;\n display: flex;\n justify-content: center;\n}\n\n.w3a-email-recovery-help {\n font-size: 0.95rem;\n line-height: 1.2;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n margin: 0 0.25rem;\n}\n\n.w3a-email-recovery-meta {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n padding: 0 0.25rem;\n font-size: 0.85rem;\n}\n\n.w3a-email-recovery-meta-label {\n opacity: 0.85;\n}\n\n.w3a-email-recovery-meta-value {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 0.85rem;\n opacity: 0.9;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 70%;\n text-align: right;\n}\n\n.w3a-email-recovery-input-pill {\n height: 54px;\n padding: 0 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n transition: box-shadow 160ms ease, border-color 160ms ease;\n}\n\n.w3a-email-recovery-input-pill:focus-within {\n border-color: var(--w3a-colors-primary, #3b82f6);\n}\n\n.w3a-email-recovery-actions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n.w3a-email-recovery-summary {\n font-size: 0.875rem;\n line-height: 1.2;\n padding: 0 0.25rem;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 20%);\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.w3a-email-recovery-warning {\n color: color-mix(in srgb, var(--w3a-colors-error), var(--w3a-colors-textPrimary) 30%);\n}\n\n.w3a-email-recovery-link {\n font-size: 0.875rem;\n color: var(--w3a-colors-primary, #3b82f6);\n text-decoration: none;\n padding: 0 0.25rem;\n}\n\n.w3a-email-recovery-link:hover {\n text-decoration: underline;\n}\n\n.w3a-email-recovery-status {\n font-size: 0.875rem;\n padding: 0.75rem 0.875rem;\n border-radius: 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n color: var(--w3a-colors-textPrimary);\n margin-bottom: 0.5rem;\n}\n\n.w3a-email-recovery-status.is-error {\n border-color: color-mix(in srgb, var(--w3a-colors-error), var(--w3a-colors-borderPrimary) 60%);\n color: var(--w3a-colors-error);\n}\n\n.w3a-email-recovery-elapsed {\n margin-left: 6px;\n opacity: 0.75;\n}\n\n.w3a-email-recovery-saved-emails {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.w3a-email-recovery-email-chip {\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n color: var(--w3a-colors-textPrimary);\n padding: 6px 10px;\n border-radius: 999px;\n font-size: 0.85rem;\n cursor: pointer;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.w3a-email-recovery-email-chip:hover:not(:disabled) {\n background: var(--w3a-colors-surface2);\n}\n\n.w3a-email-recovery-email-chip:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.w3a-email-recovery-toast {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 0.75rem 0.875rem;\n border-radius: 1rem;\n border: 1px solid var(--w3a-colors-borderPrimary);\n background: var(--w3a-colors-surface);\n font-size: 0.875rem;\n color: var(--w3a-colors-textPrimary);\n}\n\n.w3a-email-recovery-toast a {\n color: var(--w3a-colors-primary, #3b82f6);\n text-decoration: none;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 100%;\n}\n\n.w3a-email-recovery-toast a:hover {\n text-decoration: underline;\n}\n\n.w3a-email-recovery-toast-close {\n margin-left: auto;\n width: 28px;\n height: 28px;\n border-radius: 999px;\n border: none;\n background: transparent;\n color: var(--w3a-colors-textSecondary);\n cursor: pointer;\n display: grid;\n place-items: center;\n}\n\n.w3a-email-recovery-toast-close:hover {\n background: var(--w3a-colors-surface2);\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA"}
|
|
@@ -1,11 +1,36 @@
|
|
|
1
1
|
import { init_accountIds, toAccountId } from "../../../sdk/src/core/types/accountIds.js";
|
|
2
2
|
import { IndexedDBManager, init_IndexedDBManager } from "../../../sdk/src/core/IndexedDBManager/index.js";
|
|
3
|
+
import { EmailRecoveryErrorCode, init_emailRecovery } from "../../../sdk/src/core/types/emailRecovery.js";
|
|
3
4
|
import React from "react";
|
|
4
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
|
|
6
7
|
//#region src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.tsx
|
|
7
8
|
init_IndexedDBManager();
|
|
8
9
|
init_accountIds();
|
|
10
|
+
init_emailRecovery();
|
|
11
|
+
function getEmailRecoveryErrorCode(err) {
|
|
12
|
+
const code = err?.code;
|
|
13
|
+
if (typeof code !== "string") return null;
|
|
14
|
+
return Object.values(EmailRecoveryErrorCode).includes(code) ? code : null;
|
|
15
|
+
}
|
|
16
|
+
function getEmailRecoveryUiError(err) {
|
|
17
|
+
const fallback = err instanceof Error ? err.message : String(err || "");
|
|
18
|
+
const code = getEmailRecoveryErrorCode(err);
|
|
19
|
+
switch (code) {
|
|
20
|
+
case EmailRecoveryErrorCode.VRF_CHALLENGE_EXPIRED: return {
|
|
21
|
+
message: fallback || "Timed out finalizing registration (VRF challenge expired). Please restart email recovery and try again.",
|
|
22
|
+
canRestart: true
|
|
23
|
+
};
|
|
24
|
+
case EmailRecoveryErrorCode.REGISTRATION_NOT_VERIFIED: return {
|
|
25
|
+
message: fallback || "Registration did not verify on-chain. Please restart email recovery and try again.",
|
|
26
|
+
canRestart: true
|
|
27
|
+
};
|
|
28
|
+
default: return {
|
|
29
|
+
message: fallback || "Email recovery failed",
|
|
30
|
+
canRestart: false
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
9
34
|
const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, emailRecoveryOptions }) => {
|
|
10
35
|
const mountedRef = React.useRef(true);
|
|
11
36
|
const mailtoAttemptTimerRef = React.useRef(null);
|
|
@@ -24,10 +49,12 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
24
49
|
const [accountIdInput, setAccountIdInput] = React.useState("");
|
|
25
50
|
const [recoveryEmailInput, setRecoveryEmailInput] = React.useState("");
|
|
26
51
|
const [pendingMailtoUrl, setPendingMailtoUrl] = React.useState(null);
|
|
52
|
+
const [pendingNearPublicKey, setPendingNearPublicKey] = React.useState(null);
|
|
27
53
|
const [mailtoUiState, setMailtoUiState] = React.useState("ready");
|
|
28
54
|
const [statusText, setStatusText] = React.useState(null);
|
|
29
55
|
const [pollingElapsedMs, setPollingElapsedMs] = React.useState(null);
|
|
30
56
|
const [errorText, setErrorText] = React.useState(null);
|
|
57
|
+
const [canRestart, setCanRestart] = React.useState(false);
|
|
31
58
|
const [accountInfo, setAccountInfo] = React.useState(null);
|
|
32
59
|
const [accountInfoLoading, setAccountInfoLoading] = React.useState(false);
|
|
33
60
|
const [accountInfoError, setAccountInfoError] = React.useState(null);
|
|
@@ -45,11 +72,13 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
45
72
|
}, [accountId]);
|
|
46
73
|
React.useEffect(() => {
|
|
47
74
|
setPendingMailtoUrl(null);
|
|
75
|
+
setPendingNearPublicKey(null);
|
|
48
76
|
setMailtoUiState("ready");
|
|
49
77
|
cancelRequestedRef.current = false;
|
|
50
78
|
setStatusText(null);
|
|
51
79
|
setPollingElapsedMs(null);
|
|
52
80
|
setErrorText(null);
|
|
81
|
+
setCanRestart(false);
|
|
53
82
|
setAccountInfo(null);
|
|
54
83
|
setAccountInfoError(null);
|
|
55
84
|
setLocalRecoveryEmails([]);
|
|
@@ -66,10 +95,12 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
66
95
|
};
|
|
67
96
|
};
|
|
68
97
|
const safeSetPendingMailtoUrl = React.useMemo(() => safeSet(setPendingMailtoUrl), []);
|
|
98
|
+
const safeSetPendingNearPublicKey = React.useMemo(() => safeSet(setPendingNearPublicKey), []);
|
|
69
99
|
const safeSetStatusText = React.useMemo(() => safeSet(setStatusText), []);
|
|
70
100
|
const safeSetPollingElapsedMs = React.useMemo(() => safeSet(setPollingElapsedMs), []);
|
|
71
101
|
const safeSetErrorText = React.useMemo(() => safeSet(setErrorText), []);
|
|
72
102
|
const safeSetIsBusy = React.useMemo(() => safeSet(setIsBusy), []);
|
|
103
|
+
const safeSetCanRestart = React.useMemo(() => safeSet(setCanRestart), []);
|
|
73
104
|
const safeSetAccountInfo = React.useMemo(() => safeSet(setAccountInfo), []);
|
|
74
105
|
const safeSetAccountInfoLoading = React.useMemo(() => safeSet(setAccountInfoLoading), []);
|
|
75
106
|
const safeSetAccountInfoError = React.useMemo(() => safeSet(setAccountInfoError), []);
|
|
@@ -98,9 +129,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
98
129
|
if (ev?.phase === "email-recovery-error" || ev?.status === "error") {
|
|
99
130
|
const raw = ev?.error || ev?.message || "Email recovery failed";
|
|
100
131
|
safeSetErrorText(String(raw));
|
|
132
|
+
safeSetCanRestart(false);
|
|
101
133
|
}
|
|
102
134
|
}, [
|
|
103
135
|
emailRecoveryOptions,
|
|
136
|
+
safeSetCanRestart,
|
|
104
137
|
safeSetErrorText,
|
|
105
138
|
safeSetExplorerToast,
|
|
106
139
|
safeSetPollingElapsedMs,
|
|
@@ -276,9 +309,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
276
309
|
safeSetIsBusy(true);
|
|
277
310
|
cancelRequestedRef.current = false;
|
|
278
311
|
safeSetErrorText(null);
|
|
312
|
+
safeSetCanRestart(false);
|
|
279
313
|
safeSetStatusText(null);
|
|
280
314
|
safeSetPollingElapsedMs(null);
|
|
281
315
|
safeSetPendingMailtoUrl(null);
|
|
316
|
+
safeSetPendingNearPublicKey(null);
|
|
282
317
|
safeSetMailtoUiState("ready");
|
|
283
318
|
let didForwardError = false;
|
|
284
319
|
try {
|
|
@@ -297,6 +332,7 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
297
332
|
}
|
|
298
333
|
});
|
|
299
334
|
safeSetPendingMailtoUrl(result.mailtoUrl);
|
|
335
|
+
safeSetPendingNearPublicKey(result.nearPublicKey);
|
|
300
336
|
safeSetStatusText("Recovery email draft ready. If it didn’t open automatically, click “Open recovery email draft”. Waiting for verification…");
|
|
301
337
|
attemptOpenMailtoAuto(result.mailtoUrl);
|
|
302
338
|
const finalizePromise = tatchiPasskey.finalizeEmailRecovery({
|
|
@@ -306,7 +342,9 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
306
342
|
onEvent,
|
|
307
343
|
onError: (err) => {
|
|
308
344
|
if (cancelRequestedRef.current) return;
|
|
309
|
-
|
|
345
|
+
const uiError = getEmailRecoveryUiError(err);
|
|
346
|
+
safeSetErrorText(uiError.message || "Failed to finalize email recovery");
|
|
347
|
+
safeSetCanRestart(uiError.canRestart);
|
|
310
348
|
didForwardError = true;
|
|
311
349
|
emailRecoveryOptions?.onError?.(err);
|
|
312
350
|
},
|
|
@@ -333,10 +371,14 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
333
371
|
safeSetStatusText(null);
|
|
334
372
|
safeSetPollingElapsedMs(null);
|
|
335
373
|
safeSetPendingMailtoUrl(null);
|
|
374
|
+
safeSetPendingNearPublicKey(null);
|
|
336
375
|
safeSetMailtoUiState("ready");
|
|
376
|
+
safeSetCanRestart(false);
|
|
337
377
|
return;
|
|
338
378
|
}
|
|
339
|
-
|
|
379
|
+
const uiError = getEmailRecoveryUiError(err);
|
|
380
|
+
safeSetErrorText(uiError.message || "Failed to start email recovery");
|
|
381
|
+
safeSetCanRestart(uiError.canRestart);
|
|
340
382
|
if (!didForwardError && err instanceof Error) emailRecoveryOptions?.onError?.(err);
|
|
341
383
|
} finally {
|
|
342
384
|
safeSetIsBusy(false);
|
|
@@ -357,6 +399,40 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
357
399
|
attemptOpenMailtoAuto,
|
|
358
400
|
tatchiPasskey
|
|
359
401
|
]);
|
|
402
|
+
const handleRestart = React.useCallback(async () => {
|
|
403
|
+
const normalizedAccountId = (accountIdInput || "").trim();
|
|
404
|
+
if (!normalizedAccountId) return;
|
|
405
|
+
safeSetIsBusy(true);
|
|
406
|
+
try {
|
|
407
|
+
cancelRequestedRef.current = true;
|
|
408
|
+
await tatchiPasskey.cancelEmailRecovery({
|
|
409
|
+
accountId: normalizedAccountId,
|
|
410
|
+
nearPublicKey: pendingNearPublicKey || void 0
|
|
411
|
+
}).catch(() => {});
|
|
412
|
+
safeSetErrorText(null);
|
|
413
|
+
safeSetStatusText(null);
|
|
414
|
+
safeSetPollingElapsedMs(null);
|
|
415
|
+
safeSetPendingMailtoUrl(null);
|
|
416
|
+
safeSetPendingNearPublicKey(null);
|
|
417
|
+
safeSetMailtoUiState("ready");
|
|
418
|
+
safeSetCanRestart(false);
|
|
419
|
+
} finally {
|
|
420
|
+
cancelRequestedRef.current = false;
|
|
421
|
+
safeSetIsBusy(false);
|
|
422
|
+
}
|
|
423
|
+
}, [
|
|
424
|
+
accountIdInput,
|
|
425
|
+
pendingNearPublicKey,
|
|
426
|
+
safeSetCanRestart,
|
|
427
|
+
safeSetErrorText,
|
|
428
|
+
safeSetIsBusy,
|
|
429
|
+
safeSetMailtoUiState,
|
|
430
|
+
safeSetPendingMailtoUrl,
|
|
431
|
+
safeSetPendingNearPublicKey,
|
|
432
|
+
safeSetPollingElapsedMs,
|
|
433
|
+
safeSetStatusText,
|
|
434
|
+
tatchiPasskey
|
|
435
|
+
]);
|
|
360
436
|
const summaryLine = accountInfoLoading ? "Checking if account has recovery emails configured..." : accountInfo && !accountInfoError ? `Recovery emails configured: ${accountInfo.emailsCount}` : "\xA0";
|
|
361
437
|
const noRecoveryEmailsConfigured = !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount === 0;
|
|
362
438
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -368,7 +444,7 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
368
444
|
}),
|
|
369
445
|
/* @__PURE__ */ jsx("div", {
|
|
370
446
|
className: "w3a-email-recovery-help",
|
|
371
|
-
children: "Send a
|
|
447
|
+
children: "Send a recovery email from your registered email address. Your account will be recovered with a new key once the email is verified."
|
|
372
448
|
}),
|
|
373
449
|
/* @__PURE__ */ jsx("div", {
|
|
374
450
|
className: "w3a-email-recovery-field",
|
|
@@ -438,22 +514,32 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
438
514
|
}),
|
|
439
515
|
/* @__PURE__ */ jsxs("div", {
|
|
440
516
|
className: "w3a-email-recovery-actions",
|
|
441
|
-
children: [
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
"
|
|
455
|
-
|
|
456
|
-
|
|
517
|
+
children: [
|
|
518
|
+
(!pendingMailtoUrl || !isBusy) && /* @__PURE__ */ jsx("button", {
|
|
519
|
+
onClick: handleStart,
|
|
520
|
+
className: "w3a-link-device-btn w3a-link-device-btn-primary",
|
|
521
|
+
disabled: isBusy || noRecoveryEmailsConfigured,
|
|
522
|
+
children: noRecoveryEmailsConfigured ? "No recovery emails configured" : isBusy ? "Working…" : "Start Email Recovery"
|
|
523
|
+
}),
|
|
524
|
+
pendingMailtoUrl && /* @__PURE__ */ jsxs("button", {
|
|
525
|
+
type: "button",
|
|
526
|
+
onClick: () => attemptOpenMailtoFromUserGesture(pendingMailtoUrl),
|
|
527
|
+
className: "w3a-link-device-btn w3a-link-device-btn-primary",
|
|
528
|
+
disabled: mailtoUiState === "opening",
|
|
529
|
+
"aria-busy": mailtoUiState === "opening",
|
|
530
|
+
children: [mailtoUiState === "opening" && /* @__PURE__ */ jsx("span", {
|
|
531
|
+
className: "w3a-spinner",
|
|
532
|
+
"aria-hidden": "true"
|
|
533
|
+
}), mailtoUiState === "opening" ? "Opening email…" : "Open recovery email draft"]
|
|
534
|
+
}),
|
|
535
|
+
errorText && canRestart && /* @__PURE__ */ jsx("button", {
|
|
536
|
+
type: "button",
|
|
537
|
+
onClick: handleRestart,
|
|
538
|
+
className: "w3a-link-device-btn",
|
|
539
|
+
disabled: isBusy,
|
|
540
|
+
children: "Restart email recovery"
|
|
541
|
+
})
|
|
542
|
+
]
|
|
457
543
|
}),
|
|
458
544
|
(errorText || statusText || explorerToast) && /* @__PURE__ */ jsxs("div", {
|
|
459
545
|
className: `w3a-email-recovery-status${errorText ? " is-error" : ""}`,
|
|
@@ -467,13 +553,13 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
467
553
|
"s)."
|
|
468
554
|
]
|
|
469
555
|
}),
|
|
470
|
-
explorerToast && /* @__PURE__ */
|
|
556
|
+
explorerToast && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("a", {
|
|
471
557
|
className: "w3a-email-recovery-link",
|
|
472
558
|
href: explorerToast.url,
|
|
473
559
|
target: "_blank",
|
|
474
560
|
rel: "noopener noreferrer",
|
|
475
561
|
children: "View on explorer"
|
|
476
|
-
})
|
|
562
|
+
}) })
|
|
477
563
|
]
|
|
478
564
|
})
|
|
479
565
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmailRecoverySlide.js","names":["EmailRecoverySlide: React.FC<EmailRecoverySlideProps>","localEmails: string[]","info: EmailRecoveryAccountInfo | null","err: any"],"sources":["../../../../../../src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.tsx"],"sourcesContent":["import React from 'react';\n\nimport type { EmailRecoverySSEEvent } from '@/core/types/sdkSentEvents';\nimport type { TatchiPasskey } from '@/core/TatchiPasskey';\nimport { IndexedDBManager } from '@/core/IndexedDBManager';\nimport { toAccountId } from '@/core/types/accountIds';\n\nexport interface EmailRecoverySlideProps {\n tatchiPasskey: TatchiPasskey;\n accountId: string;\n refreshLoginState?: (nearAccountId?: string) => Promise<void>;\n emailRecoveryOptions?: {\n onEvent?: (event: EmailRecoverySSEEvent) => void;\n onError?: (error: Error) => void;\n };\n}\n\ntype EmailRecoveryPolicy = {\n minRequiredEmails?: number;\n maxAgeMs?: number;\n};\n\ntype EmailRecoveryAccountInfo = {\n emailsCount: number;\n};\n\ntype MailtoUiState = 'ready' | 'opening';\n\nexport const EmailRecoverySlide: React.FC<EmailRecoverySlideProps> = ({ tatchiPasskey, accountId, refreshLoginState, emailRecoveryOptions }) => {\n const mountedRef = React.useRef(true);\n const mailtoAttemptTimerRef = React.useRef<number | null>(null);\n const cancelRequestedRef = React.useRef(false);\n React.useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n };\n }, []);\n\n const [isBusy, setIsBusy] = React.useState(false);\n const [accountIdInput, setAccountIdInput] = React.useState('');\n const [recoveryEmailInput, setRecoveryEmailInput] = React.useState('');\n const [pendingMailtoUrl, setPendingMailtoUrl] = React.useState<string | null>(null);\n const [mailtoUiState, setMailtoUiState] = React.useState<MailtoUiState>('ready');\n const [statusText, setStatusText] = React.useState<string | null>(null);\n const [pollingElapsedMs, setPollingElapsedMs] = React.useState<number | null>(null);\n const [errorText, setErrorText] = React.useState<string | null>(null);\n const [accountInfo, setAccountInfo] = React.useState<EmailRecoveryAccountInfo | null>(null);\n const [accountInfoLoading, setAccountInfoLoading] = React.useState(false);\n const [accountInfoError, setAccountInfoError] = React.useState<string | null>(null);\n const [localRecoveryEmails, setLocalRecoveryEmails] = React.useState<string[]>([]);\n const [explorerToast, setExplorerToast] = React.useState<{ url: string; accountId?: string; transactionHash?: string } | null>(null);\n\n const lastPrefilledAccountIdRef = React.useRef<string>('');\n const lastPrefilledRecoveryEmailRef = React.useRef<string>('');\n\n React.useEffect(() => {\n const next = (accountId || '').trim();\n if (!next) return;\n if (accountIdInput.trim() === '' || accountIdInput === lastPrefilledAccountIdRef.current) {\n lastPrefilledAccountIdRef.current = next;\n setAccountIdInput(next);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [accountId]);\n\n React.useEffect(() => {\n setPendingMailtoUrl(null);\n setMailtoUiState('ready');\n cancelRequestedRef.current = false;\n setStatusText(null);\n setPollingElapsedMs(null);\n setErrorText(null);\n setAccountInfo(null);\n setAccountInfoError(null);\n setLocalRecoveryEmails([]);\n setExplorerToast(null);\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n }, [accountId]);\n\n const safeSet = <T,>(setter: React.Dispatch<React.SetStateAction<T>>) => {\n return (value: React.SetStateAction<T>) => {\n if (!mountedRef.current) return;\n setter(value);\n };\n };\n\n const safeSetPendingMailtoUrl = React.useMemo(() => safeSet(setPendingMailtoUrl), []);\n const safeSetStatusText = React.useMemo(() => safeSet(setStatusText), []);\n const safeSetPollingElapsedMs = React.useMemo(() => safeSet(setPollingElapsedMs), []);\n const safeSetErrorText = React.useMemo(() => safeSet(setErrorText), []);\n const safeSetIsBusy = React.useMemo(() => safeSet(setIsBusy), []);\n const safeSetAccountInfo = React.useMemo(() => safeSet(setAccountInfo), []);\n const safeSetAccountInfoLoading = React.useMemo(() => safeSet(setAccountInfoLoading), []);\n const safeSetAccountInfoError = React.useMemo(() => safeSet(setAccountInfoError), []);\n const safeSetLocalRecoveryEmails = React.useMemo(() => safeSet(setLocalRecoveryEmails), []);\n const safeSetExplorerToast = React.useMemo(() => safeSet(setExplorerToast), []);\n const safeSetMailtoUiState = React.useMemo(() => safeSet(setMailtoUiState), []);\n\n const onEvent = React.useCallback(\n (ev: EmailRecoverySSEEvent) => {\n if (cancelRequestedRef.current) return;\n safeSetStatusText(ev?.message || null);\n emailRecoveryOptions?.onEvent?.(ev);\n\n const data = (ev as any)?.data || {};\n const rawTxHash = data?.transactionHash ?? data?.transaction_hash;\n const txHash = typeof rawTxHash === 'string' ? rawTxHash.trim() : '';\n if (txHash) {\n const base = String(tatchiPasskey.configs?.nearExplorerUrl || 'https://testnet.nearblocks.io').replace(/\\/$/, '');\n const url = base.includes('nearblocks.io')\n ? `${base}/txns/${txHash}`\n : `${base}/transactions/${txHash}`;\n safeSetExplorerToast({ url, transactionHash: txHash });\n }\n const elapsedRaw = data?.elapsedMs ?? data?.elapsed_ms;\n if (elapsedRaw == null) safeSetPollingElapsedMs(null);\n const elapsed = elapsedRaw == null ? Number.NaN : Number(elapsedRaw);\n if (!Number.isNaN(elapsed)) safeSetPollingElapsedMs(elapsed);\n\n if (ev?.phase === 'email-recovery-error' || (ev as any)?.status === 'error') {\n const raw = (ev as any)?.error || ev?.message || 'Email recovery failed';\n safeSetErrorText(String(raw));\n }\n },\n [emailRecoveryOptions, safeSetErrorText, safeSetExplorerToast, safeSetPollingElapsedMs, safeSetStatusText, tatchiPasskey],\n );\n\n const showExplorerToast = React.useCallback(\n (rawAccountId: string) => {\n const normalized = (rawAccountId || '').trim();\n if (!normalized) return;\n const base = String(tatchiPasskey.configs?.nearExplorerUrl || 'https://testnet.nearblocks.io').replace(/\\/$/, '');\n const url = base.includes('nearblocks.io')\n ? `${base}/address/${normalized}`\n : `${base}/accounts/${normalized}`;\n\n safeSetExplorerToast({ url, accountId: normalized });\n },\n [safeSetExplorerToast, tatchiPasskey],\n );\n\n const launchMailto = React.useCallback((rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n\n if (typeof window !== 'undefined') {\n try {\n window.location.href = url;\n } catch {}\n }\n }, []);\n\n const attemptOpenMailtoFromUserGesture = React.useCallback(\n (rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n\n safeSetMailtoUiState('opening');\n\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n }\n\n // If the browser never blurs/hides (i.e. mailto blocked or cancelled), re-enable so users can retry.\n mailtoAttemptTimerRef.current = window.setTimeout(() => {\n safeSetMailtoUiState(prev => (prev === 'opening' ? 'ready' : prev));\n mailtoAttemptTimerRef.current = null;\n }, 2_000);\n\n launchMailto(url);\n },\n [launchMailto, safeSetMailtoUiState],\n );\n\n const attemptOpenMailtoAuto = React.useCallback(\n (rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n // Best-effort only: do not change `mailtoUiState` so users can immediately click the CTA.\n launchMailto(url);\n },\n [launchMailto],\n );\n\n React.useEffect(() => {\n if (mailtoUiState !== 'opening') return;\n if (typeof window === 'undefined' || typeof document === 'undefined') return;\n\n // Heuristic signals that the mail client likely opened. Treat as a hint only:\n // re-enable immediately so the CTA remains retryable even if this is a false-positive.\n const markMaybeOpened = () => {\n safeSetMailtoUiState('ready');\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n };\n\n const onVisibilityChange = () => {\n if (document.visibilityState === 'hidden') markMaybeOpened();\n };\n\n window.addEventListener('blur', markMaybeOpened);\n window.addEventListener('pagehide', markMaybeOpened);\n document.addEventListener('visibilitychange', onVisibilityChange);\n\n return () => {\n window.removeEventListener('blur', markMaybeOpened);\n window.removeEventListener('pagehide', markMaybeOpened);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n };\n }, [mailtoUiState, safeSetMailtoUiState]);\n\n const fetchLocalRecoveryEmailsFromIndexedDB = React.useCallback(\n async (rawAccountId: string): Promise<string[]> => {\n const normalized = (rawAccountId || '').trim();\n if (!normalized) {\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: empty accountId');\n return [];\n }\n\n try {\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: loading from IndexedDB', { accountId: normalized });\n const records = await IndexedDBManager.getRecoveryEmails(toAccountId(normalized));\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: raw IndexedDB records', {\n accountId: normalized,\n count: Array.isArray(records) ? records.length : 0,\n records,\n });\n if (!Array.isArray(records) || records.length === 0) return [];\n\n const sorted = [...records].sort((a, b) => (b?.addedAt || 0) - (a?.addedAt || 0));\n const emails = sorted\n .map(r => String(r?.email || '').trim().toLowerCase())\n .filter(e => !!e && e.includes('@'));\n\n const uniq = Array.from(new Set(emails));\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: parsed emails', {\n accountId: normalized,\n emails: uniq,\n });\n return uniq;\n } catch (err) {\n // best-effort; treat as no saved emails (e.g., IndexedDB unavailable)\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: failed to read IndexedDB', {\n accountId: normalized,\n error: err instanceof Error ? err.message : String(err),\n });\n return [];\n }\n },\n [],\n );\n\n const deriveEmailsFromRecoveryRecords = React.useCallback((records: unknown): string[] => {\n if (!Array.isArray(records) || records.length === 0) return [];\n const emails = records\n .map((r: any) => String(r?.email || '').trim().toLowerCase())\n .filter((e: string) => !!e && e.includes('@'));\n return Array.from(new Set(emails));\n }, []);\n\n React.useEffect(() => {\n const normalized = (accountIdInput || '').trim();\n if (!normalized) {\n setAccountInfo(null);\n setAccountInfoError(null);\n setAccountInfoLoading(false);\n safeSetLocalRecoveryEmails([]);\n return;\n }\n\n let cancelled = false;\n // Show loading state immediately (don't wait for debounce).\n safeSetAccountInfoLoading(true);\n safeSetAccountInfoError(null);\n const handle = window.setTimeout(() => {\n void (async () => {\n try {\n const isWalletIframeMode = !!tatchiPasskey.configs?.iframeWallet?.walletOrigin;\n\n // Legacy mode: suggest recovery emails from local IndexedDB mapping (best-effort).\n let localEmails: string[] = [];\n if (!isWalletIframeMode) {\n localEmails = await fetchLocalRecoveryEmailsFromIndexedDB(normalized);\n if (!cancelled) {\n console.log('[EmailRecoverySlide] local saved emails (IndexedDB)', { accountId: normalized, localEmails });\n }\n }\n\n const records = await tatchiPasskey.getRecoveryEmails(normalized);\n const resolvedEmails = isWalletIframeMode\n ? deriveEmailsFromRecoveryRecords(records)\n : localEmails;\n\n if (!cancelled) {\n safeSetLocalRecoveryEmails(resolvedEmails);\n console.log('[EmailRecoverySlide] recovery email suggestions (state)', { accountId: normalized, emails: resolvedEmails });\n\n if (\n resolvedEmails.length === 1 &&\n (recoveryEmailInput.trim() === '' || recoveryEmailInput === lastPrefilledRecoveryEmailRef.current)\n ) {\n lastPrefilledRecoveryEmailRef.current = resolvedEmails[0];\n setRecoveryEmailInput(resolvedEmails[0]);\n }\n }\n\n const info: EmailRecoveryAccountInfo | null = records\n ? { emailsCount: Array.isArray(records) ? records.length : 0 }\n : null;\n if (cancelled) return;\n safeSetAccountInfo(info);\n } catch (err: any) {\n if (cancelled) return;\n safeSetAccountInfo(null);\n safeSetAccountInfoError(err?.message || 'Failed to load email recovery settings for this account');\n } finally {\n if (!cancelled) safeSetAccountInfoLoading(false);\n }\n })();\n }, 350);\n\n return () => {\n cancelled = true;\n window.clearTimeout(handle);\n };\n }, [\n accountIdInput,\n deriveEmailsFromRecoveryRecords,\n fetchLocalRecoveryEmailsFromIndexedDB,\n recoveryEmailInput,\n safeSetAccountInfo,\n safeSetAccountInfoError,\n safeSetAccountInfoLoading,\n safeSetLocalRecoveryEmails,\n tatchiPasskey,\n ]);\n\n const handleStart = React.useCallback(async () => {\n const normalizedAccountId = (accountIdInput || '').trim();\n if (!normalizedAccountId) {\n safeSetErrorText('Enter an account ID.');\n return;\n }\n\n const emailCandidate = (recoveryEmailInput || '').trim().toLowerCase();\n if (!emailCandidate) {\n safeSetErrorText('Enter the recovery email to send from.');\n return;\n }\n\n safeSetIsBusy(true);\n cancelRequestedRef.current = false;\n safeSetErrorText(null);\n safeSetStatusText(null);\n safeSetPollingElapsedMs(null);\n safeSetPendingMailtoUrl(null);\n safeSetMailtoUiState('ready');\n\n let didForwardError = false;\n try {\n const result = await tatchiPasskey.startEmailRecovery({\n accountId: normalizedAccountId,\n recoveryEmail: emailCandidate,\n options: {\n onEvent,\n onError: (err: Error) => {\n if (cancelRequestedRef.current) return;\n safeSetErrorText(err?.message || 'Failed to start email recovery');\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n afterCall: async () => {},\n } as any,\n });\n\n safeSetPendingMailtoUrl(result.mailtoUrl);\n safeSetStatusText('Recovery email draft ready. If it didn’t open automatically, click “Open recovery email draft”. Waiting for verification…');\n\n // Best-effort open. If blocked/cancelled, the CTA remains immediately clickable for a user-gesture retry.\n attemptOpenMailtoAuto(result.mailtoUrl);\n\n // Start polling immediately after attempting to open the email prompt.\n const finalizePromise = tatchiPasskey.finalizeEmailRecovery({\n accountId: normalizedAccountId,\n nearPublicKey: result.nearPublicKey,\n options: {\n onEvent,\n onError: (err: Error) => {\n if (cancelRequestedRef.current) return;\n safeSetErrorText(err?.message || 'Failed to finalize email recovery');\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n afterCall: async () => {},\n } as any,\n });\n\n showExplorerToast(normalizedAccountId);\n\n await finalizePromise;\n\n // Best-effort auto-login: the core flow attempts it, but if it couldn't (e.g. missing Shamir\n // auto-unlock and user cancelled TouchID), try once more here.\n let loginOk = false;\n const session = await tatchiPasskey.getLoginSession(normalizedAccountId).catch(() => null);\n if (session?.login?.isLoggedIn) {\n loginOk = true;\n } else {\n safeSetStatusText('Email recovery completed. Logging you in…');\n loginOk = await tatchiPasskey.loginAndCreateSession(normalizedAccountId)\n .then(() => true)\n .catch(() => false);\n }\n\n if (refreshLoginState) {\n await refreshLoginState(normalizedAccountId).catch(() => {});\n }\n\n safeSetStatusText(loginOk ? 'Email recovery completed on this device.' : 'Email recovery completed. Please log in on this device.');\n safeSetPendingMailtoUrl(null);\n safeSetMailtoUiState('ready');\n safeSetPollingElapsedMs(null);\n } catch (err: any) {\n if (cancelRequestedRef.current) {\n safeSetErrorText('Email recovery cancelled. Please try again.');\n safeSetStatusText(null);\n safeSetPollingElapsedMs(null);\n safeSetPendingMailtoUrl(null);\n safeSetMailtoUiState('ready');\n return;\n }\n safeSetErrorText(err?.message || 'Failed to start email recovery');\n if (!didForwardError && err instanceof Error) {\n emailRecoveryOptions?.onError?.(err);\n }\n } finally {\n safeSetIsBusy(false);\n }\n }, [\n accountIdInput,\n emailRecoveryOptions,\n recoveryEmailInput,\n onEvent,\n refreshLoginState,\n showExplorerToast,\n safeSetErrorText,\n safeSetIsBusy,\n safeSetPendingMailtoUrl,\n safeSetPollingElapsedMs,\n safeSetStatusText,\n safeSetMailtoUiState,\n attemptOpenMailtoAuto,\n tatchiPasskey,\n ]);\n\n const summaryLine = accountInfoLoading\n ? 'Checking if account has recovery emails configured...'\n : accountInfo && !accountInfoError\n ? `Recovery emails configured: ${accountInfo.emailsCount}`\n : '\\u00A0';\n\n const noRecoveryEmailsConfigured =\n !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount === 0;\n\n return (\n <div className=\"w3a-email-recovery-slide\">\n <div className=\"w3a-email-recovery-title\">Recover Account with Email</div>\n <div className=\"w3a-email-recovery-help\">\n Send a special recovery email from your recovery email address.\n Your account will be recovered with a new key once the email is verified.\n </div>\n\n <div className=\"w3a-email-recovery-field\">\n <div className=\"w3a-input-pill w3a-email-recovery-input-pill\">\n <div className=\"w3a-input-wrap\">\n <input\n type=\"text\"\n value={accountIdInput}\n onChange={(e) => setAccountIdInput(e.target.value)}\n placeholder=\"NEAR account ID (e.g. alice.testnet)\"\n className=\"w3a-input\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n inputMode=\"text\"\n disabled={isBusy}\n />\n </div>\n </div>\n </div>\n\n <div className=\"w3a-email-recovery-summary\" aria-live=\"polite\">\n <div>{summaryLine}</div>\n </div>\n\n <div className=\"w3a-email-recovery-field\">\n <div className=\"w3a-input-pill w3a-email-recovery-input-pill\">\n <div className=\"w3a-input-wrap\">\n <input\n type=\"email\"\n value={recoveryEmailInput}\n onChange={(e) => setRecoveryEmailInput(e.target.value)}\n placeholder=\"Recovery email to send from\"\n className=\"w3a-input\"\n list={localRecoveryEmails.length > 0 ? 'w3a-email-recovery-saved-emails' : undefined}\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n inputMode=\"email\"\n disabled={isBusy || noRecoveryEmailsConfigured}\n />\n </div>\n </div>\n </div>\n\n {localRecoveryEmails.length > 0 && (\n <div className=\"w3a-email-recovery-summary\" aria-live=\"polite\">\n <div>Saved on this device:</div>\n <div className=\"w3a-email-recovery-saved-emails\">\n {localRecoveryEmails.map((email) => (\n <button\n key={email}\n type=\"button\"\n className=\"w3a-email-recovery-email-chip\"\n onClick={() => setRecoveryEmailInput(email)}\n disabled={isBusy}\n >\n {email}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {localRecoveryEmails.length > 0 && (\n <datalist id=\"w3a-email-recovery-saved-emails\">\n {localRecoveryEmails.map((email) => (\n <option key={email} value={email} />\n ))}\n </datalist>\n )}\n\n <div className=\"w3a-email-recovery-actions\">\n {(!pendingMailtoUrl || !isBusy) && (\n <button\n onClick={handleStart}\n className=\"w3a-link-device-btn w3a-link-device-btn-primary\"\n disabled={isBusy || noRecoveryEmailsConfigured}\n >\n {noRecoveryEmailsConfigured ? 'No recovery emails configured' : (isBusy ? 'Working…' : 'Start Email Recovery')}\n </button>\n )}\n\n {pendingMailtoUrl && (\n <button\n type=\"button\"\n onClick={() => attemptOpenMailtoFromUserGesture(pendingMailtoUrl)}\n className=\"w3a-link-device-btn w3a-link-device-btn-primary\"\n disabled={mailtoUiState === 'opening'}\n aria-busy={mailtoUiState === 'opening'}\n >\n {mailtoUiState === 'opening' && <span className=\"w3a-spinner\" aria-hidden=\"true\" />}\n {mailtoUiState === 'opening' ? 'Opening email…' : 'Open recovery email draft'}\n </button>\n )}\n </div>\n\n {(errorText || statusText || explorerToast) && (\n <div className={`w3a-email-recovery-status${errorText ? ' is-error' : ''}`}>\n {errorText ? errorText : statusText}\n {pollingElapsedMs != null && !Number.isNaN(pollingElapsedMs) && pollingElapsedMs > 0 && (\n <span className=\"w3a-email-recovery-elapsed\">\n (~{Math.round(pollingElapsedMs / 1000)}s).\n </span>\n )}\n {explorerToast && (\n <>\n <br />\n <a className=\"w3a-email-recovery-link\" href={explorerToast.url} target=\"_blank\" rel=\"noopener noreferrer\">\n View on explorer\n </a>\n </>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default EmailRecoverySlide;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EmailRecoverySlide.js","names":["EmailRecoverySlide: React.FC<EmailRecoverySlideProps>","localEmails: string[]","info: EmailRecoveryAccountInfo | null","err: any"],"sources":["../../../../../../src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.tsx"],"sourcesContent":["import React from 'react';\n\nimport type { EmailRecoverySSEEvent } from '@/core/types/sdkSentEvents';\nimport type { TatchiPasskey } from '@/core/TatchiPasskey';\nimport { IndexedDBManager } from '@/core/IndexedDBManager';\nimport { toAccountId } from '@/core/types/accountIds';\nimport { EmailRecoveryErrorCode } from '@/core/types/emailRecovery';\n\nexport interface EmailRecoverySlideProps {\n tatchiPasskey: TatchiPasskey;\n accountId: string;\n refreshLoginState?: (nearAccountId?: string) => Promise<void>;\n emailRecoveryOptions?: {\n onEvent?: (event: EmailRecoverySSEEvent) => void;\n onError?: (error: Error) => void;\n };\n}\n\ntype EmailRecoveryPolicy = {\n minRequiredEmails?: number;\n maxAgeMs?: number;\n};\n\ntype EmailRecoveryAccountInfo = {\n emailsCount: number;\n};\n\ntype MailtoUiState = 'ready' | 'opening';\n\nfunction getEmailRecoveryErrorCode(err: unknown): EmailRecoveryErrorCode | null {\n const code = (err as { code?: unknown } | null)?.code;\n if (typeof code !== 'string') return null;\n return Object.values(EmailRecoveryErrorCode).includes(code as EmailRecoveryErrorCode)\n ? (code as EmailRecoveryErrorCode)\n : null;\n}\n\nfunction getEmailRecoveryUiError(err: unknown): { message: string; canRestart: boolean } {\n const fallback = err instanceof Error ? err.message : String(err || '');\n const code = getEmailRecoveryErrorCode(err);\n switch (code) {\n case EmailRecoveryErrorCode.VRF_CHALLENGE_EXPIRED:\n return {\n message: fallback || 'Timed out finalizing registration (VRF challenge expired). Please restart email recovery and try again.',\n canRestart: true,\n };\n case EmailRecoveryErrorCode.REGISTRATION_NOT_VERIFIED:\n return {\n message: fallback || 'Registration did not verify on-chain. Please restart email recovery and try again.',\n canRestart: true,\n };\n default:\n return { message: fallback || 'Email recovery failed', canRestart: false };\n }\n}\n\nexport const EmailRecoverySlide: React.FC<EmailRecoverySlideProps> = ({ tatchiPasskey, accountId, refreshLoginState, emailRecoveryOptions }) => {\n const mountedRef = React.useRef(true);\n const mailtoAttemptTimerRef = React.useRef<number | null>(null);\n const cancelRequestedRef = React.useRef(false);\n React.useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n };\n }, []);\n\n const [isBusy, setIsBusy] = React.useState(false);\n const [accountIdInput, setAccountIdInput] = React.useState('');\n const [recoveryEmailInput, setRecoveryEmailInput] = React.useState('');\n const [pendingMailtoUrl, setPendingMailtoUrl] = React.useState<string | null>(null);\n const [pendingNearPublicKey, setPendingNearPublicKey] = React.useState<string | null>(null);\n const [mailtoUiState, setMailtoUiState] = React.useState<MailtoUiState>('ready');\n const [statusText, setStatusText] = React.useState<string | null>(null);\n const [pollingElapsedMs, setPollingElapsedMs] = React.useState<number | null>(null);\n const [errorText, setErrorText] = React.useState<string | null>(null);\n const [canRestart, setCanRestart] = React.useState(false);\n const [accountInfo, setAccountInfo] = React.useState<EmailRecoveryAccountInfo | null>(null);\n const [accountInfoLoading, setAccountInfoLoading] = React.useState(false);\n const [accountInfoError, setAccountInfoError] = React.useState<string | null>(null);\n const [localRecoveryEmails, setLocalRecoveryEmails] = React.useState<string[]>([]);\n const [explorerToast, setExplorerToast] = React.useState<{ url: string; accountId?: string; transactionHash?: string } | null>(null);\n\n const lastPrefilledAccountIdRef = React.useRef<string>('');\n const lastPrefilledRecoveryEmailRef = React.useRef<string>('');\n\n React.useEffect(() => {\n const next = (accountId || '').trim();\n if (!next) return;\n if (accountIdInput.trim() === '' || accountIdInput === lastPrefilledAccountIdRef.current) {\n lastPrefilledAccountIdRef.current = next;\n setAccountIdInput(next);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [accountId]);\n\n React.useEffect(() => {\n setPendingMailtoUrl(null);\n setPendingNearPublicKey(null);\n setMailtoUiState('ready');\n cancelRequestedRef.current = false;\n setStatusText(null);\n setPollingElapsedMs(null);\n setErrorText(null);\n setCanRestart(false);\n setAccountInfo(null);\n setAccountInfoError(null);\n setLocalRecoveryEmails([]);\n setExplorerToast(null);\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n }, [accountId]);\n\n const safeSet = <T,>(setter: React.Dispatch<React.SetStateAction<T>>) => {\n return (value: React.SetStateAction<T>) => {\n if (!mountedRef.current) return;\n setter(value);\n };\n };\n\n const safeSetPendingMailtoUrl = React.useMemo(() => safeSet(setPendingMailtoUrl), []);\n const safeSetPendingNearPublicKey = React.useMemo(() => safeSet(setPendingNearPublicKey), []);\n const safeSetStatusText = React.useMemo(() => safeSet(setStatusText), []);\n const safeSetPollingElapsedMs = React.useMemo(() => safeSet(setPollingElapsedMs), []);\n const safeSetErrorText = React.useMemo(() => safeSet(setErrorText), []);\n const safeSetIsBusy = React.useMemo(() => safeSet(setIsBusy), []);\n const safeSetCanRestart = React.useMemo(() => safeSet(setCanRestart), []);\n const safeSetAccountInfo = React.useMemo(() => safeSet(setAccountInfo), []);\n const safeSetAccountInfoLoading = React.useMemo(() => safeSet(setAccountInfoLoading), []);\n const safeSetAccountInfoError = React.useMemo(() => safeSet(setAccountInfoError), []);\n const safeSetLocalRecoveryEmails = React.useMemo(() => safeSet(setLocalRecoveryEmails), []);\n const safeSetExplorerToast = React.useMemo(() => safeSet(setExplorerToast), []);\n const safeSetMailtoUiState = React.useMemo(() => safeSet(setMailtoUiState), []);\n\n const onEvent = React.useCallback(\n (ev: EmailRecoverySSEEvent) => {\n if (cancelRequestedRef.current) return;\n safeSetStatusText(ev?.message || null);\n emailRecoveryOptions?.onEvent?.(ev);\n\n const data = (ev as any)?.data || {};\n const rawTxHash = data?.transactionHash ?? data?.transaction_hash;\n const txHash = typeof rawTxHash === 'string' ? rawTxHash.trim() : '';\n if (txHash) {\n const base = String(tatchiPasskey.configs?.nearExplorerUrl || 'https://testnet.nearblocks.io').replace(/\\/$/, '');\n const url = base.includes('nearblocks.io')\n ? `${base}/txns/${txHash}`\n : `${base}/transactions/${txHash}`;\n safeSetExplorerToast({ url, transactionHash: txHash });\n }\n const elapsedRaw = data?.elapsedMs ?? data?.elapsed_ms;\n if (elapsedRaw == null) safeSetPollingElapsedMs(null);\n const elapsed = elapsedRaw == null ? Number.NaN : Number(elapsedRaw);\n if (!Number.isNaN(elapsed)) safeSetPollingElapsedMs(elapsed);\n\n if (ev?.phase === 'email-recovery-error' || (ev as any)?.status === 'error') {\n const raw = (ev as any)?.error || ev?.message || 'Email recovery failed';\n safeSetErrorText(String(raw));\n safeSetCanRestart(false);\n }\n },\n [emailRecoveryOptions, safeSetCanRestart, safeSetErrorText, safeSetExplorerToast, safeSetPollingElapsedMs, safeSetStatusText, tatchiPasskey],\n );\n\n const showExplorerToast = React.useCallback(\n (rawAccountId: string) => {\n const normalized = (rawAccountId || '').trim();\n if (!normalized) return;\n const base = String(tatchiPasskey.configs?.nearExplorerUrl || 'https://testnet.nearblocks.io').replace(/\\/$/, '');\n const url = base.includes('nearblocks.io')\n ? `${base}/address/${normalized}`\n : `${base}/accounts/${normalized}`;\n\n safeSetExplorerToast({ url, accountId: normalized });\n },\n [safeSetExplorerToast, tatchiPasskey],\n );\n\n const launchMailto = React.useCallback((rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n\n if (typeof window !== 'undefined') {\n try {\n window.location.href = url;\n } catch {}\n }\n }, []);\n\n const attemptOpenMailtoFromUserGesture = React.useCallback(\n (rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n\n safeSetMailtoUiState('opening');\n\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n }\n\n // If the browser never blurs/hides (i.e. mailto blocked or cancelled), re-enable so users can retry.\n mailtoAttemptTimerRef.current = window.setTimeout(() => {\n safeSetMailtoUiState(prev => (prev === 'opening' ? 'ready' : prev));\n mailtoAttemptTimerRef.current = null;\n }, 2_000);\n\n launchMailto(url);\n },\n [launchMailto, safeSetMailtoUiState],\n );\n\n const attemptOpenMailtoAuto = React.useCallback(\n (rawMailtoUrl: string) => {\n const url = String(rawMailtoUrl || '').trim();\n if (!url) return;\n // Best-effort only: do not change `mailtoUiState` so users can immediately click the CTA.\n launchMailto(url);\n },\n [launchMailto],\n );\n\n React.useEffect(() => {\n if (mailtoUiState !== 'opening') return;\n if (typeof window === 'undefined' || typeof document === 'undefined') return;\n\n // Heuristic signals that the mail client likely opened. Treat as a hint only:\n // re-enable immediately so the CTA remains retryable even if this is a false-positive.\n const markMaybeOpened = () => {\n safeSetMailtoUiState('ready');\n if (mailtoAttemptTimerRef.current != null) {\n window.clearTimeout(mailtoAttemptTimerRef.current);\n mailtoAttemptTimerRef.current = null;\n }\n };\n\n const onVisibilityChange = () => {\n if (document.visibilityState === 'hidden') markMaybeOpened();\n };\n\n window.addEventListener('blur', markMaybeOpened);\n window.addEventListener('pagehide', markMaybeOpened);\n document.addEventListener('visibilitychange', onVisibilityChange);\n\n return () => {\n window.removeEventListener('blur', markMaybeOpened);\n window.removeEventListener('pagehide', markMaybeOpened);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n };\n }, [mailtoUiState, safeSetMailtoUiState]);\n\n const fetchLocalRecoveryEmailsFromIndexedDB = React.useCallback(\n async (rawAccountId: string): Promise<string[]> => {\n const normalized = (rawAccountId || '').trim();\n if (!normalized) {\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: empty accountId');\n return [];\n }\n\n try {\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: loading from IndexedDB', { accountId: normalized });\n const records = await IndexedDBManager.getRecoveryEmails(toAccountId(normalized));\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: raw IndexedDB records', {\n accountId: normalized,\n count: Array.isArray(records) ? records.length : 0,\n records,\n });\n if (!Array.isArray(records) || records.length === 0) return [];\n\n const sorted = [...records].sort((a, b) => (b?.addedAt || 0) - (a?.addedAt || 0));\n const emails = sorted\n .map(r => String(r?.email || '').trim().toLowerCase())\n .filter(e => !!e && e.includes('@'));\n\n const uniq = Array.from(new Set(emails));\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: parsed emails', {\n accountId: normalized,\n emails: uniq,\n });\n return uniq;\n } catch (err) {\n // best-effort; treat as no saved emails (e.g., IndexedDB unavailable)\n console.log('[EmailRecoverySlide] fetchLocalRecoveryEmails: failed to read IndexedDB', {\n accountId: normalized,\n error: err instanceof Error ? err.message : String(err),\n });\n return [];\n }\n },\n [],\n );\n\n const deriveEmailsFromRecoveryRecords = React.useCallback((records: unknown): string[] => {\n if (!Array.isArray(records) || records.length === 0) return [];\n const emails = records\n .map((r: any) => String(r?.email || '').trim().toLowerCase())\n .filter((e: string) => !!e && e.includes('@'));\n return Array.from(new Set(emails));\n }, []);\n\n React.useEffect(() => {\n const normalized = (accountIdInput || '').trim();\n if (!normalized) {\n setAccountInfo(null);\n setAccountInfoError(null);\n setAccountInfoLoading(false);\n safeSetLocalRecoveryEmails([]);\n return;\n }\n\n let cancelled = false;\n // Show loading state immediately (don't wait for debounce).\n safeSetAccountInfoLoading(true);\n safeSetAccountInfoError(null);\n const handle = window.setTimeout(() => {\n void (async () => {\n try {\n const isWalletIframeMode = !!tatchiPasskey.configs?.iframeWallet?.walletOrigin;\n\n // Legacy mode: suggest recovery emails from local IndexedDB mapping (best-effort).\n let localEmails: string[] = [];\n if (!isWalletIframeMode) {\n localEmails = await fetchLocalRecoveryEmailsFromIndexedDB(normalized);\n if (!cancelled) {\n console.log('[EmailRecoverySlide] local saved emails (IndexedDB)', { accountId: normalized, localEmails });\n }\n }\n\n const records = await tatchiPasskey.getRecoveryEmails(normalized);\n const resolvedEmails = isWalletIframeMode\n ? deriveEmailsFromRecoveryRecords(records)\n : localEmails;\n\n if (!cancelled) {\n safeSetLocalRecoveryEmails(resolvedEmails);\n console.log('[EmailRecoverySlide] recovery email suggestions (state)', { accountId: normalized, emails: resolvedEmails });\n\n if (\n resolvedEmails.length === 1 &&\n (recoveryEmailInput.trim() === '' || recoveryEmailInput === lastPrefilledRecoveryEmailRef.current)\n ) {\n lastPrefilledRecoveryEmailRef.current = resolvedEmails[0];\n setRecoveryEmailInput(resolvedEmails[0]);\n }\n }\n\n const info: EmailRecoveryAccountInfo | null = records\n ? { emailsCount: Array.isArray(records) ? records.length : 0 }\n : null;\n if (cancelled) return;\n safeSetAccountInfo(info);\n } catch (err: any) {\n if (cancelled) return;\n safeSetAccountInfo(null);\n safeSetAccountInfoError(err?.message || 'Failed to load email recovery settings for this account');\n } finally {\n if (!cancelled) safeSetAccountInfoLoading(false);\n }\n })();\n }, 350);\n\n return () => {\n cancelled = true;\n window.clearTimeout(handle);\n };\n }, [\n accountIdInput,\n deriveEmailsFromRecoveryRecords,\n fetchLocalRecoveryEmailsFromIndexedDB,\n recoveryEmailInput,\n safeSetAccountInfo,\n safeSetAccountInfoError,\n safeSetAccountInfoLoading,\n safeSetLocalRecoveryEmails,\n tatchiPasskey,\n ]);\n\n const handleStart = React.useCallback(async () => {\n const normalizedAccountId = (accountIdInput || '').trim();\n if (!normalizedAccountId) {\n safeSetErrorText('Enter an account ID.');\n return;\n }\n\n const emailCandidate = (recoveryEmailInput || '').trim().toLowerCase();\n if (!emailCandidate) {\n safeSetErrorText('Enter the recovery email to send from.');\n return;\n }\n\n safeSetIsBusy(true);\n cancelRequestedRef.current = false;\n safeSetErrorText(null);\n safeSetCanRestart(false);\n safeSetStatusText(null);\n safeSetPollingElapsedMs(null);\n safeSetPendingMailtoUrl(null);\n safeSetPendingNearPublicKey(null);\n safeSetMailtoUiState('ready');\n\n let didForwardError = false;\n try {\n const result = await tatchiPasskey.startEmailRecovery({\n accountId: normalizedAccountId,\n recoveryEmail: emailCandidate,\n options: {\n onEvent,\n onError: (err: Error) => {\n if (cancelRequestedRef.current) return;\n safeSetErrorText(err?.message || 'Failed to start email recovery');\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n afterCall: async () => {},\n } as any,\n });\n\n safeSetPendingMailtoUrl(result.mailtoUrl);\n safeSetPendingNearPublicKey(result.nearPublicKey);\n safeSetStatusText('Recovery email draft ready. If it didn’t open automatically, click “Open recovery email draft”. Waiting for verification…');\n\n // Best-effort open. If blocked/cancelled, the CTA remains immediately clickable for a user-gesture retry.\n attemptOpenMailtoAuto(result.mailtoUrl);\n\n // Start polling immediately after attempting to open the email prompt.\n const finalizePromise = tatchiPasskey.finalizeEmailRecovery({\n accountId: normalizedAccountId,\n nearPublicKey: result.nearPublicKey,\n options: {\n onEvent,\n onError: (err: Error) => {\n if (cancelRequestedRef.current) return;\n const uiError = getEmailRecoveryUiError(err);\n safeSetErrorText(uiError.message || 'Failed to finalize email recovery');\n safeSetCanRestart(uiError.canRestart);\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n afterCall: async () => {},\n } as any,\n });\n\n showExplorerToast(normalizedAccountId);\n\n await finalizePromise;\n\n // Best-effort auto-login: the core flow attempts it, but if it couldn't (e.g. missing Shamir\n // auto-unlock and user cancelled TouchID), try once more here.\n let loginOk = false;\n const session = await tatchiPasskey.getLoginSession(normalizedAccountId).catch(() => null);\n if (session?.login?.isLoggedIn) {\n loginOk = true;\n } else {\n safeSetStatusText('Email recovery completed. Logging you in…');\n loginOk = await tatchiPasskey.loginAndCreateSession(normalizedAccountId)\n .then(() => true)\n .catch(() => false);\n }\n\n if (refreshLoginState) {\n await refreshLoginState(normalizedAccountId).catch(() => {});\n }\n\n safeSetStatusText(loginOk ? 'Email recovery completed on this device.' : 'Email recovery completed. Please log in on this device.');\n safeSetPendingMailtoUrl(null);\n safeSetMailtoUiState('ready');\n safeSetPollingElapsedMs(null);\n } catch (err: any) {\n if (cancelRequestedRef.current) {\n safeSetErrorText('Email recovery cancelled. Please try again.');\n safeSetStatusText(null);\n safeSetPollingElapsedMs(null);\n safeSetPendingMailtoUrl(null);\n safeSetPendingNearPublicKey(null);\n safeSetMailtoUiState('ready');\n safeSetCanRestart(false);\n return;\n }\n const uiError = getEmailRecoveryUiError(err);\n safeSetErrorText(uiError.message || 'Failed to start email recovery');\n safeSetCanRestart(uiError.canRestart);\n if (!didForwardError && err instanceof Error) {\n emailRecoveryOptions?.onError?.(err);\n }\n } finally {\n safeSetIsBusy(false);\n }\n }, [\n accountIdInput,\n emailRecoveryOptions,\n recoveryEmailInput,\n onEvent,\n refreshLoginState,\n showExplorerToast,\n safeSetErrorText,\n safeSetIsBusy,\n safeSetPendingMailtoUrl,\n safeSetPollingElapsedMs,\n safeSetStatusText,\n safeSetMailtoUiState,\n attemptOpenMailtoAuto,\n tatchiPasskey,\n ]);\n\n const handleRestart = React.useCallback(async () => {\n const normalizedAccountId = (accountIdInput || '').trim();\n if (!normalizedAccountId) return;\n\n safeSetIsBusy(true);\n try {\n cancelRequestedRef.current = true;\n await tatchiPasskey.cancelEmailRecovery({\n accountId: normalizedAccountId,\n nearPublicKey: pendingNearPublicKey || undefined,\n }).catch(() => {});\n safeSetErrorText(null);\n safeSetStatusText(null);\n safeSetPollingElapsedMs(null);\n safeSetPendingMailtoUrl(null);\n safeSetPendingNearPublicKey(null);\n safeSetMailtoUiState('ready');\n safeSetCanRestart(false);\n } finally {\n cancelRequestedRef.current = false;\n safeSetIsBusy(false);\n }\n }, [\n accountIdInput,\n pendingNearPublicKey,\n safeSetCanRestart,\n safeSetErrorText,\n safeSetIsBusy,\n safeSetMailtoUiState,\n safeSetPendingMailtoUrl,\n safeSetPendingNearPublicKey,\n safeSetPollingElapsedMs,\n safeSetStatusText,\n tatchiPasskey,\n ]);\n\n const summaryLine = accountInfoLoading\n ? 'Checking if account has recovery emails configured...'\n : accountInfo && !accountInfoError\n ? `Recovery emails configured: ${accountInfo.emailsCount}`\n : '\\u00A0';\n\n const noRecoveryEmailsConfigured =\n !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount === 0;\n\n return (\n <div className=\"w3a-email-recovery-slide\">\n <div className=\"w3a-email-recovery-title\">Recover Account with Email</div>\n <div className=\"w3a-email-recovery-help\">\n Send a recovery email from your registered email address.\n Your account will be recovered with a new key once the email is verified.\n </div>\n\n <div className=\"w3a-email-recovery-field\">\n <div className=\"w3a-input-pill w3a-email-recovery-input-pill\">\n <div className=\"w3a-input-wrap\">\n <input\n type=\"text\"\n value={accountIdInput}\n onChange={(e) => setAccountIdInput(e.target.value)}\n placeholder=\"NEAR account ID (e.g. alice.testnet)\"\n className=\"w3a-input\"\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n inputMode=\"text\"\n disabled={isBusy}\n />\n </div>\n </div>\n </div>\n\n <div className=\"w3a-email-recovery-summary\" aria-live=\"polite\">\n <div>{summaryLine}</div>\n </div>\n\n <div className=\"w3a-email-recovery-field\">\n <div className=\"w3a-input-pill w3a-email-recovery-input-pill\">\n <div className=\"w3a-input-wrap\">\n <input\n type=\"email\"\n value={recoveryEmailInput}\n onChange={(e) => setRecoveryEmailInput(e.target.value)}\n placeholder=\"Recovery email to send from\"\n className=\"w3a-input\"\n list={localRecoveryEmails.length > 0 ? 'w3a-email-recovery-saved-emails' : undefined}\n autoCapitalize=\"none\"\n autoCorrect=\"off\"\n spellCheck={false}\n inputMode=\"email\"\n disabled={isBusy || noRecoveryEmailsConfigured}\n />\n </div>\n </div>\n </div>\n\n {localRecoveryEmails.length > 0 && (\n <div className=\"w3a-email-recovery-summary\" aria-live=\"polite\">\n <div>Saved on this device:</div>\n <div className=\"w3a-email-recovery-saved-emails\">\n {localRecoveryEmails.map((email) => (\n <button\n key={email}\n type=\"button\"\n className=\"w3a-email-recovery-email-chip\"\n onClick={() => setRecoveryEmailInput(email)}\n disabled={isBusy}\n >\n {email}\n </button>\n ))}\n </div>\n </div>\n )}\n\n {localRecoveryEmails.length > 0 && (\n <datalist id=\"w3a-email-recovery-saved-emails\">\n {localRecoveryEmails.map((email) => (\n <option key={email} value={email} />\n ))}\n </datalist>\n )}\n\n <div className=\"w3a-email-recovery-actions\">\n {(!pendingMailtoUrl || !isBusy) && (\n <button\n onClick={handleStart}\n className=\"w3a-link-device-btn w3a-link-device-btn-primary\"\n disabled={isBusy || noRecoveryEmailsConfigured}\n >\n {noRecoveryEmailsConfigured ? 'No recovery emails configured' : (isBusy ? 'Working…' : 'Start Email Recovery')}\n </button>\n )}\n\n {pendingMailtoUrl && (\n <button\n type=\"button\"\n onClick={() => attemptOpenMailtoFromUserGesture(pendingMailtoUrl)}\n className=\"w3a-link-device-btn w3a-link-device-btn-primary\"\n disabled={mailtoUiState === 'opening'}\n aria-busy={mailtoUiState === 'opening'}\n >\n {mailtoUiState === 'opening' && <span className=\"w3a-spinner\" aria-hidden=\"true\" />}\n {mailtoUiState === 'opening' ? 'Opening email…' : 'Open recovery email draft'}\n </button>\n )}\n\n {errorText && canRestart && (\n <button\n type=\"button\"\n onClick={handleRestart}\n className=\"w3a-link-device-btn\"\n disabled={isBusy}\n >\n Restart email recovery\n </button>\n )}\n </div>\n\n {(errorText || statusText || explorerToast) && (\n <div className={`w3a-email-recovery-status${errorText ? ' is-error' : ''}`}>\n {errorText ? errorText : statusText}\n {pollingElapsedMs != null && !Number.isNaN(pollingElapsedMs) && pollingElapsedMs > 0 && (\n <span className=\"w3a-email-recovery-elapsed\">\n (~{Math.round(pollingElapsedMs / 1000)}s).\n </span>\n )}\n {explorerToast && (\n <>\n <a className=\"w3a-email-recovery-link\" href={explorerToast.url} target=\"_blank\" rel=\"noopener noreferrer\">\n View on explorer\n </a>\n </>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default EmailRecoverySlide;\n"],"mappings":"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"}
|
package/dist/esm/react/components/{ShowQRCode-CCN4h6Uv.css.map → ShowQRCode-CL4gsszN.css.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShowQRCode-
|
|
1
|
+
{"version":3,"file":"ShowQRCode-CL4gsszN.css","names":[],"sources":["../../../../src/react/components/ShowQRCode.css"],"sourcesContent":[".qr-code-container {\n padding-top: 1rem;\n}\n\n/* Modal Header */\n.qr-header {\n position: relative;\n display: grid;\n place-content: center;\n padding: 0rem;\n}\n\n.qr-title {\n font-size: 1.5rem;\n font-weight: 700;\n color: var(--w3a-colors-textPrimary, #1e293b);\n padding-top: 0rem;\n margin: 0;\n}\n\n.qr-body {\n padding: 0rem;\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n.qr-code-section {\n width: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n}\n\n/* QR Code Display */\n.qr-code-display {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0rem;\n padding: 1rem;\n border-radius: 1.5rem;\n width: 100%;\n max-width: 300px;\n}\n\n.qr-instruction, .qr-status {\n margin: 0;\n font-size: 1rem;\n font-weight: 500;\n line-height: 1.5;\n color: var(--w3a-colors-textSecondary, #1e293b);\n text-align: center;\n}\n\n.qr-status {\n margin-bottom: 0.5rem;\n}\n\n.animated-ellipsis {\n display: inline-block;\n width: 1.2em;\n text-align: left;\n}\n\n.animated-ellipsis::after {\n content: \"...\";\n animation: ellipsis 1.5s infinite;\n}\n\n@keyframes ellipsis {\n 0% { content: \"...\"; }\n 25% { content: \"\"; }\n 50% { content: \".\"; }\n 75% { content: \"..\"; }\n 100% { content: \"...\"; }\n}\n\n.qr-code-image {\n max-width: 200px;\n height: auto;\n border-radius: var(--w3a-border-radius-md, 0.5rem);\n}\n\n.qr-loading {\n text-align: center;\n padding: 2rem;\n color: var(--w3a-colors-textSecondary, #64748b);\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n .qr-modal-content {\n margin: 1rem;\n max-width: calc(100vw - 2rem);\n }\n\n @supports (width: 1dvw) {\n .qr-modal-content { max-width: calc(100dvw - 2rem); }\n }\n\n .qr-code-image {\n max-width: 200px;\n }\n\n .qr-code-display {\n padding: 1rem;\n }\n}\n"],"mappings":"AAAA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA"}
|