decane-connect-kit 2.28.0 → 2.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -5551,8 +5551,8 @@ async function deriveAddressesFromShares(a, b) {
5551
5551
  init_errors();
5552
5552
 
5553
5553
  // src/ui/WalletSelector.tsx
5554
- var import_react2 = __toESM(require("react"), 1);
5555
- var import_react_dom = require("react-dom");
5554
+ var import_react3 = __toESM(require("react"), 1);
5555
+ var import_react_dom2 = require("react-dom");
5556
5556
 
5557
5557
  // src/ui/styles.ts
5558
5558
  var tokens = {
@@ -5601,6 +5601,7 @@ var tokens = {
5601
5601
  accent: "#F5C800",
5602
5602
  accentHover: "#D4A800",
5603
5603
  accentText: "#0D0D0B",
5604
+ accentInk: "#7A5F00",
5604
5605
  badgeEvm: "#1A1917",
5605
5606
  badgeEvmText: "#F5C800",
5606
5607
  badgeSolana: "#F5C800",
@@ -5621,6 +5622,7 @@ var tokens = {
5621
5622
  accent: "#F5C800",
5622
5623
  accentHover: "#FFE04D",
5623
5624
  accentText: "#0D0D0B",
5625
+ accentInk: "#F5C800",
5624
5626
  badgeEvm: "#F5C800",
5625
5627
  badgeEvmText: "#0D0D0B",
5626
5628
  badgeSolana: "#1A1917",
@@ -5646,6 +5648,7 @@ var CSS_VARS = {
5646
5648
  --dc-accent: ${tokens.light.accent};
5647
5649
  --dc-accent-hover: ${tokens.light.accentHover};
5648
5650
  --dc-accent-text: ${tokens.light.accentText};
5651
+ --dc-accent-ink: ${tokens.light.accentInk};
5649
5652
  --dc-badge-evm: ${tokens.light.badgeEvm};
5650
5653
  --dc-badge-evm-text: ${tokens.light.badgeEvmText};
5651
5654
  --dc-badge-sol: ${tokens.light.badgeSolana};
@@ -5667,6 +5670,7 @@ var CSS_VARS = {
5667
5670
  --dc-accent: ${tokens.dark.accent};
5668
5671
  --dc-accent-hover: ${tokens.dark.accentHover};
5669
5672
  --dc-accent-text: ${tokens.dark.accentText};
5673
+ --dc-accent-ink: ${tokens.dark.accentInk};
5670
5674
  --dc-badge-evm: ${tokens.dark.badgeEvm};
5671
5675
  --dc-badge-evm-text: ${tokens.dark.badgeEvmText};
5672
5676
  --dc-badge-sol: ${tokens.dark.badgeSolana};
@@ -5828,145 +5832,262 @@ function XLogo({ size = 14 }) {
5828
5832
  /* @__PURE__ */ import_react.default.createElement("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" })
5829
5833
  );
5830
5834
  }
5831
-
5832
- // src/ui/WalletSelector.tsx
5833
- var FONT_URL = "https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap";
5834
- function injectTokens(theme) {
5835
- let resolved;
5836
- if (theme === "auto") {
5837
- resolved = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
5838
- } else {
5839
- resolved = theme;
5840
- }
5841
- let styleEl = document.getElementById("decane-tokens");
5842
- if (!styleEl) {
5843
- styleEl = document.createElement("style");
5844
- styleEl.id = "decane-tokens";
5845
- document.head.appendChild(styleEl);
5846
- }
5847
- styleEl.textContent = `:root { ${CSS_VARS[resolved]} }`;
5835
+ var line = {
5836
+ fill: "none",
5837
+ stroke: "currentColor",
5838
+ strokeWidth: 1.8,
5839
+ strokeLinecap: "round",
5840
+ strokeLinejoin: "round"
5841
+ };
5842
+ function GoogleMark({ size = 18 }) {
5843
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 48 48", "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("path", { fill: "#EA4335", d: "M24 9.5c3.5 0 6 1.5 7.4 2.8l5.4-5.3C33.5 3.9 29.2 2 24 2 15.4 2 8 7 4.7 14.2l6.3 4.9C12.6 13.4 17.8 9.5 24 9.5z" }), /* @__PURE__ */ import_react.default.createElement("path", { fill: "#4285F4", d: "M46 24.5c0-1.6-.1-2.8-.4-4H24v7.5h12.6c-.3 2.2-1.7 5.5-4.9 7.7l6.1 4.7C41.5 37 46 31.4 46 24.5z" }), /* @__PURE__ */ import_react.default.createElement("path", { fill: "#FBBC05", d: "M11 29.1a13.9 13.9 0 0 1 0-10l-6.3-4.9A22 22 0 0 0 2 24c0 3.5.8 6.9 2.4 9.8L11 29.1z" }), /* @__PURE__ */ import_react.default.createElement("path", { fill: "#34A853", d: "M24 46c5.9 0 10.9-2 14.5-5.4l-6.1-4.7c-1.7 1.2-4 2-8.4 2-6.2 0-11.4-4-13.1-9.6l-6.3 4.9C7.9 40.9 15.3 46 24 46z" }));
5848
5844
  }
5849
- function injectFont() {
5850
- if (document.getElementById("decane-font")) return;
5851
- const link = document.createElement("link");
5852
- link.id = "decane-font";
5853
- link.rel = "stylesheet";
5854
- link.href = FONT_URL;
5855
- document.head.appendChild(link);
5845
+ function MailIcon({ size = 18 }) {
5846
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2.5" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "m3.5 7 8.5 6 8.5-6" }));
5856
5847
  }
5857
- function WalletRow({ wallet, onClick }) {
5858
- const [hovered, setHovered] = (0, import_react2.useState)(false);
5859
- const [focused, setFocused] = (0, import_react2.useState)(false);
5860
- return /* @__PURE__ */ import_react2.default.createElement(
5861
- "button",
5862
- {
5863
- onClick,
5864
- onMouseEnter: () => setHovered(true),
5865
- onMouseLeave: () => setHovered(false),
5866
- onFocus: () => setFocused(true),
5867
- onBlur: () => setFocused(false),
5868
- style: {
5869
- display: "flex",
5870
- alignItems: "center",
5871
- gap: 12,
5872
- width: "100%",
5873
- padding: "11px 14px",
5874
- background: hovered ? "var(--dc-surface-hover)" : "transparent",
5875
- border: focused ? "1px solid var(--dc-border-accent)" : "1px solid transparent",
5876
- borderRadius: 10,
5877
- cursor: "pointer",
5878
- textAlign: "left",
5879
- transition: "background 0.12s, border-color 0.12s",
5880
- outline: "none",
5881
- fontFamily: "inherit"
5882
- }
5883
- },
5884
- /* @__PURE__ */ import_react2.default.createElement(WalletIcon, { src: wallet.icon || void 0, name: wallet.name, size: 38 }),
5885
- /* @__PURE__ */ import_react2.default.createElement("span", { style: { flex: 1, fontSize: 14, fontWeight: 600, color: "var(--dc-text)", letterSpacing: "-0.01em" } }, wallet.name),
5886
- /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: wallet.chainSupport, size: 16 }),
5887
- /* @__PURE__ */ import_react2.default.createElement(
5888
- "svg",
5889
- {
5890
- width: "14",
5891
- height: "14",
5892
- viewBox: "0 0 14 14",
5893
- fill: "none",
5894
- style: { color: hovered ? "var(--dc-text-secondary)" : "var(--dc-text-muted)", flexShrink: 0, transition: "color 0.12s" }
5895
- },
5896
- /* @__PURE__ */ import_react2.default.createElement("path", { d: "M5 2.5L9.5 7L5 11.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
5897
- )
5898
- );
5848
+ function PhoneIcon({ size = 18 }) {
5849
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("rect", { x: "7", y: "2.5", width: "10", height: "19", rx: "2.5" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M11 18h2" }));
5899
5850
  }
5900
- function FilterTab({ label, active, onClick }) {
5901
- const [hovered, setHovered] = (0, import_react2.useState)(false);
5902
- return /* @__PURE__ */ import_react2.default.createElement(
5903
- "button",
5904
- {
5905
- onClick,
5906
- onMouseEnter: () => setHovered(true),
5907
- onMouseLeave: () => setHovered(false),
5908
- style: {
5909
- flex: 1,
5910
- padding: "6px 8px",
5911
- borderRadius: 8,
5912
- border: active ? "1px solid var(--dc-border-accent)" : "1px solid transparent",
5913
- background: active ? "rgba(245,200,0,0.1)" : hovered ? "var(--dc-surface-hover)" : "transparent",
5914
- color: active ? "var(--dc-accent)" : "var(--dc-text-muted)",
5915
- fontSize: 11,
5916
- fontWeight: 700,
5917
- letterSpacing: "0.04em",
5918
- textTransform: "uppercase",
5919
- cursor: "pointer",
5920
- transition: "all 0.12s",
5921
- fontFamily: "inherit",
5922
- outline: "none"
5923
- }
5924
- },
5925
- label
5926
- );
5851
+ function ChatIcon({ size = 18 }) {
5852
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M4 6.5A2.5 2.5 0 0 1 6.5 4h11A2.5 2.5 0 0 1 20 6.5v7a2.5 2.5 0 0 1-2.5 2.5H10l-4.2 3.2a.6.6 0 0 1-1-.5V16A2.5 2.5 0 0 1 4 13.5z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M8.5 9h7M8.5 12.5h4.5" }));
5853
+ }
5854
+ function KeyIcon({ size = 18 }) {
5855
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "8", cy: "12", r: "4" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 12h9M18 12v3M15 12v2.5" }));
5856
+ }
5857
+ function UserIcon({ size = 18 }) {
5858
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "8.5", r: "3.8" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M4.5 20a7.5 7.5 0 0 1 15 0" }));
5859
+ }
5860
+ function CopyIcon({ size = 15 }) {
5861
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("rect", { x: "8.5", y: "8.5", width: "12", height: "12", rx: "2.5" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M15.5 8.5V6A2.5 2.5 0 0 0 13 3.5H6A2.5 2.5 0 0 0 3.5 6v7A2.5 2.5 0 0 0 6 15.5h2.5" }));
5862
+ }
5863
+ function CheckIcon({ size = 15 }) {
5864
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("path", { d: "m5 12.5 4.5 4.5L19 7.5" }));
5927
5865
  }
5928
- function ChainOption({ label, description, badges, onClick }) {
5929
- const [hovered, setHovered] = (0, import_react2.useState)(false);
5930
- return /* @__PURE__ */ import_react2.default.createElement(
5931
- "button",
5866
+ function CloseIcon({ size = 16 }) {
5867
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M6 6l12 12M18 6 6 18" }));
5868
+ }
5869
+ function ChevronIcon({ size = 16, open = false }) {
5870
+ return /* @__PURE__ */ import_react.default.createElement(
5871
+ "svg",
5932
5872
  {
5933
- onClick,
5934
- onMouseEnter: () => setHovered(true),
5935
- onMouseLeave: () => setHovered(false),
5936
- style: {
5937
- display: "flex",
5938
- flexDirection: "column",
5939
- alignItems: "flex-start",
5940
- gap: 6,
5941
- width: "100%",
5942
- padding: "14px 16px",
5943
- background: hovered ? "var(--dc-surface-hover)" : "var(--dc-surface)",
5944
- border: hovered ? "1px solid var(--dc-border-accent)" : "1px solid var(--dc-border)",
5945
- borderRadius: 12,
5946
- cursor: "pointer",
5947
- textAlign: "left",
5948
- transition: "all 0.12s",
5949
- fontFamily: "inherit",
5950
- outline: "none"
5951
- }
5873
+ width: size,
5874
+ height: size,
5875
+ viewBox: "0 0 24 24",
5876
+ ...line,
5877
+ "aria-hidden": "true",
5878
+ style: { flexShrink: 0, transition: "transform .2s", transform: open ? "rotate(180deg)" : "none" }
5952
5879
  },
5953
- badges,
5954
- /* @__PURE__ */ import_react2.default.createElement("span", { style: { fontSize: 13, fontWeight: 700, color: "var(--dc-text)" } }, label),
5955
- /* @__PURE__ */ import_react2.default.createElement("span", { style: { fontSize: 11, color: "var(--dc-text-muted)", lineHeight: 1.4 } }, description)
5880
+ /* @__PURE__ */ import_react.default.createElement("path", { d: "m6 9 6 6 6-6" })
5956
5881
  );
5957
5882
  }
5958
- function hasSocialMode(mode) {
5959
- return mode === "all" || mode === "social" || mode === "evm+social" || mode === "solana+social" || mode === "tron+social" || mode === "evm+tron+social";
5883
+ function ArrowLeftIcon({ size = 16 }) {
5884
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M19 12H5M11 6l-6 6 6 6" }));
5960
5885
  }
5961
- function WalletSelector({
5962
- provider,
5963
- open,
5964
- onClose,
5965
- onConnect,
5966
- theme = "auto",
5967
- networks = "all",
5968
- mode = "wallets",
5969
- socialAuthMethods = ["google", "email"],
5886
+ function WalletLineIcon({ size = 18 }) {
5887
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M4 7.5A2.5 2.5 0 0 1 6.5 5H18a1 1 0 0 1 1 1v2" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M4 7.5v9A2.5 2.5 0 0 0 6.5 19H19a1 1 0 0 0 1-1v-9a1 1 0 0 0-1-1H6.5A2.5 2.5 0 0 1 4 7.5z" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "16", cy: "13.5", r: "1", fill: "currentColor", stroke: "none" }));
5888
+ }
5889
+ function SearchIcon({ size = 16 }) {
5890
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "11", cy: "11", r: "6.5" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "m20 20-4.2-4.2" }));
5891
+ }
5892
+ function ChevronRightIcon({ size = 16 }) {
5893
+ return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", ...line, "aria-hidden": "true", style: { flexShrink: 0 } }, /* @__PURE__ */ import_react.default.createElement("path", { d: "m9 6 6 6-6 6" }));
5894
+ }
5895
+
5896
+ // src/ui/SocialWalletModal.tsx
5897
+ var import_react2 = __toESM(require("react"), 1);
5898
+ var import_react_dom = require("react-dom");
5899
+ function injectTokens(theme) {
5900
+ const resolved = theme === "auto" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
5901
+ let el = document.getElementById("decane-tokens");
5902
+ if (!el) {
5903
+ el = document.createElement("style");
5904
+ el.id = "decane-tokens";
5905
+ document.head.appendChild(el);
5906
+ }
5907
+ el.textContent = `:root { ${CSS_VARS[resolved]} }`;
5908
+ }
5909
+ function countdown(expiresAt) {
5910
+ const secs = Math.max(0, Math.round((expiresAt - Date.now()) / 1e3));
5911
+ return `${Math.floor(secs / 60)}m ${String(secs % 60).padStart(2, "0")}s`;
5912
+ }
5913
+ function downloadJson(data, filename) {
5914
+ const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
5915
+ const url = URL.createObjectURL(blob);
5916
+ const a = document.createElement("a");
5917
+ a.href = url;
5918
+ a.download = filename;
5919
+ a.click();
5920
+ URL.revokeObjectURL(url);
5921
+ }
5922
+ function useBalance(kind, address, chain, rpcUrls) {
5923
+ const [state, setState] = (0, import_react2.useState)({ loading: false, value: null, symbol: kind === "evm" ? "ETH" : "SOL" });
5924
+ (0, import_react2.useEffect)(() => {
5925
+ if (!address || !chain) return;
5926
+ let cancelled = false;
5927
+ setState((s) => ({ ...s, loading: true }));
5928
+ fetchBalance({ kind, address, chain, rpcUrls }).then((b) => {
5929
+ if (!cancelled) setState({ loading: false, value: b.formatted, symbol: b.symbol });
5930
+ }).catch(() => {
5931
+ if (!cancelled) setState({ loading: false, value: null, symbol: kind === "evm" ? "ETH" : "SOL" });
5932
+ });
5933
+ return () => {
5934
+ cancelled = true;
5935
+ };
5936
+ }, [kind, address, chain, rpcUrls]);
5937
+ return state;
5938
+ }
5939
+ var MODAL_CSS = `
5940
+ .dcm-card { position: relative; width: 100%; max-width: 380px; max-height: calc(100vh - 32px); overflow-y: auto;
5941
+ background: var(--dc-bg); color: var(--dc-text); border: 1px solid var(--dc-border); border-radius: 24px;
5942
+ box-shadow: 0 24px 64px -12px rgba(0,0,0,.35), 0 2px 8px rgba(0,0,0,.08);
5943
+ animation: dcm-in .22s cubic-bezier(.2,.8,.2,1); box-sizing: border-box; }
5944
+ .dcm-card *, .dcm-card *::before, .dcm-card *::after { box-sizing: border-box; }
5945
+ @keyframes dcm-in { from { opacity: 0; transform: translateY(8px) scale(.985); } to { opacity: 1; transform: none; } }
5946
+ @keyframes dcm-fade { from { opacity: 0; } to { opacity: 1; } }
5947
+ @media (prefers-reduced-motion: reduce) { .dcm-card, .dcm-backdrop { animation: none !important; } }
5948
+ .dcm-backdrop { position: absolute; inset: 0; background: var(--dc-bg-overlay);
5949
+ backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); animation: dcm-fade .2s ease; }
5950
+ .dcm-icon-btn { position: absolute; top: 14px; width: 32px; height: 32px; border-radius: 10px; border: 0;
5951
+ background: transparent; color: var(--dc-text-muted); cursor: pointer; display: grid; place-items: center;
5952
+ padding: 0; transition: background .15s, color .15s; z-index: 1; }
5953
+ .dcm-icon-btn:hover { background: var(--dc-surface-hover); color: var(--dc-text); }
5954
+ .dcm-body { padding: 32px 24px 20px; display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; }
5955
+ .dcm-title { margin: 4px 0 0; font-size: 20px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.25; color: var(--dc-text); }
5956
+ .dcm-sub { margin: -6px 0 2px; font-size: 13.5px; line-height: 1.5; color: var(--dc-text-secondary); overflow-wrap: anywhere; }
5957
+ .dcm-sub b { color: var(--dc-text); font-weight: 600; }
5958
+ .dcm-methods { width: 100%; display: grid; gap: 8px; margin-top: 4px; }
5959
+ .dcm-method { width: 100%; height: 48px; display: flex; align-items: center; gap: 12px; padding: 0 14px;
5960
+ border-radius: 14px; border: 1px solid var(--dc-border); background: var(--dc-surface); color: var(--dc-text);
5961
+ font-weight: 500; font-size: 14.5px; line-height: 1; font-family: inherit; cursor: pointer; text-align: left;
5962
+ transition: border-color .15s, background .15s; }
5963
+ .dcm-method:hover:not(:disabled) { border-color: var(--dc-text-muted); background: var(--dc-surface-hover); }
5964
+ .dcm-method:disabled { opacity: .6; cursor: default; }
5965
+ .dcm-method:focus-visible, .dcm-primary:focus-visible, .dcm-link:focus-visible, .dcm-icon-btn:focus-visible,
5966
+ .dcm-ghost:focus-visible, .dcm-copy:focus-visible { outline: 2px solid var(--dc-accent); outline-offset: 2px; }
5967
+ .dcm-method > svg { color: var(--dc-text-secondary); }
5968
+ .dcm-method-input { cursor: text; padding-right: 6px; }
5969
+ .dcm-method-input:focus-within { border-color: var(--dc-accent); }
5970
+ .dcm-method-input input { flex: 1; min-width: 0; height: 100%; border: 0; outline: 0; background: transparent;
5971
+ color: var(--dc-text); font-family: inherit; font-size: 14.5px; padding: 0; }
5972
+ .dcm-method-input input::placeholder { color: var(--dc-text-muted); }
5973
+ .dcm-submit { height: 34px; padding: 0 12px; border-radius: 10px; border: 0; background: transparent;
5974
+ color: var(--dc-accent-ink); font-weight: 600; font-size: 13.5px; line-height: 1; font-family: inherit; cursor: pointer; transition: background .15s; }
5975
+ .dcm-submit:hover:not(:disabled) { background: var(--dc-surface-hover); }
5976
+ .dcm-submit:disabled { color: var(--dc-text-muted); cursor: default; }
5977
+ .dcm-form { width: 100%; display: grid; gap: 10px; margin-top: 4px; }
5978
+ .dcm-field { width: 100%; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--dc-border);
5979
+ background: var(--dc-surface); color: var(--dc-text); font-family: inherit; font-size: 15px; outline: none;
5980
+ transition: border-color .15s, box-shadow .15s; }
5981
+ .dcm-field::placeholder { color: var(--dc-text-muted); }
5982
+ .dcm-field:focus { border-color: var(--dc-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--dc-accent) 22%, transparent); }
5983
+ .dcm-code { height: 56px; text-align: center; font-family: var(--dc-font-mono); font-size: 24px; letter-spacing: .45em; padding-left: calc(14px + .45em); }
5984
+ .dcm-primary { width: 100%; height: 48px; border-radius: 14px; border: 0; background: var(--dc-accent); color: var(--dc-accent-text);
5985
+ font-weight: 600; font-size: 14.5px; line-height: 1; font-family: inherit; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px;
5986
+ transition: background .15s, opacity .15s; }
5987
+ .dcm-primary:hover:not(:disabled) { background: var(--dc-accent-hover); }
5988
+ .dcm-primary:disabled { opacity: .55; cursor: default; }
5989
+ .dcm-ghost { height: 44px; padding: 0 16px; border-radius: 12px; border: 1px solid var(--dc-border); background: transparent;
5990
+ color: var(--dc-text); font-weight: 500; font-size: 14px; line-height: 1; font-family: inherit; cursor: pointer; transition: background .15s, border-color .15s; white-space: nowrap; }
5991
+ .dcm-ghost:hover:not(:disabled) { background: var(--dc-surface-hover); border-color: var(--dc-text-muted); }
5992
+ .dcm-ghost:disabled { opacity: .55; cursor: default; }
5993
+ .dcm-link { border: 0; background: transparent; color: var(--dc-accent-ink); font-weight: 500; font-size: 13.5px; line-height: 1.4; font-family: inherit;
5994
+ cursor: pointer; padding: 4px; border-radius: 6px; }
5995
+ .dcm-link:hover { text-decoration: underline; text-underline-offset: 3px; }
5996
+ .dcm-badge { width: 52px; height: 52px; border-radius: 16px; display: grid; place-items: center;
5997
+ background: var(--dc-surface); border: 1px solid var(--dc-border); color: var(--dc-text); }
5998
+ .dcm-error { margin: 0; width: 100%; font-size: 13px; line-height: 1.45; color: var(--dc-danger); overflow-wrap: anywhere; }
5999
+ .dcm-protected { width: 100%; display: flex; align-items: center; justify-content: center; gap: 6px;
6000
+ margin-top: 6px; padding-top: 14px; border-top: 1px solid var(--dc-border); font-size: 12.5px; color: var(--dc-text-muted); }
6001
+ .dcm-status { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 500; }
6002
+ .dcm-status i { width: 7px; height: 7px; border-radius: 50%; display: block; }
6003
+ .dcm-addresses { width: 100%; border: 1px solid var(--dc-border); border-radius: 16px; overflow: hidden; text-align: left; }
6004
+ .dcm-address { display: flex; align-items: center; gap: 12px; padding: 12px 14px; background: var(--dc-surface); }
6005
+ .dcm-address + .dcm-address { border-top: 1px solid var(--dc-border); }
6006
+ .dcm-address-main { flex: 1; min-width: 0; display: grid; gap: 3px; }
6007
+ .dcm-address-main span { font-size: 13px; color: var(--dc-text-secondary); }
6008
+ .dcm-address-main code { font-family: var(--dc-font-mono); font-size: 13px; color: var(--dc-text); }
6009
+ .dcm-balance { font-family: var(--dc-font-mono); font-size: 13px; color: var(--dc-text); white-space: nowrap; }
6010
+ .dcm-copy { width: 30px; height: 30px; border-radius: 9px; border: 0; background: transparent; color: var(--dc-text-muted);
6011
+ display: grid; place-items: center; cursor: pointer; padding: 0; transition: background .15s, color .15s; }
6012
+ .dcm-copy:hover { background: var(--dc-surface-hover); color: var(--dc-text); }
6013
+ .dcm-panel { width: 100%; border: 1px solid var(--dc-border); border-radius: 16px; text-align: left; overflow: hidden; }
6014
+ .dcm-panel-head { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 13px 14px;
6015
+ border: 0; background: var(--dc-surface); color: var(--dc-text); font-weight: 500; font-size: 14px; line-height: 1; font-family: inherit; cursor: pointer; }
6016
+ .dcm-panel-head:hover { background: var(--dc-surface-hover); }
6017
+ .dcm-panel-head svg { color: var(--dc-text-muted); }
6018
+ .dcm-panel-body { padding: 14px; border-top: 1px solid var(--dc-border); display: grid; gap: 10px; }
6019
+ .dcm-note { margin: 0; font-size: 13px; line-height: 1.5; color: var(--dc-text-secondary); }
6020
+ .dcm-warn { padding: 12px; border-radius: 12px; font-size: 13px; line-height: 1.5;
6021
+ background: color-mix(in srgb, var(--dc-danger) 9%, transparent); border: 1px solid color-mix(in srgb, var(--dc-danger) 30%, transparent); color: var(--dc-text); }
6022
+ .dcm-warn strong { display: block; margin-bottom: 2px; color: var(--dc-danger); font-weight: 600; }
6023
+ .dcm-check { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--dc-text); cursor: pointer; }
6024
+ .dcm-check input { width: 16px; height: 16px; margin: 0; accent-color: var(--dc-accent); }
6025
+ .dcm-row { display: flex; gap: 8px; width: 100%; }
6026
+ .dcm-row > .dcm-primary { flex: 1; height: 44px; border-radius: 12px; }
6027
+ .dcm-actions { width: 100%; display: flex; gap: 8px; }
6028
+ .dcm-or { width: 100%; display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--dc-text-muted); }
6029
+ .dcm-or::before, .dcm-or::after { content: ""; flex: 1; height: 1px; background: var(--dc-border); }
6030
+ .dcm-method .dcm-trail { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; color: var(--dc-text-muted); font-size: 12.5px; font-weight: 500; }
6031
+ .dcm-stack { display: inline-flex; }
6032
+ .dcm-stack img, .dcm-stack span { width: 22px; height: 22px; border-radius: 7px; border: 2px solid var(--dc-surface); margin-left: -7px; object-fit: cover; background: var(--dc-surface-hover); }
6033
+ .dcm-stack > :first-child { margin-left: 0; }
6034
+ .dcm-method:hover:not(:disabled) .dcm-stack img { border-color: var(--dc-surface-hover); }
6035
+ .dcm-wallet-img { width: 26px; height: 26px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }
6036
+ .dcm-list { width: 100%; display: grid; gap: 8px; max-height: min(380px, 50vh); overflow-y: auto; padding: 2px; margin: -2px; }
6037
+ .dcm-pills { width: 100%; display: flex; gap: 4px; padding: 4px; border-radius: 12px; background: var(--dc-surface); border: 1px solid var(--dc-border); }
6038
+ .dcm-pills button { flex: 1; height: 30px; border: 0; border-radius: 9px; background: transparent; color: var(--dc-text-secondary);
6039
+ font-family: inherit; font-size: 13px; font-weight: 500; cursor: pointer; transition: background .15s, color .15s; }
6040
+ .dcm-pills button:hover { color: var(--dc-text); }
6041
+ .dcm-pills button[aria-pressed="true"] { background: var(--dc-bg); color: var(--dc-text); box-shadow: 0 1px 3px rgba(0,0,0,.12); }
6042
+ .dcm-search { position: relative; width: 100%; }
6043
+ .dcm-search svg { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--dc-text-muted); pointer-events: none; }
6044
+ .dcm-search .dcm-field { padding: 10px 14px 10px 38px; font-size: 14px; }
6045
+ .dcm-empty { width: 100%; padding: 28px 12px; font-size: 13.5px; color: var(--dc-text-muted); }
6046
+ .dcm-option { width: 100%; display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: 14px; border: 1px solid var(--dc-border);
6047
+ background: var(--dc-surface); color: var(--dc-text); font-family: inherit; text-align: left; cursor: pointer; transition: border-color .15s, background .15s; }
6048
+ .dcm-option:hover { border-color: var(--dc-text-muted); background: var(--dc-surface-hover); }
6049
+ .dcm-option:focus-visible, .dcm-pills button:focus-visible { outline: 2px solid var(--dc-accent); outline-offset: 2px; }
6050
+ .dcm-option-icons { width: 64px; flex-shrink: 0; display: flex; }
6051
+ .dcm-option-text { flex: 1; min-width: 0; }
6052
+ .dcm-option b { display: block; font-size: 14.5px; font-weight: 500; }
6053
+ .dcm-option small { display: block; margin-top: 2px; font-size: 12.5px; line-height: 1.4; color: var(--dc-text-secondary); }
6054
+ .dcm-option > svg { color: var(--dc-text-muted); }
6055
+ .dcm-actions > * { flex: 1; }
6056
+ `;
6057
+ function injectModalCss() {
6058
+ if (document.getElementById("decane-modal-css")) return;
6059
+ const el = document.createElement("style");
6060
+ el.id = "decane-modal-css";
6061
+ el.textContent = MODAL_CSS;
6062
+ document.head.appendChild(el);
6063
+ }
6064
+ function shortAddress(a, head = 6, tail = 4) {
6065
+ return a.length > head + tail + 1 ? `${a.slice(0, head)}\u2026${a.slice(-tail)}` : a;
6066
+ }
6067
+ function CopyButton({ value, label }) {
6068
+ const [copied, setCopied] = (0, import_react2.useState)(false);
6069
+ async function copy() {
6070
+ await navigator.clipboard.writeText(value).catch(() => {
6071
+ });
6072
+ setCopied(true);
6073
+ setTimeout(() => setCopied(false), 1500);
6074
+ }
6075
+ return /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-copy", onClick: copy, "aria-label": copied ? "Copied" : `Copy ${label} address`, title: copied ? "Copied" : "Copy address" }, copied ? /* @__PURE__ */ import_react2.default.createElement(CheckIcon, null) : /* @__PURE__ */ import_react2.default.createElement(CopyIcon, null));
6076
+ }
6077
+ function AddressRow({
6078
+ label,
6079
+ address,
6080
+ kind,
6081
+ chain,
6082
+ rpcUrls
6083
+ }) {
6084
+ const balance = useBalance(kind, address, chain, rpcUrls);
6085
+ return /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-address" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-address-main" }, /* @__PURE__ */ import_react2.default.createElement("span", null, label), /* @__PURE__ */ import_react2.default.createElement("code", { title: address }, shortAddress(address, 8, 6))), /* @__PURE__ */ import_react2.default.createElement("span", { className: "dcm-balance" }, balance.loading ? "\u2026" : `${formatBalanceDisplay(balance.value)} ${balance.symbol}`), /* @__PURE__ */ import_react2.default.createElement(CopyButton, { value: address, label }));
6086
+ }
6087
+ function ProtectedBy() {
6088
+ return /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-protected" }, /* @__PURE__ */ import_react2.default.createElement("span", null, "Protected by"), /* @__PURE__ */ import_react2.default.createElement(DecaneMark, { size: 14, muted: true }), /* @__PURE__ */ import_react2.default.createElement(DecaneWordmark, { size: 12, muted: true }));
6089
+ }
6090
+ function SignInView({
5970
6091
  onGoogleSignIn,
5971
6092
  onKingsChatSignIn,
5972
6093
  onXSignIn,
@@ -5974,1362 +6095,219 @@ function WalletSelector({
5974
6095
  onEmailVerify,
5975
6096
  onPhoneStart,
5976
6097
  onPhoneVerify,
6098
+ authMethods,
6099
+ resumeHint,
5977
6100
  customAuthLabel,
5978
6101
  onCustomAuthSignIn,
5979
- canUsePasskey = false,
5980
- passkeyAddress = null,
5981
- onPasskeySignIn
6102
+ canUsePasskey,
6103
+ passkeyAddress,
6104
+ onPasskeySignIn,
6105
+ extra
5982
6106
  }) {
5983
- const showSocial = hasSocialMode(mode);
5984
- const showWallets = mode !== "social";
5985
- const [view, setView] = (0, import_react2.useState)(showSocial ? "social" : "wallets");
5986
- const [search, setSearch] = (0, import_react2.useState)("");
5987
- const [filter, setFilter] = (0, import_react2.useState)("all");
5988
- const [pendingWallet, setPendingWallet] = (0, import_react2.useState)(null);
5989
- const [emailStep, setEmailStep] = (0, import_react2.useState)("input");
5990
- const [emailVal, setEmailVal] = (0, import_react2.useState)("");
5991
- const [codeVal, setCodeVal] = (0, import_react2.useState)("");
5992
- const [phoneStep, setPhoneStep] = (0, import_react2.useState)("input");
5993
- const [phoneVal, setPhoneVal] = (0, import_react2.useState)("");
6107
+ const [googleLoading, setGoogleLoading] = (0, import_react2.useState)(false);
6108
+ const [kingsChatLoading, setKingsChatLoading] = (0, import_react2.useState)(false);
6109
+ const [xLoading, setXLoading] = (0, import_react2.useState)(false);
6110
+ const [email, setEmail] = (0, import_react2.useState)("");
6111
+ const [code, setCode] = (0, import_react2.useState)("");
6112
+ const [emailSent, setEmailSent] = (0, import_react2.useState)(false);
6113
+ const [emailLoading, setEmailLoading] = (0, import_react2.useState)(false);
6114
+ const [phone, setPhone] = (0, import_react2.useState)("");
5994
6115
  const [phoneCode, setPhoneCode] = (0, import_react2.useState)("");
5995
- const [socialLoad, setSocialLoad] = (0, import_react2.useState)(false);
5996
- const [socialErr, setSocialErr] = (0, import_react2.useState)("");
6116
+ const [phoneSent, setPhoneSent] = (0, import_react2.useState)(false);
6117
+ const [phoneLoading, setPhoneLoading] = (0, import_react2.useState)(false);
6118
+ const [customLoading, setCustomLoading] = (0, import_react2.useState)(false);
6119
+ const [passkeyLoading, setPasskeyLoading] = (0, import_react2.useState)(false);
5997
6120
  const [showOtherMethods, setShowOtherMethods] = (0, import_react2.useState)(false);
5998
- const passkeyFirst = canUsePasskey && !!onPasskeySignIn && !showOtherMethods;
5999
- (0, import_react2.useEffect)(() => {
6000
- if (!open) return;
6001
- injectFont();
6002
- injectTokens(theme);
6003
- if (theme !== "auto") return;
6004
- const mq = window.matchMedia("(prefers-color-scheme: dark)");
6005
- const handler = () => injectTokens("auto");
6006
- mq.addEventListener("change", handler);
6007
- return () => mq.removeEventListener("change", handler);
6008
- }, [open, theme]);
6009
- (0, import_react2.useEffect)(() => {
6010
- if (!open) {
6011
- setSearch("");
6012
- setFilter("all");
6013
- setPendingWallet(null);
6014
- setView(showSocial ? "social" : "wallets");
6015
- setEmailStep("input");
6016
- setEmailVal("");
6017
- setCodeVal("");
6018
- setSocialErr("");
6019
- setShowOtherMethods(false);
6020
- return;
6021
- }
6022
- return () => {
6023
- document.getElementById("decane-tokens")?.remove();
6024
- };
6025
- }, [open, showWallets]);
6026
- async function handlePasskeySignIn() {
6121
+ const [error, setError] = (0, import_react2.useState)("");
6122
+ const passkeyFirst = !!canUsePasskey && !!onPasskeySignIn && !showOtherMethods;
6123
+ const busy = googleLoading || kingsChatLoading || xLoading || customLoading || emailLoading || phoneLoading;
6124
+ async function handlePasskey() {
6027
6125
  if (!onPasskeySignIn) return;
6028
- setSocialLoad(true);
6029
- setSocialErr("");
6126
+ setError("");
6127
+ setPasskeyLoading(true);
6030
6128
  try {
6031
6129
  await onPasskeySignIn();
6032
6130
  } catch (e) {
6033
6131
  const err = e;
6034
6132
  if (err?.name !== "UserCancelledError") {
6035
- setSocialErr(err?.message ?? "Passkey sign-in failed");
6133
+ setError(err?.message ?? "Passkey sign-in failed");
6036
6134
  setShowOtherMethods(true);
6037
6135
  }
6038
- setSocialLoad(false);
6136
+ setPasskeyLoading(false);
6039
6137
  }
6040
6138
  }
6041
- async function handlePasskeyClick() {
6042
- void handlePasskeySignIn();
6043
- }
6044
- async function handleGoogleClick() {
6045
- if (!onGoogleSignIn) return;
6046
- setSocialLoad(true);
6047
- setSocialErr("");
6139
+ async function handleGoogle() {
6140
+ setError("");
6141
+ setGoogleLoading(true);
6048
6142
  try {
6049
6143
  await onGoogleSignIn();
6050
6144
  } catch (e) {
6051
- setSocialErr(e.message);
6052
- setSocialLoad(false);
6145
+ setError(e.message);
6146
+ setGoogleLoading(false);
6053
6147
  }
6054
6148
  }
6055
- async function handleKingsChatClick() {
6149
+ async function handleKingsChat() {
6056
6150
  if (!onKingsChatSignIn) return;
6057
- setSocialLoad(true);
6058
- setSocialErr("");
6151
+ setError("");
6152
+ setKingsChatLoading(true);
6059
6153
  try {
6060
6154
  await onKingsChatSignIn();
6061
6155
  } catch (e) {
6062
- setSocialErr(e.message);
6156
+ setError(e.message);
6063
6157
  } finally {
6064
- setSocialLoad(false);
6158
+ setKingsChatLoading(false);
6065
6159
  }
6066
6160
  }
6067
- async function handleXClick() {
6161
+ async function handleX() {
6068
6162
  if (!onXSignIn) return;
6069
- setSocialLoad(true);
6070
- setSocialErr("");
6163
+ setError("");
6164
+ setXLoading(true);
6071
6165
  try {
6072
6166
  await onXSignIn();
6073
6167
  } catch (e) {
6074
- setSocialErr(e.message);
6075
- setSocialLoad(false);
6076
- }
6077
- }
6078
- async function handleCustomAuthClick() {
6079
- if (!onCustomAuthSignIn) return;
6080
- setSocialLoad(true);
6081
- setSocialErr("");
6082
- try {
6083
- await onCustomAuthSignIn();
6084
- } catch (e) {
6085
- setSocialErr(e.message);
6086
- setSocialLoad(false);
6168
+ setError(e.message);
6169
+ setXLoading(false);
6087
6170
  }
6088
6171
  }
6089
6172
  async function handleEmailStart(e) {
6090
6173
  e.preventDefault();
6091
- if (!onEmailStart) return;
6092
- setSocialLoad(true);
6093
- setSocialErr("");
6174
+ setError("");
6175
+ setEmailLoading(true);
6094
6176
  try {
6095
- await onEmailStart(emailVal);
6096
- setEmailStep("code");
6177
+ await onEmailStart(email.trim());
6178
+ setEmailSent(true);
6097
6179
  } catch (e2) {
6098
- setSocialErr(e2.message);
6180
+ setError(e2.message);
6099
6181
  } finally {
6100
- setSocialLoad(false);
6182
+ setEmailLoading(false);
6101
6183
  }
6102
6184
  }
6103
6185
  async function handleEmailVerify(e) {
6104
6186
  e.preventDefault();
6105
- if (!onEmailVerify) return;
6106
- setSocialLoad(true);
6107
- setSocialErr("");
6187
+ setError("");
6188
+ setEmailLoading(true);
6108
6189
  try {
6109
- await onEmailVerify(emailVal, codeVal);
6190
+ await onEmailVerify(email.trim(), code);
6110
6191
  } catch (e2) {
6111
- setSocialErr(e2.message);
6192
+ setError(e2.message);
6112
6193
  } finally {
6113
- setSocialLoad(false);
6194
+ setEmailLoading(false);
6114
6195
  }
6115
6196
  }
6116
6197
  async function handlePhoneStart(e) {
6117
6198
  e.preventDefault();
6118
6199
  if (!onPhoneStart) return;
6119
- setSocialLoad(true);
6120
- setSocialErr("");
6200
+ setError("");
6201
+ setPhoneLoading(true);
6121
6202
  try {
6122
- await onPhoneStart(phoneVal);
6123
- setPhoneStep("code");
6203
+ await onPhoneStart(phone.trim());
6204
+ setPhoneSent(true);
6124
6205
  } catch (e2) {
6125
- setSocialErr(e2.message);
6206
+ setError(e2.message);
6126
6207
  } finally {
6127
- setSocialLoad(false);
6208
+ setPhoneLoading(false);
6128
6209
  }
6129
6210
  }
6130
6211
  async function handlePhoneVerify(e) {
6131
6212
  e.preventDefault();
6132
6213
  if (!onPhoneVerify) return;
6133
- setSocialLoad(true);
6134
- setSocialErr("");
6214
+ setError("");
6215
+ setPhoneLoading(true);
6135
6216
  try {
6136
- await onPhoneVerify(phoneVal, phoneCode);
6217
+ await onPhoneVerify(phone.trim(), phoneCode);
6137
6218
  } catch (e2) {
6138
- setSocialErr(e2.message);
6219
+ setError(e2.message);
6139
6220
  } finally {
6140
- setSocialLoad(false);
6221
+ setPhoneLoading(false);
6141
6222
  }
6142
6223
  }
6143
- const handleKey = (0, import_react2.useCallback)(
6144
- (e) => {
6145
- if (e.key === "Escape") {
6146
- if (pendingWallet) {
6147
- setPendingWallet(null);
6148
- } else {
6149
- onClose();
6150
- }
6151
- }
6152
- },
6153
- [onClose, pendingWallet]
6154
- );
6155
- (0, import_react2.useEffect)(() => {
6156
- if (!open) return;
6157
- document.addEventListener("keydown", handleKey);
6158
- return () => document.removeEventListener("keydown", handleKey);
6159
- }, [open, handleKey]);
6160
- if (!open) return null;
6161
- const q = search.toLowerCase();
6162
- const networkWallets = provider.wallets.filter((w) => {
6163
- const cs = w.chainSupport;
6164
- if (networks === "evm") return cs.includes("evm");
6165
- if (networks === "solana") return cs.includes("solana");
6166
- if (networks === "tron") return cs.includes("tron");
6167
- if (networks === "bitcoin") return cs.includes("bitcoin");
6168
- return true;
6169
- });
6170
- const baseWallets = filter === "evm" ? networkWallets.filter((w) => w.chainSupport.includes("evm")) : filter === "solana" ? networkWallets.filter((w) => w.chainSupport.includes("solana")) : filter === "tron" ? networkWallets.filter((w) => w.chainSupport.includes("tron")) : filter === "bitcoin" ? networkWallets.filter((w) => w.chainSupport.includes("bitcoin")) : networkWallets;
6171
- const filtered = q ? baseWallets.filter((w) => w.name.toLowerCase().includes(q)) : baseWallets;
6172
- function handleWalletClick(wallet) {
6173
- const cs = wallet.chainSupport;
6174
- const isMulti = cs.length >= 2;
6175
- if (isMulti && networks === "all") {
6176
- setPendingWallet(wallet);
6177
- } else {
6178
- const preference = networks === "evm" ? "evm" : networks === "solana" ? "solana" : networks === "tron" ? "tron" : networks === "bitcoin" ? "bitcoin" : void 0;
6179
- onConnect(wallet, preference);
6180
- onClose();
6224
+ async function handleCustomAuth() {
6225
+ if (!onCustomAuthSignIn) return;
6226
+ setError("");
6227
+ setCustomLoading(true);
6228
+ try {
6229
+ await onCustomAuthSignIn();
6230
+ } catch (e) {
6231
+ setError(e.message);
6232
+ } finally {
6233
+ setCustomLoading(false);
6181
6234
  }
6182
6235
  }
6183
- function handleChainChoice(preference) {
6184
- if (!pendingWallet) return;
6185
- onConnect(pendingWallet, preference);
6186
- onClose();
6236
+ function backToMethods() {
6237
+ setEmailSent(false);
6238
+ setCode("");
6239
+ setPhoneSent(false);
6240
+ setPhoneCode("");
6241
+ setError("");
6187
6242
  }
6188
- const modal = /* @__PURE__ */ import_react2.default.createElement(
6189
- "div",
6190
- {
6191
- role: "dialog",
6192
- "aria-modal": "true",
6193
- "aria-label": "Connect wallet",
6194
- style: {
6195
- position: "fixed",
6196
- inset: 0,
6197
- zIndex: 9999,
6198
- display: "flex",
6199
- alignItems: "center",
6200
- justifyContent: "center",
6201
- padding: "16px",
6202
- // Same fallback chain as SocialWalletModal — without it, this modal
6203
- // drops to the browser default serif whenever the token block hasn't
6204
- // been injected, while the social modal still lands on system-ui.
6205
- fontFamily: "var(--dc-font-sans, system-ui, sans-serif)"
6206
- }
6207
- },
6208
- /* @__PURE__ */ import_react2.default.createElement(
6209
- "div",
6210
- {
6211
- onClick: () => {
6212
- if (pendingWallet) {
6213
- setPendingWallet(null);
6214
- } else {
6215
- onClose();
6216
- }
6217
- },
6218
- style: {
6219
- position: "absolute",
6220
- inset: 0,
6221
- background: "var(--dc-bg-overlay)",
6222
- backdropFilter: "blur(8px)",
6223
- WebkitBackdropFilter: "blur(8px)"
6224
- }
6225
- }
6226
- ),
6227
- /* @__PURE__ */ import_react2.default.createElement(
6228
- "div",
6243
+ const errorLine = error ? /* @__PURE__ */ import_react2.default.createElement("p", { className: "dcm-error", role: "alert" }, error) : null;
6244
+ if (passkeyFirst) {
6245
+ return /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-body" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-badge" }, /* @__PURE__ */ import_react2.default.createElement(KeyIcon, { size: 22 })), /* @__PURE__ */ import_react2.default.createElement("h2", { className: "dcm-title" }, "Welcome back"), /* @__PURE__ */ import_react2.default.createElement("p", { className: "dcm-sub" }, passkeyAddress ? /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, "Unlock ", /* @__PURE__ */ import_react2.default.createElement("b", null, shortAddress(passkeyAddress)), " with your passkey.") : "Unlock your wallet with your passkey."), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-primary", onClick: handlePasskey, disabled: passkeyLoading }, passkeyLoading ? "Waiting for passkey\u2026" : "Continue with passkey"), errorLine, /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-link", onClick: () => {
6246
+ setError("");
6247
+ setShowOtherMethods(true);
6248
+ } }, "Use another sign-in method"), /* @__PURE__ */ import_react2.default.createElement(ProtectedBy, null));
6249
+ }
6250
+ if (emailSent || phoneSent) {
6251
+ const isEmail = emailSent;
6252
+ const value = isEmail ? code : phoneCode;
6253
+ const setValue = isEmail ? setCode : setPhoneCode;
6254
+ const loading = isEmail ? emailLoading : phoneLoading;
6255
+ return /* @__PURE__ */ import_react2.default.createElement("form", { className: "dcm-body", onSubmit: isEmail ? handleEmailVerify : handlePhoneVerify }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-badge" }, isEmail ? /* @__PURE__ */ import_react2.default.createElement(MailIcon, { size: 22 }) : /* @__PURE__ */ import_react2.default.createElement(PhoneIcon, { size: 22 })), /* @__PURE__ */ import_react2.default.createElement("h2", { className: "dcm-title" }, "Enter your code"), /* @__PURE__ */ import_react2.default.createElement("p", { className: "dcm-sub" }, "We sent a 6-digit code to ", /* @__PURE__ */ import_react2.default.createElement("b", null, isEmail ? email.trim() : phone.trim())), /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-form" }, /* @__PURE__ */ import_react2.default.createElement(
6256
+ "input",
6229
6257
  {
6230
- style: {
6231
- position: "relative",
6232
- background: "var(--dc-bg)",
6233
- border: "1px solid var(--dc-border)",
6234
- borderRadius: 20,
6235
- width: "100%",
6236
- maxWidth: 400,
6237
- maxHeight: "85vh",
6238
- display: "flex",
6239
- flexDirection: "column",
6240
- boxShadow: "0 24px 64px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04)",
6241
- overflow: "hidden"
6242
- }
6243
- },
6244
- /* @__PURE__ */ import_react2.default.createElement(
6245
- "div",
6246
- {
6247
- style: {
6248
- height: 2,
6249
- background: "linear-gradient(90deg, transparent, var(--dc-accent) 30%, var(--dc-accent) 70%, transparent)"
6250
- }
6251
- }
6252
- ),
6253
- pendingWallet ? (
6254
- /* ── Chain picker step ───────────────────────────────────────── */
6255
- /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { style: { padding: "18px 20px 16px", display: "flex", alignItems: "center", gap: 10 } }, /* @__PURE__ */ import_react2.default.createElement(
6256
- "button",
6257
- {
6258
- onClick: () => setPendingWallet(null),
6259
- "aria-label": "Back",
6260
- style: {
6261
- background: "var(--dc-surface)",
6262
- border: "1px solid var(--dc-border)",
6263
- borderRadius: 8,
6264
- width: 28,
6265
- height: 28,
6266
- display: "flex",
6267
- alignItems: "center",
6268
- justifyContent: "center",
6269
- cursor: "pointer",
6270
- color: "var(--dc-text-muted)",
6271
- flexShrink: 0,
6272
- fontFamily: "inherit",
6273
- padding: 0
6274
- }
6275
- },
6276
- /* @__PURE__ */ import_react2.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" }, /* @__PURE__ */ import_react2.default.createElement("path", { d: "M7.5 2L3 6l4.5 4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }))
6277
- ), /* @__PURE__ */ import_react2.default.createElement("h2", { style: { margin: 0, fontSize: 16, fontWeight: 800, color: "var(--dc-text)", letterSpacing: "-0.02em" } }, "Choose networks"), /* @__PURE__ */ import_react2.default.createElement(
6278
- "button",
6279
- {
6280
- onClick: onClose,
6281
- "aria-label": "Close",
6282
- style: {
6283
- marginLeft: "auto",
6284
- background: "var(--dc-surface)",
6285
- border: "1px solid var(--dc-border)",
6286
- borderRadius: 8,
6287
- width: 28,
6288
- height: 28,
6289
- display: "flex",
6290
- alignItems: "center",
6291
- justifyContent: "center",
6292
- cursor: "pointer",
6293
- color: "var(--dc-text-muted)",
6294
- flexShrink: 0,
6295
- fontFamily: "inherit",
6296
- padding: 0
6297
- }
6298
- },
6299
- /* @__PURE__ */ import_react2.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" }, /* @__PURE__ */ import_react2.default.createElement("path", { d: "M1.5 1.5L10.5 10.5M10.5 1.5L1.5 10.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }))
6300
- )), /* @__PURE__ */ import_react2.default.createElement(
6301
- "div",
6302
- {
6303
- style: {
6304
- margin: "0 20px 16px",
6305
- padding: "12px 14px",
6306
- background: "var(--dc-surface)",
6307
- border: "1px solid var(--dc-border)",
6308
- borderRadius: 12,
6309
- display: "flex",
6310
- alignItems: "center",
6311
- gap: 12
6312
- }
6313
- },
6314
- /* @__PURE__ */ import_react2.default.createElement(WalletIcon, { src: pendingWallet.icon || void 0, name: pendingWallet.name, size: 36 }),
6315
- /* @__PURE__ */ import_react2.default.createElement("div", null, /* @__PURE__ */ import_react2.default.createElement("div", { style: { fontSize: 14, fontWeight: 700, color: "var(--dc-text)" } }, pendingWallet.name), /* @__PURE__ */ import_react2.default.createElement("div", { style: { fontSize: 11, color: "var(--dc-text-muted)", marginTop: 2 } }, "Multi-chain wallet detected"))
6316
- ), /* @__PURE__ */ import_react2.default.createElement("div", { style: { padding: "0 12px 20px", display: "flex", flexDirection: "column", gap: 8 } }, pendingWallet.chainSupport.includes("evm") && /* @__PURE__ */ import_react2.default.createElement(
6317
- ChainOption,
6318
- {
6319
- label: "EVM networks",
6320
- description: "Connect your Ethereum-compatible address only",
6321
- badges: /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: ["evm"], size: 18 }),
6322
- onClick: () => handleChainChoice("evm")
6323
- }
6324
- ), pendingWallet.chainSupport.includes("solana") && /* @__PURE__ */ import_react2.default.createElement(
6325
- ChainOption,
6326
- {
6327
- label: "Solana network",
6328
- description: "Connect your Solana address only",
6329
- badges: /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: ["solana"], size: 18 }),
6330
- onClick: () => handleChainChoice("solana")
6331
- }
6332
- ), pendingWallet.chainSupport.includes("tron") && /* @__PURE__ */ import_react2.default.createElement(
6333
- ChainOption,
6334
- {
6335
- label: "Tron network",
6336
- description: "Connect your Tron address only",
6337
- badges: /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: ["tron"], size: 18 }),
6338
- onClick: () => handleChainChoice("tron")
6339
- }
6340
- ), pendingWallet.chainSupport.includes("bitcoin") && /* @__PURE__ */ import_react2.default.createElement(
6341
- ChainOption,
6342
- {
6343
- label: "Bitcoin network",
6344
- description: "Connect your Bitcoin address only",
6345
- badges: /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: ["bitcoin"], size: 18 }),
6346
- onClick: () => handleChainChoice("bitcoin")
6347
- }
6348
- ), /* @__PURE__ */ import_react2.default.createElement(
6349
- ChainOption,
6350
- {
6351
- label: "All networks",
6352
- description: "Connect all supported addresses together",
6353
- badges: /* @__PURE__ */ import_react2.default.createElement(ChainIconStack, { support: pendingWallet.chainSupport, size: 18 }),
6354
- onClick: () => handleChainChoice(void 0)
6355
- }
6356
- )))
6357
- ) : (
6358
- /* ── Wallet list / Social sign-in ────────────────────────────── */
6359
- /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { style: { padding: "18px 20px 0" } }, /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between", marginBottom: 14 } }, /* @__PURE__ */ import_react2.default.createElement("div", null, /* @__PURE__ */ import_react2.default.createElement("h2", { style: { margin: 0, fontSize: 17, fontWeight: 800, color: "var(--dc-text)", letterSpacing: "-0.02em", lineHeight: 1.2 } }, view === "social" ? "Sign in" : "Connect wallet"), view === "wallets" && networkWallets.length > 0 && /* @__PURE__ */ import_react2.default.createElement("p", { style: { margin: "3px 0 0", fontSize: 12, color: "var(--dc-text-muted)" } }, networkWallets.length, " wallet", networkWallets.length !== 1 ? "s" : "", " detected")), /* @__PURE__ */ import_react2.default.createElement(
6360
- "button",
6361
- {
6362
- onClick: onClose,
6363
- "aria-label": "Close",
6364
- style: {
6365
- background: "var(--dc-surface)",
6366
- border: "1px solid var(--dc-border)",
6367
- cursor: "pointer",
6368
- padding: 0,
6369
- width: 28,
6370
- height: 28,
6371
- borderRadius: 8,
6372
- display: "flex",
6373
- alignItems: "center",
6374
- justifyContent: "center",
6375
- color: "var(--dc-text-muted)",
6376
- flexShrink: 0,
6377
- transition: "background 0.12s, color 0.12s",
6378
- fontFamily: "inherit"
6379
- },
6380
- onMouseEnter: (e) => {
6381
- e.currentTarget.style.background = "var(--dc-surface-hover)";
6382
- e.currentTarget.style.color = "var(--dc-text)";
6383
- },
6384
- onMouseLeave: (e) => {
6385
- e.currentTarget.style.background = "var(--dc-surface)";
6386
- e.currentTarget.style.color = "var(--dc-text-muted)";
6387
- }
6388
- },
6389
- /* @__PURE__ */ import_react2.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" }, /* @__PURE__ */ import_react2.default.createElement("path", { d: "M1.5 1.5L10.5 10.5M10.5 1.5L1.5 10.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }))
6390
- )), showWallets && showSocial && /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", gap: 4, marginBottom: 14, background: "var(--dc-surface)", borderRadius: 10, padding: 3 } }, ["social", "wallets"].map((v) => /* @__PURE__ */ import_react2.default.createElement(
6391
- "button",
6392
- {
6393
- key: v,
6394
- onClick: () => setView(v),
6395
- style: {
6396
- flex: 1,
6397
- padding: "7px 0",
6398
- borderRadius: 8,
6399
- border: "none",
6400
- background: view === v ? "var(--dc-bg)" : "transparent",
6401
- color: view === v ? "var(--dc-text)" : "var(--dc-text-muted)",
6402
- fontSize: 13,
6403
- fontWeight: view === v ? 700 : 500,
6404
- cursor: "pointer",
6405
- fontFamily: "inherit",
6406
- boxShadow: view === v ? "0 1px 4px rgba(0,0,0,0.2)" : "none",
6407
- transition: "all 0.15s"
6408
- }
6409
- },
6410
- v === "wallets" ? "Wallet" : "Sign in"
6411
- ))), view === "wallets" && networks === "all" && /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", gap: 4, marginBottom: 10 } }, /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "All", active: filter === "all", onClick: () => setFilter("all") }), /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "EVM", active: filter === "evm", onClick: () => setFilter("evm") }), /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "Solana", active: filter === "solana", onClick: () => setFilter("solana") }), provider.tronWallets && provider.tronWallets.length > 0 && /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "Tron", active: filter === "tron", onClick: () => setFilter("tron") }), provider.bitcoinWallets && provider.bitcoinWallets.length > 0 && /* @__PURE__ */ import_react2.default.createElement(FilterTab, { label: "Bitcoin", active: filter === "bitcoin", onClick: () => setFilter("bitcoin") })), view === "wallets" && /* @__PURE__ */ import_react2.default.createElement("div", { style: { position: "relative", marginBottom: 10 } }, /* @__PURE__ */ import_react2.default.createElement(
6412
- "svg",
6413
- {
6414
- width: "14",
6415
- height: "14",
6416
- viewBox: "0 0 14 14",
6417
- fill: "none",
6418
- style: { position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "var(--dc-text-muted)", pointerEvents: "none" }
6419
- },
6420
- /* @__PURE__ */ import_react2.default.createElement("circle", { cx: "6", cy: "6", r: "4", stroke: "currentColor", strokeWidth: "1.4" }),
6421
- /* @__PURE__ */ import_react2.default.createElement("path", { d: "M9.5 9.5L12 12", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" })
6422
- ), /* @__PURE__ */ import_react2.default.createElement(
6423
- "input",
6424
- {
6425
- type: "text",
6426
- placeholder: "Search wallets\u2026",
6427
- value: search,
6428
- onChange: (e) => setSearch(e.target.value),
6429
- style: {
6430
- width: "100%",
6431
- background: "var(--dc-surface)",
6432
- border: "1px solid var(--dc-border)",
6433
- borderRadius: 10,
6434
- color: "var(--dc-text)",
6435
- fontSize: 13,
6436
- padding: "8px 12px 8px 32px",
6437
- outline: "none",
6438
- fontFamily: "var(--dc-font-sans, system-ui, sans-serif)",
6439
- transition: "border-color 0.15s",
6440
- boxSizing: "border-box"
6441
- },
6442
- onFocus: (e) => {
6443
- e.currentTarget.style.borderColor = "var(--dc-border-accent)";
6444
- },
6445
- onBlur: (e) => {
6446
- e.currentTarget.style.borderColor = "var(--dc-border)";
6447
- }
6448
- }
6449
- ))), view === "social" && /* @__PURE__ */ import_react2.default.createElement("div", { style: { padding: "4px 20px 24px", display: "flex", flexDirection: "column", gap: 10 } }, socialErr && /* @__PURE__ */ import_react2.default.createElement("div", { style: { background: "rgba(204,51,0,0.1)", border: "1px solid var(--dc-danger)", borderRadius: 8, padding: "9px 12px", fontSize: 12, color: "var(--dc-danger)" } }, socialErr), passkeyFirst && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(
6450
- "button",
6451
- {
6452
- onClick: handlePasskeyClick,
6453
- disabled: socialLoad,
6454
- style: {
6455
- display: "flex",
6456
- alignItems: "center",
6457
- justifyContent: "center",
6458
- gap: 10,
6459
- width: "100%",
6460
- padding: "13px 16px",
6461
- background: "var(--dc-accent)",
6462
- border: "none",
6463
- borderRadius: 10,
6464
- cursor: socialLoad ? "not-allowed" : "pointer",
6465
- color: "var(--dc-accent-text)",
6466
- fontSize: 14,
6467
- fontWeight: 700,
6468
- fontFamily: "inherit",
6469
- opacity: socialLoad ? 0.6 : 1
6470
- }
6471
- },
6472
- /* @__PURE__ */ import_react2.default.createElement("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }, /* @__PURE__ */ import_react2.default.createElement("circle", { cx: "12", cy: "8", r: "4" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M6 21v-1a4 4 0 0 1 4-4h1" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M17 15v6M14.5 18h5" })),
6473
- socialLoad ? "Verifying\u2026" : "Continue with passkey"
6474
- ), passkeyAddress && /* @__PURE__ */ import_react2.default.createElement("div", { style: { textAlign: "center", fontSize: 12, color: "var(--dc-text-muted)" } }, "Resuming ", passkeyAddress.slice(0, 6), "\u2026", passkeyAddress.slice(-4)), /* @__PURE__ */ import_react2.default.createElement(
6475
- "button",
6476
- {
6477
- onClick: () => {
6478
- setShowOtherMethods(true);
6479
- setSocialErr("");
6480
- },
6481
- disabled: socialLoad,
6482
- style: {
6483
- background: "none",
6484
- border: "none",
6485
- padding: "6px 0",
6486
- color: "var(--dc-text-muted)",
6487
- fontSize: 12.5,
6488
- cursor: socialLoad ? "not-allowed" : "pointer",
6489
- fontFamily: "inherit",
6490
- textDecoration: "underline",
6491
- textUnderlineOffset: 3
6492
- }
6493
- },
6494
- "Use a different account"
6495
- )), !passkeyFirst && socialAuthMethods.includes("google") && /* @__PURE__ */ import_react2.default.createElement(
6496
- "button",
6497
- {
6498
- onClick: handleGoogleClick,
6499
- disabled: socialLoad,
6500
- style: {
6501
- display: "flex",
6502
- alignItems: "center",
6503
- justifyContent: "center",
6504
- gap: 10,
6505
- width: "100%",
6506
- padding: "11px 16px",
6507
- background: "var(--dc-surface)",
6508
- border: "1px solid var(--dc-border)",
6509
- borderRadius: 10,
6510
- cursor: socialLoad ? "not-allowed" : "pointer",
6511
- fontSize: 14,
6512
- fontWeight: 600,
6513
- color: "var(--dc-text)",
6514
- fontFamily: "inherit",
6515
- transition: "border-color 0.12s, background 0.12s",
6516
- opacity: socialLoad ? 0.6 : 1
6517
- },
6518
- onMouseEnter: (e) => {
6519
- if (!socialLoad) e.currentTarget.style.borderColor = "var(--dc-border-accent)";
6520
- },
6521
- onMouseLeave: (e) => {
6522
- e.currentTarget.style.borderColor = "var(--dc-border)";
6523
- }
6524
- },
6525
- /* @__PURE__ */ import_react2.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none" }, /* @__PURE__ */ import_react2.default.createElement("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.875 2.684-6.615z", fill: "#4285F4" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M9 18c2.43 0 4.467-.806 5.956-2.18l-2.908-2.259c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332A8.997 8.997 0 0 0 9 18z", fill: "#34A853" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M3.964 10.71A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.957A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.957 4.042l3.007-2.332z", fill: "#FBBC05" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0A8.997 8.997 0 0 0 .957 4.958L3.964 6.29C4.672 4.163 6.656 3.58 9 3.58z", fill: "#EA4335" })),
6526
- socialLoad ? "Redirecting\u2026" : "Continue with Google"
6527
- ), !passkeyFirst && socialAuthMethods.includes("kingschat") && onKingsChatSignIn && /* @__PURE__ */ import_react2.default.createElement(
6528
- "button",
6529
- {
6530
- onClick: handleKingsChatClick,
6531
- disabled: socialLoad,
6532
- style: {
6533
- display: "flex",
6534
- alignItems: "center",
6535
- justifyContent: "center",
6536
- gap: 10,
6537
- width: "100%",
6538
- padding: "11px 16px",
6539
- background: "var(--dc-surface)",
6540
- border: "1px solid var(--dc-border)",
6541
- borderRadius: 10,
6542
- cursor: socialLoad ? "not-allowed" : "pointer",
6543
- fontSize: 14,
6544
- fontWeight: 600,
6545
- color: "var(--dc-text)",
6546
- fontFamily: "inherit",
6547
- transition: "border-color 0.12s, background 0.12s",
6548
- opacity: socialLoad ? 0.6 : 1
6549
- },
6550
- onMouseEnter: (e) => {
6551
- if (!socialLoad) e.currentTarget.style.borderColor = "var(--dc-border-accent)";
6552
- },
6553
- onMouseLeave: (e) => {
6554
- e.currentTarget.style.borderColor = "var(--dc-border)";
6555
- }
6556
- },
6557
- /* @__PURE__ */ import_react2.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", "aria-hidden": "true" }, /* @__PURE__ */ import_react2.default.createElement("circle", { cx: "9", cy: "9", r: "9", fill: "var(--dc-accent)" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M5.5 4.5h1.9v3.6l3.1-3.6h2.3l-3.3 3.8 3.5 5.2h-2.3l-2.5-3.8-.8.9v2.9H5.5V4.5z", fill: "var(--dc-accent-text)" })),
6558
- socialLoad ? "Waiting for KingsChat\u2026" : "Continue with KingsChat"
6559
- ), !passkeyFirst && socialAuthMethods.includes("x") && onXSignIn && /* @__PURE__ */ import_react2.default.createElement(
6560
- "button",
6561
- {
6562
- onClick: handleXClick,
6563
- disabled: socialLoad,
6564
- style: {
6565
- display: "flex",
6566
- alignItems: "center",
6567
- justifyContent: "center",
6568
- gap: 10,
6569
- width: "100%",
6570
- padding: "11px 16px",
6571
- background: "var(--dc-surface)",
6572
- border: "1px solid var(--dc-border)",
6573
- borderRadius: 10,
6574
- cursor: socialLoad ? "not-allowed" : "pointer",
6575
- fontSize: 14,
6576
- fontWeight: 600,
6577
- color: "var(--dc-text)",
6578
- fontFamily: "inherit",
6579
- transition: "border-color 0.12s, background 0.12s",
6580
- opacity: socialLoad ? 0.6 : 1
6581
- },
6582
- onMouseEnter: (e) => {
6583
- if (!socialLoad) e.currentTarget.style.borderColor = "var(--dc-border-accent)";
6584
- },
6585
- onMouseLeave: (e) => {
6586
- e.currentTarget.style.borderColor = "var(--dc-border)";
6587
- }
6588
- },
6589
- /* @__PURE__ */ import_react2.default.createElement(XLogo, { size: 16 }),
6590
- socialLoad ? "Redirecting\u2026" : "Continue with X"
6591
- ), !passkeyFirst && socialAuthMethods.includes("google") && socialAuthMethods.includes("email") && /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10 } }, /* @__PURE__ */ import_react2.default.createElement("div", { style: { flex: 1, height: 1, background: "var(--dc-border)" } }), /* @__PURE__ */ import_react2.default.createElement("span", { style: { fontSize: 11, color: "var(--dc-text-muted)", whiteSpace: "nowrap" } }, "or continue with email"), /* @__PURE__ */ import_react2.default.createElement("div", { style: { flex: 1, height: 1, background: "var(--dc-border)" } })), !passkeyFirst && socialAuthMethods.includes("email") && (emailStep === "input" ? /* @__PURE__ */ import_react2.default.createElement("form", { onSubmit: handleEmailStart, style: { display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ import_react2.default.createElement(
6592
- "input",
6593
- {
6594
- type: "email",
6595
- placeholder: "your@email.com",
6596
- value: emailVal,
6597
- onChange: (e) => setEmailVal(e.target.value),
6598
- required: true,
6599
- style: {
6600
- width: "100%",
6601
- padding: "10px 12px",
6602
- background: "var(--dc-surface)",
6603
- border: "1px solid var(--dc-border)",
6604
- borderRadius: 10,
6605
- color: "var(--dc-text)",
6606
- fontSize: 13,
6607
- fontFamily: "inherit",
6608
- outline: "none",
6609
- boxSizing: "border-box"
6610
- },
6611
- onFocus: (e) => {
6612
- e.currentTarget.style.borderColor = "var(--dc-border-accent)";
6613
- },
6614
- onBlur: (e) => {
6615
- e.currentTarget.style.borderColor = "var(--dc-border)";
6616
- }
6617
- }
6618
- ), /* @__PURE__ */ import_react2.default.createElement(
6619
- "button",
6620
- {
6621
- type: "submit",
6622
- disabled: socialLoad || !emailVal,
6623
- style: {
6624
- width: "100%",
6625
- padding: "10px 16px",
6626
- background: "var(--dc-accent)",
6627
- color: "var(--dc-accent-text)",
6628
- border: "none",
6629
- borderRadius: 10,
6630
- fontSize: 14,
6631
- fontWeight: 700,
6632
- cursor: socialLoad ? "not-allowed" : "pointer",
6633
- fontFamily: "inherit",
6634
- opacity: socialLoad || !emailVal ? 0.6 : 1
6635
- }
6636
- },
6637
- socialLoad ? "Sending\u2026" : "Send code"
6638
- )) : /* @__PURE__ */ import_react2.default.createElement("form", { onSubmit: handleEmailVerify, style: { display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ import_react2.default.createElement("p", { style: { margin: 0, fontSize: 12, color: "var(--dc-text-muted)", textAlign: "center" } }, "Code sent to ", /* @__PURE__ */ import_react2.default.createElement("strong", { style: { color: "var(--dc-text)" } }, emailVal)), /* @__PURE__ */ import_react2.default.createElement(
6639
- "input",
6640
- {
6641
- type: "text",
6642
- placeholder: "6-digit code",
6643
- value: codeVal,
6644
- onChange: (e) => setCodeVal(e.target.value.replace(/\D/g, "").slice(0, 6)),
6645
- autoFocus: true,
6646
- required: true,
6647
- style: {
6648
- width: "100%",
6649
- padding: "10px 12px",
6650
- background: "var(--dc-surface)",
6651
- border: "1px solid var(--dc-border)",
6652
- borderRadius: 10,
6653
- color: "var(--dc-text)",
6654
- fontSize: 20,
6655
- fontFamily: "monospace",
6656
- letterSpacing: 8,
6657
- textAlign: "center",
6658
- outline: "none",
6659
- boxSizing: "border-box"
6660
- },
6661
- onFocus: (e) => {
6662
- e.currentTarget.style.borderColor = "var(--dc-border-accent)";
6663
- },
6664
- onBlur: (e) => {
6665
- e.currentTarget.style.borderColor = "var(--dc-border)";
6666
- }
6667
- }
6668
- ), /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", gap: 8 } }, /* @__PURE__ */ import_react2.default.createElement(
6669
- "button",
6670
- {
6671
- type: "button",
6672
- onClick: () => {
6673
- setEmailStep("input");
6674
- setCodeVal("");
6675
- setSocialErr("");
6676
- },
6677
- style: {
6678
- flex: 1,
6679
- padding: "9px 0",
6680
- background: "transparent",
6681
- border: "1px solid var(--dc-border)",
6682
- borderRadius: 10,
6683
- color: "var(--dc-text-muted)",
6684
- fontSize: 13,
6685
- cursor: "pointer",
6686
- fontFamily: "inherit"
6687
- }
6688
- },
6689
- "Back"
6690
- ), /* @__PURE__ */ import_react2.default.createElement(
6691
- "button",
6692
- {
6693
- type: "submit",
6694
- disabled: socialLoad || codeVal.length < 6,
6695
- style: {
6696
- flex: 2,
6697
- padding: "9px 0",
6698
- background: "var(--dc-accent)",
6699
- color: "var(--dc-accent-text)",
6700
- border: "none",
6701
- borderRadius: 10,
6702
- fontSize: 13,
6703
- fontWeight: 700,
6704
- cursor: socialLoad || codeVal.length < 6 ? "not-allowed" : "pointer",
6705
- fontFamily: "inherit",
6706
- opacity: socialLoad || codeVal.length < 6 ? 0.6 : 1
6707
- }
6708
- },
6709
- socialLoad ? "Verifying\u2026" : "Verify"
6710
- )))), !passkeyFirst && socialAuthMethods.includes("phone") && onPhoneStart && onPhoneVerify && (phoneStep === "input" ? /* @__PURE__ */ import_react2.default.createElement("form", { onSubmit: handlePhoneStart, style: { display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ import_react2.default.createElement(
6711
- "input",
6712
- {
6713
- type: "tel",
6714
- placeholder: "+234 801 234 5678",
6715
- value: phoneVal,
6716
- onChange: (e) => setPhoneVal(e.target.value),
6717
- required: true,
6718
- style: {
6719
- width: "100%",
6720
- padding: "10px 12px",
6721
- background: "var(--dc-surface)",
6722
- border: "1px solid var(--dc-border)",
6723
- borderRadius: 10,
6724
- color: "var(--dc-text)",
6725
- fontSize: 13,
6726
- fontFamily: "inherit",
6727
- outline: "none",
6728
- boxSizing: "border-box"
6729
- },
6730
- onFocus: (e) => {
6731
- e.currentTarget.style.borderColor = "var(--dc-border-accent)";
6732
- },
6733
- onBlur: (e) => {
6734
- e.currentTarget.style.borderColor = "var(--dc-border)";
6735
- }
6736
- }
6737
- ), /* @__PURE__ */ import_react2.default.createElement(
6738
- "button",
6739
- {
6740
- type: "submit",
6741
- disabled: socialLoad || !phoneVal,
6742
- style: {
6743
- width: "100%",
6744
- padding: "10px 16px",
6745
- background: "var(--dc-accent)",
6746
- color: "var(--dc-accent-text)",
6747
- border: "none",
6748
- borderRadius: 10,
6749
- fontSize: 14,
6750
- fontWeight: 700,
6751
- cursor: socialLoad ? "not-allowed" : "pointer",
6752
- fontFamily: "inherit",
6753
- opacity: socialLoad || !phoneVal ? 0.6 : 1
6754
- }
6755
- },
6756
- socialLoad ? "Sending\u2026" : "Send code"
6757
- )) : /* @__PURE__ */ import_react2.default.createElement("form", { onSubmit: handlePhoneVerify, style: { display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ import_react2.default.createElement("p", { style: { margin: 0, fontSize: 12, color: "var(--dc-text-muted)", textAlign: "center" } }, "Code sent to ", /* @__PURE__ */ import_react2.default.createElement("strong", { style: { color: "var(--dc-text)" } }, phoneVal)), /* @__PURE__ */ import_react2.default.createElement(
6758
- "input",
6759
- {
6760
- type: "text",
6761
- inputMode: "numeric",
6762
- placeholder: "6-digit code",
6763
- value: phoneCode,
6764
- onChange: (e) => setPhoneCode(e.target.value.replace(/\D/g, "").slice(0, 6)),
6765
- autoFocus: true,
6766
- required: true,
6767
- style: {
6768
- width: "100%",
6769
- padding: "10px 12px",
6770
- background: "var(--dc-surface)",
6771
- border: "1px solid var(--dc-border)",
6772
- borderRadius: 10,
6773
- color: "var(--dc-text)",
6774
- fontSize: 20,
6775
- fontFamily: "monospace",
6776
- letterSpacing: 8,
6777
- textAlign: "center",
6778
- outline: "none",
6779
- boxSizing: "border-box"
6780
- },
6781
- onFocus: (e) => {
6782
- e.currentTarget.style.borderColor = "var(--dc-border-accent)";
6783
- },
6784
- onBlur: (e) => {
6785
- e.currentTarget.style.borderColor = "var(--dc-border)";
6786
- }
6787
- }
6788
- ), /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", gap: 8 } }, /* @__PURE__ */ import_react2.default.createElement(
6789
- "button",
6790
- {
6791
- type: "button",
6792
- onClick: () => {
6793
- setPhoneStep("input");
6794
- setPhoneCode("");
6795
- setSocialErr("");
6796
- },
6797
- style: {
6798
- flex: 1,
6799
- padding: "9px 0",
6800
- background: "transparent",
6801
- border: "1px solid var(--dc-border)",
6802
- borderRadius: 10,
6803
- color: "var(--dc-text-muted)",
6804
- fontSize: 13,
6805
- cursor: "pointer",
6806
- fontFamily: "inherit"
6807
- }
6808
- },
6809
- "Back"
6810
- ), /* @__PURE__ */ import_react2.default.createElement(
6811
- "button",
6812
- {
6813
- type: "submit",
6814
- disabled: socialLoad || phoneCode.length < 6,
6815
- style: {
6816
- flex: 2,
6817
- padding: "9px 0",
6818
- background: "var(--dc-accent)",
6819
- color: "var(--dc-accent-text)",
6820
- border: "none",
6821
- borderRadius: 10,
6822
- fontSize: 13,
6823
- fontWeight: 700,
6824
- cursor: socialLoad || phoneCode.length < 6 ? "not-allowed" : "pointer",
6825
- fontFamily: "inherit",
6826
- opacity: socialLoad || phoneCode.length < 6 ? 0.6 : 1
6827
- }
6828
- },
6829
- socialLoad ? "Verifying\u2026" : "Verify"
6830
- )))), !passkeyFirst && customAuthLabel && onCustomAuthSignIn && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, (socialAuthMethods.includes("google") || socialAuthMethods.includes("email")) && /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 10 } }, /* @__PURE__ */ import_react2.default.createElement("div", { style: { flex: 1, height: 1, background: "var(--dc-border)" } }), /* @__PURE__ */ import_react2.default.createElement("span", { style: { fontSize: 11, color: "var(--dc-text-muted)", whiteSpace: "nowrap" } }, "or"), /* @__PURE__ */ import_react2.default.createElement("div", { style: { flex: 1, height: 1, background: "var(--dc-border)" } })), /* @__PURE__ */ import_react2.default.createElement(
6831
- "button",
6832
- {
6833
- onClick: handleCustomAuthClick,
6834
- disabled: socialLoad,
6835
- style: {
6836
- display: "flex",
6837
- alignItems: "center",
6838
- justifyContent: "center",
6839
- gap: 10,
6840
- width: "100%",
6841
- padding: "11px 16px",
6842
- background: "var(--dc-surface)",
6843
- border: "1px solid var(--dc-border)",
6844
- borderRadius: 10,
6845
- cursor: socialLoad ? "not-allowed" : "pointer",
6846
- fontSize: 14,
6847
- fontWeight: 600,
6848
- color: "var(--dc-text)",
6849
- fontFamily: "inherit",
6850
- transition: "border-color 0.12s, background 0.12s",
6851
- opacity: socialLoad ? 0.6 : 1
6852
- },
6853
- onMouseEnter: (e) => {
6854
- if (!socialLoad) e.currentTarget.style.borderColor = "var(--dc-border-accent)";
6855
- },
6856
- onMouseLeave: (e) => {
6857
- e.currentTarget.style.borderColor = "var(--dc-border)";
6858
- }
6859
- },
6860
- socialLoad ? "Connecting\u2026" : customAuthLabel
6861
- ))), view === "wallets" && /* @__PURE__ */ import_react2.default.createElement("div", { style: { overflowY: "auto", flex: 1, padding: "0 12px 20px" } }, filtered.length > 0 ? /* @__PURE__ */ import_react2.default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 2 } }, filtered.map((w) => /* @__PURE__ */ import_react2.default.createElement(WalletRow, { key: w.id, wallet: w, onClick: () => handleWalletClick(w) }))) : /* @__PURE__ */ import_react2.default.createElement("div", { style: { textAlign: "center", padding: "32px 16px", color: "var(--dc-text-muted)", fontSize: 13 } }, q ? `No wallets matching "${q}"` : "No wallets detected")), view === "wallets" && /* @__PURE__ */ import_react2.default.createElement("div", { style: { padding: "10px 20px 14px", borderTop: "1px solid var(--dc-border)", textAlign: "center", fontSize: 11, color: "var(--dc-text-muted)" } }, "Don't see your wallet? Make sure it's installed and unlocked"))
6862
- )
6863
- )
6864
- );
6865
- return (0, import_react_dom.createPortal)(modal, document.body);
6866
- }
6867
-
6868
- // src/ui/SocialWalletModal.tsx
6869
- var import_react3 = __toESM(require("react"), 1);
6870
- var import_react_dom2 = require("react-dom");
6871
- function injectTokens2(theme) {
6872
- const resolved = theme === "auto" ? window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : theme;
6873
- let el = document.getElementById("decane-tokens");
6874
- if (!el) {
6875
- el = document.createElement("style");
6876
- el.id = "decane-tokens";
6877
- document.head.appendChild(el);
6878
- }
6879
- el.textContent = `:root { ${CSS_VARS[resolved]} }`;
6880
- }
6881
- function countdown(expiresAt) {
6882
- const secs = Math.max(0, Math.round((expiresAt - Date.now()) / 1e3));
6883
- return `${Math.floor(secs / 60)}m ${String(secs % 60).padStart(2, "0")}s`;
6884
- }
6885
- function downloadJson(data, filename) {
6886
- const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
6887
- const url = URL.createObjectURL(blob);
6888
- const a = document.createElement("a");
6889
- a.href = url;
6890
- a.download = filename;
6891
- a.click();
6892
- URL.revokeObjectURL(url);
6893
- }
6894
- function CopyButton({ value }) {
6895
- const [copied, setCopied] = (0, import_react3.useState)(false);
6896
- async function copy() {
6897
- await navigator.clipboard.writeText(value).catch(() => {
6898
- });
6899
- setCopied(true);
6900
- setTimeout(() => setCopied(false), 1500);
6901
- }
6902
- return /* @__PURE__ */ import_react3.default.createElement(
6903
- "button",
6904
- {
6905
- onClick: copy,
6906
- style: {
6907
- background: "none",
6908
- border: "none",
6909
- cursor: "pointer",
6910
- color: copied ? "var(--dc-accent)" : "var(--dc-text-muted)",
6911
- fontSize: 11,
6912
- fontFamily: "inherit",
6913
- padding: "2px 6px",
6914
- borderRadius: 5,
6915
- transition: "color 0.15s"
6916
- }
6917
- },
6918
- copied ? "\u2713" : "copy"
6919
- );
6920
- }
6921
- function useBalance(kind, address, chain, rpcUrls) {
6922
- const [state, setState] = (0, import_react3.useState)({ loading: false, value: null, symbol: kind === "evm" ? "ETH" : "SOL" });
6923
- (0, import_react3.useEffect)(() => {
6924
- if (!address || !chain) return;
6925
- let cancelled = false;
6926
- setState((s) => ({ ...s, loading: true }));
6927
- fetchBalance({ kind, address, chain, rpcUrls }).then((b) => {
6928
- if (!cancelled) setState({ loading: false, value: b.formatted, symbol: b.symbol });
6929
- }).catch(() => {
6930
- if (!cancelled) setState({ loading: false, value: null, symbol: kind === "evm" ? "ETH" : "SOL" });
6931
- });
6932
- return () => {
6933
- cancelled = true;
6934
- };
6935
- }, [kind, address, chain, rpcUrls]);
6936
- return state;
6937
- }
6938
- function AddressRow({
6939
- label,
6940
- address,
6941
- kind,
6942
- chain,
6943
- rpcUrls
6944
- }) {
6945
- const balance = useBalance(kind, address, chain, rpcUrls);
6946
- const short = `${address.slice(0, 8)}\u2026${address.slice(-6)}`;
6947
- return /* @__PURE__ */ import_react3.default.createElement("div", { style: {
6948
- background: "var(--dc-surface)",
6949
- border: "1px solid var(--dc-border)",
6950
- borderRadius: 10,
6951
- padding: "10px 14px",
6952
- marginBottom: 8
6953
- } }, /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 5 } }, /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 10, fontWeight: 700, color: "var(--dc-text-muted)", letterSpacing: "0.06em", textTransform: "uppercase" } }, label), /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 11, fontFamily: "monospace", color: "var(--dc-text)" } }, balance.loading ? "\u2026" : `${formatBalanceDisplay(balance.value)} ${balance.symbol}`)), /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 13, fontFamily: "monospace", color: "var(--dc-text)", letterSpacing: "0.02em" } }, short), /* @__PURE__ */ import_react3.default.createElement(CopyButton, { value: address })));
6954
- }
6955
- function SignInView({
6956
- onGoogleSignIn,
6957
- onKingsChatSignIn,
6958
- onXSignIn,
6959
- onEmailStart,
6960
- onEmailVerify,
6961
- onPhoneStart,
6962
- onPhoneVerify,
6963
- authMethods,
6964
- resumeHint,
6965
- customAuthLabel,
6966
- onCustomAuthSignIn,
6967
- canUsePasskey,
6968
- passkeyAddress,
6969
- onPasskeySignIn
6970
- }) {
6971
- const [googleLoading, setGoogleLoading] = (0, import_react3.useState)(false);
6972
- const [kingsChatLoading, setKingsChatLoading] = (0, import_react3.useState)(false);
6973
- const [xLoading, setXLoading] = (0, import_react3.useState)(false);
6974
- const [email, setEmail] = (0, import_react3.useState)("");
6975
- const [code, setCode] = (0, import_react3.useState)("");
6976
- const [emailSent, setEmailSent] = (0, import_react3.useState)(false);
6977
- const [emailLoading, setEmailLoading] = (0, import_react3.useState)(false);
6978
- const [phone, setPhone] = (0, import_react3.useState)("");
6979
- const [phoneCode, setPhoneCode] = (0, import_react3.useState)("");
6980
- const [phoneSent, setPhoneSent] = (0, import_react3.useState)(false);
6981
- const [phoneLoading, setPhoneLoading] = (0, import_react3.useState)(false);
6982
- const [customLoading, setCustomLoading] = (0, import_react3.useState)(false);
6983
- const [passkeyLoading, setPasskeyLoading] = (0, import_react3.useState)(false);
6984
- const [showOtherMethods, setShowOtherMethods] = (0, import_react3.useState)(false);
6985
- const [error, setError] = (0, import_react3.useState)("");
6986
- const passkeyFirst = !!canUsePasskey && !!onPasskeySignIn && !showOtherMethods;
6987
- async function handlePasskey() {
6988
- if (!onPasskeySignIn) return;
6989
- setError("");
6990
- setPasskeyLoading(true);
6991
- try {
6992
- await onPasskeySignIn();
6993
- } catch (e) {
6994
- const err = e;
6995
- if (err?.name !== "UserCancelledError") {
6996
- setError(err?.message ?? "Passkey sign-in failed");
6997
- setShowOtherMethods(true);
6998
- }
6999
- setPasskeyLoading(false);
7000
- }
7001
- }
7002
- async function handleGoogle() {
7003
- setError("");
7004
- setGoogleLoading(true);
7005
- try {
7006
- await onGoogleSignIn();
7007
- } catch (e) {
7008
- setError(e.message);
7009
- setGoogleLoading(false);
7010
- }
7011
- }
7012
- async function handleKingsChat() {
7013
- if (!onKingsChatSignIn) return;
7014
- setError("");
7015
- setKingsChatLoading(true);
7016
- try {
7017
- await onKingsChatSignIn();
7018
- } catch (e) {
7019
- setError(e.message);
7020
- } finally {
7021
- setKingsChatLoading(false);
7022
- }
7023
- }
7024
- async function handleX() {
7025
- if (!onXSignIn) return;
7026
- setError("");
7027
- setXLoading(true);
7028
- try {
7029
- await onXSignIn();
7030
- } catch (e) {
7031
- setError(e.message);
7032
- setXLoading(false);
7033
- }
7034
- }
7035
- async function handleEmailStart(e) {
7036
- e.preventDefault();
7037
- setError("");
7038
- setEmailLoading(true);
7039
- try {
7040
- await onEmailStart(email);
7041
- setEmailSent(true);
7042
- } catch (e2) {
7043
- setError(e2.message);
7044
- } finally {
7045
- setEmailLoading(false);
7046
- }
7047
- }
7048
- async function handleEmailVerify(e) {
7049
- e.preventDefault();
7050
- setError("");
7051
- setEmailLoading(true);
7052
- try {
7053
- await onEmailVerify(email, code);
7054
- } catch (e2) {
7055
- setError(e2.message);
7056
- } finally {
7057
- setEmailLoading(false);
7058
- }
7059
- }
7060
- async function handlePhoneStart(e) {
7061
- e.preventDefault();
7062
- if (!onPhoneStart) return;
7063
- setError("");
7064
- setPhoneLoading(true);
7065
- try {
7066
- await onPhoneStart(phone);
7067
- setPhoneSent(true);
7068
- } catch (e2) {
7069
- setError(e2.message);
7070
- } finally {
7071
- setPhoneLoading(false);
7072
- }
7073
- }
7074
- async function handlePhoneVerify(e) {
7075
- e.preventDefault();
7076
- if (!onPhoneVerify) return;
7077
- setError("");
7078
- setPhoneLoading(true);
7079
- try {
7080
- await onPhoneVerify(phone, phoneCode);
7081
- } catch (e2) {
7082
- setError(e2.message);
7083
- } finally {
7084
- setPhoneLoading(false);
7085
- }
7086
- }
7087
- async function handleCustomAuth() {
7088
- if (!onCustomAuthSignIn) return;
7089
- setError("");
7090
- setCustomLoading(true);
7091
- try {
7092
- await onCustomAuthSignIn();
7093
- } catch (e) {
7094
- setError(e.message);
7095
- } finally {
7096
- setCustomLoading(false);
7097
- }
7098
- }
7099
- const inputStyle = {
7100
- width: "100%",
7101
- background: "var(--dc-surface)",
7102
- border: "1px solid var(--dc-border)",
7103
- borderRadius: 8,
7104
- color: "var(--dc-text)",
7105
- padding: "9px 12px",
7106
- fontSize: 13,
7107
- outline: "none",
7108
- fontFamily: "inherit",
7109
- boxSizing: "border-box"
7110
- };
7111
- return /* @__PURE__ */ import_react3.default.createElement("div", { style: { padding: "0 16px 16px" } }, resumeHint && !passkeyFirst && /* @__PURE__ */ import_react3.default.createElement("div", { style: { fontSize: 12, color: "var(--dc-text-muted)", marginBottom: 12, textAlign: "center" } }, "Welcome back \u2014 sign in again to resume ", resumeHint), passkeyFirst && /* @__PURE__ */ import_react3.default.createElement("div", null, /* @__PURE__ */ import_react3.default.createElement("div", { style: { fontSize: 12, color: "var(--dc-text-muted)", marginBottom: 12, textAlign: "center" } }, "Welcome back \u2014 unlock to resume", passkeyAddress ? ` ${passkeyAddress.slice(0, 6)}\u2026${passkeyAddress.slice(-4)}` : ""), /* @__PURE__ */ import_react3.default.createElement(
7112
- "button",
7113
- {
7114
- onClick: handlePasskey,
7115
- disabled: passkeyLoading,
7116
- style: {
7117
- width: "100%",
7118
- padding: "11px 0",
7119
- background: "var(--dc-accent)",
7120
- color: "var(--dc-accent-text)",
7121
- border: "none",
7122
- borderRadius: 10,
7123
- fontSize: 13,
7124
- fontWeight: 700,
7125
- cursor: passkeyLoading ? "not-allowed" : "pointer",
7126
- opacity: passkeyLoading ? 0.7 : 1,
7127
- fontFamily: "inherit",
7128
- display: "flex",
7129
- alignItems: "center",
7130
- justifyContent: "center",
7131
- gap: 7
7132
- }
7133
- },
7134
- passkeyLoading ? "Verifying\u2026" : "\u{1F513} Continue with passkey"
7135
- ), /* @__PURE__ */ import_react3.default.createElement(
7136
- "button",
7137
- {
7138
- onClick: () => setShowOtherMethods(true),
7139
- style: {
7140
- width: "100%",
7141
- marginTop: 10,
7142
- background: "none",
7143
- border: "none",
7144
- color: "var(--dc-text-muted)",
7145
- fontSize: 12,
7146
- cursor: "pointer",
7147
- fontFamily: "inherit"
7148
- }
7149
- },
7150
- "Use email or Google instead"
7151
- ), error && /* @__PURE__ */ import_react3.default.createElement("div", { style: { marginTop: 10, fontSize: 12, color: "var(--dc-danger, #ff5533)" } }, error)), !passkeyFirst && authMethods.includes("google") && /* @__PURE__ */ import_react3.default.createElement(
7152
- "button",
7153
- {
7154
- onClick: handleGoogle,
7155
- disabled: googleLoading,
7156
- style: {
7157
- width: "100%",
7158
- padding: "10px 0",
7159
- marginBottom: 10,
7160
- background: "var(--dc-accent)",
7161
- color: "var(--dc-accent-text)",
7162
- border: "none",
7163
- borderRadius: 10,
7164
- fontSize: 13,
7165
- fontWeight: 700,
7166
- cursor: googleLoading ? "not-allowed" : "pointer",
7167
- opacity: googleLoading ? 0.7 : 1,
7168
- fontFamily: "inherit"
7169
- }
7170
- },
7171
- googleLoading ? "Redirecting\u2026" : "Continue with Google"
7172
- ), !passkeyFirst && authMethods.includes("kingschat") && onKingsChatSignIn && /* @__PURE__ */ import_react3.default.createElement(
7173
- "button",
7174
- {
7175
- onClick: handleKingsChat,
7176
- disabled: kingsChatLoading,
7177
- style: {
7178
- width: "100%",
7179
- padding: "10px 0",
7180
- marginBottom: 10,
7181
- background: "var(--dc-surface)",
7182
- color: "var(--dc-text)",
7183
- border: "1px solid var(--dc-border)",
7184
- borderRadius: 10,
7185
- fontSize: 13,
7186
- fontWeight: 700,
7187
- cursor: kingsChatLoading ? "not-allowed" : "pointer",
7188
- opacity: kingsChatLoading ? 0.7 : 1,
7189
- fontFamily: "inherit"
7190
- }
7191
- },
7192
- kingsChatLoading ? "Waiting for KingsChat\u2026" : "Continue with KingsChat"
7193
- ), !passkeyFirst && authMethods.includes("x") && onXSignIn && /* @__PURE__ */ import_react3.default.createElement(
7194
- "button",
7195
- {
7196
- onClick: handleX,
7197
- disabled: xLoading,
7198
- style: {
7199
- width: "100%",
7200
- padding: "10px 0",
7201
- marginBottom: 10,
7202
- background: "var(--dc-surface)",
7203
- color: "var(--dc-text)",
7204
- border: "1px solid var(--dc-border)",
7205
- borderRadius: 10,
7206
- fontSize: 13,
7207
- fontWeight: 700,
7208
- cursor: xLoading ? "not-allowed" : "pointer",
7209
- opacity: xLoading ? 0.7 : 1,
7210
- fontFamily: "inherit",
7211
- display: "flex",
7212
- alignItems: "center",
7213
- justifyContent: "center",
7214
- gap: 8
7215
- }
7216
- },
7217
- /* @__PURE__ */ import_react3.default.createElement(XLogo, null),
7218
- xLoading ? "Redirecting\u2026" : "Continue with X"
7219
- ), !passkeyFirst && authMethods.includes("email") && /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, authMethods.includes("google") && /* @__PURE__ */ import_react3.default.createElement("div", { style: { textAlign: "center", color: "var(--dc-text-muted)", fontSize: 12, margin: "10px 0" } }, "\u2014 or \u2014"), !emailSent ? /* @__PURE__ */ import_react3.default.createElement("form", { onSubmit: handleEmailStart, style: { display: "flex", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement(
6258
+ className: "dcm-field dcm-code",
6259
+ "aria-label": "6-digit code",
6260
+ placeholder: "000000",
6261
+ value,
6262
+ maxLength: 6,
6263
+ autoFocus: true,
6264
+ inputMode: "numeric",
6265
+ autoComplete: "one-time-code",
6266
+ onChange: (e) => setValue(e.target.value.replace(/\D/g, ""))
6267
+ }
6268
+ ), /* @__PURE__ */ import_react2.default.createElement("button", { type: "submit", className: "dcm-primary", disabled: loading || value.length < 6 }, loading ? "Verifying\u2026" : "Continue")), errorLine, /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-link", onClick: backToMethods }, "Use a different method"), /* @__PURE__ */ import_react2.default.createElement(ProtectedBy, null));
6269
+ }
6270
+ const showPhone = authMethods.includes("phone") && !!onPhoneStart && !!onPhoneVerify;
6271
+ return /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-body" }, /* @__PURE__ */ import_react2.default.createElement(DecaneMark, { size: 44 }), /* @__PURE__ */ import_react2.default.createElement("h2", { className: "dcm-title" }, resumeHint ? "Welcome back" : "Log in or sign up"), resumeHint && /* @__PURE__ */ import_react2.default.createElement("p", { className: "dcm-sub" }, "Sign in again to resume ", resumeHint, "."), /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-methods" }, authMethods.includes("google") && /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-method", onClick: handleGoogle, disabled: busy }, /* @__PURE__ */ import_react2.default.createElement(GoogleMark, { size: 18 }), /* @__PURE__ */ import_react2.default.createElement("span", null, googleLoading ? "Redirecting to Google\u2026" : "Google")), authMethods.includes("email") && /* @__PURE__ */ import_react2.default.createElement("form", { className: "dcm-method dcm-method-input", onSubmit: handleEmailStart }, /* @__PURE__ */ import_react2.default.createElement(MailIcon, { size: 18 }), /* @__PURE__ */ import_react2.default.createElement(
7220
6272
  "input",
7221
6273
  {
7222
6274
  type: "email",
7223
6275
  required: true,
7224
6276
  placeholder: "your@email.com",
6277
+ "aria-label": "Email address",
6278
+ autoComplete: "email",
7225
6279
  value: email,
7226
- onChange: (e) => setEmail(e.target.value),
7227
- style: { ...inputStyle, flex: 1 }
7228
- }
7229
- ), /* @__PURE__ */ import_react3.default.createElement("button", { type: "submit", disabled: emailLoading, style: {
7230
- padding: "0 16px",
7231
- background: "var(--dc-surface)",
7232
- border: "1px solid var(--dc-border)",
7233
- borderRadius: 8,
7234
- color: "var(--dc-text)",
7235
- fontSize: 13,
7236
- cursor: "pointer",
7237
- fontFamily: "inherit"
7238
- } }, emailLoading ? "\u2026" : "Send code")) : /* @__PURE__ */ import_react3.default.createElement("form", { onSubmit: handleEmailVerify, style: { display: "flex", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement(
7239
- "input",
7240
- {
7241
- placeholder: "6-digit code",
7242
- value: code,
7243
- maxLength: 6,
7244
- autoFocus: true,
7245
- onChange: (e) => setCode(e.target.value.replace(/\D/g, "")),
7246
- style: { ...inputStyle, flex: 1, letterSpacing: 4, textAlign: "center" }
7247
- }
7248
- ), /* @__PURE__ */ import_react3.default.createElement("button", { type: "submit", disabled: emailLoading, style: {
7249
- padding: "0 16px",
7250
- background: "var(--dc-accent)",
7251
- color: "var(--dc-accent-text)",
7252
- border: "none",
7253
- borderRadius: 8,
7254
- fontSize: 13,
7255
- fontWeight: 700,
7256
- cursor: "pointer",
7257
- fontFamily: "inherit"
7258
- } }, emailLoading ? "\u2026" : "Verify"))), !passkeyFirst && authMethods.includes("phone") && onPhoneStart && onPhoneVerify && /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, (authMethods.includes("google") || authMethods.includes("email")) && /* @__PURE__ */ import_react3.default.createElement("div", { style: { textAlign: "center", color: "var(--dc-text-muted)", fontSize: 12, margin: "10px 0" } }, "\u2014 or \u2014"), !phoneSent ? /* @__PURE__ */ import_react3.default.createElement("form", { onSubmit: handlePhoneStart, style: { display: "flex", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement(
6280
+ onChange: (e) => setEmail(e.target.value)
6281
+ }
6282
+ ), /* @__PURE__ */ import_react2.default.createElement("button", { type: "submit", className: "dcm-submit", disabled: busy || !email.trim() }, emailLoading ? "Sending\u2026" : "Submit")), showPhone && /* @__PURE__ */ import_react2.default.createElement("form", { className: "dcm-method dcm-method-input", onSubmit: handlePhoneStart }, /* @__PURE__ */ import_react2.default.createElement(PhoneIcon, { size: 18 }), /* @__PURE__ */ import_react2.default.createElement(
7259
6283
  "input",
7260
6284
  {
7261
6285
  type: "tel",
7262
6286
  required: true,
7263
6287
  placeholder: "+234 801 234 5678",
6288
+ "aria-label": "Phone number",
6289
+ autoComplete: "tel",
7264
6290
  value: phone,
7265
- onChange: (e) => setPhone(e.target.value),
7266
- style: { ...inputStyle, flex: 1 }
7267
- }
7268
- ), /* @__PURE__ */ import_react3.default.createElement("button", { type: "submit", disabled: phoneLoading, style: {
7269
- padding: "0 16px",
7270
- background: "var(--dc-surface)",
7271
- border: "1px solid var(--dc-border)",
7272
- borderRadius: 8,
7273
- color: "var(--dc-text)",
7274
- fontSize: 13,
7275
- cursor: "pointer",
7276
- fontFamily: "inherit"
7277
- } }, phoneLoading ? "\u2026" : "Send code")) : /* @__PURE__ */ import_react3.default.createElement("form", { onSubmit: handlePhoneVerify, style: { display: "flex", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement(
7278
- "input",
7279
- {
7280
- placeholder: "6-digit code",
7281
- value: phoneCode,
7282
- maxLength: 6,
7283
- autoFocus: true,
7284
- inputMode: "numeric",
7285
- onChange: (e) => setPhoneCode(e.target.value.replace(/\D/g, "")),
7286
- style: { ...inputStyle, flex: 1, letterSpacing: 4, textAlign: "center" }
7287
- }
7288
- ), /* @__PURE__ */ import_react3.default.createElement("button", { type: "submit", disabled: phoneLoading, style: {
7289
- padding: "0 16px",
7290
- background: "var(--dc-accent)",
7291
- color: "var(--dc-accent-text)",
7292
- border: "none",
7293
- borderRadius: 8,
7294
- fontSize: 13,
7295
- fontWeight: 700,
7296
- cursor: "pointer",
7297
- fontFamily: "inherit"
7298
- } }, phoneLoading ? "\u2026" : "Verify"))), !passkeyFirst && customAuthLabel && onCustomAuthSignIn && /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, (authMethods.includes("google") || authMethods.includes("email")) && /* @__PURE__ */ import_react3.default.createElement("div", { style: { textAlign: "center", color: "var(--dc-text-muted)", fontSize: 12, margin: "10px 0" } }, "\u2014 or \u2014"), /* @__PURE__ */ import_react3.default.createElement(
7299
- "button",
7300
- {
7301
- onClick: handleCustomAuth,
7302
- disabled: customLoading,
7303
- style: {
7304
- width: "100%",
7305
- padding: "10px 0",
7306
- background: "var(--dc-surface)",
7307
- color: "var(--dc-text)",
7308
- border: "1px solid var(--dc-border)",
7309
- borderRadius: 10,
7310
- fontSize: 13,
7311
- fontWeight: 600,
7312
- cursor: customLoading ? "not-allowed" : "pointer",
7313
- opacity: customLoading ? 0.7 : 1,
7314
- fontFamily: "inherit"
7315
- }
7316
- },
7317
- customLoading ? "Connecting\u2026" : customAuthLabel
7318
- )), error && /* @__PURE__ */ import_react3.default.createElement("div", { style: { marginTop: 10, fontSize: 12, color: "var(--dc-danger, #ff5533)" } }, error));
6291
+ onChange: (e) => setPhone(e.target.value)
6292
+ }
6293
+ ), /* @__PURE__ */ import_react2.default.createElement("button", { type: "submit", className: "dcm-submit", disabled: busy || !phone.trim() }, phoneLoading ? "Sending\u2026" : "Submit")), authMethods.includes("x") && onXSignIn && /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-method", onClick: handleX, disabled: busy }, /* @__PURE__ */ import_react2.default.createElement(XLogo, { size: 16 }), /* @__PURE__ */ import_react2.default.createElement("span", null, xLoading ? "Redirecting to X\u2026" : "X")), authMethods.includes("kingschat") && onKingsChatSignIn && /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-method", onClick: handleKingsChat, disabled: busy }, /* @__PURE__ */ import_react2.default.createElement(ChatIcon, { size: 18 }), /* @__PURE__ */ import_react2.default.createElement("span", null, kingsChatLoading ? "Waiting for KingsChat\u2026" : "KingsChat")), customAuthLabel && onCustomAuthSignIn && /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-method", onClick: handleCustomAuth, disabled: busy }, /* @__PURE__ */ import_react2.default.createElement(UserIcon, { size: 18 }), /* @__PURE__ */ import_react2.default.createElement("span", null, customLoading ? "Connecting\u2026" : customAuthLabel))), extra, errorLine, canUsePasskey && onPasskeySignIn && /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-link", onClick: () => {
6294
+ setError("");
6295
+ setShowOtherMethods(false);
6296
+ } }, "Use my passkey instead"), /* @__PURE__ */ import_react2.default.createElement(ProtectedBy, null));
7319
6297
  }
7320
6298
  function RecoverySection({
7321
6299
  addresses,
7322
6300
  onRotateShares,
7323
6301
  onExportPortableBackup
7324
6302
  }) {
7325
- const [expanded, setExpanded] = (0, import_react3.useState)(false);
7326
- const [mode, setMode] = (0, import_react3.useState)(null);
7327
- const [password, setPassword] = (0, import_react3.useState)("");
7328
- const [passwordHint, setPasswordHint] = (0, import_react3.useState)("");
7329
- const [confirmed, setConfirmed] = (0, import_react3.useState)(false);
7330
- const [busy, setBusy] = (0, import_react3.useState)(false);
7331
- const [result, setResult] = (0, import_react3.useState)(null);
7332
- const [error, setError] = (0, import_react3.useState)("");
6303
+ const [expanded, setExpanded] = (0, import_react2.useState)(false);
6304
+ const [mode, setMode] = (0, import_react2.useState)(null);
6305
+ const [password, setPassword] = (0, import_react2.useState)("");
6306
+ const [passwordHint, setPasswordHint] = (0, import_react2.useState)("");
6307
+ const [confirmed, setConfirmed] = (0, import_react2.useState)(false);
6308
+ const [busy, setBusy] = (0, import_react2.useState)(false);
6309
+ const [result, setResult] = (0, import_react2.useState)(null);
6310
+ const [error, setError] = (0, import_react2.useState)("");
7333
6311
  function reset() {
7334
6312
  setMode(null);
7335
6313
  setPassword("");
@@ -7366,60 +6344,34 @@ function RecoverySection({
7366
6344
  setBusy(false);
7367
6345
  }
7368
6346
  }
7369
- const inputStyle = {
7370
- width: "100%",
7371
- background: "var(--dc-bg)",
7372
- border: "1px solid var(--dc-border)",
7373
- borderRadius: 8,
7374
- color: "var(--dc-text)",
7375
- padding: "8px 10px",
7376
- fontSize: 12,
7377
- outline: "none",
7378
- fontFamily: "inherit",
7379
- boxSizing: "border-box"
7380
- };
7381
- const btnStyle = {
7382
- padding: "8px 12px",
7383
- borderRadius: 8,
7384
- fontSize: 12,
7385
- fontWeight: 700,
7386
- cursor: "pointer",
7387
- fontFamily: "inherit",
7388
- border: "none"
7389
- };
7390
- return /* @__PURE__ */ import_react3.default.createElement("div", { style: { margin: "0 16px 14px", border: "1px solid var(--dc-border)", borderRadius: 10, overflow: "hidden" } }, /* @__PURE__ */ import_react3.default.createElement(
7391
- "button",
6347
+ const passwordFields = /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(
6348
+ "input",
7392
6349
  {
7393
- onClick: () => setExpanded((v) => !v),
7394
- style: {
7395
- width: "100%",
7396
- padding: "10px 14px",
7397
- background: "var(--dc-surface)",
7398
- border: "none",
7399
- display: "flex",
7400
- alignItems: "center",
7401
- justifyContent: "space-between",
7402
- cursor: "pointer",
7403
- fontFamily: "inherit"
7404
- }
7405
- },
7406
- /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 12, fontWeight: 700, color: "var(--dc-text)" } }, "Recovery"),
7407
- /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 11, color: "var(--dc-text-muted)" } }, expanded ? "\u25B2" : "\u25BC")
7408
- ), expanded && /* @__PURE__ */ import_react3.default.createElement("div", { style: { padding: "12px 14px", borderTop: "1px solid var(--dc-border)" } }, /* @__PURE__ */ import_react3.default.createElement("p", { style: { fontSize: 11, color: "var(--dc-text-muted)", lineHeight: 1.5, margin: "0 0 10px" } }, "Save a recovery file so you can restore this wallet on a new device."), !mode && /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement("button", { onClick: () => {
6350
+ className: "dcm-field",
6351
+ type: "password",
6352
+ placeholder: "Password (at least 8 characters)",
6353
+ "aria-label": "Password",
6354
+ autoComplete: "new-password",
6355
+ value: password,
6356
+ onChange: (e) => setPassword(e.target.value)
6357
+ }
6358
+ ), /* @__PURE__ */ import_react2.default.createElement(
6359
+ "input",
6360
+ {
6361
+ className: "dcm-field",
6362
+ placeholder: "Password hint (optional)",
6363
+ "aria-label": "Password hint",
6364
+ value: passwordHint,
6365
+ onChange: (e) => setPasswordHint(e.target.value)
6366
+ }
6367
+ ), error && /* @__PURE__ */ import_react2.default.createElement("p", { className: "dcm-error", role: "alert" }, error));
6368
+ return /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-panel" }, /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-panel-head", onClick: () => setExpanded((v) => !v), "aria-expanded": expanded }, /* @__PURE__ */ import_react2.default.createElement("span", null, "Recovery file"), /* @__PURE__ */ import_react2.default.createElement(ChevronIcon, { open: expanded })), expanded && /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-panel-body" }, !mode && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("p", { className: "dcm-note" }, "Save a recovery file so you can restore this wallet on a new device."), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-primary", style: { height: 44, borderRadius: 12 }, onClick: () => {
7409
6369
  reset();
7410
6370
  setMode("share");
7411
- }, style: { ...btnStyle, background: "var(--dc-accent)", color: "var(--dc-accent-text)" } }, "Generate recovery-share file"), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: () => {
6371
+ } }, "Download recovery-share file"), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-ghost", onClick: () => {
7412
6372
  reset();
7413
6373
  setMode("portable");
7414
- }, style: { ...btnStyle, background: "transparent", border: "1px solid var(--dc-border)", color: "var(--dc-text)" } }, "Generate full recovery file")), mode === "share" && /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement("p", { style: { fontSize: 11, color: "var(--dc-text-muted)", margin: 0 } }, "One share \u2014 useless alone, safe to keep in a password manager or cloud drive. Generating a new one invalidates any previous recovery-share file."), /* @__PURE__ */ import_react3.default.createElement("input", { type: "password", placeholder: "Password (min 8 chars)", value: password, onChange: (e) => setPassword(e.target.value), style: inputStyle }), /* @__PURE__ */ import_react3.default.createElement("input", { placeholder: "Password hint (optional)", value: passwordHint, onChange: (e) => setPasswordHint(e.target.value), style: inputStyle }), error && /* @__PURE__ */ import_react3.default.createElement("div", { style: { fontSize: 11, color: "var(--dc-danger, #ff5533)" } }, error), /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement("button", { onClick: handleGenerate, disabled: busy, style: { ...btnStyle, flex: 1, background: "var(--dc-accent)", color: "var(--dc-accent-text)" } }, busy ? "Generating\u2026" : "Generate & download"), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: reset, style: { ...btnStyle, background: "transparent", border: "1px solid var(--dc-border)", color: "var(--dc-text-muted)" } }, "Cancel"))), mode === "portable" && /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", flexDirection: "column", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement("div", { style: {
7415
- background: "rgba(255,85,51,0.08)",
7416
- border: "1px solid rgba(255,85,51,0.3)",
7417
- borderRadius: 8,
7418
- padding: "8px 10px",
7419
- fontSize: 11,
7420
- color: "#ff9977",
7421
- lineHeight: 1.5
7422
- } }, /* @__PURE__ */ import_react3.default.createElement("strong", { style: { display: "block", marginBottom: 3, color: "#ff5533" } }, "This file controls your wallet"), "Contains two shares \u2014 file plus password gives complete control. Keep it offline, not a cloud drive. This also invalidates your current recovery-share file."), /* @__PURE__ */ import_react3.default.createElement("label", { style: { display: "flex", alignItems: "center", gap: 6, fontSize: 11, color: "var(--dc-text)" } }, /* @__PURE__ */ import_react3.default.createElement("input", { type: "checkbox", checked: confirmed, onChange: (e) => setConfirmed(e.target.checked), style: { width: "auto" } }), "I understand this is a bearer secret"), /* @__PURE__ */ import_react3.default.createElement("input", { type: "password", placeholder: "Password (min 8 chars)", value: password, onChange: (e) => setPassword(e.target.value), style: inputStyle }), /* @__PURE__ */ import_react3.default.createElement("input", { placeholder: "Password hint (optional)", value: passwordHint, onChange: (e) => setPasswordHint(e.target.value), style: inputStyle }), error && /* @__PURE__ */ import_react3.default.createElement("div", { style: { fontSize: 11, color: "var(--dc-danger, #ff5533)" } }, error), /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement("button", { onClick: handleGenerate, disabled: busy || !confirmed, style: { ...btnStyle, flex: 1, background: "var(--dc-accent)", color: "var(--dc-accent-text)" } }, busy ? "Generating\u2026" : "Generate & download"), /* @__PURE__ */ import_react3.default.createElement("button", { onClick: reset, style: { ...btnStyle, background: "transparent", border: "1px solid var(--dc-border)", color: "var(--dc-text-muted)" } }, "Cancel"))), result && /* @__PURE__ */ import_react3.default.createElement("div", { style: { marginTop: 10, fontSize: 11, color: "var(--dc-text-muted)", lineHeight: 1.5 } }, result.kind === "share" ? "Recovery-share file" : "Full recovery file", " downloaded \u2014 share set is now version ", result.version, ". Any previous recovery file no longer works.")));
6374
+ } }, "Download full recovery file")), mode === "share" && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("p", { className: "dcm-note" }, "One share. It is useless on its own, so a password manager or cloud drive is a fine place for it. A new file replaces any previous recovery-share file."), passwordFields, /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-row" }, /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-primary", onClick: handleGenerate, disabled: busy }, busy ? "Preparing\u2026" : "Download"), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-ghost", onClick: reset }, "Cancel"))), mode === "portable" && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-warn" }, /* @__PURE__ */ import_react2.default.createElement("strong", null, "This file controls your wallet"), "It holds two shares, so the file plus its password is full control. Keep it offline, not in a cloud drive. It also replaces your current recovery-share file."), /* @__PURE__ */ import_react2.default.createElement("label", { className: "dcm-check" }, /* @__PURE__ */ import_react2.default.createElement("input", { type: "checkbox", checked: confirmed, onChange: (e) => setConfirmed(e.target.checked) }), "I understand anyone with this file and password controls the wallet"), passwordFields, /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-row" }, /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-primary", onClick: handleGenerate, disabled: busy || !confirmed }, busy ? "Preparing\u2026" : "Download"), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-ghost", onClick: reset }, "Cancel"))), result && /* @__PURE__ */ import_react2.default.createElement("p", { className: "dcm-note" }, result.kind === "share" ? "Recovery-share file" : "Full recovery file", " downloaded. The share set is now version ", result.version, ", and any earlier recovery file no longer works.")));
7423
6375
  }
7424
6376
  function SocialWalletModal({
7425
6377
  open,
@@ -7430,6 +6382,7 @@ function SocialWalletModal({
7430
6382
  onDisconnect,
7431
6383
  onGoogleSignIn,
7432
6384
  onKingsChatSignIn,
6385
+ onXSignIn,
7433
6386
  onEmailStart,
7434
6387
  onEmailVerify,
7435
6388
  onPhoneStart,
@@ -7445,19 +6398,21 @@ function SocialWalletModal({
7445
6398
  rpcUrls,
7446
6399
  chains
7447
6400
  }) {
7448
- const [timer, setTimer] = (0, import_react3.useState)("");
7449
- const [unlocking, setUnlocking] = (0, import_react3.useState)(false);
7450
- const [disconnecting, setDisconnecting] = (0, import_react3.useState)(false);
7451
- (0, import_react3.useEffect)(() => {
6401
+ const [timer, setTimer] = (0, import_react2.useState)("");
6402
+ const [unlocking, setUnlocking] = (0, import_react2.useState)(false);
6403
+ const [disconnecting, setDisconnecting] = (0, import_react2.useState)(false);
6404
+ const [actionError, setActionError] = (0, import_react2.useState)("");
6405
+ (0, import_react2.useEffect)(() => {
7452
6406
  if (!open) return;
7453
- injectTokens2(theme);
6407
+ injectTokens(theme);
6408
+ injectModalCss();
7454
6409
  if (theme !== "auto") return;
7455
6410
  const mq = window.matchMedia("(prefers-color-scheme: dark)");
7456
- const h = () => injectTokens2("auto");
6411
+ const h = () => injectTokens("auto");
7457
6412
  mq.addEventListener("change", h);
7458
6413
  return () => mq.removeEventListener("change", h);
7459
6414
  }, [open, theme]);
7460
- (0, import_react3.useEffect)(() => {
6415
+ (0, import_react2.useEffect)(() => {
7461
6416
  if (!socialAuth.sessionExpiresAt) {
7462
6417
  setTimer("");
7463
6418
  return;
@@ -7466,10 +6421,10 @@ function SocialWalletModal({
7466
6421
  const id = setInterval(() => setTimer(countdown(socialAuth.sessionExpiresAt)), 1e3);
7467
6422
  return () => clearInterval(id);
7468
6423
  }, [socialAuth.sessionExpiresAt]);
7469
- const handleKey = (0, import_react3.useCallback)((e) => {
6424
+ const handleKey = (0, import_react2.useCallback)((e) => {
7470
6425
  if (e.key === "Escape") onClose();
7471
6426
  }, [onClose]);
7472
- (0, import_react3.useEffect)(() => {
6427
+ (0, import_react2.useEffect)(() => {
7473
6428
  if (!open) return;
7474
6429
  document.addEventListener("keydown", handleKey);
7475
6430
  return () => document.removeEventListener("keydown", handleKey);
@@ -7477,17 +6432,23 @@ function SocialWalletModal({
7477
6432
  if (!open) return null;
7478
6433
  async function handleUnlock() {
7479
6434
  setUnlocking(true);
6435
+ setActionError("");
7480
6436
  try {
7481
6437
  await onUnlock();
6438
+ } catch (e) {
6439
+ setActionError(e.message);
7482
6440
  } finally {
7483
6441
  setUnlocking(false);
7484
6442
  }
7485
6443
  }
7486
6444
  async function handleDisconnect() {
7487
6445
  setDisconnecting(true);
6446
+ setActionError("");
7488
6447
  try {
7489
6448
  await onDisconnect();
7490
6449
  onClose();
6450
+ } catch (e) {
6451
+ setActionError(e.message);
7491
6452
  } finally {
7492
6453
  setDisconnecting(false);
7493
6454
  }
@@ -7495,12 +6456,13 @@ function SocialWalletModal({
7495
6456
  const evmChain = chains?.find((c) => c.startsWith("evm:")) ?? "evm:11155111";
7496
6457
  const solChain = chains?.find((c) => c.startsWith("solana:")) ?? "solana:mainnet";
7497
6458
  const showSignIn = !socialAuth.addresses || socialAuth.needsReconnect;
7498
- const modal = /* @__PURE__ */ import_react3.default.createElement(
6459
+ const unlocked = socialAuth.isUnlocked;
6460
+ const modal = /* @__PURE__ */ import_react2.default.createElement(
7499
6461
  "div",
7500
6462
  {
7501
6463
  role: "dialog",
7502
6464
  "aria-modal": "true",
7503
- "aria-label": "Social wallet",
6465
+ "aria-label": showSignIn ? "Log in or sign up" : "Your wallet",
7504
6466
  style: {
7505
6467
  position: "fixed",
7506
6468
  inset: 0,
@@ -7509,63 +6471,17 @@ function SocialWalletModal({
7509
6471
  alignItems: "center",
7510
6472
  justifyContent: "center",
7511
6473
  padding: 16,
7512
- fontFamily: "var(--dc-font-sans, system-ui, sans-serif)"
6474
+ fontFamily: "var(--dc-font-sans, system-ui, sans-serif)",
6475
+ WebkitFontSmoothing: "antialiased"
7513
6476
  }
7514
6477
  },
7515
- /* @__PURE__ */ import_react3.default.createElement(
7516
- "div",
7517
- {
7518
- onClick: onClose,
7519
- style: {
7520
- position: "absolute",
7521
- inset: 0,
7522
- background: "var(--dc-bg-overlay)",
7523
- backdropFilter: "blur(8px)",
7524
- WebkitBackdropFilter: "blur(8px)"
7525
- }
7526
- }
7527
- ),
7528
- /* @__PURE__ */ import_react3.default.createElement("div", { style: {
7529
- position: "relative",
7530
- background: "var(--dc-bg)",
7531
- border: "1px solid var(--dc-border)",
7532
- borderRadius: 20,
7533
- width: "100%",
7534
- maxWidth: 380,
7535
- maxHeight: "90vh",
7536
- overflowY: "auto",
7537
- boxShadow: "0 24px 64px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.04)"
7538
- } }, /* @__PURE__ */ import_react3.default.createElement("div", { style: {
7539
- height: 2,
7540
- position: "sticky",
7541
- top: 0,
7542
- zIndex: 1,
7543
- background: "linear-gradient(90deg, transparent, var(--dc-accent) 30%, var(--dc-accent) 70%, transparent)"
7544
- } }), /* @__PURE__ */ import_react3.default.createElement("div", { style: { padding: "18px 20px 16px", display: "flex", alignItems: "center", gap: 11 } }, /* @__PURE__ */ import_react3.default.createElement(DecaneMark, { size: 38 }), /* @__PURE__ */ import_react3.default.createElement("div", { style: { flex: 1 } }, /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", alignItems: "baseline", gap: 6 } }, /* @__PURE__ */ import_react3.default.createElement(DecaneWordmark, { size: 15 }), /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 13, fontWeight: 700, color: "var(--dc-text-muted)", letterSpacing: "-0.01em" } }, "wallet")), /* @__PURE__ */ import_react3.default.createElement("div", { style: { fontSize: 11, color: "var(--dc-text-muted)", marginTop: 2 } }, "Non-custodial \xB7 key split three ways")), /* @__PURE__ */ import_react3.default.createElement(
7545
- "button",
7546
- {
7547
- onClick: onClose,
7548
- style: {
7549
- background: "var(--dc-surface)",
7550
- border: "1px solid var(--dc-border)",
7551
- borderRadius: 8,
7552
- width: 28,
7553
- height: 28,
7554
- cursor: "pointer",
7555
- display: "flex",
7556
- alignItems: "center",
7557
- justifyContent: "center",
7558
- color: "var(--dc-text-muted)",
7559
- flexShrink: 0,
7560
- padding: 0
7561
- }
7562
- },
7563
- /* @__PURE__ */ import_react3.default.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none" }, /* @__PURE__ */ import_react3.default.createElement("path", { d: "M1.5 1.5L10.5 10.5M10.5 1.5L1.5 10.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }))
7564
- )), showSignIn ? /* @__PURE__ */ import_react3.default.createElement(
6478
+ /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-backdrop", onClick: onClose }),
6479
+ /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-card" }, /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-icon-btn", style: { right: 14 }, onClick: onClose, "aria-label": "Close" }, /* @__PURE__ */ import_react2.default.createElement(CloseIcon, null)), showSignIn ? /* @__PURE__ */ import_react2.default.createElement(
7565
6480
  SignInView,
7566
6481
  {
7567
6482
  onGoogleSignIn,
7568
6483
  onKingsChatSignIn,
6484
+ onXSignIn,
7569
6485
  onEmailStart,
7570
6486
  onEmailVerify,
7571
6487
  onPhoneStart,
@@ -7578,86 +6494,238 @@ function SocialWalletModal({
7578
6494
  passkeyAddress,
7579
6495
  onPasskeySignIn
7580
6496
  }
7581
- ) : /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement("div", { style: {
7582
- margin: "0 16px 14px",
7583
- padding: "8px 14px",
7584
- background: socialAuth.isUnlocked ? "rgba(18,183,106,0.08)" : "rgba(245,200,0,0.08)",
7585
- border: `1px solid ${socialAuth.isUnlocked ? "rgba(18,183,106,0.2)" : "rgba(245,200,0,0.2)"}`,
7586
- borderRadius: 10,
7587
- display: "flex",
7588
- alignItems: "center",
7589
- justifyContent: "space-between"
7590
- } }, /* @__PURE__ */ import_react3.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 8 } }, /* @__PURE__ */ import_react3.default.createElement("span", { style: {
7591
- width: 7,
7592
- height: 7,
7593
- borderRadius: "50%",
7594
- flexShrink: 0,
7595
- background: socialAuth.isUnlocked ? "#12b76a" : "var(--dc-accent)",
7596
- boxShadow: `0 0 6px ${socialAuth.isUnlocked ? "#12b76a" : "var(--dc-accent)"}`
7597
- } }), /* @__PURE__ */ import_react3.default.createElement("span", { style: {
7598
- fontSize: 12,
7599
- fontWeight: 700,
7600
- color: socialAuth.isUnlocked ? "#12b76a" : "var(--dc-accent)"
7601
- } }, socialAuth.isUnlocked ? "Unlocked" : "Locked")), socialAuth.isUnlocked && timer && /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 11, color: "var(--dc-text-muted)", fontFamily: "monospace" } }, "expires ", timer)), /* @__PURE__ */ import_react3.default.createElement("div", { style: { padding: "0 16px 14px" } }, socialAuth.addresses?.evm && /* @__PURE__ */ import_react3.default.createElement(AddressRow, { label: "EVM (Ethereum, Base, \u2026)", address: socialAuth.addresses.evm, kind: "evm", chain: evmChain, rpcUrls }), socialAuth.addresses?.solana && /* @__PURE__ */ import_react3.default.createElement(AddressRow, { label: "Solana", address: socialAuth.addresses.solana, kind: "solana", chain: solChain, rpcUrls })), socialAuth.isUnlocked && /* @__PURE__ */ import_react3.default.createElement(
6497
+ ) : /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-body" }, /* @__PURE__ */ import_react2.default.createElement(DecaneMark, { size: 44 }), /* @__PURE__ */ import_react2.default.createElement("h2", { className: "dcm-title" }, "Your wallet"), /* @__PURE__ */ import_react2.default.createElement(
6498
+ "span",
6499
+ {
6500
+ className: "dcm-status",
6501
+ style: { color: unlocked ? "#12b76a" : "var(--dc-accent-ink)", marginTop: -8 }
6502
+ },
6503
+ /* @__PURE__ */ import_react2.default.createElement("i", { style: { background: unlocked ? "#12b76a" : "var(--dc-accent)" } }),
6504
+ unlocked ? timer ? `Unlocked, expires in ${timer}` : "Unlocked" : "Locked"
6505
+ ), (socialAuth.addresses?.evm || socialAuth.addresses?.solana) && /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-addresses" }, socialAuth.addresses?.evm && /* @__PURE__ */ import_react2.default.createElement(AddressRow, { label: "Ethereum and EVM", address: socialAuth.addresses.evm, kind: "evm", chain: evmChain, rpcUrls }), socialAuth.addresses?.solana && /* @__PURE__ */ import_react2.default.createElement(AddressRow, { label: "Solana", address: socialAuth.addresses.solana, kind: "solana", chain: solChain, rpcUrls })), unlocked && /* @__PURE__ */ import_react2.default.createElement(
7602
6506
  RecoverySection,
7603
6507
  {
7604
6508
  addresses: socialAuth.addresses,
7605
6509
  onRotateShares,
7606
6510
  onExportPortableBackup
7607
6511
  }
7608
- ), /* @__PURE__ */ import_react3.default.createElement("div", { style: {
7609
- padding: "14px 16px",
7610
- borderTop: "1px solid var(--dc-border)",
7611
- display: "flex",
7612
- gap: 8
7613
- } }, !socialAuth.isUnlocked && /* @__PURE__ */ import_react3.default.createElement(
7614
- "button",
6512
+ ), actionError && /* @__PURE__ */ import_react2.default.createElement("p", { className: "dcm-error", role: "alert" }, actionError), /* @__PURE__ */ import_react2.default.createElement("div", { className: "dcm-actions" }, !unlocked && /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-primary", style: { height: 44, borderRadius: 12 }, onClick: handleUnlock, disabled: unlocking }, unlocking ? "Unlocking\u2026" : "Unlock wallet"), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "dcm-ghost", onClick: handleDisconnect, disabled: disconnecting }, disconnecting ? "Signing out\u2026" : "Sign out")), /* @__PURE__ */ import_react2.default.createElement(ProtectedBy, null)))
6513
+ );
6514
+ return (0, import_react_dom.createPortal)(modal, document.body);
6515
+ }
6516
+
6517
+ // src/ui/WalletSelector.tsx
6518
+ var FONT_URL = "https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap";
6519
+ function injectTokens2(theme) {
6520
+ let resolved;
6521
+ if (theme === "auto") {
6522
+ resolved = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
6523
+ } else {
6524
+ resolved = theme;
6525
+ }
6526
+ let styleEl = document.getElementById("decane-tokens");
6527
+ if (!styleEl) {
6528
+ styleEl = document.createElement("style");
6529
+ styleEl.id = "decane-tokens";
6530
+ document.head.appendChild(styleEl);
6531
+ }
6532
+ styleEl.textContent = `:root { ${CSS_VARS[resolved]} }`;
6533
+ }
6534
+ function injectFont() {
6535
+ if (document.getElementById("decane-font")) return;
6536
+ const link = document.createElement("link");
6537
+ link.id = "decane-font";
6538
+ link.rel = "stylesheet";
6539
+ link.href = FONT_URL;
6540
+ document.head.appendChild(link);
6541
+ }
6542
+ function hasSocialMode(mode) {
6543
+ return mode === "all" || mode === "social" || mode === "evm+social" || mode === "solana+social" || mode === "tron+social" || mode === "evm+tron+social";
6544
+ }
6545
+ var NETWORK_LABEL = {
6546
+ evm: "EVM networks",
6547
+ solana: "Solana",
6548
+ tron: "Tron",
6549
+ bitcoin: "Bitcoin"
6550
+ };
6551
+ function WalletSelector({
6552
+ provider,
6553
+ open,
6554
+ onClose,
6555
+ onConnect,
6556
+ theme = "auto",
6557
+ networks = "all",
6558
+ mode = "wallets",
6559
+ socialAuthMethods = ["google", "email"],
6560
+ onGoogleSignIn,
6561
+ onKingsChatSignIn,
6562
+ onXSignIn,
6563
+ onEmailStart,
6564
+ onEmailVerify,
6565
+ onPhoneStart,
6566
+ onPhoneVerify,
6567
+ customAuthLabel,
6568
+ onCustomAuthSignIn,
6569
+ canUsePasskey = false,
6570
+ passkeyAddress = null,
6571
+ onPasskeySignIn
6572
+ }) {
6573
+ const showSocial = hasSocialMode(mode);
6574
+ const showWallets = mode !== "social";
6575
+ const [view, setView] = (0, import_react3.useState)(showSocial ? "social" : "wallets");
6576
+ const [search, setSearch] = (0, import_react3.useState)("");
6577
+ const [filter, setFilter] = (0, import_react3.useState)("all");
6578
+ const [pendingWallet, setPendingWallet] = (0, import_react3.useState)(null);
6579
+ const [session, setSession] = (0, import_react3.useState)(0);
6580
+ (0, import_react3.useEffect)(() => {
6581
+ if (!open) return;
6582
+ injectFont();
6583
+ injectTokens2(theme);
6584
+ injectModalCss();
6585
+ if (theme !== "auto") return;
6586
+ const mq = window.matchMedia("(prefers-color-scheme: dark)");
6587
+ const handler = () => injectTokens2("auto");
6588
+ mq.addEventListener("change", handler);
6589
+ return () => mq.removeEventListener("change", handler);
6590
+ }, [open, theme]);
6591
+ (0, import_react3.useEffect)(() => {
6592
+ if (!open) {
6593
+ setSearch("");
6594
+ setFilter("all");
6595
+ setPendingWallet(null);
6596
+ setView(showSocial ? "social" : "wallets");
6597
+ setSession((n) => n + 1);
6598
+ return;
6599
+ }
6600
+ return () => {
6601
+ document.getElementById("decane-tokens")?.remove();
6602
+ };
6603
+ }, [open, showWallets, showSocial]);
6604
+ const handleKey = (0, import_react3.useCallback)(
6605
+ (e) => {
6606
+ if (e.key !== "Escape") return;
6607
+ if (pendingWallet) setPendingWallet(null);
6608
+ else onClose();
6609
+ },
6610
+ [onClose, pendingWallet]
6611
+ );
6612
+ (0, import_react3.useEffect)(() => {
6613
+ if (!open) return;
6614
+ document.addEventListener("keydown", handleKey);
6615
+ return () => document.removeEventListener("keydown", handleKey);
6616
+ }, [open, handleKey]);
6617
+ if (!open) return null;
6618
+ const q = search.trim().toLowerCase();
6619
+ const networkWallets = provider.wallets.filter((w) => {
6620
+ const cs = w.chainSupport;
6621
+ if (networks === "evm") return cs.includes("evm");
6622
+ if (networks === "solana") return cs.includes("solana");
6623
+ if (networks === "tron") return cs.includes("tron");
6624
+ if (networks === "bitcoin") return cs.includes("bitcoin");
6625
+ return true;
6626
+ });
6627
+ const baseWallets = filter === "all" ? networkWallets : networkWallets.filter((w) => w.chainSupport.includes(filter));
6628
+ const filtered = q ? baseWallets.filter((w) => w.name.toLowerCase().includes(q)) : baseWallets;
6629
+ const filters = [
6630
+ { id: "all", label: "All" },
6631
+ { id: "evm", label: "EVM" },
6632
+ { id: "solana", label: "Solana" },
6633
+ ...provider.tronWallets?.length ? [{ id: "tron", label: "Tron" }] : [],
6634
+ ...provider.bitcoinWallets?.length ? [{ id: "bitcoin", label: "Bitcoin" }] : []
6635
+ ];
6636
+ function handleWalletClick(wallet) {
6637
+ const cs = wallet.chainSupport;
6638
+ const isMulti = cs.length >= 2;
6639
+ if (isMulti && networks === "all") {
6640
+ setPendingWallet(wallet);
6641
+ } else {
6642
+ const preference = networks === "evm" ? "evm" : networks === "solana" ? "solana" : networks === "tron" ? "tron" : networks === "bitcoin" ? "bitcoin" : void 0;
6643
+ onConnect(wallet, preference);
6644
+ onClose();
6645
+ }
6646
+ }
6647
+ function handleChainChoice(preference) {
6648
+ if (!pendingWallet) return;
6649
+ onConnect(pendingWallet, preference);
6650
+ onClose();
6651
+ }
6652
+ const signInMethods = socialAuthMethods.filter(
6653
+ (m) => m === "google" ? !!onGoogleSignIn : m === "email" ? !!onEmailStart && !!onEmailVerify : true
6654
+ );
6655
+ const noop = async () => {
6656
+ };
6657
+ const noopStart = async () => ({ codeRequired: true });
6658
+ const walletEntry = showWallets ? /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement("div", { className: "dcm-or" }, "or"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "dcm-methods", style: { marginTop: 0 } }, /* @__PURE__ */ import_react3.default.createElement("button", { type: "button", className: "dcm-method", onClick: () => setView("wallets") }, /* @__PURE__ */ import_react3.default.createElement(WalletLineIcon, { size: 18 }), /* @__PURE__ */ import_react3.default.createElement("span", null, "Continue with a wallet"), /* @__PURE__ */ import_react3.default.createElement("span", { className: "dcm-trail" }, networkWallets.length > 0 && /* @__PURE__ */ import_react3.default.createElement("span", { className: "dcm-stack", "aria-label": `${networkWallets.length} detected` }, networkWallets.slice(0, 3).map(
6659
+ (w) => w.icon ? /* @__PURE__ */ import_react3.default.createElement("img", { key: w.id, src: w.icon, alt: "" }) : /* @__PURE__ */ import_react3.default.createElement("span", { key: w.id })
6660
+ )), /* @__PURE__ */ import_react3.default.createElement(ChevronRightIcon, null))))) : null;
6661
+ const closeButton = /* @__PURE__ */ import_react3.default.createElement("button", { type: "button", className: "dcm-icon-btn", style: { right: 14 }, onClick: onClose, "aria-label": "Close" }, /* @__PURE__ */ import_react3.default.createElement(CloseIcon, null));
6662
+ let body;
6663
+ if (pendingWallet) {
6664
+ const support = pendingWallet.chainSupport;
6665
+ body = /* @__PURE__ */ import_react3.default.createElement("div", { className: "dcm-body" }, /* @__PURE__ */ import_react3.default.createElement("button", { type: "button", className: "dcm-icon-btn", style: { left: 14 }, onClick: () => setPendingWallet(null), "aria-label": "Back" }, /* @__PURE__ */ import_react3.default.createElement(ArrowLeftIcon, null)), closeButton, /* @__PURE__ */ import_react3.default.createElement(WalletIcon, { src: pendingWallet.icon || void 0, name: pendingWallet.name, size: 52 }), /* @__PURE__ */ import_react3.default.createElement("h2", { className: "dcm-title" }, "Choose networks"), /* @__PURE__ */ import_react3.default.createElement("p", { className: "dcm-sub" }, pendingWallet.name, " works on more than one network. Pick what to connect."), /* @__PURE__ */ import_react3.default.createElement("div", { className: "dcm-methods" }, /* @__PURE__ */ import_react3.default.createElement("button", { type: "button", className: "dcm-option", onClick: () => handleChainChoice(void 0) }, /* @__PURE__ */ import_react3.default.createElement("span", { className: "dcm-option-icons" }, /* @__PURE__ */ import_react3.default.createElement(ChainIconStack, { support, size: 20 })), /* @__PURE__ */ import_react3.default.createElement("span", { className: "dcm-option-text" }, /* @__PURE__ */ import_react3.default.createElement("b", null, "All networks"), /* @__PURE__ */ import_react3.default.createElement("small", null, "Every address this wallet has")), /* @__PURE__ */ import_react3.default.createElement(ChevronRightIcon, null)), support.map((c) => /* @__PURE__ */ import_react3.default.createElement("button", { key: c, type: "button", className: "dcm-option", onClick: () => handleChainChoice(c) }, /* @__PURE__ */ import_react3.default.createElement("span", { className: "dcm-option-icons" }, /* @__PURE__ */ import_react3.default.createElement(ChainIconStack, { support: [c], size: 20 })), /* @__PURE__ */ import_react3.default.createElement("span", { className: "dcm-option-text" }, /* @__PURE__ */ import_react3.default.createElement("b", null, NETWORK_LABEL[c] ?? c), /* @__PURE__ */ import_react3.default.createElement("small", null, "Only your ", c === "evm" ? "Ethereum-compatible" : NETWORK_LABEL[c] ?? c, " address")), /* @__PURE__ */ import_react3.default.createElement(ChevronRightIcon, null)))), /* @__PURE__ */ import_react3.default.createElement(ProtectedBy, null));
6666
+ } else if (view === "wallets") {
6667
+ body = /* @__PURE__ */ import_react3.default.createElement("div", { className: "dcm-body" }, showSocial && /* @__PURE__ */ import_react3.default.createElement("button", { type: "button", className: "dcm-icon-btn", style: { left: 14 }, onClick: () => setView("social"), "aria-label": "Back to sign-in" }, /* @__PURE__ */ import_react3.default.createElement(ArrowLeftIcon, null)), closeButton, /* @__PURE__ */ import_react3.default.createElement(DecaneMark, { size: 44 }), /* @__PURE__ */ import_react3.default.createElement("h2", { className: "dcm-title" }, "Connect a wallet"), /* @__PURE__ */ import_react3.default.createElement("p", { className: "dcm-sub" }, networkWallets.length ? `${networkWallets.length} wallet${networkWallets.length === 1 ? "" : "s"} found in this browser` : "No wallets found in this browser"), networks === "all" && networkWallets.length > 0 && filters.length > 1 && /* @__PURE__ */ import_react3.default.createElement("div", { className: "dcm-pills", role: "group", "aria-label": "Filter by network" }, filters.map((f) => /* @__PURE__ */ import_react3.default.createElement("button", { key: f.id, type: "button", "aria-pressed": filter === f.id, onClick: () => setFilter(f.id) }, f.label))), networkWallets.length > 5 && /* @__PURE__ */ import_react3.default.createElement("div", { className: "dcm-search" }, /* @__PURE__ */ import_react3.default.createElement(SearchIcon, null), /* @__PURE__ */ import_react3.default.createElement(
6668
+ "input",
7615
6669
  {
7616
- onClick: handleUnlock,
7617
- disabled: unlocking,
7618
- style: {
7619
- flex: 1,
7620
- padding: "10px 0",
7621
- background: "var(--dc-accent)",
7622
- color: "var(--dc-accent-text)",
7623
- border: "none",
7624
- borderRadius: 10,
7625
- fontSize: 13,
7626
- fontWeight: 700,
7627
- cursor: unlocking ? "not-allowed" : "pointer",
7628
- fontFamily: "inherit",
7629
- opacity: unlocking ? 0.7 : 1
7630
- }
7631
- },
7632
- unlocking ? "Unlocking\u2026" : "\u{1F513} Unlock wallet"
7633
- ), /* @__PURE__ */ import_react3.default.createElement(
7634
- "button",
6670
+ className: "dcm-field",
6671
+ type: "text",
6672
+ placeholder: "Search wallets",
6673
+ "aria-label": "Search wallets",
6674
+ value: search,
6675
+ onChange: (e) => setSearch(e.target.value)
6676
+ }
6677
+ )), filtered.length > 0 ? /* @__PURE__ */ import_react3.default.createElement("div", { className: "dcm-list" }, filtered.map((w) => /* @__PURE__ */ import_react3.default.createElement("button", { key: w.id, type: "button", className: "dcm-method", onClick: () => handleWalletClick(w) }, /* @__PURE__ */ import_react3.default.createElement(WalletIcon, { src: w.icon || void 0, name: w.name, size: 26 }), /* @__PURE__ */ import_react3.default.createElement("span", null, w.name), /* @__PURE__ */ import_react3.default.createElement("span", { className: "dcm-trail" }, /* @__PURE__ */ import_react3.default.createElement(ChainIconStack, { support: w.chainSupport, size: 16 }), /* @__PURE__ */ import_react3.default.createElement(ChevronRightIcon, null))))) : /* @__PURE__ */ import_react3.default.createElement("p", { className: "dcm-empty" }, q ? `No wallets match "${search.trim()}".` : networkWallets.length ? "No wallets for this network." : "Install a wallet extension, or unlock the one you have, then reopen this window."), /* @__PURE__ */ import_react3.default.createElement(ProtectedBy, null));
6678
+ } else {
6679
+ body = /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, closeButton, /* @__PURE__ */ import_react3.default.createElement(
6680
+ SignInView,
7635
6681
  {
7636
- onClick: handleDisconnect,
7637
- disabled: disconnecting,
7638
- style: {
7639
- flex: socialAuth.isUnlocked ? 1 : 0,
7640
- padding: "10px 16px",
7641
- background: "transparent",
7642
- border: "1px solid var(--dc-border)",
7643
- borderRadius: 10,
7644
- color: "var(--dc-text-muted)",
7645
- fontSize: 13,
7646
- cursor: disconnecting ? "not-allowed" : "pointer",
7647
- fontFamily: "inherit",
7648
- opacity: disconnecting ? 0.7 : 1,
7649
- whiteSpace: "nowrap"
7650
- }
7651
- },
7652
- disconnecting ? "Signing out\u2026" : "Sign out"
7653
- ))), /* @__PURE__ */ import_react3.default.createElement("div", { style: {
7654
- padding: "11px 16px",
7655
- borderTop: "1px solid var(--dc-border)",
7656
- display: "flex",
7657
- alignItems: "center",
7658
- justifyContent: "center",
7659
- gap: 6
7660
- } }, /* @__PURE__ */ import_react3.default.createElement("span", { style: { fontSize: 10.5, color: "var(--dc-text-muted)", letterSpacing: "0.02em" } }, "Secured by"), /* @__PURE__ */ import_react3.default.createElement(DecaneMark, { size: 13, muted: true }), /* @__PURE__ */ import_react3.default.createElement(DecaneWordmark, { size: 11, muted: true })))
6682
+ key: session,
6683
+ onGoogleSignIn: onGoogleSignIn ?? noop,
6684
+ onKingsChatSignIn,
6685
+ onXSignIn,
6686
+ onEmailStart: onEmailStart ?? noopStart,
6687
+ onEmailVerify: onEmailVerify ?? noop,
6688
+ onPhoneStart,
6689
+ onPhoneVerify,
6690
+ authMethods: signInMethods,
6691
+ customAuthLabel,
6692
+ onCustomAuthSignIn,
6693
+ canUsePasskey,
6694
+ passkeyAddress,
6695
+ onPasskeySignIn,
6696
+ extra: walletEntry
6697
+ }
6698
+ ));
6699
+ }
6700
+ const modal = /* @__PURE__ */ import_react3.default.createElement(
6701
+ "div",
6702
+ {
6703
+ role: "dialog",
6704
+ "aria-modal": "true",
6705
+ "aria-label": pendingWallet ? "Choose networks" : view === "wallets" ? "Connect a wallet" : "Log in or sign up",
6706
+ style: {
6707
+ position: "fixed",
6708
+ inset: 0,
6709
+ zIndex: 9999,
6710
+ display: "flex",
6711
+ alignItems: "center",
6712
+ justifyContent: "center",
6713
+ padding: "16px",
6714
+ // Same fallback chain as SocialWalletModal — without it, this modal
6715
+ // drops to the browser default serif whenever the token block hasn't
6716
+ // been injected, while the social modal still lands on system-ui.
6717
+ fontFamily: "var(--dc-font-sans, system-ui, sans-serif)",
6718
+ WebkitFontSmoothing: "antialiased"
6719
+ }
6720
+ },
6721
+ /* @__PURE__ */ import_react3.default.createElement(
6722
+ "div",
6723
+ {
6724
+ className: "dcm-backdrop",
6725
+ onClick: () => pendingWallet ? setPendingWallet(null) : onClose()
6726
+ }
6727
+ ),
6728
+ /* @__PURE__ */ import_react3.default.createElement("div", { className: "dcm-card" }, body)
7661
6729
  );
7662
6730
  return (0, import_react_dom2.createPortal)(modal, document.body);
7663
6731
  }