@xapp/chat-widget 1.49.5 → 1.50.2

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
@@ -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 () {
@@ -8035,7 +8059,7 @@ var Input = function (props) {
8035
8059
  var handleClear = useCallback(function () {
8036
8060
  onChange({
8037
8061
  text: "",
8038
- formats: []
8062
+ formats: [],
8039
8063
  });
8040
8064
  }, [onChange]);
8041
8065
  var handleKeyDown = useCallback(function (event) {
@@ -8060,13 +8084,16 @@ var Input = function (props) {
8060
8084
  }
8061
8085
  }
8062
8086
  }, [suggestion, onChange, onSuggestionCommand]);
8063
- 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 },
8064
8091
  React$1.createElement("form", { className: "xappw-input-form", onSubmit: handleOnSubmit },
8065
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,
8066
8093
  // onFocus={onFocus}
8067
8094
  value: value, spellCheck: true }),
8068
8095
  React$1.createElement("div", { className: "xappw-input-form__buttons" },
8069
- 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 }),
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 })),
8070
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 })))));
8071
8098
  };
8072
8099
 
@@ -8108,22 +8135,26 @@ var Suggestions = function (props) {
8108
8135
  };
8109
8136
 
8110
8137
  var ChatFooter = function (props) {
8111
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
8112
- var placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, footerConfig = props.footerConfig, inputConfig = props.inputConfig, onSubmit = props.onSubmit;
8113
- var _k = useState(false), drawer = _k[0], setDrawerState = _k[1]; // false initially
8114
- 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];
8115
8142
  var contexts = useSelector(function (state) { return state.activeContexts; });
8116
8143
  var suggestions = useSuggestions(suggestionSearch, contexts);
8117
- 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;
8118
8149
  var menuItems = useMemo(function () { return menuItemsRaw ? menuItemsRaw : []; }, [menuItemsRaw]);
8119
- 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;
8120
- 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;
8121
- 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({
8122
8153
  text: "",
8123
8154
  formats: []
8124
- }), input = _m[0], setInput = _m[1];
8155
+ }), input = _g[0], setInput = _g[1];
8125
8156
  function toggleDrawer() {
8126
- var newDrawer = !drawer;
8157
+ var newDrawer = !drawerOpen;
8127
8158
  setDrawerState(newDrawer);
8128
8159
  set$1("drawer", newDrawer);
8129
8160
  }
@@ -8136,6 +8167,7 @@ var ChatFooter = function (props) {
8136
8167
  props.onChange(val.text);
8137
8168
  setSuggestionSearch(val.text);
8138
8169
  }
8170
+ // Clears out suggestion and input text
8139
8171
  var handleSubmit = useCallback(function (message) {
8140
8172
  setSuggestionSearch("");
8141
8173
  setInput({
@@ -8151,13 +8183,13 @@ var ChatFooter = function (props) {
8151
8183
  setInput(data);
8152
8184
  setSuggestionSearch(data.text);
8153
8185
  }, []);
8154
- return (React$1.createElement("div", { className: "chat-footer" },
8155
- 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 ?
8156
8188
  React$1.createElement(React$1.Fragment, null,
8157
- 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),
8158
8190
  React$1.createElement("div", { className: "chat-footer__menu-icon" },
8159
- React$1.createElement(DrawerBars, { onToggle: toggleDrawer }))) : React$1.createElement(React$1.Fragment, null),
8160
- ((_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 }),
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 }),
8161
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,
8162
8194
  // onFocus={this.inputOnFocus}
8163
8195
  onFileUpload: props.onFileUpload }),
@@ -30682,15 +30714,15 @@ var ServerOffline = function () {
30682
30714
  };
30683
30715
 
30684
30716
  var CancelButton = function (props) {
30685
- return React$1.createElement("button", { id: "xapp-widget-close", tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, 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 }));
30686
30718
  };
30687
30719
 
30688
30720
  var MinimizeButton = function (props) {
30689
- return (React$1.createElement("button", { id: "xapp-widget-minimize", tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, 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 }));
30690
30722
  };
30691
30723
 
30692
30724
  var RefreshButton = function (props) {
30693
- return (React$1.createElement("button", { id: "xapp-widget-refresh", tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, 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 }));
30694
30726
  };
30695
30727
 
30696
30728
  var DEFAULT_STATUS_CONFIG = {
@@ -30712,19 +30744,45 @@ function getStatusText(status, config) {
30712
30744
  return (_d = config === null || config === void 0 ? void 0 : config.connecting) !== null && _d !== void 0 ? _d : DEFAULT_STATUS_CONFIG.connecting;
30713
30745
  }
30714
30746
  }
30715
- var StatusContainer = function (props) {
30716
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
30717
- return (React$1.createElement("div", { className: "status-container" },
30718
- React$1.createElement("div", { className: "status-container__avatar" },
30719
- React$1.createElement(Avatar, { entity: props.agent })),
30720
- React$1.createElement("div", { className: "".concat("status-text", " ").concat(((_a = props.config) === null || _a === void 0 ? void 0 : _a.alignTextCenter)
30721
- ? "status-text-positionCenter"
30722
- : "status-text-positionLeft") },
30723
- React$1.createElement("span", { className: "status-text-title" }, getStatusText(props.accountStatus, (_b = props.config) === null || _b === void 0 ? void 0 : _b.status)),
30724
- ((_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 : ""))),
30725
- props.canRefresh && (React$1.createElement(RefreshButton, { onClick: props.refreshOnClick, tabIndex: (_j = (_h = props.config) === null || _h === void 0 ? void 0 : _h.actions) === null || _j === void 0 ? void 0 : _j.refreshTabIndex, showInLeft: props.canMinimize && props.canCancel, showInRight: !props.canMinimize && !props.canCancel })),
30726
- props.canMinimize && (React$1.createElement(MinimizeButton, { onClick: props.minimizeOnClick, tabIndex: (_l = (_k = props.config) === null || _k === void 0 ? void 0 : _k.actions) === null || _l === void 0 ? void 0 : _l.minimizeTabIndex, showInRight: !props.canCancel })),
30727
- props.canCancel && (React$1.createElement(CancelButton, { onClick: props.cancelOnClick, tabIndex: (_o = (_m = props.config) === null || _m === void 0 ? void 0 : _m.actions) === null || _o === void 0 ? void 0 : _o.cancelTabIndex }))));
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)));
30728
30786
  };
30729
30787
 
30730
30788
  function buildStyleContent(theme) {
@@ -31015,7 +31073,8 @@ var ChatWidgetWrapper = function (props) {
31015
31073
  displayName: rawConfig.botName,
31016
31074
  avatarPath: rawConfig.avatarUrl,
31017
31075
  },
31018
- configurableMessages: configurableMessages
31076
+ configurableMessages: configurableMessages,
31077
+ hooks: rawConfig.hooks
31019
31078
  };
31020
31079
  }, [token, rawConfig]);
31021
31080
  var chatServer = useChatServer(connection, options);
@@ -31181,12 +31240,12 @@ var ChatWidget = function (props) {
31181
31240
  return (React$1.createElement(React$1.Fragment, null,
31182
31241
  React$1.createElement("div", { className: "widget-container ".concat(modeClass, " ").concat(getVisibilityClass()) },
31183
31242
  React$1.createElement(WidgetStylesheet, { theme: config === null || config === void 0 ? void 0 : config.theme }),
31184
- 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 }),
31185
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 }),
31186
31245
  React$1.createElement("div", { className: "spinner-container ".concat(visible && connectionStatus === "pending" ? "visible" : "") },
31187
31246
  React$1.createElement("div", { className: "spinner" })),
31188
31247
  connectionStatus === "offline" && React$1.createElement(ServerOffline, null),
31189
- 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, 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 })),
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 })),
31190
31249
  React$1.createElement(ChatButton, { addClass: getVisibilityClass(), onClick: chatButtonOnClick, config: (_w = props.config) === null || _w === void 0 ? void 0 : _w.cta, visible: visible })));
31191
31250
  };
31192
31251
 
@@ -31316,7 +31375,7 @@ function resetReducer(state) {
31316
31375
  })), { connection: __assign(__assign({}, state.connection), { greetingRequested: false, nonce: uuid_1() }), visitor: state.visitor, visitorId: state.visitorId });
31317
31376
  }
31318
31377
 
31319
- // todo: create reducer (requires redux-thunk dependncy)
31378
+ // todo: create reducer (requires redux-thunk dependency)
31320
31379
  function appendMessageToState(state, msg) {
31321
31380
  state.chats = joinMessages(state.chats, msg);
31322
31381
  if (msg.type === "chat.msg") {