npm package: @spin-studio/sdk
Description: Lightweight JavaScript SDK for embedding Spin Studio wheels
Author: Spin Studio
Latest version: 0.1.1

# @spin-studio/sdk

Lightweight JavaScript SDK for embedding Spin Studio wheels into any website. Framework-agnostic, works everywhere.

## Installation

```bash
npm install @spin-studio/sdk
```

Or via CDN:

```html
<script src="https://unpkg.com/@spin-studio/sdk@latest/dist/spin-studio.umd.js"></script>
```

## Quick Start

### 1. Get Your API Key

1. Sign up at [spin-studio.weez.boo](https://spin-studio.weez.boo)
2. Create an organization
3. Go to **Settings → API Keys → Create API Key**
4. Copy your API key (shown only once!)

### 2. Create a Wheel

1. Go to **Dashboard → Wheels → Create Wheel**
2. Add segments (e.g., "10% OFF", "20% OFF", "Free Shipping")
3. Customize colors and styling
4. Click **Publish**
5. Copy the **Wheel ID** from the URL

### 3. Integrate

```javascript
import SpinStudio from '@spin-studio/sdk';

// Initialize with your API key
SpinStudio.init({
  apiKey: 'sk_live_your_api_key_here',
  baseUrl: 'https://spin-studio.weez.boo'
});

// Open wheel as modal
SpinStudio.open('your-wheel-id');
```

## Usage Examples

### Modal Popup (Default)

```javascript
SpinStudio.init({ apiKey: 'sk_live_xxx' });

document.getElementById('spin-btn').addEventListener('click', () => {
  SpinStudio.open('wheel-id');
});
```

### Inline Embed

```javascript
SpinStudio.init({ apiKey: 'sk_live_xxx' });

SpinStudio.open({
  wheelId: 'wheel-id',
  container: '#wheel-container', // CSS selector or HTMLElement
  mode: 'inline'
});
```

### With Event Handlers

```javascript
SpinStudio.init({ apiKey: 'sk_live_xxx' });

SpinStudio.open({
  wheelId: 'wheel-id',
  on: {
    onReady: (event) => {
      console.log('Wheel loaded:', event.wheelId);
    },
    onSpinStart: (event) => {
      console.log('Spin started!');
    },
    onSpinEnd: (event) => {
      console.log('Spin ended');
    },
    onPrizeWon: (event) => {
      console.log('Prize won:', event.prize);
      console.log('Redemption code:', event.redemptionCode);

      // Apply discount to your cart
      applyDiscount(event.prize.value, event.redemptionCode);
    },
    onError: (event) => {
      console.error('Error:', event.message);
    }
  }
});
```

### Theming

```javascript
SpinStudio.init({
  apiKey: 'sk_live_xxx',
  theme: {
    overlayBackground: 'rgba(0, 0, 0, 0.8)',
    modalBackground: '#ffffff',
    modalBorderRadius: '16px',
    primaryColor: '#6366F1',
    fontFamily: 'Inter, sans-serif'
  }
});
```

## API Reference

### `SpinStudio.init(config)`

Initialize the SDK. Call this once before using other methods.

```typescript
interface SpinStudioConfig {
  apiKey: string;              // Required - Your API key
  baseUrl?: string;            // Default: 'https://spin-studio.weez.boo'
  debug?: boolean;             // Default: false
  theme?: ThemeConfig;         // Custom theme
  locale?: string;             // Default: 'en'
}
```

### `SpinStudio.open(wheelId | options)`

Open a wheel. Returns a `WheelInstance`.

```typescript
// Simple
SpinStudio.open('wheel-id');

// With options
SpinStudio.open({
  wheelId: string;
  container?: string | HTMLElement;  // For inline mode
  mode?: 'modal' | 'inline';         // Default: 'modal'
  userId?: string;                   // Track user
  metadata?: Record<string, any>;    // Custom data
  theme?: ThemeConfig;               // Override theme
  on?: EventCallbacks;               // Event handlers
});
```

### `SpinStudio.preload(wheelId)`

Preload wheel assets for faster display.

```javascript
await SpinStudio.preload('wheel-id');
```

### `SpinStudio.closeAll()`

Close all open wheels.

### `SpinStudio.destroy()`

Cleanup and destroy the SDK instance.

### `SpinStudio.setUser(userId, metadata?)`

Set user information for tracking.

```javascript
SpinStudio.setUser('user-123', { email: 'user@example.com' });
```

## Events

| Event | Description | Payload |
|-------|-------------|---------|
| `onReady` | Wheel loaded and ready | `{ wheelId, sessionId, timestamp }` |
| `onSpinStart` | Spin animation started | `{ wheelId, sessionId, timestamp }` |
| `onSpinEnd` | Spin animation ended | `{ wheelId, sessionId, timestamp }` |
| `onPrizeWon` | Prize won | `{ wheelId, sessionId, prize, redemptionCode }` |
| `onLevelUp` | Level increased | `{ wheelId, fromLevel, toLevel }` |
| `onLevelDown` | Level decreased | `{ wheelId, fromLevel, toLevel }` |
| `onError` | Error occurred | `{ wheelId, code, message }` |

## Prize Object

```typescript
interface Prize {
  id: string;
  name: string;
  type: 'discount_percentage' | 'discount_fixed' | 'free_shipping' |
        'free_product' | 'points' | 'coupon' | 'custom';
  value?: number;      // e.g., 15 for 15% off
  code?: string;       // Coupon code if applicable
  imageUrl?: string;
  expiresAt?: string;  // ISO date string
}
```

## Storing Discounts (Recommended)

To persist discount data in your database, add these fields to your Order model:

### Prisma Example

```prisma
model Order {
  // ... your existing fields
  discountCode     String?   // e.g., "SPIN-ABC123"
  discountType     String?   // "percentage", "fixed", "free_shipping"
  discountPercent  Float?    // e.g., 15
  discountAmount   Float?    // e.g., 15.00 (calculated)
  originalTotal    Float?    // Total before discount
}
```

### SQL Example

```sql
ALTER TABLE orders ADD COLUMN discount_code VARCHAR(50);
ALTER TABLE orders ADD COLUMN discount_type VARCHAR(20);
ALTER TABLE orders ADD COLUMN discount_percent DECIMAL(5,2);
ALTER TABLE orders ADD COLUMN discount_amount DECIMAL(10,2);
ALTER TABLE orders ADD COLUMN original_total DECIMAL(10,2);
```

> **Note:** Without these fields, discounts will only be applied visually and won't be persisted. The wheel will still work - you just won't have a record of the discount in your database.

## Web Component

You can also use the SDK as a Web Component:

```html
<script src="https://unpkg.com/@spin-studio/sdk@latest/dist/spin-studio.umd.js"></script>

<spin-wheel
  wheel-id="your-wheel-id"
  api-key="sk_live_xxx"
  mode="inline"
></spin-wheel>

<script>
  document.querySelector('spin-wheel').addEventListener('prize-won', (e) => {
    console.log('Prize:', e.detail.prize);
  });
</script>
```

## Framework-Specific Packages

For better integration with React or Vue, use our dedicated packages:

- **React:** `npm install @spin-studio/react` - [Documentation](https://www.npmjs.com/package/@spin-studio/react)
- **Vue 3:** `npm install @spin-studio/vue` - [Documentation](https://www.npmjs.com/package/@spin-studio/vue)

## Browser Support

- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+

## Bundle Size

- ESM: ~21 KB (minified)
- UMD: ~21 KB (minified)
- Gzipped: ~7 KB

## License

MIT