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

@jazzmine-ui/react

v0.1.13

Published

Jazzmine: A customizable React chat UI component library

Readme

@jazzmine-ui/react

Production-ready React chat UI for the Jazzmine ecosystem.

This package is the UI layer for Jazzmine apps. It provides composable chat components, a managed SDK-powered experience, and a strongly typed contract for backend clients.

Package: @jazzmine-ui/react
Version: 0.1.10
Runtime: React 18+

Overview

@jazzmine-ui/react supports two integration styles:

  • JazzmineChat: managed mode that handles conversation lifecycle and message flow.
  • ChatInterface: controlled mode where your app owns data fetching and state.

Both modes share the same visual system and core message/context model.

Package Role In The Ecosystem

This package is responsible for UI and interaction orchestration:

  1. Renders chat layouts, message streams, sidebars, and search UI.
  2. Maps backend conversation/message data into UI state.
  3. Exposes reusable components for custom app-level composition.
  4. Stays SDK-agnostic at runtime: any client matching IJazzmineClient works.

Install

npm install @jazzmine-ui/react

Install peer dependencies if your app does not already provide them:

npm install react react-dom react-markdown remark-gfm remark-math rehype-katex katex

Import package styles once at app entry:

import '@jazzmine-ui/react/styles';

Choose An Integration Mode

| Mode | Best for | You manage | Package manages | | --- | --- | --- | --- | | JazzmineChat | Fastest production integration | Client instance + optional callbacks | Conversation create/list/search/delete/update, history loading, send flow, loading states | | ChatInterface | Full custom state architecture | All data/state/actions | Presentation, local UI interactions, context selection UX |

Key Features

  • Managed conversation flows (create/select/rename/delete).
  • Sidebar pagination and search modal integration.
  • Markdown + GFM + LaTeX rendering (react-markdown + remark-gfm + remark-math + rehype-katex).
  • Explicit context selection and forwarding support.
  • Empty-state assistant message via defaultMessage.
  • History mapping based on backend original_content.
  • Optional history context hydration from backend explicit_context.

Quick Start

1) SDK-Powered With JazzmineChat

'use client';

import React from 'react';
import JazzmineClient from '@jazzmine-ui/sdk';
import { JazzmineChat } from '@jazzmine-ui/react';
import '@jazzmine-ui/react/styles';

const client = new JazzmineClient('https://your-jazzmine-api.example.com', {
  apiKey: 'your-api-key',
  defaultUserId: 'user',
});

export function App() {
  return (
    <div style={{ height: '100vh' }}>
      <JazzmineChat
        client={client}
        assistantName="Jazzmine AI"
        placeholder="Ask anything..."
        defaultMessage="Welcome! Ask me anything to get started."
        onError={(error) => {
          console.error('JazzmineChat error:', error);
        }}
      />
    </div>
  );
}

2) Fully Controlled With ChatInterface

import React from 'react';
import { ChatInterface } from '@jazzmine-ui/react';
import type { Chat, Message } from '@jazzmine-ui/react';
import '@jazzmine-ui/react/styles';

export function App() {
  const [messages, setMessages] = React.useState<Message[]>([]);
  const [chats, setChats] = React.useState<Chat[]>([]);
  const [activeChatId, setActiveChatId] = React.useState<string>();
  const [isLoading, setIsLoading] = React.useState(false);

  const onSend = async (text: string) => {
    setMessages((prev) => [
      ...prev,
      { id: crypto.randomUUID(), text, sender: 'user', timestamp: new Date().toISOString() },
    ]);

    setIsLoading(true);
    try {
      const reply = `Echo: ${text}`;
      setMessages((prev) => [
        ...prev,
        {
          id: crypto.randomUUID(),
          text: reply,
          sender: 'assistant',
          timestamp: new Date().toISOString(),
        },
      ]);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <div style={{ height: '100vh' }}>
      <ChatInterface
        chats={chats}
        activeChatId={activeChatId}
        messages={messages}
        onSend={onSend}
        onNewChat={() => {}}
        onSelectChat={setActiveChatId}
        isLoading={isLoading}
        defaultMessage="Welcome! Ask me anything to get started."
      />
    </div>
  );
}

Public Exports

Components:

  • ChatInterface
  • Sidebar
  • MessageList
  • FloatingChatWidget
  • JazzmineChat
  • SearchModal

Types:

  • ChatInterfaceProps
  • SidebarProps
  • MessageListProps
  • FloatingChatWidgetProps
  • JazzmineChatProps
  • SearchModalProps
  • IJazzmineClient
  • Context
  • Message
  • Chat

API Reference

JazzmineChatProps

| Prop | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | client | IJazzmineClient | Yes | - | Backend client implementation. | | userId | string | No | 'user' | Used for list/search conversation calls. | | assistantName | string | No | Health response or 'AI Assistant' | Header/avatar assistant label. | | placeholder | string | No | 'Type your message...' | Input placeholder text. | | className | string | No | '' | Root class override. | | defaultMessage | string | No | '' | Rendered when conversation has no messages and is not loading. | | onError | (error: Error) => void | No | - | Called for recoverable client-side errors. |

ChatInterfaceProps

| Prop | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | messages | Message[] | Yes | - | Current message list. | | chats | Chat[] | Yes | - | Sidebar conversation list. | | onSend | (text: string, contexts?: Context[]) => void | Yes | - | Send handler; receives selected context snippets when present. | | onNewChat | () => void | Yes | - | New chat action. | | onSelectChat | (chatId: string) => void | Yes | - | Active chat selection. | | activeChatId | string | No | - | Active conversation id. | | assistantName | string | No | 'AI Assistant' | Assistant display name. | | onRenameChat | (chatId: string, newTitle?: string) => void | No | - | Rename conversation action. | | onDeleteChat | (chatId: string) => void | No | - | Delete conversation action. | | onSearchClick | () => void | No | - | Opens external conversation search flow. | | onLoadMore | () => void | No | - | Load-more trigger for infinite conversation lists. | | hasMore | boolean | No | false | Indicates additional chat pages are available. | | isLoadingChats | boolean | No | false | Sidebar list loading indicator. | | isSearchOpen | boolean | No | false | Controls sidebar search visibility. | | searchQuery | string | No | '' | Sidebar search query value. | | onSearchQueryChange | (query: string) => void | No | - | Sidebar search input handler. | | isLoading | boolean | No | false | Message send/load state. | | loadingText | string | No | '' | Assistant status text while loading. | | loadingVariant | 'text-and-dots' \| 'dots-only' | No | 'text-and-dots' | Loading indicator style. | | placeholder | string | No | 'Type your message...' | Input placeholder text. | | className | string | No | '' | Root class override. | | defaultMessage | string | No | '' | Empty-state assistant message. |

SidebarProps

| Prop | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | chats | Chat[] | Yes | - | Conversations to render. | | onNewChat | () => void | Yes | - | New chat button callback. | | onSelectChat | (chatId: string) => void | Yes | - | Select chat callback. | | activeChatId | string | No | - | Current selected chat id. | | assistantName | string | No | - | Header title label. | | logo | string | No | Built-in logo | Custom header/logo image. | | logoAlt | string | No | - | Logo alt text. | | chatActions | ChatAction[] | No | Built-in actions | Custom chat action menu items. | | onRenameChat | (chatId: string, newTitle?: string) => void | No | - | Enables default rename action. | | onDeleteChat | (chatId: string) => void | No | - | Enables default delete action. | | onArchiveChat | (chatId: string) => void | No | - | Enables default archive action. | | onSearchClick | () => void | No | - | Search trigger callback. | | onLoadMore | () => void | No | - | Infinite-scroll load callback. | | hasMore | boolean | No | false | More pages available. | | isLoadingChats | boolean | No | false | Loading state for chat list. | | isSearchOpen | boolean | No | false | Search input visibility. | | searchQuery | string | No | '' | Search query value. | | onSearchQueryChange | (query: string) => void | No | - | Search query change callback. | | className | string | No | '' | Root class override. | | collapsed | boolean | No | Internal state | Controlled collapse mode. | | onToggleCollapse | (value?: boolean) => void | No | - | Controlled collapse handler. |

MessageListProps

| Prop | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | messages | Message[] | Yes | - | Message feed data. | | assistantName | string | No | - | Assistant label in assistant messages. | | defaultMessage | string | No | '' | Empty-state assistant message. | | isLoading | boolean | No | false | Appends loading assistant row. | | loadingText | string | No | 'typing' | Loading indicator text. | | loadingVariant | 'text-and-dots' \| 'dots-only' | No | 'text-and-dots' | Loading indicator style. | | className | string | No | '' | Root class override. | | searchQuery | string | No | - | Highlight query string. | | activeSearchMessageId | string | No | - | Auto-scroll target message id. | | onAddContext | (context: Context) => void | No | - | Adds selected snippet to context panel. | | scrollRef | React.RefObject<HTMLDivElement \| null> \| ((node: HTMLDivElement \| null) => void) | No | - | External scroll node access. |

FloatingChatWidgetProps

| Prop | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | messages | Message[] | Yes | - | Message feed data. | | assistantName | string | No | - | Header title in widget panel. | | isLoading | boolean | No | false | Loading state. | | loadingText | string | No | 'typing' | Loading text. | | loadingVariant | 'text-and-dots' \| 'dots-only' | No | 'text-and-dots' | Loading indicator style. | | initialOpen | boolean | No | false | Initial panel open state. | | onOpen | (open: boolean) => void | No | - | Open/close change callback. | | onSend | (text: string) => void | No | - | Message send callback. | | logo | string | No | Built-in logo | Widget button image source. | | className | string | No | '' | Root class override. |

SearchModalProps

| Prop | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | isOpen | boolean | Yes | - | Modal visibility state. | | onClose | () => void | Yes | - | Close callback. | | onSelectConversation | (conversationId: string) => void | Yes | - | Select result callback. | | searchQuery | string | Yes | - | Controlled input value. | | onSearchQueryChange | (query: string) => void | Yes | - | Controlled input update callback. | | results | Chat[] | Yes | - | Search results. | | isSearching | boolean | Yes | - | Loading state for async search. |

ChatAction

interface ChatAction {
  label: string;
  icon?: React.ReactNode;
  onClick: (chatId: string) => void;
  danger?: boolean;
}

IJazzmineClient Contract

JazzmineChat depends on this contract and does not require a specific concrete implementation.

interface IJazzmineClient {
  sendMessage(
    message: string,
    options?: {
      conversationId?: string;
      autoCreateConversation?: boolean;
      conversationTitle?: string;
      explicitContext?: string[];
    }
  ): Promise<{
    response: {
      response: string;
      response_markdown: string;
      conversation_id: string;
      message_id: string;
      is_blocked: boolean;
      errors: string[];
    };
    conversationId: string;
  }>;

  createConversation(payload?: { title?: string; user_id?: string }): Promise<{
    conversation_id: string;
    title: string;
  }>;

  deleteConversation(conversationId: string): Promise<{
    conversation_id: string;
    deleted: boolean;
  }>;

  listConversations(params: {
    userId: string;
    limit?: number;
    offset?: number;
  }): Promise<{
    conversations: Array<{
      conversation_id: string;
      title: string;
      last_updated_at: number;
    }>;
    total: number;
    hasMore: boolean;
    offset: number;
    limit: number;
  }>;

  searchConversations(params: {
    userId: string;
    query: string;
    limit?: number;
    offset?: number;
  }): Promise<{
    conversations: Array<{
      conversation_id: string;
      title: string;
      last_updated_at: number;
    }>;
    total: number;
    hasMore: boolean;
    offset: number;
    limit: number;
    query?: string;
  }>;

  updateConversation(
    conversationId: string,
    payload: { title: string }
  ): Promise<{
    conversation_id: string;
    title: string;
    last_updated_at: number;
  }>;

  getConversationMessages(params: {
    conversationId: string;
    limit?: number;
    offset?: number;
  }): Promise<{
    conversation_id: string;
    messages: Array<{
      id: string;
      role: 'user' | 'assistant' | 'colleague_assistant' | 'system';
      original_content: string;
      enhanced_message: string;
      explicit_context?: string[] | null;
      timestamp: number;
    }>;
    total: number;
    hasMore: boolean;
  }>;

  getHealth(): Promise<{
    status: string;
    agent_name: string;
  }>;
}

Data Mapping Notes (JazzmineChat)

When loading historical messages, JazzmineChat intentionally applies these rules:

  1. Only user and assistant roles are rendered.
  2. Message text is sourced from original_content.
  3. explicit_context is mapped into Message.contexts when non-empty.
  4. If explicit_context is missing or empty, contexts is omitted.

Theming

The package uses CSS variables. Override them globally after importing styles:

:root {
  --jazzmine-primary: #3b82f6;
  --jazzmine-primary-hover: #2563eb;
  --jazzmine-bg: #f8fafc;
  --jazzmine-text-primary: #0f172a;
  --jazzmine-border-radius: 14px;
  --jazzmine-sidebar-width: 300px;
}

Development

npm install
npm run lint
npm run build

Changelog

0.1.10

  • Synced SDK history contract docs with explicit_context support.
  • Exported Context in the package type barrel and docs export list.
  • Updated README package version metadata.

0.1.9

  • Added empty-state defaultMessage support in chat flow.
  • Improved history mapping to use original_content as message text.
  • Added support for mapping backend explicit_context to message contexts.
  • Expanded README structure for ecosystem docs pages.

0.1.8

  • Added defaultMessage prop to JazzmineChat and ChatInterface pathways.
  • Updated docs and usage examples.

0.1.7

  • Added conversation search modal and sidebar search integration.
  • Added pagination/load-more behavior in sidebar.
  • Added rename and delete flows for conversations.

License

MIT