@tatchi-xyz/sdk 0.31.0 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/core/IndexedDBManager/passkeyClientDB.js +2 -2
- package/dist/cjs/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/faucets/createAccountRelayServer.js +9 -8
- package/dist/cjs/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/login.js +1 -1
- package/dist/cjs/core/TatchiPasskey/login.js.map +1 -1
- package/dist/cjs/core/TatchiPasskey/registration.js +67 -56
- package/dist/cjs/core/TatchiPasskey/registration.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js +1 -10
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +58 -67
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +74 -75
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js +17 -7
- package/dist/cjs/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js.map +1 -1
- package/dist/cjs/core/WebAuthnManager/index.js +3 -3
- package/dist/cjs/core/WebAuthnManager/index.js.map +1 -1
- package/dist/cjs/core/defaultConfigs.js +3 -1
- package/dist/cjs/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/react/components/AccountMenuButton/TransactionSettingsSection.js +3 -3
- package/dist/cjs/react/components/AccountMenuButton/TransactionSettingsSection.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-CRlobBrN.css → PasskeyAuthMenu-D2eRb2-S.css} +3 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/PasskeyAuthMenu-D2eRb2-S.css.map +1 -0
- package/dist/cjs/react/components/PasskeyAuthMenu/preload.js +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/preload.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/shell.js +52 -13
- package/dist/cjs/react/components/PasskeyAuthMenu/shell.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/skeleton.js +4 -2
- package/dist/cjs/react/components/PasskeyAuthMenu/skeleton.js.map +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +5 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/cjs/react/index.js +1 -1
- package/dist/cjs/react/src/core/IndexedDBManager/passkeyClientDB.js +2 -2
- package/dist/cjs/react/src/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/cjs/react/src/core/TatchiPasskey/faucets/createAccountRelayServer.js +9 -8
- package/dist/cjs/react/src/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/cjs/react/src/core/TatchiPasskey/login.js +1 -1
- package/dist/cjs/react/src/core/TatchiPasskey/login.js.map +1 -1
- package/dist/cjs/react/src/core/TatchiPasskey/registration.js +67 -56
- package/dist/cjs/react/src/core/TatchiPasskey/registration.js.map +1 -1
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js +1 -10
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js.map +1 -1
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +58 -67
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +74 -75
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js +17 -7
- package/dist/cjs/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js.map +1 -1
- package/dist/cjs/react/src/core/WebAuthnManager/index.js +3 -3
- package/dist/cjs/react/src/core/WebAuthnManager/index.js.map +1 -1
- package/dist/cjs/react/src/core/defaultConfigs.js +3 -1
- package/dist/cjs/react/src/core/defaultConfigs.js.map +1 -1
- package/dist/cjs/server/core/AuthService.js +49 -6
- package/dist/cjs/server/core/AuthService.js.map +1 -1
- package/dist/cjs/server/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/core/IndexedDBManager/passkeyClientDB.js +2 -2
- package/dist/esm/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/faucets/createAccountRelayServer.js +9 -8
- package/dist/esm/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/login.js +1 -1
- package/dist/esm/core/TatchiPasskey/login.js.map +1 -1
- package/dist/esm/core/TatchiPasskey/registration.js +67 -56
- package/dist/esm/core/TatchiPasskey/registration.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js +1 -10
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +58 -67
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +74 -75
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js +17 -7
- package/dist/esm/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js.map +1 -1
- package/dist/esm/core/WebAuthnManager/index.js +3 -3
- package/dist/esm/core/WebAuthnManager/index.js.map +1 -1
- package/dist/esm/core/defaultConfigs.js +3 -1
- package/dist/esm/core/defaultConfigs.js.map +1 -1
- package/dist/esm/react/components/AccountMenuButton/TransactionSettingsSection.js +3 -3
- package/dist/esm/react/components/AccountMenuButton/TransactionSettingsSection.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/{PasskeyAuthMenu-D2VHZ04W.css → PasskeyAuthMenu-qTHAv58Z.css} +3 -1
- package/dist/esm/react/components/PasskeyAuthMenu/PasskeyAuthMenu-qTHAv58Z.css.map +1 -0
- package/dist/esm/react/components/PasskeyAuthMenu/preload.js +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/preload.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/shell.js +52 -13
- package/dist/esm/react/components/PasskeyAuthMenu/shell.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/skeleton.js +4 -2
- package/dist/esm/react/components/PasskeyAuthMenu/skeleton.js.map +1 -1
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js +5 -1
- package/dist/esm/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.js.map +1 -1
- package/dist/esm/react/index.js +1 -1
- package/dist/esm/react/src/core/IndexedDBManager/passkeyClientDB.js +2 -2
- package/dist/esm/react/src/core/IndexedDBManager/passkeyClientDB.js.map +1 -1
- package/dist/esm/react/src/core/TatchiPasskey/faucets/createAccountRelayServer.js +9 -8
- package/dist/esm/react/src/core/TatchiPasskey/faucets/createAccountRelayServer.js.map +1 -1
- package/dist/esm/react/src/core/TatchiPasskey/login.js +1 -1
- package/dist/esm/react/src/core/TatchiPasskey/login.js.map +1 -1
- package/dist/esm/react/src/core/TatchiPasskey/registration.js +67 -56
- package/dist/esm/react/src/core/TatchiPasskey/registration.js.map +1 -1
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js +1 -10
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.js.map +1 -1
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js +58 -67
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.js.map +1 -1
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js +74 -75
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.js.map +1 -1
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js +17 -7
- package/dist/esm/react/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.js.map +1 -1
- package/dist/esm/react/src/core/WebAuthnManager/index.js +3 -3
- package/dist/esm/react/src/core/WebAuthnManager/index.js.map +1 -1
- package/dist/esm/react/src/core/defaultConfigs.js +3 -1
- package/dist/esm/react/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/react/styles/styles.css +2 -0
- package/dist/esm/sdk/{EmailRecovery-Dl8b4ONg.js → EmailRecovery-Y7rurd4B.js} +3 -3
- package/dist/esm/sdk/{EmailRecovery-v9oNO2Tc.js → EmailRecovery-lsjLWApQ.js} +1 -1
- package/dist/esm/sdk/{IndexedDBManager-B1cUvdyY.js → IndexedDBManager-CmdN7smS.js} +3 -3
- package/dist/esm/sdk/{createAdapters-Dv7ZJPf1.js → createAdapters-4c8mBiD5.js} +2 -11
- package/dist/esm/sdk/{createAdapters-Dv7ZJPf1.js.map → createAdapters-4c8mBiD5.js.map} +1 -1
- package/dist/esm/sdk/{createAdapters-1Hmc1vVC.js → createAdapters-DF32SIZa.js} +1 -10
- package/dist/esm/sdk/{defaultConfigs-BmCU1_qI.js → defaultConfigs-BQqiXif-.js} +3 -1
- package/dist/esm/sdk/{emailRecovery-4J-g9tlY.js → emailRecovery-C0LSDleV.js} +5 -5
- package/dist/esm/sdk/{getDeviceNumber-f8bfPB9U.js → getDeviceNumber-WiNzKx1x.js} +4 -2
- package/dist/esm/sdk/{getDeviceNumber-f8bfPB9U.js.map → getDeviceNumber-WiNzKx1x.js.map} +1 -1
- package/dist/esm/sdk/{linkDevice-C98klpcE.js → linkDevice-Ds1GNIDk.js} +4 -4
- package/dist/esm/sdk/{localOnly-40zxrBMm.js → localOnly-COpDBMkm.js} +2 -2
- package/dist/esm/sdk/{localOnly-40zxrBMm.js.map → localOnly-COpDBMkm.js.map} +1 -1
- package/dist/esm/sdk/{localOnly-BZPBj14l.js → localOnly-DQQuqgjJ.js} +1 -1
- package/dist/esm/sdk/{login-DnROv3eA.js → login-BKhTuGcy.js} +3 -3
- package/dist/esm/sdk/offline-export-app.js +29 -19
- package/dist/esm/sdk/offline-export-app.js.map +1 -1
- package/dist/esm/sdk/{registration-BP9M3tE1.js → registration-BR2G9tz_.js} +59 -68
- package/dist/esm/sdk/{registration-MrAOC8Ub.js → registration-R70lvG_o.js} +60 -69
- package/dist/esm/sdk/registration-R70lvG_o.js.map +1 -0
- package/dist/esm/sdk/{router-BEGGuWaB.js → router-2aGn-CTp.js} +1 -1
- package/dist/esm/sdk/{rpcCalls-CMzj_Va_.js → rpcCalls-BPI0icZG.js} +2 -2
- package/dist/esm/sdk/{rpcCalls-B44MZora.js → rpcCalls-BW3M_q3-.js} +1 -1
- package/dist/esm/sdk/{scanDevice-Cp-r-Z2T.js → scanDevice-BBSehlMx.js} +4 -4
- package/dist/esm/sdk/{syncAccount-CqWCmBVb.js → syncAccount-DEZHBiRa.js} +4 -4
- package/dist/esm/sdk/{syncAccount-Dt5jJbEB.js → syncAccount-DHKtl-xh.js} +2 -2
- package/dist/esm/sdk/{transactions-DAZrPW-6.js → transactions-Cg1TIUyK.js} +76 -77
- package/dist/esm/sdk/{transactions-CrjP8yPD.js → transactions-CxsklyCK.js} +77 -78
- package/dist/esm/sdk/transactions-CxsklyCK.js.map +1 -0
- package/dist/esm/sdk/wallet-iframe-host.js +116 -94
- package/dist/esm/server/core/AuthService.js +49 -6
- package/dist/esm/server/core/AuthService.js.map +1 -1
- package/dist/esm/server/sdk/src/core/defaultConfigs.js.map +1 -1
- package/dist/esm/wasm_vrf_worker/pkg/wasm_vrf_worker_bg.wasm +0 -0
- package/dist/types/src/__tests__/setup/bootstrap.d.ts.map +1 -1
- package/dist/types/src/core/IndexedDBManager/passkeyClientDB.d.ts +1 -1
- package/dist/types/src/core/IndexedDBManager/passkeyClientDB.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/faucets/createAccountRelayServer.d.ts +6 -6
- package/dist/types/src/core/TatchiPasskey/faucets/createAccountRelayServer.d.ts.map +1 -1
- package/dist/types/src/core/TatchiPasskey/registration.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.d.ts +0 -5
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/adapters/session.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/registration.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/flows/transactions.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/VrfWorkerManager/confirmTxFlow/handleSecureConfirmRequest.d.ts.map +1 -1
- package/dist/types/src/core/WebAuthnManager/index.d.ts +1 -1
- package/dist/types/src/core/WebAuthnManager/index.d.ts.map +1 -1
- package/dist/types/src/core/defaultConfigs.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/preload.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/shell.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/skeleton.d.ts +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/skeleton.d.ts.map +1 -1
- package/dist/types/src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.d.ts.map +1 -1
- package/dist/types/src/server/core/AuthService.d.ts.map +1 -1
- package/dist/workers/offline-export-sw.js +156 -1
- package/dist/workers/wasm_vrf_worker_bg.wasm +0 -0
- package/dist/workers/web3authn-signer.worker.js +1360 -2
- package/dist/workers/web3authn-vrf.worker.js +2857 -2
- package/package.json +1 -1
- package/dist/cjs/react/components/PasskeyAuthMenu/PasskeyAuthMenu-CRlobBrN.css.map +0 -1
- package/dist/esm/react/components/PasskeyAuthMenu/PasskeyAuthMenu-D2VHZ04W.css.map +0 -1
- package/dist/esm/sdk/registration-MrAOC8Ub.js.map +0 -1
- package/dist/esm/sdk/transactions-CrjP8yPD.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransactionSettingsSection.js","names":["TransactionSettingsSection: React.FC<TransactionSettingsSectionProps>"],"sources":["../../../../../src/react/components/AccountMenuButton/TransactionSettingsSection.tsx"],"sourcesContent":["import React from 'react';\nimport { Slider } from './Slider';\nimport type { TransactionSettingsSectionProps } from './types';\nimport { SegmentedControl } from '../PasskeyAuthMenu/ui/SegmentedControl';\n\nexport const TransactionSettingsSection: React.FC<TransactionSettingsSectionProps> = ({\n currentConfirmConfig,\n signerMode,\n onToggleThresholdSigning,\n onSetUiMode,\n onToggleShowDetails,\n onToggleSkipClick,\n onSetDelay,\n className,\n style,\n isOpen = true,\n theme = 'dark'\n}) => {\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n };\n\n const disableRequireClick = currentConfirmConfig?.uiMode === 'skip';\n const disableDelaySlider = disableRequireClick || currentConfirmConfig?.behavior !== 'autoProceed';\n const disableAll = !isOpen;\n const selectedSignerMode = signerMode?.mode ?? 'local-signer';\n\n return (\n <div\n className={`w3a-dropdown-tx-settings-root ${isOpen ? 'is-expanded' : ''} ${className || ''}`}\n style={style}\n onClick={handleClick}\n >\n <div className=\"w3a-dropdown-toggle-tx-settings\">\n <div\n className=\"w3a-dropdown-toggle-tx-settings-content\"\n aria-hidden={!isOpen}\n style={{ pointerEvents: isOpen ? 'auto' : 'none' }}\n >\n <div style={{\n width: '100%',\n display: 'flex',\n flexDirection: 'column',\n gap: 8\n }}>\n {signerMode && onToggleThresholdSigning && (\n <div>\n <div className=\"w3a-confirmation-options\">\n Signing Mode\n </div>\n <div style={{ width: '100%' }}>\n <SegmentedControl\n items={[\n { value: 'local-signer', label: 'Local Signer', disabled: disableAll },\n { value: 'threshold-signer', label: 'MPC Signer', disabled: disableAll },\n ]}\n value={selectedSignerMode}\n onValueChange={(v) => onToggleThresholdSigning(v === 'threshold-signer')}\n activeBg={'var(--w3a-colors-primary)'}\n height={40}\n buttonFontSize={12}\n containerStyle={{ background: 'var(--w3a-colors-surface2)', width: '100%' }}\n buttonStyle={{ display: 'grid', placeItems: 'center', lineHeight: 1, padding: '0 10px' }}\n activeButtonStyle={{ color: 'var(--w3a-colors-
|
|
1
|
+
{"version":3,"file":"TransactionSettingsSection.js","names":["TransactionSettingsSection: React.FC<TransactionSettingsSectionProps>"],"sources":["../../../../../src/react/components/AccountMenuButton/TransactionSettingsSection.tsx"],"sourcesContent":["import React from 'react';\nimport { Slider } from './Slider';\nimport type { TransactionSettingsSectionProps } from './types';\nimport { SegmentedControl } from '../PasskeyAuthMenu/ui/SegmentedControl';\n\nexport const TransactionSettingsSection: React.FC<TransactionSettingsSectionProps> = ({\n currentConfirmConfig,\n signerMode,\n onToggleThresholdSigning,\n onSetUiMode,\n onToggleShowDetails,\n onToggleSkipClick,\n onSetDelay,\n className,\n style,\n isOpen = true,\n theme = 'dark'\n}) => {\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n };\n\n const disableRequireClick = currentConfirmConfig?.uiMode === 'skip';\n const disableDelaySlider = disableRequireClick || currentConfirmConfig?.behavior !== 'autoProceed';\n const disableAll = !isOpen;\n const selectedSignerMode = signerMode?.mode ?? 'local-signer';\n\n return (\n <div\n className={`w3a-dropdown-tx-settings-root ${isOpen ? 'is-expanded' : ''} ${className || ''}`}\n style={style}\n onClick={handleClick}\n >\n <div className=\"w3a-dropdown-toggle-tx-settings\">\n <div\n className=\"w3a-dropdown-toggle-tx-settings-content\"\n aria-hidden={!isOpen}\n style={{ pointerEvents: isOpen ? 'auto' : 'none' }}\n >\n <div style={{\n width: '100%',\n display: 'flex',\n flexDirection: 'column',\n gap: 8\n }}>\n {signerMode && onToggleThresholdSigning && (\n <div>\n <div className=\"w3a-confirmation-options\">\n Signing Mode\n </div>\n <div style={{ width: '100%' }}>\n <SegmentedControl\n items={[\n { value: 'local-signer', label: 'Local Signer', disabled: disableAll },\n { value: 'threshold-signer', label: 'MPC Signer', disabled: disableAll },\n ]}\n value={selectedSignerMode}\n onValueChange={(v) => onToggleThresholdSigning(v === 'threshold-signer')}\n activeBg={'var(--w3a-colors-primary)'}\n height={40}\n buttonFontSize={12}\n containerStyle={{ background: 'var(--w3a-colors-surface2)', width: '100%' }}\n buttonStyle={{ display: 'grid', placeItems: 'center', lineHeight: 1, padding: '0 10px' }}\n activeButtonStyle={{ color: 'var(--w3a-colors-textButton)' }}\n />\n </div>\n </div>\n )}\n <div>\n <div className=\"w3a-confirmation-options\">\n Confirmation Options\n </div>\n <div style={{ width: '100%' }}>\n <SegmentedControl\n items={[\n { value: 'skip', label: 'skip', disabled: disableAll },\n { value: 'modal', label: 'modal', disabled: disableAll },\n { value: 'drawer', label: 'drawer', disabled: disableAll },\n ]}\n value={(currentConfirmConfig?.uiMode ?? 'modal')}\n onValueChange={(v) => onSetUiMode?.(v as 'skip' | 'modal' | 'drawer')}\n activeBg={'var(--w3a-colors-primary)'}\n height={40}\n buttonFontSize={12}\n containerStyle={{ background: 'var(--w3a-colors-surface2)', width: '100%' }}\n buttonStyle={{ display: 'grid', placeItems: 'center', lineHeight: 1, padding: '0 10px' }}\n activeButtonStyle={{ color: 'var(--w3a-colors-textButton)' }}\n />\n </div>\n </div>\n <div\n style={{\n opacity: disableRequireClick ? 0.6 : 1,\n pointerEvents: disableRequireClick ? 'none' : 'auto'\n }}\n >\n <div style={{ width: '100%' }}>\n <SegmentedControl\n items={[\n { value: 'auto', label: 'auto proceed', disabled: disableAll || disableRequireClick },\n { value: 'require', label: 'require click', disabled: disableAll || disableRequireClick },\n ]}\n value={(currentConfirmConfig?.behavior === 'autoProceed') ? 'auto' : 'require'}\n onValueChange={(v) => {\n const wantsAuto = v === 'auto';\n const isAuto = currentConfirmConfig?.behavior === 'autoProceed';\n if (wantsAuto !== isAuto) onToggleSkipClick?.();\n }}\n activeBg={'var(--w3a-colors-primary)'}\n height={40}\n buttonFontSize={12}\n containerStyle={{ background: 'var(--w3a-colors-surface2)', width: '100%' }}\n buttonStyle={{ display: 'grid', placeItems: 'center', lineHeight: 1, padding: '0 10px' }}\n activeButtonStyle={{ color: 'var(--w3a-colors-textButton)' }}\n />\n </div>\n </div>\n <Slider\n disabled={disableAll || disableDelaySlider}\n min={0}\n max={6}\n step={1}\n value={Math.round((currentConfirmConfig?.autoProceedDelay ?? 0) / 500)}\n onChange={(v) => onSetDelay(v * 500)}\n theme={theme}\n />\n </div>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;AAKA,MAAaA,8BAAyE,EACpF,sBACA,YACA,0BACA,aACA,qBACA,mBACA,YACA,WACA,OACA,SAAS,MACT,QAAQ,aACJ;CAEJ,MAAM,eAAe,MAAwB;AAC3C,IAAE;;CAGJ,MAAM,sBAAsB,sBAAsB,WAAW;CAC7D,MAAM,qBAAqB,uBAAuB,sBAAsB,aAAa;CACrF,MAAM,aAAa,CAAC;CACpB,MAAM,qBAAqB,YAAY,QAAQ;AAE/C,QACE,oBAAC;EACC,WAAW,iCAAiC,SAAS,gBAAgB,GAAG,GAAG,aAAa;EACjF;EACP,SAAS;YAET,oBAAC;GAAI,WAAU;aACb,oBAAC;IACC,WAAU;IACV,eAAa,CAAC;IACd,OAAO,EAAE,eAAe,SAAS,SAAS;cAE1C,qBAAC;KAAI,OAAO;MACV,OAAO;MACP,SAAS;MACT,eAAe;MACf,KAAK;;;MAEJ,cAAc,4BACb,qBAAC,oBACC,oBAAC;OAAI,WAAU;iBAA2B;UAG1C,oBAAC;OAAI,OAAO,EAAE,OAAO;iBACnB,oBAAC;QACC,OAAO,CACL;SAAE,OAAO;SAAgB,OAAO;SAAgB,UAAU;WAC1D;SAAE,OAAO;SAAoB,OAAO;SAAc,UAAU;;QAE9D,OAAO;QACP,gBAAgB,MAAM,yBAAyB,MAAM;QACrD,UAAU;QACV,QAAQ;QACR,gBAAgB;QAChB,gBAAgB;SAAE,YAAY;SAA8B,OAAO;;QACnE,aAAa;SAAE,SAAS;SAAQ,YAAY;SAAU,YAAY;SAAG,SAAS;;QAC9E,mBAAmB,EAAE,OAAO;;;MAKpC,qBAAC,oBACC,oBAAC;OAAI,WAAU;iBAA2B;UAG1C,oBAAC;OAAI,OAAO,EAAE,OAAO;iBACnB,oBAAC;QACC,OAAO;SACL;UAAE,OAAO;UAAQ,OAAO;UAAQ,UAAU;;SAC1C;UAAE,OAAO;UAAS,OAAO;UAAS,UAAU;;SAC5C;UAAE,OAAO;UAAU,OAAO;UAAU,UAAU;;;QAEhD,OAAQ,sBAAsB,UAAU;QACxC,gBAAgB,MAAM,cAAc;QACpC,UAAU;QACV,QAAQ;QACR,gBAAgB;QAChB,gBAAgB;SAAE,YAAY;SAA8B,OAAO;;QACnE,aAAa;SAAE,SAAS;SAAQ,YAAY;SAAU,YAAY;SAAG,SAAS;;QAC9E,mBAAmB,EAAE,OAAO;;;MAIlC,oBAAC;OACC,OAAO;QACL,SAAS,sBAAsB,KAAM;QACrC,eAAe,sBAAsB,SAAS;;iBAGhD,oBAAC;QAAI,OAAO,EAAE,OAAO;kBACnB,oBAAC;SACC,OAAO,CACL;UAAE,OAAO;UAAQ,OAAO;UAAgB,UAAU,cAAc;YAChE;UAAE,OAAO;UAAW,OAAO;UAAiB,UAAU,cAAc;;SAEtE,OAAQ,sBAAsB,aAAa,gBAAiB,SAAS;SACrE,gBAAgB,MAAM;UACpB,MAAM,YAAY,MAAM;UACxB,MAAM,SAAS,sBAAsB,aAAa;AAClD,cAAI,cAAc,OAAQ;;SAE5B,UAAU;SACV,QAAQ;SACR,gBAAgB;SAChB,gBAAgB;UAAE,YAAY;UAA8B,OAAO;;SACnE,aAAa;UAAE,SAAS;UAAQ,YAAY;UAAU,YAAY;UAAG,SAAS;;SAC9E,mBAAmB,EAAE,OAAO;;;;MAIlC,oBAAC;OACC,UAAU,cAAc;OACxB,KAAK;OACL,KAAK;OACL,MAAM;OACN,OAAO,KAAK,OAAO,sBAAsB,oBAAoB,KAAK;OAClE,WAAW,MAAM,WAAW,IAAI;OACzB"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/* Root container */
|
|
2
2
|
.w3a-signup-menu-root {
|
|
3
|
+
/* JS sentinel used to avoid FOUC when CSS is still loading */
|
|
4
|
+
--w3a-pam2-css-ready: 1;
|
|
3
5
|
position: relative; /* relative position to anchor back button */
|
|
4
6
|
width: min(100dvw, 420px);
|
|
5
7
|
max-width: 100dvw;
|
|
@@ -1006,4 +1008,4 @@
|
|
|
1006
1008
|
}
|
|
1007
1009
|
|
|
1008
1010
|
|
|
1009
|
-
/*# sourceMappingURL=PasskeyAuthMenu-
|
|
1011
|
+
/*# sourceMappingURL=PasskeyAuthMenu-qTHAv58Z.css.map*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasskeyAuthMenu-qTHAv58Z.css","names":[],"sources":["../../../../../src/react/components/PasskeyAuthMenu/PasskeyAuthMenu.css"],"sourcesContent":["/* Root container */\n.w3a-signup-menu-root {\n /* JS sentinel used to avoid FOUC when CSS is still loading */\n --w3a-pam2-css-ready: 1;\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-message {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n}\n.w3a-waiting-text { font-size: 18px; font-weight: 600; }\n.w3a-waiting-subtext {\n font-size: 12px;\n font-weight: 500;\n line-height: 1.35;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 25%);\n}\n.w3a-waiting-sdk-events {\n font-size: 11px;\n font-weight: 500;\n line-height: 1.35;\n white-space: pre-wrap;\n color: color-mix(in srgb, var(--w3a-colors-textSecondary), var(--w3a-colors-textPrimary) 15%);\n}\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@keyframes w3a-ellipsis-dot {\n 0%, 80%, 100% { opacity: 0; }\n 40% { opacity: 1; }\n}\n\n.w3a-ellipsis {\n display: inline-block;\n}\n\n.w3a-ellipsis-dot {\n display: inline-block;\n opacity: 0;\n animation: w3a-ellipsis-dot 1.2s infinite;\n}\n\n.w3a-ellipsis-dot:nth-child(2) { animation-delay: 0.15s; }\n.w3a-ellipsis-dot:nth-child(3) { animation-delay: 0.3s; }\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 .w3a-ellipsis-dot { animation: none; opacity: 1; }\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-from-warning {\n margin-top: 1rem;\n font-weight: 600;\n}\n\n[data-w3a-theme=\"light\"] .w3a-email-recovery-from-warning {\n color: #d80;\n}\n\n[data-w3a-theme=\"dark\"] .w3a-email-recovery-from-warning {\n color: #ea5;\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;\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-surface2);\n color: var(--w3a-colors-textPrimary);\n margin-bottom: 4px;\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-static {\n cursor: default;\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;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;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;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;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;;AAEA;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;;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"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Useful for hover/viewport/idle prefetch to reduce interaction latency.
|
|
5
5
|
*/
|
|
6
6
|
function preloadPasskeyAuthMenu() {
|
|
7
|
-
return import("./client.js").then(() => void 0);
|
|
7
|
+
return import("./client.js").then(() => void 0).catch(() => void 0);
|
|
8
8
|
}
|
|
9
9
|
var preload_default = preloadPasskeyAuthMenu;
|
|
10
10
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preload.js","names":[],"sources":["../../../../../src/react/components/PasskeyAuthMenu/preload.ts"],"sourcesContent":["/**\n * Preload the client-only implementation chunk for `PasskeyAuthMenu`.\n * Useful for hover/viewport/idle prefetch to reduce interaction latency.\n */\nexport function preloadPasskeyAuthMenu(): Promise<void> {\n return import('./client').then(() => undefined);\n}\n\nexport default preloadPasskeyAuthMenu;\n"],"mappings":";;;;;AAIA,SAAgB,yBAAwC;
|
|
1
|
+
{"version":3,"file":"preload.js","names":[],"sources":["../../../../../src/react/components/PasskeyAuthMenu/preload.ts"],"sourcesContent":["/**\n * Preload the client-only implementation chunk for `PasskeyAuthMenu`.\n * Useful for hover/viewport/idle prefetch to reduce interaction latency.\n */\nexport function preloadPasskeyAuthMenu(): Promise<void> {\n // Best-effort: preloading should never crash callers or surface unhandled rejections.\n return import('./client')\n .then(() => undefined)\n .catch(() => undefined);\n}\n\nexport default preloadPasskeyAuthMenu;\n"],"mappings":";;;;;AAIA,SAAgB,yBAAwC;AAEtD,QAAO,OAAO,eACX,WAAW,QACX,YAAY;;AAGjB,sBAAe"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useTheme } from "../theme/ThemeProvider.js";
|
|
2
2
|
import { PasskeyAuthMenuThemeScope } from "./themeScope.js";
|
|
3
3
|
import { PasskeyAuthMenuSkeletonInner } from "./skeleton.js";
|
|
4
|
+
import { preloadPasskeyAuthMenu } from "./preload.js";
|
|
4
5
|
import React from "react";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
|
|
@@ -34,19 +35,63 @@ var LazyErrorBoundary = class extends React.Component {
|
|
|
34
35
|
const PasskeyAuthMenu = (props) => {
|
|
35
36
|
const [isClient, setIsClient] = React.useState(false);
|
|
36
37
|
const [retryKey, setRetryKey] = React.useState(0);
|
|
38
|
+
const [stylesReady, setStylesReady] = React.useState(false);
|
|
37
39
|
const ClientLazy = React.useMemo(() => createClientLazy(), [retryKey]);
|
|
40
|
+
const skeletonRootRef = React.useRef(null);
|
|
38
41
|
const { theme } = useTheme();
|
|
39
42
|
React.useEffect(() => {
|
|
40
43
|
setIsClient(true);
|
|
44
|
+
preloadPasskeyAuthMenu();
|
|
41
45
|
}, []);
|
|
46
|
+
React.useEffect(() => {
|
|
47
|
+
if (!isClient) return;
|
|
48
|
+
if (stylesReady) return;
|
|
49
|
+
if (typeof window === "undefined" || typeof requestAnimationFrame !== "function") {
|
|
50
|
+
setStylesReady(true);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
let cancelled = false;
|
|
54
|
+
const start = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
55
|
+
const maxWaitMs = 1500;
|
|
56
|
+
const tick = () => {
|
|
57
|
+
if (cancelled) return;
|
|
58
|
+
const el = skeletonRootRef.current;
|
|
59
|
+
if (el) try {
|
|
60
|
+
const cs = window.getComputedStyle(el);
|
|
61
|
+
const sentinelReady = cs.getPropertyValue("--w3a-pam2-css-ready").trim() === "1";
|
|
62
|
+
const borderOk = cs.borderTopStyle !== "none" && cs.borderTopWidth !== "0px";
|
|
63
|
+
const radiusOk = cs.borderTopLeftRadius !== "0px";
|
|
64
|
+
if (sentinelReady || borderOk || radiusOk) {
|
|
65
|
+
setStylesReady(true);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
} catch {}
|
|
69
|
+
const now = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
70
|
+
if (now - start >= maxWaitMs) {
|
|
71
|
+
setStylesReady(true);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
requestAnimationFrame(tick);
|
|
75
|
+
};
|
|
76
|
+
requestAnimationFrame(tick);
|
|
77
|
+
return () => {
|
|
78
|
+
cancelled = true;
|
|
79
|
+
};
|
|
80
|
+
}, [isClient, stylesReady]);
|
|
81
|
+
const skeletonWithRef = /* @__PURE__ */ jsx(PasskeyAuthMenuSkeletonInner, {
|
|
82
|
+
ref: skeletonRootRef,
|
|
83
|
+
className: props.className,
|
|
84
|
+
style: props.style
|
|
85
|
+
});
|
|
86
|
+
const skeleton = /* @__PURE__ */ jsx(PasskeyAuthMenuSkeletonInner, {
|
|
87
|
+
className: props.className,
|
|
88
|
+
style: props.style
|
|
89
|
+
});
|
|
42
90
|
return /* @__PURE__ */ jsx(PasskeyAuthMenuThemeScope, {
|
|
43
91
|
theme,
|
|
44
|
-
children: isClient ? /* @__PURE__ */ jsx(LazyErrorBoundary, {
|
|
92
|
+
children: isClient && stylesReady ? /* @__PURE__ */ jsx(LazyErrorBoundary, {
|
|
45
93
|
onRetry: () => setRetryKey((k) => k + 1),
|
|
46
|
-
fallback: ({ retry }) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */
|
|
47
|
-
className: props.className,
|
|
48
|
-
style: props.style
|
|
49
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
94
|
+
fallback: ({ retry }) => /* @__PURE__ */ jsxs("div", { children: [skeleton, /* @__PURE__ */ jsxs("div", {
|
|
50
95
|
style: {
|
|
51
96
|
marginTop: 10,
|
|
52
97
|
fontSize: 12,
|
|
@@ -65,16 +110,10 @@ const PasskeyAuthMenu = (props) => {
|
|
|
65
110
|
]
|
|
66
111
|
})] }),
|
|
67
112
|
children: /* @__PURE__ */ jsx(React.Suspense, {
|
|
68
|
-
fallback:
|
|
69
|
-
className: props.className,
|
|
70
|
-
style: props.style
|
|
71
|
-
}),
|
|
113
|
+
fallback: skeleton,
|
|
72
114
|
children: /* @__PURE__ */ jsx(ClientLazy, { ...props })
|
|
73
115
|
})
|
|
74
|
-
}) :
|
|
75
|
-
className: props.className,
|
|
76
|
-
style: props.style
|
|
77
|
-
})
|
|
116
|
+
}) : skeletonWithRef
|
|
78
117
|
});
|
|
79
118
|
};
|
|
80
119
|
var shell_default = PasskeyAuthMenu;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.js","names":["PasskeyAuthMenu: React.FC<PasskeyAuthMenuProps>"],"sources":["../../../../../src/react/components/PasskeyAuthMenu/shell.tsx"],"sourcesContent":["import React from 'react';\nimport { PasskeyAuthMenuSkeletonInner } from './skeleton';\nimport { PasskeyAuthMenuThemeScope } from './themeScope';\nimport type { PasskeyAuthMenuProps } from './types';\nimport { useTheme } from '../theme';\n\nfunction createClientLazy() {\n return React.lazy(() => import('./client').then((m) => ({ default: m.PasskeyAuthMenuClient })));\n}\n\nclass LazyErrorBoundary extends React.Component<\n {\n fallback: (args: { error: Error; retry: () => void }) => React.ReactNode;\n onRetry: () => void;\n children: React.ReactNode;\n },\n { error: Error | null }\n> {\n state: { error: Error | null } = { error: null };\n\n static getDerivedStateFromError(error: Error): { error: Error } {\n return { error };\n }\n\n retry = () => {\n this.setState({ error: null });\n this.props.onRetry();\n };\n\n render() {\n if (this.state.error) {\n return this.props.fallback({ error: this.state.error, retry: this.retry });\n }\n return this.props.children;\n }\n}\n\n/**\n * `PasskeyAuthMenu` — SSR-safe shell.\n *\n * - Server: renders a skeleton only.\n * - Client: lazy-loads the full implementation after mount.\n */\nexport const PasskeyAuthMenu: React.FC<PasskeyAuthMenuProps> = (props) => {\n const [isClient, setIsClient] = React.useState(false);\n const [retryKey, setRetryKey] = React.useState(0);\n const ClientLazy = React.useMemo(() => createClientLazy(), [retryKey]);\n\n // Align with the SDK Theme boundary when present (TatchiPasskeyProvider wraps one by default).\n // Falls back to system preference when used standalone.\n const { theme } = useTheme();\n\n React.useEffect(() => {\n setIsClient(true);\n }, []);\n\n return (\n <PasskeyAuthMenuThemeScope theme={theme}>\n {isClient ? (\n <LazyErrorBoundary\n onRetry={() => setRetryKey((k) => k + 1)}\n fallback={({ retry }) => (\n <div>\n
|
|
1
|
+
{"version":3,"file":"shell.js","names":["PasskeyAuthMenu: React.FC<PasskeyAuthMenuProps>"],"sources":["../../../../../src/react/components/PasskeyAuthMenu/shell.tsx"],"sourcesContent":["import React from 'react';\nimport { PasskeyAuthMenuSkeletonInner } from './skeleton';\nimport { PasskeyAuthMenuThemeScope } from './themeScope';\nimport type { PasskeyAuthMenuProps } from './types';\nimport { useTheme } from '../theme';\nimport { preloadPasskeyAuthMenu } from './preload';\n\nfunction createClientLazy() {\n return React.lazy(() => import('./client').then((m) => ({ default: m.PasskeyAuthMenuClient })));\n}\n\nclass LazyErrorBoundary extends React.Component<\n {\n fallback: (args: { error: Error; retry: () => void }) => React.ReactNode;\n onRetry: () => void;\n children: React.ReactNode;\n },\n { error: Error | null }\n> {\n state: { error: Error | null } = { error: null };\n\n static getDerivedStateFromError(error: Error): { error: Error } {\n return { error };\n }\n\n retry = () => {\n this.setState({ error: null });\n this.props.onRetry();\n };\n\n render() {\n if (this.state.error) {\n return this.props.fallback({ error: this.state.error, retry: this.retry });\n }\n return this.props.children;\n }\n}\n\n/**\n * `PasskeyAuthMenu` — SSR-safe shell.\n *\n * - Server: renders a skeleton only.\n * - Client: lazy-loads the full implementation after mount.\n */\nexport const PasskeyAuthMenu: React.FC<PasskeyAuthMenuProps> = (props) => {\n const [isClient, setIsClient] = React.useState(false);\n const [retryKey, setRetryKey] = React.useState(0);\n const [stylesReady, setStylesReady] = React.useState(false);\n const ClientLazy = React.useMemo(() => createClientLazy(), [retryKey]);\n const skeletonRootRef = React.useRef<HTMLDivElement | null>(null);\n\n // Align with the SDK Theme boundary when present (TatchiPasskeyProvider wraps one by default).\n // Falls back to system preference when used standalone.\n const { theme } = useTheme();\n\n React.useEffect(() => {\n setIsClient(true);\n // Start fetching the client chunk immediately; we’ll still gate showing it on `stylesReady`.\n preloadPasskeyAuthMenu();\n }, []);\n\n // Avoid FOUC when PasskeyAuthMenu is code-split and styles are still streaming in:\n // keep rendering the skeleton until we can observe CSS being applied.\n React.useEffect(() => {\n if (!isClient) return;\n if (stylesReady) return;\n if (typeof window === 'undefined' || typeof requestAnimationFrame !== 'function') {\n setStylesReady(true);\n return;\n }\n\n let cancelled = false;\n const start = typeof performance !== 'undefined' ? performance.now() : Date.now();\n const maxWaitMs = 1500;\n\n const tick = () => {\n if (cancelled) return;\n const el = skeletonRootRef.current;\n if (el) {\n try {\n const cs = window.getComputedStyle(el);\n const sentinelReady = cs.getPropertyValue('--w3a-pam2-css-ready').trim() === '1';\n // Back-compat heuristic if the sentinel is ever missing.\n const borderOk = cs.borderTopStyle !== 'none' && cs.borderTopWidth !== '0px';\n const radiusOk = cs.borderTopLeftRadius !== '0px';\n if (sentinelReady || borderOk || radiusOk) {\n setStylesReady(true);\n return;\n }\n } catch {}\n }\n const now = typeof performance !== 'undefined' ? performance.now() : Date.now();\n if (now - start >= maxWaitMs) {\n setStylesReady(true);\n return;\n }\n requestAnimationFrame(tick);\n };\n\n requestAnimationFrame(tick);\n return () => {\n cancelled = true;\n };\n }, [isClient, stylesReady]);\n\n const skeletonWithRef = (\n <PasskeyAuthMenuSkeletonInner\n ref={skeletonRootRef}\n className={props.className}\n style={props.style}\n />\n );\n\n const skeleton = (\n <PasskeyAuthMenuSkeletonInner className={props.className} style={props.style} />\n );\n\n return (\n <PasskeyAuthMenuThemeScope theme={theme}>\n {isClient && stylesReady ? (\n <LazyErrorBoundary\n onRetry={() => setRetryKey((k) => k + 1)}\n fallback={({ retry }) => (\n <div>\n {skeleton}\n <div style={{ marginTop: 10, fontSize: 12, textAlign: 'center', opacity: 0.9 }}>\n Failed to load menu.{' '}\n <button type=\"button\" onClick={retry} style={{ textDecoration: 'underline' }}>\n Retry\n </button>\n </div>\n </div>\n )}\n >\n <React.Suspense\n fallback={skeleton}\n >\n <ClientLazy {...props} />\n </React.Suspense>\n </LazyErrorBoundary>\n ) : (\n skeletonWithRef\n )}\n </PasskeyAuthMenuThemeScope>\n );\n};\n\nexport default PasskeyAuthMenu;\n"],"mappings":";;;;;;;;AAOA,SAAS,mBAAmB;AAC1B,QAAO,MAAM,WAAW,OAAO,eAAY,MAAM,OAAO,EAAE,SAAS,EAAE;;AAGvE,IAAM,oBAAN,cAAgC,MAAM,UAOpC;CACA,QAAiC,EAAE,OAAO;CAE1C,OAAO,yBAAyB,OAAgC;AAC9D,SAAO,EAAE;;CAGX,cAAc;AACZ,OAAK,SAAS,EAAE,OAAO;AACvB,OAAK,MAAM;;CAGb,SAAS;AACP,MAAI,KAAK,MAAM,MACb,QAAO,KAAK,MAAM,SAAS;GAAE,OAAO,KAAK,MAAM;GAAO,OAAO,KAAK;;AAEpE,SAAO,KAAK,MAAM;;;;;;;;;AAUtB,MAAaA,mBAAmD,UAAU;CACxE,MAAM,CAAC,UAAU,eAAe,MAAM,SAAS;CAC/C,MAAM,CAAC,UAAU,eAAe,MAAM,SAAS;CAC/C,MAAM,CAAC,aAAa,kBAAkB,MAAM,SAAS;CACrD,MAAM,aAAa,MAAM,cAAc,oBAAoB,CAAC;CAC5D,MAAM,kBAAkB,MAAM,OAA8B;CAI5D,MAAM,EAAE,UAAU;AAElB,OAAM,gBAAgB;AACpB,cAAY;AAEZ;IACC;AAIH,OAAM,gBAAgB;AACpB,MAAI,CAAC,SAAU;AACf,MAAI,YAAa;AACjB,MAAI,OAAO,WAAW,eAAe,OAAO,0BAA0B,YAAY;AAChF,kBAAe;AACf;;EAGF,IAAI,YAAY;EAChB,MAAM,QAAQ,OAAO,gBAAgB,cAAc,YAAY,QAAQ,KAAK;EAC5E,MAAM,YAAY;EAElB,MAAM,aAAa;AACjB,OAAI,UAAW;GACf,MAAM,KAAK,gBAAgB;AAC3B,OAAI,GACF,KAAI;IACF,MAAM,KAAK,OAAO,iBAAiB;IACnC,MAAM,gBAAgB,GAAG,iBAAiB,wBAAwB,WAAW;IAE7E,MAAM,WAAW,GAAG,mBAAmB,UAAU,GAAG,mBAAmB;IACvE,MAAM,WAAW,GAAG,wBAAwB;AAC5C,QAAI,iBAAiB,YAAY,UAAU;AACzC,oBAAe;AACf;;WAEI;GAEV,MAAM,MAAM,OAAO,gBAAgB,cAAc,YAAY,QAAQ,KAAK;AAC1E,OAAI,MAAM,SAAS,WAAW;AAC5B,mBAAe;AACf;;AAEF,yBAAsB;;AAGxB,wBAAsB;AACtB,eAAa;AACX,eAAY;;IAEb,CAAC,UAAU;CAEd,MAAM,kBACJ,oBAAC;EACC,KAAK;EACL,WAAW,MAAM;EACjB,OAAO,MAAM;;CAIjB,MAAM,WACJ,oBAAC;EAA6B,WAAW,MAAM;EAAW,OAAO,MAAM;;AAGzE,QACE,oBAAC;EAAiC;YAC/B,YAAY,cACX,oBAAC;GACC,eAAe,aAAa,MAAM,IAAI;GACtC,WAAW,EAAE,YACX,qBAAC,oBACE,UACD,qBAAC;IAAI,OAAO;KAAE,WAAW;KAAI,UAAU;KAAI,WAAW;KAAU,SAAS;;;KAAO;KACzD;KACrB,oBAAC;MAAO,MAAK;MAAS,SAAS;MAAO,OAAO,EAAE,gBAAgB;gBAAe;;;;aAOpF,oBAAC,MAAM;IACL,UAAU;cAEV,oBAAC,cAAW,GAAI;;OAIpB;;;AAMR,oBAAe"}
|
|
@@ -5,8 +5,9 @@ import React from "react";
|
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
|
|
7
7
|
//#region src/react/components/PasskeyAuthMenu/skeleton.tsx
|
|
8
|
-
const PasskeyAuthMenuSkeletonInner = ({ className, style }) => {
|
|
8
|
+
const PasskeyAuthMenuSkeletonInner = React.forwardRef(({ className, style }, ref) => {
|
|
9
9
|
return /* @__PURE__ */ jsxs("div", {
|
|
10
|
+
ref,
|
|
10
11
|
className: `w3a-signup-menu-root w3a-skeleton${className ? ` ${className}` : ""}`,
|
|
11
12
|
style,
|
|
12
13
|
children: [
|
|
@@ -111,7 +112,8 @@ const PasskeyAuthMenuSkeletonInner = ({ className, style }) => {
|
|
|
111
112
|
})
|
|
112
113
|
]
|
|
113
114
|
});
|
|
114
|
-
};
|
|
115
|
+
});
|
|
116
|
+
PasskeyAuthMenuSkeletonInner.displayName = "PasskeyAuthMenuSkeletonInner";
|
|
115
117
|
const PasskeyAuthMenuSkeleton = (props) => {
|
|
116
118
|
const { theme } = useTheme();
|
|
117
119
|
return /* @__PURE__ */ jsx(PasskeyAuthMenuThemeScope, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skeleton.js","names":["
|
|
1
|
+
{"version":3,"file":"skeleton.js","names":["PasskeyAuthMenuSkeleton: React.FC<PasskeyAuthMenuSkeletonProps>"],"sources":["../../../../../src/react/components/PasskeyAuthMenu/skeleton.tsx"],"sourcesContent":["import React from 'react';\nimport './PasskeyAuthMenu.css';\nimport { PasskeyAuthMenuThemeScope } from './themeScope';\nimport { useTheme } from '../theme';\n\nexport interface PasskeyAuthMenuSkeletonProps {\n className?: string;\n style?: React.CSSProperties;\n}\n\nexport const PasskeyAuthMenuSkeletonInner = React.forwardRef<\n HTMLDivElement,\n PasskeyAuthMenuSkeletonProps\n>(({ className, style }, ref) => {\n return (\n <div\n ref={ref}\n className={`w3a-signup-menu-root w3a-skeleton${className ? ` ${className}` : ''}`}\n style={style}\n >\n <div className=\"w3a-header\">\n <div\n className=\"w3a-skeleton-block w3a-title-skeleton\"\n style={{ width: '60%', height: '24px', marginBottom: '8px' }}\n />\n <div\n className=\"w3a-skeleton-block w3a-subtitle-skeleton\"\n style={{ width: '80%', height: '16px' }}\n />\n </div>\n\n <div className=\"w3a-passkey-row\">\n <div className=\"w3a-input-pill w3a-skeleton-input\">\n <div\n className=\"w3a-skeleton-block\"\n style={{ width: '40%', height: '18px', marginLeft: '12px' }}\n />\n </div>\n </div>\n\n <div className=\"w3a-segmented-root\">\n <div className=\"w3a-seg-track\">\n <div className=\"w3a-seg-button\">Register</div>\n <div className=\"w3a-seg-button\">Login</div>\n <div className=\"w3a-seg-button\">Sync</div>\n </div>\n </div>\n\n <div className=\"w3a-seg-help-row\">\n <div\n className=\"w3a-skeleton-block\"\n style={{ width: '50%', height: '14px', margin: '0 auto' }}\n />\n </div>\n\n <div className=\"w3a-scan-device-row\">\n <div className=\"w3a-section-divider\">\n <div className=\"w3a-section-divider-text\">Already have an account?</div>\n </div>\n <div className=\"w3a-secondary-actions\">\n <button className=\"w3a-link-device-btn\" disabled>\n <div\n className=\"w3a-skeleton-block\"\n style={{\n width: '18px',\n height: '18px',\n marginRight: '8px',\n borderRadius: '4px',\n }}\n />\n Scan and Link Device\n </button>\n <button className=\"w3a-link-device-btn\" disabled>\n <div\n className=\"w3a-skeleton-block\"\n style={{\n width: '18px',\n height: '18px',\n marginRight: '8px',\n borderRadius: '9999px',\n }}\n />\n Recover Account with Email\n </button>\n </div>\n </div>\n </div>\n );\n});\nPasskeyAuthMenuSkeletonInner.displayName = 'PasskeyAuthMenuSkeletonInner';\n\nexport const PasskeyAuthMenuSkeleton: React.FC<PasskeyAuthMenuSkeletonProps> = (props) => {\n const { theme } = useTheme();\n return (\n <PasskeyAuthMenuThemeScope theme={theme}>\n <PasskeyAuthMenuSkeletonInner {...props} />\n </PasskeyAuthMenuThemeScope>\n );\n};\n\nexport default PasskeyAuthMenuSkeleton;\n"],"mappings":";;;;;;;AAUA,MAAa,+BAA+B,MAAM,YAG/C,EAAE,WAAW,SAAS,QAAQ;AAC/B,QACE,qBAAC;EACM;EACL,WAAW,oCAAoC,YAAY,IAAI,cAAc;EACtE;;GAEP,qBAAC;IAAI,WAAU;eACb,oBAAC;KACC,WAAU;KACV,OAAO;MAAE,OAAO;MAAO,QAAQ;MAAQ,cAAc;;QAEvD,oBAAC;KACC,WAAU;KACV,OAAO;MAAE,OAAO;MAAO,QAAQ;;;;GAInC,oBAAC;IAAI,WAAU;cACb,oBAAC;KAAI,WAAU;eACb,oBAAC;MACC,WAAU;MACV,OAAO;OAAE,OAAO;OAAO,QAAQ;OAAQ,YAAY;;;;;GAKzD,oBAAC;IAAI,WAAU;cACb,qBAAC;KAAI,WAAU;;MACb,oBAAC;OAAI,WAAU;iBAAiB;;MAChC,oBAAC;OAAI,WAAU;iBAAiB;;MAChC,oBAAC;OAAI,WAAU;iBAAiB;;;;;GAIpC,oBAAC;IAAI,WAAU;cACb,oBAAC;KACC,WAAU;KACV,OAAO;MAAE,OAAO;MAAO,QAAQ;MAAQ,QAAQ;;;;GAInD,qBAAC;IAAI,WAAU;eACb,oBAAC;KAAI,WAAU;eACb,oBAAC;MAAI,WAAU;gBAA2B;;QAE5C,qBAAC;KAAI,WAAU;gBACb,qBAAC;MAAO,WAAU;MAAsB;iBACtC,oBAAC;OACC,WAAU;OACV,OAAO;QACL,OAAO;QACP,QAAQ;QACR,aAAa;QACb,cAAc;;UAEhB;SAGJ,qBAAC;MAAO,WAAU;MAAsB;iBACtC,oBAAC;OACC,WAAU;OACV,OAAO;QACL,OAAO;QACP,QAAQ;QACR,aAAa;QACb,cAAc;;UAEhB;;;;;;;AAQd,6BAA6B,cAAc;AAE3C,MAAaA,2BAAmE,UAAU;CACxF,MAAM,EAAE,UAAU;AAClB,QACE,oBAAC;EAAiC;YAChC,oBAAC,gCAA6B,GAAI;;;AAKxC,uBAAe"}
|
|
@@ -462,7 +462,11 @@ const EmailRecoverySlide = ({ tatchiPasskey, accountId, refreshLoginState, email
|
|
|
462
462
|
if (session?.login?.isLoggedIn) loginOk = true;
|
|
463
463
|
else {
|
|
464
464
|
safeSet(setStatusText, "Email recovery completed. Logging you in…");
|
|
465
|
-
|
|
465
|
+
const loginResult = await tatchiPasskey.loginAndCreateSession(normalizedAccountId).catch(() => null);
|
|
466
|
+
if (loginResult?.success) {
|
|
467
|
+
const updatedSession = await tatchiPasskey.getLoginSession(normalizedAccountId).catch(() => null);
|
|
468
|
+
loginOk = !!updatedSession?.login?.isLoggedIn;
|
|
469
|
+
} else loginOk = false;
|
|
466
470
|
}
|
|
467
471
|
if (refreshLoginState) await refreshLoginState(normalizedAccountId).catch(() => {});
|
|
468
472
|
safeSet(setStatusText, loginOk ? "Email recovery completed on this device." : "Email recovery completed. Please log in on this device.");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmailRecoverySlide.js","names":["EmailRecoverySlide: React.FC<EmailRecoverySlideProps>","info: EmailRecoveryAccountInfo | null","err: unknown","summaryLine: React.ReactNode"],"sources":["../../../../../../src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.tsx"],"sourcesContent":["import React from 'react';\n\nimport {\n EmailRecoveryPhase,\n EmailRecoveryStatus,\n type EmailRecoverySSEEvent,\n} from '@/core/types/sdkSentEvents';\nimport type { TatchiPasskey } from '@/core/TatchiPasskey';\nimport { EmailRecoveryErrorCode } from '@/core/types/emailRecovery';\nimport type { EmailRecoveryFlowOptions } 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 EmailRecoveryAccountInfo = {\n emailsCount: number;\n};\n\ntype MailtoUiState = 'ready' | 'opening';\n\ntype RecoveryEmailRecord = Awaited<ReturnType<TatchiPasskey['getRecoveryEmails']>>[number];\n\ntype ExplorerToast = { url: string; accountId?: string; transactionHash?: string };\n\nconst DEFAULT_NEAR_EXPLORER_URL = 'https://testnet.nearblocks.io';\nconst ACCOUNT_INFO_DEBOUNCE_MS = 350;\nconst MAILTO_REENABLE_MS = 2_000;\n\nfunction getExplorerBaseUrl(tatchiPasskey: TatchiPasskey): string {\n return String(tatchiPasskey.configs?.nearExplorerUrl || DEFAULT_NEAR_EXPLORER_URL).replace(/\\/$/, '');\n}\n\nfunction getExplorerAccountUrl(args: { base: string; accountId: string }): string {\n const { base, accountId } = args;\n return base.includes('nearblocks.io') ? `${base}/address/${accountId}` : `${base}/accounts/${accountId}`;\n}\n\nfunction getExplorerTxUrl(args: { base: string; txHash: string }): string {\n const { base, txHash } = args;\n return base.includes('nearblocks.io') ? `${base}/txns/${txHash}` : `${base}/transactions/${txHash}`;\n}\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 normalizedFallback = fallback.trim().toLowerCase();\n if (normalizedFallback.includes('recovery email is required')) {\n return {\n message:\n fallback ||\n 'Recovery email is required for email-based account recovery. Make sure you send the email from your configured recovery email address.',\n canRestart: true,\n };\n }\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\nfunction getEmailRecoveryErrorTxHash(err: unknown): string | null {\n const carrier = (err as { context?: unknown; details?: unknown } | null);\n const ctx = carrier?.context && typeof carrier.context === 'object' ? carrier.context : null;\n const details = carrier?.details && typeof carrier.details === 'object' ? carrier.details : null;\n const source = ctx ?? details;\n if (!source) return null;\n const txHash = (source as { transactionHash?: unknown }).transactionHash;\n return typeof txHash === 'string' && txHash.trim().length > 0 ? txHash.trim() : null;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (!value || typeof value !== 'object') return null;\n return value as Record<string, unknown>;\n}\n\nfunction extractTxHashFromEmailRecoveryEvent(ev: EmailRecoverySSEEvent): string | null {\n const data = 'data' in ev ? asRecord(ev.data) : null;\n const rawTxHash = data?.['transactionHash'] ?? data?.['transaction_hash'];\n const txHash = typeof rawTxHash === 'string' ? rawTxHash.trim() : '';\n return txHash || null;\n}\n\nfunction extractElapsedMsFromEmailRecoveryEvent(ev: EmailRecoverySSEEvent): number | null | undefined {\n const data = 'data' in ev ? asRecord(ev.data) : null;\n const elapsedRaw = data?.['elapsedMs'] ?? data?.['elapsed_ms'];\n if (elapsedRaw == null) return null;\n const elapsed = Number(elapsedRaw);\n return Number.isNaN(elapsed) ? undefined : elapsed;\n}\n\nfunction deriveEmailsFromRecoveryRecords(records: RecoveryEmailRecord[]): string[] {\n if (records.length === 0) return [];\n const emails = records\n .map((r) => r.email.trim().toLowerCase())\n .filter((e) => e.length > 0 && e.includes('@'));\n return Array.from(new Set(emails));\n}\n\nfunction EmailRecoveryHeader() {\n return (\n <>\n <div className=\"w3a-email-recovery-title\">Recover Account with Email</div>\n <div className=\"w3a-email-recovery-help\">\n Send a special email to recover your account.\n This email must be sent from the designated email recovery address.\n </div>\n </>\n );\n}\n\nfunction AccountIdInputRow(props: {\n value: string;\n onChange: (value: string) => void;\n disabled: boolean;\n}) {\n const { value, onChange, disabled } = props;\n return (\n <div>\n <div className=\"w3a-input-pill w3a-email-recovery-input-pill\">\n <div className=\"w3a-input-wrap\">\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(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={disabled}\n />\n </div>\n </div>\n </div>\n );\n}\n\nfunction RecoveryEmailsSummary(props: {\n summaryLine: React.ReactNode;\n accountInfoError: string | null;\n localRecoveryEmails: string[];\n showFromWarning: boolean;\n}) {\n const { summaryLine, accountInfoError, localRecoveryEmails, showFromWarning } = props;\n return (\n <div className=\"w3a-email-recovery-summary\" aria-live=\"polite\">\n <div>{summaryLine}</div>\n {!!accountInfoError && (\n <div className=\"w3a-email-recovery-warning\">{accountInfoError}</div>\n )}\n {localRecoveryEmails.length > 0 && (\n <div className=\"w3a-email-recovery-saved-emails\" role=\"list\" aria-label=\"Recovery emails\">\n {localRecoveryEmails.map((email) => (\n <span key={email} className=\"w3a-email-recovery-email-chip w3a-email-recovery-email-chip-static\" role=\"listitem\">\n {email}\n </span>\n ))}\n </div>\n )}\n {showFromWarning && (\n <div className=\"w3a-email-recovery-from-warning\">\n {localRecoveryEmails.length === 1\n ? `Check that you are sending the recovery email from ${localRecoveryEmails[0]}.`\n : 'Check that you are sending the recovery email from your designated recovery email.'}\n </div>\n )}\n </div>\n );\n}\n\nfunction EmailRecoveryActions(props: {\n isBusy: boolean;\n pendingMailtoUrl: string | null;\n mailtoUiState: MailtoUiState;\n startDisabled: boolean;\n accountInfoLoading: boolean;\n noRecoveryEmailsConfigured: boolean;\n showRestart: boolean;\n onStart: () => void;\n onOpenDraft: (mailtoUrl: string) => void;\n onRestart: () => void;\n}) {\n const {\n isBusy,\n pendingMailtoUrl,\n mailtoUiState,\n startDisabled,\n accountInfoLoading,\n noRecoveryEmailsConfigured,\n showRestart,\n onStart,\n onOpenDraft,\n onRestart,\n } = props;\n\n return (\n <div className=\"w3a-email-recovery-actions\">\n {(!pendingMailtoUrl || !isBusy) && (\n <button\n onClick={onStart}\n className=\"w3a-link-device-btn w3a-link-device-btn-primary\"\n disabled={startDisabled}\n >\n {accountInfoLoading\n ? 'Checking recovery emails…'\n : noRecoveryEmailsConfigured\n ? 'No recovery emails configured'\n : (isBusy ? 'Working…' : 'Start Email Recovery')}\n </button>\n )}\n\n {pendingMailtoUrl && (\n <button\n type=\"button\"\n onClick={() => onOpenDraft(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 {showRestart && (\n <button\n type=\"button\"\n onClick={onRestart}\n className=\"w3a-link-device-btn\"\n disabled={isBusy}\n >\n Restart email recovery\n </button>\n )}\n </div>\n );\n}\n\nfunction EmailRecoveryStatusPanel(props: {\n errorText: string | null;\n statusText: string | null;\n pollingElapsedMs: number | null;\n explorerToast: ExplorerToast | null;\n}) {\n const { errorText, statusText, pollingElapsedMs, explorerToast } = props;\n if (!errorText && !statusText && !explorerToast) return null;\n\n return (\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}\n\nexport const EmailRecoverySlide: React.FC<EmailRecoverySlideProps> = ({\n tatchiPasskey,\n accountId,\n refreshLoginState,\n emailRecoveryOptions\n}) => {\n\n const mountedRef = React.useRef(true);\n const mailtoAttemptTimerRef = React.useRef<number | null>(null);\n const cancelRequestedRef = React.useRef(false);\n\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 type NoInferType<T> = [T][T extends any ? 0 : never];\n const safeSet = React.useCallback(<T,>(\n setter: React.Dispatch<React.SetStateAction<T>>,\n value: React.SetStateAction<NoInferType<T>>,\n ) => {\n if (!mountedRef.current) return;\n setter(value);\n }, []);\n\n const [isBusy, setIsBusy] = React.useState(false);\n const [accountIdInput, setAccountIdInput] = 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<ExplorerToast | null>(null);\n\n const lastPrefilledAccountIdRef = 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 onEvent = React.useCallback(\n (ev: EmailRecoverySSEEvent) => {\n if (cancelRequestedRef.current) return;\n safeSet(setStatusText, ev?.message || null);\n emailRecoveryOptions?.onEvent?.(ev);\n\n const txHash = extractTxHashFromEmailRecoveryEvent(ev);\n if (txHash) {\n const base = getExplorerBaseUrl(tatchiPasskey);\n safeSet(setExplorerToast, { url: getExplorerTxUrl({ base, txHash }), transactionHash: txHash });\n }\n const elapsed = extractElapsedMsFromEmailRecoveryEvent(ev);\n if (elapsed === null) safeSet(setPollingElapsedMs, null);\n else if (elapsed != null) safeSet(setPollingElapsedMs, elapsed);\n\n if (ev.phase === EmailRecoveryPhase.ERROR || ev.status === EmailRecoveryStatus.ERROR) {\n const raw = 'error' in ev ? ev.error : ev.message;\n safeSet(setErrorText, raw || 'Email recovery failed');\n safeSet(setCanRestart, false);\n }\n },\n [emailRecoveryOptions, safeSet, tatchiPasskey],\n );\n\n const showExplorerToast = React.useCallback(\n (rawAccountId: string) => {\n const normalized = (rawAccountId || '').trim();\n if (!normalized) return;\n const base = getExplorerBaseUrl(tatchiPasskey);\n safeSet(setExplorerToast, { url: getExplorerAccountUrl({ base, accountId: normalized }), accountId: normalized });\n },\n [safeSet, tatchiPasskey],\n );\n\n const showExplorerTxToast = React.useCallback(\n (txHash: string) => {\n const normalized = (txHash || '').trim();\n if (!normalized) return;\n const base = getExplorerBaseUrl(tatchiPasskey);\n safeSet(setExplorerToast, { url: getExplorerTxUrl({ base, txHash: normalized }), transactionHash: normalized });\n },\n [safeSet, 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 safeSet(setMailtoUiState, '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 safeSet(setMailtoUiState, prev => (prev === 'opening' ? 'ready' : prev));\n mailtoAttemptTimerRef.current = null;\n }, MAILTO_REENABLE_MS);\n\n launchMailto(url);\n },\n [launchMailto, safeSet],\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 safeSet(setMailtoUiState, '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, safeSet]);\n\n React.useEffect(() => {\n const normalized = (accountIdInput || '').trim();\n if (!normalized) {\n setAccountInfo(null);\n setAccountInfoError(null);\n setAccountInfoLoading(false);\n safeSet(setLocalRecoveryEmails, []);\n return;\n }\n\n let cancelled = false;\n // Show loading state immediately (don't wait for debounce).\n safeSet(setAccountInfoLoading, true);\n safeSet(setAccountInfoError, null);\n const handle = window.setTimeout(() => {\n void (async () => {\n try {\n const records = await tatchiPasskey.getRecoveryEmails(normalized);\n const resolvedEmails = deriveEmailsFromRecoveryRecords(records);\n\n if (!cancelled) {\n safeSet(setLocalRecoveryEmails, resolvedEmails);\n }\n\n const info: EmailRecoveryAccountInfo | null = records\n ? { emailsCount: Array.isArray(records) ? records.length : 0 }\n : null;\n if (cancelled) return;\n safeSet(setAccountInfo, info);\n } catch (err: unknown) {\n if (cancelled) return;\n safeSet(setAccountInfo, null);\n const msg = err instanceof Error ? err.message : '';\n safeSet(setAccountInfoError, msg || 'Failed to load email recovery settings for this account');\n safeSet(setLocalRecoveryEmails, []);\n } finally {\n if (!cancelled) safeSet(setAccountInfoLoading, false);\n }\n })();\n }, ACCOUNT_INFO_DEBOUNCE_MS);\n\n return () => {\n cancelled = true;\n window.clearTimeout(handle);\n };\n }, [accountIdInput, safeSet, tatchiPasskey]);\n\n const handleStart = React.useCallback(async () => {\n const normalizedAccountId = (accountIdInput || '').trim();\n if (!normalizedAccountId) {\n safeSet(setErrorText, 'Enter an account ID.');\n return;\n }\n\n if (accountInfoLoading) {\n safeSet(setErrorText, 'Checking recovery email settings…');\n return;\n }\n\n if (accountInfoError) {\n safeSet(setErrorText, accountInfoError);\n return;\n }\n\n if (!accountInfo) {\n safeSet(setErrorText, 'Failed to load email recovery settings for this account.');\n return;\n }\n\n if (accountInfo.emailsCount === 0) {\n safeSet(setErrorText, 'No recovery emails are configured for this account.');\n return;\n }\n\n safeSet(setIsBusy, true);\n cancelRequestedRef.current = false;\n safeSet(setErrorText, null);\n safeSet(setCanRestart, false);\n safeSet(setStatusText, null);\n safeSet(setPollingElapsedMs, null);\n safeSet(setPendingMailtoUrl, null);\n safeSet(setPendingNearPublicKey, null);\n safeSet(setMailtoUiState, 'ready');\n\n let didForwardError = false;\n try {\n const result = await tatchiPasskey.startEmailRecovery({\n accountId: normalizedAccountId,\n options: {\n onEvent,\n onError: (err: Error) => {\n if (cancelRequestedRef.current) return;\n safeSet(setErrorText, err?.message || 'Failed to start email recovery');\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n } satisfies EmailRecoveryFlowOptions,\n });\n\n safeSet(setPendingMailtoUrl, result.mailtoUrl);\n safeSet(setPendingNearPublicKey, result.nearPublicKey);\n safeSet(\n setStatusText,\n 'Recovery email draft ready. If it didn’t open automatically, click “Open recovery email draft”. Waiting for verification…'\n );\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 safeSet(setErrorText, uiError.message || 'Failed to finalize email recovery');\n safeSet(setCanRestart, uiError.canRestart);\n const txHash = getEmailRecoveryErrorTxHash(err);\n if (txHash) showExplorerTxToast(txHash);\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n } satisfies EmailRecoveryFlowOptions,\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 safeSet(setStatusText, 'Email recovery completed. Logging you in…');\n loginOk = await tatchiPasskey\n .loginAndCreateSession(normalizedAccountId)\n .then(() => true)\n .catch(() => false);\n }\n\n if (refreshLoginState) {\n await refreshLoginState(normalizedAccountId).catch(() => {});\n }\n\n safeSet(\n setStatusText,\n loginOk ? 'Email recovery completed on this device.' : 'Email recovery completed. Please log in on this device.'\n );\n safeSet(setPendingMailtoUrl, null);\n safeSet(setMailtoUiState, 'ready');\n safeSet(setPollingElapsedMs, null);\n } catch (err: unknown) {\n if (cancelRequestedRef.current) {\n safeSet(setErrorText, 'Email recovery cancelled. Please try again.');\n safeSet(setStatusText, null);\n safeSet(setPollingElapsedMs, null);\n safeSet(setPendingMailtoUrl, null);\n safeSet(setPendingNearPublicKey, null);\n safeSet(setMailtoUiState, 'ready');\n safeSet(setCanRestart, false);\n return;\n }\n const uiError = getEmailRecoveryUiError(err);\n safeSet(setErrorText, uiError.message || 'Failed to start email recovery');\n safeSet(setCanRestart, uiError.canRestart);\n const txHash = getEmailRecoveryErrorTxHash(err);\n if (txHash) showExplorerTxToast(txHash);\n if (!didForwardError && err instanceof Error) {\n emailRecoveryOptions?.onError?.(err);\n }\n } finally {\n safeSet(setIsBusy, false);\n }\n }, [\n accountIdInput,\n accountInfo,\n accountInfoError,\n accountInfoLoading,\n attemptOpenMailtoAuto,\n emailRecoveryOptions,\n onEvent,\n refreshLoginState,\n safeSet,\n showExplorerToast,\n showExplorerTxToast,\n tatchiPasskey,\n ]);\n\n const handleRestart = React.useCallback(async () => {\n const normalizedAccountId = (accountIdInput || '').trim();\n if (!normalizedAccountId) return;\n\n safeSet(setIsBusy, true);\n try {\n cancelRequestedRef.current = true;\n await tatchiPasskey\n .cancelEmailRecovery({\n accountId: normalizedAccountId,\n nearPublicKey: pendingNearPublicKey || undefined,\n })\n .catch(() => {});\n safeSet(setErrorText, null);\n safeSet(setStatusText, null);\n safeSet(setPollingElapsedMs, null);\n safeSet(setPendingMailtoUrl, null);\n safeSet(setPendingNearPublicKey, null);\n safeSet(setMailtoUiState, 'ready');\n safeSet(setCanRestart, false);\n } finally {\n cancelRequestedRef.current = false;\n safeSet(setIsBusy, false);\n }\n }, [accountIdInput, pendingNearPublicKey, safeSet, tatchiPasskey]);\n\n const summaryLine: React.ReactNode = accountInfoLoading\n ? (\n <>\n Checking if account has recovery emails configured\n <span className=\"w3a-ellipsis\" aria-hidden=\"true\">\n <span className=\"w3a-ellipsis-dot\">.</span>\n <span className=\"w3a-ellipsis-dot\">.</span>\n <span className=\"w3a-ellipsis-dot\">.</span>\n </span>\n </>\n )\n : accountInfo && !accountInfoError\n ? `Recovery emails configured: ${accountInfo.emailsCount}`\n : '\\u00A0';\n\n const noRecoveryEmailsConfigured =\n !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount === 0;\n const startDisabled = isBusy || accountInfoLoading || !!accountInfoError || !accountInfo || noRecoveryEmailsConfigured;\n const showFromWarning = !!accountIdInput.trim() && !noRecoveryEmailsConfigured;\n const showRestart = !!errorText && canRestart;\n\n return (\n <div className=\"w3a-email-recovery-slide\">\n <EmailRecoveryHeader />\n <AccountIdInputRow value={accountIdInput} onChange={setAccountIdInput} disabled={isBusy} />\n <RecoveryEmailsSummary\n summaryLine={summaryLine}\n accountInfoError={accountInfoError}\n localRecoveryEmails={localRecoveryEmails}\n showFromWarning={showFromWarning}\n />\n <EmailRecoveryActions\n isBusy={isBusy}\n pendingMailtoUrl={pendingMailtoUrl}\n mailtoUiState={mailtoUiState}\n startDisabled={startDisabled}\n accountInfoLoading={accountInfoLoading}\n noRecoveryEmailsConfigured={noRecoveryEmailsConfigured}\n showRestart={showRestart}\n onStart={handleStart}\n onOpenDraft={attemptOpenMailtoFromUserGesture}\n onRestart={handleRestart}\n />\n <EmailRecoveryStatusPanel\n errorText={errorText}\n statusText={statusText}\n pollingElapsedMs={pollingElapsedMs}\n explorerToast={explorerToast}\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>","info: EmailRecoveryAccountInfo | null","err: unknown","summaryLine: React.ReactNode"],"sources":["../../../../../../src/react/components/PasskeyAuthMenu/ui/EmailRecoverySlide.tsx"],"sourcesContent":["import React from 'react';\n\nimport {\n EmailRecoveryPhase,\n EmailRecoveryStatus,\n type EmailRecoverySSEEvent,\n} from '@/core/types/sdkSentEvents';\nimport type { TatchiPasskey } from '@/core/TatchiPasskey';\nimport { EmailRecoveryErrorCode } from '@/core/types/emailRecovery';\nimport type { EmailRecoveryFlowOptions } 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 EmailRecoveryAccountInfo = {\n emailsCount: number;\n};\n\ntype MailtoUiState = 'ready' | 'opening';\n\ntype RecoveryEmailRecord = Awaited<ReturnType<TatchiPasskey['getRecoveryEmails']>>[number];\n\ntype ExplorerToast = { url: string; accountId?: string; transactionHash?: string };\n\nconst DEFAULT_NEAR_EXPLORER_URL = 'https://testnet.nearblocks.io';\nconst ACCOUNT_INFO_DEBOUNCE_MS = 350;\nconst MAILTO_REENABLE_MS = 2_000;\n\nfunction getExplorerBaseUrl(tatchiPasskey: TatchiPasskey): string {\n return String(tatchiPasskey.configs?.nearExplorerUrl || DEFAULT_NEAR_EXPLORER_URL).replace(/\\/$/, '');\n}\n\nfunction getExplorerAccountUrl(args: { base: string; accountId: string }): string {\n const { base, accountId } = args;\n return base.includes('nearblocks.io') ? `${base}/address/${accountId}` : `${base}/accounts/${accountId}`;\n}\n\nfunction getExplorerTxUrl(args: { base: string; txHash: string }): string {\n const { base, txHash } = args;\n return base.includes('nearblocks.io') ? `${base}/txns/${txHash}` : `${base}/transactions/${txHash}`;\n}\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 normalizedFallback = fallback.trim().toLowerCase();\n if (normalizedFallback.includes('recovery email is required')) {\n return {\n message:\n fallback ||\n 'Recovery email is required for email-based account recovery. Make sure you send the email from your configured recovery email address.',\n canRestart: true,\n };\n }\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\nfunction getEmailRecoveryErrorTxHash(err: unknown): string | null {\n const carrier = (err as { context?: unknown; details?: unknown } | null);\n const ctx = carrier?.context && typeof carrier.context === 'object' ? carrier.context : null;\n const details = carrier?.details && typeof carrier.details === 'object' ? carrier.details : null;\n const source = ctx ?? details;\n if (!source) return null;\n const txHash = (source as { transactionHash?: unknown }).transactionHash;\n return typeof txHash === 'string' && txHash.trim().length > 0 ? txHash.trim() : null;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (!value || typeof value !== 'object') return null;\n return value as Record<string, unknown>;\n}\n\nfunction extractTxHashFromEmailRecoveryEvent(ev: EmailRecoverySSEEvent): string | null {\n const data = 'data' in ev ? asRecord(ev.data) : null;\n const rawTxHash = data?.['transactionHash'] ?? data?.['transaction_hash'];\n const txHash = typeof rawTxHash === 'string' ? rawTxHash.trim() : '';\n return txHash || null;\n}\n\nfunction extractElapsedMsFromEmailRecoveryEvent(ev: EmailRecoverySSEEvent): number | null | undefined {\n const data = 'data' in ev ? asRecord(ev.data) : null;\n const elapsedRaw = data?.['elapsedMs'] ?? data?.['elapsed_ms'];\n if (elapsedRaw == null) return null;\n const elapsed = Number(elapsedRaw);\n return Number.isNaN(elapsed) ? undefined : elapsed;\n}\n\nfunction deriveEmailsFromRecoveryRecords(records: RecoveryEmailRecord[]): string[] {\n if (records.length === 0) return [];\n const emails = records\n .map((r) => r.email.trim().toLowerCase())\n .filter((e) => e.length > 0 && e.includes('@'));\n return Array.from(new Set(emails));\n}\n\nfunction EmailRecoveryHeader() {\n return (\n <>\n <div className=\"w3a-email-recovery-title\">Recover Account with Email</div>\n <div className=\"w3a-email-recovery-help\">\n Send a special email to recover your account.\n This email must be sent from the designated email recovery address.\n </div>\n </>\n );\n}\n\nfunction AccountIdInputRow(props: {\n value: string;\n onChange: (value: string) => void;\n disabled: boolean;\n}) {\n const { value, onChange, disabled } = props;\n return (\n <div>\n <div className=\"w3a-input-pill w3a-email-recovery-input-pill\">\n <div className=\"w3a-input-wrap\">\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(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={disabled}\n />\n </div>\n </div>\n </div>\n );\n}\n\nfunction RecoveryEmailsSummary(props: {\n summaryLine: React.ReactNode;\n accountInfoError: string | null;\n localRecoveryEmails: string[];\n showFromWarning: boolean;\n}) {\n const { summaryLine, accountInfoError, localRecoveryEmails, showFromWarning } = props;\n return (\n <div className=\"w3a-email-recovery-summary\" aria-live=\"polite\">\n <div>{summaryLine}</div>\n {!!accountInfoError && (\n <div className=\"w3a-email-recovery-warning\">{accountInfoError}</div>\n )}\n {localRecoveryEmails.length > 0 && (\n <div className=\"w3a-email-recovery-saved-emails\" role=\"list\" aria-label=\"Recovery emails\">\n {localRecoveryEmails.map((email) => (\n <span key={email} className=\"w3a-email-recovery-email-chip w3a-email-recovery-email-chip-static\" role=\"listitem\">\n {email}\n </span>\n ))}\n </div>\n )}\n {showFromWarning && (\n <div className=\"w3a-email-recovery-from-warning\">\n {localRecoveryEmails.length === 1\n ? `Check that you are sending the recovery email from ${localRecoveryEmails[0]}.`\n : 'Check that you are sending the recovery email from your designated recovery email.'}\n </div>\n )}\n </div>\n );\n}\n\nfunction EmailRecoveryActions(props: {\n isBusy: boolean;\n pendingMailtoUrl: string | null;\n mailtoUiState: MailtoUiState;\n startDisabled: boolean;\n accountInfoLoading: boolean;\n noRecoveryEmailsConfigured: boolean;\n showRestart: boolean;\n onStart: () => void;\n onOpenDraft: (mailtoUrl: string) => void;\n onRestart: () => void;\n}) {\n const {\n isBusy,\n pendingMailtoUrl,\n mailtoUiState,\n startDisabled,\n accountInfoLoading,\n noRecoveryEmailsConfigured,\n showRestart,\n onStart,\n onOpenDraft,\n onRestart,\n } = props;\n\n return (\n <div className=\"w3a-email-recovery-actions\">\n {(!pendingMailtoUrl || !isBusy) && (\n <button\n onClick={onStart}\n className=\"w3a-link-device-btn w3a-link-device-btn-primary\"\n disabled={startDisabled}\n >\n {accountInfoLoading\n ? 'Checking recovery emails…'\n : noRecoveryEmailsConfigured\n ? 'No recovery emails configured'\n : (isBusy ? 'Working…' : 'Start Email Recovery')}\n </button>\n )}\n\n {pendingMailtoUrl && (\n <button\n type=\"button\"\n onClick={() => onOpenDraft(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 {showRestart && (\n <button\n type=\"button\"\n onClick={onRestart}\n className=\"w3a-link-device-btn\"\n disabled={isBusy}\n >\n Restart email recovery\n </button>\n )}\n </div>\n );\n}\n\nfunction EmailRecoveryStatusPanel(props: {\n errorText: string | null;\n statusText: string | null;\n pollingElapsedMs: number | null;\n explorerToast: ExplorerToast | null;\n}) {\n const { errorText, statusText, pollingElapsedMs, explorerToast } = props;\n if (!errorText && !statusText && !explorerToast) return null;\n\n return (\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}\n\nexport const EmailRecoverySlide: React.FC<EmailRecoverySlideProps> = ({\n tatchiPasskey,\n accountId,\n refreshLoginState,\n emailRecoveryOptions\n}) => {\n\n const mountedRef = React.useRef(true);\n const mailtoAttemptTimerRef = React.useRef<number | null>(null);\n const cancelRequestedRef = React.useRef(false);\n\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 type NoInferType<T> = [T][T extends any ? 0 : never];\n const safeSet = React.useCallback(<T,>(\n setter: React.Dispatch<React.SetStateAction<T>>,\n value: React.SetStateAction<NoInferType<T>>,\n ) => {\n if (!mountedRef.current) return;\n setter(value);\n }, []);\n\n const [isBusy, setIsBusy] = React.useState(false);\n const [accountIdInput, setAccountIdInput] = 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<ExplorerToast | null>(null);\n\n const lastPrefilledAccountIdRef = 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 onEvent = React.useCallback(\n (ev: EmailRecoverySSEEvent) => {\n if (cancelRequestedRef.current) return;\n safeSet(setStatusText, ev?.message || null);\n emailRecoveryOptions?.onEvent?.(ev);\n\n const txHash = extractTxHashFromEmailRecoveryEvent(ev);\n if (txHash) {\n const base = getExplorerBaseUrl(tatchiPasskey);\n safeSet(setExplorerToast, { url: getExplorerTxUrl({ base, txHash }), transactionHash: txHash });\n }\n const elapsed = extractElapsedMsFromEmailRecoveryEvent(ev);\n if (elapsed === null) safeSet(setPollingElapsedMs, null);\n else if (elapsed != null) safeSet(setPollingElapsedMs, elapsed);\n\n if (ev.phase === EmailRecoveryPhase.ERROR || ev.status === EmailRecoveryStatus.ERROR) {\n const raw = 'error' in ev ? ev.error : ev.message;\n safeSet(setErrorText, raw || 'Email recovery failed');\n safeSet(setCanRestart, false);\n }\n },\n [emailRecoveryOptions, safeSet, tatchiPasskey],\n );\n\n const showExplorerToast = React.useCallback(\n (rawAccountId: string) => {\n const normalized = (rawAccountId || '').trim();\n if (!normalized) return;\n const base = getExplorerBaseUrl(tatchiPasskey);\n safeSet(setExplorerToast, { url: getExplorerAccountUrl({ base, accountId: normalized }), accountId: normalized });\n },\n [safeSet, tatchiPasskey],\n );\n\n const showExplorerTxToast = React.useCallback(\n (txHash: string) => {\n const normalized = (txHash || '').trim();\n if (!normalized) return;\n const base = getExplorerBaseUrl(tatchiPasskey);\n safeSet(setExplorerToast, { url: getExplorerTxUrl({ base, txHash: normalized }), transactionHash: normalized });\n },\n [safeSet, 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 safeSet(setMailtoUiState, '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 safeSet(setMailtoUiState, prev => (prev === 'opening' ? 'ready' : prev));\n mailtoAttemptTimerRef.current = null;\n }, MAILTO_REENABLE_MS);\n\n launchMailto(url);\n },\n [launchMailto, safeSet],\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 safeSet(setMailtoUiState, '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, safeSet]);\n\n React.useEffect(() => {\n const normalized = (accountIdInput || '').trim();\n if (!normalized) {\n setAccountInfo(null);\n setAccountInfoError(null);\n setAccountInfoLoading(false);\n safeSet(setLocalRecoveryEmails, []);\n return;\n }\n\n let cancelled = false;\n // Show loading state immediately (don't wait for debounce).\n safeSet(setAccountInfoLoading, true);\n safeSet(setAccountInfoError, null);\n const handle = window.setTimeout(() => {\n void (async () => {\n try {\n const records = await tatchiPasskey.getRecoveryEmails(normalized);\n const resolvedEmails = deriveEmailsFromRecoveryRecords(records);\n\n if (!cancelled) {\n safeSet(setLocalRecoveryEmails, resolvedEmails);\n }\n\n const info: EmailRecoveryAccountInfo | null = records\n ? { emailsCount: Array.isArray(records) ? records.length : 0 }\n : null;\n if (cancelled) return;\n safeSet(setAccountInfo, info);\n } catch (err: unknown) {\n if (cancelled) return;\n safeSet(setAccountInfo, null);\n const msg = err instanceof Error ? err.message : '';\n safeSet(setAccountInfoError, msg || 'Failed to load email recovery settings for this account');\n safeSet(setLocalRecoveryEmails, []);\n } finally {\n if (!cancelled) safeSet(setAccountInfoLoading, false);\n }\n })();\n }, ACCOUNT_INFO_DEBOUNCE_MS);\n\n return () => {\n cancelled = true;\n window.clearTimeout(handle);\n };\n }, [accountIdInput, safeSet, tatchiPasskey]);\n\n const handleStart = React.useCallback(async () => {\n const normalizedAccountId = (accountIdInput || '').trim();\n if (!normalizedAccountId) {\n safeSet(setErrorText, 'Enter an account ID.');\n return;\n }\n\n if (accountInfoLoading) {\n safeSet(setErrorText, 'Checking recovery email settings…');\n return;\n }\n\n if (accountInfoError) {\n safeSet(setErrorText, accountInfoError);\n return;\n }\n\n if (!accountInfo) {\n safeSet(setErrorText, 'Failed to load email recovery settings for this account.');\n return;\n }\n\n if (accountInfo.emailsCount === 0) {\n safeSet(setErrorText, 'No recovery emails are configured for this account.');\n return;\n }\n\n safeSet(setIsBusy, true);\n cancelRequestedRef.current = false;\n safeSet(setErrorText, null);\n safeSet(setCanRestart, false);\n safeSet(setStatusText, null);\n safeSet(setPollingElapsedMs, null);\n safeSet(setPendingMailtoUrl, null);\n safeSet(setPendingNearPublicKey, null);\n safeSet(setMailtoUiState, 'ready');\n\n let didForwardError = false;\n try {\n const result = await tatchiPasskey.startEmailRecovery({\n accountId: normalizedAccountId,\n options: {\n onEvent,\n onError: (err: Error) => {\n if (cancelRequestedRef.current) return;\n safeSet(setErrorText, err?.message || 'Failed to start email recovery');\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n } satisfies EmailRecoveryFlowOptions,\n });\n\n safeSet(setPendingMailtoUrl, result.mailtoUrl);\n safeSet(setPendingNearPublicKey, result.nearPublicKey);\n safeSet(\n setStatusText,\n 'Recovery email draft ready. If it didn’t open automatically, click “Open recovery email draft”. Waiting for verification…'\n );\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 safeSet(setErrorText, uiError.message || 'Failed to finalize email recovery');\n safeSet(setCanRestart, uiError.canRestart);\n const txHash = getEmailRecoveryErrorTxHash(err);\n if (txHash) showExplorerTxToast(txHash);\n didForwardError = true;\n emailRecoveryOptions?.onError?.(err);\n },\n } satisfies EmailRecoveryFlowOptions,\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 safeSet(setStatusText, 'Email recovery completed. Logging you in…');\n const loginResult = await tatchiPasskey\n .loginAndCreateSession(normalizedAccountId)\n .catch(() => null);\n if (loginResult?.success) {\n const updatedSession = await tatchiPasskey.getLoginSession(normalizedAccountId).catch(() => null);\n loginOk = !!updatedSession?.login?.isLoggedIn;\n } else {\n loginOk = false;\n }\n }\n\n if (refreshLoginState) {\n await refreshLoginState(normalizedAccountId).catch(() => {});\n }\n\n safeSet(\n setStatusText,\n loginOk ? 'Email recovery completed on this device.' : 'Email recovery completed. Please log in on this device.'\n );\n safeSet(setPendingMailtoUrl, null);\n safeSet(setMailtoUiState, 'ready');\n safeSet(setPollingElapsedMs, null);\n } catch (err: unknown) {\n if (cancelRequestedRef.current) {\n safeSet(setErrorText, 'Email recovery cancelled. Please try again.');\n safeSet(setStatusText, null);\n safeSet(setPollingElapsedMs, null);\n safeSet(setPendingMailtoUrl, null);\n safeSet(setPendingNearPublicKey, null);\n safeSet(setMailtoUiState, 'ready');\n safeSet(setCanRestart, false);\n return;\n }\n const uiError = getEmailRecoveryUiError(err);\n safeSet(setErrorText, uiError.message || 'Failed to start email recovery');\n safeSet(setCanRestart, uiError.canRestart);\n const txHash = getEmailRecoveryErrorTxHash(err);\n if (txHash) showExplorerTxToast(txHash);\n if (!didForwardError && err instanceof Error) {\n emailRecoveryOptions?.onError?.(err);\n }\n } finally {\n safeSet(setIsBusy, false);\n }\n }, [\n accountIdInput,\n accountInfo,\n accountInfoError,\n accountInfoLoading,\n attemptOpenMailtoAuto,\n emailRecoveryOptions,\n onEvent,\n refreshLoginState,\n safeSet,\n showExplorerToast,\n showExplorerTxToast,\n tatchiPasskey,\n ]);\n\n const handleRestart = React.useCallback(async () => {\n const normalizedAccountId = (accountIdInput || '').trim();\n if (!normalizedAccountId) return;\n\n safeSet(setIsBusy, true);\n try {\n cancelRequestedRef.current = true;\n await tatchiPasskey\n .cancelEmailRecovery({\n accountId: normalizedAccountId,\n nearPublicKey: pendingNearPublicKey || undefined,\n })\n .catch(() => {});\n safeSet(setErrorText, null);\n safeSet(setStatusText, null);\n safeSet(setPollingElapsedMs, null);\n safeSet(setPendingMailtoUrl, null);\n safeSet(setPendingNearPublicKey, null);\n safeSet(setMailtoUiState, 'ready');\n safeSet(setCanRestart, false);\n } finally {\n cancelRequestedRef.current = false;\n safeSet(setIsBusy, false);\n }\n }, [accountIdInput, pendingNearPublicKey, safeSet, tatchiPasskey]);\n\n const summaryLine: React.ReactNode = accountInfoLoading\n ? (\n <>\n Checking if account has recovery emails configured\n <span className=\"w3a-ellipsis\" aria-hidden=\"true\">\n <span className=\"w3a-ellipsis-dot\">.</span>\n <span className=\"w3a-ellipsis-dot\">.</span>\n <span className=\"w3a-ellipsis-dot\">.</span>\n </span>\n </>\n )\n : accountInfo && !accountInfoError\n ? `Recovery emails configured: ${accountInfo.emailsCount}`\n : '\\u00A0';\n\n const noRecoveryEmailsConfigured =\n !accountInfoLoading && !accountInfoError && !!accountInfo && accountInfo.emailsCount === 0;\n const startDisabled = isBusy || accountInfoLoading || !!accountInfoError || !accountInfo || noRecoveryEmailsConfigured;\n const showFromWarning = !!accountIdInput.trim() && !noRecoveryEmailsConfigured;\n const showRestart = !!errorText && canRestart;\n\n return (\n <div className=\"w3a-email-recovery-slide\">\n <EmailRecoveryHeader />\n <AccountIdInputRow value={accountIdInput} onChange={setAccountIdInput} disabled={isBusy} />\n <RecoveryEmailsSummary\n summaryLine={summaryLine}\n accountInfoError={accountInfoError}\n localRecoveryEmails={localRecoveryEmails}\n showFromWarning={showFromWarning}\n />\n <EmailRecoveryActions\n isBusy={isBusy}\n pendingMailtoUrl={pendingMailtoUrl}\n mailtoUiState={mailtoUiState}\n startDisabled={startDisabled}\n accountInfoLoading={accountInfoLoading}\n noRecoveryEmailsConfigured={noRecoveryEmailsConfigured}\n showRestart={showRestart}\n onStart={handleStart}\n onOpenDraft={attemptOpenMailtoFromUserGesture}\n onRestart={handleRestart}\n />\n <EmailRecoveryStatusPanel\n errorText={errorText}\n statusText={statusText}\n pollingElapsedMs={pollingElapsedMs}\n explorerToast={explorerToast}\n />\n </div>\n );\n};\n\nexport default EmailRecoverySlide;\n"],"mappings":"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"}
|
package/dist/esm/react/index.js
CHANGED
|
@@ -20,10 +20,10 @@ import { QRCodeScanner } from "./components/QRCodeScanner.js";
|
|
|
20
20
|
import { AccountMenuButton, ProfileSettingsButton } from "./components/AccountMenuButton/index.js";
|
|
21
21
|
import { ShowQRCode } from "./components/ShowQRCode2.js";
|
|
22
22
|
import { PasskeyAuthMenuSkeleton, PasskeyAuthMenuSkeletonInner } from "./components/PasskeyAuthMenu/skeleton.js";
|
|
23
|
+
import { preloadPasskeyAuthMenu } from "./components/PasskeyAuthMenu/preload.js";
|
|
23
24
|
import { PasskeyAuthMenu } from "./components/PasskeyAuthMenu/shell.js";
|
|
24
25
|
import { AuthMenuMode, AuthMenuModeMap } from "./components/PasskeyAuthMenu/authMenuTypes.js";
|
|
25
26
|
import QRCodeIcon_default from "./components/QRCodeIcon.js";
|
|
26
27
|
import { PasskeyAuthMenuClient } from "./components/PasskeyAuthMenu/client.js";
|
|
27
|
-
import { preloadPasskeyAuthMenu } from "./components/PasskeyAuthMenu/preload.js";
|
|
28
28
|
|
|
29
29
|
export { AccountMenuButton, ActionPhase, ActionStatus, ActionType, AuthMenuMode, AuthMenuModeMap, DARK_TOKENS, ActionPhase as DelegateActionPhase, DeviceLinkingPhase, DeviceLinkingStatus, EmailRecoveryPhase, EmailRecoveryStatus, LIGHT_TOKENS, LoginPhase, LoginStatus, MoonIcon_default as MoonIcon, PASSKEY_MANAGER_DEFAULT_CONFIGS, PROFILE_MENU_ITEM_IDS, PasskeyAuthMenu, PasskeyAuthMenuClient, PasskeyAuthMenuSkeleton, PasskeyAuthMenuSkeletonInner, ProfileSettingsButton, QRCodeIcon_default as QRCodeIcon, QRCodeScanner, QRScanMode, RegistrationPhase, RegistrationStatus, ShowQRCode, SunIcon_default as SunIcon, SyncAccountPhase, SyncAccountStatus, TatchiContextProvider, TatchiPasskey, TatchiPasskeyProvider, Theme, TouchIcon_default as TouchIcon, TxExecutionStatus, preloadPasskeyAuthMenu, useAccountInput, useDeviceLinking, useNearClient, usePostfixPosition, useQRCamera, useQRFileUpload, useTatchi, useTheme };
|
|
@@ -298,8 +298,8 @@ var PasskeyClientDBManager = class {
|
|
|
298
298
|
await this.storeUser(userData);
|
|
299
299
|
return userData;
|
|
300
300
|
}
|
|
301
|
-
async updateUser(nearAccountId, updates) {
|
|
302
|
-
const user = await this.getUser(nearAccountId);
|
|
301
|
+
async updateUser(nearAccountId, updates, deviceNumber) {
|
|
302
|
+
const user = await this.getUser(nearAccountId, deviceNumber);
|
|
303
303
|
if (user) {
|
|
304
304
|
const updatedUser = {
|
|
305
305
|
...user,
|