npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@getspot/spot-widget

v3.2.2

Published

Core JavaScript/TypeScript library for integrating Spot's refund guarantee widget into your applications.

Readme

@getspot/spot-widget

Core JavaScript/TypeScript library for integrating Spot's refund guarantee widget into your applications.

Installation

npm install @getspot/spot-widget

Quick Start

import SpotWidget from '@getspot/spot-widget';

// Create widget instance
const widget = new SpotWidget({
  location: '#spot-widget-container', // CSS selector or DOM element
  apiConfig: {
    environment: 'production', // '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'
  },
  callbacks: {
    onOptIn: (data) => {
      console.log('User opted in:', data);
      // Handle opt-in logic
    },
    onOptOut: (data) => {
      console.log('User opted out:', data);
      // Handle opt-out logic
    },
    onQuoteRetrieved: (quote) => {
      console.log('Quote retrieved:', quote);
    },
    onError: (error) => {
      console.error('Widget error:', error);
    }
  }
});

TypeScript Support

This package is written in TypeScript and includes full type definitions.

import SpotWidget, { SpotWidgetOptions, SelectionData, Quote } from '@getspot/spot-widget';

const options: SpotWidgetOptions = {
  // ... your configuration
};

const widget = new SpotWidget(options);

Configuration

SpotWidgetOptions

| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | location | string \| HTMLElement | No | "body" | Target element for the widget | | apiConfig | ApiConfig | Yes | - | API configuration | | quoteRequestData | QuoteRequestData | Yes | - | Quote request information | | showTable | boolean | No | true | Whether to show payout table | | optInSelected | boolean | No | false | Pre-select opt-in option | | theme | Theme | No | - | Custom styling | | callbacks | Callbacks | No | {} | Event callbacks |

ApiConfig

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

QuoteRequestData

Single Product Quote

{
  startDate: string;        // ISO 8601 date
  endDate: string;          // ISO 8601 date
  currencyCode: 'USD' | 'CAD' | 'AUD';
  eventType: string;        // Event description
  productType: 'Pass' | 'Trip' | 'Registration';
  productDuration: 'Daily' | 'Seasonal' | 'Trip' | 'Event';
  productPrice: number;     // Price in specified currency
  productId: string;        // Unique product identifier
  cartId: string;           // Shopping cart identifier
  productName: string;      // Human-readable product name
  participantDescription?: string; // Optional participant info
}

Batch Quote (Multiple Products)

{
  cartInfo: {
    cartId: string;
    cartName: string;
    currencyCode: 'USD' | 'CAD' | 'AUD';
  };
  items: Array<{
    // All single product fields except cartId and currencyCode
    cartItemId?: string; // Optional item identifier
  }>;
}

Widget Methods

updateQuote(newQuoteRequestData)

Update the widget with new quote data.

const success = await widget.updateQuote({
  // new quote request data
});
console.log('Update successful:', success);

Returns: Promise<boolean>

getSelection()

Get the current user selection.

const selection = widget.getSelection();
console.log('User selection:', selection);

Returns: SelectionData | null

validateSelection()

Check if the user has made a selection.

const isValid = widget.validateSelection();
if (!isValid) {
  console.log('Please make a selection');
}

Returns: boolean

destroy()

Clean up the widget instance.

widget.destroy();

Callbacks

onOptIn(data: SelectionData)

Called when user opts into the refund guarantee.

{
  onOptIn: (data) => {
    console.log('Opt-in data:', data);
    // data.status === 'QUOTE_ACCEPTED'
    // data.quoteId - unique quote identifier
    // data.spotPrice - refund guarantee price
  }
}

onOptOut(data: SelectionData)

Called when user opts out of the refund guarantee.

{
  onOptOut: (data) => {
    console.log('Opt-out data:', data);
    // data.status === 'QUOTE_DECLINED'
    // data.quoteId - unique quote identifier
  }
}

onQuoteRetrieved(quote: Quote)

Called when a quote is successfully retrieved.

{
  onQuoteRetrieved: (quote) => {
    console.log('Quote:', quote);
    // quote.id - quote identifier
    // quote.spotPrice - refund guarantee price
    // quote.communication - display text and labels
  }
}

onError(error: ErrorData)

Called when an error occurs.

{
  onError: (error) => {
    console.error('Error:', error);
    // error.message - error description
    // error.status - HTTP status code (if applicable)
    // error.responseBody - API response (if applicable)
  }
}

noMatchingQuote(data)

Called when no quote is available for the request.

{
  noMatchingQuote: (data) => {
    console.log('No quote available:', data);
    // Handle case where product isn't eligible
  }
}

Styling

Customize the widget appearance using the theme option:

const widget = new SpotWidget({
  // ... other options
  theme: {
    primaryColor: '#007bff',
    secondaryColor: '#6c757d',
    borderRadius: '8px',
    fontFamily: 'Arial, sans-serif',
    fontSize: '14px'
    // Any CSS custom properties (without -- prefix)
  }
});

Error Handling

Always implement comprehensive error handling:

const widget = new SpotWidget({
  // ... configuration
  callbacks: {
    onError: (error) => {
      // Log for debugging
      console.error('Spot Widget Error:', error);
      
      // Handle different error types
      if (error.status === 404) {
        console.log('Product not eligible for refund guarantee');
      } else if (error.status >= 500) {
        console.log('Service temporarily unavailable');
      }
      
      // Track in analytics
      if (window.analytics) {
        window.analytics.track('spot_widget_error', {
          message: error.message,
          status: error.status
        });
      }
    },
    noMatchingQuote: (data) => {
      console.log('No refund guarantee available');
      // Hide widget or show alternative messaging
    }
  }
});

Environments

Sandbox (Development)

Use the sandbox environment for testing:

{
  apiConfig: {
    environment: 'sandbox',
    partnerId: 'your-sandbox-partner-id'
  }
}

Production

Use the production environment for live applications:

{
  apiConfig: {
    environment: 'production',
    partnerId: 'your-production-partner-id'
  }
}

API Reference

This package exports the following types and interfaces:

Interfaces

ApiConfig

export interface ApiConfig {
  environment: "sandbox" | "production" | "local";
  partnerId: string;
  customEndpoint?: string;
}

QuoteMetadata

export interface QuoteMetadata {
  segment?: string;
  operator?: string;
  channel?: string;
  consumerId?: string;
}

CartInfo

export interface CartInfo {
  cartId: string;
  cartName: string;
  currencyCode: "USD" | "CAD" | "AUD";
  metadata?: QuoteMetadata;
  isPartialPayment?: boolean;
}

QuoteItem

export interface QuoteItem {
  productPrice: number;
  productType: "Pass" | "Trip" | "Registration";
  productDuration: "Daily" | "Seasonal" | "Trip" | "Event";
  productId: string;
  cartId: string;
  cartName: string;
  productName: string;
  participantDescription?: string;
  eventType: string;
  eventId?: string;
  currencyCode: "USD" | "CAD" | "AUD";
  startDate: string;
  endDate: string;
  partnerRiskEnd?: Date;
  metadata?: QuoteMetadata;
  isPartialPayment?: boolean;
  hostCountry?: string;
  hostCountryState?: string;
  destinations?: string[];
  dob?: string;
}

BatchQuoteRequest

export interface BatchQuoteRequest {
  cartInfo: CartInfo;
  items: BatchQuoteItem[];
}

QualifyingReason

export interface QualifyingReason {
  rank: number;
  name?: string;
  benefitType?: {
    name: string;
  };
}

PayoutScheduleItem

export interface PayoutScheduleItem {
  text: string;
  percent: string | number;
  amount: number;
}

Communication

export interface Communication {
  name: string;
  description: string;
  bulletPoints: string[];
  yesOptionText: string;
  noOptionText: string;
  legalDisclaimer: string;
  termsAndConditionsUrl: string;
  paymentTerms?: string;
}

Quote

export interface Quote {
  id: string;
  cartItemId?: string;
  spotPrice: number;
  currencyCode: string;
  communication: Communication;
  payoutSchedule: PayoutScheduleItem[];
  qualifyingReasons?: QualifyingReason[];
  coveredItems?: string[];
  originalQuotes?: Quote[];
}

QuoteUpdates

export interface QuoteUpdates {
  spotPriceWithFees?: number;
}

ApiResponse

export interface ApiResponse {
  status: "QUOTE_AVAILABLE" | "QUOTES_AVAILABLE" | "NO_MATCHING_QUOTE";
  data?: Quote;
  quotes?: Quote[];
  totalSpotPrice?: number;
  spotPrice?: number;
  currencyCode?: string;
  communication?: Communication;
  payoutSchedule?: PayoutScheduleItem[];
  coveredItems?: string[];
}

SelectionData

export interface SelectionData {
  status: "QUOTE_ACCEPTED" | "QUOTE_DECLINED";
  spotPrice?: number;
  quoteId?: string;
  selection?: string;
  batchQuoteDetails?: Array<{
    quoteId: string;
    productPrice: number;
    cartItemId: string;
  }>;
}

Callbacks

export interface Callbacks {
  onOptIn?: (data: SelectionData) => void;
  onOptOut?: (data: SelectionData) => void;
  onQuoteRetrieved?: (quote: Quote) => QuoteUpdates | void;
  onError?: (error: { message: string; status?: number; responseBody?: any }) => void;
  noMatchingQuote?: (data: { status: string; data: QuoteRequestData }) => void;
}

Theme

export interface Theme {
  [key: string]: string;
}

SpotWidgetOptions

export interface SpotWidgetOptions {
  location?: string | HTMLElement;
  showTable?: boolean;
  optInSelected?: boolean;
  logoPosition?: "bottom-right" | "top-right";
  apiConfig: ApiConfig;
  quoteRequestData: QuoteRequestData;
  callbacks?: Callbacks;
  theme?: Theme;
  isPartialPayment?: boolean;
  useMockData?: boolean;
  mockData?: ApiResponse;
}

ElementOptions

export interface ElementOptions {
  text?: string;
  className?: string;
  parent?: HTMLElement;
  innerHTML?: string;
  href?: string;
  target?: string;
}

Type Aliases

QuoteRequestData

export type QuoteRequestData = QuoteItem | BatchQuoteRequest;

Framework Integration

This is the core library. For framework-specific wrappers:

Browser Support

  • Modern browsers (ES2020+)
  • Chrome 80+
  • Firefox 74+
  • Safari 13+
  • Edge 80+

License

See the main package for license information.

Support

For support, please contact [email protected].