@courseecho/ai-widget-react 1.0.25 → 1.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,6 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  * Usage: <AiChatWidget config={...} apiKey="..." />
5
5
  */
6
6
  import { useRef, useEffect, useState, useCallback } from 'react';
7
+ import { ICONS } from '@courseecho/ai-core-sdk';
7
8
  import { useAiWidget } from './hooks';
8
9
  import { ShadowWrapper } from './ShadowWrapper';
9
10
  // Chat sound — Web Audio API (no external files)
@@ -217,10 +218,10 @@ export const AiChatWidget = ({ config, apiKey, jwtToken, title = 'AI Assistant',
217
218
  const themeClass = mergedConfig.theme === 'dark' ? 'aiwg-dark' : '';
218
219
  const minimizedClass = isMinimized ? 'aiwg-minimized' : '';
219
220
  const poweredByLabel = poweredBy || 'CourseEcho.com';
220
- return (_jsx(ShadowWrapper, { children: _jsxs("div", { className: `aiwg-root ${themeClass} ${minimizedClass} ${className || ''}`, style: { height: isMinimized ? '72px' : expandedHeight }, children: [_jsxs("div", { className: "aiwg-header", onClick: () => isMinimized && setIsMinimized(false), children: [_jsx("div", { className: "aiwg-avatar" }), _jsxs("div", { className: "aiwg-header-info", children: [_jsx("div", { className: "aiwg-title", children: title }), _jsxs("div", { className: "aiwg-subtitle", children: [_jsx("span", { className: "aiwg-online-dot" }), subtitle] })] }), _jsx("button", { className: "aiwg-minimize-btn", "aria-label": "Minimize", onClick: (e) => { e.stopPropagation(); setIsMinimized(true); }, children: "\u2715" })] }), _jsxs("div", { className: "aiwg-messages", children: [messages.length === 0 && (_jsxs("div", { className: "aiwg-welcome", children: [_jsx("div", { className: "aiwg-welcome-icon" }), _jsx("h4", { children: "Hi there! I'm your AI assistant." }), _jsx("p", { children: "Ask me anything or pick a suggestion below." })] })), messages.map((msg) => {
221
+ return (_jsx(ShadowWrapper, { children: _jsxs("div", { className: `aiwg-root ${themeClass} ${minimizedClass} ${className || ''}`, style: { height: isMinimized ? '72px' : expandedHeight }, children: [_jsxs("div", { className: "aiwg-header", onClick: () => isMinimized && setIsMinimized(false), children: [_jsx("div", { className: "aiwg-avatar", dangerouslySetInnerHTML: { __html: ICONS.BOT } }), _jsxs("div", { className: "aiwg-header-info", children: [_jsx("div", { className: "aiwg-title", children: title }), _jsxs("div", { className: "aiwg-subtitle", children: [_jsx("span", { className: "aiwg-online-dot" }), subtitle] })] }), _jsx("button", { className: "aiwg-minimize-btn", "aria-label": "Minimize", onClick: (e) => { e.stopPropagation(); setIsMinimized(true); }, dangerouslySetInnerHTML: { __html: ICONS.CLOSE } })] }), _jsxs("div", { className: "aiwg-messages", children: [messages.length === 0 && (_jsxs("div", { className: "aiwg-welcome", children: [_jsx("div", { className: "aiwg-welcome-icon", dangerouslySetInnerHTML: { __html: ICONS.WAVE } }), _jsx("h4", { children: "Hi there! I'm your AI assistant." }), _jsx("p", { children: "Ask me anything or pick a suggestion below." })] })), messages.map((msg) => {
221
222
  const isUser = msg.role === 'user';
222
223
  const time = new Date(msg.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
223
- return (_jsxs("div", { className: `aiwg-msg ${isUser ? 'aiwg-msg--user' : 'aiwg-msg--bot'}`, children: [_jsx("div", { className: "aiwg-msg-avatar", children: isUser ? '' : '' }), _jsxs("div", { className: "aiwg-msg-body", children: [_jsx("div", { className: "aiwg-msg-bubble", children: isUser ? msg.content : renderMarkdown(msg.content) }), _jsx("div", { className: "aiwg-msg-time", children: time })] })] }, msg.id));
224
- }), isLoading && (_jsxs("div", { className: "aiwg-msg aiwg-msg--bot", children: [_jsx("div", { className: "aiwg-msg-avatar" }), _jsx("div", { className: "aiwg-msg-body", children: _jsx("div", { className: "aiwg-msg-bubble aiwg-typing", children: _jsxs("div", { className: "aiwg-typing-dots", children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] }) }) })] })), error && _jsxs("div", { className: "aiwg-error", style: { display: 'block' }, children: [" ", error] }), _jsx("div", { ref: messagesEndRef })] }), chipsVisible && messages.length === 0 && (_jsx("div", { className: "aiwg-chip-row", children: allSugs.slice(0, 4).map(s => (_jsxs("button", { className: "aiwg-chip", onClick: () => selectSuggestion(s.text), children: [s.icon, " ", s.text] }, s.id))) })), _jsxs("div", { className: "aiwg-input-area", children: [showSuggestions && filteredSugs.length > 0 && (_jsxs("div", { className: "aiwg-suggestions", children: [_jsx("div", { className: "aiwg-suggestions-header", children: "Suggestions" }), _jsx("div", { className: "aiwg-suggestions-list", children: filteredSugs.map((s, i) => (_jsxs("div", { className: `aiwg-suggestion-item${i === activeIdx ? ' aiwg-active' : ''}`, onMouseEnter: () => setActiveIdx(i), onClick: () => selectSuggestion(s.text), children: [s.icon && _jsx("span", { className: "aiwg-suggestion-icon", children: s.icon }), _jsxs("div", { className: "aiwg-suggestion-main", children: [_jsx("div", { className: "aiwg-suggestion-text", children: s.text }), s.description && _jsx("div", { className: "aiwg-suggestion-desc", children: s.description })] }), s.category && _jsx("span", { className: "aiwg-suggestion-badge", children: s.category })] }, s.id))) }), _jsxs("div", { className: "aiwg-kbd-hint", children: [_jsxs("span", { children: [_jsx("kbd", {}), " navigate"] }), _jsxs("span", { children: [_jsx("kbd", {}), " select"] }), _jsxs("span", { children: [_jsx("kbd", { children: "Esc" }), " close"] })] })] })), _jsxs("div", { className: "aiwg-input-row", children: [_jsx("textarea", { ref: inputRef, className: "aiwg-input", placeholder: placeholder, value: userInput, rows: 1, onChange: handleInputChange, onFocus: () => filterSugs(userInput), onKeyDown: handleKeyDown, disabled: isLoading, "aria-label": "Chat message input" }), _jsx("button", { className: "aiwg-send-btn", type: "button", disabled: isLoading || !userInput.trim(), onClick: () => doSend(userInput), "aria-label": "Send", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), _jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] }) })] })] }), _jsxs("div", { className: "aiwg-powered", children: ["Powered by", ' ', _jsx("a", { href: poweredByUrl, target: "_blank", rel: "noopener noreferrer", children: poweredByLabel })] })] }) }));
224
+ return (_jsxs("div", { className: `aiwg-msg ${isUser ? 'aiwg-msg--user' : 'aiwg-msg--bot'}`, children: [_jsx("div", { className: "aiwg-msg-avatar", dangerouslySetInnerHTML: { __html: isUser ? ICONS.USER : ICONS.BOT } }), _jsxs("div", { className: "aiwg-msg-body", children: [_jsx("div", { className: "aiwg-msg-bubble", children: isUser ? msg.content : renderMarkdown(msg.content) }), _jsx("div", { className: "aiwg-msg-time", children: time })] })] }, msg.id));
225
+ }), isLoading && (_jsxs("div", { className: "aiwg-msg aiwg-msg--bot", children: [_jsx("div", { className: "aiwg-msg-avatar", dangerouslySetInnerHTML: { __html: ICONS.BOT } }), _jsx("div", { className: "aiwg-msg-body", children: _jsx("div", { className: "aiwg-msg-bubble aiwg-typing", children: _jsxs("div", { className: "aiwg-typing-dots", children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] }) }) })] })), error && _jsxs("div", { className: "aiwg-error", style: { display: 'block' }, children: [" ", error] }), _jsx("div", { ref: messagesEndRef })] }), chipsVisible && messages.length === 0 && (_jsx("div", { className: "aiwg-chip-row", children: allSugs.slice(0, 4).map(s => (_jsxs("button", { className: "aiwg-chip", onClick: () => selectSuggestion(s.text), children: [s.icon, " ", s.text] }, s.id))) })), _jsxs("div", { className: "aiwg-input-area", children: [showSuggestions && filteredSugs.length > 0 && (_jsxs("div", { className: "aiwg-suggestions", children: [_jsx("div", { className: "aiwg-suggestions-header", children: "Suggestions" }), _jsx("div", { className: "aiwg-suggestions-list", children: filteredSugs.map((s, i) => (_jsxs("div", { className: `aiwg-suggestion-item${i === activeIdx ? ' aiwg-active' : ''}`, onMouseEnter: () => setActiveIdx(i), onClick: () => selectSuggestion(s.text), children: [s.icon && _jsx("span", { className: "aiwg-suggestion-icon", children: s.icon }), _jsxs("div", { className: "aiwg-suggestion-main", children: [_jsx("div", { className: "aiwg-suggestion-text", children: s.text }), s.description && _jsx("div", { className: "aiwg-suggestion-desc", children: s.description })] }), s.category && _jsx("span", { className: "aiwg-suggestion-badge", children: s.category })] }, s.id))) }), _jsxs("div", { className: "aiwg-kbd-hint", children: [_jsxs("span", { children: [_jsx("kbd", {}), " navigate"] }), _jsxs("span", { children: [_jsx("kbd", {}), " select"] }), _jsxs("span", { children: [_jsx("kbd", { children: "Esc" }), " close"] })] })] })), _jsxs("div", { className: "aiwg-input-row", children: [_jsx("textarea", { ref: inputRef, className: "aiwg-input", placeholder: placeholder, value: userInput, rows: 1, onChange: handleInputChange, onFocus: () => filterSugs(userInput), onKeyDown: handleKeyDown, disabled: isLoading, "aria-label": "Chat message input" }), _jsx("button", { className: "aiwg-send-btn", type: "button", disabled: isLoading || !userInput.trim(), onClick: () => doSend(userInput), "aria-label": "Send", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), _jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] }) })] })] }), _jsxs("div", { className: "aiwg-powered", children: ["Powered by", ' ', _jsx("a", { href: poweredByUrl, target: "_blank", rel: "noopener noreferrer", children: poweredByLabel })] })] }) }));
225
226
  };
226
227
  export default AiChatWidget;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@courseecho/ai-widget-react",
3
- "version": "1.0.25",
3
+ "version": "1.0.26",
4
4
  "description": "React AI chat widget component for CourseEcho.",
5
5
  "license": "MIT",
6
6
  "author": "CourseEcho",