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