UNPKG

smart-ai-chatbot

Version:

A customizable AI chatbot component for React and web applications.

93 lines (92 loc) 5.59 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useState, useEffect, useCallback } from "react"; import * as use from "@tensorflow-models/universal-sentence-encoder"; import * as tf from "@tensorflow/tfjs"; import { FaRobot, FaTimes, FaPaperPlane } from "react-icons/fa"; const Chatbot = ({ dataset, title = "AI Chatbot", theme = "dark", }) => { const [message, setMessage] = useState(""); const [reply, setReply] = useState(""); const [model, setModel] = useState(null); const [isOpen, setIsOpen] = useState(false); const [isLoading, setIsLoading] = useState(false); useEffect(() => { if (isOpen && !model) { use.load().then(setModel); } }, [isOpen, model]); const handleSubmit = useCallback(() => __awaiter(void 0, void 0, void 0, function* () { if (!model || !message.trim()) return; setIsLoading(true); setReply(""); try { const inputEmbedding = yield model.embed([message]); const questionEmbeddings = yield model.embed(dataset.map((q) => q.question)); const similarities = tf.matMul(tf.tensor2d(inputEmbedding.arraySync(), inputEmbedding.shape), tf.tensor(questionEmbeddings.arraySync(), questionEmbeddings.shape), false, true); const bestMatchIndex = similarities.argMax(1).dataSync()[0]; setReply(dataset[bestMatchIndex].answer); } catch (error) { console.error(error); setReply("Sorry, something went wrong. Please try again."); } finally { setMessage(""); setIsLoading(false); } }), [model, message, dataset]); const handleKeyDown = (e) => { if (e.key === "Enter") { e.preventDefault(); // Prevent default form submission handleSubmit(); } }; const handleClose = () => { setIsOpen(false); setMessage(""); setReply(""); }; const themes = { dark: { backgroundColor: "#1A1A1A", buttonColor: "#4CAF50", textColor: "#FFFFFF", inputBackgroundColor: "#121212", borderColor: "#4CAF50", }, light: { backgroundColor: "#FFFFFF", buttonColor: "#2196F3", textColor: "#000000", inputBackgroundColor: "#F5F5F5", borderColor: "#2196F3", }, }; const selectedTheme = themes[theme]; return (_jsx("section", { className: "fixed bottom-6 right-6 z-50", children: isOpen ? (_jsxs("div", { className: "p-6 rounded-lg shadow-2xl w-96 max-w-[90vw] border", style: { backgroundColor: selectedTheme.backgroundColor, color: selectedTheme.textColor, borderColor: selectedTheme.borderColor, }, children: [_jsxs("div", { className: "flex justify-between items-center mb-4", children: [_jsxs("h3", { className: "text-lg font-bold flex items-center space-x-2", children: [_jsx(FaRobot, {}), _jsx("span", { children: title })] }), _jsx("button", { onClick: handleClose, className: "text-gray-400 hover:text-white", children: _jsx(FaTimes, { size: 20 }) })] }), _jsxs("div", { className: "mb-4 flex space-x-2", children: [_jsx("input", { type: "text", value: message, onChange: (e) => setMessage(e.target.value), onKeyDown: handleKeyDown, placeholder: "Ask me anything...", className: "w-full p-3 rounded-lg border focus:ring focus:ring-blue-500", style: { backgroundColor: selectedTheme.inputBackgroundColor, color: selectedTheme.textColor, borderColor: selectedTheme.borderColor, }, required: true }), _jsx("button", { type: "button" // Keep as type="button" , onClick: handleSubmit, disabled: isLoading, className: "p-3 rounded-lg hover:bg-opacity-80 disabled:bg-gray-500 flex items-center justify-center", style: { backgroundColor: selectedTheme.buttonColor }, children: _jsx(FaPaperPlane, { size: 18 }) })] }), !reply && !isLoading ? null : (_jsx("div", { className: "p-4 rounded-lg border min-h-[50px]", style: { backgroundColor: selectedTheme.inputBackgroundColor, borderColor: selectedTheme.borderColor, }, children: isLoading ? (_jsx("p", { className: "animate-pulse", children: "\u23F3 Typing..." })) : (_jsx("p", { children: reply })) }))] })) : (_jsxs("button", { onClick: () => setIsOpen(true), className: "p-4 rounded-full shadow-lg flex items-center space-x-2", style: { backgroundColor: selectedTheme.backgroundColor, color: selectedTheme.textColor, }, children: [_jsx(FaRobot, { size: 20 }), _jsx("span", { children: "Chat" })] })) })); }; export default Chatbot;