feat: add support chat widget demo and state management

- Implemented SupportWidgetDemo component for configuring and mounting the support chat widget.
- Introduced Zustand store for managing support chat state, including message handling and socket connection.
- Created support host bridge for communication between the widget and parent window.
- Added utility functions for JWT token generation and local storage management.
- Enhanced user experience with notifications for new messages and chat status updates.
This commit is contained in:
mlogclub
2026-05-30 14:00:23 +08:00
parent bcab31eaa8
commit 86ff71596d
28 changed files with 139 additions and 139 deletions
+2 -2
View File
@@ -16,7 +16,7 @@ export type CSAgentConfig = {
width?: string
}
export type KefuChatRuntimeConfig = Omit<CSAgentConfig, "getUserToken"> & {
export type SupportChatRuntimeConfig = Omit<CSAgentConfig, "getUserToken"> & {
/** Used only by /support/chat to exchange for a chat token; not part of CSAgentConfig. */
userToken?: string
}
@@ -33,7 +33,7 @@ declare global {
interface Window {
CSAgentConfig?: CSAgentConfig
CSAgentWidget?: CSAgentWidget
__CS_AGENT_WIDGET_CONFIG__?: KefuChatRuntimeConfig
__CS_AGENT_WIDGET_CONFIG__?: SupportChatRuntimeConfig
__CS_AGENT_WIDGET_STATE__?: unknown
}
}
+4 -4
View File
@@ -1,7 +1,7 @@
import type {
CSAgentConfig,
CSAgentWidget,
KefuChatRuntimeConfig,
SupportChatRuntimeConfig,
} from "./config-types"
type NormalizedCSAgentConfig = CSAgentConfig & {
@@ -24,7 +24,7 @@ type WidgetState = {
frameHideTimer: number | null
frameDestroyTimer: number | null
config: NormalizedCSAgentConfig | null
frameConfig: KefuChatRuntimeConfig | null
frameConfig: SupportChatRuntimeConfig | null
frameUrl: URL | null
animationDuration: number
listenerBound?: boolean
@@ -57,7 +57,7 @@ function getLauncherText() {
}
type FrameMessage =
| { type: "cs-agent:init"; payload: KefuChatRuntimeConfig }
| { type: "cs-agent:init"; payload: SupportChatRuntimeConfig }
| { type: "cs-agent:open" }
| { type: "cs-agent:minimize" }
| { type: "cs-agent:maximized"; payload: { isMaximized: boolean } }
@@ -135,7 +135,7 @@ type FrameMessage =
function createFrameConfig(
config: NormalizedCSAgentConfig,
userToken: string
): KefuChatRuntimeConfig {
): SupportChatRuntimeConfig {
const { getUserToken: _getUserToken, ...payload } = config
if (userToken) {
return { ...payload, userToken }
+4 -4
View File
@@ -1,6 +1,6 @@
import type { KefuChatRuntimeConfig } from "@/lib/sdk/config-types"
import type { SupportChatRuntimeConfig } from "@/lib/sdk/config-types"
export function readKefuChatRuntimeConfig(): KefuChatRuntimeConfig {
export function readSupportChatRuntimeConfig(): SupportChatRuntimeConfig {
if (typeof window === "undefined") {
return {
channelId: "",
@@ -10,7 +10,7 @@ export function readKefuChatRuntimeConfig(): KefuChatRuntimeConfig {
}
const query = new URLSearchParams(window.location.search)
const fallback: KefuChatRuntimeConfig = {
const fallback: SupportChatRuntimeConfig = {
channelId:
query.get("channelId") ??
process.env.NEXT_PUBLIC_OPEN_IM_CHANNEL_ID?.trim() ??
@@ -46,7 +46,7 @@ export function readKefuChatRuntimeConfig(): KefuChatRuntimeConfig {
return fallback
}
export function setKefuChatRuntimeConfig(config: KefuChatRuntimeConfig) {
export function setSupportChatRuntimeConfig(config: SupportChatRuntimeConfig) {
if (typeof window === "undefined") {
return
}