npm package: @smarteremr/chat-widget
Description: A chat widget for SmarterEMR client applications.
Author: Rishabh Kumrawat
Latest version: 1.1.43

# @smarteremr/chat-widget

A comprehensive React-based chat widget component for SmarterEMR client applications with real-time messaging capabilities powered by Azure Communication Services (ACS).

## 🚀 Features

- 💬 **Real-time messaging** - Powered by Azure Communication Services
- 🎨 **Customizable theming** - Full control over colors and styling
- 📱 **Responsive design** - Works seamlessly on desktop and mobile
- ⚡ **TypeScript support** - Full type definitions included
- 🔒 **Error boundaries** - Graceful error handling and recovery
- ♿ **Accessibility** - WCAG compliant components
- 🎯 **Redux integration** - Built-in state management
- 🔧 **Configurable menu** - Customizable dropdown menu options
- 📊 **Message history** - Load and display conversation history
- 🛡️ **Input validation** - Built-in XSS protection and validation

## 📦 Installation

```bash
npm install @smarteremr/chat-widget
```

### Peer Dependencies

Ensure you have the required peer dependencies installed:

```bash
npm install react@>=16.8.0 react-dom@>=16.8.0
```

## 🎯 Quick Start

### Basic Implementation

```tsx
import React from 'react';
import { ChatWidget } from '@smarteremr/chat-widget';
import '@smarteremr/chat-widget/lib/styles.css';

function App() {
  const initParams = {
    baseUrl: 'https://your-api-endpoint.com',
    apiKey: 'your-api-key',
    userInfo: {
      userEmail: 'user@example.com',
      firstName: 'John',
      lastName: 'Doe'
    },
    metaData: {
      orderNumber: 'ORD-12345'
    }
  };

  const menuItems = [
    {
      id: 'help',
      label: 'Help Center',
      onClick: () => window.open('/help', '_blank')
    },
    {
      id: 'feedback',
      label: 'Send Feedback',
      onClick: () => console.log('Feedback clicked')
    }
  ];

  return (
    <div className="app">
      <ChatWidget
        initParams={initParams}
        primaryColor="#007bff"
        secondaryColor="#6c757d"
        menuItems={menuItems}
        showMenu={true}
      />
    </div>
  );
}

export default App;
```

### With Custom Redux Store

```tsx
import React from 'react';
import { Provider } from 'react-redux';
import { ChatWidget } from '@smarteremr/chat-widget';
import { store } from './store';

function App() {
  return (
    <Provider store={store}>
      <ChatWidget
        initParams={initParams}
        primaryColor="#007bff"
        secondaryColor="#6c757d"
        menuItems={[]}
        showMenu={false}
      />
    </Provider>
  );
}
```

## 📚 API Reference

### ChatWidget Props

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `initParams` | `InitiateChatRequest` | ✅ | API configuration and user information |
| `primaryColor` | `string` | ✅ | Primary theme color (hex format) |
| `secondaryColor` | `string` | ✅ | Secondary theme color (hex format) |
| `menuItems` | `MenuItemConfig[]` | ✅ | Dropdown menu configuration |
| `showMenu` | `boolean` | ✅ | Whether to show the dropdown menu |

### InitiateChatRequest Interface

```tsx
interface InitiateChatRequest {
  baseUrl: string;           // Your backend API base URL
  apiKey: string;            // API authentication key
  userInfo: {
    userEmail: string;       // User's email address
    firstName: string;       // User's first name
    lastName: string;        // User's last name
  };
  metaData: {
    orderNumber?: string;    // Optional order/reference number
  };
}
```

### MenuItemConfig Interface

```tsx
interface MenuItemConfig {
  id: string;                // Unique identifier
  label: string;             // Display text
  onClick: () => void;       // Click handler function
  icon?: string;             // Optional icon class/name
  disabled?: boolean;        // Whether item is disabled
}
```

## 🎨 Theming & Customization

### CSS Custom Properties

The widget uses CSS custom properties for theming. You can override these in your CSS:

```css
:root {
  --chat-primary-color: #007bff;
  --chat-primary-hover: #0056b3;
  --chat-background-color: #ffffff;
  --chat-text-color: #333333;
  --chat-border-color: #e0e0e0;
  --chat-shadow-color: rgba(0, 0, 0, 0.1);
  --chat-user-message-bg: #007bff;
  --chat-agent-message-bg: #e9ecef;
  --chat-input-bg: #ffffff;
  --chat-header-bg: #007bff;
}
```

### Using StyleManager

```tsx
import { StyleManager, applyDefaultTheme } from '@smarteremr/chat-widget';

// Apply default theme
applyDefaultTheme();

// Or customize individual properties
const styleManager = StyleManager.getInstance();
styleManager.setProperty('primary-color', '#ff6b6b');
styleManager.setProperty('background-color', '#f8f9fa');

// Set multiple properties at once
styleManager.setTheme({
  'primary-color': '#28a745',
  'user-message-bg': '#28a745',
  'header-bg': '#28a745'
});
```

## 🔧 Advanced Usage

### Using Hooks

```tsx
import { useChatInit } from '@smarteremr/chat-widget';

function CustomChatComponent() {
  const {
    isInitializing,
    isInitialized,
    error,
    initializeChat,
    sendMessage,
    loadMessages
  } = useChatInit();

  const handleSendMessage = async (message: string) => {
    const result = await sendMessage(message);
    if (!result.success) {
      console.error('Failed to send message:', result.error);
    }
  };

  return (
    <div>
      {isInitializing && <div>Initializing chat...</div>}
      {error && <div>Error: {error}</div>}
      {/* Your custom UI */}
    </div>
  );
}
```

### Redux Store Integration

```tsx
import { 
  store, 
  useAppDispatch, 
  useAppSelector,
  selectMessages,
  addNewMessage 
} from '@smarteremr/chat-widget';

function MessageDisplay() {
  const messages = useAppSelector(selectMessages);
  const dispatch = useAppDispatch();

  const handleAddMessage = () => {
    dispatch(addNewMessage({
      id: Date.now().toString(),
      content: 'New message',
      senderDisplayName: 'User',
      senderACSId: 'user-123',
      version: 1,
      createdOn: new Date().toISOString(),
      updatedOn: new Date().toISOString()
    }));
  };

  return (
    <div>
      {messages.map(message => (
        <div key={message.id}>{message.content}</div>
      ))}
    </div>
  );
}
```

## 🛠️ Utilities

### Date Utilities

```tsx
import { formatTime, formatDate, getRelativeTime } from '@smarteremr/chat-widget';

const now = new Date();
console.log(formatTime(now));        // "2:30 PM"
console.log(formatDate(now));        // "12/25/2023"
console.log(getRelativeTime(now));   // "Just now"
```

### Validation Utilities

```tsx
import { 
  validateMessage, 
  validateEmail, 
  sanitizeInput,
  isValidUUID 
} from '@smarteremr/chat-widget';

console.log(validateMessage('Hello'));                    // true
console.log(validateEmail('user@example.com'));          // true
console.log(sanitizeInput('<script>alert("xss")</script>')); // Safe HTML
console.log(isValidUUID('123e4567-e89b-12d3-a456-426614174000')); // true
```

## 📁 Project Structure

```
@smarteremr-chat-widget/
├── src/
│   ├── components/          # React components
│   │   ├── ChatWidget/      # Main widget component
│   │   ├── ChatContainer/   # Message container
│   │   ├── ChatHeader/      # Header with controls
│   │   ├── MessageList/     # Message display
│   │   ├── MessageInput/    # Input component
│   │   ├── MessageBubble/   # Individual message
│   │   ├── LoadingIndicator/# Loading states
│   │   ├── ErrorBoundary/   # Error handling
│   │   ├── ErrorDisplay/    # Error UI
│   │   ├── DropdownMenu/    # Menu component
│   │   ├── MenuButton/      # Menu button
│   │   ├── MenuItem/        # Menu items
│   │   └── StatusIndicator/ # Status display
│   ├── config/              # Configuration
│   │   ├── api.ts          # API interfaces
│   │   └── constants.ts    # Constants
│   ├── hooks/              # Custom hooks
│   │   ├── useChatInit.ts  # Chat initialization
│   │   └── index.ts        # Hook exports
│   ├── services/           # Business logic
│   │   ├── chatService.ts  # Main chat service
│   │   ├── acs/            # Azure Communication Services
│   │   └── api/            # API services
│   ├── store/              # Redux store
│   │   ├── store.ts        # Store configuration
│   │   └── slices/         # Redux slices
│   ├── styles/             # SCSS styles
│   │   ├── global.scss     # Global styles
│   │   ├── reset.scss      # CSS reset
│   │   └── components/     # Component styles
│   ├── types/              # TypeScript types
│   ├── utils/              # Utility functions
│   │   ├── dateUtils.ts    # Date formatting
│   │   ├── validation.ts   # Input validation
│   │   └── styleManager.ts # Theme management
│   └── index.ts            # Main export
├── lib/                    # Compiled output
├── tests/                  # Test files
├── package.json           # Package configuration
├── tsconfig.json          # TypeScript config
├── rollup.config.cjs      # Build configuration
└── README.md              # This file
```

## 🧪 Testing

```bash
# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Run linting
npm run lint
```

## 🏗️ Development

```bash
# Install dependencies
npm install

# Build the package
npm run build

# Build in watch mode
npm run build:watch

# Clean build artifacts
npm run clean
```

## 📋 Requirements

- **Node.js**: >= 16.0.0
- **npm**: >= 8.0.0
- **React**: >= 16.8.0
- **React DOM**: >= 16.8.0

## 🌐 Browser Support

- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- Mobile browsers (iOS Safari, Chrome Mobile)

## 🔒 Security

The widget includes built-in security features:

- **XSS Protection**: All user inputs are sanitized
- **Input Validation**: Message length and format validation
- **Error Boundaries**: Prevents crashes from propagating
- **Secure API Communication**: Uses API keys for authentication

## 🚨 Error Handling

The widget provides comprehensive error handling:

```tsx
// Error boundary catches component errors
<ErrorBoundary 
  onError={(error, errorInfo) => {
    console.error('Chat widget error:', error, errorInfo);
  }}
  fallback={<CustomErrorComponent />}
>
  <ChatWidget {...props} />
</ErrorBoundary>
```

## 📈 Performance

- **Code Splitting**: Components are lazy-loaded where possible
- **Memoization**: React.memo used for expensive components
- **Efficient Rendering**: Redux selectors prevent unnecessary re-renders
- **Bundle Size**: Optimized build with tree-shaking

## 🤝 Contributing

1. Fork the repository
2. Create a feature branch: `git checkout -b feature/new-feature`
3. Make your changes and add tests
4. Run tests: `npm test`
5. Commit your changes: `git commit -am 'Add new feature'`
6. Push to the branch: `git push origin feature/new-feature`
7. Submit a pull request

## 📄 License

MIT License - see [LICENSE](LICENSE) file for details.

## 👥 Author

**SmarterEMR Dev Team**

## 🆘 Support

For support and questions:

1. Check the [documentation](#-api-reference)
2. Search existing [issues](https://github.com/your-repo/issues)
3. Create a new issue with detailed information
4. Contact the development team

## 📝 Changelog

### v1.1.21
- Current stable release
- Full TypeScript support
- Azure Communication Services integration
- Comprehensive theming system
- Error boundary implementation
- Mobile responsiveness improvements

---

**Made with ❤️ for SmarterEMR**