npm package: @sideshiftapp/connect
Description: SideShift Connect - Embeddable payout and pay-in widgets
Latest version: 0.1.0

# @sideshiftapp/connect

Embed SideShift Connect payout and pay-in widgets in your application.

## Installation

```bash
npm install @sideshiftapp/connect
```

## Quick Start

### React

```tsx
import { SideShiftPayout, SideShiftPayin } from '@sideshiftapp/connect/react';

function App() {
  // Generate this token server-side via POST /api/embed/auth/token
  const token = 'eyJ...';

  return (
    <SideShiftPayout
      token={token}
      theme={{ theme: 'light', primaryColor: '#3D8CFA', borderRadius: 12 }}
      onLoad={() => console.log('Widget ready')}
      onWithdrawCompleted={(data) => console.log('Withdrew', data.amountCents / 100)}
      onSessionExpired={() => {
        // Refresh the token and re-render
      }}
    />
  );
}
```

### Vanilla JS

```js
import { mount } from '@sideshiftapp/connect/vanilla';

const widget = mount({
  widgetType: 'payout',
  token: 'eyJ...',
  container: '#widget-root',
  theme: { theme: 'light', primaryColor: '#3D8CFA' },
  onLoad: () => console.log('Widget ready'),
  onWithdrawCompleted: (data) => console.log('Withdrew', data.amountCents / 100),
});

// Later: clean up
widget.unmount();
```

### Script Tag

```html
<script type="module">
  import { mount } from 'https://cdn.jsdelivr.net/npm/@sideshiftapp/connect/dist/vanilla.mjs';

  mount({
    widgetType: 'payout',
    token: 'YOUR_TOKEN',
    container: '#widget',
    theme: { theme: 'light' },
  });
</script>

<div id="widget"></div>
```

## Widgets

### SideShiftPayout

Displays a user's balance and lets them withdraw funds to their bank account.

```tsx
<SideShiftPayout
  token={token}
  theme={{ theme: 'dark', primaryColor: '#10B981' }}
  autoResize={true}
  onLoad={() => {}}
  onError={(err) => console.error(err.message)}
  onSessionExpired={() => refreshToken()}
  onWithdrawInitiated={(data) => console.log('Initiating', data.amountCents)}
  onWithdrawCompleted={(data) => console.log('Done', data.withdrawalId)}
  onBalanceUpdated={(data) => console.log('Balance:', data.balanceCents)}
  onKycStarted={() => console.log('KYC flow started')}
  onKycCompleted={() => console.log('KYC verified')}
/>
```

### SideShiftPayin

Lets users deposit funds via credit/debit card.

```tsx
<SideShiftPayin
  token={token}
  theme={{ theme: 'light' }}
  defaultAmountCents={5000}
  quickAmountsCents={[1000, 5000, 10000, 25000]}
  onDepositInitiated={(data) => console.log('Depositing', data.amountCents)}
  onDepositCompleted={(data) => console.log('Deposited', data.depositId)}
  onDepositFailed={(data) => console.error('Failed:', data.error)}
  onMethodAdded={() => console.log('Payment method added')}
  onAmountChanged={(data) => console.log('Amount:', data.amountCents)}
/>
```

## Props

### Common Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `token` | `string` | **required** | Access token from `POST /api/embed/auth/token` |
| `baseUrl` | `string` | `https://app.sideshift.app` | SideShift app URL |
| `theme` | `WidgetThemeConfig` | `{ theme: 'light' }` | Theme configuration |
| `style` | `CSSProperties` | - | Container inline styles |
| `className` | `string` | - | Container CSS class |
| `autoResize` | `boolean` | `true` | Auto-resize iframe height to fit content |
| `onLoad` | `() => void` | - | Widget loaded and ready |
| `onError` | `(err) => void` | - | Widget encountered an error |
| `onSessionExpired` | `() => void` | - | Token expired, regenerate and re-render |

### Payout-Specific Props

| Prop | Type | Description |
|------|------|-------------|
| `onWithdrawInitiated` | `(data: { amountCents }) => void` | User started a withdrawal |
| `onWithdrawCompleted` | `(data: { amountCents, withdrawalId? }) => void` | Withdrawal succeeded |
| `onBalanceUpdated` | `(data: { balanceCents }) => void` | Balance changed |
| `onKycStarted` | `() => void` | User started identity verification |
| `onKycCompleted` | `() => void` | Identity verification completed |

### Pay-in-Specific Props

| Prop | Type | Description |
|------|------|-------------|
| `defaultAmountCents` | `number` | Pre-filled deposit amount |
| `quickAmountsCents` | `number[]` | Quick-select amount buttons |
| `onDepositInitiated` | `(data: { amountCents }) => void` | User started a deposit |
| `onDepositCompleted` | `(data: { amountCents, depositId? }) => void` | Deposit succeeded |
| `onDepositFailed` | `(data: { amountCents, error? }) => void` | Deposit failed |
| `onMethodAdded` | `() => void` | User added a payment method |
| `onAmountChanged` | `(data: { amountCents }) => void` | User changed the deposit amount |

## Theme Configuration

Full theme customization is supported:

```tsx
const theme: WidgetThemeConfig = {
  theme: 'light', // 'light' | 'dark' | 'auto'

  // Simple options
  primaryColor: '#3D8CFA',
  borderRadius: 12,
  fontFamily: 'Inter, sans-serif',

  // Fine-grained color control
  colors: {
    background: '#ffffff',
    cardBackground: '#ffffff',
    primary: '#3D8CFA',
    textPrimary: '#111827',
    border: '#e5e7eb',
  },

  // Typography
  typography: {
    fontFamily: 'Inter, sans-serif',
    headingSize: '16px',
    bodySize: '14px',
  },

  // Layout options
  layout: {
    showBalance: true,
    showHistory: true,
    maxWidth: '450px',
  },

  // Custom labels
  labels: {
    balanceLabel: 'Your Earnings',
    withdrawButton: 'Cash Out',
    historyTitle: 'Past Withdrawals',
  },
};
```

## Server-Side Token Generation

Tokens are generated on your server using your API key:

```js
const response = await fetch('https://app.sideshift.app/api/embed/auth/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': process.env.SIDESHIFT_API_KEY, // sk_live_... or sk_test_...
  },
  body: JSON.stringify({
    sideshiftAccountId: 'user-account-id',
    widgetType: 'payout', // or 'payin' or 'both'
    expiresInSeconds: 3600,
  }),
});

const { data } = await response.json();
const token = data.accessToken; // Pass this to the widget component
```

Use `sk_test_*` keys for sandbox mode (no real money moves).

## License

MIT