@cedros/login-react 0.0.11 → 0.0.13

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 (428) hide show
  1. package/README.md +68 -0
  2. package/dist/AdminDepositList-Cx0xRwES.js +305 -0
  3. package/dist/AdminDepositList-Cx0xRwES.js.map +1 -0
  4. package/dist/AdminDepositList-UEcyRZkA.cjs +1 -0
  5. package/dist/AdminDepositList-UEcyRZkA.cjs.map +1 -0
  6. package/dist/AdminUserDetail-BzEIdNJh.cjs +1 -0
  7. package/dist/AdminUserDetail-BzEIdNJh.cjs.map +1 -0
  8. package/dist/AdminUserDetail-DHFDzY8B.js +1195 -0
  9. package/dist/AdminUserDetail-DHFDzY8B.js.map +1 -0
  10. package/dist/AdminWithdrawalHistory-0yxtMh6q.cjs +1 -0
  11. package/dist/AdminWithdrawalHistory-0yxtMh6q.cjs.map +1 -0
  12. package/dist/AdminWithdrawalHistory-BGjfrIe3.js +904 -0
  13. package/dist/AdminWithdrawalHistory-BGjfrIe3.js.map +1 -0
  14. package/dist/AuthenticationSettings-5Vi7Ib_A.cjs +1 -0
  15. package/dist/AuthenticationSettings-5Vi7Ib_A.cjs.map +1 -0
  16. package/dist/AuthenticationSettings-BPAh1my6.cjs +1 -0
  17. package/dist/AuthenticationSettings-BPAh1my6.cjs.map +1 -0
  18. package/dist/AuthenticationSettings-CJg8CJY9.js +9 -0
  19. package/dist/AuthenticationSettings-CJg8CJY9.js.map +1 -0
  20. package/dist/AuthenticationSettings-CR_i6TTS.js +495 -0
  21. package/dist/AuthenticationSettings-CR_i6TTS.js.map +1 -0
  22. package/dist/AutosaveStatus-CYkC2aI_.cjs +1 -0
  23. package/dist/AutosaveStatus-CYkC2aI_.cjs.map +1 -0
  24. package/dist/AutosaveStatus-N4uNS6-2.js +1497 -0
  25. package/dist/AutosaveStatus-N4uNS6-2.js.map +1 -0
  26. package/dist/CreditSystemSettings-BnAOK_tT.cjs +1 -0
  27. package/dist/CreditSystemSettings-BnAOK_tT.cjs.map +1 -0
  28. package/dist/CreditSystemSettings-CIf_SfJq.js +210 -0
  29. package/dist/CreditSystemSettings-CIf_SfJq.js.map +1 -0
  30. package/dist/CreditSystemSettings-CePYGgev.js +9 -0
  31. package/dist/CreditSystemSettings-CePYGgev.js.map +1 -0
  32. package/dist/CreditSystemSettings-Ck5WIMp3.cjs +1 -0
  33. package/dist/CreditSystemSettings-Ck5WIMp3.cjs.map +1 -0
  34. package/dist/{DepositsSection-BH5K162Q.js → DepositsSection-DA89uR9A.js} +5 -5
  35. package/dist/{DepositsSection-BH5K162Q.js.map → DepositsSection-DA89uR9A.js.map} +1 -1
  36. package/dist/DepositsSection-i6XdhLNs.cjs +1 -0
  37. package/dist/{DepositsSection-DpRn0koq.cjs.map → DepositsSection-i6XdhLNs.cjs.map} +1 -1
  38. package/dist/EmailRegisterForm-BrDL3BZy.js +927 -0
  39. package/dist/EmailRegisterForm-BrDL3BZy.js.map +1 -0
  40. package/dist/EmailRegisterForm-CxktR-4J.cjs +1 -0
  41. package/dist/EmailRegisterForm-CxktR-4J.cjs.map +1 -0
  42. package/dist/EmailSettings-B8xwgd6_.cjs +1 -0
  43. package/dist/EmailSettings-B8xwgd6_.cjs.map +1 -0
  44. package/dist/{AuthenticationSettings-DlVILxY4.js → EmailSettings-Bna7Z53E.js} +3 -3
  45. package/dist/EmailSettings-Bna7Z53E.js.map +1 -0
  46. package/dist/EmailSettings-DZywTTRq.cjs +1 -0
  47. package/dist/EmailSettings-DZywTTRq.cjs.map +1 -0
  48. package/dist/EmailSettings-DbMDfVaM.js +17 -0
  49. package/dist/EmailSettings-DbMDfVaM.js.map +1 -0
  50. package/dist/{EmbeddedWalletSettings-Bff6raAT.js → EmbeddedWalletSettings-ANbhj3Lt.js} +3 -3
  51. package/dist/EmbeddedWalletSettings-ANbhj3Lt.js.map +1 -0
  52. package/dist/EmbeddedWalletSettings-BEztqO19.js +79 -0
  53. package/dist/EmbeddedWalletSettings-BEztqO19.js.map +1 -0
  54. package/dist/EmbeddedWalletSettings-D6M7pwgk.cjs +1 -0
  55. package/dist/EmbeddedWalletSettings-D6M7pwgk.cjs.map +1 -0
  56. package/dist/EmbeddedWalletSettings-DivEPn39.cjs +1 -0
  57. package/dist/EmbeddedWalletSettings-DivEPn39.cjs.map +1 -0
  58. package/dist/ErrorMessage-CHbYbVi2.cjs +1 -0
  59. package/dist/ErrorMessage-CHbYbVi2.cjs.map +1 -0
  60. package/dist/ErrorMessage-CcEK0pYO.js +64 -0
  61. package/dist/ErrorMessage-CcEK0pYO.js.map +1 -0
  62. package/dist/{GoogleLoginButton-BzHr545L.js → GoogleLoginButton-B3uRMJ_n.js} +4 -3
  63. package/dist/{GoogleLoginButton-BzHr545L.js.map → GoogleLoginButton-B3uRMJ_n.js.map} +1 -1
  64. package/dist/GoogleLoginButton-BydKswn4.cjs +1 -0
  65. package/dist/{GoogleLoginButton-DoAdOqb3.cjs.map → GoogleLoginButton-BydKswn4.cjs.map} +1 -1
  66. package/dist/LoadingSpinner-6vml-zwr.js +79 -0
  67. package/dist/LoadingSpinner-6vml-zwr.js.map +1 -0
  68. package/dist/LoadingSpinner-d6sSxgQN.cjs +1 -0
  69. package/dist/LoadingSpinner-d6sSxgQN.cjs.map +1 -0
  70. package/dist/PermissionsSection-BGaj_sI7.js +1026 -0
  71. package/dist/PermissionsSection-BGaj_sI7.js.map +1 -0
  72. package/dist/PermissionsSection-CKXXDfqi.cjs +1 -0
  73. package/dist/PermissionsSection-CKXXDfqi.cjs.map +1 -0
  74. package/dist/ServerSettings-B2RKhJtZ.js +84 -0
  75. package/dist/ServerSettings-B2RKhJtZ.js.map +1 -0
  76. package/dist/ServerSettings-BZXlm1BX.cjs +1 -0
  77. package/dist/ServerSettings-BZXlm1BX.cjs.map +1 -0
  78. package/dist/{ServerSettings-UIVR0R4l.js → ServerSettings-Bqm4-bt2.js} +3 -3
  79. package/dist/ServerSettings-Bqm4-bt2.js.map +1 -0
  80. package/dist/ServerSettings-DZUKo6By.cjs +1 -0
  81. package/dist/ServerSettings-DZUKo6By.cjs.map +1 -0
  82. package/dist/SettingsPageLayout-COSYLMu7.cjs +1 -0
  83. package/dist/SettingsPageLayout-COSYLMu7.cjs.map +1 -0
  84. package/dist/SettingsPageLayout-DpgNEkuu.js +50 -0
  85. package/dist/SettingsPageLayout-DpgNEkuu.js.map +1 -0
  86. package/dist/{SolanaLoginButton-C-CfZxAZ.js → SolanaLoginButton-C_u9OppS.js} +5 -4
  87. package/dist/{SolanaLoginButton-C-CfZxAZ.js.map → SolanaLoginButton-C_u9OppS.js.map} +1 -1
  88. package/dist/SolanaLoginButton-fAW7kRUu.cjs +1 -0
  89. package/dist/{SolanaLoginButton-CPzms0kf.cjs.map → SolanaLoginButton-fAW7kRUu.cjs.map} +1 -1
  90. package/dist/StatsBar-BX-hHtTq.js +66 -0
  91. package/dist/StatsBar-BX-hHtTq.js.map +1 -0
  92. package/dist/StatsBar-DTUZCwDD.cjs +1 -0
  93. package/dist/StatsBar-DTUZCwDD.cjs.map +1 -0
  94. package/dist/{TeamSection-DnJudC38.js → TeamSection-CvrCoa9D.js} +27 -26
  95. package/dist/TeamSection-CvrCoa9D.js.map +1 -0
  96. package/dist/TeamSection-DlUD5kp5.cjs +1 -0
  97. package/dist/TeamSection-DlUD5kp5.cjs.map +1 -0
  98. package/dist/UsersSection-C2U8Tb7V.cjs +1 -0
  99. package/dist/{UsersSection-Ce7xVKfp.cjs.map → UsersSection-C2U8Tb7V.cjs.map} +1 -1
  100. package/dist/{UsersSection-mOOjcUEv.js → UsersSection-Dbh9PTSA.js} +17 -15
  101. package/dist/{UsersSection-mOOjcUEv.js.map → UsersSection-Dbh9PTSA.js.map} +1 -1
  102. package/dist/WebhookSettings-BT5q6AZ8.js +17 -0
  103. package/dist/WebhookSettings-BT5q6AZ8.js.map +1 -0
  104. package/dist/WebhookSettings-BWl_wsvg.cjs +1 -0
  105. package/dist/WebhookSettings-BWl_wsvg.cjs.map +1 -0
  106. package/dist/WebhookSettings-DXNH5bal.cjs +1 -0
  107. package/dist/WebhookSettings-DXNH5bal.cjs.map +1 -0
  108. package/dist/{WebhookSettings-D0i0JhQD.js → WebhookSettings-bUg2u_p0.js} +4 -4
  109. package/dist/WebhookSettings-bUg2u_p0.js.map +1 -0
  110. package/dist/WithdrawalsSection-BL_LOUq8.cjs +1 -0
  111. package/dist/{WithdrawalsSection-igRQJfjj.cjs.map → WithdrawalsSection-BL_LOUq8.cjs.map} +1 -1
  112. package/dist/WithdrawalsSection-CN-lLnqX.js +20 -0
  113. package/dist/{WithdrawalsSection-Grebjjks.js.map → WithdrawalsSection-CN-lLnqX.js.map} +1 -1
  114. package/dist/admin-only.cjs +1 -0
  115. package/dist/admin-only.cjs.map +1 -0
  116. package/dist/{admin/types.d.ts → admin-only.d.ts} +228 -167
  117. package/dist/admin-only.js +8 -0
  118. package/dist/admin-only.js.map +1 -0
  119. package/dist/apiClient-B2JxVPlH.js +216 -0
  120. package/dist/apiClient-B2JxVPlH.js.map +1 -0
  121. package/dist/apiClient-CTTKhsYb.cjs +1 -0
  122. package/dist/apiClient-CTTKhsYb.cjs.map +1 -0
  123. package/dist/assets/argon2Worker-Bi5TuQvD.js.map +1 -1
  124. package/dist/email-only.cjs +1 -1
  125. package/dist/email-only.d.ts +634 -16
  126. package/dist/email-only.js +16 -13
  127. package/dist/email-only.js.map +1 -1
  128. package/dist/google-only.cjs +1 -1
  129. package/dist/google-only.d.ts +543 -13
  130. package/dist/google-only.js +11 -8
  131. package/dist/google-only.js.map +1 -1
  132. package/dist/index.cjs +2061 -1
  133. package/dist/index.cjs.map +1 -1
  134. package/dist/index.d.ts +5007 -144
  135. package/dist/index.js +13507 -116
  136. package/dist/index.js.map +1 -1
  137. package/dist/login-react.css +1 -1
  138. package/dist/plugin-5qRh-YhX.js +596 -0
  139. package/dist/plugin-5qRh-YhX.js.map +1 -0
  140. package/dist/plugin-BtYBW6JY.cjs +1 -0
  141. package/dist/plugin-BtYBW6JY.cjs.map +1 -0
  142. package/dist/sanitization-Bo_tn-L2.cjs +1 -0
  143. package/dist/sanitization-Bo_tn-L2.cjs.map +1 -0
  144. package/dist/sanitization-CQ-H1MSg.js +39 -0
  145. package/dist/sanitization-CQ-H1MSg.js.map +1 -0
  146. package/dist/shamir-AeLLfw0p.cjs +1 -0
  147. package/dist/shamir-AeLLfw0p.cjs.map +1 -0
  148. package/dist/{solanaKeypair-BlXol3nh.js → shamir-B0wConeK.js} +765 -757
  149. package/dist/shamir-B0wConeK.js.map +1 -0
  150. package/dist/silentWalletEnroll-B8pgdKZO.cjs +1 -0
  151. package/dist/silentWalletEnroll-B8pgdKZO.cjs.map +1 -0
  152. package/dist/silentWalletEnroll-DR2kPw7W.js +41 -0
  153. package/dist/silentWalletEnroll-DR2kPw7W.js.map +1 -0
  154. package/dist/solana-only.cjs +1 -1
  155. package/dist/solana-only.d.ts +594 -13
  156. package/dist/solana-only.js +12 -9
  157. package/dist/solana-only.js.map +1 -1
  158. package/dist/style.d.ts +1 -0
  159. package/dist/useAdminDeposits-BDY5KJ0-.js +151 -0
  160. package/dist/useAdminDeposits-BDY5KJ0-.js.map +1 -0
  161. package/dist/useAdminDeposits-Dvx3_UUE.cjs +1 -0
  162. package/dist/useAdminDeposits-Dvx3_UUE.cjs.map +1 -0
  163. package/dist/{ErrorMessage-DU2VBb85.js → useAuth-Bge6KaWN.js} +954 -1226
  164. package/dist/useAuth-Bge6KaWN.js.map +1 -0
  165. package/dist/useAuth-DhIDTLRd.cjs +1 -0
  166. package/dist/useAuth-DhIDTLRd.cjs.map +1 -0
  167. package/dist/useOrgs-Be3KH4ib.js +215 -0
  168. package/dist/useOrgs-Be3KH4ib.js.map +1 -0
  169. package/dist/useOrgs-CVbacmaQ.cjs +1 -0
  170. package/dist/useOrgs-CVbacmaQ.cjs.map +1 -0
  171. package/dist/useSystemSettings-D9Cr7ZTl.cjs +1 -0
  172. package/dist/useSystemSettings-D9Cr7ZTl.cjs.map +1 -0
  173. package/dist/useSystemSettings-DN5YqfNq.js +97 -0
  174. package/dist/useSystemSettings-DN5YqfNq.js.map +1 -0
  175. package/dist/{validation-BebL7hMF.js → validation-B8kMV3BL.js} +1 -1
  176. package/dist/{validation-BebL7hMF.js.map → validation-B8kMV3BL.js.map} +1 -1
  177. package/dist/{validation-BeXIfuHB.cjs → validation-BuGQrA-K.cjs} +1 -1
  178. package/dist/{validation-BeXIfuHB.cjs.map → validation-BuGQrA-K.cjs.map} +1 -1
  179. package/package.json +11 -1
  180. package/dist/AuthenticationSettings-D8oXHkM6.cjs +0 -1
  181. package/dist/AuthenticationSettings-D8oXHkM6.cjs.map +0 -1
  182. package/dist/AuthenticationSettings-DlVILxY4.js.map +0 -1
  183. package/dist/CreditSystemSettings-Bv6u9lTs.js +0 -9
  184. package/dist/CreditSystemSettings-Bv6u9lTs.js.map +0 -1
  185. package/dist/CreditSystemSettings-D45pwDZM.cjs +0 -1
  186. package/dist/CreditSystemSettings-D45pwDZM.cjs.map +0 -1
  187. package/dist/DepositsSection-DpRn0koq.cjs +0 -1
  188. package/dist/EmailRegisterForm-C0PStlj5.js +0 -961
  189. package/dist/EmailRegisterForm-C0PStlj5.js.map +0 -1
  190. package/dist/EmailRegisterForm-DaPLGws2.cjs +0 -1
  191. package/dist/EmailRegisterForm-DaPLGws2.cjs.map +0 -1
  192. package/dist/EmailSettings-DdjoMO_c.cjs +0 -1
  193. package/dist/EmailSettings-DdjoMO_c.cjs.map +0 -1
  194. package/dist/EmailSettings-khmiWqhx.js +0 -9
  195. package/dist/EmailSettings-khmiWqhx.js.map +0 -1
  196. package/dist/EmbeddedWalletSettings-Bff6raAT.js.map +0 -1
  197. package/dist/EmbeddedWalletSettings-C5qkJtAr.cjs +0 -1
  198. package/dist/EmbeddedWalletSettings-C5qkJtAr.cjs.map +0 -1
  199. package/dist/ErrorMessage-BXHiYibN.cjs +0 -1
  200. package/dist/ErrorMessage-BXHiYibN.cjs.map +0 -1
  201. package/dist/ErrorMessage-DU2VBb85.js.map +0 -1
  202. package/dist/GoogleLoginButton-DoAdOqb3.cjs +0 -1
  203. package/dist/ServerSettings-BpZhkxh6.cjs +0 -1
  204. package/dist/ServerSettings-BpZhkxh6.cjs.map +0 -1
  205. package/dist/ServerSettings-UIVR0R4l.js.map +0 -1
  206. package/dist/SolanaLoginButton-CPzms0kf.cjs +0 -1
  207. package/dist/TeamSection-BoGqQhD5.cjs +0 -1
  208. package/dist/TeamSection-BoGqQhD5.cjs.map +0 -1
  209. package/dist/TeamSection-DnJudC38.js.map +0 -1
  210. package/dist/UsersSection-Ce7xVKfp.cjs +0 -1
  211. package/dist/WebhookSettings-Cx-BxzNQ.cjs +0 -1
  212. package/dist/WebhookSettings-Cx-BxzNQ.cjs.map +0 -1
  213. package/dist/WebhookSettings-D0i0JhQD.js.map +0 -1
  214. package/dist/WithdrawalsSection-Grebjjks.js +0 -20
  215. package/dist/WithdrawalsSection-igRQJfjj.cjs +0 -1
  216. package/dist/admin/AdminShell.d.ts +0 -38
  217. package/dist/admin/icons.d.ts +0 -2
  218. package/dist/admin/index.d.ts +0 -10
  219. package/dist/admin/plugin.d.ts +0 -3
  220. package/dist/admin/sections/AuthenticationSettings.d.ts +0 -3
  221. package/dist/admin/sections/CreditSystemSettings.d.ts +0 -3
  222. package/dist/admin/sections/DepositsSection.d.ts +0 -3
  223. package/dist/admin/sections/EmailSettings.d.ts +0 -3
  224. package/dist/admin/sections/EmbeddedWalletSettings.d.ts +0 -3
  225. package/dist/admin/sections/FeatureSettings.d.ts +0 -3
  226. package/dist/admin/sections/InvitesSection.d.ts +0 -3
  227. package/dist/admin/sections/MembersSection.d.ts +0 -3
  228. package/dist/admin/sections/ServerSettings.d.ts +0 -3
  229. package/dist/admin/sections/SettingsSections.d.ts +0 -7
  230. package/dist/admin/sections/TeamSection.d.ts +0 -3
  231. package/dist/admin/sections/UsersSection.d.ts +0 -3
  232. package/dist/admin/sections/WebhookSettings.d.ts +0 -3
  233. package/dist/admin/sections/WithdrawalsSection.d.ts +0 -3
  234. package/dist/components/LoginButton.d.ts +0 -23
  235. package/dist/components/LoginForm.d.ts +0 -9
  236. package/dist/components/LoginModal.d.ts +0 -9
  237. package/dist/components/admin/AdminUserDetail.d.ts +0 -23
  238. package/dist/components/admin/AdminUserList.d.ts +0 -21
  239. package/dist/components/admin/CedrosAdminDashboard.d.ts +0 -52
  240. package/dist/components/admin/PermissionsSection.d.ts +0 -7
  241. package/dist/components/admin/ProfileDropdown.d.ts +0 -34
  242. package/dist/components/admin/SetupWizard.d.ts +0 -30
  243. package/dist/components/admin/StatsBar.d.ts +0 -17
  244. package/dist/components/admin/SystemSettings.d.ts +0 -19
  245. package/dist/components/admin/settings/AuthenticationSettings.d.ts +0 -4
  246. package/dist/components/admin/settings/AutosaveStatus.d.ts +0 -6
  247. package/dist/components/admin/settings/CreditSystemSettings.d.ts +0 -6
  248. package/dist/components/admin/settings/EmailSettings.d.ts +0 -4
  249. package/dist/components/admin/settings/EmbeddedWalletSettings.d.ts +0 -4
  250. package/dist/components/admin/settings/FeatureSettings.d.ts +0 -4
  251. package/dist/components/admin/settings/MessagingSettings.d.ts +0 -4
  252. package/dist/components/admin/settings/SecuritySettings.d.ts +0 -4
  253. package/dist/components/admin/settings/ServerSettings.d.ts +0 -4
  254. package/dist/components/admin/settings/SettingsPageLayout.d.ts +0 -16
  255. package/dist/components/admin/settings/SsoProvidersSettings.d.ts +0 -4
  256. package/dist/components/admin/settings/WebhookSettings.d.ts +0 -4
  257. package/dist/components/admin/settings/index.d.ts +0 -31
  258. package/dist/components/admin/settings/settingsInputs.d.ts +0 -79
  259. package/dist/components/admin/settings/settingsMetadata.d.ts +0 -18
  260. package/dist/components/apple/AppleLoginButton.d.ts +0 -29
  261. package/dist/components/deposit/CreditBalance.d.ts +0 -19
  262. package/dist/components/deposit/DepositFlow.d.ts +0 -118
  263. package/dist/components/deposit/FeeConfigDisplay.d.ts +0 -15
  264. package/dist/components/deposit/History.d.ts +0 -21
  265. package/dist/components/deposit/TieredAmountSlider.d.ts +0 -19
  266. package/dist/components/deposit/TokenSelector.d.ts +0 -23
  267. package/dist/components/deposit/admin/AdminDepositList.d.ts +0 -21
  268. package/dist/components/deposit/admin/AdminDepositStats.d.ts +0 -15
  269. package/dist/components/deposit/admin/AdminPrivacyPeriodDeposits.d.ts +0 -19
  270. package/dist/components/deposit/admin/AdminWithdrawalHistory.d.ts +0 -19
  271. package/dist/components/deposit/admin/AdminWithdrawalQueue.d.ts +0 -23
  272. package/dist/components/deposit/admin/AdminWithdrawalStats.d.ts +0 -10
  273. package/dist/components/deposit/admin/FeatureDisabledMessage.d.ts +0 -15
  274. package/dist/components/deposit/admin/PrivacySystemStatus.d.ts +0 -15
  275. package/dist/components/deposit/admin/featureDisabled.d.ts +0 -14
  276. package/dist/components/deposit/admin/index.d.ts +0 -22
  277. package/dist/components/deposit/index.d.ts +0 -12
  278. package/dist/components/deposit/tierUtils.d.ts +0 -8
  279. package/dist/components/deposit/tokens.d.ts +0 -19
  280. package/dist/components/email/EmailLoginForm.d.ts +0 -11
  281. package/dist/components/email/EmailRegisterForm.d.ts +0 -14
  282. package/dist/components/email/ForgotPasswordForm.d.ts +0 -17
  283. package/dist/components/email/PasswordInput.d.ts +0 -14
  284. package/dist/components/email/ResetPasswordForm.d.ts +0 -22
  285. package/dist/components/google/GoogleLoginButton.d.ts +0 -12
  286. package/dist/components/invites/InviteForm.d.ts +0 -38
  287. package/dist/components/invites/InviteList.d.ts +0 -40
  288. package/dist/components/members/MemberList.d.ts +0 -47
  289. package/dist/components/org/CreateOrgForm.d.ts +0 -7
  290. package/dist/components/org/OrgAvatar.d.ts +0 -7
  291. package/dist/components/org/OrgListView.d.ts +0 -9
  292. package/dist/components/org/OrgSelector.d.ts +0 -52
  293. package/dist/components/org/OrgSwitcher.d.ts +0 -47
  294. package/dist/components/org/icons.d.ts +0 -8
  295. package/dist/components/profile/UserProfileSettings.d.ts +0 -35
  296. package/dist/components/profile/index.d.ts +0 -2
  297. package/dist/components/sessions/SessionList.d.ts +0 -33
  298. package/dist/components/shared/ErrorBoundary.d.ts +0 -38
  299. package/dist/components/shared/ErrorMessage.d.ts +0 -14
  300. package/dist/components/shared/LoadingSpinner.d.ts +0 -16
  301. package/dist/components/solana/SolanaLoginButton.d.ts +0 -49
  302. package/dist/components/templates/FullPageLayout.d.ts +0 -40
  303. package/dist/components/templates/SplitPageLayout.d.ts +0 -44
  304. package/dist/components/templates/index.d.ts +0 -4
  305. package/dist/components/totp/OtpInput.d.ts +0 -32
  306. package/dist/components/totp/QrCode.d.ts +0 -21
  307. package/dist/components/totp/TotpSettings.d.ts +0 -38
  308. package/dist/components/totp/TotpSetup.d.ts +0 -23
  309. package/dist/components/totp/TotpVerify.d.ts +0 -25
  310. package/dist/components/totp/index.d.ts +0 -10
  311. package/dist/components/wallet/CapabilityWarning.d.ts +0 -11
  312. package/dist/components/wallet/PasskeyPrompt.d.ts +0 -34
  313. package/dist/components/wallet/RecoveryPhraseDisplay.d.ts +0 -18
  314. package/dist/components/wallet/RecoveryPhraseInput.d.ts +0 -21
  315. package/dist/components/wallet/WalletAddressRow.d.ts +0 -10
  316. package/dist/components/wallet/WalletEnrollment.d.ts +0 -15
  317. package/dist/components/wallet/WalletManager.d.ts +0 -9
  318. package/dist/components/wallet/WalletRecovery.d.ts +0 -19
  319. package/dist/components/wallet/WalletStatus.d.ts +0 -28
  320. package/dist/components/wallet/WalletUnlock.d.ts +0 -23
  321. package/dist/components/wallet/index.d.ts +0 -23
  322. package/dist/components/webauthn/PasskeyLoginButton.d.ts +0 -8
  323. package/dist/context/CedrosLoginContext.d.ts +0 -24
  324. package/dist/context/CedrosLoginProvider.d.ts +0 -17
  325. package/dist/context/EmbeddedWalletExposure.d.ts +0 -19
  326. package/dist/context/useCedrosLogin.d.ts +0 -12
  327. package/dist/crypto/aesGcm.d.ts +0 -89
  328. package/dist/crypto/argon2.d.ts +0 -65
  329. package/dist/crypto/argon2Worker.d.ts +0 -1
  330. package/dist/crypto/argon2WorkerClient.d.ts +0 -28
  331. package/dist/crypto/bip39.d.ts +0 -106
  332. package/dist/crypto/capabilities.d.ts +0 -35
  333. package/dist/crypto/entropy.d.ts +0 -56
  334. package/dist/crypto/hkdf.d.ts +0 -38
  335. package/dist/crypto/index.d.ts +0 -30
  336. package/dist/crypto/secureWipe.d.ts +0 -71
  337. package/dist/crypto/shamir.d.ts +0 -52
  338. package/dist/crypto/solanaKeypair.d.ts +0 -63
  339. package/dist/crypto/types.d.ts +0 -134
  340. package/dist/crypto/webauthnPrf.d.ts +0 -108
  341. package/dist/hooks/useAdminDeposits.d.ts +0 -10
  342. package/dist/hooks/useAdminUsers.d.ts +0 -28
  343. package/dist/hooks/useAppleAuth.d.ts +0 -52
  344. package/dist/hooks/useAuth.d.ts +0 -34
  345. package/dist/hooks/useAuthSession.d.ts +0 -19
  346. package/dist/hooks/useAuthorize.d.ts +0 -62
  347. package/dist/hooks/useCredits.d.ts +0 -11
  348. package/dist/hooks/useDashboardPermissions.d.ts +0 -45
  349. package/dist/hooks/useDeposit.d.ts +0 -16
  350. package/dist/hooks/useEmailAuth.d.ts +0 -60
  351. package/dist/hooks/useGoogleAuth.d.ts +0 -67
  352. package/dist/hooks/useInstantLink.d.ts +0 -42
  353. package/dist/hooks/useInvites.d.ts +0 -57
  354. package/dist/hooks/useMembers.d.ts +0 -52
  355. package/dist/hooks/useOrgs.d.ts +0 -49
  356. package/dist/hooks/usePasswordReset.d.ts +0 -32
  357. package/dist/hooks/usePendingRecovery.d.ts +0 -34
  358. package/dist/hooks/useProfile.d.ts +0 -35
  359. package/dist/hooks/useRateLimiter.d.ts +0 -58
  360. package/dist/hooks/useServerFeatures.d.ts +0 -55
  361. package/dist/hooks/useSessions.d.ts +0 -45
  362. package/dist/hooks/useSettingsAutosave.d.ts +0 -29
  363. package/dist/hooks/useSetup.d.ts +0 -25
  364. package/dist/hooks/useSolanaAuth.d.ts +0 -30
  365. package/dist/hooks/useSsoProviders.d.ts +0 -52
  366. package/dist/hooks/useSystemSettings.d.ts +0 -47
  367. package/dist/hooks/useThemeManager.d.ts +0 -11
  368. package/dist/hooks/useTotp.d.ts +0 -52
  369. package/dist/hooks/useTotpVerify.d.ts +0 -38
  370. package/dist/hooks/useTransactionSigning.d.ts +0 -45
  371. package/dist/hooks/useWallet.d.ts +0 -10
  372. package/dist/hooks/useWalletDiscovery.d.ts +0 -24
  373. package/dist/hooks/useWalletEnrollment.d.ts +0 -9
  374. package/dist/hooks/useWalletMaterial.d.ts +0 -10
  375. package/dist/hooks/useWalletRecovery.d.ts +0 -9
  376. package/dist/hooks/useWalletSigning.d.ts +0 -31
  377. package/dist/hooks/useWebAuthn.d.ts +0 -25
  378. package/dist/i18n/I18nProvider.d.ts +0 -16
  379. package/dist/i18n/context.d.ts +0 -6
  380. package/dist/i18n/index.d.ts +0 -5
  381. package/dist/i18n/translations.d.ts +0 -66
  382. package/dist/i18n/useI18n.d.ts +0 -9
  383. package/dist/index-BI9Bj9DF.js +0 -19650
  384. package/dist/index-BI9Bj9DF.js.map +0 -1
  385. package/dist/index-CDRTfEJz.cjs +0 -2061
  386. package/dist/index-CDRTfEJz.cjs.map +0 -1
  387. package/dist/silentWalletEnroll-C3JRAD9_.js +0 -42
  388. package/dist/silentWalletEnroll-C3JRAD9_.js.map +0 -1
  389. package/dist/silentWalletEnroll-DRYQAQfg.cjs +0 -1
  390. package/dist/silentWalletEnroll-DRYQAQfg.cjs.map +0 -1
  391. package/dist/solanaKeypair-BlXol3nh.js.map +0 -1
  392. package/dist/solanaKeypair-C-lIR1JY.cjs +0 -1
  393. package/dist/solanaKeypair-C-lIR1JY.cjs.map +0 -1
  394. package/dist/types/adminUser.d.ts +0 -168
  395. package/dist/types/auth.d.ts +0 -122
  396. package/dist/types/config.d.ts +0 -266
  397. package/dist/types/deposit.d.ts +0 -490
  398. package/dist/types/index.d.ts +0 -13
  399. package/dist/types/invite.d.ts +0 -71
  400. package/dist/types/member.d.ts +0 -45
  401. package/dist/types/org.d.ts +0 -133
  402. package/dist/types/profile.d.ts +0 -56
  403. package/dist/types/session.d.ts +0 -28
  404. package/dist/types/setup.d.ts +0 -47
  405. package/dist/types/systemSettings.d.ts +0 -85
  406. package/dist/types/totp.d.ts +0 -52
  407. package/dist/types/wallet.d.ts +0 -309
  408. package/dist/utils/adminUserApi.d.ts +0 -60
  409. package/dist/utils/apiClient.d.ts +0 -78
  410. package/dist/utils/cryptoShim.d.ts +0 -17
  411. package/dist/utils/csrf.d.ts +0 -1
  412. package/dist/utils/deviceDetection.d.ts +0 -17
  413. package/dist/utils/embeddedWallet.d.ts +0 -75
  414. package/dist/utils/inviteApi.d.ts +0 -31
  415. package/dist/utils/memberApi.d.ts +0 -23
  416. package/dist/utils/orgApi.d.ts +0 -36
  417. package/dist/utils/profileApi.d.ts +0 -26
  418. package/dist/utils/sanitization.d.ts +0 -66
  419. package/dist/utils/sessionApi.d.ts +0 -16
  420. package/dist/utils/setupApi.d.ts +0 -21
  421. package/dist/utils/silentWalletEnroll.d.ts +0 -41
  422. package/dist/utils/systemSettingsApi.d.ts +0 -18
  423. package/dist/utils/tabSync.d.ts +0 -46
  424. package/dist/utils/tokenManager.d.ts +0 -107
  425. package/dist/utils/unlockCredential.d.ts +0 -5
  426. package/dist/utils/validation.d.ts +0 -48
  427. package/dist/utils/walletDetection.d.ts +0 -23
  428. package/dist/utils/webauthnJson.d.ts +0 -21
@@ -0,0 +1,79 @@
1
+ import { jsxs as s, jsx as e } from "react/jsx-runtime";
2
+ import { useEffect as v } from "react";
3
+ import { L as S } from "./LoadingSpinner-6vml-zwr.js";
4
+ import { E } from "./ErrorMessage-CcEK0pYO.js";
5
+ import { u as y, A as k, S as _ } from "./AutosaveStatus-N4uNS6-2.js";
6
+ const l = ["wallet_recovery_mode"];
7
+ function O({ className: r }) {
8
+ const {
9
+ settings: d,
10
+ edits: m,
11
+ isLoading: u,
12
+ autosaveStatus: f,
13
+ autosaveError: p,
14
+ error: o,
15
+ fetchSettings: c,
16
+ handleChange: n,
17
+ getEffectiveValue: g
18
+ } = y();
19
+ v(() => {
20
+ c();
21
+ }, [c]);
22
+ const h = (d.features ?? []).filter((i) => l.includes(i.key)).sort((i, w) => l.indexOf(i.key) - l.indexOf(w.key)), t = g("feature_wallet_signing") === "true", b = () => {
23
+ n("feature_wallet_signing", t ? "false" : "true");
24
+ }, a = g("feature_user_withdrawals") === "true", N = () => {
25
+ n("feature_user_withdrawals", a ? "false" : "true");
26
+ };
27
+ return u && Object.keys(d).length === 0 ? /* @__PURE__ */ s("div", { className: `cedros-system-settings cedros-system-settings-loading ${r ?? ""}`, children: [
28
+ /* @__PURE__ */ e(S, {}),
29
+ /* @__PURE__ */ e("span", { children: "Loading settings..." })
30
+ ] }) : o ? /* @__PURE__ */ e("div", { className: `cedros-system-settings ${r ?? ""}`, children: /* @__PURE__ */ e(E, { error: o.message }) }) : /* @__PURE__ */ s("div", { className: `cedros-system-settings ${r ?? ""}`, children: [
31
+ /* @__PURE__ */ s("div", { className: "cedros-settings-page-header", children: [
32
+ /* @__PURE__ */ s("div", { className: "cedros-settings-page-header-content", children: [
33
+ /* @__PURE__ */ e("h2", { className: "cedros-settings-page-title", children: "Embedded Wallet" }),
34
+ /* @__PURE__ */ e("p", { className: "cedros-settings-page-description", children: "Configure the embedded wallet for transaction signing." })
35
+ ] }),
36
+ /* @__PURE__ */ s("div", { className: "cedros-settings-page-header-actions", children: [
37
+ /* @__PURE__ */ s(
38
+ "button",
39
+ {
40
+ type: "button",
41
+ role: "switch",
42
+ "aria-checked": t,
43
+ className: `cedros-toggle ${t ? "cedros-toggle-on" : "cedros-toggle-off"}`,
44
+ onClick: b,
45
+ children: [
46
+ /* @__PURE__ */ e("span", { className: "cedros-toggle-track", children: /* @__PURE__ */ e("span", { className: "cedros-toggle-thumb" }) }),
47
+ /* @__PURE__ */ e("span", { className: "cedros-toggle-label", children: t ? "Enabled" : "Disabled" })
48
+ ]
49
+ }
50
+ ),
51
+ /* @__PURE__ */ e(k, { status: f, error: p })
52
+ ] })
53
+ ] }),
54
+ t && /* @__PURE__ */ e("div", { className: "cedros-settings-subsection", children: /* @__PURE__ */ s("div", { className: "cedros-settings-subsection-header", children: [
55
+ /* @__PURE__ */ s("div", { children: [
56
+ /* @__PURE__ */ e("h3", { className: "cedros-settings-subsection-title", children: "User Withdrawals" }),
57
+ /* @__PURE__ */ e("p", { className: "cedros-settings-subsection-description", children: "Allow users to withdraw SOL/SPL tokens from their embedded wallet to external addresses." })
58
+ ] }),
59
+ /* @__PURE__ */ s(
60
+ "button",
61
+ {
62
+ type: "button",
63
+ role: "switch",
64
+ "aria-checked": a,
65
+ className: `cedros-toggle ${a ? "cedros-toggle-on" : "cedros-toggle-off"}`,
66
+ onClick: N,
67
+ children: [
68
+ /* @__PURE__ */ e("span", { className: "cedros-toggle-track", children: /* @__PURE__ */ e("span", { className: "cedros-toggle-thumb" }) }),
69
+ /* @__PURE__ */ e("span", { className: "cedros-toggle-label", children: a ? "Enabled" : "Disabled" })
70
+ ]
71
+ }
72
+ )
73
+ ] }) }),
74
+ /* @__PURE__ */ e("div", { className: "cedros-admin-tab-content", children: h.length === 0 ? /* @__PURE__ */ e("div", { className: "cedros-system-settings-empty", children: /* @__PURE__ */ e("p", { children: "No additional settings available." }) }) : /* @__PURE__ */ e(_, { settings: h, edits: m, onChange: n }) })
75
+ ] });
76
+ }
77
+ export {
78
+ O as E
79
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmbeddedWalletSettings-BEztqO19.js","sources":["../src/components/admin/settings/EmbeddedWalletSettings.tsx"],"sourcesContent":["/**\n * Embedded Wallet settings page - enable/disable and configure recovery\n */\nimport { useEffect } from 'react';\nimport { LoadingSpinner } from '../../shared/LoadingSpinner';\nimport { ErrorMessage } from '../../shared/ErrorMessage';\nimport { useSettingsAutosave } from '../../../hooks/useSettingsAutosave';\nimport { SettingsSection } from './settingsInputs';\nimport { AutosaveStatus } from './AutosaveStatus';\n\n/** Keys to show on this page (excluding the master toggle which is in header) */\nconst SETTINGS_KEYS = ['wallet_recovery_mode'];\n\nexport interface EmbeddedWalletSettingsProps {\n className?: string;\n}\n\nexport function EmbeddedWalletSettings({ className }: EmbeddedWalletSettingsProps) {\n const {\n settings,\n edits,\n isLoading,\n autosaveStatus,\n autosaveError,\n error,\n fetchSettings,\n handleChange,\n getEffectiveValue,\n } = useSettingsAutosave();\n\n useEffect(() => {\n fetchSettings();\n }, [fetchSettings]);\n\n // Get wallet settings from features category\n const featuresSettings = settings['features'] ?? [];\n const currentSettings = featuresSettings\n .filter((s) => SETTINGS_KEYS.includes(s.key))\n .sort((a, b) => SETTINGS_KEYS.indexOf(a.key) - SETTINGS_KEYS.indexOf(b.key));\n\n // Embedded wallet master toggle\n const walletEnabled = getEffectiveValue('feature_wallet_signing') === 'true';\n const handleWalletToggle = () => {\n handleChange('feature_wallet_signing', walletEnabled ? 'false' : 'true');\n };\n\n // User withdrawals toggle (only visible when wallet is enabled)\n const withdrawalsEnabled = getEffectiveValue('feature_user_withdrawals') === 'true';\n const handleWithdrawalsToggle = () => {\n handleChange('feature_user_withdrawals', withdrawalsEnabled ? 'false' : 'true');\n };\n\n if (isLoading && Object.keys(settings).length === 0) {\n return (\n <div className={`cedros-system-settings cedros-system-settings-loading ${className ?? ''}`}>\n <LoadingSpinner />\n <span>Loading settings...</span>\n </div>\n );\n }\n\n if (error) {\n return (\n <div className={`cedros-system-settings ${className ?? ''}`}>\n <ErrorMessage error={error.message} />\n </div>\n );\n }\n\n return (\n <div className={`cedros-system-settings ${className ?? ''}`}>\n <div className=\"cedros-settings-page-header\">\n <div className=\"cedros-settings-page-header-content\">\n <h2 className=\"cedros-settings-page-title\">Embedded Wallet</h2>\n <p className=\"cedros-settings-page-description\">\n Configure the embedded wallet for transaction signing.\n </p>\n </div>\n <div className=\"cedros-settings-page-header-actions\">\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={walletEnabled}\n className={`cedros-toggle ${walletEnabled ? 'cedros-toggle-on' : 'cedros-toggle-off'}`}\n onClick={handleWalletToggle}\n >\n <span className=\"cedros-toggle-track\">\n <span className=\"cedros-toggle-thumb\" />\n </span>\n <span className=\"cedros-toggle-label\">{walletEnabled ? 'Enabled' : 'Disabled'}</span>\n </button>\n <AutosaveStatus status={autosaveStatus} error={autosaveError} />\n </div>\n </div>\n\n {/* User Withdrawals toggle (only visible when wallet is enabled) */}\n {walletEnabled && (\n <div className=\"cedros-settings-subsection\">\n <div className=\"cedros-settings-subsection-header\">\n <div>\n <h3 className=\"cedros-settings-subsection-title\">User Withdrawals</h3>\n <p className=\"cedros-settings-subsection-description\">\n Allow users to withdraw SOL/SPL tokens from their embedded wallet to external\n addresses.\n </p>\n </div>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={withdrawalsEnabled}\n className={`cedros-toggle ${withdrawalsEnabled ? 'cedros-toggle-on' : 'cedros-toggle-off'}`}\n onClick={handleWithdrawalsToggle}\n >\n <span className=\"cedros-toggle-track\">\n <span className=\"cedros-toggle-thumb\" />\n </span>\n <span className=\"cedros-toggle-label\">\n {withdrawalsEnabled ? 'Enabled' : 'Disabled'}\n </span>\n </button>\n </div>\n </div>\n )}\n\n {/* Settings content */}\n <div className=\"cedros-admin-tab-content\">\n {currentSettings.length === 0 ? (\n <div className=\"cedros-system-settings-empty\">\n <p>No additional settings available.</p>\n </div>\n ) : (\n <SettingsSection settings={currentSettings} edits={edits} onChange={handleChange} />\n )}\n </div>\n </div>\n );\n}\n"],"names":["SETTINGS_KEYS","EmbeddedWalletSettings","className","settings","edits","isLoading","autosaveStatus","autosaveError","error","fetchSettings","handleChange","getEffectiveValue","useSettingsAutosave","useEffect","currentSettings","s","a","b","walletEnabled","handleWalletToggle","withdrawalsEnabled","handleWithdrawalsToggle","jsx","LoadingSpinner","ErrorMessage","jsxs","AutosaveStatus","SettingsSection"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime");require("react");const t=require("./EmbeddedWalletSettings-DivEPn39.cjs");function d(){return e.jsx("div",{className:"cedros-dashboard__section",children:e.jsx(t.EmbeddedWalletSettings,{})})}exports.default=d;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmbeddedWalletSettings-D6M7pwgk.cjs","sources":["../src/admin/sections/EmbeddedWalletSettings.tsx"],"sourcesContent":["/**\n * Embedded Wallet Settings Section - Plugin wrapper\n */\n\nimport React from 'react';\nimport { EmbeddedWalletSettings as Settings } from '../../components/admin/settings';\n\nexport default function EmbeddedWalletSettings(): React.JSX.Element {\n return (\n <div className=\"cedros-dashboard__section\">\n <Settings />\n </div>\n );\n}\n"],"names":["EmbeddedWalletSettings","jsx","Settings"],"mappings":"+LAOA,SAAwBA,GAA4C,CAClE,aACG,MAAA,CAAI,UAAU,4BACb,SAAAC,MAACC,EAAAA,yBAAS,EACZ,CAEJ"}
@@ -0,0 +1 @@
1
+ "use strict";const e=require("react/jsx-runtime"),N=require("react"),v=require("./LoadingSpinner-d6sSxgQN.cjs"),w=require("./ErrorMessage-CHbYbVi2.cjs"),i=require("./AutosaveStatus-CYkC2aI_.cjs"),l=["wallet_recovery_mode"];function S({className:a}){const{settings:c,edits:u,isLoading:m,autosaveStatus:x,autosaveError:j,error:d,fetchSettings:o,handleChange:r,getEffectiveValue:g}=i.useSettingsAutosave();N.useEffect(()=>{o()},[o]);const h=(c.features??[]).filter(n=>l.includes(n.key)).sort((n,p)=>l.indexOf(n.key)-l.indexOf(p.key)),s=g("feature_wallet_signing")==="true",f=()=>{r("feature_wallet_signing",s?"false":"true")},t=g("feature_user_withdrawals")==="true",b=()=>{r("feature_user_withdrawals",t?"false":"true")};return m&&Object.keys(c).length===0?e.jsxs("div",{className:`cedros-system-settings cedros-system-settings-loading ${a??""}`,children:[e.jsx(v.LoadingSpinner,{}),e.jsx("span",{children:"Loading settings..."})]}):d?e.jsx("div",{className:`cedros-system-settings ${a??""}`,children:e.jsx(w.ErrorMessage,{error:d.message})}):e.jsxs("div",{className:`cedros-system-settings ${a??""}`,children:[e.jsxs("div",{className:"cedros-settings-page-header",children:[e.jsxs("div",{className:"cedros-settings-page-header-content",children:[e.jsx("h2",{className:"cedros-settings-page-title",children:"Embedded Wallet"}),e.jsx("p",{className:"cedros-settings-page-description",children:"Configure the embedded wallet for transaction signing."})]}),e.jsxs("div",{className:"cedros-settings-page-header-actions",children:[e.jsxs("button",{type:"button",role:"switch","aria-checked":s,className:`cedros-toggle ${s?"cedros-toggle-on":"cedros-toggle-off"}`,onClick:f,children:[e.jsx("span",{className:"cedros-toggle-track",children:e.jsx("span",{className:"cedros-toggle-thumb"})}),e.jsx("span",{className:"cedros-toggle-label",children:s?"Enabled":"Disabled"})]}),e.jsx(i.AutosaveStatus,{status:x,error:j})]})]}),s&&e.jsx("div",{className:"cedros-settings-subsection",children:e.jsxs("div",{className:"cedros-settings-subsection-header",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"cedros-settings-subsection-title",children:"User Withdrawals"}),e.jsx("p",{className:"cedros-settings-subsection-description",children:"Allow users to withdraw SOL/SPL tokens from their embedded wallet to external addresses."})]}),e.jsxs("button",{type:"button",role:"switch","aria-checked":t,className:`cedros-toggle ${t?"cedros-toggle-on":"cedros-toggle-off"}`,onClick:b,children:[e.jsx("span",{className:"cedros-toggle-track",children:e.jsx("span",{className:"cedros-toggle-thumb"})}),e.jsx("span",{className:"cedros-toggle-label",children:t?"Enabled":"Disabled"})]})]})}),e.jsx("div",{className:"cedros-admin-tab-content",children:h.length===0?e.jsx("div",{className:"cedros-system-settings-empty",children:e.jsx("p",{children:"No additional settings available."})}):e.jsx(i.SettingsSection,{settings:h,edits:u,onChange:r})})]})}exports.EmbeddedWalletSettings=S;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmbeddedWalletSettings-DivEPn39.cjs","sources":["../src/components/admin/settings/EmbeddedWalletSettings.tsx"],"sourcesContent":["/**\n * Embedded Wallet settings page - enable/disable and configure recovery\n */\nimport { useEffect } from 'react';\nimport { LoadingSpinner } from '../../shared/LoadingSpinner';\nimport { ErrorMessage } from '../../shared/ErrorMessage';\nimport { useSettingsAutosave } from '../../../hooks/useSettingsAutosave';\nimport { SettingsSection } from './settingsInputs';\nimport { AutosaveStatus } from './AutosaveStatus';\n\n/** Keys to show on this page (excluding the master toggle which is in header) */\nconst SETTINGS_KEYS = ['wallet_recovery_mode'];\n\nexport interface EmbeddedWalletSettingsProps {\n className?: string;\n}\n\nexport function EmbeddedWalletSettings({ className }: EmbeddedWalletSettingsProps) {\n const {\n settings,\n edits,\n isLoading,\n autosaveStatus,\n autosaveError,\n error,\n fetchSettings,\n handleChange,\n getEffectiveValue,\n } = useSettingsAutosave();\n\n useEffect(() => {\n fetchSettings();\n }, [fetchSettings]);\n\n // Get wallet settings from features category\n const featuresSettings = settings['features'] ?? [];\n const currentSettings = featuresSettings\n .filter((s) => SETTINGS_KEYS.includes(s.key))\n .sort((a, b) => SETTINGS_KEYS.indexOf(a.key) - SETTINGS_KEYS.indexOf(b.key));\n\n // Embedded wallet master toggle\n const walletEnabled = getEffectiveValue('feature_wallet_signing') === 'true';\n const handleWalletToggle = () => {\n handleChange('feature_wallet_signing', walletEnabled ? 'false' : 'true');\n };\n\n // User withdrawals toggle (only visible when wallet is enabled)\n const withdrawalsEnabled = getEffectiveValue('feature_user_withdrawals') === 'true';\n const handleWithdrawalsToggle = () => {\n handleChange('feature_user_withdrawals', withdrawalsEnabled ? 'false' : 'true');\n };\n\n if (isLoading && Object.keys(settings).length === 0) {\n return (\n <div className={`cedros-system-settings cedros-system-settings-loading ${className ?? ''}`}>\n <LoadingSpinner />\n <span>Loading settings...</span>\n </div>\n );\n }\n\n if (error) {\n return (\n <div className={`cedros-system-settings ${className ?? ''}`}>\n <ErrorMessage error={error.message} />\n </div>\n );\n }\n\n return (\n <div className={`cedros-system-settings ${className ?? ''}`}>\n <div className=\"cedros-settings-page-header\">\n <div className=\"cedros-settings-page-header-content\">\n <h2 className=\"cedros-settings-page-title\">Embedded Wallet</h2>\n <p className=\"cedros-settings-page-description\">\n Configure the embedded wallet for transaction signing.\n </p>\n </div>\n <div className=\"cedros-settings-page-header-actions\">\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={walletEnabled}\n className={`cedros-toggle ${walletEnabled ? 'cedros-toggle-on' : 'cedros-toggle-off'}`}\n onClick={handleWalletToggle}\n >\n <span className=\"cedros-toggle-track\">\n <span className=\"cedros-toggle-thumb\" />\n </span>\n <span className=\"cedros-toggle-label\">{walletEnabled ? 'Enabled' : 'Disabled'}</span>\n </button>\n <AutosaveStatus status={autosaveStatus} error={autosaveError} />\n </div>\n </div>\n\n {/* User Withdrawals toggle (only visible when wallet is enabled) */}\n {walletEnabled && (\n <div className=\"cedros-settings-subsection\">\n <div className=\"cedros-settings-subsection-header\">\n <div>\n <h3 className=\"cedros-settings-subsection-title\">User Withdrawals</h3>\n <p className=\"cedros-settings-subsection-description\">\n Allow users to withdraw SOL/SPL tokens from their embedded wallet to external\n addresses.\n </p>\n </div>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={withdrawalsEnabled}\n className={`cedros-toggle ${withdrawalsEnabled ? 'cedros-toggle-on' : 'cedros-toggle-off'}`}\n onClick={handleWithdrawalsToggle}\n >\n <span className=\"cedros-toggle-track\">\n <span className=\"cedros-toggle-thumb\" />\n </span>\n <span className=\"cedros-toggle-label\">\n {withdrawalsEnabled ? 'Enabled' : 'Disabled'}\n </span>\n </button>\n </div>\n </div>\n )}\n\n {/* Settings content */}\n <div className=\"cedros-admin-tab-content\">\n {currentSettings.length === 0 ? (\n <div className=\"cedros-system-settings-empty\">\n <p>No additional settings available.</p>\n </div>\n ) : (\n <SettingsSection settings={currentSettings} edits={edits} onChange={handleChange} />\n )}\n </div>\n </div>\n );\n}\n"],"names":["SETTINGS_KEYS","EmbeddedWalletSettings","className","settings","edits","isLoading","autosaveStatus","autosaveError","error","fetchSettings","handleChange","getEffectiveValue","useSettingsAutosave","useEffect","currentSettings","s","a","b","walletEnabled","handleWalletToggle","withdrawalsEnabled","handleWithdrawalsToggle","jsx","LoadingSpinner","ErrorMessage","jsxs","AutosaveStatus","SettingsSection"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ "use strict";const e=require("react/jsx-runtime"),i=require("react"),l=i.memo(function({error:r,className:c="",onDismiss:o,autoFocus:s=!1}){const t=i.useRef(null);if(i.useEffect(()=>{r&&s&&t.current&&t.current.focus()},[r,s]),!r)return null;const n=typeof r=="string"?r:r.message;return e.jsxs("div",{ref:t,className:`cedros-error ${c}`,role:"alert","aria-live":"assertive",tabIndex:s?-1:void 0,children:[e.jsxs("svg",{className:"cedros-error-icon",width:"16",height:"16",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[e.jsx("circle",{cx:"8",cy:"8",r:"7",stroke:"currentColor",strokeWidth:"1.5"}),e.jsx("path",{d:"M8 4.5v4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"}),e.jsx("circle",{cx:"8",cy:"11",r:"0.75",fill:"currentColor"})]}),e.jsx("span",{className:"cedros-error-message",children:n}),o&&e.jsx("button",{type:"button",className:"cedros-error-dismiss",onClick:o,"aria-label":"Dismiss error",children:e.jsx("svg",{width:"14",height:"14",viewBox:"0 0 14 14",fill:"none","aria-hidden":"true",children:e.jsx("path",{d:"M10.5 3.5L3.5 10.5M3.5 3.5l7 7",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})})})]})});exports.ErrorMessage=l;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorMessage-CHbYbVi2.cjs","sources":["../src/components/shared/ErrorMessage.tsx"],"sourcesContent":["import { memo, useRef, useEffect } from 'react';\nimport type { DisplayError } from '../../types';\n\nexport interface ErrorMessageProps {\n error: DisplayError;\n className?: string;\n onDismiss?: () => void;\n /** If true, focus the error message when it appears (for accessibility) */\n autoFocus?: boolean;\n}\n\n/**\n * Error message display component with accessibility support.\n * Announces errors to screen readers and optionally focuses the message.\n * Wrapped with React.memo to prevent unnecessary re-renders.\n */\nexport const ErrorMessage = memo(function ErrorMessage({\n error,\n className = '',\n onDismiss,\n autoFocus = false,\n}: ErrorMessageProps) {\n const errorRef = useRef<HTMLDivElement>(null);\n\n // Focus the error message when it appears (for accessibility)\n useEffect(() => {\n if (error && autoFocus && errorRef.current) {\n errorRef.current.focus();\n }\n }, [error, autoFocus]);\n\n if (!error) return null;\n\n const message = typeof error === 'string' ? error : error.message;\n\n return (\n <div\n ref={errorRef}\n className={`cedros-error ${className}`}\n role=\"alert\"\n aria-live=\"assertive\"\n tabIndex={autoFocus ? -1 : undefined}\n >\n <svg\n className=\"cedros-error-icon\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <circle cx=\"8\" cy=\"8\" r=\"7\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path d=\"M8 4.5v4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <circle cx=\"8\" cy=\"11\" r=\"0.75\" fill=\"currentColor\" />\n </svg>\n <span className=\"cedros-error-message\">{message}</span>\n {onDismiss && (\n <button\n type=\"button\"\n className=\"cedros-error-dismiss\"\n onClick={onDismiss}\n aria-label=\"Dismiss error\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M10.5 3.5L3.5 10.5M3.5 3.5l7 7\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n )}\n </div>\n );\n});\n"],"names":["ErrorMessage","memo","error","className","onDismiss","autoFocus","errorRef","useRef","useEffect","message","jsxs","jsx"],"mappings":"qEAgBaA,EAAeC,EAAAA,KAAK,SAAsB,CACrD,MAAAC,EACA,UAAAC,EAAY,GACZ,UAAAC,EACA,UAAAC,EAAY,EACd,EAAsB,CACpB,MAAMC,EAAWC,EAAAA,OAAuB,IAAI,EAS5C,GANAC,EAAAA,UAAU,IAAM,CACVN,GAASG,GAAaC,EAAS,SACjCA,EAAS,QAAQ,MAAA,CAErB,EAAG,CAACJ,EAAOG,CAAS,CAAC,EAEjB,CAACH,EAAO,OAAO,KAEnB,MAAMO,EAAU,OAAOP,GAAU,SAAWA,EAAQA,EAAM,QAE1D,OACEQ,EAAAA,KAAC,MAAA,CACC,IAAKJ,EACL,UAAW,gBAAgBH,CAAS,GACpC,KAAK,QACL,YAAU,YACV,SAAUE,EAAY,GAAK,OAE3B,SAAA,CAAAK,EAAAA,KAAC,MAAA,CACC,UAAU,oBACV,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,cAAY,OAEZ,SAAA,CAAAC,EAAAA,IAAC,SAAA,CAAO,GAAG,IAAI,GAAG,IAAI,EAAE,IAAI,OAAO,eAAe,YAAY,KAAA,CAAM,EACpEA,EAAAA,IAAC,QAAK,EAAE,WAAW,OAAO,eAAe,YAAY,MAAM,cAAc,OAAA,CAAQ,EACjFA,EAAAA,IAAC,UAAO,GAAG,IAAI,GAAG,KAAK,EAAE,OAAO,KAAK,cAAA,CAAe,CAAA,CAAA,CAAA,EAEtDA,EAAAA,IAAC,OAAA,CAAK,UAAU,uBAAwB,SAAAF,EAAQ,EAC/CL,GACCO,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,UAAU,uBACV,QAASP,EACT,aAAW,gBAEX,SAAAO,EAAAA,IAAC,MAAA,CAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,cAAY,OACtE,SAAAA,EAAAA,IAAC,OAAA,CACC,EAAE,iCACF,OAAO,eACP,YAAY,MACZ,cAAc,OAAA,CAAA,CAChB,CACF,CAAA,CAAA,CACF,CAAA,CAAA,CAIR,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { jsxs as i, jsx as e } from "react/jsx-runtime";
2
+ import { memo as l, useRef as a, useEffect as d } from "react";
3
+ const m = l(function({
4
+ error: r,
5
+ className: n = "",
6
+ onDismiss: o,
7
+ autoFocus: s = !1
8
+ }) {
9
+ const t = a(null);
10
+ if (d(() => {
11
+ r && s && t.current && t.current.focus();
12
+ }, [r, s]), !r) return null;
13
+ const c = typeof r == "string" ? r : r.message;
14
+ return /* @__PURE__ */ i(
15
+ "div",
16
+ {
17
+ ref: t,
18
+ className: `cedros-error ${n}`,
19
+ role: "alert",
20
+ "aria-live": "assertive",
21
+ tabIndex: s ? -1 : void 0,
22
+ children: [
23
+ /* @__PURE__ */ i(
24
+ "svg",
25
+ {
26
+ className: "cedros-error-icon",
27
+ width: "16",
28
+ height: "16",
29
+ viewBox: "0 0 16 16",
30
+ fill: "none",
31
+ "aria-hidden": "true",
32
+ children: [
33
+ /* @__PURE__ */ e("circle", { cx: "8", cy: "8", r: "7", stroke: "currentColor", strokeWidth: "1.5" }),
34
+ /* @__PURE__ */ e("path", { d: "M8 4.5v4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }),
35
+ /* @__PURE__ */ e("circle", { cx: "8", cy: "11", r: "0.75", fill: "currentColor" })
36
+ ]
37
+ }
38
+ ),
39
+ /* @__PURE__ */ e("span", { className: "cedros-error-message", children: c }),
40
+ o && /* @__PURE__ */ e(
41
+ "button",
42
+ {
43
+ type: "button",
44
+ className: "cedros-error-dismiss",
45
+ onClick: o,
46
+ "aria-label": "Dismiss error",
47
+ children: /* @__PURE__ */ e("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ e(
48
+ "path",
49
+ {
50
+ d: "M10.5 3.5L3.5 10.5M3.5 3.5l7 7",
51
+ stroke: "currentColor",
52
+ strokeWidth: "1.5",
53
+ strokeLinecap: "round"
54
+ }
55
+ ) })
56
+ }
57
+ )
58
+ ]
59
+ }
60
+ );
61
+ });
62
+ export {
63
+ m as E
64
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorMessage-CcEK0pYO.js","sources":["../src/components/shared/ErrorMessage.tsx"],"sourcesContent":["import { memo, useRef, useEffect } from 'react';\nimport type { DisplayError } from '../../types';\n\nexport interface ErrorMessageProps {\n error: DisplayError;\n className?: string;\n onDismiss?: () => void;\n /** If true, focus the error message when it appears (for accessibility) */\n autoFocus?: boolean;\n}\n\n/**\n * Error message display component with accessibility support.\n * Announces errors to screen readers and optionally focuses the message.\n * Wrapped with React.memo to prevent unnecessary re-renders.\n */\nexport const ErrorMessage = memo(function ErrorMessage({\n error,\n className = '',\n onDismiss,\n autoFocus = false,\n}: ErrorMessageProps) {\n const errorRef = useRef<HTMLDivElement>(null);\n\n // Focus the error message when it appears (for accessibility)\n useEffect(() => {\n if (error && autoFocus && errorRef.current) {\n errorRef.current.focus();\n }\n }, [error, autoFocus]);\n\n if (!error) return null;\n\n const message = typeof error === 'string' ? error : error.message;\n\n return (\n <div\n ref={errorRef}\n className={`cedros-error ${className}`}\n role=\"alert\"\n aria-live=\"assertive\"\n tabIndex={autoFocus ? -1 : undefined}\n >\n <svg\n className=\"cedros-error-icon\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <circle cx=\"8\" cy=\"8\" r=\"7\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path d=\"M8 4.5v4\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n <circle cx=\"8\" cy=\"11\" r=\"0.75\" fill=\"currentColor\" />\n </svg>\n <span className=\"cedros-error-message\">{message}</span>\n {onDismiss && (\n <button\n type=\"button\"\n className=\"cedros-error-dismiss\"\n onClick={onDismiss}\n aria-label=\"Dismiss error\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M10.5 3.5L3.5 10.5M3.5 3.5l7 7\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n </button>\n )}\n </div>\n );\n});\n"],"names":["ErrorMessage","memo","error","className","onDismiss","autoFocus","errorRef","useRef","useEffect","message","jsxs","jsx"],"mappings":";;AAgBO,MAAMA,IAAeC,EAAK,SAAsB;AAAA,EACrD,OAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,WAAAC;AAAA,EACA,WAAAC,IAAY;AACd,GAAsB;AACpB,QAAMC,IAAWC,EAAuB,IAAI;AAS5C,MANAC,EAAU,MAAM;AACd,IAAIN,KAASG,KAAaC,EAAS,WACjCA,EAAS,QAAQ,MAAA;AAAA,EAErB,GAAG,CAACJ,GAAOG,CAAS,CAAC,GAEjB,CAACH,EAAO,QAAO;AAEnB,QAAMO,IAAU,OAAOP,KAAU,WAAWA,IAAQA,EAAM;AAE1D,SACE,gBAAAQ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKJ;AAAA,MACL,WAAW,gBAAgBH,CAAS;AAAA,MACpC,MAAK;AAAA,MACL,aAAU;AAAA,MACV,UAAUE,IAAY,KAAK;AAAA,MAE3B,UAAA;AAAA,QAAA,gBAAAK;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAM;AAAA,YACN,QAAO;AAAA,YACP,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,eAAY;AAAA,YAEZ,UAAA;AAAA,cAAA,gBAAAC,EAAC,UAAA,EAAO,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI,QAAO,gBAAe,aAAY,MAAA,CAAM;AAAA,cACpE,gBAAAA,EAAC,UAAK,GAAE,YAAW,QAAO,gBAAe,aAAY,OAAM,eAAc,QAAA,CAAQ;AAAA,cACjF,gBAAAA,EAAC,YAAO,IAAG,KAAI,IAAG,MAAK,GAAE,QAAO,MAAK,eAAA,CAAe;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAEtD,gBAAAA,EAAC,QAAA,EAAK,WAAU,wBAAwB,UAAAF,GAAQ;AAAA,QAC/CL,KACC,gBAAAO;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAASP;AAAA,YACT,cAAW;AAAA,YAEX,UAAA,gBAAAO,EAAC,OAAA,EAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,eAAY,QACtE,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,GAAE;AAAA,gBACF,QAAO;AAAA,gBACP,aAAY;AAAA,gBACZ,eAAc;AAAA,cAAA;AAAA,YAAA,EAChB,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAAA;AAIR,CAAC;"}
@@ -1,6 +1,7 @@
1
1
  import { jsxs as w, jsx as u } from "react/jsx-runtime";
2
2
  import { useState as b, useRef as k, useMemo as C, useEffect as S, useCallback as I } from "react";
3
- import { u as A, A as y, h as v, L as G } from "./ErrorMessage-DU2VBb85.js";
3
+ import { u as A, A as y, h as v } from "./apiClient-B2JxVPlH.js";
4
+ import { L as G } from "./LoadingSpinner-6vml-zwr.js";
4
5
  const L = {
5
6
  loading: !1,
6
7
  loaded: !1,
@@ -143,7 +144,7 @@ function _() {
143
144
  clearError: E
144
145
  };
145
146
  }
146
- function V({
147
+ function D({
147
148
  onSuccess: e,
148
149
  onError: c,
149
150
  className: d = "",
@@ -222,6 +223,6 @@ function V({
222
223
  );
223
224
  }
224
225
  export {
225
- V as G,
226
+ D as G,
226
227
  _ as u
227
228
  };
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleLoginButton-BzHr545L.js","sources":["../src/hooks/useGoogleAuth.ts","../src/components/google/GoogleLoginButton.tsx"],"sourcesContent":["import { useState, useCallback, useEffect, useRef, useMemo } from 'react';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { ApiClient, handleApiError } from '../utils/apiClient';\nimport type { AuthResponse, AuthError } from '../types';\n\n/**\n * Module-level singleton for Google script loading (P-01)\n *\n * Prevents race conditions when multiple components mount simultaneously.\n * Uses a promise queue pattern to ensure the script is only loaded once.\n *\n * ## SSR Limitations (F-08)\n *\n * This singleton persists across the module lifecycle. In SSR environments:\n * - Module state persists between requests (potential cross-request leakage)\n * - Google Sign-In requires browser APIs (document, window)\n * - The hook guards against SSR with `googleClientId` checks\n *\n * For SSR frameworks (Next.js, Remix), ensure this hook is only used\n * in client-side components.\n *\n * ## Test Isolation\n *\n * For test isolation, call `scriptLoader._reset()` in test setup/teardown.\n *\n * @internal\n */\nconst scriptLoader = {\n loading: false,\n loaded: false,\n error: null as Error | null,\n callbacks: [] as Array<{ resolve: () => void; reject: (err: Error) => void }>,\n\n load(): Promise<void> {\n // SSR guard: avoid touching browser globals when running in Node/SSR.\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return Promise.reject(new Error('Google Sign-In script loader cannot run in SSR'));\n }\n\n // Already loaded\n if (this.loaded) {\n return Promise.resolve();\n }\n\n // Loading in progress - queue callback\n if (this.loading) {\n return new Promise((resolve, reject) => {\n this.callbacks.push({ resolve, reject });\n });\n }\n\n // Start loading\n this.loading = true;\n return new Promise((resolve, reject) => {\n this.callbacks.push({ resolve, reject });\n\n // Check if script already exists (from previous session or SSR)\n const existingScript = document.getElementById('google-gsi-script');\n if (existingScript) {\n if (window.google?.accounts?.id) {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n } else {\n existingScript.addEventListener('load', () => {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n });\n }\n return;\n }\n\n const script = document.createElement('script');\n script.src = 'https://accounts.google.com/gsi/client';\n script.async = true;\n script.defer = true;\n script.id = 'google-gsi-script';\n\n script.onload = () => {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n };\n\n script.onerror = () => {\n this.loading = false;\n // M-02: Remove failed script from DOM to allow retry on next load() call.\n // Without removal, retry finds existingScript and waits for a load event\n // that will never fire on an already-failed script.\n script.remove();\n const error = new Error('Failed to load Google Sign-In script');\n this.callbacks.forEach((cb) => cb.reject(error));\n this.callbacks = [];\n };\n\n document.head.appendChild(script);\n });\n },\n\n /**\n * Reset singleton state for test isolation (F-08)\n * @internal - Only use in test setup/teardown\n */\n _reset(): void {\n this.loading = false;\n this.loaded = false;\n this.error = null;\n this.callbacks = [];\n },\n};\n\n/** @internal */\nexport const _internalGoogleScriptLoader = scriptLoader;\n\nexport interface UseGoogleAuthReturn {\n signIn: () => Promise<AuthResponse>;\n isLoading: boolean;\n isInitialized: boolean;\n error: AuthError | null;\n clearError: () => void;\n}\n\ninterface PromiseCallbacks {\n resolve: (value: AuthResponse) => void;\n reject: (error: AuthError) => void;\n}\n\n/**\n * Hook for Google OAuth authentication.\n *\n * @example\n * ```tsx\n * function GoogleButton() {\n * const { signIn, isLoading, isInitialized, error } = useGoogleAuth();\n *\n * return (\n * <button onClick={signIn} disabled={!isInitialized || isLoading}>\n * {isLoading ? 'Signing in...' : 'Sign in with Google'}\n * </button>\n * );\n * }\n * ```\n */\nexport function useGoogleAuth(): UseGoogleAuthReturn {\n const { config, _internal } = useCedrosLogin();\n const [isLoading, setIsLoading] = useState(false);\n const [isInitialized, setIsInitialized] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n\n const promiseCallbacksRef = useRef<PromiseCallbacks | null>(null);\n const configRef = useRef(config);\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 // Keep config ref in sync\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n // Handle credential response from Google\n const handleCredentialResponse = useCallback(\n async (response: { credential: string }) => {\n const callbacks = promiseCallbacksRef.current;\n if (!callbacks) return;\n\n try {\n const data = await apiClient.post<AuthResponse>('/google', {\n idToken: response.credential,\n });\n configRef.current.callbacks?.onLoginSuccess?.(data.user, 'google');\n _internal?.handleLoginSuccess(data.user, data.tokens);\n setIsLoading(false);\n callbacks.resolve(data);\n } catch (err) {\n const authError = handleApiError(err, 'Google sign-in failed');\n setError(authError);\n setIsLoading(false);\n callbacks.reject(authError);\n } finally {\n promiseCallbacksRef.current = null;\n }\n },\n [apiClient, _internal]\n );\n\n // P-01: Initialize Google Sign-In SDK using singleton loader\n useEffect(() => {\n // Early return if Google auth is not enabled\n if (!config.googleClientId) {\n return;\n }\n\n // Track mounted state to prevent state updates after unmount\n let isMounted = true;\n\n const initializeGoogleSignIn = () => {\n if (!isMounted) return;\n\n window.google?.accounts?.id?.initialize({\n client_id: config.googleClientId!,\n callback: handleCredentialResponse,\n auto_select: false,\n cancel_on_tap_outside: true,\n });\n\n if (isMounted) {\n setIsInitialized(true);\n }\n };\n\n // Use singleton loader to handle script loading\n scriptLoader\n .load()\n .then(() => {\n if (isMounted) {\n initializeGoogleSignIn();\n }\n })\n .catch(() => {\n if (isMounted) {\n setError({\n code: 'SERVER_ERROR',\n message: 'Failed to load Google Sign-In',\n });\n }\n });\n\n return () => {\n isMounted = false;\n };\n }, [config.googleClientId, handleCredentialResponse]);\n\n const signIn = useCallback(async (): Promise<AuthResponse> => {\n if (!config.googleClientId) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Client ID not configured',\n };\n setError(err);\n throw err;\n }\n\n if (!isInitialized) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Sign-In not initialized',\n };\n setError(err);\n throw err;\n }\n\n if (promiseCallbacksRef.current) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Sign-In already in progress',\n };\n setError(err);\n throw err;\n }\n\n setIsLoading(true);\n setError(null);\n\n return new Promise<AuthResponse>((resolve, reject) => {\n promiseCallbacksRef.current = { resolve, reject };\n\n // Show Google One Tap prompt\n window.google?.accounts?.id?.prompt((notification) => {\n if (notification.isNotDisplayed()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In popup was blocked. Please allow popups or try again.',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n } else if (notification.isSkippedMoment()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In was cancelled',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n } else if (notification.isDismissedMoment()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In was cancelled',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n }\n });\n });\n }, [config.googleClientId, isInitialized]);\n\n const clearError = useCallback(() => setError(null), []);\n\n return {\n signIn,\n isLoading,\n isInitialized,\n error,\n clearError,\n };\n}\n\n// Type declaration for Google Identity Services\ndeclare global {\n interface Window {\n google?: {\n accounts?: {\n id?: {\n initialize: (config: {\n client_id: string;\n callback: (response: { credential: string }) => void;\n auto_select?: boolean;\n cancel_on_tap_outside?: boolean;\n }) => void;\n prompt: (\n callback: (notification: {\n isNotDisplayed: () => boolean;\n isSkippedMoment: () => boolean;\n isDismissedMoment: () => boolean;\n getMomentType: () => string;\n }) => void\n ) => void;\n renderButton: (element: HTMLElement, config: object) => void;\n disableAutoSelect: () => void;\n };\n };\n };\n }\n}\n","import { useGoogleAuth } from '../../hooks/useGoogleAuth';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\n\nexport interface GoogleLoginButtonProps {\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n className?: string;\n variant?: 'default' | 'outline';\n size?: 'sm' | 'md' | 'lg';\n disabled?: boolean;\n}\n\n/**\n * Google OAuth login button\n */\nexport function GoogleLoginButton({\n onSuccess,\n onError,\n className = '',\n variant = 'default',\n size = 'md',\n disabled = false,\n}: GoogleLoginButtonProps) {\n const { signIn, isLoading, isInitialized } = useGoogleAuth();\n\n const handleClick = async () => {\n try {\n await signIn();\n onSuccess?.();\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n onError?.(error);\n }\n };\n\n const sizeClasses = {\n sm: 'cedros-button-sm',\n md: 'cedros-button-md',\n lg: 'cedros-button-lg',\n };\n\n const variantClasses = {\n default: 'cedros-button-google',\n outline: 'cedros-button-google-outline',\n };\n\n return (\n <button\n type=\"button\"\n className={`cedros-button ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}\n onClick={handleClick}\n disabled={disabled || !isInitialized || isLoading}\n aria-label=\"Sign in with Google\"\n >\n {isLoading ? (\n <LoadingSpinner size=\"sm\" />\n ) : (\n <svg\n className=\"cedros-button-icon\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z\"\n fill=\"#4285F4\"\n />\n <path\n d=\"M9.003 18c2.43 0 4.467-.806 5.956-2.18l-2.909-2.26c-.806.54-1.836.86-3.047.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332A8.997 8.997 0 0 0 9.003 18z\"\n fill=\"#34A853\"\n />\n <path\n d=\"M3.964 10.712A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.96A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.96 4.042l3.004-2.33z\"\n fill=\"#FBBC05\"\n />\n <path\n d=\"M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.428 0 9.002 0A8.997 8.997 0 0 0 .96 4.958l3.005 2.332c.708-2.127 2.692-3.71 5.036-3.71z\"\n fill=\"#EA4335\"\n />\n </svg>\n )}\n <span>Continue with Google</span>\n </button>\n );\n}\n"],"names":["scriptLoader","resolve","reject","existingScript","cb","script","error","useGoogleAuth","config","_internal","useCedrosLogin","isLoading","setIsLoading","useState","isInitialized","setIsInitialized","setError","promiseCallbacksRef","useRef","configRef","apiClient","useMemo","ApiClient","useEffect","handleCredentialResponse","useCallback","response","callbacks","data","err","authError","handleApiError","isMounted","initializeGoogleSignIn","signIn","notification","clearError","GoogleLoginButton","onSuccess","onError","className","variant","size","disabled","handleClick","sizeClasses","jsxs","jsx","LoadingSpinner"],"mappings":"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"}
1
+ {"version":3,"file":"GoogleLoginButton-B3uRMJ_n.js","sources":["../src/hooks/useGoogleAuth.ts","../src/components/google/GoogleLoginButton.tsx"],"sourcesContent":["import { useState, useCallback, useEffect, useRef, useMemo } from 'react';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { ApiClient, handleApiError } from '../utils/apiClient';\nimport type { AuthResponse, AuthError } from '../types';\n\n/**\n * Module-level singleton for Google script loading (P-01)\n *\n * Prevents race conditions when multiple components mount simultaneously.\n * Uses a promise queue pattern to ensure the script is only loaded once.\n *\n * ## SSR Limitations (F-08)\n *\n * This singleton persists across the module lifecycle. In SSR environments:\n * - Module state persists between requests (potential cross-request leakage)\n * - Google Sign-In requires browser APIs (document, window)\n * - The hook guards against SSR with `googleClientId` checks\n *\n * For SSR frameworks (Next.js, Remix), ensure this hook is only used\n * in client-side components.\n *\n * ## Test Isolation\n *\n * For test isolation, call `scriptLoader._reset()` in test setup/teardown.\n *\n * @internal\n */\nconst scriptLoader = {\n loading: false,\n loaded: false,\n error: null as Error | null,\n callbacks: [] as Array<{ resolve: () => void; reject: (err: Error) => void }>,\n\n load(): Promise<void> {\n // SSR guard: avoid touching browser globals when running in Node/SSR.\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return Promise.reject(new Error('Google Sign-In script loader cannot run in SSR'));\n }\n\n // Already loaded\n if (this.loaded) {\n return Promise.resolve();\n }\n\n // Loading in progress - queue callback\n if (this.loading) {\n return new Promise((resolve, reject) => {\n this.callbacks.push({ resolve, reject });\n });\n }\n\n // Start loading\n this.loading = true;\n return new Promise((resolve, reject) => {\n this.callbacks.push({ resolve, reject });\n\n // Check if script already exists (from previous session or SSR)\n const existingScript = document.getElementById('google-gsi-script');\n if (existingScript) {\n if (window.google?.accounts?.id) {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n } else {\n existingScript.addEventListener('load', () => {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n });\n }\n return;\n }\n\n const script = document.createElement('script');\n script.src = 'https://accounts.google.com/gsi/client';\n script.async = true;\n script.defer = true;\n script.id = 'google-gsi-script';\n\n script.onload = () => {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n };\n\n script.onerror = () => {\n this.loading = false;\n // M-02: Remove failed script from DOM to allow retry on next load() call.\n // Without removal, retry finds existingScript and waits for a load event\n // that will never fire on an already-failed script.\n script.remove();\n const error = new Error('Failed to load Google Sign-In script');\n this.callbacks.forEach((cb) => cb.reject(error));\n this.callbacks = [];\n };\n\n document.head.appendChild(script);\n });\n },\n\n /**\n * Reset singleton state for test isolation (F-08)\n * @internal - Only use in test setup/teardown\n */\n _reset(): void {\n this.loading = false;\n this.loaded = false;\n this.error = null;\n this.callbacks = [];\n },\n};\n\n/** @internal */\nexport const _internalGoogleScriptLoader = scriptLoader;\n\nexport interface UseGoogleAuthReturn {\n signIn: () => Promise<AuthResponse>;\n isLoading: boolean;\n isInitialized: boolean;\n error: AuthError | null;\n clearError: () => void;\n}\n\ninterface PromiseCallbacks {\n resolve: (value: AuthResponse) => void;\n reject: (error: AuthError) => void;\n}\n\n/**\n * Hook for Google OAuth authentication.\n *\n * @example\n * ```tsx\n * function GoogleButton() {\n * const { signIn, isLoading, isInitialized, error } = useGoogleAuth();\n *\n * return (\n * <button onClick={signIn} disabled={!isInitialized || isLoading}>\n * {isLoading ? 'Signing in...' : 'Sign in with Google'}\n * </button>\n * );\n * }\n * ```\n */\nexport function useGoogleAuth(): UseGoogleAuthReturn {\n const { config, _internal } = useCedrosLogin();\n const [isLoading, setIsLoading] = useState(false);\n const [isInitialized, setIsInitialized] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n\n const promiseCallbacksRef = useRef<PromiseCallbacks | null>(null);\n const configRef = useRef(config);\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 // Keep config ref in sync\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n // Handle credential response from Google\n const handleCredentialResponse = useCallback(\n async (response: { credential: string }) => {\n const callbacks = promiseCallbacksRef.current;\n if (!callbacks) return;\n\n try {\n const data = await apiClient.post<AuthResponse>('/google', {\n idToken: response.credential,\n });\n configRef.current.callbacks?.onLoginSuccess?.(data.user, 'google');\n _internal?.handleLoginSuccess(data.user, data.tokens);\n setIsLoading(false);\n callbacks.resolve(data);\n } catch (err) {\n const authError = handleApiError(err, 'Google sign-in failed');\n setError(authError);\n setIsLoading(false);\n callbacks.reject(authError);\n } finally {\n promiseCallbacksRef.current = null;\n }\n },\n [apiClient, _internal]\n );\n\n // P-01: Initialize Google Sign-In SDK using singleton loader\n useEffect(() => {\n // Early return if Google auth is not enabled\n if (!config.googleClientId) {\n return;\n }\n\n // Track mounted state to prevent state updates after unmount\n let isMounted = true;\n\n const initializeGoogleSignIn = () => {\n if (!isMounted) return;\n\n window.google?.accounts?.id?.initialize({\n client_id: config.googleClientId!,\n callback: handleCredentialResponse,\n auto_select: false,\n cancel_on_tap_outside: true,\n });\n\n if (isMounted) {\n setIsInitialized(true);\n }\n };\n\n // Use singleton loader to handle script loading\n scriptLoader\n .load()\n .then(() => {\n if (isMounted) {\n initializeGoogleSignIn();\n }\n })\n .catch(() => {\n if (isMounted) {\n setError({\n code: 'SERVER_ERROR',\n message: 'Failed to load Google Sign-In',\n });\n }\n });\n\n return () => {\n isMounted = false;\n };\n }, [config.googleClientId, handleCredentialResponse]);\n\n const signIn = useCallback(async (): Promise<AuthResponse> => {\n if (!config.googleClientId) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Client ID not configured',\n };\n setError(err);\n throw err;\n }\n\n if (!isInitialized) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Sign-In not initialized',\n };\n setError(err);\n throw err;\n }\n\n if (promiseCallbacksRef.current) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Sign-In already in progress',\n };\n setError(err);\n throw err;\n }\n\n setIsLoading(true);\n setError(null);\n\n return new Promise<AuthResponse>((resolve, reject) => {\n promiseCallbacksRef.current = { resolve, reject };\n\n // Show Google One Tap prompt\n window.google?.accounts?.id?.prompt((notification) => {\n if (notification.isNotDisplayed()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In popup was blocked. Please allow popups or try again.',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n } else if (notification.isSkippedMoment()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In was cancelled',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n } else if (notification.isDismissedMoment()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In was cancelled',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n }\n });\n });\n }, [config.googleClientId, isInitialized]);\n\n const clearError = useCallback(() => setError(null), []);\n\n return {\n signIn,\n isLoading,\n isInitialized,\n error,\n clearError,\n };\n}\n\n// Type declaration for Google Identity Services\ndeclare global {\n interface Window {\n google?: {\n accounts?: {\n id?: {\n initialize: (config: {\n client_id: string;\n callback: (response: { credential: string }) => void;\n auto_select?: boolean;\n cancel_on_tap_outside?: boolean;\n }) => void;\n prompt: (\n callback: (notification: {\n isNotDisplayed: () => boolean;\n isSkippedMoment: () => boolean;\n isDismissedMoment: () => boolean;\n getMomentType: () => string;\n }) => void\n ) => void;\n renderButton: (element: HTMLElement, config: object) => void;\n disableAutoSelect: () => void;\n };\n };\n };\n }\n}\n","import { useGoogleAuth } from '../../hooks/useGoogleAuth';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\n\nexport interface GoogleLoginButtonProps {\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n className?: string;\n variant?: 'default' | 'outline';\n size?: 'sm' | 'md' | 'lg';\n disabled?: boolean;\n}\n\n/**\n * Google OAuth login button\n */\nexport function GoogleLoginButton({\n onSuccess,\n onError,\n className = '',\n variant = 'default',\n size = 'md',\n disabled = false,\n}: GoogleLoginButtonProps) {\n const { signIn, isLoading, isInitialized } = useGoogleAuth();\n\n const handleClick = async () => {\n try {\n await signIn();\n onSuccess?.();\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n onError?.(error);\n }\n };\n\n const sizeClasses = {\n sm: 'cedros-button-sm',\n md: 'cedros-button-md',\n lg: 'cedros-button-lg',\n };\n\n const variantClasses = {\n default: 'cedros-button-google',\n outline: 'cedros-button-google-outline',\n };\n\n return (\n <button\n type=\"button\"\n className={`cedros-button ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}\n onClick={handleClick}\n disabled={disabled || !isInitialized || isLoading}\n aria-label=\"Sign in with Google\"\n >\n {isLoading ? (\n <LoadingSpinner size=\"sm\" />\n ) : (\n <svg\n className=\"cedros-button-icon\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z\"\n fill=\"#4285F4\"\n />\n <path\n d=\"M9.003 18c2.43 0 4.467-.806 5.956-2.18l-2.909-2.26c-.806.54-1.836.86-3.047.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332A8.997 8.997 0 0 0 9.003 18z\"\n fill=\"#34A853\"\n />\n <path\n d=\"M3.964 10.712A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.96A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.96 4.042l3.004-2.33z\"\n fill=\"#FBBC05\"\n />\n <path\n d=\"M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.428 0 9.002 0A8.997 8.997 0 0 0 .96 4.958l3.005 2.332c.708-2.127 2.692-3.71 5.036-3.71z\"\n fill=\"#EA4335\"\n />\n </svg>\n )}\n <span>Continue with Google</span>\n </button>\n );\n}\n"],"names":["scriptLoader","resolve","reject","existingScript","cb","script","error","useGoogleAuth","config","_internal","useCedrosLogin","isLoading","setIsLoading","useState","isInitialized","setIsInitialized","setError","promiseCallbacksRef","useRef","configRef","apiClient","useMemo","ApiClient","useEffect","handleCredentialResponse","useCallback","response","callbacks","data","err","authError","handleApiError","isMounted","initializeGoogleSignIn","signIn","notification","clearError","GoogleLoginButton","onSuccess","onError","className","variant","size","disabled","handleClick","sizeClasses","jsxs","jsx","LoadingSpinner"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ "use strict";const u=require("react/jsx-runtime"),i=require("react"),I=require("./apiClient-CTTKhsYb.cjs"),S=require("./LoadingSpinner-d6sSxgQN.cjs"),k={loading:!1,loaded:!1,error:null,callbacks:[],load(){return typeof window>"u"||typeof document>"u"?Promise.reject(new Error("Google Sign-In script loader cannot run in SSR")):this.loaded?Promise.resolve():this.loading?new Promise((e,d)=>{this.callbacks.push({resolve:e,reject:d})}):(this.loading=!0,new Promise((e,d)=>{this.callbacks.push({resolve:e,reject:d});const g=document.getElementById("google-gsi-script");if(g){window.google?.accounts?.id?(this.loaded=!0,this.loading=!1,this.callbacks.forEach(t=>t.resolve()),this.callbacks=[]):g.addEventListener("load",()=>{this.loaded=!0,this.loading=!1,this.callbacks.forEach(t=>t.resolve()),this.callbacks=[]});return}const o=document.createElement("script");o.src="https://accounts.google.com/gsi/client",o.async=!0,o.defer=!0,o.id="google-gsi-script",o.onload=()=>{this.loaded=!0,this.loading=!1,this.callbacks.forEach(t=>t.resolve()),this.callbacks=[]},o.onerror=()=>{this.loading=!1,o.remove();const t=new Error("Failed to load Google Sign-In script");this.callbacks.forEach(f=>f.reject(t)),this.callbacks=[]},document.head.appendChild(o)}))},_reset(){this.loading=!1,this.loaded=!1,this.error=null,this.callbacks=[]}};function w(){const{config:e,_internal:d}=I.useCedrosLogin(),[g,o]=i.useState(!1),[t,f]=i.useState(!1),[E,n]=i.useState(null),c=i.useRef(null),p=i.useRef(e),m=i.useMemo(()=>new I.ApiClient({baseUrl:e.serverUrl,timeoutMs:e.requestTimeout,retryAttempts:e.retryAttempts}),[e.serverUrl,e.requestTimeout,e.retryAttempts]);i.useEffect(()=>{p.current=e},[e]);const R=i.useCallback(async s=>{const r=c.current;if(r)try{const a=await m.post("/google",{idToken:s.credential});p.current.callbacks?.onLoginSuccess?.(a.user,"google"),d?.handleLoginSuccess(a.user,a.tokens),o(!1),r.resolve(a)}catch(a){const l=I.handleApiError(a,"Google sign-in failed");n(l),o(!1),r.reject(l)}finally{c.current=null}},[m,d]);i.useEffect(()=>{if(!e.googleClientId)return;let s=!0;const r=()=>{s&&(window.google?.accounts?.id?.initialize({client_id:e.googleClientId,callback:R,auto_select:!1,cancel_on_tap_outside:!0}),s&&f(!0))};return k.load().then(()=>{s&&r()}).catch(()=>{s&&n({code:"SERVER_ERROR",message:"Failed to load Google Sign-In"})}),()=>{s=!1}},[e.googleClientId,R]);const h=i.useCallback(async()=>{if(!e.googleClientId){const s={code:"VALIDATION_ERROR",message:"Google Client ID not configured"};throw n(s),s}if(!t){const s={code:"VALIDATION_ERROR",message:"Google Sign-In not initialized"};throw n(s),s}if(c.current){const s={code:"VALIDATION_ERROR",message:"Google Sign-In already in progress"};throw n(s),s}return o(!0),n(null),new Promise((s,r)=>{c.current={resolve:s,reject:r},window.google?.accounts?.id?.prompt(a=>{if(a.isNotDisplayed()){const l={code:"SERVER_ERROR",message:"Google Sign-In popup was blocked. Please allow popups or try again."};n(l),o(!1),c.current=null,r(l)}else if(a.isSkippedMoment()){const l={code:"SERVER_ERROR",message:"Google Sign-In was cancelled"};n(l),o(!1),c.current=null,r(l)}else if(a.isDismissedMoment()){const l={code:"SERVER_ERROR",message:"Google Sign-In was cancelled"};n(l),o(!1),c.current=null,r(l)}})})},[e.googleClientId,t]),b=i.useCallback(()=>n(null),[]);return{signIn:h,isLoading:g,isInitialized:t,error:E,clearError:b}}function C({onSuccess:e,onError:d,className:g="",variant:o="default",size:t="md",disabled:f=!1}){const{signIn:E,isLoading:n,isInitialized:c}=w(),p=async()=>{try{await E(),e?.()}catch(h){const b=h instanceof Error?h:new Error(String(h));d?.(b)}},m={sm:"cedros-button-sm",md:"cedros-button-md",lg:"cedros-button-lg"},R={default:"cedros-button-google",outline:"cedros-button-google-outline"};return u.jsxs("button",{type:"button",className:`cedros-button ${R[o]} ${m[t]} ${g}`,onClick:p,disabled:f||!c||n,"aria-label":"Sign in with Google",children:[n?u.jsx(S.LoadingSpinner,{size:"sm"}):u.jsxs("svg",{className:"cedros-button-icon",width:"18",height:"18",viewBox:"0 0 18 18",fill:"none","aria-hidden":"true",children:[u.jsx("path",{d:"M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z",fill:"#4285F4"}),u.jsx("path",{d:"M9.003 18c2.43 0 4.467-.806 5.956-2.18l-2.909-2.26c-.806.54-1.836.86-3.047.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332A8.997 8.997 0 0 0 9.003 18z",fill:"#34A853"}),u.jsx("path",{d:"M3.964 10.712A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.96A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.96 4.042l3.004-2.33z",fill:"#FBBC05"}),u.jsx("path",{d:"M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.428 0 9.002 0A8.997 8.997 0 0 0 .96 4.958l3.005 2.332c.708-2.127 2.692-3.71 5.036-3.71z",fill:"#EA4335"})]}),u.jsx("span",{children:"Continue with Google"})]})}exports.GoogleLoginButton=C;exports.useGoogleAuth=w;
@@ -1 +1 @@
1
- {"version":3,"file":"GoogleLoginButton-DoAdOqb3.cjs","sources":["../src/hooks/useGoogleAuth.ts","../src/components/google/GoogleLoginButton.tsx"],"sourcesContent":["import { useState, useCallback, useEffect, useRef, useMemo } from 'react';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { ApiClient, handleApiError } from '../utils/apiClient';\nimport type { AuthResponse, AuthError } from '../types';\n\n/**\n * Module-level singleton for Google script loading (P-01)\n *\n * Prevents race conditions when multiple components mount simultaneously.\n * Uses a promise queue pattern to ensure the script is only loaded once.\n *\n * ## SSR Limitations (F-08)\n *\n * This singleton persists across the module lifecycle. In SSR environments:\n * - Module state persists between requests (potential cross-request leakage)\n * - Google Sign-In requires browser APIs (document, window)\n * - The hook guards against SSR with `googleClientId` checks\n *\n * For SSR frameworks (Next.js, Remix), ensure this hook is only used\n * in client-side components.\n *\n * ## Test Isolation\n *\n * For test isolation, call `scriptLoader._reset()` in test setup/teardown.\n *\n * @internal\n */\nconst scriptLoader = {\n loading: false,\n loaded: false,\n error: null as Error | null,\n callbacks: [] as Array<{ resolve: () => void; reject: (err: Error) => void }>,\n\n load(): Promise<void> {\n // SSR guard: avoid touching browser globals when running in Node/SSR.\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return Promise.reject(new Error('Google Sign-In script loader cannot run in SSR'));\n }\n\n // Already loaded\n if (this.loaded) {\n return Promise.resolve();\n }\n\n // Loading in progress - queue callback\n if (this.loading) {\n return new Promise((resolve, reject) => {\n this.callbacks.push({ resolve, reject });\n });\n }\n\n // Start loading\n this.loading = true;\n return new Promise((resolve, reject) => {\n this.callbacks.push({ resolve, reject });\n\n // Check if script already exists (from previous session or SSR)\n const existingScript = document.getElementById('google-gsi-script');\n if (existingScript) {\n if (window.google?.accounts?.id) {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n } else {\n existingScript.addEventListener('load', () => {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n });\n }\n return;\n }\n\n const script = document.createElement('script');\n script.src = 'https://accounts.google.com/gsi/client';\n script.async = true;\n script.defer = true;\n script.id = 'google-gsi-script';\n\n script.onload = () => {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n };\n\n script.onerror = () => {\n this.loading = false;\n // M-02: Remove failed script from DOM to allow retry on next load() call.\n // Without removal, retry finds existingScript and waits for a load event\n // that will never fire on an already-failed script.\n script.remove();\n const error = new Error('Failed to load Google Sign-In script');\n this.callbacks.forEach((cb) => cb.reject(error));\n this.callbacks = [];\n };\n\n document.head.appendChild(script);\n });\n },\n\n /**\n * Reset singleton state for test isolation (F-08)\n * @internal - Only use in test setup/teardown\n */\n _reset(): void {\n this.loading = false;\n this.loaded = false;\n this.error = null;\n this.callbacks = [];\n },\n};\n\n/** @internal */\nexport const _internalGoogleScriptLoader = scriptLoader;\n\nexport interface UseGoogleAuthReturn {\n signIn: () => Promise<AuthResponse>;\n isLoading: boolean;\n isInitialized: boolean;\n error: AuthError | null;\n clearError: () => void;\n}\n\ninterface PromiseCallbacks {\n resolve: (value: AuthResponse) => void;\n reject: (error: AuthError) => void;\n}\n\n/**\n * Hook for Google OAuth authentication.\n *\n * @example\n * ```tsx\n * function GoogleButton() {\n * const { signIn, isLoading, isInitialized, error } = useGoogleAuth();\n *\n * return (\n * <button onClick={signIn} disabled={!isInitialized || isLoading}>\n * {isLoading ? 'Signing in...' : 'Sign in with Google'}\n * </button>\n * );\n * }\n * ```\n */\nexport function useGoogleAuth(): UseGoogleAuthReturn {\n const { config, _internal } = useCedrosLogin();\n const [isLoading, setIsLoading] = useState(false);\n const [isInitialized, setIsInitialized] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n\n const promiseCallbacksRef = useRef<PromiseCallbacks | null>(null);\n const configRef = useRef(config);\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 // Keep config ref in sync\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n // Handle credential response from Google\n const handleCredentialResponse = useCallback(\n async (response: { credential: string }) => {\n const callbacks = promiseCallbacksRef.current;\n if (!callbacks) return;\n\n try {\n const data = await apiClient.post<AuthResponse>('/google', {\n idToken: response.credential,\n });\n configRef.current.callbacks?.onLoginSuccess?.(data.user, 'google');\n _internal?.handleLoginSuccess(data.user, data.tokens);\n setIsLoading(false);\n callbacks.resolve(data);\n } catch (err) {\n const authError = handleApiError(err, 'Google sign-in failed');\n setError(authError);\n setIsLoading(false);\n callbacks.reject(authError);\n } finally {\n promiseCallbacksRef.current = null;\n }\n },\n [apiClient, _internal]\n );\n\n // P-01: Initialize Google Sign-In SDK using singleton loader\n useEffect(() => {\n // Early return if Google auth is not enabled\n if (!config.googleClientId) {\n return;\n }\n\n // Track mounted state to prevent state updates after unmount\n let isMounted = true;\n\n const initializeGoogleSignIn = () => {\n if (!isMounted) return;\n\n window.google?.accounts?.id?.initialize({\n client_id: config.googleClientId!,\n callback: handleCredentialResponse,\n auto_select: false,\n cancel_on_tap_outside: true,\n });\n\n if (isMounted) {\n setIsInitialized(true);\n }\n };\n\n // Use singleton loader to handle script loading\n scriptLoader\n .load()\n .then(() => {\n if (isMounted) {\n initializeGoogleSignIn();\n }\n })\n .catch(() => {\n if (isMounted) {\n setError({\n code: 'SERVER_ERROR',\n message: 'Failed to load Google Sign-In',\n });\n }\n });\n\n return () => {\n isMounted = false;\n };\n }, [config.googleClientId, handleCredentialResponse]);\n\n const signIn = useCallback(async (): Promise<AuthResponse> => {\n if (!config.googleClientId) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Client ID not configured',\n };\n setError(err);\n throw err;\n }\n\n if (!isInitialized) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Sign-In not initialized',\n };\n setError(err);\n throw err;\n }\n\n if (promiseCallbacksRef.current) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Sign-In already in progress',\n };\n setError(err);\n throw err;\n }\n\n setIsLoading(true);\n setError(null);\n\n return new Promise<AuthResponse>((resolve, reject) => {\n promiseCallbacksRef.current = { resolve, reject };\n\n // Show Google One Tap prompt\n window.google?.accounts?.id?.prompt((notification) => {\n if (notification.isNotDisplayed()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In popup was blocked. Please allow popups or try again.',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n } else if (notification.isSkippedMoment()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In was cancelled',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n } else if (notification.isDismissedMoment()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In was cancelled',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n }\n });\n });\n }, [config.googleClientId, isInitialized]);\n\n const clearError = useCallback(() => setError(null), []);\n\n return {\n signIn,\n isLoading,\n isInitialized,\n error,\n clearError,\n };\n}\n\n// Type declaration for Google Identity Services\ndeclare global {\n interface Window {\n google?: {\n accounts?: {\n id?: {\n initialize: (config: {\n client_id: string;\n callback: (response: { credential: string }) => void;\n auto_select?: boolean;\n cancel_on_tap_outside?: boolean;\n }) => void;\n prompt: (\n callback: (notification: {\n isNotDisplayed: () => boolean;\n isSkippedMoment: () => boolean;\n isDismissedMoment: () => boolean;\n getMomentType: () => string;\n }) => void\n ) => void;\n renderButton: (element: HTMLElement, config: object) => void;\n disableAutoSelect: () => void;\n };\n };\n };\n }\n}\n","import { useGoogleAuth } from '../../hooks/useGoogleAuth';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\n\nexport interface GoogleLoginButtonProps {\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n className?: string;\n variant?: 'default' | 'outline';\n size?: 'sm' | 'md' | 'lg';\n disabled?: boolean;\n}\n\n/**\n * Google OAuth login button\n */\nexport function GoogleLoginButton({\n onSuccess,\n onError,\n className = '',\n variant = 'default',\n size = 'md',\n disabled = false,\n}: GoogleLoginButtonProps) {\n const { signIn, isLoading, isInitialized } = useGoogleAuth();\n\n const handleClick = async () => {\n try {\n await signIn();\n onSuccess?.();\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n onError?.(error);\n }\n };\n\n const sizeClasses = {\n sm: 'cedros-button-sm',\n md: 'cedros-button-md',\n lg: 'cedros-button-lg',\n };\n\n const variantClasses = {\n default: 'cedros-button-google',\n outline: 'cedros-button-google-outline',\n };\n\n return (\n <button\n type=\"button\"\n className={`cedros-button ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}\n onClick={handleClick}\n disabled={disabled || !isInitialized || isLoading}\n aria-label=\"Sign in with Google\"\n >\n {isLoading ? (\n <LoadingSpinner size=\"sm\" />\n ) : (\n <svg\n className=\"cedros-button-icon\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z\"\n fill=\"#4285F4\"\n />\n <path\n d=\"M9.003 18c2.43 0 4.467-.806 5.956-2.18l-2.909-2.26c-.806.54-1.836.86-3.047.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332A8.997 8.997 0 0 0 9.003 18z\"\n fill=\"#34A853\"\n />\n <path\n d=\"M3.964 10.712A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.96A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.96 4.042l3.004-2.33z\"\n fill=\"#FBBC05\"\n />\n <path\n d=\"M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.428 0 9.002 0A8.997 8.997 0 0 0 .96 4.958l3.005 2.332c.708-2.127 2.692-3.71 5.036-3.71z\"\n fill=\"#EA4335\"\n />\n </svg>\n )}\n <span>Continue with Google</span>\n </button>\n );\n}\n"],"names":["scriptLoader","resolve","reject","existingScript","cb","script","error","useGoogleAuth","config","_internal","useCedrosLogin","isLoading","setIsLoading","useState","isInitialized","setIsInitialized","setError","promiseCallbacksRef","useRef","configRef","apiClient","useMemo","ApiClient","useEffect","handleCredentialResponse","useCallback","response","callbacks","data","err","authError","handleApiError","isMounted","initializeGoogleSignIn","signIn","notification","clearError","GoogleLoginButton","onSuccess","onError","className","variant","size","disabled","handleClick","sizeClasses","variantClasses","jsxs","jsx","LoadingSpinner"],"mappings":"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"}
1
+ {"version":3,"file":"GoogleLoginButton-BydKswn4.cjs","sources":["../src/hooks/useGoogleAuth.ts","../src/components/google/GoogleLoginButton.tsx"],"sourcesContent":["import { useState, useCallback, useEffect, useRef, useMemo } from 'react';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { ApiClient, handleApiError } from '../utils/apiClient';\nimport type { AuthResponse, AuthError } from '../types';\n\n/**\n * Module-level singleton for Google script loading (P-01)\n *\n * Prevents race conditions when multiple components mount simultaneously.\n * Uses a promise queue pattern to ensure the script is only loaded once.\n *\n * ## SSR Limitations (F-08)\n *\n * This singleton persists across the module lifecycle. In SSR environments:\n * - Module state persists between requests (potential cross-request leakage)\n * - Google Sign-In requires browser APIs (document, window)\n * - The hook guards against SSR with `googleClientId` checks\n *\n * For SSR frameworks (Next.js, Remix), ensure this hook is only used\n * in client-side components.\n *\n * ## Test Isolation\n *\n * For test isolation, call `scriptLoader._reset()` in test setup/teardown.\n *\n * @internal\n */\nconst scriptLoader = {\n loading: false,\n loaded: false,\n error: null as Error | null,\n callbacks: [] as Array<{ resolve: () => void; reject: (err: Error) => void }>,\n\n load(): Promise<void> {\n // SSR guard: avoid touching browser globals when running in Node/SSR.\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return Promise.reject(new Error('Google Sign-In script loader cannot run in SSR'));\n }\n\n // Already loaded\n if (this.loaded) {\n return Promise.resolve();\n }\n\n // Loading in progress - queue callback\n if (this.loading) {\n return new Promise((resolve, reject) => {\n this.callbacks.push({ resolve, reject });\n });\n }\n\n // Start loading\n this.loading = true;\n return new Promise((resolve, reject) => {\n this.callbacks.push({ resolve, reject });\n\n // Check if script already exists (from previous session or SSR)\n const existingScript = document.getElementById('google-gsi-script');\n if (existingScript) {\n if (window.google?.accounts?.id) {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n } else {\n existingScript.addEventListener('load', () => {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n });\n }\n return;\n }\n\n const script = document.createElement('script');\n script.src = 'https://accounts.google.com/gsi/client';\n script.async = true;\n script.defer = true;\n script.id = 'google-gsi-script';\n\n script.onload = () => {\n this.loaded = true;\n this.loading = false;\n this.callbacks.forEach((cb) => cb.resolve());\n this.callbacks = [];\n };\n\n script.onerror = () => {\n this.loading = false;\n // M-02: Remove failed script from DOM to allow retry on next load() call.\n // Without removal, retry finds existingScript and waits for a load event\n // that will never fire on an already-failed script.\n script.remove();\n const error = new Error('Failed to load Google Sign-In script');\n this.callbacks.forEach((cb) => cb.reject(error));\n this.callbacks = [];\n };\n\n document.head.appendChild(script);\n });\n },\n\n /**\n * Reset singleton state for test isolation (F-08)\n * @internal - Only use in test setup/teardown\n */\n _reset(): void {\n this.loading = false;\n this.loaded = false;\n this.error = null;\n this.callbacks = [];\n },\n};\n\n/** @internal */\nexport const _internalGoogleScriptLoader = scriptLoader;\n\nexport interface UseGoogleAuthReturn {\n signIn: () => Promise<AuthResponse>;\n isLoading: boolean;\n isInitialized: boolean;\n error: AuthError | null;\n clearError: () => void;\n}\n\ninterface PromiseCallbacks {\n resolve: (value: AuthResponse) => void;\n reject: (error: AuthError) => void;\n}\n\n/**\n * Hook for Google OAuth authentication.\n *\n * @example\n * ```tsx\n * function GoogleButton() {\n * const { signIn, isLoading, isInitialized, error } = useGoogleAuth();\n *\n * return (\n * <button onClick={signIn} disabled={!isInitialized || isLoading}>\n * {isLoading ? 'Signing in...' : 'Sign in with Google'}\n * </button>\n * );\n * }\n * ```\n */\nexport function useGoogleAuth(): UseGoogleAuthReturn {\n const { config, _internal } = useCedrosLogin();\n const [isLoading, setIsLoading] = useState(false);\n const [isInitialized, setIsInitialized] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n\n const promiseCallbacksRef = useRef<PromiseCallbacks | null>(null);\n const configRef = useRef(config);\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 // Keep config ref in sync\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n // Handle credential response from Google\n const handleCredentialResponse = useCallback(\n async (response: { credential: string }) => {\n const callbacks = promiseCallbacksRef.current;\n if (!callbacks) return;\n\n try {\n const data = await apiClient.post<AuthResponse>('/google', {\n idToken: response.credential,\n });\n configRef.current.callbacks?.onLoginSuccess?.(data.user, 'google');\n _internal?.handleLoginSuccess(data.user, data.tokens);\n setIsLoading(false);\n callbacks.resolve(data);\n } catch (err) {\n const authError = handleApiError(err, 'Google sign-in failed');\n setError(authError);\n setIsLoading(false);\n callbacks.reject(authError);\n } finally {\n promiseCallbacksRef.current = null;\n }\n },\n [apiClient, _internal]\n );\n\n // P-01: Initialize Google Sign-In SDK using singleton loader\n useEffect(() => {\n // Early return if Google auth is not enabled\n if (!config.googleClientId) {\n return;\n }\n\n // Track mounted state to prevent state updates after unmount\n let isMounted = true;\n\n const initializeGoogleSignIn = () => {\n if (!isMounted) return;\n\n window.google?.accounts?.id?.initialize({\n client_id: config.googleClientId!,\n callback: handleCredentialResponse,\n auto_select: false,\n cancel_on_tap_outside: true,\n });\n\n if (isMounted) {\n setIsInitialized(true);\n }\n };\n\n // Use singleton loader to handle script loading\n scriptLoader\n .load()\n .then(() => {\n if (isMounted) {\n initializeGoogleSignIn();\n }\n })\n .catch(() => {\n if (isMounted) {\n setError({\n code: 'SERVER_ERROR',\n message: 'Failed to load Google Sign-In',\n });\n }\n });\n\n return () => {\n isMounted = false;\n };\n }, [config.googleClientId, handleCredentialResponse]);\n\n const signIn = useCallback(async (): Promise<AuthResponse> => {\n if (!config.googleClientId) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Client ID not configured',\n };\n setError(err);\n throw err;\n }\n\n if (!isInitialized) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Sign-In not initialized',\n };\n setError(err);\n throw err;\n }\n\n if (promiseCallbacksRef.current) {\n const err: AuthError = {\n code: 'VALIDATION_ERROR',\n message: 'Google Sign-In already in progress',\n };\n setError(err);\n throw err;\n }\n\n setIsLoading(true);\n setError(null);\n\n return new Promise<AuthResponse>((resolve, reject) => {\n promiseCallbacksRef.current = { resolve, reject };\n\n // Show Google One Tap prompt\n window.google?.accounts?.id?.prompt((notification) => {\n if (notification.isNotDisplayed()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In popup was blocked. Please allow popups or try again.',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n } else if (notification.isSkippedMoment()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In was cancelled',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n } else if (notification.isDismissedMoment()) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: 'Google Sign-In was cancelled',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n reject(err);\n }\n });\n });\n }, [config.googleClientId, isInitialized]);\n\n const clearError = useCallback(() => setError(null), []);\n\n return {\n signIn,\n isLoading,\n isInitialized,\n error,\n clearError,\n };\n}\n\n// Type declaration for Google Identity Services\ndeclare global {\n interface Window {\n google?: {\n accounts?: {\n id?: {\n initialize: (config: {\n client_id: string;\n callback: (response: { credential: string }) => void;\n auto_select?: boolean;\n cancel_on_tap_outside?: boolean;\n }) => void;\n prompt: (\n callback: (notification: {\n isNotDisplayed: () => boolean;\n isSkippedMoment: () => boolean;\n isDismissedMoment: () => boolean;\n getMomentType: () => string;\n }) => void\n ) => void;\n renderButton: (element: HTMLElement, config: object) => void;\n disableAutoSelect: () => void;\n };\n };\n };\n }\n}\n","import { useGoogleAuth } from '../../hooks/useGoogleAuth';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\n\nexport interface GoogleLoginButtonProps {\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n className?: string;\n variant?: 'default' | 'outline';\n size?: 'sm' | 'md' | 'lg';\n disabled?: boolean;\n}\n\n/**\n * Google OAuth login button\n */\nexport function GoogleLoginButton({\n onSuccess,\n onError,\n className = '',\n variant = 'default',\n size = 'md',\n disabled = false,\n}: GoogleLoginButtonProps) {\n const { signIn, isLoading, isInitialized } = useGoogleAuth();\n\n const handleClick = async () => {\n try {\n await signIn();\n onSuccess?.();\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n onError?.(error);\n }\n };\n\n const sizeClasses = {\n sm: 'cedros-button-sm',\n md: 'cedros-button-md',\n lg: 'cedros-button-lg',\n };\n\n const variantClasses = {\n default: 'cedros-button-google',\n outline: 'cedros-button-google-outline',\n };\n\n return (\n <button\n type=\"button\"\n className={`cedros-button ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}\n onClick={handleClick}\n disabled={disabled || !isInitialized || isLoading}\n aria-label=\"Sign in with Google\"\n >\n {isLoading ? (\n <LoadingSpinner size=\"sm\" />\n ) : (\n <svg\n className=\"cedros-button-icon\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z\"\n fill=\"#4285F4\"\n />\n <path\n d=\"M9.003 18c2.43 0 4.467-.806 5.956-2.18l-2.909-2.26c-.806.54-1.836.86-3.047.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332A8.997 8.997 0 0 0 9.003 18z\"\n fill=\"#34A853\"\n />\n <path\n d=\"M3.964 10.712A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.96A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.96 4.042l3.004-2.33z\"\n fill=\"#FBBC05\"\n />\n <path\n d=\"M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.428 0 9.002 0A8.997 8.997 0 0 0 .96 4.958l3.005 2.332c.708-2.127 2.692-3.71 5.036-3.71z\"\n fill=\"#EA4335\"\n />\n </svg>\n )}\n <span>Continue with Google</span>\n </button>\n );\n}\n"],"names":["scriptLoader","resolve","reject","existingScript","cb","script","error","useGoogleAuth","config","_internal","useCedrosLogin","isLoading","setIsLoading","useState","isInitialized","setIsInitialized","setError","promiseCallbacksRef","useRef","configRef","apiClient","useMemo","ApiClient","useEffect","handleCredentialResponse","useCallback","response","callbacks","data","err","authError","handleApiError","isMounted","initializeGoogleSignIn","signIn","notification","clearError","GoogleLoginButton","onSuccess","onError","className","variant","size","disabled","handleClick","sizeClasses","variantClasses","jsxs","jsx","LoadingSpinner"],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ import { createContext as e, memo as d } from "react";
2
+ import { jsxs as a, jsx as r } from "react/jsx-runtime";
3
+ const f = e(null), x = e(null), C = e(null), m = {
4
+ sm: 16,
5
+ md: 24,
6
+ lg: 32,
7
+ xl: 48
8
+ // H-04: Added for WalletUnlock component
9
+ }, k = d(function({
10
+ size: i = "md",
11
+ className: c = "",
12
+ style: l,
13
+ label: t = "Loading",
14
+ announce: n = !1
15
+ }) {
16
+ const s = m[i], o = /* @__PURE__ */ a(
17
+ "svg",
18
+ {
19
+ className: `cedros-spinner ${c}`,
20
+ width: s,
21
+ height: s,
22
+ viewBox: "0 0 24 24",
23
+ fill: "none",
24
+ style: l,
25
+ "aria-label": t,
26
+ role: "status",
27
+ "aria-hidden": n ? "true" : void 0,
28
+ children: [
29
+ /* @__PURE__ */ r(
30
+ "circle",
31
+ {
32
+ className: "cedros-spinner-track",
33
+ cx: "12",
34
+ cy: "12",
35
+ r: "10",
36
+ stroke: "currentColor",
37
+ strokeWidth: "3",
38
+ strokeOpacity: "0.25"
39
+ }
40
+ ),
41
+ /* @__PURE__ */ r(
42
+ "circle",
43
+ {
44
+ className: "cedros-spinner-head",
45
+ cx: "12",
46
+ cy: "12",
47
+ r: "10",
48
+ stroke: "currentColor",
49
+ strokeWidth: "3",
50
+ strokeLinecap: "round",
51
+ strokeDasharray: "31.4 31.4",
52
+ transform: "rotate(-90 12 12)",
53
+ children: /* @__PURE__ */ r(
54
+ "animateTransform",
55
+ {
56
+ attributeName: "transform",
57
+ type: "rotate",
58
+ from: "0 12 12",
59
+ to: "360 12 12",
60
+ dur: "1s",
61
+ repeatCount: "indefinite"
62
+ }
63
+ )
64
+ }
65
+ )
66
+ ]
67
+ }
68
+ );
69
+ return n ? /* @__PURE__ */ a("span", { "aria-live": "polite", "aria-busy": "true", children: [
70
+ o,
71
+ /* @__PURE__ */ r("span", { className: "cedros-sr-only", children: t })
72
+ ] }) : o;
73
+ });
74
+ export {
75
+ f as A,
76
+ C,
77
+ k as L,
78
+ x as a
79
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingSpinner-6vml-zwr.js","sources":["../src/context/CedrosLoginContext.ts","../src/components/shared/LoadingSpinner.tsx"],"sourcesContent":["import { createContext } from 'react';\nimport type { CedrosLoginConfig, AuthUser, AuthState, AuthError, TokenPair } from '../types';\n\n/**\n * Internal helpers for auth hooks (not part of public API)\n */\nexport interface CedrosLoginInternalAPI {\n handleLoginSuccess: (user: AuthUser, tokens?: TokenPair) => void;\n getAccessToken: () => string | null;\n}\n\n/**\n * Auth state context — changes only on login/logout/token refresh.\n *\n * Subscribing to this context alone avoids re-renders from UI state\n * changes (modal open/close, error display).\n */\nexport interface AuthStateContextValue {\n config: CedrosLoginConfig;\n user: AuthUser | null;\n authState: AuthState;\n logout: () => Promise<void>;\n refreshUser: () => Promise<void>;\n _internal?: CedrosLoginInternalAPI;\n}\n\n/**\n * UI state context — changes on modal/error state changes.\n *\n * Subscribing to this context alone avoids re-renders from auth state\n * changes (login, token refresh).\n */\nexport interface AuthUIContextValue {\n error: AuthError | null;\n isModalOpen: boolean;\n openModal: () => void;\n closeModal: () => void;\n}\n\n/**\n * Combined context value (backward-compatible with existing consumers)\n */\nexport interface CedrosLoginContextValue extends AuthStateContextValue, AuthUIContextValue {}\n\nexport const AuthStateContext = createContext<AuthStateContextValue | null>(null);\nexport const AuthUIContext = createContext<AuthUIContextValue | null>(null);\n\n/**\n * @deprecated Use AuthStateContext + AuthUIContext directly for better performance.\n * Kept for backward compatibility with useCedrosLogin.\n */\nexport const CedrosLoginContext = createContext<CedrosLoginContextValue | null>(null);\n","import { memo, type CSSProperties } from 'react';\n\nexport interface LoadingSpinnerProps {\n size?: 'sm' | 'md' | 'lg' | 'xl';\n className?: string;\n style?: CSSProperties;\n /** Custom label for screen readers (default: \"Loading\") */\n label?: string;\n /** If true, announce the loading state to screen readers */\n announce?: boolean;\n}\n\nconst sizeMap = {\n sm: 16,\n md: 24,\n lg: 32,\n xl: 48, // H-04: Added for WalletUnlock component\n};\n\n/**\n * Accessible loading spinner component.\n * Announces loading state to screen readers when announce prop is true.\n * Wrapped with React.memo to prevent unnecessary re-renders.\n */\nexport const LoadingSpinner = memo(function LoadingSpinner({\n size = 'md',\n className = '',\n style,\n label = 'Loading',\n announce = false,\n}: LoadingSpinnerProps) {\n const dimension = sizeMap[size];\n\n const spinner = (\n <svg\n className={`cedros-spinner ${className}`}\n width={dimension}\n height={dimension}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n style={style}\n aria-label={label}\n role=\"status\"\n aria-hidden={announce ? 'true' : undefined}\n >\n <circle\n className=\"cedros-spinner-track\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeOpacity=\"0.25\"\n />\n <circle\n className=\"cedros-spinner-head\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeDasharray=\"31.4 31.4\"\n transform=\"rotate(-90 12 12)\"\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 12 12\"\n to=\"360 12 12\"\n dur=\"1s\"\n repeatCount=\"indefinite\"\n />\n </circle>\n </svg>\n );\n\n // Wrap in aria-live region if announce is true\n if (announce) {\n return (\n <span aria-live=\"polite\" aria-busy=\"true\">\n {spinner}\n <span className=\"cedros-sr-only\">{label}</span>\n </span>\n );\n }\n\n return spinner;\n});\n"],"names":["AuthStateContext","createContext","AuthUIContext","CedrosLoginContext","sizeMap","LoadingSpinner","memo","size","className","style","label","announce","dimension","spinner","jsxs","jsx"],"mappings":";;AA4CO,MAAMA,IAAmBC,EAA4C,IAAI,GACnEC,IAAgBD,EAAyC,IAAI,GAM7DE,IAAqBF,EAA8C,IAAI,GCvC9EG,IAAU;AAAA,EACd,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA;AACN,GAOaC,IAAiBC,EAAK,SAAwB;AAAA,EACzD,MAAAC,IAAO;AAAA,EACP,WAAAC,IAAY;AAAA,EACZ,OAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,UAAAC,IAAW;AACb,GAAwB;AACtB,QAAMC,IAAYR,EAAQG,CAAI,GAExBM,IACJ,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,kBAAkBN,CAAS;AAAA,MACtC,OAAOI;AAAA,MACP,QAAQA;AAAA,MACR,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,OAAAH;AAAA,MACA,cAAYC;AAAA,MACZ,MAAK;AAAA,MACL,eAAaC,IAAW,SAAS;AAAA,MAEjC,UAAA;AAAA,QAAA,gBAAAI;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,IAAG;AAAA,YACH,IAAG;AAAA,YACH,GAAE;AAAA,YACF,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAc;AAAA,UAAA;AAAA,QAAA;AAAA,QAEhB,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,IAAG;AAAA,YACH,IAAG;AAAA,YACH,GAAE;AAAA,YACF,QAAO;AAAA,YACP,aAAY;AAAA,YACZ,eAAc;AAAA,YACd,iBAAgB;AAAA,YAChB,WAAU;AAAA,YAEV,UAAA,gBAAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAc;AAAA,gBACd,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL,IAAG;AAAA,gBACH,KAAI;AAAA,gBACJ,aAAY;AAAA,cAAA;AAAA,YAAA;AAAA,UACd;AAAA,QAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAAA;AAKJ,SAAIJ,IAEA,gBAAAG,EAAC,QAAA,EAAK,aAAU,UAAS,aAAU,QAChC,UAAA;AAAA,IAAAD;AAAA,IACD,gBAAAE,EAAC,QAAA,EAAK,WAAU,kBAAkB,UAAAL,EAAA,CAAM;AAAA,EAAA,GAC1C,IAIGG;AACT,CAAC;"}
@@ -0,0 +1 @@
1
+ "use strict";const t=require("react"),e=require("react/jsx-runtime"),d=t.createContext(null),l=t.createContext(null),u=t.createContext(null),x={sm:16,md:24,lg:32,xl:48},m=t.memo(function({size:i="md",className:a="",style:c,label:r="Loading",announce:n=!1}){const s=x[i],o=e.jsxs("svg",{className:`cedros-spinner ${a}`,width:s,height:s,viewBox:"0 0 24 24",fill:"none",style:c,"aria-label":r,role:"status","aria-hidden":n?"true":void 0,children:[e.jsx("circle",{className:"cedros-spinner-track",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"3",strokeOpacity:"0.25"}),e.jsx("circle",{className:"cedros-spinner-head",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round",strokeDasharray:"31.4 31.4",transform:"rotate(-90 12 12)",children:e.jsx("animateTransform",{attributeName:"transform",type:"rotate",from:"0 12 12",to:"360 12 12",dur:"1s",repeatCount:"indefinite"})})]});return n?e.jsxs("span",{"aria-live":"polite","aria-busy":"true",children:[o,e.jsx("span",{className:"cedros-sr-only",children:r})]}):o});exports.AuthStateContext=d;exports.AuthUIContext=l;exports.CedrosLoginContext=u;exports.LoadingSpinner=m;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingSpinner-d6sSxgQN.cjs","sources":["../src/context/CedrosLoginContext.ts","../src/components/shared/LoadingSpinner.tsx"],"sourcesContent":["import { createContext } from 'react';\nimport type { CedrosLoginConfig, AuthUser, AuthState, AuthError, TokenPair } from '../types';\n\n/**\n * Internal helpers for auth hooks (not part of public API)\n */\nexport interface CedrosLoginInternalAPI {\n handleLoginSuccess: (user: AuthUser, tokens?: TokenPair) => void;\n getAccessToken: () => string | null;\n}\n\n/**\n * Auth state context — changes only on login/logout/token refresh.\n *\n * Subscribing to this context alone avoids re-renders from UI state\n * changes (modal open/close, error display).\n */\nexport interface AuthStateContextValue {\n config: CedrosLoginConfig;\n user: AuthUser | null;\n authState: AuthState;\n logout: () => Promise<void>;\n refreshUser: () => Promise<void>;\n _internal?: CedrosLoginInternalAPI;\n}\n\n/**\n * UI state context — changes on modal/error state changes.\n *\n * Subscribing to this context alone avoids re-renders from auth state\n * changes (login, token refresh).\n */\nexport interface AuthUIContextValue {\n error: AuthError | null;\n isModalOpen: boolean;\n openModal: () => void;\n closeModal: () => void;\n}\n\n/**\n * Combined context value (backward-compatible with existing consumers)\n */\nexport interface CedrosLoginContextValue extends AuthStateContextValue, AuthUIContextValue {}\n\nexport const AuthStateContext = createContext<AuthStateContextValue | null>(null);\nexport const AuthUIContext = createContext<AuthUIContextValue | null>(null);\n\n/**\n * @deprecated Use AuthStateContext + AuthUIContext directly for better performance.\n * Kept for backward compatibility with useCedrosLogin.\n */\nexport const CedrosLoginContext = createContext<CedrosLoginContextValue | null>(null);\n","import { memo, type CSSProperties } from 'react';\n\nexport interface LoadingSpinnerProps {\n size?: 'sm' | 'md' | 'lg' | 'xl';\n className?: string;\n style?: CSSProperties;\n /** Custom label for screen readers (default: \"Loading\") */\n label?: string;\n /** If true, announce the loading state to screen readers */\n announce?: boolean;\n}\n\nconst sizeMap = {\n sm: 16,\n md: 24,\n lg: 32,\n xl: 48, // H-04: Added for WalletUnlock component\n};\n\n/**\n * Accessible loading spinner component.\n * Announces loading state to screen readers when announce prop is true.\n * Wrapped with React.memo to prevent unnecessary re-renders.\n */\nexport const LoadingSpinner = memo(function LoadingSpinner({\n size = 'md',\n className = '',\n style,\n label = 'Loading',\n announce = false,\n}: LoadingSpinnerProps) {\n const dimension = sizeMap[size];\n\n const spinner = (\n <svg\n className={`cedros-spinner ${className}`}\n width={dimension}\n height={dimension}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n style={style}\n aria-label={label}\n role=\"status\"\n aria-hidden={announce ? 'true' : undefined}\n >\n <circle\n className=\"cedros-spinner-track\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeOpacity=\"0.25\"\n />\n <circle\n className=\"cedros-spinner-head\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n strokeLinecap=\"round\"\n strokeDasharray=\"31.4 31.4\"\n transform=\"rotate(-90 12 12)\"\n >\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 12 12\"\n to=\"360 12 12\"\n dur=\"1s\"\n repeatCount=\"indefinite\"\n />\n </circle>\n </svg>\n );\n\n // Wrap in aria-live region if announce is true\n if (announce) {\n return (\n <span aria-live=\"polite\" aria-busy=\"true\">\n {spinner}\n <span className=\"cedros-sr-only\">{label}</span>\n </span>\n );\n }\n\n return spinner;\n});\n"],"names":["AuthStateContext","createContext","AuthUIContext","CedrosLoginContext","sizeMap","LoadingSpinner","memo","size","className","style","label","announce","dimension","spinner","jsxs","jsx"],"mappings":"qEA4CaA,EAAmBC,EAAAA,cAA4C,IAAI,EACnEC,EAAgBD,EAAAA,cAAyC,IAAI,EAM7DE,EAAqBF,EAAAA,cAA8C,IAAI,ECvC9EG,EAAU,CACd,GAAI,GACJ,GAAI,GACJ,GAAI,GACJ,GAAI,EACN,EAOaC,EAAiBC,EAAAA,KAAK,SAAwB,CACzD,KAAAC,EAAO,KACP,UAAAC,EAAY,GACZ,MAAAC,EACA,MAAAC,EAAQ,UACR,SAAAC,EAAW,EACb,EAAwB,CACtB,MAAMC,EAAYR,EAAQG,CAAI,EAExBM,EACJC,EAAAA,KAAC,MAAA,CACC,UAAW,kBAAkBN,CAAS,GACtC,MAAOI,EACP,OAAQA,EACR,QAAQ,YACR,KAAK,OACL,MAAAH,EACA,aAAYC,EACZ,KAAK,SACL,cAAaC,EAAW,OAAS,OAEjC,SAAA,CAAAI,EAAAA,IAAC,SAAA,CACC,UAAU,uBACV,GAAG,KACH,GAAG,KACH,EAAE,KACF,OAAO,eACP,YAAY,IACZ,cAAc,MAAA,CAAA,EAEhBA,EAAAA,IAAC,SAAA,CACC,UAAU,sBACV,GAAG,KACH,GAAG,KACH,EAAE,KACF,OAAO,eACP,YAAY,IACZ,cAAc,QACd,gBAAgB,YAChB,UAAU,oBAEV,SAAAA,EAAAA,IAAC,mBAAA,CACC,cAAc,YACd,KAAK,SACL,KAAK,UACL,GAAG,YACH,IAAI,KACJ,YAAY,YAAA,CAAA,CACd,CAAA,CACF,CAAA,CAAA,EAKJ,OAAIJ,EAEAG,EAAAA,KAAC,OAAA,CAAK,YAAU,SAAS,YAAU,OAChC,SAAA,CAAAD,EACDE,EAAAA,IAAC,OAAA,CAAK,UAAU,iBAAkB,SAAAL,CAAA,CAAM,CAAA,EAC1C,EAIGG,CACT,CAAC"}