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