UNPKG

@klever-one/web-sdk

Version:

Web SDK for integrating real-time room management and streaming functionality into web applications

784 lines (759 loc) 29.1 kB
"use client"; import { useRef as x, useState as f, useEffect as y, useCallback as u, useMemo as M } from "react"; import { KleverOneClient as J } from "../core/klever-one-core-v0.1.0-beta.14.es.js"; import { jsx as n, jsxs as v } from "react/jsx-runtime"; const Q = ` /* Klever One SDK Styles - Scoped to prevent external interference */ /* All styles are scoped within .klever-one-sdk container */ /* This prevents SDK styles from affecting the parent application */ /* Layout utilities */ .klever-one-sdk.kos-relative, .klever-one-sdk .kos-relative { position: relative; } .klever-one-sdk.kos-absolute, .klever-one-sdk .kos-absolute { position: absolute; } .klever-one-sdk.kos-flex, .klever-one-sdk .kos-flex { display: flex; } .klever-one-sdk.kos-inline-flex, .klever-one-sdk .kos-inline-flex { display: inline-flex; } .klever-one-sdk.kos-flex-1, .klever-one-sdk .kos-flex-1 { flex: 1 1 0%; } .klever-one-sdk.kos-flex-col, .klever-one-sdk .kos-flex-col { flex-direction: column; } .klever-one-sdk.kos-flex-shrink-0, .klever-one-sdk .kos-flex-shrink-0 { flex-shrink: 0; } .klever-one-sdk.kos-items-center, .klever-one-sdk .kos-items-center { align-items: center; } .klever-one-sdk.kos-items-start, .klever-one-sdk .kos-items-start { align-items: flex-start; } .klever-one-sdk.kos-items-end, .klever-one-sdk .kos-items-end { align-items: flex-end; } .klever-one-sdk.kos-items-stretch, .klever-one-sdk .kos-items-stretch { align-items: stretch; } .klever-one-sdk.kos-justify-start, .klever-one-sdk .kos-justify-start { justify-content: flex-start; } .klever-one-sdk.kos-justify-end, .klever-one-sdk .kos-justify-end { justify-content: flex-end; } .klever-one-sdk.kos-justify-center, .klever-one-sdk .kos-justify-center { justify-content: center; } .klever-one-sdk.kos-justify-between, .klever-one-sdk .kos-justify-between { justify-content: space-between; } .klever-one-sdk.kos-gap-2, .klever-one-sdk .kos-gap-2 { gap: 0.5rem; } .klever-one-sdk.kos-gap-4, .klever-one-sdk .kos-gap-4 { gap: 1rem; } /* Sizing */ .klever-one-sdk.kos-w-full, .klever-one-sdk .kos-w-full { width: 100%; } .klever-one-sdk.kos-h-full, .klever-one-sdk .kos-h-full { height: 100%; } .klever-one-sdk.kos-w-auto, .klever-one-sdk .kos-w-auto { width: auto; } .klever-one-sdk.kos-h-auto, .klever-one-sdk .kos-h-auto { height: auto; } .klever-one-sdk.kos-min-w-0, .klever-one-sdk .kos-min-w-0 { min-width: 0; } .klever-one-sdk.kos-min-h-0, .klever-one-sdk .kos-min-h-0 { min-height: 0; } .klever-one-sdk.kos-w-4, .klever-one-sdk .kos-w-4 { width: 1rem; } .klever-one-sdk.kos-h-4, .klever-one-sdk .kos-h-4 { height: 1rem; } .klever-one-sdk.kos-w-11, .klever-one-sdk .kos-w-11 { width: 2.75rem; } .klever-one-sdk.kos-h-11, .klever-one-sdk .kos-h-11 { height: 2.75rem; } .klever-one-sdk.kos-w-80, .klever-one-sdk .kos-w-80 { width: 20rem; } .klever-one-sdk.kos-w-96, .klever-one-sdk .kos-w-96 { width: 24rem; } .klever-one-sdk.kos-h-96, .klever-one-sdk .kos-h-96 { height: 24rem; } .klever-one-sdk.kos-max-w-xs, .klever-one-sdk .kos-max-w-xs { max-width: 20rem; } .klever-one-sdk.kos-max-w-md, .klever-one-sdk .kos-max-w-md { max-width: 28rem; } .klever-one-sdk.kos-max-w-4xl, .klever-one-sdk .kos-max-w-4xl { max-width: 56rem; } /* Spacing */ .klever-one-sdk.kos-p-3, .klever-one-sdk .kos-p-3 { padding: 0.75rem; } .klever-one-sdk.kos-p-4, .klever-one-sdk .kos-p-4 { padding: 1rem; } .klever-one-sdk.kos-px-3, .klever-one-sdk .kos-px-3 { padding-left: 0.75rem; padding-right: 0.75rem; } .klever-one-sdk.kos-px-4, .klever-one-sdk .kos-px-4 { padding-left: 1rem; padding-right: 1rem; } .klever-one-sdk.kos-py-1, .klever-one-sdk .kos-py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; } .klever-one-sdk.kos-py-2, .klever-one-sdk .kos-py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; } .klever-one-sdk.kos-pr-2, .klever-one-sdk .kos-pr-2 { padding-right: 0.5rem; } .klever-one-sdk.kos-mx-auto, .klever-one-sdk .kos-mx-auto { margin-left: auto; margin-right: auto; } .klever-one-sdk.kos-space-y-4, .klever-one-sdk .kos-space-y-4 > * + * { margin-top: 1rem; } /* Positioning */ .klever-one-sdk.kos-top-0, .klever-one-sdk .kos-top-0 { top: 0; } .klever-one-sdk.kos-left-0, .klever-one-sdk .kos-left-0 { left: 0; } .klever-one-sdk.kos-z-0, .klever-one-sdk .kos-z-0 { z-index: 0; } .klever-one-sdk.kos-z-10, .klever-one-sdk .kos-z-10 { z-index: 10; } .klever-one-sdk.kos-z-20, .klever-one-sdk .kos-z-20 { z-index: 20; } /* Colors & Backgrounds */ .klever-one-sdk.kos-bg-black, .klever-one-sdk .kos-bg-black { background-color: #000; } .klever-one-sdk.kos-bg-gray-100, .klever-one-sdk .kos-bg-gray-100 { background-color: #f3f4f6; } .klever-one-sdk.kos-bg-gray-700, .klever-one-sdk .kos-bg-gray-700 { background-color: #374151; } .klever-one-sdk.kos-bg-blue-500, .klever-one-sdk .kos-bg-blue-500 { background-color: #3b82f6; } .klever-one-sdk.kos-bg-blue-600, .klever-one-sdk .kos-bg-blue-600 { background-color: #2563eb; } .klever-one-sdk.kos-bg-green-500, .klever-one-sdk .kos-bg-green-500 { background-color: #10b981; } .klever-one-sdk.kos-bg-yellow-500, .klever-one-sdk .kos-bg-yellow-500 { background-color: #f59e0b; } .klever-one-sdk.kos-bg-red-500, .klever-one-sdk .kos-bg-red-500 { background-color: #ef4444; } .klever-one-sdk.kos-bg-opacity-50, .klever-one-sdk .kos-bg-opacity-50 { background-color: rgba(0, 0, 0, 0.5); } /* Text */ .klever-one-sdk.kos-text-white, .klever-one-sdk .kos-text-white { color: #fff; } .klever-one-sdk.kos-text-xs, .klever-one-sdk .kos-text-xs { font-size: 0.75rem; line-height: 1rem; } .klever-one-sdk.kos-text-sm, .klever-one-sdk .kos-text-sm { font-size: 0.875rem; line-height: 1.25rem; } .klever-one-sdk.kos-text-blue-400, .klever-one-sdk .kos-text-blue-400 { color: #60a5fa; } .klever-one-sdk.kos-text-green-400, .klever-one-sdk .kos-text-green-400 { color: #4ade80; } .klever-one-sdk.kos-text-yellow-400, .klever-one-sdk .kos-text-yellow-400 { color: #fbbf24; } .klever-one-sdk.kos-text-red-400, .klever-one-sdk .kos-text-red-400 { color: #f87171; } /* Borders & Radius */ .klever-one-sdk.kos-rounded-lg, .klever-one-sdk .kos-rounded-lg { border-radius: 0.5rem; } .klever-one-sdk.kos-rounded-2xl, .klever-one-sdk .kos-rounded-2xl { border-radius: 1rem; } .klever-one-sdk.kos-rounded-full, .klever-one-sdk .kos-rounded-full { border-radius: 9999px; } .klever-one-sdk.kos-rounded-bl-none, .klever-one-sdk .kos-rounded-bl-none { border-bottom-left-radius: 0; } .klever-one-sdk.kos-rounded-br-none, .klever-one-sdk .kos-rounded-br-none { border-bottom-right-radius: 0; } /* Overflow & Scroll */ .klever-one-sdk.kos-overflow-y-auto, .klever-one-sdk .kos-overflow-y-auto { overflow-y: auto; } .klever-one-sdk.kos-overflow-y-hidden, .klever-one-sdk .kos-overflow-y-hidden { overflow-y: hidden; } .klever-one-sdk.kos-scroll-smooth, .klever-one-sdk .kos-scroll-smooth { scroll-behavior: smooth; } .klever-one-sdk.kos-resize-none, .klever-one-sdk .kos-resize-none { resize: none; } /* Text wrapping utilities */ .klever-one-sdk.kos-break-words, .klever-one-sdk .kos-break-words { overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; } .klever-one-sdk.kos-whitespace-pre-wrap, .klever-one-sdk .kos-whitespace-pre-wrap { white-space: pre-wrap; } .klever-one-sdk.kos-whitespace-normal, .klever-one-sdk .kos-whitespace-normal { white-space: normal; } .klever-one-sdk.kos-hyphens-auto, .klever-one-sdk .kos-hyphens-auto { hyphens: auto; -webkit-hyphens: auto; -ms-hyphens: auto; } /* Outline */ .klever-one-sdk.kos-outline-none, .klever-one-sdk .kos-outline-none { outline: none; } .klever-one-sdk.kos-outline-none, .klever-one-sdk .kos-outline-none:focus { outline: none; } /* Transitions */ .klever-one-sdk.kos-transition-colors, .klever-one-sdk .kos-transition-colors { transition-property: color, background-color, border-color; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; } .klever-one-sdk.kos-transition-all, .klever-one-sdk .kos-transition-all { transition-property: all; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; } /* Cursor */ .klever-one-sdk.kos-cursor-pointer, .klever-one-sdk .kos-cursor-pointer { cursor: pointer; } .klever-one-sdk.kos-cursor-not-allowed, .klever-one-sdk .kos-cursor-not-allowed { cursor: not-allowed !important; } /* Opacity */ .klever-one-sdk.kos-opacity-50, .klever-one-sdk .kos-opacity-50 { opacity: 0.5; } /* Animations - scoped with unique prefix */ @keyframes klever-one-sdk-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .klever-one-sdk.kos-animate-pulse, .klever-one-sdk .kos-animate-pulse { animation: klever-one-sdk-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } /* Hover states */ @media (hover: hover) { .klever-one-sdk.kos-hover-bg-blue-600, .klever-one-sdk .kos-hover-bg-blue-600:hover { background-color: #2563eb; } .klever-one-sdk.kos-hover-bg-green-600, .klever-one-sdk .kos-hover-bg-green-600:hover { background-color: #059669; } .klever-one-sdk.kos-hover-bg-red-600, .klever-one-sdk .kos-hover-bg-red-600:hover { background-color: #dc2626; } .klever-one-sdk.kos-hover-bg-gray-600, .klever-one-sdk .kos-hover-bg-gray-600:hover { background-color: #4b5563; } } /* Input & Textarea base styles */ .klever-one-sdk textarea { box-sizing: border-box; line-height: 1.5; font-family: inherit; } /* Disabled states */ .klever-one-sdk input:disabled, .klever-one-sdk textarea:disabled, .klever-one-sdk button:disabled { opacity: 0.5; cursor: not-allowed; } /* Keep disabled button colors unchanged on hover */ .klever-one-sdk button.kos-bg-blue-500:disabled:hover, .klever-one-sdk .kos-bg-blue-500:disabled:hover { background-color: #3b82f6 !important; } .klever-one-sdk button.kos-bg-green-500:disabled:hover, .klever-one-sdk .kos-bg-green-500:disabled:hover { background-color: #10b981 !important; } .klever-one-sdk button.kos-bg-red-500:disabled:hover, .klever-one-sdk .kos-bg-red-500:disabled:hover { background-color: #ef4444 !important; } .klever-one-sdk button.kos-bg-gray-700:disabled:hover, .klever-one-sdk .kos-bg-gray-700:disabled:hover { background-color: #374151 !important; } /* Focus states */ .klever-one-sdk input:focus, .klever-one-sdk textarea:focus, .klever-one-sdk button:focus { outline: 2px solid #3b82f6; outline-offset: 2px; } /* Placeholder */ .klever-one-sdk input::placeholder, .klever-one-sdk textarea::placeholder { color: #9ca3af; opacity: 1; } /* Pointer events - scoped */ .klever-one-sdk .pointer-events-none { pointer-events: none; } .klever-one-sdk .pointer-events-auto { pointer-events: auto; } /* React resizable - scoped */ .klever-one-sdk.react-resizable, .klever-one-sdk .react-resizable { position: relative; } .klever-one-sdk.react-resizable, .klever-one-sdk .react-resizable .react-resizable-handle { position: absolute; width: 20px; height: 20px; bottom: 0; right: 0; cursor: se-resize; background: rgba(0, 0, 0, 0.2); } /* Animations - scoped with unique prefix */ @keyframes klever-one-sdk-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } /* Pixel Streaming specific - scoped to SDK container to prevent global conflicts */ .klever-one-sdk #connectOverlay, .klever-one-sdk #disconnectOverlay, .klever-one-sdk #infoOverlay, .klever-one-sdk #afkOverlay { display: none !important; } .klever-one-sdk #streamingVideo { object-fit: cover !important; } `; let I = !1; function j() { if (I || typeof document > "u") return; const s = document.createElement("style"); s.id = "klever-one-sdk-styles", s.textContent = Q, document.head && (document.head.appendChild(s), I = !0); } typeof document < "u" && (document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", j) : j()), !0; let C = 0; function X(s) { const { apiKey: k, container: l, callbacks: i, conversation: d, ...g } = s, o = x(i); o.current = i; const e = x(null), [p, a] = f({ connection: "disconnected", recording: "idle", isStreaming: !1, isStreamingReady: !1, isConversationReady: !1, lastUpdated: /* @__PURE__ */ new Date() }), [c, b] = f({ reconnectAttempts: 0, messagesSent: 0, messagesReceived: 0, recordingSessions: 0, errorCount: 0 }), [N, z] = f({ messages: [], isStreaming: !1, isCompleted: !1 }), [O, w] = f([]); y(() => { try { const r = new J({ apiKey: k, container: l, conversation: d, ...g, callbacks: { ...o.current, // 기존 콜백과 상태 업데이트를 결합 onConnectionStatusChange: (t) => { a((h) => ({ ...h, connection: t })), o.current?.onConnectionStatusChange?.(t); }, onRecordingStatusChange: (t) => { a((h) => ({ ...h, recording: t })), o.current?.onRecordingStatusChange?.(t); }, onStreamingStatusChange: (t) => { a((h) => ({ ...h, isStreaming: t })), o.current?.onStreamingStatusChange?.(t); }, onMessageReceived: (t) => { w((h) => { const R = h.findIndex((S) => S.id === t.id); if (R >= 0) { const S = [...h]; return S[R] = t, S; } else return [...h, t]; }), o.current?.onMessageReceived?.(t); }, onReady: () => { a((t) => ({ ...t, isStreamingReady: !0, isConversationReady: !0 })), o.current?.onReady?.(); }, onDisconnect: () => { a({ connection: "disconnected", recording: "idle", isStreaming: !1, isStreamingReady: !1, isConversationReady: !1, lastUpdated: /* @__PURE__ */ new Date() }), w([]), o.current?.onDisconnect?.(); }, onError: (t) => { b((h) => ({ ...h, errorCount: h.errorCount + 1, lastErrorTime: /* @__PURE__ */ new Date() })), o.current?.onError?.(t); }, onRoomInfoUpdated: (t) => { o.current?.onRoomInfoUpdated?.(t); }, onLog: (t) => { o.current?.onLog?.(t); }, onRoomSessionTimeout: (t) => { o.current?.onRoomSessionTimeout?.(t); } } }); e.current = r, C++, a(r.getState()), b(r.getMetrics()), z(r.getConversationState()), w(r.getMessages()); } catch { } return () => { C--, C === 0 && e.current && e.current.getState().connection !== "disconnected" && e.current.disconnect(); }; }, [k, l]), y(() => { if (!e.current) return; const t = setInterval(() => { e.current && e.current.getState().connection !== "disconnected" && (a(e.current.getState()), b(e.current.getMetrics()), z(e.current.getConversationState()), w(e.current.getMessages())); }, 1e3); return () => clearInterval(t); }, []); const T = u(async () => { if (e.current) return e.current.connect(); throw new Error("KleverOneClient not initialized"); }, []), E = u(() => { e.current && e.current.disconnect(); }, []), D = u(async () => { if (e.current) return e.current.reconnect(); throw new Error("KleverOneClient not initialized"); }, []), K = u(async (r) => { if (e.current) return e.current.sendText(r); throw new Error("KleverOneClient not initialized"); }, []), A = u(async () => { if (e.current) return e.current.startRecording(); throw new Error("KleverOneClient not initialized"); }, []), P = u(async () => { if (e.current) return e.current.stopRecording(); throw new Error("KleverOneClient not initialized"); }, []), $ = u(() => e.current ? e.current.isReady() : !1, []), U = u(() => e.current ? e.current.isRecording() : !1, []), B = u((r, t) => { e.current && e.current.resize(r, t); }, []), H = u((r) => { e.current && e.current.sendAvatarNum(r); }, []), L = u((r) => { e.current && e.current.sendAvatarAppearanceChange(r); }, []), W = u((r) => { e.current && e.current.sendPlaceBackgroundChange(r); }, []), F = u((r) => { e.current && e.current.sendVoiceSetting(r); }, []), V = u( (r) => { e.current && e.current.sendMessage(r); }, [] ), q = u( async (r) => { if (e.current) return e.current.sendDataInChunks(r); throw new Error("KleverOneClient not initialized"); }, [] ), G = u( ((r) => { e.current && (Array.isArray(r), e.current.speak(r)); }), [] ); return { client: e.current, state: p, metrics: c, conversationState: N, messages: O, connect: T, disconnect: E, reconnect: D, sendText: K, speak: G, startRecording: A, stopRecording: P, isReady: $, isRecording: U, // 고급 기능들 resize: B, sendAvatarNum: H, sendAvatarAppearanceChange: L, sendPlaceBackgroundChange: W, sendVoiceSetting: F, sendMessage: V, sendDataInChunks: q }; } const m = ({ size: s = 24, color: k = "currentColor", stroke: l = 2, className: i = "", style: d, children: g, name: o }) => /* @__PURE__ */ n( "svg", { width: s, height: s, viewBox: "0 0 24 24", fill: "none", stroke: k, strokeWidth: l, strokeLinecap: "round", strokeLinejoin: "round", className: i, style: d, role: "img", "aria-label": o, children: g } ), Y = (s) => /* @__PURE__ */ v( m, { name: "Send", ...s, children: [ /* @__PURE__ */ n("path", { d: "M10 14l11 -11" }), /* @__PURE__ */ n("path", { d: "M21 3l-6.5 18a.55 .55 0 0 1 -1 0l-3.5 -7l-7 -3.5a.55 .55 0 0 1 0 -1l18 -6.5" }) ] } ), Z = (s) => /* @__PURE__ */ v( m, { name: "Microphone", ...s, children: [ /* @__PURE__ */ n("path", { d: "M9 2m0 3a3 3 0 0 1 3 -3h0a3 3 0 0 1 3 3v5a3 3 0 0 1 -3 3h0a3 3 0 0 1 -3 -3z" }), /* @__PURE__ */ n("path", { d: "M5 10a7 7 0 0 0 14 0" }), /* @__PURE__ */ n("path", { d: "M8 21l8 0" }), /* @__PURE__ */ n("path", { d: "M12 17l0 4" }) ] } ), _ = (s) => /* @__PURE__ */ n( m, { name: "PlayerStop", ...s, children: /* @__PURE__ */ n("path", { d: "M5 5m0 2a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2z" }) } ), ee = (s) => /* @__PURE__ */ v( m, { name: "PhoneCall", ...s, children: [ /* @__PURE__ */ n("path", { d: "M5 4h4l2 5l-2.5 1.5a11 11 0 0 0 5 5l1.5 -2.5l5 2v4a2 2 0 0 1 -2 2a16 16 0 0 1 -15 -15a2 2 0 0 1 2 -2" }), /* @__PURE__ */ n("path", { d: "M15 7a2 2 0 0 1 2 2" }), /* @__PURE__ */ n("path", { d: "M15 3a6 6 0 0 1 6 6" }) ] } ), oe = (s) => /* @__PURE__ */ v( m, { name: "PhoneOff", ...s, children: [ /* @__PURE__ */ n("path", { d: "M3 21l18 -18" }), /* @__PURE__ */ n("path", { d: "M5.831 14.161a15.946 15.946 0 0 1 -2.831 -8.161a2 2 0 0 1 2 -2h4l2 5l-2.5 1.5c.108 .22 .223 .435 .345 .645m1.751 2.277c.843 .84 1.822 1.544 2.904 2.078l1.5 -2.5l5 2v4a2 2 0 0 1 -2 2a15.963 15.963 0 0 1 -10.344 -4.657" }) ] } ), ne = (s) => /* @__PURE__ */ v( m, { name: "Wifi", ...s, children: [ /* @__PURE__ */ n("path", { d: "M12 18l.01 0" }), /* @__PURE__ */ n("path", { d: "M9.172 15.172a4 4 0 0 1 5.656 0" }), /* @__PURE__ */ n("path", { d: "M6.343 12.343a8 8 0 0 1 11.314 0" }), /* @__PURE__ */ n("path", { d: "M3.515 9.515c4.686 -4.687 12.284 -4.687 17 0" }) ] } ), se = (s) => /* @__PURE__ */ v( m, { name: "WifiOff", ...s, children: [ /* @__PURE__ */ n("path", { d: "M12 18l.01 0" }), /* @__PURE__ */ n("path", { d: "M9.172 15.172a4 4 0 0 1 5.656 0" }), /* @__PURE__ */ n("path", { d: "M6.343 12.343a7.963 7.963 0 0 1 3.864 -2.14m4.163 .155a7.965 7.965 0 0 1 3.287 2" }), /* @__PURE__ */ n("path", { d: "M3.515 9.515a12 12 0 0 1 3.544 -2.455m3.101 -.92a12 12 0 0 1 10.325 3.374" }), /* @__PURE__ */ n("path", { d: "M3 3l18 18" }) ] } ), re = ({ state: s }) => { const k = s.connection === "connected", l = s.connection === "connecting", i = k ? "kos-text-green-400" : l ? "kos-text-yellow-400" : "kos-text-red-400", d = k ? "연결됨" : l ? "연결 중..." : "연결 안됨", g = k || l ? ne : se; return /* @__PURE__ */ v( "div", { className: `klever-one-sdk kos-flex kos-items-center kos-gap-2 kos-px-3 kos-py-1 kos-bg-black kos-bg-opacity-50 kos-rounded-full kos-text-white kos-text-xs ${i}`, children: [ /* @__PURE__ */ n( g, { className: `kos-w-4 kos-h-4 ${l ? "kos-animate-pulse" : ""}` } ), /* @__PURE__ */ n("span", { children: d }), s.isStreaming && /* @__PURE__ */ n("span", { className: "kos-text-sm kos-text-blue-400", children: "응답 생성 중..." }) ] } ); }, te = ({ state: s, connect: k, disconnect: l }) => { const i = s.connection === "connected", d = s.connection === "connecting"; return /* @__PURE__ */ n( "button", { onClick: () => { i || d ? l() : k(); }, disabled: d, className: `klever-one-sdk kos-w-11 kos-h-11 kos-inline-flex kos-items-center kos-justify-center kos-rounded-full kos-transition-colors ${i ? "kos-bg-red-500 kos-hover-bg-red-600 kos-text-white kos-cursor-pointer" : d ? "kos-bg-yellow-500 kos-text-white kos-animate-pulse kos-cursor-not-allowed" : "kos-bg-green-500 kos-hover-bg-green-600 kos-text-white kos-cursor-pointer"}`, children: i || d ? /* @__PURE__ */ n(oe, { size: 20 }) : /* @__PURE__ */ n(ee, { size: 20 }) } ); }, ke = ({ state: s, isReady: k, sendText: l, startRecording: i, stopRecording: d }) => { const g = x(null), [o, e] = f(""); y(() => { const c = g.current; if (c) { c.style.height = "44px"; const b = Math.min(Math.max(c.scrollHeight, 44), 120); c.style.height = `${b}px`; } }, [o]); const p = async (c) => { if (c.preventDefault(), !(!o.trim() || s.isStreaming)) try { await l(o), e(""); } catch { } }, a = async () => { try { s.recording === "recording" ? await d() : await i(); } catch { } }; return /* @__PURE__ */ v( "form", { onSubmit: p, className: "klever-one-sdk kos-w-full kos-flex kos-items-stretch kos-gap-4", children: [ /* @__PURE__ */ n( "textarea", { ref: g, className: "kos-flex-1 kos-min-w-0 kos-bg-gray-700 kos-text-white kos-p-3 kos-rounded-lg kos-resize-none kos-outline-none kos-overflow-y-hidden kos-transition-all", placeholder: "메시지를 입력하세요...", value: o, onChange: (c) => e(c.target.value), disabled: s.isStreaming, rows: 1, style: { minHeight: "44px", maxHeight: "120px" }, onKeyDown: (c) => { c.key === "Enter" && !c.shiftKey && (c.preventDefault(), p(c)); } } ), /* @__PURE__ */ v("div", { className: "kos-flex kos-items-center kos-gap-2 kos-flex-shrink-0", children: [ /* @__PURE__ */ n( "button", { type: "button", onClick: a, disabled: s.isStreaming || !k(), className: `kos-w-11 kos-h-11 kos-inline-flex kos-items-center kos-justify-center kos-rounded-full kos-transition-colors ${s.recording === "recording" ? "kos-bg-red-500 kos-text-white kos-animate-pulse kos-cursor-pointer" : "kos-bg-gray-700 kos-hover-bg-gray-600 kos-text-white kos-cursor-pointer"}`, children: s.recording === "recording" ? /* @__PURE__ */ n(_, { size: 20 }) : /* @__PURE__ */ n(Z, { size: 20 }) } ), /* @__PURE__ */ n( "button", { type: "submit", disabled: !o.trim() || s.isStreaming || !k(), className: "kos-w-11 kos-h-11 kos-inline-flex kos-items-center kos-justify-center kos-bg-blue-500 kos-text-white kos-rounded-full kos-cursor-pointer kos-hover-bg-blue-600 kos-transition-colors", children: /* @__PURE__ */ n(Y, { size: 20 }) } ) ] }) ] } ); }, le = ({ messages: s }) => { const k = x(null), [l, i] = f(!1), d = M(() => { const o = /* @__PURE__ */ new Map(); return s.forEach((e) => { e.id ? o.set(e.id, e) : o.set(Symbol("unique-msg"), e); }), Array.from(o.values()); }, [s]); return y(() => { k.current && !l && (k.current.scrollTop = k.current.scrollHeight); }, [d, l]), /* @__PURE__ */ n( "div", { ref: k, onScroll: () => { if (k.current) { const { scrollTop: o, scrollHeight: e, clientHeight: p } = k.current, a = e - o - p < 10; i(!a); } }, className: "klever-one-sdk kos-flex-1 kos-overflow-y-auto kos-space-y-4 kos-pr-2 kos-scroll-smooth", children: d.map((o, e) => /* @__PURE__ */ n( "div", { className: `kos-flex kos-items-end kos-gap-2 ${o.role === "user" ? "kos-justify-end" : "kos-justify-start"}`, children: /* @__PURE__ */ n( "div", { className: `kos-px-4 kos-py-2 kos-rounded-2xl kos-max-w-xs kos-break-words kos-whitespace-pre-wrap ${o.role === "user" ? "kos-bg-blue-600 kos-text-white kos-rounded-br-none" : "kos-bg-gray-700 kos-text-white kos-rounded-bl-none"}`, children: /* @__PURE__ */ n("span", { className: "kos-text-sm kos-break-words", children: o.fullContent || o.content }) } ) }, o.id || `msg-${e}` )) } ); }, ie = ({ apiKey: s, width: k = 800, className: l = "" }) => { const i = x(null), d = M(() => typeof document < "u" ? document.createElement("div") : {}, []), g = M( () => ({ onReady: () => /* @__PURE__ */ console.log("디지털 휴먼 준비 완료!"), onMessageReceived: (a) => /* @__PURE__ */ console.log("받은 메시지:", a), onError: (a) => alert(a?.message || "오류가 발생했습니다.") }), [] ), o = X({ apiKey: s, container: i.current || d, callbacks: g }); y(() => () => { if (o.client) try { o.disconnect(); } catch { } }, [o.client]); const e = async () => { if (i.current && o.client) try { await o.connect(); } catch { } }, p = () => { o.client && o.disconnect(); }; return /* @__PURE__ */ v("div", { className: `klever-one-sdk kos-flex kos-gap-4 ${l}`, children: [ /* @__PURE__ */ v( "div", { className: "kos-flex kos-flex-col kos-gap-4", style: { width: `${k}px` }, children: [ /* @__PURE__ */ v( "div", { className: "kos-relative kos-bg-black kos-rounded-lg", style: { height: "400px" }, children: [ /* @__PURE__ */ n( "div", { ref: i, className: "kos-w-full kos-h-full kos-rounded-lg" } ), /* @__PURE__ */ v("div", { className: "kos-absolute kos-top-0 kos-left-0 kos-w-full kos-h-full kos-p-4 kos-flex kos-justify-between kos-items-start pointer-events-none", children: [ /* @__PURE__ */ n(re, { state: o.state }), /* @__PURE__ */ n("div", { className: "pointer-events-auto", children: /* @__PURE__ */ n( te, { state: o.state, connect: e, disconnect: p } ) }) ] }) ] } ), /* @__PURE__ */ n( ke, { state: o.state, isReady: o.isReady, sendText: o.sendText, startRecording: o.startRecording, stopRecording: o.stopRecording } ) ] } ), /* @__PURE__ */ n( "div", { className: "kos-flex kos-flex-col kos-bg-gray-100 kos-rounded-lg kos-p-4", style: { minWidth: "384px" }, children: /* @__PURE__ */ n(le, { messages: o.messages }) } ) ] }); }, ue = ({ apiKey: s }) => { const [k, l] = f(!1); return /* @__PURE__ */ n("div", { className: "klever-one-sdk kos-p-4", children: /* @__PURE__ */ n( ie, { apiKey: s, width: 800, isFullscreen: k, onToggleFullscreen: () => l(!k), className: "kos-max-w-4xl kos-mx-auto" } ) }); }; export { re as ConnectionStatusIndicator, te as ConnectionToggleButton, J as KleverOneClient, ke as MessageInput, le as MessageList, ie as UnifiedConversation, ue as UnifiedConversationExample, X as useKleverOneClient };