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

@snap/react-camera-kit

v0.6.0

Published

React Camera Kit for web applications

Readme

@snap/react-camera-kit

The official React wrapper for the Camera Kit Web SDK. It provides declarative components and hooks that handle SDK bootstrapping, session lifecycle, media sources, and Lens management — so you can integrate Snap AR into React apps with minimal boilerplate.

Live Demo · Camera Kit Docs

Installation

npm install @snap/react-camera-kit @snap/camera-kit

Requirements

  • @snap/camera-kit ^1.13.0 (peer dependency)
  • react >=16.8.0 and react-dom >=16.8.0
  • rxjs >=7
  • https:// for deployed apps (http://localhost works for local development)

You'll need a Camera Kit API token, Lens ID, and Lens Group ID from the Snap Developer Portal. See Setting Up Accounts if you're new to Camera Kit.

Quick start

import { CameraKitProvider, LensPlayer } from "@snap/react-camera-kit";

function App() {
  return (
    <CameraKitProvider apiToken="YOUR_API_TOKEN">
      <LensPlayer lensId="YOUR_LENS_ID" lensGroupId="YOUR_LENS_GROUP_ID" />
    </CameraKitProvider>
  );
}

That's it — CameraKitProvider initializes the SDK, and LensPlayer sets up the camera, applies the Lens, and renders the output canvas.

Components

CameraKitProvider

The root provider that initializes the Camera Kit SDK. All other components and hooks must be descendants of this provider.

import { CameraKitProvider, createConsoleLogger } from "@snap/react-camera-kit";

<CameraKitProvider apiToken="YOUR_API_TOKEN" logger={createConsoleLogger()} logLevel="info">
  {children}
</CameraKitProvider>;

| Prop | Type | Default | Description | | ----------------------------- | ---------------------------------------- | ------------ | ------------------------------------------------------------- | | apiToken | string | required | Camera Kit API token | | logger | CameraKitLogger | noopLogger | Logger instance — use createConsoleLogger() for development | | logLevel | "debug" \| "info" \| "warn" \| "error" | "info" | Log verbosity | | renderWhileTabHidden | boolean | false | Continue rendering when the browser tab is hidden | | stabilityKey | string \| number | auto | Manual control over when the SDK re-initializes | | extendContainer | (container) => container | — | Customize the SDK's DI container | | createBootstrapEventHandler | MetricEventHandlerFactory | — | Factory for tracking bootstrap success/failure |

LensPlayer

All-in-one component that handles source setup, Lens application, and playback. Defaults to the user's camera if no source is provided.

<LensPlayer lensId="YOUR_LENS_ID" lensGroupId="YOUR_LENS_GROUP_ID" className="camera-canvas" />

| Prop | Type | Default | Description | | ---------------- | ----------------------- | -------------------- | ------------------------------------------------------------------------------------------------ | | lensId | string | — | Lens to apply | | lensGroupId | string | — | Lens Group containing the Lens | | source | SourceInput | { kind: "camera" } | Media source (camera, video, or image) | | outputSize | OutputSize | — | Rendering canvas size | | lensLaunchData | LensLaunchData | — | Launch parameters passed to the Lens | | lensReadyGuard | () => Promise<void> | — | Async guard called while Lens is loading (2s timeout) | | refreshTrigger | unknown | — | When this value changes, the Lens is removed and reapplied | | canvasType | "live" \| "capture" | "live" | Which canvas to render. For custom layouts, use LiveCanvas/CaptureCanvas as children instead | | fpsLimit | number | — | Maximum rendering framerate | | muted | boolean | false | Mute audio output | | screenRegions | ScreenRegions | — | Screen regions for Lens-aware UI layout | | onError | (error, lens) => void | — | Callback for playback errors | | className | string | — | CSS class name | | style | CSSProperties | — | Inline styles | | children | ReactNode | — | Custom children (use with LiveCanvas/CaptureCanvas) |

LiveCanvas / CaptureCanvas

Render the live preview or capture canvas as children of LensPlayer:

<LensPlayer lensId="YOUR_LENS_ID" lensGroupId="YOUR_LENS_GROUP_ID">
  <div>
    <LiveCanvas style={{ width: "100%" }} />
  </div>
  <div>
    <CaptureCanvas style={{ width: "100%" }} />
  </div>
</LensPlayer>

Both accept className and style props.

Hooks

useCameraKit

Access the full Camera Kit context — SDK status, source/Lens state, and imperative methods. Must be called within a CameraKitProvider.

import { useCameraKit } from "@snap/react-camera-kit";

function Controls() {
  const { sdkStatus, lens, lenses, isMuted, toggleMuted, applyLens, removeLens, fetchLenses } = useCameraKit();

  if (sdkStatus !== "ready") return <p>Loading SDK...</p>;

  return (
    <div>
      <p>Lens: {lens.lensId ?? "None"}</p>
      <button onClick={toggleMuted}>{isMuted ? "Unmute" : "Mute"}</button>
      <button onClick={removeLens}>Remove Lens</button>
    </div>
  );
}

State properties:

| Property | Type | Description | | --------------- | --------------------------------------------------------- | --------------------------------------- | | sdkStatus | "uninitialized" \| "initializing" \| "ready" \| "error" | SDK initialization status | | sdkError | Error \| undefined | Error from SDK initialization | | source | CurrentSource | Current source status, input, and error | | lens | CurrentLens | Current Lens status, IDs, and error | | lenses | Lens[] | Array of loaded Lens objects | | liveCanvas | HTMLCanvasElement \| undefined | Live preview canvas element | | captureCanvas | HTMLCanvasElement \| undefined | Capture canvas element | | keyboard | Keyboard \| undefined | Keyboard API for Lens keyboard requests | | isMuted | boolean | Whether audio is muted | | fpsLimit | number \| undefined | Current FPS limit | | screenRegions | ScreenRegions \| undefined | Current screen regions |

Methods:

| Method | Description | | ------------------------------------------------------ | ------------------------------------------------------- | | applySource(input, size?) | Apply a media source (camera, video, or image) | | removeSource() | Remove the current source | | fetchLens(lensId, groupId) | Load a single Lens (returns cached if already loaded) | | fetchLenses(groupId) | Load all Lenses in a group (accepts string or string[]) | | applyLens(lensId, groupId, launchData?, readyGuard?) | Apply a Lens by ID | | removeLens() | Remove the current Lens | | refreshLens() | Remove and reapply the current Lens | | reinitialize() | Re-bootstrap the SDK (useful after errors) | | setMuted(muted) | Set the muted state | | toggleMuted() | Toggle audio mute | | setFPSLimit(fps) | Set maximum rendering FPS | | setScreenRegions(regions) | Set screen regions for Lens-aware layout |

useApplyLens

Declaratively apply a Lens — it updates automatically when parameters change.

import { useApplyLens } from "@snap/react-camera-kit";

useApplyLens("YOUR_LENS_ID", "YOUR_LENS_GROUP_ID");

| Parameter | Type | Description | | ---------------- | --------------------- | -------------------------------------------- | | lensId | string \| undefined | Lens ID — pass undefined to remove | | lensGroupId | string \| undefined | Lens Group ID | | lensLaunchData | LensLaunchData | Optional launch parameters | | lensReadyGuard | () => Promise<void> | Optional async ready guard | | refreshTrigger | unknown | Reapply with current parameters when changed |

useApplySource

Declaratively apply a media source. Defaults to camera if no source is provided.

import { useApplySource } from "@snap/react-camera-kit";

// Video source with fixed output size
useApplySource({ kind: "video", url: "/demo.mp4", autoplay: true }, { mode: "fixed", width: 720, height: 1280 });

| Parameter | Type | Default | Description | | ------------ | ------------- | -------------------- | -------------- | | source | SourceInput | { kind: "camera" } | Media source | | outputSize | OutputSize | — | Rendering size |

usePlaybackOptions

Declaratively set playback options.

import { usePlaybackOptions } from "@snap/react-camera-kit";

usePlaybackOptions({
  fpsLimit: 30,
  muted: false,
  onError: (error) => console.error("Playback error:", error),
});

| Option | Type | Description | | --------------- | ----------------------- | ------------------------------ | | fpsLimit | number | Maximum rendering FPS | | muted | boolean | Mute audio | | screenRegions | ScreenRegions | Screen regions for Lens layout | | onError | (error, lens) => void | Playback error callback |

Media sources

Pass a SourceInput to LensPlayer's source prop or to useApplySource:

// Camera (default)
{ kind: "camera" }
{ kind: "camera", deviceId: "abc123", options: { cameraFacing: "environment" } }

// Video
{ kind: "video", url: "/demo.mp4", autoplay: true }

// Image
{ kind: "image", url: "/photo.jpg" }

Camera source options

| Option | Type | Default | Description | | ------------------- | ------------------------- | ------------------------------ | ----------------------------- | | cameraFacing | "user" \| "environment" | "user" | Front or back camera | | cameraConstraints | MediaTrackConstraints | { width: 1280, height: 720 } | Camera resolution constraints | | cameraRotation | 0 \| -90 \| 90 \| 180 | 0 | Camera rotation | | fpsLimit | number | — | Max FPS for the source | | outputSize | OutputSize | — | Rendering canvas size |

Output size

// Fixed resolution
{ mode: "fixed", width: 720, height: 1280 }

// Match input source resolution
{ mode: "match-input" }

Handling loading and error states

Use useCameraKit() to track the status of the SDK, source, and Lens. Each progresses through "none" → "loading" → "ready" (or "error"):

function Preview() {
  const { sdkStatus, sdkError, source, lens } = useCameraKit();

  if (sdkStatus === "error") return <p>SDK failed: {sdkError?.message}</p>;
  if (sdkStatus !== "ready") return <p>Initializing...</p>;
  if (source.status === "loading") return <p>Setting up camera...</p>;
  if (lens.status === "error") return <p>Lens error: {lens.error?.message}</p>;

  return (
    <LensPlayer lensId="YOUR_LENS_ID" lensGroupId="YOUR_LENS_GROUP_ID">
      {lens.status !== "ready" && <div className="spinner" />}
      <LiveCanvas />
    </LensPlayer>
  );
}

Frame Metrics

Use useLensFrameMetrics to monitor lens rendering performance:

import { useLensFrameMetrics } from "@snap/react-camera-kit";

function PerformanceOverlay() {
  const metrics = useLensFrameMetrics({ interval: 500 });

  if (!metrics) return null;

  return (
    <div>
      <p>FPS: {metrics.avgFps.toFixed(1)}</p>
      <p>Frame time: {metrics.lensFrameProcessingTimeMsAvg.toFixed(1)}ms</p>
    </div>
  );
}

The hook accepts:

  • interval (required) — polling interval in milliseconds
  • enabled (optional, defaults to true) — set to false to disable measurement without unmounting

Full example: Lens switcher

import { CameraKitProvider, LensPlayer, LiveCanvas, useCameraKit } from "@snap/react-camera-kit";
import { useEffect } from "react";

const LENS_GROUP_ID = "YOUR_LENS_GROUP_ID";

function LensSwitcher() {
  const { sdkStatus, lenses, lens, fetchLenses, applyLens, isMuted, toggleMuted, reinitialize, sdkError } =
    useCameraKit();

  useEffect(() => {
    if (sdkStatus === "ready") fetchLenses(LENS_GROUP_ID);
  }, [sdkStatus]);

  if (sdkStatus === "error") {
    return (
      <div>
        <p>SDK error: {sdkError?.message}</p>
        <button onClick={reinitialize}>Retry</button>
      </div>
    );
  }

  return (
    <div>
      <select value={lens.lensId ?? ""} onChange={(e) => applyLens(e.target.value, LENS_GROUP_ID)}>
        <option value="" disabled>
          Select a Lens
        </option>
        {lenses.map((l) => (
          <option key={l.id} value={l.id}>
            {l.name}
          </option>
        ))}
      </select>
      <button onClick={toggleMuted}>{isMuted ? "Unmute" : "Mute"}</button>

      <LensPlayer lensId={lens.lensId} lensGroupId={LENS_GROUP_ID}>
        <LiveCanvas style={{ width: "100%", maxWidth: 640 }} />
      </LensPlayer>
    </div>
  );
}

export default function App() {
  return (
    <CameraKitProvider apiToken="YOUR_API_TOKEN">
      <LensSwitcher />
    </CameraKitProvider>
  );
}

Utilities

| Export | Description | | ------------------------ | --------------------------------------------------- | | createConsoleLogger() | Returns a logger that prints to the browser console | | createNoopLogger() | Returns a silent logger (default) | | isCameraSource(source) | Type guard for CameraSourceInput | | isVideoSource(source) | Type guard for VideoSourceInput | | isImageSource(source) | Type guard for ImageSourceInput | | CameraRotationOptions | Valid rotation values: [0, -90, 90, 180] |

Development

npm install           # Install dependencies
npm run build         # Build ESM + CJS
npm run watch         # Build in watch mode
npm run typecheck     # Type checking
npm test              # Run tests
npm run clean         # Clean dist folder

Demo app

A Vite demo app is available in demo/:

npm run demo:install
cp demo/.env.example demo/.env
npm run demo:dev

Contributing

We welcome contributions! Please see our Contributing Guidelines for details.

License

MIT