@xapp/chat-widget 1.64.2 → 1.65.1

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
@@ -12,14 +12,15 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
12
12
  var React__default$1 = /*#__PURE__*/_interopDefaultLegacy(React$1);
13
13
  var thunk__default = /*#__PURE__*/_interopDefaultLegacy(thunk);
14
14
 
15
- var ActionButton = function (props) {
15
+ var ActionButton = function (_a) {
16
+ var label = _a.label, disable = _a.disable, type = _a.type, addClass = _a.addClass, onClick = _a.onClick;
16
17
  function handleClick(ev) {
17
18
  ev.stopPropagation();
18
- if (props.onClick) {
19
- props.onClick(props.label);
19
+ if (onClick) {
20
+ onClick(label);
20
21
  }
21
22
  }
22
- return (React__default$1["default"].createElement("button", { type: props.type, className: "action-button ".concat(props.addClass), onClick: handleClick }, props.label));
23
+ return (React__default$1["default"].createElement("button", { disabled: disable, type: type, className: "action-button ".concat(addClass), onClick: handleClick }, label));
23
24
  };
24
25
 
25
26
  var defaultServerUrl = "";
@@ -678,40 +679,45 @@ var CtaBubble = function (props) {
678
679
  };
679
680
 
680
681
  var CtaBubbleContainer = function (props) {
681
- var visible = props.visible, timeout = props.timeout, delay = props.delay, animate = props.animate, buttonAnimation = props.buttonAnimation, onClick = props.onClick;
682
+ var visible = props.visible, timeout = props.timeout, delay = props.delay, animate = props.animate, buttonAnimation = props.buttonAnimation, onClick = props.onClick, children = props.children;
682
683
  var startTime = React$1.useMemo(function () {
683
- if (visible) {
684
- return new Date().valueOf();
685
- }
686
- return undefined;
684
+ return visible ? new Date().valueOf() : undefined;
687
685
  }, [visible]);
688
686
  var _a = React$1.useState(false), showBubble = _a[0], setShowBubble = _a[1];
687
+ var isMounted = React$1.useRef(true);
689
688
  React$1.useEffect(function () {
690
- var isMounted = true;
689
+ var hideTimer = null;
691
690
  if (startTime) {
692
691
  var delayTimer_1 = setTimeout(function () {
693
- if (isMounted) {
692
+ if (isMounted.current) {
694
693
  setShowBubble(true);
695
694
  }
696
- var hideTimer = setTimeout(function () {
697
- if (isMounted) {
698
- setShowBubble(false);
699
- }
700
- }, timeout);
701
- return function () {
702
- clearTimeout(hideTimer);
703
- };
695
+ if (typeof timeout === "number") {
696
+ hideTimer = setTimeout(function () {
697
+ if (isMounted.current) {
698
+ setShowBubble(false);
699
+ }
700
+ }, timeout);
701
+ }
704
702
  }, delay);
705
703
  return function () {
706
- isMounted = false;
704
+ if (hideTimer) {
705
+ clearTimeout(hideTimer);
706
+ }
707
707
  clearTimeout(delayTimer_1);
708
+ isMounted.current = false;
708
709
  };
709
710
  }
711
+ // Return a cleanup function for the case where startTime is undefined
710
712
  return function () {
711
- isMounted = false;
713
+ if (hideTimer) {
714
+ clearTimeout(hideTimer);
715
+ }
716
+ isMounted.current = false;
712
717
  };
713
718
  }, [startTime, timeout, delay]);
714
- return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null, visible && showBubble && React__default$1["default"].createElement(CtaBubble, { onClick: onClick, animate: animate, buttonAnimation: buttonAnimation }, props.children)));
719
+ console.log("visible ".concat(visible, " showBubble ").concat(showBubble));
720
+ return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null, visible && showBubble && React__default$1["default"].createElement(CtaBubble, { onClick: onClick, animate: animate, buttonAnimation: buttonAnimation }, children)));
715
721
  };
716
722
 
717
723
  var ChatButton = function (_a) {
@@ -753,7 +759,7 @@ var ChatButton = function (_a) {
753
759
  setAnimate(false);
754
760
  }, configToApply.animationTimeout);
755
761
  }
756
- else {
762
+ else if (configToApply === null || configToApply === void 0 ? void 0 : configToApply.animation) {
757
763
  // No delay or timeout, start animation immediately
758
764
  setAnimate(true);
759
765
  }
@@ -796,8 +802,8 @@ var ChatButton = function (_a) {
796
802
  // Fallback to default SVG
797
803
  React__default$1["default"].createElement("svg", { width: svgSize, height: svgSize, viewBox: "0 0 22 22" },
798
804
  React__default$1["default"].createElement("path", { d: "M13 22l-4-6H2c-1.11-.043-2-.935-2-2V2C0 .89.89 0 2 0h18c1.11 0 2 .892 2 2v12c0 1.067-.89 1.957-2 2h-3l-4 6zm3-8h4c-.005.3-.01-12 0-12-.01.004-18 .006-18 0 .005.006 0 12 0 12h8l3 5 3-5z", fill: "#FFF", fillRule: "evenodd" })))),
799
- config && config.message && (React__default$1["default"].createElement("div", { className: "xapp-chat-button__cta" },
800
- React__default$1["default"].createElement(CtaBubbleContainer, { timeout: configToApply === null || configToApply === void 0 ? void 0 : configToApply.timeout, delay: configToApply === null || configToApply === void 0 ? void 0 : configToApply.delay, animate: animate, buttonAnimation: animation, visible: !visible }, config.message)))));
805
+ configToApply && configToApply.message && (React__default$1["default"].createElement("div", { className: "xapp-chat-button__cta" },
806
+ React__default$1["default"].createElement(CtaBubbleContainer, { timeout: configToApply === null || configToApply === void 0 ? void 0 : configToApply.timeout, delay: configToApply === null || configToApply === void 0 ? void 0 : configToApply.delay, animate: animate, buttonAnimation: animation, visible: !visible /** Why is this !visible */ }, configToApply === null || configToApply === void 0 ? void 0 : configToApply.message)))));
801
807
  };
802
808
 
803
809
  var ChatCard = function (props) {
@@ -2952,24 +2958,34 @@ var StentorRouterChat = /** @class */ (function () {
2952
2958
  _this.setConnectionStatus("online");
2953
2959
  };
2954
2960
  };
2955
- StentorRouterChat.prototype.wsCreate = function () {
2961
+ StentorRouterChat.prototype.wsClose = function () {
2962
+ if (this.ws) {
2963
+ this.ws.onclose = null;
2964
+ this.ws.onerror = null;
2965
+ this.ws.onopen = null;
2966
+ this.ws.onmessage = null;
2967
+ this.ws.close();
2968
+ }
2969
+ };
2970
+ StentorRouterChat.prototype.wsCreate = function (createWsReason) {
2956
2971
  var _this = this;
2957
- var _a, _b;
2958
2972
  if (this.isDisposed) {
2959
2973
  log("Stopping reconnect for disposed router connector");
2960
2974
  return undefined;
2961
2975
  }
2962
2976
  else {
2963
- log("Trying to re-connect...");
2977
+ log("Trying to re-connect. Reason: \"".concat(createWsReason, "\""));
2964
2978
  }
2965
2979
  var url = new URL(this.serverUrl);
2966
2980
  url.searchParams.set("userId", this._userId);
2967
2981
  url.searchParams.set("isAdmin", "".concat(this.isAdmin));
2982
+ url.searchParams.set("createWsReason", createWsReason); // tell the server the reconnect reason
2968
2983
  // Force close - just in case - when you create new
2969
- if (this.ws && ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) !== WebSocket.CLOSED) {
2970
- var wsState = (_b = this.ws) === null || _b === void 0 ? void 0 : _b.readyState;
2984
+ if (this.ws && !(this.ws.readyState === WebSocket.CLOSED || this.ws.readyState === WebSocket.CLOSING)) {
2985
+ var wsState = this.ws.readyState;
2986
+ log("Forced WS close. State: ".concat(wsState));
2971
2987
  try {
2972
- this.ws.close();
2988
+ this.wsClose();
2973
2989
  }
2974
2990
  catch (err) {
2975
2991
  err("Failed to close WS (ready state: ".concat(wsState, "): ").concat(err));
@@ -3014,7 +3030,7 @@ var StentorRouterChat = /** @class */ (function () {
3014
3030
  log("Widget says: ".concat(payloadData));
3015
3031
  if (!this.ws) {
3016
3032
  // Fire up the WebSocket
3017
- this.autoReconnect(this.wsCreate.bind(this));
3033
+ this.autoReconnect(this.wsCreate.bind(this, "emitNoWs"));
3018
3034
  }
3019
3035
  return [4 /*yield*/, waitFor(this.checkConnection.bind(this), 1000, 10000, "connection")
3020
3036
  .then(function (t) {
@@ -3169,14 +3185,14 @@ var StentorRouterChat = /** @class */ (function () {
3169
3185
  StentorRouterChat.prototype.dispose = function () {
3170
3186
  this.isDisposed = true;
3171
3187
  if (this.ws) {
3172
- this.ws.close();
3188
+ this.wsClose();
3173
3189
  }
3174
3190
  log("Closed web socket (dispose)");
3175
3191
  };
3176
3192
  StentorRouterChat.prototype.sleep = function () {
3177
3193
  this.isDisposed = true;
3178
3194
  if (this.ws) {
3179
- this.ws.close();
3195
+ this.wsClose();
3180
3196
  }
3181
3197
  log("Closed web socket (sleep)");
3182
3198
  };
@@ -3187,7 +3203,7 @@ var StentorRouterChat = /** @class */ (function () {
3187
3203
  return;
3188
3204
  }
3189
3205
  // Fire up the WebSocket
3190
- this.autoReconnect(this.wsCreate.bind(this));
3206
+ this.autoReconnect(this.wsCreate.bind(this, "wakeup"));
3191
3207
  log("Waking up");
3192
3208
  };
3193
3209
  StentorRouterChat.prototype.bargeOut = function (_cb) {
@@ -7949,11 +7965,17 @@ function useSuggestions(search, context) {
7949
7965
  }); }, [suggestions, suggestionIndex, execute, suggestionItem]);
7950
7966
  }
7951
7967
 
7952
- var AdminBar = function (_props) {
7968
+ var AdminBar = function (_a) {
7969
+ var onAdminJoin = _a.onAdminJoin;
7953
7970
  var name = React$1.useRef(null);
7954
7971
  // We can manage this locally
7955
7972
  // const hasAdminJoined = useSelector<ChatState, boolean | undefined>(state => state.hasAdminJoined);
7956
- var _a = React$1.useState(false), joined = _a[0], setJoined = _a[1];
7973
+ var _b = React$1.useState(false), joined = _b[0], setJoined = _b[1];
7974
+ var _c = React$1.useState(""), inputName = _c[0], setInputName = _c[1];
7975
+ function handleInputChange(event) {
7976
+ setInputName(event.target.value);
7977
+ }
7978
+ var disable = inputName === "" || inputName === undefined;
7957
7979
  var dispatch = useChatServerDispatch();
7958
7980
  function onSubmit(event) {
7959
7981
  var _a;
@@ -7961,18 +7983,21 @@ var AdminBar = function (_props) {
7961
7983
  if (!joined) {
7962
7984
  dispatch(sendBargeIn((_a = name.current) === null || _a === void 0 ? void 0 : _a.value));
7963
7985
  setJoined(true);
7986
+ onAdminJoin(true);
7964
7987
  }
7965
7988
  else {
7966
7989
  dispatch(sendBargeOut());
7967
7990
  setJoined(false);
7991
+ onAdminJoin(false);
7992
+ setInputName("");
7968
7993
  }
7969
7994
  }
7970
7995
  function renderJoin() {
7971
7996
  return (React__default$1["default"].createElement("form", { className: "xappw-admin-input-form", onSubmit: onSubmit },
7972
7997
  React__default$1["default"].createElement("div", { className: "xappw-admin-input-form__buttons" },
7973
- React__default$1["default"].createElement(ActionButton, { addClass: "xappw-admin-input-form__btn", type: "submit", label: "Join" })),
7998
+ React__default$1["default"].createElement(ActionButton, { addClass: "xappw-admin-input-form__btn", type: "submit", label: "Join", disable: disable })),
7974
7999
  React__default$1["default"].createElement("div", { className: "xappw-admin-input" },
7975
- React__default$1["default"].createElement("input", { ref: name, id: "adminBarInput", placeholder: "Type your name here...", className: "xappw-admin-input__input" }))));
8000
+ React__default$1["default"].createElement("input", { ref: name, id: "adminBarInput", placeholder: "Type your name here...", className: "xappw-admin-input__input", onChange: handleInputChange }))));
7976
8001
  }
7977
8002
  function renderLeave() {
7978
8003
  return (React__default$1["default"].createElement("form", { className: "xappw-admin-input-form", onSubmit: onSubmit },
@@ -8230,11 +8255,11 @@ var Suggestions = function (props) {
8230
8255
  };
8231
8256
 
8232
8257
  var ChatFooter = function (props) {
8233
- var _a, _b;
8258
+ var _a, _b, _c;
8259
+ var isAdmin = props.isAdmin, isChatting = props.isChatting, visible = props.visible, placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, footerConfig = props.footerConfig, menuConfig = props.menuConfig, inputConfig = props.inputConfig, onSubmit = props.onSubmit;
8234
8260
  var innerDispatch = useChatDispatch();
8235
- var placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, footerConfig = props.footerConfig, menuConfig = props.menuConfig, inputConfig = props.inputConfig, onSubmit = props.onSubmit;
8236
- var _c = React$1.useState(false), drawerOpen = _c[0], setDrawerState = _c[1]; // false initially
8237
- var _d = React$1.useState(), suggestionSearch = _d[0], setSuggestionSearch = _d[1];
8261
+ var _d = React$1.useState(false), drawerOpen = _d[0], setDrawerState = _d[1]; // false initially
8262
+ var _e = React$1.useState(), suggestionSearch = _e[0], setSuggestionSearch = _e[1];
8238
8263
  var contexts = reactRedux.useSelector(function (state) { return state.activeContexts; });
8239
8264
  var suggestions = useSuggestions(suggestionSearch, contexts);
8240
8265
  var menuPosition = (menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.menuButtonLocation) || "FOOTER";
@@ -8244,10 +8269,13 @@ var ChatFooter = function (props) {
8244
8269
  var menuButtonTabIndex = (_a = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.button) === null || _a === void 0 ? void 0 : _a.tabIndex;
8245
8270
  var menuItems = React$1.useMemo(function () { return menuItemsRaw ? menuItemsRaw : []; }, [menuItemsRaw]);
8246
8271
  var brandingEnabled = (_b = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.branding) === null || _b === void 0 ? void 0 : _b.enabled;
8247
- var _e = React$1.useState({
8272
+ var brandingText = (_c = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.branding) === null || _c === void 0 ? void 0 : _c.text;
8273
+ // If they are NOT an admin, automatically enabled the input
8274
+ var _f = React$1.useState(!isAdmin), enableInput = _f[0], setEnableInput = _f[1];
8275
+ var _g = React$1.useState({
8248
8276
  text: "",
8249
8277
  formats: []
8250
- }), input = _e[0], setInput = _e[1];
8278
+ }), input = _g[0], setInput = _g[1];
8251
8279
  function toggleDrawer() {
8252
8280
  var newDrawer = !drawerOpen;
8253
8281
  setDrawerState(newDrawer);
@@ -8283,6 +8311,9 @@ var ChatFooter = function (props) {
8283
8311
  setInput(data);
8284
8312
  setSuggestionSearch(data.text);
8285
8313
  }, []);
8314
+ var handleAdminJoin = function (status) {
8315
+ setEnableInput(status);
8316
+ };
8286
8317
  return (React__default$1["default"].createElement("div", { className: "chat-footer background-footer", "aria-label": menuItems.length ? "to open menu click a button above the rounded rectangle at the bottom of widget" : "", "aria-hidden": false },
8287
8318
  showMenu && menuItems.length ?
8288
8319
  React__default$1["default"].createElement(React__default$1["default"].Fragment, null,
@@ -8290,11 +8321,12 @@ var ChatFooter = function (props) {
8290
8321
  React__default$1["default"].createElement("div", { className: "chat-footer__menu-icon" },
8291
8322
  React__default$1["default"].createElement(DrawerBars, { tabIndex: menuButtonTabIndex, onToggle: toggleDrawer }))) : React__default$1["default"].createElement(React__default$1["default"].Fragment, null),
8292
8323
  React__default$1["default"].createElement(Suggestions, { className: "xappw-chat-footer__suggestions", data: suggestions.suggestions, index: suggestions.index, searchTerms: suggestionSearch, onItemClick: handleItemClick, onItemUse: handleItemUse }),
8293
- props.isAdmin && props.isChatting && props.visible && React__default$1["default"].createElement(AdminBar, null),
8294
- 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,
8295
- // onFocus={this.inputOnFocus}
8296
- onFileUpload: props.onFileUpload }),
8297
- brandingEnabled && React__default$1["default"].createElement(ChatBranding, { text: 'Powered by [XAPP AI](https://xapp.ai)' })));
8324
+ isAdmin && isChatting && visible && React__default$1["default"].createElement(AdminBar, { onAdminJoin: handleAdminJoin }),
8325
+ React__default$1["default"].createElement("div", { style: { pointerEvents: enableInput ? "auto" : "none", opacity: enableInput ? 1 : 0.5 } },
8326
+ React__default$1["default"].createElement(Input, { addClass: "chat-footer__input " + (isChatting && visible ? "visible" : ""), suggestion: suggestions.item, value: input, placeholder: placeholder, sendButtonIcon: sendButtonIcon, footerConfig: footerConfig, inputConfig: inputConfig, onSubmit: handleSubmit, onChange: handleChange, onSuggestionCommand: suggestions.execute,
8327
+ // onFocus={this.inputOnFocus}
8328
+ onFileUpload: props.onFileUpload })),
8329
+ brandingEnabled && brandingText && React__default$1["default"].createElement(ChatBranding, { text: brandingText })));
8298
8330
  };
8299
8331
 
8300
8332
  var noop = function () { };