@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.es.js CHANGED
@@ -1688,7 +1688,7 @@ function getLeftArrowSvg() {
1688
1688
  React$1.createElement("path", { d: "M 2.5 -15 L -2.5 0 L 2.5 15", stroke: "currentColor", strokeLinecap: "square", strokeWidth: "4px", fill: "none" })));
1689
1689
  }
1690
1690
  var ChevronLeft = function (props) {
1691
- return (React$1.createElement("div", { onClick: props.onClick, className: "chevron" }, getLeftArrowSvg()));
1691
+ return (React$1.createElement("button", { onClick: props.onClick, className: "chevron" }, getLeftArrowSvg()));
1692
1692
  };
1693
1693
 
1694
1694
  function getRightArrowSvg() {
@@ -1696,7 +1696,7 @@ function getRightArrowSvg() {
1696
1696
  React$1.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 ChevronRight = function (props) {
1699
- return (React$1.createElement("div", { onClick: props.onClick, className: "chevron" }, getRightArrowSvg()));
1699
+ return (React$1.createElement("button", { onClick: props.onClick, className: "chevron" }, getRightArrowSvg()));
1700
1700
  };
1701
1701
 
1702
1702
  var Carousel = function (props) {
@@ -2221,7 +2221,7 @@ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
2221
2221
  var IconButton = function (props) {
2222
2222
  var type = props.type || "button";
2223
2223
  var Icon = props.icon;
2224
- return (React__default["default"].createElement("button", { type: type, className: "xapp-search-icon-button ".concat(props.className || ""), onClick: props.onClick },
2224
+ 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 },
2225
2225
  React__default["default"].createElement("div", { className: "xapp-search-icon-button__content" },
2226
2226
  React__default["default"].createElement(Icon, null))));
2227
2227
  };
@@ -2425,7 +2425,7 @@ var RichText = function (props) {
2425
2425
  };
2426
2426
 
2427
2427
  var RichInput = function (props) {
2428
- 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;
2428
+ 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;
2429
2429
  var rich = value.formats.some(function (f) { return f.type === "inputText"; });
2430
2430
  var handleChange = React.useCallback(function (ev) {
2431
2431
  onChange({
@@ -2475,7 +2475,7 @@ var RichInput = function (props) {
2475
2475
  return undefined;
2476
2476
  }, [inputNode, onSearch]);
2477
2477
  return (React__default["default"].createElement("div", { className: "xappw-rich-input ".concat(props.className) }, rich ?
2478
- 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 })));
2478
+ 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 })));
2479
2479
  };
2480
2480
 
2481
2481
  var SuggestionsGroupHeading = function (props) {
@@ -2854,6 +2854,15 @@ dist.useJsonFetch = useJsonFetch;
2854
2854
  var useSuggestionsFetch_1 = dist.useSuggestionsFetch = useSuggestionsFetch$1;
2855
2855
  var uuid_1 = dist.uuid = uuid;
2856
2856
 
2857
+ /**
2858
+ * Sends a POST to your STENTOR based server.
2859
+ *
2860
+ * @param data
2861
+ * @param url
2862
+ * @param key
2863
+ * @param signal
2864
+ * @returns
2865
+ */
2857
2866
  function postMessageToStentor(data, url, key, signal) {
2858
2867
  return __awaiter$1(this, void 0, void 0, function () {
2859
2868
  var body, response;
@@ -3096,6 +3105,7 @@ var StentorDirectChat = /** @class */ (function () {
3096
3105
  this.options = options;
3097
3106
  this.configurableMessages = options.configurableMessages;
3098
3107
  this.isNewSession = false;
3108
+ this.hooks = options.hooks;
3099
3109
  }
3100
3110
  StentorDirectChat.prototype.init = function (dispatch) {
3101
3111
  this.dispatch = dispatch;
@@ -3279,12 +3289,12 @@ var StentorDirectChat = /** @class */ (function () {
3279
3289
  StentorDirectChat.prototype.dispose = function () {
3280
3290
  };
3281
3291
  StentorDirectChat.prototype.postMessage = function (message) {
3282
- var _a, _b, _c, _d;
3292
+ var _a, _b, _c, _d, _e;
3283
3293
  return __awaiter$1(this, void 0, void 0, function () {
3284
3294
  var request, userId, sessionId, accessToken, attributes, now, permissionRequest, expired, text, granted, userProfile, isEmail, configurableMessages, botResponse, successResult, success, fail, i, timeout, responseMessage;
3285
3295
  var _this = this;
3286
- return __generator$1(this, function (_e) {
3287
- switch (_e.label) {
3296
+ return __generator$1(this, function (_f) {
3297
+ switch (_f.label) {
3288
3298
  case 0:
3289
3299
  userId = this._userId;
3290
3300
  sessionId = this._sessionId;
@@ -3406,7 +3416,7 @@ var StentorDirectChat = /** @class */ (function () {
3406
3416
  });
3407
3417
  }); };
3408
3418
  i = 1;
3409
- _e.label = 1;
3419
+ _f.label = 1;
3410
3420
  case 1:
3411
3421
  if (!(i < configurableMessages.length)) return [3 /*break*/, 4];
3412
3422
  timeout = configurableMessages[i - 1].delay * 1000;
@@ -3421,12 +3431,12 @@ var StentorDirectChat = /** @class */ (function () {
3421
3431
  .catch(fail.bind(this, i))];
3422
3432
  case 2:
3423
3433
  // We don't start typing IF we have a failure message displayed and we are waiting on the timeout
3424
- _e.sent();
3434
+ _f.sent();
3425
3435
  // If we have what we want, break the for loop
3426
3436
  if (successResult) {
3427
3437
  return [3 /*break*/, 4];
3428
3438
  }
3429
- _e.label = 3;
3439
+ _f.label = 3;
3430
3440
  case 3:
3431
3441
  i++;
3432
3442
  return [3 /*break*/, 1];
@@ -3450,6 +3460,9 @@ var StentorDirectChat = /** @class */ (function () {
3450
3460
  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."
3451
3461
  };
3452
3462
  }
3463
+ if (typeof ((_e = this.hooks) === null || _e === void 0 ? void 0 : _e.onResponse) === "function") {
3464
+ this.hooks.onResponse(botResponse);
3465
+ }
3453
3466
  this.stopTyping();
3454
3467
  return [2 /*return*/, responseMessage];
3455
3468
  }
@@ -7184,12 +7197,13 @@ var ChatMenuItem = function (props) {
7184
7197
  var content = props.subtitle ? (React$1.createElement("span", null,
7185
7198
  React$1.createElement("div", null, props.label),
7186
7199
  React$1.createElement("div", { className: "chat-menu-item--subtitle" }, props.subtitle))) : (React$1.createElement("span", null, props.label));
7187
- return (React$1.createElement("button", { type: "button", className: "chat-menu-item", onClick: handleClick }, content));
7200
+ return (React$1.createElement("button", { type: "button", className: "chat-menu-item", tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, onClick: handleClick }, content));
7188
7201
  };
7189
7202
 
7190
7203
  var ChatMenu = function (props) {
7191
- var items = props.items;
7192
- return (React$1.createElement("div", { className: "chat-menu ".concat(props.opened ? "chat-menu--opened" : "chat-menu--closed") }, items.map(function (item, i) {
7204
+ var items = props.items, opened = props.opened;
7205
+ var openFrom = props.openFrom || "bottom";
7206
+ return (React$1.createElement("div", { className: "chat-menu-".concat(openFrom, " ").concat(opened ? "chat-menu-".concat(openFrom, "--opened") : "chat-menu-".concat(openFrom, "--closed")) }, items.map(function (item, i) {
7193
7207
  if (lib.isStandardMenuItem(item)) {
7194
7208
  return React$1.createElement(ChatMenuItem, { key: i, onClick: props.onItemClick, label: item.label, subtitle: item.subtitle });
7195
7209
  }
@@ -7984,9 +7998,19 @@ var ChatBranding = function (props) {
7984
7998
  };
7985
7999
 
7986
8000
  var DrawerBars = function (props) {
7987
- return (React$1.createElement("button", { className: "drawer-bars", onClick: props.onToggle },
7988
- React$1.createElement("div", { className: "drawer-bar bar1" }),
7989
- React$1.createElement("div", { className: "drawer-bar bar2" })));
8001
+ var bars = props.bars;
8002
+ // 0 is not a valid number of bars so a simple truthy check works here
8003
+ if (!bars) {
8004
+ bars = 2;
8005
+ }
8006
+ function getBars() {
8007
+ var barElements = [];
8008
+ for (var bar = 0; bar < bars; bar++) {
8009
+ barElements.push(React$1.createElement("div", { className: "drawer-bar bar".concat(bar) }));
8010
+ }
8011
+ return barElements;
8012
+ }
8013
+ return (React$1.createElement("button", { className: "drawer-bars", tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, "aria-label": "open menu", "aria-hidden": true, onClick: props.onToggle }, getBars()));
7990
8014
  };
7991
8015
 
7992
8016
  var CloseIcon = function () {
@@ -8008,13 +8032,14 @@ var SendIcon = function () {
8008
8032
  };
8009
8033
 
8010
8034
  var SendButton = function (props) {
8011
- return (React$1.createElement(React$1.Fragment, null, !props.sendButtonIcon ? (React$1.createElement(IconButton_1, { className: "xappw-send-button ".concat(props.className || ""), onClick: props.onClick, icon: SendIcon })) : (React$1.createElement("span", { className: "xappw-custom-send-button", onClick: props.onClick },
8035
+ return (React$1.createElement(React$1.Fragment, null, !props.sendButtonIcon ? (React$1.createElement(IconButton_1, { className: "xappw-send-button ".concat(props.className || ""), tabIndex: props.tabIndex, onClick: props.onClick, icon: SendIcon })) : (React$1.createElement("button", { className: "xappw-custom-send-button", tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, onClick: props.onClick },
8012
8036
  React$1.createElement("img", { src: props.sendButtonIcon, alt: "Send button", draggable: false })))));
8013
8037
  };
8014
8038
 
8015
8039
  var Input = function (props) {
8016
- var value = props.value, placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, suggestion = props.suggestion, onChange = props.onChange, onSubmit = props.onSubmit, onSuggestionCommand = props.onSuggestionCommand;
8017
- var _a = useState(false), dragover = _a[0], setDragover = _a[1];
8040
+ var _a, _b;
8041
+ 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;
8042
+ var _c = useState(false), dragover = _c[0], setDragover = _c[1];
8018
8043
  function onDragOver(event) {
8019
8044
  setDragover(true);
8020
8045
  event.preventDefault();
@@ -8034,7 +8059,7 @@ var Input = function (props) {
8034
8059
  var handleClear = useCallback(function () {
8035
8060
  onChange({
8036
8061
  text: "",
8037
- formats: []
8062
+ formats: [],
8038
8063
  });
8039
8064
  }, [onChange]);
8040
8065
  var handleKeyDown = useCallback(function (event) {
@@ -8059,14 +8084,17 @@ var Input = function (props) {
8059
8084
  }
8060
8085
  }
8061
8086
  }, [suggestion, onChange, onSuggestionCommand]);
8062
- return (React$1.createElement("div", { className: "xappw-input-container ".concat(props.addClass, " ").concat(dragover ? "drag-drop-zone" : ""), onDrop: onDrop, onDragOver: onDragOver, onDragLeave: onDragLeave },
8087
+ return (React$1.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" +
8088
+ value.text
8089
+ ? "To clear ipnut field click on clear icon on the left of send button"
8090
+ : "", "aria-hidden": true, onDrop: onDrop, onDragOver: onDragOver, onDragLeave: onDragLeave },
8063
8091
  React$1.createElement("form", { className: "xappw-input-form", onSubmit: handleOnSubmit },
8064
- React$1.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,
8092
+ React$1.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,
8065
8093
  // onFocus={onFocus}
8066
8094
  value: value, spellCheck: true }),
8067
8095
  React$1.createElement("div", { className: "xappw-input-form__buttons" },
8068
- value.text && React$1.createElement(IconButton_1, { icon: CloseIcon, className: "xappw-input-form__btn", onClick: handleClear }),
8069
- React$1.createElement(SendButton, { className: "xappw-input-form__btn", sendButtonIcon: sendButtonIcon, onClick: handleOnSubmit })))));
8096
+ value.text && (React$1.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 })),
8097
+ React$1.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 })))));
8070
8098
  };
8071
8099
 
8072
8100
  function createActions(onItemUse) {
@@ -8107,22 +8135,26 @@ var Suggestions = function (props) {
8107
8135
  };
8108
8136
 
8109
8137
  var ChatFooter = function (props) {
8110
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
8111
- var placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, onSubmit = props.onSubmit;
8112
- var _k = useState(false), drawer = _k[0], setDrawerState = _k[1]; // false initially
8113
- var _l = useState(), suggestionSearch = _l[0], setSuggestionSearch = _l[1];
8138
+ var _a, _b, _c, _d;
8139
+ var placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, footerConfig = props.footerConfig, menuConfig = props.menuConfig, inputConfig = props.inputConfig, onSubmit = props.onSubmit;
8140
+ var _e = useState(false), drawerOpen = _e[0], setDrawerState = _e[1]; // false initially
8141
+ var _f = useState(), suggestionSearch = _f[0], setSuggestionSearch = _f[1];
8114
8142
  var contexts = useSelector(function (state) { return state.activeContexts; });
8115
8143
  var suggestions = useSuggestions(suggestionSearch, contexts);
8116
- var menuItemsRaw = (_b = (_a = useWidgetEnv()) === null || _a === void 0 ? void 0 : _a.menu) === null || _b === void 0 ? void 0 : _b.items;
8144
+ var menuPosition = (menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.menuButtonLocation) || "FOOTER";
8145
+ var showMenu = menuPosition === "FOOTER";
8146
+ var menuItemsRaw = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.items; // useWidgetEnv()?.menu?.items;
8147
+ var menuItemsTabIndex = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.itemsTabIndex; // useWidgetEnv()?.menu?.itemsTabIndex;
8148
+ var menuButtonTabIndex = (_a = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.button) === null || _a === void 0 ? void 0 : _a.tabIndex; // useWidgetEnv()?.menu?.button?.tabIndex;
8117
8149
  var menuItems = useMemo(function () { return menuItemsRaw ? menuItemsRaw : []; }, [menuItemsRaw]);
8118
- 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;
8119
- 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;
8120
- var _m = useState({
8150
+ var branding = (_b = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.branding) === null || _b === void 0 ? void 0 : _b.text; // useWidgetEnv()?.footer?.branding?.text;
8151
+ var brandingEnabled = (_c = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.branding) === null || _c === void 0 ? void 0 : _c.enabled; // useWidgetEnv()?.footer?.branding?.enabled;
8152
+ var _g = useState({
8121
8153
  text: "",
8122
8154
  formats: []
8123
- }), input = _m[0], setInput = _m[1];
8155
+ }), input = _g[0], setInput = _g[1];
8124
8156
  function toggleDrawer() {
8125
- var newDrawer = !drawer;
8157
+ var newDrawer = !drawerOpen;
8126
8158
  setDrawerState(newDrawer);
8127
8159
  set$1("drawer", newDrawer);
8128
8160
  }
@@ -8135,6 +8167,7 @@ var ChatFooter = function (props) {
8135
8167
  props.onChange(val.text);
8136
8168
  setSuggestionSearch(val.text);
8137
8169
  }
8170
+ // Clears out suggestion and input text
8138
8171
  var handleSubmit = useCallback(function (message) {
8139
8172
  setSuggestionSearch("");
8140
8173
  setInput({
@@ -8150,14 +8183,14 @@ var ChatFooter = function (props) {
8150
8183
  setInput(data);
8151
8184
  setSuggestionSearch(data.text);
8152
8185
  }, []);
8153
- return (React$1.createElement("div", { className: "chat-footer" },
8154
- menuItems.length ?
8186
+ return (React$1.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 },
8187
+ showMenu && menuItems.length ?
8155
8188
  React$1.createElement(React$1.Fragment, null,
8156
- drawer && React$1.createElement(ChatMenu, { opened: drawer, onItemClick: handleMenuItem, items: menuItems }),
8189
+ drawerOpen ? React$1.createElement(ChatMenu, { opened: drawerOpen, tabIndex: menuItemsTabIndex, onItemClick: handleMenuItem, items: menuItems }) : React$1.createElement(React$1.Fragment, null),
8157
8190
  React$1.createElement("div", { className: "chat-footer__menu-icon" },
8158
- React$1.createElement(DrawerBars, { onToggle: toggleDrawer }))) : React$1.createElement(React$1.Fragment, null),
8159
- ((_j = suggestions.suggestions) === null || _j === void 0 ? void 0 : _j.length) > 0 && React$1.createElement(Suggestions, { className: "xappw-chat-footer__suggestions", data: suggestions.suggestions, index: suggestions.index, onItemClick: handleItemClick, onItemUse: handleItemUse }),
8160
- React$1.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,
8191
+ React$1.createElement(DrawerBars, { tabIndex: menuButtonTabIndex, onToggle: toggleDrawer }))) : React$1.createElement(React$1.Fragment, null),
8192
+ ((_d = suggestions.suggestions) === null || _d === void 0 ? void 0 : _d.length) > 0 && React$1.createElement(Suggestions, { className: "xappw-chat-footer__suggestions", data: suggestions.suggestions, index: suggestions.index, onItemClick: handleItemClick, onItemUse: handleItemUse }),
8193
+ React$1.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,
8161
8194
  // onFocus={this.inputOnFocus}
8162
8195
  onFileUpload: props.onFileUpload }),
8163
8196
  brandingEnabled && React$1.createElement(ChatBranding, { text: branding })));
@@ -30681,46 +30714,75 @@ var ServerOffline = function () {
30681
30714
  };
30682
30715
 
30683
30716
  var CancelButton = function (props) {
30684
- return React$1.createElement("button", { id: "xapp-widget-close", className: "cancel-button", onClick: props.onClick });
30717
+ return (React$1.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 }));
30685
30718
  };
30686
30719
 
30687
30720
  var MinimizeButton = function (props) {
30688
- return (React$1.createElement("button", { id: "xapp-widget-minimize", className: "minimize-button ".concat(props.showInRight ? "positionRight" : ""), onClick: props.onClick }));
30721
+ return (React$1.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 }));
30689
30722
  };
30690
30723
 
30691
30724
  var RefreshButton = function (props) {
30692
- return (React$1.createElement("button", { id: "xapp-widget-refresh", className: "refresh-button ".concat(props.showInRight ? "positionRight" : props.showInLeft ? "positionLeft" : ""), onClick: props.onClick }));
30725
+ return (React$1.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 }));
30693
30726
  };
30694
30727
 
30695
30728
  var DEFAULT_STATUS_CONFIG = {
30696
30729
  online: "Virtual Assistant",
30697
30730
  offline: "Leave us a message",
30698
30731
  away: "We're away!",
30699
- connecting: "Connecting..."
30732
+ connecting: "Connecting...",
30700
30733
  };
30701
30734
  function getStatusText(status, config) {
30702
30735
  var _a, _b, _c, _d;
30703
30736
  switch (status) {
30704
- case "online": return (_a = config === null || config === void 0 ? void 0 : config.online) !== null && _a !== void 0 ? _a : DEFAULT_STATUS_CONFIG.online;
30705
- case "offline": return (_b = config === null || config === void 0 ? void 0 : config.offline) !== null && _b !== void 0 ? _b : DEFAULT_STATUS_CONFIG.offline;
30706
- case "away": return (_c = config === null || config === void 0 ? void 0 : config.away) !== null && _c !== void 0 ? _c : DEFAULT_STATUS_CONFIG.away;
30707
- default: return (_d = config === null || config === void 0 ? void 0 : config.connecting) !== null && _d !== void 0 ? _d : DEFAULT_STATUS_CONFIG.connecting;
30737
+ case "online":
30738
+ return (_a = config === null || config === void 0 ? void 0 : config.online) !== null && _a !== void 0 ? _a : DEFAULT_STATUS_CONFIG.online;
30739
+ case "offline":
30740
+ return (_b = config === null || config === void 0 ? void 0 : config.offline) !== null && _b !== void 0 ? _b : DEFAULT_STATUS_CONFIG.offline;
30741
+ case "away":
30742
+ return (_c = config === null || config === void 0 ? void 0 : config.away) !== null && _c !== void 0 ? _c : DEFAULT_STATUS_CONFIG.away;
30743
+ default:
30744
+ return (_d = config === null || config === void 0 ? void 0 : config.connecting) !== null && _d !== void 0 ? _d : DEFAULT_STATUS_CONFIG.connecting;
30708
30745
  }
30709
30746
  }
30710
- var StatusContainer = function (props) {
30711
- var _a, _b, _c, _d, _e, _f, _g;
30712
- return (React$1.createElement("div", { className: "status-container" },
30713
- React$1.createElement("div", { className: "status-container__avatar" },
30714
- React$1.createElement(Avatar, { entity: props.agent })),
30715
- React$1.createElement("div", { className: "".concat("status-text", " ").concat(((_a = props.config) === null || _a === void 0 ? void 0 : _a.alignTextCenter) ? "status-text-positionCenter" : "status-text-positionLeft") },
30716
- React$1.createElement("span", { className: "status-text-title" }, getStatusText(props.accountStatus, (_b = props.config) === null || _b === void 0 ? void 0 : _b.status)),
30717
- ((_d = (_c = props.config) === null || _c === void 0 ? void 0 : _c.subtitle) === null || _d === void 0 ? void 0 : _d.enabled) && React$1.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 : "")),
30718
- props.canRefresh &&
30719
- React$1.createElement(RefreshButton, { onClick: props.refreshOnClick, showInLeft: props.canMinimize && props.canCancel, showInRight: !props.canMinimize && !props.canCancel }),
30720
- props.canMinimize &&
30721
- React$1.createElement(MinimizeButton, { onClick: props.minimizeOnClick, showInRight: !props.canCancel }),
30722
- props.canCancel &&
30723
- React$1.createElement(CancelButton, { onClick: props.cancelOnClick })));
30747
+ var refreshButtonAriaLabel = "To refresh chat click on clockwise gapped circle arrow icon in top right side of widget. ";
30748
+ var minimizeButtonAriaLabel = "To minimize widget click on minus icon in top right side of widget. ";
30749
+ var closeButtonAriaLabel = "To close widget click on close icon in top right side of widget.";
30750
+ var ChatHeader = function (props) {
30751
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
30752
+ var menuConfig = props.menuConfig, onSubmit = props.onSubmit;
30753
+ var _q = useState(false), drawerOpen = _q[0], setDrawerState = _q[1]; // false initially
30754
+ var menuPosition = (menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.menuButtonLocation) || "FOOTER";
30755
+ var showMenu = menuPosition === "HEADER_LEFT";
30756
+ var menuItemsRaw = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.items; // useWidgetEnv()?.menu?.items;
30757
+ var menuItemsTabIndex = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.itemsTabIndex; // useWidgetEnv()?.menu?.itemsTabIndex;
30758
+ var menuButtonTabIndex = (_a = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.button) === null || _a === void 0 ? void 0 : _a.tabIndex; // useWidgetEnv()?.menu?.button?.tabIndex;
30759
+ var menuItems = useMemo(function () { return menuItemsRaw ? menuItemsRaw : []; }, [menuItemsRaw]);
30760
+ function toggleDrawer() {
30761
+ var newDrawer = !drawerOpen;
30762
+ setDrawerState(newDrawer);
30763
+ set$1("drawer", newDrawer);
30764
+ }
30765
+ function handleMenuItem(label) {
30766
+ setDrawerState(false);
30767
+ onSubmit(label);
30768
+ }
30769
+ return (React$1.createElement(React$1.Fragment, null,
30770
+ React$1.createElement("div", { className: "status-container", "aria-label": props.canRefresh ? refreshButtonAriaLabel : "" + props.canMinimize ? minimizeButtonAriaLabel : "" + props.canCancel ? closeButtonAriaLabel : "", "aria-hidden": true },
30771
+ showMenu && menuItems.length ? (React$1.createElement(React$1.Fragment, null,
30772
+ React$1.createElement("div", { className: "chat-footer__menu-icon" },
30773
+ React$1.createElement(DrawerBars, { bars: 3, tabIndex: menuButtonTabIndex, onToggle: toggleDrawer })))) : React$1.createElement(React$1.Fragment, null),
30774
+ React$1.createElement("div", { className: "status-container__avatar" },
30775
+ React$1.createElement(Avatar, { entity: props.agent })),
30776
+ React$1.createElement("div", { className: "".concat("status-text", " ").concat(((_b = props.config) === null || _b === void 0 ? void 0 : _b.alignTextCenter)
30777
+ ? "status-text-positionCenter"
30778
+ : "status-text-positionLeft") },
30779
+ React$1.createElement("span", { className: "status-text-title" }, getStatusText(props.accountStatus, (_c = props.config) === null || _c === void 0 ? void 0 : _c.status)),
30780
+ ((_e = (_d = props.config) === null || _d === void 0 ? void 0 : _d.subtitle) === null || _e === void 0 ? void 0 : _e.enabled) && (React$1.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 : ""))),
30781
+ props.canRefresh && (React$1.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 })),
30782
+ props.canMinimize && (React$1.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 })),
30783
+ props.canCancel && (React$1.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 }))),
30784
+ drawerOpen ? (React$1.createElement("div", { className: "xa-chat-menu-container" },
30785
+ React$1.createElement(ChatMenu, { openFrom: "left", opened: drawerOpen, tabIndex: menuItemsTabIndex, onItemClick: handleMenuItem, items: menuItems }))) : React$1.createElement(React$1.Fragment, null)));
30724
30786
  };
30725
30787
 
30726
30788
  function buildStyleContent(theme) {
@@ -31011,7 +31073,8 @@ var ChatWidgetWrapper = function (props) {
31011
31073
  displayName: rawConfig.botName,
31012
31074
  avatarPath: rawConfig.avatarUrl,
31013
31075
  },
31014
- configurableMessages: configurableMessages
31076
+ configurableMessages: configurableMessages,
31077
+ hooks: rawConfig.hooks
31015
31078
  };
31016
31079
  }, [token, rawConfig]);
31017
31080
  var chatServer = useChatServer(connection, options);
@@ -31020,7 +31083,7 @@ var ChatWidgetWrapper = function (props) {
31020
31083
  React$1.createElement(ChatWidget, __assign({}, props)))));
31021
31084
  };
31022
31085
  var ChatWidget = function (props) {
31023
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
31086
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
31024
31087
  var innerDispatch = useChatDispatch();
31025
31088
  var dispatch = useChatServerDispatch();
31026
31089
  // From Redux
@@ -31040,8 +31103,8 @@ var ChatWidget = function (props) {
31040
31103
  canCancel = !dockedMode && !staticMode;
31041
31104
  }
31042
31105
  // Our state - pull from storage
31043
- var _v = 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];
31044
- var _w = useState(false), typing = _w[0], setTypingState = _w[1]; // false initially
31106
+ var _x = 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];
31107
+ var _y = useState(false), typing = _y[0], setTypingState = _y[1]; // false initially
31045
31108
  var chatServer = useContext(ChatServerContext);
31046
31109
  var setVisible = useCallback(function (newVisible) {
31047
31110
  if (staticMode) {
@@ -31177,13 +31240,13 @@ var ChatWidget = function (props) {
31177
31240
  return (React$1.createElement(React$1.Fragment, null,
31178
31241
  React$1.createElement("div", { className: "widget-container ".concat(modeClass, " ").concat(getVisibilityClass()) },
31179
31242
  React$1.createElement(WidgetStylesheet, { theme: config === null || config === void 0 ? void 0 : config.theme }),
31180
- React$1.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 }),
31243
+ React$1.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 }),
31181
31244
  React$1.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 }),
31182
31245
  React$1.createElement("div", { className: "spinner-container ".concat(visible && connectionStatus === "pending" ? "visible" : "") },
31183
31246
  React$1.createElement("div", { className: "spinner" })),
31184
31247
  connectionStatus === "offline" && React$1.createElement(ServerOffline, null),
31185
- React$1.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 })),
31186
- React$1.createElement(ChatButton, { addClass: getVisibilityClass(), onClick: chatButtonOnClick, config: (_u = props.config) === null || _u === void 0 ? void 0 : _u.cta, visible: visible })));
31248
+ React$1.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 })),
31249
+ React$1.createElement(ChatButton, { addClass: getVisibilityClass(), onClick: chatButtonOnClick, config: (_w = props.config) === null || _w === void 0 ? void 0 : _w.cta, visible: visible })));
31187
31250
  };
31188
31251
 
31189
31252
  function tryParseJson(str) {
@@ -31312,7 +31375,7 @@ function resetReducer(state) {
31312
31375
  })), { connection: __assign(__assign({}, state.connection), { greetingRequested: false, nonce: uuid_1() }), visitor: state.visitor, visitorId: state.visitorId });
31313
31376
  }
31314
31377
 
31315
- // todo: create reducer (requires redux-thunk dependncy)
31378
+ // todo: create reducer (requires redux-thunk dependency)
31316
31379
  function appendMessageToState(state, msg) {
31317
31380
  state.chats = joinMessages(state.chats, msg);
31318
31381
  if (msg.type === "chat.msg") {