ragged-chat-sdk 1.0.0

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/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Ragged Chatbot SDK
2
+
3
+ The official SDK for integrating Ragged Chatbots into your website.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install ragged-chat-sdk
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ Import the SDK and initialize it with your chatbot's subdomain.
14
+
15
+ ```javascript
16
+ import { init } from 'ragged-chat-sdk';
17
+
18
+ init({
19
+ subdomain: 'your-chatbot-subdomain'
20
+ });
21
+ ```
22
+
23
+ ### Configuration Options
24
+
25
+ | Option | Type | Description |
26
+ | --- | --- | --- |
27
+ | `subdomain` | `string` | **Required**. The unique subdomain of your chatbot. |
28
+ | `apiUrl` | `string` | Optional. The base URL of the Ragged API. Defaults to `https://ragflowdb.onrender.com/api`. |
29
+
30
+ ## Example
31
+
32
+ ```javascript
33
+ import { init } from 'ragged-chat-sdk';
34
+
35
+ // Initialize the chatbot
36
+ init({
37
+ subdomain: 'my-awesome-bot'
38
+ });
39
+ ```
package/index.js ADDED
@@ -0,0 +1,783 @@
1
+ export function init(config = {}) {
2
+ 'use strict';
3
+
4
+ // Configuration
5
+ const API_URL = config.apiUrl || 'https://ragflowdb.onrender.com/api';
6
+ const subdomain = config.subdomain;
7
+
8
+ if (!subdomain) {
9
+ console.error('[Ragged SDK] Error: subdomain is required. Usage: Ragged.init({ subdomain: "your-subdomain" })');
10
+ return;
11
+ }
12
+
13
+ // State
14
+ let isOpen = false;
15
+ let initialized = false;
16
+ let chatConfig = null;
17
+ let messages = [];
18
+ let isLoading = false;
19
+
20
+ // Fetch chatbot configuration
21
+ async function fetchConfig() {
22
+ try {
23
+ const response = await fetch(`${API_URL}/chat/${subdomain}/config`);
24
+ chatConfig = await response.json();
25
+ } catch (error) {
26
+ console.error('[Ragged SDK] Failed to fetch config:', error);
27
+ }
28
+ }
29
+
30
+ // Send message to chatbot
31
+ async function sendMessage(message) {
32
+ try {
33
+ const response = await fetch(`${API_URL}/chat/${subdomain}`, {
34
+ method: 'POST',
35
+ headers: { 'Content-Type': 'application/json' },
36
+ body: JSON.stringify({ message, history: messages })
37
+ });
38
+ const data = await response.json();
39
+ return data.response;
40
+ } catch (error) {
41
+ console.error('[Ragged SDK] Failed to send message:', error);
42
+ return "Sorry, I'm having trouble connecting right now.";
43
+ }
44
+ }
45
+
46
+ // Format message content (bold and tables)
47
+ function formatMessage(content) {
48
+ if (!content) return '';
49
+
50
+ let formatted = content;
51
+
52
+ // 1. Bold: **text** -> <strong>text</strong>
53
+ formatted = formatted.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
54
+
55
+ // 2. Tables: | col1 | col2 |
56
+ const lines = formatted.split('\n');
57
+ let inTable = false;
58
+ let tableHTML = '';
59
+ let result = [];
60
+
61
+ for (let i = 0; i < lines.length; i++) {
62
+ const line = lines[i].trim();
63
+ if (line.startsWith('|') && line.endsWith('|')) {
64
+ if (!inTable) {
65
+ inTable = true;
66
+ tableHTML = '<div class="ragged-table-container"><table>';
67
+ }
68
+
69
+ const cells = line.split('|').filter(c => c.trim() !== '' || (line.indexOf('|' + c + '|') !== -1));
70
+ // Handle header/separator
71
+ if (line.includes('---')) {
72
+ continue;
73
+ }
74
+
75
+ const isHeader = !tableHTML.includes('</thead>') && !tableHTML.includes('<tbody>');
76
+ if (isHeader) {
77
+ tableHTML += '<thead><tr>';
78
+ cells.forEach(cell => {
79
+ tableHTML += `<th>${cell.trim()}</th>`;
80
+ });
81
+ tableHTML += '</tr></thead><tbody>';
82
+ } else {
83
+ tableHTML += '<tr>';
84
+ cells.forEach(cell => {
85
+ tableHTML += `<td>${cell.trim()}</td>`;
86
+ });
87
+ tableHTML += '</tr>';
88
+ }
89
+ } else {
90
+ if (inTable) {
91
+ inTable = false;
92
+ tableHTML += '</tbody></table></div>';
93
+ result.push(tableHTML);
94
+ tableHTML = '';
95
+ }
96
+ result.push(line);
97
+ }
98
+ }
99
+
100
+ if (inTable) {
101
+ tableHTML += '</tbody></table></div>';
102
+ result.push(tableHTML);
103
+ }
104
+
105
+ return result.join('\n');
106
+ }
107
+
108
+ // Create widget HTML
109
+ function createWidget() {
110
+ const container = document.createElement('div');
111
+ container.id = 'ragged-chat-widget';
112
+ container.innerHTML = `
113
+ <style>
114
+ #ragged-chat-widget * {
115
+ box-sizing: border-box;
116
+ margin: 0;
117
+ padding: 0;
118
+ }
119
+
120
+ #ragged-widget-container {
121
+ position: fixed;
122
+ bottom: 24px;
123
+ right: 24px;
124
+ z-index: 999999;
125
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
126
+ display: flex;
127
+ flex-direction: column;
128
+ align-items: flex-end;
129
+ }
130
+
131
+ #ragged-chat-window {
132
+ position: fixed;
133
+ bottom: 96px;
134
+ right: 24px;
135
+ width: calc(100% - 48px);
136
+ height: calc(100% - 140px);
137
+ max-width: 380px;
138
+ max-height: 540px;
139
+ background: rgba(9, 9, 11, 0.8);
140
+ backdrop-filter: blur(48px);
141
+ border: 1px solid rgba(255, 255, 255, 0.1);
142
+ display: flex;
143
+ flex-direction: column;
144
+ overflow: hidden;
145
+ transition: all 0.3s ease;
146
+ border-radius: 24px;
147
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.4);
148
+ }
149
+
150
+ @media (min-width: 640px) {
151
+ #ragged-chat-window {
152
+ position: static;
153
+ width: 380px;
154
+ height: 540px;
155
+ margin-bottom: 20px;
156
+ border-radius: 32px;
157
+ box-shadow: 0 32px 64px -12px rgba(0, 0, 0, 0.6);
158
+ }
159
+ }
160
+
161
+ #ragged-chat-header {
162
+ padding: 16px;
163
+ background: white;
164
+ color: black;
165
+ display: flex;
166
+ justify-content: space-between;
167
+ align-items: center;
168
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
169
+ flex-shrink: 0;
170
+ }
171
+
172
+ @media (min-width: 640px) {
173
+ #ragged-chat-header {
174
+ padding: 24px;
175
+ }
176
+ }
177
+
178
+ #ragged-chat-header-left {
179
+ display: flex;
180
+ align-items: center;
181
+ gap: 16px;
182
+ }
183
+
184
+ #ragged-chat-avatar {
185
+ width: 32px;
186
+ height: 32px;
187
+ background: black;
188
+ color: white;
189
+ border-radius: 50%;
190
+ display: flex;
191
+ align-items: center;
192
+ justify-content: center;
193
+ box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06);
194
+ overflow: hidden;
195
+ flex-shrink: 0;
196
+ }
197
+
198
+ @media (min-width: 640px) {
199
+ #ragged-chat-avatar {
200
+ width: 40px;
201
+ height: 40px;
202
+ }
203
+ }
204
+
205
+ #ragged-chat-avatar img {
206
+ width: 100%;
207
+ height: 100%;
208
+ object-fit: cover;
209
+ }
210
+
211
+ #ragged-chat-title {
212
+ font-weight: 700;
213
+ font-size: 13px;
214
+ letter-spacing: -0.05em;
215
+ }
216
+
217
+ @media (min-width: 640px) {
218
+ #ragged-chat-title {
219
+ font-size: 14px;
220
+ }
221
+ }
222
+
223
+ #ragged-chat-status {
224
+ font-size: 9px;
225
+ font-weight: 700;
226
+ text-transform: uppercase;
227
+ letter-spacing: 0.1em;
228
+ color: #71717a;
229
+ margin-top: 2px;
230
+ }
231
+
232
+ @media (min-width: 640px) {
233
+ #ragged-chat-status {
234
+ font-size: 10px;
235
+ margin-top: 4px;
236
+ }
237
+ }
238
+
239
+ #ragged-close-btn {
240
+ background: transparent;
241
+ border: none;
242
+ cursor: pointer;
243
+ padding: 12px;
244
+ border-radius: 50%;
245
+ transition: background 0.2s;
246
+ min-width: 44px;
247
+ min-height: 44px;
248
+ display: flex;
249
+ align-items: center;
250
+ justify-content: center;
251
+ }
252
+
253
+ @media (min-width: 640px) {
254
+ #ragged-close-btn {
255
+ padding: 8px;
256
+ min-width: auto;
257
+ min-height: auto;
258
+ }
259
+ }
260
+
261
+ #ragged-close-btn:hover {
262
+ background: rgba(0, 0, 0, 0.05);
263
+ }
264
+
265
+ #ragged-messages {
266
+ flex: 1;
267
+ overflow-y: auto;
268
+ padding: 16px 24px;
269
+ display: flex;
270
+ flex-direction: column;
271
+ gap: 24px;
272
+ }
273
+
274
+ @media (min-width: 768px) {
275
+ #ragged-messages {
276
+ padding: 24px;
277
+ }
278
+ }
279
+
280
+ #ragged-empty-state {
281
+ text-align: center;
282
+ padding: 40px 20px;
283
+ }
284
+
285
+ @media (min-width: 640px) {
286
+ #ragged-empty-state {
287
+ padding: 80px 20px;
288
+ }
289
+ }
290
+
291
+ #ragged-empty-icon {
292
+ width: 64px;
293
+ height: 64px;
294
+ background: rgba(255, 255, 255, 0.05);
295
+ border-radius: 16px;
296
+ display: flex;
297
+ align-items: center;
298
+ justify-content: center;
299
+ margin: 0 auto 16px;
300
+ border: 1px solid rgba(255, 255, 255, 0.1);
301
+ }
302
+
303
+ #ragged-empty-title {
304
+ font-size: 18px;
305
+ font-weight: 600;
306
+ color: #e4e4e7;
307
+ margin-bottom: 8px;
308
+ }
309
+
310
+ @media (min-width: 640px) {
311
+ #ragged-empty-title {
312
+ font-size: 20px;
313
+ }
314
+ }
315
+
316
+ #ragged-empty-text {
317
+ color: #71717a;
318
+ font-size: 14px;
319
+ max-width: 300px;
320
+ margin: 0 auto;
321
+ }
322
+
323
+ .ragged-message {
324
+ display: flex;
325
+ animation: fadeIn 0.3s ease;
326
+ }
327
+
328
+ @keyframes fadeIn {
329
+ from { opacity: 0; transform: translateY(8px); }
330
+ to { opacity: 1; transform: translateY(0); }
331
+ }
332
+
333
+ .ragged-message.user {
334
+ justify-content: flex-end;
335
+ }
336
+
337
+ .ragged-message-content {
338
+ max-width: 85%;
339
+ padding: 12px 16px;
340
+ border-radius: 16px;
341
+ font-size: 14px;
342
+ line-height: 1.5;
343
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
344
+ }
345
+
346
+ .ragged-message-content strong {
347
+ font-weight: 700;
348
+ color: inherit;
349
+ }
350
+
351
+ .ragged-table-container {
352
+ width: 100%;
353
+ overflow-x: auto;
354
+ margin: 12px 0;
355
+ border-radius: 8px;
356
+ border: 1px solid rgba(255, 255, 255, 0.1);
357
+ background: rgba(255, 255, 255, 0.02);
358
+ }
359
+
360
+ .ragged-message.user .ragged-table-container {
361
+ border-color: rgba(255, 255, 255, 0.2);
362
+ background: rgba(0, 0, 0, 0.1);
363
+ }
364
+
365
+ table {
366
+ width: 100%;
367
+ border-collapse: collapse;
368
+ font-size: 11px;
369
+ line-height: 1.4;
370
+ }
371
+
372
+ th, td {
373
+ padding: 8px 12px;
374
+ text-align: left;
375
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
376
+ }
377
+
378
+ th {
379
+ font-weight: 700;
380
+ color: #a1a1aa;
381
+ background: rgba(255, 255, 255, 0.03);
382
+ text-transform: uppercase;
383
+ letter-spacing: 0.05em;
384
+ }
385
+
386
+ tr:last-child td {
387
+ border-bottom: none;
388
+ }
389
+
390
+ .ragged-message.user td, .ragged-message.user th {
391
+ border-bottom-color: rgba(255, 255, 255, 0.1);
392
+ }
393
+
394
+ .ragged-message.user .ragged-message-content {
395
+ color: white;
396
+ border-top-right-radius: 4px;
397
+ }
398
+
399
+ .ragged-message.assistant .ragged-message-content {
400
+ background: rgba(39, 39, 42, 0.8);
401
+ color: #fafafa;
402
+ border-top-left-radius: 4px;
403
+ border: 1px solid rgba(255, 255, 255, 0.1);
404
+ }
405
+
406
+ .ragged-loading {
407
+ display: flex;
408
+ gap: 4px;
409
+ padding: 16px;
410
+ background: rgba(39, 39, 42, 0.8);
411
+ border-radius: 16px;
412
+ border-top-left-radius: 4px;
413
+ border: 1px solid rgba(255, 255, 255, 0.1);
414
+ width: fit-content;
415
+ }
416
+
417
+ .ragged-loading-dot {
418
+ width: 8px;
419
+ height: 8px;
420
+ border-radius: 50%;
421
+ animation: bounce 1.4s infinite ease-in-out both;
422
+ }
423
+
424
+ .ragged-loading-dot:nth-child(1) { animation-delay: -0.32s; }
425
+ .ragged-loading-dot:nth-child(2) { animation-delay: -0.16s; }
426
+
427
+ @keyframes bounce {
428
+ 0%, 80%, 100% { transform: scale(0); }
429
+ 40% { transform: scale(1); }
430
+ }
431
+
432
+ #ragged-input-container {
433
+ padding: 16px 24px;
434
+ background: rgba(24, 24, 27, 0.5);
435
+ border-top: 1px solid rgba(255, 255, 255, 0.05);
436
+ flex-shrink: 0;
437
+ }
438
+
439
+ @media (min-width: 768px) {
440
+ #ragged-input-container {
441
+ padding: 24px;
442
+ }
443
+ }
444
+
445
+ #ragged-input-form {
446
+ display: flex;
447
+ gap: 12px;
448
+ }
449
+
450
+ #ragged-input {
451
+ flex: 1;
452
+ background: rgba(39, 39, 42, 0.5);
453
+ border: 1px solid rgba(255, 255, 255, 0.1);
454
+ border-radius: 16px;
455
+ padding: 12px 20px;
456
+ font-size: 14px;
457
+ color: white;
458
+ outline: none;
459
+ transition: all 0.2s;
460
+ }
461
+
462
+ #ragged-input::placeholder {
463
+ color: #52525b;
464
+ }
465
+
466
+ #ragged-input:focus {
467
+ border-color: rgba(59, 130, 246, 0.5);
468
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
469
+ }
470
+
471
+ #ragged-send-btn {
472
+ padding: 12px 16px;
473
+ border: none;
474
+ border-radius: 16px;
475
+ font-weight: 500;
476
+ font-size: 14px;
477
+ cursor: pointer;
478
+ transition: all 0.2s;
479
+ display: flex;
480
+ align-items: center;
481
+ gap: 6px;
482
+ color: white;
483
+ min-height: 44px;
484
+ }
485
+
486
+ @media (min-width: 640px) {
487
+ #ragged-send-btn {
488
+ padding: 12px 24px;
489
+ gap: 8px;
490
+ }
491
+ }
492
+
493
+ #ragged-send-btn:hover {
494
+ transform: scale(1.05);
495
+ }
496
+
497
+ #ragged-send-btn:active {
498
+ transform: scale(0.95);
499
+ }
500
+
501
+ #ragged-send-btn:disabled {
502
+ opacity: 0.5;
503
+ cursor: not-allowed;
504
+ transform: none;
505
+ }
506
+
507
+ #ragged-toggle-btn {
508
+ width: 56px;
509
+ height: 56px;
510
+ border: none;
511
+ border-radius: 50%;
512
+ color: white;
513
+ cursor: pointer;
514
+ display: flex;
515
+ align-items: center;
516
+ justify-content: center;
517
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
518
+ transition: all 0.2s;
519
+ position: relative;
520
+ overflow: hidden;
521
+ }
522
+
523
+ #ragged-toggle-btn:hover {
524
+ transform: scale(1.1);
525
+ }
526
+
527
+ #ragged-toggle-btn:active {
528
+ transform: scale(0.9);
529
+ }
530
+
531
+ .ragged-toggle-icon {
532
+ position: absolute;
533
+ transition: all 0.3s;
534
+ }
535
+
536
+ .ragged-toggle-icon.hidden {
537
+ opacity: 0;
538
+ transform: scale(0);
539
+ }
540
+
541
+ #ragged-toggle-logo {
542
+ position: absolute;
543
+ inset: 0;
544
+ transition: all 0.3s;
545
+ }
546
+
547
+ #ragged-toggle-logo img {
548
+ width: 100%;
549
+ height: 100%;
550
+ object-fit: cover;
551
+ }
552
+
553
+ #ragged-toggle-logo.hidden {
554
+ opacity: 0;
555
+ transform: scale(0);
556
+ }
557
+
558
+ .ragged-hidden {
559
+ visibility: hidden !important;
560
+ opacity: 0 !important;
561
+ pointer-events: none !important;
562
+ }
563
+ </style>
564
+
565
+ <div id="ragged-widget-container">
566
+ <div id="ragged-chat-window" class="ragged-hidden">
567
+ <div id="ragged-chat-header">
568
+ <div id="ragged-chat-header-left">
569
+ <div id="ragged-chat-avatar">
570
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
571
+ <rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
572
+ <path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
573
+ </svg>
574
+ </div>
575
+ <div>
576
+ <div id="ragged-chat-title">AI Agent</div>
577
+ <div id="ragged-chat-status">Online</div>
578
+ </div>
579
+ </div>
580
+ <button id="ragged-close-btn">
581
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
582
+ <line x1="18" y1="6" x2="6" y2="18"></line>
583
+ <line x1="6" y1="6" x2="18" y2="18"></line>
584
+ </svg>
585
+ </button>
586
+ </div>
587
+
588
+ <div id="ragged-messages">
589
+ <div id="ragged-empty-state">
590
+ <div id="ragged-empty-icon">
591
+ <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#71717a" stroke-width="2">
592
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
593
+ </svg>
594
+ </div>
595
+ <div id="ragged-empty-title">How can I help you?</div>
596
+ <div id="ragged-empty-text">Ask anything about our services, products, or pricing. I'm here to help!</div>
597
+ </div>
598
+ </div>
599
+
600
+ <div id="ragged-input-container">
601
+ <form id="ragged-input-form">
602
+ <input
603
+ type="text"
604
+ id="ragged-input"
605
+ placeholder="Type your message here..."
606
+ autocomplete="off"
607
+ />
608
+ <button type="submit" id="ragged-send-btn">
609
+ <span>Send</span>
610
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
611
+ <line x1="22" y1="2" x2="11" y2="13"></line>
612
+ <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
613
+ </svg>
614
+ </button>
615
+ </form>
616
+ </div>
617
+ </div>
618
+
619
+ <button id="ragged-toggle-btn">
620
+ <div id="ragged-toggle-logo" class="hidden"></div>
621
+ <svg class="ragged-toggle-icon" id="ragged-icon-message" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
622
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
623
+ </svg>
624
+ <svg class="ragged-toggle-icon hidden" id="ragged-icon-close" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
625
+ <line x1="18" y1="6" x2="6" y2="18"></line>
626
+ <line x1="6" y1="6" x2="18" y2="18"></line>
627
+ </svg>
628
+ </button>
629
+ </div>
630
+ `;
631
+
632
+ document.body.appendChild(container);
633
+ return container;
634
+ }
635
+
636
+ // Render messages
637
+ function renderMessages() {
638
+ const messagesContainer = document.getElementById('ragged-messages');
639
+ const emptyState = document.getElementById('ragged-empty-state');
640
+
641
+ if (!messagesContainer) {
642
+ console.error('[Ragged SDK] Messages container not found. Widget might not be fully initialized.');
643
+ return;
644
+ }
645
+
646
+ if (!emptyState) {
647
+ console.warn('[Ragged SDK] Empty state container not found.');
648
+ }
649
+
650
+ if (messages.length === 0) {
651
+ if (emptyState) emptyState.classList.remove('ragged-hidden');
652
+ return;
653
+ }
654
+
655
+ if (emptyState) emptyState.classList.add('ragged-hidden');
656
+
657
+ const messagesHTML = messages.map(msg => `
658
+ <div class="ragged-message ${msg.role}">
659
+ <div class="ragged-message-content" style="${msg.role === 'user' ? `background-color: ${chatConfig?.settings?.primaryColor || '#3b82f6'}` : ''}">${formatMessage(msg.content)}</div>
660
+ </div>
661
+ `).join('');
662
+
663
+ const loadingHTML = isLoading ? `
664
+ <div class="ragged-message assistant">
665
+ <div class="ragged-loading">
666
+ <div class="ragged-loading-dot" style="background-color: ${chatConfig?.settings?.primaryColor || '#3b82f6'}"></div>
667
+ <div class="ragged-loading-dot" style="background-color: ${chatConfig?.settings?.primaryColor || '#3b82f6'}"></div>
668
+ <div class="ragged-loading-dot" style="background-color: ${chatConfig?.settings?.primaryColor || '#3b82f6'}"></div>
669
+ </div>
670
+ </div>
671
+ ` : '';
672
+
673
+ messagesContainer.innerHTML = messagesHTML + loadingHTML;
674
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
675
+ }
676
+
677
+ // Toggle widget
678
+ function toggleWidget() {
679
+ isOpen = !isOpen;
680
+ const chatWindow = document.getElementById('ragged-chat-window');
681
+ const toggleBtn = document.getElementById('ragged-toggle-btn');
682
+ const iconMessage = document.getElementById('ragged-icon-message');
683
+ const iconClose = document.getElementById('ragged-icon-close');
684
+ const toggleLogo = document.getElementById('ragged-toggle-logo');
685
+
686
+ if (isOpen) {
687
+ chatWindow.classList.remove('ragged-hidden');
688
+ iconMessage.classList.add('hidden');
689
+ iconClose.classList.remove('hidden');
690
+ if (chatConfig?.settings?.brandLogo) {
691
+ toggleLogo.classList.add('hidden');
692
+ }
693
+ toggleBtn.style.backgroundColor = '#000000';
694
+ } else {
695
+ chatWindow.classList.add('ragged-hidden');
696
+ if (!chatConfig?.settings?.brandLogo) {
697
+ iconMessage.classList.remove('hidden');
698
+ }
699
+ iconClose.classList.add('hidden');
700
+ if (chatConfig?.settings?.brandLogo) {
701
+ toggleLogo.classList.remove('hidden');
702
+ }
703
+ toggleBtn.style.backgroundColor = chatConfig?.settings?.primaryColor || '#000000';
704
+ }
705
+ }
706
+
707
+ // Handle message send
708
+ async function handleSend(e) {
709
+ e.preventDefault();
710
+
711
+ const input = document.getElementById('ragged-input');
712
+ if (!input) {
713
+ console.error('[Ragged SDK] Input element not found');
714
+ return;
715
+ }
716
+
717
+ const message = input.value.trim();
718
+
719
+ if (!message || isLoading) return;
720
+
721
+ messages.push({ role: 'user', content: message });
722
+ input.value = '';
723
+ isLoading = true;
724
+ renderMessages();
725
+
726
+ const response = await sendMessage(message);
727
+ messages.push({ role: 'assistant', content: response });
728
+ isLoading = false;
729
+ renderMessages();
730
+ }
731
+
732
+ // Initialize widget
733
+ async function initializeWidget() {
734
+ // Prevent double initialization
735
+ if (initialized) return;
736
+ initialized = true;
737
+
738
+ await fetchConfig();
739
+
740
+ const widget = createWidget();
741
+
742
+ if (chatConfig) {
743
+ const toggleBtn = document.getElementById('ragged-toggle-btn');
744
+ const sendBtn = document.getElementById('ragged-send-btn');
745
+ const chatTitle = document.getElementById('ragged-chat-title');
746
+ const input = document.getElementById('ragged-input');
747
+ const emptyTitle = document.getElementById('ragged-empty-title');
748
+ const avatar = document.getElementById('ragged-chat-avatar');
749
+ const toggleLogo = document.getElementById('ragged-toggle-logo');
750
+
751
+ toggleBtn.style.backgroundColor = chatConfig.settings?.primaryColor || '#000000';
752
+ sendBtn.style.backgroundColor = chatConfig.settings?.primaryColor || '#3b82f6';
753
+ chatTitle.textContent = chatConfig.name || 'AI Agent';
754
+ input.placeholder = chatConfig.settings?.placeholder || 'Type your message here...';
755
+ emptyTitle.textContent = chatConfig.settings?.welcomeMessage || 'How can I help you?';
756
+
757
+ // Set custom logo for all users (free platform)
758
+ if (chatConfig.settings?.brandLogo) {
759
+ const logoUrl = chatConfig.settings.brandLogo;
760
+ if (avatar) {
761
+ avatar.innerHTML = `<img src="${logoUrl}" alt="Logo" style="width:100%; height:100%; object-fit:cover;" />`;
762
+ }
763
+ if (toggleLogo) {
764
+ toggleLogo.innerHTML = `<img src="${logoUrl}" alt="Chat" style="width:100%; height:100%; object-fit:cover;" />`;
765
+ toggleLogo.classList.remove('hidden');
766
+ // Hide the default message icon if logo is present
767
+ const iconMessage = document.getElementById('ragged-icon-message');
768
+ if (iconMessage) iconMessage.classList.add('hidden');
769
+ }
770
+ }
771
+ }
772
+
773
+ document.getElementById('ragged-toggle-btn').addEventListener('click', toggleWidget);
774
+ document.getElementById('ragged-close-btn').addEventListener('click', toggleWidget);
775
+ document.getElementById('ragged-input-form').addEventListener('submit', handleSend);
776
+ }
777
+
778
+ if (document.readyState === 'loading') {
779
+ document.addEventListener('DOMContentLoaded', initializeWidget);
780
+ } else {
781
+ initializeWidget();
782
+ }
783
+ }
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "ragged-chat-sdk",
3
+ "version": "1.0.0",
4
+ "description": "Official SDK for integrating Ragged Chatbots into your website.",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "keywords": [
11
+ "ragged",
12
+ "chatbot",
13
+ "sdk",
14
+ "ai",
15
+ "chat"
16
+ ],
17
+ "author": "Ragged",
18
+ "license": "ISC"
19
+ }
Binary file
package/test-import.js ADDED
@@ -0,0 +1,28 @@
1
+ import { init } from './index.js';
2
+
3
+ if (typeof init === 'function') {
4
+ console.log('SDK exports init function successfully.');
5
+ } else {
6
+ console.error('SDK failed to export init function.');
7
+ process.exit(1);
8
+ }
9
+
10
+ global.window = {
11
+ RAGGED_CONFIG: {}
12
+ };
13
+ global.document = {
14
+ readyState: 'complete',
15
+ addEventListener: () => { },
16
+ createElement: () => ({ style: {}, classList: { add: () => { }, remove: () => { } }, addEventListener: () => { } }),
17
+ body: { appendChild: () => { } },
18
+ getElementById: () => ({ addEventListener: () => { } })
19
+ };
20
+ global.fetch = async () => ({ json: async () => ({}) });
21
+
22
+ try {
23
+ init({ subdomain: 'test-bot' });
24
+ console.log('SDK init function runs without immediate crashing.');
25
+ } catch (e) {
26
+ console.error('SDK init function crashed:', e);
27
+ process.exit(1);
28
+ }
package/test-simple.js ADDED
@@ -0,0 +1,2 @@
1
+ import { init } from './index.js';
2
+ console.log('Type of init:', typeof init);