@pollar/react 0.11.0 → 0.11.1-rc.3

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.d.mts CHANGED
@@ -43,6 +43,15 @@ interface PollarContextValue {
43
43
  openSessionsModal: () => void;
44
44
  appConfig: PollarConfig;
45
45
  styles: PollarStyles;
46
+ /** Remote app-config load state. 'loading' while the initial fetch is in
47
+ * flight, 'error' if it failed (styles fall back to empty defaults), 'ready'
48
+ * once resolved — or immediately 'ready' when `appConfig` is passed as a prop.
49
+ * The login modal shows a spinner/retry instead of an empty shell until this
50
+ * is 'ready'. */
51
+ configStatus: 'loading' | 'ready' | 'error';
52
+ /** Re-run the remote app-config fetch after an error. No-op when `appConfig`
53
+ * was supplied as a prop. */
54
+ retryConfig: () => void;
46
55
  openTxModal: () => void;
47
56
  tx: TransactionState;
48
57
  buildTx: (operation: TxBuildBody['operation'], params: TxBuildBody['params'], options?: TxBuildBody['options']) => Promise<BuildOutcome>;
package/dist/index.d.ts CHANGED
@@ -43,6 +43,15 @@ interface PollarContextValue {
43
43
  openSessionsModal: () => void;
44
44
  appConfig: PollarConfig;
45
45
  styles: PollarStyles;
46
+ /** Remote app-config load state. 'loading' while the initial fetch is in
47
+ * flight, 'error' if it failed (styles fall back to empty defaults), 'ready'
48
+ * once resolved — or immediately 'ready' when `appConfig` is passed as a prop.
49
+ * The login modal shows a spinner/retry instead of an empty shell until this
50
+ * is 'ready'. */
51
+ configStatus: 'loading' | 'ready' | 'error';
52
+ /** Re-run the remote app-config fetch after an error. No-op when `appConfig`
53
+ * was supplied as a prop. */
54
+ retryConfig: () => void;
46
55
  openTxModal: () => void;
47
56
  tx: TransactionState;
48
57
  buildTx: (operation: TxBuildBody['operation'], params: TxBuildBody['params'], options?: TxBuildBody['options']) => Promise<BuildOutcome>;
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.0"
1038
+ "0.11.1-rc.3"
1039
1039
  ] })
1040
1040
  ] })
1041
1041
  ] });
@@ -2054,6 +2054,29 @@ function authStateToStatus(step) {
2054
2054
  if (error.includes(step)) return "ERROR";
2055
2055
  return "NONE";
2056
2056
  }
2057
+ function buildModalCssVars(theme, accentColor) {
2058
+ const isDark = theme === "dark";
2059
+ return {
2060
+ "--pollar-accent": accentColor,
2061
+ "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
2062
+ "--pollar-border": isDark ? "#374151" : "#e5e7eb",
2063
+ "--pollar-text": isDark ? "#ffffff" : "#111827",
2064
+ "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
2065
+ "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
2066
+ "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
2067
+ "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
2068
+ "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
2069
+ "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
2070
+ "--pollar-buttons-border-radius": "6px",
2071
+ "--pollar-buttons-height": "44px",
2072
+ "--pollar-input-height": "44px",
2073
+ "--pollar-input-border-radius": "0.5rem",
2074
+ "--pollar-card-border-radius": "10px",
2075
+ "--pollar-modal-padding": "2rem",
2076
+ "--pollar-modal-heading-size": "1.375rem",
2077
+ "--pollar-modal-subtitle-size": "0.9rem"
2078
+ };
2079
+ }
2057
2080
  function LoginModalTemplate({
2058
2081
  theme,
2059
2082
  accentColor,
@@ -2080,7 +2103,6 @@ function LoginModalTemplate({
2080
2103
  }) {
2081
2104
  const [showPasskeyChooser, setShowPasskeyChooser] = react.useState(false);
2082
2105
  const [activeGroup, setActiveGroup] = react.useState(null);
2083
- const isDark = theme === "dark";
2084
2106
  const enabledSocial = Object.entries(providers).filter(([, enabled]) => enabled);
2085
2107
  const rootAdapters = walletAdapters.filter((a) => !a.meta.group);
2086
2108
  const walletGroups = walletAdapters.filter((a) => a.meta.group).reduce((acc, a) => {
@@ -2091,26 +2113,7 @@ function LoginModalTemplate({
2091
2113
  return acc;
2092
2114
  }, []);
2093
2115
  const activeGroupAdapters = walletGroups.find((g) => g.label === activeGroup)?.adapters ?? [];
2094
- const cssVars = {
2095
- "--pollar-accent": accentColor,
2096
- "--pollar-bg": isDark ? "#1a1a1a" : "#ffffff",
2097
- "--pollar-border": isDark ? "#374151" : "#e5e7eb",
2098
- "--pollar-text": isDark ? "#ffffff" : "#111827",
2099
- "--pollar-muted": isDark ? "#9ca3af" : "#6b7280",
2100
- "--pollar-input-bg": isDark ? "#374151" : "#f9fafb",
2101
- "--pollar-error-bg": isDark ? "#2a1515" : "#fef2f2",
2102
- "--pollar-error-border": isDark ? "#7f1d1d" : "#fecaca",
2103
- "--pollar-error-text": isDark ? "#f87171" : "#dc2626",
2104
- "--pollar-success-text": isDark ? "#4ade80" : "#16a34a",
2105
- "--pollar-buttons-border-radius": "6px",
2106
- "--pollar-buttons-height": "44px",
2107
- "--pollar-input-height": "44px",
2108
- "--pollar-input-border-radius": "0.5rem",
2109
- "--pollar-card-border-radius": "10px",
2110
- "--pollar-modal-padding": "2rem",
2111
- "--pollar-modal-heading-size": "1.375rem",
2112
- "--pollar-modal-subtitle-size": "0.9rem"
2113
- };
2116
+ const cssVars = buildModalCssVars(theme, accentColor);
2114
2117
  const status = authStateToStatus(authState.step);
2115
2118
  const isLoading = status === "LOADING";
2116
2119
  const isEmailCodeError = authState.step === "error" && (authState.errorCode === core.AUTH_ERROR_CODES.EMAIL_CODE_EXPIRED || authState.errorCode === core.AUTH_ERROR_CODES.EMAIL_CODE_INVALID);
@@ -2285,6 +2288,46 @@ function LoginModalTemplate({
2285
2288
  /* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
2286
2289
  ] });
2287
2290
  }
2291
+ function LoginModalStatus({
2292
+ status,
2293
+ theme,
2294
+ accentColor,
2295
+ logoUrl,
2296
+ appName,
2297
+ onRetry,
2298
+ onCancel
2299
+ }) {
2300
+ const cssVars = buildModalCssVars(theme, accentColor);
2301
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-modal-card pollar-modal", style: cssVars, onClick: (e) => e.stopPropagation(), children: [
2302
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-close-btn", onClick: onCancel, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx(
2303
+ "svg",
2304
+ {
2305
+ width: "18",
2306
+ height: "18",
2307
+ viewBox: "0 0 24 24",
2308
+ fill: "none",
2309
+ stroke: "currentColor",
2310
+ strokeWidth: "2.5",
2311
+ strokeLinecap: "round",
2312
+ strokeLinejoin: "round",
2313
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12" })
2314
+ }
2315
+ ) }),
2316
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-header", children: [
2317
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-logo-wrap", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoUrl ?? LOGO_POLLAR, alt: "Logo", className: "pollar-logo" }) }),
2318
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "pollar-title", children: appName }),
2319
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-subtitle", children: "Log in or sign up" })
2320
+ ] }),
2321
+ status === "loading" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-loading-block", children: [
2322
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-spinner" }),
2323
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Loading..." })
2324
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pollar-wallet-section", children: [
2325
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "pollar-modal-error", children: "Could not load sign-in options. Check your connection and try again." }),
2326
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "pollar-btn-primary", onClick: onRetry, children: "Try again" })
2327
+ ] }),
2328
+ /* @__PURE__ */ jsxRuntime.jsx(PollarModalFooter, {})
2329
+ ] });
2330
+ }
2288
2331
  function PrivyLoginSubmodal({
2289
2332
  adapter,
2290
2333
  theme,
@@ -2441,7 +2484,7 @@ function PrivyLoginSubmodal({
2441
2484
  }
2442
2485
  function LoginModal({ onClose }) {
2443
2486
  const [email, setEmail] = react.useState("");
2444
- const { getClient, styles, appConfig: config } = usePollar();
2487
+ const { getClient, styles, appConfig: config, configStatus, retryConfig } = usePollar();
2445
2488
  const [authState, setAuthState] = react.useState(() => getClient().getAuthState());
2446
2489
  const walletAdapters = react.useMemo(() => getClient().listWalletAdapters(), [getClient]);
2447
2490
  const [codeInputKey, setCodeInputKey] = react.useState(0);
@@ -2527,7 +2570,18 @@ function LoginModal({ onClose }) {
2527
2570
  getClient().login({ provider });
2528
2571
  }
2529
2572
  }
2530
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: handleClose, children: interactiveAdapter ? /* @__PURE__ */ jsxRuntime.jsx(
2573
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pollar-overlay", onClick: handleClose, children: configStatus !== "ready" ? /* @__PURE__ */ jsxRuntime.jsx(
2574
+ LoginModalStatus,
2575
+ {
2576
+ status: configStatus === "error" ? "error" : "loading",
2577
+ theme,
2578
+ accentColor,
2579
+ logoUrl: logoUrl ?? null,
2580
+ appName: config.application?.name ?? "Pollar",
2581
+ onRetry: retryConfig,
2582
+ onCancel: handleClose
2583
+ }
2584
+ ) : interactiveAdapter ? /* @__PURE__ */ jsxRuntime.jsx(
2531
2585
  PrivyLoginSubmodal,
2532
2586
  {
2533
2587
  adapter: interactiveAdapter,
@@ -5823,7 +5877,7 @@ var browserPasskeySigner = async ({ credentialId, challenge }) => {
5823
5877
  };
5824
5878
  };
5825
5879
  var DEFAULT_APP_CONFIG = {
5826
- application: { name: "" },
5880
+ application: { name: "", network: "testnet", chains: [] },
5827
5881
  styles: {}
5828
5882
  };
5829
5883
  function sessionsEqual(a, b) {
@@ -5863,6 +5917,11 @@ function PollarProvider({
5863
5917
  const [walletBalance, setWalletBalance] = react.useState({ step: "idle" });
5864
5918
  const [enabledAssets, setEnabledAssets] = react.useState({ step: "idle" });
5865
5919
  const [resolvedConfig, setResolvedConfig] = react.useState(() => appConfigProp ?? DEFAULT_APP_CONFIG);
5920
+ const [configStatus, setConfigStatus] = react.useState(
5921
+ appConfigProp !== void 0 ? "ready" : "loading"
5922
+ );
5923
+ const [configRetry, setConfigRetry] = react.useState(0);
5924
+ const retryConfig = react.useCallback(() => setConfigRetry((n) => n + 1), []);
5866
5925
  react.useEffect(() => {
5867
5926
  return pollarClient.onTransactionStateChange(setTransaction);
5868
5927
  }, [pollarClient]);
@@ -5926,18 +5985,29 @@ function PollarProvider({
5926
5985
  setModalErrorLogger(pollarClient.getLogger());
5927
5986
  }, [pollarClient]);
5928
5987
  react.useEffect(() => {
5929
- if (appConfigProp !== void 0) return;
5988
+ if (appConfigProp !== void 0) {
5989
+ setConfigStatus("ready");
5990
+ return;
5991
+ }
5930
5992
  let cancelled = false;
5993
+ setConfigStatus("loading");
5931
5994
  pollarClient.getAppConfig().then((fetched) => {
5932
- if (cancelled || !fetched) return;
5995
+ if (cancelled) return;
5996
+ if (!fetched) {
5997
+ setConfigStatus("error");
5998
+ return;
5999
+ }
5933
6000
  setResolvedConfig(fetched);
6001
+ setConfigStatus("ready");
5934
6002
  }).catch((err) => {
6003
+ if (cancelled) return;
5935
6004
  pollarClient.getLogger().error("[PollarProvider] getAppConfig failed", err);
6005
+ setConfigStatus("error");
5936
6006
  });
5937
6007
  return () => {
5938
6008
  cancelled = true;
5939
6009
  };
5940
- }, [pollarClient, appConfigProp]);
6010
+ }, [pollarClient, appConfigProp, configRetry]);
5941
6011
  const [loginModalOpen, setLoginModalOpen] = react.useState(false);
5942
6012
  const [transactionModalOpen, setTransactionModalOpen] = react.useState(false);
5943
6013
  const [kycModalOpen, setKycModalOpen] = react.useState(false);
@@ -6039,6 +6109,8 @@ function PollarProvider({
6039
6109
  // config
6040
6110
  appConfig: resolvedConfig,
6041
6111
  styles,
6112
+ configStatus,
6113
+ retryConfig,
6042
6114
  adapters
6043
6115
  };
6044
6116
  }, [
@@ -6055,6 +6127,8 @@ function PollarProvider({
6055
6127
  refreshAssets,
6056
6128
  networkState,
6057
6129
  resolvedConfig,
6130
+ configStatus,
6131
+ retryConfig,
6058
6132
  adapters
6059
6133
  ]);
6060
6134
  return /* @__PURE__ */ jsxRuntime.jsxs(PollarContext.Provider, { value: contextValue, children: [