@classic-homes/chat-widget

中文文档
0.1.15发布于 2026/11/12MITTypeScriptES Module近 30 天下载 2658

High-performance embeddable chat widget built with Svelte

原始使用文档
文档目录18 节
  1. Installation
  2. Usage
  3. Vanilla JavaScript
  4. React Component
  5. Docusaurus Plugin
  6. Custom Element (Web Component)
  7. Configuration Options
  8. Account Login
  9. Widget API
  10. Conversation Management
  11. State Getters
  12. Lifecycle Methods
  13. Events
  14. Available Events
  15. TypeScript Support
  16. Styling
  17. Browser Support
  18. License

@classic-homes/chat-widget

High-performance embeddable chat widget built with Svelte. Can be integrated via multiple methods: Vanilla JS, React, Docusaurus plugin, or Custom Element.

Installation

npm install @classic-homes/chat-widget

For React projects, ensure you have React 17+ installed:

npm install react react-dom

Usage

Vanilla JavaScript

The simplest way to add the widget to any website:

import { init, destroy } from '@classic-homes/chat-widget/vanilla';

// Initialize the widget
init({
  apiBase: 'https://api.example.com',
  site: 'docs',
  siteName: 'Documentation',
  title: 'Help Assistant',
  welcomeMessage: 'How can I help you today?',
  welcomeTopics: ['Getting started', 'API reference', 'Troubleshooting'],
});

// Later, to destroy the widget
destroy();

React Component

Use the React adapter for seamless integration with React applications:

import { ChatWidget } from '@classic-homes/chat-widget/react';

function App() {
  return (
    <ChatWidget
      apiBase="https://api.example.com"
      site="docs"
      siteName="Documentation"
      title="Help Assistant"
      welcomeMessage="How can I help you today?"
      welcomeTopics={['Getting started', 'API reference', 'Troubleshooting']}
    />
  );
}

The React adapter also provides ChatWidgetElement for using the custom element directly:

import { ChatWidgetElement } from '@classic-homes/chat-widget/react';

function App() {
  return (
    <ChatWidgetElement
      apiBase="https://api.example.com"
      site="docs"
      siteName="Documentation"
    />
  );
}

Docusaurus Plugin

For Docusaurus 3.x sites:

// docusaurus.config.js
module.exports = {
  plugins: [
    [
      '@classic-homes/chat-widget/docusaurus',
      {
        apiBase: 'https://api.example.com',
        site: 'docs',
        siteName: 'Documentation',
        title: 'Help Assistant',
      },
    ],
  ],
};

Custom Element (Web Component)

Use the <chat-widget> custom element directly in HTML:

<script type="module">
  import '@classic-homes/chat-widget';
</script>

<chat-widget
  api-base="https://api.example.com"
  site="docs"
  site-name="Documentation"
  title="Help Assistant"
  welcome-message="How can I help you today?"
  welcome-topics='["Getting started", "API reference"]'
></chat-widget>

Note: Attribute names use kebab-case (e.g., api-base instead of apiBase).

Configuration Options

OptionTypeRequiredDefaultDescription
apiBasestringYes-Base URL for the chat API
sitestringYes-Site identifier (e.g., "docs", "marketing")
siteNamestringYes-Display name for current site
titlestringNo"Chat Assistant"Widget header title
logoUrlstringNo-Logo URL for header
primaryColorstringNo-Primary brand color (CSS color value)
position"bottom-right" | "bottom-left"No"bottom-right"Widget position
fullscreenbooleanNofalseEnable fullscreen mode
welcomeMessagestringNo-Welcome message text
welcomeTopicsstring[]No-Suggested topics shown in welcome
disclaimerHtmlstringNo-Disclaimer HTML shown below welcome
storagePrefixstringNo"chat_"Prefix for localStorage keys
sentryDsnstringNo-Sentry DSN for error tracking
environment"development" | "production"No"production"Environment name
sitesRecord<string, SiteConfig>No-Cross-site configuration
onNavigate(url: string) => voidNo-Custom navigation handler
onOpen() => voidNo-Called when widget opens
onClose() => voidNo-Called when widget closes
getAuthToken() => string | null | Promise<string | null>No-CHAPI account bearer token provider (see Account Login)

Account Login

The widget is anonymous by default — history is scoped to a per-browser anon token. To scope history to a logged-in CHAPI account instead, the host page owns login and hands the widget a getAuthToken callback that returns the current account bearer token (or null when logged out). The widget attaches it as Authorization: Bearer <token> and, on first authenticated init, claims the visitor's anon history into the account.

The widget bundles no login UI — the embedding page is responsible for authenticating against CHAPI (it already must, so its origin is whitelisted for SSO).

Programmatic / Vanilla / Docusaurus — pass getAuthToken in the config:

const widget = initChatWidget(element, {
  apiBase: 'https://api.example.com',
  site: 'docs',
  siteName: 'Documentation',
  getAuthToken: () => myAuthClient.getAccessToken(), // string | null | Promise<...>
});

React — pass getAuthToken as a prop. Use a stable reference (useCallback); the token provider is intentionally excluded from the remount deps, so its identity changing will not remount the widget:

const getAuthToken = useCallback(() => myAuthClient.getAccessToken(), []);
<ChatWidget apiBase={...} site="docs" siteName="Documentation" getAuthToken={getAuthToken} />

Custom element <chat-widget> — a function can't be an HTML attribute, so set it as a property before the element connects:

<chat-widget id="chat" api-base="https://api.example.com" site="docs" site-name="Documentation"></chat-widget>
<script type="module">
  import '@classic-homes/chat-widget';
  const el = document.getElementById('chat');
  el.getAuthToken = () => myAuthClient.getAccessToken();
</script>

Set the property before the element is added to the DOM (or set it, then re-append) so it's present when the widget mounts.

After login/logout — the account is bound at mount. If the host's auth state changes while the widget is already mounted, call widget.refresh() to remount and re-run the account claim with the new token.

Widget API

The initChatWidget function returns a ChatWidgetAPI object with the following methods:

Conversation Management

const widget = initChatWidget(element, config);

// List all conversations
const conversations = await widget.listConversations();

// Get a specific conversation with messages
const conversation = await widget.getConversation(id);

// Switch to a conversation
await widget.selectConversation(id);

// Start a new conversation
await widget.startNewConversation();

// Delete a conversation
await widget.deleteConversation(id);

// Rename a conversation
await widget.renameConversation(id, 'New Title');

State Getters

// Get current conversation ID (null if new chat)
const currentId = await widget.getCurrentConversationId();

// Get current conversation title
const title = await widget.getCurrentTitle();

Lifecycle Methods

// Clear messages and reset chat
widget.clearMessages();

// Refresh widget (reload from storage)
widget.refresh();

// Destroy the widget
widget.destroy();

Events

Subscribe to widget events using the on method:

const widget = initChatWidget(element, config);

// Subscribe to events
const unsubscribe = widget.on('message:received', ({ message }) => {
  console.log('New message:', message.content);
});

// One-time subscription
widget.once('ready', () => {
  console.log('Widget is ready');
});

// Unsubscribe
unsubscribe();

Available Events

EventPayloadDescription
readyundefinedWidget has finished initializing
conversation:created{ id: string, title: string | null }New conversation created
conversation:selected{ id: string | null, title: string | null }Conversation selected/switched
conversation:deleted{ id: string }Conversation deleted
conversation:titleChanged{ id: string, title: string }Conversation renamed
conversations:updated{ conversations: ConversationPreview[] }Conversation list changed
message:sent{ message: Message }User sent a message
message:received{ message: Message }Assistant response received
error{ message: string, error?: Error }Error occurred

TypeScript Support

Full TypeScript definitions are included. Import types as needed:

import type {
  ChatWidgetConfig,
  ChatWidgetAPI,
  PageContext,
  Message,
  ConversationPreview,
} from '@classic-homes/chat-widget';

Styling

The widget is a self-contained Classic Theme island. Its stylesheet (theme tokens, the --chat-* bridge and the Tailwind utilities theme components need) is scoped to .chat-widget, so it neither depends on nor leaks into the host page's CSS. The script injects it automatically before the first render; hosts may also load @classic-homes/chat-widget/styles.css with a <link> to avoid a flash before the script runs (loading both is harmless).

The widget ships no web fonts: it uses Figtree when the host page loads it and falls back to the system UI font otherwise.

Brand color: pass primaryColor at init, which sets --chat-primary inline on the widget root. Other --chat-* variables are declared on .chat-widget; to override them, target that element with a more specific selector:

body .chat-widget {
  --chat-radius: 12px;
  --chat-header-bg: #f2f3ee;
}

Browser Support

  • Chrome/Edge 88+
  • Firefox 78+
  • Safari 14+

Decorative tints and shadows use color-mix() (Safari 16.2+, Chrome 111+, Firefox 113+); older browsers render without them.

The widget requires support for:

  • Custom Elements v1
  • ES Modules
  • CSS Custom Properties

License

MIT

版本与发布记录

@classic-homes/chat-widget 共发布 108 个版本,首次发布于 2026/01/26;过去 12 个月发布了 108 个版本。

版本发布日期距今
0.1.15latest2026/11/12今天
0.0.0-dev-20261111191944dev2026/11/12今天
0.0.0-dev-202611111807452026/11/12今天
0.0.0-dev-202611061500512026/11/065 天前
0.0.0-dev-202611042218052026/11/057 天前
0.1.142026/11/057 天前

关于 @classic-homes/chat-widget 的常见问题

@classic-homes/chat-widget 是什么?

High-performance embeddable chat widget built with Svelte

如何安装 @classic-homes/chat-widget?

在项目目录运行 npm install @classic-homes/chat-widget,或使用 pnpm add / yarn add / bun add。

@classic-homes/chat-widget 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@classic-homes/chat-widget 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@classic-homes/chat-widget 可以商用吗?

@classic-homes/chat-widget 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@classic-homes/chat-widget 的下载量有多少?

根据 npm 官方下载统计,@classic-homes/chat-widget 在 2026/10/10 – 2026/11/08 这 30 天内被下载 2,658 次,日均约 89 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@classic-homes/chat-widget 还在维护吗?

最新版本 0.1.15 发布于 2026/11/12(今天);至今共发布 108 个版本,其中过去 12 个月发布了 108 个;首次发布于 2026/01/26。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。