@xapp/chat-widget 1.49.4 → 1.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1696,7 +1696,7 @@ function getLeftArrowSvg() {
1696
1696
  React__default$1["default"].createElement("path", { d: "M 2.5 -15 L -2.5 0 L 2.5 15", stroke: "currentColor", strokeLinecap: "square", strokeWidth: "4px", fill: "none" })));
1697
1697
  }
1698
1698
  var ChevronLeft = function (props) {
1699
- return (React__default$1["default"].createElement("div", { onClick: props.onClick, className: "chevron" }, getLeftArrowSvg()));
1699
+ return (React__default$1["default"].createElement("button", { onClick: props.onClick, className: "chevron" }, getLeftArrowSvg()));
1700
1700
  };
1701
1701
 
1702
1702
  function getRightArrowSvg() {
@@ -1704,7 +1704,7 @@ function getRightArrowSvg() {
1704
1704
  React__default$1["default"].createElement("path", { d: "M -2.5 -15 L 2.5 0 L -2.5 15", stroke: "currentColor", strokeLinecap: "square", strokeWidth: "4px", fill: "none" })));
1705
1705
  }
1706
1706
  var ChevronRight = function (props) {
1707
- return (React__default$1["default"].createElement("div", { onClick: props.onClick, className: "chevron" }, getRightArrowSvg()));
1707
+ return (React__default$1["default"].createElement("button", { onClick: props.onClick, className: "chevron" }, getRightArrowSvg()));
1708
1708
  };
1709
1709
 
1710
1710
  var Carousel = function (props) {
@@ -2229,7 +2229,7 @@ var React__default = /*#__PURE__*/_interopDefaultLegacy$1(React);
2229
2229
  var IconButton = function (props) {
2230
2230
  var type = props.type || "button";
2231
2231
  var Icon = props.icon;
2232
- return (React__default["default"].createElement("button", { type: type, className: "xapp-search-icon-button ".concat(props.className || ""), onClick: props.onClick },
2232
+ return (React__default["default"].createElement("button", { type: type, tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, className: "xapp-search-icon-button ".concat(props.className || ""), onClick: props.onClick },
2233
2233
  React__default["default"].createElement("div", { className: "xapp-search-icon-button__content" },
2234
2234
  React__default["default"].createElement(Icon, null))));
2235
2235
  };
@@ -2433,7 +2433,7 @@ var RichText = function (props) {
2433
2433
  };
2434
2434
 
2435
2435
  var RichInput = function (props) {
2436
- var id = props.id, value = props.value, type = props.type, autoFocus = props.autoFocus, spellCheck = props.spellCheck, onChange = props.onChange, onInput = props.onInput, onKeyDown = props.onKeyDown, onSearch = props.onSearch;
2436
+ var id = props.id, value = props.value, type = props.type, autoFocus = props.autoFocus, spellCheck = props.spellCheck, tabIndex = props.tabIndex, onChange = props.onChange, onInput = props.onInput, onKeyDown = props.onKeyDown, onSearch = props.onSearch;
2437
2437
  var rich = value.formats.some(function (f) { return f.type === "inputText"; });
2438
2438
  var handleChange = React.useCallback(function (ev) {
2439
2439
  onChange({
@@ -2483,7 +2483,7 @@ var RichInput = function (props) {
2483
2483
  return undefined;
2484
2484
  }, [inputNode, onSearch]);
2485
2485
  return (React__default["default"].createElement("div", { className: "xappw-rich-input ".concat(props.className) }, rich ?
2486
- React__default["default"].createElement(RichText, { id: id, value: value, onChange: handleRichChange, onInput: handleRichInput, onKeyDown: handleKeyDown, className: "xappw-rich-input__input ".concat(props.className, "__input") }) : React__default["default"].createElement("input", { id: id, ref: inputRef, type: type, value: value.text, autoFocus: autoFocus, placeholder: props.placeholder, spellCheck: spellCheck, className: "xappw-rich-input__input ".concat(props.className, "__input"), onFocus: props.onFocus, onChange: handleChange, onInput: handleInput, onKeyDown: handleKeyDown })));
2486
+ React__default["default"].createElement(RichText, { id: id, value: value, onChange: handleRichChange, onInput: handleRichInput, onKeyDown: handleKeyDown, className: "xappw-rich-input__input ".concat(props.className, "__input") }) : React__default["default"].createElement("input", { id: id, ref: inputRef, type: type, value: value.text, autoComplete: "off", autoFocus: autoFocus, placeholder: props.placeholder, spellCheck: spellCheck, tabIndex: tabIndex ? Number(tabIndex) : 0, className: "xappw-rich-input__input ".concat(props.className, "__input"), onFocus: props.onFocus, onChange: handleChange, onInput: handleInput, onKeyDown: handleKeyDown })));
2487
2487
  };
2488
2488
 
2489
2489
  var SuggestionsGroupHeading = function (props) {
@@ -2862,6 +2862,15 @@ dist.useJsonFetch = useJsonFetch;
2862
2862
  var useSuggestionsFetch_1 = dist.useSuggestionsFetch = useSuggestionsFetch$1;
2863
2863
  var uuid_1 = dist.uuid = uuid;
2864
2864
 
2865
+ /**
2866
+ * Sends a POST to your STENTOR based server.
2867
+ *
2868
+ * @param data
2869
+ * @param url
2870
+ * @param key
2871
+ * @param signal
2872
+ * @returns
2873
+ */
2865
2874
  function postMessageToStentor(data, url, key, signal) {
2866
2875
  return __awaiter$1(this, void 0, void 0, function () {
2867
2876
  var body, response;
@@ -3104,6 +3113,7 @@ var StentorDirectChat = /** @class */ (function () {
3104
3113
  this.options = options;
3105
3114
  this.configurableMessages = options.configurableMessages;
3106
3115
  this.isNewSession = false;
3116
+ this.hooks = options.hooks;
3107
3117
  }
3108
3118
  StentorDirectChat.prototype.init = function (dispatch) {
3109
3119
  this.dispatch = dispatch;
@@ -3287,12 +3297,12 @@ var StentorDirectChat = /** @class */ (function () {
3287
3297
  StentorDirectChat.prototype.dispose = function () {
3288
3298
  };
3289
3299
  StentorDirectChat.prototype.postMessage = function (message) {
3290
- var _a, _b, _c, _d;
3300
+ var _a, _b, _c, _d, _e;
3291
3301
  return __awaiter$1(this, void 0, void 0, function () {
3292
3302
  var request, userId, sessionId, accessToken, attributes, now, permissionRequest, expired, text, granted, userProfile, isEmail, configurableMessages, botResponse, successResult, success, fail, i, timeout, responseMessage;
3293
3303
  var _this = this;
3294
- return __generator$1(this, function (_e) {
3295
- switch (_e.label) {
3304
+ return __generator$1(this, function (_f) {
3305
+ switch (_f.label) {
3296
3306
  case 0:
3297
3307
  userId = this._userId;
3298
3308
  sessionId = this._sessionId;
@@ -3414,7 +3424,7 @@ var StentorDirectChat = /** @class */ (function () {
3414
3424
  });
3415
3425
  }); };
3416
3426
  i = 1;
3417
- _e.label = 1;
3427
+ _f.label = 1;
3418
3428
  case 1:
3419
3429
  if (!(i < configurableMessages.length)) return [3 /*break*/, 4];
3420
3430
  timeout = configurableMessages[i - 1].delay * 1000;
@@ -3429,12 +3439,12 @@ var StentorDirectChat = /** @class */ (function () {
3429
3439
  .catch(fail.bind(this, i))];
3430
3440
  case 2:
3431
3441
  // We don't start typing IF we have a failure message displayed and we are waiting on the timeout
3432
- _e.sent();
3442
+ _f.sent();
3433
3443
  // If we have what we want, break the for loop
3434
3444
  if (successResult) {
3435
3445
  return [3 /*break*/, 4];
3436
3446
  }
3437
- _e.label = 3;
3447
+ _f.label = 3;
3438
3448
  case 3:
3439
3449
  i++;
3440
3450
  return [3 /*break*/, 1];
@@ -3458,6 +3468,9 @@ var StentorDirectChat = /** @class */ (function () {
3458
3468
  text: (botResponse === null || botResponse === void 0 ? void 0 : botResponse.hasOwnProperty("errorText")) ? botResponse.errorText : "The assistant is not responding right now. Please close the widget and open it again."
3459
3469
  };
3460
3470
  }
3471
+ if (typeof ((_e = this.hooks) === null || _e === void 0 ? void 0 : _e.onResponse) === "function") {
3472
+ this.hooks.onResponse(botResponse);
3473
+ }
3461
3474
  this.stopTyping();
3462
3475
  return [2 /*return*/, responseMessage];
3463
3476
  }
@@ -7192,12 +7205,13 @@ var ChatMenuItem = function (props) {
7192
7205
  var content = props.subtitle ? (React__default$1["default"].createElement("span", null,
7193
7206
  React__default$1["default"].createElement("div", null, props.label),
7194
7207
  React__default$1["default"].createElement("div", { className: "chat-menu-item--subtitle" }, props.subtitle))) : (React__default$1["default"].createElement("span", null, props.label));
7195
- return (React__default$1["default"].createElement("button", { type: "button", className: "chat-menu-item", onClick: handleClick }, content));
7208
+ return (React__default$1["default"].createElement("button", { type: "button", className: "chat-menu-item", tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, onClick: handleClick }, content));
7196
7209
  };
7197
7210
 
7198
7211
  var ChatMenu = function (props) {
7199
- var items = props.items;
7200
- return (React__default$1["default"].createElement("div", { className: "chat-menu ".concat(props.opened ? "chat-menu--opened" : "chat-menu--closed") }, items.map(function (item, i) {
7212
+ var items = props.items, opened = props.opened;
7213
+ var openFrom = props.openFrom || "bottom";
7214
+ return (React__default$1["default"].createElement("div", { className: "chat-menu-".concat(openFrom, " ").concat(opened ? "chat-menu-".concat(openFrom, "--opened") : "chat-menu-".concat(openFrom, "--closed")) }, items.map(function (item, i) {
7201
7215
  if (lib.isStandardMenuItem(item)) {
7202
7216
  return React__default$1["default"].createElement(ChatMenuItem, { key: i, onClick: props.onItemClick, label: item.label, subtitle: item.subtitle });
7203
7217
  }
@@ -7992,9 +8006,19 @@ var ChatBranding = function (props) {
7992
8006
  };
7993
8007
 
7994
8008
  var DrawerBars = function (props) {
7995
- return (React__default$1["default"].createElement("button", { className: "drawer-bars", onClick: props.onToggle },
7996
- React__default$1["default"].createElement("div", { className: "drawer-bar bar1" }),
7997
- React__default$1["default"].createElement("div", { className: "drawer-bar bar2" })));
8009
+ var bars = props.bars;
8010
+ // 0 is not a valid number of bars so a simple truthy check works here
8011
+ if (!bars) {
8012
+ bars = 2;
8013
+ }
8014
+ function getBars() {
8015
+ var barElements = [];
8016
+ for (var bar = 0; bar < bars; bar++) {
8017
+ barElements.push(React__default$1["default"].createElement("div", { className: "drawer-bar bar".concat(bar) }));
8018
+ }
8019
+ return barElements;
8020
+ }
8021
+ return (React__default$1["default"].createElement("button", { className: "drawer-bars", tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, "aria-label": "open menu", "aria-hidden": true, onClick: props.onToggle }, getBars()));
7998
8022
  };
7999
8023
 
8000
8024
  var CloseIcon = function () {
@@ -8016,13 +8040,14 @@ var SendIcon = function () {
8016
8040
  };
8017
8041
 
8018
8042
  var SendButton = function (props) {
8019
- return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null, !props.sendButtonIcon ? (React__default$1["default"].createElement(IconButton_1, { className: "xappw-send-button ".concat(props.className || ""), onClick: props.onClick, icon: SendIcon })) : (React__default$1["default"].createElement("span", { className: "xappw-custom-send-button", onClick: props.onClick },
8043
+ return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null, !props.sendButtonIcon ? (React__default$1["default"].createElement(IconButton_1, { className: "xappw-send-button ".concat(props.className || ""), tabIndex: props.tabIndex, onClick: props.onClick, icon: SendIcon })) : (React__default$1["default"].createElement("button", { className: "xappw-custom-send-button", tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, onClick: props.onClick },
8020
8044
  React__default$1["default"].createElement("img", { src: props.sendButtonIcon, alt: "Send button", draggable: false })))));
8021
8045
  };
8022
8046
 
8023
8047
  var Input = function (props) {
8024
- var value = props.value, placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, suggestion = props.suggestion, onChange = props.onChange, onSubmit = props.onSubmit, onSuggestionCommand = props.onSuggestionCommand;
8025
- var _a = React$1.useState(false), dragover = _a[0], setDragover = _a[1];
8048
+ var _a, _b;
8049
+ var value = props.value, placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, suggestion = props.suggestion, footerConfig = props.footerConfig, inputConfig = props.inputConfig, onChange = props.onChange, onSubmit = props.onSubmit, onSuggestionCommand = props.onSuggestionCommand;
8050
+ var _c = React$1.useState(false), dragover = _c[0], setDragover = _c[1];
8026
8051
  function onDragOver(event) {
8027
8052
  setDragover(true);
8028
8053
  event.preventDefault();
@@ -8042,7 +8067,7 @@ var Input = function (props) {
8042
8067
  var handleClear = React$1.useCallback(function () {
8043
8068
  onChange({
8044
8069
  text: "",
8045
- formats: []
8070
+ formats: [],
8046
8071
  });
8047
8072
  }, [onChange]);
8048
8073
  var handleKeyDown = React$1.useCallback(function (event) {
@@ -8067,14 +8092,17 @@ var Input = function (props) {
8067
8092
  }
8068
8093
  }
8069
8094
  }, [suggestion, onChange, onSuggestionCommand]);
8070
- return (React__default$1["default"].createElement("div", { className: "xappw-input-container ".concat(props.addClass, " ").concat(dragover ? "drag-drop-zone" : ""), onDrop: onDrop, onDragOver: onDragOver, onDragLeave: onDragLeave },
8095
+ return (React__default$1["default"].createElement("div", { className: "xappw-input-container ".concat(props.addClass, " ").concat(dragover ? "drag-drop-zone" : ""), "aria-label": "To start typing click on rounded rectangle at the bottom of widget. To send your message click icon on right side of rounded rectangle at the bottom of widget" +
8096
+ value.text
8097
+ ? "To clear ipnut field click on clear icon on the left of send button"
8098
+ : "", "aria-hidden": true, onDrop: onDrop, onDragOver: onDragOver, onDragLeave: onDragLeave },
8071
8099
  React__default$1["default"].createElement("form", { className: "xappw-input-form", onSubmit: handleOnSubmit },
8072
- React__default$1["default"].createElement(RichInput_1, { key: "input", id: "chatWidgetInput", className: "xappw-input", placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : "Type your question here...", onInput: onChange, onChange: onChange, onKeyDown: handleKeyDown,
8100
+ React__default$1["default"].createElement(RichInput_1, { key: "input", id: "chatWidgetInput", className: "xappw-input", placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : "Type your question here...", tabIndex: inputConfig === null || inputConfig === void 0 ? void 0 : inputConfig.tabIndex, onInput: onChange, onChange: onChange, onKeyDown: handleKeyDown,
8073
8101
  // onFocus={onFocus}
8074
8102
  value: value, spellCheck: true }),
8075
8103
  React__default$1["default"].createElement("div", { className: "xappw-input-form__buttons" },
8076
- value.text && React__default$1["default"].createElement(IconButton_1, { icon: CloseIcon, className: "xappw-input-form__btn", onClick: handleClear }),
8077
- React__default$1["default"].createElement(SendButton, { className: "xappw-input-form__btn", sendButtonIcon: sendButtonIcon, onClick: handleOnSubmit })))));
8104
+ value.text && (React__default$1["default"].createElement(IconButton_1, { icon: CloseIcon, tabIndex: (_a = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.clearButton) === null || _a === void 0 ? void 0 : _a.tabIndex, className: "xappw-input-form__btn", onClick: handleClear })),
8105
+ React__default$1["default"].createElement(SendButton, { className: "xappw-input-form__btn", sendButtonIcon: sendButtonIcon, tabIndex: (_b = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.sendButton) === null || _b === void 0 ? void 0 : _b.tabIndex, onClick: handleOnSubmit })))));
8078
8106
  };
8079
8107
 
8080
8108
  function createActions(onItemUse) {
@@ -8115,22 +8143,26 @@ var Suggestions = function (props) {
8115
8143
  };
8116
8144
 
8117
8145
  var ChatFooter = function (props) {
8118
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
8119
- var placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, onSubmit = props.onSubmit;
8120
- var _k = React$1.useState(false), drawer = _k[0], setDrawerState = _k[1]; // false initially
8121
- var _l = React$1.useState(), suggestionSearch = _l[0], setSuggestionSearch = _l[1];
8146
+ var _a, _b, _c, _d;
8147
+ var placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, footerConfig = props.footerConfig, menuConfig = props.menuConfig, inputConfig = props.inputConfig, onSubmit = props.onSubmit;
8148
+ var _e = React$1.useState(false), drawerOpen = _e[0], setDrawerState = _e[1]; // false initially
8149
+ var _f = React$1.useState(), suggestionSearch = _f[0], setSuggestionSearch = _f[1];
8122
8150
  var contexts = reactRedux.useSelector(function (state) { return state.activeContexts; });
8123
8151
  var suggestions = useSuggestions(suggestionSearch, contexts);
8124
- var menuItemsRaw = (_b = (_a = useWidgetEnv()) === null || _a === void 0 ? void 0 : _a.menu) === null || _b === void 0 ? void 0 : _b.items;
8152
+ var menuPosition = (menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.menuButtonLocation) || "FOOTER";
8153
+ var showMenu = menuPosition === "FOOTER";
8154
+ var menuItemsRaw = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.items; // useWidgetEnv()?.menu?.items;
8155
+ var menuItemsTabIndex = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.itemsTabIndex; // useWidgetEnv()?.menu?.itemsTabIndex;
8156
+ var menuButtonTabIndex = (_a = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.button) === null || _a === void 0 ? void 0 : _a.tabIndex; // useWidgetEnv()?.menu?.button?.tabIndex;
8125
8157
  var menuItems = React$1.useMemo(function () { return menuItemsRaw ? menuItemsRaw : []; }, [menuItemsRaw]);
8126
- var branding = (_e = (_d = (_c = useWidgetEnv()) === null || _c === void 0 ? void 0 : _c.footer) === null || _d === void 0 ? void 0 : _d.branding) === null || _e === void 0 ? void 0 : _e.text;
8127
- var brandingEnabled = (_h = (_g = (_f = useWidgetEnv()) === null || _f === void 0 ? void 0 : _f.footer) === null || _g === void 0 ? void 0 : _g.branding) === null || _h === void 0 ? void 0 : _h.enabled;
8128
- var _m = React$1.useState({
8158
+ var branding = (_b = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.branding) === null || _b === void 0 ? void 0 : _b.text; // useWidgetEnv()?.footer?.branding?.text;
8159
+ var brandingEnabled = (_c = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.branding) === null || _c === void 0 ? void 0 : _c.enabled; // useWidgetEnv()?.footer?.branding?.enabled;
8160
+ var _g = React$1.useState({
8129
8161
  text: "",
8130
8162
  formats: []
8131
- }), input = _m[0], setInput = _m[1];
8163
+ }), input = _g[0], setInput = _g[1];
8132
8164
  function toggleDrawer() {
8133
- var newDrawer = !drawer;
8165
+ var newDrawer = !drawerOpen;
8134
8166
  setDrawerState(newDrawer);
8135
8167
  set$1("drawer", newDrawer);
8136
8168
  }
@@ -8143,6 +8175,7 @@ var ChatFooter = function (props) {
8143
8175
  props.onChange(val.text);
8144
8176
  setSuggestionSearch(val.text);
8145
8177
  }
8178
+ // Clears out suggestion and input text
8146
8179
  var handleSubmit = React$1.useCallback(function (message) {
8147
8180
  setSuggestionSearch("");
8148
8181
  setInput({
@@ -8158,14 +8191,14 @@ var ChatFooter = function (props) {
8158
8191
  setInput(data);
8159
8192
  setSuggestionSearch(data.text);
8160
8193
  }, []);
8161
- return (React__default$1["default"].createElement("div", { className: "chat-footer" },
8162
- menuItems.length ?
8194
+ return (React__default$1["default"].createElement("div", { className: "chat-footer", "aria-label": menuItems.length ? "to open menu click a button above the rounded rectangle at the bottom of widget" : "", "aria-hidden": true },
8195
+ showMenu && menuItems.length ?
8163
8196
  React__default$1["default"].createElement(React__default$1["default"].Fragment, null,
8164
- drawer && React__default$1["default"].createElement(ChatMenu, { opened: drawer, onItemClick: handleMenuItem, items: menuItems }),
8197
+ drawerOpen ? React__default$1["default"].createElement(ChatMenu, { opened: drawerOpen, tabIndex: menuItemsTabIndex, onItemClick: handleMenuItem, items: menuItems }) : React__default$1["default"].createElement(React__default$1["default"].Fragment, null),
8165
8198
  React__default$1["default"].createElement("div", { className: "chat-footer__menu-icon" },
8166
- React__default$1["default"].createElement(DrawerBars, { onToggle: toggleDrawer }))) : React__default$1["default"].createElement(React__default$1["default"].Fragment, null),
8167
- ((_j = suggestions.suggestions) === null || _j === void 0 ? void 0 : _j.length) > 0 && React__default$1["default"].createElement(Suggestions, { className: "xappw-chat-footer__suggestions", data: suggestions.suggestions, index: suggestions.index, onItemClick: handleItemClick, onItemUse: handleItemUse }),
8168
- React__default$1["default"].createElement(Input, { addClass: "chat-footer__input " + (props.isChatting && props.visible ? "visible" : ""), suggestion: suggestions.item, value: input, placeholder: placeholder, sendButtonIcon: sendButtonIcon, onSubmit: handleSubmit, onChange: handleChange, onSuggestionCommand: suggestions.execute,
8199
+ React__default$1["default"].createElement(DrawerBars, { tabIndex: menuButtonTabIndex, onToggle: toggleDrawer }))) : React__default$1["default"].createElement(React__default$1["default"].Fragment, null),
8200
+ ((_d = suggestions.suggestions) === null || _d === void 0 ? void 0 : _d.length) > 0 && React__default$1["default"].createElement(Suggestions, { className: "xappw-chat-footer__suggestions", data: suggestions.suggestions, index: suggestions.index, onItemClick: handleItemClick, onItemUse: handleItemUse }),
8201
+ React__default$1["default"].createElement(Input, { addClass: "chat-footer__input " + (props.isChatting && props.visible ? "visible" : ""), suggestion: suggestions.item, value: input, placeholder: placeholder, sendButtonIcon: sendButtonIcon, footerConfig: footerConfig, inputConfig: inputConfig, onSubmit: handleSubmit, onChange: handleChange, onSuggestionCommand: suggestions.execute,
8169
8202
  // onFocus={this.inputOnFocus}
8170
8203
  onFileUpload: props.onFileUpload }),
8171
8204
  brandingEnabled && React__default$1["default"].createElement(ChatBranding, { text: branding })));
@@ -30689,46 +30722,75 @@ var ServerOffline = function () {
30689
30722
  };
30690
30723
 
30691
30724
  var CancelButton = function (props) {
30692
- return React__default$1["default"].createElement("button", { id: "xapp-widget-close", className: "cancel-button", onClick: props.onClick });
30725
+ return (React__default$1["default"].createElement("button", { id: "xapp-widget-close", "aria-label": "close widget", "aria-hidden": true, tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, className: "cancel-button", onClick: props.onClick }));
30693
30726
  };
30694
30727
 
30695
30728
  var MinimizeButton = function (props) {
30696
- return (React__default$1["default"].createElement("button", { id: "xapp-widget-minimize", className: "minimize-button ".concat(props.showInRight ? "positionRight" : ""), onClick: props.onClick }));
30729
+ return (React__default$1["default"].createElement("button", { id: "xapp-widget-minimize", "aria-label": "minimize widget", "aria-hidden": true, tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, className: "minimize-button ".concat(props.showInRight ? "positionRight" : ""), onClick: props.onClick }));
30697
30730
  };
30698
30731
 
30699
30732
  var RefreshButton = function (props) {
30700
- return (React__default$1["default"].createElement("button", { id: "xapp-widget-refresh", className: "refresh-button ".concat(props.showInRight ? "positionRight" : props.showInLeft ? "positionLeft" : ""), onClick: props.onClick }));
30733
+ return (React__default$1["default"].createElement("button", { id: "xapp-widget-refresh", "aria-label": "refresh chat", "aria-hidden": true, tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, className: "refresh-button ".concat(props.showInRight ? "positionRight" : props.showInLeft ? "positionLeft" : ""), onClick: props.onClick }));
30701
30734
  };
30702
30735
 
30703
30736
  var DEFAULT_STATUS_CONFIG = {
30704
30737
  online: "Virtual Assistant",
30705
30738
  offline: "Leave us a message",
30706
30739
  away: "We're away!",
30707
- connecting: "Connecting..."
30740
+ connecting: "Connecting...",
30708
30741
  };
30709
30742
  function getStatusText(status, config) {
30710
30743
  var _a, _b, _c, _d;
30711
30744
  switch (status) {
30712
- case "online": return (_a = config === null || config === void 0 ? void 0 : config.online) !== null && _a !== void 0 ? _a : DEFAULT_STATUS_CONFIG.online;
30713
- case "offline": return (_b = config === null || config === void 0 ? void 0 : config.offline) !== null && _b !== void 0 ? _b : DEFAULT_STATUS_CONFIG.offline;
30714
- case "away": return (_c = config === null || config === void 0 ? void 0 : config.away) !== null && _c !== void 0 ? _c : DEFAULT_STATUS_CONFIG.away;
30715
- default: return (_d = config === null || config === void 0 ? void 0 : config.connecting) !== null && _d !== void 0 ? _d : DEFAULT_STATUS_CONFIG.connecting;
30745
+ case "online":
30746
+ return (_a = config === null || config === void 0 ? void 0 : config.online) !== null && _a !== void 0 ? _a : DEFAULT_STATUS_CONFIG.online;
30747
+ case "offline":
30748
+ return (_b = config === null || config === void 0 ? void 0 : config.offline) !== null && _b !== void 0 ? _b : DEFAULT_STATUS_CONFIG.offline;
30749
+ case "away":
30750
+ return (_c = config === null || config === void 0 ? void 0 : config.away) !== null && _c !== void 0 ? _c : DEFAULT_STATUS_CONFIG.away;
30751
+ default:
30752
+ return (_d = config === null || config === void 0 ? void 0 : config.connecting) !== null && _d !== void 0 ? _d : DEFAULT_STATUS_CONFIG.connecting;
30716
30753
  }
30717
30754
  }
30718
- var StatusContainer = function (props) {
30719
- var _a, _b, _c, _d, _e, _f, _g;
30720
- return (React__default$1["default"].createElement("div", { className: "status-container" },
30721
- React__default$1["default"].createElement("div", { className: "status-container__avatar" },
30722
- React__default$1["default"].createElement(Avatar, { entity: props.agent })),
30723
- React__default$1["default"].createElement("div", { className: "".concat("status-text", " ").concat(((_a = props.config) === null || _a === void 0 ? void 0 : _a.alignTextCenter) ? "status-text-positionCenter" : "status-text-positionLeft") },
30724
- React__default$1["default"].createElement("span", { className: "status-text-title" }, getStatusText(props.accountStatus, (_b = props.config) === null || _b === void 0 ? void 0 : _b.status)),
30725
- ((_d = (_c = props.config) === null || _c === void 0 ? void 0 : _c.subtitle) === null || _d === void 0 ? void 0 : _d.enabled) && React__default$1["default"].createElement("span", { className: "status-text-subtitle" }, (_g = (_f = (_e = props.config) === null || _e === void 0 ? void 0 : _e.subtitle) === null || _f === void 0 ? void 0 : _f.text) !== null && _g !== void 0 ? _g : "")),
30726
- props.canRefresh &&
30727
- React__default$1["default"].createElement(RefreshButton, { onClick: props.refreshOnClick, showInLeft: props.canMinimize && props.canCancel, showInRight: !props.canMinimize && !props.canCancel }),
30728
- props.canMinimize &&
30729
- React__default$1["default"].createElement(MinimizeButton, { onClick: props.minimizeOnClick, showInRight: !props.canCancel }),
30730
- props.canCancel &&
30731
- React__default$1["default"].createElement(CancelButton, { onClick: props.cancelOnClick })));
30755
+ var refreshButtonAriaLabel = "To refresh chat click on clockwise gapped circle arrow icon in top right side of widget. ";
30756
+ var minimizeButtonAriaLabel = "To minimize widget click on minus icon in top right side of widget. ";
30757
+ var closeButtonAriaLabel = "To close widget click on close icon in top right side of widget.";
30758
+ var ChatHeader = function (props) {
30759
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
30760
+ var menuConfig = props.menuConfig, onSubmit = props.onSubmit;
30761
+ var _q = React$1.useState(false), drawerOpen = _q[0], setDrawerState = _q[1]; // false initially
30762
+ var menuPosition = (menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.menuButtonLocation) || "FOOTER";
30763
+ var showMenu = menuPosition === "HEADER_LEFT";
30764
+ var menuItemsRaw = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.items; // useWidgetEnv()?.menu?.items;
30765
+ var menuItemsTabIndex = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.itemsTabIndex; // useWidgetEnv()?.menu?.itemsTabIndex;
30766
+ var menuButtonTabIndex = (_a = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.button) === null || _a === void 0 ? void 0 : _a.tabIndex; // useWidgetEnv()?.menu?.button?.tabIndex;
30767
+ var menuItems = React$1.useMemo(function () { return menuItemsRaw ? menuItemsRaw : []; }, [menuItemsRaw]);
30768
+ function toggleDrawer() {
30769
+ var newDrawer = !drawerOpen;
30770
+ setDrawerState(newDrawer);
30771
+ set$1("drawer", newDrawer);
30772
+ }
30773
+ function handleMenuItem(label) {
30774
+ setDrawerState(false);
30775
+ onSubmit(label);
30776
+ }
30777
+ return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null,
30778
+ React__default$1["default"].createElement("div", { className: "status-container", "aria-label": props.canRefresh ? refreshButtonAriaLabel : "" + props.canMinimize ? minimizeButtonAriaLabel : "" + props.canCancel ? closeButtonAriaLabel : "", "aria-hidden": true },
30779
+ showMenu && menuItems.length ? (React__default$1["default"].createElement(React__default$1["default"].Fragment, null,
30780
+ React__default$1["default"].createElement("div", { className: "chat-footer__menu-icon" },
30781
+ React__default$1["default"].createElement(DrawerBars, { bars: 3, tabIndex: menuButtonTabIndex, onToggle: toggleDrawer })))) : React__default$1["default"].createElement(React__default$1["default"].Fragment, null),
30782
+ React__default$1["default"].createElement("div", { className: "status-container__avatar" },
30783
+ React__default$1["default"].createElement(Avatar, { entity: props.agent })),
30784
+ React__default$1["default"].createElement("div", { className: "".concat("status-text", " ").concat(((_b = props.config) === null || _b === void 0 ? void 0 : _b.alignTextCenter)
30785
+ ? "status-text-positionCenter"
30786
+ : "status-text-positionLeft") },
30787
+ React__default$1["default"].createElement("span", { className: "status-text-title" }, getStatusText(props.accountStatus, (_c = props.config) === null || _c === void 0 ? void 0 : _c.status)),
30788
+ ((_e = (_d = props.config) === null || _d === void 0 ? void 0 : _d.subtitle) === null || _e === void 0 ? void 0 : _e.enabled) && (React__default$1["default"].createElement("span", { className: "status-text-subtitle" }, (_h = (_g = (_f = props.config) === null || _f === void 0 ? void 0 : _f.subtitle) === null || _g === void 0 ? void 0 : _g.text) !== null && _h !== void 0 ? _h : ""))),
30789
+ props.canRefresh && (React__default$1["default"].createElement(RefreshButton, { onClick: props.refreshOnClick, tabIndex: (_k = (_j = props.config) === null || _j === void 0 ? void 0 : _j.actions) === null || _k === void 0 ? void 0 : _k.refreshTabIndex, showInLeft: props.canMinimize && props.canCancel, showInRight: !props.canMinimize && !props.canCancel })),
30790
+ props.canMinimize && (React__default$1["default"].createElement(MinimizeButton, { onClick: props.minimizeOnClick, tabIndex: (_m = (_l = props.config) === null || _l === void 0 ? void 0 : _l.actions) === null || _m === void 0 ? void 0 : _m.minimizeTabIndex, showInRight: !props.canCancel })),
30791
+ props.canCancel && (React__default$1["default"].createElement(CancelButton, { onClick: props.cancelOnClick, tabIndex: (_p = (_o = props.config) === null || _o === void 0 ? void 0 : _o.actions) === null || _p === void 0 ? void 0 : _p.cancelTabIndex }))),
30792
+ drawerOpen ? (React__default$1["default"].createElement("div", { className: "xa-chat-menu-container" },
30793
+ React__default$1["default"].createElement(ChatMenu, { openFrom: "left", opened: drawerOpen, tabIndex: menuItemsTabIndex, onItemClick: handleMenuItem, items: menuItems }))) : React__default$1["default"].createElement(React__default$1["default"].Fragment, null)));
30732
30794
  };
30733
30795
 
30734
30796
  function buildStyleContent(theme) {
@@ -31019,7 +31081,8 @@ var ChatWidgetWrapper = function (props) {
31019
31081
  displayName: rawConfig.botName,
31020
31082
  avatarPath: rawConfig.avatarUrl,
31021
31083
  },
31022
- configurableMessages: configurableMessages
31084
+ configurableMessages: configurableMessages,
31085
+ hooks: rawConfig.hooks
31023
31086
  };
31024
31087
  }, [token, rawConfig]);
31025
31088
  var chatServer = useChatServer(connection, options);
@@ -31028,7 +31091,7 @@ var ChatWidgetWrapper = function (props) {
31028
31091
  React__default$1["default"].createElement(ChatWidget, __assign({}, props)))));
31029
31092
  };
31030
31093
  var ChatWidget = function (props) {
31031
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
31094
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
31032
31095
  var innerDispatch = useChatDispatch();
31033
31096
  var dispatch = useChatServerDispatch();
31034
31097
  // From Redux
@@ -31048,8 +31111,8 @@ var ChatWidget = function (props) {
31048
31111
  canCancel = !dockedMode && !staticMode;
31049
31112
  }
31050
31113
  // Our state - pull from storage
31051
- var _v = React$1.useState((!canMinimize && !canCancel) || !!get("visible") || (((_k = props.config) === null || _k === void 0 ? void 0 : _k.autoOpenOnWidth) && window.matchMedia("(min-width: ".concat((_l = props.config) === null || _l === void 0 ? void 0 : _l.autoOpenOnWidth, ")")).matches)), visible = _v[0], setVisibleState = _v[1];
31052
- var _w = React$1.useState(false), typing = _w[0], setTypingState = _w[1]; // false initially
31114
+ var _x = React$1.useState((!canMinimize && !canCancel) || !!get("visible") || (((_k = props.config) === null || _k === void 0 ? void 0 : _k.autoOpenOnWidth) && window.matchMedia("(min-width: ".concat((_l = props.config) === null || _l === void 0 ? void 0 : _l.autoOpenOnWidth, ")")).matches)), visible = _x[0], setVisibleState = _x[1];
31115
+ var _y = React$1.useState(false), typing = _y[0], setTypingState = _y[1]; // false initially
31053
31116
  var chatServer = React$1.useContext(ChatServerContext);
31054
31117
  var setVisible = React$1.useCallback(function (newVisible) {
31055
31118
  if (staticMode) {
@@ -31185,13 +31248,13 @@ var ChatWidget = function (props) {
31185
31248
  return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null,
31186
31249
  React__default$1["default"].createElement("div", { className: "widget-container ".concat(modeClass, " ").concat(getVisibilityClass()) },
31187
31250
  React__default$1["default"].createElement(WidgetStylesheet, { theme: config === null || config === void 0 ? void 0 : config.theme }),
31188
- React__default$1["default"].createElement(StatusContainer, { accountStatus: chatState.accountStatus, refreshOnClick: refreshOnClick, minimizeOnClick: minimizeOnClick, cancelOnClick: cancelOnClick, agent: (_o = chatState.agents["agent:robot"]) === null || _o === void 0 ? void 0 : _o.user, canRefresh: canRefresh, canMinimize: canMinimize, canCancel: canCancel, config: config === null || config === void 0 ? void 0 : config.header }),
31251
+ React__default$1["default"].createElement(ChatHeader, { accountStatus: chatState.accountStatus, refreshOnClick: refreshOnClick, minimizeOnClick: minimizeOnClick, cancelOnClick: cancelOnClick, agent: (_o = chatState.agents["agent:robot"]) === null || _o === void 0 ? void 0 : _o.user, canRefresh: canRefresh, canMinimize: canMinimize, canCancel: canCancel, config: config === null || config === void 0 ? void 0 : config.header, menuConfig: config.menu, onSubmit: handleOnSubmit }),
31189
31252
  React__default$1["default"].createElement(MessageList, { visible: visible, queuePosition: chatState.queuePosition, isChatting: chatState.isChatting, isOffline: isOffline, messages: messages, agents: chatState.agents, lastRatingRequestTimestamp: chatState.lastRatingRequestTimestamp, hasRating: chatState.hasRating, visitorId: chatState.visitorId, messageMiddleware: props.messageMiddleware, textTypingStatusEnabled: (_q = (_p = props.config) === null || _p === void 0 ? void 0 : _p.typingStatus) === null || _q === void 0 ? void 0 : _q.textTypingStatusEnabled, onSend: handleSendMessage, onWrite: handleWriteMessage, onOpenUrl: handleOpenUrl }),
31190
31253
  React__default$1["default"].createElement("div", { className: "spinner-container ".concat(visible && connectionStatus === "pending" ? "visible" : "") },
31191
31254
  React__default$1["default"].createElement("div", { className: "spinner" })),
31192
31255
  connectionStatus === "offline" && React__default$1["default"].createElement(ServerOffline, null),
31193
- React__default$1["default"].createElement(ChatFooter, { isChatting: chatState.isChatting, placeholder: (_r = config === null || config === void 0 ? void 0 : config.input) === null || _r === void 0 ? void 0 : _r.placeholder, sendButtonIcon: (_t = (_s = config === null || config === void 0 ? void 0 : config.footer) === null || _s === void 0 ? void 0 : _s.sendButton) === null || _t === void 0 ? void 0 : _t.icon, visible: visible, onChange: handleOnChange, onSubmit: handleOnSubmit, onFileUpload: handleFileUpload })),
31194
- React__default$1["default"].createElement(ChatButton, { addClass: getVisibilityClass(), onClick: chatButtonOnClick, config: (_u = props.config) === null || _u === void 0 ? void 0 : _u.cta, visible: visible })));
31256
+ React__default$1["default"].createElement(ChatFooter, { isChatting: chatState.isChatting, placeholder: (_r = config === null || config === void 0 ? void 0 : config.input) === null || _r === void 0 ? void 0 : _r.placeholder, sendButtonIcon: (_t = (_s = config === null || config === void 0 ? void 0 : config.footer) === null || _s === void 0 ? void 0 : _s.sendButton) === null || _t === void 0 ? void 0 : _t.icon, visible: visible, menuConfig: props.config.menu, footerConfig: (_u = props.config) === null || _u === void 0 ? void 0 : _u.footer, inputConfig: (_v = props.config) === null || _v === void 0 ? void 0 : _v.input, onChange: handleOnChange, onSubmit: handleOnSubmit, onFileUpload: handleFileUpload })),
31257
+ React__default$1["default"].createElement(ChatButton, { addClass: getVisibilityClass(), onClick: chatButtonOnClick, config: (_w = props.config) === null || _w === void 0 ? void 0 : _w.cta, visible: visible })));
31195
31258
  };
31196
31259
 
31197
31260
  function tryParseJson(str) {
@@ -31320,7 +31383,7 @@ function resetReducer(state) {
31320
31383
  })), { connection: __assign(__assign({}, state.connection), { greetingRequested: false, nonce: uuid_1() }), visitor: state.visitor, visitorId: state.visitorId });
31321
31384
  }
31322
31385
 
31323
- // todo: create reducer (requires redux-thunk dependncy)
31386
+ // todo: create reducer (requires redux-thunk dependency)
31324
31387
  function appendMessageToState(state, msg) {
31325
31388
  state.chats = joinMessages(state.chats, msg);
31326
31389
  if (msg.type === "chat.msg") {