ragged-chat-sdk 1.0.3 → 1.0.5

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.
@@ -0,0 +1,33 @@
1
+ # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3
+
4
+ name: Node.js Package
5
+
6
+ on:
7
+ release:
8
+ types: [created]
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-node@v4
16
+ with:
17
+ node-version: 20
18
+ - run: npm ci
19
+ - run: npm test
20
+
21
+ publish-npm:
22
+ needs: build
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+ - uses: actions/setup-node@v4
27
+ with:
28
+ node-version: 20
29
+ registry-url: https://registry.npmjs.org/
30
+ - run: npm ci
31
+ - run: npm publish
32
+ env:
33
+ NODE_AUTH_TOKEN: ${{secrets.npm_token}}
package/README.md CHANGED
@@ -26,14 +26,57 @@ init({
26
26
  | --- | --- | --- |
27
27
  | `subdomain` | `string` | **Required**. The unique subdomain of your chatbot. |
28
28
  | `apiUrl` | `string` | Optional. The base URL of the Ragged API. Defaults to `https://ragflowdb.onrender.com/api`. |
29
+ | `widgetShape` | `'circle' \| 'rounded-square'` | Optional. The shape of the floating widget button. Defaults to `'circle'`. |
30
+ | `widgetSize` | `'small' \| 'medium' \| 'large'` | Optional. The size of the floating widget button. Defaults to `'medium'`. |
29
31
 
30
- ## Example
32
+ ### Widget Customization
33
+
34
+ You can customize the appearance of the floating chat widget button:
35
+
36
+ **Shape Options:**
37
+ - `'circle'` - Circular button (default)
38
+ - `'rounded-square'` - Square button with rounded corners
39
+
40
+ **Size Options:**
41
+ - `'small'` - 48x48 pixels
42
+ - `'medium'` - 56x56 pixels (default)
43
+ - `'large'` - 68x68 pixels
44
+
45
+ ## Examples
46
+
47
+ ### Basic Setup
31
48
 
32
49
  ```javascript
33
50
  import { init } from 'ragged-chat-sdk';
34
51
 
35
- // Initialize the chatbot
52
+ // Initialize the chatbot with default settings
36
53
  init({
37
54
  subdomain: 'my-awesome-bot'
38
55
  });
39
56
  ```
57
+
58
+ ### Custom Widget Appearance
59
+
60
+ ```javascript
61
+ import { init } from 'ragged-chat-sdk';
62
+
63
+ // Large rounded square button
64
+ init({
65
+ subdomain: 'my-awesome-bot',
66
+ widgetShape: 'rounded-square',
67
+ widgetSize: 'large'
68
+ });
69
+ ```
70
+
71
+ ### Small Circular Button
72
+
73
+ ```javascript
74
+ import { init } from 'ragged-chat-sdk';
75
+
76
+ // Small circular button
77
+ init({
78
+ subdomain: 'my-awesome-bot',
79
+ widgetShape: 'circle',
80
+ widgetSize: 'small'
81
+ });
82
+ ```
package/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  export interface InitOptions {
2
- subdomain?: string;
3
- apiKey?: string;
2
+ subdomain: string;
4
3
  apiUrl?: string;
4
+ widgetShape?: 'circle' | 'rounded-square';
5
+ widgetSize?: 'small' | 'medium' | 'large';
5
6
  [key: string]: any;
6
7
  }
7
8
 
8
- export function init(config?: InitOptions): void;
9
+ export function init(config: InitOptions): void;
package/index.js CHANGED
@@ -1,25 +1,14 @@
1
1
  export function init(config = {}) {
2
- // Configuration
3
- // Automatically detect API URL if loaded via script tag, or use default production URL
4
- let defaultApiUrl = 'https://ragflowdb.onrender.com/api';
5
2
 
6
- // Attempt to detect API URL from the current script tag if in browser
7
- if (typeof document !== 'undefined' && document.currentScript) {
8
- try {
9
- const scriptUrl = new URL(document.currentScript.src);
10
- if (scriptUrl.origin.includes('ragflowdb.onrender.com') || scriptUrl.origin.includes('localhost')) {
11
- defaultApiUrl = scriptUrl.origin + '/api';
12
- }
13
- } catch (e) {
14
- // Fallback to default
15
- }
16
- }
17
3
 
18
- const API_URL = config.apiUrl || defaultApiUrl;
19
- const identifier = config.apiKey || config.subdomain;
4
+ // Configuration
5
+ const API_URL = config.apiUrl || 'https://ragflowdb.onrender.com/api';
6
+ const subdomain = config.subdomain;
7
+ let widgetShape = config.widgetShape || 'circle'; // Fallback to circle
8
+ let widgetSize = config.widgetSize || 'medium'; // Fallback to medium
20
9
 
21
- if (!identifier) {
22
- console.error('[Ragged SDK] Error: apiKey or subdomain is required. Usage: Ragged.init({ apiKey: "your-api-key" })');
10
+ if (!subdomain) {
11
+ console.error('[Ragged SDK] Error: subdomain is required. Usage: Ragged.init({ subdomain: "your-subdomain" })');
23
12
  return;
24
13
  }
25
14
 
@@ -29,11 +18,13 @@ export function init(config = {}) {
29
18
  let chatConfig = null;
30
19
  let messages = [];
31
20
  let isLoading = false;
21
+ let activeTab = 'chat';
22
+ let isSubmittingSupport = false;
32
23
 
33
24
  // Fetch chatbot configuration
34
25
  async function fetchConfig() {
35
26
  try {
36
- const response = await fetch(`${API_URL}/chat/${identifier}/config`);
27
+ const response = await fetch(`${API_URL}/chat/${subdomain}/config`);
37
28
  chatConfig = await response.json();
38
29
  } catch (error) {
39
30
  console.error('[Ragged SDK] Failed to fetch config:', error);
@@ -43,7 +34,7 @@ export function init(config = {}) {
43
34
  // Send message to chatbot
44
35
  async function sendMessage(message) {
45
36
  try {
46
- const response = await fetch(`${API_URL}/chat/${identifier}`, {
37
+ const response = await fetch(`${API_URL}/chat/${subdomain}`, {
47
38
  method: 'POST',
48
39
  headers: { 'Content-Type': 'application/json' },
49
40
  body: JSON.stringify({ message, history: messages })
@@ -56,6 +47,101 @@ export function init(config = {}) {
56
47
  }
57
48
  }
58
49
 
50
+ // Switch between tabs
51
+ function switchTab(tabId) {
52
+ activeTab = tabId;
53
+
54
+ // Update tab buttons
55
+ const tabs = ['chat', 'links', 'support'];
56
+ tabs.forEach(t => {
57
+ const btn = document.getElementById(`ragged-tab-${t}`);
58
+ if (btn) {
59
+ if (t === tabId) btn.classList.add('active');
60
+ else btn.classList.remove('active');
61
+ }
62
+ });
63
+
64
+ // Update views
65
+ const views = {
66
+ 'chat': document.getElementById('ragged-chat-view'),
67
+ 'links': document.getElementById('ragged-links-view'),
68
+ 'support': document.getElementById('ragged-support-view')
69
+ };
70
+
71
+ Object.keys(views).forEach(t => {
72
+ const view = views[t];
73
+ if (view) {
74
+ if (t === tabId) view.classList.remove('ragged-hidden');
75
+ else view.classList.add('ragged-hidden');
76
+ }
77
+ });
78
+
79
+ if (tabId === 'chat') renderMessages();
80
+ if (tabId === 'links') renderLinks();
81
+ }
82
+
83
+ // Render links
84
+ function renderLinks() {
85
+ const container = document.getElementById('ragged-links-list');
86
+ if (!container || !chatConfig?.settings?.bookmarks) return;
87
+
88
+ const links = chatConfig.settings.bookmarks;
89
+ container.innerHTML = links.map(link => `
90
+ <a href="${link.url}" target="_blank" rel="noopener noreferrer" class="ragged-link-item">
91
+ <span class="ragged-link-label">${link.label}</span>
92
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
93
+ <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
94
+ <polyline points="15 3 22 3 22 10"></polyline>
95
+ <line x1="10" y1="14" x2="22" y2="3"></line>
96
+ </svg>
97
+ </a>
98
+ `).join('');
99
+ }
100
+
101
+ // Handle support form submission
102
+ async function handleSubmitSupport(e) {
103
+ e.preventDefault();
104
+ if (isSubmittingSupport) return;
105
+
106
+ const submitBtn = document.getElementById('ragged-support-submit');
107
+ const originalText = submitBtn.innerHTML;
108
+
109
+ const data = {
110
+ name: document.getElementById('ragged-support-name').value,
111
+ email: document.getElementById('ragged-support-email').value,
112
+ type: document.getElementById('ragged-support-type').value,
113
+ impact: document.getElementById('ragged-support-impact').value,
114
+ description: document.getElementById('ragged-support-desc').value
115
+ };
116
+
117
+ try {
118
+ isSubmittingSupport = true;
119
+ submitBtn.disabled = true;
120
+ submitBtn.innerHTML = '<div class="ragged-loading-spinner"></div> Sending...';
121
+
122
+ const response = await fetch(`${API_URL}/chatbots/${subdomain}/support`, {
123
+ method: 'POST',
124
+ headers: { 'Content-Type': 'application/json' },
125
+ body: JSON.stringify(data)
126
+ });
127
+
128
+ if (response.ok) {
129
+ alert('Support ticket submitted successfully!');
130
+ document.getElementById('ragged-support-form').reset();
131
+ switchTab('chat');
132
+ } else {
133
+ throw new Error('Failed to submit');
134
+ }
135
+ } catch (error) {
136
+ console.error('[Ragged SDK] Support submission failed:', error);
137
+ alert('Failed to submit support ticket. Please try again.');
138
+ } finally {
139
+ isSubmittingSupport = false;
140
+ submitBtn.disabled = false;
141
+ submitBtn.innerHTML = originalText;
142
+ }
143
+ }
144
+
59
145
  // Format message content (bold, tables, and links)
60
146
  function formatMessage(content) {
61
147
  if (!content) return '';
@@ -548,10 +634,7 @@ export function init(config = {}) {
548
634
  }
549
635
 
550
636
  #ragged-toggle-btn {
551
- width: 56px;
552
- height: 56px;
553
637
  border: none;
554
- border-radius: 50%;
555
638
  color: white;
556
639
  cursor: pointer;
557
640
  display: flex;
@@ -563,6 +646,31 @@ export function init(config = {}) {
563
646
  overflow: hidden;
564
647
  }
565
648
 
649
+ /* Size variations */
650
+ #ragged-toggle-btn.size-small {
651
+ width: 48px;
652
+ height: 48px;
653
+ }
654
+
655
+ #ragged-toggle-btn.size-medium {
656
+ width: 56px;
657
+ height: 56px;
658
+ }
659
+
660
+ #ragged-toggle-btn.size-large {
661
+ width: 68px;
662
+ height: 68px;
663
+ }
664
+
665
+ /* Shape variations */
666
+ #ragged-toggle-btn.shape-circle {
667
+ border-radius: 50%;
668
+ }
669
+
670
+ #ragged-toggle-btn.shape-rounded-square {
671
+ border-radius: 16px;
672
+ }
673
+
566
674
  #ragged-toggle-btn:hover {
567
675
  transform: scale(1.1);
568
676
  }
@@ -599,64 +707,291 @@ export function init(config = {}) {
599
707
  }
600
708
 
601
709
  .ragged-hidden {
602
- visibility: hidden !important;
603
- opacity: 0 !important;
604
- pointer-events: none !important;
710
+ display: none !important;
711
+ }
712
+
713
+ #ragged-tabs {
714
+ display: flex;
715
+ background: #18181b;
716
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
717
+ flex-shrink: 0;
718
+ }
719
+
720
+ .ragged-tab-btn {
721
+ flex: 1;
722
+ padding: 12px 0;
723
+ background: transparent;
724
+ border: none;
725
+ color: #71717a;
726
+ font-size: 10px;
727
+ font-weight: 700;
728
+ text-transform: uppercase;
729
+ letter-spacing: 0.1em;
730
+ cursor: pointer;
731
+ display: flex;
732
+ flex-direction: column;
733
+ align-items: center;
734
+ gap: 4px;
735
+ transition: all 0.2s;
736
+ position: relative;
737
+ }
738
+
739
+ .ragged-tab-btn:hover {
740
+ color: #e4e4e7;
741
+ }
742
+
743
+ .ragged-tab-btn.active {
744
+ color: white;
745
+ }
746
+
747
+ .ragged-tab-btn.active::after {
748
+ content: '';
749
+ position: absolute;
750
+ bottom: 0;
751
+ left: 50%;
752
+ transform: translateX(-50%);
753
+ width: 4px;
754
+ height: 4px;
755
+ background: white;
756
+ border-radius: 50%;
757
+ }
758
+
759
+ #ragged-links-view, #ragged-support-view {
760
+ flex: 1;
761
+ overflow-y: auto;
762
+ padding: 24px;
763
+ display: flex;
764
+ flex-direction: column;
765
+ gap: 12px;
766
+ }
767
+
768
+ .ragged-view-title {
769
+ font-size: 10px;
770
+ font-weight: 700;
771
+ text-transform: uppercase;
772
+ letter-spacing: 0.1em;
773
+ color: #71717a;
774
+ margin-bottom: 12px;
775
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
776
+ padding-bottom: 8px;
777
+ }
778
+
779
+ .ragged-link-item {
780
+ display: flex;
781
+ align-items: center;
782
+ justify-content: space-between;
783
+ padding: 16px;
784
+ background: rgba(255, 255, 255, 0.05);
785
+ border: 1px solid rgba(255, 255, 255, 0.05);
786
+ border-radius: 16px;
787
+ text-decoration: none;
788
+ color: #e4e4e7;
789
+ transition: all 0.2s;
790
+ }
791
+
792
+ .ragged-link-item:hover {
793
+ background: rgba(255, 255, 255, 0.1);
794
+ transform: translateY(-2px);
795
+ }
796
+
797
+ .ragged-link-label {
798
+ font-weight: 600;
799
+ font-size: 14px;
800
+ }
801
+
802
+ .ragged-support-form {
803
+ display: flex;
804
+ flex-direction: column;
805
+ gap: 16px;
806
+ }
807
+
808
+ .ragged-form-group {
809
+ display: flex;
810
+ flex-direction: column;
811
+ gap: 4px;
812
+ }
813
+
814
+ .ragged-form-label {
815
+ font-size: 10px;
816
+ font-weight: 700;
817
+ text-transform: uppercase;
818
+ letter-spacing: 0.1em;
819
+ color: #71717a;
820
+ margin-left: 4px;
821
+ }
822
+
823
+ .ragged-form-input, .ragged-form-select, .ragged-form-textarea {
824
+ background: rgba(255, 255, 255, 0.05);
825
+ border: 1px solid rgba(255, 255, 255, 0.1);
826
+ border-radius: 12px;
827
+ padding: 10px 14px;
828
+ color: white;
829
+ font-size: 14px;
830
+ outline: none;
831
+ width: 100%;
832
+ }
833
+
834
+ .ragged-form-input:focus, .ragged-form-select:focus, .ragged-form-textarea:focus {
835
+ border-color: rgba(255, 255, 255, 0.2);
836
+ background: rgba(255, 255, 255, 0.08);
837
+ }
838
+
839
+ .ragged-form-textarea {
840
+ height: 100px;
841
+ resize: none;
842
+ }
843
+
844
+ .ragged-form-row {
845
+ display: grid;
846
+ grid-template-cols: 1fr 1fr;
847
+ gap: 12px;
848
+ }
849
+
850
+ #ragged-support-submit {
851
+ margin-top: 8px;
852
+ height: 48px;
853
+ border-radius: 16px;
854
+ border: none;
855
+ color: white;
856
+ font-weight: 700;
857
+ cursor: pointer;
858
+ display: flex;
859
+ align-items: center;
860
+ justify-content: center;
861
+ gap: 8px;
862
+ transition: all 0.2s;
863
+ }
864
+
865
+ #ragged-support-submit:hover {
866
+ transform: translateY(-2px);
867
+ filter: brightness(1.1);
868
+ }
869
+
870
+ #ragged-support-submit:disabled {
871
+ opacity: 0.5;
872
+ cursor: not-allowed;
873
+ transform: none;
874
+ }
875
+
876
+ .ragged-loading-spinner {
877
+ width: 16px;
878
+ height: 16px;
879
+ border: 2px solid rgba(255, 255, 255, 0.3);
880
+ border-radius: 50%;
881
+ border-top-color: white;
882
+ animation: ragged-spin 0.6s linear infinite;
883
+ }
884
+
885
+ @keyframes ragged-spin {
886
+ to { transform: rotate(360deg); }
605
887
  }
606
888
  </style>
607
889
 
608
890
  <div id="ragged-widget-container">
609
891
  <div id="ragged-chat-window" class="ragged-hidden">
610
- <div id="ragged-chat-header">
611
- <div id="ragged-chat-header-left">
612
- <div id="ragged-chat-avatar">
613
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
614
- <rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
615
- <path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
892
+ <div id="ragged-tabs">
893
+ <button id="ragged-tab-chat" class="ragged-tab-btn active">
894
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-bottom: 2px;">
895
+ <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>
616
896
  </svg>
897
+ <span>Chat</span>
898
+ </button>
899
+ <button id="ragged-tab-links" class="ragged-tab-btn ragged-hidden">
900
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-bottom: 2px;">
901
+ <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
902
+ <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
903
+ </svg>
904
+ <span>Links</span>
905
+ </button>
906
+ <button id="ragged-tab-support" class="ragged-tab-btn ragged-hidden">
907
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-bottom: 2px;">
908
+ <circle cx="12" cy="12" r="10"></circle>
909
+ <circle cx="12" cy="12" r="4"></circle>
910
+ <line x1="4.93" y1="4.93" x2="9.17" y2="9.17"></line>
911
+ <line x1="14.83" y1="14.83" x2="19.07" y2="19.07"></line>
912
+ <line x1="14.83" y1="4.93" x2="10.59" y2="9.17"></line>
913
+ <line x1="4.93" y1="14.83" x2="9.17" y2="19.07"></line>
914
+ </svg>
915
+ <span>Support</span>
916
+ </button>
917
+ </div>
918
+
919
+ <div id="ragged-chat-view">
920
+ <div id="ragged-messages">
921
+ <div id="ragged-empty-state">
922
+ <div id="ragged-empty-icon">
923
+ <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#71717a" stroke-width="2">
924
+ <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>
925
+ </svg>
926
+ </div>
927
+ <div id="ragged-empty-title">How can I help you?</div>
928
+ <div id="ragged-empty-text">Ask anything about our services, products, or pricing. I'm here to help!</div>
929
+ </div>
617
930
  </div>
618
- <div>
619
- <div id="ragged-chat-title">AI Agent</div>
620
- <div id="ragged-chat-status">Online</div>
931
+
932
+ <div id="ragged-input-container">
933
+ <form id="ragged-input-form">
934
+ <input
935
+ type="text"
936
+ id="ragged-input"
937
+ placeholder="Type your message here..."
938
+ autocomplete="off"
939
+ />
940
+ <button type="submit" id="ragged-send-btn">
941
+ <span>Send</span>
942
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
943
+ <line x1="22" y1="2" x2="11" y2="13"></line>
944
+ <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
945
+ </svg>
946
+ </button>
947
+ </form>
621
948
  </div>
622
949
  </div>
623
- <button id="ragged-close-btn">
624
- <svg width="20" height="20" 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
- <div id="ragged-messages">
632
- <div id="ragged-empty-state">
633
- <div id="ragged-empty-icon">
634
- <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#71717a" stroke-width="2">
635
- <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>
636
- </svg>
637
- </div>
638
- <div id="ragged-empty-title">How can I help you?</div>
639
- <div id="ragged-empty-text">Ask anything about our services, products, or pricing. I'm here to help!</div>
950
+
951
+ <div id="ragged-links-view" class="ragged-hidden">
952
+ <div class="ragged-view-title">Vital Resources</div>
953
+ <div id="ragged-links-list"></div>
954
+ </div>
955
+
956
+ <div id="ragged-support-view" class="ragged-hidden">
957
+ <div class="ragged-view-title">Support Ticket</div>
958
+ <form id="ragged-support-form" class="ragged-support-form">
959
+ <div class="ragged-form-group">
960
+ <label class="ragged-form-label">Name</label>
961
+ <input type="text" id="ragged-support-name" class="ragged-form-input" required placeholder="Your Name" />
962
+ </div>
963
+ <div class="ragged-form-group">
964
+ <label class="ragged-form-label">Email</label>
965
+ <input type="email" id="ragged-support-email" class="ragged-form-input" required placeholder="Your Email" />
966
+ </div>
967
+ <div class="ragged-form-row">
968
+ <div class="ragged-form-group">
969
+ <label class="ragged-form-label">Type</label>
970
+ <select id="ragged-support-type" class="ragged-form-select">
971
+ <option value="general question">General Question</option>
972
+ <option value="feature request">Feature Request</option>
973
+ <option value="issue/bug">Issue/Bug</option>
974
+ <option value="account creation">Account Creation</option>
975
+ <option value="unclear">Unclear</option>
976
+ </select>
977
+ </div>
978
+ <div class="ragged-form-group">
979
+ <label class="ragged-form-label">Impact</label>
980
+ <select id="ragged-support-impact" class="ragged-form-select">
981
+ <option value="low">Low</option>
982
+ <option value="moderate" selected>Moderate</option>
983
+ <option value="high">High</option>
984
+ <option value="blocking">Blocking</option>
985
+ </select>
986
+ </div>
987
+ </div>
988
+ <div class="ragged-form-group">
989
+ <label class="ragged-form-label">Message</label>
990
+ <textarea id="ragged-support-desc" class="ragged-form-textarea" required placeholder="Tell us more..."></textarea>
991
+ </div>
992
+ <button type="submit" id="ragged-support-submit">Submit Ticket</button>
993
+ </form>
640
994
  </div>
641
- </div>
642
-
643
- <div id="ragged-input-container">
644
- <form id="ragged-input-form">
645
- <input
646
- type="text"
647
- id="ragged-input"
648
- placeholder="Type your message here..."
649
- autocomplete="off"
650
- />
651
- <button type="submit" id="ragged-send-btn">
652
- <span>Send</span>
653
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
654
- <line x1="22" y1="2" x2="11" y2="13"></line>
655
- <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
656
- </svg>
657
- </button>
658
- </form>
659
- </div>
660
995
  </div>
661
996
 
662
997
  <button id="ragged-toggle-btn">
@@ -790,13 +1125,51 @@ export function init(config = {}) {
790
1125
  const emptyTitle = document.getElementById('ragged-empty-title');
791
1126
  const avatar = document.getElementById('ragged-chat-avatar');
792
1127
  const toggleLogo = document.getElementById('ragged-toggle-logo');
1128
+ const supportSubmitBtn = document.getElementById('ragged-support-submit');
1129
+
1130
+ const primaryColor = chatConfig.settings?.primaryColor || '#000000';
1131
+ toggleBtn.style.backgroundColor = primaryColor;
1132
+ sendBtn.style.backgroundColor = primaryColor;
1133
+ if (supportSubmitBtn) supportSubmitBtn.style.backgroundColor = primaryColor;
793
1134
 
794
- toggleBtn.style.backgroundColor = chatConfig.settings?.primaryColor || '#000000';
795
- sendBtn.style.backgroundColor = chatConfig.settings?.primaryColor || '#3b82f6';
796
1135
  chatTitle.textContent = chatConfig.name || 'AI Agent';
797
1136
  input.placeholder = chatConfig.settings?.placeholder || 'Type your message here...';
798
1137
  emptyTitle.textContent = chatConfig.settings?.welcomeMessage || 'How can I help you?';
799
1138
 
1139
+ // Show Tabs based on config
1140
+ if (chatConfig.settings?.bookmarks?.length > 0) {
1141
+ document.getElementById('ragged-tab-links').classList.remove('ragged-hidden');
1142
+ }
1143
+ if (chatConfig.settings?.supportSettings?.enabled) {
1144
+ document.getElementById('ragged-tab-support').classList.remove('ragged-hidden');
1145
+ }
1146
+
1147
+ // Apply widget shape and size customization
1148
+ if (chatConfig.settings) {
1149
+ // Prioritize backend settings if they exist, otherwise use init config
1150
+ if (chatConfig.settings.widgetShape) widgetShape = chatConfig.settings.widgetShape;
1151
+ if (chatConfig.settings.widgetSize) widgetSize = chatConfig.settings.widgetSize;
1152
+ }
1153
+
1154
+ if (toggleBtn) {
1155
+ // Clear any existing shape/size classes
1156
+ toggleBtn.classList.remove('shape-circle', 'shape-rounded-square', 'size-small', 'size-medium', 'size-large');
1157
+ toggleBtn.classList.add(`shape-${widgetShape}`);
1158
+ toggleBtn.classList.add(`size-${widgetSize}`);
1159
+
1160
+ // Also update icon sizing
1161
+ const iconMessage = document.getElementById('ragged-icon-message');
1162
+ const iconClose = document.getElementById('ragged-icon-close');
1163
+ if (iconMessage) {
1164
+ iconMessage.setAttribute('width', widgetSize === 'small' ? '24' : widgetSize === 'large' ? '32' : '28');
1165
+ iconMessage.setAttribute('height', widgetSize === 'small' ? '24' : widgetSize === 'large' ? '32' : '28');
1166
+ }
1167
+ if (iconClose) {
1168
+ iconClose.setAttribute('width', widgetSize === 'small' ? '24' : widgetSize === 'large' ? '32' : '28');
1169
+ iconClose.setAttribute('height', widgetSize === 'small' ? '24' : widgetSize === 'large' ? '32' : '28');
1170
+ }
1171
+ }
1172
+
800
1173
  // Set custom logo for all users (free platform)
801
1174
  if (chatConfig.settings?.brandLogo) {
802
1175
  const logoUrl = chatConfig.settings.brandLogo;
@@ -816,6 +1189,14 @@ export function init(config = {}) {
816
1189
  document.getElementById('ragged-toggle-btn').addEventListener('click', toggleWidget);
817
1190
  document.getElementById('ragged-close-btn').addEventListener('click', toggleWidget);
818
1191
  document.getElementById('ragged-input-form').addEventListener('submit', handleSend);
1192
+
1193
+ // Tab Listeners
1194
+ document.getElementById('ragged-tab-chat').addEventListener('click', () => switchTab('chat'));
1195
+ document.getElementById('ragged-tab-links').addEventListener('click', () => switchTab('links'));
1196
+ document.getElementById('ragged-tab-support').addEventListener('click', () => switchTab('support'));
1197
+
1198
+ // Support Form Listener
1199
+ document.getElementById('ragged-support-form').addEventListener('submit', handleSubmitSupport);
819
1200
  }
820
1201
 
821
1202
  if (document.readyState === 'loading') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ragged-chat-sdk",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Official SDK for integrating Ragged Chatbots into your website.",
5
5
  "type": "module",
6
6
  "main": "index.js",