@pollar/react 0.11.1 → 0.11.3-rc.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.js CHANGED
@@ -1035,7 +1035,7 @@ var PollarModalFooter = () => {
1035
1035
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-footer-name", children: "Pollar" }),
1036
1036
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-footer-version", children: [
1037
1037
  "v",
1038
- "0.11.1"
1038
+ "0.11.3-rc.1"
1039
1039
  ] })
1040
1040
  ] })
1041
1041
  ] });
@@ -1131,6 +1131,81 @@ function Toggle({ checked, onChange, disabled = false, busy = false, label }) {
1131
1131
  }
1132
1132
  );
1133
1133
  }
1134
+
1135
+ // src/components/modal-theme.ts
1136
+ var DEFAULT_MODAL_BORDER_RADIUS = 16;
1137
+ var DEFAULT_BUTTON_BORDER_RADIUS = 6;
1138
+ var DEFAULT_OVERLAY_Z_INDEX = 50;
1139
+ function px(value, fallback) {
1140
+ return `${typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : fallback}px`;
1141
+ }
1142
+ function color(value, fallback) {
1143
+ return typeof value === "string" && value.trim() !== "" ? value : fallback;
1144
+ }
1145
+ function parseHex(value) {
1146
+ const hex = value.trim().replace(/^#/, "");
1147
+ const full = hex.length === 3 ? [...hex].map((c) => c + c).join("") : hex;
1148
+ if (!/^[0-9a-f]{6}$/i.test(full)) return null;
1149
+ return [Number.parseInt(full.slice(0, 2), 16), Number.parseInt(full.slice(2, 4), 16), Number.parseInt(full.slice(4, 6), 16)];
1150
+ }
1151
+ function readableTextOn(background) {
1152
+ const rgb = parseHex(background);
1153
+ if (!rgb) return "#ffffff";
1154
+ const [r, g, b] = rgb;
1155
+ return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 > 0.6 ? "#111827" : "#ffffff";
1156
+ }
1157
+ function buildModalCssVars(theme, accentColor, overrides = {}, variant = "compact") {
1158
+ const isDark = theme === "dark";
1159
+ const textColor = color(overrides.textColor, isDark ? "#ffffff" : "#111827");
1160
+ const secondaryBg = color(overrides.buttonColor, "");
1161
+ return {
1162
+ "--pollar-accent": accentColor,
1163
+ "--pollar-bg": color(overrides.backgroundColor, isDark ? "#1a1a1a" : "#ffffff"),
1164
+ "--pollar-border": isDark ? "#374151" : "#e5e7eb",
1165
+ "--pollar-text": textColor,
1166
+ "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
1167
+ // The primary button is the accent's, straight up; its label follows the
1168
+ // accent's luminance so a pale accent doesn't render white-on-white.
1169
+ "--pollar-btn-primary-fg": readableTextOn(accentColor),
1170
+ ...secondaryBg ? {
1171
+ "--pollar-btn-secondary-bg": secondaryBg,
1172
+ "--pollar-btn-secondary-fg": readableTextOn(secondaryBg)
1173
+ } : {},
1174
+ "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
1175
+ "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
1176
+ "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
1177
+ "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
1178
+ "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
1179
+ "--pollar-modal-border-radius": px(overrides.modalBorderRadius, DEFAULT_MODAL_BORDER_RADIUS),
1180
+ "--pollar-buttons-border-radius": px(overrides.buttonBorderRadius, DEFAULT_BUTTON_BORDER_RADIUS),
1181
+ "--pollar-buttons-height": "44px",
1182
+ "--pollar-input-height": "44px",
1183
+ "--pollar-input-border-radius": "0.5rem",
1184
+ "--pollar-card-border-radius": "10px",
1185
+ ...variant === "hero" ? {
1186
+ "--pollar-modal-padding": "2rem",
1187
+ "--pollar-modal-heading-size": "1.375rem",
1188
+ "--pollar-modal-subtitle-size": "0.9rem"
1189
+ } : {}
1190
+ };
1191
+ }
1192
+ function modalChrome(styles) {
1193
+ const zIndex = styles.modalZIndex;
1194
+ return {
1195
+ theme: styles.theme ?? "light",
1196
+ accentColor: styles.accentColor ?? "#005DB4",
1197
+ styleOverrides: {
1198
+ backgroundColor: styles.backgroundColor,
1199
+ textColor: styles.textColor,
1200
+ buttonColor: styles.buttonColor,
1201
+ modalBorderRadius: styles.modalBorderRadius,
1202
+ buttonBorderRadius: styles.buttonBorderRadius
1203
+ },
1204
+ overlayStyle: {
1205
+ "--pollar-overlay-z-index": typeof zIndex === "number" && Number.isFinite(zIndex) ? zIndex : DEFAULT_OVERLAY_Z_INDEX
1206
+ }
1207
+ };
1208
+ }
1134
1209
  var PERIOD_LABEL = {
1135
1210
  DAY: "every 24h",
1136
1211
  DAY_CALENDAR: "daily",
@@ -1200,6 +1275,7 @@ function RuleCard({
1200
1275
  function DistributionRulesModalTemplate({
1201
1276
  theme,
1202
1277
  accentColor,
1278
+ styleOverrides,
1203
1279
  state,
1204
1280
  claimingId,
1205
1281
  claimErrors,
@@ -1208,24 +1284,7 @@ function DistributionRulesModalTemplate({
1208
1284
  onClaim,
1209
1285
  onClose
1210
1286
  }) {
1211
- const isDark = theme === "dark";
1212
- const cssVars = {
1213
- "--pollar-accent": accentColor,
1214
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
1215
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
1216
- "--pollar-text": isDark ? "#ffffff" : "#111827",
1217
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
1218
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
1219
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
1220
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
1221
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
1222
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
1223
- "--pollar-buttons-border-radius": "6px",
1224
- "--pollar-buttons-height": "44px",
1225
- "--pollar-input-height": "44px",
1226
- "--pollar-input-border-radius": "0.5rem",
1227
- "--pollar-card-border-radius": "10px"
1228
- };
1287
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
1229
1288
  const isLoading = state.step === "loading";
1230
1289
  const rules = state.step === "loaded" ? state.rules : [];
1231
1290
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1300,7 +1359,7 @@ function DistributionRulesModalTemplate({
1300
1359
  }
1301
1360
  function DistributionRulesModal({ onClose }) {
1302
1361
  const { getClient, styles } = usePollar();
1303
- const { theme = "light", accentColor = "#005DB4" } = styles;
1362
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
1304
1363
  const [state, setState] = react.useState({ step: "idle" });
1305
1364
  const [claimingId, setClaimingId] = react.useState(null);
1306
1365
  const [claimErrors, setClaimErrors] = react.useState({});
@@ -1343,11 +1402,12 @@ function DistributionRulesModal({ onClose }) {
1343
1402
  },
1344
1403
  [getClient]
1345
1404
  );
1346
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
1405
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
1347
1406
  DistributionRulesModalTemplate,
1348
1407
  {
1349
1408
  theme,
1350
1409
  accentColor,
1410
+ styleOverrides,
1351
1411
  state,
1352
1412
  claimingId,
1353
1413
  claimErrors,
@@ -1419,26 +1479,6 @@ function useChains() {
1419
1479
  return { chains, primaryChain, primaryAddress: addressForChain(wallets, primaryChain), ready: true };
1420
1480
  }, [wallets, configured, ready]);
1421
1481
  }
1422
- function cssVarsFor(theme, accentColor) {
1423
- const isDark = theme === "dark";
1424
- return {
1425
- "--pollar-accent": accentColor,
1426
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
1427
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
1428
- "--pollar-text": isDark ? "#ffffff" : "#111827",
1429
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
1430
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
1431
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
1432
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
1433
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
1434
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
1435
- "--pollar-buttons-border-radius": "6px",
1436
- "--pollar-buttons-height": "44px",
1437
- "--pollar-input-height": "44px",
1438
- "--pollar-input-border-radius": "0.5rem",
1439
- "--pollar-card-border-radius": "10px"
1440
- };
1441
- }
1442
1482
  function assetKey(record) {
1443
1483
  return record.code + (record.issuer ?? "");
1444
1484
  }
@@ -1485,6 +1525,7 @@ function AssetItem({
1485
1525
  function EnabledAssetsModalTemplate({
1486
1526
  theme,
1487
1527
  accentColor,
1528
+ styleOverrides,
1488
1529
  enabledAssets,
1489
1530
  walletAddress,
1490
1531
  chains,
@@ -1497,7 +1538,7 @@ function EnabledAssetsModalTemplate({
1497
1538
  onToggleTrustline,
1498
1539
  onAddCustom
1499
1540
  }) {
1500
- const cssVars = cssVarsFor(theme, accentColor);
1541
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
1501
1542
  const isLoading = enabledAssets.step === "loading";
1502
1543
  const data = useStickyData(enabledAssets.step === "loaded" ? enabledAssets.data : null);
1503
1544
  const busy = busyKey !== null;
@@ -1589,13 +1630,14 @@ function isValidIssuer(issuer) {
1589
1630
  function CustomTrustlineModalTemplate({
1590
1631
  theme,
1591
1632
  accentColor,
1633
+ styleOverrides,
1592
1634
  busy,
1593
1635
  actionError,
1594
1636
  onBack,
1595
1637
  onClose,
1596
1638
  onSubmit
1597
1639
  }) {
1598
- const cssVars = cssVarsFor(theme, accentColor);
1640
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
1599
1641
  const [code, setCode] = react.useState("");
1600
1642
  const [issuer, setIssuer] = react.useState("");
1601
1643
  const [limit, setLimit] = react.useState("");
@@ -1692,7 +1734,7 @@ function assetKey2(record) {
1692
1734
  }
1693
1735
  function EnabledAssetsModal({ onClose }) {
1694
1736
  const { enabledAssets, refreshAssets, setTrustline, wallets, styles } = usePollar();
1695
- const { theme = "light", accentColor = "#005DB4" } = styles;
1737
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
1696
1738
  const { chains } = useChains();
1697
1739
  const [selectedChain, setSelectedChain] = react.useState(null);
1698
1740
  react.useEffect(() => {
@@ -1743,11 +1785,12 @@ function EnabledAssetsModal({ onClose }) {
1743
1785
  },
1744
1786
  [runAction]
1745
1787
  );
1746
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: onClose, children: view === "list" ? /* @__PURE__ */ jsxRuntime.jsx(
1788
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: view === "list" ? /* @__PURE__ */ jsxRuntime.jsx(
1747
1789
  EnabledAssetsModalTemplate,
1748
1790
  {
1749
1791
  theme,
1750
1792
  accentColor,
1793
+ styleOverrides,
1751
1794
  enabledAssets,
1752
1795
  walletAddress,
1753
1796
  chains,
@@ -1768,6 +1811,7 @@ function EnabledAssetsModal({ onClose }) {
1768
1811
  {
1769
1812
  theme,
1770
1813
  accentColor,
1814
+ styleOverrides,
1771
1815
  busy: busyKey === "custom",
1772
1816
  actionError,
1773
1817
  onBack: () => {
@@ -1802,6 +1846,7 @@ function KycStatus({ status, className }) {
1802
1846
  function KycModalTemplate({
1803
1847
  theme,
1804
1848
  accentColor,
1849
+ styleOverrides,
1805
1850
  step,
1806
1851
  providers,
1807
1852
  selectedProvider,
@@ -1813,27 +1858,7 @@ function KycModalTemplate({
1813
1858
  onRefresh,
1814
1859
  onClose
1815
1860
  }) {
1816
- const isDark = theme === "dark";
1817
- const cssVars = {
1818
- "--pollar-accent": accentColor,
1819
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
1820
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
1821
- "--pollar-text": isDark ? "#ffffff" : "#111827",
1822
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
1823
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
1824
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
1825
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
1826
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
1827
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
1828
- "--pollar-buttons-border-radius": "6px",
1829
- "--pollar-buttons-height": "44px",
1830
- "--pollar-input-height": "44px",
1831
- "--pollar-input-border-radius": "0.5rem",
1832
- "--pollar-card-border-radius": "10px",
1833
- "--pollar-modal-padding": "2rem",
1834
- "--pollar-modal-heading-size": "1.375rem",
1835
- "--pollar-modal-subtitle-size": "0.9rem"
1836
- };
1861
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides, "hero");
1837
1862
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-kyc-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
1838
1863
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-header", children: [
1839
1864
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-kyc-header-text", children: [
@@ -1932,7 +1957,7 @@ function KycModal({ onClose, country = "MX", level = "basic", onApproved }) {
1932
1957
  const [kycStatus, setKycStatus] = react.useState("none");
1933
1958
  const [isLoading, setIsLoading] = react.useState(false);
1934
1959
  const client = getClient();
1935
- const { theme = "light", accentColor = "#005DB4" } = styles;
1960
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
1936
1961
  const loadProviders = react.useCallback(() => {
1937
1962
  setIsLoading(true);
1938
1963
  return getClient().getKycProviders(country).then((result) => setProviders(result.providers)).catch(() => setProviders([])).finally(() => setIsLoading(false));
@@ -1972,11 +1997,12 @@ function KycModal({ onClose, country = "MX", level = "basic", onApproved }) {
1972
1997
  setStep("done");
1973
1998
  }
1974
1999
  }
1975
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
2000
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
1976
2001
  KycModalTemplate,
1977
2002
  {
1978
2003
  theme,
1979
2004
  accentColor,
2005
+ styleOverrides,
1980
2006
  step,
1981
2007
  providers,
1982
2008
  selectedProvider,
@@ -2168,32 +2194,10 @@ function authStateToStatus(step) {
2168
2194
  if (error.includes(step)) return "ERROR";
2169
2195
  return "NONE";
2170
2196
  }
2171
- function buildModalCssVars(theme, accentColor) {
2172
- const isDark = theme === "dark";
2173
- return {
2174
- "--pollar-accent": accentColor,
2175
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
2176
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
2177
- "--pollar-text": isDark ? "#ffffff" : "#111827",
2178
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
2179
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
2180
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
2181
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
2182
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
2183
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
2184
- "--pollar-buttons-border-radius": "6px",
2185
- "--pollar-buttons-height": "44px",
2186
- "--pollar-input-height": "44px",
2187
- "--pollar-input-border-radius": "0.5rem",
2188
- "--pollar-card-border-radius": "10px",
2189
- "--pollar-modal-padding": "2rem",
2190
- "--pollar-modal-heading-size": "1.375rem",
2191
- "--pollar-modal-subtitle-size": "0.9rem"
2192
- };
2193
- }
2194
2197
  function LoginModalTemplate({
2195
2198
  theme,
2196
2199
  accentColor,
2200
+ styleOverrides,
2197
2201
  logoUrl,
2198
2202
  emailEnabled,
2199
2203
  embeddedWallets,
@@ -2227,7 +2231,7 @@ function LoginModalTemplate({
2227
2231
  return acc;
2228
2232
  }, []);
2229
2233
  const activeGroupAdapters = walletGroups.find((g) => g.label === activeGroup)?.adapters ?? [];
2230
- const cssVars = buildModalCssVars(theme, accentColor);
2234
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides, "hero");
2231
2235
  const status = authStateToStatus(authState.step);
2232
2236
  const isLoading = status === "LOADING";
2233
2237
  const isEmailCodeError = authState.step === "error" && (authState.errorCode === core.AUTH_ERROR_CODES.EMAIL_CODE_EXPIRED || authState.errorCode === core.AUTH_ERROR_CODES.EMAIL_CODE_INVALID);
@@ -2406,12 +2410,13 @@ function LoginModalStatus({
2406
2410
  status,
2407
2411
  theme,
2408
2412
  accentColor,
2413
+ styleOverrides,
2409
2414
  logoUrl,
2410
2415
  appName,
2411
2416
  onRetry,
2412
2417
  onCancel
2413
2418
  }) {
2414
- const cssVars = buildModalCssVars(theme, accentColor);
2419
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides, "hero");
2415
2420
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
2416
2421
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-close-btn", onClick: onCancel, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx(
2417
2422
  "svg",
@@ -2446,6 +2451,7 @@ function PrivyLoginSubmodal({
2446
2451
  adapter,
2447
2452
  theme,
2448
2453
  accentColor,
2454
+ styleOverrides,
2449
2455
  logoUrl,
2450
2456
  appName,
2451
2457
  onBack,
@@ -2457,28 +2463,8 @@ function PrivyLoginSubmodal({
2457
2463
  const [view, setView] = react.useState("root");
2458
2464
  const [status, setStatus] = react.useState("NONE");
2459
2465
  const [message, setMessage] = react.useState("");
2460
- const isDark = theme === "dark";
2461
2466
  const isLoading = status === "LOADING";
2462
- const cssVars = {
2463
- "--pollar-accent": accentColor,
2464
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
2465
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
2466
- "--pollar-text": isDark ? "#ffffff" : "#111827",
2467
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
2468
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
2469
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
2470
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
2471
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
2472
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
2473
- "--pollar-buttons-border-radius": "6px",
2474
- "--pollar-buttons-height": "44px",
2475
- "--pollar-input-height": "44px",
2476
- "--pollar-input-border-radius": "0.5rem",
2477
- "--pollar-card-border-radius": "10px",
2478
- "--pollar-modal-padding": "2rem",
2479
- "--pollar-modal-heading-size": "1.375rem",
2480
- "--pollar-modal-subtitle-size": "0.9rem"
2481
- };
2467
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides, "hero");
2482
2468
  function fail(error) {
2483
2469
  setStatus("ERROR");
2484
2470
  setMessage(error instanceof Error ? error.message : "Something went wrong. Please try again.");
@@ -2635,8 +2621,10 @@ function LoginModal({ onClose }) {
2635
2621
  }
2636
2622
  };
2637
2623
  }, [getClient]);
2638
- const { theme = "light", accentColor = "#005DB4", logoUrl, emailEnabled, embeddedWallets, smartWallet, providers } = styles;
2624
+ const { logoUrl, emailEnabled, embeddedWallets, smartWallet, providers } = styles;
2625
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
2639
2626
  const smartWalletEnabled = smartWallet ?? false;
2627
+ const modalTitle = styles.modalTitle?.trim() || config.application?.name || "Pollar";
2640
2628
  function handleClose() {
2641
2629
  setEmail("");
2642
2630
  getClient().cancelLogin();
@@ -2684,14 +2672,15 @@ function LoginModal({ onClose }) {
2684
2672
  getClient().login({ provider });
2685
2673
  }
2686
2674
  }
2687
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: handleClose, children: configStatus !== "ready" ? /* @__PURE__ */ jsxRuntime.jsx(
2675
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: handleClose, children: configStatus !== "ready" ? /* @__PURE__ */ jsxRuntime.jsx(
2688
2676
  LoginModalStatus,
2689
2677
  {
2690
2678
  status: configStatus === "error" ? "error" : "loading",
2691
2679
  theme,
2692
2680
  accentColor,
2681
+ styleOverrides,
2693
2682
  logoUrl: logoUrl ?? null,
2694
- appName: config.application?.name ?? "Pollar",
2683
+ appName: modalTitle,
2695
2684
  onRetry: retryConfig,
2696
2685
  onCancel: handleClose
2697
2686
  }
@@ -2701,8 +2690,9 @@ function LoginModal({ onClose }) {
2701
2690
  adapter: interactiveAdapter,
2702
2691
  theme,
2703
2692
  accentColor,
2693
+ styleOverrides,
2704
2694
  logoUrl: logoUrl ?? null,
2705
- appName: config.application?.name ?? "Pollar",
2695
+ appName: modalTitle,
2706
2696
  onBack: () => setInteractiveAdapter(null),
2707
2697
  onCancel: handleClose,
2708
2698
  onAuthenticated: handleInteractiveAuthenticated
@@ -2712,6 +2702,7 @@ function LoginModal({ onClose }) {
2712
2702
  {
2713
2703
  theme,
2714
2704
  accentColor,
2705
+ styleOverrides,
2715
2706
  logoUrl: logoUrl ?? null,
2716
2707
  emailEnabled: !!emailEnabled,
2717
2708
  embeddedWallets: !!embeddedWallets,
@@ -2724,7 +2715,7 @@ function LoginModal({ onClose }) {
2724
2715
  apple: !!providers?.apple
2725
2716
  },
2726
2717
  walletAdapters,
2727
- appName: config.application?.name ?? "Pollar",
2718
+ appName: modalTitle,
2728
2719
  email,
2729
2720
  onEmailChange: setEmail,
2730
2721
  onEmailSubmit: handleEmailSubmit,
@@ -2747,34 +2738,36 @@ var RAIL_LABELS = {
2747
2738
  PSE: "PSE (Colombia)",
2748
2739
  ACH: "ACH (US)"
2749
2740
  };
2750
- function RouteDisplay({ quote, onSelect }) {
2741
+ function RouteDisplay({ quote, busy = false, disabled = false, onSelect }) {
2742
+ const inert = busy || disabled;
2743
+ const select = () => {
2744
+ if (!inert) onSelect(quote);
2745
+ };
2751
2746
  return /* @__PURE__ */ jsxRuntime.jsxs(
2752
2747
  "div",
2753
2748
  {
2754
2749
  className: "pollar-ramp-route-card",
2755
2750
  "data-recommended": quote.recommended,
2751
+ "data-busy": busy || void 0,
2752
+ "data-disabled": disabled || void 0,
2756
2753
  role: "button",
2757
- tabIndex: 0,
2758
- onClick: () => onSelect(quote),
2759
- onKeyDown: (e) => e.key === "Enter" && onSelect(quote),
2754
+ "aria-busy": busy,
2755
+ "aria-disabled": inert,
2756
+ tabIndex: inert ? -1 : 0,
2757
+ onClick: select,
2758
+ onKeyDown: (e) => e.key === "Enter" && select(),
2760
2759
  children: [
2761
2760
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-route-left", children: [
2762
2761
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-route-provider", children: quote.provider }),
2763
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-ramp-route-meta", children: [
2764
- RAIL_LABELS[quote.rail] ?? quote.rail,
2765
- " \xB7 ",
2766
- quote.protocol,
2767
- " \xB7 ",
2768
- quote.estimatedTime
2769
- ] })
2762
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-route-meta", children: busy ? "Starting\u2026" : `${RAIL_LABELS[quote.rail] ?? quote.rail} \xB7 ${quote.protocol} \xB7 ${quote.estimatedTime}` })
2770
2763
  ] }),
2771
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-route-right", children: [
2764
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-route-right", children: busy ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-spinner pollar-spinner-sm" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2772
2765
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-ramp-route-fee", children: [
2773
2766
  quote.fee,
2774
2767
  "% fee"
2775
2768
  ] }),
2776
2769
  quote.recommended && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-route-badge", children: "Best rate" })
2777
- ] })
2770
+ ] }) })
2778
2771
  ]
2779
2772
  }
2780
2773
  );
@@ -2782,10 +2775,24 @@ function RouteDisplay({ quote, onSelect }) {
2782
2775
  var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2783
2776
  function isFieldValid(spec, raw) {
2784
2777
  const value = (raw ?? "").trim();
2785
- if (!value) return false;
2778
+ if (!value) return spec.optional === true;
2786
2779
  if (spec.type === "email") return EMAIL_RE.test(value);
2787
2780
  return true;
2788
2781
  }
2782
+ function listOf(items) {
2783
+ const last = items[items.length - 1];
2784
+ if (last === void 0) return "a few details";
2785
+ if (items.length === 1) return last;
2786
+ return `${items.slice(0, -1).join(", ")} and ${last}`;
2787
+ }
2788
+ function placeholderFor(field, fields, values) {
2789
+ if (field.placeholderFrom) {
2790
+ const source = fields.find((f) => f.key === field.placeholderFrom);
2791
+ const chosen = source?.options?.find((o) => o.value === values[field.placeholderFrom]);
2792
+ if (chosen?.placeholder) return chosen.placeholder;
2793
+ }
2794
+ return field.placeholder;
2795
+ }
2789
2796
  var LOADING_STEPS = ["Detecting your country\u2026", "Consulting providers\u2026", "Route found!"];
2790
2797
  function flagEmoji(code) {
2791
2798
  const cc = code.trim().toUpperCase();
@@ -2799,47 +2806,19 @@ var STATUS_LABEL = {
2799
2806
  completed: "Completed",
2800
2807
  failed: "Failed"
2801
2808
  };
2802
- var INSTRUCTION_LABELS = {
2803
- br_code: "Pix code",
2804
- account_holder_name: "Account holder",
2805
- bank_name: "Bank",
2806
- bank_address: "Bank address",
2807
- bank_account_number: "Account number",
2808
- bank_routing_number: "Routing number",
2809
- iban: "IBAN",
2810
- bic: "BIC",
2811
- clabe: "CLABE",
2812
- amount: "Amount",
2813
- currency: "Currency",
2814
- payment_rails: "Rails"
2815
- };
2816
- function flattenInstructions(instr) {
2817
- const out = [];
2818
- for (const [k, v] of Object.entries(instr)) {
2819
- if (k === "qrBase64") {
2820
- if (typeof v === "string" && v) out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? "Payment QR", value: v, kind: "qr" });
2821
- continue;
2822
- }
2823
- if ((k === "expiresAt" || k === "expires_at") && (typeof v === "number" || typeof v === "string")) {
2824
- const ms = Number(v);
2825
- if (Number.isFinite(ms) && ms > 0) {
2826
- out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? "Expires", value: new Date(ms).toLocaleString(), kind: "datetime" });
2827
- }
2828
- continue;
2829
- }
2830
- let value;
2831
- if (typeof v === "string" || typeof v === "number") value = String(v);
2832
- else if (Array.isArray(v)) value = v.filter((x) => typeof x === "string" || typeof x === "number").join(", ");
2833
- else continue;
2834
- if (!value) continue;
2835
- out.push({ key: k, label: INSTRUCTION_LABELS[k] ?? k, value, kind: "text" });
2836
- }
2837
- return out;
2809
+ function displayValue(field) {
2810
+ if (field.type !== "datetime") return field.value;
2811
+ const at = new Date(field.value);
2812
+ return Number.isNaN(at.getTime()) ? field.value : at.toLocaleString();
2838
2813
  }
2839
2814
  function RampWidgetTemplate({
2840
2815
  theme,
2841
2816
  accentColor,
2817
+ styleOverrides,
2842
2818
  step,
2819
+ flowSteps,
2820
+ flowStepIndex,
2821
+ startingQuoteId,
2843
2822
  direction,
2844
2823
  amount,
2845
2824
  currency,
@@ -2855,6 +2834,8 @@ function RampWidgetTemplate({
2855
2834
  txStatus,
2856
2835
  kycUrl,
2857
2836
  tosUrl,
2837
+ kycBlocking,
2838
+ kycJustApproved,
2858
2839
  stellarTxHash,
2859
2840
  explorerUrl,
2860
2841
  depositInstructions,
@@ -2871,31 +2852,12 @@ function RampWidgetTemplate({
2871
2852
  onOpenKyc,
2872
2853
  onOpenTos,
2873
2854
  onCompleteWithdraw,
2855
+ onBack,
2874
2856
  onRetry,
2875
2857
  onRefresh,
2876
2858
  onClose
2877
2859
  }) {
2878
- const isDark = theme === "dark";
2879
- const cssVars = {
2880
- "--pollar-accent": accentColor,
2881
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
2882
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
2883
- "--pollar-text": isDark ? "#ffffff" : "#111827",
2884
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
2885
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
2886
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
2887
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
2888
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
2889
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
2890
- "--pollar-buttons-border-radius": "6px",
2891
- "--pollar-buttons-height": "44px",
2892
- "--pollar-input-height": "44px",
2893
- "--pollar-input-border-radius": "0.5rem",
2894
- "--pollar-card-border-radius": "10px",
2895
- "--pollar-modal-padding": "2rem",
2896
- "--pollar-modal-heading-size": "1.375rem",
2897
- "--pollar-modal-subtitle-size": "0.9rem"
2898
- };
2860
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides, "hero");
2899
2861
  const stepTitle = {
2900
2862
  input: direction === "onramp" ? "Buy crypto" : "Sell crypto",
2901
2863
  loading_quote: "Finding best route",
@@ -2908,7 +2870,11 @@ function RampWidgetTemplate({
2908
2870
  input: direction === "onramp" ? "Enter the amount you want to deposit" : "Enter the amount you want to withdraw",
2909
2871
  loading_quote: "Comparing providers in real time\u2026",
2910
2872
  select_route: "All prices include fees",
2911
- contact: `${provider || "This provider"} needs your name and email to verify you`,
2873
+ // What this step actually asks for is whatever the route declared, and that
2874
+ // is rarely a name and an email: an Abroad off-ramp asks where to send the
2875
+ // money, not who you are. Say which, rather than asserting the Bridge case
2876
+ // over every provider.
2877
+ contact: `${provider || "This provider"} needs ${listOf(requiredFields.filter((f) => !f.optional).map((f) => f.label.toLowerCase()))} to continue`,
2912
2878
  status: `Finish the flow at ${provider || "the provider"} to continue`,
2913
2879
  error: "Please try again"
2914
2880
  };
@@ -2943,6 +2909,26 @@ function RampWidgetTemplate({
2943
2909
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
2944
2910
  ] })
2945
2911
  ] }),
2912
+ flowStepIndex >= 0 && flowSteps.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-steps", children: [
2913
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pollar-ramp-steps-label", children: [
2914
+ "Step ",
2915
+ flowStepIndex + 1,
2916
+ " of ",
2917
+ flowSteps.length
2918
+ ] }),
2919
+ /* @__PURE__ */ jsxRuntime.jsx(
2920
+ "div",
2921
+ {
2922
+ className: "pollar-ramp-steps-track",
2923
+ role: "progressbar",
2924
+ "aria-valuenow": flowStepIndex + 1,
2925
+ "aria-valuemin": 1,
2926
+ "aria-valuemax": flowSteps.length,
2927
+ "aria-label": flowSteps[flowStepIndex],
2928
+ children: flowSteps.map((label, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-steps-segment", "data-done": i <= flowStepIndex || void 0 }, label))
2929
+ }
2930
+ )
2931
+ ] }),
2946
2932
  step === "input" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2947
2933
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-tabs", children: [
2948
2934
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2993,7 +2979,8 @@ function RampWidgetTemplate({
2993
2979
  min: "0",
2994
2980
  onChange: (e) => onAmountChange(e.target.value)
2995
2981
  }
2996
- )
2982
+ ),
2983
+ errorMsg && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-field-error", children: errorMsg })
2997
2984
  ] }),
2998
2985
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
2999
2986
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" }),
@@ -3017,12 +3004,25 @@ function RampWidgetTemplate({
3017
3004
  ] }, i))
3018
3005
  ] }),
3019
3006
  step === "select_route" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3020
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-route-list", children: quotes.map((q, i) => /* @__PURE__ */ jsxRuntime.jsx(RouteDisplay, { quote: q, onSelect: onSelectQuote }, i)) }),
3021
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onClose, children: "Cancel" })
3007
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-route-list", children: quotes.map((q, i) => /* @__PURE__ */ jsxRuntime.jsx(
3008
+ RouteDisplay,
3009
+ {
3010
+ quote: q,
3011
+ busy: startingQuoteId != null && q.quoteId === startingQuoteId,
3012
+ disabled: startingQuoteId != null && q.quoteId !== startingQuoteId,
3013
+ onSelect: onSelectQuote
3014
+ },
3015
+ i
3016
+ )) }),
3017
+ errorMsg && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-ramp-payment-note", style: { color: "var(--pollar-error-text)" }, children: errorMsg }),
3018
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: errorMsg ? "pollar-btn-primary" : "pollar-btn-secondary", onClick: onBack, children: "Back" })
3022
3019
  ] }),
3023
3020
  step === "contact" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3024
3021
  requiredFields.map((f) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-field", children: [
3025
- /* @__PURE__ */ jsxRuntime.jsx("label", { className: "pollar-ramp-label", children: f.label }),
3022
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "pollar-ramp-label", children: [
3023
+ f.label,
3024
+ f.optional && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-field-optional", children: " (optional)" })
3025
+ ] }),
3026
3026
  f.type === "select" ? /* @__PURE__ */ jsxRuntime.jsxs(
3027
3027
  "select",
3028
3028
  {
@@ -3040,14 +3040,16 @@ function RampWidgetTemplate({
3040
3040
  type: f.type,
3041
3041
  className: "pollar-ramp-input",
3042
3042
  value: fieldValues[f.key] ?? "",
3043
+ placeholder: placeholderFor(f, requiredFields, fieldValues),
3043
3044
  autoComplete: f.type === "email" ? "email" : "off",
3044
3045
  onChange: (e) => onFieldChange(f.key, e.target.value)
3045
3046
  }
3046
3047
  ),
3048
+ f.hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-field-hint", children: f.hint }),
3047
3049
  f.type === "email" && (fieldValues[f.key] ?? "").trim() !== "" && !isFieldValid(f, fieldValues[f.key]) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-field-error", children: "Enter a valid email address." })
3048
3050
  ] }, f.key)),
3049
3051
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-actions", children: [
3050
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onRetry, children: "Back" }),
3052
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-secondary", onClick: onBack, children: "Back" }),
3051
3053
  /* @__PURE__ */ jsxRuntime.jsx(
3052
3054
  "button",
3053
3055
  {
@@ -3119,20 +3121,44 @@ function RampWidgetTemplate({
3119
3121
  )
3120
3122
  ] })
3121
3123
  ] }),
3122
- depositInstructions && txStatus !== "completed" && flattenInstructions(depositInstructions).map(({ key, label, value, kind }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
3123
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: label }),
3124
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-payment-value", children: kind === "qr" ? /* @__PURE__ */ jsxRuntime.jsx(
3124
+ depositInstructions?.scannable && txStatus !== "completed" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
3125
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: "Payment QR" }),
3126
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-payment-value", children: depositInstructions.scannable.image.inlineSafe ? /* @__PURE__ */ jsxRuntime.jsx(
3127
+ "div",
3128
+ {
3129
+ className: "pollar-ramp-qr",
3130
+ "aria-label": "Payment QR",
3131
+ dangerouslySetInnerHTML: { __html: depositInstructions.scannable.image.data }
3132
+ }
3133
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
3125
3134
  "img",
3126
3135
  {
3127
- src: value.startsWith("data:") ? value : `data:image/png;base64,${value}`,
3128
- alt: label,
3136
+ src: `data:${depositInstructions.scannable.image.mediaType};base64,${depositInstructions.scannable.image.data}`,
3137
+ alt: "Payment QR",
3129
3138
  style: { width: "100%", maxWidth: 220, height: "auto", display: "block", margin: "0 auto" }
3130
3139
  }
3131
- ) : kind === "datetime" ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: value }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
3132
- /* @__PURE__ */ jsxRuntime.jsx("code", { style: { flex: 1, wordBreak: "break-all" }, children: value }),
3133
- /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value, label: `Copy ${label}` })
3140
+ ) })
3141
+ ] }),
3142
+ depositInstructions?.scannable?.payload && depositInstructions.scannable.payloadLabel && txStatus !== "completed" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
3143
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: depositInstructions.scannable.payloadLabel }),
3144
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-payment-value", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
3145
+ /* @__PURE__ */ jsxRuntime.jsx("code", { style: { flex: 1, wordBreak: "break-all" }, children: depositInstructions.scannable.payload }),
3146
+ /* @__PURE__ */ jsxRuntime.jsx(
3147
+ CopyButton,
3148
+ {
3149
+ value: depositInstructions.scannable.payload,
3150
+ label: `Copy ${depositInstructions.scannable.payloadLabel}`
3151
+ }
3152
+ )
3134
3153
  ] }) })
3135
- ] }, key)),
3154
+ ] }),
3155
+ depositInstructions && txStatus !== "completed" && depositInstructions.fields.map((f) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-ramp-payment-field", children: [
3156
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-ramp-payment-label", children: f.label }),
3157
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-ramp-payment-value", children: f.copyable ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
3158
+ /* @__PURE__ */ jsxRuntime.jsx("code", { style: { flex: 1, wordBreak: "break-all" }, children: f.value }),
3159
+ /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: f.value, label: `Copy ${f.label}` })
3160
+ ] }) : f.type === "url" ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: f.value, target: "_blank", rel: "noopener noreferrer", children: f.value }) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: displayValue(f) }) })
3161
+ ] }, f.key)),
3136
3162
  tosUrl && !depositInstructions && txStatus !== "completed" && /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "pollar-btn-primary", onClick: onOpenTos, children: [
3137
3163
  "Accept terms at ",
3138
3164
  provider
@@ -3141,6 +3167,16 @@ function RampWidgetTemplate({
3141
3167
  "Continue at ",
3142
3168
  provider
3143
3169
  ] }),
3170
+ kycBlocking && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-ramp-payment-note", children: [
3171
+ provider,
3172
+ " needs to verify your identity before this payout. Nothing has been sent yet \u2014 complete verification with ",
3173
+ provider,
3174
+ ", and this will update on its own."
3175
+ ] }),
3176
+ kycJustApproved && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "pollar-ramp-payment-note", children: [
3177
+ provider,
3178
+ " approved your verification. Request a new quote to continue \u2014 the previous one was consumed."
3179
+ ] }),
3144
3180
  canComplete && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", disabled: completing, onClick: onCompleteWithdraw, children: completing ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3145
3181
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-spinner pollar-spinner-sm" }),
3146
3182
  "Submitting\u2026"
@@ -3161,11 +3197,53 @@ var TERMINAL = ["completed", "failed"];
3161
3197
  function requiredFieldsOf(quote) {
3162
3198
  return quote.requiredFields ?? [];
3163
3199
  }
3200
+ function flowStepsOf(quotes, selected) {
3201
+ const needsDetails = selected != null ? requiredFieldsOf(selected).length > 0 : quotes.some((q) => requiredFieldsOf(q).length > 0);
3202
+ return needsDetails ? ["Amount", "Provider", "Details", "Complete"] : ["Amount", "Provider", "Complete"];
3203
+ }
3204
+ var STEP_LABEL = {
3205
+ input: "Amount",
3206
+ loading_quote: "Amount",
3207
+ select_route: "Provider",
3208
+ contact: "Details",
3209
+ status: "Complete"
3210
+ };
3211
+ function brokenLimitOf(amount, quote) {
3212
+ const { minAmount, maxAmount } = quote;
3213
+ if (!Number.isFinite(amount)) return null;
3214
+ if (minAmount != null && amount < minAmount) return { limit: "min", value: minAmount };
3215
+ if (maxAmount != null && amount > maxAmount) return { limit: "max", value: maxAmount };
3216
+ return null;
3217
+ }
3218
+ function limitMessage(limit, value, currency) {
3219
+ return `The ${limit === "min" ? "minimum" : "maximum"} amount for this route is ${value} ${currency}.`;
3220
+ }
3221
+ var RAMP_ERROR_MESSAGES = {
3222
+ SDK_RAMPS_QUOTE_EXPIRED: "This quote expired. Request a new one and try again.",
3223
+ SDK_RAMPS_ASSET_NOT_ENABLED: "This currency is not available for that route right now.",
3224
+ SDK_RAMPS_KYC_REQUIRED: "The provider needs to verify your identity before continuing.",
3225
+ SDK_RAMPS_WALLET_UNSUPPORTED: "This wallet type cannot be used for this ramp.",
3226
+ SDK_RAMPS_PROVIDER_NOT_CONFIGURED: "This ramp provider is not configured for this app yet.",
3227
+ SDK_RAMPS_ANCHOR_ERROR: "The provider rejected the request. Please try again in a moment.",
3228
+ SDK_RAMPS_BRIDGE_ERROR: "The provider rejected the request. Please try again in a moment."
3229
+ };
3230
+ function rampErrorMessage(e, fallback) {
3231
+ const body = e?.body;
3232
+ const code = e?.code;
3233
+ if (typeof code !== "string") return e instanceof Error ? e.message : fallback;
3234
+ const limit = body?.limit;
3235
+ const value = body?.limitAmount;
3236
+ const currency = body?.limitCurrency;
3237
+ if ((limit === "min" || limit === "max") && typeof value === "number" && typeof currency === "string") {
3238
+ return limitMessage(limit, value, currency);
3239
+ }
3240
+ return RAMP_ERROR_MESSAGES[code] ?? (e instanceof Error ? e.message : fallback);
3241
+ }
3164
3242
  function RampWidget({ onClose }) {
3165
3243
  const { getClient, signTx, wallet, styles, network } = usePollar();
3166
3244
  const walletAddress = wallet?.address ?? "";
3167
3245
  const client = getClient();
3168
- const { theme = "light", accentColor = "#005DB4" } = styles;
3246
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
3169
3247
  const [step, setStep] = react.useState("input");
3170
3248
  const [direction, setDirection] = react.useState("onramp");
3171
3249
  const [amount, setAmount] = react.useState("");
@@ -3183,6 +3261,8 @@ function RampWidget({ onClose }) {
3183
3261
  const [provider, setProvider] = react.useState("");
3184
3262
  const [kycUrl, setKycUrl] = react.useState(null);
3185
3263
  const [tosUrl, setTosUrl] = react.useState(null);
3264
+ const [kycPending, setKycPending] = react.useState(false);
3265
+ const [kycApproved, setKycApproved] = react.useState(false);
3186
3266
  const [txStatus, setTxStatus] = react.useState(null);
3187
3267
  const [stellarTxHash, setStellarTxHash] = react.useState(null);
3188
3268
  const [depositInstructions, setDepositInstructions] = react.useState(null);
@@ -3211,6 +3291,23 @@ function RampWidget({ onClose }) {
3211
3291
  clearInterval(id);
3212
3292
  };
3213
3293
  }, [step, txId, txStatus, client]);
3294
+ react.useEffect(() => {
3295
+ if (step !== "status" || !kycPending || kycApproved) return;
3296
+ let active = true;
3297
+ const check = async () => {
3298
+ try {
3299
+ const { hasApproved } = await client.getRampKycStatus();
3300
+ if (active && hasApproved) setKycApproved(true);
3301
+ } catch {
3302
+ }
3303
+ };
3304
+ void check();
3305
+ const id = setInterval(check, 1e4);
3306
+ return () => {
3307
+ active = false;
3308
+ clearInterval(id);
3309
+ };
3310
+ }, [step, kycPending, kycApproved, client]);
3214
3311
  async function loadCountries(resetSelection) {
3215
3312
  setCountriesLoading(true);
3216
3313
  try {
@@ -3256,7 +3353,7 @@ function RampWidget({ onClose }) {
3256
3353
  setRefreshing(false);
3257
3354
  }
3258
3355
  }
3259
- function resetToInput() {
3356
+ function resetToInput({ keepMessage = false } = {}) {
3260
3357
  setStep("input");
3261
3358
  setQuotes([]);
3262
3359
  setSelectedQuote(null);
@@ -3268,7 +3365,7 @@ function RampWidget({ onClose }) {
3268
3365
  setTxStatus(null);
3269
3366
  setStellarTxHash(null);
3270
3367
  setDepositInstructions(null);
3271
- setErrorMsg(null);
3368
+ if (!keepMessage) setErrorMsg(null);
3272
3369
  }
3273
3370
  async function resumeWithSignature(id, ps) {
3274
3371
  const outcome = await signTx(ps.unsignedXdr);
@@ -3292,6 +3389,8 @@ function RampWidget({ onClose }) {
3292
3389
  }
3293
3390
  setKycUrl(result.kycUrl ?? null);
3294
3391
  setTosUrl(result.tosUrl ?? null);
3392
+ setKycPending(result.kycRequired === true);
3393
+ if (result.kycRequired) setKycApproved(false);
3295
3394
  setTxStatus(result.status);
3296
3395
  setStellarTxHash(result.stellarTxHash ?? null);
3297
3396
  setDepositInstructions(result.depositInstructions ?? null);
@@ -3312,7 +3411,7 @@ function RampWidget({ onClose }) {
3312
3411
  setQuotes(list);
3313
3412
  setStep("select_route");
3314
3413
  } catch (e) {
3315
- setErrorMsg(e instanceof Error ? e.message : "Failed to fetch quotes.");
3414
+ setErrorMsg(rampErrorMessage(e, "Failed to fetch quotes."));
3316
3415
  setStep("error");
3317
3416
  } finally {
3318
3417
  setIsLoading(false);
@@ -3321,8 +3420,13 @@ function RampWidget({ onClose }) {
3321
3420
  function handleSelectQuote(quote) {
3322
3421
  setSelectedQuote(quote);
3323
3422
  setErrorMsg(null);
3423
+ const broken = brokenLimitOf(Number(amount), quote);
3424
+ if (broken) {
3425
+ setErrorMsg(limitMessage(broken.limit, broken.value, currency));
3426
+ return;
3427
+ }
3324
3428
  const fields = requiredFieldsOf(quote);
3325
- const missing = fields.some((f) => !(fieldValues[f.key] ?? "").trim());
3429
+ const missing = fields.some((f) => !f.optional && !(fieldValues[f.key] ?? "").trim());
3326
3430
  if (fields.length > 0 && missing) {
3327
3431
  setStep("contact");
3328
3432
  return;
@@ -3351,7 +3455,7 @@ function RampWidget({ onClose }) {
3351
3455
  const result = direction === "onramp" ? await client.createOnRamp(base) : await client.createOffRamp(base);
3352
3456
  await applyResult(result);
3353
3457
  } catch (e) {
3354
- setErrorMsg(e instanceof Error ? e.message : "Failed to start the ramp.");
3458
+ setErrorMsg(rampErrorMessage(e, "Failed to start the ramp."));
3355
3459
  setStep("error");
3356
3460
  } finally {
3357
3461
  setIsLoading(false);
@@ -3384,13 +3488,20 @@ function RampWidget({ onClose }) {
3384
3488
  setCompleting(false);
3385
3489
  }
3386
3490
  }
3387
- const canComplete = direction === "offramp" && step === "status" && txStatus !== "completed" && !stellarTxHash;
3388
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
3491
+ const kycBlocking = kycPending && !kycApproved;
3492
+ const canComplete = direction === "offramp" && step === "status" && txStatus !== "completed" && !stellarTxHash && !kycBlocking;
3493
+ const flowSteps = flowStepsOf(quotes, selectedQuote);
3494
+ const flowStepIndex = flowSteps.indexOf(STEP_LABEL[step] ?? "");
3495
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
3389
3496
  RampWidgetTemplate,
3390
3497
  {
3391
3498
  theme,
3392
3499
  accentColor,
3500
+ styleOverrides,
3393
3501
  step,
3502
+ flowSteps,
3503
+ flowStepIndex,
3504
+ startingQuoteId: isLoading && selectedQuote ? selectedQuote.quoteId : null,
3394
3505
  direction,
3395
3506
  amount,
3396
3507
  currency,
@@ -3406,6 +3517,8 @@ function RampWidget({ onClose }) {
3406
3517
  txStatus,
3407
3518
  kycUrl,
3408
3519
  tosUrl,
3520
+ kycBlocking,
3521
+ kycJustApproved: kycPending && kycApproved,
3409
3522
  stellarTxHash,
3410
3523
  explorerUrl: stellarTxHash ? `https://stellar.expert/explorer/${network === "mainnet" ? "public" : "testnet"}/tx/${stellarTxHash}` : null,
3411
3524
  depositInstructions,
@@ -3413,7 +3526,10 @@ function RampWidget({ onClose }) {
3413
3526
  completing,
3414
3527
  errorMsg,
3415
3528
  onDirectionChange: setDirection,
3416
- onAmountChange: setAmount,
3529
+ onAmountChange: (next) => {
3530
+ setAmount(next);
3531
+ setErrorMsg(null);
3532
+ },
3417
3533
  onFieldChange: setFieldValue,
3418
3534
  onCountryChange: handleCountryChange,
3419
3535
  onFindRoute: handleFindRoute,
@@ -3422,7 +3538,8 @@ function RampWidget({ onClose }) {
3422
3538
  onOpenKyc: handleOpenKyc,
3423
3539
  onOpenTos: handleOpenTos,
3424
3540
  onCompleteWithdraw: handleCompleteWithdraw,
3425
- onRetry: resetToInput,
3541
+ onBack: () => resetToInput({ keepMessage: true }),
3542
+ onRetry: () => resetToInput(),
3426
3543
  onRefresh: handleRefresh,
3427
3544
  onClose
3428
3545
  }
@@ -3479,6 +3596,7 @@ var CHAIN_NAME = {
3479
3596
  function ReceiveModalTemplate({
3480
3597
  theme,
3481
3598
  accentColor,
3599
+ styleOverrides,
3482
3600
  walletAddress,
3483
3601
  chains,
3484
3602
  selectedChain,
@@ -3488,23 +3606,7 @@ function ReceiveModalTemplate({
3488
3606
  onClose
3489
3607
  }) {
3490
3608
  const isDark = theme === "dark";
3491
- const cssVars = {
3492
- "--pollar-accent": accentColor,
3493
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
3494
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
3495
- "--pollar-text": isDark ? "#ffffff" : "#111827",
3496
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
3497
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
3498
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
3499
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
3500
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
3501
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
3502
- "--pollar-buttons-border-radius": "6px",
3503
- "--pollar-buttons-height": "44px",
3504
- "--pollar-input-height": "44px",
3505
- "--pollar-input-border-radius": "0.5rem",
3506
- "--pollar-card-border-radius": "10px"
3507
- };
3609
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
3508
3610
  const chainName = selectedChain ? CHAIN_NAME[selectedChain] ?? selectedChain : "wallet";
3509
3611
  return /* @__PURE__ */ jsxRuntime.jsxs(
3510
3612
  "div",
@@ -3569,7 +3671,7 @@ function ReceiveModalTemplate({
3569
3671
  }
3570
3672
  function ReceiveModal({ onClose }) {
3571
3673
  const { wallets, styles } = usePollar();
3572
- const { theme = "light", accentColor = "#005DB4" } = styles;
3674
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
3573
3675
  const [copied, setCopied] = react.useState(false);
3574
3676
  const copyTimerRef = react.useRef(null);
3575
3677
  const { chains } = useChains();
@@ -3595,11 +3697,12 @@ function ReceiveModal({ onClose }) {
3595
3697
  }, 2e3);
3596
3698
  });
3597
3699
  }
3598
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
3700
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
3599
3701
  ReceiveModalTemplate,
3600
3702
  {
3601
3703
  theme,
3602
3704
  accentColor,
3705
+ styleOverrides,
3603
3706
  walletAddress,
3604
3707
  chains,
3605
3708
  selectedChain,
@@ -3862,6 +3965,7 @@ function assetKey3(record) {
3862
3965
  function SendModalTemplate({
3863
3966
  theme,
3864
3967
  accentColor,
3968
+ styleOverrides,
3865
3969
  step,
3866
3970
  txTitle,
3867
3971
  assets,
@@ -3895,24 +3999,7 @@ function SendModalTemplate({
3895
3999
  onRetry,
3896
4000
  onDone
3897
4001
  }) {
3898
- const isDark = theme === "dark";
3899
- const cssVars = {
3900
- "--pollar-accent": accentColor,
3901
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
3902
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
3903
- "--pollar-text": isDark ? "#ffffff" : "#111827",
3904
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
3905
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
3906
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
3907
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
3908
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
3909
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
3910
- "--pollar-buttons-border-radius": "6px",
3911
- "--pollar-buttons-height": "44px",
3912
- "--pollar-input-height": "44px",
3913
- "--pollar-input-border-radius": "0.5rem",
3914
- "--pollar-card-border-radius": "10px"
3915
- };
4002
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
3916
4003
  const selectedKey = selectedAsset ? assetKey3(selectedAsset) : "";
3917
4004
  const canSubmit = canSendOnChain && !!selectedAsset && !!amount && !!destination.trim() && !isLoadingBalance;
3918
4005
  const title = step === "form" ? "Send" : txTitle;
@@ -4072,7 +4159,7 @@ function SendModal({ onClose }) {
4072
4159
  styles
4073
4160
  } = usePollar();
4074
4161
  const walletType = wallet?.custody === "external" ? wallet.provider : null;
4075
- const { theme = "light", accentColor = "#005DB4" } = styles;
4162
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
4076
4163
  const [step, setStep] = react.useState("form");
4077
4164
  const [amount, setAmount] = react.useState("");
4078
4165
  const [destination, setDestination] = react.useState("");
@@ -4151,6 +4238,11 @@ function SendModal({ onClose }) {
4151
4238
  setFormError("Enter a destination address");
4152
4239
  return;
4153
4240
  }
4241
+ const isNativeAsset = selectedAsset.type === "native";
4242
+ if (isBaseUnitChain && !isNativeAsset && (!selectedAsset.issuer || selectedAsset.decimals === void 0)) {
4243
+ setFormError("This token is missing its mint or decimals and cannot be sent.");
4244
+ return;
4245
+ }
4154
4246
  let sendAmount = amount;
4155
4247
  if (isBaseUnitChain) {
4156
4248
  try {
@@ -4166,8 +4258,9 @@ function SendModal({ onClose }) {
4166
4258
  chain: "SOLANA",
4167
4259
  destination: destination.trim(),
4168
4260
  amount: sendAmount,
4169
- // Native SOL carries no mint; an SPL token's mint rides in `issuer`.
4170
- ...selectedAsset.type === "native" ? {} : { mint: selectedAsset.issuer ?? null }
4261
+ // Native SOL carries no mint; an SPL token's mint rides in `issuer`,
4262
+ // which the guard above proved is present.
4263
+ ...isNativeAsset ? {} : { mint: selectedAsset.issuer }
4171
4264
  });
4172
4265
  return;
4173
4266
  }
@@ -4199,11 +4292,12 @@ function SendModal({ onClose }) {
4199
4292
  setShowXdr(false);
4200
4293
  setCopied(false);
4201
4294
  }
4202
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(
4295
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(
4203
4296
  SendModalTemplate,
4204
4297
  {
4205
4298
  theme,
4206
4299
  accentColor,
4300
+ styleOverrides,
4207
4301
  step,
4208
4302
  txTitle,
4209
4303
  assets: sortedAssets,
@@ -4255,6 +4349,7 @@ function formatAmount3(value) {
4255
4349
  function SwapModalTemplate({
4256
4350
  theme,
4257
4351
  accentColor,
4352
+ styleOverrides,
4258
4353
  step,
4259
4354
  txTitle,
4260
4355
  sellOptions,
@@ -4294,7 +4389,6 @@ function SwapModalTemplate({
4294
4389
  onRetry,
4295
4390
  onDone
4296
4391
  }) {
4297
- const isDark = theme === "dark";
4298
4392
  const [customOpen, setCustomOpen] = react.useState(false);
4299
4393
  const [customCode, setCustomCode] = react.useState("");
4300
4394
  const [customIssuer, setCustomIssuer] = react.useState("");
@@ -4310,23 +4404,7 @@ function SwapModalTemplate({
4310
4404
  setCustomError("");
4311
4405
  setCustomOpen(false);
4312
4406
  };
4313
- const cssVars = {
4314
- "--pollar-accent": accentColor,
4315
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
4316
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
4317
- "--pollar-text": isDark ? "#ffffff" : "#111827",
4318
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
4319
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
4320
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
4321
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
4322
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
4323
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
4324
- "--pollar-buttons-border-radius": "6px",
4325
- "--pollar-buttons-height": "44px",
4326
- "--pollar-input-height": "44px",
4327
- "--pollar-input-border-radius": "0.5rem",
4328
- "--pollar-card-border-radius": "10px"
4329
- };
4407
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
4330
4408
  const sellKey = selectedSell ? assetOptionKey(selectedSell) : "";
4331
4409
  const buyKey = selectedBuy ? assetOptionKey(selectedBuy) : "";
4332
4410
  const canSwap = !smartUnsupported && !!selectedSell && !!selectedBuy && !!amount && !!quote && !quoteLoading && !isLoadingData;
@@ -4588,7 +4666,7 @@ function SwapModal({ onClose }) {
4588
4666
  } = usePollar();
4589
4667
  const walletType = wallet?.custody === "external" ? wallet.provider : null;
4590
4668
  const smartUnsupported = wallet?.custody === "smart";
4591
- const { theme = "light", accentColor = "#005DB4" } = styles;
4669
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
4592
4670
  const [step, setStep] = react.useState("form");
4593
4671
  const [selectedSell, setSelectedSell] = react.useState(null);
4594
4672
  const [selectedBuy, setSelectedBuy] = react.useState(null);
@@ -4639,7 +4717,7 @@ function SwapModal({ onClose }) {
4639
4717
  const assetRecords = enabledAssets.step === "loaded" ? enabledAssets.data.assets : [];
4640
4718
  const isLoadingData = walletBalance.step === "loading" || enabledAssets.step === "loading";
4641
4719
  const sellOptions = balances.filter(
4642
- (b) => b.type != null && (b.type === "native" || !b.trustlineRemoved)
4720
+ (b) => (b.chain === void 0 || b.chain === "STELLAR") && (b.type === "native" || (b.type === "credit_alphanum4" || b.type === "credit_alphanum12") && !b.trustlineRemoved)
4643
4721
  ).map((b) => ({
4644
4722
  ref: toRef(b),
4645
4723
  code: b.code,
@@ -4793,11 +4871,12 @@ function SwapModal({ onClose }) {
4793
4871
  setShowXdr(false);
4794
4872
  setCopied(false);
4795
4873
  }
4796
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(
4874
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(
4797
4875
  SwapModalTemplate,
4798
4876
  {
4799
4877
  theme,
4800
4878
  accentColor,
4879
+ styleOverrides,
4801
4880
  step,
4802
4881
  txTitle,
4803
4882
  sellOptions,
@@ -4875,8 +4954,7 @@ function EarnModal({ onClose }) {
4875
4954
  } = usePollar();
4876
4955
  const walletType = wallet?.custody === "external" ? wallet.provider : null;
4877
4956
  const smartUnsupported = wallet?.custody === "smart";
4878
- const { theme = "light", accentColor = "#005DB4" } = styles;
4879
- const isDark = theme === "dark";
4957
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
4880
4958
  const [step, setStep] = react.useState("form");
4881
4959
  const [tab, setTab] = react.useState("deposit");
4882
4960
  const [providers, setProviders] = react.useState(null);
@@ -4952,9 +5030,7 @@ function EarnModal({ onClose }) {
4952
5030
  if (!selectedOpportunity) return null;
4953
5031
  const balances = walletBalance.step === "loaded" ? walletBalance.data.balances : [];
4954
5032
  const issuer = selectedOpportunity.asset.issuer;
4955
- const rec = balances.find(
4956
- (b) => issuer === null ? b.type === "native" : b.code === assetCode && b.issuer === issuer
4957
- );
5033
+ const rec = balances.find((b) => issuer === null ? b.type === "native" : b.code === assetCode && b.issuer === issuer);
4958
5034
  return rec ? rec.available : null;
4959
5035
  })();
4960
5036
  const depositAssetRecord = (() => {
@@ -4974,23 +5050,7 @@ function EarnModal({ onClose }) {
4974
5050
  const parsedAmount = parseFloat(amount);
4975
5051
  const exceedsAvailable = tab === "deposit" ? walletAvailable != null && parsedAmount > parseFloat(walletAvailable) : position != null && parsedAmount > parseFloat(position.withdrawable);
4976
5052
  const canSubmit = !smartUnsupported && !!provider && !!opportunityId && !!amount && parsedAmount > 0 && !exceedsAvailable && !providersLoading && !loadingOpps;
4977
- const cssVars = {
4978
- "--pollar-accent": accentColor,
4979
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
4980
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
4981
- "--pollar-text": isDark ? "#ffffff" : "#111827",
4982
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
4983
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
4984
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
4985
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
4986
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
4987
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
4988
- "--pollar-buttons-border-radius": "6px",
4989
- "--pollar-buttons-height": "44px",
4990
- "--pollar-input-height": "44px",
4991
- "--pollar-input-border-radius": "0.5rem",
4992
- "--pollar-card-border-radius": "10px"
4993
- };
5053
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
4994
5054
  async function handleSubmit() {
4995
5055
  setFormError("");
4996
5056
  if (smartUnsupported) {
@@ -5069,7 +5129,7 @@ function EarnModal({ onClose }) {
5069
5129
  }
5070
5130
  }
5071
5131
  const title = step === "form" ? "Earn" : txTitle;
5072
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsxRuntime.jsxs(
5132
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: !isInProgress ? onClose : void 0, children: /* @__PURE__ */ jsxRuntime.jsxs(
5073
5133
  "div",
5074
5134
  {
5075
5135
  className: "pollar-modal-card pollar-send-modal",
@@ -5317,6 +5377,7 @@ function shortIp(hash) {
5317
5377
  function SessionsModalTemplate({
5318
5378
  theme,
5319
5379
  accentColor,
5380
+ styleOverrides,
5320
5381
  state,
5321
5382
  revokingFamilyId,
5322
5383
  signingOutEverywhere,
@@ -5325,24 +5386,7 @@ function SessionsModalTemplate({
5325
5386
  onLogoutEverywhere,
5326
5387
  onClose
5327
5388
  }) {
5328
- const isDark = theme === "dark";
5329
- const cssVars = {
5330
- "--pollar-accent": accentColor,
5331
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
5332
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
5333
- "--pollar-text": isDark ? "#ffffff" : "#111827",
5334
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
5335
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
5336
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
5337
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
5338
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
5339
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
5340
- "--pollar-buttons-border-radius": "6px",
5341
- "--pollar-buttons-height": "44px",
5342
- "--pollar-input-height": "44px",
5343
- "--pollar-input-border-radius": "0.5rem",
5344
- "--pollar-card-border-radius": "10px"
5345
- };
5389
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
5346
5390
  const isLoading = state.step === "loading";
5347
5391
  const sessions = state.step === "loaded" ? state.sessions : [];
5348
5392
  const otherCount = sessions.filter((s) => !s.current).length;
@@ -5454,7 +5498,7 @@ function SessionsModalTemplate({
5454
5498
  }
5455
5499
  function SessionsModal({ onClose }) {
5456
5500
  const { getClient, styles, sessions } = usePollar();
5457
- const { theme = "light", accentColor = "#005DB4" } = styles;
5501
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
5458
5502
  const [revokingFamilyId, setRevokingFamilyId] = react.useState(null);
5459
5503
  const [signingOutEverywhere, setSigningOutEverywhere] = react.useState(false);
5460
5504
  const load = react.useCallback(() => {
@@ -5492,11 +5536,12 @@ function SessionsModal({ onClose }) {
5492
5536
  setSigningOutEverywhere(false);
5493
5537
  }
5494
5538
  }, [getClient, onClose]);
5495
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
5539
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
5496
5540
  SessionsModalTemplate,
5497
5541
  {
5498
5542
  theme,
5499
5543
  accentColor,
5544
+ styleOverrides,
5500
5545
  state: sessions,
5501
5546
  revokingFamilyId,
5502
5547
  signingOutEverywhere,
@@ -5510,6 +5555,7 @@ function SessionsModal({ onClose }) {
5510
5555
  function TransactionModalTemplate({
5511
5556
  theme,
5512
5557
  accentColor,
5558
+ styleOverrides,
5513
5559
  transaction,
5514
5560
  showXdr,
5515
5561
  copied,
@@ -5521,24 +5567,7 @@ function TransactionModalTemplate({
5521
5567
  onCopyHash,
5522
5568
  onRetry
5523
5569
  }) {
5524
- const isDark = theme === "dark";
5525
- const cssVars = {
5526
- "--pollar-accent": accentColor,
5527
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
5528
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
5529
- "--pollar-text": isDark ? "#ffffff" : "#111827",
5530
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
5531
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
5532
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
5533
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
5534
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
5535
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
5536
- "--pollar-buttons-border-radius": "6px",
5537
- "--pollar-buttons-height": "44px",
5538
- "--pollar-input-height": "44px",
5539
- "--pollar-input-border-radius": "0.5rem",
5540
- "--pollar-card-border-radius": "10px"
5541
- };
5570
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
5542
5571
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-tx-modal", "data-theme": theme, style: cssVars, onClick: (e) => e.stopPropagation(), children: [
5543
5572
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-header", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-modal-title", children: "Transaction" }) }),
5544
5573
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-close-btn", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -5577,7 +5606,7 @@ function TransactionModalTemplate({
5577
5606
  function TransactionModal({ onClose }) {
5578
5607
  const { getClient, styles, tx: transaction, network, wallet } = usePollar();
5579
5608
  const walletType = wallet?.custody === "external" ? wallet.provider : null;
5580
- const { theme = "light", accentColor = "#005DB4" } = styles;
5609
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
5581
5610
  const [showXdr, setShowXdr] = react.useState(false);
5582
5611
  const [copied, setCopied] = react.useState(false);
5583
5612
  const copyTimerRef = react.useRef(null);
@@ -5612,11 +5641,12 @@ function TransactionModal({ onClose }) {
5612
5641
  await getClient().signAndSubmitTx(transaction.buildData.unsignedXdr);
5613
5642
  }
5614
5643
  }
5615
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
5644
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
5616
5645
  TransactionModalTemplate,
5617
5646
  {
5618
5647
  theme,
5619
5648
  accentColor,
5649
+ styleOverrides,
5620
5650
  transaction,
5621
5651
  showXdr,
5622
5652
  copied,
@@ -5631,6 +5661,12 @@ function TransactionModal({ onClose }) {
5631
5661
  ) });
5632
5662
  }
5633
5663
  var PAGE_SIZE = 10;
5664
+ function explorerUrlFor(chain, hash, network) {
5665
+ if (chain === "SOLANA") {
5666
+ return `https://explorer.solana.com/tx/${hash}${network === "testnet" ? "?cluster=devnet" : ""}`;
5667
+ }
5668
+ return `https://stellar.expert/explorer/${network === "testnet" ? "testnet" : "public"}/tx/${hash}`;
5669
+ }
5634
5670
  function StatusBadge({ status }) {
5635
5671
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-hist-item-badge", "data-status": status, children: status });
5636
5672
  }
@@ -5667,31 +5703,19 @@ function renderSummary(summary) {
5667
5703
  function TxHistoryModalTemplate({
5668
5704
  theme,
5669
5705
  accentColor,
5706
+ styleOverrides,
5670
5707
  txHistory,
5671
5708
  offset,
5709
+ chains,
5710
+ selectedChain,
5711
+ walletAddress,
5712
+ onSelectChain,
5672
5713
  onRefresh,
5673
5714
  onPrev,
5674
5715
  onNext,
5675
5716
  onClose
5676
5717
  }) {
5677
- const isDark = theme === "dark";
5678
- const cssVars = {
5679
- "--pollar-accent": accentColor,
5680
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
5681
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
5682
- "--pollar-text": isDark ? "#ffffff" : "#111827",
5683
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
5684
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
5685
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
5686
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
5687
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
5688
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
5689
- "--pollar-buttons-border-radius": "6px",
5690
- "--pollar-buttons-height": "44px",
5691
- "--pollar-input-height": "44px",
5692
- "--pollar-input-border-radius": "0.5rem",
5693
- "--pollar-card-border-radius": "10px"
5694
- };
5718
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
5695
5719
  const isLoading = txHistory.step === "loading";
5696
5720
  const records = txHistory.step === "loaded" ? txHistory.data.records : [];
5697
5721
  const total = txHistory.step === "loaded" ? txHistory.data.total : 0;
@@ -5744,6 +5768,11 @@ function TxHistoryModalTemplate({
5744
5768
  /* @__PURE__ */ jsxRuntime.jsx("button", { className: "pollar-modal-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 2l12 12M14 2L2 14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }) })
5745
5769
  ] })
5746
5770
  ] }),
5771
+ /* @__PURE__ */ jsxRuntime.jsx(ChainSelect, { value: selectedChain, options: chains, onChange: onSelectChain, disabled: isLoading }),
5772
+ walletAddress && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-address-row", children: [
5773
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pollar-address", children: cropAddress(walletAddress) }),
5774
+ /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { value: walletAddress, label: "Copy wallet address" })
5775
+ ] }),
5747
5776
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-hist-list", children: [
5748
5777
  txHistory.step === "idle" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "Click Refresh to load transactions." }),
5749
5778
  isLoading && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-loading-block", children: [
@@ -5754,7 +5783,7 @@ function TxHistoryModalTemplate({
5754
5783
  txHistory.step === "loaded" && records.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-modal-empty", children: "No transactions yet." }),
5755
5784
  records.map((record) => {
5756
5785
  const hash = typeof record.hash === "string" && record.hash.length > 0 ? record.hash : void 0;
5757
- const explorerUrl = hash ? `https://stellar.expert/explorer/${record.network === "testnet" ? "testnet" : "public"}/tx/${hash}` : void 0;
5786
+ const explorerUrl = hash ? explorerUrlFor(record.chain, hash, record.network) : void 0;
5758
5787
  const asset = typeof record.details?.asset === "string" ? record.details.asset : void 0;
5759
5788
  const colon = asset ? asset.indexOf(":") : -1;
5760
5789
  const trustline = record.operation === "change_trust" && asset && colon > 0 ? {
@@ -5788,10 +5817,11 @@ function TxHistoryModalTemplate({
5788
5817
  "\xB7 ",
5789
5818
  record.details.sponsored ? "Sponsored" : "Self-paid"
5790
5819
  ] }),
5791
- record.feeXlm && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5820
+ record.fee && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5792
5821
  "\xB7 ",
5793
- record.feeXlm,
5794
- " XLM"
5822
+ record.fee.amount,
5823
+ " ",
5824
+ record.fee.unit
5795
5825
  ] })
5796
5826
  ] }),
5797
5827
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-hist-item-footer", children: [
@@ -5807,7 +5837,7 @@ function TxHistoryModalTemplate({
5807
5837
  href: explorerUrl,
5808
5838
  target: "_blank",
5809
5839
  rel: "noopener noreferrer",
5810
- "aria-label": "View on Stellar Explorer",
5840
+ "aria-label": "View on block explorer",
5811
5841
  children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "12", height: "12", viewBox: "0 0 13 13", fill: "none", "aria-hidden": true, children: [
5812
5842
  /* @__PURE__ */ jsxRuntime.jsx(
5813
5843
  "path",
@@ -5856,29 +5886,44 @@ function TxHistoryModalTemplate({
5856
5886
  }
5857
5887
  var PAGE_SIZE2 = 10;
5858
5888
  function TxHistoryModal({ onClose }) {
5859
- const { getClient, styles, txHistory } = usePollar();
5860
- const { theme = "light", accentColor = "#005DB4" } = styles;
5889
+ const { getClient, styles, txHistory, wallets } = usePollar();
5890
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
5861
5891
  const [offset, setOffset] = react.useState(0);
5892
+ const { chains } = useChains();
5893
+ const [selectedChain, setSelectedChain] = react.useState(null);
5894
+ react.useEffect(() => {
5895
+ if (selectedChain === null && chains.length > 0) setSelectedChain(chains[0]);
5896
+ }, [chains, selectedChain]);
5897
+ const walletAddress = addressForChain(wallets, selectedChain);
5862
5898
  const load = react.useCallback(
5863
- (nextOffset) => {
5899
+ (nextOffset, chain) => {
5864
5900
  setOffset(nextOffset);
5865
- void getClient().fetchTxHistory({ limit: PAGE_SIZE2, offset: nextOffset });
5901
+ void getClient().fetchTxHistory({ limit: PAGE_SIZE2, offset: nextOffset, chain });
5866
5902
  },
5867
5903
  [getClient]
5868
5904
  );
5869
5905
  react.useEffect(() => {
5870
- load(0);
5871
- }, [load]);
5872
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
5906
+ if (selectedChain) load(0, selectedChain);
5907
+ }, [selectedChain, load]);
5908
+ const onSelectChain = (chain) => setSelectedChain(chain);
5909
+ const paged = (nextOffset) => {
5910
+ if (selectedChain) load(nextOffset, selectedChain);
5911
+ };
5912
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
5873
5913
  TxHistoryModalTemplate,
5874
5914
  {
5875
5915
  theme,
5876
5916
  accentColor,
5917
+ styleOverrides,
5877
5918
  txHistory,
5878
5919
  offset,
5879
- onRefresh: () => load(offset),
5880
- onPrev: () => load(Math.max(0, offset - PAGE_SIZE2)),
5881
- onNext: () => load(offset + PAGE_SIZE2),
5920
+ chains,
5921
+ selectedChain,
5922
+ walletAddress,
5923
+ onSelectChain,
5924
+ onRefresh: () => paged(offset),
5925
+ onPrev: () => paged(Math.max(0, offset - PAGE_SIZE2)),
5926
+ onNext: () => paged(offset + PAGE_SIZE2),
5882
5927
  onClose
5883
5928
  }
5884
5929
  ) });
@@ -5922,6 +5967,7 @@ function BalanceItem({ record, faucet }) {
5922
5967
  function WalletBalanceModalTemplate({
5923
5968
  theme,
5924
5969
  accentColor,
5970
+ styleOverrides,
5925
5971
  walletBalance,
5926
5972
  walletAddress,
5927
5973
  chains,
@@ -5931,24 +5977,7 @@ function WalletBalanceModalTemplate({
5931
5977
  onRefresh,
5932
5978
  onClose
5933
5979
  }) {
5934
- const isDark = theme === "dark";
5935
- const cssVars = {
5936
- "--pollar-accent": accentColor,
5937
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
5938
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
5939
- "--pollar-text": isDark ? "#ffffff" : "#111827",
5940
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
5941
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
5942
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
5943
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
5944
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
5945
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
5946
- "--pollar-buttons-border-radius": "6px",
5947
- "--pollar-buttons-height": "44px",
5948
- "--pollar-input-height": "44px",
5949
- "--pollar-input-border-radius": "0.5rem",
5950
- "--pollar-card-border-radius": "10px"
5951
- };
5980
+ const cssVars = buildModalCssVars(theme, accentColor, styleOverrides);
5952
5981
  const isLoading = walletBalance.step === "loading";
5953
5982
  const data = useStickyData(walletBalance.step === "loaded" ? walletBalance.data : null);
5954
5983
  const balances = (data?.balances ?? []).filter((b) => resolveChain(b.chain) === selectedChain);
@@ -6022,7 +6051,7 @@ function WalletBalanceModalTemplate({
6022
6051
  }
6023
6052
  function WalletBalanceModal({ onClose }) {
6024
6053
  const { walletBalance, refreshWalletBalance, wallets, network, styles } = usePollar();
6025
- const { theme = "light", accentColor = "#005DB4" } = styles;
6054
+ const { theme, accentColor, styleOverrides, overlayStyle } = modalChrome(styles);
6026
6055
  const { chains } = useChains();
6027
6056
  const [selectedChain, setSelectedChain] = react.useState(null);
6028
6057
  react.useEffect(() => {
@@ -6032,11 +6061,12 @@ function WalletBalanceModal({ onClose }) {
6032
6061
  react.useEffect(() => {
6033
6062
  void refreshWalletBalance();
6034
6063
  }, [refreshWalletBalance]);
6035
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
6064
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", style: overlayStyle, onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(
6036
6065
  WalletBalanceModalTemplate,
6037
6066
  {
6038
6067
  theme,
6039
6068
  accentColor,
6069
+ styleOverrides,
6040
6070
  walletBalance,
6041
6071
  walletAddress,
6042
6072
  chains,
@@ -6118,9 +6148,17 @@ function PollarProvider({
6118
6148
  onStorageDegrade,
6119
6149
  children
6120
6150
  }) {
6121
- const [pollarClient] = react.useState(
6122
- () => client instanceof core.PollarClient ? client : new core.PollarClient({ passkey: browserPasskeyCeremony, passkeySign: browserPasskeySigner, ...client })
6123
- );
6151
+ const [pollarClient] = react.useState(() => {
6152
+ if (client instanceof core.PollarClient) {
6153
+ client.setPasskeyDefaults({ passkey: browserPasskeyCeremony, passkeySign: browserPasskeySigner });
6154
+ return client;
6155
+ }
6156
+ return new core.PollarClient({
6157
+ ...client,
6158
+ passkey: client.passkey ?? browserPasskeyCeremony,
6159
+ passkeySign: client.passkeySign ?? browserPasskeySigner
6160
+ });
6161
+ });
6124
6162
  const ownsClientRef = react.useRef(!(client instanceof core.PollarClient));
6125
6163
  const destroyTimerRef = react.useRef(null);
6126
6164
  react.useEffect(() => {
@@ -6147,6 +6185,9 @@ function PollarProvider({
6147
6185
  );
6148
6186
  const [configRetry, setConfigRetry] = react.useState(0);
6149
6187
  const retryConfig = react.useCallback(() => setConfigRetry((n) => n + 1), []);
6188
+ const appConfigKey = appConfigProp === void 0 ? "" : JSON.stringify(appConfigProp);
6189
+ const appConfigPropRef = react.useRef(appConfigProp);
6190
+ appConfigPropRef.current = appConfigProp;
6150
6191
  react.useEffect(() => {
6151
6192
  return pollarClient.onTransactionStateChange(setTransaction);
6152
6193
  }, [pollarClient]);
@@ -6210,7 +6251,9 @@ function PollarProvider({
6210
6251
  setModalErrorLogger(pollarClient.getLogger());
6211
6252
  }, [pollarClient]);
6212
6253
  react.useEffect(() => {
6213
- if (appConfigProp !== void 0) {
6254
+ const localConfig = appConfigPropRef.current;
6255
+ if (localConfig !== void 0) {
6256
+ setResolvedConfig(localConfig ?? DEFAULT_APP_CONFIG);
6214
6257
  setConfigStatus("ready");
6215
6258
  return;
6216
6259
  }
@@ -6232,7 +6275,7 @@ function PollarProvider({
6232
6275
  return () => {
6233
6276
  cancelled = true;
6234
6277
  };
6235
- }, [pollarClient, appConfigProp, configRetry]);
6278
+ }, [pollarClient, appConfigKey, configRetry]);
6236
6279
  const [loginModalOpen, setLoginModalOpen] = react.useState(false);
6237
6280
  const [transactionModalOpen, setTransactionModalOpen] = react.useState(false);
6238
6281
  const [kycModalOpen, setKycModalOpen] = react.useState(false);
@@ -6914,8 +6957,13 @@ exports.WalletBalanceModalTemplate = WalletBalanceModalTemplate;
6914
6957
  exports.WalletButton = WalletButton;
6915
6958
  exports.WalletButtonTemplate = WalletButtonTemplate;
6916
6959
  exports.addressForChain = addressForChain;
6960
+ exports.browserPasskeyCeremony = browserPasskeyCeremony;
6961
+ exports.browserPasskeySigner = browserPasskeySigner;
6962
+ exports.buildModalCssVars = buildModalCssVars;
6917
6963
  exports.chainsOf = chainsOf;
6918
6964
  exports.createPollarAdapterHook = createPollarAdapterHook;
6965
+ exports.modalChrome = modalChrome;
6966
+ exports.readableTextOn = readableTextOn;
6919
6967
  exports.resolveChain = resolveChain;
6920
6968
  exports.useChains = useChains;
6921
6969
  exports.usePollar = usePollar;