knm-chat-core
v0.0.28
Published
A lightweight chat SDK with a floating button
Maintainers
Readme
KnMWallE Chat Widget
KnMWallE là một widget chat được thiết kế để tích hợp vào các trang web, cho phép khách truy cập tương tác với hỗ trợ viên.
✨ Features
- 🆔 Unique visitor identification using browser fingerprinting
- 🎨 Customizable colors and positioning
- 💅 Custom CSS support (inline, external URLs, CSS Variables)
- 🌍 Multi-language support (Vietnamese, English, custom)
- 📎 Drag & drop file upload with preview
- 📱 Responsive design that works on all devices
- 🚀 Lightweight and fast
- 🔌 Easy to integrate with any website
- 🛠 Built with vanilla JavaScript, no frameworks required
- 🎨 Styled with Tailwind CSS
- 📦 Works on HTML, Next.js, Nest.js, and more
- ⚡ CSS automatically injected (no separate CSS import needed)
- 🎯 Default logo and colors included
📦 Cài Đặt
NPM
npm install knm-chat-coreYarn
yarn add knm-chat-corePNPM
pnpm add knm-chat-core🚀 Cách Dùng
🎯 TL;DR - Chọn cách phù hợp:
| Cách | Khi nào dùng | Độ khó | |------|-------------|--------| | Iframe 🖼️ | WordPress, Wix, Shopify, không cần build | ⭐ (Dễ nhất) | | Script Tag 📜 | HTML thuần, landing page | ⭐⭐ | | NPM 📦 | React, Vue, Next.js, có build tools | ⭐⭐⭐ |
🖼️ Iframe Integration (KHUYẾN NGHỊ cho non-technical)
Ưu điểm:
- ✅ Chỉ cần 1 dòng HTML
- ✅ Không xung đột CSS/JS
- ✅ Không cần npm, webpack, build tools
- ✅ Bảo mật cao (sandbox)
Bước 1: Nhúng iframe vào website:
<iframe
src="https://your-domain.com/iframe-chat.html?apiUrl=YOUR_API_URL&buttonText=Chat+ngay"
style="position: fixed; bottom: 0; right: 0; width: 100%; height: 100%; border: none; z-index: 9999;"
></iframe>Bước 2: Done! 🎉
📚 Chi tiết: Iframe Integration Guide
1️⃣ HTML (Vanilla JavaScript)
Cách đơn giản nhất - chỉ cần 1 dòng!
⚠️ Lưu ý: Khi dùng UMD build (
<script>tag), cần sử dụngwindow.ChatSdk?.default || window.ChatSdk
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Website</title>
</head>
<body>
<h1>Welcome to My Website</h1>
<!-- Load CSS (BẮT BUỘC!) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/knm-chat-core@latest/dist/style.css" />
<!-- Load JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/knm-chat-core@latest/dist/chat-sdk.umd.cjs"></script>
<script>
// UMD build cần dùng window.ChatSdk
const SDK = window.ChatSdk?.default || window.ChatSdk;
// Khởi tạo với cấu hình mặc định
const chat = new SDK({
position: 'bottom-right',
buttonColor: '#007bff',
apiUrl: 'https://your-api.com',
socketUrl: 'https://your-socket.com'
});
</script>
</body>
</html>2️⃣ Next.js (React/TypeScript)
Cách 1: Dùng Dynamic Import (Recommended)
// app/page.tsx
'use client';
import dynamic from 'next/dynamic';
import { useEffect } from 'react';
import type ChatSdk from 'knm-chat-core';
export default function Home() {
useEffect(() => {
// Dynamic import để tránh SSR issues
import('knm-chat-core').then((module) => {
const ChatSdkClass = module.default;
new ChatSdkClass({
position: 'bottom-right',
buttonColor: '#007bff',
apiUrl: process.env.NEXT_PUBLIC_API_URL,
socketUrl: process.env.NEXT_PUBLIC_SOCKET_URL,
buttonText: 'Chat with us'
});
});
}, []);
return (
<main>
<h1>Welcome to Next.js</h1>
</main>
);
}Cách 2: Dùng Script Component
// app/layout.tsx
import Script from 'next/script';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
<Script
src="https://cdn.jsdelivr.net/npm/knm-chat-core@latest/dist/chat-sdk.umd.cjs"
onLoad={() => {
if (window.ChatSdk) {
new window.ChatSdk({
position: 'bottom-right',
buttonColor: '#007bff',
apiUrl: process.env.NEXT_PUBLIC_API_URL,
socketUrl: process.env.NEXT_PUBLIC_SOCKET_URL
});
}
}}
/>
</body>
</html>
);
}Cách 3: Tạo Custom Hook
// hooks/useChat.ts
import { useEffect } from 'react';
import type ChatSdk from 'knm-chat-core';
import type { ChatSdkConfig } from 'knm-chat-core';
export const useChat = (config: ChatSdkConfig) => {
useEffect(() => {
import('knm-chat-core').then(({ default: ChatSdkClass }) => {
new ChatSdkClass(config);
});
}, [config]);
};
// app/page.tsx
'use client';
import { useChat } from '@/hooks/useChat';
export default function Home() {
useChat({
position: 'bottom-right',
buttonColor: '#007bff',
apiUrl: process.env.NEXT_PUBLIC_API_URL,
socketUrl: process.env.NEXT_PUBLIC_SOCKET_URL,
});
return <main>Welcome!</main>;
}3️⃣ Nest.js (Backend)
Khi cần truyền chat script đến frontend (Server-Side Rendering)
// chat.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class ChatService {
getChatScript(config: any): string {
return `
<script src="https://cdn.jsdelivr.net/npm/knm-chat-core@latest/dist/chat-sdk.umd.cjs"></script>
<script>
new ChatSdk(${JSON.stringify(config)});
</script>
`;
}
getChatConfig() {
return {
position: 'bottom-right',
buttonColor: process.env.CHAT_BUTTON_COLOR || '#007bff',
apiUrl: process.env.API_URL,
socketUrl: process.env.SOCKET_URL,
buttonText: 'Support'
};
}
}
// app.controller.ts
import { Controller, Get, Res } from '@nestjs/common';
import { ChatService } from './chat.service';
import { Response } from 'express';
@Controller('api')
export class AppController {
constructor(private chatService: ChatService) {}
@Get('chat-script')
getChatScript(@Res() res: Response) {
const config = this.chatService.getChatConfig();
const script = this.chatService.getChatScript(config);
res.type('text/html').send(script);
}
}⚙️ Cấu Hình (Configuration)
| Tham số | Kiểu | Mặc định | Mô tả |
|---------|------|----------|--------|
| position | string | 'bottom-right' | Vị trí widget: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' |
| buttonText | string | 'Điện máy XANH' | Text hiển thị trên nút chat |
| buttonColor | string | '#007bff' | Màu của nút chat (hex color) |
| headerColor | string | '#007bff' | Màu header của chat window |
| apiUrl | string | - | URL của API server (bắt buộc) |
| socketUrl | string | - | URL của WebSocket server (bắt buộc) |
| getConversationUrlIdPath | string | '/api/webhook/external-web' | Path API lấy conversation ID |
| getMessagesUrlPath | string | '/api/webhook/external-web' | Path API lấy tin nhắn |
| uploadImagePath | string | '/api/webhook/external-web' | Path API upload ảnh |
| messagesPerPage | number | 20 | Số tin nhắn mỗi lần load |
| maxImageSize | number | 5242880 (5MB) | Kích thước ảnh tối đa |
| allowedImageTypes | string[] | ['image/jpeg', 'image/png', ...] | Các loại ảnh cho phép |
| assetBasePath | string | 'dist/assets' | Đường dẫn tới thư mục assets |
| teaserEnabled | boolean | true | Bật/tắt teaser popup |
| teaserTitle | string | 'Điện máy XANH' | Tiêu đề teaser |
| teaserMessage | string | 'Em rất sẵn lòng...' | Tin nhắn teaser |
| teaserDelayMs | number | 800 | Delay trước khi hiển thị teaser (ms) |
| teaserAutoHideMs | number | 0 | Thời gian tự động ẩn teaser (ms, 0 = không ẩn) |
| teaserWidth | number | 280 | Chiều rộng teaser (px) |
| teaserShowOnMobile | boolean | true | Hiển thị teaser trên mobile |
📖 API Methods
openChat()
Mở cửa sổ chat.
chat.openChat();closeChat()
Đóng cửa sổ chat.
chat.closeChat();toggleChat()
Chuyển đổi trạng thái mở/đóng.
chat.toggleChat();addMessage(sender, text, contentType?)
Thêm một tin nhắn vào chat.
sender: 'user' | 'bot' | 'them'text: Nội dung tin nhắncontentType: 'text' | 'image' | 'markdown' (tùy chọn)
chat.addMessage('user', 'Hello!');
chat.addMessage('bot', 'Hi there! How can I help?');Properties
chat.isOpen- Kiểm tra xem chat có mở khôngchat.visitorId- Lấy unique visitor IDchat.conversationId- Lấy conversation ID hiện tạichat.config- Cấu hình hiện tại
🎨 Customization
Custom CSS (NEW! 🔥)
SDK hỗ trợ 3 cách custom CSS:
1️⃣ Inline CSS (Khuyến nghị cho quick styling)
new ChatSdk({
customCss: `
/* Override button */
.knm-chat-button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
box-shadow: 0 10px 30px rgba(102, 126, 234, 0.5) !important;
}
/* Custom message bubbles */
.knm-message-user .knm-bubble {
background: #667eea !important;
}
`
});2️⃣ External CSS URLs
new ChatSdk({
customCssUrls: [
"https://yourcdn.com/chat-theme.css",
"/assets/custom-chat.css"
]
});3️⃣ CSS Variables (Auto-generated từ config)
new ChatSdk({
button: { color: "#667eea" },
customCss: `
.knm-header {
background: var(--knm-button-color) !important;
}
`
});📌 Available CSS Classes (13+):
.knm-chat-button- Button chat chính.knm-teaser-container- Container chứa tất cả teaser items.knm-teaser-item- Mỗi teaser card/item.knm-teaser-avatar- Avatar của teaser.knm-teaser-content- Container chứa title và message.knm-teaser-title- Title text của teaser.knm-teaser-message- Message text của teaser.knm-header- Header.knm-chat-window- Cửa sổ chat.knm-chat-messages- Container tin nhắn.knm-input- Input container.knm-send-button- Nút gửi.knm-attachment-button- Nút đính kèm.knm-message-user/.knm-message-bot- Tin nhắn.knm-bubble- Bubble tin nhắn.knm-file-preview-inline- Preview file
💡 Tip: Không cần !important
Thay vì dùng !important, bạn có thể tăng specificity bằng cách thêm .knm-chat-sdk prefix:
// ✅ KHÔNG CẦN !important - Dùng specificity cao hơn
customCss: `
.knm-chat-sdk .knm-teaser-item {
background: linear-gradient(135deg, #f0f9ff, #e0f2fe);
border: 2px solid #0ea5e9;
border-radius: 20px;
}
.knm-chat-sdk .knm-teaser-avatar {
width: 40px;
height: 40px;
border: 3px solid #0ea5e9;
}
`Hoặc custom teaser đầy đủ:
customCss: `
/* Teaser container */
.knm-chat-sdk .knm-teaser-container {
gap: 8px;
}
/* Teaser item/card */
.knm-chat-sdk .knm-teaser-item {
background: linear-gradient(135deg, #f0f9ff, #e0f2fe);
border: 2px solid #0ea5e9;
border-radius: 20px;
padding: 16px;
box-shadow: 0 4px 12px rgba(14, 165, 233, 0.2);
}
/* Teaser avatar */
.knm-chat-sdk .knm-teaser-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
border: 3px solid #0ea5e9;
box-shadow: 0 2px 8px rgba(14, 165, 233, 0.3);
}
/* Teaser title */
.knm-chat-sdk .knm-teaser-title {
font-size: 15px;
font-weight: 600;
color: #0c4a6e;
}
/* Teaser message */
.knm-chat-sdk .knm-teaser-message {
font-size: 13px;
color: #075985;
margin-top: 4px;
}
/* Hover effect */
.knm-chat-sdk .knm-teaser-item:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(14, 165, 233, 0.3);
}
`📌 Available CSS Variables (25+):
--knm-overlay-loading-bg/--knm-overlay-error-bg--knm-spinner-color/--knm-spinner-track--knm-message-user-bg/--knm-message-bot-bg--knm-retry-btn-bg/--knm-retry-btn-border--knm-glass-blur/--knm-glass-saturate- ... và nhiều hơn nữa
📚 Tài liệu đầy đủ:
- 🚀 Quick Start:
docs/QUICK_START_CSS.md - 🇻🇳 Tiếng Việt:
docs/CUSTOM_CSS_VI.md - 🇬🇧 English:
docs/CUSTOM_CSS.md - 📖 Index:
docs/README.md
🎨 Demo files:
test-custom-demo.html- 6 themes đầy đủ (Default, Đỏ, Xanh, Tím, Cam, Dark Mode)test.html- Demo cấu hình đầy đủ SDK
CSS Classes & Variables
Widget sử dụng các CSS classes và variables sau:
Classes:
.knm-chat-button { /* Nút chat */ }
.knm-chat-window { /* Cửa sổ chat */ }
#chat-messages { /* Khu vực tin nhắn */ }
.knm-message-user, .knm-message-bot { /* Message bubbles */ }
.markdown-content { /* Nội dung markdown */ }CSS Variables:
/* General */
--knm-button-color /* Button primary color */
--knm-header-color /* Header background */
--knm-window-width /* Chat window width */
--knm-window-height /* Chat window height */
/* Glass Effects */
--knm-glass-blur /* Glass blur (8px) */
--knm-glass-saturate /* Glass saturation (180%) */
/* Overlays */
--knm-overlay-loading-bg /* Loading overlay background */
--knm-overlay-loading-border /* Loading overlay border */
--knm-overlay-error-bg /* Error overlay background */
--knm-overlay-error-border /* Error overlay border */
/* Retry Button */
--knm-retry-btn-bg /* Retry button background */
--knm-retry-btn-border /* Retry button border & icon */
--knm-retry-btn-shadow /* Retry button shadow */
/* Spinner */
--knm-spinner-color /* Spinner color */
--knm-spinner-track /* Spinner track color */
/* Message Bubbles */
--knm-message-user-bg /* User message background */
--knm-message-user-color /* User message text */
--knm-message-bot-bg /* Bot message background */
--knm-message-bot-color /* Bot message text */
/* Drag & Drop */
--knm-drop-overlay-bg /* Drag overlay background */
--knm-drop-overlay-border /* Drag overlay border */
/* File Preview */
--knm-preview-item-bg /* Preview item background */
--knm-preview-item-border /* Preview item border */Default Assets
Widget đã bao gồm logo, favicon, và avatar mặc định. Bạn có thể override bằng cách cấu hình assetBasePath:
new ChatSdk({
assetBasePath: 'https://your-cdn.com/assets', // Custom asset path
// ... other config
});🌍 Hỗ Trợ Browser
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- Mobile Safari (iOS 12+)
- Chrome for Android
📱 Mobile Support
Widget được thiết kế responsive và hoạt động hoàn hảo trên mobile. Trên mobile:
- Chat window sẽ fullscreen
- Teaser có thể tắt bằng
teaserShowOnMobile: false
🔒 Privacy & Security
- Mỗi user được gán unique ID dùng browser fingerprinting
- Tất cả communication qua HTTPS/WSS
- Không lưu trữ data nhạy cảm trên client
📝 License
MIT
🤝 Support
Nếu có vấn đề, vui lòng report tại:
- GitHub Issues: https://github.com/KnM-Holdings/knm-chat-sdk/issues
- Email: [email protected]
📚 Ví Dụ Thêm
Sử dụng trong Vue.js
<template>
<div>
<h1>Welcome</h1>
</div>
</template>
<script setup>
import { onMounted } from 'vue';
onMounted(() => {
import('knm-chat-core').then(({ default: ChatSdk }) => {
new ChatSdk({
position: 'bottom-right',
apiUrl: 'https://your-api.com'
});
});
});
</script>Sử dụng trong Svelte
<script>
import { onMount } from 'svelte';
onMount(async () => {
const { default: ChatSdk } = await import('knm-chat-core');
new ChatSdk({
position: 'bottom-right',
apiUrl: 'https://your-api.com'
});
});
</script>
<h1>Welcome</h1>Sử dụng trong Angular
// app.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-root',
template: `<h1>Welcome</h1>`,
})
export class AppComponent implements OnInit {
async ngOnInit() {
const { default: ChatSdk } = await import('knm-chat-core');
new ChatSdk({
position: 'bottom-right',
apiUrl: 'https://your-api.com'
});
}
}