@xapp/chat-widget 1.78.1 → 1.79.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.d.ts +0 -0
- package/dist/components/ChatButton/ChatButton.d.ts +0 -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/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 +581 -96
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +581 -96
- 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,9 +695,9 @@ 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;
|
|
@@ -686,10 +710,11 @@ var CtaBubble = function (props) {
|
|
|
686
710
|
props.onDismiss();
|
|
687
711
|
}
|
|
688
712
|
};
|
|
713
|
+
console.log("Returning CTABubble with message: ", props.children);
|
|
689
714
|
return (React$1.createElement("div", { ref: ref, style: {
|
|
690
|
-
border: props.borderStyle ?
|
|
691
|
-
borderWidth: ((_a = props.borderStyle) === null || _a === void 0 ? void 0 : _a.width) ||
|
|
692
|
-
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",
|
|
693
718
|
animation: "".concat(animation, " 1s infinite"),
|
|
694
719
|
}, className: "cta-bubble", onClick: props.onClick },
|
|
695
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 }),
|
|
@@ -701,54 +726,102 @@ var CtaBubble = function (props) {
|
|
|
701
726
|
|
|
702
727
|
var CtaBubbleContainer = function (props) {
|
|
703
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
|
+
});
|
|
704
742
|
var startTime = React$1.useMemo(function () {
|
|
705
|
-
|
|
743
|
+
var time = visible ? new Date().valueOf() : undefined;
|
|
744
|
+
log("[CtaBubbleContainer] StartTime calculated: visible=".concat(visible, ", startTime=").concat(time));
|
|
745
|
+
return time;
|
|
706
746
|
}, [visible]);
|
|
707
747
|
var _a = React$1.useState(false), showBubble = _a[0], setShowBubble = _a[1];
|
|
708
|
-
|
|
748
|
+
log("[CtaBubbleContainer] Current state: showBubble=".concat(showBubble));
|
|
709
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
|
+
});
|
|
710
759
|
var hideTimer = null;
|
|
760
|
+
var delayTimer = null;
|
|
761
|
+
var isMounted = true;
|
|
711
762
|
if (startTime) {
|
|
712
|
-
var
|
|
713
|
-
|
|
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");
|
|
714
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
|
+
}
|
|
715
786
|
}
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
if (isMounted.current) {
|
|
719
|
-
setShowBubble(false);
|
|
720
|
-
}
|
|
721
|
-
}, timeout);
|
|
722
|
-
}
|
|
723
|
-
}, delay);
|
|
724
|
-
return function () {
|
|
725
|
-
if (hideTimer) {
|
|
726
|
-
clearTimeout(hideTimer);
|
|
787
|
+
else {
|
|
788
|
+
log("[CtaBubbleContainer] Component unmounted before delay timer, not showing bubble");
|
|
727
789
|
}
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
790
|
+
}, actualDelay_1);
|
|
791
|
+
}
|
|
792
|
+
else {
|
|
793
|
+
log("[CtaBubbleContainer] No startTime, skipping timer setup");
|
|
731
794
|
}
|
|
732
|
-
// Return a cleanup function for the case where startTime is undefined
|
|
733
795
|
return function () {
|
|
796
|
+
log("[CtaBubbleContainer] Cleanup triggered, unmounting component");
|
|
797
|
+
isMounted = false;
|
|
734
798
|
if (hideTimer) {
|
|
799
|
+
log("[CtaBubbleContainer] Clearing hide timer");
|
|
735
800
|
clearTimeout(hideTimer);
|
|
736
801
|
}
|
|
737
|
-
|
|
802
|
+
if (delayTimer) {
|
|
803
|
+
log("[CtaBubbleContainer] Clearing delay timer");
|
|
804
|
+
clearTimeout(delayTimer);
|
|
805
|
+
}
|
|
738
806
|
};
|
|
739
|
-
}, [startTime, timeout, delay]);
|
|
807
|
+
}, [startTime, timeout, delay, visible]);
|
|
740
808
|
var handleDismiss = function () {
|
|
809
|
+
log("[CtaBubbleContainer] handleDismiss called, setting showBubble=false");
|
|
741
810
|
setShowBubble(false);
|
|
742
811
|
if (onDismiss) {
|
|
812
|
+
log("[CtaBubbleContainer] Calling onDismiss callback");
|
|
743
813
|
onDismiss();
|
|
744
814
|
}
|
|
745
815
|
};
|
|
816
|
+
// Final render decision
|
|
817
|
+
var shouldRender = visible && showBubble;
|
|
818
|
+
log("[CtaBubbleContainer] Render decision: visible=".concat(visible, ", showBubble=").concat(showBubble, ", shouldRender=").concat(shouldRender));
|
|
746
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))));
|
|
747
820
|
};
|
|
748
821
|
|
|
749
822
|
var ChatButton = function (_a) {
|
|
750
823
|
var _b;
|
|
751
|
-
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;
|
|
752
825
|
var _c = React$1.useState(defaultWidgetButtonWidth), buttonWidth = _c[0], setButtonWidth = _c[1];
|
|
753
826
|
var _d = React$1.useState(false), animate = _d[0], setAnimate = _d[1];
|
|
754
827
|
var mobileWidth = ((_b = config === null || config === void 0 ? void 0 : config.mobile) === null || _b === void 0 ? void 0 : _b.applyAtLessThanWidth) || defaultNonMobileScreenWidth;
|
|
@@ -767,6 +840,11 @@ var ChatButton = function (_a) {
|
|
|
767
840
|
var _a;
|
|
768
841
|
var delayTimer;
|
|
769
842
|
var timeoutTimer;
|
|
843
|
+
// Don't animate if user has already interacted
|
|
844
|
+
if (hasInteracted) {
|
|
845
|
+
setAnimate(false);
|
|
846
|
+
return function () { }; // Return empty cleanup function
|
|
847
|
+
}
|
|
770
848
|
// Use animationDelay if provided, otherwise fall back to delay for backwards compatibility
|
|
771
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;
|
|
772
850
|
if (animationDelayToUse) {
|
|
@@ -799,8 +877,8 @@ var ChatButton = function (_a) {
|
|
|
799
877
|
if (timeoutTimer)
|
|
800
878
|
clearTimeout(timeoutTimer);
|
|
801
879
|
};
|
|
802
|
-
}, [configToApply, setAnimate]);
|
|
803
|
-
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";
|
|
804
882
|
React$1.useEffect(function () {
|
|
805
883
|
var handleResize = function () {
|
|
806
884
|
var screenWidth = window.innerWidth;
|
|
@@ -832,8 +910,8 @@ var ChatButton = function (_a) {
|
|
|
832
910
|
// Fallback to default SVG
|
|
833
911
|
React$1.createElement("svg", { width: svgSize, height: svgSize, viewBox: "0 0 22 22" },
|
|
834
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" })))),
|
|
835
|
-
configToApply && configToApply.message && (React$1.createElement("div", { className: "xapp-chat-button__cta" },
|
|
836
|
-
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
|
|
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)))));
|
|
837
915
|
};
|
|
838
916
|
|
|
839
917
|
var ChatCard = function (props) {
|
|
@@ -2813,6 +2891,7 @@ var StentorRouterChat = /** @class */ (function () {
|
|
|
2813
2891
|
this._sessionId = "";
|
|
2814
2892
|
this.accessToken = "";
|
|
2815
2893
|
this.attributes = {};
|
|
2894
|
+
this.routerAttributes = {};
|
|
2816
2895
|
this.isAdmin = false;
|
|
2817
2896
|
this.urlAttributes = {};
|
|
2818
2897
|
this.handlers = {};
|
|
@@ -2881,13 +2960,19 @@ var StentorRouterChat = /** @class */ (function () {
|
|
|
2881
2960
|
this.handlers["new message"] = function (data, sender, ts) {
|
|
2882
2961
|
// Because the router's internal message format is Stentor channel compatible.
|
|
2883
2962
|
// So the data is either a stentor Request (from widget) or a stentor Response (from bot)
|
|
2884
|
-
var _a;
|
|
2963
|
+
var _a, _b;
|
|
2885
2964
|
var message;
|
|
2886
2965
|
if (sender.deviceId === "Bot") {
|
|
2887
|
-
|
|
2888
|
-
|
|
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)));
|
|
2971
|
+
}
|
|
2972
|
+
if (typeof ((_b = _this.options.hooks) === null || _b === void 0 ? void 0 : _b.onResponse) === "function") {
|
|
2973
|
+
_this.options.hooks.onResponse(response);
|
|
2889
2974
|
}
|
|
2890
|
-
message = responseToMessage(
|
|
2975
|
+
message = responseToMessage(response);
|
|
2891
2976
|
}
|
|
2892
2977
|
else if (sender.deviceId === "Widget") {
|
|
2893
2978
|
message = requestToMessage(data);
|
|
@@ -3320,7 +3405,7 @@ var StentorRouterChat = /** @class */ (function () {
|
|
|
3320
3405
|
};
|
|
3321
3406
|
StentorRouterChat.prototype.postMessage = function (message) {
|
|
3322
3407
|
return __awaiter$1(this, void 0, void 0, function () {
|
|
3323
|
-
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;
|
|
3324
3409
|
return __generator$1(this, function (_a) {
|
|
3325
3410
|
userId = this._userId;
|
|
3326
3411
|
sessionId = this._sessionId;
|
|
@@ -3350,7 +3435,8 @@ var StentorRouterChat = /** @class */ (function () {
|
|
|
3350
3435
|
if (origin) {
|
|
3351
3436
|
attributes["origin"] = origin;
|
|
3352
3437
|
}
|
|
3353
|
-
|
|
3438
|
+
mergedAttributes = __assign(__assign({}, attributes), this.routerAttributes);
|
|
3439
|
+
request = requestFromMessage(message, userId, this.isNewSession, sessionId, accessToken, mergedAttributes, this.visitorInfo);
|
|
3354
3440
|
this.emit("new message", request);
|
|
3355
3441
|
return [2 /*return*/];
|
|
3356
3442
|
});
|
|
@@ -7642,22 +7728,21 @@ var StentorServerChat = /** @class */ (function () {
|
|
|
7642
7728
|
return StentorServerChat;
|
|
7643
7729
|
}());
|
|
7644
7730
|
|
|
7645
|
-
// import { useWhatChanged } from '@simbathesailor/use-what-changed';
|
|
7646
7731
|
function createChatServerCore(config, options) {
|
|
7647
7732
|
switch (config.type) {
|
|
7648
7733
|
case "direct":
|
|
7649
7734
|
return new StentorDirectChat({
|
|
7650
7735
|
url: config.serverUrl,
|
|
7651
7736
|
key: config.accountKey,
|
|
7652
|
-
timeout: config.timeout
|
|
7737
|
+
timeout: config.timeout,
|
|
7653
7738
|
}, options);
|
|
7654
7739
|
case "websocket":
|
|
7655
7740
|
return new StentorServerChat({
|
|
7656
|
-
url: config.serverUrl
|
|
7741
|
+
url: config.serverUrl,
|
|
7657
7742
|
}, options);
|
|
7658
7743
|
case "websocketraw":
|
|
7659
7744
|
return new StentorRouterChat({
|
|
7660
|
-
url: config.serverUrl
|
|
7745
|
+
url: config.serverUrl,
|
|
7661
7746
|
}, options);
|
|
7662
7747
|
case "local":
|
|
7663
7748
|
return new StentorLocalChat();
|
|
@@ -7676,6 +7761,11 @@ function useChatServer(config, options) {
|
|
|
7676
7761
|
// Log what caused the "effect"
|
|
7677
7762
|
// useWhatChanged(deps, "options, config, dispatch");
|
|
7678
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
|
+
}
|
|
7679
7769
|
var newServer = createChatServer(config, options);
|
|
7680
7770
|
newServer.init(dispatch);
|
|
7681
7771
|
setServer(newServer);
|
|
@@ -8960,13 +9050,25 @@ var SendIcon = function () {
|
|
|
8960
9050
|
};
|
|
8961
9051
|
|
|
8962
9052
|
var SendButton = function (props) {
|
|
8963
|
-
|
|
8964
|
-
|
|
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" })))));
|
|
8965
9067
|
};
|
|
8966
9068
|
|
|
8967
9069
|
var Input = function (props) {
|
|
8968
9070
|
var _a, _b;
|
|
8969
|
-
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;
|
|
8970
9072
|
var _c = React$1.useState(false), dragover = _c[0], setDragover = _c[1];
|
|
8971
9073
|
function onDragOver(event) {
|
|
8972
9074
|
setDragover(true);
|
|
@@ -9022,7 +9124,7 @@ var Input = function (props) {
|
|
|
9022
9124
|
value: value, spellCheck: true }),
|
|
9023
9125
|
React$1.createElement("div", { className: "xappw-input-form__buttons" },
|
|
9024
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 })),
|
|
9025
|
-
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 })))));
|
|
9026
9128
|
};
|
|
9027
9129
|
|
|
9028
9130
|
function createActions(onItemUse) {
|
|
@@ -9084,7 +9186,7 @@ var Suggestions = function (props) {
|
|
|
9084
9186
|
|
|
9085
9187
|
var ChatFooter = function (props) {
|
|
9086
9188
|
var _a, _b, _c;
|
|
9087
|
-
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;
|
|
9088
9190
|
var innerDispatch = useChatDispatch();
|
|
9089
9191
|
var _d = React$1.useState(false), drawerOpen = _d[0], setDrawerState = _d[1]; // false initially
|
|
9090
9192
|
var _e = React$1.useState(), suggestionSearch = _e[0], setSuggestionSearch = _e[1];
|
|
@@ -9150,7 +9252,7 @@ var ChatFooter = function (props) {
|
|
|
9150
9252
|
React$1.createElement(Suggestions, { className: "xappw-chat-footer__suggestions", data: suggestions.suggestions, index: suggestions.index, searchTerms: suggestionSearch, onItemClick: handleItemClick, onItemUse: handleItemUse }),
|
|
9151
9253
|
isAdmin && isChatting && visible && React$1.createElement(AdminBar, { onAdminJoin: handleAdminJoin }),
|
|
9152
9254
|
React$1.createElement("div", { style: { pointerEvents: enableInput ? "auto" : "none", opacity: enableInput ? 1 : 0.5 } },
|
|
9153
|
-
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,
|
|
9154
9256
|
// onFocus={this.inputOnFocus}
|
|
9155
9257
|
onFileUpload: props.onFileUpload })),
|
|
9156
9258
|
brandingEnabled && brandingText && React$1.createElement(ChatBranding, { text: brandingText })));
|
|
@@ -31378,6 +31480,9 @@ function getButtonStyle(style) {
|
|
|
31378
31480
|
_a.sent();
|
|
31379
31481
|
return [4 /*yield*/, ["button-hover-bg", style === null || style === void 0 ? void 0 : style.hoverBackground]];
|
|
31380
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:
|
|
31381
31486
|
_a.sent();
|
|
31382
31487
|
return [2 /*return*/];
|
|
31383
31488
|
}
|
|
@@ -31434,6 +31539,270 @@ function getCtaStyle(style) {
|
|
|
31434
31539
|
return union(getBackgroundStyle(style.background), getTextStyle(style.text));
|
|
31435
31540
|
}
|
|
31436
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 (_a) {
|
|
31569
|
+
var enableErrorOverlay = _a.enableErrorOverlay;
|
|
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
|
+
// 1. Check localStorage (highest priority)
|
|
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
|
+
// 2. Check widget configuration
|
|
31593
|
+
if (enableErrorOverlay !== undefined) {
|
|
31594
|
+
console.log("[ErrorOverlay] Using config setting:", enableErrorOverlay);
|
|
31595
|
+
return enableErrorOverlay;
|
|
31596
|
+
}
|
|
31597
|
+
// 3. Check for React Native dev mode
|
|
31598
|
+
if (typeof globalThis.__DEV__ !== "undefined" && globalThis.__DEV__) {
|
|
31599
|
+
console.log("[ErrorOverlay] Enabled via __DEV__");
|
|
31600
|
+
return true;
|
|
31601
|
+
}
|
|
31602
|
+
// 4. Default: disabled
|
|
31603
|
+
return false;
|
|
31604
|
+
};
|
|
31605
|
+
var enabled = checkEnabled();
|
|
31606
|
+
setIsEnabled(enabled);
|
|
31607
|
+
// Load position preference
|
|
31608
|
+
var savedPosition = (_a = window.localStorage) === null || _a === void 0 ? void 0 : _a.getItem("xaErrorOverlayPosition");
|
|
31609
|
+
if (savedPosition === "top" || savedPosition === "bottom") {
|
|
31610
|
+
setPosition(savedPosition);
|
|
31611
|
+
}
|
|
31612
|
+
console.log("[ErrorOverlay] Component mounted, enabled:", enabled, "position:", savedPosition || "bottom");
|
|
31613
|
+
}, [enableErrorOverlay]);
|
|
31614
|
+
// Define addError with useCallback to prevent stale closures
|
|
31615
|
+
var addError = React$1.useCallback(function (error) {
|
|
31616
|
+
console.log("[ErrorOverlay] Adding error:", error);
|
|
31617
|
+
setErrors(function (prev) {
|
|
31618
|
+
var timestamp = new Date().toISOString();
|
|
31619
|
+
// Check if this is a duplicate of the last error
|
|
31620
|
+
var lastError = prev[prev.length - 1];
|
|
31621
|
+
if (lastError && lastError.message === error.message) {
|
|
31622
|
+
// Update count of last error
|
|
31623
|
+
return __spreadArray$1(__spreadArray$1([], prev.slice(0, -1), true), [
|
|
31624
|
+
__assign(__assign({}, lastError), { count: lastError.count + 1, timestamp: timestamp }),
|
|
31625
|
+
], false);
|
|
31626
|
+
}
|
|
31627
|
+
// Add new error
|
|
31628
|
+
var newError = __assign({ id: "".concat(timestamp, "-").concat(Math.random()), timestamp: timestamp, count: 1 }, error);
|
|
31629
|
+
// Keep only last 50 errors
|
|
31630
|
+
var updated = __spreadArray$1(__spreadArray$1([], prev, true), [newError], false);
|
|
31631
|
+
return updated.slice(-50);
|
|
31632
|
+
});
|
|
31633
|
+
}, []);
|
|
31634
|
+
React$1.useEffect(function () {
|
|
31635
|
+
if (!isEnabled) {
|
|
31636
|
+
console.log("[ErrorOverlay] Not enabled, skipping error interception");
|
|
31637
|
+
return undefined;
|
|
31638
|
+
}
|
|
31639
|
+
console.log("[ErrorOverlay] Setting up error interception");
|
|
31640
|
+
// Store original console methods
|
|
31641
|
+
var originalError = console.error;
|
|
31642
|
+
var originalWarn = console.warn;
|
|
31643
|
+
// Override console.error
|
|
31644
|
+
console.error = function () {
|
|
31645
|
+
var args = [];
|
|
31646
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
31647
|
+
args[_i] = arguments[_i];
|
|
31648
|
+
}
|
|
31649
|
+
var message = args.map(function (arg) { return safeStringify(arg); }).join(" ");
|
|
31650
|
+
var error = new Error();
|
|
31651
|
+
addError({
|
|
31652
|
+
message: message,
|
|
31653
|
+
type: "error",
|
|
31654
|
+
stack: error.stack,
|
|
31655
|
+
});
|
|
31656
|
+
// Call original method
|
|
31657
|
+
originalError.apply(console, args);
|
|
31658
|
+
};
|
|
31659
|
+
// Override console.warn
|
|
31660
|
+
console.warn = function () {
|
|
31661
|
+
var args = [];
|
|
31662
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
31663
|
+
args[_i] = arguments[_i];
|
|
31664
|
+
}
|
|
31665
|
+
var message = args.map(function (arg) { return safeStringify(arg); }).join(" ");
|
|
31666
|
+
addError({
|
|
31667
|
+
message: message,
|
|
31668
|
+
type: "warning",
|
|
31669
|
+
});
|
|
31670
|
+
// Call original method
|
|
31671
|
+
originalWarn.apply(console, args);
|
|
31672
|
+
};
|
|
31673
|
+
// Capture unhandled errors
|
|
31674
|
+
var handleError = function (event) {
|
|
31675
|
+
var _a;
|
|
31676
|
+
addError({
|
|
31677
|
+
message: event.message,
|
|
31678
|
+
type: "error",
|
|
31679
|
+
stack: (_a = event.error) === null || _a === void 0 ? void 0 : _a.stack,
|
|
31680
|
+
});
|
|
31681
|
+
};
|
|
31682
|
+
// Capture unhandled promise rejections
|
|
31683
|
+
var handleRejection = function (event) {
|
|
31684
|
+
var _a;
|
|
31685
|
+
addError({
|
|
31686
|
+
message: "Unhandled Promise Rejection: ".concat(event.reason),
|
|
31687
|
+
type: "error",
|
|
31688
|
+
stack: (_a = event.reason) === null || _a === void 0 ? void 0 : _a.stack,
|
|
31689
|
+
});
|
|
31690
|
+
};
|
|
31691
|
+
window.addEventListener("error", handleError);
|
|
31692
|
+
window.addEventListener("unhandledrejection", handleRejection);
|
|
31693
|
+
// Cleanup
|
|
31694
|
+
return function () {
|
|
31695
|
+
console.log("[ErrorOverlay] Cleaning up error interception");
|
|
31696
|
+
console.error = originalError;
|
|
31697
|
+
console.warn = originalWarn;
|
|
31698
|
+
window.removeEventListener("error", handleError);
|
|
31699
|
+
window.removeEventListener("unhandledrejection", handleRejection);
|
|
31700
|
+
};
|
|
31701
|
+
}, [isEnabled, addError]);
|
|
31702
|
+
var clearErrors = function () {
|
|
31703
|
+
setErrors([]);
|
|
31704
|
+
};
|
|
31705
|
+
var copyToClipboard = function () { return __awaiter$1(void 0, void 0, void 0, function () {
|
|
31706
|
+
var errorText, err_1, textarea;
|
|
31707
|
+
return __generator$1(this, function (_a) {
|
|
31708
|
+
switch (_a.label) {
|
|
31709
|
+
case 0:
|
|
31710
|
+
errorText = errors
|
|
31711
|
+
.map(function (e) {
|
|
31712
|
+
return "[".concat(e.timestamp, "] ").concat(e.type.toUpperCase(), ": ").concat(e.message).concat(e.stack ? "\n" + e.stack : "");
|
|
31713
|
+
})
|
|
31714
|
+
.join("\n\n");
|
|
31715
|
+
_a.label = 1;
|
|
31716
|
+
case 1:
|
|
31717
|
+
_a.trys.push([1, 3, , 4]);
|
|
31718
|
+
return [4 /*yield*/, navigator.clipboard.writeText(errorText)];
|
|
31719
|
+
case 2:
|
|
31720
|
+
_a.sent();
|
|
31721
|
+
console.log("[ErrorOverlay] Errors copied to clipboard");
|
|
31722
|
+
return [3 /*break*/, 4];
|
|
31723
|
+
case 3:
|
|
31724
|
+
err_1 = _a.sent();
|
|
31725
|
+
console.error("[ErrorOverlay] Failed to copy to clipboard:", err_1);
|
|
31726
|
+
textarea = document.createElement("textarea");
|
|
31727
|
+
textarea.value = errorText;
|
|
31728
|
+
textarea.style.position = "fixed";
|
|
31729
|
+
textarea.style.opacity = "0";
|
|
31730
|
+
document.body.appendChild(textarea);
|
|
31731
|
+
textarea.select();
|
|
31732
|
+
try {
|
|
31733
|
+
document.execCommand("copy");
|
|
31734
|
+
console.log("[ErrorOverlay] Errors copied to clipboard using fallback method");
|
|
31735
|
+
}
|
|
31736
|
+
catch (fallbackErr) {
|
|
31737
|
+
console.error("[ErrorOverlay] Fallback copy method also failed:", fallbackErr);
|
|
31738
|
+
}
|
|
31739
|
+
document.body.removeChild(textarea);
|
|
31740
|
+
return [3 /*break*/, 4];
|
|
31741
|
+
case 4: return [2 /*return*/];
|
|
31742
|
+
}
|
|
31743
|
+
});
|
|
31744
|
+
}); };
|
|
31745
|
+
// Toggle enabled state
|
|
31746
|
+
var toggleEnabled = function () {
|
|
31747
|
+
var newState = !isEnabled;
|
|
31748
|
+
setIsEnabled(newState);
|
|
31749
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
31750
|
+
window.localStorage.setItem("xaErrorOverlay", newState ? "enabled" : "disabled");
|
|
31751
|
+
}
|
|
31752
|
+
console.log("[ErrorOverlay] Toggled enabled state to:", newState);
|
|
31753
|
+
// Clear errors when disabling
|
|
31754
|
+
if (!newState) {
|
|
31755
|
+
setErrors([]);
|
|
31756
|
+
}
|
|
31757
|
+
};
|
|
31758
|
+
// Toggle position between top and bottom
|
|
31759
|
+
var togglePosition = function () {
|
|
31760
|
+
var newPosition = position === "bottom" ? "top" : "bottom";
|
|
31761
|
+
setPosition(newPosition);
|
|
31762
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
31763
|
+
window.localStorage.setItem("xaErrorOverlayPosition", newPosition);
|
|
31764
|
+
}
|
|
31765
|
+
};
|
|
31766
|
+
// Don't render anything if not enabled
|
|
31767
|
+
if (!isEnabled) {
|
|
31768
|
+
return null;
|
|
31769
|
+
}
|
|
31770
|
+
// If enabled but not visible (user closed it), don't render
|
|
31771
|
+
if (!isVisible) {
|
|
31772
|
+
return null;
|
|
31773
|
+
}
|
|
31774
|
+
// If enabled and visible but no errors yet, don't show the overlay
|
|
31775
|
+
// Only show when there are actual errors to display
|
|
31776
|
+
if (errors.length === 0) {
|
|
31777
|
+
return null;
|
|
31778
|
+
}
|
|
31779
|
+
return (React$1.createElement("div", { className: "error-overlay error-overlay--".concat(position, " ").concat(isMinimized ? "minimized" : "") },
|
|
31780
|
+
React$1.createElement("div", { className: "error-overlay-header" },
|
|
31781
|
+
React$1.createElement("span", { className: "error-overlay-title" },
|
|
31782
|
+
"Debug Console (",
|
|
31783
|
+
errors.length,
|
|
31784
|
+
")"),
|
|
31785
|
+
React$1.createElement("div", { className: "error-overlay-actions" },
|
|
31786
|
+
React$1.createElement("button", { onClick: copyToClipboard, title: "Copy all to clipboard" }, "\uD83D\uDCCB"),
|
|
31787
|
+
React$1.createElement("button", { onClick: clearErrors, title: "Clear all" }, "\uD83D\uDDD1\uFE0F"),
|
|
31788
|
+
React$1.createElement("button", { onClick: togglePosition, title: "Move to ".concat(position === "bottom" ? "top" : "bottom") }, position === "bottom" ? "⬆️" : "⬇️"),
|
|
31789
|
+
React$1.createElement("button", { onClick: toggleEnabled, title: "Disable Error Overlay" }, "\uD83D\uDD27"),
|
|
31790
|
+
React$1.createElement("button", { onClick: function () { return setIsMinimized(!isMinimized); }, title: "Minimize/Maximize" }, isMinimized ? "▲" : "▼"),
|
|
31791
|
+
React$1.createElement("button", { onClick: function () { return setIsVisible(false); }, title: "Close" }, "\u2715"))),
|
|
31792
|
+
!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) },
|
|
31793
|
+
React$1.createElement("div", { className: "error-header" },
|
|
31794
|
+
React$1.createElement("span", { className: "error-time" }, new Date(error.timestamp).toLocaleTimeString()),
|
|
31795
|
+
error.count > 1 && (React$1.createElement("span", { className: "error-count" },
|
|
31796
|
+
"(",
|
|
31797
|
+
error.count,
|
|
31798
|
+
"x)")),
|
|
31799
|
+
React$1.createElement("span", { className: "error-badge error-badge-".concat(error.type) }, error.type)),
|
|
31800
|
+
React$1.createElement("div", { className: "error-message" }, error.message),
|
|
31801
|
+
error.stack && (React$1.createElement("details", { className: "error-stack" },
|
|
31802
|
+
React$1.createElement("summary", null, "Stack trace"),
|
|
31803
|
+
React$1.createElement("pre", null, error.stack))))); })))));
|
|
31804
|
+
};
|
|
31805
|
+
|
|
31437
31806
|
var ModalContent = function (_a) {
|
|
31438
31807
|
var onClose = _a.onClose, onReset = _a.onReset;
|
|
31439
31808
|
return (React$1.createElement("div", { className: "modalContent" },
|
|
@@ -31446,7 +31815,44 @@ var ModalContent = function (_a) {
|
|
|
31446
31815
|
};
|
|
31447
31816
|
|
|
31448
31817
|
var ChatWidgetWrapper = function (props) {
|
|
31449
|
-
var
|
|
31818
|
+
var _a;
|
|
31819
|
+
var _b = React$1.useState(props.config), rawConfig = _b[0], setRawConfig = _b[1];
|
|
31820
|
+
var _c = React$1.useState(!!props.getConfig), configLoading = _c[0], setConfigLoading = _c[1];
|
|
31821
|
+
var _d = React$1.useState(), configError = _d[0], setConfigError = _d[1];
|
|
31822
|
+
// Load config from callback if provided
|
|
31823
|
+
React$1.useEffect(function () {
|
|
31824
|
+
var cancelled = false;
|
|
31825
|
+
if (props.getConfig) {
|
|
31826
|
+
setConfigLoading(true);
|
|
31827
|
+
setConfigError(undefined);
|
|
31828
|
+
props
|
|
31829
|
+
.getConfig()
|
|
31830
|
+
.then(function (config) {
|
|
31831
|
+
if (!cancelled) {
|
|
31832
|
+
setRawConfig(config);
|
|
31833
|
+
setConfigLoading(false);
|
|
31834
|
+
log("[ChatWidget] Config loaded from getConfig callback");
|
|
31835
|
+
}
|
|
31836
|
+
})
|
|
31837
|
+
.catch(function (error) {
|
|
31838
|
+
if (!cancelled) {
|
|
31839
|
+
setConfigError(error);
|
|
31840
|
+
setConfigLoading(false);
|
|
31841
|
+
err("[ChatWidget] Failed to load config: ".concat(error.message));
|
|
31842
|
+
}
|
|
31843
|
+
});
|
|
31844
|
+
}
|
|
31845
|
+
else if (props.config) {
|
|
31846
|
+
// If no callback, use the config prop directly
|
|
31847
|
+
setRawConfig(props.config);
|
|
31848
|
+
setConfigLoading(false);
|
|
31849
|
+
}
|
|
31850
|
+
return function () {
|
|
31851
|
+
cancelled = true;
|
|
31852
|
+
};
|
|
31853
|
+
// Only depend on getConfig and config - not the entire props object to avoid infinite loops
|
|
31854
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
31855
|
+
}, [props.getConfig, props.config]);
|
|
31450
31856
|
var connection = useConnectionInfo(rawConfig);
|
|
31451
31857
|
var config = React$1.useMemo(function () {
|
|
31452
31858
|
var _a;
|
|
@@ -31455,7 +31861,7 @@ var ChatWidgetWrapper = function (props) {
|
|
|
31455
31861
|
var token = reactRedux.useSelector(function (state) { return state.connection.token; });
|
|
31456
31862
|
var options = React$1.useMemo(function () {
|
|
31457
31863
|
var configurableMessages = getConfigurableMessages();
|
|
31458
|
-
if (rawConfig.configurableMessages &&
|
|
31864
|
+
if ((rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.configurableMessages) &&
|
|
31459
31865
|
Array.isArray(rawConfig.configurableMessages.items) &&
|
|
31460
31866
|
rawConfig.configurableMessages.items.length > 0) {
|
|
31461
31867
|
configurableMessages = rawConfig.configurableMessages;
|
|
@@ -31464,20 +31870,37 @@ var ChatWidgetWrapper = function (props) {
|
|
|
31464
31870
|
token: token,
|
|
31465
31871
|
bot: {
|
|
31466
31872
|
nick: "Bot",
|
|
31467
|
-
displayName: rawConfig.botName,
|
|
31468
|
-
avatarPath: rawConfig.avatarUrl
|
|
31873
|
+
displayName: rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.botName,
|
|
31874
|
+
avatarPath: rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.avatarUrl,
|
|
31469
31875
|
},
|
|
31470
31876
|
configurableMessages: configurableMessages,
|
|
31471
|
-
hooks: rawConfig.hooks
|
|
31877
|
+
hooks: rawConfig === null || rawConfig === void 0 ? void 0 : rawConfig.hooks,
|
|
31472
31878
|
};
|
|
31473
31879
|
}, [token, rawConfig]);
|
|
31474
|
-
|
|
31880
|
+
// Only create chat server when config is ready (not loading and no error)
|
|
31881
|
+
var chatServer = useChatServer(configLoading || configError ? null : connection, configLoading || configError ? null : options);
|
|
31882
|
+
// Determine mode class for loading/error states
|
|
31883
|
+
var mode = (_a = props.mode) !== null && _a !== void 0 ? _a : "normal";
|
|
31884
|
+
var modeClass = "widget-container--".concat(mode);
|
|
31885
|
+
// Show loading state while config is being fetched
|
|
31886
|
+
if (configLoading) {
|
|
31887
|
+
return (React$1.createElement("div", { className: "widget-container widget-container--loading ".concat(modeClass) },
|
|
31888
|
+
React$1.createElement("div", { className: "xa-spinner-container visible" },
|
|
31889
|
+
React$1.createElement("div", { className: "xa-spinner" }))));
|
|
31890
|
+
}
|
|
31891
|
+
// Show error state if config failed to load
|
|
31892
|
+
if (configError) {
|
|
31893
|
+
return (React$1.createElement("div", { className: "widget-container widget-container--error ".concat(modeClass) },
|
|
31894
|
+
React$1.createElement("div", { className: "widget-error-message" },
|
|
31895
|
+
"Failed to load chat configuration: ",
|
|
31896
|
+
configError.message)));
|
|
31897
|
+
}
|
|
31475
31898
|
return (React$1.createElement(ChatConfigContext.Provider, { value: config },
|
|
31476
31899
|
React$1.createElement(ChatServerContext.Provider, { value: chatServer },
|
|
31477
|
-
React$1.createElement(ChatWidget, __assign({}, props)))));
|
|
31900
|
+
React$1.createElement(ChatWidget, __assign({}, props, { config: rawConfig })))));
|
|
31478
31901
|
};
|
|
31479
31902
|
var ChatWidget = function (props) {
|
|
31480
|
-
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;
|
|
31903
|
+
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;
|
|
31481
31904
|
var innerDispatch = useChatDispatch();
|
|
31482
31905
|
var dispatch = useChatServerDispatch();
|
|
31483
31906
|
// From Redux
|
|
@@ -31491,7 +31914,7 @@ var ChatWidget = function (props) {
|
|
|
31491
31914
|
var canRefresh = (_c = (_b = props.config.header) === null || _b === void 0 ? void 0 : _b.actions) === null || _c === void 0 ? void 0 : _c.refresh;
|
|
31492
31915
|
// can't minimize in docked mode or static mode.
|
|
31493
31916
|
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);
|
|
31494
|
-
log("docked: ".concat(dockedMode, " static: ").concat(staticMode, "
|
|
31917
|
+
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));
|
|
31495
31918
|
var canCancel;
|
|
31496
31919
|
// To preserve legacy behavior, cancel needs a little more checks
|
|
31497
31920
|
if (typeof ((_j = (_h = props.config.header) === null || _h === void 0 ? void 0 : _h.actions) === null || _j === void 0 ? void 0 : _j.cancel) === "boolean") {
|
|
@@ -31500,17 +31923,17 @@ var ChatWidget = function (props) {
|
|
|
31500
31923
|
else {
|
|
31501
31924
|
canCancel = !dockedMode && !staticMode;
|
|
31502
31925
|
}
|
|
31503
|
-
// For backward compatibility. Note: the action will create the actual "visuals" object" (this is a copy).
|
|
31926
|
+
// For backward compatibility. Note: the action will create the actual "visuals" object" (this is a copy).
|
|
31504
31927
|
if (!chatState.visuals) {
|
|
31505
31928
|
chatState.visuals = {};
|
|
31506
31929
|
}
|
|
31507
31930
|
// Our state - pull from storage
|
|
31508
|
-
var
|
|
31931
|
+
var _8 = React$1.useState((!canMinimize && !canCancel) ||
|
|
31509
31932
|
// !!get("visible") ||
|
|
31510
31933
|
chatState.visuals.visible ||
|
|
31511
31934
|
(((_m = props.config) === null || _m === void 0 ? void 0 : _m.autoOpenOnWidth) &&
|
|
31512
|
-
window.matchMedia("(min-width: ".concat((_o = props.config) === null || _o === void 0 ? void 0 : _o.autoOpenOnWidth, ")")).matches)), visible =
|
|
31513
|
-
var
|
|
31935
|
+
window.matchMedia("(min-width: ".concat((_o = props.config) === null || _o === void 0 ? void 0 : _o.autoOpenOnWidth, ")")).matches)), visible = _8[0], setVisibleState = _8[1];
|
|
31936
|
+
var _9 = React$1.useState(false), typing = _9[0], setTypingState = _9[1]; // false initially
|
|
31514
31937
|
var chatServer = React$1.useContext(ChatServerContext);
|
|
31515
31938
|
var patternsConfig = (_q = (_p = props.config) === null || _p === void 0 ? void 0 : _p.autoOpenOnPattern) === null || _q === void 0 ? void 0 : _q.patterns;
|
|
31516
31939
|
var currentUrl = window.location.href;
|
|
@@ -31525,32 +31948,36 @@ var ChatWidget = function (props) {
|
|
|
31525
31948
|
}
|
|
31526
31949
|
setVisibleState(newVisible);
|
|
31527
31950
|
innerDispatch(setVisualStatus({
|
|
31528
|
-
visible: newVisible
|
|
31951
|
+
visible: newVisible,
|
|
31529
31952
|
}));
|
|
31530
31953
|
}, [innerDispatch, staticMode]);
|
|
31531
31954
|
React$1.useEffect(function () {
|
|
31532
31955
|
var _a, _b;
|
|
31533
|
-
|
|
31956
|
+
var handleKeyDown = function (event) {
|
|
31534
31957
|
var body = document.getElementsByTagName("body")[0];
|
|
31535
31958
|
body.tabIndex = -1;
|
|
31536
31959
|
if (event.key === "Escape") {
|
|
31537
31960
|
body.focus();
|
|
31538
31961
|
}
|
|
31539
|
-
}
|
|
31962
|
+
};
|
|
31963
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
31540
31964
|
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)) {
|
|
31541
31965
|
innerDispatch(setSessionId(undefined));
|
|
31542
31966
|
innerDispatch(reset());
|
|
31543
31967
|
}
|
|
31968
|
+
return function () {
|
|
31969
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
31970
|
+
};
|
|
31544
31971
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
31545
31972
|
}, []);
|
|
31546
|
-
var
|
|
31973
|
+
var _10 = React$1.useState(!document.hidden), isTabVisible = _10[0], setIsTabVisible = _10[1];
|
|
31547
31974
|
React$1.useEffect(function () {
|
|
31548
31975
|
var handleVisibilityChange = function () {
|
|
31549
31976
|
setIsTabVisible(!document.hidden);
|
|
31550
31977
|
};
|
|
31551
|
-
document.addEventListener(
|
|
31978
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
31552
31979
|
return function () {
|
|
31553
|
-
document.removeEventListener(
|
|
31980
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
31554
31981
|
};
|
|
31555
31982
|
}, []);
|
|
31556
31983
|
React$1.useEffect(function () {
|
|
@@ -31584,7 +32011,15 @@ var ChatWidget = function (props) {
|
|
|
31584
32011
|
if (currentWidth < +configWidth) {
|
|
31585
32012
|
setVisible(false);
|
|
31586
32013
|
}
|
|
31587
|
-
}, [
|
|
32014
|
+
}, [
|
|
32015
|
+
currentWidth,
|
|
32016
|
+
patternExist,
|
|
32017
|
+
patternMatches,
|
|
32018
|
+
configWidth,
|
|
32019
|
+
setVisible,
|
|
32020
|
+
chatState.visuals.opened,
|
|
32021
|
+
mode,
|
|
32022
|
+
]);
|
|
31588
32023
|
function handleOnChange() {
|
|
31589
32024
|
if (!typing) {
|
|
31590
32025
|
dispatch(sendTyping(true));
|
|
@@ -31656,28 +32091,37 @@ var ChatWidget = function (props) {
|
|
|
31656
32091
|
/** Called when minimize button is clicked */
|
|
31657
32092
|
function handleMinimizeClick() {
|
|
31658
32093
|
innerDispatch(setVisualStatus({
|
|
31659
|
-
opened: false
|
|
32094
|
+
opened: false,
|
|
32095
|
+
hasInteracted: true,
|
|
31660
32096
|
}));
|
|
31661
32097
|
setVisible(false);
|
|
31662
32098
|
}
|
|
31663
32099
|
/** Called when cancel is clicked */
|
|
31664
32100
|
function handleCancelClick() {
|
|
31665
|
-
//
|
|
32101
|
+
// First reset to clear all state
|
|
32102
|
+
innerDispatch(reset());
|
|
32103
|
+
// Then set hasInteracted to prevent CTA from showing after cancel
|
|
31666
32104
|
innerDispatch(setVisualStatus({
|
|
31667
|
-
opened: false
|
|
32105
|
+
opened: false,
|
|
32106
|
+
hasInteracted: true,
|
|
31668
32107
|
}));
|
|
31669
|
-
innerDispatch(reset());
|
|
31670
32108
|
setVisible(false);
|
|
31671
32109
|
}
|
|
31672
32110
|
function chatButtonOnClick() {
|
|
31673
32111
|
innerDispatch(setVisualStatus({
|
|
31674
|
-
opened: true
|
|
32112
|
+
opened: true,
|
|
32113
|
+
hasInteracted: true,
|
|
31675
32114
|
}));
|
|
31676
32115
|
setVisible(true);
|
|
31677
32116
|
setTimeout(function () {
|
|
31678
32117
|
document.getElementById("chatWidgetInput").focus();
|
|
31679
32118
|
}, 100);
|
|
31680
32119
|
}
|
|
32120
|
+
function handleCtaDismiss() {
|
|
32121
|
+
innerDispatch(setVisualStatus({
|
|
32122
|
+
hasInteracted: true,
|
|
32123
|
+
}));
|
|
32124
|
+
}
|
|
31681
32125
|
var isOffline = chatState.accountStatus === "offline" && !chatState.isChatting;
|
|
31682
32126
|
var messages = chatState && chatState.chats;
|
|
31683
32127
|
var config = props.config, onConnectionStatusChange = props.onConnectionStatusChange;
|
|
@@ -31690,8 +32134,12 @@ var ChatWidget = function (props) {
|
|
|
31690
32134
|
}, [connectionStatus, onConnectionStatusChange]);
|
|
31691
32135
|
useExternalScript((_t = props.config) === null || _t === void 0 ? void 0 : _t.middlewareUrl);
|
|
31692
32136
|
// This is a pseudo agent. It represent's the widget (shown in the header avatar for instance)
|
|
31693
|
-
var widgetAgent = ((_u = chatState.agents["agent:robot"]) === null || _u === void 0 ? void 0 : _u.user) ||
|
|
31694
|
-
||
|
|
32137
|
+
var widgetAgent = ((_u = chatState.agents["agent:robot"]) === null || _u === void 0 ? void 0 : _u.user) ||
|
|
32138
|
+
(config === null || config === void 0 ? void 0 : config.agent) || {
|
|
32139
|
+
nick: "agent:robot",
|
|
32140
|
+
avatarPath: config.avatarUrl,
|
|
32141
|
+
display_name: "Agent",
|
|
32142
|
+
};
|
|
31695
32143
|
return (React$1.createElement(React$1.Fragment, null,
|
|
31696
32144
|
React$1.createElement("div", { className: "widget-container ".concat(modeClass, " ").concat(getVisibilityClass()) },
|
|
31697
32145
|
React$1.createElement(WidgetStylesheet, { theme: config === null || config === void 0 ? void 0 : config.theme }),
|
|
@@ -31700,10 +32148,11 @@ var ChatWidget = function (props) {
|
|
|
31700
32148
|
React$1.createElement("div", { className: "xa-spinner-container ".concat(visible && connectionStatus === "pending" ? "visible" : "") },
|
|
31701
32149
|
React$1.createElement("div", { className: "xa-spinner" })),
|
|
31702
32150
|
connectionStatus === "offline" && React$1.createElement(ServerOffline, null),
|
|
31703
|
-
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: (
|
|
32151
|
+
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 }),
|
|
31704
32152
|
React$1.createElement("div", { className: "restartModal", ref: modalRef, onClick: handleRestartModalCloseClick },
|
|
31705
32153
|
React$1.createElement(ModalContent, { onClose: handleRestartModalCloseClick, onReset: handleReset }))),
|
|
31706
|
-
React$1.createElement(ChatButton, { addClass: getVisibilityClass(), onClick: chatButtonOnClick, config: config === null || config === void 0 ? void 0 : config.cta, imageUrl: (
|
|
32154
|
+
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 }),
|
|
32155
|
+
React$1.createElement(ErrorOverlay, { enableErrorOverlay: config === null || config === void 0 ? void 0 : config.enableErrorOverlay })));
|
|
31707
32156
|
};
|
|
31708
32157
|
|
|
31709
32158
|
// src/utils/formatProdErrorMessage.ts
|
|
@@ -32180,17 +32629,37 @@ var DEFAULT_VISITOR = {
|
|
|
32180
32629
|
nick: "visitor:",
|
|
32181
32630
|
typing: false
|
|
32182
32631
|
};
|
|
32183
|
-
function createDefaultState(state) {
|
|
32632
|
+
function createDefaultState(state, options) {
|
|
32633
|
+
var _a;
|
|
32184
32634
|
if (!state) {
|
|
32185
32635
|
state = {};
|
|
32186
32636
|
}
|
|
32187
32637
|
state.userId = state.userId ? state.userId : visitorFingerprint();
|
|
32188
32638
|
state.visitorId = state.userId;
|
|
32639
|
+
// Determine if debug mode should be enabled
|
|
32640
|
+
var debugMode = false;
|
|
32641
|
+
if (typeof window !== 'undefined') {
|
|
32642
|
+
var localStorageSetting = (_a = window.localStorage) === null || _a === void 0 ? void 0 : _a.getItem('xaErrorOverlay');
|
|
32643
|
+
if (localStorageSetting === 'enabled') {
|
|
32644
|
+
debugMode = true;
|
|
32645
|
+
}
|
|
32646
|
+
else if (localStorageSetting === 'disabled') {
|
|
32647
|
+
debugMode = false;
|
|
32648
|
+
}
|
|
32649
|
+
else if (options === null || options === void 0 ? void 0 : options.enableErrorOverlay) {
|
|
32650
|
+
// Use config option if no localStorage override
|
|
32651
|
+
debugMode = true;
|
|
32652
|
+
}
|
|
32653
|
+
else if (typeof globalThis.__DEV__ !== 'undefined' && globalThis.__DEV__) {
|
|
32654
|
+
// For React Native, default to true in development mode
|
|
32655
|
+
debugMode = true;
|
|
32656
|
+
}
|
|
32657
|
+
}
|
|
32189
32658
|
return __assign({ connection: {
|
|
32190
32659
|
connectionStatus: "offline",
|
|
32191
32660
|
token: null,
|
|
32192
32661
|
greetingRequested: false
|
|
32193
|
-
}, 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);
|
|
32662
|
+
}, 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);
|
|
32194
32663
|
}
|
|
32195
32664
|
var DEFAULT_STATE = createDefaultState();
|
|
32196
32665
|
|
|
@@ -32239,6 +32708,10 @@ var LocalStorage = /** @class */ (function () {
|
|
|
32239
32708
|
function persistStateReducer(storage, initialState, innerReducer) {
|
|
32240
32709
|
var _a;
|
|
32241
32710
|
var obj = (_a = storage.get()) !== null && _a !== void 0 ? _a : initialState;
|
|
32711
|
+
// Clean up hasInteracted flag on page load - don't persist across browser refreshes
|
|
32712
|
+
if (obj && obj.visuals) {
|
|
32713
|
+
obj = __assign(__assign({}, obj), { visuals: __assign(__assign({}, obj.visuals), { hasInteracted: undefined }) });
|
|
32714
|
+
}
|
|
32242
32715
|
return function (state, action) {
|
|
32243
32716
|
if (state === void 0) { state = obj; }
|
|
32244
32717
|
var res = innerReducer(state, action);
|
|
@@ -32297,13 +32770,14 @@ function memberLeave(state, detail) {
|
|
|
32297
32770
|
|
|
32298
32771
|
function resetReducer(state) {
|
|
32299
32772
|
if (state === void 0) { state = DEFAULT_STATE; }
|
|
32300
|
-
// pass through some of the items to persis
|
|
32301
32773
|
return __assign(__assign({}, createDefaultState({
|
|
32302
32774
|
accessToken: state.accessToken,
|
|
32303
32775
|
userId: state.userId,
|
|
32304
32776
|
attributes: state.attributes,
|
|
32305
32777
|
sessionExpiration: state.sessionExpiration
|
|
32306
|
-
})), { connection: __assign(__assign({}, state.connection), { greetingRequested: false, nonce: uuid_1() }), visitor: state.visitor, visitorId: state.visitorId
|
|
32778
|
+
})), { connection: __assign(__assign({}, state.connection), { greetingRequested: false, nonce: uuid_1() }), visitor: state.visitor, visitorId: state.visitorId,
|
|
32779
|
+
// Explicitly reset visuals to clear hasInteracted flag for widget refresh
|
|
32780
|
+
visuals: {} });
|
|
32307
32781
|
}
|
|
32308
32782
|
|
|
32309
32783
|
// todo: create reducer (requires redux-thunk dependency)
|
|
@@ -32336,7 +32810,14 @@ function update(state, action) {
|
|
|
32336
32810
|
case "session_id":
|
|
32337
32811
|
return __assign(__assign({}, state), { lastTimestamp: (_g = action.detail) === null || _g === void 0 ? void 0 : _g.timestamp, sessionId: action.detail.sessionId });
|
|
32338
32812
|
case "visual_status":
|
|
32339
|
-
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 })) });
|
|
32813
|
+
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 })) });
|
|
32814
|
+
case "toggle_debug_mode":
|
|
32815
|
+
var newDebugMode = !state.debugMode;
|
|
32816
|
+
// Update localStorage to persist the setting
|
|
32817
|
+
if (typeof window !== 'undefined' && window.localStorage) {
|
|
32818
|
+
window.localStorage.setItem('xaErrorOverlay', newDebugMode ? 'enabled' : 'disabled');
|
|
32819
|
+
}
|
|
32820
|
+
return __assign(__assign({}, state), { debugMode: newDebugMode });
|
|
32340
32821
|
case "department_update":
|
|
32341
32822
|
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)) });
|
|
32342
32823
|
case "visitor_update":
|
|
@@ -32487,6 +32968,8 @@ function createChatStore(config, dataStorage) {
|
|
|
32487
32968
|
userId: config.userId,
|
|
32488
32969
|
attributes: config.attributes,
|
|
32489
32970
|
sessionExpiration: config.sessionExpiration
|
|
32971
|
+
}, {
|
|
32972
|
+
enableErrorOverlay: config.enableErrorOverlay
|
|
32490
32973
|
});
|
|
32491
32974
|
var chatReducer = persistStateReducer(storage, defaultState, storeHandler);
|
|
32492
32975
|
// Configure store with @reduxjs/toolkit
|
|
@@ -32526,23 +33009,25 @@ function generateKey(connection, sessionId) {
|
|
|
32526
33009
|
}
|
|
32527
33010
|
|
|
32528
33011
|
var ChatWidgetContainer = function (props) {
|
|
32529
|
-
var _a, _b, _c, _d, _e;
|
|
33012
|
+
var _a, _b, _c, _d, _e, _f;
|
|
32530
33013
|
var messageMiddleware = useStandardMiddleware();
|
|
32531
33014
|
var connection = useServerConfig(props.config);
|
|
32532
33015
|
var chatStore = React$1.useMemo(function () {
|
|
32533
|
-
var _a, _b, _c, _d;
|
|
33016
|
+
var _a, _b, _c, _d, _e;
|
|
32534
33017
|
return createChatStore({
|
|
32535
33018
|
connection: connection,
|
|
32536
33019
|
userId: (_a = props.config) === null || _a === void 0 ? void 0 : _a.userId,
|
|
32537
33020
|
accessToken: (_b = props.config) === null || _b === void 0 ? void 0 : _b.accessToken,
|
|
32538
33021
|
attributes: (_c = props.config) === null || _c === void 0 ? void 0 : _c.attributes,
|
|
32539
|
-
sessionExpiration: (_d = props.config) === null || _d === void 0 ? void 0 : _d.sessionExpiration
|
|
33022
|
+
sessionExpiration: (_d = props.config) === null || _d === void 0 ? void 0 : _d.sessionExpiration,
|
|
33023
|
+
enableErrorOverlay: (_e = props.config) === null || _e === void 0 ? void 0 : _e.enableErrorOverlay
|
|
32540
33024
|
});
|
|
32541
|
-
}, [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]);
|
|
32542
|
-
if ((
|
|
33025
|
+
}, [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]);
|
|
33026
|
+
if ((_f = props.config) === null || _f === void 0 ? void 0 : _f.disabled) {
|
|
32543
33027
|
return React$1.createElement(React$1.Fragment, null);
|
|
32544
33028
|
}
|
|
32545
|
-
var widgetProps = __assign(__assign({}, props), { messageMiddleware: messageMiddleware
|
|
33029
|
+
var widgetProps = __assign(__assign({}, props), { messageMiddleware: messageMiddleware, getConfig: props.getConfig // Pass through getConfig callback
|
|
33030
|
+
});
|
|
32546
33031
|
return (React$1.createElement(reactRedux.Provider, { store: chatStore },
|
|
32547
33032
|
React$1.createElement(ChatWidgetWrapper, __assign({}, widgetProps))));
|
|
32548
33033
|
};
|