@ihoomanai/chat-widget 3.0.9 → 3.0.10

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.9';
20
+ const VERSION = '3.0.10';
21
21
  const STORAGE_PREFIX = 'ihooman_chat_';
22
22
  const DEFAULT_SERVER_URL = 'https://api.ihooman.ai';
23
23
 
@@ -231,9 +231,21 @@ function generateStyles(): string {
231
231
  const positionBottom = config.position?.includes('bottom') ?? true;
232
232
 
233
233
  return `
234
- .ihooman-widget * { box-sizing: border-box !important; margin: 0; padding: 0; }
234
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
235
+ :host { all: initial; }
235
236
  .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 !important; cursor: pointer !important; font-family: inherit !important; appearance: none !important; -webkit-appearance: none !important; outline: none !important; }
237
+ button {
238
+ font-family: inherit;
239
+ font-size: 100%;
240
+ line-height: inherit;
241
+ color: inherit;
242
+ margin: 0;
243
+ padding: 0;
244
+ background: transparent;
245
+ border: none;
246
+ cursor: pointer;
247
+ outline: none;
248
+ }
237
249
  .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
250
  .ihooman-toggle:hover { transform: scale(1.08); box-shadow: 0 6px 28px rgba(0, 174, 255, 0.45); }
239
251
  .ihooman-toggle:active { transform: scale(0.95); }
@@ -300,8 +312,7 @@ function generateStyles(): string {
300
312
  .ihooman-powered { text-align: center; padding: 8px; font-size: 11px; color: ${mutedColor}; background: ${bgColor}; }
301
313
  .ihooman-powered a { color: ${primaryColor}; text-decoration: none; }
302
314
  .ihooman-escalation-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
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; }
315
+ .ihooman-escalation-btn svg { width: 14px; height: 14px; flex-shrink: 0; }
305
316
  .ihooman-status-bar { padding: 10px 16px; text-align: center; font-size: 13px; display: none; }
306
317
  .ihooman-status-bar.show { display: block; }
307
318
  .ihooman-status-bar.waiting { background: #fef3c7; color: #92400e; }
@@ -337,8 +348,7 @@ function generateStyles(): string {
337
348
  .ihooman-history-empty { padding: 40px; text-align: center; color: ${mutedColor}; font-size: 14px; }
338
349
  .ihooman-preset-questions { padding: 10px 16px; display: flex; flex-wrap: wrap; gap: 6px; background: ${bgColor}; border-top: 1px solid ${borderColor}; }
339
350
  .ihooman-preset-questions:empty { display: none; }
340
- .ihooman-preset-questions.hidden { display: none !important; }
341
- .ihooman-widget .ihooman-preset-btn { cursor: pointer !important; font-family: inherit !important; transition: all 0.2s !important; }
351
+ .ihooman-preset-questions.hidden { display: none; }
342
352
  .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}; }
343
353
  .ihooman-proactive-toast.show { opacity: 1; visibility: visible; transform: translateY(0); }
344
354
  .ihooman-proactive-toast-content { font-size: 14px; color: ${textColor}; margin-bottom: 12px; }
@@ -361,8 +371,7 @@ function generateStyles(): string {
361
371
  .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; }
362
372
  .ihooman-survey-skip:hover { color: ${textColor}; }
363
373
  .ihooman-feedback-btns { display: flex; gap: 6px; margin-top: 6px; }
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; }
374
+ .ihooman-feedback-btn svg { width: 12px; height: 12px; }
366
375
  .ihooman-carousel { display: flex; gap: 12px; overflow-x: auto; padding: 8px 0; scroll-snap-type: x mandatory; }
367
376
  .ihooman-carousel::-webkit-scrollbar { height: 4px; }
368
377
  .ihooman-carousel-card { min-width: 200px; max-width: 250px; border: 1px solid ${borderColor}; border-radius: 12px; overflow: hidden; scroll-snap-align: start; background: ${bgColor}; }
@@ -371,9 +380,7 @@ function generateStyles(): string {
371
380
  .ihooman-carousel-card-title { font-size: 14px; font-weight: 600; color: ${textColor}; margin-bottom: 4px; }
372
381
  .ihooman-carousel-card-desc { font-size: 12px; color: ${mutedColor}; margin-bottom: 8px; }
373
382
  .ihooman-carousel-card-btns { display: flex; flex-direction: column; gap: 6px; }
374
- .ihooman-widget .ihooman-carousel-card-btn { cursor: pointer !important; transition: all 0.2s !important; }
375
383
  .ihooman-quick-replies { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
376
- .ihooman-widget .ihooman-quick-reply { cursor: pointer !important; transition: all 0.2s !important; }
377
384
  @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; } }
378
385
  `;
379
386
  }
@@ -383,14 +390,27 @@ function generateStyles(): string {
383
390
  // DOM CREATION
384
391
  // ============================================================================
385
392
 
393
+ let shadowRoot: ShadowRoot | null = null;
394
+
386
395
  function createWidget(): void {
396
+ // Create host element
397
+ const host = document.createElement('div');
398
+ host.id = 'ihooman-chat-widget-host';
399
+ host.style.cssText = 'all: initial !important; position: fixed !important; z-index: 2147483647 !important; pointer-events: none !important;';
400
+ document.body.appendChild(host);
401
+
402
+ // Create Shadow DOM for style isolation
403
+ shadowRoot = host.attachShadow({ mode: 'open' });
404
+
405
+ // Add styles inside shadow DOM
387
406
  const styleEl = document.createElement('style');
388
407
  styleEl.id = 'ihooman-widget-styles';
389
408
  styleEl.textContent = generateStyles();
390
- document.head.appendChild(styleEl);
409
+ shadowRoot.appendChild(styleEl);
391
410
 
392
411
  const widget = document.createElement('div');
393
412
  widget.className = 'ihooman-widget';
413
+ widget.style.cssText = 'pointer-events: auto;';
394
414
  widget.innerHTML = `
395
415
  <button class="ihooman-toggle" aria-label="Open chat">
396
416
  <span class="ihooman-pulse"></span>
@@ -459,7 +479,7 @@ function createWidget(): void {
459
479
  </div>
460
480
  `;
461
481
 
462
- document.body.appendChild(widget);
482
+ shadowRoot.appendChild(widget);
463
483
 
464
484
  elements = {
465
485
  widget,
@@ -1793,12 +1813,15 @@ const DEFAULT_BUTTON_STYLES = {
1793
1813
 
1794
1814
  function applyButtonStyling(buttonStyling?: Record<string, Record<string, unknown>>): void {
1795
1815
  const styleId = 'ihooman-button-styling';
1796
- let styleEl = document.getElementById(styleId) as HTMLStyleElement | null;
1816
+
1817
+ // Get the shadow root or fall back to document.head
1818
+ const styleContainer = shadowRoot || document.head;
1819
+ let styleEl = styleContainer.querySelector(`#${styleId}`) as HTMLStyleElement | null;
1797
1820
 
1798
1821
  if (!styleEl) {
1799
1822
  styleEl = document.createElement('style');
1800
1823
  styleEl.id = styleId;
1801
- document.head.appendChild(styleEl);
1824
+ styleContainer.appendChild(styleEl);
1802
1825
  }
1803
1826
 
1804
1827
  // Merge provided styles with defaults
@@ -1824,37 +1847,37 @@ function applyButtonStyling(buttonStyling?: Record<string, Record<string, unknow
1824
1847
  const fontSize = style.fontSize as number;
1825
1848
  const fontWeight = getFontWeightValue(style.fontWeight as string);
1826
1849
 
1850
+ // Shadow DOM provides isolation, so we don't need !important or high specificity
1827
1851
  return `
1828
- .ihooman-widget ${selector},
1829
- html body .ihooman-widget ${selector} {
1830
- background: ${bg} !important;
1831
- color: ${color} !important;
1832
- border: ${borderWidth}px solid ${borderColor} !important;
1833
- border-radius: ${borderRadius}px !important;
1834
- padding: ${paddingV}px ${paddingH}px !important;
1835
- font-size: ${fontSize}px !important;
1836
- font-weight: ${fontWeight} !important;
1837
- min-width: auto !important;
1838
- min-height: auto !important;
1839
- width: auto !important;
1840
- height: auto !important;
1841
- max-width: none !important;
1842
- max-height: none !important;
1843
- display: inline-flex !important;
1844
- align-items: center !important;
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;
1852
+ ${selector} {
1853
+ background: ${bg};
1854
+ color: ${color};
1855
+ border: ${borderWidth}px solid ${borderColor};
1856
+ border-radius: ${borderRadius}px;
1857
+ padding: ${paddingV}px ${paddingH}px;
1858
+ margin: 0;
1859
+ font-family: inherit;
1860
+ font-size: ${fontSize}px;
1861
+ font-weight: ${fontWeight};
1862
+ min-width: unset;
1863
+ min-height: unset;
1864
+ width: auto;
1865
+ height: auto;
1866
+ max-width: none;
1867
+ max-height: none;
1868
+ display: inline-flex;
1869
+ align-items: center;
1870
+ justify-content: center;
1871
+ gap: 6px;
1872
+ line-height: 1.4;
1873
+ text-transform: none;
1874
+ letter-spacing: normal;
1875
+ box-shadow: none;
1876
+ text-decoration: none;
1877
+ white-space: nowrap;
1878
+ box-sizing: border-box;
1879
+ cursor: pointer;
1880
+ transition: all 0.2s ease;
1858
1881
  }
1859
1882
  `;
1860
1883
  };