@netlify/spark-ui 0.0.47-alpha → 0.0.47
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.
- package/dist/chunks/compat.module.DT16W4Wr.js +175 -0
- package/dist/chunks/hooks.module.CNV9mxng.js +138 -0
- package/dist/chunks/{useTimeout.DYuvQwFN.js → useTimeout.DOkYFG64.js} +1 -1
- package/dist/components/index.d.ts +0 -1
- package/dist/components/preact/Modal/Modal.js +1 -1
- package/dist/components/preact/SearchModal/components/SearchInput.js +2 -2
- package/dist/components/preact/SearchModal/components/SearchLink/SearchLink.js +1 -1
- package/dist/components/preact/SearchModal/components/SearchModal/SearchModal.js +1 -1
- package/dist/components/preact/SearchModal/components/SearchToggle/SearchToggle.js +1 -1
- package/dist/components/preact/SearchModal/components/SearchWindow.js +1 -1
- package/dist/components/preact/SearchModal/hooks/useKeyboardNav.js +1 -1
- package/dist/components/preact/SearchModal/hooks/useSearch.js +2 -2
- package/dist/components/preact/SearchModal/hooks/useSearchHotkeys.js +1 -1
- package/dist/components/preact/SearchModal/hooks/useSearchLogger.js +1 -1
- package/dist/components/preact/SearchModal/hooks/useSearchParams.js +1 -1
- package/dist/components/preact/SearchModal/hooks/useSearchToggles.js +1 -1
- package/dist/components/preact/index.d.ts +0 -1
- package/dist/components/preact/index.js +5 -7
- package/package.json +2 -4
- package/packages/assets/fonts/README.md +5 -0
- package/packages/assets/fonts/figtree/Figtree-Italic[wght].woff2 +0 -0
- package/packages/assets/fonts/figtree/Figtree[wght].woff2 +0 -0
- package/packages/assets/fonts/instrument-sans/InstrumentSans-Italic[wdth,wght].woff2 +0 -0
- package/packages/assets/fonts/instrument-sans/InstrumentSans[wdth,wght].woff2 +0 -0
- package/packages/assets/fonts/martian-mono/MartianMono-Bold.woff2 +0 -0
- package/packages/assets/fonts/martian-mono/MartianMono-Medium.woff2 +0 -0
- package/packages/assets/fonts/martian-mono/MartianMono-Regular.woff2 +0 -0
- package/packages/assets/fonts/martian-mono/MartianMono-SemiBold.woff2 +0 -0
- package/packages/components/index.ts +0 -1
- package/packages/components/preact/index.ts +0 -1
- package/packages/styles/base.css +1 -0
- package/packages/styles/fonts.css +125 -10
- package/packages/styles/reset.css +79 -0
- package/packages/styles/tokens.css +24 -19
- package/dist/assets/ChatApp.css +0 -1
- package/dist/chunks/compat.module.BjTzMHXJ.js +0 -296
- package/dist/chunks/hooks.module.DeYLzLnU.js +0 -177
- package/dist/components/preact/ChatApp/ChatApp.d.ts +0 -2
- package/dist/components/preact/ChatApp/ChatApp.js +0 -5346
- package/packages/components/preact/ChatApp/ChatApp.css +0 -142
- package/packages/components/preact/ChatApp/ChatApp.tsx +0 -237
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
/* styles.css */
|
|
2
|
-
|
|
3
|
-
/* Main container */
|
|
4
|
-
.chatbot-container {
|
|
5
|
-
display: flex;
|
|
6
|
-
padding: 3rem;
|
|
7
|
-
height: 100vh;
|
|
8
|
-
background-color: #f7fafc;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.chatbot-wrapper {
|
|
12
|
-
display: flex;
|
|
13
|
-
flex-direction: column;
|
|
14
|
-
width: 100%;
|
|
15
|
-
max-width: 1024px;
|
|
16
|
-
margin: 0 auto;
|
|
17
|
-
background-color: white;
|
|
18
|
-
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
19
|
-
border-radius: 8px;
|
|
20
|
-
overflow: hidden;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/* Header */
|
|
24
|
-
.header {
|
|
25
|
-
background-color: #2d3748;
|
|
26
|
-
color: white;
|
|
27
|
-
padding: 1rem;
|
|
28
|
-
display: flex;
|
|
29
|
-
justify-content: space-between;
|
|
30
|
-
align-items: center;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.header-left {
|
|
34
|
-
display: flex;
|
|
35
|
-
align-items: center;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.header-title {
|
|
39
|
-
font-weight: bold;
|
|
40
|
-
font-size: 1.25rem;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.new-chat-button {
|
|
44
|
-
display: flex;
|
|
45
|
-
align-items: center;
|
|
46
|
-
background-color: #4a5568;
|
|
47
|
-
border-radius: 0.375rem;
|
|
48
|
-
padding: 0.25rem 0.75rem;
|
|
49
|
-
font-size: 0.875rem;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.icon {
|
|
53
|
-
margin-right: 0.25rem;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/* Chat container */
|
|
57
|
-
.chat-container {
|
|
58
|
-
flex: 1;
|
|
59
|
-
overflow-y: auto;
|
|
60
|
-
padding: 1rem;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/* Error message */
|
|
64
|
-
.error-message {
|
|
65
|
-
background-color: #fed7d7;
|
|
66
|
-
border: 1px solid #fbd5d5;
|
|
67
|
-
color: #9b2c2c;
|
|
68
|
-
padding: 1rem;
|
|
69
|
-
border-radius: 0.375rem;
|
|
70
|
-
margin-bottom: 1rem;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.error-title {
|
|
74
|
-
font-weight: bold;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/* Message bubbles */
|
|
78
|
-
.message {
|
|
79
|
-
display: flex;
|
|
80
|
-
flex-direction: column;
|
|
81
|
-
margin-bottom: 1rem;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.message-right {
|
|
85
|
-
display: flex;
|
|
86
|
-
justify-content: flex-end;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.message-bubble {
|
|
90
|
-
padding: 1rem;
|
|
91
|
-
border-radius: 0.5rem;
|
|
92
|
-
max-width: 75%;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
.user-message {
|
|
96
|
-
background-color: #4299e1;
|
|
97
|
-
color: white;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.bot-message {
|
|
101
|
-
background-color: #edf2f7;
|
|
102
|
-
color: #2d3748;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/* Input area */
|
|
106
|
-
.input-area {
|
|
107
|
-
border-top: 1px solid #e2e8f0;
|
|
108
|
-
padding: 1rem;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
.input-form {
|
|
112
|
-
display: flex;
|
|
113
|
-
align-items: center;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.input-field {
|
|
117
|
-
flex: 1;
|
|
118
|
-
background-color: #edf2f7;
|
|
119
|
-
border-radius: 0.5rem;
|
|
120
|
-
padding: 0.5rem 1rem;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.input {
|
|
124
|
-
width: 100%;
|
|
125
|
-
background-color: transparent;
|
|
126
|
-
border: none;
|
|
127
|
-
outline: none;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.stop-button,
|
|
131
|
-
.send-button {
|
|
132
|
-
margin-left: 0.5rem;
|
|
133
|
-
background-color: #3182ce;
|
|
134
|
-
border-radius: 9999px;
|
|
135
|
-
padding: 0.5rem;
|
|
136
|
-
color: white;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
.stop-icon {
|
|
140
|
-
width: 1rem;
|
|
141
|
-
height: 1rem;
|
|
142
|
-
}
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import { useState, useRef, useEffect } from 'preact/hooks';
|
|
2
|
-
import * as marked from 'marked';
|
|
3
|
-
import { KapaProvider, useChat } from '@kapaai/react-sdk';
|
|
4
|
-
|
|
5
|
-
import './ChatApp.css';
|
|
6
|
-
|
|
7
|
-
function ChatApp() {
|
|
8
|
-
return (
|
|
9
|
-
<KapaProvider
|
|
10
|
-
integrationId="3c0789a6-c6a8-4fbc-b0cc-235f9e4a6351"
|
|
11
|
-
callbacks={{
|
|
12
|
-
askAI: {
|
|
13
|
-
onQuerySubmit: (data) => console.log('Question asked:', data.question),
|
|
14
|
-
},
|
|
15
|
-
}}
|
|
16
|
-
>
|
|
17
|
-
<ChatInterface />
|
|
18
|
-
</KapaProvider>
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Main App Component
|
|
23
|
-
const ChatInterface = () => {
|
|
24
|
-
const [inputMessage, setInputMessage] = useState('');
|
|
25
|
-
const [feedbackStates, setFeedbackStates] = useState({});
|
|
26
|
-
const [showCommentId, setShowCommentId] = useState(null);
|
|
27
|
-
const chatRef = useRef(null);
|
|
28
|
-
const {
|
|
29
|
-
conversation,
|
|
30
|
-
submitQuery,
|
|
31
|
-
isGeneratingAnswer,
|
|
32
|
-
isPreparingAnswer,
|
|
33
|
-
resetConversation,
|
|
34
|
-
stopGeneration,
|
|
35
|
-
addFeedback,
|
|
36
|
-
error,
|
|
37
|
-
} = useChat();
|
|
38
|
-
|
|
39
|
-
// Configure marked options for better code highlighting
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
marked.setOptions({
|
|
42
|
-
breaks: true,
|
|
43
|
-
gfm: true,
|
|
44
|
-
headerIds: false,
|
|
45
|
-
});
|
|
46
|
-
}, []);
|
|
47
|
-
|
|
48
|
-
const handleSubmit = (e) => {
|
|
49
|
-
if (e) e.preventDefault();
|
|
50
|
-
if (inputMessage.trim() && !isGeneratingAnswer && !isPreparingAnswer) {
|
|
51
|
-
submitQuery(inputMessage);
|
|
52
|
-
setInputMessage('');
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const handleClearThread = () => {
|
|
57
|
-
resetConversation();
|
|
58
|
-
setFeedbackStates({});
|
|
59
|
-
setShowCommentId(null);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const handleCopyText = (text) => {
|
|
63
|
-
navigator.clipboard.writeText(text);
|
|
64
|
-
|
|
65
|
-
// Show a temporary copied message
|
|
66
|
-
const target = event.currentTarget;
|
|
67
|
-
const buttons = document.querySelectorAll('.copy-active');
|
|
68
|
-
buttons.forEach((button) => {
|
|
69
|
-
button.classList.remove('copy-active');
|
|
70
|
-
const textEl = button.querySelector('.copy-text');
|
|
71
|
-
if (textEl) textEl.textContent = '';
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// Now set the current button to show "Copied!"
|
|
75
|
-
target.classList.add('copy-active');
|
|
76
|
-
const textEl = target.querySelector('.copy-text');
|
|
77
|
-
if (textEl) textEl.textContent = 'Copied!';
|
|
78
|
-
|
|
79
|
-
setTimeout(() => {
|
|
80
|
-
target.classList.remove('copy-active');
|
|
81
|
-
if (textEl) textEl.textContent = '';
|
|
82
|
-
}, 2000);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const handleFeedback = (qaId, reaction) => {
|
|
86
|
-
addFeedback(qaId, reaction);
|
|
87
|
-
|
|
88
|
-
// Update local feedback state
|
|
89
|
-
setFeedbackStates((prev) => ({
|
|
90
|
-
...prev,
|
|
91
|
-
[qaId]: reaction,
|
|
92
|
-
}));
|
|
93
|
-
|
|
94
|
-
// Close comment form if it's open
|
|
95
|
-
if (showCommentId === qaId) {
|
|
96
|
-
setShowCommentId(null);
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const toggleComment = (qaId) => {
|
|
101
|
-
setShowCommentId(showCommentId === qaId ? null : qaId);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// Scroll to bottom when new messages arrive
|
|
105
|
-
useEffect(() => {
|
|
106
|
-
const el = chatRef.current;
|
|
107
|
-
if (el) el.scrollTop = el.scrollHeight;
|
|
108
|
-
}, [conversation]);
|
|
109
|
-
|
|
110
|
-
return (
|
|
111
|
-
<div className="chatbot-container">
|
|
112
|
-
<div className="chatbot-wrapper">
|
|
113
|
-
{/* Header */}
|
|
114
|
-
<header className="header">
|
|
115
|
-
<div className="header-left">
|
|
116
|
-
<h1 className="header-title">AI Chatbot</h1>
|
|
117
|
-
</div>
|
|
118
|
-
<button className="new-chat-button" aria-label="New chat" onClick={handleClearThread}>
|
|
119
|
-
New Chat
|
|
120
|
-
</button>
|
|
121
|
-
</header>
|
|
122
|
-
|
|
123
|
-
{/* Chat Container */}
|
|
124
|
-
<div ref={chatRef} className="chat-container">
|
|
125
|
-
{error && (
|
|
126
|
-
<div className="error-message">
|
|
127
|
-
<p className="error-title">Error</p>
|
|
128
|
-
<p>{error}</p>
|
|
129
|
-
</div>
|
|
130
|
-
)}
|
|
131
|
-
|
|
132
|
-
{conversation.length > 0 && (
|
|
133
|
-
<div className="clear-thread-button-container">
|
|
134
|
-
<button className="clear-thread-button" aria-label="Clear thread" onClick={handleClearThread}>
|
|
135
|
-
Clear thread
|
|
136
|
-
</button>
|
|
137
|
-
</div>
|
|
138
|
-
)}
|
|
139
|
-
|
|
140
|
-
{/* Messages */}
|
|
141
|
-
<div className="messages-container">
|
|
142
|
-
{conversation.length === 0 ? (
|
|
143
|
-
<div className="no-conversation-message">
|
|
144
|
-
<p>Ask a question to start a conversation!</p>
|
|
145
|
-
</div>
|
|
146
|
-
) : (
|
|
147
|
-
conversation.map((qa, index) => (
|
|
148
|
-
<div key={qa.id || `qa-${index}`} className="message">
|
|
149
|
-
<div className="message-right">
|
|
150
|
-
<div className="message-bubble user-message">
|
|
151
|
-
<p>{qa.question}</p>
|
|
152
|
-
</div>
|
|
153
|
-
</div>
|
|
154
|
-
|
|
155
|
-
<div className="message-left">
|
|
156
|
-
<div className="message-bubble bot-message">
|
|
157
|
-
<div
|
|
158
|
-
className="message-answer"
|
|
159
|
-
dangerouslySetInnerHTML={{
|
|
160
|
-
__html: qa.answer
|
|
161
|
-
? marked.parse(qa.answer)
|
|
162
|
-
: '<p class="text-gray-500">Generating answer...</p>',
|
|
163
|
-
}}
|
|
164
|
-
/>
|
|
165
|
-
|
|
166
|
-
{/* Only show feedback controls when answer is completed (not during generation) */}
|
|
167
|
-
{qa.isFeedbackSubmissionEnabled && (
|
|
168
|
-
<div className="feedback-controls">
|
|
169
|
-
<div className="feedback-buttons">
|
|
170
|
-
<button
|
|
171
|
-
className={`feedback-button upvote ${
|
|
172
|
-
feedbackStates[qa.id] === 'upvote' ? 'upvoted' : ''
|
|
173
|
-
}`}
|
|
174
|
-
aria-label="Upvote"
|
|
175
|
-
onClick={() => qa.id && handleFeedback(qa.id, 'upvote')}
|
|
176
|
-
></button>
|
|
177
|
-
<button
|
|
178
|
-
className={`feedback-button downvote ${
|
|
179
|
-
feedbackStates[qa.id] === 'downvote' ? 'downvoted' : ''
|
|
180
|
-
}`}
|
|
181
|
-
aria-label="Downvote"
|
|
182
|
-
onClick={() => qa.id && handleFeedback(qa.id, 'downvote')}
|
|
183
|
-
></button>
|
|
184
|
-
<button
|
|
185
|
-
className="feedback-button copy"
|
|
186
|
-
onClick={(event) => handleCopyText(qa.answer)}
|
|
187
|
-
aria-label="Copy message"
|
|
188
|
-
>
|
|
189
|
-
<span className="copy-text"></span>
|
|
190
|
-
</button>
|
|
191
|
-
</div>
|
|
192
|
-
</div>
|
|
193
|
-
)}
|
|
194
|
-
</div>
|
|
195
|
-
</div>
|
|
196
|
-
</div>
|
|
197
|
-
))
|
|
198
|
-
)}
|
|
199
|
-
{/* <div ref={chatRef} /> */}
|
|
200
|
-
</div>
|
|
201
|
-
</div>
|
|
202
|
-
|
|
203
|
-
{/* Input Area */}
|
|
204
|
-
<div className="input-area">
|
|
205
|
-
<form onSubmit={handleSubmit} className="input-form">
|
|
206
|
-
<div className="input-field">
|
|
207
|
-
<input
|
|
208
|
-
type="text"
|
|
209
|
-
placeholder="Type your message..."
|
|
210
|
-
className="input"
|
|
211
|
-
value={inputMessage}
|
|
212
|
-
onChange={(e) => setInputMessage(e.target.value)}
|
|
213
|
-
disabled={isGeneratingAnswer || isPreparingAnswer}
|
|
214
|
-
/>
|
|
215
|
-
</div>
|
|
216
|
-
{isGeneratingAnswer ? (
|
|
217
|
-
<button type="button" className="stop-button" onClick={stopGeneration} aria-label="Stop generation">
|
|
218
|
-
<svg xmlns="http://www.w3.org/2000/svg" className="stop-icon" viewBox="0 0 20 20" fill="currentColor">
|
|
219
|
-
<rect x="6" y="6" width="8" height="8" />
|
|
220
|
-
</svg>
|
|
221
|
-
</button>
|
|
222
|
-
) : (
|
|
223
|
-
<button
|
|
224
|
-
type="submit"
|
|
225
|
-
className="send-button"
|
|
226
|
-
disabled={!inputMessage.trim() || isPreparingAnswer}
|
|
227
|
-
aria-label="Send message"
|
|
228
|
-
></button>
|
|
229
|
-
)}
|
|
230
|
-
</form>
|
|
231
|
-
</div>
|
|
232
|
-
</div>
|
|
233
|
-
</div>
|
|
234
|
-
);
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
export default ChatApp;
|