@phantom/react-sdk 1.0.0-beta.25 → 1.0.0-beta.27

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/README.md CHANGED
@@ -221,6 +221,165 @@ function Header() {
221
221
  - Uses theme styling for consistent appearance
222
222
  - Fully clickable in both states
223
223
 
224
+ ### ConnectBox Component
225
+
226
+ An inline embedded component that displays the connection UI directly in your page layout (without a modal backdrop). Perfect for auth callback pages or when you want a more integrated connection experience. The component automatically handles all connection states including loading, error, and success during the auth callback flow.
227
+
228
+ ```tsx
229
+ import { ConnectBox } from "@phantom/react-sdk";
230
+
231
+ function AuthCallbackPage() {
232
+ return (
233
+ <div>
234
+ <h1>Connecting to Phantom...</h1>
235
+ <ConnectBox />
236
+ </div>
237
+ );
238
+ }
239
+ ```
240
+
241
+ **Props:**
242
+
243
+ - `maxWidth?: string | number` - Maximum width of the box. Can be a string (e.g., `"500px"`) or number (e.g., `500`). Default: `"350px"`
244
+ - `transparent?: boolean` - When `true`, removes background, border, and shadow for a transparent appearance. Default: `false`
245
+ - `appIcon?: string` - URL to your app icon (optional, can also be set via `PhantomProvider`)
246
+ - `appName?: string` - Your app name (optional, can also be set via `PhantomProvider`)
247
+
248
+ **Usage Examples:**
249
+
250
+ ```tsx
251
+ import { ConnectBox } from "@phantom/react-sdk";
252
+
253
+ // Default usage
254
+ <ConnectBox />
255
+
256
+ // Custom width
257
+ <ConnectBox maxWidth="500px" />
258
+
259
+ // Transparent (no background/border)
260
+ <ConnectBox transparent />
261
+
262
+ // Custom width with transparent
263
+ <ConnectBox maxWidth={600} transparent />
264
+ ```
265
+
266
+ **Features:**
267
+
268
+ - **Inline embedded**: Renders directly in page flow (not as a floating modal)
269
+ - **Auto state management**: Automatically shows connection/login UI when disconnected, wallet info when connected
270
+ - **Auth callback support**: Handles loading and error states during OAuth callback flows
271
+ - **No close button**: Designed for embedded use cases where users shouldn't dismiss the UI
272
+ - **Theme-aware**: Uses your configured theme for consistent styling
273
+ - **Responsive**: Adapts to mobile and desktop layouts
274
+
275
+ **Use Cases:**
276
+
277
+ - Auth callback pages (e.g., `/auth/callback`) where users return from OAuth providers
278
+ - Embedded wallet connection flows in your app's layout
279
+ - Custom connection pages where you want full control over the page design
280
+
281
+ ### Handling Auth Callback Pages
282
+
283
+ When using embedded authentication providers (Google, Apple, Phantom Login, etc.), users are redirected to your app's callback URL after authentication. The SDK automatically handles the callback and completes the connection. Here's how to build a callback page if you're not using `ConnectBox`:
284
+
285
+ **Basic Auth Callback Page:**
286
+
287
+ ```tsx
288
+ import { usePhantom, useConnect, useAccounts } from "@phantom/react-sdk";
289
+ import { useNavigate } from "react-router-dom"; // or your router
290
+
291
+ function AuthCallbackPage() {
292
+ const navigate = useNavigate();
293
+ const { isConnected } = usePhantom();
294
+ const { isConnecting, error: connectError } = useConnect();
295
+ const addresses = useAccounts();
296
+
297
+ const handleGoHome = () => {
298
+ navigate("/");
299
+ };
300
+
301
+ // Loading state - SDK is processing the callback
302
+ if (isConnecting) {
303
+ return (
304
+ <div>
305
+ <h1>Connecting to wallet...</h1>
306
+ <p>Please wait while we complete your authentication.</p>
307
+ </div>
308
+ );
309
+ }
310
+
311
+ // Success state - connection completed
312
+ if (isConnected && addresses && addresses.length > 0) {
313
+ return (
314
+ <div>
315
+ <h1>Authentication Successful</h1>
316
+ <p>You are now connected to your wallet.</p>
317
+ <div>
318
+ <h2>Addresses:</h2>
319
+ {addresses.map((addr, index) => (
320
+ <div key={index}>
321
+ <strong>{addr.addressType}:</strong> {addr.address}
322
+ </div>
323
+ ))}
324
+ </div>
325
+ <button onClick={handleGoHome}>Go to Main App</button>
326
+ </div>
327
+ );
328
+ }
329
+
330
+ // Error state - connection failed
331
+ if (connectError) {
332
+ return (
333
+ <div>
334
+ <h1>Authentication Failed</h1>
335
+ <p>{connectError.message || "An unknown error occurred during authentication."}</p>
336
+ <div>
337
+ <button onClick={handleGoHome}>Go to Main App</button>
338
+ </div>
339
+ </div>
340
+ );
341
+ }
342
+
343
+ // Default state (shouldn't normally reach here)
344
+ return (
345
+ <div>
346
+ <h1>Processing authentication...</h1>
347
+ </div>
348
+ );
349
+ }
350
+ ```
351
+
352
+ **Key Points:**
353
+
354
+ - The SDK's `autoConnect()` automatically processes the callback URL parameters when the page loads
355
+ - Use `useConnect()` to access `isConnecting` and `error` states during the callback flow
356
+ - Use `usePhantom()` to check `isConnected` status
357
+ - Use `useAccounts()` to get connected wallet addresses
358
+ - The connection state will automatically update as the SDK processes the callback
359
+ - You can monitor `connectError` to handle authentication failures
360
+
361
+ **Router Setup:**
362
+
363
+ Make sure your callback route is configured in your router:
364
+
365
+ ```tsx
366
+ import { Routes, Route } from "react-router-dom";
367
+ import { PhantomProvider } from "@phantom/react-sdk";
368
+
369
+ function App() {
370
+ return (
371
+ <PhantomProvider config={config} theme={darkTheme}>
372
+ <Routes>
373
+ <Route path="/auth/callback" element={<AuthCallbackPage />} />
374
+ <Route path="/" element={<MainApp />} />
375
+ </Routes>
376
+ </PhantomProvider>
377
+ );
378
+ }
379
+ ```
380
+
381
+ **Note:** For a simpler implementation, consider using the `ConnectBox` component which handles all these states automatically.
382
+
224
383
  ## Theming
225
384
 
226
385
  Customize the modal appearance by passing a theme object to the `PhantomProvider`. The SDK includes two built-in themes: `darkTheme` (default) and `lightTheme`.
package/dist/index.d.ts CHANGED
@@ -130,4 +130,12 @@ interface ConnectButtonProps {
130
130
  }
131
131
  declare function ConnectButton({ addressType, fullWidth }: ConnectButtonProps): react_jsx_runtime.JSX.Element;
132
132
 
133
- export { ConnectButton, ConnectButtonProps, ConnectOptions, PhantomDebugConfig, PhantomProvider, PhantomProviderProps, PhantomSDKConfig, UseDiscoveredWalletsResult, UseModalResult, useAccounts, useAutoConfirm, useConnect, useDisconnect, useDiscoveredWallets, useEthereum, useIsExtensionInstalled, useIsPhantomLoginAvailable, useModal, usePhantom, useSolana };
133
+ interface ConnectBoxProps {
134
+ maxWidth?: string | number;
135
+ transparent?: boolean;
136
+ appIcon?: string;
137
+ appName?: string;
138
+ }
139
+ declare function ConnectBox({ maxWidth, transparent, appIcon, appName }: ConnectBoxProps): react_jsx_runtime.JSX.Element;
140
+
141
+ export { ConnectBox, ConnectBoxProps, ConnectButton, ConnectButtonProps, ConnectOptions, PhantomDebugConfig, PhantomProvider, PhantomProviderProps, PhantomSDKConfig, UseDiscoveredWalletsResult, UseModalResult, useAccounts, useAutoConfirm, useConnect, useDisconnect, useDiscoveredWallets, useEthereum, useIsExtensionInstalled, useIsPhantomLoginAvailable, useModal, usePhantom, useSolana };
package/dist/index.js CHANGED
@@ -31,15 +31,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  AddressType: () => import_browser_sdk8.AddressType,
34
+ ConnectBox: () => ConnectBox,
34
35
  ConnectButton: () => ConnectButton,
35
36
  DebugLevel: () => import_browser_sdk8.DebugLevel,
36
37
  NetworkId: () => import_browser_sdk8.NetworkId,
37
38
  PhantomProvider: () => PhantomProvider,
38
- darkTheme: () => import_wallet_sdk_ui8.darkTheme,
39
+ darkTheme: () => import_wallet_sdk_ui9.darkTheme,
39
40
  debug: () => import_browser_sdk8.debug,
40
41
  isMobileDevice: () => import_browser_sdk8.isMobileDevice,
41
- lightTheme: () => import_wallet_sdk_ui8.lightTheme,
42
- mergeTheme: () => import_wallet_sdk_ui8.mergeTheme,
42
+ lightTheme: () => import_wallet_sdk_ui9.lightTheme,
43
+ mergeTheme: () => import_wallet_sdk_ui9.mergeTheme,
43
44
  useAccounts: () => useAccounts,
44
45
  useAutoConfirm: () => useAutoConfirm,
45
46
  useConnect: () => useConnect,
@@ -296,7 +297,12 @@ function ChainIcon({ addressType, size = 8 }) {
296
297
 
297
298
  // src/components/ConnectModalContent.tsx
298
299
  var import_jsx_runtime2 = require("react/jsx-runtime");
299
- function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
300
+ function ConnectModalContent({
301
+ appIcon,
302
+ appName = "App Name",
303
+ onClose,
304
+ hideCloseButton = false
305
+ }) {
300
306
  const theme = (0, import_wallet_sdk_ui2.useTheme)();
301
307
  const { isLoading, allowedProviders } = usePhantom();
302
308
  const baseConnect = useConnect();
@@ -309,6 +315,8 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
309
315
  const [providerType, setProviderType] = (0, import_react5.useState)(null);
310
316
  const [showOtherWallets, setShowOtherWallets] = (0, import_react5.useState)(false);
311
317
  const [selectedWalletId, setSelectedWalletId] = (0, import_react5.useState)(null);
318
+ const isConnectingState = baseConnect.isConnecting || isConnecting;
319
+ const errorState = baseConnect.error ? baseConnect.error.message : error;
312
320
  const showDivider = !(allowedProviders.length === 1 && allowedProviders.includes("injected"));
313
321
  const shouldShowOtherWalletsButton = discoveredWallets.length > 2;
314
322
  const walletsToShowInline = shouldShowOtherWalletsButton ? [] : discoveredWallets;
@@ -482,7 +490,7 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
482
490
  100% { transform: rotate(360deg); }
483
491
  }
484
492
  ` }),
485
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: loadingContainerStyle, children: [
493
+ isLoading || baseConnect.isConnecting ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: loadingContainerStyle, children: [
486
494
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: spinnerStyle }),
487
495
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_wallet_sdk_ui2.Text, { variant: "label", color: theme.secondary, children: "Loading..." })
488
496
  ] }) : showOtherWallets ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
@@ -495,17 +503,18 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
495
503
  setShowOtherWallets(false);
496
504
  },
497
505
  title: "Other Wallets",
498
- onClose
506
+ onClose,
507
+ hideCloseButton
499
508
  }
500
509
  ),
501
510
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: otherWalletsContainerStyle, children: [
502
- error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: errorStyle, children: error }),
511
+ errorState && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: errorStyle, children: errorState }),
503
512
  discoveredWallets.map((wallet) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
504
513
  import_wallet_sdk_ui2.Button,
505
514
  {
506
515
  onClick: () => connectWithWallet(wallet),
507
- disabled: isConnecting,
508
- isLoading: isConnecting && providerType === "injected" && selectedWalletId === wallet.id,
516
+ disabled: isConnectingState,
517
+ isLoading: isConnectingState && providerType === "injected" && selectedWalletId === wallet.id,
509
518
  fullWidth: true,
510
519
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: walletButtonContentStyle, children: [
511
520
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: walletButtonLeftStyle, children: [
@@ -522,16 +531,16 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
522
531
  ))
523
532
  ] })
524
533
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
525
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_wallet_sdk_ui2.ModalHeader, { title: "Login or Sign Up", onClose }),
534
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_wallet_sdk_ui2.ModalHeader, { title: "Login or Sign Up", onClose, hideCloseButton }),
526
535
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: connectContentContainerStyle, children: [
527
536
  appIcon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("img", { src: appIcon, alt: appName, style: appIconStyle }),
528
- error && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: errorStyle, children: error }),
537
+ errorState && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: errorStyle, children: errorState }),
529
538
  isMobile && !isExtensionInstalled.isInstalled && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
530
539
  import_wallet_sdk_ui2.Button,
531
540
  {
532
541
  onClick: connectWithDeeplink,
533
- disabled: isConnecting,
534
- isLoading: isConnecting && providerType === "deeplink",
542
+ disabled: isConnectingState,
543
+ isLoading: isConnectingState && providerType === "deeplink",
535
544
  fullWidth: true,
536
545
  children: isConnecting && providerType === "deeplink" ? "Opening Phantom..." : "Open in Phantom App"
537
546
  }
@@ -540,16 +549,16 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
540
549
  import_wallet_sdk_ui2.LoginWithPhantomButton,
541
550
  {
542
551
  onClick: () => connectWithAuthProvider("phantom"),
543
- disabled: isConnecting,
544
- isLoading: isConnecting && providerType === "phantom"
552
+ disabled: isConnectingState,
553
+ isLoading: isConnectingState && providerType === "phantom"
545
554
  }
546
555
  ),
547
556
  allowedProviders.includes("google") && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
548
557
  import_wallet_sdk_ui2.Button,
549
558
  {
550
559
  onClick: () => connectWithAuthProvider("google"),
551
- disabled: isConnecting,
552
- isLoading: isConnecting && providerType === "google",
560
+ disabled: isConnectingState,
561
+ isLoading: isConnectingState && providerType === "google",
553
562
  fullWidth: true,
554
563
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: walletButtonContentStyle, children: [
555
564
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: walletButtonLeftStyle, children: [
@@ -564,8 +573,8 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
564
573
  import_wallet_sdk_ui2.Button,
565
574
  {
566
575
  onClick: () => connectWithAuthProvider("apple"),
567
- disabled: isConnecting,
568
- isLoading: isConnecting && providerType === "apple",
576
+ disabled: isConnectingState,
577
+ isLoading: isConnectingState && providerType === "apple",
569
578
  fullWidth: true,
570
579
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: walletButtonContentStyle, children: [
571
580
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: walletButtonLeftStyle, children: [
@@ -576,7 +585,7 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
576
585
  ] })
577
586
  }
578
587
  ),
579
- !isMobile && allowedProviders.includes("injected") && isExtensionInstalled.isInstalled && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
588
+ !isMobile && allowedProviders.includes("injected") && (isExtensionInstalled.isInstalled || discoveredWallets.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
580
589
  showDivider && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: dividerStyle, children: [
581
590
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: dividerLineStyle }),
582
591
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: dividerTextStyle, children: "OR" }),
@@ -586,8 +595,8 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
586
595
  import_wallet_sdk_ui2.Button,
587
596
  {
588
597
  onClick: () => connectWithWallet(wallet),
589
- disabled: isConnecting,
590
- isLoading: isConnecting && providerType === "injected" && selectedWalletId === wallet.id,
598
+ disabled: isConnectingState,
599
+ isLoading: isConnectingState && providerType === "injected" && selectedWalletId === wallet.id,
591
600
  fullWidth: true,
592
601
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: walletButtonContentStyle, children: [
593
602
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: walletButtonLeftStyle, children: [
@@ -602,7 +611,7 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
602
611
  },
603
612
  wallet.id
604
613
  )),
605
- shouldShowOtherWalletsButton && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_wallet_sdk_ui2.Button, { onClick: () => setShowOtherWallets(true), disabled: isConnecting, fullWidth: true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: walletButtonContentStyle, children: [
614
+ shouldShowOtherWalletsButton && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_wallet_sdk_ui2.Button, { onClick: () => setShowOtherWallets(true), disabled: isConnectingState, fullWidth: true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: walletButtonContentStyle, children: [
606
615
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: walletButtonLeftStyle, children: [
607
616
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_wallet_sdk_ui2.BoundedIcon, { type: "wallet", size: 20, background: theme.aux, color: theme.text }),
608
617
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_wallet_sdk_ui2.Text, { variant: "captionBold", children: "Other Wallets" })
@@ -655,7 +664,7 @@ function useDisconnect() {
655
664
 
656
665
  // src/components/ConnectedModalContent.tsx
657
666
  var import_jsx_runtime3 = require("react/jsx-runtime");
658
- function ConnectedModalContent({ onClose }) {
667
+ function ConnectedModalContent({ onClose, hideCloseButton = false }) {
659
668
  const theme = (0, import_wallet_sdk_ui3.useTheme)();
660
669
  const { addresses } = usePhantom();
661
670
  const { disconnect } = useDisconnect();
@@ -734,7 +743,7 @@ function ConnectedModalContent({ onClose }) {
734
743
  minWidth: 0
735
744
  };
736
745
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: contentWrapperStyle, children: [
737
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_wallet_sdk_ui3.ModalHeader, { title: "Wallet", onClose }),
746
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_wallet_sdk_ui3.ModalHeader, { title: "Wallet", onClose, hideCloseButton }),
738
747
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: accountListContainerStyle, children: [
739
748
  disconnectError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: errorContainerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_wallet_sdk_ui3.Text, { variant: "caption", color: theme.error, children: "Failed to disconnect" }) }),
740
749
  addresses && addresses.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: accountListStyle, children: addresses.map((account, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: accountItemStyle, children: [
@@ -820,7 +829,12 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
820
829
  const handleConnectError = (errorData) => {
821
830
  setIsConnecting(false);
822
831
  setIsConnected(false);
823
- setConnectError(new Error(errorData.error || "Connection failed"));
832
+ const isAutoConnectNoSession = errorData.source === "auto-connect" && (errorData.error === "No valid session found" || errorData.error === "No trusted connections available");
833
+ if (isAutoConnectNoSession) {
834
+ setConnectError(null);
835
+ } else {
836
+ setConnectError(new Error(errorData.error || "Connection failed"));
837
+ }
824
838
  setAddresses([]);
825
839
  };
826
840
  const handleDisconnect = () => {
@@ -1108,6 +1122,31 @@ function ConnectButton({ addressType, fullWidth = false }) {
1108
1122
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { style: buttonStyle, onClick: open, children: "Connect Wallet" });
1109
1123
  }
1110
1124
 
1111
- // src/index.ts
1125
+ // src/components/ConnectBox.tsx
1126
+ var import_react12 = require("react");
1112
1127
  var import_wallet_sdk_ui8 = require("@phantom/wallet-sdk-ui");
1128
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1129
+ function ConnectBox({ maxWidth = "350px", transparent = false, appIcon, appName }) {
1130
+ const theme = (0, import_wallet_sdk_ui8.useTheme)();
1131
+ const { isConnected } = usePhantom();
1132
+ const boxStyle = (0, import_react12.useMemo)(() => {
1133
+ const style = {
1134
+ width: "100%",
1135
+ maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth,
1136
+ position: "relative",
1137
+ overflow: "hidden"
1138
+ };
1139
+ if (!transparent) {
1140
+ style.backgroundColor = theme.background;
1141
+ style.borderRadius = theme.borderRadius;
1142
+ }
1143
+ return style;
1144
+ }, [maxWidth, transparent, theme.background, theme.borderRadius]);
1145
+ const noOp = () => {
1146
+ };
1147
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: boxStyle, children: isConnected ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ConnectedModalContent, { onClose: noOp, hideCloseButton: true }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ConnectModalContent, { appIcon, appName, onClose: noOp, hideCloseButton: true }) });
1148
+ }
1149
+
1150
+ // src/index.ts
1151
+ var import_wallet_sdk_ui9 = require("@phantom/wallet-sdk-ui");
1113
1152
  var import_browser_sdk8 = require("@phantom/browser-sdk");
package/dist/index.mjs CHANGED
@@ -251,7 +251,12 @@ function ChainIcon({ addressType, size = 8 }) {
251
251
 
252
252
  // src/components/ConnectModalContent.tsx
253
253
  import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
254
- function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
254
+ function ConnectModalContent({
255
+ appIcon,
256
+ appName = "App Name",
257
+ onClose,
258
+ hideCloseButton = false
259
+ }) {
255
260
  const theme = useTheme2();
256
261
  const { isLoading, allowedProviders } = usePhantom();
257
262
  const baseConnect = useConnect();
@@ -264,6 +269,8 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
264
269
  const [providerType, setProviderType] = useState4(null);
265
270
  const [showOtherWallets, setShowOtherWallets] = useState4(false);
266
271
  const [selectedWalletId, setSelectedWalletId] = useState4(null);
272
+ const isConnectingState = baseConnect.isConnecting || isConnecting;
273
+ const errorState = baseConnect.error ? baseConnect.error.message : error;
267
274
  const showDivider = !(allowedProviders.length === 1 && allowedProviders.includes("injected"));
268
275
  const shouldShowOtherWalletsButton = discoveredWallets.length > 2;
269
276
  const walletsToShowInline = shouldShowOtherWalletsButton ? [] : discoveredWallets;
@@ -437,7 +444,7 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
437
444
  100% { transform: rotate(360deg); }
438
445
  }
439
446
  ` }),
440
- isLoading ? /* @__PURE__ */ jsxs("div", { style: loadingContainerStyle, children: [
447
+ isLoading || baseConnect.isConnecting ? /* @__PURE__ */ jsxs("div", { style: loadingContainerStyle, children: [
441
448
  /* @__PURE__ */ jsx2("div", { style: spinnerStyle }),
442
449
  /* @__PURE__ */ jsx2(Text, { variant: "label", color: theme.secondary, children: "Loading..." })
443
450
  ] }) : showOtherWallets ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -450,17 +457,18 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
450
457
  setShowOtherWallets(false);
451
458
  },
452
459
  title: "Other Wallets",
453
- onClose
460
+ onClose,
461
+ hideCloseButton
454
462
  }
455
463
  ),
456
464
  /* @__PURE__ */ jsxs("div", { style: otherWalletsContainerStyle, children: [
457
- error && /* @__PURE__ */ jsx2("div", { style: errorStyle, children: error }),
465
+ errorState && /* @__PURE__ */ jsx2("div", { style: errorStyle, children: errorState }),
458
466
  discoveredWallets.map((wallet) => /* @__PURE__ */ jsx2(
459
467
  Button,
460
468
  {
461
469
  onClick: () => connectWithWallet(wallet),
462
- disabled: isConnecting,
463
- isLoading: isConnecting && providerType === "injected" && selectedWalletId === wallet.id,
470
+ disabled: isConnectingState,
471
+ isLoading: isConnectingState && providerType === "injected" && selectedWalletId === wallet.id,
464
472
  fullWidth: true,
465
473
  children: /* @__PURE__ */ jsxs("span", { style: walletButtonContentStyle, children: [
466
474
  /* @__PURE__ */ jsxs("span", { style: walletButtonLeftStyle, children: [
@@ -477,16 +485,16 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
477
485
  ))
478
486
  ] })
479
487
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
480
- /* @__PURE__ */ jsx2(ModalHeader, { title: "Login or Sign Up", onClose }),
488
+ /* @__PURE__ */ jsx2(ModalHeader, { title: "Login or Sign Up", onClose, hideCloseButton }),
481
489
  /* @__PURE__ */ jsxs("div", { style: connectContentContainerStyle, children: [
482
490
  appIcon && /* @__PURE__ */ jsx2("img", { src: appIcon, alt: appName, style: appIconStyle }),
483
- error && /* @__PURE__ */ jsx2("div", { style: errorStyle, children: error }),
491
+ errorState && /* @__PURE__ */ jsx2("div", { style: errorStyle, children: errorState }),
484
492
  isMobile && !isExtensionInstalled.isInstalled && /* @__PURE__ */ jsx2(
485
493
  Button,
486
494
  {
487
495
  onClick: connectWithDeeplink,
488
- disabled: isConnecting,
489
- isLoading: isConnecting && providerType === "deeplink",
496
+ disabled: isConnectingState,
497
+ isLoading: isConnectingState && providerType === "deeplink",
490
498
  fullWidth: true,
491
499
  children: isConnecting && providerType === "deeplink" ? "Opening Phantom..." : "Open in Phantom App"
492
500
  }
@@ -495,16 +503,16 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
495
503
  LoginWithPhantomButton,
496
504
  {
497
505
  onClick: () => connectWithAuthProvider("phantom"),
498
- disabled: isConnecting,
499
- isLoading: isConnecting && providerType === "phantom"
506
+ disabled: isConnectingState,
507
+ isLoading: isConnectingState && providerType === "phantom"
500
508
  }
501
509
  ),
502
510
  allowedProviders.includes("google") && /* @__PURE__ */ jsx2(
503
511
  Button,
504
512
  {
505
513
  onClick: () => connectWithAuthProvider("google"),
506
- disabled: isConnecting,
507
- isLoading: isConnecting && providerType === "google",
514
+ disabled: isConnectingState,
515
+ isLoading: isConnectingState && providerType === "google",
508
516
  fullWidth: true,
509
517
  children: /* @__PURE__ */ jsxs("span", { style: walletButtonContentStyle, children: [
510
518
  /* @__PURE__ */ jsxs("span", { style: walletButtonLeftStyle, children: [
@@ -519,8 +527,8 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
519
527
  Button,
520
528
  {
521
529
  onClick: () => connectWithAuthProvider("apple"),
522
- disabled: isConnecting,
523
- isLoading: isConnecting && providerType === "apple",
530
+ disabled: isConnectingState,
531
+ isLoading: isConnectingState && providerType === "apple",
524
532
  fullWidth: true,
525
533
  children: /* @__PURE__ */ jsxs("span", { style: walletButtonContentStyle, children: [
526
534
  /* @__PURE__ */ jsxs("span", { style: walletButtonLeftStyle, children: [
@@ -531,7 +539,7 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
531
539
  ] })
532
540
  }
533
541
  ),
534
- !isMobile && allowedProviders.includes("injected") && isExtensionInstalled.isInstalled && /* @__PURE__ */ jsxs(Fragment, { children: [
542
+ !isMobile && allowedProviders.includes("injected") && (isExtensionInstalled.isInstalled || discoveredWallets.length > 0) && /* @__PURE__ */ jsxs(Fragment, { children: [
535
543
  showDivider && /* @__PURE__ */ jsxs("div", { style: dividerStyle, children: [
536
544
  /* @__PURE__ */ jsx2("div", { style: dividerLineStyle }),
537
545
  /* @__PURE__ */ jsx2("span", { style: dividerTextStyle, children: "OR" }),
@@ -541,8 +549,8 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
541
549
  Button,
542
550
  {
543
551
  onClick: () => connectWithWallet(wallet),
544
- disabled: isConnecting,
545
- isLoading: isConnecting && providerType === "injected" && selectedWalletId === wallet.id,
552
+ disabled: isConnectingState,
553
+ isLoading: isConnectingState && providerType === "injected" && selectedWalletId === wallet.id,
546
554
  fullWidth: true,
547
555
  children: /* @__PURE__ */ jsxs("span", { style: walletButtonContentStyle, children: [
548
556
  /* @__PURE__ */ jsxs("span", { style: walletButtonLeftStyle, children: [
@@ -557,7 +565,7 @@ function ConnectModalContent({ appIcon, appName = "App Name", onClose }) {
557
565
  },
558
566
  wallet.id
559
567
  )),
560
- shouldShowOtherWalletsButton && /* @__PURE__ */ jsx2(Button, { onClick: () => setShowOtherWallets(true), disabled: isConnecting, fullWidth: true, children: /* @__PURE__ */ jsxs("span", { style: walletButtonContentStyle, children: [
568
+ shouldShowOtherWalletsButton && /* @__PURE__ */ jsx2(Button, { onClick: () => setShowOtherWallets(true), disabled: isConnectingState, fullWidth: true, children: /* @__PURE__ */ jsxs("span", { style: walletButtonContentStyle, children: [
561
569
  /* @__PURE__ */ jsxs("span", { style: walletButtonLeftStyle, children: [
562
570
  /* @__PURE__ */ jsx2(BoundedIcon, { type: "wallet", size: 20, background: theme.aux, color: theme.text }),
563
571
  /* @__PURE__ */ jsx2(Text, { variant: "captionBold", children: "Other Wallets" })
@@ -610,7 +618,7 @@ function useDisconnect() {
610
618
 
611
619
  // src/components/ConnectedModalContent.tsx
612
620
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
613
- function ConnectedModalContent({ onClose }) {
621
+ function ConnectedModalContent({ onClose, hideCloseButton = false }) {
614
622
  const theme = useTheme3();
615
623
  const { addresses } = usePhantom();
616
624
  const { disconnect } = useDisconnect();
@@ -689,7 +697,7 @@ function ConnectedModalContent({ onClose }) {
689
697
  minWidth: 0
690
698
  };
691
699
  return /* @__PURE__ */ jsxs2("div", { style: contentWrapperStyle, children: [
692
- /* @__PURE__ */ jsx3(ModalHeader2, { title: "Wallet", onClose }),
700
+ /* @__PURE__ */ jsx3(ModalHeader2, { title: "Wallet", onClose, hideCloseButton }),
693
701
  /* @__PURE__ */ jsxs2("div", { style: accountListContainerStyle, children: [
694
702
  disconnectError && /* @__PURE__ */ jsx3("div", { style: errorContainerStyle, children: /* @__PURE__ */ jsx3(Text2, { variant: "caption", color: theme.error, children: "Failed to disconnect" }) }),
695
703
  addresses && addresses.length > 0 && /* @__PURE__ */ jsx3("div", { style: accountListStyle, children: addresses.map((account, index) => /* @__PURE__ */ jsxs2("div", { style: accountItemStyle, children: [
@@ -775,7 +783,12 @@ function PhantomProvider({ children, config, debugConfig, theme, appIcon, appNam
775
783
  const handleConnectError = (errorData) => {
776
784
  setIsConnecting(false);
777
785
  setIsConnected(false);
778
- setConnectError(new Error(errorData.error || "Connection failed"));
786
+ const isAutoConnectNoSession = errorData.source === "auto-connect" && (errorData.error === "No valid session found" || errorData.error === "No trusted connections available");
787
+ if (isAutoConnectNoSession) {
788
+ setConnectError(null);
789
+ } else {
790
+ setConnectError(new Error(errorData.error || "Connection failed"));
791
+ }
779
792
  setAddresses([]);
780
793
  };
781
794
  const handleDisconnect = () => {
@@ -1063,11 +1076,37 @@ function ConnectButton({ addressType, fullWidth = false }) {
1063
1076
  return /* @__PURE__ */ jsx6("button", { style: buttonStyle, onClick: open, children: "Connect Wallet" });
1064
1077
  }
1065
1078
 
1079
+ // src/components/ConnectBox.tsx
1080
+ import { useMemo as useMemo5 } from "react";
1081
+ import { useTheme as useTheme6 } from "@phantom/wallet-sdk-ui";
1082
+ import { jsx as jsx7 } from "react/jsx-runtime";
1083
+ function ConnectBox({ maxWidth = "350px", transparent = false, appIcon, appName }) {
1084
+ const theme = useTheme6();
1085
+ const { isConnected } = usePhantom();
1086
+ const boxStyle = useMemo5(() => {
1087
+ const style = {
1088
+ width: "100%",
1089
+ maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth,
1090
+ position: "relative",
1091
+ overflow: "hidden"
1092
+ };
1093
+ if (!transparent) {
1094
+ style.backgroundColor = theme.background;
1095
+ style.borderRadius = theme.borderRadius;
1096
+ }
1097
+ return style;
1098
+ }, [maxWidth, transparent, theme.background, theme.borderRadius]);
1099
+ const noOp = () => {
1100
+ };
1101
+ return /* @__PURE__ */ jsx7("div", { style: boxStyle, children: isConnected ? /* @__PURE__ */ jsx7(ConnectedModalContent, { onClose: noOp, hideCloseButton: true }) : /* @__PURE__ */ jsx7(ConnectModalContent, { appIcon, appName, onClose: noOp, hideCloseButton: true }) });
1102
+ }
1103
+
1066
1104
  // src/index.ts
1067
1105
  import { darkTheme as darkTheme2, lightTheme, mergeTheme as mergeTheme2 } from "@phantom/wallet-sdk-ui";
1068
1106
  import { NetworkId, AddressType as AddressType3, DebugLevel, debug, isMobileDevice as isMobileDevice3 } from "@phantom/browser-sdk";
1069
1107
  export {
1070
1108
  AddressType3 as AddressType,
1109
+ ConnectBox,
1071
1110
  ConnectButton,
1072
1111
  DebugLevel,
1073
1112
  NetworkId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/react-sdk",
3
- "version": "1.0.0-beta.25",
3
+ "version": "1.0.0-beta.27",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/phantom/phantom-connect-sdk",
@@ -31,10 +31,10 @@
31
31
  "prettier": "prettier --write \"src/**/*.{ts,tsx}\""
32
32
  },
33
33
  "dependencies": {
34
- "@phantom/browser-sdk": "^1.0.0-beta.25",
35
- "@phantom/chain-interfaces": "^1.0.0-beta.13",
36
- "@phantom/constants": "^1.0.0-beta.13",
37
- "@phantom/wallet-sdk-ui": "^1.0.0-beta.4"
34
+ "@phantom/browser-sdk": "^1.0.0-beta.27",
35
+ "@phantom/chain-interfaces": "^1.0.0-beta.15",
36
+ "@phantom/constants": "^1.0.0-beta.15",
37
+ "@phantom/wallet-sdk-ui": "^1.0.0-beta.6"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@testing-library/dom": "^10.4.0",