@ihoomanai/chat-widget 3.0.8 → 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.8';
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
 
@@ -300,15 +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-widget .ihooman-escalation-btn,
304
- html body .ihooman-widget .ihooman-escalation-btn { display: inline-flex !important; align-items: center !important; justify-content: center !important; gap: 6px !important; padding: 8px 14px !important; border-radius: 6px !important; border: none !important; cursor: pointer !important; font-family: inherit !important; font-size: 12px !important; font-weight: 500 !important; transition: all 0.2s ease !important; line-height: 1.4 !important; min-width: auto !important; min-height: auto !important; width: auto !important; height: auto !important; max-width: none !important; max-height: none !important; box-shadow: none !important; text-transform: none !important; letter-spacing: normal !important; white-space: nowrap !important; flex-shrink: 0 !important; flex-grow: 0 !important; }
303
+ .ihooman-widget .ihooman-escalation-btn { cursor: pointer !important; font-family: inherit !important; transition: all 0.2s ease !important; }
305
304
  .ihooman-widget .ihooman-escalation-btn svg { width: 14px !important; height: 14px !important; flex-shrink: 0 !important; }
306
- .ihooman-widget .ihooman-escalation-btn.primary,
307
- html body .ihooman-widget .ihooman-escalation-btn.primary { background: linear-gradient(135deg, ${gradientFrom}, ${gradientTo}) !important; color: white !important; }
308
- .ihooman-widget .ihooman-escalation-btn.primary:hover { opacity: 0.9 !important; }
309
- .ihooman-widget .ihooman-escalation-btn.secondary,
310
- html body .ihooman-widget .ihooman-escalation-btn.secondary { background: ${isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)'} !important; color: ${textColor} !important; border: 1px solid ${borderColor} !important; }
311
- .ihooman-widget .ihooman-escalation-btn.secondary:hover { background: ${isDark ? 'rgba(255,255,255,0.15)' : 'rgba(0,0,0,0.08)'} !important; }
312
305
  .ihooman-status-bar { padding: 10px 16px; text-align: center; font-size: 13px; display: none; }
313
306
  .ihooman-status-bar.show { display: block; }
314
307
  .ihooman-status-bar.waiting { background: #fef3c7; color: #92400e; }
@@ -345,9 +338,7 @@ function generateStyles(): string {
345
338
  .ihooman-preset-questions { padding: 10px 16px; display: flex; flex-wrap: wrap; gap: 6px; background: ${bgColor}; border-top: 1px solid ${borderColor}; }
346
339
  .ihooman-preset-questions:empty { display: none; }
347
340
  .ihooman-preset-questions.hidden { display: none !important; }
348
- .ihooman-widget .ihooman-preset-btn,
349
- html body .ihooman-widget .ihooman-preset-btn { display: inline-flex !important; align-items: center !important; justify-content: center !important; gap: 4px !important; padding: 6px 10px !important; border-radius: 6px !important; border: 1px solid ${borderColor} !important; background: ${isDark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.02)'} !important; color: ${textColor} !important; font-size: 12px !important; font-weight: 500 !important; cursor: pointer !important; transition: all 0.2s !important; white-space: nowrap !important; line-height: 1.4 !important; min-width: auto !important; min-height: auto !important; width: auto !important; height: auto !important; max-width: none !important; max-height: none !important; box-shadow: none !important; text-transform: none !important; letter-spacing: normal !important; flex-shrink: 0 !important; flex-grow: 0 !important; }
350
- .ihooman-widget .ihooman-preset-btn:hover { background: ${isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)'} !important; border-color: ${primaryColor} !important; }
341
+ .ihooman-widget .ihooman-preset-btn { cursor: pointer !important; font-family: inherit !important; transition: all 0.2s !important; }
351
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}; }
352
343
  .ihooman-proactive-toast.show { opacity: 1; visibility: visible; transform: translateY(0); }
353
344
  .ihooman-proactive-toast-content { font-size: 14px; color: ${textColor}; margin-bottom: 12px; }
@@ -370,10 +361,7 @@ function generateStyles(): string {
370
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; }
371
362
  .ihooman-survey-skip:hover { color: ${textColor}; }
372
363
  .ihooman-feedback-btns { display: flex; gap: 6px; margin-top: 6px; }
373
- .ihooman-widget .ihooman-feedback-btn,
374
- html body .ihooman-widget .ihooman-feedback-btn { display: inline-flex !important; align-items: center !important; justify-content: center !important; padding: 4px 6px !important; border: 1px solid ${borderColor} !important; border-radius: 4px !important; background: transparent !important; cursor: pointer !important; color: ${mutedColor} !important; transition: all 0.2s !important; min-width: auto !important; min-height: auto !important; width: auto !important; height: auto !important; max-width: none !important; max-height: none !important; box-shadow: none !important; flex-shrink: 0 !important; flex-grow: 0 !important; }
375
- .ihooman-widget .ihooman-feedback-btn:hover { background: ${isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)'} !important; }
376
- .ihooman-widget .ihooman-feedback-btn.active { background: ${primaryColor} !important; color: white !important; border-color: ${primaryColor} !important; }
364
+ .ihooman-widget .ihooman-feedback-btn { cursor: pointer !important; transition: all 0.2s !important; }
377
365
  .ihooman-widget .ihooman-feedback-btn svg { width: 12px !important; height: 12px !important; }
378
366
  .ihooman-carousel { display: flex; gap: 12px; overflow-x: auto; padding: 8px 0; scroll-snap-type: x mandatory; }
379
367
  .ihooman-carousel::-webkit-scrollbar { height: 4px; }
@@ -383,13 +371,9 @@ function generateStyles(): string {
383
371
  .ihooman-carousel-card-title { font-size: 14px; font-weight: 600; color: ${textColor}; margin-bottom: 4px; }
384
372
  .ihooman-carousel-card-desc { font-size: 12px; color: ${mutedColor}; margin-bottom: 8px; }
385
373
  .ihooman-carousel-card-btns { display: flex; flex-direction: column; gap: 6px; }
386
- .ihooman-widget .ihooman-carousel-card-btn,
387
- html body .ihooman-widget .ihooman-carousel-card-btn { display: flex !important; align-items: center !important; justify-content: center !important; padding: 6px 10px !important; border: 1px solid ${borderColor} !important; border-radius: 6px !important; background: transparent !important; color: ${textColor} !important; font-size: 11px !important; cursor: pointer !important; transition: all 0.2s !important; text-align: center !important; line-height: 1.4 !important; min-width: auto !important; min-height: auto !important; width: auto !important; height: auto !important; max-width: none !important; max-height: none !important; box-shadow: none !important; text-transform: none !important; letter-spacing: normal !important; }
388
- .ihooman-carousel-card-btn:hover { background: ${isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.05)'} !important; border-color: ${primaryColor} !important; }
374
+ .ihooman-widget .ihooman-carousel-card-btn { cursor: pointer !important; transition: all 0.2s !important; }
389
375
  .ihooman-quick-replies { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
390
- .ihooman-widget .ihooman-quick-reply,
391
- html body .ihooman-widget .ihooman-quick-reply { display: inline-flex !important; align-items: center !important; justify-content: center !important; padding: 5px 10px !important; border: 1px solid ${primaryColor} !important; border-radius: 14px !important; background: transparent !important; color: ${primaryColor} !important; font-size: 11px !important; cursor: pointer !important; transition: all 0.2s !important; line-height: 1.4 !important; min-width: auto !important; min-height: auto !important; width: auto !important; height: auto !important; max-width: none !important; max-height: none !important; box-shadow: none !important; text-transform: none !important; letter-spacing: normal !important; white-space: nowrap !important; flex-shrink: 0 !important; flex-grow: 0 !important; }
392
- .ihooman-widget .ihooman-quick-reply:hover { background: ${primaryColor} !important; color: white !important; }
376
+ .ihooman-widget .ihooman-quick-reply { cursor: pointer !important; transition: all 0.2s !important; }
393
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; } }
394
378
  `;
395
379
  }
@@ -1715,7 +1699,99 @@ function getFontWeightValue(weight: string): number {
1715
1699
  }
1716
1700
  }
1717
1701
 
1718
- 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 {
1719
1795
  const styleId = 'ihooman-button-styling';
1720
1796
  let styleEl = document.getElementById(styleId) as HTMLStyleElement | null;
1721
1797
 
@@ -1725,27 +1801,34 @@ function applyButtonStyling(buttonStyling: Record<string, Record<string, unknown
1725
1801
  document.head.appendChild(styleEl);
1726
1802
  }
1727
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
+
1728
1816
  const generateButtonCSS = (selector: string, style: Record<string, unknown>): string => {
1729
- if (!style) return '';
1730
-
1731
- const bg = style.backgroundColor as string || '';
1732
- const color = style.textColor as string || '';
1733
- const borderColor = style.borderColor as string || 'transparent';
1734
- const borderWidth = style.borderWidth as number ?? 0;
1735
- const borderRadius = style.borderRadius as number ?? 8;
1736
- const paddingV = style.paddingVertical as number ?? 8;
1737
- const paddingH = style.paddingHorizontal as number ?? 16;
1738
- const fontSize = style.fontSize as number ?? 13;
1739
- const fontWeight = getFontWeightValue(style.fontWeight as string || 'medium');
1740
-
1741
- // Use 'background' instead of 'background-color' to override gradients
1742
- // Use very high specificity to override any external styles
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
+
1743
1827
  return `
1744
1828
  .ihooman-widget ${selector},
1745
- .ihooman-widget ${selector}:not(:disabled),
1746
1829
  html body .ihooman-widget ${selector} {
1747
- ${bg ? `background: ${bg} !important;` : ''}
1748
- ${color ? `color: ${color} !important;` : ''}
1830
+ background: ${bg} !important;
1831
+ color: ${color} !important;
1749
1832
  border: ${borderWidth}px solid ${borderColor} !important;
1750
1833
  border-radius: ${borderRadius}px !important;
1751
1834
  padding: ${paddingV}px ${paddingH}px !important;
@@ -1766,11 +1849,12 @@ function applyButtonStyling(buttonStyling: Record<string, Record<string, unknown
1766
1849
  letter-spacing: normal !important;
1767
1850
  box-shadow: none !important;
1768
1851
  text-decoration: none !important;
1769
- vertical-align: middle !important;
1770
1852
  white-space: nowrap !important;
1771
- overflow: visible !important;
1772
1853
  flex-shrink: 0 !important;
1773
1854
  flex-grow: 0 !important;
1855
+ box-sizing: border-box !important;
1856
+ appearance: none !important;
1857
+ -webkit-appearance: none !important;
1774
1858
  }
1775
1859
  `;
1776
1860
  };
@@ -1778,50 +1862,36 @@ function applyButtonStyling(buttonStyling: Record<string, Record<string, unknown
1778
1862
  let css = '';
1779
1863
 
1780
1864
  // Primary buttons (send, submit, etc)
1781
- if (buttonStyling.primary) {
1782
- css += generateButtonCSS('.ihooman-input-btn.send', buttonStyling.primary);
1783
- css += generateButtonCSS('.ihooman-proactive-toast-btn.primary', buttonStyling.primary);
1784
- css += generateButtonCSS('.ihooman-survey-submit', buttonStyling.primary);
1785
- }
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);
1786
1870
 
1787
1871
  // Secondary buttons
1788
- if (buttonStyling.secondary) {
1789
- css += generateButtonCSS('.ihooman-proactive-toast-btn.secondary', buttonStyling.secondary);
1790
- css += generateButtonCSS('.ihooman-survey-skip', buttonStyling.secondary);
1791
- css += generateButtonCSS('.ihooman-ticket-back', buttonStyling.secondary);
1792
- }
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);
1793
1875
 
1794
1876
  // Preset question buttons
1795
- if (buttonStyling.presetQuestions) {
1796
- css += generateButtonCSS('.ihooman-preset-btn', buttonStyling.presetQuestions);
1797
- }
1877
+ css += generateButtonCSS('.ihooman-preset-btn', mergedStyles.presetQuestions);
1798
1878
 
1799
1879
  // Quick reply buttons
1800
- if (buttonStyling.quickReplies) {
1801
- css += generateButtonCSS('.ihooman-quick-reply', buttonStyling.quickReplies);
1802
- }
1880
+ css += generateButtonCSS('.ihooman-quick-reply', mergedStyles.quickReplies);
1803
1881
 
1804
1882
  // Feedback buttons (thumbs up/down)
1805
- if (buttonStyling.feedback) {
1806
- css += generateButtonCSS('.ihooman-feedback-btn', buttonStyling.feedback);
1807
- }
1883
+ css += generateButtonCSS('.ihooman-feedback-btn', mergedStyles.feedback);
1808
1884
 
1809
1885
  // Header action buttons
1810
- if (buttonStyling.headerActions) {
1811
- css += generateButtonCSS('.ihooman-header-btn', buttonStyling.headerActions);
1812
- }
1886
+ css += generateButtonCSS('.ihooman-header-btn', mergedStyles.headerActions);
1813
1887
 
1814
1888
  // Escalation buttons (Talk to Agent, Create Ticket)
1815
- if (buttonStyling.escalation) {
1816
- css += generateButtonCSS('.ihooman-escalation-btn', buttonStyling.escalation);
1817
- css += generateButtonCSS('.ihooman-escalation-btn.primary', buttonStyling.escalation);
1818
- css += generateButtonCSS('.ihooman-escalation-btn.secondary', buttonStyling.escalation);
1819
- }
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);
1820
1892
 
1821
1893
  // Card action buttons
1822
- if (buttonStyling.cardActions) {
1823
- css += generateButtonCSS('.ihooman-carousel-card-btn', buttonStyling.cardActions);
1824
- }
1894
+ css += generateButtonCSS('.ihooman-carousel-card-btn', mergedStyles.cardActions);
1825
1895
 
1826
1896
  console.debug('[IhoomanChat] Applied button styling CSS:', css.length, 'chars');
1827
1897
  styleEl.textContent = css;
@@ -1988,6 +2058,7 @@ async function init(userConfig: WidgetConfig): Promise<IhoomanChatAPI | null> {
1988
2058
  }
1989
2059
 
1990
2060
  createWidget();
2061
+ applyButtonStyling(config.buttonStyling as Record<string, Record<string, unknown>> | undefined);
1991
2062
  renderPresetQuestions();
1992
2063
 
1993
2064
  state.messages.forEach((msg) => addMessage(msg.content, msg.sender === 'user' ? 'user' : 'bot', msg.metadata));