JSPM

  • Created
  • Published
  • Downloads 189
  • Score
    100M100P100Q96954F
  • License MIT

Embeddable healthcare chatbot widget for websites and mobile apps

Package Exports

  • @mypatientspace/chatbot-widget
  • @mypatientspace/chatbot-widget/dist/mypatientspace-widget.es.js
  • @mypatientspace/chatbot-widget/dist/mypatientspace-widget.umd.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@mypatientspace/chatbot-widget) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

MPS Chatbot Widget

A standalone chatbot widget that third-party websites can embed via a single <script> tag.

npm version

Features

  • Self-contained React application bundled into a single JS file
  • Easy integration with any website
  • Embedded mode (default) or floating button mode
  • Customizable theming with light, dark, and system color modes
  • Style isolation (won't conflict with host site CSS)
  • Native mobile support via WebView
  • Voice input support
  • Quick action buttons
  • Survey/questionnaire support
  • Content citations with overlay view

Tech Stack

  • React 19 with TypeScript
  • Vite (library mode build)
  • Emotion (CSS-in-JS for style isolation)
  • lucide-react (icons)

Compatibility

Via CDN/Script Tag (Any Project)

When using the UMD bundle via <script> tag, the widget bundles its own React and renders in an isolated container. Your project's React version doesn't matter — this works with any framework (or no framework at all), including:

  • Vanilla JavaScript/HTML
  • jQuery
  • Angular, Vue, Svelte
  • Older React versions (14, 15, 16, etc.)

Via npm Import (React 18+ Required)

When importing as an ES module in a React project:

import '@mypatientspace/chatbot-widget';

You need React 18 or higher. The widget uses modern React features (hooks, Context API) that aren't available in older versions.

Integration Method React Version Required
CDN / Script tag Any (bundles own React)
npm import React 18+

Installation

unpkg:

<script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>

jsDelivr:

<script src="https://cdn.jsdelivr.net/npm/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>

Via npm

npm install @mypatientspace/chatbot-widget

Development

# Install dependencies
yarn install

# Start dev server (includes demo UI)
yarn dev

# Build for production
yarn build              # Builds both widget and demo
yarn build:widget       # Widget only
yarn build:demo         # Demo only

# Preview production build
yarn preview

Web Integration

Minimal Setup

<script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
<script>
  ChatbotWidget.init({
    apiEndpoint: 'https://your-api.com',
    token: 'your-auth-token'
  });
</script>

Full Customization

<script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
<script>
  ChatbotWidget.init({
    // API & Auth
    apiEndpoint: 'https://your-api.com',
    token: 'your-auth-token',
    userType: 'patient',             // 'patient' (default) or 'staff'
    assistantId: 'your-assistant-id',

    // Display mode
    floatingMode: true,          // false = embedded (default), true = FAB button
    position: 'bottom-left',     // FAB position (default: 'bottom-right')
    hideExpandButton: true,      // Hide expand/minimize button from header
    showCloseSlot: true,         // Empty placeholder for custom close button

    // Content
    headerTitle: 'Health Support',
    headerSubtitle: 'Online now',
    greeting: 'Hi! How can I help?',
    placeholder: 'Ask me anything...',
    brandingText: 'Powered by MyCompany',
    disclaimerText: 'AI can make mistakes. Verify important information.',
    headerIcon: '/logo.png',
    fabIcon: '/avatar.png',       // Only used in floating mode
    quickActions: ['I need help', 'Book appointment'],

    // Appearance
    colorMode: 'system',  // 'light', 'dark', or 'system' (auto-detect)
    theme: {
      colors: {
        primary: '#ff6600',        // FAB button, links, main accent
        primaryDark: '#cc5200',    // Hover states
        secondary: '#2d3748',      // Header background
        headerText: '#ffffff',     // Header text color
        background: '#ffffff',     // Chat window background
        surface: '#f7fafc',        // Input/card backgrounds
        text: '#2d3748',           // Primary text
        textLight: '#718096',      // Secondary text, timestamps
        userBubble: '#ff6600',     // User message background
        userBubbleText: '#ffffff', // User message text
        botBubble: '#edf2f7',      // Bot message background
        botBubbleText: '#2d3748',  // Bot message text
      },
      fontFamily: 'Inter, system-ui, sans-serif',
      borderRadius: '8px',
      shadow: '0 4px 12px rgba(0, 0, 0, 0.1)',
    },

    // Callbacks
    onOpen: () => console.log('Chat opened'),
    onClose: () => console.log('Chat closed'),
    onMessageSent: (message) => console.log('Sent:', message),
    onMessageReceived: (message) => console.log('Received:', message),
    onQuickAction: (action) => console.log('Quick action:', action),
    onStreamChunk: (chunk) => console.log('Chunk:', chunk),
    onCitationClick: (citation) => console.log('Citation:', citation),
    onNewChat: () => console.log('New chat started'),
    onWidgetReady: (api) => console.log('Widget ready:', api),
  });
</script>

Via npm import

import '@mypatientspace/chatbot-widget';

ChatbotWidget.init({
  apiEndpoint: 'https://your-api.com'
});

Patient & Staff Integration

The widget supports two user types with separate API routing. Each type uses different backend endpoints for chat, message history, and assistant lookup.

Patient (Default)

Patient mode is the default — no userType needed:

<script>
  ChatbotWidget.init({
    apiEndpoint: 'https://your-api.com',
    token: 'your-auth-token'
  });
</script>

API endpoints used:

  • POST /api/patient/chat/stream — Send messages
  • GET /api/patient/chat/messages — Load history
  • GET /api/patient/assistant — Get assistant config

Staff

Staff mode requires userType: 'staff' along with contextPatientId and patientTypeId:

<script>
  ChatbotWidget.init({
    apiEndpoint: 'https://your-api.com',
    token: 'your-auth-token',
    userType: 'staff',
    contextPatientId: 'patient-123',
    patientTypeId: 'type-456'
  });
</script>

API endpoints used:

  • POST /api/staff/chat/stream — Send messages (includes contextPatientId in body)
  • GET /api/staff/chat/messages — Load history (requires contextPatientId query param)
  • GET /api/staff/assistant/{patientTypeId} — Get assistant config

Required Fields by User Type

Field Patient Staff
apiEndpoint Required Required
token Required Required
userType Optional (default) 'staff'
contextPatientId Optional Required
patientTypeId - Required

API Methods

ChatbotWidget.open();         // Open chat window
ChatbotWidget.close();        // Close chat window
ChatbotWidget.toggle();       // Toggle open/close
ChatbotWidget.startNewChat(); // Clear session and start new chat
ChatbotWidget.update(config); // Update widget configuration
ChatbotWidget.destroy();      // Remove widget completely

Embedded Mode

By default, the widget is embedded inside a container element. You can enable floating mode for a FAB button popup.

Using containerSelector

Embed the chat inside an existing element:

<div id="my-chat" style="width: 400px; height: 600px;"></div>

<script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
<script>
  ChatbotWidget.init({
    apiEndpoint: 'https://your-api.com',
    containerSelector: '#my-chat'
  });
</script>

Using floatingMode

Enable floating mode with FAB button (classic chatbot style):

<script>
  ChatbotWidget.init({
    apiEndpoint: 'https://your-api.com',
    floatingMode: true
  });
</script>

Comparison

Feature Embedded (default) floatingMode: true
FAB button Hidden Shown
Chat visibility Always open Opens on click
Position Fills container Fixed bottom-right/left
Sizing 100% of parent 380x520px

Mobile Integration

Android (Kotlin)

class ChatActivity : AppCompatActivity() {
    private lateinit var webView: WebView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        webView = WebView(this).apply {
            settings.javaScriptEnabled = true
            settings.domStorageEnabled = true
            loadDataWithBaseURL(
                "https://your-domain.com",
                """
                <!DOCTYPE html>
                <html>
                <head>
                    <meta name="viewport" content="width=device-width, initial-scale=1">
                </head>
                <body style="margin:0;padding:0;">
                    <script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
                    <script>
                        ChatbotWidget.init({
                            apiEndpoint: 'https://your-api.com'
                        });
                        ChatbotWidget.open();
                    </script>
                </body>
                </html>
                """.trimIndent(),
                "text/html", "UTF-8", null
            )
        }
        setContentView(webView)
    }
}

iOS (Swift)

import UIKit
import WebKit

class ChatViewController: UIViewController {
    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let config = WKWebViewConfiguration()
        config.preferences.javaScriptEnabled = true

        webView = WKWebView(frame: view.bounds, configuration: config)
        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(webView)

        let html = """
        <!DOCTYPE html>
        <html>
        <head>
            <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
            <style>body { margin: 0; padding: 0; }</style>
        </head>
        <body>
            <script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
            <script>
                ChatbotWidget.init({
                    apiEndpoint: 'https://your-api.com'
                });
                ChatbotWidget.open();
            </script>
        </body>
        </html>
        """

        webView.loadHTMLString(html, baseURL: URL(string: "https://your-domain.com"))
    }
}

iOS (Objective-C)

#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>

@interface ChatViewController : UIViewController
@property (nonatomic, strong) WKWebView *webView;
@end

@implementation ChatViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    config.preferences.javaScriptEnabled = YES;

    self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
    self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self.view addSubview:self.webView];

    NSString *html = @"<!DOCTYPE html>"
        "<html>"
        "<head>"
        "<meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1'>"
        "<style>body { margin: 0; padding: 0; }</style>"
        "</head>"
        "<body>"
        "<script src='https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js'></script>"
        "<script>"
        "ChatbotWidget.init({ apiEndpoint: 'https://your-api.com' });"
        "ChatbotWidget.open();"
        "</script>"
        "</body>"
        "</html>";

    [self.webView loadHTMLString:html baseURL:[NSURL URLWithString:@"https://your-domain.com"]];
}

@end

React Native

import { WebView } from 'react-native-webview';

const ChatScreen = () => {
  const html = `
    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body style="margin:0;padding:0;">
        <script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
        <script>
            ChatbotWidget.init({
                apiEndpoint: 'https://your-api.com'
            });
            ChatbotWidget.open();
        </script>
    </body>
    </html>
  `;

  return (
    <WebView
      source={{ html }}
      javaScriptEnabled={true}
      domStorageEnabled={true}
    />
  );
};

Configuration Reference

All Options

Option Type Default Description
apiEndpoint string - Base API URL, e.g. https://your-api.com (widget offline if not set)
token string - Auth token for API requests
userType 'patient' | 'staff' 'patient' User type for API endpoint routing
patientTypeId string - Patient type ID for staff assistant lookup (required when userType is 'staff')
sessionId string - Existing session ID to resume
assistantId string - Specific assistant ID to use
contextPatientId string - Patient context for the chat
loadHistory boolean true Load previous chat history
colorMode 'light' | 'dark' | 'system' 'light' Color mode for the widget
theme ThemeConfig - Custom theme colors, fonts, border radius, shadow
position 'bottom-right' | 'bottom-left' 'bottom-right' FAB button position
containerSelector string - CSS selector for embedded container
floatingMode boolean false Show FAB button and floating chat
hideExpandButton boolean false Hide the expand/minimize button from header
showCloseSlot boolean false Show empty circle placeholder for custom close button
greeting string From API Initial bot greeting message
placeholder string From API Input field placeholder text
headerTitle string From API Chat window header title
headerSubtitle string From API Chat window header subtitle
headerIcon string From API Header icon image URL
fabIcon string From API FAB button image URL
brandingText string From API Footer branding text
disclaimerText string From API Disclaimer text below input area
quickActions string[] From API Predefined quick action buttons

Note: Content fields (greeting, headerTitle, placeholder, brandingText, headerIcon, fabIcon, quickActions, disclaimerText) are loaded from the assistant's API configuration by default. Setting them in the widget config overrides the API values.

Callbacks

Callback Parameters Description
onOpen () Called when chat window opens
onClose () Called when chat window closes
onMessageSent (message: Message) Called after user sends a message
onMessageReceived (message: Message) Called after bot response completes
onQuickAction (action: string) Called when quick action is clicked
onStreamChunk (chunk: string) Called for each streamed response chunk
onCitationClick (citation: Citation) Called when a content card is clicked
onNewChat () Called when user starts a new chat
onWidgetReady (api: WidgetApi) Called when widget is ready with API methods

Available Theme Colors

Color Light Default Description
primary #00c2d1 FAB button, links, main accent
primaryDark #017992 Hover states
secondary #3c4d73 Header background
accent #33b1e6 Secondary accent color
accentLight #b8ebff Light accent
success #00dec4 Success states
info #30d7ed Info states
background #ffffff Chat window background
surface #fdfefe Input/card backgrounds
text #3c4d73 Primary text
textLight #6b7280 Secondary text, timestamps
userBubble #00c2d1 User message background
userBubbleText #ffffff User message text
botBubble #e0f7fa Bot message background
botBubbleText #3c4d73 Bot message text
border #d1d5db Border color
borderLight #e5e7eb Light border
error #ef4444 Error states
errorBackground #fef2f2 Error background
white #ffffff White color
recording #ef4444 Voice recording indicator
headerText #ffffff Header text and icon color
scrollbarThumb rgba(60, 77, 115, 0.2) Scrollbar thumb color
scrollbarThumbHover rgba(60, 77, 115, 0.3) Scrollbar thumb hover

Default Fallback Values

Content fields are resolved with this priority: Config > Assistant API > Component default

Field Component Fallback
headerTitle "AI Doctor"
greeting "Hello! Welcome to our healthcare support. How can I assist you today?"
placeholder "Type a message..."
brandingText "Developed by myPatientSpace"
disclaimerText "AI can make mistakes. Verify important information."
headerIcon MPS logo
fabIcon MPS logo
quickActions Empty (from API only)

License

MIT