@cedros/login-react 0.0.29 → 0.0.30

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.
Files changed (175) hide show
  1. package/README.md +2 -0
  2. package/dist/{AdminDepositList-CyT4VBH8.js → AdminDepositList-BUm_ZcAW.js} +1 -1
  3. package/dist/{AdminDepositList-CyT4VBH8.js.map → AdminDepositList-BUm_ZcAW.js.map} +1 -1
  4. package/dist/{AdminDepositList-b2AXtLg0.cjs → AdminDepositList-B_z6x3j5.cjs} +1 -1
  5. package/dist/{AdminDepositList-b2AXtLg0.cjs.map → AdminDepositList-B_z6x3j5.cjs.map} +1 -1
  6. package/dist/{AdminWithdrawalHistory-DL9zbu2b.cjs → AdminWithdrawalHistory-B2EY2ZmH.cjs} +1 -1
  7. package/dist/{AdminWithdrawalHistory-DL9zbu2b.cjs.map → AdminWithdrawalHistory-B2EY2ZmH.cjs.map} +1 -1
  8. package/dist/{AdminWithdrawalHistory-Cud-yuWy.js → AdminWithdrawalHistory-C76bkbjX.js} +1 -1
  9. package/dist/{AdminWithdrawalHistory-Cud-yuWy.js.map → AdminWithdrawalHistory-C76bkbjX.js.map} +1 -1
  10. package/dist/{AuthenticationSettings-D6GvSw3g.cjs → AuthenticationSettings-C-aYDXNH.cjs} +1 -1
  11. package/dist/{AuthenticationSettings-D6GvSw3g.cjs.map → AuthenticationSettings-C-aYDXNH.cjs.map} +1 -1
  12. package/dist/AuthenticationSettings-CoTic-d_.cjs +1 -0
  13. package/dist/AuthenticationSettings-CoTic-d_.cjs.map +1 -0
  14. package/dist/{AuthenticationSettings-rb4Fksw5.js → AuthenticationSettings-CsPbxwP7.js} +1 -1
  15. package/dist/{AuthenticationSettings-rb4Fksw5.js.map → AuthenticationSettings-CsPbxwP7.js.map} +1 -1
  16. package/dist/AuthenticationSettings-DIVk0OP8.js +712 -0
  17. package/dist/AuthenticationSettings-DIVk0OP8.js.map +1 -0
  18. package/dist/AutosaveStatus-DGNI4lXn.cjs +1 -0
  19. package/dist/AutosaveStatus-DGNI4lXn.cjs.map +1 -0
  20. package/dist/{AutosaveStatus-vkJxtuEw.js → AutosaveStatus-f-jw25Ay.js} +141 -93
  21. package/dist/AutosaveStatus-f-jw25Ay.js.map +1 -0
  22. package/dist/{CreditSystemSettings-ChA_lbef.cjs → CreditSystemSettings-BNkvsgsk.cjs} +1 -1
  23. package/dist/{CreditSystemSettings-ChA_lbef.cjs.map → CreditSystemSettings-BNkvsgsk.cjs.map} +1 -1
  24. package/dist/{CreditSystemSettings-DsRipb2R.js → CreditSystemSettings-C6ed3yp7.js} +1 -1
  25. package/dist/{CreditSystemSettings-DsRipb2R.js.map → CreditSystemSettings-C6ed3yp7.js.map} +1 -1
  26. package/dist/{CreditSystemSettings-r3gnGjiU.cjs → CreditSystemSettings-DM9ep1TF.cjs} +1 -1
  27. package/dist/{CreditSystemSettings-r3gnGjiU.cjs.map → CreditSystemSettings-DM9ep1TF.cjs.map} +1 -1
  28. package/dist/{CreditSystemSettings-a31pqSYS.js → CreditSystemSettings-uinhzoha.js} +1 -1
  29. package/dist/{CreditSystemSettings-a31pqSYS.js.map → CreditSystemSettings-uinhzoha.js.map} +1 -1
  30. package/dist/{DepositsSection-DD9MKUFt.js → DepositsSection-Bb4ISzvE.js} +1 -1
  31. package/dist/{DepositsSection-DD9MKUFt.js.map → DepositsSection-Bb4ISzvE.js.map} +1 -1
  32. package/dist/{DepositsSection-BkKUS4vk.cjs → DepositsSection-uQUdGeVb.cjs} +1 -1
  33. package/dist/{DepositsSection-BkKUS4vk.cjs.map → DepositsSection-uQUdGeVb.cjs.map} +1 -1
  34. package/dist/EmailRegisterForm-B_TiJkD6.cjs +1 -0
  35. package/dist/EmailRegisterForm-B_TiJkD6.cjs.map +1 -0
  36. package/dist/EmailRegisterForm-CCEuQA-w.js +773 -0
  37. package/dist/EmailRegisterForm-CCEuQA-w.js.map +1 -0
  38. package/dist/{EmailSettings-BVJ4vz0Y.js → EmailSettings-BAuQtEfM.js} +1 -1
  39. package/dist/{EmailSettings-BVJ4vz0Y.js.map → EmailSettings-BAuQtEfM.js.map} +1 -1
  40. package/dist/{EmailSettings-Dg2SAiHj.cjs → EmailSettings-BC0f1PCI.cjs} +1 -1
  41. package/dist/{EmailSettings-Dg2SAiHj.cjs.map → EmailSettings-BC0f1PCI.cjs.map} +1 -1
  42. package/dist/{EmailSettings-CM5l8qqK.cjs → EmailSettings-BF5EiPl9.cjs} +1 -1
  43. package/dist/{EmailSettings-CM5l8qqK.cjs.map → EmailSettings-BF5EiPl9.cjs.map} +1 -1
  44. package/dist/{EmailSettings-xtVl4kXD.js → EmailSettings-BKuXy8sc.js} +1 -1
  45. package/dist/{EmailSettings-xtVl4kXD.js.map → EmailSettings-BKuXy8sc.js.map} +1 -1
  46. package/dist/{EmbeddedWalletSettings-Bmx8x21f.cjs → EmbeddedWalletSettings-BRjt2PAj.cjs} +1 -1
  47. package/dist/{EmbeddedWalletSettings-Bmx8x21f.cjs.map → EmbeddedWalletSettings-BRjt2PAj.cjs.map} +1 -1
  48. package/dist/{EmbeddedWalletSettings-BuDgqv-K.js → EmbeddedWalletSettings-C27X9He2.js} +1 -1
  49. package/dist/{EmbeddedWalletSettings-BuDgqv-K.js.map → EmbeddedWalletSettings-C27X9He2.js.map} +1 -1
  50. package/dist/{EmbeddedWalletSettings-BXN9VbNJ.cjs → EmbeddedWalletSettings-CJY39UZN.cjs} +1 -1
  51. package/dist/{EmbeddedWalletSettings-BXN9VbNJ.cjs.map → EmbeddedWalletSettings-CJY39UZN.cjs.map} +1 -1
  52. package/dist/{EmbeddedWalletSettings-DY5iJhS0.js → EmbeddedWalletSettings-Dmi-EQ7W.js} +1 -1
  53. package/dist/{EmbeddedWalletSettings-DY5iJhS0.js.map → EmbeddedWalletSettings-Dmi-EQ7W.js.map} +1 -1
  54. package/dist/GoogleLoginButton-CjBO3Rf1.cjs +1 -0
  55. package/dist/GoogleLoginButton-CjBO3Rf1.cjs.map +1 -0
  56. package/dist/{GoogleLoginButton-B6qnNMZp.js → GoogleLoginButton-DEbiQngr.js} +51 -51
  57. package/dist/GoogleLoginButton-DEbiQngr.js.map +1 -0
  58. package/dist/LoadingSpinner-6vml-zwr.js.map +1 -1
  59. package/dist/LoadingSpinner-d6sSxgQN.cjs.map +1 -1
  60. package/dist/{PermissionsSection-BPbE-hNx.cjs → PermissionsSection-DEMVp7X3.cjs} +1 -1
  61. package/dist/PermissionsSection-DEMVp7X3.cjs.map +1 -0
  62. package/dist/{PermissionsSection-CighC1p6.js → PermissionsSection-DNzOL1xW.js} +27 -25
  63. package/dist/PermissionsSection-DNzOL1xW.js.map +1 -0
  64. package/dist/{ServerSettings-BAstMKHS.js → ServerSettings-BT9weFPz.js} +1 -1
  65. package/dist/{ServerSettings-BAstMKHS.js.map → ServerSettings-BT9weFPz.js.map} +1 -1
  66. package/dist/{ServerSettings-LIIP5TPz.cjs → ServerSettings-CKfiLfXi.cjs} +1 -1
  67. package/dist/{ServerSettings-LIIP5TPz.cjs.map → ServerSettings-CKfiLfXi.cjs.map} +1 -1
  68. package/dist/{ServerSettings-9Q091f3o.js → ServerSettings-CZfBdMxG.js} +1 -1
  69. package/dist/{ServerSettings-9Q091f3o.js.map → ServerSettings-CZfBdMxG.js.map} +1 -1
  70. package/dist/{ServerSettings-PH7T8JKI.cjs → ServerSettings-rHrVN8O8.cjs} +1 -1
  71. package/dist/{ServerSettings-PH7T8JKI.cjs.map → ServerSettings-rHrVN8O8.cjs.map} +1 -1
  72. package/dist/SolanaLoginButton-DAV3r4oB.cjs +1 -0
  73. package/dist/SolanaLoginButton-DAV3r4oB.cjs.map +1 -0
  74. package/dist/{mobileWalletAdapter-Cm_AUXhg.js → SolanaLoginButton-DFOoLqoj.js} +75 -74
  75. package/dist/SolanaLoginButton-DFOoLqoj.js.map +1 -0
  76. package/dist/{TeamSection-BIECkp7g.js → TeamSection-CoMXyFtz.js} +2 -2
  77. package/dist/{TeamSection-BIECkp7g.js.map → TeamSection-CoMXyFtz.js.map} +1 -1
  78. package/dist/{TeamSection-BOH9pv_E.cjs → TeamSection-DopbZClq.cjs} +1 -1
  79. package/dist/{TeamSection-BOH9pv_E.cjs.map → TeamSection-DopbZClq.cjs.map} +1 -1
  80. package/dist/{UsersSection-t-zm0jZW.js → UsersSection--PAE1XRh.js} +1 -1
  81. package/dist/{UsersSection-t-zm0jZW.js.map → UsersSection--PAE1XRh.js.map} +1 -1
  82. package/dist/{UsersSection-e6q7FHzx.cjs → UsersSection-C7aRNkK2.cjs} +1 -1
  83. package/dist/{UsersSection-e6q7FHzx.cjs.map → UsersSection-C7aRNkK2.cjs.map} +1 -1
  84. package/dist/{WebhookSettings-D0F8ESlB.js → WebhookSettings-Bgld6D_T.js} +1 -1
  85. package/dist/{WebhookSettings-D0F8ESlB.js.map → WebhookSettings-Bgld6D_T.js.map} +1 -1
  86. package/dist/{WebhookSettings-2p9abGm5.cjs → WebhookSettings-DXjnq-c7.cjs} +1 -1
  87. package/dist/{WebhookSettings-2p9abGm5.cjs.map → WebhookSettings-DXjnq-c7.cjs.map} +1 -1
  88. package/dist/{WebhookSettings-CdFM7_V-.cjs → WebhookSettings-DnLk97Mr.cjs} +1 -1
  89. package/dist/{WebhookSettings-CdFM7_V-.cjs.map → WebhookSettings-DnLk97Mr.cjs.map} +1 -1
  90. package/dist/{WebhookSettings-CXMBju7N.js → WebhookSettings-ufiGTmbG.js} +1 -1
  91. package/dist/{WebhookSettings-CXMBju7N.js.map → WebhookSettings-ufiGTmbG.js.map} +1 -1
  92. package/dist/{WithdrawalsSection-yRDTVFsb.js → WithdrawalsSection-BN-FjTEV.js} +1 -1
  93. package/dist/{WithdrawalsSection-yRDTVFsb.js.map → WithdrawalsSection-BN-FjTEV.js.map} +1 -1
  94. package/dist/{WithdrawalsSection-sljIyeaz.cjs → WithdrawalsSection-BhuCwFat.cjs} +1 -1
  95. package/dist/{WithdrawalsSection-sljIyeaz.cjs.map → WithdrawalsSection-BhuCwFat.cjs.map} +1 -1
  96. package/dist/admin-only.cjs +1 -1
  97. package/dist/admin-only.js +1 -1
  98. package/dist/email-only.cjs +1 -1
  99. package/dist/email-only.d.ts +17 -1
  100. package/dist/email-only.js +3 -3
  101. package/dist/google-only.cjs +1 -1
  102. package/dist/google-only.d.ts +16 -0
  103. package/dist/google-only.js +3 -3
  104. package/dist/index.cjs +12 -12
  105. package/dist/index.cjs.map +1 -1
  106. package/dist/index.d.ts +246 -10
  107. package/dist/index.js +3384 -2508
  108. package/dist/index.js.map +1 -1
  109. package/dist/login-react.css +1 -1
  110. package/dist/{plugin-DbkijwEV.js → plugin-BbExid4E.js} +1 -1
  111. package/dist/{plugin-DbkijwEV.js.map → plugin-BbExid4E.js.map} +1 -1
  112. package/dist/{plugin-PU2vAozn.cjs → plugin-Xca67fp7.cjs} +1 -1
  113. package/dist/{plugin-PU2vAozn.cjs.map → plugin-Xca67fp7.cjs.map} +1 -1
  114. package/dist/{shamir-CiBczzDN.cjs → shamir-DBpHm7WN.cjs} +1 -1
  115. package/dist/{shamir-CiBczzDN.cjs.map → shamir-DBpHm7WN.cjs.map} +1 -1
  116. package/dist/{shamir-OAB2zD9Y.js → shamir-R8ddesFt.js} +1 -1
  117. package/dist/{shamir-OAB2zD9Y.js.map → shamir-R8ddesFt.js.map} +1 -1
  118. package/dist/{silentWalletEnroll-FqXS7Rvh.js → silentWalletEnroll-Dp1GTeNr.js} +3 -3
  119. package/dist/{silentWalletEnroll-FqXS7Rvh.js.map → silentWalletEnroll-Dp1GTeNr.js.map} +1 -1
  120. package/dist/{silentWalletEnroll-wnkcB9HP.cjs → silentWalletEnroll-HPvsbd2J.cjs} +1 -1
  121. package/dist/{silentWalletEnroll-wnkcB9HP.cjs.map → silentWalletEnroll-HPvsbd2J.cjs.map} +1 -1
  122. package/dist/solana-only.cjs +1 -1
  123. package/dist/solana-only.d.ts +16 -0
  124. package/dist/solana-only.js +3 -3
  125. package/dist/{useAdminDeposits-BTSyeAfg.js → useAdminDeposits-C76B2Q_8.js} +1 -1
  126. package/dist/{useAdminDeposits-BTSyeAfg.js.map → useAdminDeposits-C76B2Q_8.js.map} +1 -1
  127. package/dist/{useAdminDeposits-BkkCwHWp.cjs → useAdminDeposits-CpLd68oP.cjs} +1 -1
  128. package/dist/{useAdminDeposits-BkkCwHWp.cjs.map → useAdminDeposits-CpLd68oP.cjs.map} +1 -1
  129. package/dist/{useAuth-m5Hf89v8.js → useAuth-CVLv2oKA.js} +547 -545
  130. package/dist/useAuth-CVLv2oKA.js.map +1 -0
  131. package/dist/useAuth-XZaciuLg.cjs +1 -0
  132. package/dist/useAuth-XZaciuLg.cjs.map +1 -0
  133. package/dist/useCedrosLogin-CFfID-0i.js +228 -0
  134. package/dist/useCedrosLogin-CFfID-0i.js.map +1 -0
  135. package/dist/useCedrosLogin-DtJorrE7.cjs +1 -0
  136. package/dist/useCedrosLogin-DtJorrE7.cjs.map +1 -0
  137. package/dist/{useOrgs-C3pzMA9h.js → useOrgs-C90KT9KP.js} +1 -1
  138. package/dist/{useOrgs-C3pzMA9h.js.map → useOrgs-C90KT9KP.js.map} +1 -1
  139. package/dist/{useOrgs-DDVRCaVi.cjs → useOrgs-CNqfn-fk.cjs} +1 -1
  140. package/dist/{useOrgs-DDVRCaVi.cjs.map → useOrgs-CNqfn-fk.cjs.map} +1 -1
  141. package/dist/{useSystemSettings-DRrreszl.cjs → useSystemSettings-B2jY51ob.cjs} +1 -1
  142. package/dist/{useSystemSettings-DRrreszl.cjs.map → useSystemSettings-B2jY51ob.cjs.map} +1 -1
  143. package/dist/{useSystemSettings-DBlAMjFi.js → useSystemSettings-rgskaDqP.js} +1 -1
  144. package/dist/{useSystemSettings-DBlAMjFi.js.map → useSystemSettings-rgskaDqP.js.map} +1 -1
  145. package/dist/{useUsersStatsSummary-NjEFvWuz.js → useUsersStatsSummary-5DJwzntC.js} +2 -2
  146. package/dist/{useUsersStatsSummary-NjEFvWuz.js.map → useUsersStatsSummary-5DJwzntC.js.map} +1 -1
  147. package/dist/{useUsersStatsSummary-8qY7iP4G.cjs → useUsersStatsSummary-DgKaUIfs.cjs} +1 -1
  148. package/dist/{useUsersStatsSummary-8qY7iP4G.cjs.map → useUsersStatsSummary-DgKaUIfs.cjs.map} +1 -1
  149. package/package.json +1 -1
  150. package/dist/AuthenticationSettings-C9f5MKgj.cjs +0 -1
  151. package/dist/AuthenticationSettings-C9f5MKgj.cjs.map +0 -1
  152. package/dist/AuthenticationSettings-DC64o_J6.js +0 -525
  153. package/dist/AuthenticationSettings-DC64o_J6.js.map +0 -1
  154. package/dist/AutosaveStatus-BFj5GIab.cjs +0 -1
  155. package/dist/AutosaveStatus-BFj5GIab.cjs.map +0 -1
  156. package/dist/AutosaveStatus-vkJxtuEw.js.map +0 -1
  157. package/dist/EmailRegisterForm-B1DB-bqe.cjs +0 -1
  158. package/dist/EmailRegisterForm-B1DB-bqe.cjs.map +0 -1
  159. package/dist/EmailRegisterForm-BAX_uBIt.js +0 -927
  160. package/dist/EmailRegisterForm-BAX_uBIt.js.map +0 -1
  161. package/dist/GoogleLoginButton-B6qnNMZp.js.map +0 -1
  162. package/dist/GoogleLoginButton-D7CoMXLq.cjs +0 -1
  163. package/dist/GoogleLoginButton-D7CoMXLq.cjs.map +0 -1
  164. package/dist/PermissionsSection-BPbE-hNx.cjs.map +0 -1
  165. package/dist/PermissionsSection-CighC1p6.js.map +0 -1
  166. package/dist/mobileWalletAdapter-B6ELaZp1.cjs +0 -1
  167. package/dist/mobileWalletAdapter-B6ELaZp1.cjs.map +0 -1
  168. package/dist/mobileWalletAdapter-Cm_AUXhg.js.map +0 -1
  169. package/dist/useAuth-X6Ds6WW4.cjs +0 -1
  170. package/dist/useAuth-X6Ds6WW4.cjs.map +0 -1
  171. package/dist/useAuth-m5Hf89v8.js.map +0 -1
  172. package/dist/useCedrosLogin-C9MrcZvh.cjs +0 -1
  173. package/dist/useCedrosLogin-C9MrcZvh.cjs.map +0 -1
  174. package/dist/useCedrosLogin-_94MmGGq.js +0 -216
  175. package/dist/useCedrosLogin-_94MmGGq.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"AutosaveStatus-vkJxtuEw.js","sources":["../src/components/admin/settings/settingsMetadata.ts","../src/components/admin/settings/settingsInputs.tsx","../src/hooks/useSettingsAutosave.ts","../src/components/admin/settings/AutosaveStatus.tsx"],"sourcesContent":["/**\n * Settings metadata - rich descriptions and input configuration\n */\nimport type { SettingMeta } from '../../../types';\n\n// =============================================================================\n// DURATION UTILITIES\n// =============================================================================\n\nexport interface DurationParts {\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n}\n\nexport function secondsToDuration(totalSeconds: number): DurationParts {\n const days = Math.floor(totalSeconds / 86400);\n const hours = Math.floor((totalSeconds % 86400) / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n return { days, hours, minutes, seconds };\n}\n\nexport function formatDuration(totalSeconds: number): string {\n const { days, hours, minutes } = secondsToDuration(totalSeconds);\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (hours > 0) parts.push(`${hours}h`);\n if (minutes > 0) parts.push(`${minutes}m`);\n if (parts.length === 0) parts.push(`${totalSeconds}s`);\n return parts.join(' ');\n}\n\n// =============================================================================\n// SETTING METADATA - Rich descriptions and input configuration\n// =============================================================================\n\nexport const SETTING_METADATA: Record<string, SettingMeta> = {\n // ============= Authentication Providers =============\n // Email auth\n auth_email_enabled: {\n key: 'auth_email_enabled',\n label: 'Enable Email Authentication',\n description: 'Allow users to sign up and log in with email/password.',\n inputType: 'boolean',\n },\n auth_email_require_verification: {\n key: 'auth_email_require_verification',\n label: 'Require Email Verification',\n description: 'Users must verify their email address before they can log in.',\n inputType: 'boolean',\n },\n auth_email_block_disposable: {\n key: 'auth_email_block_disposable',\n label: 'Block Disposable Emails',\n description: 'Reject registrations from known disposable email providers.',\n inputType: 'boolean',\n },\n\n // Google OAuth\n auth_google_enabled: {\n key: 'auth_google_enabled',\n label: 'Enable Google Sign-In',\n description:\n 'Allow users to authenticate with their Google account. Configure at <a href=\"https://console.cloud.google.com/apis/credentials\" target=\"_blank\" rel=\"noopener\">Google Cloud Console &gt; Credentials</a>.',\n inputType: 'boolean',\n },\n auth_google_client_id: {\n key: 'auth_google_client_id',\n label: 'Google Client ID',\n description:\n 'OAuth 2.0 client ID from Google Cloud Console. Create a Web application credential and add your frontend URL to Authorized JavaScript origins.',\n inputType: 'text',\n },\n // Apple OAuth\n auth_apple_enabled: {\n key: 'auth_apple_enabled',\n label: 'Enable Sign in with Apple',\n description:\n 'Allow users to authenticate with their Apple ID. Configure at <a href=\"https://developer.apple.com/account/resources/identifiers\" target=\"_blank\" rel=\"noopener\">Apple Developer &gt; Identifiers</a>.',\n inputType: 'boolean',\n },\n auth_apple_client_id: {\n key: 'auth_apple_client_id',\n label: 'Apple Services ID',\n description:\n 'Your Client ID (e.g. com.yourdomain.service). Create at Identifiers &gt; Services IDs, then enable Sign in with Apple and add your frontend URL as a Return URL (e.g. https://yourdomain.com).',\n inputType: 'text',\n placeholder: 'com.yourdomain.service',\n },\n auth_apple_team_id: {\n key: 'auth_apple_team_id',\n label: 'Apple Team ID',\n description:\n 'Identifies your developer account. Found at the top-right of <a href=\"https://developer.apple.com/account\" target=\"_blank\" rel=\"noopener\">Apple Developer</a>.',\n inputType: 'text',\n },\n\n // Solana auth\n auth_solana_enabled: {\n key: 'auth_solana_enabled',\n label: 'Enable Solana Wallet Auth',\n description: 'Allow users to authenticate by signing with their Solana wallet.',\n inputType: 'boolean',\n },\n auth_solana_challenge_expiry: {\n key: 'auth_solana_challenge_expiry',\n label: 'Challenge Expiry',\n description: 'How long a wallet signature challenge is valid.',\n inputType: 'duration',\n min: 60,\n presets: [\n { label: '1 minute', value: '60' },\n { label: '5 minutes', value: '300' },\n { label: '10 minutes', value: '600' },\n ],\n },\n\n // WebAuthn/Passkeys\n auth_webauthn_enabled: {\n key: 'auth_webauthn_enabled',\n label: 'Enable WebAuthn/Passkeys',\n description: 'Allow passwordless authentication with FIDO2/WebAuthn credentials.',\n inputType: 'boolean',\n },\n auth_webauthn_rp_id: {\n key: 'auth_webauthn_rp_id',\n label: 'Relying Party ID',\n description: 'Usually your domain (e.g., example.com). Passkeys are bound to this.',\n inputType: 'text',\n },\n auth_webauthn_rp_name: {\n key: 'auth_webauthn_rp_name',\n label: 'Relying Party Name',\n description: 'Display name shown to users during passkey registration.',\n inputType: 'text',\n },\n auth_webauthn_rp_origin: {\n key: 'auth_webauthn_rp_origin',\n label: 'Allowed Origins',\n description: 'Comma-separated origins allowed for WebAuthn (e.g., https://example.com).',\n inputType: 'text',\n },\n\n // Instant Link (Magic Link)\n auth_instantlink_enabled: {\n key: 'auth_instantlink_enabled',\n label: 'Enable Instant Link',\n description:\n 'When enabled, \"Forgot your password?\" on the sign-in form sends a one-time sign-in link instead of a password reset. This replaces the password reset flow — it is not a separate login button.',\n inputType: 'boolean',\n },\n auth_instantlink_expiry: {\n key: 'auth_instantlink_expiry',\n label: 'Link Expiry',\n description: 'How long the magic link remains valid.',\n inputType: 'duration',\n min: 60,\n presets: [\n { label: '5 minutes', value: '300' },\n { label: '15 minutes', value: '900' },\n { label: '30 minutes', value: '1800' },\n { label: '1 hour', value: '3600' },\n ],\n },\n auth_instantlink_rate_limit: {\n key: 'auth_instantlink_rate_limit',\n label: 'Rate Limit',\n description: 'Maximum instant link requests per email per hour.',\n inputType: 'select',\n presets: [\n { label: '3 per hour', value: '3' },\n { label: '5 per hour', value: '5' },\n { label: '10 per hour', value: '10' },\n ],\n },\n\n // ============= Feature Flags =============\n // Order: organizations, enterprise SSO, 2fa, embedded wallets, credit system\n feature_organizations: {\n key: 'feature_organizations',\n label: 'Organizations',\n description: 'Enable multi-user organizations with role-based access.',\n inputType: 'boolean',\n },\n feature_sso: {\n key: 'feature_sso',\n label: 'Enterprise SSO',\n description: 'Enable SAML/OIDC single sign-on for enterprise customers.',\n inputType: 'boolean',\n },\n feature_mfa: {\n key: 'feature_mfa',\n label: 'Two-Factor Authentication',\n description: 'Allow users to enable TOTP-based two-factor authentication.',\n inputType: 'boolean',\n },\n feature_wallet_signing: {\n key: 'feature_wallet_signing',\n label: 'Enable Embedded Wallet',\n description: 'Enable the embedded wallet for transaction signing.',\n inputType: 'boolean',\n },\n wallet_recovery_mode: {\n key: 'wallet_recovery_mode',\n label: 'Recovery Mode',\n description:\n 'Controls whether users can recover their embedded wallet seed. <b>Share C Only</b> lets users export a single key share (cannot reconstruct the full seed). <b>Full Seed</b> lets users export the complete seed phrase. <b>No Recovery</b> prevents any seed export — required when Private Deposits are enabled, because recoverable seeds would let users front-run privacy withdrawals.',\n inputType: 'select',\n presets: [\n { label: 'Share C Only (Recommended)', value: 'share_c_only' },\n { label: 'Full Seed Phrase', value: 'full_seed' },\n { label: 'No Recovery (Required for Private Deposits)', value: 'none' },\n ],\n },\n feature_credits: {\n key: 'feature_credits',\n label: 'Credit System',\n description:\n 'Enable the deposits and credits system. Users can deposit tokens to receive platform credits.',\n inputType: 'boolean',\n },\n feature_user_withdrawals: {\n key: 'feature_user_withdrawals',\n label: 'User Withdrawals',\n description:\n 'Allow users to initiate withdrawals from their embedded wallet to external addresses. This is separate from the automated privacy withdrawal worker, which moves funds from the privacy pool to the treasury.',\n inputType: 'boolean',\n },\n\n // ============= Security Settings =============\n security_cors_origins: {\n key: 'security_cors_origins',\n label: 'CORS Origins',\n description:\n 'Allowed origins for cross-origin requests (comma-separated). Empty = same origin only.',\n inputType: 'text',\n },\n security_cookie_domain: {\n key: 'security_cookie_domain',\n label: 'Cookie Domain',\n description: 'Domain for auth cookies. Empty uses the request origin.',\n inputType: 'text',\n },\n security_cookie_secure: {\n key: 'security_cookie_secure',\n label: 'Secure Cookies',\n description: 'Require HTTPS for cookies. Disable only for local development.',\n inputType: 'boolean',\n },\n security_cookie_same_site: {\n key: 'security_cookie_same_site',\n label: 'Cookie SameSite',\n description: 'SameSite policy for cookies. Use \"none\" only if needed for cross-site embeds.',\n inputType: 'select',\n presets: [\n { label: 'Strict', value: 'strict' },\n { label: 'Lax (Recommended)', value: 'lax' },\n { label: 'None (cross-site)', value: 'none' },\n ],\n },\n security_session_timeout: {\n key: 'security_session_timeout',\n label: 'Session Timeout',\n description: 'How long sessions remain valid before requiring re-authentication.',\n inputType: 'duration',\n min: 300,\n presets: [\n { label: '1 hour', value: '3600' },\n { label: '24 hours', value: '86400' },\n { label: '7 days', value: '604800' },\n { label: '30 days', value: '2592000' },\n ],\n },\n security_jwt_issuer: {\n key: 'security_jwt_issuer',\n label: 'JWT Issuer',\n description: 'Issuer claim for JWTs. Empty uses the server URL.',\n inputType: 'text',\n },\n security_jwt_audience: {\n key: 'security_jwt_audience',\n label: 'JWT Audience',\n description: 'Audience claim for JWTs. Empty uses default.',\n inputType: 'text',\n },\n\n // ============= Email/SMTP Settings =============\n email_provider: {\n key: 'email_provider',\n label: 'Email Provider',\n description:\n 'Select a provider to auto-configure SMTP host, port, and TLS. Choose Custom SMTP to enter settings manually.',\n inputType: 'select',\n presets: [\n { label: 'Mailgun', value: 'mailgun' },\n { label: 'SendGrid', value: 'sendgrid' },\n { label: 'Postmark', value: 'postmark' },\n { label: 'AWS SES', value: 'ses' },\n { label: 'Resend', value: 'resend' },\n { label: 'Custom SMTP', value: 'custom' },\n ],\n },\n email_smtp_host: {\n key: 'email_smtp_host',\n label: 'SMTP Host',\n description:\n 'SMTP server hostname. Auto-filled when selecting a provider above.',\n inputType: 'text',\n placeholder: 'smtp.example.com',\n },\n email_smtp_port: {\n key: 'email_smtp_port',\n label: 'SMTP Port',\n description: 'SMTP server port. Most providers use 587 (TLS).',\n inputType: 'select',\n presets: [\n { label: '587 (TLS)', value: '587' },\n { label: '465 (SSL)', value: '465' },\n { label: '25 (Plain)', value: '25' },\n ],\n },\n email_smtp_user: {\n key: 'email_smtp_user',\n label: 'SMTP Username',\n description:\n 'Username for SMTP authentication. For SendGrid use \"apikey\", for Postmark use your server API token, for Mailgun use your full Mailgun SMTP login.',\n inputType: 'text',\n },\n email_smtp_password: {\n key: 'email_smtp_password',\n label: 'API Key',\n description:\n 'API key or password for your email provider. For SendGrid this is your API key, for Postmark your server API token, for Mailgun your SMTP password.',\n inputType: 'secret',\n },\n email_smtp_tls: {\n key: 'email_smtp_tls',\n label: 'Use TLS',\n description: 'Enable TLS encryption for SMTP connections. Required by most providers.',\n inputType: 'boolean',\n },\n email_from_address: {\n key: 'email_from_address',\n label: 'From Address',\n description:\n 'Sender email address for verification, password reset, and instant link emails. Must be verified with your provider.',\n inputType: 'text',\n placeholder: 'noreply@yourdomain.com',\n },\n email_from_name: {\n key: 'email_from_name',\n label: 'From Name',\n description: 'Display name shown in the \"From\" field of outbound emails.',\n inputType: 'text',\n placeholder: 'My App',\n },\n\n // ============= Webhook Settings =============\n webhook_enabled: {\n key: 'webhook_enabled',\n label: 'Enable Webhooks',\n description: 'Send notifications to a Discord or Slack webhook URL.',\n inputType: 'boolean',\n },\n webhook_url: {\n key: 'webhook_url',\n label: 'Webhook URL',\n description: 'Discord or Slack webhook URL to receive notifications.',\n inputType: 'text',\n placeholder: 'https://discord.com/api/webhooks/...',\n },\n webhook_notify_registrations: {\n key: 'webhook_notify_registrations',\n label: 'New Registrations',\n description: 'Notify when a new user registers.',\n inputType: 'boolean',\n },\n webhook_notify_signins: {\n key: 'webhook_notify_signins',\n label: 'Sign-Ins',\n description: 'Notify when a user signs in.',\n inputType: 'boolean',\n },\n webhook_notify_deposits: {\n key: 'webhook_notify_deposits',\n label: 'Deposits',\n description: 'Notify when a user makes a deposit.',\n inputType: 'boolean',\n },\n\n // ============= Server Settings =============\n server_frontend_url: {\n key: 'server_frontend_url',\n label: 'Frontend URL',\n description: 'URL of your frontend app (for redirects and email links).',\n inputType: 'text',\n },\n server_base_path: {\n key: 'server_base_path',\n label: 'Base Path',\n description: 'Base path for auth endpoints (e.g., /auth).',\n inputType: 'text',\n },\n server_trust_proxy: {\n key: 'server_trust_proxy',\n label: 'Trust Proxy',\n description: 'Trust X-Forwarded-For headers. Enable if behind a reverse proxy.',\n inputType: 'boolean',\n },\n feature_cedros_pay: {\n key: 'feature_cedros_pay',\n label: 'Cedros Pay Integration',\n description:\n 'Enable Cedros Pay integration. When enabled, shows the Integrations tab with API key configuration. Not needed for co-located deployments using JWT/JWKS inter-service auth.',\n inputType: 'boolean',\n },\n server_cedros_pay_api_key: {\n key: 'server_cedros_pay_api_key',\n label: 'Cedros Pay API Key',\n description:\n 'API key for Cedros Pay to authenticate with this server. Copy this into your Cedros Pay settings.',\n inputType: 'secret',\n },\n jupiter_api_key: {\n key: 'jupiter_api_key',\n label: 'Jupiter API Key',\n description:\n 'API key for Jupiter Ultra API (gasless swaps). Get a free key at <a href=\"https://portal.jup.ag\" target=\"_blank\" rel=\"noopener\">portal.jup.ag</a>.',\n inputType: 'secret',\n },\n server_metrics_api_key: {\n key: 'server_metrics_api_key',\n label: 'Metrics API Key',\n description:\n 'API key for Prometheus/Grafana to scrape the /metrics endpoint. Use with Authorization: Bearer header.',\n inputType: 'secret',\n },\n server_log_level: {\n key: 'server_log_level',\n label: 'Log Level',\n description: 'Minimum severity level for log output. Lower levels are more verbose.',\n inputType: 'select',\n presets: [\n { label: 'Trace (most verbose)', value: 'trace' },\n { label: 'Debug', value: 'debug' },\n { label: 'Info', value: 'info' },\n { label: 'Warn', value: 'warn' },\n { label: 'Error (least verbose)', value: 'error' },\n ],\n },\n server_log_format: {\n key: 'server_log_format',\n label: 'Log Format',\n description: 'Output format for log messages.',\n inputType: 'select',\n presets: [\n { label: 'JSON (structured)', value: 'json' },\n { label: 'Pretty (human-readable)', value: 'pretty' },\n ],\n },\n server_environment: {\n key: 'server_environment',\n label: 'Environment',\n description: 'Deployment environment. Affects default behaviors and log verbosity.',\n inputType: 'select',\n presets: [\n { label: 'Development', value: 'development' },\n { label: 'Staging', value: 'staging' },\n { label: 'Production', value: 'production' },\n ],\n },\n\n // ============= Privacy Settings (existing) =============\n privacy_period_secs: {\n key: 'privacy_period_secs',\n label: 'Privacy Period',\n description:\n 'How long deposits are held before withdrawal to provide timing privacy. Longer periods provide better privacy but delay user access to funds.',\n inputType: 'duration',\n min: 0,\n presets: [\n { label: 'Disabled', value: '0' },\n { label: '1 hour', value: '3600' },\n { label: '6 hours', value: '21600' },\n { label: '24 hours', value: '86400' },\n { label: '7 days', value: '604800' },\n { label: '14 days', value: '1209600' },\n { label: '30 days', value: '2592000' },\n ],\n warningThreshold: {\n below: 3600,\n message: 'Very short privacy periods may not provide adequate timing protection.',\n },\n },\n\n // Treasury settings\n treasury_wallet_address: {\n key: 'treasury_wallet_address',\n label: 'Treasury Wallet Address',\n description:\n 'Solana wallet address where funds are sent. Used for privacy cash withdrawals, micro payment batches, and direct payments.',\n inputType: 'text',\n placeholder: 'e.g., 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU',\n },\n\n // Withdrawal worker settings\n withdrawal_poll_interval_secs: {\n key: 'withdrawal_poll_interval_secs',\n label: 'Worker Poll Interval',\n description:\n 'How often the withdrawal worker checks for deposits ready to process. Lower values process faster but increase server load.',\n inputType: 'duration',\n min: 60,\n presets: [\n { label: '1 minute', value: '60' },\n { label: '5 minutes', value: '300' },\n { label: '15 minutes', value: '900' },\n { label: '1 hour', value: '3600' },\n { label: '6 hours', value: '21600' },\n ],\n warningThreshold: {\n below: 60,\n message: 'Polling more than once per minute may cause excessive load.',\n },\n },\n withdrawal_batch_size: {\n key: 'withdrawal_batch_size',\n label: 'Batch Size',\n description:\n 'Maximum number of withdrawals to process in a single batch. Higher values improve throughput but may cause timeouts.',\n inputType: 'select',\n min: 1,\n max: 100,\n presets: [\n { label: '1 (Sequential)', value: '1' },\n { label: '5', value: '5' },\n { label: '10 (Recommended)', value: '10' },\n { label: '25', value: '25' },\n { label: '50', value: '50' },\n { label: '100 (Max)', value: '100' },\n ],\n },\n withdrawal_timeout_secs: {\n key: 'withdrawal_timeout_secs',\n label: 'Transaction Timeout',\n description:\n 'How long to wait for a withdrawal transaction to confirm before considering it failed.',\n inputType: 'duration',\n min: 30,\n presets: [\n { label: '30 seconds', value: '30' },\n { label: '1 minute', value: '60' },\n { label: '2 minutes', value: '120' },\n { label: '5 minutes', value: '300' },\n ],\n warningThreshold: {\n below: 30,\n message: 'Very short timeouts may cause premature failure on slow networks.',\n },\n },\n withdrawal_max_retries: {\n key: 'withdrawal_max_retries',\n label: 'Max Retries',\n description:\n 'Number of times to retry a failed withdrawal before marking it as permanently failed.',\n inputType: 'select',\n min: 0,\n max: 10,\n presets: [\n { label: '0 (No retries)', value: '0' },\n { label: '1', value: '1' },\n { label: '3 (Recommended)', value: '3' },\n { label: '5', value: '5' },\n { label: '10', value: '10' },\n ],\n },\n withdrawal_percentage: {\n key: 'withdrawal_percentage',\n label: 'Withdrawal Percentage',\n description:\n 'Percentage of ready funds to withdraw each cycle. Lower values spread withdrawals over time for better privacy.',\n inputType: 'percentage',\n min: 1,\n max: 100,\n step: 5,\n presets: [\n { label: '25%', value: '25' },\n { label: '50%', value: '50' },\n { label: '75%', value: '75' },\n { label: '100% (All at once)', value: '100' },\n ],\n warningThreshold: {\n above: 75,\n message:\n 'High percentages may reduce timing privacy by processing most withdrawals together.',\n },\n },\n partial_withdrawal_count: {\n key: 'partial_withdrawal_count',\n label: 'Partial Withdrawals',\n description:\n 'Maximum partial withdrawals per batch. Partial withdrawals add noise to timing analysis. Set to 0 to disable.',\n inputType: 'select',\n min: 0,\n presets: [\n { label: 'Disabled', value: '0' },\n { label: '1', value: '1' },\n { label: '3', value: '3' },\n { label: '5', value: '5' },\n { label: '10', value: '10' },\n ],\n },\n partial_withdrawal_min_lamports: {\n key: 'partial_withdrawal_min_lamports',\n label: 'Min Balance for Partial',\n description:\n 'Minimum account balance (in lamports) required before partial withdrawals are considered. 1 SOL = 1,000,000,000 lamports.',\n inputType: 'select',\n min: 0,\n presets: [\n { label: '0.1 SOL', value: '100000000' },\n { label: '0.5 SOL', value: '500000000' },\n { label: '1 SOL', value: '1000000000' },\n { label: '5 SOL', value: '5000000000' },\n { label: '10 SOL', value: '10000000000' },\n ],\n },\n\n // Rate limit settings\n rate_limit_auth: {\n key: 'rate_limit_auth',\n label: 'Auth Request Limit',\n description:\n 'Maximum authentication attempts (login, register, password reset) per IP per window. Protects against brute force attacks.',\n inputType: 'select',\n min: 1,\n unit: 'requests',\n presets: [\n { label: '5 (Strict)', value: '5' },\n { label: '10 (Recommended)', value: '10' },\n { label: '20', value: '20' },\n { label: '50 (Permissive)', value: '50' },\n ],\n warningThreshold: {\n above: 20,\n message: 'High auth limits may allow brute force attempts.',\n },\n },\n rate_limit_general: {\n key: 'rate_limit_general',\n label: 'General Request Limit',\n description: 'Maximum general API requests per IP per window. Affects all non-auth endpoints.',\n inputType: 'select',\n min: 1,\n unit: 'requests',\n presets: [\n { label: '30', value: '30' },\n { label: '60 (Recommended)', value: '60' },\n { label: '120', value: '120' },\n { label: '300', value: '300' },\n ],\n },\n rate_limit_credit: {\n key: 'rate_limit_credit',\n label: 'Credit Request Limit',\n description:\n 'Maximum credit/balance check requests per IP per window. Higher for apps that poll balance frequently.',\n inputType: 'select',\n min: 1,\n unit: 'requests',\n presets: [\n { label: '10', value: '10' },\n { label: '30 (Recommended)', value: '30' },\n { label: '60', value: '60' },\n { label: '120', value: '120' },\n ],\n },\n rate_limit_window: {\n key: 'rate_limit_window',\n label: 'Rate Limit Window',\n description:\n 'Time window for rate limiting. All limits above are \"per window\". Shorter windows are stricter.',\n inputType: 'duration',\n min: 1,\n presets: [\n { label: '30 seconds', value: '30' },\n { label: '1 minute', value: '60' },\n { label: '5 minutes', value: '300' },\n { label: '15 minutes', value: '900' },\n ],\n },\n\n // ============= Deposit General Settings =============\n solana_rpc_url: {\n key: 'solana_rpc_url',\n label: 'Solana RPC URL',\n description:\n 'Get a fast RPC endpoint from <a href=\"https://helius.dev\" target=\"_blank\" rel=\"noopener\">Helius</a> or <a href=\"https://quicknode.com\" target=\"_blank\" rel=\"noopener\">QuickNode</a>.',\n inputType: 'text',\n placeholder: 'https://api.mainnet-beta.solana.com',\n },\n solana_network: {\n key: 'solana_network',\n label: 'Solana Network',\n description: 'The Solana network to use for deposits and withdrawals.',\n inputType: 'select',\n presets: [\n { label: 'Mainnet', value: 'mainnet-beta' },\n { label: 'Devnet', value: 'devnet' },\n ],\n },\n deposit_privacy_enabled: {\n key: 'deposit_privacy_enabled',\n label: 'Enable Private Deposits',\n description:\n 'When enabled, deposits are held for a privacy period before withdrawal. Provides timing privacy but delays fund availability.',\n inputType: 'boolean',\n },\n deposit_company_token: {\n key: 'deposit_company_token',\n label: 'Platform Token',\n description:\n 'The token that represents platform credits. Deposits are converted to this token. Common choices: USDC, SOL.',\n inputType: 'select',\n presets: [\n { label: 'USDC', value: 'USDC' },\n { label: 'USDT', value: 'USDT' },\n { label: 'SOL', value: 'SOL' },\n { label: 'EURC', value: 'EURC' },\n ],\n },\n deposit_micro_enabled: {\n key: 'deposit_micro_enabled',\n label: 'SOL Micro Payments',\n description: 'Allow small SOL deposits (under $10) that are batched together for efficiency.',\n inputType: 'boolean',\n },\n deposit_gasless_swap_enabled: {\n key: 'deposit_gasless_swap_enabled',\n label: 'Gasless Swap Payments',\n description: 'Allow deposits via Jupiter swaps.',\n inputType: 'boolean',\n },\n deposit_min_usd: {\n key: 'deposit_min_usd',\n label: 'Minimum Deposit',\n description: 'Minimum deposit amount in USD equivalent.',\n inputType: 'select',\n unit: 'USD',\n presets: [\n { label: '$1', value: '1' },\n { label: '$5', value: '5' },\n { label: '$10', value: '10' },\n { label: '$25', value: '25' },\n ],\n },\n deposit_max_usd: {\n key: 'deposit_max_usd',\n label: 'Maximum Deposit',\n description:\n 'Maximum deposit amount per transaction in USD equivalent. Set to 0 for unlimited.',\n inputType: 'select',\n unit: 'USD',\n presets: [\n { label: 'Unlimited', value: '0' },\n { label: '$1,000', value: '1000' },\n { label: '$10,000', value: '10000' },\n { label: '$100,000', value: '100000' },\n ],\n },\n\n // Deposit component settings\n deposit_show_explainer: {\n key: 'deposit_show_explainer',\n label: 'Show Explainer Screen',\n description: 'Show the introductory explainer screen at the start of the deposit flow.',\n inputType: 'boolean',\n },\n\n // Deposit token settings\n deposit_quick_action_tokens: {\n key: 'deposit_quick_action_tokens',\n label: 'Quick Action Tokens',\n description:\n 'Comma-separated token symbols shown as quick action buttons. First token is the default.',\n inputType: 'tokenSymbolList',\n },\n deposit_custom_tokens: {\n key: 'deposit_custom_tokens',\n label: 'Custom Dropdown Tokens',\n description:\n 'Comma-separated token symbols shown in the \"Custom\" dropdown. Leave empty to show all.',\n inputType: 'tokenSymbolList',\n },\n deposit_custom_tokens_json: {\n key: 'deposit_custom_tokens_json',\n label: 'Custom Token Definitions',\n description:\n 'Add tokens beyond the built-in list. Define symbol, mint address, decimals, and logo URL.',\n inputType: 'tokenList',\n },\n\n // Deposit fee settings\n deposit_fee_policy: {\n key: 'deposit_fee_policy',\n label: 'Fee Policy',\n description: 'Who pays deposit fees: company absorbs all, or user pays swap/privacy/all fees.',\n inputType: 'select',\n presets: [\n { label: 'Company Pays All', value: 'company_pays_all' },\n { label: 'User Pays Swap Fees', value: 'user_pays_swap' },\n { label: 'User Pays Privacy Fees', value: 'user_pays_privacy' },\n { label: 'User Pays All Fees', value: 'user_pays_all' },\n ],\n },\n privacy_fee_fixed_lamports: {\n key: 'privacy_fee_fixed_lamports',\n label: 'Privacy Fixed Fee',\n description: 'Fixed fee for Privacy Cash deposits in lamports. 1 SOL = 1,000,000,000 lamports.',\n inputType: 'select',\n unit: 'lamports',\n presets: [\n { label: '0 SOL', value: '0' },\n { label: '0.001 SOL', value: '1000000' },\n { label: '0.005 SOL', value: '5000000' },\n { label: '0.006 SOL (Default)', value: '6000000' },\n { label: '0.01 SOL', value: '10000000' },\n ],\n },\n privacy_fee_percent_bps: {\n key: 'privacy_fee_percent_bps',\n label: 'Privacy Percentage Fee',\n description: 'Percentage fee for Privacy Cash deposits in basis points. 100 bps = 1%.',\n inputType: 'select',\n unit: 'bps',\n presets: [\n { label: '0%', value: '0' },\n { label: '0.25%', value: '25' },\n { label: '0.35% (Default)', value: '35' },\n { label: '0.5%', value: '50' },\n { label: '1%', value: '100' },\n ],\n },\n swap_fee_fixed_lamports: {\n key: 'swap_fee_fixed_lamports',\n label: 'Swap Fixed Fee',\n description: 'Fixed fee for Jupiter swaps in lamports. Covers transaction costs.',\n inputType: 'select',\n unit: 'lamports',\n presets: [\n { label: '0 SOL', value: '0' },\n { label: '0.001 SOL (Default)', value: '1000000' },\n { label: '0.002 SOL', value: '2000000' },\n { label: '0.005 SOL', value: '5000000' },\n ],\n },\n swap_fee_percent_bps: {\n key: 'swap_fee_percent_bps',\n label: 'Swap Percentage Fee',\n description: 'Percentage fee for Jupiter swaps in basis points. 100 bps = 1%.',\n inputType: 'select',\n unit: 'bps',\n presets: [\n { label: '0%', value: '0' },\n { label: '0.1% (Default)', value: '10' },\n { label: '0.25%', value: '25' },\n { label: '0.5%', value: '50' },\n ],\n },\n company_fee_fixed_lamports: {\n key: 'company_fee_fixed_lamports',\n label: 'Company Fixed Fee',\n description: 'Additional fixed processing fee in lamports. Set to 0 to disable.',\n inputType: 'select',\n unit: 'lamports',\n presets: [\n { label: 'Disabled', value: '0' },\n { label: '0.001 SOL', value: '1000000' },\n { label: '0.005 SOL', value: '5000000' },\n { label: '0.01 SOL', value: '10000000' },\n ],\n },\n company_fee_percent_bps: {\n key: 'company_fee_percent_bps',\n label: 'Company Percentage Fee',\n description: 'Additional percentage processing fee in basis points. 100 bps = 1%.',\n inputType: 'select',\n unit: 'bps',\n presets: [\n { label: 'Disabled', value: '0' },\n { label: '0.1%', value: '10' },\n { label: '0.25%', value: '25' },\n { label: '0.5%', value: '50' },\n { label: '1%', value: '100' },\n ],\n },\n micro_batch_threshold_usd: {\n key: 'micro_batch_threshold_usd',\n label: 'Batch Threshold',\n description:\n 'Minimum accumulated USD value before triggering a batch swap. Jupiter requires ~$10 minimum.',\n inputType: 'select',\n unit: 'USD',\n presets: [\n { label: '$10 (Minimum)', value: '10' },\n { label: '$25', value: '25' },\n { label: '$50', value: '50' },\n { label: '$100', value: '100' },\n ],\n },\n micro_batch_poll_secs: {\n key: 'micro_batch_poll_secs',\n label: 'Batch Poll Interval',\n description:\n 'How often to check for batchable micro deposits. Lower values process faster but increase load.',\n inputType: 'duration',\n min: 60,\n presets: [\n { label: '1 minute', value: '60' },\n { label: '5 minutes (Default)', value: '300' },\n { label: '15 minutes', value: '900' },\n { label: '1 hour', value: '3600' },\n ],\n },\n private_deposit_min_lamports: {\n key: 'private_deposit_min_lamports',\n label: 'Min Private Deposit',\n description:\n 'Minimum amount for Privacy Cash deposits in lamports. Smaller deposits use micro batching.',\n inputType: 'select',\n unit: 'lamports',\n presets: [\n { label: '0.1 SOL', value: '100000000' },\n { label: '0.25 SOL (Default)', value: '250000000' },\n { label: '0.5 SOL', value: '500000000' },\n { label: '1 SOL', value: '1000000000' },\n ],\n },\n withdrawal_min_lamports: {\n key: 'withdrawal_min_lamports',\n label: 'Min Withdrawal Amount',\n description:\n 'Minimum amount to withdraw in lamports. Deposits below this remain pending. Fees are ~0.006 SOL + 0.35% + Jupiter.',\n inputType: 'select',\n unit: 'lamports',\n presets: [\n { label: '0.5 SOL', value: '500000000' },\n { label: '1 SOL (Default)', value: '1000000000' },\n { label: '2 SOL', value: '2000000000' },\n { label: '5 SOL', value: '5000000000' },\n ],\n warningThreshold: {\n below: 500000000,\n message: 'Very small withdrawals may lose significant value to fees.',\n },\n },\n};\n\n// =============================================================================\n// CATEGORY METADATA\n// =============================================================================\n\nexport interface CategoryMeta {\n label: string;\n description: string;\n icon: string;\n}\n\nexport const CATEGORY_METADATA: Record<string, CategoryMeta> = {\n // Auth providers (sorted alphabetically by subcategory)\n 'auth.apple': {\n label: 'Apple Sign-In',\n description: 'Configure Sign in with Apple OAuth integration.',\n icon: '',\n },\n 'auth.email': {\n label: 'Email Authentication',\n description: 'Configure email/password authentication settings.',\n icon: '',\n },\n 'auth.google': {\n label: 'Google Sign-In',\n description: 'Configure Google OAuth integration.',\n icon: '',\n },\n 'auth.solana': {\n label: 'Solana Wallet Auth',\n description: 'Configure Solana wallet signature authentication.',\n icon: '',\n },\n 'auth.webauthn': {\n label: 'WebAuthn / Passkeys',\n description: 'Configure FIDO2/WebAuthn passwordless authentication.',\n icon: '',\n },\n 'auth.instantlink': {\n label: 'Instant Link',\n description:\n 'Passwordless sign-in via email link. Replaces \"Forgot your password?\" with a one-time login link instead of a password reset.',\n icon: '',\n },\n 'deposit.general': {\n label: 'General',\n description: 'Core deposit and credit system configuration.',\n icon: '',\n },\n deposit: {\n label: 'Deposit Settings',\n description: 'Configure deposit tokens, fees, and related settings.',\n icon: '',\n },\n email: {\n label: 'Email / SMTP',\n description:\n 'Configure outbound email delivery for verification, password reset, and notifications.',\n icon: '',\n },\n features: {\n label: 'Feature Flags',\n description: 'Enable or disable major platform features.',\n icon: '',\n },\n privacy: {\n label: 'Privacy Settings',\n description:\n 'Control the privacy period for deposits. Longer periods provide better timing privacy but delay fund availability.',\n icon: '',\n },\n rate_limit: {\n label: 'Rate Limiting',\n description:\n 'Protect the system from abuse by limiting request rates. Balance security with user experience.',\n icon: '',\n },\n security: {\n label: 'Security',\n description: 'Configure CORS, cookies, sessions, and JWT settings.',\n icon: '',\n },\n server: {\n label: 'Server',\n description: 'Server infrastructure settings. Some may be overridden by environment variables.',\n icon: '',\n },\n webhook: {\n label: 'Webhooks',\n description: 'Configure HTTP webhook notifications for auth events.',\n icon: '',\n },\n withdrawal: {\n label: 'Withdrawal Worker',\n description:\n 'Configure how the automated withdrawal processor handles pending withdrawals. These settings affect throughput and privacy.',\n icon: '',\n },\n};\n\n/** Preset tokens that are always available without needing to be redefined */\nexport const PRESET_TOKEN_SYMBOLS = [\n 'SOL',\n 'USDC',\n 'USDT',\n 'EURC',\n 'USD1',\n 'PYUSD',\n 'USDH',\n 'CASH',\n 'BONK',\n 'ORE',\n];\n","/**\n * Settings input components - reusable inputs for system settings\n */\nimport { useState, useCallback, useMemo, type ReactNode } from 'react';\nimport type { SystemSetting, SettingMeta } from '../../../types';\nimport { formatDuration, SETTING_METADATA, PRESET_TOKEN_SYMBOLS } from './settingsMetadata';\n\n/** UI-01: Safely render description text that may contain simple <a> tags */\nfunction renderDescription(html: string): ReactNode {\n // Split on <a href=\"...\">...</a> pattern, render links as React elements\n const parts = html.split(/(<a\\s[^>]*>.*?<\\/a>)/g);\n if (parts.length === 1) return html;\n return parts.map((part, i) => {\n const match = part.match(/^<a\\s+href=\"([^\"]+)\"[^>]*>([^<]+)<\\/a>$/);\n if (match) {\n return (\n <a key={i} href={match[1]} target=\"_blank\" rel=\"noopener noreferrer\">\n {match[2]}\n </a>\n );\n }\n return part;\n });\n}\n\n// =============================================================================\n// SETTINGS SECTION\n// =============================================================================\n\nexport interface SettingsSectionProps {\n settings: SystemSetting[];\n edits: Record<string, string>;\n onChange: (key: string, value: string) => void;\n /** External warnings keyed by setting key */\n externalWarnings?: Record<string, string>;\n}\n\nexport function SettingsSection({\n settings,\n edits,\n onChange,\n externalWarnings,\n}: SettingsSectionProps) {\n return (\n <div className=\"cedros-settings-grid\">\n {settings.map((setting) => (\n <SettingRow\n key={setting.key}\n setting={setting}\n editValue={edits[setting.key]}\n onChange={onChange}\n externalWarning={externalWarnings?.[setting.key]}\n />\n ))}\n </div>\n );\n}\n\n// =============================================================================\n// SETTING ROW\n// =============================================================================\n\ninterface SettingRowProps {\n setting: SystemSetting;\n editValue?: string;\n onChange: (key: string, value: string) => void;\n /** External warning message that overrides threshold-based warnings */\n externalWarning?: string;\n}\n\nexport function SettingRow({ setting, editValue, onChange, externalWarning }: SettingRowProps) {\n const meta = SETTING_METADATA[setting.key];\n const currentValue = editValue ?? setting.value;\n const hasChange = editValue !== undefined && editValue !== setting.value;\n const isBoolean = meta?.inputType === 'boolean';\n\n // Check for warnings (external warnings take precedence)\n const warning = useMemo(() => {\n if (externalWarning) return externalWarning;\n if (!meta?.warningThreshold) return null;\n const numValue = parseInt(currentValue, 10);\n if (isNaN(numValue)) return null;\n const { above, below, message } = meta.warningThreshold;\n if (above !== undefined && numValue > above) return message;\n if (below !== undefined && numValue < below) return message;\n return null;\n }, [currentValue, meta?.warningThreshold, externalWarning]);\n\n if (!meta) {\n // Fallback for unknown settings\n return (\n <div className={`cedros-setting-row ${hasChange ? 'cedros-setting-row-changed' : ''}`}>\n <div className=\"cedros-setting-label\">\n <span className=\"cedros-setting-name\">{setting.key}</span>\n {setting.description && (\n <span className=\"cedros-setting-description\">{setting.description}</span>\n )}\n </div>\n <div className=\"cedros-setting-input-wrapper\">\n <input\n type=\"text\"\n value={currentValue}\n onChange={(e) => onChange(setting.key, e.target.value)}\n className=\"cedros-setting-input\"\n />\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={`cedros-setting-row ${hasChange ? 'cedros-setting-row-changed' : ''} ${warning ? 'cedros-setting-row-warning' : ''} ${isBoolean ? 'cedros-setting-row-toggle' : ''}`}\n >\n {isBoolean ? (\n <>\n <div className=\"cedros-setting-control cedros-setting-control-toggle\">\n <SettingInput\n meta={meta}\n value={currentValue}\n onChange={(value) => onChange(setting.key, value)}\n />\n {warning && <div className=\"cedros-setting-warning\">{warning}</div>}\n </div>\n <div className=\"cedros-setting-label\">\n <span className=\"cedros-setting-name\">{meta.label}</span>\n <span className=\"cedros-setting-description\">\n {renderDescription(meta.description)}\n </span>\n </div>\n </>\n ) : (\n <>\n <div className=\"cedros-setting-label\">\n <span className=\"cedros-setting-name\">{meta.label}</span>\n <span className=\"cedros-setting-description\">\n {renderDescription(meta.description)}\n </span>\n </div>\n\n <div className=\"cedros-setting-control\">\n <SettingInput\n meta={meta}\n value={currentValue}\n onChange={(value) => onChange(setting.key, value)}\n />\n {warning && <div className=\"cedros-setting-warning\">{warning}</div>}\n </div>\n </>\n )}\n </div>\n );\n}\n\n// =============================================================================\n// SETTING INPUT - Renders the appropriate input based on type\n// =============================================================================\n\ninterface SettingInputProps {\n meta: SettingMeta;\n value: string;\n onChange: (value: string) => void;\n}\n\nfunction SettingInput({ meta, value, onChange }: SettingInputProps) {\n switch (meta.inputType) {\n case 'duration':\n return (\n <DurationInput value={value} onChange={onChange} presets={meta.presets} min={meta.min} />\n );\n case 'percentage':\n return (\n <PercentageInput\n value={value}\n onChange={onChange}\n min={meta.min ?? 1}\n max={meta.max ?? 100}\n step={meta.step ?? 5}\n presets={meta.presets}\n />\n );\n case 'select':\n return (\n <SelectInput\n value={value}\n onChange={onChange}\n presets={meta.presets ?? []}\n unit={meta.unit}\n />\n );\n case 'number':\n return (\n <NumberInput\n value={value}\n onChange={onChange}\n min={meta.min}\n max={meta.max}\n unit={meta.unit}\n />\n );\n case 'tokenList':\n return <TokenListInput value={value} onChange={onChange} />;\n case 'text':\n return (\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"cedros-setting-input\"\n placeholder={meta.label}\n />\n );\n case 'boolean':\n return <BooleanInput value={value} onChange={onChange} />;\n case 'secret':\n return <SecretInput value={value} onChange={onChange} multiline={meta.multiline} />;\n case 'tokenSymbolList':\n return <TokenSymbolListInput value={value} onChange={onChange} />;\n default:\n return (\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"cedros-setting-input\"\n />\n );\n }\n}\n\n// =============================================================================\n// DURATION INPUT\n// =============================================================================\n\ninterface DurationInputProps {\n value: string;\n onChange: (value: string) => void;\n presets?: { label: string; value: string }[];\n min?: number;\n}\n\nexport function DurationInput({ value, onChange, presets, min = 0 }: DurationInputProps) {\n const numValue = parseInt(value, 10) || 0;\n const displayValue = formatDuration(numValue);\n\n const handlePresetChange = useCallback(\n (e: React.ChangeEvent<HTMLSelectElement>) => {\n if (e.target.value) {\n onChange(e.target.value);\n }\n },\n [onChange]\n );\n\n const handleCustomChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = Math.max(min, parseInt(e.target.value, 10) || 0);\n onChange(String(newValue));\n },\n [onChange, min]\n );\n\n return (\n <div className=\"cedros-duration-input\">\n {presets && presets.length > 0 && (\n <select\n value={presets.find((p) => p.value === value)?.value ?? ''}\n onChange={handlePresetChange}\n className=\"cedros-setting-select\"\n >\n <option value=\"\">Custom...</option>\n {presets.map((preset) => (\n <option key={preset.value} value={preset.value}>\n {preset.label}\n </option>\n ))}\n </select>\n )}\n <div className=\"cedros-duration-custom\">\n <input\n type=\"number\"\n value={numValue}\n onChange={handleCustomChange}\n min={min}\n className=\"cedros-setting-input cedros-setting-input-sm\"\n />\n <span className=\"cedros-setting-unit\">seconds</span>\n <span className=\"cedros-duration-display\">= {displayValue}</span>\n </div>\n </div>\n );\n}\n\n// =============================================================================\n// PERCENTAGE INPUT\n// =============================================================================\n\ninterface PercentageInputProps {\n value: string;\n onChange: (value: string) => void;\n min: number;\n max: number;\n step: number;\n presets?: { label: string; value: string }[];\n}\n\nexport function PercentageInput({\n value,\n onChange,\n min,\n max,\n step,\n presets,\n}: PercentageInputProps) {\n const numValue = parseInt(value, 10) || min;\n\n const handleSliderChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.value);\n },\n [onChange]\n );\n\n const handlePresetClick = useCallback(\n (presetValue: string) => {\n onChange(presetValue);\n },\n [onChange]\n );\n\n return (\n <div className=\"cedros-percentage-input\">\n <div className=\"cedros-percentage-slider-row\">\n <input\n type=\"range\"\n value={numValue}\n onChange={handleSliderChange}\n min={min}\n max={max}\n step={step}\n className=\"cedros-percentage-slider\"\n />\n <span className=\"cedros-percentage-value\">{numValue}%</span>\n </div>\n {presets && presets.length > 0 && (\n <div className=\"cedros-preset-buttons\">\n {presets.map((preset) => (\n <button\n key={preset.value}\n type=\"button\"\n className={`cedros-preset-button ${preset.value === value ? 'cedros-preset-button-active' : ''}`}\n onClick={() => handlePresetClick(preset.value)}\n >\n {preset.label}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// =============================================================================\n// SELECT INPUT\n// =============================================================================\n\ninterface SelectInputProps {\n value: string;\n onChange: (value: string) => void;\n presets: { label: string; value: string }[];\n unit?: string;\n}\n\nexport function SelectInput({ value, onChange, presets, unit }: SelectInputProps) {\n const isCustomValue = !presets.some((p) => p.value === value);\n\n const handleSelectChange = useCallback(\n (e: React.ChangeEvent<HTMLSelectElement>) => {\n if (e.target.value !== '__custom__') {\n onChange(e.target.value);\n }\n },\n [onChange]\n );\n\n const handleCustomChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.value);\n },\n [onChange]\n );\n\n return (\n <div className=\"cedros-select-input\">\n <select\n value={isCustomValue ? '__custom__' : value}\n onChange={handleSelectChange}\n className=\"cedros-setting-select\"\n >\n {presets.map((preset) => (\n <option key={preset.value} value={preset.value}>\n {preset.label}\n </option>\n ))}\n <option value=\"__custom__\">Custom...</option>\n </select>\n {isCustomValue && (\n <div className=\"cedros-select-custom\">\n <input\n type=\"number\"\n value={value}\n onChange={handleCustomChange}\n className=\"cedros-setting-input cedros-setting-input-sm\"\n />\n {unit && <span className=\"cedros-setting-unit\">{unit}</span>}\n </div>\n )}\n </div>\n );\n}\n\n// =============================================================================\n// NUMBER INPUT\n// =============================================================================\n\ninterface NumberInputProps {\n value: string;\n onChange: (value: string) => void;\n min?: number;\n max?: number;\n unit?: string;\n}\n\nexport function NumberInput({ value, onChange, min, max, unit }: NumberInputProps) {\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.value);\n },\n [onChange]\n );\n\n return (\n <div className=\"cedros-number-input\">\n <input\n type=\"number\"\n value={value}\n onChange={handleChange}\n min={min}\n max={max}\n className=\"cedros-setting-input\"\n />\n {unit && <span className=\"cedros-setting-unit\">{unit}</span>}\n </div>\n );\n}\n\n// =============================================================================\n// BOOLEAN INPUT (Toggle)\n// =============================================================================\n\ninterface BooleanInputProps {\n value: string;\n onChange: (value: string) => void;\n}\n\nexport function BooleanInput({ value, onChange }: BooleanInputProps) {\n const isEnabled = value === 'true';\n\n const handleToggle = useCallback(() => {\n onChange(isEnabled ? 'false' : 'true');\n }, [isEnabled, onChange]);\n\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={isEnabled}\n className={`cedros-toggle ${isEnabled ? 'cedros-toggle-on' : 'cedros-toggle-off'}`}\n onClick={handleToggle}\n >\n <span className=\"cedros-toggle-track\">\n <span className=\"cedros-toggle-thumb\" />\n </span>\n <span className=\"cedros-toggle-label\">{isEnabled ? 'Enabled' : 'Disabled'}</span>\n </button>\n );\n}\n\n// =============================================================================\n// SECRET INPUT (Masked)\n// =============================================================================\n\ninterface SecretInputProps {\n value: string;\n onChange: (value: string) => void;\n multiline?: boolean;\n}\n\nexport function SecretInput({ value, onChange, multiline }: SecretInputProps) {\n const [isEditing, setIsEditing] = useState(false);\n const [showValue, setShowValue] = useState(false);\n const hasValue = value && value.length > 0;\n\n const handleEdit = useCallback(() => {\n setIsEditing(true);\n setShowValue(true);\n }, []);\n\n const handleDone = useCallback(() => {\n setIsEditing(false);\n setShowValue(false);\n }, []);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n onChange(e.target.value);\n },\n [onChange]\n );\n\n if (!isEditing && hasValue) {\n return (\n <div className=\"cedros-secret-input cedros-secret-input-masked\">\n <span className=\"cedros-secret-masked\">{'•'.repeat(Math.min(value.length, 20))}</span>\n <button type=\"button\" className=\"cedros-secret-edit-btn\" onClick={handleEdit}>\n Edit\n </button>\n </div>\n );\n }\n\n return (\n <div className=\"cedros-secret-input\">\n {multiline ? (\n <textarea\n value={value}\n onChange={handleChange}\n className=\"cedros-setting-input cedros-setting-textarea\"\n placeholder=\"Enter secret value...\"\n rows={4}\n />\n ) : (\n <input\n type={showValue ? 'text' : 'password'}\n value={value}\n onChange={handleChange}\n className=\"cedros-setting-input\"\n placeholder=\"Enter secret value...\"\n />\n )}\n <div className=\"cedros-secret-actions\">\n {!multiline && (\n <button\n type=\"button\"\n className=\"cedros-secret-toggle-btn\"\n onClick={() => setShowValue(!showValue)}\n >\n {showValue ? 'Hide' : 'Show'}\n </button>\n )}\n {isEditing && (\n <button type=\"button\" className=\"cedros-secret-done-btn\" onClick={handleDone}>\n Done\n </button>\n )}\n </div>\n </div>\n );\n}\n\n// =============================================================================\n// TOKEN LIST INPUT\n// =============================================================================\n\ninterface TokenDefinition {\n symbol: string;\n mint: string;\n decimals: number;\n logoUrl?: string;\n}\n\ninterface TokenListInputProps {\n value: string;\n onChange: (value: string) => void;\n}\n\nexport function TokenListInput({ value, onChange }: TokenListInputProps) {\n const tokens: TokenDefinition[] = useMemo(() => {\n try {\n return JSON.parse(value || '[]');\n } catch {\n return [];\n }\n }, [value]);\n\n const updateTokens = useCallback(\n (updated: TokenDefinition[]) => {\n onChange(JSON.stringify(updated));\n },\n [onChange]\n );\n\n const addToken = useCallback(() => {\n updateTokens([...tokens, { symbol: '', mint: '', decimals: 6 }]);\n }, [tokens, updateTokens]);\n\n const updateToken = useCallback(\n (index: number, field: keyof TokenDefinition, val: string | number | undefined) => {\n const updated = [...tokens];\n updated[index] = { ...updated[index], [field]: val };\n updateTokens(updated);\n },\n [tokens, updateTokens]\n );\n\n const removeToken = useCallback(\n (index: number) => {\n updateTokens(tokens.filter((_, i) => i !== index));\n },\n [tokens, updateTokens]\n );\n\n return (\n <div className=\"cedros-token-list-input\">\n {/* Preset tokens info */}\n <div className=\"cedros-token-presets\">\n <span className=\"cedros-token-presets-label\">Built-in tokens:</span>\n <div className=\"cedros-token-presets-list\">\n {PRESET_TOKEN_SYMBOLS.map((symbol) => (\n <span key={symbol} className=\"cedros-token-preset-chip\">\n {symbol}\n </span>\n ))}\n </div>\n </div>\n\n {tokens.length === 0 && (\n <p className=\"cedros-token-list-empty\">\n No custom tokens added. Use the built-in tokens above or add your own.\n </p>\n )}\n\n {tokens.map((token, i) => (\n <div key={i} className=\"cedros-token-row\">\n <div className=\"cedros-token-row-fields\">\n <input\n type=\"text\"\n placeholder=\"Symbol\"\n value={token.symbol}\n onChange={(e) => updateToken(i, 'symbol', e.target.value.toUpperCase())}\n className=\"cedros-setting-input cedros-token-input-symbol\"\n maxLength={10}\n />\n <input\n type=\"text\"\n placeholder=\"Mint address\"\n value={token.mint}\n onChange={(e) => updateToken(i, 'mint', e.target.value)}\n className=\"cedros-setting-input cedros-token-input-mint\"\n />\n <input\n type=\"number\"\n placeholder=\"Decimals\"\n value={token.decimals}\n onChange={(e) => updateToken(i, 'decimals', parseInt(e.target.value, 10) || 0)}\n className=\"cedros-setting-input cedros-token-input-decimals\"\n min={0}\n max={18}\n />\n <input\n type=\"text\"\n placeholder=\"Logo URL (optional)\"\n value={token.logoUrl || ''}\n onChange={(e) => updateToken(i, 'logoUrl', e.target.value || undefined)}\n className=\"cedros-setting-input cedros-token-input-logo\"\n />\n </div>\n <button\n type=\"button\"\n className=\"cedros-token-remove-btn\"\n onClick={() => removeToken(i)}\n title=\"Remove token\"\n >\n ×\n </button>\n </div>\n ))}\n\n <button type=\"button\" className=\"cedros-token-add-btn\" onClick={addToken}>\n + Add Token\n </button>\n </div>\n );\n}\n\n// =============================================================================\n// TOKEN SYMBOL LIST INPUT\n// =============================================================================\n\ninterface TokenSymbolListInputProps {\n value: string;\n onChange: (value: string) => void;\n}\n\nexport function TokenSymbolListInput({ value, onChange }: TokenSymbolListInputProps) {\n const symbols = useMemo(() => {\n return value\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n }, [value]);\n\n const addSymbol = useCallback(\n (symbol: string) => {\n if (!symbol || symbols.includes(symbol)) return;\n const updated = [...symbols, symbol].join(', ');\n onChange(updated);\n },\n [symbols, onChange]\n );\n\n const removeSymbol = useCallback(\n (symbol: string) => {\n const updated = symbols.filter((s) => s !== symbol).join(', ');\n onChange(updated);\n },\n [symbols, onChange]\n );\n\n return (\n <div className=\"cedros-token-symbol-list-input\">\n {/* Preset tokens - click to add */}\n <div className=\"cedros-token-presets\">\n <span className=\"cedros-token-presets-label\">Click to add:</span>\n <div className=\"cedros-token-presets-list\">\n {PRESET_TOKEN_SYMBOLS.map((symbol) => {\n const isSelected = symbols.includes(symbol);\n return (\n <button\n key={symbol}\n type=\"button\"\n className={`cedros-token-preset-chip ${isSelected ? 'cedros-token-preset-chip-selected' : ''}`}\n onClick={() => (isSelected ? removeSymbol(symbol) : addSymbol(symbol))}\n title={isSelected ? `Remove ${symbol}` : `Add ${symbol}`}\n >\n {symbol}\n {isSelected && <span className=\"cedros-token-chip-check\">✓</span>}\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Text input for manual entry or custom symbols */}\n <input\n type=\"text\"\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"cedros-setting-input\"\n placeholder=\"USDC, SOL, BONK...\"\n />\n </div>\n );\n}\n","import { useState, useCallback, useEffect, useRef } from 'react';\nimport type { UpdateSettingRequest } from '../types';\nimport { useSystemSettings } from './useSystemSettings';\n\n/** Autosave status */\nexport type AutosaveStatus = 'idle' | 'pending' | 'saving' | 'saved' | 'error';\n\n/** Debounce delay in milliseconds */\nconst DEBOUNCE_MS = 800;\n\n/** How long to show \"saved\" status before returning to idle */\nconst SAVED_DISPLAY_MS = 2000;\n\nexport interface UseSettingsAutosaveReturn {\n /** Settings grouped by category */\n settings: Record<string, import('../types').SystemSetting[]>;\n /** Current edits (key -> value) */\n edits: Record<string, string>;\n /** Whether initial load is in progress */\n isLoading: boolean;\n /** Current autosave status */\n autosaveStatus: AutosaveStatus;\n /** Error message if autosave failed */\n autosaveError: string | null;\n /** Loading error */\n error: Error | null;\n /** Fetch settings from server */\n fetchSettings: () => Promise<void>;\n /** Handle a setting change (triggers autosave) */\n handleChange: (key: string, value: string) => void;\n /** Get effective value (edit or original) */\n getEffectiveValue: (key: string) => string;\n}\n\n/**\n * Hook for managing system settings with autosave.\n *\n * Automatically saves changes after a debounce period.\n * Provides status feedback for the autosave process.\n */\nexport function useSettingsAutosave(): UseSettingsAutosaveReturn {\n const { settings, isLoading, error, fetchSettings, updateSettings } = useSystemSettings();\n\n const [edits, setEdits] = useState<Record<string, string>>({});\n const [autosaveStatus, setAutosaveStatus] = useState<AutosaveStatus>('idle');\n const [autosaveError, setAutosaveError] = useState<string | null>(null);\n\n // Refs for debounce timer and pending edits\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const savedTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const pendingEditsRef = useRef<Record<string, string>>({});\n\n // Cleanup timers on unmount\n useEffect(() => {\n return () => {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);\n if (savedTimerRef.current) clearTimeout(savedTimerRef.current);\n };\n }, []);\n\n // Perform the actual save\n const performSave = useCallback(async () => {\n const editsToSave = { ...pendingEditsRef.current };\n if (Object.keys(editsToSave).length === 0) {\n setAutosaveStatus('idle');\n return;\n }\n\n setAutosaveStatus('saving');\n setAutosaveError(null);\n\n const updates: UpdateSettingRequest[] = Object.entries(editsToSave).map(([key, value]) => ({\n key,\n value,\n }));\n\n try {\n await updateSettings(updates);\n\n // Clear saved edits from state\n setEdits((prev) => {\n const next = { ...prev };\n for (const key of Object.keys(editsToSave)) {\n delete next[key];\n }\n return next;\n });\n\n // Clear from pending ref\n for (const key of Object.keys(editsToSave)) {\n delete pendingEditsRef.current[key];\n }\n\n setAutosaveStatus('saved');\n\n // Reset to idle after delay\n if (savedTimerRef.current) clearTimeout(savedTimerRef.current);\n savedTimerRef.current = setTimeout(() => {\n setAutosaveStatus('idle');\n }, SAVED_DISPLAY_MS);\n } catch (err) {\n setAutosaveStatus('error');\n setAutosaveError(err instanceof Error ? err.message : 'Failed to save');\n }\n }, [updateSettings]);\n\n // Handle a setting change\n const handleChange = useCallback(\n (key: string, value: string) => {\n // Update local edits\n setEdits((prev) => ({ ...prev, [key]: value }));\n pendingEditsRef.current[key] = value;\n\n // Clear any error state\n setAutosaveError(null);\n\n // Set status to pending\n setAutosaveStatus('pending');\n\n // Reset debounce timer\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current);\n }\n\n debounceTimerRef.current = setTimeout(() => {\n performSave();\n }, DEBOUNCE_MS);\n },\n [performSave]\n );\n\n // Get effective value (edit or original)\n const getEffectiveValue = useCallback(\n (key: string) => {\n if (edits[key] !== undefined) return edits[key];\n for (const categorySettings of Object.values(settings)) {\n const found = categorySettings.find((s) => s.key === key);\n if (found) return found.value;\n }\n return '';\n },\n [edits, settings]\n );\n\n return {\n settings,\n edits,\n isLoading,\n autosaveStatus,\n autosaveError,\n error,\n fetchSettings,\n handleChange,\n getEffectiveValue,\n };\n}\n","/**\n * Autosave status indicator for settings pages\n */\nimport type { AutosaveStatus as Status } from '../../../hooks/useSettingsAutosave';\n\nexport interface AutosaveStatusProps {\n status: Status;\n error?: string | null;\n}\n\nexport function AutosaveStatus({ status, error }: AutosaveStatusProps) {\n if (status === 'idle') return null;\n\n return (\n <div className={`cedros-autosave-status cedros-autosave-status--${status}`}>\n {status === 'pending' && (\n <>\n <span className=\"cedros-autosave-dot\" />\n <span>Unsaved changes</span>\n </>\n )}\n {status === 'saving' && (\n <>\n <span className=\"cedros-autosave-spinner\" />\n <span>Saving...</span>\n </>\n )}\n {status === 'saved' && (\n <>\n <span className=\"cedros-autosave-check\">&#10003;</span>\n <span>Saved</span>\n </>\n )}\n {status === 'error' && (\n <>\n <span className=\"cedros-autosave-error-icon\">!</span>\n <span>{error || 'Save failed'}</span>\n </>\n )}\n </div>\n );\n}\n"],"names":["secondsToDuration","totalSeconds","days","hours","minutes","seconds","formatDuration","parts","SETTING_METADATA","CATEGORY_METADATA","PRESET_TOKEN_SYMBOLS","renderDescription","html","part","i","match","jsx","SettingsSection","settings","edits","onChange","externalWarnings","setting","SettingRow","editValue","externalWarning","meta","currentValue","hasChange","isBoolean","warning","useMemo","numValue","above","below","message","jsxs","Fragment","SettingInput","value","e","DurationInput","PercentageInput","SelectInput","NumberInput","TokenListInput","BooleanInput","SecretInput","TokenSymbolListInput","presets","min","displayValue","handlePresetChange","useCallback","handleCustomChange","newValue","p","preset","max","step","handleSliderChange","handlePresetClick","presetValue","unit","isCustomValue","handleSelectChange","handleChange","isEnabled","handleToggle","multiline","isEditing","setIsEditing","useState","showValue","setShowValue","hasValue","handleEdit","handleDone","tokens","updateTokens","updated","addToken","updateToken","index","field","val","removeToken","_","symbol","token","symbols","s","addSymbol","removeSymbol","isSelected","DEBOUNCE_MS","SAVED_DISPLAY_MS","useSettingsAutosave","isLoading","error","fetchSettings","updateSettings","useSystemSettings","setEdits","autosaveStatus","setAutosaveStatus","autosaveError","setAutosaveError","debounceTimerRef","useRef","savedTimerRef","pendingEditsRef","useEffect","performSave","editsToSave","updates","key","prev","next","err","getEffectiveValue","categorySettings","found","AutosaveStatus","status"],"mappings":"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"}
@@ -1 +0,0 @@
1
- "use strict";const e=require("react/jsx-runtime"),t=require("react"),L=require("./useCedrosLogin-C9MrcZvh.cjs"),V=require("./validation-BuGQrA-K.cjs"),F=require("./LoadingSpinner-d6sSxgQN.cjs"),z=require("./ErrorMessage-CHbYbVi2.cjs"),te=require("./sanitization-Bo_tn-L2.cjs");function P(n={}){const{maxAttempts:f=5,windowMs:x=6e4,showCountdown:u=!1}=n,p=t.useRef([]),[c,k]=t.useState(!1),[,d]=t.useState(0),h=t.useCallback(()=>{d(r=>r+1)},[]),m=t.useCallback(()=>{const r=Date.now();p.current=p.current.filter(s=>r-s<x)},[x]),b=t.useCallback(()=>{m(),k(r=>p.current.length===0&&r?!1:r)},[m]),l=t.useCallback(()=>(m(),Math.max(0,f-p.current.length)),[m,f]),g=t.useCallback(()=>{if(m(),p.current.length===0)return 0;const s=p.current[0]+x;return Math.max(0,s-Date.now())},[m,x]),v=t.useCallback(()=>(m(),p.current.length<f),[m,f]),y=t.useCallback(()=>{if(b(),p.current.length>=f){const r=g(),s=Math.ceil(r/1e3);throw new Error(`Too many attempts. Please wait ${s} second${s===1?"":"s"} before trying again.`)}p.current.push(Date.now()),k(r=>r||!0),h()},[b,f,g,h]),w=t.useCallback(()=>{p.current=[],k(r=>r&&!1),h()},[h]);return t.useEffect(()=>{if(!c||!u)return;const r=window.setInterval(()=>{b(),h()},1e3);return()=>{window.clearInterval(r)}},[c,u,h,b]),{checkLimit:y,isAllowed:v,getRemainingAttempts:l,getTimeUntilReset:g,reset:w}}function re(n){return"mfaRequired"in n&&n.mfaRequired===!0}function _(){const{config:n,_internal:f}=L.useCedrosLogin(),[x,u]=t.useState(!1),[p,c]=t.useState(null),{checkLimit:k,getRemainingAttempts:d,getTimeUntilReset:h,reset:m}=P({maxAttempts:5,windowMs:6e4}),b=t.useMemo(()=>new L.ApiClient({baseUrl:n.serverUrl,timeoutMs:n.requestTimeout,retryAttempts:n.retryAttempts}),[n.serverUrl,n.requestTimeout,n.retryAttempts]),l=n.callbacks,g=n.features?.walletEnrollment!==!1,v=n.serverUrl,y=t.useCallback(async(s,a)=>{if(!V.validateEmail(s)){const i={code:"VALIDATION_ERROR",message:"Please enter a valid email address"};throw c(i),i}try{k()}catch(i){const o={code:"RATE_LIMITED",message:i instanceof Error?i.message:"Too many attempts"};throw c(o),o}u(!0),c(null);try{const i=await b.post("/login",{email:s,password:a});if(re(i))return{mfaRequired:!0,mfaToken:i.mfaToken,email:s,userId:i.userId};const o=i;return l?.onLoginSuccess?.(o.user,"email"),f?.handleLoginSuccess(o.user,o.tokens),m(),{mfaRequired:!1,response:o}}catch(i){const o=L.handleApiError(i,"Login failed");throw c(o),o}finally{u(!1)}},[b,l,f,k,m]),w=t.useCallback(async(s,a,i)=>{if(!V.validateEmail(s)){const o={code:"VALIDATION_ERROR",message:"Please enter a valid email address"};throw c(o),o}try{k()}catch(o){const C={code:"RATE_LIMITED",message:o instanceof Error?o.message:"Too many attempts"};throw c(C),C}u(!0),c(null);try{const o=await b.post("/register",{email:s,password:a,name:i});if(l?.onLoginSuccess?.(o.user,"email"),f?.handleLoginSuccess(o.user,o.tokens),m(),g){const C=o.tokens?.accessToken??"",A=!C?200:0;new Promise(j=>setTimeout(j,A)).then(()=>Promise.resolve().then(()=>require("./silentWalletEnroll-wnkcB9HP.cjs"))).then(({silentWalletEnroll:j})=>j({password:a,serverUrl:v,accessToken:C})).then(j=>{j.success||console.warn("[useEmailAuth] Wallet auto-enrollment failed:",j.error)}).catch(j=>{const R=j instanceof Error?j.message:"Unknown error";console.warn("[useEmailAuth] Wallet auto-enrollment unavailable:",R)})}return o}catch(o){const C=L.handleApiError(o,"Registration failed");throw c(C),C}finally{u(!1)}},[b,l,f,k,m,v,g]),r=t.useCallback(()=>c(null),[]);return{login:y,register:w,isLoading:x,error:p,clearError:r,remainingAttempts:d(),timeUntilReset:h()}}function ae(n){return typeof n=="object"&&n!==null&&"mfaRequired"in n&&n.mfaRequired===!0}function H(){const{config:n,_internal:f}=L.useCedrosLogin(),[x,u]=t.useState(!1),[p,c]=t.useState(!1),[k,d]=t.useState(null),h=t.useMemo(()=>new L.ApiClient({baseUrl:n.serverUrl,timeoutMs:n.requestTimeout,retryAttempts:n.retryAttempts}),[n.serverUrl,n.requestTimeout,n.retryAttempts]),{checkLimit:m,getRemainingAttempts:b}=P({maxAttempts:3,windowMs:3e5}),l=t.useCallback(async w=>{if(!V.validateEmail(w)){const r={code:"VALIDATION_ERROR",message:"Please enter a valid email address"};throw d(r),r}try{m()}catch(r){const s={code:"RATE_LIMITED",message:r instanceof Error?r.message:"Too many attempts"};throw d(s),s}u(!0),d(null),c(!1);try{await h.post("/instant-link",{email:w}),c(!0)}catch(r){const s=L.handleApiError(r,"Failed to send sign-in link");throw d(s),s}finally{u(!1)}},[h,m]),g=t.useCallback(async w=>{if(!w||w.trim().length===0){const r={code:"VALIDATION_ERROR",message:"Invalid or missing sign-in link token"};throw d(r),r}u(!0),d(null),c(!1);try{const r=await h.post("/instant-link/verify",{token:w});return ae(r)||(n.callbacks?.onLoginSuccess?.(r.user,"email"),f?.handleLoginSuccess(r.user,r.tokens)),r}catch(r){const s=L.handleApiError(r,"Failed to verify sign-in link");throw d(s),s}finally{u(!1)}},[h,n.callbacks,f]),v=t.useCallback(()=>d(null),[]),y=t.useCallback(()=>{d(null),c(!1),u(!1)},[]);return{sendInstantLink:l,verifyInstantLink:g,isLoading:x,isSuccess:p,error:k,clearError:v,reset:y,remainingAttempts:b()}}function B({label:n="Password",labelAction:f,showStrengthMeter:x=!1,onValidationChange:u,error:p,className:c="",onChange:k,value:d,...h}){const[m,b]=t.useState(!1),[l,g]=t.useState(null),v=t.useId(),y=r=>{const s=r.target.value;if(x||u){const a=V.validatePassword(s);g(a),u?.(a)}k?.(r)},w={weak:"var(--cedros-destructive, #ef4444)",fair:"var(--cedros-warning, #f59e0b)",good:"var(--cedros-success, #22c55e)",strong:"var(--cedros-success, #22c55e)"};return e.jsxs("div",{className:`cedros-password-input ${c}`,children:[e.jsxs("div",{className:"cedros-label-row",children:[e.jsx("label",{htmlFor:v,className:"cedros-label",children:n}),f]}),e.jsxs("div",{className:"cedros-password-wrapper",children:[e.jsx("input",{id:v,type:m?"text":"password",className:"cedros-input",onChange:y,value:d,"aria-invalid":p?"true":void 0,"aria-describedby":p?`${v}-error`:void 0,...h}),e.jsx("button",{type:"button",className:"cedros-password-toggle",onClick:()=>b(!m),"aria-label":m?"Hide password":"Show password","aria-pressed":m,children:m?e.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none","aria-hidden":"true",children:[e.jsx("path",{d:"M2.5 10s3-6 7.5-6 7.5 6 7.5 6-3 6-7.5 6-7.5-6-7.5-6z",stroke:"currentColor",strokeWidth:"1.5"}),e.jsx("circle",{cx:"10",cy:"10",r:"2.5",stroke:"currentColor",strokeWidth:"1.5"}),e.jsx("path",{d:"M3 17L17 3",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})]}):e.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none","aria-hidden":"true",children:[e.jsx("path",{d:"M2.5 10s3-6 7.5-6 7.5 6 7.5 6-3 6-7.5 6-7.5-6-7.5-6z",stroke:"currentColor",strokeWidth:"1.5"}),e.jsx("circle",{cx:"10",cy:"10",r:"2.5",stroke:"currentColor",strokeWidth:"1.5"})]})})]}),p&&e.jsx("p",{id:`${v}-error`,className:"cedros-input-error",children:p}),x&&l&&d?.length>0&&e.jsxs("div",{className:"cedros-password-strength",children:[e.jsx("div",{className:"cedros-strength-bar",children:e.jsx("div",{className:"cedros-strength-fill",style:{width:`${l.strength==="weak"?25:l.strength==="fair"?50:l.strength==="good"?75:100}%`,backgroundColor:w[l.strength]}})}),e.jsx("span",{className:"cedros-strength-label",children:l.strength})]})]})}function K(){const{config:n,_internal:f}=L.useCedrosLogin(),[x,u]=t.useState("idle"),[p,c]=t.useState(!1),[k,d]=t.useState(null),{checkLimit:h,getRemainingAttempts:m,getTimeUntilReset:b,reset:l}=P({maxAttempts:5,windowMs:12e4}),g=t.useMemo(()=>new L.ApiClient({baseUrl:n.serverUrl,timeoutMs:n.requestTimeout,retryAttempts:n.retryAttempts}),[n.serverUrl,n.requestTimeout,n.retryAttempts]),v=t.useCallback(async(r,s)=>{const a=/^[A-Z0-9]{16}$/i.test(s)||/^[A-Z0-9]{4}(-[A-Z0-9]{4}){3}$/i.test(s);if(!(/^\d{6}$/.test(s)||a)){const o={code:"VALIDATION_ERROR",message:"Please enter a valid 6-digit code or recovery code"};throw d(o),o}try{h()}catch(o){const C={code:"RATE_LIMITED",message:o instanceof Error?o.message:"Too many attempts"};throw d(C),C}c(!0),d(null),u("verifying");try{const o=await g.post("/login/mfa",{mfaToken:r,code:s});return u("success"),l(),f&&o.user&&o.tokens&&f.handleLoginSuccess(o.user,o.tokens),o}catch(o){const C=L.handleApiError(o,"Invalid verification code");throw d(C),u("error"),C}finally{c(!1)}},[g,f,h,l]),y=t.useCallback(()=>d(null),[]),w=t.useCallback(()=>{d(null),u("idle"),c(!1)},[]);return{state:x,isLoading:p,error:k,verifyTotp:v,clearError:y,reset:w,remainingAttempts:m(),timeUntilReset:b()}}const N=6;function Z({value:n="",onChange:f,onComplete:x,disabled:u=!1,error:p,autoFocus:c=!1,className:k=""}){const d=t.useRef([]),[h,m]=t.useState(n.padEnd(N,"")),b=t.useId();t.useEffect(()=>{m(n.padEnd(N,""))},[n]);const l=t.useCallback(s=>{s>=0&&s<N&&d.current[s]?.focus()},[]),g=t.useCallback(s=>{const a=s.replace(/\D/g,"").slice(0,N);m(a.padEnd(N,"")),f?.(a),a.length===N&&x?.(a)},[f,x]),v=t.useCallback((s,a)=>{if(!/^\d?$/.test(a))return;const i=h.split("");i[s]=a;const o=i.join("").replace(/ /g,"");g(o),a&&s<N-1&&l(s+1)},[h,g,l]),y=t.useCallback((s,a)=>{if(a.key==="Backspace"){a.preventDefault();const i=h.split("");i[s]&&i[s]!==" "?(i[s]=" ",g(i.join("").replace(/ /g,""))):s>0&&(i[s-1]=" ",g(i.join("").replace(/ /g,"")),l(s-1))}else a.key==="ArrowLeft"&&s>0?(a.preventDefault(),l(s-1)):a.key==="ArrowRight"&&s<N-1&&(a.preventDefault(),l(s+1))},[h,g,l]),w=t.useCallback(s=>{s.preventDefault();const i=s.clipboardData.getData("text").replace(/\D/g,"").slice(0,N);i&&(g(i),l(Math.min(i.length,N-1)))},[g,l]),r=t.useCallback(s=>{s.target.select()},[]);return t.useEffect(()=>{c&&!u&&d.current[0]?.focus()},[c,u]),e.jsxs("div",{className:`cedros-otp-input ${k}`,children:[e.jsx("div",{className:"cedros-otp-slots",role:"group","aria-label":"One-time password",children:Array.from({length:N}).map((s,a)=>e.jsx("input",{ref:i=>{d.current[a]=i},id:`${b}-${a}`,type:"text",inputMode:"numeric",pattern:"[0-9]*",maxLength:1,className:`cedros-otp-slot ${p?"cedros-otp-slot-error":""}`,value:h[a]===" "?"":h[a]||"",onChange:i=>v(a,i.target.value),onKeyDown:i=>y(a,i),onPaste:w,onFocus:r,disabled:u,autoComplete:"one-time-code","aria-label":`Digit ${a+1}`,"aria-invalid":p?"true":void 0},a))}),p&&e.jsx("p",{className:"cedros-otp-error",role:"alert",children:p})]})}function Y({mfaToken:n,email:f,onSuccess:x,onBack:u,className:p=""}){const{verifyTotp:c,isLoading:k,error:d,clearError:h}=K(),[m,b]=t.useState(""),[l,g]=t.useState(!1),[v,y]=t.useState(""),w=async a=>{const i=a||(l?v:m);if(i)try{await c(n,i),x?.()}catch{l?y(""):b("")}},r=a=>{w(a)},s=()=>{g(!l),h(),b(""),y("")};return e.jsxs("div",{className:`cedros-totp-verify ${p}`,children:[e.jsxs("div",{className:"cedros-totp-verify-header",children:[e.jsxs("svg",{className:"cedros-totp-verify-icon",width:"48",height:"48",viewBox:"0 0 48 48",fill:"none","aria-hidden":"true",children:[e.jsx("rect",{x:"8",y:"20",width:"32",height:"24",rx:"4",stroke:"currentColor",strokeWidth:"2"}),e.jsx("path",{d:"M16 20V14a8 8 0 1 1 16 0v6",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"}),e.jsx("circle",{cx:"24",cy:"32",r:"3",fill:"currentColor"})]}),e.jsx("h3",{className:"cedros-totp-title",children:"Two-factor authentication"}),e.jsx("p",{className:"cedros-totp-description",children:l?"Enter one of your recovery codes to sign in.":"Enter the 6-digit code from your authenticator app."}),f&&e.jsx("p",{className:"cedros-totp-email",children:f})]}),l?e.jsxs("div",{className:"cedros-totp-backup-input",children:[e.jsx("input",{type:"text",className:`cedros-input ${d?"cedros-input-error":""}`,placeholder:"Enter recovery code",value:v,onChange:a=>{y(a.target.value.toUpperCase()),h()},onKeyDown:a=>{a.key==="Enter"&&v&&w()},disabled:k,autoFocus:!0,autoComplete:"one-time-code"}),d&&e.jsx("p",{className:"cedros-input-error",role:"alert",children:d.message})]}):e.jsx(Z,{value:m,onChange:a=>{b(a),h()},onComplete:r,disabled:k,error:d?.message,autoFocus:!0}),e.jsx("button",{type:"button",className:"cedros-button cedros-button-primary cedros-button-md cedros-button-full",onClick:()=>w(),disabled:k||(l?!v:m.length!==6),children:k?e.jsxs(e.Fragment,{children:[e.jsx(F.LoadingSpinner,{size:"sm"}),e.jsx("span",{children:"Verifying..."})]}):"Verify"}),e.jsxs("div",{className:"cedros-totp-verify-footer",children:[e.jsx("button",{type:"button",className:"cedros-link cedros-link-sm",onClick:s,disabled:k,children:l?"Use authenticator app":"Use a recovery code"}),u&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"cedros-totp-verify-divider",children:"•"}),e.jsx("button",{type:"button",className:"cedros-link cedros-link-sm",onClick:u,disabled:k,children:"Back to login"})]})]})]})}function oe({onSuccess:n,onSwitchToRegister:f,onForgotPassword:x,className:u=""}){const{config:p}=L.useCedrosLogin(),{login:c,isLoading:k,error:d,clearError:h}=_(),{sendInstantLink:m,isLoading:b,isSuccess:l,error:g,clearError:v,reset:y}=H(),[w,r]=t.useState(""),[s,a]=t.useState(""),[i,o]=t.useState(null),[C,I]=t.useState(""),A=p.forms?.forgotPassword?.mode??(p.features?.instantLink?"instantLink":"reset"),j=async S=>{S.preventDefault();try{const q=await c(w,s);q.mfaRequired?(o(q.mfaToken),I(q.email)):n?.()}catch{}},R=()=>{o(null),I(""),n?.()},O=()=>{o(null),I(""),a("")},M=async()=>{if(A==="instantLink")try{await m(w)}catch{}else x?.()};if(i)return e.jsx(Y,{mfaToken:i,email:C,onSuccess:R,onBack:O,className:u});if(l)return e.jsxs("div",{className:`cedros-instant-link-success ${u}`,children:[e.jsxs("svg",{className:"cedros-success-icon",width:"48",height:"48",viewBox:"0 0 48 48",fill:"none","aria-hidden":"true",children:[e.jsx("circle",{cx:"24",cy:"24",r:"22",stroke:"currentColor",strokeWidth:"2"}),e.jsx("path",{d:"M14 24l7 7 13-13",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})]}),e.jsx("h3",{className:"cedros-success-title",children:"Check your email"}),e.jsxs("p",{className:"cedros-success-message",children:["We sent a sign-in link to ",e.jsx("strong",{children:w}),". Click the link to sign in."]}),e.jsx("button",{type:"button",className:"cedros-button cedros-button-md cedros-button-outline",onClick:y,children:"Back to login"})]});const U=d||g,$=()=>{h(),v()},T=k||b;return e.jsxs("form",{onSubmit:j,className:`cedros-form ${u}`,children:[e.jsxs("div",{className:"cedros-form-field",children:[e.jsx("label",{htmlFor:"email",className:"cedros-label",children:"Email"}),e.jsx("input",{id:"email",type:"email",className:"cedros-input",value:w,onChange:S=>r(S.target.value),placeholder:"you@example.com",required:!0,"aria-required":"true",autoComplete:"email",disabled:T})]}),e.jsx("div",{className:"cedros-form-field",children:e.jsx(B,{value:s,onChange:S=>a(S.target.value),placeholder:"Enter your password",required:!0,autoComplete:"current-password",disabled:T,labelAction:x||A==="instantLink"?e.jsx("button",{type:"button",className:"cedros-link cedros-link-sm",onClick:M,disabled:b,children:b?"Sending...":"Forgot your password?"}):void 0})}),e.jsx(z.ErrorMessage,{error:U,onDismiss:$}),e.jsx("button",{type:"submit",className:"cedros-button cedros-button-primary cedros-button-md cedros-button-full",disabled:T||!w||!s,"aria-busy":k,children:k?e.jsxs(e.Fragment,{children:[e.jsx(F.LoadingSpinner,{size:"sm",announce:!0,label:"Signing in"}),e.jsx("span",{children:"Signing in..."})]}):"Sign in"}),f&&e.jsxs("p",{className:"cedros-form-footer",children:["Don't have an account?"," ",e.jsx("button",{type:"button",className:"cedros-link",onClick:f,children:"Sign up"})]})]})}function ne({onSuccess:n,onSwitchToLogin:f,className:x=""}){const{config:u}=L.useCedrosLogin(),{register:p,isLoading:c,error:k,clearError:d}=_(),[h,m]=t.useState(""),[b,l]=t.useState(""),[g,v]=t.useState(""),[y,w]=t.useState(""),[r,s]=t.useState(null),[a,i]=t.useState(null),o=u.forms?.termsOfService,C=u.forms?.emailOptIn,I=o?.show??!1,A=o?.required??!0,j=o?.defaultChecked??!1,R=o?.label??"I agree to the Terms of Service",O=o?.url,M=te.sanitizeExternalUrl(O),U=C?.show??!1,$=C?.defaultChecked??!1,T=C?.label??"Send me updates and news",[S,q]=t.useState(j),[G,J]=t.useState($),D=g===y,Q=r?.isValid??!1,W=b&&g&&y&&D&&Q&&(!I||!A||S)&&!c,X=async E=>{if(E.preventDefault(),i(null),I&&A&&!S){i({code:"VALIDATION_ERROR",message:"You must agree to the Terms of Service to continue"});return}if(W)try{await p(b,g,h||void 0),n?.()}catch{}},ee=k||a,se=()=>{d(),i(null)};return e.jsxs("form",{onSubmit:X,className:`cedros-form ${x}`,children:[e.jsxs("div",{className:"cedros-form-field",children:[e.jsxs("label",{htmlFor:"name",className:"cedros-label",children:["Name ",e.jsx("span",{className:"cedros-optional",children:"(optional)"})]}),e.jsx("input",{id:"name",type:"text",className:"cedros-input",value:h,onChange:E=>m(E.target.value),placeholder:"Your name",autoComplete:"name",disabled:c})]}),e.jsxs("div",{className:"cedros-form-field",children:[e.jsx("label",{htmlFor:"register-email",className:"cedros-label",children:"Email"}),e.jsx("input",{id:"register-email",type:"email",className:"cedros-input",value:b,onChange:E=>l(E.target.value),placeholder:"you@example.com",required:!0,"aria-required":"true",autoComplete:"email",disabled:c})]}),e.jsx("div",{className:"cedros-form-field",children:e.jsx(B,{value:g,onChange:E=>v(E.target.value),placeholder:"Create a password",required:!0,autoComplete:"new-password",disabled:c,showStrengthMeter:!0,onValidationChange:s})}),e.jsxs("div",{className:"cedros-form-field",children:[e.jsx("label",{htmlFor:"confirm-password",className:"cedros-label",children:"Confirm Password"}),e.jsx("input",{id:"confirm-password",type:"password",className:"cedros-input",value:y,onChange:E=>w(E.target.value),placeholder:"Confirm your password",required:!0,"aria-required":"true",autoComplete:"new-password",disabled:c,"aria-invalid":y&&!D?"true":void 0,"aria-describedby":y&&!D?"confirm-password-error":void 0}),y&&!D&&e.jsx("p",{id:"confirm-password-error",className:"cedros-input-error",role:"alert",children:"Passwords do not match"})]}),I&&e.jsx("div",{className:"cedros-form-field cedros-checkbox-field",children:e.jsxs("label",{className:"cedros-checkbox-label",children:[e.jsx("input",{type:"checkbox",className:"cedros-checkbox",checked:S,onChange:E=>q(E.target.checked),disabled:c,"aria-required":A}),e.jsxs("span",{className:"cedros-checkbox-text",children:[M?e.jsxs(e.Fragment,{children:[R.replace("Terms of Service","").trim()||"I agree to the"," ",e.jsx("a",{href:M,target:"_blank",rel:"noopener noreferrer",className:"cedros-link",children:"Terms of Service"})]}):R,A&&e.jsx("span",{className:"cedros-required",children:"*"})]})]})}),U&&e.jsx("div",{className:"cedros-form-field cedros-checkbox-field",children:e.jsxs("label",{className:"cedros-checkbox-label",children:[e.jsx("input",{type:"checkbox",className:"cedros-checkbox",checked:G,onChange:E=>J(E.target.checked),disabled:c}),e.jsx("span",{className:"cedros-checkbox-text",children:T})]})}),e.jsx(z.ErrorMessage,{error:ee,onDismiss:se}),e.jsx("button",{type:"submit",className:"cedros-button cedros-button-primary cedros-button-md cedros-button-full",disabled:!W,"aria-busy":c,children:c?e.jsxs(e.Fragment,{children:[e.jsx(F.LoadingSpinner,{size:"sm",announce:!0,label:"Creating account"}),e.jsx("span",{children:"Creating account..."})]}):"Create account"}),f&&e.jsxs("p",{className:"cedros-form-footer",children:["Already have an account?"," ",e.jsx("button",{type:"button",className:"cedros-link",onClick:f,children:"Sign in"})]})]})}exports.EmailLoginForm=oe;exports.EmailRegisterForm=ne;exports.OtpInput=Z;exports.PasswordInput=B;exports.TotpVerify=Y;exports.useEmailAuth=_;exports.useInstantLink=H;exports.useRateLimiter=P;exports.useTotpVerify=K;
@@ -1 +0,0 @@
1
- {"version":3,"file":"EmailRegisterForm-B1DB-bqe.cjs","sources":["../src/hooks/useRateLimiter.ts","../src/hooks/useEmailAuth.ts","../src/hooks/useInstantLink.ts","../src/components/email/PasswordInput.tsx","../src/hooks/useTotpVerify.ts","../src/components/totp/OtpInput.tsx","../src/components/totp/TotpVerify.tsx","../src/components/email/EmailLoginForm.tsx","../src/components/email/EmailRegisterForm.tsx"],"sourcesContent":["import { useRef, useCallback, useState, useEffect } from 'react';\n\nexport interface UseRateLimiterOptions {\n /** Maximum number of attempts allowed within the window */\n maxAttempts?: number;\n /** Time window in milliseconds */\n windowMs?: number;\n /**\n * UI-25: Set to true to enable the 1s countdown interval for displaying\n * time-until-reset in the UI. When false (default), no interval is started,\n * saving resources for callers that don't display a countdown.\n */\n showCountdown?: boolean;\n}\n\nexport interface UseRateLimiterReturn {\n /**\n * Check if an action is allowed. Throws an error if rate limited.\n * Call this before performing the action.\n */\n checkLimit: () => void;\n /**\n * Check if an action is allowed without throwing.\n * Returns true if allowed, false if rate limited.\n */\n isAllowed: () => boolean;\n /**\n * Get remaining attempts in current window\n */\n getRemainingAttempts: () => number;\n /**\n * Get time until rate limit resets (in ms)\n */\n getTimeUntilReset: () => number;\n /**\n * Reset the rate limiter (e.g., after successful action)\n */\n reset: () => void;\n}\n\n/**\n * Rate limiting hook to prevent excessive API calls from the client.\n *\n * @param options - Rate limiter configuration\n * @returns Rate limiter functions\n *\n * @example\n * ```tsx\n * function LoginForm() {\n * const { checkLimit, getRemainingAttempts } = useRateLimiter({\n * maxAttempts: 5,\n * windowMs: 60000, // 1 minute\n * });\n *\n * const handleLogin = async () => {\n * try {\n * checkLimit(); // Throws if rate limited\n * await login(email, password);\n * } catch (err) {\n * if (err.message.includes('Too many attempts')) {\n * // Show rate limit message\n * }\n * }\n * };\n * }\n * ```\n */\nexport function useRateLimiter(options: UseRateLimiterOptions = {}): UseRateLimiterReturn {\n const { maxAttempts = 5, windowMs = 60000, showCountdown = false } = options;\n\n // Store timestamps of recent attempts\n const attemptsRef = useRef<number[]>([]);\n const [hasAttempts, setHasAttempts] = useState(false);\n const [, setTick] = useState(0);\n\n const bump = useCallback(() => {\n setTick((value) => value + 1);\n }, []);\n\n /**\n * Remove expired attempts from the tracking array (no state update).\n * Safe to call during render for getter functions.\n */\n const cleanupAttemptsArray = useCallback(() => {\n const now = Date.now();\n attemptsRef.current = attemptsRef.current.filter((timestamp) => now - timestamp < windowMs);\n }, [windowMs]);\n\n /**\n * Remove expired attempts AND update hasAttempts state.\n * M-04: Use functional setState to avoid hasAttempts dependency cascade.\n * Only call from event handlers and effects, NOT during render.\n */\n const cleanupExpiredAttempts = useCallback(() => {\n cleanupAttemptsArray();\n // Functional update avoids dependency on hasAttempts\n setHasAttempts((current) => (attemptsRef.current.length === 0 && current ? false : current));\n }, [cleanupAttemptsArray]);\n\n /**\n * Get the number of remaining attempts\n * Uses cleanupAttemptsArray (no state) so safe to call during render.\n */\n const getRemainingAttempts = useCallback((): number => {\n cleanupAttemptsArray();\n return Math.max(0, maxAttempts - attemptsRef.current.length);\n }, [cleanupAttemptsArray, maxAttempts]);\n\n /**\n * Get time until rate limit resets\n * Uses cleanupAttemptsArray (no state) so safe to call during render.\n */\n const getTimeUntilReset = useCallback((): number => {\n cleanupAttemptsArray();\n if (attemptsRef.current.length === 0) {\n return 0;\n }\n const oldestAttempt = attemptsRef.current[0];\n const resetTime = oldestAttempt + windowMs;\n return Math.max(0, resetTime - Date.now());\n }, [cleanupAttemptsArray, windowMs]);\n\n /**\n * Check if an action is allowed without throwing\n * Uses cleanupAttemptsArray (no state) so safe to call during render.\n */\n const isAllowed = useCallback((): boolean => {\n cleanupAttemptsArray();\n return attemptsRef.current.length < maxAttempts;\n }, [cleanupAttemptsArray, maxAttempts]);\n\n /**\n * Check rate limit and throw if exceeded\n */\n const checkLimit = useCallback((): void => {\n cleanupExpiredAttempts();\n\n if (attemptsRef.current.length >= maxAttempts) {\n const waitTime = getTimeUntilReset();\n const waitSeconds = Math.ceil(waitTime / 1000);\n throw new Error(\n `Too many attempts. Please wait ${waitSeconds} second${waitSeconds === 1 ? '' : 's'} before trying again.`\n );\n }\n\n // Record this attempt\n attemptsRef.current.push(Date.now());\n // M-04: Functional update avoids hasAttempts dependency\n setHasAttempts((current) => (current ? current : true));\n bump();\n }, [cleanupExpiredAttempts, maxAttempts, getTimeUntilReset, bump]);\n\n /**\n * Reset the rate limiter\n */\n const reset = useCallback((): void => {\n attemptsRef.current = [];\n // M-04: Functional update avoids hasAttempts dependency\n setHasAttempts((current) => (current ? false : current));\n bump();\n }, [bump]);\n\n // UI-25: Only start the 1s interval when the caller opts into countdown display.\n // This avoids a tick firing every second for all callers that don't show a countdown.\n useEffect(() => {\n if (!hasAttempts || !showCountdown) return;\n const intervalId = window.setInterval(() => {\n cleanupExpiredAttempts();\n bump();\n }, 1000);\n return () => {\n window.clearInterval(intervalId);\n };\n }, [hasAttempts, showCountdown, bump, cleanupExpiredAttempts]);\n\n return {\n checkLimit,\n isAllowed,\n getRemainingAttempts,\n getTimeUntilReset,\n reset,\n };\n}\n","import { useState, useCallback, useMemo } from 'react';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { ApiClient, handleApiError } from '../utils/apiClient';\nimport { validateEmail } from '../utils/validation';\nimport { useRateLimiter } from './useRateLimiter';\nimport type { AuthResponse, AuthError } from '../types';\nimport type { MfaRequiredResponse } from '../types';\n\nfunction isMfaRequiredResponse(\n response: AuthResponse | MfaRequiredResponse\n): response is MfaRequiredResponse {\n return 'mfaRequired' in response && response.mfaRequired === true;\n}\n\n/** Result when MFA verification is required */\nexport interface MfaRequiredResult {\n mfaRequired: true;\n mfaToken: string;\n email: string;\n userId: string;\n}\n\n/** Result of successful login (no TOTP required or after TOTP verification) */\nexport interface LoginSuccessResult {\n mfaRequired: false;\n response: AuthResponse;\n}\n\n/** Union type for login result */\nexport type LoginResult = MfaRequiredResult | LoginSuccessResult;\n\nexport interface UseEmailAuthReturn {\n /** Login - may return mfaRequired if 2FA is enabled */\n login: (email: string, password: string) => Promise<LoginResult>;\n register: (email: string, password: string, name?: string) => Promise<AuthResponse>;\n isLoading: boolean;\n error: AuthError | null;\n clearError: () => void;\n /**\n * Number of remaining login attempts before rate limiting.\n *\n * M-10: Snapshot Behavior\n * This value is a point-in-time snapshot computed at render time.\n * It may be briefly stale during rapid requests or concurrent renders.\n * For UI display only - actual rate limiting is enforced inside login/register.\n */\n remainingAttempts: number;\n /**\n * Time in ms until rate limit resets (0 if not rate limited).\n *\n * M-10: Snapshot Behavior\n * This value is a point-in-time snapshot computed at render time.\n * It may be briefly stale - use for UI display, not for logic decisions.\n */\n timeUntilReset: number;\n}\n\n/**\n * Hook for email/password authentication.\n *\n * @example\n * ```tsx\n * function LoginForm() {\n * const { login, isLoading, error } = useEmailAuth();\n *\n * const handleSubmit = async (e) => {\n * e.preventDefault();\n * try {\n * await login(email, password);\n * } catch (err) {\n * // Handle error\n * }\n * };\n * }\n * ```\n */\nexport function useEmailAuth(): UseEmailAuthReturn {\n const { config, _internal } = useCedrosLogin();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n\n // Rate limiter for login attempts (5 attempts per minute)\n const {\n checkLimit,\n getRemainingAttempts,\n getTimeUntilReset,\n reset: resetRateLimit,\n } = useRateLimiter({ maxAttempts: 5, windowMs: 60000 });\n\n const apiClient = useMemo(\n () =>\n new ApiClient({\n baseUrl: config.serverUrl,\n timeoutMs: config.requestTimeout,\n retryAttempts: config.retryAttempts,\n }),\n [config.serverUrl, config.requestTimeout, config.retryAttempts]\n );\n\n const callbacks = config.callbacks;\n const walletEnrollmentEnabled = config.features?.walletEnrollment !== false;\n const serverUrl = config.serverUrl;\n\n const login = useCallback(\n async (email: string, password: string): Promise<LoginResult> => {\n // Validate email format before API call\n if (!validateEmail(email)) {\n const validationError: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Please enter a valid email address',\n };\n setError(validationError);\n throw validationError;\n }\n\n // UI-7: Rate limit is checked BEFORE API call intentionally.\n // This prevents brute force attacks by limiting attempt frequency,\n // not just successful request frequency.\n try {\n checkLimit();\n } catch (err) {\n const rateLimitError: AuthError = {\n code: 'RATE_LIMITED',\n message: err instanceof Error ? err.message : 'Too many attempts',\n };\n setError(rateLimitError);\n throw rateLimitError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const data = await apiClient.post<AuthResponse | MfaRequiredResponse>('/login', {\n email,\n password,\n });\n\n // Check if MFA verification is required\n if (isMfaRequiredResponse(data)) {\n return {\n mfaRequired: true,\n mfaToken: data.mfaToken,\n email,\n userId: data.userId,\n };\n }\n\n // Normal login success\n const authResponse: AuthResponse = data;\n callbacks?.onLoginSuccess?.(authResponse.user, 'email');\n _internal?.handleLoginSuccess(authResponse.user, authResponse.tokens);\n resetRateLimit(); // Reset on successful login\n return {\n mfaRequired: false,\n response: authResponse,\n };\n } catch (err) {\n const authError = handleApiError(err, 'Login failed');\n setError(authError);\n throw authError;\n } finally {\n setIsLoading(false);\n }\n },\n [apiClient, callbacks, _internal, checkLimit, resetRateLimit]\n );\n\n const register = useCallback(\n async (email: string, password: string, name?: string): Promise<AuthResponse> => {\n // Validate email format before API call\n if (!validateEmail(email)) {\n const validationError: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Please enter a valid email address',\n };\n setError(validationError);\n throw validationError;\n }\n\n // UI-7: Rate limit is checked BEFORE API call intentionally.\n // This prevents brute force attacks by limiting attempt frequency,\n // not just successful request frequency.\n try {\n checkLimit();\n } catch (err) {\n const rateLimitError: AuthError = {\n code: 'RATE_LIMITED',\n message: err instanceof Error ? err.message : 'Too many attempts',\n };\n setError(rateLimitError);\n throw rateLimitError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const data = await apiClient.post<AuthResponse>('/register', { email, password, name });\n callbacks?.onLoginSuccess?.(data.user, 'email');\n _internal?.handleLoginSuccess(data.user, data.tokens);\n resetRateLimit(); // Reset on successful registration\n\n // Auto-enroll embedded wallet in background (don't block registration)\n // Uses password for Share A encryption. Recovery phrase can be retrieved later.\n // UI-09: In cookie mode the accessToken is absent; add a short delay to allow\n // the session cookie to be written before the enroll request is sent.\n if (walletEnrollmentEnabled) {\n const accessToken = data.tokens?.accessToken ?? '';\n const isCookieMode = !accessToken;\n const enrollDelay = isCookieMode ? 200 : 0;\n void new Promise<void>((resolve) => setTimeout(resolve, enrollDelay))\n .then(() => import('../utils/silentWalletEnroll'))\n .then(({ silentWalletEnroll }) =>\n silentWalletEnroll({\n password,\n serverUrl,\n accessToken,\n })\n )\n .then((result) => {\n if (!result.success) {\n // Log auto-enrollment failures for debugging\n console.warn('[useEmailAuth] Wallet auto-enrollment failed:', result.error);\n }\n })\n .catch((err) => {\n const message = err instanceof Error ? err.message : 'Unknown error';\n // Log enrollment errors for debugging\n console.warn('[useEmailAuth] Wallet auto-enrollment unavailable:', message);\n });\n }\n\n return data;\n } catch (err) {\n const authError = handleApiError(err, 'Registration failed');\n setError(authError);\n throw authError;\n } finally {\n setIsLoading(false);\n }\n },\n [\n apiClient,\n callbacks,\n _internal,\n checkLimit,\n resetRateLimit,\n serverUrl,\n walletEnrollmentEnabled,\n ]\n );\n\n const clearError = useCallback(() => setError(null), []);\n\n return {\n login,\n register,\n isLoading,\n error,\n clearError,\n // M-10: Point-in-time snapshots for UI display (see interface JSDoc)\n remainingAttempts: getRemainingAttempts(),\n timeUntilReset: getTimeUntilReset(),\n };\n}\n","import { useState, useCallback, useMemo } from 'react';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { validateEmail } from '../utils/validation';\nimport { useRateLimiter } from './useRateLimiter';\nimport { ApiClient, handleApiError } from '../utils/apiClient';\nimport type { AuthError, AuthResponse, MfaRequiredResponse } from '../types';\n\nfunction isMfaRequiredResponse(data: unknown): data is MfaRequiredResponse {\n return (\n typeof data === 'object' &&\n data !== null &&\n 'mfaRequired' in data &&\n (data as { mfaRequired?: unknown }).mfaRequired === true\n );\n}\n\nexport interface UseInstantLinkReturn {\n /** Send an instant link email to the given address */\n sendInstantLink: (email: string) => Promise<void>;\n /** Verify an instant link token and sign in */\n verifyInstantLink: (token: string) => Promise<AuthResponse | MfaRequiredResponse>;\n /** Whether a request is in progress */\n isLoading: boolean;\n /** Whether the instant link was sent successfully */\n isSuccess: boolean;\n /** Error from the last request */\n error: AuthError | null;\n /** Clear the error state */\n clearError: () => void;\n /** Reset to initial state */\n reset: () => void;\n /** Number of remaining attempts before rate limiting */\n remainingAttempts: number;\n}\n\n/**\n * Hook for instant link (passwordless) authentication.\n *\n * Sends an instant link email that allows the user to sign in\n * without entering their password.\n *\n * @example\n * ```tsx\n * function InstantLinkForm() {\n * const { sendInstantLink, isLoading, isSuccess, error } = useInstantLink();\n *\n * const handleSubmit = async (e) => {\n * e.preventDefault();\n * await sendInstantLink(email);\n * };\n *\n * if (isSuccess) {\n * return <p>Check your email for the sign-in link</p>;\n * }\n * }\n * ```\n */\nexport function useInstantLink(): UseInstantLinkReturn {\n const { config, _internal } = useCedrosLogin();\n const [isLoading, setIsLoading] = useState(false);\n const [isSuccess, setIsSuccess] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n\n const apiClient = useMemo(\n () =>\n new ApiClient({\n baseUrl: config.serverUrl,\n timeoutMs: config.requestTimeout,\n retryAttempts: config.retryAttempts,\n }),\n [config.serverUrl, config.requestTimeout, config.retryAttempts]\n );\n\n // Rate limiter for instant link attempts (3 attempts per 5 minutes)\n const { checkLimit, getRemainingAttempts } = useRateLimiter({\n maxAttempts: 3,\n windowMs: 300000,\n });\n\n const sendInstantLink = useCallback(\n async (email: string): Promise<void> => {\n // Validate email format before API call\n if (!validateEmail(email)) {\n const validationError: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Please enter a valid email address',\n };\n setError(validationError);\n throw validationError;\n }\n\n // Check rate limit before API call\n try {\n checkLimit();\n } catch (err) {\n const rateLimitError: AuthError = {\n code: 'RATE_LIMITED',\n message: err instanceof Error ? err.message : 'Too many attempts',\n };\n setError(rateLimitError);\n throw rateLimitError;\n }\n\n setIsLoading(true);\n setError(null);\n setIsSuccess(false);\n\n try {\n await apiClient.post('/instant-link', { email });\n setIsSuccess(true);\n } catch (err) {\n const authError = handleApiError(err, 'Failed to send sign-in link');\n setError(authError);\n throw authError;\n } finally {\n setIsLoading(false);\n }\n },\n [apiClient, checkLimit]\n );\n\n const verifyInstantLink = useCallback(\n async (token: string): Promise<AuthResponse | MfaRequiredResponse> => {\n if (!token || token.trim().length === 0) {\n const validationError: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Invalid or missing sign-in link token',\n };\n setError(validationError);\n throw validationError;\n }\n\n setIsLoading(true);\n setError(null);\n setIsSuccess(false);\n\n try {\n const data = await apiClient.post<AuthResponse | MfaRequiredResponse>(\n '/instant-link/verify',\n {\n token,\n }\n );\n\n if (isMfaRequiredResponse(data)) {\n return data;\n }\n\n // Successful login\n config.callbacks?.onLoginSuccess?.(data.user, 'email');\n _internal?.handleLoginSuccess(data.user, data.tokens);\n return data;\n } catch (err) {\n const authError = handleApiError(err, 'Failed to verify sign-in link');\n setError(authError);\n throw authError;\n } finally {\n setIsLoading(false);\n }\n },\n [apiClient, config.callbacks, _internal]\n );\n\n const clearError = useCallback(() => setError(null), []);\n\n const reset = useCallback(() => {\n setError(null);\n setIsSuccess(false);\n setIsLoading(false);\n }, []);\n\n return {\n sendInstantLink,\n verifyInstantLink,\n isLoading,\n isSuccess,\n error,\n clearError,\n reset,\n remainingAttempts: getRemainingAttempts(),\n };\n}\n","import { useState, useId, type InputHTMLAttributes } from 'react';\nimport { validatePassword } from '../../utils/validation';\nimport type { PasswordValidation } from '../../types';\n\nexport interface PasswordInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {\n label?: string;\n /** Action element shown on the right side of the label (e.g., \"Forgot password?\" link) */\n labelAction?: React.ReactNode;\n showStrengthMeter?: boolean;\n onValidationChange?: (validation: PasswordValidation) => void;\n error?: string;\n}\n\n/**\n * Password input with visibility toggle and optional strength meter\n */\nexport function PasswordInput({\n label = 'Password',\n labelAction,\n showStrengthMeter = false,\n onValidationChange,\n error,\n className = '',\n onChange,\n value,\n ...props\n}: PasswordInputProps) {\n const [showPassword, setShowPassword] = useState(false);\n const [validation, setValidation] = useState<PasswordValidation | null>(null);\n const inputId = useId();\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = e.target.value;\n\n if (showStrengthMeter || onValidationChange) {\n const newValidation = validatePassword(newValue);\n setValidation(newValidation);\n onValidationChange?.(newValidation);\n }\n\n onChange?.(e);\n };\n\n const strengthColors = {\n weak: 'var(--cedros-destructive, #ef4444)',\n fair: 'var(--cedros-warning, #f59e0b)',\n good: 'var(--cedros-success, #22c55e)',\n strong: 'var(--cedros-success, #22c55e)',\n };\n\n return (\n <div className={`cedros-password-input ${className}`}>\n <div className=\"cedros-label-row\">\n <label htmlFor={inputId} className=\"cedros-label\">\n {label}\n </label>\n {labelAction}\n </div>\n <div className=\"cedros-password-wrapper\">\n <input\n id={inputId}\n type={showPassword ? 'text' : 'password'}\n className=\"cedros-input\"\n onChange={handleChange}\n value={value}\n aria-invalid={error ? 'true' : undefined}\n aria-describedby={error ? `${inputId}-error` : undefined}\n {...props}\n />\n <button\n type=\"button\"\n className=\"cedros-password-toggle\"\n onClick={() => setShowPassword(!showPassword)}\n aria-label={showPassword ? 'Hide password' : 'Show password'}\n aria-pressed={showPassword}\n >\n {showPassword ? (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M2.5 10s3-6 7.5-6 7.5 6 7.5 6-3 6-7.5 6-7.5-6-7.5-6z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <circle cx=\"10\" cy=\"10\" r=\"2.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path d=\"M3 17L17 3\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n ) : (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M2.5 10s3-6 7.5-6 7.5 6 7.5 6-3 6-7.5 6-7.5-6-7.5-6z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <circle cx=\"10\" cy=\"10\" r=\"2.5\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n </svg>\n )}\n </button>\n </div>\n\n {error && (\n <p id={`${inputId}-error`} className=\"cedros-input-error\">\n {error}\n </p>\n )}\n\n {showStrengthMeter && validation && (value as string)?.length > 0 && (\n <div className=\"cedros-password-strength\">\n <div className=\"cedros-strength-bar\">\n <div\n className=\"cedros-strength-fill\"\n style={{\n width: `${\n validation.strength === 'weak'\n ? 25\n : validation.strength === 'fair'\n ? 50\n : validation.strength === 'good'\n ? 75\n : 100\n }%`,\n backgroundColor: strengthColors[validation.strength],\n }}\n />\n </div>\n <span className=\"cedros-strength-label\">{validation.strength}</span>\n </div>\n )}\n </div>\n );\n}\n","import { useState, useCallback, useMemo } from 'react';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { ApiClient, handleApiError } from '../utils/apiClient';\nimport { useRateLimiter } from './useRateLimiter';\nimport type { AuthError, AuthResponse, TotpVerifyState } from '../types';\n\nexport interface UseTotpVerifyReturn {\n /** Verification state */\n state: TotpVerifyState;\n /** Whether verification is in progress */\n isLoading: boolean;\n /** Error from the last request */\n error: AuthError | null;\n /** Verify MFA code during login */\n verifyTotp: (mfaToken: string, code: string) => Promise<AuthResponse>;\n /** Clear error state */\n clearError: () => void;\n /** Reset to initial state */\n reset: () => void;\n /** Number of remaining verification attempts before rate limiting */\n remainingAttempts: number;\n /** Time in ms until rate limit resets (0 if not rate limited) */\n timeUntilReset: number;\n}\n\n/**\n * Hook for verifying TOTP codes during the login flow.\n *\n * Used when a user has TOTP enabled and needs to provide\n * their 6-digit code after password authentication.\n *\n * @example\n * ```tsx\n * function TotpVerifyStep({ mfaToken }) {\n * const { verifyTotp, isLoading, error } = useTotpVerify();\n *\n * const handleVerify = async (code: string) => {\n * const response = await verifyTotp(mfaToken, code);\n * // User is now authenticated\n * };\n * }\n * ```\n */\nexport function useTotpVerify(): UseTotpVerifyReturn {\n const { config, _internal } = useCedrosLogin();\n const [state, setState] = useState<TotpVerifyState>('idle');\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n\n // Rate limiter for TOTP verification (5 attempts per 2 minutes)\n // Stricter than login to prevent brute force on short codes\n const {\n checkLimit,\n getRemainingAttempts,\n getTimeUntilReset,\n reset: resetRateLimit,\n } = useRateLimiter({ maxAttempts: 5, windowMs: 120000 });\n\n const apiClient = useMemo(\n () =>\n new ApiClient({\n baseUrl: config.serverUrl,\n timeoutMs: config.requestTimeout,\n retryAttempts: config.retryAttempts,\n }),\n [config.serverUrl, config.requestTimeout, config.retryAttempts]\n );\n\n const verifyTotp = useCallback(\n async (mfaToken: string, code: string): Promise<AuthResponse> => {\n // Validate code format (6 digits or recovery code)\n const isRecoveryCode =\n /^[A-Z0-9]{16}$/i.test(code) || /^[A-Z0-9]{4}(-[A-Z0-9]{4}){3}$/i.test(code);\n const isValidCode = /^\\d{6}$/.test(code) || isRecoveryCode;\n if (!isValidCode) {\n const validationError: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Please enter a valid 6-digit code or recovery code',\n };\n setError(validationError);\n throw validationError;\n }\n\n // Rate limit check before API call to prevent brute force\n try {\n checkLimit();\n } catch (err) {\n const rateLimitError: AuthError = {\n code: 'RATE_LIMITED',\n message: err instanceof Error ? err.message : 'Too many attempts',\n };\n setError(rateLimitError);\n throw rateLimitError;\n }\n\n setIsLoading(true);\n setError(null);\n setState('verifying');\n\n try {\n const response = await apiClient.post<AuthResponse>('/login/mfa', { mfaToken, code });\n\n setState('success');\n resetRateLimit(); // Reset on successful verification\n\n // Complete authentication via internal API\n if (_internal && response.user && response.tokens) {\n _internal.handleLoginSuccess(response.user, response.tokens);\n }\n\n return response;\n } catch (err) {\n const authError = handleApiError(err, 'Invalid verification code');\n setError(authError);\n setState('error');\n throw authError;\n } finally {\n setIsLoading(false);\n }\n },\n [apiClient, _internal, checkLimit, resetRateLimit]\n );\n\n const clearError = useCallback(() => setError(null), []);\n\n const reset = useCallback(() => {\n setError(null);\n setState('idle');\n setIsLoading(false);\n }, []);\n\n return {\n state,\n isLoading,\n error,\n verifyTotp,\n clearError,\n reset,\n // Point-in-time snapshots for UI display\n remainingAttempts: getRemainingAttempts(),\n timeUntilReset: getTimeUntilReset(),\n };\n}\n","/**\n * OTP Input component (shadcn-style)\n *\n * A 6-digit input with separate boxes for each digit,\n * designed for TOTP verification codes.\n */\n\nimport { useRef, useCallback, useState, useEffect, useId } from 'react';\n\n/** Number of OTP digits */\nconst OTP_LENGTH = 6;\n\nexport interface OtpInputProps {\n /** Current value (up to 6 digits) */\n value?: string;\n /** Called when the value changes */\n onChange?: (value: string) => void;\n /** Called when all 6 digits are entered */\n onComplete?: (value: string) => void;\n /** Whether the input is disabled */\n disabled?: boolean;\n /** Error message to display */\n error?: string;\n /** Auto-focus the first input on mount */\n autoFocus?: boolean;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * OTP input with separate boxes for each digit (shadcn pattern)\n *\n * Features:\n * - Auto-advances to next input on digit entry\n * - Backspace moves to previous input\n * - Supports paste of full code\n * - Numeric keyboard on mobile\n */\nexport function OtpInput({\n value = '',\n onChange,\n onComplete,\n disabled = false,\n error,\n autoFocus = false,\n className = '',\n}: OtpInputProps) {\n const inputRefs = useRef<(HTMLInputElement | null)[]>([]);\n const [localValue, setLocalValue] = useState(value.padEnd(OTP_LENGTH, ''));\n const id = useId();\n\n // Sync with controlled value\n useEffect(() => {\n setLocalValue(value.padEnd(OTP_LENGTH, ''));\n }, [value]);\n\n const focusInput = useCallback((index: number) => {\n if (index >= 0 && index < OTP_LENGTH) {\n inputRefs.current[index]?.focus();\n }\n }, []);\n\n const updateValue = useCallback(\n (newValue: string) => {\n const sanitized = newValue.replace(/\\D/g, '').slice(0, OTP_LENGTH);\n setLocalValue(sanitized.padEnd(OTP_LENGTH, ''));\n onChange?.(sanitized);\n\n if (sanitized.length === OTP_LENGTH) {\n onComplete?.(sanitized);\n }\n },\n [onChange, onComplete]\n );\n\n const handleChange = useCallback(\n (index: number, digit: string) => {\n if (!/^\\d?$/.test(digit)) return;\n\n const chars = localValue.split('');\n chars[index] = digit;\n const newValue = chars.join('').replace(/ /g, '');\n updateValue(newValue);\n\n // Move to next input if digit entered\n if (digit && index < OTP_LENGTH - 1) {\n focusInput(index + 1);\n }\n },\n [localValue, updateValue, focusInput]\n );\n\n const handleKeyDown = useCallback(\n (index: number, e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Backspace') {\n e.preventDefault();\n const chars = localValue.split('');\n\n if (chars[index] && chars[index] !== ' ') {\n // Clear current digit\n chars[index] = ' ';\n updateValue(chars.join('').replace(/ /g, ''));\n } else if (index > 0) {\n // Move to previous and clear it\n chars[index - 1] = ' ';\n updateValue(chars.join('').replace(/ /g, ''));\n focusInput(index - 1);\n }\n } else if (e.key === 'ArrowLeft' && index > 0) {\n e.preventDefault();\n focusInput(index - 1);\n } else if (e.key === 'ArrowRight' && index < OTP_LENGTH - 1) {\n e.preventDefault();\n focusInput(index + 1);\n }\n },\n [localValue, updateValue, focusInput]\n );\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent) => {\n e.preventDefault();\n const pasted = e.clipboardData.getData('text');\n const digits = pasted.replace(/\\D/g, '').slice(0, OTP_LENGTH);\n if (digits) {\n updateValue(digits);\n // Focus the next empty slot or the last one\n focusInput(Math.min(digits.length, OTP_LENGTH - 1));\n }\n },\n [updateValue, focusInput]\n );\n\n const handleFocus = useCallback((e: React.FocusEvent<HTMLInputElement>) => {\n e.target.select();\n }, []);\n\n // Auto-focus first input\n useEffect(() => {\n if (autoFocus && !disabled) {\n inputRefs.current[0]?.focus();\n }\n }, [autoFocus, disabled]);\n\n return (\n <div className={`cedros-otp-input ${className}`}>\n <div className=\"cedros-otp-slots\" role=\"group\" aria-label=\"One-time password\">\n {Array.from({ length: OTP_LENGTH }).map((_, index) => (\n <input\n key={index}\n ref={(el) => {\n inputRefs.current[index] = el;\n }}\n id={`${id}-${index}`}\n type=\"text\"\n inputMode=\"numeric\"\n pattern=\"[0-9]*\"\n maxLength={1}\n className={`cedros-otp-slot ${error ? 'cedros-otp-slot-error' : ''}`}\n value={localValue[index] === ' ' ? '' : localValue[index] || ''}\n onChange={(e) => handleChange(index, e.target.value)}\n onKeyDown={(e) => handleKeyDown(index, e)}\n onPaste={handlePaste}\n onFocus={handleFocus}\n disabled={disabled}\n autoComplete=\"one-time-code\"\n aria-label={`Digit ${index + 1}`}\n aria-invalid={error ? 'true' : undefined}\n />\n ))}\n </div>\n {error && (\n <p className=\"cedros-otp-error\" role=\"alert\">\n {error}\n </p>\n )}\n </div>\n );\n}\n","/**\n * TOTP Verification component for login flow\n *\n * Displayed when a user with 2FA enabled needs to\n * enter their verification code to complete login.\n */\n\nimport { useState } from 'react';\nimport { useTotpVerify } from '../../hooks/useTotpVerify';\nimport { OtpInput } from './OtpInput';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\n\nexport interface TotpVerifyProps {\n /** Temporary token from password authentication */\n mfaToken: string;\n /** Email address (for display) */\n email?: string;\n /** Called when verification succeeds */\n onSuccess?: () => void;\n /** Called when user wants to go back */\n onBack?: () => void;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * Two-factor authentication verification for login.\n *\n * Accepts 6-digit codes from authenticator apps\n * or recovery codes for account recovery.\n */\nexport function TotpVerify({\n mfaToken,\n email,\n onSuccess,\n onBack,\n className = '',\n}: TotpVerifyProps) {\n const { verifyTotp, isLoading, error, clearError } = useTotpVerify();\n const [code, setCode] = useState('');\n const [useBackupCode, setUseBackupCode] = useState(false);\n const [backupCode, setBackupCode] = useState('');\n\n const handleVerify = async (verifyCode?: string) => {\n const codeToVerify = verifyCode || (useBackupCode ? backupCode : code);\n if (!codeToVerify) return;\n\n try {\n await verifyTotp(mfaToken, codeToVerify);\n onSuccess?.();\n } catch {\n // Error handled by hook, clear the input\n if (useBackupCode) {\n setBackupCode('');\n } else {\n setCode('');\n }\n }\n };\n\n const handleOtpComplete = (value: string) => {\n handleVerify(value);\n };\n\n const toggleBackupCode = () => {\n setUseBackupCode(!useBackupCode);\n clearError();\n setCode('');\n setBackupCode('');\n };\n\n return (\n <div className={`cedros-totp-verify ${className}`}>\n <div className=\"cedros-totp-verify-header\">\n <svg\n className=\"cedros-totp-verify-icon\"\n width=\"48\"\n height=\"48\"\n viewBox=\"0 0 48 48\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <rect x=\"8\" y=\"20\" width=\"32\" height=\"24\" rx=\"4\" stroke=\"currentColor\" strokeWidth=\"2\" />\n <path\n d=\"M16 20V14a8 8 0 1 1 16 0v6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n <circle cx=\"24\" cy=\"32\" r=\"3\" fill=\"currentColor\" />\n </svg>\n <h3 className=\"cedros-totp-title\">Two-factor authentication</h3>\n <p className=\"cedros-totp-description\">\n {useBackupCode\n ? 'Enter one of your recovery codes to sign in.'\n : 'Enter the 6-digit code from your authenticator app.'}\n </p>\n {email && <p className=\"cedros-totp-email\">{email}</p>}\n </div>\n\n {useBackupCode ? (\n <div className=\"cedros-totp-backup-input\">\n <input\n type=\"text\"\n className={`cedros-input ${error ? 'cedros-input-error' : ''}`}\n placeholder=\"Enter recovery code\"\n value={backupCode}\n onChange={(e) => {\n setBackupCode(e.target.value.toUpperCase());\n clearError();\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && backupCode) {\n handleVerify();\n }\n }}\n disabled={isLoading}\n autoFocus\n autoComplete=\"one-time-code\"\n />\n {error && (\n <p className=\"cedros-input-error\" role=\"alert\">\n {error.message}\n </p>\n )}\n </div>\n ) : (\n <OtpInput\n value={code}\n onChange={(value) => {\n setCode(value);\n clearError();\n }}\n onComplete={handleOtpComplete}\n disabled={isLoading}\n error={error?.message}\n autoFocus\n />\n )}\n\n <button\n type=\"button\"\n className=\"cedros-button cedros-button-primary cedros-button-md cedros-button-full\"\n onClick={() => handleVerify()}\n disabled={isLoading || (useBackupCode ? !backupCode : code.length !== 6)}\n >\n {isLoading ? (\n <>\n <LoadingSpinner size=\"sm\" />\n <span>Verifying...</span>\n </>\n ) : (\n 'Verify'\n )}\n </button>\n\n <div className=\"cedros-totp-verify-footer\">\n <button\n type=\"button\"\n className=\"cedros-link cedros-link-sm\"\n onClick={toggleBackupCode}\n disabled={isLoading}\n >\n {useBackupCode ? 'Use authenticator app' : 'Use a recovery code'}\n </button>\n\n {onBack && (\n <>\n <span className=\"cedros-totp-verify-divider\">•</span>\n <button\n type=\"button\"\n className=\"cedros-link cedros-link-sm\"\n onClick={onBack}\n disabled={isLoading}\n >\n Back to login\n </button>\n </>\n )}\n </div>\n </div>\n );\n}\n","import { useState, type FormEvent } from 'react';\nimport { useCedrosLogin } from '../../context/useCedrosLogin';\nimport { useEmailAuth } from '../../hooks/useEmailAuth';\nimport { useInstantLink } from '../../hooks/useInstantLink';\nimport { PasswordInput } from './PasswordInput';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\nimport { ErrorMessage } from '../shared/ErrorMessage';\nimport { TotpVerify } from '../totp/TotpVerify';\n// COMP-01: Email validation now handled by useInstantLink hook internally\n\nexport interface EmailLoginFormProps {\n onSuccess?: () => void;\n onSwitchToRegister?: () => void;\n /** Called when user clicks \"Forgot password?\" (only in 'reset' mode) */\n onForgotPassword?: () => void;\n className?: string;\n}\n\n/**\n * Email/password login form\n */\nexport function EmailLoginForm({\n onSuccess,\n onSwitchToRegister,\n onForgotPassword,\n className = '',\n}: EmailLoginFormProps) {\n const { config } = useCedrosLogin();\n const { login, isLoading, error, clearError } = useEmailAuth();\n const {\n sendInstantLink,\n isLoading: isInstantLinkLoading,\n isSuccess: isInstantLinkSuccess,\n error: instantLinkError,\n clearError: clearInstantLinkError,\n reset: resetInstantLink,\n } = useInstantLink();\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n // MFA state for 2FA flow\n const [mfaToken, setMfaToken] = useState<string | null>(null);\n const [mfaEmail, setMfaEmail] = useState<string>('');\n\n const forgotPasswordMode = config.forms?.forgotPassword?.mode\n ?? (config.features?.instantLink ? 'instantLink' : 'reset');\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n try {\n const result = await login(email, password);\n if (result.mfaRequired) {\n // MFA verification needed\n setMfaToken(result.mfaToken);\n setMfaEmail(result.email);\n } else {\n // Login successful\n onSuccess?.();\n }\n } catch {\n // Error is handled by the hook\n }\n };\n\n const handleTotpSuccess = () => {\n setMfaToken(null);\n setMfaEmail('');\n onSuccess?.();\n };\n\n const handleTotpBack = () => {\n setMfaToken(null);\n setMfaEmail('');\n setPassword(''); // Clear password for security\n };\n\n const handleForgotPassword = async () => {\n if (forgotPasswordMode === 'instantLink') {\n // COMP-01: In instant link mode, call sendInstantLink directly.\n // The hook validates email and sets error state if invalid.\n try {\n await sendInstantLink(email);\n } catch {\n // Error handled by hook's error state\n }\n } else {\n // In reset mode, call the callback\n onForgotPassword?.();\n }\n };\n\n // Show TOTP verification step\n if (mfaToken) {\n return (\n <TotpVerify\n mfaToken={mfaToken}\n email={mfaEmail}\n onSuccess={handleTotpSuccess}\n onBack={handleTotpBack}\n className={className}\n />\n );\n }\n\n // Show instant link success state\n if (isInstantLinkSuccess) {\n return (\n <div className={`cedros-instant-link-success ${className}`}>\n <svg\n className=\"cedros-success-icon\"\n width=\"48\"\n height=\"48\"\n viewBox=\"0 0 48 48\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <circle cx=\"24\" cy=\"24\" r=\"22\" stroke=\"currentColor\" strokeWidth=\"2\" />\n <path\n d=\"M14 24l7 7 13-13\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n <h3 className=\"cedros-success-title\">Check your email</h3>\n <p className=\"cedros-success-message\">\n We sent a sign-in link to <strong>{email}</strong>. Click the link to sign in.\n </p>\n <button\n type=\"button\"\n className=\"cedros-button cedros-button-md cedros-button-outline\"\n onClick={resetInstantLink}\n >\n Back to login\n </button>\n </div>\n );\n }\n\n const combinedError = error || instantLinkError;\n const combinedClearError = () => {\n clearError();\n clearInstantLinkError();\n };\n const isAnyLoading = isLoading || isInstantLinkLoading;\n\n return (\n <form onSubmit={handleSubmit} className={`cedros-form ${className}`}>\n <div className=\"cedros-form-field\">\n <label htmlFor=\"email\" className=\"cedros-label\">\n Email\n </label>\n <input\n id=\"email\"\n type=\"email\"\n className=\"cedros-input\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"you@example.com\"\n required\n aria-required=\"true\"\n autoComplete=\"email\"\n disabled={isAnyLoading}\n />\n </div>\n\n <div className=\"cedros-form-field\">\n <PasswordInput\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n placeholder=\"Enter your password\"\n required\n autoComplete=\"current-password\"\n disabled={isAnyLoading}\n labelAction={\n onForgotPassword || forgotPasswordMode === 'instantLink' ? (\n <button\n type=\"button\"\n className=\"cedros-link cedros-link-sm\"\n onClick={handleForgotPassword}\n disabled={isInstantLinkLoading}\n >\n {isInstantLinkLoading ? 'Sending...' : 'Forgot your password?'}\n </button>\n ) : undefined\n }\n />\n </div>\n\n <ErrorMessage error={combinedError} onDismiss={combinedClearError} />\n\n <button\n type=\"submit\"\n className=\"cedros-button cedros-button-primary cedros-button-md cedros-button-full\"\n disabled={isAnyLoading || !email || !password}\n aria-busy={isLoading}\n >\n {isLoading ? (\n <>\n <LoadingSpinner size=\"sm\" announce label=\"Signing in\" />\n <span>Signing in...</span>\n </>\n ) : (\n 'Sign in'\n )}\n </button>\n\n {onSwitchToRegister && (\n <p className=\"cedros-form-footer\">\n Don&apos;t have an account?{' '}\n <button type=\"button\" className=\"cedros-link\" onClick={onSwitchToRegister}>\n Sign up\n </button>\n </p>\n )}\n </form>\n );\n}\n","import { useState, type FormEvent } from 'react';\nimport { useCedrosLogin } from '../../context/useCedrosLogin';\nimport { useEmailAuth } from '../../hooks/useEmailAuth';\nimport { PasswordInput } from './PasswordInput';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\nimport { ErrorMessage } from '../shared/ErrorMessage';\nimport { sanitizeExternalUrl } from '../../utils/sanitization';\nimport type { PasswordValidation, AuthError } from '../../types';\n\nexport interface EmailRegisterFormProps {\n onSuccess?: () => void;\n onSwitchToLogin?: () => void;\n className?: string;\n}\n\n/** Values collected from the registration form (for callback) */\nexport interface RegistrationData {\n termsAccepted: boolean;\n emailOptIn: boolean;\n}\n\n/**\n * Email/password registration form\n */\nexport function EmailRegisterForm({\n onSuccess,\n onSwitchToLogin,\n className = '',\n}: EmailRegisterFormProps) {\n const { config } = useCedrosLogin();\n const { register, isLoading, error, clearError } = useEmailAuth();\n const [name, setName] = useState('');\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [confirmPassword, setConfirmPassword] = useState('');\n const [passwordValidation, setPasswordValidation] = useState<PasswordValidation | null>(null);\n const [termsError, setTermsError] = useState<AuthError | null>(null);\n\n // Get form configuration\n const termsConfig = config.forms?.termsOfService;\n const emailOptInConfig = config.forms?.emailOptIn;\n\n const showTerms = termsConfig?.show ?? false;\n const termsRequired = termsConfig?.required ?? true;\n const termsDefaultChecked = termsConfig?.defaultChecked ?? false;\n const termsLabel = termsConfig?.label ?? 'I agree to the Terms of Service';\n const termsUrl = termsConfig?.url;\n const safeTermsUrl = sanitizeExternalUrl(termsUrl);\n\n const showEmailOptIn = emailOptInConfig?.show ?? false;\n const emailOptInDefaultChecked = emailOptInConfig?.defaultChecked ?? false;\n const emailOptInLabel = emailOptInConfig?.label ?? 'Send me updates and news';\n\n // Initialize checkbox states with defaults\n const [termsAccepted, setTermsAccepted] = useState(termsDefaultChecked);\n const [emailOptIn, setEmailOptIn] = useState(emailOptInDefaultChecked);\n\n const passwordsMatch = password === confirmPassword;\n const isPasswordValid = passwordValidation?.isValid ?? false;\n\n // Terms must be accepted if shown and required\n const termsValid = !showTerms || !termsRequired || termsAccepted;\n\n const canSubmit =\n email &&\n password &&\n confirmPassword &&\n passwordsMatch &&\n isPasswordValid &&\n termsValid &&\n !isLoading;\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n\n // Clear any previous terms error\n setTermsError(null);\n\n // Validate terms if required\n if (showTerms && termsRequired && !termsAccepted) {\n setTermsError({\n code: 'VALIDATION_ERROR',\n message: 'You must agree to the Terms of Service to continue',\n });\n return;\n }\n\n if (!canSubmit) return;\n\n try {\n // Note: termsAccepted and emailOptIn values can be passed to the backend\n // via the register function if needed. For now, we call register with the\n // standard params, but the backend could be extended to accept these values.\n await register(email, password, name || undefined);\n onSuccess?.();\n } catch {\n // Error is handled by the hook\n }\n };\n\n const combinedError = error || termsError;\n const combinedClearError = () => {\n clearError();\n setTermsError(null);\n };\n\n return (\n <form onSubmit={handleSubmit} className={`cedros-form ${className}`}>\n <div className=\"cedros-form-field\">\n <label htmlFor=\"name\" className=\"cedros-label\">\n Name <span className=\"cedros-optional\">(optional)</span>\n </label>\n <input\n id=\"name\"\n type=\"text\"\n className=\"cedros-input\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"Your name\"\n autoComplete=\"name\"\n disabled={isLoading}\n />\n </div>\n\n <div className=\"cedros-form-field\">\n <label htmlFor=\"register-email\" className=\"cedros-label\">\n Email\n </label>\n <input\n id=\"register-email\"\n type=\"email\"\n className=\"cedros-input\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"you@example.com\"\n required\n aria-required=\"true\"\n autoComplete=\"email\"\n disabled={isLoading}\n />\n </div>\n\n <div className=\"cedros-form-field\">\n <PasswordInput\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n placeholder=\"Create a password\"\n required\n autoComplete=\"new-password\"\n disabled={isLoading}\n showStrengthMeter\n onValidationChange={setPasswordValidation}\n />\n </div>\n\n <div className=\"cedros-form-field\">\n <label htmlFor=\"confirm-password\" className=\"cedros-label\">\n Confirm Password\n </label>\n <input\n id=\"confirm-password\"\n type=\"password\"\n className=\"cedros-input\"\n value={confirmPassword}\n onChange={(e) => setConfirmPassword(e.target.value)}\n placeholder=\"Confirm your password\"\n required\n aria-required=\"true\"\n autoComplete=\"new-password\"\n disabled={isLoading}\n aria-invalid={confirmPassword && !passwordsMatch ? 'true' : undefined}\n aria-describedby={\n confirmPassword && !passwordsMatch ? 'confirm-password-error' : undefined\n }\n />\n {confirmPassword && !passwordsMatch && (\n <p id=\"confirm-password-error\" className=\"cedros-input-error\" role=\"alert\">\n Passwords do not match\n </p>\n )}\n </div>\n\n {/* Terms of Service checkbox */}\n {showTerms && (\n <div className=\"cedros-form-field cedros-checkbox-field\">\n <label className=\"cedros-checkbox-label\">\n <input\n type=\"checkbox\"\n className=\"cedros-checkbox\"\n checked={termsAccepted}\n onChange={(e) => setTermsAccepted(e.target.checked)}\n disabled={isLoading}\n aria-required={termsRequired}\n />\n <span className=\"cedros-checkbox-text\">\n {safeTermsUrl ? (\n <>\n {termsLabel.replace('Terms of Service', '').trim() || 'I agree to the'}{' '}\n <a\n href={safeTermsUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"cedros-link\"\n >\n Terms of Service\n </a>\n </>\n ) : (\n termsLabel\n )}\n {termsRequired && <span className=\"cedros-required\">*</span>}\n </span>\n </label>\n </div>\n )}\n\n {/* Email opt-in checkbox */}\n {showEmailOptIn && (\n <div className=\"cedros-form-field cedros-checkbox-field\">\n <label className=\"cedros-checkbox-label\">\n <input\n type=\"checkbox\"\n className=\"cedros-checkbox\"\n checked={emailOptIn}\n onChange={(e) => setEmailOptIn(e.target.checked)}\n disabled={isLoading}\n />\n <span className=\"cedros-checkbox-text\">{emailOptInLabel}</span>\n </label>\n </div>\n )}\n\n <ErrorMessage error={combinedError} onDismiss={combinedClearError} />\n\n <button\n type=\"submit\"\n className=\"cedros-button cedros-button-primary cedros-button-md cedros-button-full\"\n disabled={!canSubmit}\n aria-busy={isLoading}\n >\n {isLoading ? (\n <>\n <LoadingSpinner size=\"sm\" announce label=\"Creating account\" />\n <span>Creating account...</span>\n </>\n ) : (\n 'Create account'\n )}\n </button>\n\n {onSwitchToLogin && (\n <p className=\"cedros-form-footer\">\n Already have an account?{' '}\n <button type=\"button\" className=\"cedros-link\" onClick={onSwitchToLogin}>\n Sign in\n </button>\n </p>\n )}\n </form>\n );\n}\n"],"names":["useRateLimiter","options","maxAttempts","windowMs","showCountdown","attemptsRef","useRef","hasAttempts","setHasAttempts","useState","setTick","bump","useCallback","value","cleanupAttemptsArray","now","timestamp","cleanupExpiredAttempts","current","getRemainingAttempts","getTimeUntilReset","resetTime","isAllowed","checkLimit","waitTime","waitSeconds","reset","useEffect","intervalId","isMfaRequiredResponse","response","useEmailAuth","config","_internal","useCedrosLogin","isLoading","setIsLoading","error","setError","resetRateLimit","apiClient","useMemo","ApiClient","callbacks","walletEnrollmentEnabled","serverUrl","login","email","password","validateEmail","validationError","err","rateLimitError","data","authResponse","authError","handleApiError","register","name","accessToken","enrollDelay","resolve","silentWalletEnroll","result","message","clearError","useInstantLink","isSuccess","setIsSuccess","sendInstantLink","verifyInstantLink","token","PasswordInput","label","labelAction","showStrengthMeter","onValidationChange","className","onChange","props","showPassword","setShowPassword","validation","setValidation","inputId","useId","handleChange","e","newValue","newValidation","validatePassword","strengthColors","jsxs","jsx","useTotpVerify","state","setState","verifyTotp","mfaToken","code","isRecoveryCode","OTP_LENGTH","OtpInput","onComplete","disabled","autoFocus","inputRefs","localValue","setLocalValue","id","focusInput","index","updateValue","sanitized","digit","chars","handleKeyDown","handlePaste","digits","handleFocus","_","el","TotpVerify","onSuccess","onBack","setCode","useBackupCode","setUseBackupCode","backupCode","setBackupCode","handleVerify","verifyCode","codeToVerify","handleOtpComplete","toggleBackupCode","Fragment","LoadingSpinner","EmailLoginForm","onSwitchToRegister","onForgotPassword","isInstantLinkLoading","isInstantLinkSuccess","instantLinkError","clearInstantLinkError","resetInstantLink","setEmail","setPassword","setMfaToken","mfaEmail","setMfaEmail","forgotPasswordMode","handleSubmit","handleTotpSuccess","handleTotpBack","handleForgotPassword","combinedError","combinedClearError","isAnyLoading","ErrorMessage","EmailRegisterForm","onSwitchToLogin","setName","confirmPassword","setConfirmPassword","passwordValidation","setPasswordValidation","termsError","setTermsError","termsConfig","emailOptInConfig","showTerms","termsRequired","termsDefaultChecked","termsLabel","termsUrl","safeTermsUrl","sanitizeExternalUrl","showEmailOptIn","emailOptInDefaultChecked","emailOptInLabel","termsAccepted","setTermsAccepted","emailOptIn","setEmailOptIn","passwordsMatch","isPasswordValid","canSubmit"],"mappings":"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"}