npm package: @saw-protocol/widget
Description: SAWP branded React widgets for dApp connections - The MetaMask-equivalent UI for agent wallets
Latest version: 1.0.8

# @saw-protocol/widget

SAWP branded React widgets for dApp connections. This is the **MetaMask-equivalent UI** for agent wallets — a complete, reusable widget system that dApps can integrate to connect to SAWP wallets.

## Features

- **ConnectionModal** — Beautiful branded modal for connection requests with permission display
- **ConnectionStatus** — Persistent status widget showing connection state at the top of your dApp
- **Notification System** — Toast notifications for connection events and transaction status
- **React Context Provider** — Easy state management across your application
- **TypeScript Support** — Fully typed for the best developer experience

## Installation

```bash
npm install @saw-protocol/widget
```

## Quick Start

Wrap your app with the `SAWPProvider` and add the widget components:

```tsx
import { 
  SAWPProvider, 
  ConnectionModal, 
  ConnectionStatus, 
  NotificationContainer 
} from '@saw-protocol/widget';

function App() {
  return (
    <SAWPProvider walletAddress="your-wallet-address">
      <ConnectionStatus position="top-right" />
      <ConnectionModal />
      <NotificationContainer />
      
      {/* Your app content */}
      <YourApp />
    </SAWPProvider>
  );
}
```

## Components

### SAWPProvider

The context provider that manages widget state and connection logic.

```tsx
<SAWPProvider 
  walletAddress="your-wallet-public-key"
  autoConnect={false}
>
  {children}
</SAWPProvider>
```

**Props:**
- `walletAddress` (string, optional) — The wallet address to connect from
- `autoConnect` (boolean, optional) — Whether to auto-restore previous connections

### ConnectionModal

Displays connection requests with full permission details. Automatically appears when a connection is requested.

```tsx
<ConnectionModal />
```

**Features:**
- Shows dApp name, icon, and origin
- Lists all requested permissions with descriptions
- Security warning about trusted dApps
- Approve/Reject actions

### ConnectionStatus

Persistent widget showing connection state. Stays visible at the edge of the screen.

```tsx
<ConnectionStatus position="top-right" />
```

**Props:**
- `position` ('top-right' | 'top-left' | 'top-center', default: 'top-right') — Where to position the widget

**Features:**
- Shows connected dApp name (truncated)
- Animated green pulse indicator when connected
- Dropdown with connection details and permissions
- One-click disconnect button
- Shows "Not Connected" state when disconnected

### NotificationContainer

Displays toast notifications for connection events and errors.

```tsx
<NotificationContainer />
```

**Features:**
- Auto-dismisses after duration
- Different colors for info/success/warning/error
- Stacked notifications with staggered animation
- Click to dismiss

## Hooks

### useSAWPWidget

Hook for dApps to initiate connections and transactions.

```tsx
import { useSAWPWidget } from '@saw-protocol/widget';

function MyDapp() {
  const { 
    isConnected, 
    isConnecting,
    requestConnection, 
    disconnect 
  } = useSAWPWidget();

  const handleConnect = async () => {
    try {
      await requestConnection(
        'my-dapp-id',
        ['transfer', 'swap', 'view'],
        { name: 'My DeFi App', url: window.location.origin }
      );
    } catch (err) {
      console.error('Connection rejected:', err);
    }
  };

  return (
    <button onClick={handleConnect}>
      {isConnected ? 'Connected' : 'Connect Wallet'}
    </button>
  );
}
```

## Complete Example

```tsx
import React from 'react';
import { 
  SAWPProvider, 
  ConnectionModal, 
  ConnectionStatus, 
  NotificationContainer,
  useSAWPWidget 
} from '@saw-protocol/widget';

// Your dApp component
function MyDeFiApp() {
  const { isConnected, requestConnection, disconnect } = useSAWPWidget();

  const handleConnect = async () => {
    await requestConnection(
      'my-defi-app',
      ['transfer', 'swap', 'stake'],
      {
        name: 'My DeFi Protocol',
        url: window.location.origin,
        icon: 'https://myapp.com/icon.png'
      }
    );
  };

  return (
    <div>
      <h1>My DeFi App</h1>
      
      {isConnected ? (
        <div>
          <p>Wallet connected!</p>
          <button onClick={disconnect}>Disconnect</button>
        </div>
      ) : (
        <button onClick={handleConnect}>Connect SAWP Wallet</button>
      )}
    </div>
  );
}

// App wrapper with SAWP widgets
function App() {
  return (
    <SAWPProvider walletAddress="your-wallet-address">
      {/* Widget components */}
      <ConnectionStatus position="top-right" />
      <ConnectionModal />
      <NotificationContainer />
      
      {/* Your app */}
      <MyDeFiApp />
    </SAWPProvider>
  );
}

export default App;
```

## Styling

The widgets come with built-in SAWP branding (purple/green dark theme). All styles are inline and scoped to components — no external CSS files required.

### Default Theme Colors
- Primary: `#9945ff` (purple)
- Secondary: `#14f195` (green)
- Background: `#12121a` (dark)
- Surface: `#1a1a25` (card backgrounds)
- Border: `#2a2a3a` (subtle borders)

## Architecture

```
┌─────────────────────────────────────┐
│           Your dApp                 │
│  ┌───────────────────────────────┐  │
│  │   useSAWPWidget() hook        │  │
│  │   - requestConnection()       │  │
│  │   - requestTransaction()      │  │
│  └───────────────────────────────┘  │
└─────────────────┬───────────────────┘
                  │
┌─────────────────▼───────────────────┐
│        SAWPProvider Context         │
│  ┌───────────────────────────────┐  │
│  │   WalletConnector instance    │  │
│  │   Connection state management │  │
│  │   Notification queue          │  │
│  └───────────────────────────────┘  │
└─────────────────┬───────────────────┘
                  │
    ┌─────────────┼─────────────┐
    │             │             │
┌───▼───┐  ┌─────▼──────┐ ┌────▼────┐
│Modal  │  │Status      │ │Notif.   │
│Widget │  │Widget      │ │Container│
└───────┘  └────────────┘ └─────────┘
```

## License

MIT