@microsoft/omnichannel-chat-widget 1.8.4-main.4478bbf → 1.8.4-main.6672d3a

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 (69) hide show
  1. package/README.md +27 -0
  2. package/lib/cjs/common/Constants.js +2 -0
  3. package/lib/cjs/common/telemetry/AppInsightsEvents.js +11 -5
  4. package/lib/cjs/common/telemetry/TelemetryConstants.js +3 -0
  5. package/lib/cjs/common/telemetry/TelemetryManager.js +10 -7
  6. package/lib/cjs/components/citationpanestateful/CitationPaneStateful.js +20 -1
  7. package/lib/cjs/components/livechatwidget/common/ChatWidgetEvents.js +1 -1
  8. package/lib/cjs/components/livechatwidget/common/PersistentConversationHandler.js +26 -20
  9. package/lib/cjs/components/livechatwidget/common/defaultProps/defaultPersistentChatHistoryProps.js +1 -2
  10. package/lib/cjs/components/livechatwidget/common/endChat.js +21 -9
  11. package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +9 -2
  12. package/lib/cjs/components/livechatwidget/common/registerTelemetryLoggers.js +3 -0
  13. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +112 -26
  14. package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +2 -2
  15. package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +9 -12
  16. package/lib/cjs/components/webchatcontainerstateful/common/activityConverters/convertPersistentChatHistoryMessageToActivity.js +8 -2
  17. package/lib/cjs/components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts.js +2 -1
  18. package/lib/cjs/components/webchatcontainerstateful/hooks/usePersistentChatHistory.js +1 -3
  19. package/lib/cjs/components/webchatcontainerstateful/interfaces/IExtendedChatConffig.js +1 -0
  20. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.js +6 -7
  21. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/ConversationDividerActivity.js +30 -1
  22. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.js +21 -1
  23. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +7 -2
  24. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/citationsMiddleware.js +6 -1
  25. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/localizedStringsBotInitialsMiddleware.js +29 -7
  26. package/lib/cjs/contexts/common/LiveChatWidgetActionType.js +1 -0
  27. package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +7 -1
  28. package/lib/cjs/contexts/createReducer.js +15 -0
  29. package/lib/esm/common/Constants.js +2 -0
  30. package/lib/esm/common/telemetry/AppInsightsEvents.js +11 -5
  31. package/lib/esm/common/telemetry/TelemetryConstants.js +3 -0
  32. package/lib/esm/common/telemetry/TelemetryManager.js +10 -7
  33. package/lib/esm/components/citationpanestateful/CitationPaneStateful.js +20 -1
  34. package/lib/esm/components/livechatwidget/common/ChatWidgetEvents.js +1 -1
  35. package/lib/esm/components/livechatwidget/common/PersistentConversationHandler.js +26 -20
  36. package/lib/esm/components/livechatwidget/common/defaultProps/defaultPersistentChatHistoryProps.js +1 -2
  37. package/lib/esm/components/livechatwidget/common/endChat.js +21 -9
  38. package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +9 -2
  39. package/lib/esm/components/livechatwidget/common/registerTelemetryLoggers.js +3 -0
  40. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +112 -26
  41. package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +2 -2
  42. package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +9 -15
  43. package/lib/esm/components/webchatcontainerstateful/common/activityConverters/convertPersistentChatHistoryMessageToActivity.js +8 -2
  44. package/lib/esm/components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts.js +2 -1
  45. package/lib/esm/components/webchatcontainerstateful/hooks/usePersistentChatHistory.js +1 -3
  46. package/lib/esm/components/webchatcontainerstateful/interfaces/IExtendedChatConffig.js +1 -0
  47. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.js +6 -7
  48. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/ConversationDividerActivity.js +30 -1
  49. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.js +21 -1
  50. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +7 -2
  51. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/citationsMiddleware.js +6 -1
  52. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/localizedStringsBotInitialsMiddleware.js +29 -7
  53. package/lib/esm/contexts/common/LiveChatWidgetActionType.js +1 -0
  54. package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +7 -1
  55. package/lib/esm/contexts/createReducer.js +15 -0
  56. package/lib/types/common/Constants.d.ts +2 -0
  57. package/lib/types/common/telemetry/TelemetryConstants.d.ts +3 -0
  58. package/lib/types/common/telemetry/interfaces/IInternalTelemetryData.d.ts +1 -0
  59. package/lib/types/components/livechatwidget/common/ChatWidgetEvents.d.ts +1 -1
  60. package/lib/types/components/livechatwidget/interfaces/IPersistentChatHistoryProps.d.ts +5 -1
  61. package/lib/types/components/webchatcontainerstateful/interfaces/IExtendedChatConffig.d.ts +15 -0
  62. package/lib/types/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.d.ts +1 -2
  63. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.d.ts +1 -1
  64. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.d.ts +2 -1
  65. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/localizedStringsBotInitialsMiddleware.d.ts +1 -1
  66. package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +1 -0
  67. package/lib/types/contexts/common/ILiveChatWidgetLocalizedTexts.d.ts +5 -0
  68. package/lib/types/contexts/common/LiveChatWidgetActionType.d.ts +2 -1
  69. package/package.json +1 -1
package/README.md CHANGED
@@ -268,6 +268,33 @@ const customizedFooterProp: IFooterProps = {
268
268
  setOnCustomEvent((event) => console.log(event));
269
269
  ```
270
270
 
271
+ #### Trigger initiateEndChat event
272
+ Customer can trigger the initiateEndChat event via BroadcastService to end a chat session.
273
+ When needed, the payload below could be triggered:
274
+ ```js
275
+ const endChatEvent = {
276
+ eventName: "InitiateEndChat",
277
+ payload: {
278
+ skipSessionCloseForPersistentChat: true
279
+ } //optional payload
280
+ };
281
+ BroadcastService.postMessage(endChatEvent);
282
+ ```
283
+
284
+ The payload of the event is optional, only needed when force closing of a persistent chat session is not required.
285
+ When chat widget receives the event without any payload, it will:
286
+ 1. set the widget to closed state, the widget panel will be minimized. Post chat survey will not be displayed.
287
+ 2. trigger a sessionclose service network request to OmniChannel services.
288
+
289
+ If skipSessionCloseForPersistentChat is set to true. The session close network request will not be triggered, instead, if postChat survey is available, post chat survey will be displayed.
290
+
291
+ After successfully processed initiateEndChat event. The CloseChat event is broadcasted.
292
+ ```js
293
+ BroadcastService.getMessageByEventName("CloseChat").subscribe(async (msg) => {
294
+ console.log("close chat received: ", msg);
295
+ //more actions to unmount component and resources
296
+ })
297
+ ```
271
298
  ## See Also
272
299
 
273
300
  [Customizations Dev Guide](https://github.com/microsoft/omnichannel-chat-widget/blob/main/docs/customizations/getstarted.md)\
@@ -143,6 +143,7 @@ _defineProperty(Constants, "customEventName", "customEventName");
143
143
  _defineProperty(Constants, "customEventValue", "customEventValue");
144
144
  _defineProperty(Constants, "Hidden", "Hidden");
145
145
  _defineProperty(Constants, "EndConversationDueToOverflow", "endconversationduetooverflow");
146
+ _defineProperty(Constants, "SkipSessionCloseForPersistentChatFlag", "skipSessionCloseForPersistentChat");
146
147
  const Regex = (_class = /*#__PURE__*/_createClass(function Regex() {
147
148
  _classCallCheck(this, Regex);
148
149
  }), _defineProperty(_class, "EmailRegex", "^(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)*|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\])$"), _class);
@@ -378,6 +379,7 @@ _defineProperty(PrepareEndChatDescriptionConstants, "ConversationEndedBy", "Conv
378
379
  _defineProperty(PrepareEndChatDescriptionConstants, "PrepareEndChatError", "There's an error while preparing to end chat. Closing chat widget.");
379
380
  _defineProperty(PrepareEndChatDescriptionConstants, "WidgetLoadFailedAfterSessionInit", "SessionInit was successful, but widget load failed. Ending chat to avoid ghost chats in OC.");
380
381
  _defineProperty(PrepareEndChatDescriptionConstants, "InitiateEndChatReceived", "Received InitiateEndChat BroadcastEvent while conversation state is not Active. Ending chat.");
382
+ _defineProperty(PrepareEndChatDescriptionConstants, "InitiateEndChatReceivedActiveChat", "Received InitiateEndChat BroadcastEvent while conversation state is Active. Updating conversation states.");
381
383
  _defineProperty(PrepareEndChatDescriptionConstants, "EndChatReceivedFromOtherTabs", "Received EndChat BroadcastEvent from other tabs. Closing this chat.");
382
384
  _defineProperty(PrepareEndChatDescriptionConstants, "CustomerCloseChatOnFailureOrPostChat", "Customer is trying to close chat widget on start chat failure or post chat pane.");
383
385
  _defineProperty(PrepareEndChatDescriptionConstants, "CustomerCloseInactiveChat", "Chat was Inactive and customer is trying to close chat widget or refreshing the page.");
@@ -6,8 +6,11 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.AppInsightsEventMapping = void 0;
7
7
  const AppInsightsEventMapping = {
8
8
  "LCWChatButtonClicked": "LCWChatButtonActionStarted",
9
- "PrechatSubmitted": "PrechatSubmitCompleted",
10
- "StartChatEventRecevied": "StartChatEventReceivedCompleted",
9
+ "UXLCWChatButtonLoadingStart": "LiveChatWidgetChatButtonLoadingStarted",
10
+ "UXLCWChatButtonLoadingCompleted": "LiveChatWidgetChatButtonLoadingCompleted",
11
+ "UXPrechatPaneStart": "PrechatSurveyStarted",
12
+ "UXPrechatPaneCompleted": "PrechatSurveyCompleted",
13
+ "PrechatSubmitted": "PrechatSurveySubmitCompleted",
11
14
  "EndChatEventReceived": "EndChatEventReceivedCompleted",
12
15
  "EmailTranscriptSent": "EmailTranscriptActionCompleted",
13
16
  "EmailTranscriptFailed": "EmailTranscriptActionFailed",
@@ -15,8 +18,6 @@ const AppInsightsEventMapping = {
15
18
  "HeaderMinimizeButtonClicked": "MinimizeChatActionStarted",
16
19
  "DownloadTranscriptButtonClicked": "DownloadTranscriptActionStarted",
17
20
  "EmailTranscriptButtonClicked": "EmailTranscriptButtonActionStarted",
18
- "CustomerVoiceFormResponseSubmitted": "CustomerVoiceFormResponseSubmitCompleted",
19
- "StartProactiveChatEventReceived": "StartProactiveChatEventReceivedCompleted",
20
21
  "ProactiveChatRejected": "ProactiveChatTimeOutCompleted",
21
22
  "MessageSent": "MessageSentCompleted",
22
23
  "MessageReceived": "MessageReceivedCompleted",
@@ -25,6 +26,11 @@ const AppInsightsEventMapping = {
25
26
  "CustomContextReceived": "CustomContextReceivedCompleted",
26
27
  "NewTokenValidationStarted": "AuthTokenValidationStarted",
27
28
  "NewTokenValidationCompleted": "AuthTokenValidationCompleted",
28
- "NewTokenValidationFailed": "AuthTokenValidationFailed"
29
+ "NewTokenValidationFailed": "AuthTokenValidationFailed",
30
+ "UXPostChatPaneStarted": "PostChatSurveyStarted",
31
+ "UXPostChatPaneCompleted": "PostChatSurveyCompleted",
32
+ "WidgetLoadStarted": "ChatSessionInitializationStarted",
33
+ "WidgetLoadComplete": "ChatSessionInitializationCompleted",
34
+ "WidgetLoadFailed": "ChatSessionInitializationFailed"
29
35
  };
30
36
  exports.AppInsightsEventMapping = AppInsightsEventMapping;
@@ -124,6 +124,7 @@ exports.TelemetryEvent = TelemetryEvent;
124
124
  TelemetryEvent["EndChatFailed"] = "EndChatFailed";
125
125
  TelemetryEvent["SettingCustomContext"] = "SettingCustomContext";
126
126
  TelemetryEvent["WebChatLoaded"] = "WebChatLoaded";
127
+ TelemetryEvent["PersistentChatHistoryEnabled"] = "PersistentChatHistoryEnabled";
127
128
  TelemetryEvent["LCWChatButtonActionCompleted"] = "LCWChatButtonActionCompleted";
128
129
  TelemetryEvent["LCWChatButtonClicked"] = "LCWChatButtonClicked";
129
130
  TelemetryEvent["LCWChatButtonShow"] = "LCWChatButtonShow";
@@ -305,6 +306,7 @@ exports.TelemetryEvent = TelemetryEvent;
305
306
  TelemetryEvent["LCWPersistentConversationHandlerInitialized"] = "LCWPersistentConversationHandlerInitialized";
306
307
  TelemetryEvent["LCWPersistentHistoryPullBlocked"] = "LCWPersistentHistoryPullBlocked";
307
308
  TelemetryEvent["LCWPersistentHistoryPullCompleted"] = "LCWPersistentHistoryPullCompleted";
309
+ TelemetryEvent["LCWPersistentHistoryReturnedNull"] = "LCWPersistentHistoryReturnedNull";
308
310
  TelemetryEvent["LCWLazyLoadInitializationStarted"] = "LCWLazyLoadInitializationStarted";
309
311
  TelemetryEvent["LCWLazyLoadContainerNotFound"] = "LCWLazyLoadContainerNotFound";
310
312
  TelemetryEvent["LCWLazyLoadInitializationCompleted"] = "LCWLazyLoadInitializationCompleted";
@@ -314,6 +316,7 @@ exports.TelemetryEvent = TelemetryEvent;
314
316
  TelemetryEvent["LCWLazyLoadActivityMounted"] = "LCWLazyLoadActivityMounted";
315
317
  TelemetryEvent["LCWLazyLoadReset"] = "LCWLazyLoadReset";
316
318
  TelemetryEvent["LCWLazyLoadNoMoreHistory"] = "LCWLazyLoadNoMoreHistory";
319
+ TelemetryEvent["LCWLazyLoadHistoryError"] = "LCWLazyLoadHistoryError";
317
320
  TelemetryEvent["LCWLazyLoadDestroyed"] = "LCWLazyLoadDestroyed";
318
321
  TelemetryEvent["SecureEventBusUnauthorizedDispatch"] = "SecureEventBusUnauthorizedDispatch";
319
322
  TelemetryEvent["SecureEventBusListenerError"] = "SecureEventBusListenerError";
@@ -50,7 +50,7 @@ const RegisterLoggers = () => {
50
50
  loggers.push((0, _consoleLogger.consoleLogger)());
51
51
  }
52
52
  if (((_TelemetryManager$Int9 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int9 === void 0 ? void 0 : (_TelemetryManager$Int10 = _TelemetryManager$Int9.telemetryConfig) === null || _TelemetryManager$Int10 === void 0 ? void 0 : _TelemetryManager$Int10.telemetryDisabled) === false) {
53
- var _TelemetryManager$Int11, _TelemetryManager$Int20, _TelemetryManager$Int21, _TelemetryManager$Int22, _TelemetryManager$Int23;
53
+ var _TelemetryManager$Int11, _TelemetryManager$Int20, _TelemetryManager$Int21, _TelemetryManager$Int22, _TelemetryManager$Int23, _TelemetryManager$Int24, _TelemetryManager$Int25, _TelemetryManager$Int26;
54
54
  if ((_TelemetryManager$Int11 = TelemetryManager.InternalTelemetryData) !== null && _TelemetryManager$Int11 !== void 0 && _TelemetryManager$Int11.ariaConfig) {
55
55
  var _TelemetryManager$Int12, _TelemetryManager$Int13, _TelemetryManager$Int14, _TelemetryManager$Int15, _TelemetryManager$Int16, _TelemetryManager$Int17, _TelemetryManager$Int18, _TelemetryManager$Int19;
56
56
  loggers.push((0, _ariaTelemetryLogger.ariaTelemetryLogger)(((_TelemetryManager$Int12 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int12 === void 0 ? void 0 : (_TelemetryManager$Int13 = _TelemetryManager$Int12.ariaConfig) === null || _TelemetryManager$Int13 === void 0 ? void 0 : _TelemetryManager$Int13.ariaTelemetryKey) ?? _defaultAriaConfig.defaultAriaConfig.ariaTelemetryKey, ((_TelemetryManager$Int14 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int14 === void 0 ? void 0 : (_TelemetryManager$Int15 = _TelemetryManager$Int14.ariaConfig) === null || _TelemetryManager$Int15 === void 0 ? void 0 : _TelemetryManager$Int15.disableCookieUsage) ?? _defaultAriaConfig.defaultAriaConfig.disableCookieUsage, ((_TelemetryManager$Int16 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int16 === void 0 ? void 0 : (_TelemetryManager$Int17 = _TelemetryManager$Int16.ariaConfig) === null || _TelemetryManager$Int17 === void 0 ? void 0 : _TelemetryManager$Int17.collectorUriForTelemetry) ?? _defaultAriaConfig.defaultAriaConfig.collectorUriForTelemetry, ((_TelemetryManager$Int18 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int18 === void 0 ? void 0 : (_TelemetryManager$Int19 = _TelemetryManager$Int18.ariaConfig) === null || _TelemetryManager$Int19 === void 0 ? void 0 : _TelemetryManager$Int19.ariaTelemetryApplicationName) ?? _defaultAriaConfig.defaultAriaConfig.ariaTelemetryApplicationName));
@@ -61,12 +61,15 @@ const RegisterLoggers = () => {
61
61
  loggers.push(logger);
62
62
  });
63
63
  }
64
- if (((_TelemetryManager$Int22 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int22 === void 0 ? void 0 : (_TelemetryManager$Int23 = _TelemetryManager$Int22.appInsightsConfig) === null || _TelemetryManager$Int23 === void 0 ? void 0 : _TelemetryManager$Int23.appInsightsDisabled) === false) {
65
- var _TelemetryManager$Int24;
66
- if ((_TelemetryManager$Int24 = TelemetryManager.InternalTelemetryData) !== null && _TelemetryManager$Int24 !== void 0 && _TelemetryManager$Int24.appInsightsConfig.appInsightsKey) {
67
- var _TelemetryManager$Int25;
68
- loggers.push((0, _appInsightsLogger.appInsightsLogger)((_TelemetryManager$Int25 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int25 === void 0 ? void 0 : _TelemetryManager$Int25.appInsightsConfig.appInsightsKey));
69
- }
64
+ const chatConfigAppInsightsKey = (_TelemetryManager$Int22 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int22 === void 0 ? void 0 : _TelemetryManager$Int22.chatConfigAppInsightsKey;
65
+ const appInsightsKeyFromUser = (_TelemetryManager$Int23 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int23 === void 0 ? void 0 : (_TelemetryManager$Int24 = _TelemetryManager$Int23.appInsightsConfig) === null || _TelemetryManager$Int24 === void 0 ? void 0 : _TelemetryManager$Int24.appInsightsKey;
66
+ // when chatConfig has AppInsightsInstrumentationKey
67
+ if (chatConfigAppInsightsKey) {
68
+ loggers.push((0, _appInsightsLogger.appInsightsLogger)(chatConfigAppInsightsKey));
69
+ }
70
+ // when key set through appInsightsConfig
71
+ else if (appInsightsKeyFromUser && ((_TelemetryManager$Int25 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int25 === void 0 ? void 0 : (_TelemetryManager$Int26 = _TelemetryManager$Int25.appInsightsConfig) === null || _TelemetryManager$Int26 === void 0 ? void 0 : _TelemetryManager$Int26.appInsightsDisabled) === false) {
72
+ loggers.push((0, _appInsightsLogger.appInsightsLogger)(appInsightsKeyFromUser));
70
73
  }
71
74
  }
72
75
  };
@@ -42,7 +42,7 @@ const CitationPaneStateful = props => {
42
42
  const [paneStyle, setPaneStyle] = (0, _react.useState)(null);
43
43
  const [isReady, setIsReady] = (0, _react.useState)(false);
44
44
 
45
- // Move focus to the container
45
+ // Initial focus pattern (mirrors ConfirmationPaneStateful): focus first focusable element (will re-attempt after visibility becomes true)
46
46
  (0, _react.useEffect)(() => {
47
47
  (0, _utils.preventFocusToMoveOutOfElement)(controlId);
48
48
  const focusableElements = (0, _utils.findAllFocusableElement)(`#${controlId}`);
@@ -64,6 +64,25 @@ const CitationPaneStateful = props => {
64
64
  });
65
65
  }, []);
66
66
 
67
+ // Retry focus once pane is actually visible (isReady) in case initial attempt occurred while wrapper was visibility:hidden
68
+ (0, _react.useEffect)(() => {
69
+ if (!isReady) return;
70
+ const focusableElements = (0, _utils.findAllFocusableElement)(`#${controlId}`);
71
+ if (focusableElements && focusableElements.length > 0) {
72
+ const first = focusableElements[0];
73
+ // If focused element is not already inside the pane, move focus
74
+ if (!first.contains(document.activeElement) && !(document.activeElement && document.activeElement.id.startsWith(controlId))) {
75
+ requestAnimationFrame(() => {
76
+ if (first.isConnected) {
77
+ first.focus({
78
+ preventScroll: true
79
+ });
80
+ }
81
+ });
82
+ }
83
+ }
84
+ }, [isReady, controlId]);
85
+
67
86
  // Compute the widget bounds and set pane style accordingly (95% of widget size
68
87
  // and centered inside the widget). If the widget container can't be found,
69
88
  // fall back to the default pane styles from defaultCitationPaneProps.
@@ -9,7 +9,7 @@ var ChatWidgetEvents;
9
9
  ChatWidgetEvents["ADD_ACTIVITY"] = "CHAT_WIDGET/ADD_ACTIVITY";
10
10
  ChatWidgetEvents["FETCH_PERSISTENT_CHAT_HISTORY"] = "CHAT_WIDGET/FETCH_PERSISTENT_CHAT_HISTORY";
11
11
  ChatWidgetEvents["NO_MORE_HISTORY_AVAILABLE"] = "CHAT_WIDGET/NO_MORE_HISTORY_AVAILABLE";
12
- ChatWidgetEvents["HIDE_LOADING_BANNER"] = "CHAT_WIDGET/HIDE_LOADING_BANNER";
12
+ ChatWidgetEvents["HISTORY_LOAD_ERROR"] = "CHAT_WIDGET/HISTORY_LOAD_ERROR";
13
13
  })(ChatWidgetEvents || (ChatWidgetEvents = {}));
14
14
  var _default = ChatWidgetEvents;
15
15
  exports.default = _default;
@@ -36,7 +36,7 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
36
36
  _defineProperty(this, "facadeChatSDK", void 0);
37
37
  _defineProperty(this, "lastMessage", null);
38
38
  _defineProperty(this, "count", 0);
39
- _defineProperty(this, "pageSize", 4);
39
+ _defineProperty(this, "pageSize", _defaultPersistentChatHistoryProps.defaultPersistentChatHistoryProps.pageSize);
40
40
  _defineProperty(this, "isCurrentlyPulling", false);
41
41
  _defineProperty(this, "pageTokenInTransitSet", new Set());
42
42
  _defineProperty(this, "resetEventListener", _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.PersistentConversationReset).subscribe(() => {
@@ -48,18 +48,21 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
48
48
  Event: _TelemetryConstants.TelemetryEvent.LCWPersistentConversationHandlerInitialized,
49
49
  Description: "PersistentConversationHandler initialized",
50
50
  CustomProperties: {
51
- pageSize: this.pageSize
51
+ pageSize: _defaultPersistentChatHistoryProps.defaultPersistentChatHistoryProps.pageSize
52
52
  }
53
53
  });
54
54
  }
55
55
  _createClass(PersistentConversationHandler, [{
56
56
  key: "appliedPropsHandler",
57
57
  value: function appliedPropsHandler(props) {
58
+ var _this$appliedProps;
58
59
  this.appliedProps = {
59
60
  ..._defaultPersistentChatHistoryProps.defaultPersistentChatHistoryProps,
60
61
  ...props
61
62
  };
62
- this.pageSize = this.appliedProps.pageSize || 4;
63
+
64
+ // if the props is not existent or is not a number then default to defaultPersistentChatHistoryProps.pageSize
65
+ this.pageSize = ((_this$appliedProps = this.appliedProps) === null || _this$appliedProps === void 0 ? void 0 : _this$appliedProps.pageSize) !== undefined && !isNaN(this.appliedProps.pageSize) ? this.appliedProps.pageSize : _defaultPersistentChatHistoryProps.defaultPersistentChatHistoryProps.pageSize;
63
66
  }
64
67
  }, {
65
68
  key: "reset",
@@ -104,12 +107,23 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
104
107
  try {
105
108
  var _ref;
106
109
  const messages = await this.fetchHistoryMessages();
107
- if (messages === null || (messages === null || messages === void 0 ? void 0 : messages.length) === 0) {
110
+
111
+ // Handle error case - null indicates an error occurred
112
+ // Don't mark as last pull to allow retry on next attempt
113
+ if (messages == null) {
114
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.WARN, {
115
+ Event: _TelemetryConstants.TelemetryEvent.LCWPersistentHistoryReturnedNull,
116
+ Description: "History pull returned null - Possible error occurred, will retry on next scroll",
117
+ ElapsedTimeInMilliseconds: pullTimer.milliSecondsElapsed
118
+ });
119
+ return;
120
+ }
121
+
122
+ // Handle legitimate end of history - empty array
123
+ if (messages.length === 0) {
108
124
  this.isLastPull = true;
109
125
  // Dispatch event to notify UI that no more history is available
110
126
  (0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.NO_MORE_HISTORY_AVAILABLE);
111
- // Also hide the loading banner
112
- (0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.HIDE_LOADING_BANNER);
113
127
  _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
114
128
  Event: _TelemetryConstants.TelemetryEvent.LCWPersistentHistoryPullCompleted,
115
129
  Description: "History pull completed - no more messages",
@@ -119,9 +133,6 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
119
133
  }
120
134
  const messagesDescOrder = (_ref = [...messages]) === null || _ref === void 0 ? void 0 : _ref.reverse();
121
135
  this.processHistoryMessages(messagesDescOrder);
122
-
123
- // Dispatch event to hide the loading banner after messages are processed
124
- (0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.HIDE_LOADING_BANNER);
125
136
  _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
126
137
  Event: _TelemetryConstants.TelemetryEvent.LCWPersistentHistoryPullCompleted,
127
138
  Description: "History pull completed successfully",
@@ -177,7 +188,6 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
177
188
  if (!this.shouldPull()) {
178
189
  // Dispatch event to ensure banner is hidden when no more pulls are needed
179
190
  (0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.NO_MORE_HISTORY_AVAILABLE);
180
- (0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.HIDE_LOADING_BANNER);
181
191
  return [];
182
192
  }
183
193
  const options = {
@@ -203,24 +213,20 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
203
213
  this.isLastPull = true;
204
214
  // Dispatch event when we reach the end of available history
205
215
  (0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.NO_MORE_HISTORY_AVAILABLE);
206
- // Also hide the loading banner
207
- (0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.HIDE_LOADING_BANNER);
208
216
  return [];
209
217
  }
210
- (0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.HIDE_LOADING_BANNER);
211
218
  return messages;
212
219
  } catch (error) {
213
220
  _TelemetryHelper.TelemetryHelper.logSDKEvent(_TelemetryConstants.LogLevel.ERROR, {
214
221
  Event: _TelemetryConstants.TelemetryEvent.FetchPersistentChatHistoryFailed,
215
222
  ExceptionDetails: error
216
223
  });
217
- this.isLastPull = true;
218
- this.pageToken = null;
219
- // Dispatch event when there's an error to stop loading banner
220
- (0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.NO_MORE_HISTORY_AVAILABLE);
221
- // Also hide the loading banner
222
- (0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.HIDE_LOADING_BANNER);
223
- return [];
224
+
225
+ // On error, dispatch HISTORY_LOAD_ERROR to hide loading banner without marking conversation as ended
226
+ // This allows recovery on the next attempt (e.g., transient network errors)
227
+ // Return null to distinguish error from legitimate empty history
228
+ (0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.HISTORY_LOAD_ERROR);
229
+ return null;
224
230
  }
225
231
  }
226
232
  }, {
@@ -5,8 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.defaultPersistentChatHistoryProps = void 0;
7
7
  const defaultPersistentChatHistoryProps = {
8
- persistentChatHistoryEnabled: true,
9
- pageSize: 4,
8
+ pageSize: 10,
10
9
  dividerActivityStyle: {
11
10
  border: "1px solid rgb(96, 94, 92, 0.5)",
12
11
  margin: "10px 20%"
@@ -201,6 +201,18 @@ const endChat = async (props, facadeChatSDK, state, dispatch, setAdapter, setWeb
201
201
  facadeChatSDK.destroy();
202
202
  }
203
203
  }
204
+
205
+ //moving logic below to before processing skipCloseChat logic to avoid race conditions of postMessage for endChatEvent for other tabs vs postMessage for CloseChat
206
+ //TODO: clarify if this postMessageToOtherTab actually works in production.
207
+ if (postMessageToOtherTab) {
208
+ const endChatEventName = await getEndChatEventName(facadeChatSDK, props);
209
+ _omnichannelChatComponents.BroadcastService.postMessage({
210
+ eventName: endChatEventName,
211
+ payload: {
212
+ runtimeId: _TelemetryManager.TelemetryManager.InternalTelemetryData.lcwRuntimeId
213
+ }
214
+ });
215
+ }
204
216
  if (!skipCloseChat) {
205
217
  try {
206
218
  var _props$webChatContain;
@@ -240,17 +252,17 @@ const endChat = async (props, facadeChatSDK, state, dispatch, setAdapter, setWeb
240
252
  });
241
253
  closeChatWidget(dispatch, setWebChatStyles, props);
242
254
  facadeChatSDK.destroy();
255
+
256
+ //always post the close chat event after chat closed and cleanup completed
257
+ _omnichannelChatComponents.BroadcastService.postMessage({
258
+ eventName: _TelemetryConstants.BroadcastEvent.CloseChat
259
+ });
260
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
261
+ Event: _TelemetryConstants.TelemetryEvent.CloseChatCall,
262
+ Description: "Broadcasted close chat event"
263
+ });
243
264
  }
244
265
  }
245
- if (postMessageToOtherTab) {
246
- const endChatEventName = await getEndChatEventName(facadeChatSDK, props);
247
- _omnichannelChatComponents.BroadcastService.postMessage({
248
- eventName: endChatEventName,
249
- payload: {
250
- runtimeId: _TelemetryManager.TelemetryManager.InternalTelemetryData.lcwRuntimeId
251
- }
252
- });
253
- }
254
266
  };
255
267
  exports.endChat = endChat;
256
268
  const callingStateCleanUp = dispatch => {
@@ -125,7 +125,14 @@ const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) =>
125
125
  };
126
126
  webChatStore = (0, _botframeworkWebchat.createStore)({},
127
127
  //initial state
128
- _preProcessingMiddleware.default, _attachmentProcessingMiddleware.default, (0, _attachmentUploadValidatorMiddleware.default)((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), (0, _customEventMiddleware.default)(_omnichannelChatComponents.BroadcastService), (0, _queueOverflowHandlerMiddleware.createQueueOverflowMiddleware)(state, dispatch), (0, _channelDataMiddleware.default)(addConversationalSurveyTagsCallback), (0, _conversationEndMiddleware.default)(conversationEndCallback, startConversationalSurveyCallback, endConversationalSurveyCallback), (0, _dataMaskingMiddleware.default)((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), _messageTimestampMiddleware.createMessageTimeStampMiddleware, _messageSequenceIdOverrideMiddleware.createMessageSequenceIdOverrideMiddleware, (0, _citationsMiddleware.createCitationsMiddleware)(state, dispatch), _gifUploadMiddleware.default, _htmlPlayerMiddleware.default, (0, _htmlTextMiddleware.default)(honorsTargetInHTMLLinks), (0, _maxMessageSizeValidator.default)(localizedTexts), _sanitizationMiddleware.default, (0, _callActionMiddleware.default)(), (0, _localizedStringsBotInitialsMiddleware.localizedStringsBotInitialsMiddleware)(),
128
+ _preProcessingMiddleware.default, _attachmentProcessingMiddleware.default, (0, _attachmentUploadValidatorMiddleware.default)((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), (0, _customEventMiddleware.default)(_omnichannelChatComponents.BroadcastService), (0, _queueOverflowHandlerMiddleware.createQueueOverflowMiddleware)(state, dispatch), (0, _channelDataMiddleware.default)(addConversationalSurveyTagsCallback), (0, _conversationEndMiddleware.default)(conversationEndCallback, startConversationalSurveyCallback, endConversationalSurveyCallback), (0, _dataMaskingMiddleware.default)((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), _messageTimestampMiddleware.createMessageTimeStampMiddleware, _messageSequenceIdOverrideMiddleware.createMessageSequenceIdOverrideMiddleware, (0, _citationsMiddleware.createCitationsMiddleware)(state, dispatch), _gifUploadMiddleware.default, _htmlPlayerMiddleware.default, (0, _htmlTextMiddleware.default)(honorsTargetInHTMLLinks), (0, _maxMessageSizeValidator.default)(localizedTexts), _sanitizationMiddleware.default, (0, _callActionMiddleware.default)(),
129
+ // Pass a callback so middleware can push initials into React context for reactivity
130
+ (0, _localizedStringsBotInitialsMiddleware.localizedStringsBotInitialsMiddleware)(initials => {
131
+ dispatch({
132
+ type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_BOT_AVATAR_INITIALS,
133
+ payload: initials
134
+ });
135
+ }),
129
136
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
137
  ...(((_props$webChatContain7 = props.webChatContainerProps) === null || _props$webChatContain7 === void 0 ? void 0 : _props$webChatContain7.storeMiddlewares) ?? []));
131
138
  _WebChatStoreLoader.WebChatStoreLoader.store = webChatStore;
@@ -168,7 +175,7 @@ const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) =>
168
175
  dir: state.domainStates.globalDir,
169
176
  locale: (0, _utils.changeLanguageCodeFormatForWebChat)((0, _omnichannelChatSdk.getLocaleStringFromId)((_state$domainStates$l4 = state.domainStates.liveChatConfig) === null || _state$domainStates$l4 === void 0 ? void 0 : (_state$domainStates$l5 = _state$domainStates$l4.ChatWidgetLanguage) === null || _state$domainStates$l5 === void 0 ? void 0 : _state$domainStates$l5.msdyn_localeid)),
170
177
  store: webChatStore,
171
- activityMiddleware: (_props$webChatContain11 = props.webChatContainerProps) !== null && _props$webChatContain11 !== void 0 && (_props$webChatContain12 = _props$webChatContain11.renderingMiddlewareProps) !== null && _props$webChatContain12 !== void 0 && _props$webChatContain12.disableActivityMiddleware ? undefined : (0, _activityMiddleware.createActivityMiddleware)(renderMarkdown, (_state$domainStates$r = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r === void 0 ? void 0 : _state$domainStates$r.systemMessageStyleProps, (_state$domainStates$r2 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r2 === void 0 ? void 0 : _state$domainStates$r2.userMessageStyleProps),
178
+ activityMiddleware: (_props$webChatContain11 = props.webChatContainerProps) !== null && _props$webChatContain11 !== void 0 && (_props$webChatContain12 = _props$webChatContain11.renderingMiddlewareProps) !== null && _props$webChatContain12 !== void 0 && _props$webChatContain12.disableActivityMiddleware ? undefined : (0, _activityMiddleware.createActivityMiddleware)(renderMarkdown, (_state$domainStates$r = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r === void 0 ? void 0 : _state$domainStates$r.systemMessageStyleProps, (_state$domainStates$r2 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r2 === void 0 ? void 0 : _state$domainStates$r2.userMessageStyleProps, localizedTexts),
172
179
  attachmentMiddleware: (_props$webChatContain13 = props.webChatContainerProps) !== null && _props$webChatContain13 !== void 0 && (_props$webChatContain14 = _props$webChatContain13.renderingMiddlewareProps) !== null && _props$webChatContain14 !== void 0 && _props$webChatContain14.disableAttachmentMiddleware ? undefined : (0, _attachmentMiddleware.createAttachmentMiddleware)(((_state$domainStates$r3 = state.domainStates.renderingMiddlewareProps) === null || _state$domainStates$r3 === void 0 ? void 0 : (_state$domainStates$r4 = _state$domainStates$r3.attachmentProps) === null || _state$domainStates$r4 === void 0 ? void 0 : _state$domainStates$r4.enableInlinePlaying) ?? _defaultAttachmentProps.defaultAttachmentProps.enableInlinePlaying),
173
180
  activityStatusMiddleware: (_props$webChatContain15 = props.webChatContainerProps) !== null && _props$webChatContain15 !== void 0 && (_props$webChatContain16 = _props$webChatContain15.renderingMiddlewareProps) !== null && _props$webChatContain16 !== void 0 && _props$webChatContain16.disableActivityStatusMiddleware ? undefined : (0, _activityStatusMiddleware.createActivityStatusMiddleware)((0, _omnichannelChatSdk.getLocaleStringFromId)((_state$domainStates$l6 = state.domainStates.liveChatConfig) === null || _state$domainStates$l6 === void 0 ? void 0 : (_state$domainStates$l7 = _state$domainStates$l6.ChatWidgetLanguage) === null || _state$domainStates$l7 === void 0 ? void 0 : _state$domainStates$l7.msdyn_localeid)),
174
181
  toastMiddleware: (_props$webChatContain17 = props.webChatContainerProps) !== null && _props$webChatContain17 !== void 0 && (_props$webChatContain18 = _props$webChatContain17.renderingMiddlewareProps) !== null && _props$webChatContain18 !== void 0 && _props$webChatContain18.disableToastMiddleware ? undefined : (0, _toastMiddleware.createToastMiddleware)(props.notificationPaneProps, endChat),
@@ -30,7 +30,10 @@ const registerTelemetryLoggers = (props, dispatch) => {
30
30
  appInsightsConfig: Object.assign({}, _defaultAppInsightsConfig.defaultAppInsightsConfig, props.appInsightsConfig)
31
31
  };
32
32
  if (props.chatConfig) {
33
+ var _props$chatConfig$Liv;
33
34
  telemetryData = _TelemetryHelper.TelemetryHelper.addChatConfigDataToTelemetry(props === null || props === void 0 ? void 0 : props.chatConfig, telemetryData);
35
+ //store AppInsights instrumentation key from chatConfig if present
36
+ telemetryData.chatConfigAppInsightsKey = (_props$chatConfig$Liv = props.chatConfig.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig$Liv === void 0 ? void 0 : _props$chatConfig$Liv.AppInsightsInstrumentationKey;
34
37
  }
35
38
  if (!((_props$chatSDK = props.chatSDK) !== null && _props$chatSDK !== void 0 && (_props$chatSDK$omnich = _props$chatSDK.omnichannelConfig) !== null && _props$chatSDK$omnich !== void 0 && _props$chatSDK$omnich.orgId) || ((_props$chatSDK2 = props.chatSDK) === null || _props$chatSDK2 === void 0 ? void 0 : (_props$chatSDK2$omnic = _props$chatSDK2.omnichannelConfig) === null || _props$chatSDK2$omnic === void 0 ? void 0 : _props$chatSDK2$omnic.orgId.trim().length) === 0) {
36
39
  throw new Error("orgId is undefined in ChatSDK");