urasoft-live-support
v1.1.10
Published
Universal live chat widget library for any web application (Vue, React, Next.js, vanilla JS)
Maintainers
Readme
@urasoft/live-chat-widget
Universal live chat widget library - A modern, TypeScript-based chat widget styled with Tailwind CSS for all your web projects.
🚀 Features
- 💬 Universal: Works everywhere - Vue, React, Next.js, Angular, or vanilla JavaScript
- 🎨 Customizable: Fully customizable position, colors, and messages
- 📱 Responsive: Mobile and desktop-friendly design
- ⚡ Lightweight: Minimal dependencies
- 🎯 TypeScript: Full type support with IntelliSense
- 🔌 SignalR Integration: Built-in SignalR support with connect/disconnect UI
- 🌐 Dynamic Configuration: Headers, query params, JWT tokens support
- 🔄 Smart Reconnection: Multiple reconnection strategies (exponential, linear, fixed, custom)
- 📡 Extensive Callbacks: 10+ event callbacks for full lifecycle control
- 🎛️ Transport Options: WebSockets, Server-Sent Events, Long Polling
📦 Installation
npm install @urasoft/live-chat-widget🔧 Quick Start
Basic Usage with SignalR (Recommended)
import { ChatWidget } from "@urasoft/live-chat-widget";
import "@urasoft/live-chat-widget/dist/styles.css";
const chat = new ChatWidget({
position: "bottom-right",
primaryColor: "#007bff",
title: "Live Support",
placeholder: "Type your message...",
agentName: "Support Team",
agentAvatar: "/avatar.png",
signalR: {
hubUrl: "https://your-server.com/chatHub",
// Query parameters (optional)
queryParams: {
userId: "12345",
roomId: "support-room",
},
// Headers (optional)
headers: {
"X-Custom-Header": "value",
},
// Token factory (optional - for JWT)
accessTokenFactory: async () => {
return await getAuthToken(); // Your token method
},
// Hub method names (optional, defaults shown)
sendMethodName: "SendMessage",
receiveMethodName: "ReceiveMessage",
// Event callbacks (optional)
onConnected: (connectionId) => {
console.log("SignalR connected:", connectionId);
},
onDisconnected: (error) => {
console.log("SignalR disconnected", error);
},
onMessageReceived: (message) => {
console.log("Message received:", message);
},
},
});Vanilla JavaScript / TypeScript (With Callback)
import { ChatWidget } from "@urasoft/live-chat-widget";
import "@urasoft/live-chat-widget/dist/styles.css";
const chat = new ChatWidget({
position: "bottom-right",
primaryColor: "#007bff",
title: "Live Support",
welcomeMessage: "Hello! How can I help you?",
placeholder: "Type your message...",
agentName: "Support Team",
agentAvatar: "/avatar.png",
autoOpen: false,
buttonIcon: "💬",
onSendMessage: (message) => {
console.log("Message sent:", message);
// Send to backend with SignalR or other service
},
});React / Next.js
"use client"; // For Next.js 13+
import { useEffect, useRef } from "react";
import { ChatWidget } from "@urasoft/live-chat-widget";
import "@urasoft/live-chat-widget/dist/styles.css";
export default function ChatComponent() {
const chatRef = useRef<ChatWidget | null>(null);
useEffect(() => {
chatRef.current = new ChatWidget({
position: "bottom-right",
primaryColor: "#007bff",
signalR: {
hubUrl: "/chatHub",
queryParams: {
userId: "user-123",
},
accessTokenFactory: async () => {
const response = await fetch("/api/auth/token");
const data = await response.json();
return data.token;
},
},
});
return () => {
chatRef.current?.destroy();
};
}, []);
return null;
}Vue 3
<template>
<div></div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted } from "vue";
import { ChatWidget } from "@urasoft/live-chat-widget";
import "@urasoft/live-chat-widget/dist/styles.css";
let chat: ChatWidget | null = null;
onMounted(() => {
chat = new ChatWidget({
position: "bottom-right",
primaryColor: "#007bff",
signalR: {
hubUrl: "/chatHub",
queryParams: {
sessionId: "vue-session-123",
},
},
});
});
onUnmounted(() => {
chat?.destroy();
});
</script>⚙️ Configuration Options
Complete Configuration Interface
interface ChatConfig {
// Widget position (default: 'bottom-right')
position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
// Primary color (default: '#007bff')
primaryColor?: string;
// Welcome message displayed when chat opens
welcomeMessage?: string;
// Chat header title (default: 'Live Support')
title?: string;
// Input placeholder text (default: 'Type your message...')
placeholder?: string;
// Agent/Support team name (default: 'Support Team')
agentName?: string;
// Agent avatar URL
agentAvatar?: string;
// Auto-open chat on page load (default: false)
autoOpen?: boolean;
// Chat button icon (default: '💬')
buttonIcon?: string;
// SignalR configuration
signalR?: {
// SignalR Hub URL (required)
hubUrl: string;
// Query parameters (optional)
queryParams?: Record<string, string>;
// HTTP Headers (optional)
headers?: Record<string, string>;
// Token factory function (for JWT authentication)
accessTokenFactory?: () => string | Promise<string>;
// Hub method names (optional)
sendMethodName?: string; // Default: 'SendMessage'
receiveMethodName?: string; // Default: 'ReceiveMessage'
// Reconnection settings (optional)
reconnect?: {
maxRetries?: number; // Maximum retry attempts (default: 5)
delayStrategy?:
| "exponential"
| "linear"
| "fixed"
| ((retryCount: number) => number); // Delay strategy
initialDelay?: number; // Initial delay in ms (default: 1000)
maxDelay?: number; // Maximum delay in ms (default: 30000)
fixedDelay?: number; // Fixed delay in ms (default: 5000)
disableAutoReconnect?: boolean; // Disable automatic reconnection
};
// Event callbacks
onConnected?: (connectionId?: string) => void;
onDisconnected?: (error?: Error) => void;
onReconnecting?: (error?: Error) => void;
onReconnected?: (connectionId?: string) => void;
onRetry?: (
retryCount: number,
delayMs: number,
elapsedMs?: number
) => void;
onReconnectFailed?: () => void;
onMessageReceived?: (message: any) => void;
onBeforeSend?: (message: string) => string | Promise<string>;
onAfterSend?: (message: string) => void;
onError?: (error: Error) => void;
// Transport and logging settings (optional)
transport?: "WebSockets" | "ServerSentEvents" | "LongPolling" | "All"; // Default: 'All'
logLevel?:
| "Trace"
| "Debug"
| "Information"
| "Warning"
| "Error"
| "Critical"
| "None"; // Default: 'Information'
};
// Callback when message is sent (when not using SignalR)
onSendMessage?: (message: string) => void;
}🔌 SignalR Kullanım Senaryoları
Temel SignalR Kullanımı
Widget otomatik olarak SignalR bağlantısını yönetir:
import { ChatWidget } from "@urasoft/live-chat-widget";
import "@urasoft/live-chat-widget/dist/styles.css";
const chat = new ChatWidget({
position: "bottom-right",
primaryColor: "#007bff",
signalR: {
hubUrl: "https://api.example.com/chatHub",
},
});Kullanıcı akışı:
- Kullanıcı chat balonuna tıklar
- "Canlı Desteğe Bağlan" butonuna tıklar
- SignalR bağlantısı otomatik kurulur
- Mesajlaşma başlar
- "Görüşmeyi Sonlandır" (🔌) butonuna tıklar
- Bağlantı kapatılır
🔄 Yeniden Bağlanma Stratejileri
SignalR bağlantısı kesildiğinde otomatik yeniden bağlanmayı özelleştirebilirsiniz:
Exponential Backoff (Varsayılan)
Her denemede gecikme ikiye katlanır: 1s, 2s, 4s, 8s, 16s...
const chat = new ChatWidget({
signalR: {
hubUrl: "/chatHub",
reconnect: {
maxRetries: 10,
delayStrategy: "exponential",
initialDelay: 1000, // 1 saniye
maxDelay: 60000, // Maksimum 60 saniye
},
onRetry: (retryCount, delayMs) => {
console.log(
`🔄 Yeniden bağlanma denemesi ${retryCount}, ${delayMs}ms sonra...`
);
},
onReconnected: (connectionId) => {
console.log("✅ Yeniden bağlandı:", connectionId);
},
onReconnectFailed: () => {
console.error(
"❌ Yeniden bağlanma başarısız, maksimum deneme aşıldı"
);
alert("Bağlantı kurulamadı, lütfen sayfayı yenileyin.");
},
},
});Linear Backoff
Her denemede sabit bir miktar eklenir: 1s, 2s, 3s, 4s, 5s...
const chat = new ChatWidget({
signalR: {
hubUrl: "/chatHub",
reconnect: {
maxRetries: 5,
delayStrategy: "linear",
initialDelay: 2000, // 2 saniye başlangıç
},
},
});Fixed Delay
Her denemede aynı gecikme: 5s, 5s, 5s, 5s...
const chat = new ChatWidget({
signalR: {
hubUrl: "/chatHub",
reconnect: {
maxRetries: 8,
delayStrategy: "fixed",
fixedDelay: 5000, // Her denemede 5 saniye bekle
},
},
});Custom Delay Function
Kendi gecikme stratejinizi tanımlayın:
const chat = new ChatWidget({
signalR: {
hubUrl: "/chatHub",
reconnect: {
maxRetries: 10,
delayStrategy: (retryCount) => {
// Özel strateji: Fibonacci benzeri gecikme
if (retryCount === 0) return 1000;
if (retryCount === 1) return 1000;
return Math.min(
fibonacci(retryCount) * 1000,
60000 // Max 60 saniye
);
},
},
},
});
function fibonacci(n: number): number {
if (n <= 1) return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
}🎯 Tüm Event Callback'leri
SignalR yaşam döngüsünün her aşamasını dinleyebilirsiniz:
const chat = new ChatWidget({
signalR: {
hubUrl: "/chatHub",
// Bağlantı kurulduğunda
onConnected: (connectionId) => {
console.log("✅ Bağlandı, Connection ID:", connectionId);
analytics.track("chat_connected");
},
// Bağlantı kesildiğinde
onDisconnected: (error) => {
console.log("❌ Bağlantı kesildi:", error?.message);
analytics.track("chat_disconnected");
},
// Yeniden bağlanma başladığında
onReconnecting: (error) => {
console.log("🔄 Yeniden bağlanıyor...", error?.message);
// UI'da "Bağlanıyor..." göster
},
// Yeniden bağlandığında
onReconnected: (connectionId) => {
console.log("✅ Yeniden bağlandı:", connectionId);
// UI'da "Bağlandı" göster
},
// Her yeniden bağlanma denemesinde
onRetry: (retryCount, delayMs, elapsedMs) => {
console.log(`🔄 Deneme ${retryCount}, ${delayMs}ms bekleyecek`);
console.log(`⏱️ Toplam geçen süre: ${elapsedMs}ms`);
// Progress bar güncelle
},
// Tüm denemeler tükendiğinde
onReconnectFailed: () => {
console.error("❌ Yeniden bağlanma başarısız");
alert("Sunucuya bağlanılamadı, lütfen sayfayı yenileyin.");
},
// Mesaj alındığında
onMessageReceived: (message) => {
console.log("📩 Mesaj alındı:", message);
playNotificationSound();
},
// Mesaj göndermeden önce (mesajı değiştirebilirsiniz)
onBeforeSend: async (message) => {
console.log("📤 Gönderiliyor:", message);
// Mesajı şifrele, temizle veya format değiştir
const sanitized = sanitizeMessage(message);
return sanitized;
},
// Mesaj gönderildikten sonra
onAfterSend: (message) => {
console.log("✅ Gönderildi:", message);
analytics.track("message_sent", { length: message.length });
},
// Herhangi bir hata oluştuğunda
onError: (error) => {
console.error("⚠️ SignalR Hatası:", error.message);
// Sentry, LogRocket vb. hata servislere gönder
errorReporter.captureException(error);
},
reconnect: {
maxRetries: 5,
delayStrategy: "exponential",
},
},
});🚀 Transport ve Log Ayarları
const chat = new ChatWidget({
signalR: {
hubUrl: "/chatHub",
// Transport türü seçimi
transport: "WebSockets", // 'WebSockets' | 'ServerSentEvents' | 'LongPolling' | 'All'
// Log seviyesi (development için 'Debug', production için 'Warning')
logLevel: "Debug", // 'Trace' | 'Debug' | 'Information' | 'Warning' | 'Error' | 'Critical' | 'None'
},
});JWT Token ile Güvenli Bağlantı
const chat = new ChatWidget({
signalR: {
hubUrl: "/chatHub",
accessTokenFactory: async () => {
const response = await fetch("/api/auth/token");
const { token } = await response.json();
return token;
},
},
});Query Parametreleri ile Kullanıcı Bilgisi Gönderme
const chat = new ChatWidget({
signalR: {
hubUrl: "/chatHub",
queryParams: {
userId: currentUser.id,
userName: currentUser.name,
department: "support",
},
},
});Custom Header'lar
const chat = new ChatWidget({
signalR: {
hubUrl: "/chatHub",
headers: {
"X-Api-Key": "your-api-key",
"X-Client-Version": "1.0.0",
},
},
});Backend Event'leri Dinleme
const chat = new ChatWidget({
signalR: {
hubUrl: "/chatHub",
onConnected: () => {
console.log("✅ Canlı desteğe bağlandı");
analytics.track("chat_connected");
},
onDisconnected: (error) => {
console.log("❌ Bağlantı kesildi", error);
analytics.track("chat_disconnected");
},
onMessageReceived: (message) => {
console.log("📩 Yeni mesaj:", message);
// Bildirim göster, ses çal, vb.
},
},
});🖥️ Backend SignalR Hub Örneği (C#)
using Microsoft.AspNetCore.SignalR;
public class ChatHub : Hub
{
public async Task SendMessage(string message)
{
// Kullanıcıdan gelen mesajı al
var userId = Context.UserIdentifier;
// Mesajı işle ve yanıt gönder
var response = await ProcessMessage(message, userId);
// Sadece gönderen kullanıcıya yanıt gönder
await Clients.Caller.SendAsync("ReceiveMessage", response);
}
public override async Task OnConnectedAsync()
{
var userId = Context.GetHttpContext()?.Request.Query["userId"];
Console.WriteLine($"User connected: {userId}");
await Clients.Caller.SendAsync("ReceiveMessage",
"Canlı desteğe hoş geldiniz! Size nasıl yardımcı olabiliriz?");
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? exception)
{
Console.WriteLine($"User disconnected: {Context.ConnectionId}");
await base.OnDisconnectedAsync(exception);
}
}🎯 API Metodları
// Chat penceresi aç
chat.open();
// Chat penceresi kapat
chat.close();
// Widget'ı tamamen kaldır
chat.destroy();
// Programatik olarak agent mesajı ekle (SignalR için)
chat.addAgentMessage("Merhaba, size yardımcı olabilir miyim?", "/avatar.png");🎨 Özel Stil
Widget Tailwind CSS kullanır, ancak CSS değişkenleri ile de özelleştirebilirsiniz:
:root {
--chat-primary-color: #007bff; /* Ana renk */
}📝 Lisans
MIT
🤝 Katkıda Bulunma
Katkılarınızı bekliyoruz! Issue açabilir veya pull request gönderebilirsiniz.
📧 İletişim
Sorularınız için: Urasoft
