@d34dman/flowdrop 0.0.30 → 0.0.32
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/components/App.svelte +54 -6
- package/dist/components/NodeSidebar.svelte +1 -1
- package/dist/components/SchemaForm.svelte +14 -14
- package/dist/components/SchemaForm.svelte.d.ts +1 -1
- package/dist/components/form/FormFieldLight.svelte +66 -66
- package/dist/components/form/FormFieldLight.svelte.d.ts +1 -1
- package/dist/components/form/types.d.ts +1 -1
- package/dist/components/playground/ChatPanel.svelte +523 -0
- package/dist/components/playground/ChatPanel.svelte.d.ts +20 -0
- package/dist/components/playground/ExecutionLogs.svelte +486 -0
- package/dist/components/playground/ExecutionLogs.svelte.d.ts +14 -0
- package/dist/components/playground/InputCollector.svelte +444 -0
- package/dist/components/playground/InputCollector.svelte.d.ts +16 -0
- package/dist/components/playground/MessageBubble.svelte +398 -0
- package/dist/components/playground/MessageBubble.svelte.d.ts +15 -0
- package/dist/components/playground/Playground.svelte +861 -0
- package/dist/components/playground/Playground.svelte.d.ts +25 -0
- package/dist/components/playground/PlaygroundModal.svelte +220 -0
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +25 -0
- package/dist/components/playground/SessionManager.svelte +537 -0
- package/dist/components/playground/SessionManager.svelte.d.ts +20 -0
- package/dist/config/endpoints.d.ts +16 -0
- package/dist/config/endpoints.js +9 -0
- package/dist/core/index.d.ts +25 -23
- package/dist/core/index.js +13 -12
- package/dist/display/index.d.ts +2 -2
- package/dist/display/index.js +2 -2
- package/dist/editor/index.d.ts +58 -49
- package/dist/editor/index.js +53 -42
- package/dist/form/code.d.ts +4 -4
- package/dist/form/code.js +11 -11
- package/dist/form/fieldRegistry.d.ts +2 -2
- package/dist/form/fieldRegistry.js +8 -10
- package/dist/form/full.d.ts +5 -5
- package/dist/form/full.js +7 -7
- package/dist/form/index.d.ts +16 -16
- package/dist/form/index.js +14 -14
- package/dist/form/markdown.d.ts +3 -3
- package/dist/form/markdown.js +6 -6
- package/dist/index.d.ts +6 -4
- package/dist/index.js +9 -4
- package/dist/playground/index.d.ts +125 -0
- package/dist/playground/index.js +147 -0
- package/dist/playground/mount.d.ts +184 -0
- package/dist/playground/mount.js +209 -0
- package/dist/services/playgroundService.d.ts +129 -0
- package/dist/services/playgroundService.js +317 -0
- package/dist/stores/playgroundStore.d.ts +199 -0
- package/dist/stores/playgroundStore.js +350 -0
- package/dist/types/playground.d.ts +230 -0
- package/dist/types/playground.js +28 -0
- package/dist/utils/colors.js +4 -4
- package/package.json +6 -1
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
ChatPanel Component
|
|
3
|
+
|
|
4
|
+
Clean conversational chat interface for the playground.
|
|
5
|
+
Displays messages with chat bubbles and includes a simple input area.
|
|
6
|
+
Styled with BEM syntax for a Langflow-like appearance.
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
<script lang="ts">
|
|
10
|
+
import Icon from '@iconify/svelte';
|
|
11
|
+
import { tick } from 'svelte';
|
|
12
|
+
import MessageBubble from './MessageBubble.svelte';
|
|
13
|
+
import type { PlaygroundMessage } from '../../types/playground.js';
|
|
14
|
+
import {
|
|
15
|
+
messages,
|
|
16
|
+
chatMessages,
|
|
17
|
+
isExecuting,
|
|
18
|
+
sessionStatus,
|
|
19
|
+
currentSession
|
|
20
|
+
} from '../../stores/playgroundStore.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Component props
|
|
24
|
+
*/
|
|
25
|
+
interface Props {
|
|
26
|
+
/** Whether to show timestamps on messages */
|
|
27
|
+
showTimestamps?: boolean;
|
|
28
|
+
/** Whether to auto-scroll to bottom on new messages */
|
|
29
|
+
autoScroll?: boolean;
|
|
30
|
+
/** Placeholder text for the input */
|
|
31
|
+
placeholder?: string;
|
|
32
|
+
/** Callback when user sends a message */
|
|
33
|
+
onSendMessage?: (content: string) => void;
|
|
34
|
+
/** Callback when user requests to stop execution */
|
|
35
|
+
onStopExecution?: () => void;
|
|
36
|
+
/** Whether to show log messages inline (false = hide them) */
|
|
37
|
+
showLogsInline?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let {
|
|
41
|
+
showTimestamps = true,
|
|
42
|
+
autoScroll = true,
|
|
43
|
+
placeholder = 'Type your message...',
|
|
44
|
+
onSendMessage,
|
|
45
|
+
onStopExecution,
|
|
46
|
+
showLogsInline = false
|
|
47
|
+
}: Props = $props();
|
|
48
|
+
|
|
49
|
+
/** Input field value */
|
|
50
|
+
let inputValue = $state('');
|
|
51
|
+
|
|
52
|
+
/** Reference to the messages container for scrolling */
|
|
53
|
+
let messagesContainer = $state<HTMLDivElement>();
|
|
54
|
+
|
|
55
|
+
/** Reference to the input field */
|
|
56
|
+
let inputField = $state<HTMLTextAreaElement>();
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Filter messages based on showLogsInline setting
|
|
60
|
+
*/
|
|
61
|
+
const displayMessages = $derived(showLogsInline ? $messages : $chatMessages);
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Check if we should show the welcome state
|
|
65
|
+
*/
|
|
66
|
+
const showWelcome = $derived(!$currentSession && displayMessages.length === 0);
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Check if we should show the empty chat state (session exists but no messages)
|
|
70
|
+
*/
|
|
71
|
+
const showEmptyChat = $derived($currentSession && displayMessages.length === 0);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Handle sending a message
|
|
75
|
+
*/
|
|
76
|
+
function handleSend(): void {
|
|
77
|
+
const trimmedValue = inputValue.trim();
|
|
78
|
+
if (!trimmedValue || $isExecuting) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
onSendMessage?.(trimmedValue);
|
|
83
|
+
inputValue = '';
|
|
84
|
+
|
|
85
|
+
// Reset textarea height
|
|
86
|
+
if (inputField) {
|
|
87
|
+
inputField.style.height = 'auto';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Re-focus the input
|
|
91
|
+
tick().then(() => {
|
|
92
|
+
inputField?.focus();
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Handle keyboard events in the input
|
|
98
|
+
*/
|
|
99
|
+
function handleKeydown(event: KeyboardEvent): void {
|
|
100
|
+
if (event.key === 'Enter' && !event.shiftKey) {
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
handleSend();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Handle stop execution
|
|
108
|
+
*/
|
|
109
|
+
function handleStop(): void {
|
|
110
|
+
onStopExecution?.();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Auto-scroll to bottom when messages change
|
|
115
|
+
*/
|
|
116
|
+
$effect(() => {
|
|
117
|
+
if (autoScroll && messagesContainer && displayMessages.length > 0) {
|
|
118
|
+
tick().then(() => {
|
|
119
|
+
if (messagesContainer) {
|
|
120
|
+
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Auto-resize textarea based on content
|
|
128
|
+
*/
|
|
129
|
+
function handleInput(): void {
|
|
130
|
+
if (inputField) {
|
|
131
|
+
inputField.style.height = 'auto';
|
|
132
|
+
inputField.style.height = `${Math.min(inputField.scrollHeight, 120)}px`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
</script>
|
|
136
|
+
|
|
137
|
+
<div class="chat-panel">
|
|
138
|
+
<!-- Messages Container -->
|
|
139
|
+
<div class="chat-panel__messages" bind:this={messagesContainer}>
|
|
140
|
+
{#if showWelcome}
|
|
141
|
+
<!-- Welcome State (no session) -->
|
|
142
|
+
<div class="chat-panel__welcome">
|
|
143
|
+
<div class="chat-panel__welcome-icon">
|
|
144
|
+
<svg
|
|
145
|
+
width="48"
|
|
146
|
+
height="48"
|
|
147
|
+
viewBox="0 0 48 48"
|
|
148
|
+
fill="none"
|
|
149
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
150
|
+
>
|
|
151
|
+
<path
|
|
152
|
+
d="M8 16L24 8L40 16V32L24 40L8 32V16Z"
|
|
153
|
+
stroke="currentColor"
|
|
154
|
+
stroke-width="2"
|
|
155
|
+
stroke-linejoin="round"
|
|
156
|
+
/>
|
|
157
|
+
<path
|
|
158
|
+
d="M8 16L24 24L40 16"
|
|
159
|
+
stroke="currentColor"
|
|
160
|
+
stroke-width="2"
|
|
161
|
+
stroke-linejoin="round"
|
|
162
|
+
/>
|
|
163
|
+
<path d="M24 24V40" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
|
|
164
|
+
<path d="M16 12L32 20" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
|
|
165
|
+
<path d="M16 36L32 28" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
|
|
166
|
+
</svg>
|
|
167
|
+
</div>
|
|
168
|
+
<h2 class="chat-panel__welcome-title">New chat</h2>
|
|
169
|
+
<p class="chat-panel__welcome-text">Test your flow with a chat prompt</p>
|
|
170
|
+
</div>
|
|
171
|
+
{:else if showEmptyChat}
|
|
172
|
+
<!-- Empty Chat State (session exists but no messages) -->
|
|
173
|
+
<div class="chat-panel__welcome">
|
|
174
|
+
<div class="chat-panel__welcome-icon">
|
|
175
|
+
<svg
|
|
176
|
+
width="48"
|
|
177
|
+
height="48"
|
|
178
|
+
viewBox="0 0 48 48"
|
|
179
|
+
fill="none"
|
|
180
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
181
|
+
>
|
|
182
|
+
<path
|
|
183
|
+
d="M8 16L24 8L40 16V32L24 40L8 32V16Z"
|
|
184
|
+
stroke="currentColor"
|
|
185
|
+
stroke-width="2"
|
|
186
|
+
stroke-linejoin="round"
|
|
187
|
+
/>
|
|
188
|
+
<path
|
|
189
|
+
d="M8 16L24 24L40 16"
|
|
190
|
+
stroke="currentColor"
|
|
191
|
+
stroke-width="2"
|
|
192
|
+
stroke-linejoin="round"
|
|
193
|
+
/>
|
|
194
|
+
<path d="M24 24V40" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
|
|
195
|
+
<path d="M16 12L32 20" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
|
|
196
|
+
<path d="M16 36L32 28" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
|
|
197
|
+
</svg>
|
|
198
|
+
</div>
|
|
199
|
+
<h2 class="chat-panel__welcome-title">New chat</h2>
|
|
200
|
+
<p class="chat-panel__welcome-text">Test your flow with a chat prompt</p>
|
|
201
|
+
</div>
|
|
202
|
+
{:else}
|
|
203
|
+
<!-- Messages -->
|
|
204
|
+
{#each displayMessages as message, index (message.id)}
|
|
205
|
+
<MessageBubble
|
|
206
|
+
{message}
|
|
207
|
+
showTimestamp={showTimestamps}
|
|
208
|
+
isLast={index === displayMessages.length - 1}
|
|
209
|
+
/>
|
|
210
|
+
{/each}
|
|
211
|
+
|
|
212
|
+
{#if $isExecuting}
|
|
213
|
+
<div class="chat-panel__typing">
|
|
214
|
+
<div class="chat-panel__typing-indicator">
|
|
215
|
+
<span></span>
|
|
216
|
+
<span></span>
|
|
217
|
+
<span></span>
|
|
218
|
+
</div>
|
|
219
|
+
<span class="chat-panel__typing-text">Processing...</span>
|
|
220
|
+
</div>
|
|
221
|
+
{/if}
|
|
222
|
+
{/if}
|
|
223
|
+
</div>
|
|
224
|
+
|
|
225
|
+
<!-- Input Area -->
|
|
226
|
+
<div class="chat-panel__input-area">
|
|
227
|
+
<div class="chat-panel__input-container">
|
|
228
|
+
<div class="chat-panel__input-wrapper">
|
|
229
|
+
<textarea
|
|
230
|
+
bind:this={inputField}
|
|
231
|
+
bind:value={inputValue}
|
|
232
|
+
class="chat-panel__input"
|
|
233
|
+
{placeholder}
|
|
234
|
+
rows="1"
|
|
235
|
+
disabled={$isExecuting}
|
|
236
|
+
onkeydown={handleKeydown}
|
|
237
|
+
oninput={handleInput}
|
|
238
|
+
></textarea>
|
|
239
|
+
|
|
240
|
+
<!-- Attachment button placeholder -->
|
|
241
|
+
<button type="button" class="chat-panel__attachment-btn" title="Attach file" disabled>
|
|
242
|
+
<Icon icon="mdi:image-outline" />
|
|
243
|
+
</button>
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
{#if $sessionStatus === 'running' || $isExecuting}
|
|
247
|
+
<button
|
|
248
|
+
type="button"
|
|
249
|
+
class="chat-panel__stop-btn"
|
|
250
|
+
onclick={handleStop}
|
|
251
|
+
title="Stop execution"
|
|
252
|
+
>
|
|
253
|
+
<Icon icon="mdi:stop" />
|
|
254
|
+
Stop
|
|
255
|
+
</button>
|
|
256
|
+
{:else}
|
|
257
|
+
<button
|
|
258
|
+
type="button"
|
|
259
|
+
class="chat-panel__send-btn"
|
|
260
|
+
onclick={handleSend}
|
|
261
|
+
disabled={!inputValue.trim()}
|
|
262
|
+
title="Send message"
|
|
263
|
+
>
|
|
264
|
+
Send
|
|
265
|
+
</button>
|
|
266
|
+
{/if}
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
|
|
271
|
+
<style>
|
|
272
|
+
.chat-panel {
|
|
273
|
+
display: flex;
|
|
274
|
+
flex-direction: column;
|
|
275
|
+
height: 100%;
|
|
276
|
+
background-color: #ffffff;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* Messages Container */
|
|
280
|
+
.chat-panel__messages {
|
|
281
|
+
flex: 1;
|
|
282
|
+
overflow-y: auto;
|
|
283
|
+
padding: 1.5rem;
|
|
284
|
+
scroll-behavior: smooth;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/* Welcome State */
|
|
288
|
+
.chat-panel__welcome {
|
|
289
|
+
display: flex;
|
|
290
|
+
flex-direction: column;
|
|
291
|
+
align-items: center;
|
|
292
|
+
justify-content: center;
|
|
293
|
+
height: 100%;
|
|
294
|
+
text-align: center;
|
|
295
|
+
padding: 2rem;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.chat-panel__welcome-icon {
|
|
299
|
+
display: flex;
|
|
300
|
+
align-items: center;
|
|
301
|
+
justify-content: center;
|
|
302
|
+
width: 80px;
|
|
303
|
+
height: 80px;
|
|
304
|
+
margin-bottom: 1.5rem;
|
|
305
|
+
color: #1f2937;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.chat-panel__welcome-icon svg {
|
|
309
|
+
width: 100%;
|
|
310
|
+
height: 100%;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.chat-panel__welcome-title {
|
|
314
|
+
font-size: 1.5rem;
|
|
315
|
+
font-weight: 600;
|
|
316
|
+
color: #1f2937;
|
|
317
|
+
margin: 0 0 0.5rem 0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.chat-panel__welcome-text {
|
|
321
|
+
font-size: 1rem;
|
|
322
|
+
color: #6b7280;
|
|
323
|
+
margin: 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/* Typing Indicator */
|
|
327
|
+
.chat-panel__typing {
|
|
328
|
+
display: flex;
|
|
329
|
+
align-items: center;
|
|
330
|
+
gap: 0.5rem;
|
|
331
|
+
padding: 0.75rem 1rem;
|
|
332
|
+
margin-top: 0.5rem;
|
|
333
|
+
background-color: #f3f4f6;
|
|
334
|
+
border-radius: 1rem;
|
|
335
|
+
width: fit-content;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.chat-panel__typing-indicator {
|
|
339
|
+
display: flex;
|
|
340
|
+
gap: 0.25rem;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.chat-panel__typing-indicator span {
|
|
344
|
+
width: 0.375rem;
|
|
345
|
+
height: 0.375rem;
|
|
346
|
+
background-color: #9ca3af;
|
|
347
|
+
border-radius: 50%;
|
|
348
|
+
animation: bounce 1.4s ease-in-out infinite;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.chat-panel__typing-indicator span:nth-child(1) {
|
|
352
|
+
animation-delay: 0s;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.chat-panel__typing-indicator span:nth-child(2) {
|
|
356
|
+
animation-delay: 0.2s;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.chat-panel__typing-indicator span:nth-child(3) {
|
|
360
|
+
animation-delay: 0.4s;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
@keyframes bounce {
|
|
364
|
+
0%,
|
|
365
|
+
60%,
|
|
366
|
+
100% {
|
|
367
|
+
transform: translateY(0);
|
|
368
|
+
}
|
|
369
|
+
30% {
|
|
370
|
+
transform: translateY(-0.25rem);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
.chat-panel__typing-text {
|
|
375
|
+
font-size: 0.8125rem;
|
|
376
|
+
color: #6b7280;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/* Input Area */
|
|
380
|
+
.chat-panel__input-area {
|
|
381
|
+
padding: 1rem 1.5rem 1.5rem;
|
|
382
|
+
background-color: #ffffff;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.chat-panel__input-container {
|
|
386
|
+
display: flex;
|
|
387
|
+
align-items: flex-end;
|
|
388
|
+
gap: 0.75rem;
|
|
389
|
+
max-width: 800px;
|
|
390
|
+
margin: 0 auto;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.chat-panel__input-wrapper {
|
|
394
|
+
flex: 1;
|
|
395
|
+
display: flex;
|
|
396
|
+
align-items: flex-end;
|
|
397
|
+
background-color: #ffffff;
|
|
398
|
+
border: 1px solid #e5e7eb;
|
|
399
|
+
border-radius: 0.75rem;
|
|
400
|
+
padding: 0.625rem 0.75rem;
|
|
401
|
+
transition:
|
|
402
|
+
border-color 0.15s ease,
|
|
403
|
+
box-shadow 0.15s ease;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.chat-panel__input-wrapper:focus-within {
|
|
407
|
+
border-color: #6366f1;
|
|
408
|
+
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.chat-panel__input {
|
|
412
|
+
flex: 1;
|
|
413
|
+
border: none;
|
|
414
|
+
outline: none;
|
|
415
|
+
resize: none;
|
|
416
|
+
font-family: inherit;
|
|
417
|
+
font-size: 0.9375rem;
|
|
418
|
+
line-height: 1.5;
|
|
419
|
+
max-height: 120px;
|
|
420
|
+
background: transparent;
|
|
421
|
+
color: #1f2937;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.chat-panel__input::placeholder {
|
|
425
|
+
color: #9ca3af;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
.chat-panel__input:disabled {
|
|
429
|
+
cursor: not-allowed;
|
|
430
|
+
opacity: 0.6;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
.chat-panel__attachment-btn {
|
|
434
|
+
display: flex;
|
|
435
|
+
align-items: center;
|
|
436
|
+
justify-content: center;
|
|
437
|
+
width: 2rem;
|
|
438
|
+
height: 2rem;
|
|
439
|
+
border: none;
|
|
440
|
+
border-radius: 0.375rem;
|
|
441
|
+
background: transparent;
|
|
442
|
+
color: #9ca3af;
|
|
443
|
+
cursor: pointer;
|
|
444
|
+
transition: all 0.15s ease;
|
|
445
|
+
flex-shrink: 0;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.chat-panel__attachment-btn:hover:not(:disabled) {
|
|
449
|
+
color: #6b7280;
|
|
450
|
+
background-color: #f3f4f6;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.chat-panel__attachment-btn:disabled {
|
|
454
|
+
opacity: 0.5;
|
|
455
|
+
cursor: not-allowed;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.chat-panel__send-btn {
|
|
459
|
+
display: flex;
|
|
460
|
+
align-items: center;
|
|
461
|
+
justify-content: center;
|
|
462
|
+
padding: 0.625rem 1.25rem;
|
|
463
|
+
border: none;
|
|
464
|
+
border-radius: 0.5rem;
|
|
465
|
+
background-color: #1f2937;
|
|
466
|
+
color: #ffffff;
|
|
467
|
+
font-size: 0.875rem;
|
|
468
|
+
font-weight: 500;
|
|
469
|
+
cursor: pointer;
|
|
470
|
+
transition: all 0.15s ease;
|
|
471
|
+
flex-shrink: 0;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.chat-panel__send-btn:hover:not(:disabled) {
|
|
475
|
+
background-color: #374151;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
.chat-panel__send-btn:disabled {
|
|
479
|
+
background-color: #e5e7eb;
|
|
480
|
+
color: #9ca3af;
|
|
481
|
+
cursor: not-allowed;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.chat-panel__stop-btn {
|
|
485
|
+
display: flex;
|
|
486
|
+
align-items: center;
|
|
487
|
+
gap: 0.375rem;
|
|
488
|
+
padding: 0.625rem 1rem;
|
|
489
|
+
border: none;
|
|
490
|
+
border-radius: 0.5rem;
|
|
491
|
+
background-color: #ef4444;
|
|
492
|
+
color: #ffffff;
|
|
493
|
+
font-size: 0.875rem;
|
|
494
|
+
font-weight: 500;
|
|
495
|
+
cursor: pointer;
|
|
496
|
+
transition: background-color 0.15s ease;
|
|
497
|
+
flex-shrink: 0;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.chat-panel__stop-btn:hover {
|
|
501
|
+
background-color: #dc2626;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/* Responsive */
|
|
505
|
+
@media (max-width: 640px) {
|
|
506
|
+
.chat-panel__messages {
|
|
507
|
+
padding: 1rem;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
.chat-panel__input-area {
|
|
511
|
+
padding: 0.75rem 1rem 1rem;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
.chat-panel__input-container {
|
|
515
|
+
gap: 0.5rem;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
.chat-panel__send-btn,
|
|
519
|
+
.chat-panel__stop-btn {
|
|
520
|
+
padding: 0.5rem 1rem;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component props
|
|
3
|
+
*/
|
|
4
|
+
interface Props {
|
|
5
|
+
/** Whether to show timestamps on messages */
|
|
6
|
+
showTimestamps?: boolean;
|
|
7
|
+
/** Whether to auto-scroll to bottom on new messages */
|
|
8
|
+
autoScroll?: boolean;
|
|
9
|
+
/** Placeholder text for the input */
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
/** Callback when user sends a message */
|
|
12
|
+
onSendMessage?: (content: string) => void;
|
|
13
|
+
/** Callback when user requests to stop execution */
|
|
14
|
+
onStopExecution?: () => void;
|
|
15
|
+
/** Whether to show log messages inline (false = hide them) */
|
|
16
|
+
showLogsInline?: boolean;
|
|
17
|
+
}
|
|
18
|
+
declare const ChatPanel: import("svelte").Component<Props, {}, "">;
|
|
19
|
+
type ChatPanel = ReturnType<typeof ChatPanel>;
|
|
20
|
+
export default ChatPanel;
|