@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.
- package/dist/App.d.ts +0 -0
- package/dist/components/ChatButton/ChatButton.d.ts +0 -0
- package/dist/components/ChatButton/ChatButton.stories.d.ts +7 -0
- package/dist/components/ChatFooter/ChatFooter.d.ts +0 -0
- package/dist/components/ChatFooter/ChatFooter.stories.d.ts +3 -0
- package/dist/components/ChatWidget/ChatWidget.d.ts +0 -0
- package/dist/components/ChatWidget/ChatWidget.stories.d.ts +6 -0
- package/dist/components/ChatWidget/ChatWidget.test.d.ts +1 -0
- package/dist/components/ChatWidget/ChatWidgetContainer.d.ts +0 -0
- package/dist/components/ChatWidget/ChatWidgetEnv.stories.d.ts +1 -0
- package/dist/components/CtaBubble/CtaBubble.d.ts +0 -0
- package/dist/components/CtaBubble/CtaBubble.stories.d.ts +2 -0
- package/dist/components/CtaBubble/CtaBubbleContainer.d.ts +0 -0
- package/dist/components/ErrorOverlay/ErrorOverlay.d.ts +0 -0
- package/dist/components/ErrorOverlay/ErrorOverlay.stories.d.ts +8 -0
- package/dist/components/ErrorOverlay/index.d.ts +0 -0
- package/dist/components/Input/Input.d.ts +0 -0
- package/dist/components/Input/Input.stories.d.ts +7 -3
- package/dist/components/SendButton/SendButton.d.ts +0 -0
- package/dist/components/SendButton/SendButton.stories.d.ts +8 -4
- package/dist/index.css +1 -1
- package/dist/index.es.js +619 -101
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +619 -101
- package/dist/index.js.map +1 -1
- package/dist/store/ChatAction.d.ts +0 -0
- package/dist/store/ChatState.d.ts +0 -0
- package/dist/store/DefaultState.d.ts +0 -0
- package/dist/store/actions/index.d.ts +0 -0
- package/dist/store/actions/toggleDebugMode.d.ts +0 -0
- package/dist/xapp/StentorRouterChat.d.ts +0 -0
- package/dist/xapp/XappChat.d.ts +0 -0
- package/dist/xapp/__tests__/StentorRouterChat.test.d.ts +2 -0
- package/dist/xapp-chat-widget.css +1 -1
- package/dist/xapp-chat-widget.js +4 -4
- package/dist/xapp-chat-widget.js.map +1 -1
- 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 = {
|
|
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 ?
|
|
684
|
-
borderWidth: ((_a = props.borderStyle) === null || _a === void 0 ? void 0 : _a.width) ||
|
|
685
|
-
borderColor: ((_b = props.borderStyle) === null || _b === void 0 ? void 0 : _b.color) ||
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
703
|
-
|
|
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
|
-
|
|
707
|
-
|
|
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
|
-
|
|
719
|
-
|
|
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
|
-
|
|
801
|
+
if (delayTimer) {
|
|
802
|
+
log("[CtaBubbleContainer] Clearing delay timer");
|
|
803
|
+
clearTimeout(delayTimer);
|
|
804
|
+
}
|
|
728
805
|
};
|
|
729
|
-
}, [startTime, timeout, delay]);
|
|
730
|
-
|
|
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
|
-
|
|
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
|
-
},
|
|
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
|
|
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
|
-
|
|
2869
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
8945
|
-
|
|
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
|
|
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
|
-
|
|
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, "
|
|
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
|
|
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 =
|
|
31494
|
-
var
|
|
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
|
-
|
|
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
|
|
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(
|
|
31992
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
31533
31993
|
return function () {
|
|
31534
|
-
document.removeEventListener(
|
|
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
|
-
}, [
|
|
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
|
-
//
|
|
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) ||
|
|
31675
|
-
||
|
|
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: (
|
|
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: (
|
|
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 ((
|
|
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
|
};
|