@widgetic/chat 0.1.4

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.
Files changed (72) hide show
  1. package/README.md +440 -0
  2. package/dist/adapters/index.d.ts +2 -0
  3. package/dist/adapters/index.js +2 -0
  4. package/dist/adapters/widgeticAdapter.d.ts +185 -0
  5. package/dist/adapters/widgeticAdapter.js +766 -0
  6. package/dist/components/ActionBar.svelte +342 -0
  7. package/dist/components/ActionBar.svelte.d.ts +37 -0
  8. package/dist/components/AttachmentDisplay.svelte +547 -0
  9. package/dist/components/AttachmentDisplay.svelte.d.ts +12 -0
  10. package/dist/components/Chat.svelte +1253 -0
  11. package/dist/components/Chat.svelte.d.ts +112 -0
  12. package/dist/components/ChatHeader.svelte +182 -0
  13. package/dist/components/ChatHeader.svelte.d.ts +12 -0
  14. package/dist/components/ChatInput.svelte +290 -0
  15. package/dist/components/ChatInput.svelte.d.ts +15 -0
  16. package/dist/components/ChatMessages.svelte +996 -0
  17. package/dist/components/ChatMessages.svelte.d.ts +28 -0
  18. package/dist/components/CodeBlock.svelte +286 -0
  19. package/dist/components/CodeBlock.svelte.d.ts +10 -0
  20. package/dist/components/ContextPreview.svelte +66 -0
  21. package/dist/components/ContextPreview.svelte.d.ts +8 -0
  22. package/dist/components/LoadingIndicator.svelte +151 -0
  23. package/dist/components/LoadingIndicator.svelte.d.ts +9 -0
  24. package/dist/components/StatusIndicator.svelte +116 -0
  25. package/dist/components/StatusIndicator.svelte.d.ts +9 -0
  26. package/dist/components/SuggestionButtons.svelte +244 -0
  27. package/dist/components/SuggestionButtons.svelte.d.ts +26 -0
  28. package/dist/components/index.d.ts +12 -0
  29. package/dist/components/index.js +12 -0
  30. package/dist/config.d.ts +43 -0
  31. package/dist/config.js +67 -0
  32. package/dist/constants/colors.d.ts +20 -0
  33. package/dist/constants/colors.js +16 -0
  34. package/dist/index.d.ts +11 -0
  35. package/dist/index.js +20 -0
  36. package/dist/services/chatService.d.ts +72 -0
  37. package/dist/services/chatService.js +355 -0
  38. package/dist/services/index.d.ts +2 -0
  39. package/dist/services/index.js +2 -0
  40. package/dist/stores/chatStore.d.ts +46 -0
  41. package/dist/stores/chatStore.js +219 -0
  42. package/dist/stores/index.d.ts +2 -0
  43. package/dist/stores/index.js +2 -0
  44. package/dist/types/adapter.d.ts +86 -0
  45. package/dist/types/adapter.js +1 -0
  46. package/dist/types/api-temp.d.ts +61 -0
  47. package/dist/types/api-temp.js +42 -0
  48. package/dist/types/attachment.d.ts +84 -0
  49. package/dist/types/attachment.js +33 -0
  50. package/dist/types/chat.d.ts +114 -0
  51. package/dist/types/chat.js +1 -0
  52. package/dist/types/config.d.ts +89 -0
  53. package/dist/types/config.js +63 -0
  54. package/dist/types/context.d.ts +108 -0
  55. package/dist/types/context.js +11 -0
  56. package/dist/types/conversation.d.ts +45 -0
  57. package/dist/types/conversation.js +1 -0
  58. package/dist/types/events.d.ts +141 -0
  59. package/dist/types/events.js +1 -0
  60. package/dist/types/index.d.ts +16 -0
  61. package/dist/types/index.js +10 -0
  62. package/dist/types/message.d.ts +82 -0
  63. package/dist/types/message.js +1 -0
  64. package/dist/types/state.d.ts +117 -0
  65. package/dist/types/state.js +1 -0
  66. package/dist/utils/fileUtils.d.ts +93 -0
  67. package/dist/utils/fileUtils.js +299 -0
  68. package/dist/utils/index.d.ts +3 -0
  69. package/dist/utils/index.js +4 -0
  70. package/dist/utils/logger.d.ts +4 -0
  71. package/dist/utils/logger.js +28 -0
  72. package/package.json +104 -0
@@ -0,0 +1,342 @@
1
+ <script lang="ts">
2
+ import { createEventDispatcher } from 'svelte';
3
+ import { chatLog } from '../utils/logger.js';
4
+ import type { ChatContext } from '../types/context.js';
5
+
6
+ // Props
7
+ interface Props {
8
+ context: ChatContext;
9
+ conversationId: string | null;
10
+ isRecording?: boolean;
11
+ isCompleted?: boolean;
12
+ disabled?: boolean;
13
+ showScreenshot?: boolean;
14
+ showRecord?: boolean;
15
+ showUpload?: boolean;
16
+ showComplete?: boolean;
17
+ }
18
+
19
+ let {
20
+ context,
21
+ conversationId,
22
+ isRecording = false,
23
+ isCompleted = false,
24
+ disabled = false,
25
+ showScreenshot = true,
26
+ showRecord = true,
27
+ showUpload = true,
28
+ showComplete = true,
29
+ }: Props = $props();
30
+
31
+ const dispatch = createEventDispatcher();
32
+
33
+ // Handle screenshot capture
34
+ async function handleScreenshot() {
35
+ if (disabled || !conversationId) return;
36
+
37
+ try {
38
+ chatLog('Triggering screenshot for context:', context.id);
39
+ dispatch('screenshot', { contextId: context.id });
40
+ } catch (error) {
41
+ console.error('Screenshot failed:', error);
42
+ dispatch('error', { type: 'screenshot', error });
43
+ }
44
+ }
45
+
46
+ // Handle recording start/stop
47
+ async function handleRecording() {
48
+ if (disabled || !conversationId) return;
49
+
50
+ try {
51
+ if (isRecording) {
52
+ chatLog('Stopping recording for context:', context.id);
53
+ dispatch('recordStop', { contextId: context.id });
54
+ } else {
55
+ chatLog('Starting recording for context:', context.id);
56
+ dispatch('recordStart', { contextId: context.id });
57
+ }
58
+ } catch (error) {
59
+ console.error('Recording action failed:', error);
60
+ dispatch('error', { type: 'recording', error });
61
+ }
62
+ }
63
+
64
+ // Handle file upload
65
+ function handleUpload() {
66
+ if (disabled || !conversationId) return;
67
+
68
+ chatLog('Triggering file upload');
69
+ dispatch('upload');
70
+ }
71
+
72
+ // Handle completion toggle
73
+ function handleCompletionToggle() {
74
+ if (disabled || !conversationId) return;
75
+
76
+ chatLog('Toggling conversation completion:', !isCompleted);
77
+ dispatch('complete', { completed: !isCompleted });
78
+ }
79
+
80
+ // Get context-specific suggestions
81
+ function getContextSuggestions(): string[] {
82
+ switch (context.type) {
83
+ case 'frame':
84
+ return [
85
+ 'Generate code from this design',
86
+ 'Explain this component structure',
87
+ 'Suggest improvements for this layout'
88
+ ];
89
+ case 'text':
90
+ return [
91
+ 'Help improve this writing',
92
+ 'Check grammar and style',
93
+ 'Suggest alternative phrasing'
94
+ ];
95
+ default:
96
+ return [
97
+ 'Ask a question about this content',
98
+ 'Get suggestions for improvement',
99
+ 'Explain what you see here'
100
+ ];
101
+ }
102
+ }
103
+ </script>
104
+
105
+ <div class="action-bar" class:disabled>
106
+ {#if showScreenshot}
107
+ <!-- Screenshot Button -->
108
+ <button
109
+ class="action-button screenshot-button"
110
+ onclick={handleScreenshot}
111
+ disabled={disabled || !conversationId}
112
+ title="Take Screenshot"
113
+ aria-label="Take screenshot of current content"
114
+ >
115
+ <svg viewBox="0 0 24 24" class="action-icon">
116
+ <path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/>
117
+ <circle cx="12" cy="13" r="4"/>
118
+ </svg>
119
+ <span class="action-label">Screenshot</span>
120
+ </button>
121
+ {/if}
122
+
123
+ {#if showRecord}
124
+ <!-- Recording Button -->
125
+ <button
126
+ class="action-button record-button"
127
+ class:recording={isRecording}
128
+ onclick={handleRecording}
129
+ disabled={disabled || !conversationId}
130
+ title={isRecording ? 'Stop Recording' : 'Start Recording'}
131
+ aria-label={isRecording ? 'Stop recording' : 'Start recording'}
132
+ >
133
+ {#if isRecording}
134
+ <svg viewBox="0 0 24 24" class="action-icon">
135
+ <rect x="6" y="6" width="12" height="12" rx="2"/>
136
+ </svg>
137
+ <span class="action-label">Stop</span>
138
+ <div class="recording-indicator"></div>
139
+ {:else}
140
+ <svg viewBox="0 0 24 24" class="action-icon">
141
+ <circle cx="12" cy="12" r="10"/>
142
+ <circle cx="12" cy="12" r="6" fill="currentColor"/>
143
+ </svg>
144
+ <span class="action-label">Record</span>
145
+ {/if}
146
+ </button>
147
+ {/if}
148
+
149
+ {#if showUpload}
150
+ <!-- Upload Button -->
151
+ <button
152
+ class="action-button upload-button"
153
+ onclick={handleUpload}
154
+ disabled={disabled || !conversationId}
155
+ title="Upload File"
156
+ aria-label="Upload file"
157
+ >
158
+ <svg viewBox="0 0 24 24" class="action-icon">
159
+ <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66L9.64 16.2a2 2 0 0 1-2.83-2.83l8.49-8.49"/>
160
+ </svg>
161
+ <span class="action-label">Upload</span>
162
+ </button>
163
+ {/if}
164
+
165
+ {#if showComplete}
166
+ <!-- Completion Toggle -->
167
+ <button
168
+ class="action-button completion-button"
169
+ class:completed={isCompleted}
170
+ onclick={handleCompletionToggle}
171
+ disabled={disabled || !conversationId}
172
+ title={isCompleted ? 'Mark as Active' : 'Mark as Complete'}
173
+ aria-label={isCompleted ? 'Mark conversation as active' : 'Mark conversation as complete'}
174
+ >
175
+ {#if isCompleted}
176
+ <svg viewBox="0 0 24 24" class="action-icon">
177
+ <polyline points="20,6 9,17 4,12"/>
178
+ </svg>
179
+ <span class="action-label">Completed</span>
180
+ {:else}
181
+ <svg viewBox="0 0 24 24" class="action-icon">
182
+ <circle cx="12" cy="12" r="10"/>
183
+ <path d="m9 12 2 2 4-4"/>
184
+ </svg>
185
+ <span class="action-label">Complete</span>
186
+ {/if}
187
+ </button>
188
+ {/if}
189
+ </div>
190
+
191
+ <style>
192
+ .action-bar {
193
+ display: flex;
194
+ align-items: center;
195
+ gap: 0.5rem;
196
+ padding: 0.75rem;
197
+ border-top: 1px solid #e5e7eb;
198
+ background-color: #f9fafb;
199
+ flex-wrap: wrap;
200
+ }
201
+
202
+ .action-bar.disabled {
203
+ opacity: 0.5;
204
+ pointer-events: none;
205
+ }
206
+
207
+ .action-button {
208
+ display: flex;
209
+ align-items: center;
210
+ gap: 0.5rem;
211
+ padding: 0.5rem 0.75rem;
212
+ border: 1px solid #d1d5db;
213
+ border-radius: 0.5rem;
214
+ background-color: white;
215
+ color: #374151;
216
+ font-size: 0.875rem;
217
+ font-weight: 500;
218
+ cursor: pointer;
219
+ transition: all 0.2s ease;
220
+ position: relative;
221
+ min-height: 2.5rem;
222
+ }
223
+
224
+ .action-button:hover:not(:disabled) {
225
+ background-color: #f3f4f6;
226
+ border-color: #9ca3af;
227
+ transform: translateY(-1px);
228
+ }
229
+
230
+ .action-button:active:not(:disabled) {
231
+ transform: translateY(0);
232
+ }
233
+
234
+ .action-button:disabled {
235
+ opacity: 0.5;
236
+ cursor: not-allowed;
237
+ transform: none;
238
+ }
239
+
240
+ .action-button:focus-visible {
241
+ outline: none;
242
+ box-shadow: 0 0 0 2px #3b82f6, 0 0 0 4px rgba(59, 130, 246, 0.1);
243
+ }
244
+
245
+ .action-icon {
246
+ width: 1.25rem;
247
+ height: 1.25rem;
248
+ fill: none;
249
+ stroke: currentColor;
250
+ stroke-width: 2;
251
+ stroke-linecap: round;
252
+ stroke-linejoin: round;
253
+ }
254
+
255
+ .action-label {
256
+ font-size: 0.75rem;
257
+ white-space: nowrap;
258
+ }
259
+
260
+ /* Screenshot button styling */
261
+ .screenshot-button:hover:not(:disabled) {
262
+ background-color: #dbeafe;
263
+ border-color: #3b82f6;
264
+ color: #1d4ed8;
265
+ }
266
+
267
+ /* Recording button styling */
268
+ .record-button.recording {
269
+ background-color: #fee2e2;
270
+ border-color: #ef4444;
271
+ color: #dc2626;
272
+ }
273
+
274
+ .record-button.recording:hover {
275
+ background-color: #fecaca;
276
+ }
277
+
278
+ .recording-indicator {
279
+ position: absolute;
280
+ top: 0.25rem;
281
+ right: 0.25rem;
282
+ width: 0.5rem;
283
+ height: 0.5rem;
284
+ background-color: #ef4444;
285
+ border-radius: 50%;
286
+ animation: pulse 2s infinite;
287
+ }
288
+
289
+ /* Upload button styling */
290
+ .upload-button:hover:not(:disabled) {
291
+ background-color: #f0fdf4;
292
+ border-color: #22c55e;
293
+ color: #15803d;
294
+ }
295
+
296
+ /* Completion button styling */
297
+ .completion-button.completed {
298
+ background-color: #dcfce7;
299
+ border-color: #22c55e;
300
+ color: #15803d;
301
+ }
302
+
303
+ .completion-button.completed:hover {
304
+ background-color: #bbf7d0;
305
+ }
306
+
307
+ .completion-button:not(.completed):hover:not(:disabled) {
308
+ background-color: #f9fafb;
309
+ border-color: #6b7280;
310
+ }
311
+
312
+ @keyframes pulse {
313
+ 0%, 100% {
314
+ opacity: 1;
315
+ }
316
+ 50% {
317
+ opacity: 0.5;
318
+ }
319
+ }
320
+
321
+ /* Responsive design */
322
+ @media (max-width: 640px) {
323
+ .action-bar {
324
+ justify-content: space-between;
325
+ }
326
+
327
+ .action-button {
328
+ flex: 1;
329
+ justify-content: center;
330
+ min-width: 0;
331
+ }
332
+
333
+ .action-label {
334
+ display: none;
335
+ }
336
+
337
+ .action-icon {
338
+ width: 1.5rem;
339
+ height: 1.5rem;
340
+ }
341
+ }
342
+ </style>
@@ -0,0 +1,37 @@
1
+ import type { ChatContext } from '../types/context.js';
2
+ interface Props {
3
+ context: ChatContext;
4
+ conversationId: string | null;
5
+ isRecording?: boolean;
6
+ isCompleted?: boolean;
7
+ disabled?: boolean;
8
+ showScreenshot?: boolean;
9
+ showRecord?: boolean;
10
+ showUpload?: boolean;
11
+ showComplete?: boolean;
12
+ }
13
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
14
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
15
+ $$bindings?: Bindings;
16
+ } & Exports;
17
+ (internal: unknown, props: Props & {
18
+ $$events?: Events;
19
+ $$slots?: Slots;
20
+ }): Exports & {
21
+ $set?: any;
22
+ $on?: any;
23
+ };
24
+ z_$$bindings?: Bindings;
25
+ }
26
+ declare const ActionBar: $$__sveltets_2_IsomorphicComponent<Props, {
27
+ screenshot: CustomEvent<any>;
28
+ error: CustomEvent<any>;
29
+ recordStop: CustomEvent<any>;
30
+ recordStart: CustomEvent<any>;
31
+ upload: CustomEvent<any>;
32
+ complete: CustomEvent<any>;
33
+ } & {
34
+ [evt: string]: CustomEvent<any>;
35
+ }, {}, {}, "">;
36
+ type ActionBar = InstanceType<typeof ActionBar>;
37
+ export default ActionBar;