@microsoft/omnichannel-chat-widget 1.7.7 → 1.7.8-main.270960e

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 (23) hide show
  1. package/lib/cjs/common/facades/FacadeChatSDK.js +2 -1
  2. package/lib/cjs/common/telemetry/TelemetryConstants.js +2 -0
  3. package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
  4. package/lib/cjs/components/livechatwidget/common/authHelper.js +15 -0
  5. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +14 -8
  6. package/lib/cjs/components/ooohpanestateful/OOOHPaneStateful.js +4 -0
  7. package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +15 -0
  8. package/lib/cjs/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +28 -0
  9. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware.js +7 -1
  10. package/lib/cjs/plugins/createChatTranscript.js +5 -5
  11. package/lib/esm/common/facades/FacadeChatSDK.js +2 -1
  12. package/lib/esm/common/telemetry/TelemetryConstants.js +2 -0
  13. package/lib/esm/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
  14. package/lib/esm/components/livechatwidget/common/authHelper.js +15 -0
  15. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +14 -8
  16. package/lib/esm/components/ooohpanestateful/OOOHPaneStateful.js +4 -0
  17. package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +15 -0
  18. package/lib/esm/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +21 -0
  19. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware.js +7 -1
  20. package/lib/esm/plugins/createChatTranscript.js +5 -5
  21. package/lib/types/common/telemetry/TelemetryConstants.d.ts +2 -0
  22. package/lib/types/components/postchatsurveypanestateful/common/isValidSurveyUrl.d.ts +2 -0
  23. package/package.json +1 -1
@@ -149,6 +149,7 @@ class FacadeChatSDK {
149
149
  }
150
150
  }
151
151
  async tokenRing() {
152
+ var _this$chatSDK$chatSDK;
152
153
  if (this.disableReauthentication === true) {
153
154
  // facade feature is disabled, so we are bypassing the re authentication and let it fail.
154
155
  return {
@@ -176,7 +177,7 @@ class FacadeChatSDK {
176
177
  message: "Token is valid"
177
178
  };
178
179
  }
179
- if (this.getAuthToken === undefined) {
180
+ if (this.getAuthToken === undefined && ((_this$chatSDK$chatSDK = this.chatSDK.chatSDKConfig) === null || _this$chatSDK$chatSDK === void 0 ? void 0 : _this$chatSDK$chatSDK.getAuthToken) === undefined) {
180
181
  _TelemetryHelper.TelemetryHelper.logFacadeChatSDKEvent(_TelemetryConstants.LogLevel.ERROR, {
181
182
  Event: _TelemetryConstants.TelemetryEvent.NewTokenFailed,
182
183
  Description: "GetAuthToken function is not present",
@@ -219,6 +219,8 @@ exports.TelemetryEvent = TelemetryEvent;
219
219
  TelemetryEvent["PostChatContextCallFailed"] = "PostChatContextCallFailed";
220
220
  TelemetryEvent["PostChatSurveyLoadingPaneLoaded"] = "PostChatSurveyLoadingPaneLoaded";
221
221
  TelemetryEvent["PostChatSurveyLoaded"] = "PostChatSurveyLoaded";
222
+ TelemetryEvent["PostChatSurveyUrlValidationCompleted"] = "PostChatSurveyUrlValidationCompleted";
223
+ TelemetryEvent["PostChatSurveyUrlValidationFailed"] = "PostChatSurveyUrlValidationFailed";
222
224
  TelemetryEvent["ChatDisconnectThreadEventReceived"] = "ChatDisconnectThreadEventReceived";
223
225
  TelemetryEvent["HiddenAdaptiveCardMessageReceived"] = "HiddenAdaptiveCardMessageReceived";
224
226
  TelemetryEvent["EndingAdapterAfterDisconnectionError"] = "EndingAdapterAfterDisconnectionError";
@@ -7,6 +7,7 @@ exports.BotAuthActivitySubscriber = void 0;
7
7
  var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
8
8
  var _TelemetryConstants = require("../../../../common/telemetry/TelemetryConstants");
9
9
  var _TelemetryHelper = require("../../../../common/telemetry/TelemetryHelper");
10
+ var _TelemetryManager = require("../../../../common/telemetry/TelemetryManager");
10
11
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
11
12
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
12
13
  function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
@@ -87,6 +88,7 @@ class BotAuthActivitySubscriber {
87
88
  return (activity === null || activity === void 0 ? void 0 : (_activity$attachments = activity.attachments) === null || _activity$attachments === void 0 ? void 0 : _activity$attachments.length) > 0 && activity.attachments[0] && supportedSignInCardContentTypes.indexOf(activity.attachments[0].contentType) >= 0;
88
89
  }
89
90
  async apply(activity) {
91
+ var _TelemetryManager$Int;
90
92
  this.observer.next(false); // Hides card
91
93
  const attachment = activity.attachments[0];
92
94
  const signInUrl = attachment.content.buttons[0].value;
@@ -106,7 +108,8 @@ class BotAuthActivitySubscriber {
106
108
  const event = {
107
109
  eventName: _TelemetryConstants.BroadcastEvent.SigninCardReceived,
108
110
  payload: {
109
- sasUrl
111
+ sasUrl,
112
+ conversationId: (_TelemetryManager$Int = _TelemetryManager.TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.conversationId
110
113
  }
111
114
  };
112
115
  if (!sasUrl) {
@@ -18,6 +18,7 @@ const getAuthClientFunction = chatConfig => {
18
18
  };
19
19
  exports.getAuthClientFunction = getAuthClientFunction;
20
20
  const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
21
+ var _chatSDK$chatSDKConfi;
21
22
  const authClientFunction = getAuthClientFunction(chatConfig);
22
23
  if (getAuthToken && authClientFunction) {
23
24
  _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
@@ -41,6 +42,20 @@ const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
41
42
  });
42
43
  throw new Error(_Constants.WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
43
44
  }
45
+ } else if (chatSDK !== null && chatSDK !== void 0 && (_chatSDK$chatSDKConfi = chatSDK.chatSDKConfig) !== null && _chatSDK$chatSDKConfi !== void 0 && _chatSDK$chatSDKConfi.getAuthToken) {
46
+ var _chatSDK$chatSDKConfi2;
47
+ const token = await ((_chatSDK$chatSDKConfi2 = chatSDK.chatSDKConfig) === null || _chatSDK$chatSDKConfi2 === void 0 ? void 0 : _chatSDK$chatSDKConfi2.getAuthToken());
48
+ if ((0, _utils.isNullOrEmptyString)(token)) {
49
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.ERROR, {
50
+ Event: _TelemetryConstants.TelemetryEvent.ReceivedNullOrEmptyToken,
51
+ Description: "getAuthToken in chat SDK returns empty string"
52
+ });
53
+ throw new Error(_Constants.WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
54
+ }
55
+ return {
56
+ "result": true,
57
+ token
58
+ };
44
59
  }
45
60
  return {
46
61
  "result": false,
@@ -417,7 +417,7 @@ const LiveChatWidgetStateful = props => {
417
417
 
418
418
  // Start chat from SDK Event
419
419
  _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.StartChat).subscribe(msg => {
420
- var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3, _inMemoryState$appSta4, _inMemoryState$appSta5;
420
+ var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3;
421
421
  // If chat is out of operating hours chat widget sets the conversation state to OutOfOffice.
422
422
  if (typeof (props === null || props === void 0 ? void 0 : (_props$chatConfig5 = props.chatConfig) === null || _props$chatConfig5 === void 0 ? void 0 : (_props$chatConfig5$Li = _props$chatConfig5.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig5$Li === void 0 ? void 0 : _props$chatConfig5$Li.OutOfOperatingHours) === "string" && (props === null || props === void 0 ? void 0 : (_props$chatConfig6 = props.chatConfig) === null || _props$chatConfig6 === void 0 ? void 0 : (_props$chatConfig6$Li = _props$chatConfig6.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig6$Li === void 0 ? void 0 : _props$chatConfig6$Li.OutOfOperatingHours.toLowerCase()) === "true") {
423
423
  (state === null || state === void 0 ? void 0 : state.appStates.isMinimized) && dispatch({
@@ -455,8 +455,14 @@ const LiveChatWidgetStateful = props => {
455
455
  });
456
456
  inMemoryState.domainStates.customContext = msg === null || msg === void 0 ? void 0 : (_msg$payload9 = msg.payload) === null || _msg$payload9 === void 0 ? void 0 : _msg$payload9.customContext;
457
457
 
458
- // Only initiate new chat if widget runtime state is one of the followings
459
- if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === _ConversationState.ConversationState.Closed || ((_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.conversationState) === _ConversationState.ConversationState.InActive || ((_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === _ConversationState.ConversationState.Postchat) {
458
+ /*
459
+ * If the conversation is in closed state then we start a new chat,
460
+ * else if the conversation is in active state then we maximize the chat
461
+ * If the conversation is in inactive or postchat state then we maximize the chat.
462
+ *
463
+ * To start a new chat, it needs to be called via the close button or close chat via SDK.
464
+ **/
465
+ if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === _ConversationState.ConversationState.Closed) {
460
466
  _omnichannelChatComponents.BroadcastService.postMessage({
461
467
  eventName: _TelemetryConstants.BroadcastEvent.ChatInitiated
462
468
  });
@@ -465,7 +471,7 @@ const LiveChatWidgetStateful = props => {
465
471
  }
466
472
 
467
473
  // If minimized, maximize the chat
468
- if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.isMinimized) === true) {
474
+ if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.isMinimized) === true) {
469
475
  var _inMemoryState$domain, _inMemoryState$domain2, _inMemoryState$domain3, _inMemoryState$domain4;
470
476
  dispatch({
471
477
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_MINIMIZED,
@@ -593,12 +599,12 @@ const LiveChatWidgetStateful = props => {
593
599
  disablePolling: true
594
600
  });
595
601
  facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.onAgentEndSession(event => {
596
- var _inMemoryState$appSta6;
602
+ var _inMemoryState$appSta4;
597
603
  const inMemoryState = (0, _createReducer.executeReducer)(state, {
598
604
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
599
605
  payload: null
600
606
  });
601
- if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta6 = inMemoryState.appStates) === null || _inMemoryState$appSta6 === void 0 ? void 0 : _inMemoryState$appSta6.conversationState) === _ConversationState.ConversationState.Active) {
607
+ if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === _ConversationState.ConversationState.Active) {
602
608
  setWebChatStyles(styles => {
603
609
  return {
604
610
  ...styles,
@@ -741,13 +747,13 @@ const LiveChatWidgetStateful = props => {
741
747
 
742
748
  // Handle Chat disconnect cases
743
749
  (0, _react2.useEffect)(() => {
744
- var _inMemoryState$appSta7;
750
+ var _inMemoryState$appSta5;
745
751
  const inMemoryState = (0, _createReducer.executeReducer)(state, {
746
752
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
747
753
  payload: null
748
754
  });
749
755
  (0, _chatDisconnectHelper.handleChatDisconnect)(props, inMemoryState, setWebChatStyles);
750
- const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta7 = inMemoryState.appStates) === null || _inMemoryState$appSta7 === void 0 ? void 0 : _inMemoryState$appSta7.chatDisconnectEventReceived;
756
+ const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.chatDisconnectEventReceived;
751
757
  if (chatDisconnectState && adapter) {
752
758
  try {
753
759
  adapter.end();
@@ -11,6 +11,7 @@ var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components
11
11
  var _TelemetryHelper = require("../../common/telemetry/TelemetryHelper");
12
12
  var _defaultgeneralOOOHPaneStyleProps = require("./common/defaultStyleProps/defaultgeneralOOOHPaneStyleProps");
13
13
  var _useChatContextStore = _interopRequireDefault(require("../../hooks/useChatContextStore"));
14
+ var _dompurify = _interopRequireDefault(require("dompurify"));
14
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
16
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
16
17
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -49,6 +50,9 @@ const OutOfOfficeHoursPaneStateful = props => {
49
50
  ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
50
51
  });
51
52
  }, []);
53
+ if (controlProps !== null && controlProps !== void 0 && controlProps.titleText) {
54
+ controlProps.titleText = _dompurify.default.sanitize(controlProps.titleText);
55
+ }
52
56
  return /*#__PURE__*/_react.default.createElement(_omnichannelChatComponents.OutOfOfficeHoursPane, {
53
57
  componentOverrides: props.componentOverrides,
54
58
  controlProps: controlProps,
@@ -14,6 +14,7 @@ var _TelemetryHelper = require("../../common/telemetry/TelemetryHelper");
14
14
  var _defaultgeneralPostChatSurveyPaneStyleProps = require("./common/defaultStyleProps/defaultgeneralPostChatSurveyPaneStyleProps");
15
15
  var _utils = require("../../common/utils");
16
16
  var _useChatContextStore = _interopRequireDefault(require("../../hooks/useChatContextStore"));
17
+ var _isValidSurveyUrl = _interopRequireDefault(require("./common/isValidSurveyUrl"));
17
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
19
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
20
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -54,6 +55,20 @@ const PostChatSurveyPaneStateful = props => {
54
55
  surveyURL: ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.surveyURL) ?? surveyInviteLink,
55
56
  ...props.controlProps
56
57
  };
58
+ if (controlProps.surveyURL) {
59
+ if (!(0, _isValidSurveyUrl.default)(controlProps.surveyURL)) {
60
+ _TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.ERROR, {
61
+ Event: _TelemetryConstants.TelemetryEvent.PostChatSurveyUrlValidationFailed,
62
+ Description: `${controlProps.surveyURL} is not a valid Survey URL`
63
+ });
64
+ controlProps.surveyURL = "";
65
+ } else {
66
+ _TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.INFO, {
67
+ Event: _TelemetryConstants.TelemetryEvent.PostChatSurveyUrlValidationCompleted,
68
+ Description: `${controlProps.surveyURL} is a valid Survey URL`
69
+ });
70
+ }
71
+ }
57
72
 
58
73
  // Move focus to the first button
59
74
  (0, _react.useEffect)(() => {
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _utils = require("../../../common/utils");
8
+ const validRootDomains = ["microsoft.com", "microsoft.us", "appsplatform.us", "powervirtualagents.cn"];
9
+ const isValidSurveyUrl = url => {
10
+ if ((0, _utils.isNullOrEmptyString)(url)) {
11
+ return false;
12
+ }
13
+ try {
14
+ const objectUrl = new URL(url);
15
+ if (!objectUrl.origin || objectUrl.origin === "null") {
16
+ return false;
17
+ }
18
+ const validDomain = validRootDomains.find(domain => objectUrl.origin.endsWith(domain));
19
+ if (validDomain) {
20
+ return true;
21
+ }
22
+ } catch (error) {
23
+ return false;
24
+ }
25
+ return false;
26
+ };
27
+ var _default = isValidSurveyUrl;
28
+ exports.default = _default;
@@ -41,6 +41,7 @@ const convertTextToHtmlNode = text => {
41
41
 
42
42
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
43
  const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
44
+ var _htmlNode$tagName;
44
45
  const htmlNode = convertTextToHtmlNode(text);
45
46
  const aNodes = htmlNode.getElementsByTagName(_Constants.HtmlAttributeNames.aTagName);
46
47
  if ((aNodes === null || aNodes === void 0 ? void 0 : aNodes.length) > 0) {
@@ -70,6 +71,7 @@ const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
70
71
  }
71
72
  }
72
73
  }
74
+ action = (0, _simpleUpdateIn.default)(action, [_Constants.Constants.payload, _Constants.Constants.activity, _Constants.Constants.text], () => htmlNode.innerHTML);
73
75
  } catch (e) {
74
76
  let errorMessage = "Failed to apply action: ";
75
77
  try {
@@ -86,7 +88,11 @@ const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
86
88
  });
87
89
  }
88
90
  }
89
- action = (0, _simpleUpdateIn.default)(action, [_Constants.Constants.payload, _Constants.Constants.activity, _Constants.Constants.text], () => htmlNode.innerHTML);
91
+
92
+ // if empty div tag after sanitization
93
+ if (((_htmlNode$tagName = htmlNode.tagName) === null || _htmlNode$tagName === void 0 ? void 0 : _htmlNode$tagName.toLowerCase()) === _Constants.HtmlAttributeNames.div && htmlNode.children.length === 0 && htmlNode.innerHTML.trim() === "") {
94
+ action = (0, _simpleUpdateIn.default)(action, [_Constants.Constants.payload, _Constants.Constants.activity, _Constants.Constants.text], () => "");
95
+ }
90
96
  return action;
91
97
  };
92
98
 
@@ -173,7 +173,7 @@ class TranscriptHTMLBuilder {
173
173
  <script>
174
174
  class Translator {
175
175
  static convertTranscriptMessageToActivity(message) {
176
- const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences} = message;
176
+ const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences, amsreferences} = message;
177
177
 
178
178
  //it's required to convert the id to a number, otherwise the webchat will not render the messages in the correct order
179
179
  // if the OrginalMessageId is not present, we can use the id as the sequence id, which is always present.
@@ -220,7 +220,7 @@ class TranscriptHTMLBuilder {
220
220
  }
221
221
 
222
222
  // Attachments
223
- if (amsReferences && amsMetadata) {
223
+ if ((amsReferences || amsreferences) && amsMetadata) {
224
224
  const metadata = JSON.parse(amsMetadata);
225
225
  const { fileName } = metadata[0];
226
226
  const text = \`${this.attachmentMessage}\${fileName}\`;
@@ -244,7 +244,7 @@ class TranscriptHTMLBuilder {
244
244
  // Message
245
245
  if (content) {
246
246
  // Adaptive card formatting
247
- if (content.includes('"text"') && content.includes('"attachments"') && content.includes('"suggestedActions"')) {
247
+ if (content.includes('"attachments"') || content.includes('"suggestedActions"')) {
248
248
  try {
249
249
  const partialActivity = JSON.parse(content);
250
250
  return {
@@ -677,13 +677,13 @@ const createChatTranscript = async function (transcript, facadeChatSDK) {
677
677
  };
678
678
  let messages = transcriptMessages.filter(message => {
679
679
  message.content = _dompurify.default.sanitize(message.content);
680
- return message.content.length > 0;
680
+ return message;
681
681
  });
682
682
  if (renderAttachments) {
683
683
  messages = await Promise.all(transcriptMessages.map(async message => {
684
684
  // eslint-disable-line @typescript-eslint/no-explicit-any
685
685
  const {
686
- amsReferences,
686
+ amsReferences = message.amsreferences,
687
687
  amsMetadata
688
688
  } = message;
689
689
  if (amsReferences && amsMetadata) {
@@ -143,6 +143,7 @@ export class FacadeChatSDK {
143
143
  }
144
144
  }
145
145
  async tokenRing() {
146
+ var _this$chatSDK$chatSDK;
146
147
  if (this.disableReauthentication === true) {
147
148
  // facade feature is disabled, so we are bypassing the re authentication and let it fail.
148
149
  return {
@@ -170,7 +171,7 @@ export class FacadeChatSDK {
170
171
  message: "Token is valid"
171
172
  };
172
173
  }
173
- if (this.getAuthToken === undefined) {
174
+ if (this.getAuthToken === undefined && ((_this$chatSDK$chatSDK = this.chatSDK.chatSDKConfig) === null || _this$chatSDK$chatSDK === void 0 ? void 0 : _this$chatSDK$chatSDK.getAuthToken) === undefined) {
174
175
  TelemetryHelper.logFacadeChatSDKEvent(LogLevel.ERROR, {
175
176
  Event: TelemetryEvent.NewTokenFailed,
176
177
  Description: "GetAuthToken function is not present",
@@ -213,6 +213,8 @@ export let TelemetryEvent;
213
213
  TelemetryEvent["PostChatContextCallFailed"] = "PostChatContextCallFailed";
214
214
  TelemetryEvent["PostChatSurveyLoadingPaneLoaded"] = "PostChatSurveyLoadingPaneLoaded";
215
215
  TelemetryEvent["PostChatSurveyLoaded"] = "PostChatSurveyLoaded";
216
+ TelemetryEvent["PostChatSurveyUrlValidationCompleted"] = "PostChatSurveyUrlValidationCompleted";
217
+ TelemetryEvent["PostChatSurveyUrlValidationFailed"] = "PostChatSurveyUrlValidationFailed";
216
218
  TelemetryEvent["ChatDisconnectThreadEventReceived"] = "ChatDisconnectThreadEventReceived";
217
219
  TelemetryEvent["HiddenAdaptiveCardMessageReceived"] = "HiddenAdaptiveCardMessageReceived";
218
220
  TelemetryEvent["EndingAdapterAfterDisconnectionError"] = "EndingAdapterAfterDisconnectionError";
@@ -6,6 +6,7 @@ function _toPrimitive(input, hint) { if (typeof input !== "object" || input ===
6
6
  import { BroadcastService } from "@microsoft/omnichannel-chat-components";
7
7
  import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../../common/telemetry/TelemetryConstants";
8
8
  import { TelemetryHelper } from "../../../../common/telemetry/TelemetryHelper";
9
+ import { TelemetryManager } from "../../../../common/telemetry/TelemetryManager";
9
10
  const supportedSignInCardContentTypes = ["application/vnd.microsoft.card.signin", "application/vnd.microsoft.card.oauth"];
10
11
  const botOauthUrlRegex = /[\S]+.botframework.com\/api\/oauth\/signin\?signin=([\S]+)/;
11
12
  const delay = t => new Promise(resolve => setTimeout(resolve, t));
@@ -83,6 +84,7 @@ export class BotAuthActivitySubscriber {
83
84
  return (activity === null || activity === void 0 ? void 0 : (_activity$attachments = activity.attachments) === null || _activity$attachments === void 0 ? void 0 : _activity$attachments.length) > 0 && activity.attachments[0] && supportedSignInCardContentTypes.indexOf(activity.attachments[0].contentType) >= 0;
84
85
  }
85
86
  async apply(activity) {
87
+ var _TelemetryManager$Int;
86
88
  this.observer.next(false); // Hides card
87
89
  const attachment = activity.attachments[0];
88
90
  const signInUrl = attachment.content.buttons[0].value;
@@ -102,7 +104,8 @@ export class BotAuthActivitySubscriber {
102
104
  const event = {
103
105
  eventName: BroadcastEvent.SigninCardReceived,
104
106
  payload: {
105
- sasUrl
107
+ sasUrl,
108
+ conversationId: (_TelemetryManager$Int = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.conversationId
106
109
  }
107
110
  };
108
111
  if (!sasUrl) {
@@ -11,6 +11,7 @@ const getAuthClientFunction = chatConfig => {
11
11
  return authClientFunction;
12
12
  };
13
13
  const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
14
+ var _chatSDK$chatSDKConfi;
14
15
  const authClientFunction = getAuthClientFunction(chatConfig);
15
16
  if (getAuthToken && authClientFunction) {
16
17
  TelemetryHelper.logActionEvent(LogLevel.INFO, {
@@ -34,6 +35,20 @@ const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
34
35
  });
35
36
  throw new Error(WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
36
37
  }
38
+ } else if (chatSDK !== null && chatSDK !== void 0 && (_chatSDK$chatSDKConfi = chatSDK.chatSDKConfig) !== null && _chatSDK$chatSDKConfi !== void 0 && _chatSDK$chatSDKConfi.getAuthToken) {
39
+ var _chatSDK$chatSDKConfi2;
40
+ const token = await ((_chatSDK$chatSDKConfi2 = chatSDK.chatSDKConfig) === null || _chatSDK$chatSDKConfi2 === void 0 ? void 0 : _chatSDK$chatSDKConfi2.getAuthToken());
41
+ if (isNullOrEmptyString(token)) {
42
+ TelemetryHelper.logActionEvent(LogLevel.ERROR, {
43
+ Event: TelemetryEvent.ReceivedNullOrEmptyToken,
44
+ Description: "getAuthToken in chat SDK returns empty string"
45
+ });
46
+ throw new Error(WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
47
+ }
48
+ return {
49
+ "result": true,
50
+ token
51
+ };
37
52
  }
38
53
  return {
39
54
  "result": false,
@@ -409,7 +409,7 @@ export const LiveChatWidgetStateful = props => {
409
409
 
410
410
  // Start chat from SDK Event
411
411
  BroadcastService.getMessageByEventName(BroadcastEvent.StartChat).subscribe(msg => {
412
- var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3, _inMemoryState$appSta4, _inMemoryState$appSta5;
412
+ var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3;
413
413
  // If chat is out of operating hours chat widget sets the conversation state to OutOfOffice.
414
414
  if (typeof (props === null || props === void 0 ? void 0 : (_props$chatConfig5 = props.chatConfig) === null || _props$chatConfig5 === void 0 ? void 0 : (_props$chatConfig5$Li = _props$chatConfig5.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig5$Li === void 0 ? void 0 : _props$chatConfig5$Li.OutOfOperatingHours) === "string" && (props === null || props === void 0 ? void 0 : (_props$chatConfig6 = props.chatConfig) === null || _props$chatConfig6 === void 0 ? void 0 : (_props$chatConfig6$Li = _props$chatConfig6.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig6$Li === void 0 ? void 0 : _props$chatConfig6$Li.OutOfOperatingHours.toLowerCase()) === "true") {
415
415
  (state === null || state === void 0 ? void 0 : state.appStates.isMinimized) && dispatch({
@@ -447,8 +447,14 @@ export const LiveChatWidgetStateful = props => {
447
447
  });
448
448
  inMemoryState.domainStates.customContext = msg === null || msg === void 0 ? void 0 : (_msg$payload9 = msg.payload) === null || _msg$payload9 === void 0 ? void 0 : _msg$payload9.customContext;
449
449
 
450
- // Only initiate new chat if widget runtime state is one of the followings
451
- if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === ConversationState.Closed || ((_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.conversationState) === ConversationState.InActive || ((_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === ConversationState.Postchat) {
450
+ /*
451
+ * If the conversation is in closed state then we start a new chat,
452
+ * else if the conversation is in active state then we maximize the chat
453
+ * If the conversation is in inactive or postchat state then we maximize the chat.
454
+ *
455
+ * To start a new chat, it needs to be called via the close button or close chat via SDK.
456
+ **/
457
+ if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === ConversationState.Closed) {
452
458
  BroadcastService.postMessage({
453
459
  eventName: BroadcastEvent.ChatInitiated
454
460
  });
@@ -457,7 +463,7 @@ export const LiveChatWidgetStateful = props => {
457
463
  }
458
464
 
459
465
  // If minimized, maximize the chat
460
- if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.isMinimized) === true) {
466
+ if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.isMinimized) === true) {
461
467
  var _inMemoryState$domain, _inMemoryState$domain2, _inMemoryState$domain3, _inMemoryState$domain4;
462
468
  dispatch({
463
469
  type: LiveChatWidgetActionType.SET_MINIMIZED,
@@ -585,12 +591,12 @@ export const LiveChatWidgetStateful = props => {
585
591
  disablePolling: true
586
592
  });
587
593
  facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.onAgentEndSession(event => {
588
- var _inMemoryState$appSta6;
594
+ var _inMemoryState$appSta4;
589
595
  const inMemoryState = executeReducer(state, {
590
596
  type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
591
597
  payload: null
592
598
  });
593
- if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta6 = inMemoryState.appStates) === null || _inMemoryState$appSta6 === void 0 ? void 0 : _inMemoryState$appSta6.conversationState) === ConversationState.Active) {
599
+ if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === ConversationState.Active) {
594
600
  setWebChatStyles(styles => {
595
601
  return {
596
602
  ...styles,
@@ -733,13 +739,13 @@ export const LiveChatWidgetStateful = props => {
733
739
 
734
740
  // Handle Chat disconnect cases
735
741
  useEffect(() => {
736
- var _inMemoryState$appSta7;
742
+ var _inMemoryState$appSta5;
737
743
  const inMemoryState = executeReducer(state, {
738
744
  type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
739
745
  payload: null
740
746
  });
741
747
  handleChatDisconnect(props, inMemoryState, setWebChatStyles);
742
- const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta7 = inMemoryState.appStates) === null || _inMemoryState$appSta7 === void 0 ? void 0 : _inMemoryState$appSta7.chatDisconnectEventReceived;
748
+ const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.chatDisconnectEventReceived;
743
749
  if (chatDisconnectState && adapter) {
744
750
  try {
745
751
  adapter.end();
@@ -5,6 +5,7 @@ import { OutOfOfficeHoursPane } from "@microsoft/omnichannel-chat-components";
5
5
  import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
6
6
  import { defaultGeneralStyleProps } from "./common/defaultStyleProps/defaultgeneralOOOHPaneStyleProps";
7
7
  import useChatContextStore from "../../hooks/useChatContextStore";
8
+ import DOMPurify from "dompurify";
8
9
  let uiTimer;
9
10
  export const OutOfOfficeHoursPaneStateful = props => {
10
11
  var _props$styleProps;
@@ -40,6 +41,9 @@ export const OutOfOfficeHoursPaneStateful = props => {
40
41
  ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
41
42
  });
42
43
  }, []);
44
+ if (controlProps !== null && controlProps !== void 0 && controlProps.titleText) {
45
+ controlProps.titleText = DOMPurify.sanitize(controlProps.titleText);
46
+ }
43
47
  return /*#__PURE__*/React.createElement(OutOfOfficeHoursPane, {
44
48
  componentOverrides: props.componentOverrides,
45
49
  controlProps: controlProps,
@@ -8,6 +8,7 @@ import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
8
8
  import { defaultGeneralPostChatSurveyPaneStyleProps } from "./common/defaultStyleProps/defaultgeneralPostChatSurveyPaneStyleProps";
9
9
  import { findAllFocusableElement } from "../../common/utils";
10
10
  import useChatContextStore from "../../hooks/useChatContextStore";
11
+ import isValidSurveyUrl from "./common/isValidSurveyUrl";
11
12
  const generateSurveyInviteLink = function (surveyInviteLink, isEmbed, locale, compact) {
12
13
  let showMultiLingual = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
13
14
  const surveyLink = `${surveyInviteLink}
@@ -45,6 +46,20 @@ export const PostChatSurveyPaneStateful = props => {
45
46
  surveyURL: ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.surveyURL) ?? surveyInviteLink,
46
47
  ...props.controlProps
47
48
  };
49
+ if (controlProps.surveyURL) {
50
+ if (!isValidSurveyUrl(controlProps.surveyURL)) {
51
+ TelemetryHelper.logLoadingEvent(LogLevel.ERROR, {
52
+ Event: TelemetryEvent.PostChatSurveyUrlValidationFailed,
53
+ Description: `${controlProps.surveyURL} is not a valid Survey URL`
54
+ });
55
+ controlProps.surveyURL = "";
56
+ } else {
57
+ TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
58
+ Event: TelemetryEvent.PostChatSurveyUrlValidationCompleted,
59
+ Description: `${controlProps.surveyURL} is a valid Survey URL`
60
+ });
61
+ }
62
+ }
48
63
 
49
64
  // Move focus to the first button
50
65
  useEffect(() => {
@@ -0,0 +1,21 @@
1
+ import { isNullOrEmptyString } from "../../../common/utils";
2
+ const validRootDomains = ["microsoft.com", "microsoft.us", "appsplatform.us", "powervirtualagents.cn"];
3
+ const isValidSurveyUrl = url => {
4
+ if (isNullOrEmptyString(url)) {
5
+ return false;
6
+ }
7
+ try {
8
+ const objectUrl = new URL(url);
9
+ if (!objectUrl.origin || objectUrl.origin === "null") {
10
+ return false;
11
+ }
12
+ const validDomain = validRootDomains.find(domain => objectUrl.origin.endsWith(domain));
13
+ if (validDomain) {
14
+ return true;
15
+ }
16
+ } catch (error) {
17
+ return false;
18
+ }
19
+ return false;
20
+ };
21
+ export default isValidSurveyUrl;
@@ -35,6 +35,7 @@ const convertTextToHtmlNode = text => {
35
35
 
36
36
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
37
  const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
38
+ var _htmlNode$tagName;
38
39
  const htmlNode = convertTextToHtmlNode(text);
39
40
  const aNodes = htmlNode.getElementsByTagName(HtmlAttributeNames.aTagName);
40
41
  if ((aNodes === null || aNodes === void 0 ? void 0 : aNodes.length) > 0) {
@@ -64,6 +65,7 @@ const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
64
65
  }
65
66
  }
66
67
  }
68
+ action = updateIn(action, [Constants.payload, Constants.activity, Constants.text], () => htmlNode.innerHTML);
67
69
  } catch (e) {
68
70
  let errorMessage = "Failed to apply action: ";
69
71
  try {
@@ -80,7 +82,11 @@ const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
80
82
  });
81
83
  }
82
84
  }
83
- action = updateIn(action, [Constants.payload, Constants.activity, Constants.text], () => htmlNode.innerHTML);
85
+
86
+ // if empty div tag after sanitization
87
+ if (((_htmlNode$tagName = htmlNode.tagName) === null || _htmlNode$tagName === void 0 ? void 0 : _htmlNode$tagName.toLowerCase()) === HtmlAttributeNames.div && htmlNode.children.length === 0 && htmlNode.innerHTML.trim() === "") {
88
+ action = updateIn(action, [Constants.payload, Constants.activity, Constants.text], () => "");
89
+ }
84
90
  return action;
85
91
  };
86
92
 
@@ -168,7 +168,7 @@ class TranscriptHTMLBuilder {
168
168
  <script>
169
169
  class Translator {
170
170
  static convertTranscriptMessageToActivity(message) {
171
- const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences} = message;
171
+ const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences, amsreferences} = message;
172
172
 
173
173
  //it's required to convert the id to a number, otherwise the webchat will not render the messages in the correct order
174
174
  // if the OrginalMessageId is not present, we can use the id as the sequence id, which is always present.
@@ -215,7 +215,7 @@ class TranscriptHTMLBuilder {
215
215
  }
216
216
 
217
217
  // Attachments
218
- if (amsReferences && amsMetadata) {
218
+ if ((amsReferences || amsreferences) && amsMetadata) {
219
219
  const metadata = JSON.parse(amsMetadata);
220
220
  const { fileName } = metadata[0];
221
221
  const text = \`${this.attachmentMessage}\${fileName}\`;
@@ -239,7 +239,7 @@ class TranscriptHTMLBuilder {
239
239
  // Message
240
240
  if (content) {
241
241
  // Adaptive card formatting
242
- if (content.includes('"text"') && content.includes('"attachments"') && content.includes('"suggestedActions"')) {
242
+ if (content.includes('"attachments"') || content.includes('"suggestedActions"')) {
243
243
  try {
244
244
  const partialActivity = JSON.parse(content);
245
245
  return {
@@ -672,13 +672,13 @@ const createChatTranscript = async function (transcript, facadeChatSDK) {
672
672
  };
673
673
  let messages = transcriptMessages.filter(message => {
674
674
  message.content = DOMPurify.sanitize(message.content);
675
- return message.content.length > 0;
675
+ return message;
676
676
  });
677
677
  if (renderAttachments) {
678
678
  messages = await Promise.all(transcriptMessages.map(async message => {
679
679
  // eslint-disable-line @typescript-eslint/no-explicit-any
680
680
  const {
681
- amsReferences,
681
+ amsReferences = message.amsreferences,
682
682
  amsMetadata
683
683
  } = message;
684
684
  if (amsReferences && amsMetadata) {
@@ -206,6 +206,8 @@ export declare enum TelemetryEvent {
206
206
  PostChatContextCallFailed = "PostChatContextCallFailed",
207
207
  PostChatSurveyLoadingPaneLoaded = "PostChatSurveyLoadingPaneLoaded",
208
208
  PostChatSurveyLoaded = "PostChatSurveyLoaded",
209
+ PostChatSurveyUrlValidationCompleted = "PostChatSurveyUrlValidationCompleted",
210
+ PostChatSurveyUrlValidationFailed = "PostChatSurveyUrlValidationFailed",
209
211
  ChatDisconnectThreadEventReceived = "ChatDisconnectThreadEventReceived",
210
212
  HiddenAdaptiveCardMessageReceived = "HiddenAdaptiveCardMessageReceived",
211
213
  EndingAdapterAfterDisconnectionError = "EndingAdapterAfterDisconnectionError",
@@ -0,0 +1,2 @@
1
+ declare const isValidSurveyUrl: (url: string) => boolean;
2
+ export default isValidSurveyUrl;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/omnichannel-chat-widget",
3
- "version": "1.7.7",
3
+ "version": "1.7.8-main.270960e",
4
4
  "description": "Microsoft Omnichannel Chat Widget",
5
5
  "main": "lib/cjs/index.js",
6
6
  "types": "lib/types/index.d.ts",