2.48.0 • Published 6 months ago

@memberjunction/ng-chat v2.48.0

Weekly downloads
-
License
ISC
Repository
-
Last release
6 months ago

@memberjunction/ng-chat

A reusable Angular component library for building chat interfaces in MemberJunction applications. This package provides a flexible chat component that can be used for AI-assisted conversations, chatbots, or peer-to-peer chat applications.

Overview

The @memberjunction/ng-chat package provides a feature-rich chat component with built-in support for:

  • User and AI message rendering with distinct styling
  • Markdown formatting in messages
  • Welcome screen with suggested prompts
  • Real-time message handling
  • Responsive design with auto-scrolling
  • Loading indicators for async operations

Features

  • Flexible Message System: Display both user and AI messages with appropriate styling and avatars
  • Markdown Support: Full markdown rendering support for rich text messages
  • Welcome Screen: Customizable welcome screen with up to 4 suggested questions/prompts
  • Smart Scrolling: Automatic scroll-to-bottom with manual scroll detection
  • Loading States: Built-in loading indicator for async operations (e.g., AI responses)
  • Responsive Design: Mobile-friendly design that adapts to different screen sizes
  • Auto-Resizing Input: Text area automatically expands as users type longer messages
  • Clear Conversation: Confirmation dialog for clearing conversation history
  • Customizable Avatars: Support for custom AI avatar images
  • Keyboard Support: Send messages with Enter key (Shift+Enter for new lines)

Installation

npm install @memberjunction/ng-chat

Peer Dependencies

This package requires the following peer dependencies:

  • @angular/common: ^18.0.2
  • @angular/core: ^18.0.2
  • @angular/forms: ^18.0.2

Usage

Import the Module

import { ChatModule } from '@memberjunction/ng-chat';

@NgModule({
  imports: [
    ChatModule,
    // other imports
  ],
  // ...
})
export class YourModule { }

Basic Component Usage

<mj-chat
  [AIImageURL]="'assets/bot-avatar.png'"
  [InitialMessage]="'How can I help you today?'"
  (MessageAdded)="handleNewMessage($event)"
  (ClearChatRequested)="handleClearChat()">
</mj-chat>

Complete Example with AI Integration

import { Component, ViewChild } from '@angular/core';
import { ChatComponent, ChatMessage, ChatWelcomeQuestion } from '@memberjunction/ng-chat';

@Component({
  selector: 'app-ai-assistant',
  template: `
    <mj-chat
      #chatComponent
      [AIImageURL]="'assets/bot-avatar.png'"
      [AILargeImageURL]="'assets/bot-large.png'"
      [InitialMessage]="'Hi! I'm your AI assistant. How can I help you today?'"
      [WelcomeQuestions]="welcomeQuestions"
      [Placeholder]="'Ask me anything...'"
      [ClearAllMessagesPrompt]="'Are you sure you want to clear this conversation?'"
      (MessageAdded)="handleNewMessage($event)"
      (ClearChatRequested)="handleClearChat()">
    </mj-chat>
  `
})
export class AIAssistantComponent {
  @ViewChild('chatComponent') chatComponent!: ChatComponent;
  
  welcomeQuestions: ChatWelcomeQuestion[] = [
    {
      topLine: 'Generate a report',
      bottomLine: 'Create a sales summary for Q2',
      prompt: 'Generate a sales report for Q2'
    },
    {
      topLine: 'Find information',
      bottomLine: 'Search for customer details',
      prompt: 'Find information about customer XYZ'
    },
    {
      topLine: 'Summarize data',
      bottomLine: 'Give me the key points from the data',
      prompt: 'Summarize the key metrics from my dashboard'
    },
    {
      topLine: 'Help with a task',
      bottomLine: 'Walk me through creating a new entity',
      prompt: 'Help me create a new entity in MemberJunction'
    }
  ];

  handleNewMessage(message: ChatMessage) {
    // Process the new message
    console.log('New message:', message);
    
    if (message.senderType === 'user') {
      // Send to AI service and handle response
      this.processUserMessage(message.message);
    }
  }

  handleClearChat() {
    // Clear any conversation state in your service
    this.conversationHistory = [];
    this.chatComponent.ClearAllMessages();
  }

  async processUserMessage(message: string) {
    // Set loading state
    this.chatComponent.ShowWaitingIndicator = true;
    
    try {
      // Call your AI or chat service
      const response = await this.aiService.getResponse(message);
      
      // Add AI response to chat
      this.chatComponent.SendMessage(
        response, 
        'Assistant', 
        'ai', 
        null
      );
    } 
    catch (error) {
      console.error('Error getting AI response:', error);
      // Show error message to user
      this.chatComponent.SendMessage(
        'Sorry, I encountered an error processing your request.', 
        'Assistant', 
        'ai', 
        null
      );
    } 
    finally {
      // End loading state
      this.chatComponent.ShowWaitingIndicator = false;
    }
  }
}

Programmatic Message Sending

// Send a user message programmatically
this.chatComponent.SendUserMessage('Hello, AI!');

// Send an AI message
this.chatComponent.SendMessage(
  'Hello! How can I assist you today?',
  'Assistant',
  'ai',
  messageId // optional ID for tracking
);

// Send a message without triggering the MessageAdded event
this.chatComponent.SendMessage(
  'System message',
  'System',
  'ai',
  null,
  false // fireEvent = false
);

API Reference

Component Selector

<mj-chat></mj-chat>

Inputs

PropertyTypeDefaultDescription
InitialMessagestring''Initial message shown when chat is empty
MessagesChatMessage[][]Array of messages to display
AIImageURLstring''URL for the AI's avatar image (24px max width)
AILargeImageURLstring''URL for the AI's large avatar on welcome screen
WelcomeQuestionsChatWelcomeQuestion[][]Array of up to 4 welcome prompts
ClearAllMessagesPromptstring'Are you sure you want to clear all messages?'Confirmation dialog text
AllowSendbooleantrueEnable/disable message sending
Placeholderstring'Type a message...'Input field placeholder text
ShowWaitingIndicatorbooleanfalseShow/hide loading spinner

Outputs

EventTypeDescription
MessageAddedEventEmitter<ChatMessage>Emitted when a new message is added to the chat
ClearChatRequestedEventEmitter<void>Emitted when user confirms clearing the chat

Public Methods

SendCurrentMessage(): void

Sends the current message in the input field. Automatically clears the input after sending.

SendMessage(message: string, senderName: string, senderType: 'user' | 'ai', id: any, fireEvent: boolean = true): void

Adds a message to the chat programmatically.

Parameters:

  • message: The message text (supports markdown)
  • senderName: Display name of the sender
  • senderType: Either 'user' or 'ai' for styling
  • id: Optional ID for message tracking
  • fireEvent: Whether to emit the MessageAdded event

SendUserMessage(message: string): void

Convenience method to send a user message. Automatically sets senderName to 'User' and senderType to 'user'.

ClearAllMessages(): void

Clears all messages from the chat and resets to initial state.

HandleClearChat(): void

Shows the confirmation dialog for clearing chat. This emits the ClearChatRequested event when confirmed.

Classes

ChatMessage

export class ChatMessage {
  public message: string;         // The message content (supports markdown)
  public senderName: string;      // Display name of sender
  public senderType: 'user' | 'ai'; // Type for styling purposes
  public id?: any;                // Optional ID for tracking

  constructor(
    message: string, 
    senderName: string, 
    senderType: 'user' | 'ai', 
    id: any = null
  );
}

ChatWelcomeQuestion

export class ChatWelcomeQuestion {
  public topLine: string = "";     // Main text of the suggestion
  public bottomLine: string = "";  // Supporting text/description
  public prompt: string = "";      // The actual prompt to send when clicked
}

Styling

The component provides several CSS classes for customization:

  • .chat-message-wrap: Container for each message
  • .chat-message: The message content container
  • .chat-message-ai: Additional class for AI messages
  • .chat-message-image: Avatar/icon container
  • .chat-input-container: Input area container
  • .chat-welcome-container: Welcome screen container

You can override these styles in your global styles or component styles:

/* Example: Customize AI message background */
::ng-deep .chat-message-ai {
  background-color: #f0f4f8;
  border-left: 3px solid #3182ce;
}

/* Example: Customize user avatar */
::ng-deep .chat-message-wrap:has(.chat-message:not(.chat-message-ai)) .chat-message-image {
  color: #48bb78;
}

Dependencies

Runtime Dependencies

  • @memberjunction/core: Core MemberJunction utilities
  • @memberjunction/ng-container-directives: Container directive utilities
  • @progress/kendo-angular-indicators: Loading spinner component
  • @progress/kendo-angular-buttons: Button components
  • @progress/kendo-angular-dialog: Dialog component for confirmations
  • ngx-markdown: Markdown rendering support
  • tslib: TypeScript runtime helpers

Integration with MemberJunction

This component integrates seamlessly with other MemberJunction packages:

  • Use with @memberjunction/ai for AI-powered conversations
  • Combine with @memberjunction/core-entities for entity-aware chat
  • Integrate with MemberJunction's authentication for user context

Build and Development

This package uses Angular's library build system. To build the package:

# From the package directory
npm run build

# From the repository root
turbo build --filter="@memberjunction/ng-chat"

The built files will be output to the dist/ directory.

Advanced Usage

Custom Message Rendering

While the component handles markdown rendering by default, you can extend functionality by processing messages before sending:

// Pre-process messages with custom formatting
const formattedMessage = this.formatMessage(userInput);
this.chatComponent.SendUserMessage(formattedMessage);

// Add metadata to messages using the id field
this.chatComponent.SendMessage(
  response,
  'Assistant',
  'ai',
  { timestamp: Date.now(), tokens: 150, model: 'gpt-4' }
);

Maintaining Conversation History

// Store conversation for persistence
private saveConversation() {
  const messages = this.chatComponent.Messages;
  localStorage.setItem('chat-history', JSON.stringify(messages));
}

// Restore previous conversation
private loadConversation() {
  const saved = localStorage.getItem('chat-history');
  if (saved) {
    const messages = JSON.parse(saved) as ChatMessage[];
    messages.forEach(msg => {
      this.chatComponent.SendMessage(
        msg.message,
        msg.senderName,
        msg.senderType,
        msg.id,
        false // Don't fire events when restoring
      );
    });
  }
}

Notes

  • The component automatically focuses the input field after operations
  • Messages support full markdown syntax including code blocks, lists, and links
  • The welcome screen is only shown when there are no messages
  • Default icons use Font Awesome (fa-robot for AI, fa-user for users)
  • The component uses Angular's ChangeDetectorRef for optimal performance
2.27.1

10 months ago

2.23.2

10 months ago

2.46.0

6 months ago

2.23.1

10 months ago

2.27.0

10 months ago

2.34.0

8 months ago

2.30.0

9 months ago

2.19.4

11 months ago

2.19.5

11 months ago

2.19.2

11 months ago

2.19.3

11 months ago

2.19.0

11 months ago

2.19.1

11 months ago

2.15.2

11 months ago

2.34.2

8 months ago

2.34.1

8 months ago

2.15.1

11 months ago

2.38.0

7 months ago

2.45.0

7 months ago

2.22.1

10 months ago

2.22.0

10 months ago

2.41.0

7 months ago

2.22.2

10 months ago

2.26.1

10 months ago

2.26.0

10 months ago

2.33.0

8 months ago

2.18.3

11 months ago

2.18.1

11 months ago

2.18.2

11 months ago

2.18.0

11 months ago

2.37.1

7 months ago

2.37.0

7 months ago

2.14.0

11 months ago

2.21.0

11 months ago

2.44.0

7 months ago

2.40.0

7 months ago

2.29.0

9 months ago

2.29.2

9 months ago

2.29.1

9 months ago

2.25.0

10 months ago

2.48.0

6 months ago

2.32.0

9 months ago

2.32.2

9 months ago

2.32.1

9 months ago

2.17.0

11 months ago

2.13.4

12 months ago

2.36.0

8 months ago

2.13.2

1 year ago

2.13.3

12 months ago

2.13.0

1 year ago

2.36.1

8 months ago

2.13.1

1 year ago

2.43.0

7 months ago

2.20.2

11 months ago

2.20.3

11 months ago

2.20.0

11 months ago

2.20.1

11 months ago

2.28.0

10 months ago

2.47.0

6 months ago

2.24.1

10 months ago

2.24.0

10 months ago

2.31.0

9 months ago

2.12.0

1 year ago

2.39.0

7 months ago

2.16.1

11 months ago

2.35.1

8 months ago

2.35.0

8 months ago

2.16.0

11 months ago

2.42.1

7 months ago

2.42.0

7 months ago

2.23.0

10 months ago

2.11.0

1 year ago

2.10.0

1 year ago

2.9.0

1 year ago

2.8.0

1 year ago

2.7.0

1 year ago

2.6.1

1 year ago

2.5.2

1 year ago

2.6.0

1 year ago

2.7.1

1 year ago

1.8.1

1 year ago

1.8.0

1 year ago

1.7.1

2 years ago

1.5.3

2 years ago

1.7.0

2 years ago

1.6.1

2 years ago

1.5.2

2 years ago

1.6.0

2 years ago

1.5.1

2 years ago

1.3.3

2 years ago

1.5.0

2 years ago

1.4.1

2 years ago

1.3.2

2 years ago

1.4.0

2 years ago

1.3.1

2 years ago

1.3.0

2 years ago

2.3.0

1 year ago

2.2.1

1 year ago

2.1.2

1 year ago

2.2.0

1 year ago

2.1.1

1 year ago

2.5.0

1 year ago

2.4.1

1 year ago

2.3.2

1 year ago

2.1.4

1 year ago

2.4.0

1 year ago

2.3.1

1 year ago

2.1.3

1 year ago

2.5.1

1 year ago

2.3.3

1 year ago

2.1.5

1 year ago

2.0.0

1 year ago

1.2.2

2 years ago

1.2.1

2 years ago

1.2.0

2 years ago

1.1.0

2 years ago