npm package: @getspot/spot-widget-react
Description: React wrapper for Spot Widget
Latest version: 4.1.1

# @getspot/spot-widget-react

React component wrapper for the Spot refund guarantee widget.

> **Note:** This React wrapper uses types from [@getspot/spot-widget](https://www.npmjs.com/package/@getspot/spot-widget).

### Key Types
- `ApiConfig` - API configuration (environment, partnerId, customEndpoint)
- `QuoteRequestData` - Quote request data for single items or batch requests
- `SelectionData` - User selection data returned in callbacks
- `Quote` - Quote response data with pricing and terms
- `Theme` - Styling customization options

For complete type definitions, see the [@getspot/spot-widget documentation](https://www.npmjs.com/package/@getspot/spot-widget).

## Installation

```bash
npm install @getspot/spot-widget-react
```

## Quick Start

```tsx
import React from 'react';
import ReactSpotWidget from '@getspot/spot-widget-react';

function App() {
  return (
    <ReactSpotWidget
      apiConfig={{
        environment: 'production', // or 'sandbox' for testing
        partnerId: 'your-partner-id'
      }}
      quoteRequestData={{
        startDate: '2024-01-01T00:00:00Z',
        endDate: '2024-01-07T23:59:59Z',
        currencyCode: 'USD',
        eventType: 'Ski Trip',
        productType: 'Trip',
        productDuration: 'Trip',
        productPrice: 500,
        productId: 'ski-trip-2024',
        cartId: 'cart-123',
        productName: 'Aspen Ski Trip 2024'
      }}
      onOptIn={(data) => {
        console.log('User opted in:', data);
        // Handle opt-in (e.g., add to cart, track analytics)
      }}
      onOptOut={(data) => {
        console.log('User opted out:', data);
        // Handle opt-out (e.g., track analytics)
      }}
      onError={(error) => {
        console.error('Widget error:', error);
        // Handle errors (e.g., show fallback UI)
      }}
    />
  );
}
```

## TypeScript Support

This package includes full TypeScript definitions. All props are typed for better development experience.

## Props Reference

### Required Props

| Prop | Type | Description |
|------|------|-------------|
| `apiConfig` | `ApiConfig` | Configuration for the Spot API including environment and partner ID |
| `quoteRequestData` | `QuoteRequestData` | Quote request data containing product and cart information |

### Optional Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `showTable` | `boolean` | `true` | Whether to show the payout table |
| `selection` | `SelectionEnum` | `'unselected'` | Initial selection state for the widget |
| `theme` | `Theme` | `undefined` | Theme customization options for styling the widget |

### Callback Props

| Prop | Type | Description |
|------|------|-------------|
| `onQuoteRetrieved` | `(quote: Quote) => void` | Callback fired when a quote is successfully retrieved |
| `onOptIn` | `(data: SelectionData) => void` | Callback fired when user opts in to the refund guarantee |
| `onOptOut` | `(data: SelectionData) => void` | Callback fired when user opts out of the refund guarantee |
| `onError` | `(error: ErrorData) => void` | Callback fired when an error occurs during quote retrieval |
| `onNoMatchingQuote` | `(data: NoQuoteData) => void` | Callback fired when no matching quote is found |
| `onSelectionChange` | `(data: SelectionData) => void` | Callback fired when user changes their selection (opt-in or opt-out) |

## Using Refs

You can access widget methods using React refs:

```tsx
import React, { useRef } from 'react';
import ReactSpotWidget, { ReactSpotWidgetRef } from '@getspot/spot-widget-react';

function App() {
  const widgetRef = useRef<ReactSpotWidgetRef>(null);

  const handleUpdateQuote = async () => {
    const success = await widgetRef.current?.updateQuote({
      // new quote data
    });
    console.log('Quote updated:', success);
  };

  const handleGetSelection = () => {
    const selection = widgetRef.current?.getSelection();
    console.log('Current selection:', selection);
  };

  const handleValidateSelection = () => {
    const isValid = widgetRef.current?.validateSelection();
    console.log('Selection is valid:', isValid);
  };

  return (
    <div>
      <ReactSpotWidget
        ref={widgetRef}
        // ... props
      />
      <button onClick={handleUpdateQuote}>Update Quote</button>
      <button onClick={handleGetSelection}>Get Selection</button>
      <button onClick={handleValidateSelection}>Validate Selection</button>
    </div>
  );
}
```

## Ref Methods

| Method | Return Type | Description |
|--------|-------------|-------------|
| `updateQuote(data)` | `Promise<boolean>` | Update the quote with new request data |
| `getSelection()` | `SelectionData \| null` | Get the current user selection |
| `validateSelection()` | `boolean` | Validate that the user has made a selection |
| `destroy()` | `void` | Destroy the widget instance and clean up resources |

## API Configuration

The `apiConfig` prop accepts the following options:

```tsx
{
  environment: 'production' | 'sandbox' | 'local',
  partnerId: string,
  customEndpoint?: string // Optional custom API endpoint
}
```

## Quote Request Data

The `quoteRequestData` prop requires the following fields:

### Single Quote Format

```tsx
{
  startDate: string,        // ISO 8601 date string
  endDate: string,          // ISO 8601 date string  
  currencyCode: 'USD' | 'CAD' | 'AUD',
  eventType: string,        // e.g., "Ski Trip", "Concert"
  productType: 'Pass' | 'Trip' | 'Registration',
  productDuration: 'Daily' | 'Seasonal' | 'Trip' | 'Event',
  productPrice: number,     // Price in specified currency
  productId: string,        // Unique product identifier
  cartId: string,           // Cart identifier
  productName: string,      // Human-readable product name
  participantDescription?: string // Optional participant details
}
```

### Batch Quote Format

For multiple items in a cart:

```tsx
{
  cartId: string,
  cartName: string,
  currencyCode: 'USD' | 'CAD' | 'AUD',
  items: Array<{
    // Same fields as single quote, minus cartId and currencyCode
    cartItemId?: string // Optional unique identifier for cart item
  }>
}
```

## Styling

Customize the widget appearance using the `theme` prop:

```tsx
<ReactSpotWidget
  theme={{
    primaryColor: '#007bff',
    borderRadius: '8px',
    fontFamily: 'Arial, sans-serif'
    // Add any CSS custom properties (without -- prefix)
  }}
  // ... other props
/>
```

## Error Handling

Always implement error handling for production use:

```tsx
<ReactSpotWidget
  onError={(error) => {
    // Log error for debugging
    console.error('Spot Widget Error:', error);
    
    // Show user-friendly message
    toast.error('Unable to load refund options. Please try again.');
    
    // Track error in analytics
    analytics.track('spot_widget_error', {
      message: error.message,
      status: error.status
    });
  }}
  onNoMatchingQuote={() => {
    // Handle case where no quote is available
    console.log('No refund guarantee available for this product');
  }}
  // ... other props
/>
```

## Compatibility

- **React**: 18.x
- **TypeScript**: 5.x
- **Node.js**: 16+

## License

See the main package for license information.

## Support

For support, please contact [support@getspot.com](mailto:support@getspot.com).