@xapp/chat-widget 1.78.0 → 1.79.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.
Files changed (37) hide show
  1. package/dist/App.d.ts +0 -0
  2. package/dist/components/ChatButton/ChatButton.d.ts +0 -0
  3. package/dist/components/ChatButton/ChatButton.stories.d.ts +7 -0
  4. package/dist/components/ChatFooter/ChatFooter.d.ts +0 -0
  5. package/dist/components/ChatFooter/ChatFooter.stories.d.ts +3 -0
  6. package/dist/components/ChatWidget/ChatWidget.d.ts +0 -0
  7. package/dist/components/ChatWidget/ChatWidget.stories.d.ts +6 -0
  8. package/dist/components/ChatWidget/ChatWidget.test.d.ts +1 -0
  9. package/dist/components/ChatWidget/ChatWidgetContainer.d.ts +0 -0
  10. package/dist/components/ChatWidget/ChatWidgetEnv.stories.d.ts +1 -0
  11. package/dist/components/CtaBubble/CtaBubble.d.ts +0 -0
  12. package/dist/components/CtaBubble/CtaBubble.stories.d.ts +2 -0
  13. package/dist/components/CtaBubble/CtaBubbleContainer.d.ts +0 -0
  14. package/dist/components/ErrorOverlay/ErrorOverlay.d.ts +0 -0
  15. package/dist/components/ErrorOverlay/ErrorOverlay.stories.d.ts +8 -0
  16. package/dist/components/ErrorOverlay/index.d.ts +0 -0
  17. package/dist/components/Input/Input.d.ts +0 -0
  18. package/dist/components/Input/Input.stories.d.ts +7 -3
  19. package/dist/components/SendButton/SendButton.d.ts +0 -0
  20. package/dist/components/SendButton/SendButton.stories.d.ts +8 -4
  21. package/dist/index.css +1 -1
  22. package/dist/index.es.js +619 -101
  23. package/dist/index.es.js.map +1 -1
  24. package/dist/index.js +619 -101
  25. package/dist/index.js.map +1 -1
  26. package/dist/store/ChatAction.d.ts +0 -0
  27. package/dist/store/ChatState.d.ts +0 -0
  28. package/dist/store/DefaultState.d.ts +0 -0
  29. package/dist/store/actions/index.d.ts +0 -0
  30. package/dist/store/actions/toggleDebugMode.d.ts +0 -0
  31. package/dist/xapp/StentorRouterChat.d.ts +0 -0
  32. package/dist/xapp/XappChat.d.ts +0 -0
  33. package/dist/xapp/__tests__/StentorRouterChat.test.d.ts +2 -0
  34. package/dist/xapp-chat-widget.css +1 -1
  35. package/dist/xapp-chat-widget.js +4 -4
  36. package/dist/xapp-chat-widget.js.map +1 -1
  37. package/package.json +10 -10
package/dist/index.js CHANGED
@@ -306,6 +306,27 @@ function getTimeAgo(date) {
306
306
  }
307
307
 
308
308
  var EMAIL_REGEX = "^\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+$";
309
+ // Initialize log level from localStorage on module load
310
+ var STORAGE_KEY = 'xaLogLevel';
311
+ var storedLogLevel = localStorage.getItem(STORAGE_KEY);
312
+ if (storedLogLevel) {
313
+ window.xaLogLevel = storedLogLevel;
314
+ }
315
+ // Override the setter to persist to localStorage
316
+ Object.defineProperty(window, 'xaLogLevel', {
317
+ get: function () {
318
+ return this._xaLogLevel;
319
+ },
320
+ set: function (value) {
321
+ this._xaLogLevel = value;
322
+ if (value) {
323
+ localStorage.setItem(STORAGE_KEY, value);
324
+ }
325
+ else {
326
+ localStorage.removeItem(STORAGE_KEY);
327
+ }
328
+ }
329
+ });
309
330
  // Returns current timestamp
310
331
  function getCurrentDateString() {
311
332
  return (new Date()).toISOString() + " ::";
@@ -605,7 +626,7 @@ function resize(vec, length) {
605
626
  return mul(vec, length / currentLength);
606
627
  }
607
628
  function rotateZ(vec, angle) {
608
- var rad = angle * Math.PI / 180;
629
+ var rad = (angle * Math.PI) / 180;
609
630
  var ca = Math.cos(rad);
610
631
  var sa = Math.sin(rad);
611
632
  var resx = vec.x * ca + vec.y * sa;
@@ -622,9 +643,9 @@ function intersectLineEllipsis(ellipsis, line) {
622
643
  var ry = ellipsis.radius.y;
623
644
  var rx2 = rx * rx;
624
645
  var ry2 = ry * ry;
625
- var a = (kx * kx / rx2 + ky * ky / ry2);
626
- var b = (2 * kx * sx / rx2 + 2 * ky * sy / ry2);
627
- var c = (sx * sx / rx2 + sy * sy / ry2 - 1);
646
+ var a = (kx * kx) / rx2 + (ky * ky) / ry2;
647
+ var b = (2 * kx * sx) / rx2 + (2 * ky * sy) / ry2;
648
+ var c = (sx * sx) / rx2 + (sy * sy) / ry2 - 1;
628
649
  var d2 = b * b - 4 * a * c;
629
650
  if (d2 >= 0) {
630
651
  var d = Math.sqrt(d2);
@@ -643,10 +664,13 @@ function intersectLineEllipsis(ellipsis, line) {
643
664
  return line.start;
644
665
  }
645
666
  function getTailSvgPath$1(props, viewport) {
646
- var baseAngleRad = props.direction * Math.PI / 180;
667
+ var baseAngleRad = (props.direction * Math.PI) / 180;
647
668
  var radius = { x: props.width / 2, y: props.height / 2 };
648
669
  var center = { x: viewport.x / 2, y: viewport.y / 2 };
649
- var intersectionRel = { x: radius.x * Math.cos(baseAngleRad), y: radius.y * Math.sin(baseAngleRad) };
670
+ var intersectionRel = {
671
+ x: radius.x * Math.cos(baseAngleRad),
672
+ y: radius.y * Math.sin(baseAngleRad),
673
+ };
650
674
  var farRel = resize(intersectionRel, len(intersectionRel) + props.length);
651
675
  var far = add$1(farRel, center);
652
676
  var direction = sub$1(intersectionRel, farRel);
@@ -655,15 +679,15 @@ function getTailSvgPath$1(props, viewport) {
655
679
  var rightDirection = rotateZ(direction, -angle / 2);
656
680
  var ellipsis = {
657
681
  center: center,
658
- radius: radius
682
+ radius: radius,
659
683
  };
660
684
  var left = intersectLineEllipsis(ellipsis, {
661
685
  start: far,
662
- direction: leftDirection
686
+ direction: leftDirection,
663
687
  });
664
688
  var right = intersectLineEllipsis(ellipsis, {
665
689
  start: far,
666
- direction: rightDirection
690
+ direction: rightDirection,
667
691
  });
668
692
  return "m ".concat(far.x, " ").concat(far.y, " L ").concat(left.x, " ").concat(left.y, " L ").concat(right.x, " ").concat(right.y, " z");
669
693
  }
@@ -671,69 +695,133 @@ var CtaBubbleTail = function (props) {
671
695
  var _a, _b;
672
696
  var _c = useDimensions(), ref = _c[0], rect = _c[1];
673
697
  var viewPort = { x: (_a = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _a !== void 0 ? _a : 0, y: (_b = rect === null || rect === void 0 ? void 0 : rect.height) !== null && _b !== void 0 ? _b : 0 };
674
- return React$1.createElement("div", { ref: ref, className: "cta-bubble__tail" },
698
+ return (React$1.createElement("div", { ref: ref, className: "cta-bubble__tail" },
675
699
  React$1.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 ".concat(viewPort.x, " ").concat(viewPort.y) },
676
- React$1.createElement("path", { d: getTailSvgPath$1(props, viewPort), fill: "currentColor" })));
700
+ React$1.createElement("path", { d: getTailSvgPath$1(props, viewPort), fill: "currentColor" }))));
677
701
  };
678
702
  var CtaBubble = function (props) {
679
703
  var _a, _b, _c, _d;
680
704
  var _e = useDimensions(), ref = _e[0], rect = _e[1];
681
705
  var animate = props.animate || false;
682
706
  var animation = animate && props.buttonAnimation === "bounce" ? "bounce" : "none";
707
+ var handleDismiss = function (e) {
708
+ e.stopPropagation();
709
+ if (props.onDismiss) {
710
+ props.onDismiss();
711
+ }
712
+ };
713
+ console.log("Returning CTABubble with message: ", props.children);
683
714
  return (React$1.createElement("div", { ref: ref, style: {
684
- border: props.borderStyle ? 'solid' : 'none',
685
- borderWidth: ((_a = props.borderStyle) === null || _a === void 0 ? void 0 : _a.width) || '0px',
686
- borderColor: ((_b = props.borderStyle) === null || _b === void 0 ? void 0 : _b.color) || 'transparent',
715
+ border: props.borderStyle ? "solid" : "none",
716
+ borderWidth: ((_a = props.borderStyle) === null || _a === void 0 ? void 0 : _a.width) || "0px",
717
+ borderColor: ((_b = props.borderStyle) === null || _b === void 0 ? void 0 : _b.color) || "transparent",
687
718
  animation: "".concat(animation, " 1s infinite"),
688
719
  }, className: "cta-bubble", onClick: props.onClick },
689
720
  React$1.createElement(CtaBubbleTail, { width: (_c = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _c !== void 0 ? _c : 0, height: (_d = rect === null || rect === void 0 ? void 0 : rect.height) !== null && _d !== void 0 ? _d : 0, direction: 60, angle: 45, length: 16 }),
690
- React$1.createElement("div", { className: "cta-bubble__content" }, props.children)));
721
+ React$1.createElement("div", { className: "cta-bubble__content" }, props.children),
722
+ props.dismissible && (React$1.createElement("button", { className: "cta-bubble__dismiss", onClick: handleDismiss, "aria-label": "Dismiss" },
723
+ React$1.createElement("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
724
+ React$1.createElement("path", { d: "M11 1L1 11M1 1L11 11", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }))))));
691
725
  };
692
726
 
693
727
  var CtaBubbleContainer = function (props) {
694
- var visible = props.visible, timeout = props.timeout, delay = props.delay, animate = props.animate, buttonAnimation = props.buttonAnimation, onClick = props.onClick, children = props.children;
728
+ var visible = props.visible, timeout = props.timeout, delay = props.delay, animate = props.animate, buttonAnimation = props.buttonAnimation, dismissible = props.dismissible, onClick = props.onClick, onDismiss = props.onDismiss, children = props.children;
729
+ // Debug: Log all props received
730
+ log("[CtaBubbleContainer] Props received:", {
731
+ visible: visible,
732
+ timeout: timeout,
733
+ delay: delay,
734
+ animate: animate,
735
+ buttonAnimation: buttonAnimation,
736
+ dismissible: dismissible,
737
+ hasOnClick: !!onClick,
738
+ hasOnDismiss: !!onDismiss,
739
+ hasChildren: !!children,
740
+ childrenContent: children,
741
+ });
695
742
  var startTime = React$1.useMemo(function () {
696
- return visible ? new Date().valueOf() : undefined;
743
+ var time = visible ? new Date().valueOf() : undefined;
744
+ log("[CtaBubbleContainer] StartTime calculated: visible=".concat(visible, ", startTime=").concat(time));
745
+ return time;
697
746
  }, [visible]);
698
747
  var _a = React$1.useState(false), showBubble = _a[0], setShowBubble = _a[1];
699
- var isMounted = React$1.useRef(true);
748
+ log("[CtaBubbleContainer] Current state: showBubble=".concat(showBubble));
700
749
  React$1.useEffect(function () {
750
+ log("[CtaBubbleContainer] useEffect triggered with:", {
751
+ startTime: startTime,
752
+ startTimeExists: !!startTime,
753
+ timeout: timeout,
754
+ timeoutType: typeof timeout,
755
+ delay: delay,
756
+ delayType: typeof delay,
757
+ visible: visible,
758
+ });
701
759
  var hideTimer = null;
760
+ var delayTimer = null;
761
+ var isMounted = true;
702
762
  if (startTime) {
703
- var delayTimer_1 = setTimeout(function () {
704
- if (isMounted.current) {
763
+ var actualDelay_1 = delay || 0;
764
+ log("[CtaBubbleContainer] Timer setup: actualDelay=".concat(actualDelay_1, "ms (from delay=").concat(delay, ")"));
765
+ delayTimer = setTimeout(function () {
766
+ log("[CtaBubbleContainer] Delay timer fired after ".concat(actualDelay_1, "ms, isMounted=").concat(isMounted));
767
+ if (isMounted) {
768
+ log("[CtaBubbleContainer] Component still mounted, setting showBubble=true");
705
769
  setShowBubble(true);
770
+ if (typeof timeout === "number") {
771
+ log("[CtaBubbleContainer] Hide timer setup: will hide after ".concat(timeout, "ms"));
772
+ hideTimer = setTimeout(function () {
773
+ log("[CtaBubbleContainer] Hide timer fired after ".concat(timeout, "ms, isMounted=").concat(isMounted));
774
+ if (isMounted) {
775
+ log("[CtaBubbleContainer] Component still mounted, setting showBubble=false");
776
+ setShowBubble(false);
777
+ }
778
+ else {
779
+ log("[CtaBubbleContainer] Component unmounted, skipping hide");
780
+ }
781
+ }, timeout);
782
+ }
783
+ else {
784
+ log("[CtaBubbleContainer] No hide timer set (timeout=".concat(timeout, ", type=").concat(typeof timeout, ")"));
785
+ }
706
786
  }
707
- if (typeof timeout === "number") {
708
- hideTimer = setTimeout(function () {
709
- if (isMounted.current) {
710
- setShowBubble(false);
711
- }
712
- }, timeout);
713
- }
714
- }, delay);
715
- return function () {
716
- if (hideTimer) {
717
- clearTimeout(hideTimer);
787
+ else {
788
+ log("[CtaBubbleContainer] Component unmounted before delay timer, not showing bubble");
718
789
  }
719
- clearTimeout(delayTimer_1);
720
- isMounted.current = false;
721
- };
790
+ }, actualDelay_1);
791
+ }
792
+ else {
793
+ log("[CtaBubbleContainer] No startTime, skipping timer setup");
722
794
  }
723
- // Return a cleanup function for the case where startTime is undefined
724
795
  return function () {
796
+ log("[CtaBubbleContainer] Cleanup triggered, unmounting component");
797
+ isMounted = false;
725
798
  if (hideTimer) {
799
+ log("[CtaBubbleContainer] Clearing hide timer");
726
800
  clearTimeout(hideTimer);
727
801
  }
728
- isMounted.current = false;
802
+ if (delayTimer) {
803
+ log("[CtaBubbleContainer] Clearing delay timer");
804
+ clearTimeout(delayTimer);
805
+ }
729
806
  };
730
- }, [startTime, timeout, delay]);
731
- return (React$1.createElement(React$1.Fragment, null, visible && showBubble && React$1.createElement(CtaBubble, { onClick: onClick, animate: animate, buttonAnimation: buttonAnimation }, children)));
807
+ }, [startTime, timeout, delay, visible]);
808
+ var handleDismiss = function () {
809
+ log("[CtaBubbleContainer] handleDismiss called, setting showBubble=false");
810
+ setShowBubble(false);
811
+ if (onDismiss) {
812
+ log("[CtaBubbleContainer] Calling onDismiss callback");
813
+ onDismiss();
814
+ }
815
+ };
816
+ // Final render decision
817
+ var shouldRender = visible && showBubble;
818
+ log("[CtaBubbleContainer] Render decision: visible=".concat(visible, ", showBubble=").concat(showBubble, ", shouldRender=").concat(shouldRender));
819
+ return (React$1.createElement(React$1.Fragment, null, visible && showBubble && (React$1.createElement(CtaBubble, { onClick: onClick, animate: animate, buttonAnimation: buttonAnimation, dismissible: dismissible, onDismiss: handleDismiss }, children))));
732
820
  };
733
821
 
734
822
  var ChatButton = function (_a) {
735
823
  var _b;
736
- var onClick = _a.onClick, addClass = _a.addClass, config = _a.config, visible = _a.visible, borderStyle = _a.borderStyle, imageUrl = _a.imageUrl;
824
+ var onClick = _a.onClick, addClass = _a.addClass, config = _a.config, visible = _a.visible, borderStyle = _a.borderStyle, imageUrl = _a.imageUrl, hasInteracted = _a.hasInteracted, onCtaDismiss = _a.onCtaDismiss;
737
825
  var _c = React$1.useState(defaultWidgetButtonWidth), buttonWidth = _c[0], setButtonWidth = _c[1];
738
826
  var _d = React$1.useState(false), animate = _d[0], setAnimate = _d[1];
739
827
  var mobileWidth = ((_b = config === null || config === void 0 ? void 0 : config.mobile) === null || _b === void 0 ? void 0 : _b.applyAtLessThanWidth) || defaultNonMobileScreenWidth;
@@ -749,9 +837,17 @@ var ChatButton = function (_a) {
749
837
  };
750
838
  var configToApply = getConfigToApply();
751
839
  React$1.useEffect(function () {
840
+ var _a;
752
841
  var delayTimer;
753
842
  var timeoutTimer;
754
- if (configToApply === null || configToApply === void 0 ? void 0 : configToApply.delay) {
843
+ // Don't animate if user has already interacted
844
+ if (hasInteracted) {
845
+ setAnimate(false);
846
+ return function () { }; // Return empty cleanup function
847
+ }
848
+ // Use animationDelay if provided, otherwise fall back to delay for backwards compatibility
849
+ var animationDelayToUse = (_a = configToApply === null || configToApply === void 0 ? void 0 : configToApply.animationDelay) !== null && _a !== void 0 ? _a : configToApply === null || configToApply === void 0 ? void 0 : configToApply.delay;
850
+ if (animationDelayToUse) {
755
851
  // Set a delay for the animation to start
756
852
  delayTimer = setTimeout(function () {
757
853
  setAnimate(true);
@@ -761,7 +857,7 @@ var ChatButton = function (_a) {
761
857
  setAnimate(false);
762
858
  }, configToApply.animationTimeout);
763
859
  }
764
- }, configToApply.delay);
860
+ }, animationDelayToUse);
765
861
  }
766
862
  else if (configToApply === null || configToApply === void 0 ? void 0 : configToApply.animationTimeout) {
767
863
  // Start animation immediately and set a timeout to stop it
@@ -781,8 +877,8 @@ var ChatButton = function (_a) {
781
877
  if (timeoutTimer)
782
878
  clearTimeout(timeoutTimer);
783
879
  };
784
- }, [configToApply, setAnimate]);
785
- var animation = animate ? (configToApply === null || configToApply === void 0 ? void 0 : configToApply.animation) || "wiggle" : "none";
880
+ }, [configToApply, setAnimate, hasInteracted]);
881
+ var animation = animate && !hasInteracted ? (configToApply === null || configToApply === void 0 ? void 0 : configToApply.animation) || "wiggle" : "none";
786
882
  React$1.useEffect(function () {
787
883
  var handleResize = function () {
788
884
  var screenWidth = window.innerWidth;
@@ -814,8 +910,8 @@ var ChatButton = function (_a) {
814
910
  // Fallback to default SVG
815
911
  React$1.createElement("svg", { width: svgSize, height: svgSize, viewBox: "0 0 22 22" },
816
912
  React$1.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" })))),
817
- configToApply && configToApply.message && (React$1.createElement("div", { className: "xapp-chat-button__cta" },
818
- React$1.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)))));
913
+ configToApply && configToApply.message && !hasInteracted && (React$1.createElement("div", { className: "xapp-chat-button__cta" },
914
+ React$1.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, dismissible: configToApply === null || configToApply === void 0 ? void 0 : configToApply.dismissible, visible: !visible /** Why is this !visible */, onDismiss: onCtaDismiss }, configToApply === null || configToApply === void 0 ? void 0 : configToApply.message)))));
819
915
  };
820
916
 
821
917
  var ChatCard = function (props) {
@@ -2795,6 +2891,7 @@ var StentorRouterChat = /** @class */ (function () {
2795
2891
  this._sessionId = "";
2796
2892
  this.accessToken = "";
2797
2893
  this.attributes = {};
2894
+ this.routerAttributes = {};
2798
2895
  this.isAdmin = false;
2799
2896
  this.urlAttributes = {};
2800
2897
  this.handlers = {};
@@ -2863,13 +2960,19 @@ var StentorRouterChat = /** @class */ (function () {
2863
2960
  this.handlers["new message"] = function (data, sender, ts) {
2864
2961
  // Because the router's internal message format is Stentor channel compatible.
2865
2962
  // So the data is either a stentor Request (from widget) or a stentor Response (from bot)
2866
- var _a;
2963
+ var _a, _b;
2867
2964
  var message;
2868
2965
  if (sender.deviceId === "Bot") {
2869
- if (typeof ((_a = _this.options.hooks) === null || _a === void 0 ? void 0 : _a.onResponse) === "function") {
2870
- _this.options.hooks.onResponse(message);
2966
+ var response = data;
2967
+ // Extract custom attributes from router response
2968
+ if (((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.routerAttributes) && typeof response.data.routerAttributes === "object") {
2969
+ _this.routerAttributes = __assign({}, response.data.routerAttributes);
2970
+ log("Extracted router attributes: ".concat(JSON.stringify(_this.routerAttributes)));
2871
2971
  }
2872
- message = responseToMessage(data);
2972
+ if (typeof ((_b = _this.options.hooks) === null || _b === void 0 ? void 0 : _b.onResponse) === "function") {
2973
+ _this.options.hooks.onResponse(response);
2974
+ }
2975
+ message = responseToMessage(response);
2873
2976
  }
2874
2977
  else if (sender.deviceId === "Widget") {
2875
2978
  message = requestToMessage(data);
@@ -3302,7 +3405,7 @@ var StentorRouterChat = /** @class */ (function () {
3302
3405
  };
3303
3406
  StentorRouterChat.prototype.postMessage = function (message) {
3304
3407
  return __awaiter$1(this, void 0, void 0, function () {
3305
- var userId, sessionId, accessToken, attributes, rwgToken, merchantId, environment, enablePreferredTime, service, origin, request;
3408
+ var userId, sessionId, accessToken, attributes, rwgToken, merchantId, environment, enablePreferredTime, service, origin, mergedAttributes, request;
3306
3409
  return __generator$1(this, function (_a) {
3307
3410
  userId = this._userId;
3308
3411
  sessionId = this._sessionId;
@@ -3332,7 +3435,8 @@ var StentorRouterChat = /** @class */ (function () {
3332
3435
  if (origin) {
3333
3436
  attributes["origin"] = origin;
3334
3437
  }
3335
- request = requestFromMessage(message, userId, this.isNewSession, sessionId, accessToken, attributes, this.visitorInfo);
3438
+ mergedAttributes = __assign(__assign({}, attributes), this.routerAttributes);
3439
+ request = requestFromMessage(message, userId, this.isNewSession, sessionId, accessToken, mergedAttributes, this.visitorInfo);
3336
3440
  this.emit("new message", request);
3337
3441
  return [2 /*return*/];
3338
3442
  });
@@ -7624,22 +7728,21 @@ var StentorServerChat = /** @class */ (function () {
7624
7728
  return StentorServerChat;
7625
7729
  }());
7626
7730
 
7627
- // import { useWhatChanged } from '@simbathesailor/use-what-changed';
7628
7731
  function createChatServerCore(config, options) {
7629
7732
  switch (config.type) {
7630
7733
  case "direct":
7631
7734
  return new StentorDirectChat({
7632
7735
  url: config.serverUrl,
7633
7736
  key: config.accountKey,
7634
- timeout: config.timeout
7737
+ timeout: config.timeout,
7635
7738
  }, options);
7636
7739
  case "websocket":
7637
7740
  return new StentorServerChat({
7638
- url: config.serverUrl
7741
+ url: config.serverUrl,
7639
7742
  }, options);
7640
7743
  case "websocketraw":
7641
7744
  return new StentorRouterChat({
7642
- url: config.serverUrl
7745
+ url: config.serverUrl,
7643
7746
  }, options);
7644
7747
  case "local":
7645
7748
  return new StentorLocalChat();
@@ -7658,6 +7761,11 @@ function useChatServer(config, options) {
7658
7761
  // Log what caused the "effect"
7659
7762
  // useWhatChanged(deps, "options, config, dispatch");
7660
7763
  React$1.useEffect(function () {
7764
+ // Don't create server if config is null (waiting for async config load)
7765
+ if (!config || !options) {
7766
+ setServer(undefined);
7767
+ return undefined;
7768
+ }
7661
7769
  var newServer = createChatServer(config, options);
7662
7770
  newServer.init(dispatch);
7663
7771
  setServer(newServer);
@@ -8942,13 +9050,25 @@ var SendIcon = function () {
8942
9050
  };
8943
9051
 
8944
9052
  var SendButton = function (props) {
8945
- 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 },
8946
- React$1.createElement("img", { src: props.sendButtonIcon, alt: "Send button", draggable: false })))));
9053
+ var _a = props.disabled, disabled = _a === void 0 ? false : _a;
9054
+ var _b = React$1.useState(false), isHovered = _b[0], setIsHovered = _b[1];
9055
+ // Determine which icon to show based on state
9056
+ var getIconSrc = function () {
9057
+ if (disabled && props.sendButtonIconDisabled) {
9058
+ return props.sendButtonIconDisabled;
9059
+ }
9060
+ if (isHovered && !disabled && props.sendButtonIconHover) {
9061
+ return props.sendButtonIconHover;
9062
+ }
9063
+ return props.sendButtonIcon;
9064
+ };
9065
+ return (React$1.createElement(React$1.Fragment, null, !props.sendButtonIcon ? (React$1.createElement(IconButton_1, { className: "xappw-send-button ".concat(props.className || "", " ").concat(disabled ? 'disabled' : ''), tabIndex: props.tabIndex, onClick: disabled ? undefined : props.onClick, icon: SendIcon })) : (React$1.createElement("button", { className: "xappw-custom-send-button ".concat(disabled ? 'disabled' : ''), tabIndex: props.tabIndex ? Number(props.tabIndex) : 0, onClick: props.onClick, disabled: disabled, onMouseEnter: function () { return setIsHovered(true); }, onMouseLeave: function () { return setIsHovered(false); } },
9066
+ React$1.createElement("img", { src: getIconSrc(), alt: "Send button", draggable: false, className: "send-button-icon" })))));
8947
9067
  };
8948
9068
 
8949
9069
  var Input = function (props) {
8950
9070
  var _a, _b;
8951
- 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;
9071
+ var value = props.value, placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, sendButtonIconHover = props.sendButtonIconHover, sendButtonIconDisabled = props.sendButtonIconDisabled, suggestion = props.suggestion, footerConfig = props.footerConfig, inputConfig = props.inputConfig, onChange = props.onChange, onSubmit = props.onSubmit, onSuggestionCommand = props.onSuggestionCommand;
8952
9072
  var _c = React$1.useState(false), dragover = _c[0], setDragover = _c[1];
8953
9073
  function onDragOver(event) {
8954
9074
  setDragover(true);
@@ -9004,7 +9124,7 @@ var Input = function (props) {
9004
9124
  value: value, spellCheck: true }),
9005
9125
  React$1.createElement("div", { className: "xappw-input-form__buttons" },
9006
9126
  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 })),
9007
- 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 })))));
9127
+ React$1.createElement(SendButton, { className: "xappw-input-form__btn", sendButtonIcon: sendButtonIcon, sendButtonIconHover: sendButtonIconHover, sendButtonIconDisabled: sendButtonIconDisabled, tabIndex: (_b = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.sendButton) === null || _b === void 0 ? void 0 : _b.tabIndex, disabled: !value.text, onClick: handleOnSubmit })))));
9008
9128
  };
9009
9129
 
9010
9130
  function createActions(onItemUse) {
@@ -9066,7 +9186,7 @@ var Suggestions = function (props) {
9066
9186
 
9067
9187
  var ChatFooter = function (props) {
9068
9188
  var _a, _b, _c;
9069
- 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;
9189
+ var isAdmin = props.isAdmin, isChatting = props.isChatting, visible = props.visible, placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, sendButtonIconHover = props.sendButtonIconHover, sendButtonIconDisabled = props.sendButtonIconDisabled, footerConfig = props.footerConfig, menuConfig = props.menuConfig, inputConfig = props.inputConfig, onSubmit = props.onSubmit;
9070
9190
  var innerDispatch = useChatDispatch();
9071
9191
  var _d = React$1.useState(false), drawerOpen = _d[0], setDrawerState = _d[1]; // false initially
9072
9192
  var _e = React$1.useState(), suggestionSearch = _e[0], setSuggestionSearch = _e[1];
@@ -9132,7 +9252,7 @@ var ChatFooter = function (props) {
9132
9252
  React$1.createElement(Suggestions, { className: "xappw-chat-footer__suggestions", data: suggestions.suggestions, index: suggestions.index, searchTerms: suggestionSearch, onItemClick: handleItemClick, onItemUse: handleItemUse }),
9133
9253
  isAdmin && isChatting && visible && React$1.createElement(AdminBar, { onAdminJoin: handleAdminJoin }),
9134
9254
  React$1.createElement("div", { style: { pointerEvents: enableInput ? "auto" : "none", opacity: enableInput ? 1 : 0.5 } },
9135
- React$1.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,
9255
+ React$1.createElement(Input, { addClass: "chat-footer__input " + (isChatting && visible ? "visible" : ""), suggestion: suggestions.item, value: input, placeholder: placeholder, sendButtonIcon: sendButtonIcon, sendButtonIconHover: sendButtonIconHover, sendButtonIconDisabled: sendButtonIconDisabled, footerConfig: footerConfig, inputConfig: inputConfig, onSubmit: handleSubmit, onChange: handleChange, onSuggestionCommand: suggestions.execute,
9136
9256
  // onFocus={this.inputOnFocus}
9137
9257
  onFileUpload: props.onFileUpload })),
9138
9258
  brandingEnabled && brandingText && React$1.createElement(ChatBranding, { text: brandingText })));
@@ -31360,6 +31480,9 @@ function getButtonStyle(style) {
31360
31480
  _a.sent();
31361
31481
  return [4 /*yield*/, ["button-hover-bg", style === null || style === void 0 ? void 0 : style.hoverBackground]];
31362
31482
  case 4:
31483
+ _a.sent();
31484
+ return [4 /*yield*/, ["button-disabled-bg", style === null || style === void 0 ? void 0 : style.disabledBackground]];
31485
+ case 5:
31363
31486
  _a.sent();
31364
31487
  return [2 /*return*/];
31365
31488
  }
@@ -31416,6 +31539,285 @@ function getCtaStyle(style) {
31416
31539
  return union(getBackgroundStyle(style.background), getTextStyle(style.text));
31417
31540
  }
31418
31541
 
31542
+ /**
31543
+ * Safely stringify objects, handling circular references and errors
31544
+ */
31545
+ var safeStringify = function (arg) {
31546
+ if (arg === null)
31547
+ return "null";
31548
+ if (arg === undefined)
31549
+ return "undefined";
31550
+ if (typeof arg !== "object")
31551
+ return String(arg);
31552
+ try {
31553
+ var seen_1 = new WeakSet();
31554
+ return JSON.stringify(arg, function (_key, value) {
31555
+ if (typeof value === "object" && value !== null) {
31556
+ if (seen_1.has(value)) {
31557
+ return "[Circular]";
31558
+ }
31559
+ seen_1.add(value);
31560
+ }
31561
+ return value;
31562
+ }, 2);
31563
+ }
31564
+ catch (e) {
31565
+ return "[Object: ".concat(Object.prototype.toString.call(arg), "]");
31566
+ }
31567
+ };
31568
+ var ErrorOverlay = function () {
31569
+ var _a;
31570
+ var _b = React$1.useState([]), errors = _b[0], setErrors = _b[1];
31571
+ var _c = React$1.useState(false), isMinimized = _c[0], setIsMinimized = _c[1];
31572
+ var _d = React$1.useState(true), isVisible = _d[0], setIsVisible = _d[1];
31573
+ var _e = React$1.useState(false), isEnabled = _e[0], setIsEnabled = _e[1];
31574
+ var _f = React$1.useState("bottom"), position = _f[0], setPosition = _f[1];
31575
+ // Check if error overlay should be enabled and load position
31576
+ React$1.useEffect(function () {
31577
+ var _a;
31578
+ var checkEnabled = function () {
31579
+ var _a;
31580
+ if (typeof window === "undefined")
31581
+ return false;
31582
+ // Check localStorage
31583
+ var localStorageSetting = (_a = window.localStorage) === null || _a === void 0 ? void 0 : _a.getItem("xaErrorOverlay");
31584
+ if (localStorageSetting === "enabled") {
31585
+ console.log("[ErrorOverlay] Enabled via localStorage");
31586
+ return true;
31587
+ }
31588
+ if (localStorageSetting === "disabled") {
31589
+ console.log("[ErrorOverlay] Disabled via localStorage");
31590
+ return false;
31591
+ }
31592
+ // Check for React Native dev mode
31593
+ if (typeof globalThis.__DEV__ !== "undefined" && globalThis.__DEV__) {
31594
+ console.log("[ErrorOverlay] Enabled via __DEV__");
31595
+ return true;
31596
+ }
31597
+ return false;
31598
+ };
31599
+ var enabled = checkEnabled();
31600
+ setIsEnabled(enabled);
31601
+ // Load position preference
31602
+ var savedPosition = (_a = window.localStorage) === null || _a === void 0 ? void 0 : _a.getItem("xaErrorOverlayPosition");
31603
+ if (savedPosition === "top" || savedPosition === "bottom") {
31604
+ setPosition(savedPosition);
31605
+ }
31606
+ console.log("[ErrorOverlay] Component mounted, enabled:", enabled, "position:", savedPosition || "bottom");
31607
+ }, []);
31608
+ // Define addError with useCallback to prevent stale closures
31609
+ var addError = React$1.useCallback(function (error) {
31610
+ console.log("[ErrorOverlay] Adding error:", error);
31611
+ setErrors(function (prev) {
31612
+ var timestamp = new Date().toISOString();
31613
+ // Check if this is a duplicate of the last error
31614
+ var lastError = prev[prev.length - 1];
31615
+ if (lastError && lastError.message === error.message) {
31616
+ // Update count of last error
31617
+ return __spreadArray$1(__spreadArray$1([], prev.slice(0, -1), true), [
31618
+ __assign(__assign({}, lastError), { count: lastError.count + 1, timestamp: timestamp }),
31619
+ ], false);
31620
+ }
31621
+ // Add new error
31622
+ var newError = __assign({ id: "".concat(timestamp, "-").concat(Math.random()), timestamp: timestamp, count: 1 }, error);
31623
+ // Keep only last 50 errors
31624
+ var updated = __spreadArray$1(__spreadArray$1([], prev, true), [newError], false);
31625
+ return updated.slice(-50);
31626
+ });
31627
+ }, []);
31628
+ React$1.useEffect(function () {
31629
+ if (!isEnabled) {
31630
+ console.log("[ErrorOverlay] Not enabled, skipping error interception");
31631
+ return undefined;
31632
+ }
31633
+ console.log("[ErrorOverlay] Setting up error interception");
31634
+ // Store original console methods
31635
+ var originalError = console.error;
31636
+ var originalWarn = console.warn;
31637
+ // Override console.error
31638
+ console.error = function () {
31639
+ var args = [];
31640
+ for (var _i = 0; _i < arguments.length; _i++) {
31641
+ args[_i] = arguments[_i];
31642
+ }
31643
+ var message = args.map(function (arg) { return safeStringify(arg); }).join(" ");
31644
+ var error = new Error();
31645
+ addError({
31646
+ message: message,
31647
+ type: "error",
31648
+ stack: error.stack,
31649
+ });
31650
+ // Call original method
31651
+ originalError.apply(console, args);
31652
+ };
31653
+ // Override console.warn
31654
+ console.warn = function () {
31655
+ var args = [];
31656
+ for (var _i = 0; _i < arguments.length; _i++) {
31657
+ args[_i] = arguments[_i];
31658
+ }
31659
+ var message = args.map(function (arg) { return safeStringify(arg); }).join(" ");
31660
+ addError({
31661
+ message: message,
31662
+ type: "warning",
31663
+ });
31664
+ // Call original method
31665
+ originalWarn.apply(console, args);
31666
+ };
31667
+ // Capture unhandled errors
31668
+ var handleError = function (event) {
31669
+ var _a;
31670
+ addError({
31671
+ message: event.message,
31672
+ type: "error",
31673
+ stack: (_a = event.error) === null || _a === void 0 ? void 0 : _a.stack,
31674
+ });
31675
+ };
31676
+ // Capture unhandled promise rejections
31677
+ var handleRejection = function (event) {
31678
+ var _a;
31679
+ addError({
31680
+ message: "Unhandled Promise Rejection: ".concat(event.reason),
31681
+ type: "error",
31682
+ stack: (_a = event.reason) === null || _a === void 0 ? void 0 : _a.stack,
31683
+ });
31684
+ };
31685
+ window.addEventListener("error", handleError);
31686
+ window.addEventListener("unhandledrejection", handleRejection);
31687
+ // Cleanup
31688
+ return function () {
31689
+ console.log("[ErrorOverlay] Cleaning up error interception");
31690
+ console.error = originalError;
31691
+ console.warn = originalWarn;
31692
+ window.removeEventListener("error", handleError);
31693
+ window.removeEventListener("unhandledrejection", handleRejection);
31694
+ };
31695
+ }, [isEnabled, addError]);
31696
+ var clearErrors = function () {
31697
+ setErrors([]);
31698
+ };
31699
+ var copyToClipboard = function () { return __awaiter$1(void 0, void 0, void 0, function () {
31700
+ var errorText, err_1, textarea;
31701
+ return __generator$1(this, function (_a) {
31702
+ switch (_a.label) {
31703
+ case 0:
31704
+ errorText = errors
31705
+ .map(function (e) {
31706
+ return "[".concat(e.timestamp, "] ").concat(e.type.toUpperCase(), ": ").concat(e.message).concat(e.stack ? "\n" + e.stack : "");
31707
+ })
31708
+ .join("\n\n");
31709
+ _a.label = 1;
31710
+ case 1:
31711
+ _a.trys.push([1, 3, , 4]);
31712
+ return [4 /*yield*/, navigator.clipboard.writeText(errorText)];
31713
+ case 2:
31714
+ _a.sent();
31715
+ console.log("[ErrorOverlay] Errors copied to clipboard");
31716
+ return [3 /*break*/, 4];
31717
+ case 3:
31718
+ err_1 = _a.sent();
31719
+ console.error("[ErrorOverlay] Failed to copy to clipboard:", err_1);
31720
+ textarea = document.createElement("textarea");
31721
+ textarea.value = errorText;
31722
+ textarea.style.position = "fixed";
31723
+ textarea.style.opacity = "0";
31724
+ document.body.appendChild(textarea);
31725
+ textarea.select();
31726
+ try {
31727
+ document.execCommand("copy");
31728
+ console.log("[ErrorOverlay] Errors copied to clipboard using fallback method");
31729
+ }
31730
+ catch (fallbackErr) {
31731
+ console.error("[ErrorOverlay] Fallback copy method also failed:", fallbackErr);
31732
+ }
31733
+ document.body.removeChild(textarea);
31734
+ return [3 /*break*/, 4];
31735
+ case 4: return [2 /*return*/];
31736
+ }
31737
+ });
31738
+ }); };
31739
+ // Toggle enabled state
31740
+ var toggleEnabled = function () {
31741
+ var newState = !isEnabled;
31742
+ setIsEnabled(newState);
31743
+ if (typeof window !== "undefined" && window.localStorage) {
31744
+ window.localStorage.setItem("xaErrorOverlay", newState ? "enabled" : "disabled");
31745
+ }
31746
+ console.log("[ErrorOverlay] Toggled enabled state to:", newState);
31747
+ // Clear errors when disabling
31748
+ if (!newState) {
31749
+ setErrors([]);
31750
+ }
31751
+ };
31752
+ // Toggle position between top and bottom
31753
+ var togglePosition = function () {
31754
+ var newPosition = position === "bottom" ? "top" : "bottom";
31755
+ setPosition(newPosition);
31756
+ if (typeof window !== "undefined" && window.localStorage) {
31757
+ window.localStorage.setItem("xaErrorOverlayPosition", newPosition);
31758
+ }
31759
+ };
31760
+ // Don't render if not enabled
31761
+ if (!isEnabled) {
31762
+ // Show a small, subtle toggle button to enable (only visible on hover)
31763
+ return (React$1.createElement("button", { onClick: toggleEnabled, style: (_a = {
31764
+ position: "fixed"
31765
+ },
31766
+ _a[position] = "10px",
31767
+ _a.right = "10px",
31768
+ _a.zIndex = 999999,
31769
+ _a.background = "#ff6b6b",
31770
+ _a.color = "white",
31771
+ _a.border = "none",
31772
+ _a.borderRadius = "6px",
31773
+ _a.padding = "8px 12px",
31774
+ _a.fontSize = "20px",
31775
+ _a.cursor = "pointer",
31776
+ _a.opacity = 0.1, // Very subtle by default
31777
+ _a.transition = "opacity 0.2s",
31778
+ _a.minWidth = "44px",
31779
+ _a.minHeight = "44px",
31780
+ _a.display = "flex",
31781
+ _a.alignItems = "center",
31782
+ _a.justifyContent = "center",
31783
+ _a), onMouseEnter: function (e) { return (e.currentTarget.style.opacity = "0.8"); }, onMouseLeave: function (e) { return (e.currentTarget.style.opacity = "0.1"); }, title: "Enable Error Overlay (for debugging)" }, "\uD83D\uDC1B"));
31784
+ }
31785
+ // If enabled but not visible (user closed it), don't render
31786
+ if (!isVisible) {
31787
+ return null;
31788
+ }
31789
+ // If enabled and visible but no errors yet, don't show the overlay
31790
+ // Only show when there are actual errors to display
31791
+ if (errors.length === 0) {
31792
+ return null;
31793
+ }
31794
+ return (React$1.createElement("div", { className: "error-overlay error-overlay--".concat(position, " ").concat(isMinimized ? "minimized" : "") },
31795
+ React$1.createElement("div", { className: "error-overlay-header" },
31796
+ React$1.createElement("span", { className: "error-overlay-title" },
31797
+ "Debug Console (",
31798
+ errors.length,
31799
+ ")"),
31800
+ React$1.createElement("div", { className: "error-overlay-actions" },
31801
+ React$1.createElement("button", { onClick: copyToClipboard, title: "Copy all to clipboard" }, "\uD83D\uDCCB"),
31802
+ React$1.createElement("button", { onClick: clearErrors, title: "Clear all" }, "\uD83D\uDDD1\uFE0F"),
31803
+ React$1.createElement("button", { onClick: togglePosition, title: "Move to ".concat(position === "bottom" ? "top" : "bottom") }, position === "bottom" ? "⬆️" : "⬇️"),
31804
+ React$1.createElement("button", { onClick: toggleEnabled, title: "Disable Error Overlay" }, "\uD83D\uDD27"),
31805
+ React$1.createElement("button", { onClick: function () { return setIsMinimized(!isMinimized); }, title: "Minimize/Maximize" }, isMinimized ? "▲" : "▼"),
31806
+ React$1.createElement("button", { onClick: function () { return setIsVisible(false); }, title: "Close" }, "\u2715"))),
31807
+ !isMinimized && (React$1.createElement("div", { className: "error-overlay-content" }, errors.map(function (error) { return (React$1.createElement("div", { key: error.id, className: "error-entry error-".concat(error.type) },
31808
+ React$1.createElement("div", { className: "error-header" },
31809
+ React$1.createElement("span", { className: "error-time" }, new Date(error.timestamp).toLocaleTimeString()),
31810
+ error.count > 1 && (React$1.createElement("span", { className: "error-count" },
31811
+ "(",
31812
+ error.count,
31813
+ "x)")),
31814
+ React$1.createElement("span", { className: "error-badge error-badge-".concat(error.type) }, error.type)),
31815
+ React$1.createElement("div", { className: "error-message" }, error.message),
31816
+ error.stack && (React$1.createElement("details", { className: "error-stack" },
31817
+ React$1.createElement("summary", null, "Stack trace"),
31818
+ React$1.createElement("pre", null, error.stack))))); })))));
31819
+ };
31820
+
31419
31821
  var ModalContent = function (_a) {
31420
31822
  var onClose = _a.onClose, onReset = _a.onReset;
31421
31823
  return (React$1.createElement("div", { className: "modalContent" },
@@ -31428,7 +31830,44 @@ var ModalContent = function (_a) {
31428
31830
  };
31429
31831
 
31430
31832
  var ChatWidgetWrapper = function (props) {
31431
- var rawConfig = props.config;
31833
+ var _a;
31834
+ var _b = React$1.useState(props.config), rawConfig = _b[0], setRawConfig = _b[1];
31835
+ var _c = React$1.useState(!!props.getConfig), configLoading = _c[0], setConfigLoading = _c[1];
31836
+ var _d = React$1.useState(), configError = _d[0], setConfigError = _d[1];
31837
+ // Load config from callback if provided
31838
+ React$1.useEffect(function () {
31839
+ var cancelled = false;
31840
+ if (props.getConfig) {
31841
+ setConfigLoading(true);
31842
+ setConfigError(undefined);
31843
+ props
31844
+ .getConfig()
31845
+ .then(function (config) {
31846
+ if (!cancelled) {
31847
+ setRawConfig(config);
31848
+ setConfigLoading(false);
31849
+ log("[ChatWidget] Config loaded from getConfig callback");
31850
+ }
31851
+ })
31852
+ .catch(function (error) {
31853
+ if (!cancelled) {
31854
+ setConfigError(error);
31855
+ setConfigLoading(false);
31856
+ err("[ChatWidget] Failed to load config: ".concat(error.message));
31857
+ }
31858
+ });
31859
+ }
31860
+ else if (props.config) {
31861
+ // If no callback, use the config prop directly
31862
+ setRawConfig(props.config);
31863
+ setConfigLoading(false);
31864
+ }
31865
+ return function () {
31866
+ cancelled = true;
31867
+ };
31868
+ // Only depend on getConfig and config - not the entire props object to avoid infinite loops
31869
+ // eslint-disable-next-line react-hooks/exhaustive-deps
31870
+ }, [props.getConfig, props.config]);
31432
31871
  var connection = useConnectionInfo(rawConfig);
31433
31872
  var config = React$1.useMemo(function () {
31434
31873
  var _a;
@@ -31437,7 +31876,7 @@ var ChatWidgetWrapper = function (props) {
31437
31876
  var token = reactRedux.useSelector(function (state) { return state.connection.token; });
31438
31877
  var options = React$1.useMemo(function () {
31439
31878
  var configurableMessages = getConfigurableMessages();
31440
- if (rawConfig.configurableMessages &&
31879
+ if ((rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.configurableMessages) &&
31441
31880
  Array.isArray(rawConfig.configurableMessages.items) &&
31442
31881
  rawConfig.configurableMessages.items.length > 0) {
31443
31882
  configurableMessages = rawConfig.configurableMessages;
@@ -31446,20 +31885,37 @@ var ChatWidgetWrapper = function (props) {
31446
31885
  token: token,
31447
31886
  bot: {
31448
31887
  nick: "Bot",
31449
- displayName: rawConfig.botName,
31450
- avatarPath: rawConfig.avatarUrl
31888
+ displayName: rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.botName,
31889
+ avatarPath: rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.avatarUrl,
31451
31890
  },
31452
31891
  configurableMessages: configurableMessages,
31453
- hooks: rawConfig.hooks
31892
+ hooks: rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.hooks,
31454
31893
  };
31455
31894
  }, [token, rawConfig]);
31456
- var chatServer = useChatServer(connection, options);
31895
+ // Only create chat server when config is ready (not loading and no error)
31896
+ var chatServer = useChatServer(configLoading || configError ? null : connection, configLoading || configError ? null : options);
31897
+ // Determine mode class for loading/error states
31898
+ var mode = (_a = props.mode) !== null && _a !== void 0 ? _a : "normal";
31899
+ var modeClass = "widget-container--".concat(mode);
31900
+ // Show loading state while config is being fetched
31901
+ if (configLoading) {
31902
+ return (React$1.createElement("div", { className: "widget-container widget-container--loading ".concat(modeClass) },
31903
+ React$1.createElement("div", { className: "xa-spinner-container visible" },
31904
+ React$1.createElement("div", { className: "xa-spinner" }))));
31905
+ }
31906
+ // Show error state if config failed to load
31907
+ if (configError) {
31908
+ return (React$1.createElement("div", { className: "widget-container widget-container--error ".concat(modeClass) },
31909
+ React$1.createElement("div", { className: "widget-error-message" },
31910
+ "Failed to load chat configuration: ",
31911
+ configError.message)));
31912
+ }
31457
31913
  return (React$1.createElement(ChatConfigContext.Provider, { value: config },
31458
31914
  React$1.createElement(ChatServerContext.Provider, { value: chatServer },
31459
- React$1.createElement(ChatWidget, __assign({}, props)))));
31915
+ React$1.createElement(ChatWidget, __assign({}, props, { config: rawConfig })))));
31460
31916
  };
31461
31917
  var ChatWidget = function (props) {
31462
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2;
31918
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7;
31463
31919
  var innerDispatch = useChatDispatch();
31464
31920
  var dispatch = useChatServerDispatch();
31465
31921
  // From Redux
@@ -31473,7 +31929,7 @@ var ChatWidget = function (props) {
31473
31929
  var canRefresh = (_c = (_b = props.config.header) === null || _b === void 0 ? void 0 : _b.actions) === null || _c === void 0 ? void 0 : _c.refresh;
31474
31930
  // can't minimize in docked mode or static mode.
31475
31931
  var canMinimize = !dockedMode && !staticMode && ((_e = (_d = props.config.header) === null || _d === void 0 ? void 0 : _d.actions) === null || _e === void 0 ? void 0 : _e.minimize);
31476
- log("docked: ".concat(dockedMode, " static: ").concat(staticMode, " minimimized: ").concat((_g = (_f = props.config.header) === null || _f === void 0 ? void 0 : _f.actions) === null || _g === void 0 ? void 0 : _g.minimize));
31932
+ log("docked: ".concat(dockedMode, " static: ").concat(staticMode, " minimized: ").concat((_g = (_f = props.config.header) === null || _f === void 0 ? void 0 : _f.actions) === null || _g === void 0 ? void 0 : _g.minimize));
31477
31933
  var canCancel;
31478
31934
  // To preserve legacy behavior, cancel needs a little more checks
31479
31935
  if (typeof ((_j = (_h = props.config.header) === null || _h === void 0 ? void 0 : _h.actions) === null || _j === void 0 ? void 0 : _j.cancel) === "boolean") {
@@ -31482,17 +31938,17 @@ var ChatWidget = function (props) {
31482
31938
  else {
31483
31939
  canCancel = !dockedMode && !staticMode;
31484
31940
  }
31485
- // For backward compatibility. Note: the action will create the actual "visuals" object" (this is a copy).
31941
+ // For backward compatibility. Note: the action will create the actual "visuals" object" (this is a copy).
31486
31942
  if (!chatState.visuals) {
31487
31943
  chatState.visuals = {};
31488
31944
  }
31489
31945
  // Our state - pull from storage
31490
- var _3 = React$1.useState((!canMinimize && !canCancel) ||
31946
+ var _8 = React$1.useState((!canMinimize && !canCancel) ||
31491
31947
  // !!get("visible") ||
31492
31948
  chatState.visuals.visible ||
31493
31949
  (((_m = props.config) === null || _m === void 0 ? void 0 : _m.autoOpenOnWidth) &&
31494
- window.matchMedia("(min-width: ".concat((_o = props.config) === null || _o === void 0 ? void 0 : _o.autoOpenOnWidth, ")")).matches)), visible = _3[0], setVisibleState = _3[1];
31495
- var _4 = React$1.useState(false), typing = _4[0], setTypingState = _4[1]; // false initially
31950
+ window.matchMedia("(min-width: ".concat((_o = props.config) === null || _o === void 0 ? void 0 : _o.autoOpenOnWidth, ")")).matches)), visible = _8[0], setVisibleState = _8[1];
31951
+ var _9 = React$1.useState(false), typing = _9[0], setTypingState = _9[1]; // false initially
31496
31952
  var chatServer = React$1.useContext(ChatServerContext);
31497
31953
  var patternsConfig = (_q = (_p = props.config) === null || _p === void 0 ? void 0 : _p.autoOpenOnPattern) === null || _q === void 0 ? void 0 : _q.patterns;
31498
31954
  var currentUrl = window.location.href;
@@ -31507,32 +31963,36 @@ var ChatWidget = function (props) {
31507
31963
  }
31508
31964
  setVisibleState(newVisible);
31509
31965
  innerDispatch(setVisualStatus({
31510
- visible: newVisible
31966
+ visible: newVisible,
31511
31967
  }));
31512
31968
  }, [innerDispatch, staticMode]);
31513
31969
  React$1.useEffect(function () {
31514
31970
  var _a, _b;
31515
- document.addEventListener("keydown", function (event) {
31971
+ var handleKeyDown = function (event) {
31516
31972
  var body = document.getElementsByTagName("body")[0];
31517
31973
  body.tabIndex = -1;
31518
31974
  if (event.key === "Escape") {
31519
31975
  body.focus();
31520
31976
  }
31521
- });
31977
+ };
31978
+ document.addEventListener("keydown", handleKeyDown);
31522
31979
  if (checkSessionExpiration((chatState === null || chatState === void 0 ? void 0 : chatState.sessionExpiration) || ((_a = props.config) === null || _a === void 0 ? void 0 : _a.sessionExpiration), (_b = chatState === null || chatState === void 0 ? void 0 : chatState.chats[chatState.chats.length - 1]) === null || _b === void 0 ? void 0 : _b.timestamp, chatState === null || chatState === void 0 ? void 0 : chatState.lastTimestamp)) {
31523
31980
  innerDispatch(setSessionId(undefined));
31524
31981
  innerDispatch(reset());
31525
31982
  }
31983
+ return function () {
31984
+ document.removeEventListener("keydown", handleKeyDown);
31985
+ };
31526
31986
  // eslint-disable-next-line react-hooks/exhaustive-deps
31527
31987
  }, []);
31528
- var _5 = React$1.useState(!document.hidden), isTabVisible = _5[0], setIsTabVisible = _5[1];
31988
+ var _10 = React$1.useState(!document.hidden), isTabVisible = _10[0], setIsTabVisible = _10[1];
31529
31989
  React$1.useEffect(function () {
31530
31990
  var handleVisibilityChange = function () {
31531
31991
  setIsTabVisible(!document.hidden);
31532
31992
  };
31533
- document.addEventListener('visibilitychange', handleVisibilityChange);
31993
+ document.addEventListener("visibilitychange", handleVisibilityChange);
31534
31994
  return function () {
31535
- document.removeEventListener('visibilitychange', handleVisibilityChange);
31995
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
31536
31996
  };
31537
31997
  }, []);
31538
31998
  React$1.useEffect(function () {
@@ -31566,7 +32026,15 @@ var ChatWidget = function (props) {
31566
32026
  if (currentWidth < +configWidth) {
31567
32027
  setVisible(false);
31568
32028
  }
31569
- }, [currentWidth, patternExist, patternMatches, configWidth, setVisible, chatState.visuals.opened, mode]);
32029
+ }, [
32030
+ currentWidth,
32031
+ patternExist,
32032
+ patternMatches,
32033
+ configWidth,
32034
+ setVisible,
32035
+ chatState.visuals.opened,
32036
+ mode,
32037
+ ]);
31570
32038
  function handleOnChange() {
31571
32039
  if (!typing) {
31572
32040
  dispatch(sendTyping(true));
@@ -31638,28 +32106,37 @@ var ChatWidget = function (props) {
31638
32106
  /** Called when minimize button is clicked */
31639
32107
  function handleMinimizeClick() {
31640
32108
  innerDispatch(setVisualStatus({
31641
- opened: false
32109
+ opened: false,
32110
+ hasInteracted: true,
31642
32111
  }));
31643
32112
  setVisible(false);
31644
32113
  }
31645
32114
  /** Called when cancel is clicked */
31646
32115
  function handleCancelClick() {
31647
- //set("opened", false);
32116
+ // First reset to clear all state
32117
+ innerDispatch(reset());
32118
+ // Then set hasInteracted to prevent CTA from showing after cancel
31648
32119
  innerDispatch(setVisualStatus({
31649
- opened: false
32120
+ opened: false,
32121
+ hasInteracted: true,
31650
32122
  }));
31651
- innerDispatch(reset());
31652
32123
  setVisible(false);
31653
32124
  }
31654
32125
  function chatButtonOnClick() {
31655
32126
  innerDispatch(setVisualStatus({
31656
- opened: true
32127
+ opened: true,
32128
+ hasInteracted: true,
31657
32129
  }));
31658
32130
  setVisible(true);
31659
32131
  setTimeout(function () {
31660
32132
  document.getElementById("chatWidgetInput").focus();
31661
32133
  }, 100);
31662
32134
  }
32135
+ function handleCtaDismiss() {
32136
+ innerDispatch(setVisualStatus({
32137
+ hasInteracted: true,
32138
+ }));
32139
+ }
31663
32140
  var isOffline = chatState.accountStatus === "offline" && !chatState.isChatting;
31664
32141
  var messages = chatState && chatState.chats;
31665
32142
  var config = props.config, onConnectionStatusChange = props.onConnectionStatusChange;
@@ -31672,8 +32149,12 @@ var ChatWidget = function (props) {
31672
32149
  }, [connectionStatus, onConnectionStatusChange]);
31673
32150
  useExternalScript((_t = props.config) === null || _t === void 0 ? void 0 : _t.middlewareUrl);
31674
32151
  // This is a pseudo agent. It represent's the widget (shown in the header avatar for instance)
31675
- var widgetAgent = ((_u = chatState.agents["agent:robot"]) === null || _u === void 0 ? void 0 : _u.user) || (config === null || config === void 0 ? void 0 : config.agent)
31676
- || { nick: "agent:robot", avatarPath: config.avatarUrl, display_name: "Agent" };
32152
+ var widgetAgent = ((_u = chatState.agents["agent:robot"]) === null || _u === void 0 ? void 0 : _u.user) ||
32153
+ (config === null || config === void 0 ? void 0 : config.agent) || {
32154
+ nick: "agent:robot",
32155
+ avatarPath: config.avatarUrl,
32156
+ display_name: "Agent",
32157
+ };
31677
32158
  return (React$1.createElement(React$1.Fragment, null,
31678
32159
  React$1.createElement("div", { className: "widget-container ".concat(modeClass, " ").concat(getVisibilityClass()) },
31679
32160
  React$1.createElement(WidgetStylesheet, { theme: config === null || config === void 0 ? void 0 : config.theme }),
@@ -31682,10 +32163,11 @@ var ChatWidget = function (props) {
31682
32163
  React$1.createElement("div", { className: "xa-spinner-container ".concat(visible && connectionStatus === "pending" ? "visible" : "") },
31683
32164
  React$1.createElement("div", { className: "xa-spinner" })),
31684
32165
  connectionStatus === "offline" && React$1.createElement(ServerOffline, null),
31685
- React$1.createElement(ChatFooter, { isAdmin: config === null || config === void 0 ? void 0 : config.isAdmin, isChatting: chatState.isChatting, placeholder: (_x = config === null || config === void 0 ? void 0 : config.input) === null || _x === void 0 ? void 0 : _x.placeholder, sendButtonIcon: (_z = (_y = config === null || config === void 0 ? void 0 : config.footer) === null || _y === void 0 ? void 0 : _y.sendButton) === null || _z === void 0 ? void 0 : _z.icon, visible: visible, menuConfig: props.config.menu, footerConfig: (_0 = props.config) === null || _0 === void 0 ? void 0 : _0.footer, inputConfig: (_1 = props.config) === null || _1 === void 0 ? void 0 : _1.input, onChange: handleOnChange, onSubmit: handleOnSubmit, onFileUpload: handleFileUpload }),
32166
+ React$1.createElement(ChatFooter, { isAdmin: config === null || config === void 0 ? void 0 : config.isAdmin, isChatting: chatState.isChatting, placeholder: (_x = config === null || config === void 0 ? void 0 : config.input) === null || _x === void 0 ? void 0 : _x.placeholder, sendButtonIcon: (_z = (_y = config === null || config === void 0 ? void 0 : config.footer) === null || _y === void 0 ? void 0 : _y.sendButton) === null || _z === void 0 ? void 0 : _z.icon, sendButtonIconHover: (_1 = (_0 = config === null || config === void 0 ? void 0 : config.footer) === null || _0 === void 0 ? void 0 : _0.sendButton) === null || _1 === void 0 ? void 0 : _1.iconHover, sendButtonIconDisabled: (_3 = (_2 = config === null || config === void 0 ? void 0 : config.footer) === null || _2 === void 0 ? void 0 : _2.sendButton) === null || _3 === void 0 ? void 0 : _3.iconDisabled, visible: visible, menuConfig: props.config.menu, footerConfig: (_4 = props.config) === null || _4 === void 0 ? void 0 : _4.footer, inputConfig: (_5 = props.config) === null || _5 === void 0 ? void 0 : _5.input, onChange: handleOnChange, onSubmit: handleOnSubmit, onFileUpload: handleFileUpload }),
31686
32167
  React$1.createElement("div", { className: "restartModal", ref: modalRef, onClick: handleRestartModalCloseClick },
31687
32168
  React$1.createElement(ModalContent, { onClose: handleRestartModalCloseClick, onReset: handleReset }))),
31688
- React$1.createElement(ChatButton, { addClass: getVisibilityClass(), onClick: chatButtonOnClick, config: config === null || config === void 0 ? void 0 : config.cta, imageUrl: (_2 = config === null || config === void 0 ? void 0 : config.chatButton) === null || _2 === void 0 ? void 0 : _2.imageUrl, visible: visible })));
32169
+ React$1.createElement(ChatButton, { addClass: getVisibilityClass(), onClick: chatButtonOnClick, config: config === null || config === void 0 ? void 0 : config.cta, imageUrl: (_6 = config === null || config === void 0 ? void 0 : config.chatButton) === null || _6 === void 0 ? void 0 : _6.imageUrl, visible: visible, hasInteracted: (_7 = chatState.visuals) === null || _7 === void 0 ? void 0 : _7.hasInteracted, onCtaDismiss: handleCtaDismiss }),
32170
+ React$1.createElement(ErrorOverlay, null)));
31689
32171
  };
31690
32172
 
31691
32173
  // src/utils/formatProdErrorMessage.ts
@@ -32162,17 +32644,37 @@ var DEFAULT_VISITOR = {
32162
32644
  nick: "visitor:",
32163
32645
  typing: false
32164
32646
  };
32165
- function createDefaultState(state) {
32647
+ function createDefaultState(state, options) {
32648
+ var _a;
32166
32649
  if (!state) {
32167
32650
  state = {};
32168
32651
  }
32169
32652
  state.userId = state.userId ? state.userId : visitorFingerprint();
32170
32653
  state.visitorId = state.userId;
32654
+ // Determine if debug mode should be enabled
32655
+ var debugMode = false;
32656
+ if (typeof window !== 'undefined') {
32657
+ var localStorageSetting = (_a = window.localStorage) === null || _a === void 0 ? void 0 : _a.getItem('xaErrorOverlay');
32658
+ if (localStorageSetting === 'enabled') {
32659
+ debugMode = true;
32660
+ }
32661
+ else if (localStorageSetting === 'disabled') {
32662
+ debugMode = false;
32663
+ }
32664
+ else if (options === null || options === void 0 ? void 0 : options.enableErrorOverlay) {
32665
+ // Use config option if no localStorage override
32666
+ debugMode = true;
32667
+ }
32668
+ else if (typeof globalThis.__DEV__ !== 'undefined' && globalThis.__DEV__) {
32669
+ // For React Native, default to true in development mode
32670
+ debugMode = true;
32671
+ }
32672
+ }
32171
32673
  return __assign({ connection: {
32172
32674
  connectionStatus: "offline",
32173
32675
  token: null,
32174
32676
  greetingRequested: false
32175
- }, accountStatus: "offline", departments: {}, visitor: DEFAULT_VISITOR, agents: {}, chats: [], lastTimestamp: 0, lastRatingRequestTimestamp: 0, hasRating: false, isChatting: false, queuePosition: 0, failureMsg: null, visitorId: visitorFingerprint(), chips: [], sessionExpiration: "24h", visuals: {} }, state);
32677
+ }, accountStatus: "offline", departments: {}, visitor: DEFAULT_VISITOR, agents: {}, chats: [], lastTimestamp: 0, lastRatingRequestTimestamp: 0, hasRating: false, isChatting: false, queuePosition: 0, failureMsg: null, visitorId: visitorFingerprint(), chips: [], sessionExpiration: "24h", visuals: {}, debugMode: debugMode }, state);
32176
32678
  }
32177
32679
  var DEFAULT_STATE = createDefaultState();
32178
32680
 
@@ -32221,6 +32723,10 @@ var LocalStorage = /** @class */ (function () {
32221
32723
  function persistStateReducer(storage, initialState, innerReducer) {
32222
32724
  var _a;
32223
32725
  var obj = (_a = storage.get()) !== null && _a !== void 0 ? _a : initialState;
32726
+ // Clean up hasInteracted flag on page load - don't persist across browser refreshes
32727
+ if (obj && obj.visuals) {
32728
+ obj = __assign(__assign({}, obj), { visuals: __assign(__assign({}, obj.visuals), { hasInteracted: undefined }) });
32729
+ }
32224
32730
  return function (state, action) {
32225
32731
  if (state === void 0) { state = obj; }
32226
32732
  var res = innerReducer(state, action);
@@ -32279,13 +32785,14 @@ function memberLeave(state, detail) {
32279
32785
 
32280
32786
  function resetReducer(state) {
32281
32787
  if (state === void 0) { state = DEFAULT_STATE; }
32282
- // pass through some of the items to persis
32283
32788
  return __assign(__assign({}, createDefaultState({
32284
32789
  accessToken: state.accessToken,
32285
32790
  userId: state.userId,
32286
32791
  attributes: state.attributes,
32287
32792
  sessionExpiration: state.sessionExpiration
32288
- })), { connection: __assign(__assign({}, state.connection), { greetingRequested: false, nonce: uuid_1() }), visitor: state.visitor, visitorId: state.visitorId });
32793
+ })), { connection: __assign(__assign({}, state.connection), { greetingRequested: false, nonce: uuid_1() }), visitor: state.visitor, visitorId: state.visitorId,
32794
+ // Explicitly reset visuals to clear hasInteracted flag for widget refresh
32795
+ visuals: {} });
32289
32796
  }
32290
32797
 
32291
32798
  // todo: create reducer (requires redux-thunk dependency)
@@ -32318,7 +32825,14 @@ function update(state, action) {
32318
32825
  case "session_id":
32319
32826
  return __assign(__assign({}, state), { lastTimestamp: (_g = action.detail) === null || _g === void 0 ? void 0 : _g.timestamp, sessionId: action.detail.sessionId });
32320
32827
  case "visual_status":
32321
- return __assign(__assign({}, state), { lastTimestamp: (_h = action.detail) === null || _h === void 0 ? void 0 : _h.timestamp, visuals: __assign(__assign(__assign(__assign({}, (state.visuals || {})), (action.detail.status.drawer !== undefined && { drawer: action.detail.status.drawer })), (action.detail.status.opened !== undefined && { opened: action.detail.status.opened })), (action.detail.status.visible !== undefined && { visible: action.detail.status.visible })) });
32828
+ return __assign(__assign({}, state), { lastTimestamp: (_h = action.detail) === null || _h === void 0 ? void 0 : _h.timestamp, visuals: __assign(__assign(__assign(__assign(__assign({}, (state.visuals || {})), (action.detail.status.drawer !== undefined && { drawer: action.detail.status.drawer })), (action.detail.status.opened !== undefined && { opened: action.detail.status.opened })), (action.detail.status.visible !== undefined && { visible: action.detail.status.visible })), (action.detail.status.hasInteracted !== undefined && { hasInteracted: action.detail.status.hasInteracted })) });
32829
+ case "toggle_debug_mode":
32830
+ var newDebugMode = !state.debugMode;
32831
+ // Update localStorage to persist the setting
32832
+ if (typeof window !== 'undefined' && window.localStorage) {
32833
+ window.localStorage.setItem('xaErrorOverlay', newDebugMode ? 'enabled' : 'disabled');
32834
+ }
32835
+ return __assign(__assign({}, state), { debugMode: newDebugMode });
32322
32836
  case "department_update":
32323
32837
  return __assign(__assign({}, state), { lastTimestamp: (_j = action.detail) === null || _j === void 0 ? void 0 : _j.timestamp, departments: __assign(__assign({}, state.departments), (_a = {}, _a[action.detail.id] = __assign({}, action.detail), _a)) });
32324
32838
  case "visitor_update":
@@ -32469,6 +32983,8 @@ function createChatStore(config, dataStorage) {
32469
32983
  userId: config.userId,
32470
32984
  attributes: config.attributes,
32471
32985
  sessionExpiration: config.sessionExpiration
32986
+ }, {
32987
+ enableErrorOverlay: config.enableErrorOverlay
32472
32988
  });
32473
32989
  var chatReducer = persistStateReducer(storage, defaultState, storeHandler);
32474
32990
  // Configure store with @reduxjs/toolkit
@@ -32508,23 +33024,25 @@ function generateKey(connection, sessionId) {
32508
33024
  }
32509
33025
 
32510
33026
  var ChatWidgetContainer = function (props) {
32511
- var _a, _b, _c, _d, _e;
33027
+ var _a, _b, _c, _d, _e, _f;
32512
33028
  var messageMiddleware = useStandardMiddleware();
32513
33029
  var connection = useServerConfig(props.config);
32514
33030
  var chatStore = React$1.useMemo(function () {
32515
- var _a, _b, _c, _d;
33031
+ var _a, _b, _c, _d, _e;
32516
33032
  return createChatStore({
32517
33033
  connection: connection,
32518
33034
  userId: (_a = props.config) === null || _a === void 0 ? void 0 : _a.userId,
32519
33035
  accessToken: (_b = props.config) === null || _b === void 0 ? void 0 : _b.accessToken,
32520
33036
  attributes: (_c = props.config) === null || _c === void 0 ? void 0 : _c.attributes,
32521
- sessionExpiration: (_d = props.config) === null || _d === void 0 ? void 0 : _d.sessionExpiration
33037
+ sessionExpiration: (_d = props.config) === null || _d === void 0 ? void 0 : _d.sessionExpiration,
33038
+ enableErrorOverlay: (_e = props.config) === null || _e === void 0 ? void 0 : _e.enableErrorOverlay
32522
33039
  });
32523
- }, [connection, (_a = props.config) === null || _a === void 0 ? void 0 : _a.userId, (_b = props.config) === null || _b === void 0 ? void 0 : _b.accessToken, (_c = props.config) === null || _c === void 0 ? void 0 : _c.attributes, (_d = props.config) === null || _d === void 0 ? void 0 : _d.sessionExpiration]);
32524
- if ((_e = props.config) === null || _e === void 0 ? void 0 : _e.disabled) {
33040
+ }, [connection, (_a = props.config) === null || _a === void 0 ? void 0 : _a.userId, (_b = props.config) === null || _b === void 0 ? void 0 : _b.accessToken, (_c = props.config) === null || _c === void 0 ? void 0 : _c.attributes, (_d = props.config) === null || _d === void 0 ? void 0 : _d.sessionExpiration, (_e = props.config) === null || _e === void 0 ? void 0 : _e.enableErrorOverlay]);
33041
+ if ((_f = props.config) === null || _f === void 0 ? void 0 : _f.disabled) {
32525
33042
  return React$1.createElement(React$1.Fragment, null);
32526
33043
  }
32527
- var widgetProps = __assign(__assign({}, props), { messageMiddleware: messageMiddleware });
33044
+ var widgetProps = __assign(__assign({}, props), { messageMiddleware: messageMiddleware, getConfig: props.getConfig // Pass through getConfig callback
33045
+ });
32528
33046
  return (React$1.createElement(reactRedux.Provider, { store: chatStore },
32529
33047
  React$1.createElement(ChatWidgetWrapper, __assign({}, widgetProps))));
32530
33048
  };