@forge-connect/react 1.0.9 → 1.0.11

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/index.js CHANGED
@@ -16,8 +16,16 @@ var ForgeConnectApiError = class extends Error {
16
16
  this.code = code;
17
17
  }
18
18
  };
19
+ var clientCache = /* @__PURE__ */ new Map();
19
20
  function createApiClient(apiUrl) {
20
21
  const base = apiUrl.replace(/\/+$/, "");
22
+ const cached = clientCache.get(base);
23
+ if (cached) return cached;
24
+ const client = buildApiClient(base);
25
+ clientCache.set(base, client);
26
+ return client;
27
+ }
28
+ function buildApiClient(base) {
21
29
  const inflightRequests = /* @__PURE__ */ new Map();
22
30
  let inflightRefresh = null;
23
31
  async function request(path, options = {}) {
@@ -486,7 +494,7 @@ function ModalOverlay({ isOpen, onClose, children }) {
486
494
  import { useState } from "react";
487
495
 
488
496
  // src/resolve-config.ts
489
- var OAUTH_PROVIDERS = /* @__PURE__ */ new Set(["google", "discord", "twitter", "apple", "telegram"]);
497
+ var OAUTH_PROVIDERS = /* @__PURE__ */ new Set(["google", "discord", "twitter", "apple", "telegram", "matrica"]);
490
498
  function isOAuthMethod(method) {
491
499
  return OAUTH_PROVIDERS.has(method);
492
500
  }
@@ -826,8 +834,105 @@ function EmailOtpForm() {
826
834
  }
827
835
 
828
836
  // src/components/tabs/wallet-connect.tsx
829
- import { useState as useState3, useMemo, useRef as useRef3, useCallback } from "react";
830
- import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
837
+ import { useState as useState3, useMemo, useRef as useRef4, useCallback } from "react";
838
+
839
+ // src/components/svg-icon.tsx
840
+ import { useRef as useRef3, useEffect as useEffect2 } from "react";
841
+ import { jsx as jsx4 } from "react/jsx-runtime";
842
+ function SvgIcon({ svg, className }) {
843
+ const ref = useRef3(null);
844
+ useEffect2(() => {
845
+ if (!ref.current || !svg) return;
846
+ try {
847
+ const doc = new DOMParser().parseFromString(svg, "text/html");
848
+ const svgEl = doc.body.querySelector("svg");
849
+ if (!svgEl) {
850
+ ref.current.textContent = "";
851
+ return;
852
+ }
853
+ const dangerous = svgEl.querySelectorAll("script,iframe,object,embed,foreignObject");
854
+ dangerous.forEach((el) => el.remove());
855
+ const all = svgEl.querySelectorAll("*");
856
+ all.forEach((el) => {
857
+ for (const attr of Array.from(el.attributes)) {
858
+ if (attr.name.startsWith("on")) {
859
+ el.removeAttribute(attr.name);
860
+ }
861
+ }
862
+ });
863
+ ref.current.textContent = "";
864
+ ref.current.appendChild(svgEl);
865
+ } catch {
866
+ ref.current.textContent = "";
867
+ }
868
+ }, [svg]);
869
+ return /* @__PURE__ */ jsx4("span", { ref, className });
870
+ }
871
+
872
+ // src/components/tabs/oauth-buttons.tsx
873
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
874
+ var PROVIDER_INFO = {
875
+ google: {
876
+ label: "Google",
877
+ icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" fill="#4285F4"/><path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/><path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/><path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/></svg>'
878
+ },
879
+ discord: {
880
+ label: "Discord",
881
+ icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128c.126-.094.252-.192.372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z" fill="#5865F2"/></svg>'
882
+ },
883
+ twitter: {
884
+ label: "Twitter",
885
+ icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" fill="currentColor"/></svg>'
886
+ },
887
+ apple: {
888
+ label: "Apple",
889
+ icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.52-3.23 0-1.44.64-2.2.45-3.06-.4C3.79 16.17 4.36 9.02 8.8 8.78c1.27.06 2.15.72 2.91.76.93-.19 1.82-.88 2.83-.8 1.21.1 2.12.58 2.72 1.49-2.46 1.48-1.88 4.73.52 5.64-.42 1.13-.98 2.24-1.73 3.41zM12.03 8.7c-.12-2.35 1.82-4.38 4.04-4.54.29 2.56-2.34 4.68-4.04 4.54z" fill="currentColor"/></svg>'
890
+ },
891
+ telegram: {
892
+ label: "Telegram",
893
+ icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.479.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z" fill="#2AABEE"/></svg>'
894
+ },
895
+ matrica: {
896
+ label: "Matrica",
897
+ icon: '<svg viewBox="2 1 26 26" width="20" height="20" xmlns="http://www.w3.org/2000/svg"><rect x="11.457" y="10.6387" width="7.00961" height="7.00962" fill="#4A99BF"/><path d="M12.6266 1.87695V5.08969H5.90903V23.1979H12.6266V26.4106H2.69629V1.87695H12.6266Z" fill="#4A99BF"/><path d="M17.2997 26.4106H27.2299V1.87695H17.2997V5.08969H24.0172V23.1979H17.2997V26.4106Z" fill="#4A99BF"/></svg>'
898
+ }
899
+ };
900
+ function OAuthButton({ provider }) {
901
+ const { loginWithOAuth } = useForgeConnect();
902
+ const info = PROVIDER_INFO[provider];
903
+ return /* @__PURE__ */ jsxs4(
904
+ "button",
905
+ {
906
+ type: "button",
907
+ className: "fc-btn fc-btn-oauth",
908
+ onClick: () => loginWithOAuth(provider),
909
+ children: [
910
+ /* @__PURE__ */ jsx5(SvgIcon, { svg: info.icon, className: "fc-oauth-icon" }),
911
+ /* @__PURE__ */ jsx5("span", { className: "fc-btn-name", children: info.label })
912
+ ]
913
+ }
914
+ );
915
+ }
916
+
917
+ // src/components/tabs/wallet-connect.tsx
918
+ import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
919
+ function MatricaWalletEntry() {
920
+ const { loginWithOAuth } = useForgeConnect();
921
+ const info = PROVIDER_INFO.matrica;
922
+ return /* @__PURE__ */ jsxs5(
923
+ "button",
924
+ {
925
+ type: "button",
926
+ className: "fc-btn fc-btn-wallet",
927
+ onClick: () => loginWithOAuth("matrica"),
928
+ children: [
929
+ /* @__PURE__ */ jsx6("span", { style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ jsx6(SvgIcon, { svg: info.icon, className: "fc-wallet-icon" }) }),
930
+ /* @__PURE__ */ jsx6("span", { className: "fc-wallet-name", children: info.label }),
931
+ /* @__PURE__ */ jsx6("span", { className: "fc-badge-preferred", children: "Brings wallets" })
932
+ ]
933
+ }
934
+ );
935
+ }
831
936
  var MOBILE_WALLETS = [
832
937
  {
833
938
  name: "Phantom",
@@ -854,22 +959,22 @@ function WalletConnectForm() {
854
959
  const methods = resolveLoginMethods(config);
855
960
  const showBack = methods.length > 1;
856
961
  if (!walletAdapter && isMobile()) {
857
- return /* @__PURE__ */ jsx4(MobileWalletFlow, {});
962
+ return /* @__PURE__ */ jsx6(MobileWalletFlow, {});
858
963
  }
859
964
  if (walletAdapter) {
860
- return /* @__PURE__ */ jsx4(WalletAdapterFlow, {});
965
+ return /* @__PURE__ */ jsx6(WalletAdapterFlow, {});
861
966
  }
862
- return /* @__PURE__ */ jsxs4("div", { className: "fc-tab", children: [
863
- /* @__PURE__ */ jsx4("h3", { className: "fc-tab-title", children: "Connect wallet" }),
864
- /* @__PURE__ */ jsxs4("p", { className: "fc-text", children: [
967
+ return /* @__PURE__ */ jsxs5("div", { className: "fc-tab", children: [
968
+ /* @__PURE__ */ jsx6("h3", { className: "fc-tab-title", children: "Connect wallet" }),
969
+ /* @__PURE__ */ jsxs5("p", { className: "fc-text", children: [
865
970
  "No wallet adapter detected. Pass ",
866
- /* @__PURE__ */ jsx4("code", { children: "walletAdapter" }),
971
+ /* @__PURE__ */ jsx6("code", { children: "walletAdapter" }),
867
972
  " to",
868
973
  " ",
869
- /* @__PURE__ */ jsx4("code", { children: "<ForgeConnectProvider>" }),
974
+ /* @__PURE__ */ jsx6("code", { children: "<ForgeConnectProvider>" }),
870
975
  " to enable wallet login."
871
976
  ] }),
872
- showBack && /* @__PURE__ */ jsx4("p", { className: "fc-switch", children: /* @__PURE__ */ jsx4("button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
977
+ showBack && /* @__PURE__ */ jsx6("p", { className: "fc-switch", children: /* @__PURE__ */ jsx6("button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
873
978
  ] });
874
979
  }
875
980
  function MobileWalletFlow() {
@@ -893,23 +998,27 @@ function MobileWalletFlow() {
893
998
  const pageUrl = window.location.href;
894
999
  window.location.href = mw.buildUrl(pageUrl);
895
1000
  };
896
- return /* @__PURE__ */ jsxs4("div", { className: "fc-tab", children: [
897
- /* @__PURE__ */ jsx4("div", { className: "fc-wallet-list", children: walletsToShow.map((mw) => /* @__PURE__ */ jsxs4(
898
- "button",
899
- {
900
- type: "button",
901
- className: "fc-btn fc-btn-wallet",
902
- onClick: () => handleOpen(mw),
903
- children: [
904
- /* @__PURE__ */ jsx4("span", { style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ jsx4("img", { src: mw.icon, alt: "", className: "fc-wallet-icon" }) }),
905
- /* @__PURE__ */ jsx4("span", { className: "fc-wallet-name", children: mw.name }),
906
- /* @__PURE__ */ jsx4("span", { className: "fc-badge-preferred", children: "Open app" })
907
- ]
908
- },
909
- mw.name
910
- )) }),
911
- /* @__PURE__ */ jsx4("p", { className: "fc-text", style: { textAlign: "center", fontSize: 12, opacity: 0.6 }, children: "You'll be redirected to the wallet app to sign in." }),
912
- showBack && /* @__PURE__ */ jsx4("p", { className: "fc-switch", children: /* @__PURE__ */ jsx4("button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
1001
+ const showMatrica = methods.includes("matrica");
1002
+ return /* @__PURE__ */ jsxs5("div", { className: "fc-tab", children: [
1003
+ /* @__PURE__ */ jsxs5("div", { className: "fc-wallet-list", children: [
1004
+ showMatrica && /* @__PURE__ */ jsx6(MatricaWalletEntry, {}),
1005
+ walletsToShow.map((mw) => /* @__PURE__ */ jsxs5(
1006
+ "button",
1007
+ {
1008
+ type: "button",
1009
+ className: "fc-btn fc-btn-wallet",
1010
+ onClick: () => handleOpen(mw),
1011
+ children: [
1012
+ /* @__PURE__ */ jsx6("span", { style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ jsx6("img", { src: mw.icon, alt: "", className: "fc-wallet-icon" }) }),
1013
+ /* @__PURE__ */ jsx6("span", { className: "fc-wallet-name", children: mw.name }),
1014
+ /* @__PURE__ */ jsx6("span", { className: "fc-badge-preferred", children: "Open app" })
1015
+ ]
1016
+ },
1017
+ mw.name
1018
+ ))
1019
+ ] }),
1020
+ /* @__PURE__ */ jsx6("p", { className: "fc-text", style: { textAlign: "center", fontSize: 12, opacity: 0.6 }, children: "You'll be redirected to the wallet app to sign in." }),
1021
+ showBack && /* @__PURE__ */ jsx6("p", { className: "fc-switch", children: /* @__PURE__ */ jsx6("button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
913
1022
  ] });
914
1023
  }
915
1024
  function WalletAdapterFlow() {
@@ -923,7 +1032,7 @@ function WalletAdapterFlow() {
923
1032
  const [showOther, setShowOther] = useState3(false);
924
1033
  const [coldWallet, setColdWallet] = useState3(false);
925
1034
  const mobile = useMemo(() => isMobile(), []);
926
- const coldWalletRef = useRef3(coldWallet);
1035
+ const coldWalletRef = useRef4(coldWallet);
927
1036
  coldWalletRef.current = coldWallet;
928
1037
  const buildSignTxFnForAdapter = useCallback((adapter) => {
929
1038
  if (!adapter.signTransaction) return void 0;
@@ -995,13 +1104,13 @@ function WalletAdapterFlow() {
995
1104
  const adapterNames = new Set(wallet.wallets.map((w) => w.adapter.name));
996
1105
  return MOBILE_WALLETS.filter((mw) => !adapterNames.has(mw.name));
997
1106
  }, [mobile, wallet.wallets]);
998
- return /* @__PURE__ */ jsxs4("div", { className: "fc-tab", children: [
999
- loading ? /* @__PURE__ */ jsxs4("div", { style: { textAlign: "center", padding: "24px 0" }, children: [
1000
- /* @__PURE__ */ jsx4("p", { className: "fc-tab-title", children: "Connecting..." }),
1001
- /* @__PURE__ */ jsx4("p", { className: "fc-text", children: coldWallet ? "Confirm the transaction on your device" : "Approve the connection, then sign the verification request in your wallet" }),
1002
- error && /* @__PURE__ */ jsxs4(Fragment, { children: [
1003
- /* @__PURE__ */ jsx4("p", { className: "fc-error", children: error }),
1004
- /* @__PURE__ */ jsx4(
1107
+ return /* @__PURE__ */ jsxs5("div", { className: "fc-tab", children: [
1108
+ loading ? /* @__PURE__ */ jsxs5("div", { style: { textAlign: "center", padding: "24px 0" }, children: [
1109
+ /* @__PURE__ */ jsx6("p", { className: "fc-tab-title", children: "Connecting..." }),
1110
+ /* @__PURE__ */ jsx6("p", { className: "fc-text", children: coldWallet ? "Confirm the transaction on your device" : "Approve the connection, then sign the verification request in your wallet" }),
1111
+ error && /* @__PURE__ */ jsxs5(Fragment, { children: [
1112
+ /* @__PURE__ */ jsx6("p", { className: "fc-error", children: error }),
1113
+ /* @__PURE__ */ jsx6(
1005
1114
  "button",
1006
1115
  {
1007
1116
  type: "button",
@@ -1015,78 +1124,79 @@ function WalletAdapterFlow() {
1015
1124
  }
1016
1125
  )
1017
1126
  ] })
1018
- ] }) : /* @__PURE__ */ jsxs4(Fragment, { children: [
1019
- /* @__PURE__ */ jsxs4("div", { className: "fc-wallet-list", children: [
1127
+ ] }) : /* @__PURE__ */ jsxs5(Fragment, { children: [
1128
+ /* @__PURE__ */ jsxs5("div", { className: "fc-wallet-list", children: [
1129
+ methods.includes("matrica") && /* @__PURE__ */ jsx6(MatricaWalletEntry, {}),
1020
1130
  preferredWallets.map((w) => {
1021
1131
  const installed = w.readyState === "Installed";
1022
1132
  const isConnected = w.adapter.name === connectedWalletName;
1023
- return /* @__PURE__ */ jsxs4(
1133
+ return /* @__PURE__ */ jsxs5(
1024
1134
  "button",
1025
1135
  {
1026
1136
  type: "button",
1027
1137
  className: "fc-btn fc-btn-wallet",
1028
1138
  onClick: () => handleConnect(w),
1029
1139
  children: [
1030
- /* @__PURE__ */ jsx4("span", { className: installed ? "fc-installed-dot" : "", style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ jsx4("img", { src: w.adapter.icon, alt: "", className: "fc-wallet-icon" }) }),
1031
- /* @__PURE__ */ jsx4("span", { className: "fc-wallet-name", children: w.adapter.name }),
1032
- isConnected ? /* @__PURE__ */ jsx4("span", { className: "fc-badge-preferred", children: "Last used" }) : /* @__PURE__ */ jsx4("span", { className: "fc-badge-preferred", children: "Preferred" }),
1033
- !installed && mobile && MOBILE_WALLETS.some((mw) => mw.name === w.adapter.name) ? /* @__PURE__ */ jsx4("span", { className: "fc-badge-install", children: "Open app" }) : !installed && /* @__PURE__ */ jsx4("span", { className: "fc-badge-install", children: "Install" })
1140
+ /* @__PURE__ */ jsx6("span", { className: installed ? "fc-installed-dot" : "", style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ jsx6("img", { src: w.adapter.icon, alt: "", className: "fc-wallet-icon" }) }),
1141
+ /* @__PURE__ */ jsx6("span", { className: "fc-wallet-name", children: w.adapter.name }),
1142
+ isConnected ? /* @__PURE__ */ jsx6("span", { className: "fc-badge-preferred", children: "Last used" }) : /* @__PURE__ */ jsx6("span", { className: "fc-badge-preferred", children: "Preferred" }),
1143
+ !installed && mobile && MOBILE_WALLETS.some((mw) => mw.name === w.adapter.name) ? /* @__PURE__ */ jsx6("span", { className: "fc-badge-install", children: "Open app" }) : !installed && /* @__PURE__ */ jsx6("span", { className: "fc-badge-install", children: "Install" })
1034
1144
  ]
1035
1145
  },
1036
1146
  w.adapter.name
1037
1147
  );
1038
1148
  }),
1039
- mobileExtraWallets.map((mw) => /* @__PURE__ */ jsxs4(
1149
+ mobileExtraWallets.map((mw) => /* @__PURE__ */ jsxs5(
1040
1150
  "button",
1041
1151
  {
1042
1152
  type: "button",
1043
1153
  className: "fc-btn fc-btn-wallet",
1044
1154
  onClick: () => handleMobileOpen(mw),
1045
1155
  children: [
1046
- /* @__PURE__ */ jsx4("span", { style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ jsx4("img", { src: mw.icon, alt: "", className: "fc-wallet-icon" }) }),
1047
- /* @__PURE__ */ jsx4("span", { className: "fc-wallet-name", children: mw.name }),
1048
- /* @__PURE__ */ jsx4("span", { className: "fc-badge-install", children: "Open app" })
1156
+ /* @__PURE__ */ jsx6("span", { style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ jsx6("img", { src: mw.icon, alt: "", className: "fc-wallet-icon" }) }),
1157
+ /* @__PURE__ */ jsx6("span", { className: "fc-wallet-name", children: mw.name }),
1158
+ /* @__PURE__ */ jsx6("span", { className: "fc-badge-install", children: "Open app" })
1049
1159
  ]
1050
1160
  },
1051
1161
  mw.name
1052
1162
  )),
1053
- otherWallets.length > 0 && !showOther && /* @__PURE__ */ jsxs4(
1163
+ otherWallets.length > 0 && !showOther && /* @__PURE__ */ jsxs5(
1054
1164
  "button",
1055
1165
  {
1056
1166
  type: "button",
1057
1167
  className: "fc-btn fc-btn-wallet",
1058
1168
  onClick: () => setShowOther(true),
1059
1169
  children: [
1060
- /* @__PURE__ */ jsx4("span", { className: "fc-other-wallets-icon", children: /* @__PURE__ */ jsxs4("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
1061
- /* @__PURE__ */ jsx4("rect", { x: "2", y: "3", width: "16", height: "14", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }),
1062
- /* @__PURE__ */ jsx4("path", { d: "M2 7h16", stroke: "currentColor", strokeWidth: "1.5" }),
1063
- /* @__PURE__ */ jsx4("rect", { x: "11", y: "10", width: "7", height: "4", rx: "1", stroke: "currentColor", strokeWidth: "1.5" })
1170
+ /* @__PURE__ */ jsx6("span", { className: "fc-other-wallets-icon", children: /* @__PURE__ */ jsxs5("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
1171
+ /* @__PURE__ */ jsx6("rect", { x: "2", y: "3", width: "16", height: "14", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }),
1172
+ /* @__PURE__ */ jsx6("path", { d: "M2 7h16", stroke: "currentColor", strokeWidth: "1.5" }),
1173
+ /* @__PURE__ */ jsx6("rect", { x: "11", y: "10", width: "7", height: "4", rx: "1", stroke: "currentColor", strokeWidth: "1.5" })
1064
1174
  ] }) }),
1065
- /* @__PURE__ */ jsx4("span", { className: "fc-wallet-name", children: "Other wallets" })
1175
+ /* @__PURE__ */ jsx6("span", { className: "fc-wallet-name", children: "Other wallets" })
1066
1176
  ]
1067
1177
  }
1068
1178
  ),
1069
1179
  showOther && otherWallets.map((w) => {
1070
1180
  const isConnected = w.adapter.name === connectedWalletName;
1071
- return /* @__PURE__ */ jsxs4(
1181
+ return /* @__PURE__ */ jsxs5(
1072
1182
  "button",
1073
1183
  {
1074
1184
  type: "button",
1075
1185
  className: "fc-btn fc-btn-wallet",
1076
1186
  onClick: () => handleConnect(w),
1077
1187
  children: [
1078
- /* @__PURE__ */ jsx4("span", { className: "fc-installed-dot", style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ jsx4("img", { src: w.adapter.icon, alt: "", className: "fc-wallet-icon" }) }),
1079
- /* @__PURE__ */ jsx4("span", { className: "fc-wallet-name", children: w.adapter.name }),
1080
- isConnected && /* @__PURE__ */ jsx4("span", { className: "fc-badge-preferred", children: "Last used" })
1188
+ /* @__PURE__ */ jsx6("span", { className: "fc-installed-dot", style: { position: "relative", display: "inline-flex" }, children: /* @__PURE__ */ jsx6("img", { src: w.adapter.icon, alt: "", className: "fc-wallet-icon" }) }),
1189
+ /* @__PURE__ */ jsx6("span", { className: "fc-wallet-name", children: w.adapter.name }),
1190
+ isConnected && /* @__PURE__ */ jsx6("span", { className: "fc-badge-preferred", children: "Last used" })
1081
1191
  ]
1082
1192
  },
1083
1193
  w.adapter.name
1084
1194
  );
1085
1195
  })
1086
1196
  ] }),
1087
- preferredWallets.length === 0 && otherWallets.length === 0 && mobileExtraWallets.length === 0 && /* @__PURE__ */ jsx4("p", { className: "fc-text", children: "No wallet found. Please install a Solana wallet (like Phantom) to continue." }),
1088
- walletConfig?.Transaction && /* @__PURE__ */ jsxs4("label", { className: "fc-cold-wallet-toggle", children: [
1089
- /* @__PURE__ */ jsx4(
1197
+ preferredWallets.length === 0 && otherWallets.length === 0 && mobileExtraWallets.length === 0 && /* @__PURE__ */ jsx6("p", { className: "fc-text", children: "No wallet found. Please install a Solana wallet (like Phantom) to continue." }),
1198
+ /* @__PURE__ */ jsxs5("label", { className: "fc-cold-wallet-toggle", children: [
1199
+ /* @__PURE__ */ jsx6(
1090
1200
  "input",
1091
1201
  {
1092
1202
  type: "checkbox",
@@ -1094,21 +1204,21 @@ function WalletAdapterFlow() {
1094
1204
  onChange: (e) => setColdWallet(e.target.checked)
1095
1205
  }
1096
1206
  ),
1097
- /* @__PURE__ */ jsx4("span", { className: "fc-toggle-track" }),
1098
- /* @__PURE__ */ jsxs4("span", { className: "fc-cold-wallet-label", children: [
1099
- /* @__PURE__ */ jsx4("span", { children: "Hardware wallet" }),
1100
- /* @__PURE__ */ jsx4("span", { children: "Ledger, Trezor, Keystone..." })
1207
+ /* @__PURE__ */ jsx6("span", { className: "fc-toggle-track" }),
1208
+ /* @__PURE__ */ jsxs5("span", { className: "fc-cold-wallet-label", children: [
1209
+ /* @__PURE__ */ jsx6("span", { children: "Hardware wallet" }),
1210
+ /* @__PURE__ */ jsx6("span", { children: "Ledger, Trezor, Keystone..." })
1101
1211
  ] })
1102
1212
  ] }),
1103
- error && /* @__PURE__ */ jsx4("p", { className: "fc-error", children: error })
1213
+ error && /* @__PURE__ */ jsx6("p", { className: "fc-error", children: error })
1104
1214
  ] }),
1105
- showBack && !loading && /* @__PURE__ */ jsx4("p", { className: "fc-switch", children: /* @__PURE__ */ jsx4("button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
1215
+ showBack && !loading && /* @__PURE__ */ jsx6("p", { className: "fc-switch", children: /* @__PURE__ */ jsx6("button", { type: "button", className: "fc-link", onClick: () => setModalStep("method-select"), children: "Back" }) })
1106
1216
  ] });
1107
1217
  }
1108
1218
 
1109
1219
  // src/components/tabs/forgot-password.tsx
1110
1220
  import { useState as useState4 } from "react";
1111
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1221
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1112
1222
  function ForgotPasswordForm() {
1113
1223
  const { forgotPassword, resetPassword, setModalStep } = useForgeConnect();
1114
1224
  const [step, setStep] = useState4("email");
@@ -1144,24 +1254,24 @@ function ForgotPasswordForm() {
1144
1254
  }
1145
1255
  };
1146
1256
  if (step === "done") {
1147
- return /* @__PURE__ */ jsxs5("div", { className: "fc-tab", children: [
1148
- /* @__PURE__ */ jsx5("h3", { className: "fc-tab-title", children: "Password updated" }),
1149
- /* @__PURE__ */ jsx5("p", { className: "fc-text", children: "Your password has been reset. You can now sign in." }),
1150
- /* @__PURE__ */ jsx5("button", { type: "button", className: "fc-btn fc-btn-primary", onClick: () => setModalStep("email-login"), children: "Sign in" })
1257
+ return /* @__PURE__ */ jsxs6("div", { className: "fc-tab", children: [
1258
+ /* @__PURE__ */ jsx7("h3", { className: "fc-tab-title", children: "Password updated" }),
1259
+ /* @__PURE__ */ jsx7("p", { className: "fc-text", children: "Your password has been reset. You can now sign in." }),
1260
+ /* @__PURE__ */ jsx7("button", { type: "button", className: "fc-btn fc-btn-primary", onClick: () => setModalStep("email-login"), children: "Sign in" })
1151
1261
  ] });
1152
1262
  }
1153
1263
  if (step === "reset") {
1154
- return /* @__PURE__ */ jsxs5("div", { className: "fc-tab", children: [
1155
- /* @__PURE__ */ jsx5("h3", { className: "fc-tab-title", children: "Set new password" }),
1156
- /* @__PURE__ */ jsxs5("p", { className: "fc-text", children: [
1264
+ return /* @__PURE__ */ jsxs6("div", { className: "fc-tab", children: [
1265
+ /* @__PURE__ */ jsx7("h3", { className: "fc-tab-title", children: "Set new password" }),
1266
+ /* @__PURE__ */ jsxs6("p", { className: "fc-text", children: [
1157
1267
  "We sent a reset code to ",
1158
- /* @__PURE__ */ jsx5("strong", { children: email }),
1268
+ /* @__PURE__ */ jsx7("strong", { children: email }),
1159
1269
  ". Paste it below with your new password."
1160
1270
  ] }),
1161
- /* @__PURE__ */ jsxs5("form", { onSubmit: handleReset, className: "fc-form", children: [
1162
- /* @__PURE__ */ jsxs5("label", { className: "fc-label", children: [
1271
+ /* @__PURE__ */ jsxs6("form", { onSubmit: handleReset, className: "fc-form", children: [
1272
+ /* @__PURE__ */ jsxs6("label", { className: "fc-label", children: [
1163
1273
  "Reset code",
1164
- /* @__PURE__ */ jsx5(
1274
+ /* @__PURE__ */ jsx7(
1165
1275
  "input",
1166
1276
  {
1167
1277
  type: "text",
@@ -1174,9 +1284,9 @@ function ForgotPasswordForm() {
1174
1284
  }
1175
1285
  )
1176
1286
  ] }),
1177
- /* @__PURE__ */ jsxs5("label", { className: "fc-label", children: [
1287
+ /* @__PURE__ */ jsxs6("label", { className: "fc-label", children: [
1178
1288
  "New password",
1179
- /* @__PURE__ */ jsx5(
1289
+ /* @__PURE__ */ jsx7(
1180
1290
  "input",
1181
1291
  {
1182
1292
  type: "password",
@@ -1190,19 +1300,19 @@ function ForgotPasswordForm() {
1190
1300
  }
1191
1301
  )
1192
1302
  ] }),
1193
- error && /* @__PURE__ */ jsx5("p", { className: "fc-error", children: error }),
1194
- /* @__PURE__ */ jsx5("button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading, children: loading ? "Resetting..." : "Reset password" })
1303
+ error && /* @__PURE__ */ jsx7("p", { className: "fc-error", children: error }),
1304
+ /* @__PURE__ */ jsx7("button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading, children: loading ? "Resetting..." : "Reset password" })
1195
1305
  ] }),
1196
- /* @__PURE__ */ jsx5("p", { className: "fc-switch", children: /* @__PURE__ */ jsx5("button", { type: "button", className: "fc-link", onClick: () => setStep("email"), children: "Resend code" }) })
1306
+ /* @__PURE__ */ jsx7("p", { className: "fc-switch", children: /* @__PURE__ */ jsx7("button", { type: "button", className: "fc-link", onClick: () => setStep("email"), children: "Resend code" }) })
1197
1307
  ] });
1198
1308
  }
1199
- return /* @__PURE__ */ jsxs5("div", { className: "fc-tab", children: [
1200
- /* @__PURE__ */ jsx5("h3", { className: "fc-tab-title", children: "Reset your password" }),
1201
- /* @__PURE__ */ jsx5("p", { className: "fc-text", children: "Enter your email and we'll send you a reset code." }),
1202
- /* @__PURE__ */ jsxs5("form", { onSubmit: handleSendCode, className: "fc-form", children: [
1203
- /* @__PURE__ */ jsxs5("label", { className: "fc-label", children: [
1309
+ return /* @__PURE__ */ jsxs6("div", { className: "fc-tab", children: [
1310
+ /* @__PURE__ */ jsx7("h3", { className: "fc-tab-title", children: "Reset your password" }),
1311
+ /* @__PURE__ */ jsx7("p", { className: "fc-text", children: "Enter your email and we'll send you a reset code." }),
1312
+ /* @__PURE__ */ jsxs6("form", { onSubmit: handleSendCode, className: "fc-form", children: [
1313
+ /* @__PURE__ */ jsxs6("label", { className: "fc-label", children: [
1204
1314
  "Email",
1205
- /* @__PURE__ */ jsx5(
1315
+ /* @__PURE__ */ jsx7(
1206
1316
  "input",
1207
1317
  {
1208
1318
  type: "email",
@@ -1215,25 +1325,25 @@ function ForgotPasswordForm() {
1215
1325
  }
1216
1326
  )
1217
1327
  ] }),
1218
- error && /* @__PURE__ */ jsx5("p", { className: "fc-error", children: error }),
1219
- /* @__PURE__ */ jsx5("button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading, children: loading ? "Sending..." : "Send reset code" })
1328
+ error && /* @__PURE__ */ jsx7("p", { className: "fc-error", children: error }),
1329
+ /* @__PURE__ */ jsx7("button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading, children: loading ? "Sending..." : "Send reset code" })
1220
1330
  ] }),
1221
- /* @__PURE__ */ jsx5("p", { className: "fc-switch", children: /* @__PURE__ */ jsx5("button", { type: "button", className: "fc-link", onClick: () => setModalStep("email-login"), children: "Back to sign in" }) })
1331
+ /* @__PURE__ */ jsx7("p", { className: "fc-switch", children: /* @__PURE__ */ jsx7("button", { type: "button", className: "fc-link", onClick: () => setModalStep("email-login"), children: "Back to sign in" }) })
1222
1332
  ] });
1223
1333
  }
1224
1334
 
1225
1335
  // src/components/tabs/verify-2fa.tsx
1226
- import { useState as useState5, useRef as useRef4, useEffect as useEffect3, useCallback as useCallback2 } from "react";
1227
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1336
+ import { useState as useState5, useRef as useRef5, useEffect as useEffect4, useCallback as useCallback2 } from "react";
1337
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1228
1338
  function Verify2FAForm() {
1229
1339
  const { verify2FA, verifyRecoveryCode, setModalStep } = useForgeConnect();
1230
1340
  const [code, setCode] = useState5("");
1231
1341
  const [loading, setLoading] = useState5(false);
1232
1342
  const [error, setError] = useState5("");
1233
1343
  const [useRecovery, setUseRecovery] = useState5(false);
1234
- const inputRef = useRef4(null);
1235
- const submittingRef = useRef4(false);
1236
- useEffect3(() => {
1344
+ const inputRef = useRef5(null);
1345
+ const submittingRef = useRef5(false);
1346
+ useEffect4(() => {
1237
1347
  inputRef.current?.focus();
1238
1348
  }, [useRecovery]);
1239
1349
  const submitCode = useCallback2(async (codeValue, isRecovery) => {
@@ -1264,15 +1374,15 @@ function Verify2FAForm() {
1264
1374
  submitCode(value, false);
1265
1375
  }
1266
1376
  };
1267
- return /* @__PURE__ */ jsxs6("div", { className: "fc-tab", children: [
1268
- /* @__PURE__ */ jsxs6("button", { type: "button", className: "fc-back", onClick: () => setModalStep("method-select"), children: [
1269
- /* @__PURE__ */ jsx6("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx6("path", { d: "M10 12L6 8l4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
1377
+ return /* @__PURE__ */ jsxs7("div", { className: "fc-tab", children: [
1378
+ /* @__PURE__ */ jsxs7("button", { type: "button", className: "fc-back", onClick: () => setModalStep("method-select"), children: [
1379
+ /* @__PURE__ */ jsx8("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx8("path", { d: "M10 12L6 8l4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
1270
1380
  "Back"
1271
1381
  ] }),
1272
- /* @__PURE__ */ jsx6("p", { className: "fc-account-section-desc", style: { marginTop: 8 }, children: useRecovery ? "Enter one of your recovery codes." : "Enter the 6-digit code from your authenticator app." }),
1273
- error && /* @__PURE__ */ jsx6("p", { className: "fc-error", children: error }),
1274
- /* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className: "fc-form", children: [
1275
- /* @__PURE__ */ jsx6(
1382
+ /* @__PURE__ */ jsx8("p", { className: "fc-account-section-desc", style: { marginTop: 8 }, children: useRecovery ? "Enter one of your recovery codes." : "Enter the 6-digit code from your authenticator app." }),
1383
+ error && /* @__PURE__ */ jsx8("p", { className: "fc-error", children: error }),
1384
+ /* @__PURE__ */ jsxs7("form", { onSubmit: handleSubmit, className: "fc-form", children: [
1385
+ /* @__PURE__ */ jsx8(
1276
1386
  "input",
1277
1387
  {
1278
1388
  ref: inputRef,
@@ -1287,9 +1397,9 @@ function Verify2FAForm() {
1287
1397
  style: useRecovery ? {} : { textAlign: "center", letterSpacing: "0.3em", fontSize: "1.25rem" }
1288
1398
  }
1289
1399
  ),
1290
- /* @__PURE__ */ jsx6("button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading || !code.trim(), children: loading ? "Verifying..." : "Verify" })
1400
+ /* @__PURE__ */ jsx8("button", { type: "submit", className: "fc-btn fc-btn-primary", disabled: loading || !code.trim(), children: loading ? "Verifying..." : "Verify" })
1291
1401
  ] }),
1292
- /* @__PURE__ */ jsx6(
1402
+ /* @__PURE__ */ jsx8(
1293
1403
  "button",
1294
1404
  {
1295
1405
  type: "button",
@@ -1306,80 +1416,6 @@ function Verify2FAForm() {
1306
1416
  ] });
1307
1417
  }
1308
1418
 
1309
- // src/components/svg-icon.tsx
1310
- import { useRef as useRef5, useEffect as useEffect4 } from "react";
1311
- import { jsx as jsx7 } from "react/jsx-runtime";
1312
- function SvgIcon({ svg, className }) {
1313
- const ref = useRef5(null);
1314
- useEffect4(() => {
1315
- if (!ref.current || !svg) return;
1316
- try {
1317
- const doc = new DOMParser().parseFromString(svg, "text/html");
1318
- const svgEl = doc.body.querySelector("svg");
1319
- if (!svgEl) {
1320
- ref.current.textContent = "";
1321
- return;
1322
- }
1323
- const dangerous = svgEl.querySelectorAll("script,iframe,object,embed,foreignObject");
1324
- dangerous.forEach((el) => el.remove());
1325
- const all = svgEl.querySelectorAll("*");
1326
- all.forEach((el) => {
1327
- for (const attr of Array.from(el.attributes)) {
1328
- if (attr.name.startsWith("on")) {
1329
- el.removeAttribute(attr.name);
1330
- }
1331
- }
1332
- });
1333
- ref.current.textContent = "";
1334
- ref.current.appendChild(svgEl);
1335
- } catch {
1336
- ref.current.textContent = "";
1337
- }
1338
- }, [svg]);
1339
- return /* @__PURE__ */ jsx7("span", { ref, className });
1340
- }
1341
-
1342
- // src/components/tabs/oauth-buttons.tsx
1343
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1344
- var PROVIDER_INFO = {
1345
- google: {
1346
- label: "Google",
1347
- icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" fill="#4285F4"/><path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/><path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/><path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/></svg>'
1348
- },
1349
- discord: {
1350
- label: "Discord",
1351
- icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128c.126-.094.252-.192.372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z" fill="#5865F2"/></svg>'
1352
- },
1353
- twitter: {
1354
- label: "Twitter",
1355
- icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" fill="currentColor"/></svg>'
1356
- },
1357
- apple: {
1358
- label: "Apple",
1359
- icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.52-3.23 0-1.44.64-2.2.45-3.06-.4C3.79 16.17 4.36 9.02 8.8 8.78c1.27.06 2.15.72 2.91.76.93-.19 1.82-.88 2.83-.8 1.21.1 2.12.58 2.72 1.49-2.46 1.48-1.88 4.73.52 5.64-.42 1.13-.98 2.24-1.73 3.41zM12.03 8.7c-.12-2.35 1.82-4.38 4.04-4.54.29 2.56-2.34 4.68-4.04 4.54z" fill="currentColor"/></svg>'
1360
- },
1361
- telegram: {
1362
- label: "Telegram",
1363
- icon: '<svg viewBox="0 0 24 24" width="20" height="20"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.479.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z" fill="#2AABEE"/></svg>'
1364
- }
1365
- };
1366
- function OAuthButton({ provider }) {
1367
- const { loginWithOAuth } = useForgeConnect();
1368
- const info = PROVIDER_INFO[provider];
1369
- return /* @__PURE__ */ jsxs7(
1370
- "button",
1371
- {
1372
- type: "button",
1373
- className: "fc-btn fc-btn-oauth",
1374
- onClick: () => loginWithOAuth(provider),
1375
- children: [
1376
- /* @__PURE__ */ jsx8(SvgIcon, { svg: info.icon, className: "fc-oauth-icon" }),
1377
- /* @__PURE__ */ jsx8("span", { className: "fc-btn-name", children: info.label })
1378
- ]
1379
- }
1380
- );
1381
- }
1382
-
1383
1419
  // src/components/login-modal.tsx
1384
1420
  import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1385
1421
  function LoginModal() {
@@ -3769,6 +3805,7 @@ function SuccessView2() {
3769
3805
 
3770
3806
  // src/provider.tsx
3771
3807
  import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
3808
+ var oauthExchangeCache = /* @__PURE__ */ new Map();
3772
3809
  function ForgeConnectProvider({ config, children, onLogin, onLogout, walletAdapter }) {
3773
3810
  const [auth, setAuth] = useState16({
3774
3811
  status: "loading",
@@ -3827,42 +3864,81 @@ function ForgeConnectProvider({ config, children, onLogin, onLogout, walletAdapt
3827
3864
  return;
3828
3865
  }
3829
3866
  const authCode = params.get("fc_code");
3830
- if (authCode && window.opener) {
3831
- window.opener.postMessage(
3832
- { type: "fc_oauth_code", code: authCode },
3833
- window.location.origin
3834
- );
3867
+ if (authCode) {
3868
+ try {
3869
+ localStorage.setItem("fc_oauth_code_pending", authCode);
3870
+ } catch {
3871
+ }
3872
+ if (window.opener) {
3873
+ window.opener.postMessage(
3874
+ { type: "fc_oauth_code", code: authCode },
3875
+ window.location.origin
3876
+ );
3877
+ }
3835
3878
  window.close();
3836
3879
  return;
3837
3880
  }
3838
3881
  }
3839
- const handleMessage = async (event) => {
3882
+ const handleCode = async (code) => {
3883
+ let exchangePromise = oauthExchangeCache.get(code);
3884
+ if (!exchangePromise) {
3885
+ try {
3886
+ localStorage.removeItem("fc_oauth_code_pending");
3887
+ } catch {
3888
+ }
3889
+ exchangePromise = (async () => {
3890
+ try {
3891
+ const result = await api.exchangeOAuthCode(code);
3892
+ if (result.requires2FA && result.challengeToken) {
3893
+ return { kind: "requires2FA", challengeToken: result.challengeToken };
3894
+ }
3895
+ const token = result.accessToken;
3896
+ if (!token) return null;
3897
+ const user = await api.getMe(token);
3898
+ return { kind: "authenticated", accessToken: token, user };
3899
+ } catch {
3900
+ return null;
3901
+ }
3902
+ })();
3903
+ oauthExchangeCache.set(code, exchangePromise);
3904
+ }
3905
+ const outcome = await exchangePromise;
3906
+ if (!outcome) return;
3907
+ if (outcome.kind === "requires2FA") {
3908
+ setChallengeToken(outcome.challengeToken);
3909
+ setModal({ isOpen: true, step: "verify-2fa" });
3910
+ return;
3911
+ }
3912
+ setModal({ isOpen: true, step: "success" });
3913
+ setAuth({ status: "authenticated", user: outcome.user, accessToken: outcome.accessToken });
3914
+ scheduleRefresh(outcome.accessToken);
3915
+ onLogin?.(outcome.user);
3916
+ setTimeout(() => {
3917
+ setModal({ isOpen: false, step: "method-select" });
3918
+ }, 1500);
3919
+ };
3920
+ const handleMessage = (event) => {
3840
3921
  if (event.origin !== window.location.origin) return;
3841
3922
  if (event.data?.type !== "fc_oauth_code") return;
3842
3923
  const code = event.data.code;
3843
3924
  if (!code) return;
3844
- try {
3845
- const result = await api.exchangeOAuthCode(code);
3846
- if (result.requires2FA && result.challengeToken) {
3847
- setChallengeToken(result.challengeToken);
3848
- setModal({ isOpen: true, step: "verify-2fa" });
3849
- return;
3850
- }
3851
- const token = result.accessToken;
3852
- if (!token) return;
3853
- setModal({ isOpen: true, step: "success" });
3854
- const user = await api.getMe(token);
3855
- setAuth({ status: "authenticated", user, accessToken: token });
3856
- scheduleRefresh(token);
3857
- onLogin?.(user);
3858
- setTimeout(() => {
3859
- setModal({ isOpen: false, step: "method-select" });
3860
- }, 1500);
3861
- } catch {
3862
- }
3925
+ void handleCode(code);
3926
+ };
3927
+ const handleStorage = (event) => {
3928
+ if (event.key !== "fc_oauth_code_pending" || !event.newValue) return;
3929
+ void handleCode(event.newValue);
3863
3930
  };
3931
+ try {
3932
+ const pending = localStorage.getItem("fc_oauth_code_pending");
3933
+ if (pending) void handleCode(pending);
3934
+ } catch {
3935
+ }
3864
3936
  window.addEventListener("message", handleMessage);
3865
- return () => window.removeEventListener("message", handleMessage);
3937
+ window.addEventListener("storage", handleStorage);
3938
+ return () => {
3939
+ window.removeEventListener("message", handleMessage);
3940
+ window.removeEventListener("storage", handleStorage);
3941
+ };
3866
3942
  }, [api, config.apiUrl, scheduleRefresh, onLogin]);
3867
3943
  useEffect12(() => {
3868
3944
  if (config.loginMethods && config.loginMethods.length > 0) {