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