@ihoomanai/chat-widget 3.0.7 → 3.0.9

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/src/widget.ts CHANGED
@@ -17,7 +17,7 @@ import type {
17
17
  WidgetView,
18
18
  } from './types';
19
19
 
20
- const VERSION = '3.0.6';
20
+ const VERSION = '3.0.9';
21
21
  const STORAGE_PREFIX = 'ihooman_chat_';
22
22
  const DEFAULT_SERVER_URL = 'https://api.ihooman.ai';
23
23
 
@@ -231,9 +231,9 @@ function generateStyles(): string {
231
231
  const positionBottom = config.position?.includes('bottom') ?? true;
232
232
 
233
233
  return `
234
- .ihooman-widget * { box-sizing: border-box; margin: 0; padding: 0; }
234
+ .ihooman-widget * { box-sizing: border-box !important; margin: 0; padding: 0; }
235
235
  .ihooman-widget { font-family: ${fontFamily}; font-size: 14px; line-height: 1.5; color: ${textColor}; -webkit-font-smoothing: antialiased; }
236
- .ihooman-widget button { box-sizing: border-box; cursor: pointer; font-family: inherit; border: none; background: transparent; }
236
+ .ihooman-widget button { box-sizing: border-box !important; cursor: pointer !important; font-family: inherit !important; appearance: none !important; -webkit-appearance: none !important; outline: none !important; }
237
237
  .ihooman-toggle { position: fixed !important; ${positionRight ? 'right: 20px' : 'left: 20px'}; ${positionBottom ? 'bottom: 20px' : 'top: 20px'}; width: ${buttonSize}px !important; height: ${buttonSize}px !important; border-radius: 50% !important; background: linear-gradient(135deg, ${gradientFrom}, ${gradientTo}) !important; border: none !important; cursor: pointer; z-index: ${zIndex}; display: flex !important; align-items: center; justify-content: center; box-shadow: 0 4px 20px rgba(0, 174, 255, 0.35); transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); overflow: hidden; }
238
238
  .ihooman-toggle:hover { transform: scale(1.08); box-shadow: 0 6px 28px rgba(0, 174, 255, 0.45); }
239
239
  .ihooman-toggle:active { transform: scale(0.95); }
@@ -300,12 +300,8 @@ function generateStyles(): string {
300
300
  .ihooman-powered { text-align: center; padding: 8px; font-size: 11px; color: ${mutedColor}; background: ${bgColor}; }
301
301
  .ihooman-powered a { color: ${primaryColor}; text-decoration: none; }
302
302
  .ihooman-escalation-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
303
- .ihooman-escalation-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 14px; border-radius: 6px; border: none; cursor: pointer; font-family: inherit; font-size: 12px; font-weight: 500; transition: all 0.2s ease; line-height: 1.4; }
304
- .ihooman-escalation-btn svg { width: 14px; height: 14px; flex-shrink: 0; }
305
- .ihooman-escalation-btn.primary { background: linear-gradient(135deg, ${gradientFrom}, ${gradientTo}); color: white; }
306
- .ihooman-escalation-btn.primary:hover { opacity: 0.9; }
307
- .ihooman-escalation-btn.secondary { background: ${isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)'}; color: ${textColor}; border: 1px solid ${borderColor}; }
308
- .ihooman-escalation-btn.secondary:hover { background: ${isDark ? 'rgba(255,255,255,0.15)' : 'rgba(0,0,0,0.08)'}; }
303
+ .ihooman-widget .ihooman-escalation-btn { cursor: pointer !important; font-family: inherit !important; transition: all 0.2s ease !important; }
304
+ .ihooman-widget .ihooman-escalation-btn svg { width: 14px !important; height: 14px !important; flex-shrink: 0 !important; }
309
305
  .ihooman-status-bar { padding: 10px 16px; text-align: center; font-size: 13px; display: none; }
310
306
  .ihooman-status-bar.show { display: block; }
311
307
  .ihooman-status-bar.waiting { background: #fef3c7; color: #92400e; }
@@ -342,8 +338,7 @@ function generateStyles(): string {
342
338
  .ihooman-preset-questions { padding: 10px 16px; display: flex; flex-wrap: wrap; gap: 6px; background: ${bgColor}; border-top: 1px solid ${borderColor}; }
343
339
  .ihooman-preset-questions:empty { display: none; }
344
340
  .ihooman-preset-questions.hidden { display: none !important; }
345
- .ihooman-preset-btn { display: inline-flex; align-items: center; justify-content: center; gap: 4px; padding: 6px 10px; border-radius: 6px; border: 1px solid ${borderColor}; background: ${isDark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.02)'}; color: ${textColor}; font-size: 12px; font-weight: 500; cursor: pointer; transition: all 0.2s; white-space: nowrap; line-height: 1.4; }
346
- .ihooman-preset-btn:hover { background: ${isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)'}; border-color: ${primaryColor}; }
341
+ .ihooman-widget .ihooman-preset-btn { cursor: pointer !important; font-family: inherit !important; transition: all 0.2s !important; }
347
342
  .ihooman-proactive-toast { position: fixed; ${positionRight ? 'right: 20px' : 'left: 20px'}; ${positionBottom ? 'bottom: 90px' : 'top: 90px'}; max-width: 300px; padding: 16px; background: ${bgColor}; border-radius: 12px; box-shadow: 0 10px 40px rgba(0,0,0,0.15); z-index: ${(zIndex ?? 9999) - 2}; opacity: 0; visibility: hidden; transform: translateY(10px); transition: all 0.3s ease; border: 1px solid ${borderColor}; }
348
343
  .ihooman-proactive-toast.show { opacity: 1; visibility: visible; transform: translateY(0); }
349
344
  .ihooman-proactive-toast-content { font-size: 14px; color: ${textColor}; margin-bottom: 12px; }
@@ -366,10 +361,8 @@ function generateStyles(): string {
366
361
  .ihooman-survey-skip { display: inline-flex; align-items: center; justify-content: center; padding: 8px 16px; background: transparent; color: ${mutedColor}; border: none; font-size: 12px; cursor: pointer; line-height: 1.4; }
367
362
  .ihooman-survey-skip:hover { color: ${textColor}; }
368
363
  .ihooman-feedback-btns { display: flex; gap: 6px; margin-top: 6px; }
369
- .ihooman-feedback-btn { display: inline-flex; align-items: center; justify-content: center; padding: 4px 6px; border: 1px solid ${borderColor}; border-radius: 4px; background: transparent; cursor: pointer; color: ${mutedColor}; transition: all 0.2s; }
370
- .ihooman-feedback-btn:hover { background: ${isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)'}; }
371
- .ihooman-feedback-btn.active { background: ${primaryColor}; color: white; border-color: ${primaryColor}; }
372
- .ihooman-feedback-btn svg { width: 12px; height: 12px; }
364
+ .ihooman-widget .ihooman-feedback-btn { cursor: pointer !important; transition: all 0.2s !important; }
365
+ .ihooman-widget .ihooman-feedback-btn svg { width: 12px !important; height: 12px !important; }
373
366
  .ihooman-carousel { display: flex; gap: 12px; overflow-x: auto; padding: 8px 0; scroll-snap-type: x mandatory; }
374
367
  .ihooman-carousel::-webkit-scrollbar { height: 4px; }
375
368
  .ihooman-carousel-card { min-width: 200px; max-width: 250px; border: 1px solid ${borderColor}; border-radius: 12px; overflow: hidden; scroll-snap-align: start; background: ${bgColor}; }
@@ -378,11 +371,9 @@ function generateStyles(): string {
378
371
  .ihooman-carousel-card-title { font-size: 14px; font-weight: 600; color: ${textColor}; margin-bottom: 4px; }
379
372
  .ihooman-carousel-card-desc { font-size: 12px; color: ${mutedColor}; margin-bottom: 8px; }
380
373
  .ihooman-carousel-card-btns { display: flex; flex-direction: column; gap: 6px; }
381
- .ihooman-carousel-card-btn { display: flex; align-items: center; justify-content: center; padding: 6px 10px; border: 1px solid ${borderColor}; border-radius: 6px; background: transparent; color: ${textColor}; font-size: 11px; cursor: pointer; transition: all 0.2s; text-align: center; line-height: 1.4; }
382
- .ihooman-carousel-card-btn:hover { background: ${isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)'}; border-color: ${primaryColor}; }
374
+ .ihooman-widget .ihooman-carousel-card-btn { cursor: pointer !important; transition: all 0.2s !important; }
383
375
  .ihooman-quick-replies { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
384
- .ihooman-quick-reply { display: inline-flex; align-items: center; justify-content: center; padding: 5px 10px; border: 1px solid ${primaryColor}; border-radius: 14px; background: transparent; color: ${primaryColor}; font-size: 11px; cursor: pointer; transition: all 0.2s; line-height: 1.4; }
385
- .ihooman-quick-reply:hover { background: ${primaryColor}; color: white; }
376
+ .ihooman-widget .ihooman-quick-reply { cursor: pointer !important; transition: all 0.2s !important; }
386
377
  @media (max-width: 480px) { .ihooman-window { width: calc(100vw - 20px); height: calc(100vh - 100px); min-height: 400px; max-height: calc(100vh - 100px); left: 10px; right: 10px; bottom: 80px; } .ihooman-toggle { ${positionRight ? 'right: 16px' : 'left: 16px'}; bottom: 16px; } .ihooman-proactive-toast { left: 10px; right: 10px; max-width: none; } }
387
378
  `;
388
379
  }
@@ -1708,7 +1699,99 @@ function getFontWeightValue(weight: string): number {
1708
1699
  }
1709
1700
  }
1710
1701
 
1711
- function applyButtonStyling(buttonStyling: Record<string, Record<string, unknown>>): void {
1702
+ // Default button styles - MUST match client-dashboard/src/components/widget/ButtonStylingEditor.tsx
1703
+ const DEFAULT_BUTTON_STYLES = {
1704
+ primary: {
1705
+ backgroundColor: '#00aeff',
1706
+ textColor: '#ffffff',
1707
+ borderColor: 'transparent',
1708
+ borderWidth: 0,
1709
+ borderRadius: 8,
1710
+ paddingVertical: 8,
1711
+ paddingHorizontal: 16,
1712
+ fontSize: 13,
1713
+ fontWeight: 'medium',
1714
+ },
1715
+ secondary: {
1716
+ backgroundColor: 'transparent',
1717
+ textColor: '#6b7280',
1718
+ borderColor: '#e5e7eb',
1719
+ borderWidth: 1,
1720
+ borderRadius: 8,
1721
+ paddingVertical: 8,
1722
+ paddingHorizontal: 16,
1723
+ fontSize: 13,
1724
+ fontWeight: 'medium',
1725
+ },
1726
+ presetQuestions: {
1727
+ backgroundColor: 'rgba(0, 174, 255, 0.1)',
1728
+ textColor: '#00aeff',
1729
+ borderColor: 'rgba(0, 174, 255, 0.2)',
1730
+ borderWidth: 1,
1731
+ borderRadius: 20,
1732
+ paddingVertical: 6,
1733
+ paddingHorizontal: 12,
1734
+ fontSize: 12,
1735
+ fontWeight: 'medium',
1736
+ },
1737
+ quickReplies: {
1738
+ backgroundColor: '#f3f4f6',
1739
+ textColor: '#374151',
1740
+ borderColor: '#e5e7eb',
1741
+ borderWidth: 1,
1742
+ borderRadius: 16,
1743
+ paddingVertical: 5,
1744
+ paddingHorizontal: 10,
1745
+ fontSize: 11,
1746
+ fontWeight: 'medium',
1747
+ },
1748
+ feedback: {
1749
+ backgroundColor: 'transparent',
1750
+ textColor: '#9ca3af',
1751
+ borderColor: '#e5e7eb',
1752
+ borderWidth: 1,
1753
+ borderRadius: 6,
1754
+ paddingVertical: 4,
1755
+ paddingHorizontal: 8,
1756
+ fontSize: 12,
1757
+ fontWeight: 'medium',
1758
+ },
1759
+ headerActions: {
1760
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
1761
+ textColor: '#ffffff',
1762
+ borderColor: 'transparent',
1763
+ borderWidth: 0,
1764
+ borderRadius: 6,
1765
+ paddingVertical: 6,
1766
+ paddingHorizontal: 6,
1767
+ fontSize: 14,
1768
+ fontWeight: 'medium',
1769
+ },
1770
+ escalation: {
1771
+ backgroundColor: '#00aeff',
1772
+ textColor: '#ffffff',
1773
+ borderColor: 'transparent',
1774
+ borderWidth: 0,
1775
+ borderRadius: 8,
1776
+ paddingVertical: 8,
1777
+ paddingHorizontal: 14,
1778
+ fontSize: 12,
1779
+ fontWeight: 'medium',
1780
+ },
1781
+ cardActions: {
1782
+ backgroundColor: '#00aeff',
1783
+ textColor: '#ffffff',
1784
+ borderColor: 'transparent',
1785
+ borderWidth: 0,
1786
+ borderRadius: 6,
1787
+ paddingVertical: 6,
1788
+ paddingHorizontal: 12,
1789
+ fontSize: 12,
1790
+ fontWeight: 'medium',
1791
+ },
1792
+ };
1793
+
1794
+ function applyButtonStyling(buttonStyling?: Record<string, Record<string, unknown>>): void {
1712
1795
  const styleId = 'ihooman-button-styling';
1713
1796
  let styleEl = document.getElementById(styleId) as HTMLStyleElement | null;
1714
1797
 
@@ -1718,24 +1801,34 @@ function applyButtonStyling(buttonStyling: Record<string, Record<string, unknown
1718
1801
  document.head.appendChild(styleEl);
1719
1802
  }
1720
1803
 
1804
+ // Merge provided styles with defaults
1805
+ const mergedStyles = {
1806
+ primary: { ...DEFAULT_BUTTON_STYLES.primary, ...(buttonStyling?.primary || {}) },
1807
+ secondary: { ...DEFAULT_BUTTON_STYLES.secondary, ...(buttonStyling?.secondary || {}) },
1808
+ presetQuestions: { ...DEFAULT_BUTTON_STYLES.presetQuestions, ...(buttonStyling?.presetQuestions || {}) },
1809
+ quickReplies: { ...DEFAULT_BUTTON_STYLES.quickReplies, ...(buttonStyling?.quickReplies || {}) },
1810
+ feedback: { ...DEFAULT_BUTTON_STYLES.feedback, ...(buttonStyling?.feedback || {}) },
1811
+ headerActions: { ...DEFAULT_BUTTON_STYLES.headerActions, ...(buttonStyling?.headerActions || {}) },
1812
+ escalation: { ...DEFAULT_BUTTON_STYLES.escalation, ...(buttonStyling?.escalation || {}) },
1813
+ cardActions: { ...DEFAULT_BUTTON_STYLES.cardActions, ...(buttonStyling?.cardActions || {}) },
1814
+ };
1815
+
1721
1816
  const generateButtonCSS = (selector: string, style: Record<string, unknown>): string => {
1722
- if (!style) return '';
1723
-
1724
- const bg = style.backgroundColor as string || '';
1725
- const color = style.textColor as string || '';
1726
- const borderColor = style.borderColor as string || 'transparent';
1727
- const borderWidth = style.borderWidth as number || 0;
1728
- const borderRadius = style.borderRadius as number || 8;
1729
- const paddingV = style.paddingVertical as number || 8;
1730
- const paddingH = style.paddingHorizontal as number || 16;
1731
- const fontSize = style.fontSize as number || 13;
1732
- const fontWeight = getFontWeightValue(style.fontWeight as string || 'medium');
1733
-
1734
- // Use 'background' instead of 'background-color' to override gradients
1817
+ const bg = style.backgroundColor as string;
1818
+ const color = style.textColor as string;
1819
+ const borderColor = style.borderColor as string;
1820
+ const borderWidth = style.borderWidth as number;
1821
+ const borderRadius = style.borderRadius as number;
1822
+ const paddingV = style.paddingVertical as number;
1823
+ const paddingH = style.paddingHorizontal as number;
1824
+ const fontSize = style.fontSize as number;
1825
+ const fontWeight = getFontWeightValue(style.fontWeight as string);
1826
+
1735
1827
  return `
1736
- .ihooman-widget ${selector} {
1737
- ${bg ? `background: ${bg} !important;` : ''}
1738
- ${color ? `color: ${color} !important;` : ''}
1828
+ .ihooman-widget ${selector},
1829
+ html body .ihooman-widget ${selector} {
1830
+ background: ${bg} !important;
1831
+ color: ${color} !important;
1739
1832
  border: ${borderWidth}px solid ${borderColor} !important;
1740
1833
  border-radius: ${borderRadius}px !important;
1741
1834
  padding: ${paddingV}px ${paddingH}px !important;
@@ -1745,9 +1838,23 @@ function applyButtonStyling(buttonStyling: Record<string, Record<string, unknown
1745
1838
  min-height: auto !important;
1746
1839
  width: auto !important;
1747
1840
  height: auto !important;
1841
+ max-width: none !important;
1842
+ max-height: none !important;
1748
1843
  display: inline-flex !important;
1749
1844
  align-items: center !important;
1750
1845
  justify-content: center !important;
1846
+ gap: 6px !important;
1847
+ line-height: 1.4 !important;
1848
+ text-transform: none !important;
1849
+ letter-spacing: normal !important;
1850
+ box-shadow: none !important;
1851
+ text-decoration: none !important;
1852
+ white-space: nowrap !important;
1853
+ flex-shrink: 0 !important;
1854
+ flex-grow: 0 !important;
1855
+ box-sizing: border-box !important;
1856
+ appearance: none !important;
1857
+ -webkit-appearance: none !important;
1751
1858
  }
1752
1859
  `;
1753
1860
  };
@@ -1755,50 +1862,36 @@ function applyButtonStyling(buttonStyling: Record<string, Record<string, unknown
1755
1862
  let css = '';
1756
1863
 
1757
1864
  // Primary buttons (send, submit, etc)
1758
- if (buttonStyling.primary) {
1759
- css += generateButtonCSS('.ihooman-input-btn.send', buttonStyling.primary);
1760
- css += generateButtonCSS('.ihooman-proactive-toast-btn.primary', buttonStyling.primary);
1761
- css += generateButtonCSS('.ihooman-survey-submit', buttonStyling.primary);
1762
- }
1865
+ css += generateButtonCSS('.ihooman-input-btn.send', mergedStyles.primary);
1866
+ css += generateButtonCSS('.ihooman-proactive-toast-btn.primary', mergedStyles.primary);
1867
+ css += generateButtonCSS('.ihooman-survey-submit', mergedStyles.primary);
1868
+ css += generateButtonCSS('.ihooman-ticket-submit', mergedStyles.primary);
1869
+ css += generateButtonCSS('.ihooman-history-new', mergedStyles.primary);
1763
1870
 
1764
1871
  // Secondary buttons
1765
- if (buttonStyling.secondary) {
1766
- css += generateButtonCSS('.ihooman-proactive-toast-btn.secondary', buttonStyling.secondary);
1767
- css += generateButtonCSS('.ihooman-survey-skip', buttonStyling.secondary);
1768
- css += generateButtonCSS('.ihooman-ticket-back', buttonStyling.secondary);
1769
- }
1872
+ css += generateButtonCSS('.ihooman-proactive-toast-btn.secondary', mergedStyles.secondary);
1873
+ css += generateButtonCSS('.ihooman-survey-skip', mergedStyles.secondary);
1874
+ css += generateButtonCSS('.ihooman-ticket-back', mergedStyles.secondary);
1770
1875
 
1771
1876
  // Preset question buttons
1772
- if (buttonStyling.presetQuestions) {
1773
- css += generateButtonCSS('.ihooman-preset-btn', buttonStyling.presetQuestions);
1774
- }
1877
+ css += generateButtonCSS('.ihooman-preset-btn', mergedStyles.presetQuestions);
1775
1878
 
1776
1879
  // Quick reply buttons
1777
- if (buttonStyling.quickReplies) {
1778
- css += generateButtonCSS('.ihooman-quick-reply', buttonStyling.quickReplies);
1779
- }
1880
+ css += generateButtonCSS('.ihooman-quick-reply', mergedStyles.quickReplies);
1780
1881
 
1781
1882
  // Feedback buttons (thumbs up/down)
1782
- if (buttonStyling.feedback) {
1783
- css += generateButtonCSS('.ihooman-feedback-btn', buttonStyling.feedback);
1784
- }
1883
+ css += generateButtonCSS('.ihooman-feedback-btn', mergedStyles.feedback);
1785
1884
 
1786
1885
  // Header action buttons
1787
- if (buttonStyling.headerActions) {
1788
- css += generateButtonCSS('.ihooman-header-btn', buttonStyling.headerActions);
1789
- }
1886
+ css += generateButtonCSS('.ihooman-header-btn', mergedStyles.headerActions);
1790
1887
 
1791
1888
  // Escalation buttons (Talk to Agent, Create Ticket)
1792
- if (buttonStyling.escalation) {
1793
- css += generateButtonCSS('.ihooman-escalation-btn', buttonStyling.escalation);
1794
- css += generateButtonCSS('.ihooman-escalation-btn.primary', buttonStyling.escalation);
1795
- css += generateButtonCSS('.ihooman-escalation-btn.secondary', buttonStyling.escalation);
1796
- }
1889
+ css += generateButtonCSS('.ihooman-escalation-btn', mergedStyles.escalation);
1890
+ css += generateButtonCSS('.ihooman-escalation-btn.primary', mergedStyles.escalation);
1891
+ css += generateButtonCSS('.ihooman-escalation-btn.secondary', mergedStyles.secondary);
1797
1892
 
1798
1893
  // Card action buttons
1799
- if (buttonStyling.cardActions) {
1800
- css += generateButtonCSS('.ihooman-carousel-card-btn', buttonStyling.cardActions);
1801
- }
1894
+ css += generateButtonCSS('.ihooman-carousel-card-btn', mergedStyles.cardActions);
1802
1895
 
1803
1896
  console.debug('[IhoomanChat] Applied button styling CSS:', css.length, 'chars');
1804
1897
  styleEl.textContent = css;
@@ -1965,6 +2058,7 @@ async function init(userConfig: WidgetConfig): Promise<IhoomanChatAPI | null> {
1965
2058
  }
1966
2059
 
1967
2060
  createWidget();
2061
+ applyButtonStyling(config.buttonStyling as Record<string, Record<string, unknown>> | undefined);
1968
2062
  renderPresetQuestions();
1969
2063
 
1970
2064
  state.messages.forEach((msg) => addMessage(msg.content, msg.sender === 'user' ? 'user' : 'bot', msg.metadata));