npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

urasoft-live-support

v1.1.10

Published

Universal live chat widget library for any web application (Vue, React, Next.js, vanilla JS)

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ışı:

  1. Kullanıcı chat balonuna tıklar
  2. "Canlı Desteğe Bağlan" butonuna tıklar
  3. SignalR bağlantısı otomatik kurulur
  4. Mesajlaşma başlar
  5. "Görüşmeyi Sonlandır" (🔌) butonuna tıklar
  6. 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