@xapp/chat-widget 1.60.3 → 1.61.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/index.js CHANGED
@@ -23,6 +23,9 @@ var ActionButton = function (props) {
23
23
  };
24
24
 
25
25
  var defaultServerUrl = "";
26
+ var defaultWidgetButtonWidth = "48";
27
+ var defaultMobileWidgetButtonWidth = "30";
28
+ var defaultNonMobileScreenWidth = "400";
26
29
  var ChatConfigContext = React$1.createContext(null);
27
30
  function useWidgetEnv() {
28
31
  var ctx = React$1.useContext(ChatConfigContext);
@@ -672,50 +675,108 @@ var CtaBubble = function (props) {
672
675
  };
673
676
 
674
677
  var CtaBubbleContainer = function (props) {
678
+ var visible = props.visible, timeout = props.timeout, delay = props.delay, onClick = props.onClick;
675
679
  var startTime = React$1.useMemo(function () {
676
- if (props.visible) {
680
+ if (visible) {
677
681
  return new Date().valueOf();
678
682
  }
679
683
  return undefined;
680
- }, [props.visible]);
681
- var _a = React$1.useState(new Date().valueOf()), currentTime = _a[0], setCurrentTime = _a[1];
682
- var timeout = props.timeout;
683
- var duration = currentTime - startTime;
684
- var pastDue = startTime && props.timeout && (duration >= props.timeout);
684
+ }, [visible]);
685
+ var _a = React$1.useState(false), showBubble = _a[0], setShowBubble = _a[1];
685
686
  React$1.useEffect(function () {
686
- if (!startTime) {
687
- return undefined;
688
- }
689
- var end = startTime + timeout;
690
- var now = new Date().valueOf();
691
- var left = end - now;
692
- if (left <= 0) {
693
- return undefined;
687
+ var isMounted = true;
688
+ if (startTime) {
689
+ var delayTimer_1 = setTimeout(function () {
690
+ if (isMounted) {
691
+ setShowBubble(true);
692
+ }
693
+ var hideTimer = setTimeout(function () {
694
+ if (isMounted) {
695
+ setShowBubble(false);
696
+ }
697
+ }, timeout);
698
+ return function () {
699
+ clearTimeout(hideTimer);
700
+ };
701
+ }, delay);
702
+ return function () {
703
+ isMounted = false;
704
+ clearTimeout(delayTimer_1);
705
+ };
694
706
  }
695
- var handle = setTimeout(function () {
696
- setCurrentTime(new Date().valueOf());
697
- }, left);
698
707
  return function () {
699
- clearTimeout(handle);
708
+ isMounted = false;
700
709
  };
701
- }, [startTime, timeout]);
702
- return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null, props.visible && !pastDue && React__default$1["default"].createElement(CtaBubble, { onClick: props.onClick }, props.children)));
710
+ }, [startTime, timeout, delay]);
711
+ return (React__default$1["default"].createElement(React__default$1["default"].Fragment, null, visible && showBubble && React__default$1["default"].createElement(CtaBubble, { onClick: onClick }, props.children)));
703
712
  };
704
713
 
705
- var ChatButton = function (props) {
706
- return (React__default$1["default"].createElement("button", { "aria-label": "open chat", className: "xapp-chat-button ".concat(props.addClass || "").trim(), onClick: props.onClick },
707
- React__default$1["default"].createElement("div", { id: "xapp-widget-button", className: "xapp-chat-button__btn", style: props.borderStyle && {
708
- border: 'solid',
709
- borderWidth: props.borderStyle.width,
710
- borderColor: props.borderStyle.color
711
- } }, props.imageUrl ? (
714
+ var ChatButton = function (_a) {
715
+ var _b;
716
+ var onClick = _a.onClick, addClass = _a.addClass, config = _a.config, visible = _a.visible, borderStyle = _a.borderStyle, imageUrl = _a.imageUrl;
717
+ var _c = React$1.useState(defaultWidgetButtonWidth), buttonWidth = _c[0], setButtonWidth = _c[1];
718
+ var _d = React$1.useState(false), animate = _d[0], setAnimate = _d[1];
719
+ var mobileWidht = ((_b = config === null || config === void 0 ? void 0 : config.mobile) === null || _b === void 0 ? void 0 : _b.applyAtLessThanWidth) || defaultNonMobileScreenWidth;
720
+ var getConfigToApply = function () {
721
+ var screenWidth = window.innerWidth;
722
+ if (screenWidth <= parseInt(mobileWidht, 10) && (config === null || config === void 0 ? void 0 : config.mobile)) {
723
+ return config.mobile;
724
+ }
725
+ else {
726
+ return config;
727
+ }
728
+ };
729
+ var configToApply = getConfigToApply();
730
+ React$1.useEffect(function () {
731
+ if ((configToApply === null || configToApply === void 0 ? void 0 : configToApply.delay) && (configToApply === null || configToApply === void 0 ? void 0 : configToApply.timeout)) {
732
+ var delayTimer_1 = setTimeout(function () {
733
+ setAnimate(true);
734
+ var timeoutTimer = setTimeout(function () {
735
+ setAnimate(false);
736
+ }, configToApply.timeout);
737
+ return function () {
738
+ clearTimeout(timeoutTimer);
739
+ };
740
+ }, configToApply.delay);
741
+ return function () {
742
+ clearTimeout(delayTimer_1);
743
+ };
744
+ }
745
+ return function () { };
746
+ }, [configToApply]);
747
+ var animation = animate ? ((configToApply === null || configToApply === void 0 ? void 0 : configToApply.animation) || "wiggle") : "none";
748
+ React$1.useEffect(function () {
749
+ var handleResize = function () {
750
+ var screenWidth = window.innerWidth;
751
+ var newButtonWidth = screenWidth < (parseInt(mobileWidht, 10))
752
+ ? defaultMobileWidgetButtonWidth : defaultWidgetButtonWidth;
753
+ setButtonWidth(newButtonWidth);
754
+ };
755
+ handleResize();
756
+ window.addEventListener('resize', handleResize);
757
+ return function () {
758
+ window.removeEventListener('resize', handleResize);
759
+ };
760
+ }, [mobileWidht]);
761
+ var maxSvgSize = 22;
762
+ var svgSize = Math.min(maxSvgSize, (+buttonWidth / +defaultWidgetButtonWidth) * maxSvgSize);
763
+ return (React__default$1["default"].createElement("button", { "aria-label": "open chat", className: "xapp-chat-button ".concat(addClass || "").trim(), onClick: onClick },
764
+ React__default$1["default"].createElement("div", { id: "xapp-widget-button", className: "xapp-chat-button__btn", style: {
765
+ width: "".concat(buttonWidth, "px"),
766
+ height: "".concat(buttonWidth, "px"),
767
+ borderRadius: "".concat(+buttonWidth / 2, "px"),
768
+ border: borderStyle && borderStyle.width ? 'solid' : 'none',
769
+ borderWidth: (borderStyle === null || borderStyle === void 0 ? void 0 : borderStyle.width) || '0px',
770
+ borderColor: (borderStyle === null || borderStyle === void 0 ? void 0 : borderStyle.color) || 'transparent',
771
+ animation: "".concat(animation, " 1s infinite"),
772
+ } }, imageUrl ? (
712
773
  // Display image from URL
713
- React__default$1["default"].createElement("img", { src: props.imageUrl, alt: "Chat Icon", width: "22", height: "22" })) : (
774
+ React__default$1["default"].createElement("img", { src: imageUrl, alt: "Chat Icon", width: "22", height: "22" })) : (
714
775
  // Fallback to default SVG
715
- React__default$1["default"].createElement("svg", { width: "22", height: "22", viewBox: "0 0 22 22" },
776
+ React__default$1["default"].createElement("svg", { width: svgSize, height: svgSize, viewBox: "0 0 22 22" },
716
777
  React__default$1["default"].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" })))),
717
- props.config && props.config.message && (React__default$1["default"].createElement("div", { className: "xapp-chat-button__cta" },
718
- React__default$1["default"].createElement(CtaBubbleContainer, { timeout: props.config.timeout, visible: !props.visible }, props.config.message)))));
778
+ config && config.message && (React__default$1["default"].createElement("div", { className: "xapp-chat-button__cta" },
779
+ React__default$1["default"].createElement(CtaBubbleContainer, { timeout: configToApply === null || configToApply === void 0 ? void 0 : configToApply.timeout, delay: configToApply === null || configToApply === void 0 ? void 0 : configToApply.delay, visible: !visible }, config.message)))));
719
780
  };
720
781
 
721
782
  var ChatCard = function (props) {
@@ -7900,9 +7961,23 @@ var AdminBar = function (_props) {
7900
7961
  return (React__default$1["default"].createElement("div", { className: "xappw-admin-input-container visible" }, joined ? renderLeave() : renderJoin()));
7901
7962
  };
7902
7963
 
7903
- var ChatBranding = function (props) {
7904
- var text = props.text;
7905
- return (React__default$1["default"].createElement("div", { className: "chat-footer__branding" }, text !== null && text !== void 0 ? text : "Powered by XAPP AI"));
7964
+ var ChatBranding = function (_a) {
7965
+ var text = _a.text;
7966
+ var regex = /\[([^\]]+)\]\((https?:\/\/[^\)]+)\)/;
7967
+ var match = text === null || text === void 0 ? void 0 : text.match(regex);
7968
+ var buildLink = function (match) {
7969
+ var linkText = match[1];
7970
+ var link = match[2];
7971
+ var prefix = text === null || text === void 0 ? void 0 : text.split(match[0])[0];
7972
+ var suffix = text === null || text === void 0 ? void 0 : text.split(match[0])[1];
7973
+ return (React__default$1["default"].createElement("div", { className: "chat-footer__branding" },
7974
+ prefix,
7975
+ React__default$1["default"].createElement("a", { style: { color: "white", textDecoration: "underline" }, href: link, target: "_blank", rel: "noopener noreferrer" }, linkText),
7976
+ suffix));
7977
+ };
7978
+ return match ? buildLink(match)
7979
+ :
7980
+ React__default$1["default"].createElement("div", { className: "chat-footer__branding", style: { color: "white" } }, text);
7906
7981
  };
7907
7982
 
7908
7983
  var CloseIcon = function () {
@@ -8038,25 +8113,24 @@ var Suggestions = function (props) {
8038
8113
  };
8039
8114
 
8040
8115
  var ChatFooter = function (props) {
8041
- var _a, _b, _c;
8116
+ var _a, _b;
8042
8117
  var innerDispatch = useChatDispatch();
8043
8118
  var placeholder = props.placeholder, sendButtonIcon = props.sendButtonIcon, footerConfig = props.footerConfig, menuConfig = props.menuConfig, inputConfig = props.inputConfig, onSubmit = props.onSubmit;
8044
- var _d = React$1.useState(false), drawerOpen = _d[0], setDrawerState = _d[1]; // false initially
8045
- var _e = React$1.useState(), suggestionSearch = _e[0], setSuggestionSearch = _e[1];
8119
+ var _c = React$1.useState(false), drawerOpen = _c[0], setDrawerState = _c[1]; // false initially
8120
+ var _d = React$1.useState(), suggestionSearch = _d[0], setSuggestionSearch = _d[1];
8046
8121
  var contexts = reactRedux.useSelector(function (state) { return state.activeContexts; });
8047
8122
  var suggestions = useSuggestions(suggestionSearch, contexts);
8048
8123
  var menuPosition = (menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.menuButtonLocation) || "FOOTER";
8049
8124
  var showMenu = menuPosition === "FOOTER";
8050
- var menuItemsRaw = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.items; // useWidgetEnv()?.menu?.items;
8051
- var menuItemsTabIndex = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.itemsTabIndex; // useWidgetEnv()?.menu?.itemsTabIndex;
8052
- var menuButtonTabIndex = (_a = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.button) === null || _a === void 0 ? void 0 : _a.tabIndex; // useWidgetEnv()?.menu?.button?.tabIndex;
8125
+ var menuItemsRaw = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.items;
8126
+ var menuItemsTabIndex = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.itemsTabIndex;
8127
+ var menuButtonTabIndex = (_a = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig.button) === null || _a === void 0 ? void 0 : _a.tabIndex;
8053
8128
  var menuItems = React$1.useMemo(function () { return menuItemsRaw ? menuItemsRaw : []; }, [menuItemsRaw]);
8054
- var branding = (_b = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.branding) === null || _b === void 0 ? void 0 : _b.text; // useWidgetEnv()?.footer?.branding?.text;
8055
- var brandingEnabled = (_c = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.branding) === null || _c === void 0 ? void 0 : _c.enabled; // useWidgetEnv()?.footer?.branding?.enabled;
8056
- var _f = React$1.useState({
8129
+ var brandingEnabled = (_b = footerConfig === null || footerConfig === void 0 ? void 0 : footerConfig.branding) === null || _b === void 0 ? void 0 : _b.enabled;
8130
+ var _e = React$1.useState({
8057
8131
  text: "",
8058
8132
  formats: []
8059
- }), input = _f[0], setInput = _f[1];
8133
+ }), input = _e[0], setInput = _e[1];
8060
8134
  function toggleDrawer() {
8061
8135
  var newDrawer = !drawerOpen;
8062
8136
  setDrawerState(newDrawer);
@@ -8103,7 +8177,7 @@ var ChatFooter = function (props) {
8103
8177
  React__default$1["default"].createElement(Input, { addClass: "chat-footer__input " + (props.isChatting && props.visible ? "visible" : ""), suggestion: suggestions.item, value: input, placeholder: placeholder, sendButtonIcon: sendButtonIcon, footerConfig: footerConfig, inputConfig: inputConfig, onSubmit: handleSubmit, onChange: handleChange, onSuggestionCommand: suggestions.execute,
8104
8178
  // onFocus={this.inputOnFocus}
8105
8179
  onFileUpload: props.onFileUpload }),
8106
- brandingEnabled && React__default$1["default"].createElement(ChatBranding, { text: branding })));
8180
+ brandingEnabled && React__default$1["default"].createElement(ChatBranding, { text: 'Powered by [XAPP AI](https://xapp.ai)' })));
8107
8181
  };
8108
8182
 
8109
8183
  var noop = function () { };