UNPKG

@jeanmemory/react

Version:

React SDK for Jean Memory - Build personalized AI chatbots in 5 lines of code

184 lines (183 loc) 8.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.JeanChatComplete = JeanChatComplete; const jsx_runtime_1 = require("react/jsx-runtime"); /** * Jean Memory React SDK - Complete Chat Component * Drop-in chat interface with authentication, input, and messages */ const react_1 = require("react"); const provider_1 = require("./provider"); const JeanAuthGuard_1 = require("./JeanAuthGuard"); /** * Complete chat component with authentication guard * Handles everything: auth, input, messages, sign out * * @example * ```jsx * <JeanProvider apiKey="your-key"> * <JeanChatComplete /> * </JeanProvider> * ``` */ function JeanChatComplete({ style, className, placeholder = "Ask Jean anything...", welcomeMessage = "Start a conversation! I remember everything we discuss.", examplePrompts = [ "What did I work on recently?", "Remember that I prefer TypeScript", "What are my current projects?", "Help me plan my week" ], showExamples = true, showSignOut = true, header, chatHeight = 400 }) { return ((0, jsx_runtime_1.jsx)(JeanAuthGuard_1.JeanAuthGuard, { children: (0, jsx_runtime_1.jsx)(JeanChatInterface, { style: style, className: className, placeholder: placeholder, welcomeMessage: welcomeMessage, examplePrompts: examplePrompts, showExamples: showExamples, showSignOut: showSignOut, header: header, chatHeight: chatHeight }) })); } /** * Internal chat interface (assumes user is authenticated) */ function JeanChatInterface({ style, className, placeholder, welcomeMessage, examplePrompts, showExamples, showSignOut, header, chatHeight }) { const { sendMessage, messages, isLoading, user, signOut } = (0, provider_1.useJean)(); const [input, setInput] = (0, react_1.useState)(''); const handleSend = async () => { if (!input.trim() || isLoading) return; try { await sendMessage(input); setInput(''); } catch (error) { console.error('Error sending message:', error); } }; const handleKeyDown = (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSend(); } }; const defaultStyles = { container: { maxWidth: '800px', margin: '0 auto', padding: '20px', fontFamily: 'system-ui, -apple-system, sans-serif', ...style }, header: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '20px', paddingBottom: '16px', borderBottom: '1px solid #e5e5e5' }, title: { margin: 0, fontSize: '24px', fontWeight: 'bold', color: '#333' }, userInfo: { fontSize: '14px', color: '#666' }, signOutButton: { padding: '8px 16px', backgroundColor: '#dc3545', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer', fontSize: '14px' }, chatArea: { height: `${chatHeight}px`, border: '1px solid #ddd', borderRadius: '8px', padding: '16px', marginBottom: '16px', overflowY: 'auto', backgroundColor: '#f9f9f9' }, welcomeText: { color: '#666', textAlign: 'center', marginTop: '50px', fontSize: '16px' }, message: { marginBottom: '12px', padding: '12px 16px', borderRadius: '8px', lineHeight: '1.4' }, userMessage: { backgroundColor: '#007bff', color: 'white', marginLeft: '20%', marginRight: '0' }, assistantMessage: { backgroundColor: '#fff', color: 'black', marginLeft: '0', marginRight: '20%', border: '1px solid #e5e5e5' }, inputContainer: { display: 'flex', gap: '8px', marginBottom: '16px' }, input: { flex: 1, padding: '12px', border: '1px solid #ddd', borderRadius: '6px', fontSize: '16px', outline: 'none' }, sendButton: { padding: '12px 24px', backgroundColor: '#007bff', color: 'white', border: 'none', borderRadius: '6px', cursor: 'pointer', fontSize: '16px' }, examplesContainer: { textAlign: 'center' }, examplesTitle: { fontSize: '16px', fontWeight: 'bold', marginBottom: '12px', color: '#333' }, exampleButtons: { display: 'flex', gap: '8px', flexWrap: 'wrap', justifyContent: 'center' }, exampleButton: { padding: '8px 16px', backgroundColor: '#f8f9fa', border: '1px solid #ddd', borderRadius: '6px', cursor: 'pointer', fontSize: '14px', transition: 'background-color 0.2s' } }; return ((0, jsx_runtime_1.jsxs)("div", { style: defaultStyles.container, className: className, children: [(0, jsx_runtime_1.jsxs)("div", { style: defaultStyles.header, children: [(0, jsx_runtime_1.jsx)("div", { children: header || ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("h1", { style: defaultStyles.title, children: "\uD83E\uDDE0 Jean Memory" }), (0, jsx_runtime_1.jsxs)("div", { style: defaultStyles.userInfo, children: ["Welcome back, ", (0, jsx_runtime_1.jsx)("strong", { children: user?.name || user?.email })] })] })) }), showSignOut && ((0, jsx_runtime_1.jsx)("button", { onClick: signOut, style: defaultStyles.signOutButton, title: "Sign out", children: "Sign Out" }))] }), (0, jsx_runtime_1.jsxs)("div", { style: defaultStyles.chatArea, children: [messages.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { style: defaultStyles.welcomeText, children: welcomeMessage })) : (messages.map((message, index) => ((0, jsx_runtime_1.jsxs)("div", { style: { ...defaultStyles.message, ...(message.role === 'user' ? defaultStyles.userMessage : defaultStyles.assistantMessage) }, children: [(0, jsx_runtime_1.jsxs)("strong", { children: [message.role === 'user' ? 'You' : 'Jean', ":"] }), ' ', message.content] }, message.id || index)))), isLoading && ((0, jsx_runtime_1.jsx)("div", { style: { textAlign: 'center', color: '#666', fontStyle: 'italic' }, children: "Jean is thinking..." }))] }), (0, jsx_runtime_1.jsxs)("div", { style: defaultStyles.inputContainer, children: [(0, jsx_runtime_1.jsx)("input", { type: "text", value: input, onChange: (e) => setInput(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, style: defaultStyles.input, disabled: isLoading }), (0, jsx_runtime_1.jsx)("button", { onClick: handleSend, disabled: isLoading || !input.trim(), style: { ...defaultStyles.sendButton, opacity: (isLoading || !input.trim()) ? 0.6 : 1 }, children: "Send" })] }), showExamples && examplePrompts && examplePrompts.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { style: defaultStyles.examplesContainer, children: [(0, jsx_runtime_1.jsx)("div", { style: defaultStyles.examplesTitle, children: "Try these examples:" }), (0, jsx_runtime_1.jsx)("div", { style: defaultStyles.exampleButtons, children: examplePrompts.map((example, index) => ((0, jsx_runtime_1.jsx)("button", { onClick: () => setInput(example), style: defaultStyles.exampleButton, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = '#e9ecef'; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = '#f8f9fa'; }, children: example }, index))) })] }))] })); }