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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@wavecx/wavecx-react

v1.10.3

Published

WaveCX React library

Readme

wavecx-react

Add WaveCX to your React application.

Installation

npm i @wavecx/wavecx-react

Quickstart

  1. Import the WaveCX provider with import { WaveCxProvider } from '@wavecx/wavecx-react';
  2. Wrap your application or component subtree where WaveCX is used in WaveCxProvider and provide your organization code.
  3. Import WaveCX styles with import '@wavecx/wavecx-react/styles.css';.
  4. In your inner components import { useWaveCx } from '@wavecx/wavecx-react';
  5. Use const {handleEvent} = useWaveCx() to access the WaveCX context and raise events.

Example

import * as React from 'react';
import { useEffect } from 'react';
import { HmacSHA256 } from 'crypto-js';

import { WaveCxProvider, useWaveCx } from '@wavecx/wavecx-react';
import '@wavecx/wavecx-react/styles.css';

export const App = () => (
  <WaveCxProvider organizationCode={'your-org-code'}>
    <Main />
  </WaveCxProvider>
);

const Main = () => {
  const { handleEvent } = useWaveCx();

  useEffect(() => {
    handleEvent({
      type: 'session-started',
      userId: 'user-id',
      userIdVerification: createUserIdVerification('user-id'),
      userAttributes: {
        creditScore: 800,
      },
    });
  }, []);

  return (
    <button
      title={'Trigger Point'}
      onClick={() => {
        handleEvent({
          type: 'trigger-point',
          triggerPoint: 'trigger-point-code',
        });
      }}
    />
  );
};

// WARNING: User ID verification should NOT be performed on client.
// This is here only for brevity of example.
const createUserIdVerification = (userId: string) =>
  HmacSHA256(userId, 'your-signing-secret').toString()

Usage

WaveCX follows an event-driven architecture, only needing events raised as they occur within your application.

Session Started Events

Because WaveCX content is targeted and tracked per user, a "session started" event is required upon user authentication.

handleEvent({
  type: 'session-started',
  userId: 'user-id',
  userIdVerification: createUserIdVerification('user-id'),
  userAttribute: {
    // your user attributes
  },
});

User ID Verification

The user ID verification parameter is an HMACSHA256 hash of the provided user ID, signed with a signing secret specific to your organization. This is used to prevent user ID spoofing and ensure that requests to WaveCX are from authorized sources.

The signing secret should be stored only in a protected environment (i.e. a backend service) which your client application can communicate with in order to retrieve ID verification hashes.

Never send or store the signing secret to the client application.

Trigger Point Events

handleEvent({
  type: 'trigger-point',
  triggerPoint: 'trigger-point-code',
  onContentDismissed: () => {
    // optional callback when content is closed by user
  }
});

A trigger point is an event within your application that content can be attached to.

When a trigger-point event is raised, WaveCX will check for and present any content set for that trigger point that is relevant for the current user.

Checking for Available Content

The WaveCX context provides a hasContent() function to check if content is available for a specific trigger point and presentation type.

const { handleEvent, hasContent } = useWaveCx();

// Check if any content is available for a trigger point
const hasAnyContent = hasContent('your-trigger-point');

// Check for specific presentation types
const hasPopup = hasContent('your-trigger-point', 'popup');
const hasButtonContent = hasContent('your-trigger-point', 'button-triggered');

if (hasPopup) {
  // your conditional logic for popup content available
}

Deprecated: hasPopupContentForTriggerPoint() is deprecated. Use hasContent(triggerPoint, 'popup') instead.

User-Triggered Content

You can check for button-triggered content availability and display a button or UI element to let users access it on demand:

const { handleEvent, hasContent } = useWaveCx();

// Check if button-triggered content is available for a specific trigger point
const hasButtonContent = hasContent('your-trigger-point', 'button-triggered');

// in render
{hasButtonContent && (
  <Button
    title={'View Content'}
    onClick={() => handleEvent({
      type: 'user-triggered-content',
      triggerPoint: 'your-trigger-point',
      onContentDismissed: () => {
        // optional callback when content is closed by user
      }
    })}
  />
)}

Deprecated: hasUserTriggeredContent boolean is deprecated. Use hasContent(triggerPoint, 'button-triggered') instead. The old flag only reflected the most recently fired trigger point and didn't indicate which one.

Content Loading State

The WaveCX context provides an isContentLoading flag that indicates when the SDK is fetching content from the API. This is useful for showing loading indicators during the initial content fetch:

const { handleEvent, isContentLoading, hasContent } = useWaveCx();

// in render
{isContentLoading ? (
  <div className="loading-spinner">Loading content...</div>
) : hasContent('your-trigger-point', 'popup') && (
  <div>Content is available!</div>
)}

The loading state is automatically set to true when a session starts and remains true until the content fetch completes.

Session Ended Events

If trigger points may still be reached in your application after the user is no longer authenticated, a session ended event must be raised to notify WaveCX that trigger points should no longer be handled for a previously identified user.

handleEvent({ type: 'session-ended' });

useWaveCx Hook

The useWaveCx() hook provides access to the WaveCX context and returns the following:

| Property | Type | Description | |----------|------|-------------| | handleEvent | EventHandler | Function to raise WaveCX events (session-started, trigger-point, etc.) | | hasContent | (triggerPoint: string, presentationType?: 'popup' \| 'button-triggered') => boolean | Check if content is available for a trigger point, optionally filtered by presentation type | | isContentLoading | boolean | Indicates if the SDK is currently loading content from the API | | hasPopupContentForTriggerPoint | (triggerPoint: string) => boolean | DEPRECATED - Use hasContent(triggerPoint, 'popup') instead | | hasUserTriggeredContent | boolean | DEPRECATED - Use hasContent(triggerPoint, 'button-triggered') instead |

API

WaveCxProvider

WaveCxProvider provides a context for WaveCX events to be raised. WaveCxProvider should be placed as high as possible in the application tree.

Props

| name | type | description | required | default | |----------------------|-------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------| | organizationCode | string | code identifying your organization in WaveCX (i.e. the "slug" of your API URL -- "your-org" in https://api.wavecx.com/your-org) | true | | | apiBaseUrl | string | base URL which API calls are made to | false | https://api.wavecx.com | | recordEvent | function (FireTargetedContentEvent) | function to record a raised event, returning relevant content | false | fireTargetedContentEventViaApi (makes real calls to WaveCX API) | | disablePopupContent | boolean | disables pop-up content; only user-triggered content will be presented | false | false | | contentFetchStrategy | ContentFetchStrategy | DEPRECATED - no longer has any effect; content is always fetched at session start | false | session-start | | debugMode | boolean | enables debug logging to console for troubleshooting | false | false | | retryConfig | RetryConfig | configures retry behavior for API calls (maxAttempts, delays) | false | {maxAttempts: 3, initialDelay: 1000, maxDelay: 32000, multiplier: 2.0} | | mockModeConfig | MockModeConfig | enables mock mode for testing without API calls, generating simulated content | false | {enabled: false} |

Types

type TargetedContent = {
  triggerPoint: string;
  type: 'featurette';
  presentationType: 'popup' | 'button-triggered';
  viewUrl: string;
};

type FireTargetedContentEvent = (options: {
  type: 'session-started' | 'trigger-point';
  triggerPoint?: string;
  organizationCode: string;
  userId: string;
  userIdVerification?: string;
  userAttributes?: object;
}) => Promise<{ content: TargetedContent[] }>;

type ContentFetchStrategy =
  | 'session-start'
  | 'trigger-point';

type RetryConfig = {
  maxAttempts: number;      // Number of retry attempts (default: 3)
  initialDelay: number;     // Initial delay in milliseconds (default: 1000)
  maxDelay: number;         // Maximum delay cap in milliseconds (default: 32000)
  multiplier: number;       // Exponential backoff multiplier (default: 2.0)
};

type MockModeConfig = {
  enabled: boolean;                            // Enable/disable mock mode (default: false)
  networkDelay?: number;                       // Simulate network latency in milliseconds
  contentStrategy?: MockContentStrategy;       // Which trigger points get content
  customContent?: Record<string, TargetedContent[]>;  // Custom content per trigger point
};

type MockContentStrategy =
  | { type: 'all-trigger-points' }             // Generate content for any trigger point
  | { type: 'specific-trigger-points'; triggerPoints: string[] };  // Only specific points

Network Retry

The SDK automatically retries failed API calls using exponential backoff. By default, it will:

  • Retry up to 3 times
  • Use delays of 1s, 2s, 4s between attempts
  • Cap maximum delay at 32 seconds

You can customize this behavior using the retryConfig prop:

<WaveCxProvider
  organizationCode={'your-org-code'}
  retryConfig={{
    maxAttempts: 5,
    initialDelay: 500,  // 500ms, 1s, 2s, 4s, 8s
    maxDelay: 10000,    // cap at 10 seconds
    multiplier: 2.0,
  }}
>
  <App />
</WaveCxProvider>

Mock Mode

Mock mode allows you to test WaveCX integration without making real API calls. When enabled, the SDK generates simulated content locally for testing purposes.

Basic Mock Mode

Enable mock mode to automatically generate content for all trigger points:

<WaveCxProvider
  organizationCode={'your-org-code'}
  mockModeConfig={{
    enabled: true,
  }}
>
  <App />
</WaveCxProvider>

Mock Mode with Network Delay

Simulate network latency for more realistic testing:

<WaveCxProvider
  organizationCode={'your-org-code'}
  mockModeConfig={{
    enabled: true,
    networkDelay: 1000,  // 1 second delay
  }}
>
  <App />
</WaveCxProvider>

Specific Trigger Points Only

Generate content only for specific trigger points:

<WaveCxProvider
  organizationCode={'your-org-code'}
  mockModeConfig={{
    enabled: true,
    contentStrategy: {
      type: 'specific-trigger-points',
      triggerPoints: ['home-screen', 'checkout-page'],
    },
  }}
>
  <App />
</WaveCxProvider>

Custom Mock Content

Provide your own custom content for testing:

<WaveCxProvider
  organizationCode={'your-org-code'}
  mockModeConfig={{
    enabled: true,
    customContent: {
      'home-screen': [
        {
          triggerPoint: 'home-screen',
          type: 'featurette',
          presentationType: 'popup',
          viewUrl: 'https://example.com/announcement',
          webModal: {
            opacity: 0.3,
            borderRadiusCss: '16px',
            heightCss: '80vh',
            widthCss: '600px',
            closeButton: { style: 'text', label: 'Close' },
          },
        },
      ],
    },
  }}
>
  <App />
</WaveCxProvider>

Note: Mock mode generates two content items per trigger point by default:

  • Popup content (automatic display) with a purple gradient
  • Button-triggered content (user-initiated) with a pink gradient

Example Application

An example application is available at https://github.com/WaveCX/wavecx-react/tree/main/example

Running the Example Application

  • Clone this repository
  • In the root directory, run npm install
  • Copy file ./example/.env.local.example to ./example/.env.local
  • Update ./example/.env.local with your organizations information
  • In the root directory, run npm run example
    • Sign in with any User ID to view content