@microsoft/omnichannel-chat-widget 1.8.3-main.38c88a7 → 1.8.3-main.4743fdc

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 (62) hide show
  1. package/lib/cjs/common/Constants.js +2 -0
  2. package/lib/cjs/common/telemetry/TelemetryConstants.js +4 -0
  3. package/lib/cjs/common/telemetry/TelemetryHelper.js +7 -5
  4. package/lib/cjs/components/citationpanestateful/CitationDim.js +29 -0
  5. package/lib/cjs/components/citationpanestateful/CitationPaneStateful.js +158 -0
  6. package/lib/cjs/components/citationpanestateful/common/defaultProps/defaultCitationPaneProps.js +70 -0
  7. package/lib/cjs/components/confirmationpanestateful/interfaces/IConfirmationPaneLocalizedTexts.js +1 -0
  8. package/lib/cjs/components/livechatwidget/common/endChat.js +17 -3
  9. package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +12 -9
  10. package/lib/cjs/components/livechatwidget/common/startChat.js +4 -3
  11. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +12 -6
  12. package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +86 -4
  13. package/lib/cjs/components/webchatcontainerstateful/interfaces/ICitation.js +1 -0
  14. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/citationsMiddleware.js +139 -0
  15. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/localizedStringsBotInitialsMiddleware.js +54 -0
  16. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/queueOverflowHandlerMiddleware.js +2 -2
  17. package/lib/cjs/contexts/common/LiveChatWidgetActionType.js +46 -45
  18. package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +2 -0
  19. package/lib/cjs/contexts/createReducer.js +15 -0
  20. package/lib/cjs/firstresponselatency/util.js +12 -2
  21. package/lib/cjs/plugins/newMessageEventHandler.js +2 -2
  22. package/lib/esm/common/Constants.js +2 -0
  23. package/lib/esm/common/telemetry/TelemetryConstants.js +4 -0
  24. package/lib/esm/common/telemetry/TelemetryHelper.js +7 -5
  25. package/lib/esm/components/citationpanestateful/CitationDim.js +20 -0
  26. package/lib/esm/components/citationpanestateful/CitationPaneStateful.js +147 -0
  27. package/lib/esm/components/citationpanestateful/common/defaultProps/defaultCitationPaneProps.js +61 -0
  28. package/lib/esm/components/confirmationpanestateful/interfaces/IConfirmationPaneLocalizedTexts.js +1 -0
  29. package/lib/esm/components/livechatwidget/common/endChat.js +17 -3
  30. package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +13 -10
  31. package/lib/esm/components/livechatwidget/common/startChat.js +4 -3
  32. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +12 -6
  33. package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +86 -5
  34. package/lib/esm/components/webchatcontainerstateful/interfaces/ICitation.js +1 -0
  35. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/citationsMiddleware.js +133 -0
  36. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/localizedStringsBotInitialsMiddleware.js +46 -0
  37. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/queueOverflowHandlerMiddleware.js +2 -2
  38. package/lib/esm/contexts/common/LiveChatWidgetActionType.js +46 -45
  39. package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +2 -0
  40. package/lib/esm/contexts/createReducer.js +15 -0
  41. package/lib/esm/firstresponselatency/util.js +9 -0
  42. package/lib/esm/plugins/newMessageEventHandler.js +3 -3
  43. package/lib/types/common/Constants.d.ts +2 -0
  44. package/lib/types/common/telemetry/TelemetryConstants.d.ts +4 -0
  45. package/lib/types/components/citationpanestateful/CitationDim.d.ts +5 -0
  46. package/lib/types/components/citationpanestateful/CitationPaneStateful.d.ts +4 -0
  47. package/lib/types/components/citationpanestateful/common/defaultProps/defaultCitationPaneProps.d.ts +11 -0
  48. package/lib/types/components/citationpanestateful/interfaces/ICitationPaneStatefulProps.d.ts +10 -0
  49. package/lib/types/components/confirmationpanestateful/common/defaultProps/defaultConfirmationPaneLocalizedTexts.d.ts +1 -1
  50. package/lib/types/components/confirmationpanestateful/interfaces/IConfirmationPaneStatefulProps.d.ts +1 -1
  51. package/lib/types/components/livechatwidget/interfaces/ILiveChatWidgetProps.d.ts +3 -1
  52. package/lib/types/components/webchatcontainerstateful/interfaces/ICitation.d.ts +12 -0
  53. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/citationsMiddleware.d.ts +4 -0
  54. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/localizedStringsBotInitialsMiddleware.d.ts +5 -0
  55. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/queueOverflowHandlerMiddleware.d.ts +2 -2
  56. package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +1 -0
  57. package/lib/types/contexts/common/LiveChatWidgetActionType.d.ts +46 -45
  58. package/lib/types/firstresponselatency/util.d.ts +1 -0
  59. package/package.json +4 -3
  60. /package/lib/cjs/components/{confirmationpanestateful/interfaces/IConfirmationPaneLocalizedText.js → citationpanestateful/interfaces/ICitationPaneStatefulProps.js} +0 -0
  61. /package/lib/esm/components/{confirmationpanestateful/interfaces/IConfirmationPaneLocalizedText.js → citationpanestateful/interfaces/ICitationPaneStatefulProps.js} +0 -0
  62. /package/lib/types/components/confirmationpanestateful/interfaces/{IConfirmationPaneLocalizedText.d.ts → IConfirmationPaneLocalizedTexts.d.ts} +0 -0
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom";
3
+ import { DimLayer } from "../dimlayer/DimLayer";
4
+ const CONTAINER_SELECTOR = ".webchat__stacked-layout_container";
5
+ export const CitationDim = _ref => {
6
+ let {
7
+ brightness = "0.2"
8
+ } = _ref;
9
+ const container = document.querySelector(CONTAINER_SELECTOR);
10
+ if (!container) return null;
11
+ return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React.createElement("div", {
12
+ style: {
13
+ position: "absolute",
14
+ inset: 0
15
+ }
16
+ }, /*#__PURE__*/React.createElement(DimLayer, {
17
+ brightness: brightness
18
+ })), container);
19
+ };
20
+ export default CitationDim;
@@ -0,0 +1,147 @@
1
+ import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
2
+ import React, { useEffect, useState } from "react";
3
+ import { createTimer, findAllFocusableElement, findParentFocusableElementsWithoutChildContainer, preventFocusToMoveOutOfElement, setTabIndices } from "../../common/utils";
4
+ import CitationDim from "./CitationDim";
5
+ import { CitationPane } from "@microsoft/omnichannel-chat-components";
6
+ import { HtmlAttributeNames } from "../../common/Constants";
7
+ import { LiveChatWidgetActionType } from "../../contexts/common/LiveChatWidgetActionType";
8
+ import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
9
+ import { defaultCitationPaneStyles } from "./common/defaultProps/defaultCitationPaneProps";
10
+ import useChatContextStore from "../../hooks/useChatContextStore";
11
+ let uiTimer;
12
+ export const CitationPaneStateful = props => {
13
+ useEffect(() => {
14
+ uiTimer = createTimer();
15
+ TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
16
+ Event: TelemetryEvent.UXCitationPaneStart
17
+ });
18
+ }, []);
19
+ const initialTabIndexMap = new Map();
20
+ let elements = [];
21
+
22
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
23
+ const [state, dispatch] = useChatContextStore();
24
+ const controlId = HtmlAttributeNames.ocwCitationPaneClassName;
25
+
26
+ // Pane style computed to match the webchat widget container bounds so the pane
27
+ // stays within the widget and scrolls only vertically. We also track an
28
+ // "isReady" flag so we don't render the pane contents until the style is
29
+ // computed — this prevents a transient render that can appear as a flicker.
30
+ const [paneStyle, setPaneStyle] = useState(null);
31
+ const [isReady, setIsReady] = useState(false);
32
+
33
+ // Move focus to the container
34
+ useEffect(() => {
35
+ preventFocusToMoveOutOfElement(controlId);
36
+ const focusableElements = findAllFocusableElement(`#${controlId}`);
37
+ requestAnimationFrame(() => {
38
+ if (focusableElements && focusableElements.length > 0 && focusableElements[0]) {
39
+ focusableElements[0].focus({
40
+ preventScroll: true
41
+ });
42
+ }
43
+ });
44
+ elements = findParentFocusableElementsWithoutChildContainer(controlId);
45
+ setTabIndices(elements, initialTabIndexMap, false);
46
+ TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
47
+ Event: TelemetryEvent.CitationPaneLoaded
48
+ });
49
+ TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
50
+ Event: TelemetryEvent.UXCitationPaneCompleted,
51
+ ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
52
+ });
53
+ }, []);
54
+
55
+ // Compute the widget bounds and set pane style accordingly (95% of widget size
56
+ // and centered inside the widget). If the widget container can't be found,
57
+ // fall back to the default pane styles from defaultCitationPaneProps.
58
+ useEffect(() => {
59
+ const compute = () => {
60
+ try {
61
+ const container = document.querySelector(".webchat__stacked-layout_container");
62
+ if (container) {
63
+ const rect = container.getBoundingClientRect();
64
+ const widthPx = Math.round(rect.width * 0.95);
65
+ const heightPx = Math.round(rect.height * 0.95);
66
+ const leftPx = Math.round(rect.left + (rect.width - widthPx) / 2);
67
+ const topPx = Math.round(rect.top + (rect.height - heightPx) / 2);
68
+ // Clone defaults and remove transform so explicit left/top pixel
69
+ // coordinates are respected and the pane stays within the
70
+ // widget bounds.
71
+ const base = Object.assign({}, defaultCitationPaneStyles.pane);
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
+ if (base && base.transform) {
74
+ // remove centering transform when we compute exact pixel coords
75
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
76
+ delete base.transform;
77
+ }
78
+ setPaneStyle(Object.assign({}, base, {
79
+ left: `${leftPx}px`,
80
+ top: `${topPx}px`,
81
+ width: `${widthPx}px`,
82
+ height: `${heightPx}px`
83
+ }));
84
+ // Make the pane visible after the next paint to avoid layout
85
+ // flashes on initial mount.
86
+ requestAnimationFrame(() => setIsReady(true));
87
+ return;
88
+ }
89
+ } catch (e) {
90
+ // ignore
91
+ }
92
+
93
+ // fallback
94
+ setPaneStyle(defaultCitationPaneStyles.pane);
95
+ requestAnimationFrame(() => setIsReady(true));
96
+ };
97
+ compute();
98
+ window.addEventListener("resize", compute);
99
+ return () => window.removeEventListener("resize", compute);
100
+ }, []);
101
+ const handleClose = () => {
102
+ if (props.onClose) props.onClose();
103
+ dispatch({
104
+ type: LiveChatWidgetActionType.SET_PREVIOUS_FOCUSED_ELEMENT_ID,
105
+ payload: null
106
+ });
107
+ setTabIndices(elements, initialTabIndexMap, true);
108
+ };
109
+
110
+ // Merge a safe style object for the container and cast to CSSProperties to satisfy TS
111
+ const mergedStyle = Object.assign({
112
+ position: "relative"
113
+ }, paneStyle ?? {
114
+ position: "fixed"
115
+ });
116
+
117
+ // If paneStyle hasn't been computed yet, render the DimLayer so clicks
118
+ // still close overlays but hide the pane itself to avoid flashes.
119
+ const hiddenStyle = {
120
+ visibility: isReady ? "visible" : "hidden",
121
+ pointerEvents: isReady ? "auto" : "none"
122
+ };
123
+ const controlProps = {
124
+ id: controlId,
125
+ dir: state.domainStates.globalDir,
126
+ titleText: props.title,
127
+ contentHtml: props.contentHtml,
128
+ brightnessValueOnDim: "0.2",
129
+ onClose: handleClose,
130
+ ...(props === null || props === void 0 ? void 0 : props.controlProps)
131
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
132
+ };
133
+
134
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(CitationDim, {
135
+ brightness: "0.2"
136
+ }), /*#__PURE__*/React.createElement("div", {
137
+ style: Object.assign({}, mergedStyle, hiddenStyle, {
138
+ display: "flex",
139
+ flexDirection: "column",
140
+ zIndex: 10001
141
+ })
142
+ }, /*#__PURE__*/React.createElement(CitationPane, {
143
+ controlProps: controlProps,
144
+ styleProps: props === null || props === void 0 ? void 0 : props.styleProps
145
+ })));
146
+ };
147
+ export default CitationPaneStateful;
@@ -0,0 +1,61 @@
1
+ export const defaultCitationPaneStyles = {
2
+ pane: {
3
+ position: "fixed",
4
+ left: "50%",
5
+ top: "18%",
6
+ transform: "translateX(-50%)",
7
+ background: "#fff",
8
+ width: "85%",
9
+ height: "85%",
10
+ overflowY: "auto",
11
+ overflowX: "hidden",
12
+ padding: 16,
13
+ borderRadius: 6,
14
+ zIndex: 10001,
15
+ boxSizing: "border-box"
16
+ }
17
+ };
18
+ export const defaultCitationContentCSS = controlId => `
19
+ #${controlId} .citation-content {
20
+ flex: 1;
21
+ min-height: 0; /* allow flex child to scroll */
22
+ overflow-y: auto;
23
+ overflow-x: auto;
24
+ margin-bottom: 12px;
25
+ white-space: normal; /* wrap normal text */
26
+ word-break: break-word;
27
+ -webkit-overflow-scrolling: touch;
28
+ }
29
+
30
+ #${controlId} .citation-content pre,
31
+ #${controlId} .citation-content code {
32
+ white-space: pre; /* preserve formatting */
33
+ }
34
+
35
+ #${controlId} .citation-content table {
36
+ width: 100%;
37
+ border-collapse: collapse;
38
+ margin-bottom: 12px;
39
+ table-layout: auto;
40
+ overflow-x: auto;
41
+ display: block;
42
+ }
43
+
44
+ #${controlId} .citation-content table th,
45
+ #${controlId} .citation-content table td {
46
+ padding: 8px 12px;
47
+ border: 1px solid rgba(0,0,0,0.08);
48
+ text-align: left;
49
+ vertical-align: top;
50
+ word-break: break-word;
51
+ }
52
+
53
+ #${controlId} .citation-content img {
54
+ max-width: 100%;
55
+ height: auto;
56
+ }
57
+ `;
58
+ export default {
59
+ defaultCitationPaneStyles,
60
+ defaultCitationContentCSS
61
+ };
@@ -39,7 +39,7 @@ const prepareEndChat = async (props, facadeChatSDK, state, dispatch, setAdapter,
39
39
  }
40
40
 
41
41
  // Use Case: If ended by Agent, stay chat in InActive state
42
- let isConversationalSurveyEnabled = state.appStates.isConversationalSurveyEnabled;
42
+ const isConversationalSurveyEnabled = state.appStates.isConversationalSurveyEnabled;
43
43
  if (isConversationalSurveyEnabled && ((state === null || state === void 0 ? void 0 : (_state$appStates2 = state.appStates) === null || _state$appStates2 === void 0 ? void 0 : _state$appStates2.conversationEndedBy) === ConversationEndEntity.Agent || (state === null || state === void 0 ? void 0 : (_state$appStates3 = state.appStates) === null || _state$appStates3 === void 0 ? void 0 : _state$appStates3.conversationEndedBy) === ConversationEndEntity.Bot)) {
44
44
  dispatch({
45
45
  type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
@@ -211,7 +211,7 @@ const endChat = async (props, facadeChatSDK, state, dispatch, setAdapter, setWeb
211
211
  payload: undefined
212
212
  });
213
213
  // Always allow to close the chat for embedded mode irrespective of end chat errors
214
- closeChatWidget(dispatch);
214
+ closeChatWidget(dispatch, setWebChatStyles, props);
215
215
  facadeChatSDK.destroy();
216
216
  }
217
217
  }
@@ -296,6 +296,10 @@ export const closeChatStateCleanUp = dispatch => {
296
296
  proactiveChatInNewWindow: false
297
297
  }
298
298
  });
299
+ dispatch({
300
+ type: LiveChatWidgetActionType.SET_CITATIONS,
301
+ payload: {}
302
+ });
299
303
 
300
304
  // Clear live chat context only if chat widget is fully closed to support transcript calls after sessionclose is called
301
305
  dispatch({
@@ -339,12 +343,22 @@ export const endVoiceVideoCallIfOngoing = async (facadeChatSDK, dispatch) => {
339
343
  }, callId);
340
344
  }
341
345
  };
342
- const closeChatWidget = dispatch => {
346
+
347
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
348
+ const closeChatWidget = (dispatch, setWebChatStyles, props) => {
349
+ var _props$webChatContain2, _props$webChatContain3;
343
350
  // Embedded chat
344
351
  dispatch({
345
352
  type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
346
353
  payload: ConversationState.Closed
347
354
  });
355
+
356
+ // if customer is setting the hideSendbox, we should not alter its value
357
+ if ((props === null || props === void 0 ? void 0 : (_props$webChatContain2 = props.webChatContainerProps) === null || _props$webChatContain2 === void 0 ? void 0 : (_props$webChatContain3 = _props$webChatContain2.webChatStyles) === null || _props$webChatContain3 === void 0 ? void 0 : _props$webChatContain3.hideSendBox) === true) return;
358
+ setWebChatStyles(styles => ({
359
+ ...styles,
360
+ hideSendBox: false
361
+ }));
348
362
  };
349
363
 
350
364
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1,6 +1,9 @@
1
1
  import { ConversationEndEntity, ParticipantType } from "../../../common/Constants";
2
2
  import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
3
3
  import { changeLanguageCodeFormatForWebChat, getConversationDetailsCall } from "../../../common/utils";
4
+ import { BroadcastService } from "@microsoft/omnichannel-chat-components";
5
+ import { Constants } from "../../../common/Constants";
6
+ import { ConversationState } from "../../../contexts/common/ConversationState";
4
7
  import DOMPurify from "dompurify";
5
8
  import HyperlinkTextOverrideRenderer from "../../webchatcontainerstateful/webchatcontroller/markdownrenderers/HyperlinkTextOverrideRenderer";
6
9
  import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
@@ -12,36 +15,35 @@ import { createActivityMiddleware } from "../../webchatcontainerstateful/webchat
12
15
  import { createAttachmentMiddleware } from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/attachmentMiddleware";
13
16
  import createAttachmentUploadValidatorMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/attachmentUploadValidatorMiddleware";
14
17
  import { createAvatarMiddleware } from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/avatarMiddleware";
18
+ import createCallActionMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/callActionMiddleware";
15
19
  import { createCardActionMiddleware } from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/cardActionMiddleware";
20
+ import { createCitationsMiddleware } from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/citationsMiddleware";
16
21
  import createConversationEndMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/conversationEndMiddleware";
22
+ import createCustomEventMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/customEventMiddleware";
17
23
  import createDataMaskingMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/dataMaskingMiddleware";
18
24
  import { createMarkdown } from "./createMarkdown";
19
25
  import createMaxMessageSizeValidator from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/maxMessageSizeValidator";
20
26
  import { createMessageSequenceIdOverrideMiddleware } from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware";
21
27
  import { createMessageTimeStampMiddleware } from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageTimestampMiddleware";
28
+ import { createQueueOverflowMiddleware } from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/queueOverflowHandlerMiddleware";
22
29
  import { createStore } from "botframework-webchat";
23
30
  import { createToastMiddleware } from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/toastMiddleware";
24
31
  import { createWebChatTelemetry } from "../../webchatcontainerstateful/webchatcontroller/webchattelemetry/WebChatLogger";
25
32
  import { defaultAttachmentProps } from "../../webchatcontainerstateful/common/defaultProps/defaultAttachmentProps";
26
33
  import { defaultMiddlewareLocalizedTexts } from "../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
27
34
  import { defaultWebChatContainerStatefulProps } from "../../webchatcontainerstateful/common/defaultProps/defaultWebChatContainerStatefulProps";
35
+ import { executeReducer } from "../../../contexts/createReducer";
28
36
  import { getLocaleStringFromId } from "@microsoft/omnichannel-chat-sdk";
29
37
  import gifUploadMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/gifUploadMiddleware";
30
38
  import htmlPlayerMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlPlayerMiddleware";
31
39
  import htmlTextMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware";
32
40
  import preProcessingMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/preProcessingMiddleware";
33
41
  import sanitizationMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware";
34
- import { Constants } from "../../../common/Constants";
35
- import createCallActionMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/callActionMiddleware";
36
- import createCustomEventMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/customEventMiddleware";
37
- import { ConversationState } from "../../../contexts/common/ConversationState";
38
- import { executeReducer } from "../../../contexts/createReducer";
39
- import { createQueueOverflowMiddleware } from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/queueOverflowHandlerMiddleware";
40
- import { BroadcastService } from "@microsoft/omnichannel-chat-components";
42
+ import { localizedStringsBotInitialsMiddleware, getOverriddenLocalizedStrings } from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/localizedStringsBotInitialsMiddleware";
41
43
 
42
44
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
45
  export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endChat) => {
44
- var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4, _props$webChatContain5, _props$webChatContain6, _state$domainStates$l4, _state$domainStates$l5, _props$webChatContain11, _props$webChatContain12, _state$domainStates$r, _state$domainStates$r2, _props$webChatContain13, _props$webChatContain14, _state$domainStates$r3, _state$domainStates$r4, _props$webChatContain15, _props$webChatContain16, _defaultWebChatContai, _props$webChatContain17, _props$webChatContain18, _props$webChatContain19, _props$webChatContain20, _state$domainStates$r5, _state$domainStates$r6, _props$webChatContain21, _props$webChatContain22, _defaultWebChatContai2, _props$webChatContain23, _props$webChatContain24, _defaultWebChatContai3, _props$webChatContain25, _props$webChatContain26;
46
+ var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4, _props$webChatContain5, _props$webChatContain6, _state$domainStates$l4, _state$domainStates$l5, _props$webChatContain11, _props$webChatContain12, _state$domainStates$r, _state$domainStates$r2, _props$webChatContain13, _props$webChatContain14, _state$domainStates$r3, _state$domainStates$r4, _props$webChatContain15, _props$webChatContain16, _defaultWebChatContai, _props$webChatContain17, _props$webChatContain18, _props$webChatContain19, _props$webChatContain20, _state$domainStates$r5, _state$domainStates$r6, _props$webChatContain21, _props$webChatContain22, _defaultWebChatContai2, _props$webChatContain23, _props$webChatContain24, _defaultWebChatContai3, _props$webChatContain25, _props$webChatContain26, _props$webChatContain27, _props$webChatContain28;
45
47
  // Add a hook to make all links open a new window
46
48
  postDomPurifyActivities();
47
49
  const localizedTexts = {
@@ -116,7 +118,7 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
116
118
  };
117
119
  webChatStore = createStore({},
118
120
  //initial state
119
- preProcessingMiddleware, attachmentProcessingMiddleware, createAttachmentUploadValidatorMiddleware((_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), createCustomEventMiddleware(BroadcastService), createQueueOverflowMiddleware(state, dispatch), channelDataMiddleware(addConversationalSurveyTagsCallback), createConversationEndMiddleware(conversationEndCallback, startConversationalSurveyCallback, endConversationalSurveyCallback), createDataMaskingMiddleware((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), createMessageTimeStampMiddleware, createMessageSequenceIdOverrideMiddleware, gifUploadMiddleware, htmlPlayerMiddleware, htmlTextMiddleware(honorsTargetInHTMLLinks), createMaxMessageSizeValidator(localizedTexts), sanitizationMiddleware, createCallActionMiddleware(),
121
+ preProcessingMiddleware, attachmentProcessingMiddleware, createAttachmentUploadValidatorMiddleware((_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), createCustomEventMiddleware(BroadcastService), createQueueOverflowMiddleware(state, dispatch), channelDataMiddleware(addConversationalSurveyTagsCallback), createConversationEndMiddleware(conversationEndCallback, startConversationalSurveyCallback, endConversationalSurveyCallback), createDataMaskingMiddleware((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), createMessageTimeStampMiddleware, createMessageSequenceIdOverrideMiddleware, createCitationsMiddleware(state, dispatch), gifUploadMiddleware, htmlPlayerMiddleware, htmlTextMiddleware(honorsTargetInHTMLLinks), createMaxMessageSizeValidator(localizedTexts), sanitizationMiddleware, createCallActionMiddleware(), localizedStringsBotInitialsMiddleware(),
120
122
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
121
123
  ...(((_props$webChatContain7 = props.webChatContainerProps) === null || _props$webChatContain7 === void 0 ? void 0 : _props$webChatContain7.storeMiddlewares) ?? []));
122
124
  WebChatStoreLoader.store = webChatStore;
@@ -170,7 +172,8 @@ export const initWebChatComposer = (props, state, dispatch, facadeChatSDK, endCh
170
172
  onTelemetry: createWebChatTelemetry(),
171
173
  cardActionMiddleware: createCardActionMiddleware(((_props$webChatContain25 = props.webChatContainerProps) === null || _props$webChatContain25 === void 0 ? void 0 : _props$webChatContain25.botMagicCode) || undefined),
172
174
  sendTypingIndicator: true,
173
- ...((_props$webChatContain26 = props.webChatContainerProps) === null || _props$webChatContain26 === void 0 ? void 0 : _props$webChatContain26.webChatProps)
175
+ overrideLocalizedStrings: getOverriddenLocalizedStrings((_props$webChatContain26 = props.webChatContainerProps) === null || _props$webChatContain26 === void 0 ? void 0 : (_props$webChatContain27 = _props$webChatContain26.webChatProps) === null || _props$webChatContain27 === void 0 ? void 0 : _props$webChatContain27.overrideLocalizedStrings),
176
+ ...((_props$webChatContain28 = props.webChatContainerProps) === null || _props$webChatContain28 === void 0 ? void 0 : _props$webChatContain28.webChatProps)
174
177
  };
175
178
  return webChatProps;
176
179
  };
@@ -1,5 +1,6 @@
1
1
  import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryConstants";
2
2
  import { Constants, LiveWorkItemState, WidgetLoadTelemetryMessage } from "../../../common/Constants";
3
+ import { TelemetryManager, TelemetryTimers } from "../../../common/telemetry/TelemetryManager";
3
4
  import { checkContactIdError, createTimer, getConversationDetailsCall, getStateFromCache, getWidgetCacheIdfromProps, isNullOrEmptyString, isNullOrUndefined, isUndefinedOrEmpty } from "../../../common/utils";
4
5
  import { handleChatReconnect, isPersistentEnabled, isReconnectEnabled } from "./reconnectChatHelper";
5
6
  import { handleStartChatError, logWidgetLoadComplete } from "./startChatErrorHandler";
@@ -8,7 +9,6 @@ import { BroadcastService } from "@microsoft/omnichannel-chat-components";
8
9
  import { ConversationState } from "../../../contexts/common/ConversationState";
9
10
  import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
10
11
  import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
11
- import { TelemetryTimers } from "../../../common/telemetry/TelemetryManager";
12
12
  import { chatSDKStateCleanUp } from "./endChat";
13
13
  import { createAdapter } from "./createAdapter";
14
14
  import { createOnNewAdapterActivityHandler } from "../../../plugins/newMessageEventHandler";
@@ -131,7 +131,7 @@ const setPreChatAndInitiateChat = async (facadeChatSDK, dispatch, setAdapter, is
131
131
  * This is because a new change to control OOH as closed event when a widget is coming from chat.
132
132
  */
133
133
  if ((state === null || state === void 0 ? void 0 : state.appStates.isMinimized) === undefined || (state === null || state === void 0 ? void 0 : (_state$appStates2 = state.appStates) === null || _state$appStates2 === void 0 ? void 0 : _state$appStates2.isMinimized) === true) {
134
- var _state$domainStates5, _state$domainStates5$, _state$domainStates6, _state$domainStates6$;
134
+ var _state$domainStates5, _state$domainStates5$, _state$domainStates6, _state$domainStates6$, _TelemetryManager$Int;
135
135
  dispatch({
136
136
  type: LiveChatWidgetActionType.SET_MINIMIZED,
137
137
  payload: false
@@ -141,7 +141,8 @@ const setPreChatAndInitiateChat = async (facadeChatSDK, dispatch, setAdapter, is
141
141
  eventName: BroadcastEvent.MaximizeChat,
142
142
  payload: {
143
143
  height: state === null || state === void 0 ? void 0 : (_state$domainStates5 = state.domainStates) === null || _state$domainStates5 === void 0 ? void 0 : (_state$domainStates5$ = _state$domainStates5.widgetSize) === null || _state$domainStates5$ === void 0 ? void 0 : _state$domainStates5$.height,
144
- width: state === null || state === void 0 ? void 0 : (_state$domainStates6 = state.domainStates) === null || _state$domainStates6 === void 0 ? void 0 : (_state$domainStates6$ = _state$domainStates6.widgetSize) === null || _state$domainStates6$ === void 0 ? void 0 : _state$domainStates6$.width
144
+ width: state === null || state === void 0 ? void 0 : (_state$domainStates6 = state.domainStates) === null || _state$domainStates6 === void 0 ? void 0 : (_state$domainStates6$ = _state$domainStates6.widgetSize) === null || _state$domainStates6$ === void 0 ? void 0 : _state$domainStates6$.width,
145
+ runtimeId: TelemetryManager === null || TelemetryManager === void 0 ? void 0 : (_TelemetryManager$Int = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.lcwRuntimeId
145
146
  }
146
147
  });
147
148
  }
@@ -9,6 +9,7 @@ import { TelemetryManager, TelemetryTimers } from "../../../common/telemetry/Tel
9
9
  import { chatSDKStateCleanUp, endChat, endChatStateCleanUp, prepareEndChat } from "../common/endChat";
10
10
  import { checkIfConversationStillValid, initStartChat, prepareStartChat, setPreChatAndInitiateChat } from "../common/startChat";
11
11
  import { createTimer, getBroadcastChannelName, getConversationDetailsCall, getLocaleDirection, getStateFromCache, getWidgetCacheIdfromProps, getWidgetEndChatEventName, isNullOrEmptyString, isNullOrUndefined, isThisSessionPopout, isUndefinedOrEmpty, setOcUserAgent } from "../../../common/utils";
12
+ import { customEventCallback, subscribeToSendCustomEvent } from "../common/customEventHandler";
12
13
  import { defaultClientDataStoreProvider, isCookieAllowed } from "../../../common/storage/default/defaultClientDataStoreProvider";
13
14
  import { handleChatReconnect, isPersistentEnabled, isReconnectEnabled } from "../common/reconnectChatHelper";
14
15
  import { shouldShowCallingContainer, shouldShowChatButton, shouldShowConfirmationPane, shouldShowEmailTranscriptPane, shouldShowHeader, shouldShowLoadingPane, shouldShowOutOfOfficeHoursPane, shouldShowPostChatLoadingPane, shouldShowPostChatSurveyPane, shouldShowPreChatSurveyPane, shouldShowProactiveChatPane, shouldShowReconnectChatPane, shouldShowStartChatErrorPane, shouldShowWebChatContainer } from "../../../controller/componentController";
@@ -53,7 +54,6 @@ import { startProactiveChat } from "../common/startProactiveChat";
53
54
  import useChatAdapterStore from "../../../hooks/useChatAdapterStore";
54
55
  import useChatContextStore from "../../../hooks/useChatContextStore";
55
56
  import useFacadeSDKStore from "../../../hooks/useFacadeChatSDKStore";
56
- import { customEventCallback, subscribeToSendCustomEvent } from "../common/customEventHandler";
57
57
  let uiTimer;
58
58
  export const LiveChatWidgetStateful = props => {
59
59
  var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4, _props$webChatContain5, _props$webChatContain6, _props$webChatContain7, _props$webChatContain8, _props$webChatContain9, _props$styleProps, _props$webChatContain10, _props$webChatContain11, _props$controlProps, _props$controlProps3, _state$appStates7, _props$webChatContain15, _state$appStates14, _props$webChatContain17, _props$webChatContain18, _props$controlProps12, _props$draggableChatW, _props$draggableChatW2, _props$draggableChatW3, _props$draggableChatW4, _props$draggableChatW5, _livechatProps$webCha, _livechatProps$styleP, _livechatProps$contro, _livechatProps$contro2, _livechatProps$compon, _livechatProps$contro3, _livechatProps$compon2, _livechatProps$contro4, _livechatProps$compon3, _livechatProps$contro5, _livechatProps$compon4, _livechatProps$contro6, _livechatProps$compon5, _livechatProps$contro7, _livechatProps$compon6, _livechatProps$contro8, _livechatProps$compon7, _livechatProps$contro9, _livechatProps$compon8, _livechatProps$contro10, _livechatProps$contro11, _livechatProps$compon9, _livechatProps$contro12, _livechatProps$compon10, _livechatProps$contro13, _livechatProps$compon11, _livechatProps$compon12, _livechatProps$compon13;
@@ -719,11 +719,7 @@ export const LiveChatWidgetStateful = props => {
719
719
  endChat(props, facadeChatSDK, state, dispatch, setAdapter, setWebChatStyles, adapter, false, false, true);
720
720
  return;
721
721
  }
722
- const inMemoryState = executeReducer(state, {
723
- type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
724
- payload: null
725
- });
726
- let isConversationalSurveyEnabled = state.appStates.isConversationalSurveyEnabled;
722
+ const isConversationalSurveyEnabled = state.appStates.isConversationalSurveyEnabled;
727
723
 
728
724
  // In conversational survey, we need to check post chat survey logics before we set ConversationState to InActive
729
725
  // Hence setting ConversationState to InActive will be done later in the post chat flows
@@ -896,11 +892,21 @@ export const LiveChatWidgetStateful = props => {
896
892
  .webchat__basic-transcript__activity-markdown-body > :first-child {
897
893
  margin-top: 0px;
898
894
  }
895
+
899
896
  .webchat__basic-transcript__activity-markdown-body img.webchat__render-markdown__external-link-icon {
900
897
  background-image : url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIzIDMgMTggMTgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTcuMjUwMSA0LjUwMDE3SDEwLjc0OTVDMTEuMTYzNyA0LjUwMDE3IDExLjQ5OTUgNC44MzU5NiAxMS40OTk1IDUuMjUwMTdDMTEuNDk5NSA1LjYyOTg2IDExLjIxNzMgNS45NDM2NiAxMC44NTEzIDUuOTkzMzJMMTAuNzQ5NSA2LjAwMDE3SDcuMjQ5NzRDNi4wNzA3OSA1Ljk5OTYxIDUuMTAzNDkgNi45MDY1NiA1LjAwNzg2IDguMDYxMTJMNS4wMDAyOCA4LjIyMDAzTDUuMDAzMTIgMTYuNzUwN0M1LjAwMzQzIDE3Ljk0MTUgNS45Mjg4NSAxOC45MTYxIDcuMDk5NjYgMTguOTk0OUw3LjI1MzcxIDE5LjAwMDFMMTUuNzUxOCAxOC45ODg0QzE2Ljk0MTUgMTguOTg2OCAxNy45MTQ1IDE4LjA2MiAxNy45OTM1IDE2Ljg5MjNMMTcuOTk4NyAxNi43Mzg0VjEzLjIzMjFDMTcuOTk4NyAxMi44MTc5IDE4LjMzNDUgMTIuNDgyMSAxOC43NDg3IDEyLjQ4MjFDMTkuMTI4NCAxMi40ODIxIDE5LjQ0MjIgMTIuNzY0MyAxOS40OTE4IDEzLjEzMDNMMTkuNDk4NyAxMy4yMzIxVjE2LjczODRDMTkuNDk4NyAxOC43NDA3IDE3LjkyOTMgMjAuMzc2OSAxNS45NTI4IDIwLjQ4MjlMMTUuNzUzOCAyMC40ODg0TDcuMjU4MjcgMjAuNTAwMUw3LjA1NDk1IDIwLjQ5NDlDNS4xNDIzOSAyMC4zOTU0IDMuNjA4OTUgMTguODYyNyAzLjUwODM3IDE2Ljk1MDJMMy41MDMxMiAxNi43NTExTDMuNTAwODkgOC4yNTI3TDMuNTA1MjkgOC4wNTAyQzMuNjA1MzkgNi4xMzc0OSA1LjEzODY3IDQuNjA0NDkgNy4wNTA5NiA0LjUwNTI3TDcuMjUwMSA0LjUwMDE3SDEwLjc0OTVINy4yNTAxWk0xMy43NDgxIDMuMDAxNDZMMjAuMzAxOCAzLjAwMTk3TDIwLjQwMTQgMy4wMTU3NUwyMC41MDIyIDMuMDQzOTNMMjAuNTU5IDMuMDY4MDNDMjAuNjEyMiAzLjA5MTIyIDIwLjY2MzQgMy4xMjE2MyAyMC43MTExIDMuMTU4ODVMMjAuNzgwNCAzLjIyMTU2TDIwLjg2NDEgMy4zMjAxNEwyMC45MTgzIDMuNDEwMjVMMjAuOTU3IDMuNTAwNTdMMjAuOTc2MiAzLjU2NDc2TDIwLjk4OTggMy42Mjg2MkwyMC45OTkyIDMuNzIyODJMMjAuOTk5NyAxMC4yNTU0QzIwLjk5OTcgMTAuNjY5NiAyMC42NjM5IDExLjAwNTQgMjAuMjQ5NyAxMS4wMDU0QzE5Ljg3IDExLjAwNTQgMTkuNTU2MiAxMC43MjMyIDE5LjUwNjUgMTAuMzU3MUwxOS40OTk3IDEwLjI1NTRMMTkuNDk4OSA1LjU2MTQ3TDEyLjI3OTcgMTIuNzg0N0MxMi4wMTM0IDEzLjA1MSAxMS41OTY4IDEzLjA3NTMgMTEuMzAzMSAxMi44NTc1TDExLjIxOSAxMi43ODQ5QzEwLjk1MjcgMTIuNTE4NyAxMC45Mjg0IDEyLjEwMjEgMTEuMTQ2MiAxMS44MDg0TDExLjIxODggMTEuNzI0M0wxOC40MzY5IDQuNTAxNDZIMTMuNzQ4MUMxMy4zNjg0IDQuNTAxNDYgMTMuMDU0NiA0LjIxOTMxIDEzLjAwNSAzLjg1MzI0TDEyLjk5ODEgMy43NTE0NkMxMi45OTgxIDMuMzcxNzcgMTMuMjgwMyAzLjA1Nzk3IDEzLjY0NjQgMy4wMDgzMUwxMy43NDgxIDMuMDAxNDZaIiBmaWxsPSIjMjEyMTIxIiAvPjwvc3ZnPg==) !important;
901
898
  height: .75em;
902
899
  margin-left: .25em;
903
900
  }
901
+
902
+ .webchat__link-definitions__header-text {
903
+ color: ${bubbleBackground}
904
+ }
905
+
906
+ .webchat__link-definitions__header-chevron {
907
+ color: ${bubbleBackground}
908
+ }
909
+
904
910
  ${(sendBoxTextArea === null || sendBoxTextArea === void 0 ? void 0 : sendBoxTextArea.minHeight) && `
905
911
  .webchat__auto-resize-textarea.webchat__send-box-text-box__text-area {
906
912
  min-height: ${sendBoxTextArea === null || sendBoxTextArea === void 0 ? void 0 : sendBoxTextArea.minHeight} !important;
@@ -1,11 +1,10 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
-
3
1
  import { Constants, HtmlAttributeNames, HtmlClassNames } from "../../common/Constants";
4
2
  import { Stack } from "@fluentui/react";
5
3
  import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
6
- import React, { useEffect } from "react";
4
+ import React, { useEffect, useRef, useState } from "react";
7
5
  import { createTimer, getDeviceType, setFocusOnSendBox } from "../../common/utils";
8
6
  import { BotMagicCodeStore } from "./webchatcontroller/BotMagicCodeStore";
7
+ import CitationPaneStateful from "../citationpanestateful/CitationPaneStateful";
9
8
  import { Components } from "botframework-webchat";
10
9
  import { LiveChatWidgetActionType } from "../../contexts/common/LiveChatWidgetActionType";
11
10
  import { NotificationHandler } from "./webchatcontroller/notification/NotificationHandler";
@@ -23,6 +22,7 @@ import { defaultWebChatContainerStatefulProps } from "./common/defaultProps/defa
23
22
  import { useChatContextStore } from "../..";
24
23
  let uiTimer;
25
24
  const broadcastChannelMessageEvent = "message";
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
26
  const postActivity = activity => {
27
27
  // eslint-disable-line @typescript-eslint/no-explicit-any
28
28
  return {
@@ -55,6 +55,17 @@ export const WebChatContainerStateful = props => {
55
55
  Event: TelemetryEvent.UXWebchatContainerCompleted
56
56
  });
57
57
  }, []);
58
+
59
+ // Citation pane state
60
+ const [citationPaneOpen, setCitationPaneOpen] = useState(false);
61
+ const [citationPaneText, setCitationPaneText] = useState("");
62
+
63
+ // Guard to prevent handling multiple rapid clicks which could cause
64
+ // the dim layer and pane to re-render out of sync and create a flicker.
65
+ const citationOpeningRef = useRef(false);
66
+
67
+ // ...existing code...
68
+
58
69
  const {
59
70
  BasicWebChat
60
71
  } = Components;
@@ -63,6 +74,53 @@ export const WebChatContainerStateful = props => {
63
74
  webChatContainerProps,
64
75
  contextDataStore
65
76
  } = props;
77
+
78
+ // Delegated click handler for citation anchors. Placed after state is
79
+ // available so we can prefer reading citations from app state and fall
80
+ // back to the legacy window map for backward-compatibility in tests.
81
+ useEffect(() => {
82
+ const clickHandler = ev => {
83
+ try {
84
+ if (citationOpeningRef.current) {
85
+ return;
86
+ }
87
+ const target = ev.target;
88
+ // Only consider anchors whose href starts with the citation scheme
89
+ const anchor = target.closest && target.closest("a[href^=\"cite:\"]");
90
+ if (anchor) {
91
+ ev.preventDefault();
92
+ citationOpeningRef.current = true;
93
+ // Rely only on the href to identify the citation key
94
+ let text = "";
95
+ try {
96
+ var _state$domainStates;
97
+ const cid = anchor.getAttribute("href");
98
+ // Prefer state-based citations injected by middleware
99
+ if (state !== null && state !== void 0 && (_state$domainStates = state.domainStates) !== null && _state$domainStates !== void 0 && _state$domainStates.citations && cid) {
100
+ text = state.domainStates.citations[cid] ?? "";
101
+ }
102
+ // If state lookup failed, fall back to the anchor's title or innerText
103
+ if (!text) {
104
+ text = anchor.getAttribute("title") || anchor.innerText || "";
105
+ }
106
+ } catch (e) {
107
+ // ignore
108
+ }
109
+ setCitationPaneOpen(true);
110
+ setCitationPaneText(text);
111
+
112
+ // Simple debounce - reset guard after a short delay
113
+ setTimeout(() => {
114
+ citationOpeningRef.current = false;
115
+ }, 100);
116
+ }
117
+ } catch (e) {
118
+ citationOpeningRef.current = false;
119
+ }
120
+ };
121
+ document.addEventListener("click", clickHandler);
122
+ return () => document.removeEventListener("click", clickHandler);
123
+ }, [state]);
66
124
  const containerStyles = {
67
125
  root: Object.assign({}, defaultWebChatContainerStatefulProps.containerStyles, webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : webChatContainerProps.containerStyles, {
68
126
  display: state.appStates.isMinimized ? "none" : ""
@@ -97,8 +155,10 @@ export const WebChatContainerStateful = props => {
97
155
  localStorage;
98
156
  sessionStorage;
99
157
  } catch (error) {
158
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
100
159
  if (!window.TPCWarningShown) {
101
160
  NotificationHandler.notifyWarning(NotificationScenarios.TPC, (localizedTexts === null || localizedTexts === void 0 ? void 0 : localizedTexts.THIRD_PARTY_COOKIES_BLOCKED_ALERT_MESSAGE) ?? "");
161
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
102
162
  window.TPCWarningShown = true;
103
163
  }
104
164
  }
@@ -287,10 +347,31 @@ export const WebChatContainerStateful = props => {
287
347
  overflow-y: unset;
288
348
  }
289
349
 
290
-
350
+ /* Custom styles for carousel hero cards */
351
+ ul.webchat__carousel-filmstrip__attachments .ac-image {
352
+ width: 200px !important;
353
+ height: 150px !important;
354
+ object-fit: cover !important;
355
+ border-radius: 8px !important;
356
+ border: 1px solid #e0e0e0 !important;
357
+ }
358
+
359
+ .webchat__carousel-filmstrip-attachment .webchat__bubble {
360
+ height: 100% !important;
361
+ }
362
+
363
+ .webchat__carousel-filmstrip-attachment .webchat__bubble #ms_lcw_webchat_adaptive_card {
364
+ height: 100% !important;
365
+ }
366
+
291
367
  `), /*#__PURE__*/React.createElement(Stack, {
292
368
  styles: containerStyles,
293
369
  className: "webchat__stacked-layout_container"
294
- }, /*#__PURE__*/React.createElement(BasicWebChat, null)));
370
+ }, /*#__PURE__*/React.createElement(BasicWebChat, null)), citationPaneOpen && /*#__PURE__*/React.createElement(CitationPaneStateful, {
371
+ id: HtmlAttributeNames.ocwCitationPaneClassName,
372
+ title: HtmlAttributeNames.ocwCitationPaneTitle,
373
+ contentHtml: citationPaneText,
374
+ onClose: () => setCitationPaneOpen(false)
375
+ }));
295
376
  };
296
377
  export default WebChatContainerStateful;