ttp-agent-sdk 2.1.13 → 2.2.1

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.
@@ -133,6 +133,69 @@
133
133
  .tab-content.active {
134
134
  display: block;
135
135
  }
136
+
137
+ .controls-panel {
138
+ background: white;
139
+ border: 2px solid #E5E7EB;
140
+ border-radius: 8px;
141
+ padding: 20px;
142
+ margin: 20px 0;
143
+ }
144
+
145
+ .control-row {
146
+ display: grid;
147
+ grid-template-columns: 150px 150px 1fr auto;
148
+ gap: 12px;
149
+ align-items: center;
150
+ margin-bottom: 12px;
151
+ padding: 12px;
152
+ background: #F9FAFB;
153
+ border-radius: 6px;
154
+ }
155
+
156
+ .control-row label {
157
+ font-weight: 600;
158
+ color: #374151;
159
+ font-size: 13px;
160
+ }
161
+
162
+ .control-row select,
163
+ .control-row input[type="text"],
164
+ .control-row input[type="color"] {
165
+ padding: 8px 12px;
166
+ border: 1px solid #D1D5DB;
167
+ border-radius: 4px;
168
+ font-size: 14px;
169
+ }
170
+
171
+ .control-row input[type="color"] {
172
+ width: 60px;
173
+ height: 40px;
174
+ cursor: pointer;
175
+ }
176
+
177
+ .control-row button {
178
+ padding: 8px 16px;
179
+ background: #3B82F6;
180
+ color: white;
181
+ border: none;
182
+ border-radius: 4px;
183
+ cursor: pointer;
184
+ font-size: 13px;
185
+ margin: 0;
186
+ }
187
+
188
+ .control-row button:hover {
189
+ background: #2563EB;
190
+ }
191
+
192
+ .control-row button.remove {
193
+ background: #EF4444;
194
+ }
195
+
196
+ .control-row button.remove:hover {
197
+ background: #DC2626;
198
+ }
136
199
  </style>
137
200
  </head>
138
201
  <body>
@@ -153,9 +216,10 @@
153
216
  <ol style="margin: 10px 0 0 20px; line-height: 1.8;">
154
217
  <li>Look for the floating voice button in the bottom-right corner</li>
155
218
  <li>Click the button to open the widget</li>
156
- <li>Click the microphone to start (will request mic permission)</li>
219
+ <li>Click the voice button to start (will request microphone permission)</li>
157
220
  <li>Widget will connect directly using agent ID + app ID</li>
158
221
  <li>Check the status updates below</li>
222
+ <li>Try the interactive customization designer below to customize colors, sizes, text, and more in real-time!</li>
159
223
  </ol>
160
224
  </div>
161
225
 
@@ -177,14 +241,67 @@
177
241
 
178
242
  <div id="simple-tab" class="tab-content active">
179
243
  <div class="code-block"><pre><code>const widget = new TTPAgentSDK.AgentWidget({
180
- agentId: 'agent_87c4a55a1',
181
- appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC',
182
-
183
- primaryColor: '#10B981',
184
- position: 'bottom-right'
244
+ agentId: 'agent_87c4a55a1',
245
+ appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC',
246
+
247
+ primaryColor: '#10B981',
248
+ position: 'bottom-right',
249
+
250
+ // Icon configuration
251
+ icon: {
252
+ type: 'custom',
253
+ customImage: 'https://talktopc.com/logo192.png',
254
+ size: 'medium'
255
+ },
256
+
257
+ // Floating button (main button) colors - WHITE
258
+ button: {
259
+ backgroundColor: '#FFFFFF', // White floating button
260
+ hoverColor: '#E5E7EB' // Gray on hover
261
+ },
262
+
263
+ // Header (top of panel) colors - LIGHT PURPLE
264
+ header: {
265
+ title: 'TTP Support',
266
+ backgroundColor: '#A78BFA', // Light purple header
267
+ textColor: '#FFFFFF'
268
+ },
269
+
270
+ // Mic button (inside panel) colors - GRAY
271
+ panel: {
272
+ micButtonColor: '#E5E7EB', // Gray mic button
273
+ micButtonActiveColor: '#EF4444' // Red when active
274
+ }
185
275
  });</code></pre></div>
186
276
  </div>
187
277
 
278
+ <h2>🎨 Interactive Customization</h2>
279
+ <div class="controls-panel">
280
+ <div style="margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid #E5E7EB;">
281
+ <strong style="color: #374151;">Customize widget colors and properties in real-time:</strong>
282
+ </div>
283
+
284
+ <div id="control-rows">
285
+ <!-- Control rows will be added dynamically -->
286
+ </div>
287
+
288
+ <button id="add-control-btn" style="margin-top: 12px; padding: 10px 20px; background: #10B981;">
289
+ + Add Customization
290
+ </button>
291
+
292
+ <div style="margin-top: 16px; padding-top: 16px; border-top: 1px solid #E5E7EB;">
293
+ <button id="reset-defaults-btn" style="background: #6B7280;">
294
+ Reset to Defaults
295
+ </button>
296
+ </div>
297
+ </div>
298
+
299
+ <h2>Implementation Code:</h2>
300
+ <div class="tabs">
301
+ <button class="tab active" onclick="switchTab('simple')">Simple</button>
302
+ <button class="tab" onclick="switchTab('advanced')">All Options</button>
303
+ </div>
304
+
188
305
  <div id="advanced-tab" class="tab-content">
189
306
  <div class="code-block"><pre><code>const widget = new TTPAgentSDK.AgentWidget({
190
307
  // Required
@@ -206,13 +323,48 @@
206
323
  primaryColor: '#10B981',
207
324
  position: 'bottom-right', // or use advanced position object below
208
325
 
209
- // Advanced Icon Configuration
326
+ // Icon Configuration
327
+ icon: {
328
+ type: 'custom', // 'microphone', 'custom', 'emoji', 'text'
329
+ customImage: 'https://talktopc.com/logo192.png', // For type: 'custom'
330
+ size: 'medium' // 'small', 'medium', 'large', 'xl'
331
+ },
332
+
333
+ // Button Configuration - Floating Button (Main Button) - WHITE
334
+ button: {
335
+ size: 'medium', // 'small', 'medium', 'large', 'xl'
336
+ shape: 'circle', // 'circle', 'square', 'rounded'
337
+ backgroundColor: '#FFFFFF', // Floating button background color (WHITE)
338
+ hoverColor: '#E5E7EB', // Floating button hover color (gray)
339
+ shadow: true,
340
+ shadowColor: 'rgba(0,0,0,0.15)'
341
+ },
342
+
343
+ // Header Configuration - Top of Panel - LIGHT PURPLE
344
+ header: {
345
+ title: 'TTP Support', // Custom title for the widget header
346
+ showTitle: true, // Show/hide title
347
+ backgroundColor: '#A78BFA', // Header background color (LIGHT PURPLE)
348
+ textColor: '#FFFFFF', // Header text color
349
+ showCloseButton: true
350
+ },
351
+
352
+ // Panel Configuration - Includes Mic Button Colors - GRAY
353
+ panel: {
354
+ width: 350,
355
+ height: 500,
356
+ borderRadius: 12,
357
+ backgroundColor: 'rgba(255,255,255,0.95)', // Panel background
358
+ backdropFilter: null,
359
+ border: '1px solid rgba(0,0,0,0.1)',
360
+ micButtonColor: '#E5E7EB', // Mic button (inside panel) background color (GRAY)
361
+ micButtonActiveColor: '#EF4444' // Mic button color when active/recording (RED)
362
+ },
210
363
  // icon: {
211
- // type: 'microphone', // 'microphone', 'custom', 'emoji', 'text'
212
- // customImage: 'https://example.com/icon.png', // For type: 'custom'
364
+ // type: 'microphone',
213
365
  // emoji: '🎤', // For type: 'emoji'
214
366
  // text: 'AI', // For type: 'text'
215
- // size: 'medium' // 'small', 'medium', 'large', 'xl'
367
+ // size: 'medium'
216
368
  // },
217
369
 
218
370
  // Advanced Positioning
@@ -362,6 +514,368 @@
362
514
  statusDiv.className = 'status ' + type;
363
515
  }
364
516
 
517
+ // ============================================
518
+ // CUSTOMIZATION CONTROLS - Declare early
519
+ // ============================================
520
+ // Initialize variable first - MUST be declared before any functions that use it
521
+ let controlRowCount = 0;
522
+
523
+ const componentOptions = {
524
+ 'button': {
525
+ label: 'Floating Button',
526
+ properties: {
527
+ 'backgroundColor': { type: 'color', label: 'Background Color' },
528
+ 'hoverColor': { type: 'color', label: 'Hover Color' },
529
+ 'size': { type: 'select', label: 'Size', options: ['small', 'medium', 'large', 'xl'] },
530
+ 'shape': { type: 'select', label: 'Shape', options: ['circle', 'square', 'rounded'] }
531
+ }
532
+ },
533
+ 'header': {
534
+ label: 'Header',
535
+ properties: {
536
+ 'backgroundColor': { type: 'color', label: 'Background Color' },
537
+ 'textColor': { type: 'color', label: 'Text Color' },
538
+ 'title': { type: 'text', label: 'Title' }
539
+ }
540
+ },
541
+ 'panel': {
542
+ label: 'Mic Button',
543
+ properties: {
544
+ 'micButtonColor': { type: 'color', label: 'Background Color' },
545
+ 'micButtonActiveColor': { type: 'color', label: 'Active Color (Recording)' }
546
+ }
547
+ },
548
+ 'micButtonHint': {
549
+ label: 'Mic Button Hint',
550
+ properties: {
551
+ 'micButtonHint.text': { type: 'text', label: 'Hint Text (empty to hide)' },
552
+ 'micButtonHint.color': { type: 'color', label: 'Text Color' },
553
+ 'micButtonHint.fontSize': { type: 'text', label: 'Font Size (e.g., 12px)' }
554
+ }
555
+ },
556
+ 'direction': {
557
+ label: 'Text Direction',
558
+ properties: {
559
+ 'direction': { type: 'select', label: 'Direction', options: ['ltr', 'rtl'] }
560
+ }
561
+ }
562
+ };
563
+
564
+ function initializeCustomizationControls() {
565
+ // Add one initial row
566
+ addControlRow();
567
+
568
+ // Set up button event listeners
569
+ const addBtn = document.getElementById('add-control-btn');
570
+ const resetBtn = document.getElementById('reset-defaults-btn');
571
+ if (addBtn) {
572
+ addBtn.addEventListener('click', addControlRow);
573
+ }
574
+ if (resetBtn) {
575
+ resetBtn.addEventListener('click', resetToDefaults);
576
+ }
577
+ }
578
+
579
+ function addControlRow() {
580
+ controlRowCount++;
581
+ const controlRows = document.getElementById('control-rows');
582
+ const row = document.createElement('div');
583
+ row.className = 'control-row';
584
+ row.id = `control-row-${controlRowCount}`;
585
+
586
+ // Component selector
587
+ const componentSelect = document.createElement('select');
588
+ componentSelect.id = `component-${controlRowCount}`;
589
+ componentSelect.innerHTML = '<option value="">Select Component</option>';
590
+ Object.keys(componentOptions).forEach(key => {
591
+ const option = document.createElement('option');
592
+ option.value = key;
593
+ option.textContent = componentOptions[key].label;
594
+ componentSelect.appendChild(option);
595
+ });
596
+ componentSelect.onchange = () => updatePropertySelect(controlRowCount);
597
+
598
+ // Property selector (will be populated based on component)
599
+ const propertySelect = document.createElement('select');
600
+ propertySelect.id = `property-${controlRowCount}`;
601
+ propertySelect.innerHTML = '<option value="">Select Property</option>';
602
+
603
+ // Value input (dynamically changes based on property type)
604
+ const valueContainer = document.createElement('div');
605
+ valueContainer.id = `value-container-${controlRowCount}`;
606
+ valueContainer.style.display = 'none';
607
+
608
+ // Action buttons
609
+ const actionContainer = document.createElement('div');
610
+ actionContainer.style.display = 'flex';
611
+ actionContainer.style.gap = '8px';
612
+
613
+ const applyBtn = document.createElement('button');
614
+ applyBtn.textContent = 'Apply';
615
+ applyBtn.onclick = () => applyChange(controlRowCount);
616
+
617
+ const removeBtn = document.createElement('button');
618
+ removeBtn.textContent = 'Remove';
619
+ removeBtn.className = 'remove';
620
+ removeBtn.onclick = () => removeControlRow(controlRowCount);
621
+
622
+ actionContainer.appendChild(applyBtn);
623
+ actionContainer.appendChild(removeBtn);
624
+
625
+ row.appendChild(componentSelect);
626
+ row.appendChild(propertySelect);
627
+ row.appendChild(valueContainer);
628
+ row.appendChild(actionContainer);
629
+
630
+ controlRows.appendChild(row);
631
+ }
632
+
633
+ function updatePropertySelect(rowId) {
634
+ const componentSelect = document.getElementById(`component-${rowId}`);
635
+ const propertySelect = document.getElementById(`property-${rowId}`);
636
+ const valueContainer = document.getElementById(`value-container-${rowId}`);
637
+
638
+ const component = componentSelect.value;
639
+ if (!component) {
640
+ propertySelect.innerHTML = '<option value="">Select Property</option>';
641
+ valueContainer.style.display = 'none';
642
+ valueContainer.innerHTML = '';
643
+ return;
644
+ }
645
+
646
+ // Populate properties
647
+ propertySelect.innerHTML = '<option value="">Select Property</option>';
648
+ const properties = componentOptions[component].properties;
649
+ Object.keys(properties).forEach(key => {
650
+ const option = document.createElement('option');
651
+ option.value = key;
652
+ option.textContent = properties[key].label;
653
+ propertySelect.appendChild(option);
654
+ });
655
+
656
+ propertySelect.onchange = () => updateValueInput(rowId);
657
+ valueContainer.style.display = 'none';
658
+ valueContainer.innerHTML = '';
659
+ }
660
+
661
+ function updateValueInput(rowId) {
662
+ const componentSelect = document.getElementById(`component-${rowId}`);
663
+ const propertySelect = document.getElementById(`property-${rowId}`);
664
+ const valueContainer = document.getElementById(`value-container-${rowId}`);
665
+
666
+ const component = componentSelect.value;
667
+ const property = propertySelect.value;
668
+
669
+ if (!component || !property) {
670
+ valueContainer.style.display = 'none';
671
+ valueContainer.innerHTML = '';
672
+ return;
673
+ }
674
+
675
+ const propConfig = componentOptions[component].properties[property];
676
+ valueContainer.innerHTML = '';
677
+
678
+ if (propConfig.type === 'color') {
679
+ const input = document.createElement('input');
680
+ input.type = 'color';
681
+ input.id = `value-${rowId}`;
682
+ // Set current value from widget
683
+ const currentValue = getCurrentValue(component, property);
684
+ if (currentValue) input.value = rgbToHex(currentValue) || currentValue;
685
+ valueContainer.appendChild(input);
686
+ } else if (propConfig.type === 'select') {
687
+ const select = document.createElement('select');
688
+ select.id = `value-${rowId}`;
689
+ propConfig.options.forEach(opt => {
690
+ const option = document.createElement('option');
691
+ option.value = opt;
692
+ option.textContent = opt.charAt(0).toUpperCase() + opt.slice(1);
693
+ select.appendChild(option);
694
+ });
695
+ // Set current value
696
+ const currentValue = getCurrentValue(component, property);
697
+ if (currentValue !== null && currentValue !== undefined) {
698
+ select.value = currentValue.toString();
699
+ }
700
+ valueContainer.appendChild(select);
701
+ } else if (propConfig.type === 'text') {
702
+ const input = document.createElement('input');
703
+ input.type = 'text';
704
+ input.id = `value-${rowId}`;
705
+ input.placeholder = 'Enter value';
706
+ // Set current value
707
+ const currentValue = getCurrentValue(component, property);
708
+ if (currentValue !== null && currentValue !== undefined) {
709
+ input.value = currentValue;
710
+ }
711
+ valueContainer.appendChild(input);
712
+ }
713
+
714
+ valueContainer.style.display = 'block';
715
+ }
716
+
717
+ function getCurrentValue(component, property) {
718
+ if (!window.testWidget) return null;
719
+ const config = window.testWidget.config;
720
+
721
+ if (component === 'button' && config.button) {
722
+ return config.button[property];
723
+ } else if (component === 'header' && config.header) {
724
+ return config.header[property];
725
+ } else if (component === 'panel' && config.panel) {
726
+ return config.panel[property];
727
+ } else if (component === 'micButtonHint' && config.panel?.micButtonHint) {
728
+ // Handle nested micButtonHint properties
729
+ const hintKey = property.split('.')[1]; // e.g., 'text', 'color', 'fontSize'
730
+ const value = config.panel.micButtonHint[hintKey];
731
+ return value;
732
+ } else if (component === 'direction') {
733
+ return config.direction;
734
+ }
735
+ return null;
736
+ }
737
+
738
+ function applyChange(rowId) {
739
+ const componentSelect = document.getElementById(`component-${rowId}`);
740
+ const propertySelect = document.getElementById(`property-${rowId}`);
741
+ const valueInput = document.getElementById(`value-${rowId}`);
742
+
743
+ const component = componentSelect.value;
744
+ const property = propertySelect.value;
745
+ let value = valueInput.value;
746
+
747
+ if (!component || !property) {
748
+ alert('Please select component and property');
749
+ return;
750
+ }
751
+
752
+ // Allow empty value for text fields (to hide hint)
753
+ if (value === undefined || value === null) {
754
+ value = '';
755
+ }
756
+
757
+ if (!window.testWidget) {
758
+ alert('Widget not initialized');
759
+ return;
760
+ }
761
+
762
+ // Handle boolean values (only for non-empty values)
763
+ if (value && value !== '') {
764
+ if (value === 'true') value = true;
765
+ if (value === 'false') value = false;
766
+ }
767
+
768
+ // Prepare update config
769
+ const updateConfig = {};
770
+ if (component === 'button') {
771
+ updateConfig.button = { [property]: value };
772
+ } else if (component === 'header') {
773
+ updateConfig.header = { [property]: value };
774
+ } else if (component === 'panel') {
775
+ updateConfig.panel = { [property]: value };
776
+ } else if (component === 'micButtonHint') {
777
+ // Handle nested micButtonHint properties
778
+ const hintKey = property.split('.')[1]; // e.g., 'text', 'color', 'fontSize', 'show'
779
+ if (!updateConfig.panel) updateConfig.panel = {};
780
+ if (!updateConfig.panel.micButtonHint) updateConfig.panel.micButtonHint = {};
781
+ updateConfig.panel.micButtonHint[hintKey] = value;
782
+ } else if (component === 'direction') {
783
+ updateConfig.direction = value;
784
+ }
785
+
786
+ // Apply update
787
+ console.log(`Applying change: ${component}.${property} = ${value}`);
788
+ window.testWidget.updateConfig(updateConfig);
789
+
790
+ // Update the displayed code blocks
791
+ updateCodeDisplay();
792
+ }
793
+
794
+ function removeControlRow(rowId) {
795
+ const row = document.getElementById(`control-row-${rowId}`);
796
+ if (row) row.remove();
797
+ }
798
+
799
+ function resetToDefaults() {
800
+ if (!window.testWidget || !window.defaultConfig) {
801
+ alert('Widget or defaults not available');
802
+ return;
803
+ }
804
+
805
+ if (confirm('Reset widget to default configuration?')) {
806
+ window.testWidget.updateConfig(window.defaultConfig);
807
+ updateCodeDisplay();
808
+
809
+ // Clear all control rows
810
+ const controlRows = document.getElementById('control-rows');
811
+ controlRows.innerHTML = '';
812
+ controlRowCount = 0;
813
+ addControlRow();
814
+ }
815
+ }
816
+
817
+ function updateCodeDisplay() {
818
+ if (!window.testWidget) return;
819
+ const config = window.testWidget.config;
820
+
821
+ // Helper to safely get position value
822
+ function getPositionValue() {
823
+ if (!config.position) return 'bottom-right';
824
+ if (typeof config.position === 'string') return config.position;
825
+ // If it's an object, extract the string representation
826
+ return `${config.position.vertical || 'bottom'}-${config.position.horizontal || 'right'}`;
827
+ }
828
+
829
+ // Update simple tab
830
+ const simpleCode = document.querySelector('#simple-tab code');
831
+ if (simpleCode) {
832
+ const position = getPositionValue();
833
+ simpleCode.textContent = `const widget = new TTPAgentSDK.AgentWidget({
834
+ agentId: 'agent_87c4a55a1',
835
+ appId: 'app_Bc01EqMQt2Euehl4qqZSi6l3FJP42Q9vJ0pC',
836
+
837
+ primaryColor: '${config.primaryColor || '#10B981'}',
838
+ position: '${position}',
839
+
840
+ icon: {
841
+ type: '${config.icon?.type || 'custom'}',
842
+ customImage: '${config.icon?.customImage || 'https://talktopc.com/logo192.png'}',
843
+ size: '${config.icon?.size || 'medium'}'
844
+ },
845
+
846
+ button: {
847
+ backgroundColor: '${config.button?.backgroundColor || '#FFFFFF'}',
848
+ hoverColor: '${config.button?.hoverColor || '#E5E7EB'}'
849
+ },
850
+
851
+ header: {
852
+ title: '${(config.header?.title || 'TTP Support').replace(/'/g, "\\'")}',
853
+ backgroundColor: '${config.header?.backgroundColor || '#A78BFA'}',
854
+ textColor: '${config.header?.textColor || '#FFFFFF'}'
855
+ },
856
+
857
+ panel: {
858
+ micButtonColor: '${config.panel?.micButtonColor || '#E5E7EB'}',
859
+ micButtonActiveColor: '${config.panel?.micButtonActiveColor || '#EF4444'}'
860
+ }
861
+ });`;
862
+ }
863
+ }
864
+
865
+ function rgbToHex(rgb) {
866
+ if (!rgb) return null;
867
+ if (rgb.startsWith('#')) return rgb;
868
+ // Try to parse rgb/rgba format
869
+ const match = rgb.match(/\d+/g);
870
+ if (match && match.length >= 3) {
871
+ return '#' + match.slice(0, 3).map(x => {
872
+ const hex = parseInt(x).toString(16);
873
+ return hex.length === 1 ? '0' + hex : hex;
874
+ }).join('');
875
+ }
876
+ return null;
877
+ }
878
+
365
879
  // Initialize the widget
366
880
  try {
367
881
  console.log('Initializing widget with agent ID + app ID...');
@@ -398,9 +912,34 @@
398
912
  primaryColor: '#10B981',
399
913
  position: 'bottom-right',
400
914
 
915
+ // Set TTP icon
916
+ icon: {
917
+ type: 'custom',
918
+ customImage: 'https://talktopc.com/logo192.png',
919
+ size: 'medium'
920
+ },
921
+
922
+ // Button colors - Floating button (main button) - WHITE
923
+ button: {
924
+ backgroundColor: '#FFFFFF', // White background for floating button
925
+ hoverColor: '#E5E7EB' // Gray on hover
926
+ },
927
+
928
+ // Header colors - Top of panel - LIGHT PURPLE
929
+ header: {
930
+ title: 'TTP Support',
931
+ backgroundColor: '#A78BFA', // Light purple header background
932
+ textColor: '#FFFFFF' // White text
933
+ },
934
+
935
+ // Panel colors - Mic button inside panel - GRAY
936
+ panel: {
937
+ micButtonColor: '#E5E7EB', // Gray mic button
938
+ micButtonActiveColor: '#EF4444' // Red when active/recording
939
+ },
940
+
401
941
  // Enhanced features are now available but using defaults
402
942
  // You can optionally add:
403
- // icon: { type: 'emoji', emoji: '🎤', size: 'large' },
404
943
  // button: { size: 'large', shape: 'circle' },
405
944
  // panel: { width: 400, height: 600 },
406
945
  // header: { title: 'My Voice Assistant' },
@@ -410,6 +949,41 @@
410
949
  // Store widget reference for testing (like the working implementation)
411
950
  window.testWidget = widget;
412
951
 
952
+ // Store default config for reset functionality (matches initial widget config)
953
+ window.defaultConfig = JSON.parse(JSON.stringify({
954
+ primaryColor: '#10B981',
955
+ position: 'bottom-right',
956
+ direction: 'ltr',
957
+ icon: {
958
+ type: 'custom',
959
+ customImage: 'https://talktopc.com/logo192.png',
960
+ size: 'medium'
961
+ },
962
+ button: {
963
+ backgroundColor: '#FFFFFF',
964
+ hoverColor: '#E5E7EB',
965
+ size: 'medium',
966
+ shape: 'circle'
967
+ },
968
+ header: {
969
+ title: 'TTP Support',
970
+ backgroundColor: '#A78BFA',
971
+ textColor: '#FFFFFF'
972
+ },
973
+ panel: {
974
+ micButtonColor: '#E5E7EB',
975
+ micButtonActiveColor: '#EF4444',
976
+ micButtonHint: {
977
+ text: 'Click the button to start voice conversation',
978
+ color: '#6B7280',
979
+ fontSize: '12px'
980
+ }
981
+ }
982
+ }));
983
+
984
+ // Initialize customization controls
985
+ initializeCustomizationControls();
986
+
413
987
  console.log('Widget initialized successfully with agent ID + app ID!');
414
988
  console.log('Widget instance:', widget);
415
989
  console.log('Test methods available at window.testWidget');
@@ -461,6 +1035,7 @@
461
1035
  alert('Microphone access DENIED! Please allow microphone in browser settings.');
462
1036
  }
463
1037
  }
1038
+
464
1039
  </script>
465
1040
  </body>
466
1041
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ttp-agent-sdk",
3
- "version": "2.1.13",
3
+ "version": "2.2.1",
4
4
  "description": "Comprehensive Voice Agent SDK with Enhanced Customizable Widget - Real-time audio, WebSocket communication, React components, and extensive customization options",
5
5
  "main": "dist/agent-widget.js",
6
6
  "module": "dist/agent-widget.js",