JSPM

@perspective-ai/sdk-react

1.1.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 4343
  • Score
    100M100P100Q112553F
  • License MIT

React components for Perspective AI embed SDK

Package Exports

  • @perspective-ai/sdk-react

Readme

@perspective-ai/sdk-react

React hooks and components for Perspective AI.

Not using React? Use @perspective-ai/sdk for vanilla JavaScript.

Installation

npm install @perspective-ai/sdk-react

Peer Dependencies: React 18+ or 19+

Quick Start

import { usePopup } from "@perspective-ai/sdk-react";

function App() {
  const { open } = usePopup({
    researchId: "your-research-id",
    onSubmit: () => console.log("Interview completed!"),
  });

  return <button onClick={open}>Give Feedback</button>;
}

API Overview

API Type Description
usePopup Hook Open popup modal programmatically
useSlider Hook Open slider panel programmatically
useFloatBubble Hook Floating chat bubble lifecycle
Widget Component Inline embed in a container
Fullpage Component Full viewport takeover
FloatBubble Component Convenience wrapper for useFloatBubble

Mental Model:

  • Hooks for overlays (popup, slider, float bubble) - you control the trigger
  • Components for embeds (widget, fullpage) - render inline DOM

Hooks

usePopup

Open a popup modal with your own trigger element.

import { usePopup } from "@perspective-ai/sdk-react";

function App() {
  const { open, close, isOpen } = usePopup({
    researchId: "your-research-id",
    onSubmit: () => console.log("Done!"),
  });

  return (
    <>
      <button onClick={open}>Take Survey</button>
      {isOpen && <span>Survey is open</span>}
    </>
  );
}

Programmatic trigger:

const { open } = usePopup({ researchId: "xxx" });

useEffect(() => {
  if (userCompletedCheckout) {
    open();
  }
}, [userCompletedCheckout, open]);

Controlled mode:

const [isOpen, setIsOpen] = useState(false);

const popup = usePopup({
  researchId: "xxx",
  open: isOpen,
  onOpenChange: setIsOpen,
});

// External control
<button onClick={() => setIsOpen(true)}>Open from anywhere</button>;

useSlider

Open a slider panel with your own trigger element.

import { useSlider } from "@perspective-ai/sdk-react";

function App() {
  const { open, close, isOpen } = useSlider({
    researchId: "your-research-id",
  });

  return <button onClick={open}>Open Feedback Panel</button>;
}

useFloatBubble

Manage a floating chat bubble lifecycle.

import { useFloatBubble } from "@perspective-ai/sdk-react";

function App() {
  const { open, close, isOpen } = useFloatBubble({
    researchId: "your-research-id",
  });

  // Bubble mounts on component mount
  // Use open/close for programmatic control
  return null;
}

Components

Widget

Inline embed that renders in a container.

import { Widget } from "@perspective-ai/sdk-react";

<Widget
  researchId="your-research-id"
  onSubmit={() => console.log("Done!")}
  className="my-widget"
  style={{ height: 600 }}
/>;

Fullpage

Full viewport takeover embed.

import { Fullpage } from "@perspective-ai/sdk-react";

<Fullpage researchId="your-research-id" />;

FloatBubble

Convenience wrapper around useFloatBubble hook.

import { FloatBubble } from "@perspective-ai/sdk-react";

<FloatBubble researchId="your-research-id" />;

Hook Options

All hooks accept options from EmbedConfig:

interface UsePopupOptions {
  researchId: string;
  host?: string;
  theme?: "light" | "dark" | "system";
  params?: Record<string, string>;
  brand?: {
    light?: {
      primary?: string;
      secondary?: string;
      bg?: string;
      text?: string;
    };
    dark?: { primary?: string; secondary?: string; bg?: string; text?: string };
  };

  // Callbacks
  onReady?: () => void;
  onSubmit?: (data: { researchId: string }) => void;
  onClose?: () => void;
  onNavigate?: (url: string) => void;
  onError?: (error: EmbedError) => void;

  // Controlled mode
  open?: boolean;
  onOpenChange?: (open: boolean) => void;
}

Hook Return Types

interface UsePopupReturn {
  open: () => void;
  close: () => void;
  toggle: () => void;
  isOpen: boolean;
  handle: EmbedHandle | null;
}

interface UseSliderReturn {
  open: () => void;
  close: () => void;
  toggle: () => void;
  isOpen: boolean;
  handle: EmbedHandle | null;
}

interface UseFloatBubbleReturn {
  open: () => void;
  close: () => void;
  toggle: () => void;
  unmount: () => void;
  isOpen: boolean;
  handle: FloatHandle | null;
}

Other Hooks

useThemeSync

Sync theme between your app and embedded interviews:

import { useThemeSync } from "@perspective-ai/sdk-react";

function App() {
  const [theme, setTheme] = useState<"light" | "dark">("light");

  // Syncs theme changes to all active embeds
  useThemeSync(theme);

  return (
    <button onClick={() => setTheme((t) => (t === "light" ? "dark" : "light"))}>
      Toggle Theme
    </button>
  );
}

TypeScript

All types are exported:

import type {
  // Hook types
  UsePopupOptions,
  UsePopupReturn,
  UseSliderOptions,
  UseSliderReturn,
  UseFloatBubbleOptions,
  UseFloatBubbleReturn,
  // Component types
  WidgetProps,
  FloatBubbleProps,
  FullpageProps,
} from "@perspective-ai/sdk-react";

// Re-exported from @perspective-ai/sdk
import type {
  EmbedConfig,
  EmbedHandle,
  FloatHandle,
  BrandColors,
  ThemeValue,
  EmbedError,
} from "@perspective-ai/sdk-react";

SSR Safety

All hooks and components are SSR-safe and include the "use client" directive. Works with Next.js, Remix, and other React frameworks.

License

MIT