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

@papermap/papermap

v1.1.0

Published

Embeddable AI chat bar and UI components from the Papermap data analytics platform

Readme

Papermap

Embeddable AI-powered components from the Papermap data analytics platform. This is a standalone package — independent from the main Papermap app. Services, SSE streaming, and UI are self-contained; the repos do not depend on each other.

Backend setup

For server-side setup (HMAC auth, dashboards per tenant, embed tokens, API endpoints), see the Backend implementation guide in the Papermap docs.

Main components

  • PaperChat — Full AI chat assistant with streaming, conversation history, and chart generation.
  • PaperCard — Standalone chart card with toolbar actions. Use variant="streaming" for an embedded chart + conversation dialog (without the floating assistant).
  • PaperBoard — Responsive grid layout of chart cards, toolbar (screenshot, generate dashboard, theme), optional chat assistant, and controlled or uncontrolled layouts.
import { PaperChat, PaperCard, PaperBoard } from '@papermap/papermap'

// AI chat assistant
<PaperChat
  token="your-base64-api-token"
  workspaceId="your-workspace-id"
  dashboardId="your-dashboard-id"
/>

// Standalone chart card
<PaperCard
  token="your-base64-api-token"
  workspaceId="your-workspace-id"
  dashboardId="your-dashboard-id"
  chartId="your-chart-id"
/>

// Streaming chart card (embedded dialog + chat)
<PaperCard
  token="your-base64-api-token"
  workspaceId="your-workspace-id"
  dashboardId="your-dashboard-id"
  variant="streaming"
  chartId="your-chart-id" // optional; card shows empty state if omitted
/>

// Full grid dashboard (wraps chart cards + optional PaperChat)
<PaperBoard
  token="..."
  workspaceId="..."
  dashboardId="..."
  showChatAssistant
/>

Each top-level component handles API calls, authentication, and UI internally unless you compose lower-level exports yourself.


Quick start

1. Install

npm install @papermap/papermap
# or
pnpm add @papermap/papermap

Requirements: React 18+ and React DOM 18+ (peer dependencies).

2. Import styles once

import '@papermap/papermap/styles.css'

3. Choose an integration pattern

A) Recommended: provider at app root

PapermapConfigProvider is an alias for PapermapProvider — same component, useful for naming consistency in app code.

import { PapermapConfigProvider, PaperChat, PaperCard } from '@papermap/papermap'

function App() {
  return (
    <PapermapConfigProvider
      token="your-base64-api-token"
      workspaceId="your-workspace-id"
      dashboardId="your-dashboard-id"
      // optional: apiUrl="https://dataapi.papermap.ai"
    >
      <PaperChat />
      <PaperCard chartId="existing-chat-id" />
    </PapermapConfigProvider>
  )
}

B) Standalone components (no provider)

Pass token, workspaceId, and dashboardId on each component (or rely on an existing parent PapermapProvider).

import { PaperChat, PaperCard } from '@papermap/papermap'

function App() {
  return (
    <>
      <PaperChat
        token="your-base64-api-token"
        workspaceId="your-workspace-id"
        dashboardId="your-dashboard-id"
      />

      <PaperCard
        token="your-base64-api-token"
        workspaceId="your-workspace-id"
        dashboardId="your-dashboard-id"
        chartId="existing-chat-id"
      />
    </>
  )
}

4. Props

PaperChat props

| Prop | Type | Required | Default | Description | | ------------- | ------------------- | -------- | ----------------------------- | ------------------------------------ | | token | string | Yes* | -- | Base64-encoded API key token | | workspaceId | string | Yes* | -- | Workspace ID | | dashboardId | string | Yes* | -- | Dashboard ID | | apiUrl | string | No | https://dataapi.papermap.ai | API base URL | | theme | 'light' \| 'dark' | No | -- | Force light or dark theme | | placeholder | string | No | "Ask anything..." | Input placeholder text | | shortcutKey | string | No | "k" | Keyboard shortcut (Cmd/Ctrl + key) | | autoFade | boolean | No | false | Fade toolbar after inactivity | | fadeDelay | number | No | 5000 | Milliseconds before auto-fade | | className | string | No | -- | Extra CSS class on toolbar container |

*Omit on the component when values come from PapermapConfigProvider / PapermapProvider.

PaperCard props

| Prop | Type | Required | Default | Description | | -------------- | -------------------------------------------- | -------- | ----------------------------- | ------------------------------------------------ | | token | string | Yes* | -- | Base64-encoded API key token | | workspaceId | string | Yes* | -- | Workspace ID | | dashboardId | string | Yes* | -- | Dashboard ID | | apiUrl | string | No | https://dataapi.papermap.ai | API base URL | | chartId | string | No | -- | Backend chat id to load the latest chart for | | chart | TChartResponse | No | -- | Pre-loaded chart data (skips API fetch) | | theme | 'light' \| 'dark' | No | -- | Force light or dark theme | | onEditClick | (chartId: string) => void | No | -- | Called when the edit button is clicked | | onDelete | (chartId: string) => void | No | -- | Called when chart deletion is confirmed | | onPinChange | (chartId: string, pinned: boolean) => void | No | -- | Called when pin state changes | | wide | boolean | No | false | Wide mode for table charts | | hideVariants | boolean | No | true | Hide the chart variation selector | | showToolbar | boolean | No | true | Show toolbar with maximize/edit/delete buttons | | className | string | No | -- | Extra CSS class on the card container | | variant | 'default' \| 'streaming' | No | 'default' | 'streaming': edit opens embedded dialog + chat |

Pre-loaded chart:

import { PaperCard } from '@papermap/papermap'
import type { TChartResponse } from '@papermap/papermap'

const chart: TChartResponse = {
  llm_data_chat_id: 'my-chart-id',
  name: 'Revenue',
  meta: { title: 'Revenue by Quarter', variant: 'default' },
  pin: false,
  chart_response: {
    chart_type: 'bar',
    data: [
      { quarter: 'Q1', revenue: 42000 },
      { quarter: 'Q2', revenue: 55000 },
    ],
    response_type: 'chart',
    schema_hints: { x_key: 'quarter', y_key: 'revenue', label_key: 'quarter' },
    visualization_config: { colors: ['#3b82f6'], width: 600, height: 400 },
  },
}

<PaperCard
  token="..."
  workspaceId="..."
  dashboardId="..."
  chart={chart}
  onEditClick={(id) => console.log('Edit', id)}
  onDelete={(id) => console.log('Delete', id)}
/>

PaperBoard props (high level)

| Prop | Notes | | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | | token, workspaceId, dashboardId, apiUrl | Same as other components; can come from provider. | | charts | Optional pre-loaded charts; otherwise fetched when enableFetch is true (default). | | layouts / onLayoutsChange | Controlled grid layouts per breakpoint. | | isEditMode, editLayout, isViewer | Edit vs view behavior. | | showToolbar, showScreenshot, showGenerateDashboard, showHeader, showChatAssistant | Feature toggles. | | variant | 'default' \| 'streaming' for embedded chart cards (matches PaperCard). | | dashboardTheme, onDashboardThemeChange, persistWorkspaceTheme, renderThemeModal | Theming; built-in modal uses ThemeCustomizationSettings. | | Callbacks | onEditChart, onDeleteChart, onPinChange, onGenerateDashboard, onTakeScreenshot, onThemeModalOpen, etc. |

See TypeScript types PaperBoardProps and Storybook stories for full detail.

Streaming chart card variant

With variant="streaming", the edit action opens an embedded expanded view with chart + conversation, SSE streaming, save-to-dashboard and maximize actions, and audit log on assistant messages.

import { PaperCard } from '@papermap/papermap'

export function EmbeddedStreamingChart() {
  return (
    <div className="h-[420px] w-[520px]">
      <PaperCard
        token="..."
        workspaceId="..."
        dashboardId="..."
        variant="streaming"
        chartId="existing-chat-id"
      />
    </div>
  )
}

Supported chart types: bar, line, area, pie, radar, scatter, table, tile — aligned with the main Papermap app.


Advanced exports

For custom layouts, the package also exports subcomponents (for example ChatAssistant, StreamingChartDialog, ChartView, DataTable), Zustand store helpers (usePapermapStore, createPapermapStore), hooks (useAnalyticsStream, …), API helpers (createApiClient, decodeToken, buildAuthHeaders), streaming and chart types, theme presets (themePresets, defaultTheme, ThemeCustomizationSettings), and chart card id ↔ chat id persistence helpers (getChartCardIdLink, resolveChartFetchChatId, …). Import paths are the same as the main entry: @papermap/papermap.


Troubleshooting

Cannot find module @papermap/papermap/styles.css

  • Use the scoped package name and the ./styles.css export.
  • Reinstall after upgrading.

"Papermap... requires token/workspaceId/dashboardId"

  • Provide values once via PapermapConfigProvider / PapermapProvider, or pass them on each component.

Requests hit the wrong backend

  • Set apiUrl on the provider or per component. Default is https://dataapi.papermap.ai.

Charts do not appear in PaperCard

  • Pass a valid backend chartId (chat id), or supply preloaded chart data.

How it works

Authentication

The token prop is base64-encoded JSON:

{
  "api_key_id": "ak_...",
  "workspace_id": "...",
  "valid_until": 1773246356,
  "signature": "88b34e..."
}

The library decodes it and sends these headers on API requests:

  • X-API-Key-ID
  • X-Workspace-ID
  • X-Valid-Until
  • X-Signature
  • X-Tenant-ID: da-app

Chat data flow (overview)

  1. User sends a message; first message may create a chat via POST /api/v1/analytics/chats.
  2. Message goes to POST /api/v1/analytics/charts/stream with SSE.
  3. SSE connects to POST /api/v1/analytics/requests/stream for live updates; HTTP remains a fallback.
  4. History: GET /api/v1/analytics/chats/{id}/conversations, dashboard recent chats, and full chart history per chat as needed.

What users see in PaperChat

  • Floating input bar (portaled to document.body), Cmd/Ctrl+K to focus, Escape to dismiss.
  • Expanding input, backdrop, conversation panel, stop during load, new chat, scroll and history pagination.
  • Recent conversations, per-chat chart history, feedback, optional execution view, model selector, and related toolbar actions.

Roadmap

Additional embeddable surfaces (for example richer explorers) will follow the same pattern: self-contained components with token / workspaceId / dashboardId and optional callbacks, exported from @papermap/papermap.