@jeanmemory/react
Version:
React SDK for Jean Memory - Build personalized AI chatbots in 5 lines of code
184 lines (183 loc) • 8.36 kB
JavaScript
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))) })] }))] }));
}
;