urasoft-live-support 1.0.0 → 1.1.0

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.
@@ -7,11 +7,17 @@ export declare class ChatWidget {
7
7
  private signalRClient;
8
8
  private emojiPicker;
9
9
  private isEmojiPickerOpen;
10
+ private scaleFactor;
11
+ private resizeObserver;
10
12
  constructor(config?: ChatConfig);
11
13
  private init;
12
14
  private createContainer;
13
15
  private attachStyles;
14
16
  private darkenColor;
17
+ private detectScaleFactor;
18
+ private getZoomLevel;
19
+ private setupResizeObserver;
20
+ private updateScaleStyles;
15
21
  private mergeClasses;
16
22
  private render;
17
23
  private renderChatWindow;
@@ -1 +1 @@
1
- {"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../../src/core/ChatWidget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAgD,MAAM,UAAU,CAAC;AAEpF,OAAO,eAAe,CAAC;AAEvB,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CASZ;IACF,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,iBAAiB,CAAkB;gBAE/B,MAAM,GAAE,UAAe;IAiCnC,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,eAAe;IAyBvB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,MAAM;IAed,OAAO,CAAC,gBAAgB;IAoGxB,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,oBAAoB;YAoCd,cAAc;YA+Dd,iBAAiB;YAiBjB,WAAW;YAyEX,kBAAkB;IAuEhC,OAAO,CAAC,UAAU;IAgBlB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,MAAM;IAKP,IAAI,IAAI,IAAI;IAKZ,KAAK,IAAI,IAAI;IAKP,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAYvF,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,UAAU;YAIJ,gBAAgB;IA2D9B,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,iBAAiB;IAgCzB,OAAO,CAAC,cAAc;YAQR,eAAe;YAwCf,iBAAiB;IAqB/B,OAAO,CAAC,kBAAkB,CAWzB;CACJ"}
1
+ {"version":3,"file":"ChatWidget.d.ts","sourceRoot":"","sources":["../../src/core/ChatWidget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAgD,MAAM,UAAU,CAAC;AAEpF,OAAO,eAAe,CAAC;AAEvB,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAYZ;IACF,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,iBAAiB,CAAkB;IAC3C,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,cAAc,CAA+B;gBAEzC,MAAM,GAAE,UAAe;IAiDnC,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,eAAe;IAyBvB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,YAAY;IAgCpB,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,MAAM;IAed,OAAO,CAAC,gBAAgB;IAoGxB,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,oBAAoB;YAoCd,cAAc;YA0Ed,iBAAiB;YAgCjB,WAAW;YAyEX,kBAAkB;IAuEhC,OAAO,CAAC,UAAU;IAgBlB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,MAAM;IAKP,IAAI,IAAI,IAAI;IAKZ,KAAK,IAAI,IAAI;IAKP,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAW9B,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAYvF,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,UAAU;YAIJ,gBAAgB;IA2D9B,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,iBAAiB;IAgCzB,OAAO,CAAC,cAAc;YAQR,eAAe;YAwCf,iBAAiB;IAqB/B,OAAO,CAAC,kBAAkB,CAWzB;CACJ"}
package/dist/index.d.ts CHANGED
@@ -88,6 +88,8 @@ interface ChatConfig {
88
88
  agentName?: string;
89
89
  agentAvatar?: string;
90
90
  autoOpen?: boolean;
91
+ autoConnect?: boolean;
92
+ previousMessages?: ChatMessage[];
91
93
  buttonIcon?: string;
92
94
  theme?: 'light' | 'dark' | 'auto';
93
95
  customClasses?: CustomClasses;
@@ -98,6 +100,7 @@ interface ChatConfig {
98
100
  maxFileSize?: number;
99
101
  allowedFileTypes?: string[];
100
102
  disableAttachments?: boolean;
103
+ onBeforeDisconnect?: () => boolean | Promise<boolean>;
101
104
  }
102
105
  interface ChatWidgetState {
103
106
  isOpen: boolean;
@@ -114,11 +117,17 @@ declare class ChatWidget {
114
117
  private signalRClient;
115
118
  private emojiPicker;
116
119
  private isEmojiPickerOpen;
120
+ private scaleFactor;
121
+ private resizeObserver;
117
122
  constructor(config?: ChatConfig);
118
123
  private init;
119
124
  private createContainer;
120
125
  private attachStyles;
121
126
  private darkenColor;
127
+ private detectScaleFactor;
128
+ private getZoomLevel;
129
+ private setupResizeObserver;
130
+ private updateScaleStyles;
122
131
  private mergeClasses;
123
132
  private render;
124
133
  private renderChatWindow;
package/dist/index.esm.js CHANGED
@@ -3605,6 +3605,8 @@ class ChatWidget {
3605
3605
  this.signalRClient = null;
3606
3606
  this.emojiPicker = null;
3607
3607
  this.isEmojiPickerOpen = false;
3608
+ this.scaleFactor = 1;
3609
+ this.resizeObserver = null;
3608
3610
  this.handleOutsideClick = (event) => {
3609
3611
  const pickerContainer = document.getElementById('chat-emoji-picker-container');
3610
3612
  const emojiButton = document.getElementById('chat-emoji-button');
@@ -3635,20 +3637,35 @@ class ChatWidget {
3635
3637
  allowedFileTypes: config.allowedFileTypes,
3636
3638
  customClasses: config.customClasses,
3637
3639
  disableAttachments: config.disableAttachments || false,
3640
+ onBeforeDisconnect: config.onBeforeDisconnect,
3638
3641
  };
3642
+ // Önceki mesajları yükle
3643
+ const previousMessages = config.previousMessages || [];
3644
+ const hasPreviousMessages = previousMessages.length > 0;
3645
+ // Eğer önceki mesajlar varsa veya autoConnect true ise, autoOpen'ı true yap
3646
+ const shouldAutoOpen = !!(config.autoOpen || hasPreviousMessages || config.autoConnect);
3639
3647
  this.state = {
3640
- isOpen: this.config.autoOpen,
3641
- messages: [],
3648
+ isOpen: shouldAutoOpen,
3649
+ messages: previousMessages,
3642
3650
  isConnected: false,
3643
3651
  isConnecting: false,
3644
3652
  selectedFiles: [],
3645
3653
  };
3646
3654
  this.init();
3655
+ // autoConnect true ise ve SignalR config varsa, otomatik bağlan
3656
+ if ((config.autoConnect || hasPreviousMessages) && config.signalR) {
3657
+ // Widget render edildikten sonra bağlan
3658
+ setTimeout(() => {
3659
+ this.connectSignalR();
3660
+ }, 100);
3661
+ }
3647
3662
  }
3648
3663
  init() {
3664
+ this.detectScaleFactor();
3649
3665
  this.createContainer();
3650
3666
  this.attachStyles();
3651
3667
  this.render();
3668
+ this.setupResizeObserver();
3652
3669
  // Welcome mesajı sadece SignalR bağlantısı kurulduğunda eklenecek
3653
3670
  }
3654
3671
  createContainer() {
@@ -3693,6 +3710,76 @@ class ChatWidget {
3693
3710
  const b = Math.max(0, (num & 0x0000FF) - (255 * percent) / 100);
3694
3711
  return `#${((1 << 24) + (Math.floor(r) << 16) + (Math.floor(g) << 8) + Math.floor(b)).toString(16).slice(1)}`;
3695
3712
  }
3713
+ detectScaleFactor() {
3714
+ // Detect device pixel ratio (for high-DPI displays)
3715
+ const dpr = window.devicePixelRatio || 1;
3716
+ // Detect browser zoom level
3717
+ const zoomLevel = this.getZoomLevel();
3718
+ // Combined scale factor
3719
+ this.scaleFactor = 1 / (dpr * zoomLevel);
3720
+ // Keep within reasonable bounds (0.5 - 2.0)
3721
+ this.scaleFactor = Math.max(0.5, Math.min(2.0, this.scaleFactor));
3722
+ }
3723
+ getZoomLevel() {
3724
+ // Multiple methods to detect zoom level
3725
+ // Method 1: window.outerWidth vs window.innerWidth
3726
+ const screenWidth = window.screen.width;
3727
+ const windowWidth = window.outerWidth;
3728
+ if (screenWidth && windowWidth) {
3729
+ const ratio = screenWidth / windowWidth;
3730
+ if (ratio > 0.5 && ratio < 2) {
3731
+ return ratio;
3732
+ }
3733
+ }
3734
+ // Method 2: CSS pixel ratio check
3735
+ const testDiv = document.createElement('div');
3736
+ testDiv.style.width = '1in';
3737
+ testDiv.style.height = '0';
3738
+ testDiv.style.position = 'absolute';
3739
+ testDiv.style.visibility = 'hidden';
3740
+ document.body.appendChild(testDiv);
3741
+ const devicePixelRatio = testDiv.offsetWidth / 96; // 96 DPI is standard
3742
+ document.body.removeChild(testDiv);
3743
+ if (devicePixelRatio > 0.5 && devicePixelRatio < 2) {
3744
+ return devicePixelRatio;
3745
+ }
3746
+ // Fallback
3747
+ return 1;
3748
+ }
3749
+ setupResizeObserver() {
3750
+ // Watch for viewport changes
3751
+ if (typeof ResizeObserver !== 'undefined') {
3752
+ this.resizeObserver = new ResizeObserver(() => {
3753
+ this.detectScaleFactor();
3754
+ this.updateScaleStyles();
3755
+ });
3756
+ if (this.container) {
3757
+ this.resizeObserver.observe(document.body);
3758
+ }
3759
+ }
3760
+ // Listen for zoom changes
3761
+ window.addEventListener('resize', () => {
3762
+ this.detectScaleFactor();
3763
+ this.updateScaleStyles();
3764
+ });
3765
+ }
3766
+ updateScaleStyles() {
3767
+ if (!this.container)
3768
+ return;
3769
+ const style = document.createElement('style');
3770
+ style.id = 'chat-widget-scale-styles';
3771
+ // Remove old scale style
3772
+ const oldStyle = document.getElementById('chat-widget-scale-styles');
3773
+ if (oldStyle) {
3774
+ oldStyle.remove();
3775
+ }
3776
+ style.textContent = `
3777
+ :root {
3778
+ --chat-scale-factor: ${this.scaleFactor};
3779
+ }
3780
+ `;
3781
+ document.head.appendChild(style);
3782
+ }
3696
3783
  mergeClasses(baseClass, customClass) {
3697
3784
  return customClass ? `${baseClass} ${customClass}` : baseClass;
3698
3785
  }
@@ -3878,18 +3965,26 @@ class ChatWidget {
3878
3965
  onConnected: () => {
3879
3966
  this.state.isConnected = true;
3880
3967
  this.state.isConnecting = false;
3881
- this.state.messages = []; // Mesajları temizle
3882
- // Welcome mesajını ekle
3883
- if (this.config.welcomeMessage) {
3884
- this.addMessage({
3885
- id: Date.now().toString(),
3886
- message: this.config.welcomeMessage,
3887
- sender: 'agent',
3888
- timestamp: new Date(),
3889
- avatar: this.config.agentAvatar,
3890
- });
3968
+ // Eğer önceden yüklenmiş mesajlar yoksa, mesajları temizle ve welcome mesajı ekle
3969
+ const hasExistingMessages = this.state.messages.length > 0;
3970
+ if (!hasExistingMessages) {
3971
+ this.state.messages = [];
3972
+ // Welcome mesajını ekle
3973
+ if (this.config.welcomeMessage) {
3974
+ this.addMessage({
3975
+ id: Date.now().toString(),
3976
+ message: this.config.welcomeMessage,
3977
+ sender: 'agent',
3978
+ timestamp: new Date(),
3979
+ avatar: this.config.agentAvatar,
3980
+ });
3981
+ }
3891
3982
  }
3892
3983
  this.render();
3984
+ // Önceki mesajlar varsa en alta scroll et
3985
+ if (hasExistingMessages) {
3986
+ this.scrollToBottom();
3987
+ }
3893
3988
  if (this.config.signalR?.onConnected) {
3894
3989
  this.config.signalR.onConnected();
3895
3990
  }
@@ -3926,6 +4021,21 @@ class ChatWidget {
3926
4021
  }
3927
4022
  async disconnectSignalR() {
3928
4023
  if (this.signalRClient) {
4024
+ // onBeforeDisconnect callback varsa çağır
4025
+ if (this.config.onBeforeDisconnect) {
4026
+ try {
4027
+ const shouldDisconnect = await this.config.onBeforeDisconnect();
4028
+ if (!shouldDisconnect) {
4029
+ // false dönerse disconnect işlemini iptal et
4030
+ return;
4031
+ }
4032
+ }
4033
+ catch (error) {
4034
+ console.error('onBeforeDisconnect error:', error);
4035
+ // Hata olursa disconnect işlemini iptal et
4036
+ return;
4037
+ }
4038
+ }
3929
4039
  await this.signalRClient.disconnect();
3930
4040
  this.signalRClient = null;
3931
4041
  this.state.isConnected = false;
@@ -4111,6 +4221,9 @@ class ChatWidget {
4111
4221
  if (this.signalRClient) {
4112
4222
  await this.signalRClient.disconnect();
4113
4223
  }
4224
+ if (this.resizeObserver) {
4225
+ this.resizeObserver.disconnect();
4226
+ }
4114
4227
  this.container?.remove();
4115
4228
  }
4116
4229
  // Public method to add messages programmatically (for SignalR integration)