chat-widget-universal
v1.2.0
Published
Widget de chat universel compatible avec React, Angular, Vue et Svelte
Maintainers
Readme
Chat Widget Universal
Un widget de chat moderne, fluide et responsive, compatible avec React, Angular, Vue, Svelte et tout framework JavaScript moderne. Construit avec TypeScript et TailwindCSS.
🚀 Installation
npm install chat-widget-universal📦 Structure du Package
chat-widget-universal/
├── dist/
│ ├── index.js # Build CommonJS
│ ├── index.esm.js # Build ES Module
│ ├── index.d.ts # Types TypeScript
│ └── styles.css # Styles TailwindCSS compilés
├── src/
│ ├── components/
│ │ └── ChatWidget.ts # Classe principale du widget
│ ├── styles/ # Styles source TailwindCSS
│ ├── types/ # Types TypeScript
│ └── index.ts # Point d'entrée
└── examples/ # Exemples d'intégration✨ Fonctionnalités
- 💬 Interface de chat moderne avec design élégant et responsive
- 🎨 Personnalisation complète des couleurs, logos et styles
- 🖼️ Upload d'images avec prévisualisation et barre de progression
- 🎤 Reconnaissance vocale intégrée (Web Speech API)
- 📱 Responsive : s'adapte automatiquement aux écrans mobiles
- 🧩 Architecture modulaire et extensible
- ⚡ Performances : léger et rapide
- 🌐 Universal : compatible avec tous les frameworks modernes
🎯 Utilisation Rapide
Exemple Basique
import { initChatWidget } from 'chat-widget-universal';
import 'chat-widget-universal/dist/styles.css';
const widget = initChatWidget({
apiUrl: 'https://api.example.com/chat',
welcomeMessage: 'Bonjour ! Comment puis-je vous aider ?',
position: 'bottom-right',
});Avec Callbacks Personnalisés
import { initChatWidget, ChatMessage } from 'chat-widget-universal';
const widget = initChatWidget({
welcomeMessage: 'Bienvenue !',
callbacks: {
onSendMessage: async (message: string) => {
// Votre logique personnalisée
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({ message }),
});
const data = await response.json();
return {
id: `msg-${Date.now()}`,
type: 'text',
content: data.response,
sender: 'bot',
timestamp: new Date(),
};
},
onReceiveMessage: (message: ChatMessage) => {
console.log('Message reçu:', message);
},
},
});⚙️ Configuration
Interface ChatWidgetConfig
interface ChatWidgetConfig {
// Identifiant unique (optionnel)
id?: string;
// Position du widget
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
// URL de l'API du chatbot
apiUrl?: string;
// Headers HTTP personnalisés
apiHeaders?: Record<string, string>;
// Méthode HTTP (GET, POST, etc.)
apiMethod?: 'GET' | 'POST' | 'PUT' | 'PATCH';
// Message d'accueil
welcomeMessage?: string | ChatMessage;
// Configuration des couleurs
colors?: {
primary?: string; // Couleur principale
secondary?: string; // Couleur secondaire
background?: string; // Couleur de fond
text?: string; // Couleur du texte
inputBackground?: string;
inputText?: string;
userMessageBg?: string;
botMessageBg?: string;
};
// Configuration du logo
logo?: {
url?: string;
alt?: string;
width?: number;
height?: number;
};
// Configuration du comportement
behavior?: {
responseDelay?: number; // Délai de réponse (ms)
showTypingIndicator?: boolean; // Afficher l'indicateur de frappe
typingIndicatorDuration?: number; // Durée de l'indicateur (ms)
enableQuickReplies?: boolean; // Activer les réponses rapides
enableSound?: boolean; // Activer les sons
soundUrl?: string; // URL du son de notification
};
// Callbacks personnalisés
callbacks?: {
onSendMessage?: (message: string, metadata?: any) => Promise<ChatMessage | ChatMessage[]> | ChatMessage | ChatMessage[];
onReceiveMessage?: (message: ChatMessage) => void;
onOpen?: () => void;
onClose?: () => void;
onError?: (error: Error) => void;
onButtonClick?: (button: ButtonOption) => void;
};
// Classes CSS personnalisées
customClasses?: {
container?: string;
chatWindow?: string;
messageList?: string;
message?: string;
input?: string;
button?: string;
};
// Autres options
locale?: string; // Langue (défaut: 'fr')
title?: string; // Titre du widget
showCloseButton?: boolean; // Afficher le bouton de fermeture
showHeader?: boolean; // Afficher le header
inputPlaceholder?: string; // Placeholder de l'input
submitOnEnter?: boolean; // Soumettre avec Enter
submitOnButtonClick?: boolean; // Soumettre avec le bouton
maxMessages?: number; // Nombre max de messages
autoScroll?: boolean; // Scroll automatique
}🎨 Personnalisation
Personnalisation des Couleurs
const widget = initChatWidget({
colors: {
primary: '#3b82f6', // Bleu
secondary: '#8b5cf6', // Violet
background: '#ffffff',
text: '#1f2937',
userMessageBg: '#3b82f6',
botMessageBg: '#f3f4f6',
},
});Personnalisation du Logo
const widget = initChatWidget({
logo: {
url: '/assets/logo.png',
alt: 'Mon Logo',
width: 32,
height: 32,
},
});Classes CSS Personnalisées
const widget = initChatWidget({
customClasses: {
container: 'my-custom-container',
chatWindow: 'my-custom-window',
message: 'my-custom-message',
},
});💬 Types de Messages
Le widget supporte plusieurs types de messages :
Message Texte
const message: ChatMessage = {
id: 'msg-1',
type: 'text',
content: 'Bonjour !',
sender: 'bot',
timestamp: new Date(),
};Message avec Image
Le widget supporte l'upload d'images avec prévisualisation :
const message: ChatMessage = {
id: 'msg-2',
type: 'image',
content: 'Voici l\'image que je souhaite analyser :',
sender: 'user',
timestamp: new Date(),
metadata: {
imageUrl: 'https://example.com/image.jpg',
fileName: 'image.jpg',
fileSize: 1024000,
fileType: 'image/jpeg',
},
};Fonctionnalités d'upload :
- Sélection d'image via le bouton dédié
- Prévisualisation avant envoi
- Barre de progression simulée
- Support de tous les formats d'image
- Affichage dans les bulles de messages
Message avec Boutons
const message: ChatMessage = {
id: 'msg-3',
type: 'button',
content: 'Choisissez une option :',
sender: 'bot',
timestamp: new Date(),
metadata: {
buttons: [
{
id: 'btn-1',
label: 'Option 1',
value: 'option1',
action: 'postback',
},
{
id: 'btn-2',
label: 'Visiter le site',
value: '',
action: 'url',
url: 'https://example.com',
},
],
},
};Message Carte
const message: ChatMessage = {
id: 'msg-4',
type: 'card',
content: '',
sender: 'bot',
timestamp: new Date(),
metadata: {
card: {
title: 'Titre de la carte',
description: 'Description de la carte',
imageUrl: 'https://example.com/image.jpg',
buttons: [
{
id: 'card-btn-1',
label: 'En savoir plus',
value: 'more',
action: 'postback',
},
],
},
},
};Message Audio (Reconnaissance Vocale)
Le widget supporte la reconnaissance vocale via l'API Web Speech :
// La reconnaissance vocale est automatiquement disponible
// L'utilisateur peut cliquer sur le bouton microphone pour dicter
// Le texte est automatiquement transcrit dans le champ de saisieFonctionnalités vocales :
- 🎤 Activation/désactivation du microphone
- ⏱️ Indicateur d'enregistrement avec minuteur
- 🗣️ Transcription automatique en temps réel
- 🌍 Support multilingue (configurable via
locale) - ⚠️ Gestion des erreurs et permissions
🔌 Intégration par Framework
React
import { useEffect } from 'react';
import { initChatWidget } from 'chat-widget-universal';
import 'chat-widget-universal/dist/styles.css';
function App() {
useEffect(() => {
const widget = initChatWidget({
apiUrl: 'https://api.example.com/chat',
welcomeMessage: 'Bonjour !',
});
return () => {
widget.destroy();
};
}, []);
return <div>Mon application</div>;
}Angular
import { Component, OnInit, OnDestroy } from '@angular/core';
import { initChatWidget, ChatWidget } from 'chat-widget-universal';
import 'chat-widget-universal/dist/styles.css';
@Component({
selector: 'app-root',
template: '<router-outlet></router-outlet>'
})
export class AppComponent implements OnInit, OnDestroy {
private widget: ChatWidget | null = null;
ngOnInit() {
this.widget = initChatWidget({
apiUrl: 'https://api.example.com/chat',
welcomeMessage: 'Bonjour !',
position: 'bottom-right',
colors: {
primary: '#4f46e5',
},
});
}
ngOnDestroy() {
this.widget?.destroy();
}
}📖 Guide complet : Consultez examples/angular-integration-guide.md pour plus de détails et d'exemples.
Vue 3
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue';
import { initChatWidget, ChatWidget } from 'chat-widget-universal';
import 'chat-widget-universal/dist/styles.css';
let widget: ChatWidget | null = null;
onMounted(() => {
widget = initChatWidget({
apiUrl: 'https://api.example.com/chat',
welcomeMessage: 'Bonjour !',
});
});
onUnmounted(() => {
widget?.destroy();
});
</script>Svelte
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { initChatWidget, ChatWidget } from 'chat-widget-universal';
import 'chat-widget-universal/dist/styles.css';
let widget: ChatWidget | null = null;
onMount(() => {
widget = initChatWidget({
apiUrl: 'https://api.example.com/chat',
welcomeMessage: 'Bonjour !',
});
});
onDestroy(() => {
widget?.destroy();
});
</script>HTML Pur
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="node_modules/chat-widget-universal/dist/styles.css">
</head>
<body>
<script type="module">
import { initChatWidget } from './node_modules/chat-widget-universal/dist/index.esm.js';
initChatWidget({
apiUrl: 'https://api.example.com/chat',
welcomeMessage: 'Bonjour !',
});
</script>
</body>
</html>🎛️ API
Fonctions Principales
initChatWidget(config: ChatWidgetConfig): ChatWidget
Initialise et injecte le widget de chat dans le DOM.
Retourne : Instance du widget de chat
getChatWidget(): ChatWidget | null
Obtient l'instance actuelle du widget.
Retourne : Instance du widget ou null si non initialisé
destroyChatWidget(): void
Détruit l'instance actuelle du widget.
Méthodes de l'instance ChatWidget
// Ouvrir le widget
widget.open();
// Fermer le widget
widget.close();
// Toggle l'état du widget
widget.toggle();
// Ajouter un message manuellement
widget.addMessage(message: ChatMessage);
// Détruire le widget
widget.destroy();🔗 Callbacks Disponibles
onSendMessage
Appelé lors de l'envoi d'un message. Vous pouvez retourner une réponse directement ou utiliser une URL d'API.
callbacks: {
onSendMessage: async (message: string, metadata?: any) => {
// Votre logique
return chatMessage; // ou [chatMessage1, chatMessage2]
},
}onReceiveMessage
Appelé lors de la réception d'un message du bot.
callbacks: {
onReceiveMessage: (message: ChatMessage) => {
console.log('Message reçu:', message);
},
}onOpen / onClose
Appelés lors de l'ouverture/fermeture du widget.
callbacks: {
onOpen: () => {
console.log('Widget ouvert');
},
onClose: () => {
console.log('Widget fermé');
},
}onError
Appelé en cas d'erreur.
callbacks: {
onError: (error: Error) => {
console.error('Erreur:', error);
},
}onButtonClick
Appelé lors du clic sur un bouton.
callbacks: {
onButtonClick: (button: ButtonOption) => {
console.log('Bouton cliqué:', button);
},
}📡 Format de l'API
Si vous utilisez apiUrl, le widget envoie des requêtes HTTP avec le format suivant :
Requête POST (par défaut)
{
"message": "Message de l'utilisateur",
"timestamp": "2024-01-01T12:00:00.000Z"
}Réponse Attendue
Format simple :
{
"id": "msg-1",
"type": "text",
"content": "Réponse du bot",
"sender": "bot",
"timestamp": "2024-01-01T12:00:00.000Z"
}Format avec boutons :
{
"id": "msg-1",
"type": "button",
"content": "Choisissez une option :",
"sender": "bot",
"timestamp": "2024-01-01T12:00:00.000Z",
"metadata": {
"buttons": [
{
"id": "btn-1",
"label": "Option 1",
"value": "option1",
"action": "postback"
}
]
}
}Format multiple messages :
[
{
"id": "msg-1",
"type": "text",
"content": "Premier message",
"sender": "bot",
"timestamp": "2024-01-01T12:00:00.000Z"
},
{
"id": "msg-2",
"type": "text",
"content": "Deuxième message",
"sender": "bot",
"timestamp": "2024-01-01T12:00:00.000Z"
}
]🎨 Styles et Thèmes
Le widget utilise TailwindCSS pour le style. Vous pouvez :
- Utiliser les variables CSS pour personnaliser les couleurs
- Surcharger les classes via
customClasses - Importer les styles :
import 'chat-widget-universal/dist/styles.css'
Personnalisation
Vous pouvez personnaliser les styles de plusieurs façons :
- Via la configuration : Utilisez l'objet
colorsdans la config - Variables CSS : Les composants respectent les variables CSS personnalisées
- Classes personnalisées : Utilisez
customClassespour ajouter vos classes
Variables CSS Disponibles
--chat-primary-color: #4f46e5;
--chat-secondary-color: #8b5cf6;
--chat-bg-color: #ffffff;
--chat-text-color: #1f2937;
--chat-input-bg-color: #f9fafb;📱 Responsive
Le widget est entièrement responsive et s'adapte automatiquement aux écrans mobiles :
- 📱 Sur mobile : Le widget prend toute la largeur disponible (moins les marges)
- 💻 Sur desktop : Taille fixe de 380px de largeur
- 🎯 Adaptation automatique : Les messages et l'interface s'ajustent selon la taille d'écran
- 📐 Hauteur flexible : S'adapte à la hauteur de la fenêtre du navigateur
🔒 Sécurité
- 🔐 Pas de stockage local : Le widget ne stocke aucune donnée localement
- 🔒 HTTPS recommandé : Toutes les communications avec l'API doivent utiliser HTTPS
- 🔑 Authentification : Les headers personnalisés peuvent être utilisés pour l'authentification
- 🎤 Permissions vocales : La reconnaissance vocale nécessite l'autorisation de l'utilisateur
- 🖼️ Upload sécurisé : Les images sont traitées côté client avant envoi
🐛 Dépannage
Le widget ne s'affiche pas
- Vérifiez que vous avez importé les styles :
import 'chat-widget-universal/dist/styles.css' - Vérifiez que le DOM est prêt avant d'appeler
initChatWidget - Vérifiez la console pour les erreurs
Les messages ne s'affichent pas
- Vérifiez le format de la réponse de votre API
- Vérifiez les callbacks
onSendMessageetonReceiveMessage - Vérifiez la console pour les erreurs
Les styles ne s'appliquent pas
- Assurez-vous d'importer les styles CSS :
import 'chat-widget-universal/dist/styles.css' - Vérifiez que TailwindCSS n'est pas en conflit avec vos styles
- Utilisez la configuration
colorspour personnaliser les couleurs - Utilisez
customClassespour surcharger les styles
La reconnaissance vocale ne fonctionne pas
- Vérifiez que votre navigateur supporte l'API Web Speech (Chrome, Edge, Safari)
- Assurez-vous que l'utilisateur a autorisé l'accès au microphone
- Vérifiez que la langue est correctement configurée via
locale - En cas d'erreur, un message d'alerte s'affichera automatiquement
📄 Licence
MIT
🤝 Contribution
Les contributions sont les bienvenues ! N'hésitez pas à ouvrir une issue ou une pull request.
📚 Exemples Complets
Consultez le dossier examples/ pour des exemples d'intégration complets pour chaque framework.
🔗 Liens Utiles
- Documentation TypeScript
- Exemples React
- Guide d'intégration Angular - Guide complet avec plusieurs méthodes
- Exemples Angular
- Exemples Vue
- Exemples Svelte
