andy-widget-react 2.2.0 → 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.
package/README.md CHANGED
@@ -8,7 +8,7 @@ The official React Widget for Andy. Its canonical source is
8
8
  Pin an exact reviewed release:
9
9
 
10
10
  ```bash
11
- bun add andy-widget-react@2.0.5
11
+ bun add andy-widget-react@2.2.1
12
12
  ```
13
13
 
14
14
  React and React DOM 18 or 19 are required peer dependencies.
package/dist/index.cjs CHANGED
@@ -1497,9 +1497,6 @@ const generateDesignTokenVariablesString = () => {
1497
1497
  --andy-chat-avatar-size: 32px;
1498
1498
  --andy-chat-avatar-size-small: 24px;
1499
1499
 
1500
- /* Keyboard handling */
1501
- --andy-keyboard-height: 0px;
1502
-
1503
1500
  /* === THEMABLE VARIABLES (Default Light Theme) === */
1504
1501
  --andy-themable-background: var(--andy-color-background);
1505
1502
  --andy-themable-background-secondary: var(--andy-color-white);
@@ -2883,11 +2880,6 @@ const getCoreStructuralCssString = () => {
2883
2880
  }
2884
2881
  }
2885
2882
 
2886
- /* No special handling for keyboard - let browser handle it naturally */
2887
- .andy-chat-window--keyboard-open {
2888
- /* Browser handles positioning automatically with our margin-based approach */
2889
- }
2890
-
2891
2883
  /* Ensure the window content is properly laid out */
2892
2884
  .andy-chat-window__messages {
2893
2885
  flex: 1 1 auto;
@@ -3005,17 +2997,12 @@ const getCoreStructuralCssString = () => {
3005
2997
  }
3006
2998
  }
3007
2999
 
3008
- /* Desktop keyboard handling (for testing) */
3000
+ /* Desktop */
3009
3001
  @media (min-width: 521px) {
3010
3002
  /* Desktop retains original positioning behavior */
3011
3003
  .andy-chat-window {
3012
3004
  transition: transform 0.3s ease-out;
3013
3005
  }
3014
-
3015
- /* Optional: Add keyboard handling for desktop if needed */
3016
- .andy-chat-window--keyboard-open {
3017
- /* No transform on desktop - keyboard doesn't affect viewport */
3018
- }
3019
3006
  }
3020
3007
 
3021
3008
  /* Orientation */
@@ -3507,244 +3494,6 @@ const UI_STRINGS = {
3507
3494
  */
3508
3495
  const getUiStrings = lang => UI_STRINGS[lang] || UI_STRINGS.en;
3509
3496
 
3510
- /**
3511
- * Keyboard detection utility for handling mobile virtual keyboards
3512
- * Provides cross-browser support for detecting keyboard open/close events
3513
- */
3514
-
3515
- class KeyboardDetector {
3516
- constructor() {
3517
- this.isKeyboardOpen = false;
3518
- this.keyboardHeight = 0;
3519
- this.listeners = new Set();
3520
- this.inputElement = null;
3521
- this.viewportHeight = window.innerHeight;
3522
- this.visualViewport = window.visualViewport;
3523
-
3524
- this.initializeDetection();
3525
- }
3526
-
3527
- /**
3528
- * Initialize keyboard detection
3529
- */
3530
- initializeDetection() {
3531
- // Use Visual Viewport API if available (most modern browsers)
3532
- if (this.visualViewport) {
3533
- this.visualViewport.addEventListener('resize', this.handleViewportResize.bind(this));
3534
- this.visualViewport.addEventListener('scroll', this.handleViewportScroll.bind(this));
3535
- } else {
3536
- // Fallback for older browsers
3537
- window.addEventListener('resize', this.handleWindowResize.bind(this));
3538
- }
3539
-
3540
- // Additional detection via focus/blur events
3541
- document.addEventListener('focusin', this.handleFocusIn.bind(this), true);
3542
- document.addEventListener('focusout', this.handleFocusOut.bind(this), true);
3543
-
3544
- // Orientation change handler
3545
- window.addEventListener('orientationchange', this.handleOrientationChange.bind(this));
3546
- }
3547
-
3548
- /**
3549
- * Handle visual viewport resize (modern browsers)
3550
- */
3551
- handleViewportResize() {
3552
- const currentHeight = this.visualViewport.height;
3553
- const heightDifference = window.innerHeight - currentHeight;
3554
-
3555
- // If viewport shrunk by more than 100px, keyboard is likely open
3556
- if (heightDifference > 100) {
3557
- this.setKeyboardOpen(true, heightDifference);
3558
- } else if (heightDifference < 50) {
3559
- this.setKeyboardOpen(false, 0);
3560
- }
3561
- }
3562
-
3563
- /**
3564
- * Handle visual viewport scroll
3565
- */
3566
- handleViewportScroll() {
3567
- // On iOS, viewport scrolls when keyboard opens
3568
- if (this.visualViewport.offsetTop > 0) {
3569
- this.setKeyboardOpen(true, this.visualViewport.offsetTop);
3570
- }
3571
- }
3572
-
3573
- /**
3574
- * Handle window resize (fallback for older browsers)
3575
- */
3576
- handleWindowResize() {
3577
- const currentHeight = window.innerHeight;
3578
- const heightDifference = this.viewportHeight - currentHeight;
3579
-
3580
- // Significant height reduction likely means keyboard opened
3581
- if (heightDifference > 100) {
3582
- this.setKeyboardOpen(true, heightDifference);
3583
- } else if (Math.abs(heightDifference) < 50) {
3584
- this.setKeyboardOpen(false, 0);
3585
- this.viewportHeight = currentHeight;
3586
- }
3587
- }
3588
-
3589
- /**
3590
- * Handle input focus
3591
- */
3592
- handleFocusIn(e) {
3593
- const isInput = ['input', 'textarea'].includes(e.target.tagName.toLowerCase());
3594
- if (isInput) {
3595
- this.inputElement = e.target;
3596
- // Delay to allow keyboard animation
3597
- setTimeout(() => {
3598
- if (this.inputElement === e.target) {
3599
- this.checkKeyboardStatus();
3600
- }
3601
- }, 300);
3602
- }
3603
- }
3604
-
3605
- /**
3606
- * Handle input blur
3607
- */
3608
- handleFocusOut(e) {
3609
- const isInput = ['input', 'textarea'].includes(e.target.tagName.toLowerCase());
3610
- if (isInput && this.inputElement === e.target) {
3611
- this.inputElement = null;
3612
- // Delay to allow keyboard animation
3613
- setTimeout(() => {
3614
- if (!this.inputElement) {
3615
- this.setKeyboardOpen(false, 0);
3616
- }
3617
- }, 300);
3618
- }
3619
- }
3620
-
3621
- /**
3622
- * Handle orientation change
3623
- */
3624
- handleOrientationChange() {
3625
- // Reset viewport height after orientation change
3626
- setTimeout(() => {
3627
- this.viewportHeight = window.innerHeight;
3628
- this.checkKeyboardStatus();
3629
- }, 500);
3630
- }
3631
-
3632
- /**
3633
- * Check keyboard status (for browsers without Visual Viewport API)
3634
- */
3635
- checkKeyboardStatus() {
3636
- if (!this.visualViewport) {
3637
- const currentHeight = window.innerHeight;
3638
- const heightDifference = this.viewportHeight - currentHeight;
3639
-
3640
- if (this.inputElement && heightDifference > 100) {
3641
- this.setKeyboardOpen(true, heightDifference);
3642
- }
3643
- }
3644
- }
3645
-
3646
- /**
3647
- * Set keyboard state and notify listeners
3648
- */
3649
- setKeyboardOpen(isOpen, height) {
3650
- const changed = this.isKeyboardOpen !== isOpen || this.keyboardHeight !== height;
3651
-
3652
- this.isKeyboardOpen = isOpen;
3653
- this.keyboardHeight = height;
3654
-
3655
- if (changed) {
3656
- this.notifyListeners();
3657
- }
3658
- }
3659
-
3660
- /**
3661
- * Add listener for keyboard state changes
3662
- */
3663
- addListener(callback) {
3664
- this.listeners.add(callback);
3665
- // Immediately notify with current state
3666
- callback({
3667
- isOpen: this.isKeyboardOpen,
3668
- height: this.keyboardHeight
3669
- });
3670
- }
3671
-
3672
- /**
3673
- * Remove listener
3674
- */
3675
- removeListener(callback) {
3676
- this.listeners.delete(callback);
3677
- }
3678
-
3679
- /**
3680
- * Notify all listeners of state change
3681
- */
3682
- notifyListeners() {
3683
- const state = {
3684
- isOpen: this.isKeyboardOpen,
3685
- height: this.keyboardHeight
3686
- };
3687
-
3688
- this.listeners.forEach(callback => {
3689
- try {
3690
- callback(state);
3691
- } catch (error) {
3692
- console.error('Error in keyboard detector listener:', error);
3693
- }
3694
- });
3695
- }
3696
-
3697
- /**
3698
- * Get current keyboard state
3699
- */
3700
- getState() {
3701
- return {
3702
- isOpen: this.isKeyboardOpen,
3703
- height: this.keyboardHeight
3704
- }
3705
- }
3706
-
3707
- /**
3708
- * Cleanup
3709
- */
3710
- destroy() {
3711
- if (this.visualViewport) {
3712
- this.visualViewport.removeEventListener('resize', this.handleViewportResize.bind(this));
3713
- this.visualViewport.removeEventListener('scroll', this.handleViewportScroll.bind(this));
3714
- } else {
3715
- window.removeEventListener('resize', this.handleWindowResize.bind(this));
3716
- }
3717
-
3718
- document.removeEventListener('focusin', this.handleFocusIn.bind(this), true);
3719
- document.removeEventListener('focusout', this.handleFocusOut.bind(this), true);
3720
- window.removeEventListener('orientationchange', this.handleOrientationChange.bind(this));
3721
-
3722
- this.listeners.clear();
3723
- }
3724
- }
3725
-
3726
- // Create singleton instance
3727
- let keyboardDetectorInstance = null;
3728
-
3729
- /**
3730
- * Get or create keyboard detector instance
3731
- */
3732
- function getKeyboardDetector() {
3733
- if (!keyboardDetectorInstance) {
3734
- keyboardDetectorInstance = new KeyboardDetector();
3735
- }
3736
- return keyboardDetectorInstance
3737
- }
3738
-
3739
- /**
3740
- * Update CSS custom property on host element
3741
- */
3742
- function updateKeyboardHeight(hostElement, height) {
3743
- if (hostElement) {
3744
- hostElement.style.setProperty('--andy-keyboard-height', `${height}px`);
3745
- }
3746
- }
3747
-
3748
3497
  /**
3749
3498
  * Mobile detection utility for AndyChat
3750
3499
  * Provides reliable mobile device detection with multiple methods
@@ -4034,22 +3783,7 @@ const AndyChat = ({ embedId, tooltip, name, headline, description, welcomeMessag
4034
3783
  portalRef.current = portalTarget;
4035
3784
  }
4036
3785
  setShadowReady(true);
4037
- const keyboardDetector = getKeyboardDetector();
4038
- const keyboardListener = ({ isOpen: kbOpen, height }) => {
4039
- updateKeyboardHeight(containerRef.current, height);
4040
- const chatWindow = shadowRef.current?.querySelector('.andy-chat-window');
4041
- if (chatWindow) {
4042
- if (kbOpen && height > 0) {
4043
- chatWindow.classList.add('andy-chat-window--keyboard-open');
4044
- }
4045
- else {
4046
- chatWindow.classList.remove('andy-chat-window--keyboard-open');
4047
- }
4048
- }
4049
- };
4050
- keyboardDetector.addListener(keyboardListener);
4051
3786
  return () => {
4052
- keyboardDetector.removeListener(keyboardListener);
4053
3787
  shadowRef.current = null;
4054
3788
  portalRef.current = null;
4055
3789
  setShadowReady(false);