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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@blumessage/react-chat

v1.5.2

Published

A React TypeScript chat widget component with floating button, theming, and Blumessage API integration

Downloads

110

Readme

Blumessage React Chat Component

A React TypeScript chat widget component with floating button, theming, and Blumessage API integration. Features real-time messaging, conversation persistence, error handling, and a modern UI built with Tailwind CSS.

✨ Features

  • 🎈 Floating Chat Widget - Appears as a button, expands to full chat
  • 🎨 Light/Dark Themes - Built-in theme support
  • 💾 Persistent Storage - Save conversations to localStorage or sessionStorage
  • 🔄 Real-time Messaging - Instant API integration with Blumessage
  • 📱 Responsive Design - Works on desktop and mobile
  • 🎯 Flexible Icons - Supports various icon patterns
  • Error Handling - Comprehensive error callbacks
  • 🔧 Highly Customizable - Extensive prop options

Installation

NPM Package (Recommended)

npm i @blumessage/react-chat

Browser Versions

Option 1: Standalone (Includes React)

For the simplest setup with everything included:

<!-- Load the Blumessage Chat component (includes React) -->
<script src="path/to/index.js"></script>

Option 2: External React (Smaller Bundle)

For when you already have React loaded:

<!-- Load React and ReactDOM from CDN -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

<!-- Load the Blumessage Chat component -->
<script src="path/to/blumessage-chat.browser.js"></script>

See BROWSER_USAGE.md for complete browser usage documentation.

Quick Start

Floating Chat Widget (Default)

import React from 'react';
import { BlumessageChat } from '@blumessage/react-chat';

function App() {
  return (
    <BlumessageChat 
      apiKey="your-blumessage-api-key"
    />
  );
}

Embedded Chat

import React from 'react';
import { BlumessageChat } from '@blumessage/react-chat';

function App() {
  return (
    <BlumessageChat 
      apiKey="your-blumessage-api-key"
      floating={false}
      width="400px"
      height="600px"
    />
  );
}

Complete Props Reference

| Prop | Type | Default | Description | |------|------|---------|-------------| | Required | | apiKey | string | - | Your Blumessage API key | | Display & Content | | name | string | "Blumessage AI" | Display name for the AI assistant | | subtitle | string | "Online • Instant responses" | Subtitle shown under the name | | placeholder | string | "Type your message..." | Input placeholder text | | theme | 'light' \| 'dark' | 'light' | Chat widget theme | | primaryColor | string | "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" | Primary color/gradient | | Layout & Sizing | | floating | boolean | true | Show as floating widget vs embedded | | width | string | '380px' (medium) | Custom width (overrides size) | | height | string | '500px' (medium) | Custom height (overrides size) | | size | 'small' \| 'medium' \| 'large' | 'medium' | Predefined size preset | | fullScreen | boolean | false | Force full screen mode | | Floating Widget Options | | buttonText | string | "Chat with us" | Text on floating button | | buttonPosition | 'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left' | 'bottom-right' | Button position | | buttonStyle | React.CSSProperties | - | Custom button styles | | defaultOpen | boolean | false | Start with chat open | | maximizeToggleButton | boolean | true | Show maximize/minimize button | | icon | string | 'message-circle' | Icon for button (flexible naming) | | Help Bubble Options | | showHelpBubble | boolean | true | Show help bubble above floating button | | helpBubbleMessage | string | "👋 If you need help chat with us" | Message text in help bubble | | helpBubbleIcon | string | 'hand' | Icon for help bubble (supports lucide-react icon names) | | helpBubbleShowAfter | number | 1 | Seconds to wait before showing bubble | | helpBubbleHideAfter | number | 5 | Seconds to wait before hiding bubble (0 = never hide) | | Messages & Data | | initialMessages | Message[] | [] | Pre-populate with messages | | conversationId | string | - | Continue specific conversation | | persistent | boolean | false | Use localStorage vs sessionStorage | | showTimestamps | boolean | false | Display timestamps: today="2:00 PM", older="17 July, 1:00 PM" | | typingText | string | "Agent is typing..." | Custom text shown while waiting for assistant response | | emptyStateText | string | "Start a conversation!" | Text shown when no messages are present | | markdown | boolean | true | Enable markdown rendering for messages | | disableAutoScroll | boolean | false | Disable automatic scrolling to bottom when new messages arrive | | Event Callbacks | | onUserMessage | (message: Message) => void | - | Called when user sends message | | onAssistantMessage | (message: Message) => void | - | Called when assistant responds | | onConversationIdChange | (id: string \| null) => void | - | Called when conversation ID changes | | onChatWidgetOpen | () => void | - | Called when floating chat opens | | onChatWidgetClosed | () => void | - | Called when floating chat closes | | onError | (error: string, context?: string) => void | - | Called on any error |

Advanced Usage Examples

Dark Theme with Callbacks

<BlumessageChat 
  apiKey="your-api-key"
  theme="dark"
  name="Support Bot"
  onUserMessage={(message) => console.log('User:', message.content)}
  onAssistantMessage={(message) => console.log('Bot:', message.content)}
  onError={(error, context) => console.error(`Error in ${context}:`, error)}
/>

Persistent Storage

<BlumessageChat 
  apiKey="your-api-key"
  persistent={true}  // Saves to localStorage instead of sessionStorage
  onConversationIdChange={(id) => {
    // Optionally save ID to your own storage
    if (id) localStorage.setItem('my-chat-id', id);
  }}
/>

Custom Styling & Size

<BlumessageChat 
  apiKey="your-api-key"
  size="large"
  primaryColor="linear-gradient(45deg, #ff6b6b, #4ecdc4)"
  buttonPosition="bottom-left"
  buttonText="Need Help?"
  icon="headphones"
  maximizeToggleButton={true}
/>

Embedded with Initial Messages

const initialMessages = [
  {
    id: '1',
    role: 'assistant' as const,
    content: 'Hello! How can I help you today?',
    timestamp: Date.now()
  }
];

<BlumessageChat 
  apiKey="your-api-key"
  floating={false}
  width="100%"
  height="500px"
  initialMessages={initialMessages}
  placeholder="Ask me anything..."
/>

Help Bubble Configuration

<BlumessageChat 
  apiKey="your-api-key"
  floating={true}
  showHelpBubble={true}
  helpBubbleMessage="👋 Need assistance? We're here to help!"
  helpBubbleIcon="hand"  // Use hand icon (default)
  helpBubbleShowAfter={3}  // Show after 3 seconds
  helpBubbleHideAfter={10} // Hide after 10 seconds
/>

Custom Help Bubble Icons

<BlumessageChat 
  apiKey="your-api-key"
  floating={true}
  showHelpBubble={true}
  helpBubbleIcon="star"  // Use star icon
  helpBubbleMessage="⭐ Rate our service!"
  helpBubbleShowAfter={2}
  helpBubbleHideAfter={8}
/>

<BlumessageChat 
  apiKey="your-api-key"
  floating={true}
  showHelpBubble={true}
  helpBubbleIcon="lightbulb"  // Use lightbulb icon
  helpBubbleMessage="💡 Got an idea? Let's discuss it!"
  helpBubbleShowAfter={1}
  helpBubbleHideAfter={0}  // Never hide
/>

<BlumessageChat 
  apiKey="your-api-key"
  floating={true}
  showHelpBubble={true}
  helpBubbleIcon="help-circle"  // Use help icon
  helpBubbleMessage="❓ Questions? We're here to help!"
  helpBubbleShowAfter={5}
  helpBubbleHideAfter={15}
/>

### Persistent Help Bubble (Never Hide)

```tsx
<BlumessageChat 
  apiKey="your-api-key"
  floating={true}
  showHelpBubble={true}
  helpBubbleMessage="💬 Questions? Click to chat with us!"
  helpBubbleShowAfter={2}  // Show after 2 seconds
  helpBubbleHideAfter={0}  // Never hide (0 = persistent)
/>

Chat with Timestamps

<BlumessageChat 
  apiKey="your-api-key"
  showTimestamps={true}  // Shows "2:00 PM" or "17 July, 1:00 PM"
  floating={false}
  initialMessages={[
    {
      id: '1',
      role: 'assistant' as const,
      content: 'Message from today',
      timestamp: Date.now() - (60 * 60 * 1000)  // Shows: "2:00 PM" (or "14:00")
    },
    {
      id: '2',
      role: 'user' as const,
      content: 'Message from yesterday',
      timestamp: Date.now() - (24 * 60 * 60 * 1000)  // Shows: "17 July, 1:00 PM"
    }
  ]}
/>

Custom Typing Indicator

<BlumessageChat 
  apiKey="your-api-key"
  typingText="Support agent is typing..."  // Custom loading message
  // Or use different text for different languages:
  // typingText="L'agent écrit..." // French
  // typingText="El agente está escribiendo..." // Spanish
/>

Custom Empty State Text

<BlumessageChat 
  apiKey="your-api-key"
  emptyStateText="Welcome! How can I help you today?"  // Custom empty state message
  // Or use different text for different contexts:
  // emptyStateText="Ask me anything about our products..."
  // emptyStateText="Ready to assist with your questions!"
/>

Disable Auto-Scroll

<BlumessageChat 
  apiKey="your-api-key"
  disableAutoScroll={true}  // Prevents automatic scrolling to bottom
  // Useful when you want users to maintain their scroll position
  // or when implementing custom scroll behavior
/>

Icon Options

The icon prop accepts any lucide-react icon name with flexible naming patterns. The component intelligently matches your input to the appropriate lucide-react icon:

// ✅ Any lucide-react icon works:
icon="message-circle"    // MessageCircle
icon="phone"             // Phone
icon="mail"              // Mail
icon="headphones"        // Headphones
icon="bot"               // Bot
icon="users"             // Users
icon="heart"             // Heart
icon="star"              // Star
icon="zap"               // Zap
icon="settings"          // Settings
icon="help-circle"       // HelpCircle
icon="info"              // Info
icon="alert-triangle"    // AlertTriangle

// ✅ Flexible naming patterns (case-insensitive, ignores hyphens/underscores):
icon="MessageCircle"     // → MessageCircle
icon="message_circle"    // → MessageCircle
icon="message circle"    // → MessageCircle
icon="chat"              // → MessageCircle (smart matching)
icon="messaging"         // → MessageCircle (smart matching)
icon="support"           // → Headphones (smart matching)
icon="email"             // → Mail (smart matching)
icon="call"              // → Phone (smart matching)

// ✅ Default fallback: MessageCircle (if no match found)
icon="unknown-icon"      // → MessageCircle

Browse all available icons at: lucide.dev/icons

Simply use the icon name from lucide-react, and the component will handle the rest!

Error Handling

The onError callback provides detailed error context:

<BlumessageChat 
  apiKey="your-api-key"
  onError={(error, context) => {
    switch(context) {
      case 'missing_api_key':
        // Handle missing API key
        break;
      case 'api_key_validation':
        // Handle invalid API key
        break;
      case 'network_error':
        // Handle network issues
        break;
      case 'conversation_history':
        // Handle history fetch errors
        break;
      case 'message_send':
        // Handle message sending errors
        break;
    }
  }}
/>

External Message Submission

The component supports external message submission through a ref, allowing parent components to programmatically send messages and control the chat widget.

Using the Ref

import React, { useRef } from 'react';
import { BlumessageChat, BlumessageChatRef } from '@blumessage/react-chat';

function App() {
  const chatRef = useRef<BlumessageChatRef>(null);

  const sendExternalMessage = async () => {
    if (chatRef.current) {
      await chatRef.current.sendMessage("Hello from external component!");
    }
  };

  const openChat = () => {
    chatRef.current?.openChat();
  };

  const closeChat = () => {
    chatRef.current?.closeChat();
  };

  const clearChat = () => {
    chatRef.current?.clearConversation();
  };

  const getMessages = () => {
    const messages = chatRef.current?.getMessages();
    console.log('Current messages:', messages);
  };

  const getToken = () => {
    const token = chatRef.current?.getToken();
    console.log('Current conversation token:', token);
  };

  return (
    <div>
      <button onClick={sendExternalMessage}>Send External Message</button>
      <button onClick={openChat}>Open Chat</button>
      <button onClick={closeChat}>Close Chat</button>
      <button onClick={clearChat}>Clear Chat</button>
      <button onClick={getMessages}>Get Messages</button>
      <button onClick={getToken}>Get Token</button>
      
      <BlumessageChat
        ref={chatRef}
        apiKey="your-api-key"
        floating={true}
      />
    </div>
  );
}

Available Ref Methods

| Method | Type | Description | |--------|------|-------------| | sendMessage(message: string) | Promise<void> | Send a message programmatically | | openChat() | void | Open the floating chat widget | | closeChat() | void | Close the floating chat widget | | clearConversation() | void | Clear all messages and reset conversation | | getMessages() | Message[] | Get current messages array | | getToken() | string \| null | Get current conversation token |

Complete Example with External Controls

import React, { useRef, useState } from 'react';
import { BlumessageChat, BlumessageChatRef } from '@blumessage/react-chat';

function App() {
  const [externalMessage, setExternalMessage] = useState('');
  const chatRef = useRef<BlumessageChatRef>(null);

  const handleSendExternalMessage = async () => {
    if (!externalMessage.trim() || !chatRef.current) return;
    
    try {
      await chatRef.current.sendMessage(externalMessage);
      setExternalMessage('');
      console.log('External message sent successfully');
    } catch (error) {
      console.error('Failed to send external message:', error);
    }
  };

  return (
    <div>
      <div style={{ marginBottom: '20px' }}>
        <input
          type="text"
          value={externalMessage}
          onChange={(e) => setExternalMessage(e.target.value)}
          placeholder="Type a message to send externally..."
          onKeyPress={(e) => e.key === 'Enter' && handleSendExternalMessage()}
        />
        <button onClick={handleSendExternalMessage}>Send</button>
        <button onClick={() => chatRef.current?.openChat()}>Open Chat</button>
        <button onClick={() => chatRef.current?.closeChat()}>Close Chat</button>
        <button onClick={() => chatRef.current?.clearConversation()}>Clear Chat</button>
      </div>
      
      <BlumessageChat
        ref={chatRef}
        apiKey="your-api-key"
        floating={true}
        onUserMessage={(message) => console.log('User message:', message)}
        onAssistantMessage={(message) => console.log('Assistant message:', message)}
      />
    </div>
  );
}

TypeScript Support

Full TypeScript definitions included:

import { BlumessageChat, Message, BlumessageChatProps, BlumessageChatRef } from '@blumessage/react-chat';

interface Message {
  id: string;
  role: 'user' | 'assistant';
  content: string;
  timestamp: number;
}

interface BlumessageChatRef {
  sendMessage: (message: string) => Promise<void>;
  openChat: () => void;
  closeChat: () => void;
  clearConversation: () => void;
  getMessages: () => Message[];
  getToken: () => string | null;
}

Storage Behavior

  • SessionStorage (default): Conversations persist until browser tab closes
  • LocalStorage (persistent=true): Conversations persist across browser sessions
  • Automatic cleanup: Invalid conversation IDs are automatically cleared
  • History restoration: Previous conversations load automatically on component mount

Browser Support

  • Modern browsers with ES2017+ support
  • React 18+
  • TypeScript 4.5+

Building

Standard Build (ES Modules)

npm run build

Browser Versions

Standalone (Includes React)

npm run build:commonjs

This creates dist/index.js which includes React and can be used directly in browsers.

External React (Smaller Bundle)

npm run build:browser

This creates dist/blumessage-chat.browser.js which requires React to be loaded separately.

License

UNLICENSED - For use only by customers with an active Blumessage subscription.

Support

For feature requests, technical support and assistance, please contact us at: [email protected]