@cedros/login-react 0.0.41 → 0.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AuthenticationSettings-D4ExU-2a.js → AuthenticationSettings-CheE3j7w.js} +1 -1
- package/dist/{AuthenticationSettings-D4ExU-2a.js.map → AuthenticationSettings-CheE3j7w.js.map} +1 -1
- package/dist/{AuthenticationSettings-Cu5Z2mTC.cjs → AuthenticationSettings-Dl41GbJL.cjs} +1 -1
- package/dist/{AuthenticationSettings-Cu5Z2mTC.cjs.map → AuthenticationSettings-Dl41GbJL.cjs.map} +1 -1
- package/dist/{AuthenticationSettings-CSoFp-_2.js → AuthenticationSettings-DwSxgjbH.js} +1 -1
- package/dist/{AuthenticationSettings-CSoFp-_2.js.map → AuthenticationSettings-DwSxgjbH.js.map} +1 -1
- package/dist/{AuthenticationSettings-DABzZHuI.cjs → AuthenticationSettings-JxHsBst9.cjs} +1 -1
- package/dist/{AuthenticationSettings-DABzZHuI.cjs.map → AuthenticationSettings-JxHsBst9.cjs.map} +1 -1
- package/dist/AutosaveStatus-BMXjH1XN.cjs +1 -0
- package/dist/AutosaveStatus-BMXjH1XN.cjs.map +1 -0
- package/dist/{AutosaveStatus-DMjvXzP2.js → AutosaveStatus-DNuCl59W.js} +578 -284
- package/dist/AutosaveStatus-DNuCl59W.js.map +1 -0
- package/dist/{CreditSystemSettings-DfSfQVE8.cjs → CreditSystemSettings-BVgl6uUg.cjs} +1 -1
- package/dist/{CreditSystemSettings-DfSfQVE8.cjs.map → CreditSystemSettings-BVgl6uUg.cjs.map} +1 -1
- package/dist/{CreditSystemSettings-Du3ac0ID.js → CreditSystemSettings-C-ksysSx.js} +1 -1
- package/dist/{CreditSystemSettings-Du3ac0ID.js.map → CreditSystemSettings-C-ksysSx.js.map} +1 -1
- package/dist/{CreditSystemSettings-BjQdysRS.js → CreditSystemSettings-HSdF2_CY.js} +1 -1
- package/dist/{CreditSystemSettings-BjQdysRS.js.map → CreditSystemSettings-HSdF2_CY.js.map} +1 -1
- package/dist/{CreditSystemSettings-BWuiRTtA.cjs → CreditSystemSettings-LvA8rb17.cjs} +1 -1
- package/dist/{CreditSystemSettings-BWuiRTtA.cjs.map → CreditSystemSettings-LvA8rb17.cjs.map} +1 -1
- package/dist/{EmailRegisterForm-CMXsa-_r.js → EmailRegisterForm-p2X5QP58.js} +147 -147
- package/dist/EmailRegisterForm-p2X5QP58.js.map +1 -0
- package/dist/EmailRegisterForm-xFb6MaVA.cjs +1 -0
- package/dist/EmailRegisterForm-xFb6MaVA.cjs.map +1 -0
- package/dist/{EmailSettings-CjngJwDS.js → EmailSettings-Cy1cuVUq.js} +1 -1
- package/dist/{EmailSettings-CjngJwDS.js.map → EmailSettings-Cy1cuVUq.js.map} +1 -1
- package/dist/{EmailSettings-BcHo0cqk.cjs → EmailSettings-DC_zT4nI.cjs} +1 -1
- package/dist/{EmailSettings-BcHo0cqk.cjs.map → EmailSettings-DC_zT4nI.cjs.map} +1 -1
- package/dist/{EmailSettings-CswtKXhb.cjs → EmailSettings-QBMzpbxv.cjs} +1 -1
- package/dist/{EmailSettings-CswtKXhb.cjs.map → EmailSettings-QBMzpbxv.cjs.map} +1 -1
- package/dist/{EmailSettings-ASDHfI0K.js → EmailSettings-hIhJzux0.js} +1 -1
- package/dist/{EmailSettings-ASDHfI0K.js.map → EmailSettings-hIhJzux0.js.map} +1 -1
- package/dist/{EmbeddedWalletSettings-BkwIbTkL.cjs → EmbeddedWalletSettings-4qC9KBwh.cjs} +1 -1
- package/dist/{EmbeddedWalletSettings-BkwIbTkL.cjs.map → EmbeddedWalletSettings-4qC9KBwh.cjs.map} +1 -1
- package/dist/{EmbeddedWalletSettings-BXlboZ9-.cjs → EmbeddedWalletSettings-C81QQMWz.cjs} +1 -1
- package/dist/{EmbeddedWalletSettings-BXlboZ9-.cjs.map → EmbeddedWalletSettings-C81QQMWz.cjs.map} +1 -1
- package/dist/{EmbeddedWalletSettings-CPLbqlxJ.js → EmbeddedWalletSettings-CvvTnRvt.js} +1 -1
- package/dist/{EmbeddedWalletSettings-CPLbqlxJ.js.map → EmbeddedWalletSettings-CvvTnRvt.js.map} +1 -1
- package/dist/{EmbeddedWalletSettings-CUY_X7Vj.js → EmbeddedWalletSettings-Cwiug0vR.js} +1 -1
- package/dist/{EmbeddedWalletSettings-CUY_X7Vj.js.map → EmbeddedWalletSettings-Cwiug0vR.js.map} +1 -1
- package/dist/GoogleLoginButton-2zNTIKMm.cjs +1 -0
- package/dist/GoogleLoginButton-2zNTIKMm.cjs.map +1 -0
- package/dist/{GoogleLoginButton-qf4A_A3G.js → GoogleLoginButton-C1WNu7W3.js} +41 -40
- package/dist/GoogleLoginButton-C1WNu7W3.js.map +1 -0
- package/dist/LoadingSpinner-6vml-zwr.js.map +1 -1
- package/dist/LoadingSpinner-d6sSxgQN.cjs.map +1 -1
- package/dist/{PermissionsSection-BeFhIgQy.js → PermissionsSection-BDDiEfho.js} +81 -77
- package/dist/{PermissionsSection-BeFhIgQy.js.map → PermissionsSection-BDDiEfho.js.map} +1 -1
- package/dist/PermissionsSection-CSB_Ikj9.cjs +1 -0
- package/dist/{PermissionsSection-B-6DJnN8.cjs.map → PermissionsSection-CSB_Ikj9.cjs.map} +1 -1
- package/dist/{ServerSettings-BygCxOTY.cjs → ServerSettings-BV0SipW1.cjs} +1 -1
- package/dist/{ServerSettings-BygCxOTY.cjs.map → ServerSettings-BV0SipW1.cjs.map} +1 -1
- package/dist/{ServerSettings-CgBdYspU.cjs → ServerSettings-Bf7gFE8r.cjs} +1 -1
- package/dist/{ServerSettings-CgBdYspU.cjs.map → ServerSettings-Bf7gFE8r.cjs.map} +1 -1
- package/dist/{ServerSettings-BLoWX7KG.js → ServerSettings-DPqHtsgV.js} +1 -1
- package/dist/{ServerSettings-BLoWX7KG.js.map → ServerSettings-DPqHtsgV.js.map} +1 -1
- package/dist/{ServerSettings-B9PNMse1.js → ServerSettings-Sfr0CG6K.js} +1 -1
- package/dist/{ServerSettings-B9PNMse1.js.map → ServerSettings-Sfr0CG6K.js.map} +1 -1
- package/dist/SolanaLoginButton-CqdzSSeJ.cjs +1 -0
- package/dist/SolanaLoginButton-CqdzSSeJ.cjs.map +1 -0
- package/dist/{SolanaLoginButton-B04dib6X.js → SolanaLoginButton-CyeX35eU.js} +41 -40
- package/dist/SolanaLoginButton-CyeX35eU.js.map +1 -0
- package/dist/{TeamSection-DbSYDRdI.js → TeamSection-BhsBEckR.js} +1 -1
- package/dist/{TeamSection-DbSYDRdI.js.map → TeamSection-BhsBEckR.js.map} +1 -1
- package/dist/{TeamSection-B1t1tU-_.cjs → TeamSection-DLxtRmta.cjs} +1 -1
- package/dist/{TeamSection-B1t1tU-_.cjs.map → TeamSection-DLxtRmta.cjs.map} +1 -1
- package/dist/{UsersSection-C7aRNkK2.cjs → UsersSection-BEKfbhQ4.cjs} +1 -1
- package/dist/{UsersSection-C7aRNkK2.cjs.map → UsersSection-BEKfbhQ4.cjs.map} +1 -1
- package/dist/{UsersSection--PAE1XRh.js → UsersSection-DbGkmxty.js} +1 -1
- package/dist/{UsersSection--PAE1XRh.js.map → UsersSection-DbGkmxty.js.map} +1 -1
- package/dist/{WebhookSettings-D19u9Uok.cjs → WebhookSettings-BPCKv5Or.cjs} +1 -1
- package/dist/{WebhookSettings-D19u9Uok.cjs.map → WebhookSettings-BPCKv5Or.cjs.map} +1 -1
- package/dist/{WebhookSettings-C923ZSKa.js → WebhookSettings-CMROMCFT.js} +1 -1
- package/dist/{WebhookSettings-C923ZSKa.js.map → WebhookSettings-CMROMCFT.js.map} +1 -1
- package/dist/{WebhookSettings-CbU3cfTJ.cjs → WebhookSettings-Cj-iELGa.cjs} +1 -1
- package/dist/{WebhookSettings-CbU3cfTJ.cjs.map → WebhookSettings-Cj-iELGa.cjs.map} +1 -1
- package/dist/{WebhookSettings-C-7Yxueu.js → WebhookSettings-D4mKAWAg.js} +1 -1
- package/dist/{WebhookSettings-C-7Yxueu.js.map → WebhookSettings-D4mKAWAg.js.map} +1 -1
- package/dist/admin-only.cjs +1 -1
- package/dist/admin-only.js +1 -1
- package/dist/email-only.cjs +1 -1
- package/dist/email-only.d.ts +6 -0
- package/dist/email-only.js +2 -2
- package/dist/google-only.cjs +1 -1
- package/dist/google-only.d.ts +6 -0
- package/dist/google-only.js +2 -2
- package/dist/index.cjs +13 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +411 -1
- package/dist/index.js +5175 -4054
- package/dist/index.js.map +1 -1
- package/dist/plugin-BHGg7ius.cjs +1 -0
- package/dist/plugin-BHGg7ius.cjs.map +1 -0
- package/dist/{plugin-BiftIhZe.js → plugin-CK2d7aP5.js} +3 -2
- package/dist/plugin-CK2d7aP5.js.map +1 -0
- package/dist/solana-only.cjs +1 -1
- package/dist/solana-only.d.ts +6 -0
- package/dist/solana-only.js +2 -2
- package/dist/useAuth-B1yS_YiD.cjs +1 -0
- package/dist/{useAuth-U5CYsHEU.cjs.map → useAuth-B1yS_YiD.cjs.map} +1 -1
- package/dist/{useAuth-C-Vw-ggy.js → useAuth-l-itM5am.js} +440 -433
- package/dist/{useAuth-C-Vw-ggy.js.map → useAuth-l-itM5am.js.map} +1 -1
- package/dist/useUsersStatsSummary-9HQDKBU5.js +1879 -0
- package/dist/useUsersStatsSummary-9HQDKBU5.js.map +1 -0
- package/dist/useUsersStatsSummary-DiRC8sGs.cjs +1 -0
- package/dist/useUsersStatsSummary-DiRC8sGs.cjs.map +1 -0
- package/package.json +1 -1
- package/dist/AutosaveStatus-B1A1zORa.cjs +0 -1
- package/dist/AutosaveStatus-B1A1zORa.cjs.map +0 -1
- package/dist/AutosaveStatus-DMjvXzP2.js.map +0 -1
- package/dist/EmailRegisterForm-CMXsa-_r.js.map +0 -1
- package/dist/EmailRegisterForm-i7f4St2N.cjs +0 -1
- package/dist/EmailRegisterForm-i7f4St2N.cjs.map +0 -1
- package/dist/GoogleLoginButton-JtRViYWS.cjs +0 -1
- package/dist/GoogleLoginButton-JtRViYWS.cjs.map +0 -1
- package/dist/GoogleLoginButton-qf4A_A3G.js.map +0 -1
- package/dist/PermissionsSection-B-6DJnN8.cjs +0 -1
- package/dist/SolanaLoginButton-B04dib6X.js.map +0 -1
- package/dist/SolanaLoginButton-nSJHVFpZ.cjs +0 -1
- package/dist/SolanaLoginButton-nSJHVFpZ.cjs.map +0 -1
- package/dist/plugin-BiftIhZe.js.map +0 -1
- package/dist/plugin-BtQdI_Ay.cjs +0 -1
- package/dist/plugin-BtQdI_Ay.cjs.map +0 -1
- package/dist/useAuth-U5CYsHEU.cjs +0 -1
- package/dist/useUsersStatsSummary-5DJwzntC.js +0 -1246
- package/dist/useUsersStatsSummary-5DJwzntC.js.map +0 -1
- package/dist/useUsersStatsSummary-DgKaUIfs.cjs +0 -1
- package/dist/useUsersStatsSummary-DgKaUIfs.cjs.map +0 -1
package/dist/{EmbeddedWalletSettings-BkwIbTkL.cjs.map → EmbeddedWalletSettings-4qC9KBwh.cjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmbeddedWalletSettings-
|
|
1
|
+
{"version":3,"file":"EmbeddedWalletSettings-4qC9KBwh.cjs","sources":["../src/components/admin/settings/EmbeddedWalletSettings.tsx"],"sourcesContent":["/**\n * Embedded Wallet settings page - enable/disable and configure recovery\n */\nimport { useEffect, useMemo } 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', 'wallet_enroll_solana_users'];\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 // Cross-category mismatch detection\n const privateDepositsEnabled = getEffectiveValue('deposit_privacy_enabled') === 'true';\n const recoveryMode = getEffectiveValue('wallet_recovery_mode');\n const recoveryMismatch = privateDepositsEnabled && recoveryMode !== 'none';\n const walletMismatch = privateDepositsEnabled && !walletEnabled;\n\n // Inline warning on recovery mode row\n const externalWarnings = useMemo(() => {\n if (!recoveryMismatch) return undefined;\n return {\n wallet_recovery_mode:\n 'Private deposits require No Recovery mode. Deposits will fail with the current setting.',\n };\n }, [recoveryMismatch]);\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 {/* Mismatch warnings */}\n {recoveryMismatch && (\n <div className=\"cedros-settings-warning-banner\">\n Private deposits are enabled but require No Recovery mode. Users will see an error when\n attempting private deposits until recovery mode is changed below.\n </div>\n )}\n {walletMismatch && (\n <div className=\"cedros-settings-warning-banner\">\n Private deposits are enabled but require the embedded wallet. Enable it above.\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\n settings={currentSettings}\n edits={edits}\n onChange={handleChange}\n externalWarnings={externalWarnings}\n />\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","privateDepositsEnabled","recoveryMode","recoveryMismatch","walletMismatch","externalWarnings","useMemo","jsx","LoadingSpinner","ErrorMessage","jsxs","AutosaveStatus","SettingsSection"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime");require("react");const t=require("./EmbeddedWalletSettings-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime");require("react");const t=require("./EmbeddedWalletSettings-4qC9KBwh.cjs");function d(){return e.jsx("div",{className:"cedros-dashboard__section",children:e.jsx(t.EmbeddedWalletSettings,{})})}exports.default=d;
|
package/dist/{EmbeddedWalletSettings-BXlboZ9-.cjs.map → EmbeddedWalletSettings-C81QQMWz.cjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmbeddedWalletSettings-
|
|
1
|
+
{"version":3,"file":"EmbeddedWalletSettings-C81QQMWz.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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as e } from "react/jsx-runtime";
|
|
2
2
|
import "react";
|
|
3
|
-
import { E as t } from "./EmbeddedWalletSettings-
|
|
3
|
+
import { E as t } from "./EmbeddedWalletSettings-Cwiug0vR.js";
|
|
4
4
|
function s() {
|
|
5
5
|
return /* @__PURE__ */ e("div", { className: "cedros-dashboard__section", children: /* @__PURE__ */ e(t, {}) });
|
|
6
6
|
}
|
package/dist/{EmbeddedWalletSettings-CPLbqlxJ.js.map → EmbeddedWalletSettings-CvvTnRvt.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmbeddedWalletSettings-
|
|
1
|
+
{"version":3,"file":"EmbeddedWalletSettings-CvvTnRvt.js","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":";;;AAOA,SAAwBA,IAA4C;AAClE,2BACG,OAAA,EAAI,WAAU,6BACb,UAAA,gBAAAC,EAACC,KAAS,GACZ;AAEJ;"}
|
|
@@ -2,7 +2,7 @@ import { jsxs as s, jsx as e } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect as k, useMemo as x } from "react";
|
|
3
3
|
import { L } from "./LoadingSpinner-6vml-zwr.js";
|
|
4
4
|
import { E as W } from "./ErrorMessage-CcEK0pYO.js";
|
|
5
|
-
import { u as C, A as M, S as $ } from "./AutosaveStatus-
|
|
5
|
+
import { u as C, A as M, S as $ } from "./AutosaveStatus-DNuCl59W.js";
|
|
6
6
|
const d = ["wallet_recovery_mode", "wallet_enroll_solana_users"];
|
|
7
7
|
function q({ className: n }) {
|
|
8
8
|
const {
|
package/dist/{EmbeddedWalletSettings-CUY_X7Vj.js.map → EmbeddedWalletSettings-Cwiug0vR.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmbeddedWalletSettings-CUY_X7Vj.js","sources":["../src/components/admin/settings/EmbeddedWalletSettings.tsx"],"sourcesContent":["/**\n * Embedded Wallet settings page - enable/disable and configure recovery\n */\nimport { useEffect, useMemo } 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', 'wallet_enroll_solana_users'];\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 // Cross-category mismatch detection\n const privateDepositsEnabled = getEffectiveValue('deposit_privacy_enabled') === 'true';\n const recoveryMode = getEffectiveValue('wallet_recovery_mode');\n const recoveryMismatch = privateDepositsEnabled && recoveryMode !== 'none';\n const walletMismatch = privateDepositsEnabled && !walletEnabled;\n\n // Inline warning on recovery mode row\n const externalWarnings = useMemo(() => {\n if (!recoveryMismatch) return undefined;\n return {\n wallet_recovery_mode:\n 'Private deposits require No Recovery mode. Deposits will fail with the current setting.',\n };\n }, [recoveryMismatch]);\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 {/* Mismatch warnings */}\n {recoveryMismatch && (\n <div className=\"cedros-settings-warning-banner\">\n Private deposits are enabled but require No Recovery mode. Users will see an error when\n attempting private deposits until recovery mode is changed below.\n </div>\n )}\n {walletMismatch && (\n <div className=\"cedros-settings-warning-banner\">\n Private deposits are enabled but require the embedded wallet. Enable it above.\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\n settings={currentSettings}\n edits={edits}\n onChange={handleChange}\n externalWarnings={externalWarnings}\n />\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","privateDepositsEnabled","recoveryMode","recoveryMismatch","walletMismatch","externalWarnings","useMemo","jsx","LoadingSpinner","ErrorMessage","jsxs","AutosaveStatus","SettingsSection"],"mappings":";;;;;AAWA,MAAMA,IAAgB,CAAC,wBAAwB,4BAA4B;AAMpE,SAASC,EAAuB,EAAE,WAAAC,KAA0C;AACjF,QAAM;AAAA,IACJ,UAAAC;AAAA,IACA,OAAAC;AAAA,IACA,WAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,eAAAC;AAAA,IACA,OAAAC;AAAA,IACA,eAAAC;AAAA,IACA,cAAAC;AAAA,IACA,mBAAAC;AAAA,EAAA,IACEC,EAAA;AAEJ,EAAAC,EAAU,MAAM;AACd,IAAAJ,EAAA;AAAA,EACF,GAAG,CAACA,CAAa,CAAC;AAIlB,QAAMK,KADmBX,EAAS,YAAe,CAAA,GAE9C,OAAO,CAACY,MAAMf,EAAc,SAASe,EAAE,GAAG,CAAC,EAC3C,KAAK,CAACC,GAAGC,MAAMjB,EAAc,QAAQgB,EAAE,GAAG,IAAIhB,EAAc,QAAQiB,EAAE,GAAG,CAAC,GAGvEC,IAAgBP,EAAkB,wBAAwB,MAAM,QAChEQ,IAAqB,MAAM;AAC/B,IAAAT,EAAa,0BAA0BQ,IAAgB,UAAU,MAAM;AAAA,EACzE,GAGME,IAAqBT,EAAkB,0BAA0B,MAAM,QACvEU,IAA0B,MAAM;AACpC,IAAAX,EAAa,4BAA4BU,IAAqB,UAAU,MAAM;AAAA,EAChF,GAGME,IAAyBX,EAAkB,yBAAyB,MAAM,QAC1EY,IAAeZ,EAAkB,sBAAsB,GACvDa,IAAmBF,KAA0BC,MAAiB,QAC9DE,IAAiBH,KAA0B,CAACJ,GAG5CQ,IAAmBC,EAAQ,MAAM;AACrC,QAAKH;AACL,aAAO;AAAA,QACL,sBACE;AAAA,MAAA;AAAA,EAEN,GAAG,CAACA,CAAgB,CAAC;AAErB,SAAInB,KAAa,OAAO,KAAKF,CAAQ,EAAE,WAAW,sBAE7C,OAAA,EAAI,WAAW,yDAAyDD,KAAa,EAAE,IACtF,UAAA;AAAA,IAAA,gBAAA0B,EAACC,GAAA,EAAe;AAAA,IAChB,gBAAAD,EAAC,UAAK,UAAA,sBAAA,CAAmB;AAAA,EAAA,GAC3B,IAIApB,IAEA,gBAAAoB,EAAC,OAAA,EAAI,WAAW,0BAA0B1B,KAAa,EAAE,IACvD,UAAA,gBAAA0B,EAACE,GAAA,EAAa,OAAOtB,EAAM,QAAA,CAAS,GACtC,sBAKD,OAAA,EAAI,WAAW,0BAA0BN,KAAa,EAAE,IACvD,UAAA;AAAA,IAAA,gBAAA6B,EAAC,OAAA,EAAI,WAAU,+BACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,uCACb,UAAA;AAAA,QAAA,gBAAAH,EAAC,MAAA,EAAG,WAAU,8BAA6B,UAAA,mBAAe;AAAA,QAC1D,gBAAAA,EAAC,KAAA,EAAE,WAAU,oCAAmC,UAAA,yDAAA,CAEhD;AAAA,MAAA,GACF;AAAA,MACA,gBAAAG,EAAC,OAAA,EAAI,WAAU,uCACb,UAAA;AAAA,QAAA,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,gBAAcb;AAAA,YACd,WAAW,iBAAiBA,IAAgB,qBAAqB,mBAAmB;AAAA,YACpF,SAASC;AAAA,YAET,UAAA;AAAA,cAAA,gBAAAS,EAAC,UAAK,WAAU,uBACd,4BAAC,QAAA,EAAK,WAAU,uBAAsB,EAAA,CACxC;AAAA,gCACC,QAAA,EAAK,WAAU,uBAAuB,UAAAV,IAAgB,YAAY,WAAA,CAAW;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAEhF,gBAAAU,EAACI,GAAA,EAAe,QAAQ1B,GAAgB,OAAOC,EAAA,CAAe;AAAA,MAAA,EAAA,CAChE;AAAA,IAAA,GACF;AAAA,IAGCW,uBACE,OAAA,EAAI,WAAU,8BACb,UAAA,gBAAAa,EAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,MAAA,gBAAAA,EAAC,OAAA,EACC,UAAA;AAAA,QAAA,gBAAAH,EAAC,MAAA,EAAG,WAAU,oCAAmC,UAAA,oBAAgB;AAAA,QACjE,gBAAAA,EAAC,KAAA,EAAE,WAAU,0CAAyC,UAAA,2FAAA,CAGtD;AAAA,MAAA,GACF;AAAA,MACA,gBAAAG;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,gBAAcX;AAAA,UACd,WAAW,iBAAiBA,IAAqB,qBAAqB,mBAAmB;AAAA,UACzF,SAASC;AAAA,UAET,UAAA;AAAA,YAAA,gBAAAO,EAAC,UAAK,WAAU,uBACd,4BAAC,QAAA,EAAK,WAAU,uBAAsB,EAAA,CACxC;AAAA,8BACC,QAAA,EAAK,WAAU,uBACb,UAAAR,IAAqB,YAAY,WAAA,CACpC;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IACF,EAAA,CACF,EAAA,CACF;AAAA,IAIDI,KACC,gBAAAI,EAAC,OAAA,EAAI,WAAU,kCAAiC,UAAA,6JAGhD;AAAA,IAEDH,KACC,gBAAAG,EAAC,OAAA,EAAI,WAAU,kCAAiC,UAAA,kFAEhD;AAAA,IAIF,gBAAAA,EAAC,OAAA,EAAI,WAAU,4BACZ,YAAgB,WAAW,IAC1B,gBAAAA,EAAC,OAAA,EAAI,WAAU,gCACb,UAAA,gBAAAA,EAAC,KAAA,EAAE,UAAA,oCAAA,CAAiC,GACtC,IAEA,gBAAAA;AAAA,MAACK;AAAA,MAAA;AAAA,QACC,UAAUnB;AAAA,QACV,OAAAV;AAAA,QACA,UAAUM;AAAA,QACV,kBAAAgB;AAAA,MAAA;AAAA,IAAA,EACF,CAEJ;AAAA,EAAA,GACF;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"EmbeddedWalletSettings-Cwiug0vR.js","sources":["../src/components/admin/settings/EmbeddedWalletSettings.tsx"],"sourcesContent":["/**\n * Embedded Wallet settings page - enable/disable and configure recovery\n */\nimport { useEffect, useMemo } 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', 'wallet_enroll_solana_users'];\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 // Cross-category mismatch detection\n const privateDepositsEnabled = getEffectiveValue('deposit_privacy_enabled') === 'true';\n const recoveryMode = getEffectiveValue('wallet_recovery_mode');\n const recoveryMismatch = privateDepositsEnabled && recoveryMode !== 'none';\n const walletMismatch = privateDepositsEnabled && !walletEnabled;\n\n // Inline warning on recovery mode row\n const externalWarnings = useMemo(() => {\n if (!recoveryMismatch) return undefined;\n return {\n wallet_recovery_mode:\n 'Private deposits require No Recovery mode. Deposits will fail with the current setting.',\n };\n }, [recoveryMismatch]);\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 {/* Mismatch warnings */}\n {recoveryMismatch && (\n <div className=\"cedros-settings-warning-banner\">\n Private deposits are enabled but require No Recovery mode. Users will see an error when\n attempting private deposits until recovery mode is changed below.\n </div>\n )}\n {walletMismatch && (\n <div className=\"cedros-settings-warning-banner\">\n Private deposits are enabled but require the embedded wallet. Enable it above.\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\n settings={currentSettings}\n edits={edits}\n onChange={handleChange}\n externalWarnings={externalWarnings}\n />\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","privateDepositsEnabled","recoveryMode","recoveryMismatch","walletMismatch","externalWarnings","useMemo","jsx","LoadingSpinner","ErrorMessage","jsxs","AutosaveStatus","SettingsSection"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const u=require("react/jsx-runtime"),n=require("react"),E=require("./useCedrosLogin-DtJorrE7.cjs"),S=require("./LoadingSpinner-d6sSxgQN.cjs"),_={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((t,a)=>{this.callbacks.push({resolve:t,reject:a})}):(this.loading=!0,new Promise((t,a)=>{this.callbacks.push({resolve:t,reject:a});const g=document.getElementById("google-gsi-script");if(g){window.google?.accounts?.id?(this.loaded=!0,this.loading=!1,this.callbacks.forEach(o=>o.resolve()),this.callbacks=[]):g.addEventListener("load",()=>{this.loaded=!0,this.loading=!1,this.callbacks.forEach(o=>o.resolve()),this.callbacks=[]});return}const s=document.createElement("script");s.src="https://accounts.google.com/gsi/client",s.async=!0,s.defer=!0,s.id="google-gsi-script",s.onload=()=>{this.loaded=!0,this.loading=!1,this.callbacks.forEach(o=>o.resolve()),this.callbacks=[]},s.onerror=()=>{this.loading=!1,s.remove();const o=new Error("Failed to load Google Sign-In script");this.callbacks.forEach(f=>f.reject(o)),this.callbacks=[]},document.head.appendChild(s)}))},_reset(){this.loading=!1,this.loaded=!1,this.error=null,this.callbacks=[]}};function I(){const{config:t,_internal:a}=E.useCedrosLogin(),[g,s]=n.useState(!1),[o,f]=n.useState(!1),[b,r]=n.useState(null),[m,h]=n.useState(null),c=n.useRef(null),p=n.useRef(t),d=n.useRef(null),k=n.useMemo(()=>new E.ApiClient({baseUrl:t.serverUrl,timeoutMs:t.requestTimeout,retryAttempts:t.retryAttempts}),[t.serverUrl,t.requestTimeout,t.retryAttempts]);n.useEffect(()=>{p.current=t},[t]);const w=n.useCallback(async e=>{const l=c.current;if(l){if(e.error){const i={code:"SERVER_ERROR",message:e.error==="access_denied"?"Google sign-in was cancelled.":"Unable to sign in with Google. Please try again."};r(i),s(!1),c.current=null,l.reject(i);return}try{const i=await k.post("/google",{accessToken:e.access_token,referral:a?.getReferralCode?.()??void 0});p.current.callbacks?.onLoginSuccess?.(i.user,"google"),a?.handleLoginSuccess(i.user,i.tokens),s(!1),l.resolve(i)}catch(i){const R=E.handleApiError(i,"Unable to sign in with Google. Please try again.");R.code==="ACCOUNT_LINK_REQUIRED"&&h(e.access_token??null),r(R),s(!1),l.reject(R)}finally{c.current=null}}},[k,a]),C=n.useCallback(e=>{const l=c.current;if(!l)return;const i={code:"SERVER_ERROR",message:e.type==="popup_failed_to_open"?"Google sign-in popup was blocked. Please allow popups for this site.":"Google sign-in was cancelled."};r(i),s(!1),c.current=null,l.reject(i)},[]);n.useEffect(()=>{if(!t.googleClientId)return;let e=!0;return _.load().then(()=>{if(!e)return;const l=window.google?.accounts?.oauth2?.initTokenClient({client_id:t.googleClientId,scope:"openid email profile",callback:w,error_callback:C});l&&(d.current=l,f(!0))}).catch(()=>{e&&r({code:"SERVER_ERROR",message:"Unable to load Google sign-in. Please refresh and try again."})}),()=>{e=!1,d.current=null}},[t.googleClientId,w,C]);const y=n.useCallback(async()=>{if(!t.googleClientId){const e={code:"VALIDATION_ERROR",message:"Google Client ID not configured"};throw r(e),e}if(!o){const e={code:"VALIDATION_ERROR",message:"Google sign-in is not ready yet. Please wait a moment and try again."};throw r(e),e}if(c.current){const e={code:"VALIDATION_ERROR",message:"Google sign-in is already in progress."};throw r(e),e}return s(!0),r(null),new Promise((e,l)=>{c.current={resolve:e,reject:l},d.current?.requestAccessToken()})},[t.googleClientId,o]),A=n.useCallback(()=>r(null),[]),L=n.useCallback(()=>h(null),[]);return{signIn:y,isLoading:g,isInitialized:o,error:b,clearError:A,pendingLinkToken:m,clearPendingLink:L}}function G({onSuccess:t,onError:a,className:g="",variant:s="default",size:o="md",disabled:f=!1}){const{signIn:b,isLoading:r,isInitialized:m}=I(),h=async()=>{try{await b(),t?.()}catch(d){const k=d instanceof Error?d:new Error(String(d));a?.(k)}},c={sm:"cedros-button-sm",md:"cedros-button-md",lg:"cedros-button-lg"},p={default:"cedros-button-social",outline:"cedros-button-social-outline"};return u.jsxs("button",{type:"button",className:`cedros-button ${p[s]} ${c[o]} ${g}`,onClick:h,disabled:f||!m||r,"aria-label":"Sign in with Google",children:[r?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=G;exports.useGoogleAuth=I;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GoogleLoginButton-2zNTIKMm.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 /** Access token saved when ACCOUNT_LINK_REQUIRED is returned. Pass to POST /auth/link-oauth with the user's password. */\n pendingLinkToken: string | null;\n /** Clear the pending link state */\n clearPendingLink: () => 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 [pendingLinkToken, setPendingLinkToken] = useState<string | null>(null);\n\n const promiseCallbacksRef = useRef<PromiseCallbacks | null>(null);\n const configRef = useRef(config);\n const tokenClientRef = useRef<GoogleTokenClient | null>(null);\n\n const apiClient = useMemo(\n () =>\n new ApiClient({\n baseUrl: config.serverUrl,\n timeoutMs: config.requestTimeout,\n retryAttempts: config.retryAttempts,\n }),\n [config.serverUrl, config.requestTimeout, config.retryAttempts]\n );\n\n // Keep config ref in sync\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n // Handle access token from OAuth popup (initTokenClient flow)\n const handleTokenResponse = useCallback(\n async (response: GoogleTokenResponse) => {\n const callbacks = promiseCallbacksRef.current;\n if (!callbacks) return;\n\n if (response.error) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: response.error === 'access_denied'\n ? 'Google sign-in was cancelled.'\n : 'Unable to sign in with Google. Please try again.',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n callbacks.reject(err);\n return;\n }\n\n try {\n const data = await apiClient.post<AuthResponse>('/google', {\n accessToken: response.access_token,\n referral: _internal?.getReferralCode?.() ?? undefined,\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, 'Unable to sign in with Google. Please try again.');\n if (authError.code === 'ACCOUNT_LINK_REQUIRED') {\n setPendingLinkToken(response.access_token ?? null);\n }\n setError(authError);\n setIsLoading(false);\n callbacks.reject(authError);\n } finally {\n promiseCallbacksRef.current = null;\n }\n },\n [apiClient, _internal]\n );\n\n // Handle popup closed / blocked without completing auth.\n // Google calls error_callback (not callback) when the user closes the popup.\n const handleTokenError = useCallback(\n (err: GoogleTokenErrorResponse) => {\n const callbacks = promiseCallbacksRef.current;\n if (!callbacks) return;\n\n const authError: AuthError = {\n code: 'SERVER_ERROR',\n message: err.type === 'popup_failed_to_open'\n ? 'Google sign-in popup was blocked. Please allow popups for this site.'\n : 'Google sign-in was cancelled.',\n };\n setError(authError);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n callbacks.reject(authError);\n },\n []\n );\n\n // P-01: Initialize Google OAuth token client using singleton loader.\n // Uses initTokenClient (OAuth popup) instead of One Tap prompt() which\n // has exponential cooldown after dismissal and is blocked by Brave.\n useEffect(() => {\n if (!config.googleClientId) {\n return;\n }\n\n let isMounted = true;\n\n scriptLoader\n .load()\n .then(() => {\n if (!isMounted) return;\n\n const client = window.google?.accounts?.oauth2?.initTokenClient({\n client_id: config.googleClientId!,\n scope: 'openid email profile',\n callback: handleTokenResponse,\n error_callback: handleTokenError,\n });\n\n if (client) {\n tokenClientRef.current = client;\n setIsInitialized(true);\n }\n })\n .catch(() => {\n if (isMounted) {\n setError({\n code: 'SERVER_ERROR',\n message: 'Unable to load Google sign-in. Please refresh and try again.',\n });\n }\n });\n\n return () => {\n isMounted = false;\n tokenClientRef.current = null;\n };\n }, [config.googleClientId, handleTokenResponse, handleTokenError]);\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 is not ready yet. Please wait a moment and try again.',\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 is 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 // Open the Google OAuth popup via initTokenClient.\n // This avoids One Tap's exponential cooldown after dismissal and works\n // in browsers that block One Tap (e.g., Brave).\n tokenClientRef.current?.requestAccessToken();\n });\n }, [config.googleClientId, isInitialized]);\n\n const clearError = useCallback(() => setError(null), []);\n const clearPendingLink = useCallback(() => setPendingLinkToken(null), []);\n\n return {\n signIn,\n isLoading,\n isInitialized,\n error,\n clearError,\n pendingLinkToken,\n clearPendingLink,\n };\n}\n\n/** Response from Google's initTokenClient callback */\ninterface GoogleTokenResponse {\n access_token?: string;\n error?: string;\n error_description?: string;\n}\n\n/** Error from initTokenClient error_callback (popup closed/blocked) */\ninterface GoogleTokenErrorResponse {\n type: 'popup_failed_to_open' | 'popup_closed' | 'unknown';\n}\n\n/** Token client returned by google.accounts.oauth2.initTokenClient */\ninterface GoogleTokenClient {\n requestAccessToken: () => void;\n}\n\n// Type declaration for Google Identity Services\ndeclare global {\n interface Window {\n google?: {\n accounts?: {\n /** Used only to detect if the GIS script has loaded */\n id?: object;\n oauth2?: {\n initTokenClient: (config: {\n client_id: string;\n scope: string;\n callback: (response: GoogleTokenResponse) => void;\n error_callback?: (error: GoogleTokenErrorResponse) => void;\n }) => GoogleTokenClient;\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-social',\n outline: 'cedros-button-social-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","pendingLinkToken","setPendingLinkToken","promiseCallbacksRef","useRef","configRef","tokenClientRef","apiClient","useMemo","ApiClient","useEffect","handleTokenResponse","useCallback","response","callbacks","err","data","authError","handleApiError","handleTokenError","isMounted","client","signIn","clearError","clearPendingLink","GoogleLoginButton","onSuccess","onError","className","variant","size","disabled","handleClick","sizeClasses","variantClasses","jsxs","jsx","LoadingSpinner"],"mappings":"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"}
|
|
@@ -8,10 +8,10 @@ const z = {
|
|
|
8
8
|
error: null,
|
|
9
9
|
callbacks: [],
|
|
10
10
|
load() {
|
|
11
|
-
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((
|
|
12
|
-
this.callbacks.push({ resolve:
|
|
13
|
-
}) : (this.loading = !0, new Promise((
|
|
14
|
-
this.callbacks.push({ resolve:
|
|
11
|
+
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((o, i) => {
|
|
12
|
+
this.callbacks.push({ resolve: o, reject: i });
|
|
13
|
+
}) : (this.loading = !0, new Promise((o, i) => {
|
|
14
|
+
this.callbacks.push({ resolve: o, reject: i });
|
|
15
15
|
const d = document.getElementById("google-gsi-script");
|
|
16
16
|
if (d) {
|
|
17
17
|
window.google?.accounts?.id ? (this.loaded = !0, this.loading = !1, this.callbacks.forEach((n) => n.resolve()), this.callbacks = []) : d.addEventListener("load", () => {
|
|
@@ -19,14 +19,14 @@ const z = {
|
|
|
19
19
|
});
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
|
-
const
|
|
23
|
-
|
|
22
|
+
const t = document.createElement("script");
|
|
23
|
+
t.src = "https://accounts.google.com/gsi/client", t.async = !0, t.defer = !0, t.id = "google-gsi-script", t.onload = () => {
|
|
24
24
|
this.loaded = !0, this.loading = !1, this.callbacks.forEach((n) => n.resolve()), this.callbacks = [];
|
|
25
|
-
},
|
|
26
|
-
this.loading = !1,
|
|
25
|
+
}, t.onerror = () => {
|
|
26
|
+
this.loading = !1, t.remove();
|
|
27
27
|
const n = new Error("Failed to load Google Sign-In script");
|
|
28
28
|
this.callbacks.forEach((g) => g.reject(n)), this.callbacks = [];
|
|
29
|
-
}, document.head.appendChild(
|
|
29
|
+
}, document.head.appendChild(t);
|
|
30
30
|
}));
|
|
31
31
|
},
|
|
32
32
|
/**
|
|
@@ -38,63 +38,64 @@ const z = {
|
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
40
|
function U() {
|
|
41
|
-
const { config:
|
|
41
|
+
const { config: o, _internal: i } = S(), [d, t] = m(!1), [n, g] = m(!1), [k, s] = m(null), [b, h] = m(null), a = w(null), E = w(o), c = w(null), p = G(
|
|
42
42
|
() => new T({
|
|
43
|
-
baseUrl:
|
|
44
|
-
timeoutMs:
|
|
45
|
-
retryAttempts:
|
|
43
|
+
baseUrl: o.serverUrl,
|
|
44
|
+
timeoutMs: o.requestTimeout,
|
|
45
|
+
retryAttempts: o.retryAttempts
|
|
46
46
|
}),
|
|
47
|
-
[
|
|
47
|
+
[o.serverUrl, o.requestTimeout, o.retryAttempts]
|
|
48
48
|
);
|
|
49
49
|
A(() => {
|
|
50
|
-
E.current =
|
|
51
|
-
}, [
|
|
50
|
+
E.current = o;
|
|
51
|
+
}, [o]);
|
|
52
52
|
const C = f(
|
|
53
53
|
async (e) => {
|
|
54
|
-
const r =
|
|
54
|
+
const r = a.current;
|
|
55
55
|
if (r) {
|
|
56
56
|
if (e.error) {
|
|
57
57
|
const l = {
|
|
58
58
|
code: "SERVER_ERROR",
|
|
59
59
|
message: e.error === "access_denied" ? "Google sign-in was cancelled." : "Unable to sign in with Google. Please try again."
|
|
60
60
|
};
|
|
61
|
-
s(l),
|
|
61
|
+
s(l), t(!1), a.current = null, r.reject(l);
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
64
|
try {
|
|
65
65
|
const l = await p.post("/google", {
|
|
66
|
-
accessToken: e.access_token
|
|
66
|
+
accessToken: e.access_token,
|
|
67
|
+
referral: i?.getReferralCode?.() ?? void 0
|
|
67
68
|
});
|
|
68
|
-
E.current.callbacks?.onLoginSuccess?.(l.user, "google"),
|
|
69
|
+
E.current.callbacks?.onLoginSuccess?.(l.user, "google"), i?.handleLoginSuccess(l.user, l.tokens), t(!1), r.resolve(l);
|
|
69
70
|
} catch (l) {
|
|
70
71
|
const R = P(l, "Unable to sign in with Google. Please try again.");
|
|
71
|
-
R.code === "ACCOUNT_LINK_REQUIRED" && h(e.access_token ?? null), s(R),
|
|
72
|
+
R.code === "ACCOUNT_LINK_REQUIRED" && h(e.access_token ?? null), s(R), t(!1), r.reject(R);
|
|
72
73
|
} finally {
|
|
73
|
-
|
|
74
|
+
a.current = null;
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
},
|
|
77
|
-
[p,
|
|
78
|
+
[p, i]
|
|
78
79
|
), I = f(
|
|
79
80
|
(e) => {
|
|
80
|
-
const r =
|
|
81
|
+
const r = a.current;
|
|
81
82
|
if (!r) return;
|
|
82
83
|
const l = {
|
|
83
84
|
code: "SERVER_ERROR",
|
|
84
85
|
message: e.type === "popup_failed_to_open" ? "Google sign-in popup was blocked. Please allow popups for this site." : "Google sign-in was cancelled."
|
|
85
86
|
};
|
|
86
|
-
s(l),
|
|
87
|
+
s(l), t(!1), a.current = null, r.reject(l);
|
|
87
88
|
},
|
|
88
89
|
[]
|
|
89
90
|
);
|
|
90
91
|
A(() => {
|
|
91
|
-
if (!
|
|
92
|
+
if (!o.googleClientId)
|
|
92
93
|
return;
|
|
93
94
|
let e = !0;
|
|
94
95
|
return z.load().then(() => {
|
|
95
96
|
if (!e) return;
|
|
96
97
|
const r = window.google?.accounts?.oauth2?.initTokenClient({
|
|
97
|
-
client_id:
|
|
98
|
+
client_id: o.googleClientId,
|
|
98
99
|
scope: "openid email profile",
|
|
99
100
|
callback: C,
|
|
100
101
|
error_callback: I
|
|
@@ -108,9 +109,9 @@ function U() {
|
|
|
108
109
|
}), () => {
|
|
109
110
|
e = !1, c.current = null;
|
|
110
111
|
};
|
|
111
|
-
}, [
|
|
112
|
+
}, [o.googleClientId, C, I]);
|
|
112
113
|
const L = f(async () => {
|
|
113
|
-
if (!
|
|
114
|
+
if (!o.googleClientId) {
|
|
114
115
|
const e = {
|
|
115
116
|
code: "VALIDATION_ERROR",
|
|
116
117
|
message: "Google Client ID not configured"
|
|
@@ -124,17 +125,17 @@ function U() {
|
|
|
124
125
|
};
|
|
125
126
|
throw s(e), e;
|
|
126
127
|
}
|
|
127
|
-
if (
|
|
128
|
+
if (a.current) {
|
|
128
129
|
const e = {
|
|
129
130
|
code: "VALIDATION_ERROR",
|
|
130
131
|
message: "Google sign-in is already in progress."
|
|
131
132
|
};
|
|
132
133
|
throw s(e), e;
|
|
133
134
|
}
|
|
134
|
-
return
|
|
135
|
-
|
|
135
|
+
return t(!0), s(null), new Promise((e, r) => {
|
|
136
|
+
a.current = { resolve: e, reject: r }, c.current?.requestAccessToken();
|
|
136
137
|
});
|
|
137
|
-
}, [
|
|
138
|
+
}, [o.googleClientId, n]), _ = f(() => s(null), []), v = f(() => h(null), []);
|
|
138
139
|
return {
|
|
139
140
|
signIn: L,
|
|
140
141
|
isLoading: d,
|
|
@@ -146,21 +147,21 @@ function U() {
|
|
|
146
147
|
};
|
|
147
148
|
}
|
|
148
149
|
function x({
|
|
149
|
-
onSuccess:
|
|
150
|
-
onError:
|
|
150
|
+
onSuccess: o,
|
|
151
|
+
onError: i,
|
|
151
152
|
className: d = "",
|
|
152
|
-
variant:
|
|
153
|
+
variant: t = "default",
|
|
153
154
|
size: n = "md",
|
|
154
155
|
disabled: g = !1
|
|
155
156
|
}) {
|
|
156
157
|
const { signIn: k, isLoading: s, isInitialized: b } = U(), h = async () => {
|
|
157
158
|
try {
|
|
158
|
-
await k(),
|
|
159
|
+
await k(), o?.();
|
|
159
160
|
} catch (c) {
|
|
160
161
|
const p = c instanceof Error ? c : new Error(String(c));
|
|
161
|
-
|
|
162
|
+
i?.(p);
|
|
162
163
|
}
|
|
163
|
-
},
|
|
164
|
+
}, a = {
|
|
164
165
|
sm: "cedros-button-sm",
|
|
165
166
|
md: "cedros-button-md",
|
|
166
167
|
lg: "cedros-button-lg"
|
|
@@ -172,7 +173,7 @@ function x({
|
|
|
172
173
|
className: `cedros-button ${{
|
|
173
174
|
default: "cedros-button-social",
|
|
174
175
|
outline: "cedros-button-social-outline"
|
|
175
|
-
}[
|
|
176
|
+
}[t]} ${a[n]} ${d}`,
|
|
176
177
|
onClick: h,
|
|
177
178
|
disabled: g || !b || s,
|
|
178
179
|
"aria-label": "Sign in with Google",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GoogleLoginButton-C1WNu7W3.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 /** Access token saved when ACCOUNT_LINK_REQUIRED is returned. Pass to POST /auth/link-oauth with the user's password. */\n pendingLinkToken: string | null;\n /** Clear the pending link state */\n clearPendingLink: () => 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 [pendingLinkToken, setPendingLinkToken] = useState<string | null>(null);\n\n const promiseCallbacksRef = useRef<PromiseCallbacks | null>(null);\n const configRef = useRef(config);\n const tokenClientRef = useRef<GoogleTokenClient | null>(null);\n\n const apiClient = useMemo(\n () =>\n new ApiClient({\n baseUrl: config.serverUrl,\n timeoutMs: config.requestTimeout,\n retryAttempts: config.retryAttempts,\n }),\n [config.serverUrl, config.requestTimeout, config.retryAttempts]\n );\n\n // Keep config ref in sync\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n // Handle access token from OAuth popup (initTokenClient flow)\n const handleTokenResponse = useCallback(\n async (response: GoogleTokenResponse) => {\n const callbacks = promiseCallbacksRef.current;\n if (!callbacks) return;\n\n if (response.error) {\n const err: AuthError = {\n code: 'SERVER_ERROR',\n message: response.error === 'access_denied'\n ? 'Google sign-in was cancelled.'\n : 'Unable to sign in with Google. Please try again.',\n };\n setError(err);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n callbacks.reject(err);\n return;\n }\n\n try {\n const data = await apiClient.post<AuthResponse>('/google', {\n accessToken: response.access_token,\n referral: _internal?.getReferralCode?.() ?? undefined,\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, 'Unable to sign in with Google. Please try again.');\n if (authError.code === 'ACCOUNT_LINK_REQUIRED') {\n setPendingLinkToken(response.access_token ?? null);\n }\n setError(authError);\n setIsLoading(false);\n callbacks.reject(authError);\n } finally {\n promiseCallbacksRef.current = null;\n }\n },\n [apiClient, _internal]\n );\n\n // Handle popup closed / blocked without completing auth.\n // Google calls error_callback (not callback) when the user closes the popup.\n const handleTokenError = useCallback(\n (err: GoogleTokenErrorResponse) => {\n const callbacks = promiseCallbacksRef.current;\n if (!callbacks) return;\n\n const authError: AuthError = {\n code: 'SERVER_ERROR',\n message: err.type === 'popup_failed_to_open'\n ? 'Google sign-in popup was blocked. Please allow popups for this site.'\n : 'Google sign-in was cancelled.',\n };\n setError(authError);\n setIsLoading(false);\n promiseCallbacksRef.current = null;\n callbacks.reject(authError);\n },\n []\n );\n\n // P-01: Initialize Google OAuth token client using singleton loader.\n // Uses initTokenClient (OAuth popup) instead of One Tap prompt() which\n // has exponential cooldown after dismissal and is blocked by Brave.\n useEffect(() => {\n if (!config.googleClientId) {\n return;\n }\n\n let isMounted = true;\n\n scriptLoader\n .load()\n .then(() => {\n if (!isMounted) return;\n\n const client = window.google?.accounts?.oauth2?.initTokenClient({\n client_id: config.googleClientId!,\n scope: 'openid email profile',\n callback: handleTokenResponse,\n error_callback: handleTokenError,\n });\n\n if (client) {\n tokenClientRef.current = client;\n setIsInitialized(true);\n }\n })\n .catch(() => {\n if (isMounted) {\n setError({\n code: 'SERVER_ERROR',\n message: 'Unable to load Google sign-in. Please refresh and try again.',\n });\n }\n });\n\n return () => {\n isMounted = false;\n tokenClientRef.current = null;\n };\n }, [config.googleClientId, handleTokenResponse, handleTokenError]);\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 is not ready yet. Please wait a moment and try again.',\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 is 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 // Open the Google OAuth popup via initTokenClient.\n // This avoids One Tap's exponential cooldown after dismissal and works\n // in browsers that block One Tap (e.g., Brave).\n tokenClientRef.current?.requestAccessToken();\n });\n }, [config.googleClientId, isInitialized]);\n\n const clearError = useCallback(() => setError(null), []);\n const clearPendingLink = useCallback(() => setPendingLinkToken(null), []);\n\n return {\n signIn,\n isLoading,\n isInitialized,\n error,\n clearError,\n pendingLinkToken,\n clearPendingLink,\n };\n}\n\n/** Response from Google's initTokenClient callback */\ninterface GoogleTokenResponse {\n access_token?: string;\n error?: string;\n error_description?: string;\n}\n\n/** Error from initTokenClient error_callback (popup closed/blocked) */\ninterface GoogleTokenErrorResponse {\n type: 'popup_failed_to_open' | 'popup_closed' | 'unknown';\n}\n\n/** Token client returned by google.accounts.oauth2.initTokenClient */\ninterface GoogleTokenClient {\n requestAccessToken: () => void;\n}\n\n// Type declaration for Google Identity Services\ndeclare global {\n interface Window {\n google?: {\n accounts?: {\n /** Used only to detect if the GIS script has loaded */\n id?: object;\n oauth2?: {\n initTokenClient: (config: {\n client_id: string;\n scope: string;\n callback: (response: GoogleTokenResponse) => void;\n error_callback?: (error: GoogleTokenErrorResponse) => void;\n }) => GoogleTokenClient;\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-social',\n outline: 'cedros-button-social-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","pendingLinkToken","setPendingLinkToken","promiseCallbacksRef","useRef","configRef","tokenClientRef","apiClient","useMemo","ApiClient","useEffect","handleTokenResponse","useCallback","response","callbacks","err","data","authError","handleApiError","handleTokenError","isMounted","client","signIn","clearError","clearPendingLink","GoogleLoginButton","onSuccess","onError","className","variant","size","disabled","handleClick","sizeClasses","jsxs","jsx","LoadingSpinner"],"mappings":"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"}
|
|
@@ -1 +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 /** Display order for social login buttons (from server auto-discovery). */\n socialButtonOrder?: string[];\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":";;
|
|
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 /** Get the referral code captured from the ?ref= URL parameter (if any) */\n getReferralCode: () => 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 /** Display order for social login buttons (from server auto-discovery). */\n socialButtonOrder?: string[];\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":";;AAgDO,MAAMA,IAAmBC,EAA4C,IAAI,GACnEC,IAAgBD,EAAyC,IAAI,GAM7DE,IAAqBF,EAA8C,IAAI,GC3C9EG,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;"}
|
|
@@ -1 +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 /** Display order for social login buttons (from server auto-discovery). */\n socialButtonOrder?: string[];\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":"
|
|
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 /** Get the referral code captured from the ?ref= URL parameter (if any) */\n getReferralCode: () => 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 /** Display order for social login buttons (from server auto-discovery). */\n socialButtonOrder?: string[];\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":"qEAgDaA,EAAmBC,EAAAA,cAA4C,IAAI,EACnEC,EAAgBD,EAAAA,cAAyC,IAAI,EAM7DE,EAAqBF,EAAAA,cAA8C,IAAI,EC3C9EG,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"}
|