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

knm-chat-core

v0.0.28

Published

A lightweight chat SDK with a floating button

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-core

Yarn

yarn add knm-chat-core

PNPM

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ụng window.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ắn
  • contentType: '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ông
  • chat.visitorId - Lấy unique visitor ID
  • chat.conversationId - Lấy conversation ID hiện tại
  • chat.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 đủ:

🎨 Demo files:


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'
    });
  }
}