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

mbxai-chat-ui

v0.5.0

Published

A simple chat user interface built with Vue.js that simulates a conversation between a user and an assistant.

Downloads

2

Readme

MBXAI Chat UI

A simple chat user interface built with Vue.js that simulates a conversation between a user and an assistant.

Features

  • Clean, modern UI design
  • Real-time message display
  • Multiple message types (text, image, file, code, math)
  • File and image upload functionality
  • Camera integration for taking photos
  • LaTeX math formula rendering
  • Code blocks with syntax highlighting and line numbers
  • Copy functionality for all message types
  • Automatic scrolling to new messages
  • Suggested message chips for quick responses
  • Confidential message masking with show/hide functionality for user inputs
  • Automatic detection of sensitive information in user messages
  • Loading state with spinner indicator and disabled send button
  • Responsive design for both desktop and mobile

Project Setup

npm install

Start Development Server

npm run dev

Build for Production

npm run build

Preview Production Build

npm run preview

Using as an npm Dependency

You can use this chat UI as a dependency in your own Vue applications. Here's how:

Building the Library

  1. Clone this repository:

    git clone https://github.com/yourusername/mbxai-chat-ui.git
    cd mbxai-chat-ui
  2. Install dependencies:

    npm install
  3. Build the library:

    npm run build:lib

Publishing to npm (Optional)

If you want to publish the package to npm:

  1. Update the package name in package.json if needed
  2. Login to npm:
    npm login
  3. Publish the package:
    npm publish

Installing in Your Project

npm install mbxai-chat-ui

Using the Components

Import the entire chat UI

<template>
  <div class="app">
    <h1>My Chat Application</h1>
    <ChatUI 
      :initial-messages="initialMessages"
      :suggestions="suggestions"
      :confidential-words="confidentialWords"
      :loading="isLoading"
      @message-sent="handleMessage"
      @suggestion-selected="handleSuggestion"
      @new-message="handleNewMessage"
      @history-updated="handleHistoryUpdate"
      @file-uploaded="handleFileUpload"
      @image-captured="handleImageCapture"
      @math-sent="handleMathFormula"
      ref="chatUI"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ChatUI from 'mbxai-chat-ui';
import 'mbxai-chat-ui/dist/mbxai-chat-ui.css';

const chatUI = ref(null);
const messageHistory = ref([]);
const isLoading = ref(false);

// Optional: Pre-populate the chat with initial messages
const initialMessages = ref([
  {
    id: 1,
    type: 'text',
    text: 'Welcome back! How can I assist you today?',
    sender: {
      id: 2,
      name: 'Assistant'
    },
    timestamp: new Date()
  }
]);

const suggestions = ref([
  "What can you help me with?",
  "Tell me about your features",
  "How do I implement this?",
  "$E = mc^2$" // LaTeX formula example
]);

// Define words that should trigger confidential masking
const confidentialWords = ref([
  'password', 
  'token', 
  'secret', 
  'key', 
  'credential',
  'username'
]);

const handleMessage = (message) => {
  // Process the message when user sends it
  console.log('Message sent:', message);
  
  // Show loading indicator while processing
  isLoading.value = true;
  
  // Simulate AI response after 2 seconds
  setTimeout(() => {
    chatUI.value.addMessage({
      type: 'text',
      text: 'This is a response to your message: ' + message.text,
      sender: {
        id: 2,
        name: 'Assistant'
      }
    });
    
    // Hide loading indicator after response
    isLoading.value = false;
  }, 2000);
};

const handleNewMessage = (message) => {
  // This is triggered for both user and assistant messages
  console.log('New message added to chat:', message);
};

const handleHistoryUpdate = (history) => {
  // Get the complete message history (including unmasked confidential messages)
  messageHistory.value = history;
  console.log('Full chat history:', history);
};

const handleSuggestion = (suggestion) => {
  console.log('Suggestion selected:', suggestion);
};

const handleFileUpload = (fileMessage) => {
  // Handle file uploads (documents, PDFs, etc.)
  console.log('File uploaded:', fileMessage);
  
  // Example: Process the file and respond
  setTimeout(() => {
    chatUI.value.addMessage({
      type: 'text',
      text: `I received your file: ${fileMessage.fileName}`,
      sender: {
        id: 2,
        name: 'Assistant'
      }
    });
  }, 1000);
};

const handleImageCapture = (imageMessage) => {
  // Handle images from uploads or camera
  console.log('Image received:', imageMessage);
  
  // Example: Process the image and respond
  setTimeout(() => {
    chatUI.value.addMessage({
      type: 'text',
      text: 'I received your image and processed it',
      sender: {
        id: 2,
        name: 'Assistant'
      }
    });
  }, 1000);
};

const handleMathFormula = (mathMessage) => {
  // Handle math formula messages
  console.log('Math formula received:', mathMessage);
  
  // Example: Respond with another formula
  setTimeout(() => {
    chatUI.value.addMathMessage('F = ma', {
      id: 2,
      name: 'Assistant'
    });
  }, 1000);
};

// You can also access the chat history directly
const getFullHistory = () => {
  return chatUI.value.getMessageHistory();
};

// You can update the confidential words list dynamically
const updateConfidentialWords = (newWords) => {
  chatUI.value.updateConfidentialWords(newWords);
};

// You can add different types of messages
const addTextMessage = (text) => {
  chatUI.value.addMessage({
    type: 'text',
    text: text,
    sender: {
      id: 2,
      name: 'Assistant'
    }
  });
};

const addImageMessage = (imageUrl, caption) => {
  chatUI.value.addMessage({
    type: 'image',
    text: caption,
    url: imageUrl,
    sender: {
      id: 2,
      name: 'Assistant'
    }
  });
};

const addFileMessage = (fileUrl, fileName, fileSize) => {
  chatUI.value.addMessage({
    type: 'file',
    text: 'Here is the requested file',
    url: fileUrl,
    fileName: fileName,
    fileSize: fileSize,
    sender: {
      id: 2,
      name: 'Assistant'
    }
  });
};

const addMathMessage = (formula) => {
  chatUI.value.addMathMessage(formula, {
    id: 2,
    name: 'Assistant'
  });
};
</script>

Initial Messages

You can pre-populate the chat with initial messages using the initial-messages prop. This is useful for:

  • Restoring a previous conversation
  • Starting with a custom welcome message
  • Pre-loading context or instructions

Basic Usage

<template>
  <ChatUI :initial-messages="messages" />
</template>

<script setup>
import { ref } from 'vue';
import ChatUI from 'mbxai-chat-ui';

const messages = ref([
  {
    id: 1,
    type: 'text',
    text: 'Welcome back! I remember our previous conversation.',
    sender: {
      id: 2,
      name: 'Assistant'
    },
    timestamp: new Date()
  },
  {
    id: 2,
    type: 'text',
    text: 'Thanks! Can you remind me what we discussed?',
    sender: {
      id: 1,
      name: 'You'
    },
    timestamp: new Date()
  }
]);
</script>

Dynamic Updates

The initial-messages prop is reactive, so you can update it to completely replace the chat history:

<script setup>
const messages = ref([]);

// Load a different conversation
const loadConversation = (conversationId) => {
  // Replace all messages with new conversation
  messages.value = getConversationHistory(conversationId);
};

// Clear chat and start fresh
const startNewChat = () => {
  messages.value = [];
};
</script>

Important Notes:

  • When initial-messages is provided, it completely replaces the default welcome message
  • If you set initial-messages to an empty array, the default welcome message will be shown
  • Each message must have a unique id and follow the message format specified below
  • Updating initial-messages will trigger the history-updated event

Import individual components

<template>
  <div class="app">
    <ChatWindow 
      :messages="messages" 
      :confidential-words="confidentialWords" 
    />
    <SuggestedMessages 
      :suggestions="suggestions" 
      @select-suggestion="handleSuggestion" 
    />
    <MessageInput 
      @send-message="handleMessage" 
      :confidential-mode="confidentialMode"
      :loading="isLoading"
      @toggle-confidential="toggleConfidential"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { ChatWindow, MessageInput, SuggestedMessages } from 'mbxai-chat-ui';
import 'mbxai-chat-ui/dist/mbxai-chat-ui.css';

// Your implementation...
</script>

Message Format

Messages should follow this format:

{
  id: Number, // Unique identifier
  type: String, // 'text', 'math', 'code', 'image', or 'file'
  text: String, // Message content, caption, math formula, or code
  language: String, // For code messages, optional (e.g., 'javascript', 'python')
  url: String, // For image or file messages
  fileName: String, // For file messages
  fileSize: Number, // For file messages, in bytes
  sender: {
    id: Number, // 1 for user, 2 for assistant (or any IDs you choose)
    name: String, // Display name
    avatar: String // Optional URL to avatar image
  },
  timestamp: Date, // Message timestamp
  confidential: Boolean, // Whether this message contains sensitive information (only for user messages)
  hasLatex: Boolean // Whether this text message contains LaTeX formulas
}

Available Props

The ChatUI component accepts the following props:

| Prop | Type | Default | Description | |------|------|---------|-------------| | initial-messages | Array | [] | Pre-populate the chat with initial messages. When empty, shows default welcome message. | | suggestions | Array | [] | Array of suggestion strings to display as clickable chips below the chat. | | confidential-words | Array | ['password', 'token', 'secret', 'key', 'credential'] | Words that trigger automatic confidential masking in user messages. | | loading | Boolean | false | Show loading spinner and disable send button. Useful when processing AI responses. |

Available Events

The ChatUI component emits the following events:

| Event | Description | Payload | |-------|-------------|---------| | message-sent | Triggered when the user sends any message | Message object | | suggestion-selected | Triggered when a suggestion is clicked | Suggestion text | | new-message | Triggered when any message is added to the chat | Message object | | history-updated | Triggered when the message history changes | Array of message objects | | file-uploaded | Triggered when a file is uploaded | File message object | | image-captured | Triggered when an image is uploaded or captured | Image message object | | math-sent | Triggered when a math formula is sent | Math message object |

Loading State

The ChatUI component includes a loading state feature that shows a spinner and disables user input while processing:

  1. Setting Loading State

    • Set the loading prop to true to enable loading mode
    • A spinning indicator appears under the last message
    • The send button becomes disabled to prevent new messages
  2. Example Usage

    <template>
      <ChatUI :loading="isLoading" @message-sent="handleMessage" />
    </template>
    
    <script setup>
    import { ref } from 'vue';
       
    const isLoading = ref(false);
       
    const handleMessage = async (message) => {
      // Show loading while processing
      isLoading.value = true;
         
      try {
        // Make API call to your backend/AI service
        const response = await fetch('/api/chat', {
          method: 'POST',
          body: JSON.stringify({ message: message.text })
        });
        const data = await response.json();
           
        // Add AI response to chat
        chatUI.value.addMessage({
          type: 'text',
          text: data.response,
          sender: { id: 2, name: 'Assistant' }
        });
      } finally {
        // Always hide loading when done
        isLoading.value = false;
      }
    };
    </script>
  3. Loading Behavior

    • Loading spinner appears centered under the last message
    • Send button becomes disabled and unclickable
    • User cannot send new messages while loading is active
    • Loading state persists until manually set to false
  4. Visual Design

    • Clean 20px circular spinner with subtle animation
    • Uses primary color (#409eff) for the spinning border
    • Transparent background to not obstruct chat content
    • Positioned to not interfere with chat flow

Message Types

The chat UI supports different types of messages:

  1. Text Messages

    • Standard text-based messages
    • Can be marked as confidential for user messages
    • Support for automatic sensitive information detection
    • Support for inline LaTeX formulas using $...$ syntax
    • Support for display mode LaTeX formulas using $$...$$ syntax
    • Copy button to easily copy message text
  2. Math Messages

    • Dedicated type for mathematical formulas
    • Rendered using KaTeX for beautiful math formatting
    • Automatically detected when a message is wrapped in $...$ or $$...$$
    • Can be created programmatically using addMathMessage()
  3. Code Messages

    • Display code with syntax highlighting
    • Support for line numbers
    • Automatically detects the code language or can be specified
    • Copy button for easy code copying
    • Grey background for improved readability regardless of message type
  4. Image Messages

    • Display images inline with optional captions
    • Support for uploading images from device
    • Camera integration for capturing photos directly
    • Click to open a full-screen preview
    • Copy button to copy image captions
  5. File Messages

    • Display file information with name and size
    • Download button for retrieving the file
    • Copy button to copy file name
    • Support for any file type

LaTeX Math Support

The chat UI includes support for mathematical formulas using LaTeX syntax:

  1. Inline Formulas

    • Wrap expressions in single dollar signs: $E = mc^2$
    • Rendered inline with the text
  2. Display Mode Formulas

    • Wrap expressions in double dollar signs: $$\int_{a}^{b} x^2 dx$$
    • Rendered in display mode (centered, larger)
  3. Dedicated Math Messages

    • When a message consists only of a LaTeX formula (wrapped in $ or $$), it's automatically converted to a dedicated math message type
    • Math messages are optimized for formula display
  4. Formula Detection

    • The UI automatically detects LaTeX formulas in text messages
    • You can check if a message contains LaTeX with the hasLatex property
  5. Programmatic Math Messages

    • Create math messages programmatically:
      chatUI.value.addMathMessage('E = mc^2', sender);

File and Image Upload

Users can upload files and images through:

  1. File Upload Button

    • Click the attachment icon to open options
    • Select "Image" to upload an image file
    • Select "File" to upload any other file type
    • Add an optional caption before sending
  2. Camera Capture

    • Click the attachment icon and select "Camera"
    • Take a photo using the device's camera
    • Review the photo before sending
    • Add an optional caption

Confidential Messages

The chat UI supports masking confidential messages that may contain sensitive information:

  1. User Messages Only: Confidential masking is only applied to messages from the user, not from the assistant
  2. Automatic Detection: User messages containing words like "password", "token", "secret", etc. are automatically masked
  3. Manual Toggle: Click the lock icon in the message input to manually mark the next user message as confidential
  4. Show/Hide Controls: Confidential messages include a "Show" button that reveals the actual content when clicked
  5. Customizable Keywords: Provide your own list of confidential words to detect via the confidential-words prop
  6. Unmasked Access: Parent applications can access the unmasked content through the history events or getMessageHistory() method

This feature is useful for collecting sensitive information like passwords, account numbers, or personal details while ensuring that:

  • Users can verify the content they've entered by clicking "Show"
  • User messages with sensitive information are protected from shoulder surfing by default
  • The parent application still has access to the unmasked content
  • Assistant messages are always displayed in full, regardless of their content

Customization

You can customize the chat UI by:

  • Modifying the styles in each component's <style> section
  • Overriding CSS variables
  • Extending components with your own implementation
  • Providing custom confidential words for automatic detection

Technologies Used

  • Vue.js 3
  • Composition API with <script setup>
  • KaTeX for LaTeX math rendering
  • CSS custom properties for styling

Code Block Support

The chat UI includes support for code blocks with syntax highlighting:

  1. Creating Code Messages

    • Create a message with type: 'code'
    • Provide the code in the text property
    • Optionally specify the language in the language property
  2. Syntax Highlighting

    • Code is automatically highlighted based on the specified language
    • If no language is specified, automatic language detection is attempted
    • Powered by highlight.js with support for most programming languages
  3. Line Numbers

    • Code blocks display line numbers for better readability
    • Numbers are properly aligned with code lines
  4. Copy Functionality

    • Each code block includes a copy button
    • Click to copy the entire code snippet to clipboard
    • Visual feedback when code is copied
  5. Example Usage

    chatUI.value.addMessage({
      type: 'code',
      text: 'function hello() {\n  console.log("Hello world!");\n}',
      language: 'javascript',
      sender: {
        id: 2,
        name: 'Assistant'
      },
      timestamp: new Date()
    });

Copy Functionality

Each message type includes a convenient copy button:

  1. Text Messages

    • Copy button appears on hover
    • Copies the entire message text to clipboard
  2. Code Messages

    • Copy button for the entire code block
    • Positioned in the top-right corner of the code block
  3. Image Messages

    • Copy button for the image caption
    • Appears on hover over the image container
  4. File Messages

    • Copy button for the file name
    • Positioned next to the download button
  5. Visual Feedback

    • "Copied!" tooltip appears when content is copied
    • Subtle animations provide user feedback