@envive-ai/react-widgets-v3 0.3.38 → 0.3.40

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.
Files changed (82) hide show
  1. package/dist/CXIntegration/implementations/useFreshChatUnifiedCXButton.cjs +76 -0
  2. package/dist/CXIntegration/implementations/useFreshChatUnifiedCXButton.js +75 -0
  3. package/dist/CXIntegration/implementations/useHelpScoutUnifiedCXButton.cjs +110 -25
  4. package/dist/CXIntegration/implementations/useHelpScoutUnifiedCXButton.js +110 -25
  5. package/dist/CXIntegration/implementations/useTalkdeskUnifiedCXButton.cjs +12 -6
  6. package/dist/CXIntegration/implementations/useTalkdeskUnifiedCXButton.js +12 -6
  7. package/dist/CXIntegration/types.cjs +1 -0
  8. package/dist/CXIntegration/types.js +1 -0
  9. package/dist/CXIntegration/utils/functions.cjs +2 -0
  10. package/dist/CXIntegration/utils/functions.js +2 -0
  11. package/dist/debug/chatEmbed.cjs +1 -1
  12. package/dist/debug/chatEmbed.js +1 -1
  13. package/dist/debug/reportIssue.cjs +1 -1
  14. package/dist/debug/reportIssue.js +1 -1
  15. package/dist/hocs/withBaseWidget/withBaseWidget.d.cts +2 -2
  16. package/dist/hocs/withBaseWidget/withBaseWidget.d.ts +2 -2
  17. package/dist/packages/widgets/dist/SearchResults/SearchResults.d.ts +2 -2
  18. package/dist/packages/widgets/dist/SearchResults/SearchResultsWidget.d.ts +2 -2
  19. package/dist/packages/widgets/dist/SearchZeroState/SearchZeroStateWidget.d.ts +2 -2
  20. package/dist/packages/widgets/dist/SuggestionBar/SuggestionBar.d.ts +2 -2
  21. package/dist/widgets/ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.cjs +6 -6
  22. package/dist/widgets/ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.d.cts +3 -3
  23. package/dist/widgets/ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.d.ts +3 -3
  24. package/dist/widgets/ChatPreviewComparisonWidget/ChatPreviewComparisonWidget.js +6 -6
  25. package/dist/widgets/ChatPreviewLoadingWidget/ChatPreviewLoadingWidget.d.cts +3 -3
  26. package/dist/widgets/ChatPreviewLoadingWidget/ChatPreviewLoadingWidget.d.ts +3 -3
  27. package/dist/widgets/ChatPreviewWidget/ChatPreviewWidget.cjs +4 -4
  28. package/dist/widgets/ChatPreviewWidget/ChatPreviewWidget.d.cts +3 -3
  29. package/dist/widgets/ChatPreviewWidget/ChatPreviewWidget.d.ts +3 -3
  30. package/dist/widgets/ChatPreviewWidget/ChatPreviewWidget.js +4 -4
  31. package/dist/widgets/FloatingChatWidget/FloatingChatOverlay.cjs +3 -0
  32. package/dist/widgets/FloatingChatWidget/FloatingChatOverlay.js +3 -0
  33. package/dist/widgets/FloatingChatWidget/FloatingChatWidget.cjs +3 -3
  34. package/dist/widgets/FloatingChatWidget/FloatingChatWidget.d.cts +2 -2
  35. package/dist/widgets/FloatingChatWidget/FloatingChatWidget.d.ts +2 -2
  36. package/dist/widgets/FloatingChatWidget/FloatingChatWidget.js +3 -3
  37. package/dist/widgets/FloatingChatWidget/hooks/useAutoPopup.cjs +1 -1
  38. package/dist/widgets/FloatingChatWidget/hooks/useAutoPopup.js +1 -1
  39. package/dist/widgets/FullPageSalesAgentWidget/FullPageSalesAgentWidget.d.cts +2 -2
  40. package/dist/widgets/FullPageSalesAgentWidget/FullPageSalesAgentWidget.d.ts +2 -2
  41. package/dist/widgets/ProductCardWidget/ProductCardWidget.cjs +3 -3
  42. package/dist/widgets/ProductCardWidget/ProductCardWidget.d.cts +2 -2
  43. package/dist/widgets/ProductCardWidget/ProductCardWidget.d.ts +2 -2
  44. package/dist/widgets/ProductCardWidget/ProductCardWidget.js +3 -3
  45. package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.cjs +5 -5
  46. package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.d.cts +3 -3
  47. package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.d.ts +3 -3
  48. package/dist/widgets/PromptButtonCarouselWithImageWidget/PromptButtonCarouselWithImageWidget.js +5 -5
  49. package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.cjs +3 -3
  50. package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.d.cts +2 -2
  51. package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.d.ts +2 -2
  52. package/dist/widgets/PromptCarouselWidget/PromptCarouselWidget.js +3 -3
  53. package/dist/widgets/SocialProofFlowWidget/SocialProofFlowWidget.d.ts +2 -2
  54. package/dist/widgets/SocialProofWidget/SocialProofWidget.cjs +6 -6
  55. package/dist/widgets/SocialProofWidget/SocialProofWidget.d.cts +3 -3
  56. package/dist/widgets/SocialProofWidget/SocialProofWidget.d.ts +3 -3
  57. package/dist/widgets/SocialProofWidget/SocialProofWidget.js +6 -6
  58. package/dist/widgets/TitledPromptCarouselWidget/TitledPromptCarouselWidget.cjs +2 -2
  59. package/dist/widgets/TitledPromptCarouselWidget/TitledPromptCarouselWidget.d.cts +2 -2
  60. package/dist/widgets/TitledPromptCarouselWidget/TitledPromptCarouselWidget.d.ts +2 -2
  61. package/dist/widgets/TitledPromptCarouselWidget/TitledPromptCarouselWidget.js +2 -2
  62. package/dist/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.d.cts +2 -2
  63. package/dist/widgets/TypingAnimationFlowWidget/TypingAnimationFlowWidget.d.ts +2 -2
  64. package/dist/widgets/TypingAnimationWidget/TypingAnimationWidget.cjs +3 -3
  65. package/dist/widgets/TypingAnimationWidget/TypingAnimationWidget.d.cts +3 -3
  66. package/dist/widgets/TypingAnimationWidget/TypingAnimationWidget.d.ts +3 -3
  67. package/dist/widgets/TypingAnimationWidget/TypingAnimationWidget.js +3 -3
  68. package/dist/widgets/dist/SearchResults/SearchResults.d.cts +2 -2
  69. package/dist/widgets/dist/SearchResults/SearchResultsWidget.d.cts +2 -2
  70. package/dist/widgets/dist/SearchZeroState/SearchZeroStateWidget.d.cts +2 -2
  71. package/dist/widgets/dist/SuggestionBar/SuggestionBar.d.cts +2 -2
  72. package/dist/widgets/hooks/useGetWidgetStatus.cjs +1 -1
  73. package/dist/widgets/hooks/useGetWidgetStatus.js +1 -1
  74. package/dist/widgets/utils/functions.cjs +1 -1
  75. package/dist/widgets/utils/functions.js +1 -1
  76. package/package.json +1 -1
  77. package/src/CXIntegration/implementations/useFreshChatUnifiedCXButton.ts +132 -0
  78. package/src/CXIntegration/implementations/useHelpScoutUnifiedCXButton.ts +184 -54
  79. package/src/CXIntegration/implementations/useTalkdeskUnifiedCXButton.ts +12 -5
  80. package/src/CXIntegration/types.ts +1 -0
  81. package/src/CXIntegration/utils/functions.ts +4 -0
  82. package/src/widgets/FloatingChatWidget/FloatingChatOverlay.tsx +3 -0
@@ -1,102 +1,232 @@
1
1
  import { SelectorFactory } from '@envive-ai/react-hooks/application/utils';
2
2
  import { useElementObserver } from '@envive-ai/react-hooks/hooks/ElementObserver';
3
+ import { useEffect, useRef } from 'react';
3
4
  import { FLOATING_BUTTON_ID } from '../../widgets/FloatingChatWidget/constants';
4
5
  import { CustomerServiceImplProps, UnifiedCXButton } from '../types';
5
6
 
6
7
  const BEACON_CONTAINER_ID = 'beacon-container';
8
+ const FAB_BUTTON_SELECTOR = '.BeaconFabButtonFrame';
9
+ const BEACON_WIDGET_SELECTOR = '.BeaconContainer';
10
+ // HelpScout's container may render the widget either as a styled `.BeaconContainer` or
11
+ // (e.g. in the "Instant Answers" view) inside an iframe. We treat either as "open".
12
+ const BEACON_OPEN_CHILD_SELECTOR = '.BeaconContainer, iframe, [class*="Beacon"][class*="ontainer"]';
7
13
 
8
14
  interface UseHelpScoutUnifiedCXButtonProps extends CustomerServiceImplProps {}
9
15
 
16
+ type BeaconApi = (command: string, ...args: unknown[]) => void;
17
+
18
+ const getBeaconApi = (): BeaconApi | undefined => {
19
+ const beacon = (window as unknown as { Beacon?: BeaconApi }).Beacon;
20
+ return typeof beacon === 'function' ? beacon : undefined;
21
+ };
22
+
23
+ const getBeaconContainer = (): HTMLElement | null => document.getElementById(BEACON_CONTAINER_ID);
24
+
25
+ const getFabButton = (): HTMLElement | null => {
26
+ return (getBeaconContainer()?.querySelector(FAB_BUTTON_SELECTOR) as HTMLElement) ?? null;
27
+ };
28
+
29
+ const getFloatingButtonEl = (): HTMLElement | null => document.getElementById(FLOATING_BUTTON_ID);
30
+
31
+ /**
32
+ * Detects whether the HelpScout beacon is currently visible/open.
33
+ * We use multiple signals because HelpScout has different "views"
34
+ * (chat, instant answers) that may use different class names.
35
+ */
36
+ const isBeaconCurrentlyOpen = (): boolean => {
37
+ const container = getBeaconContainer();
38
+ if (!container) return false;
39
+
40
+ // Signal 1: a `.BeaconContainer` exists with an enter-* class
41
+ const beaconWidget = container.querySelector(BEACON_WIDGET_SELECTOR);
42
+ if (beaconWidget) {
43
+ const cl = beaconWidget.classList;
44
+ if (
45
+ cl.contains('BeaconContainer-enter-done') ||
46
+ cl.contains('BeaconContainer-enter-active') ||
47
+ cl.contains('BeaconContainer-enter')
48
+ ) {
49
+ return true;
50
+ }
51
+ if (
52
+ cl.contains('BeaconContainer-exit') ||
53
+ cl.contains('BeaconContainer-exit-active') ||
54
+ cl.contains('BeaconContainer-exit-done')
55
+ ) {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ // Signal 2: any non-FAB visible child in the container means the panel is rendered
61
+ const children = Array.from(container.children);
62
+ return children.some(child => {
63
+ if (child.matches(FAB_BUTTON_SELECTOR)) return false;
64
+ const rect = (child as HTMLElement).getBoundingClientRect();
65
+ return rect.width > 50 && rect.height > 50;
66
+ });
67
+ };
68
+
69
+ /**
70
+ * Force-hides the Envive floating button via direct DOM manipulation. This is a
71
+ * safety net for cases where React state alone doesn't unmount the element fast
72
+ * enough (or at all), so we never get a flash of the floating button on top of
73
+ * the merchant's CX UI.
74
+ */
75
+ const forceHideFloatingButton = () => {
76
+ const el = getFloatingButtonEl();
77
+ if (el) el.style.display = 'none';
78
+ };
79
+
80
+ /**
81
+ * Restores the Envive floating button display, letting React's render logic take
82
+ * over again.
83
+ */
84
+ const forceShowFloatingButton = () => {
85
+ const el = getFloatingButtonEl();
86
+ if (el && el.style.display === 'none') el.style.display = '';
87
+ };
88
+
10
89
  export const useHelpScoutUnifiedCXButton = ({
11
90
  onSwitchToAgent,
91
+ onCXClose,
12
92
  suppressMerchantButton,
13
93
  }: UseHelpScoutUnifiedCXButtonProps): UnifiedCXButton => {
14
94
  const beaconContainer = useElementObserver(SelectorFactory.id(BEACON_CONTAINER_ID));
15
95
  const enviveFloatingButton = useElementObserver(SelectorFactory.id(FLOATING_BUTTON_ID));
16
96
 
97
+ // Track previous open state so we only fire onCXClose on a real open→closed
98
+ // transition, not on initial render or during the open animation.
99
+ const wasOpenRef = useRef(false);
100
+
101
+ // Keep latest callbacks/flags in refs so the Beacon API effect can read them
102
+ // without re-binding listeners on every render.
103
+ const onCXCloseRef = useRef(onCXClose);
104
+ const suppressMerchantButtonRef = useRef(suppressMerchantButton);
105
+ useEffect(() => {
106
+ onCXCloseRef.current = onCXClose;
107
+ suppressMerchantButtonRef.current = suppressMerchantButton;
108
+ }, [onCXClose, suppressMerchantButton]);
109
+
110
+ const handleBeaconOpened = () => {
111
+ wasOpenRef.current = true;
112
+ // Always force-hide the Envive floating button when the merchant CX opens.
113
+ // This is the safety net regardless of suppressMerchantButton.
114
+ forceHideFloatingButton();
115
+ if (suppressMerchantButtonRef.current) {
116
+ const fabButton = getFabButton();
117
+ if (fabButton) fabButton.style.display = '';
118
+ enviveFloatingButton.hide();
119
+ }
120
+ };
121
+
122
+ const handleBeaconClosed = () => {
123
+ if (!wasOpenRef.current) return;
124
+ wasOpenRef.current = false;
125
+ onCXCloseRef.current?.();
126
+ forceShowFloatingButton();
127
+ if (suppressMerchantButtonRef.current) {
128
+ const fabButton = getFabButton();
129
+ if (fabButton) fabButton.style.display = 'none';
130
+ enviveFloatingButton.show();
131
+ }
132
+ };
133
+
17
134
  const toggle = () => {
18
135
  onSwitchToAgent();
136
+ // Force hide BEFORE opening HelpScout so there's no flash of the floating
137
+ // button next to the merchant's CX panel.
138
+ wasOpenRef.current = true;
139
+ forceHideFloatingButton();
140
+ if (suppressMerchantButton) {
141
+ enviveFloatingButton.hide();
142
+ }
19
143
 
20
- // Try using the Help Scout Beacon API first
21
- if (typeof (window as any).Beacon !== 'undefined') {
22
- (window as any).Beacon('open');
144
+ const beacon = getBeaconApi();
145
+ if (beacon) {
146
+ beacon('open');
23
147
  } else {
24
- // Fallback: Find and click the FAB button
25
- const container = document.getElementById(BEACON_CONTAINER_ID);
26
- const fabButton = container?.querySelector('.BeaconFabButtonFrame') as HTMLElement;
148
+ // Fallback: find and click the FAB button
149
+ const fabButton = getFabButton();
27
150
  if (fabButton) {
28
151
  fabButton.style.display = '';
29
152
  fabButton.click();
30
153
  }
31
154
  }
32
-
33
- if (suppressMerchantButton) {
34
- enviveFloatingButton.hide();
35
- }
36
155
  };
37
156
 
38
157
  const isHelpScoutButtonEnabled = () => {
39
- // Check for the main Help Scout Beacon container
40
- const beaconContainerEl = document.getElementById('beacon-container');
158
+ const beaconContainerEl = getBeaconContainer();
41
159
  if (!beaconContainerEl) return false;
42
-
43
- // Check for the FAB button (Floating Action Button) or the global Beacon API
44
- const fabButton = beaconContainerEl.querySelector('.BeaconFabButtonFrame');
45
- const hasBeaconAPI = typeof (window as any).Beacon !== 'undefined';
46
-
160
+ const fabButton = beaconContainerEl.querySelector(FAB_BUTTON_SELECTOR);
161
+ const hasBeaconAPI = !!getBeaconApi();
47
162
  return !!(fabButton || hasBeaconAPI);
48
163
  };
49
164
 
50
165
  const isSwitchEnabled = () => isHelpScoutButtonEnabled();
51
166
 
52
- // Hide Help Scout FAB button when beacon container is added
167
+ // Use the official HelpScout Beacon API events for the most reliable open/close
168
+ // detection. We use empty deps + refs so this binds exactly once per mount, not
169
+ // every render — important because the Beacon listener registry doesn't dedupe.
170
+ useEffect(() => {
171
+ const beacon = getBeaconApi();
172
+ if (!beacon) return undefined;
173
+
174
+ try {
175
+ beacon('on', 'open', handleBeaconOpened);
176
+ beacon('on', 'close', handleBeaconClosed);
177
+ } catch {
178
+ // Beacon may not be initialized yet — the MutationObserver fallback will
179
+ // still detect the open/close transitions below.
180
+ }
181
+
182
+ return () => {
183
+ try {
184
+ beacon('off', 'open', handleBeaconOpened);
185
+ beacon('off', 'close', handleBeaconClosed);
186
+ } catch {
187
+ // ignore — beacon may already be torn down
188
+ }
189
+ };
190
+ // eslint-disable-next-line react-hooks/exhaustive-deps
191
+ }, []);
192
+
193
+ // Hide the merchant's FAB button when the beacon container is added. Do NOT
194
+ // blindly re-show the Envive floating button here — if `Beacon('open')` creates
195
+ // the container in response to a "live support" click, this would un-hide the
196
+ // floating button the user just hid via toggle().
53
197
  beaconContainer.onAdd(() => {
54
198
  if (suppressMerchantButton) {
55
- const fabButton = document
56
- .getElementById(BEACON_CONTAINER_ID)
57
- ?.querySelector('.BeaconFabButtonFrame') as HTMLElement;
58
- if (fabButton) {
59
- fabButton.style.display = 'none';
60
- }
199
+ const fabButton = getFabButton();
200
+ if (fabButton) fabButton.style.display = 'none';
201
+ }
202
+ // If the beacon happens to mount in an already-open state, treat it like a
203
+ // proper open transition so the floating button is hidden.
204
+ if (isBeaconCurrentlyOpen()) {
205
+ handleBeaconOpened();
206
+ } else if (suppressMerchantButton) {
61
207
  enviveFloatingButton.show();
62
208
  }
63
209
  });
64
210
 
65
- // Observe the beacon container for visibility changes
66
- // Help Scout Beacon adds/removes classes to show/hide the widget
211
+ // MutationObserver fallback for cases where the Beacon API events don't fire
212
+ // (older Beacon versions, opened via direct DOM manipulation, etc.). The logic
213
+ // here is broader than just checking enter/exit classes because the "Instant
214
+ // Answers" view can use different DOM markers.
67
215
  beaconContainer.onChange(el => {
68
- if (el && suppressMerchantButton) {
69
- // Check if the BeaconContainer widget is open
70
- const beaconWidget = el.querySelector('.BeaconContainer');
71
- const fabButton = el.querySelector('.BeaconFabButtonFrame') as HTMLElement;
72
-
73
- if (beaconWidget && fabButton) {
74
- const { classList } = beaconWidget;
75
-
76
- // When beacon is open (has enter-done class)
77
- if (
78
- classList.contains('BeaconContainer-enter-done') ||
79
- classList.contains('BeaconContainer-enter-active')
80
- ) {
81
- fabButton.style.display = '';
82
- enviveFloatingButton.hide();
83
- }
84
-
85
- // When beacon is closed (has exit class)
86
- if (
87
- classList.contains('BeaconContainer-exit') ||
88
- classList.contains('BeaconContainer-exit-active')
89
- ) {
90
- fabButton.style.display = 'none';
91
- enviveFloatingButton.show();
92
- }
93
- }
216
+ if (!el) return;
217
+ const open = isBeaconCurrentlyOpen();
218
+ if (open && !wasOpenRef.current) {
219
+ handleBeaconOpened();
220
+ } else if (!open && wasOpenRef.current) {
221
+ handleBeaconClosed();
94
222
  }
95
223
  });
96
224
 
97
- // Cleanup when container is removed
225
+ // Cleanup when the entire container is removed.
98
226
  beaconContainer.onRemove(() => {
99
- if (suppressMerchantButton) {
227
+ if (wasOpenRef.current) {
228
+ handleBeaconClosed();
229
+ } else if (suppressMerchantButton) {
100
230
  enviveFloatingButton.show();
101
231
  }
102
232
  });
@@ -7,6 +7,7 @@ interface UseTalkdeskUnifiedCXButtonProps extends CustomerServiceImplProps {}
7
7
 
8
8
  export const useTalkdeskUnifiedCXButton = ({
9
9
  onSwitchToAgent,
10
+ onCXClose,
10
11
  suppressMerchantButton,
11
12
  }: UseTalkdeskUnifiedCXButtonProps): UnifiedCXButton => {
12
13
  const talkdeskButton = useElementObserver(SelectorFactory.id('talkdesk-chat-widget-trigger'));
@@ -62,25 +63,31 @@ export const useTalkdeskUnifiedCXButton = ({
62
63
 
63
64
  // Track widget visibility changes
64
65
  talkdeskWidget.onChange(el => {
65
- if (el && suppressMerchantButton) {
66
+ if (el) {
66
67
  const ariaHidden = el.getAttribute('aria-hidden');
67
68
 
68
69
  // Widget is open (aria-hidden="false")
69
70
  if (ariaHidden === 'false') {
70
- talkdeskButton.show();
71
- enviveFloatingButton.hide();
71
+ if (suppressMerchantButton) {
72
+ talkdeskButton.show();
73
+ enviveFloatingButton.hide();
74
+ }
72
75
  }
73
76
 
74
77
  // Widget is closed (aria-hidden="true")
75
78
  if (ariaHidden === 'true') {
76
- talkdeskButton.hide();
77
- enviveFloatingButton.show();
79
+ onCXClose?.();
80
+ if (suppressMerchantButton) {
81
+ talkdeskButton.hide();
82
+ enviveFloatingButton.show();
83
+ }
78
84
  }
79
85
  }
80
86
  });
81
87
 
82
88
  // Cleanup when container is removed
83
89
  talkdeskContainer.onRemove(() => {
90
+ onCXClose?.();
84
91
  if (suppressMerchantButton) {
85
92
  talkdeskButton.hide();
86
93
  enviveFloatingButton.show();
@@ -12,6 +12,7 @@ export enum CustomerServiceType {
12
12
  helpscout = 'helpscout',
13
13
  talkdesk = 'talkdesk',
14
14
  eightByEight = '8x8',
15
+ freshchat = 'freshchat',
15
16
  unsupported = 'unsupported',
16
17
  }
17
18
 
@@ -13,6 +13,7 @@ import { useKustomerUnifiedCXButton } from '../implementations/useKustomerUnifie
13
13
  import { useHelpScoutUnifiedCXButton } from '../implementations/useHelpScoutUnifiedCXButton';
14
14
  import { useTalkdeskUnifiedCXButton } from '../implementations/useTalkdeskUnifiedCXButton';
15
15
  import { useEightByEightUnifiedCXButton } from '../implementations/useEightByEightUnifiedCXButton';
16
+ import { useFreshChatUnifiedCXButton } from '../implementations/useFreshChatUnifiedCXButton';
16
17
  import { useDefaultUnifiedCXButton } from '../implementations/useDefaultUnifiedCXButton';
17
18
 
18
19
  export const findCustomerServiceImpl = (
@@ -57,6 +58,9 @@ export const findCustomerServiceImpl = (
57
58
  if (provider === CustomerServiceType.eightByEight) {
58
59
  return useEightByEightUnifiedCXButton;
59
60
  }
61
+ if (provider === CustomerServiceType.freshchat) {
62
+ return useFreshChatUnifiedCXButton;
63
+ }
60
64
 
61
65
  return useDefaultUnifiedCXButton;
62
66
  };
@@ -137,6 +137,9 @@ export const FloatingChatOverlay = ({
137
137
  }}
138
138
  className="envive-tw-shadow-md"
139
139
  onClick={e => e.stopPropagation()}
140
+ role="dialog"
141
+ aria-modal="true"
142
+ aria-label="Envive Chat Window"
140
143
  >
141
144
  {children}
142
145
  </motion.div>