@wallavi/widget 1.2.1 → 1.3.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/index.d.mts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +60 -14
- package/dist/index.mjs +60 -14
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -111,8 +111,16 @@ interface BubbleWidgetProps extends ChatWidgetConfig {
|
|
|
111
111
|
bubbleSize?: number;
|
|
112
112
|
/** className applied to the chat panel */
|
|
113
113
|
panelClassName?: string;
|
|
114
|
+
/**
|
|
115
|
+
* Auto-fetch the agent's configuration from the Wallavi public API and apply it
|
|
116
|
+
* as defaults (profilePicture, chatIcon, colors, messages, autoOpen, keyboardShortcut…).
|
|
117
|
+
* The client only needs to pass `agentId` — everything else self-configures.
|
|
118
|
+
* Pass `autoConfig={false}` if you are providing all props manually.
|
|
119
|
+
* @default true
|
|
120
|
+
*/
|
|
121
|
+
autoConfig?: boolean;
|
|
114
122
|
}
|
|
115
|
-
declare function BubbleWidget({ position, width, height, expandedWidth, expandedHeight, keyboardShortcut, shortcutKey, autoOpen, bubbleIconUrl, bubbleSize, panelClassName, ...chatProps }: BubbleWidgetProps): react_jsx_runtime.JSX.Element;
|
|
123
|
+
declare function BubbleWidget({ position: positionProp, width, height, expandedWidth, expandedHeight, keyboardShortcut: keyboardShortcutProp, shortcutKey, autoOpen: autoOpenProp, bubbleIconUrl: bubbleIconUrlProp, bubbleSize, panelClassName, autoConfig, ...chatProps }: BubbleWidgetProps): react_jsx_runtime.JSX.Element;
|
|
116
124
|
|
|
117
125
|
declare function ChatWidget({ agentId, workspaceId, agentName, displayName, profilePicture, userMessageColor, initialMessages, suggestedMessages, messagePlaceholder, watermark, watermarkLogoUrl, footer, theme, showThinking, regenerateMessage, persist, onNavigate, hideCloseButton, source, userContext, playgroundOverrides, className, onClose, onReset, }: ChatWidgetProps): react_jsx_runtime.JSX.Element;
|
|
118
126
|
|
package/dist/index.d.ts
CHANGED
|
@@ -111,8 +111,16 @@ interface BubbleWidgetProps extends ChatWidgetConfig {
|
|
|
111
111
|
bubbleSize?: number;
|
|
112
112
|
/** className applied to the chat panel */
|
|
113
113
|
panelClassName?: string;
|
|
114
|
+
/**
|
|
115
|
+
* Auto-fetch the agent's configuration from the Wallavi public API and apply it
|
|
116
|
+
* as defaults (profilePicture, chatIcon, colors, messages, autoOpen, keyboardShortcut…).
|
|
117
|
+
* The client only needs to pass `agentId` — everything else self-configures.
|
|
118
|
+
* Pass `autoConfig={false}` if you are providing all props manually.
|
|
119
|
+
* @default true
|
|
120
|
+
*/
|
|
121
|
+
autoConfig?: boolean;
|
|
114
122
|
}
|
|
115
|
-
declare function BubbleWidget({ position, width, height, expandedWidth, expandedHeight, keyboardShortcut, shortcutKey, autoOpen, bubbleIconUrl, bubbleSize, panelClassName, ...chatProps }: BubbleWidgetProps): react_jsx_runtime.JSX.Element;
|
|
123
|
+
declare function BubbleWidget({ position: positionProp, width, height, expandedWidth, expandedHeight, keyboardShortcut: keyboardShortcutProp, shortcutKey, autoOpen: autoOpenProp, bubbleIconUrl: bubbleIconUrlProp, bubbleSize, panelClassName, autoConfig, ...chatProps }: BubbleWidgetProps): react_jsx_runtime.JSX.Element;
|
|
116
124
|
|
|
117
125
|
declare function ChatWidget({ agentId, workspaceId, agentName, displayName, profilePicture, userMessageColor, initialMessages, suggestedMessages, messagePlaceholder, watermark, watermarkLogoUrl, footer, theme, showThinking, regenerateMessage, persist, onNavigate, hideCloseButton, source, userContext, playgroundOverrides, className, onClose, onReset, }: ChatWidgetProps): react_jsx_runtime.JSX.Element;
|
|
118
126
|
|
package/dist/index.js
CHANGED
|
@@ -307,7 +307,7 @@ function ChatHeader({
|
|
|
307
307
|
"header",
|
|
308
308
|
{
|
|
309
309
|
className: "flex items-center justify-between px-4 py-3 shrink-0",
|
|
310
|
-
style: { backgroundColor: headerBg, color: headerText },
|
|
310
|
+
style: { backgroundColor: headerBg, color: headerText, borderBottom: `1px solid ${headerText}18` },
|
|
311
311
|
children: [
|
|
312
312
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5 min-w-0", children: [
|
|
313
313
|
/* @__PURE__ */ jsxRuntime.jsx(Avatar, { style: { width: 32, height: 32, border: `2px solid ${headerText}30` }, children: profilePicture ? /* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src: profilePicture, alt: title }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -500,7 +500,7 @@ function ChatMessages({
|
|
|
500
500
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
501
501
|
}, [messages]);
|
|
502
502
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col overflow-y-auto overscroll-contain", children: [
|
|
503
|
-
showGreeting && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2.5 items-start px-4 pt-
|
|
503
|
+
showGreeting && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2.5 items-start px-4 pt-5", children: [
|
|
504
504
|
/* @__PURE__ */ jsxRuntime.jsx(Avatar3, { className: "h-7 w-7 shrink-0 mt-0.5 border", children: profilePicture ? /* @__PURE__ */ jsxRuntime.jsx(AvatarImage3, { src: profilePicture, alt: agentName }) : /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback3, { className: "text-[10px] font-semibold bg-primary text-primary-foreground", children: agentName.slice(0, 2).toUpperCase() }) }),
|
|
505
505
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-2xl rounded-tl-sm bg-muted px-4 py-2.5 text-sm leading-relaxed max-w-[82%]", children: initialMessages[0] ?? "Hello! How can I help you today?" })
|
|
506
506
|
] }),
|
|
@@ -710,6 +710,7 @@ function ChatWidget({
|
|
|
710
710
|
);
|
|
711
711
|
}
|
|
712
712
|
var cn4 = (...inputs) => tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
713
|
+
var WALLAVI_API = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_API_URL ?? "https://wallavi-production.up.railway.app" : "https://wallavi-production.up.railway.app";
|
|
713
714
|
function DefaultIcon() {
|
|
714
715
|
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", style: { width: 26, height: 26 }, children: [
|
|
715
716
|
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "12", fill: "currentColor", opacity: 0.12 }),
|
|
@@ -732,17 +733,18 @@ function MinimizeIcon() {
|
|
|
732
733
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", style: { width: 12, height: 12 }, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 14h6v6M20 10h-6V4M14 10l7-7M3 21l7-7", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
733
734
|
}
|
|
734
735
|
function BubbleWidget({
|
|
735
|
-
position
|
|
736
|
+
position: positionProp,
|
|
736
737
|
width = 360,
|
|
737
738
|
height = 580,
|
|
738
739
|
expandedWidth = 640,
|
|
739
740
|
expandedHeight = "calc(100vh - 100px)",
|
|
740
|
-
keyboardShortcut = false,
|
|
741
|
+
keyboardShortcut: keyboardShortcutProp = false,
|
|
741
742
|
shortcutKey = "k",
|
|
742
|
-
autoOpen = false,
|
|
743
|
-
bubbleIconUrl,
|
|
743
|
+
autoOpen: autoOpenProp = false,
|
|
744
|
+
bubbleIconUrl: bubbleIconUrlProp,
|
|
744
745
|
bubbleSize = 52,
|
|
745
746
|
panelClassName,
|
|
747
|
+
autoConfig = true,
|
|
746
748
|
// ChatWidgetConfig props
|
|
747
749
|
...chatProps
|
|
748
750
|
}) {
|
|
@@ -750,16 +752,50 @@ function BubbleWidget({
|
|
|
750
752
|
const [expanded, setExpanded] = react.useState(false);
|
|
751
753
|
const panelRef = react.useRef(null);
|
|
752
754
|
const autoOpenedRef = react.useRef(false);
|
|
755
|
+
const [remoteConfig, setRemoteConfig] = react.useState({});
|
|
756
|
+
const [resolvedBubbleIcon, setResolvedBubbleIcon] = react.useState(bubbleIconUrlProp);
|
|
757
|
+
const [resolvedAutoOpen, setResolvedAutoOpen] = react.useState(autoOpenProp);
|
|
758
|
+
const [resolvedKeyboardShortcut, setResolvedKeyboardShortcut] = react.useState(keyboardShortcutProp);
|
|
759
|
+
const [resolvedPosition, setResolvedPosition] = react.useState(positionProp ?? "bottom-right");
|
|
753
760
|
react.useEffect(() => {
|
|
754
|
-
if (!
|
|
761
|
+
if (!autoConfig) return;
|
|
762
|
+
fetch(`${WALLAVI_API}/api/public/widget/${chatProps.agentId}`).then((r) => r.json()).then((body) => {
|
|
763
|
+
const cfg = body?.data ?? {};
|
|
764
|
+
const remote = {};
|
|
765
|
+
if (cfg.profilePicture != null) remote.profilePicture = cfg.profilePicture;
|
|
766
|
+
if (cfg.displayName != null) remote.displayName = cfg.displayName;
|
|
767
|
+
if (cfg.theme) remote.theme = cfg.theme;
|
|
768
|
+
if (cfg.userMessageColor) remote.userMessageColor = cfg.userMessageColor;
|
|
769
|
+
if (Array.isArray(cfg.initialMessages) && cfg.initialMessages.length > 0) remote.initialMessages = cfg.initialMessages;
|
|
770
|
+
if (Array.isArray(cfg.suggestedMessages)) remote.suggestedMessages = cfg.suggestedMessages;
|
|
771
|
+
if (cfg.messagePlaceholder != null) remote.messagePlaceholder = cfg.messagePlaceholder;
|
|
772
|
+
if (cfg.watermark != null) remote.watermark = cfg.watermark;
|
|
773
|
+
if (cfg.footer != null) remote.footer = cfg.footer;
|
|
774
|
+
if (cfg.showThinking != null) remote.showThinking = cfg.showThinking;
|
|
775
|
+
if (cfg.regenerateMessage != null) remote.regenerateMessage = cfg.regenerateMessage;
|
|
776
|
+
setRemoteConfig(remote);
|
|
777
|
+
if (!bubbleIconUrlProp) {
|
|
778
|
+
const icon = cfg.chatIcon || cfg.profilePicture;
|
|
779
|
+
if (icon) setResolvedBubbleIcon(icon);
|
|
780
|
+
}
|
|
781
|
+
if (!autoOpenProp && cfg.autoOpen) setResolvedAutoOpen(true);
|
|
782
|
+
if (!keyboardShortcutProp && cfg.keyboardShortcut) setResolvedKeyboardShortcut(true);
|
|
783
|
+
if (!positionProp && cfg.alignChatBubbleButton) {
|
|
784
|
+
setResolvedPosition(cfg.alignChatBubbleButton === "left" ? "bottom-left" : "bottom-right");
|
|
785
|
+
}
|
|
786
|
+
}).catch(() => {
|
|
787
|
+
});
|
|
788
|
+
}, [autoConfig, chatProps.agentId]);
|
|
789
|
+
react.useEffect(() => {
|
|
790
|
+
if (!resolvedAutoOpen || autoOpenedRef.current) return;
|
|
755
791
|
const dismissedUntil = Number(localStorage.getItem("wallavi_bubble_dismissed") ?? 0);
|
|
756
792
|
if (dismissedUntil < Date.now()) {
|
|
757
793
|
autoOpenedRef.current = true;
|
|
758
794
|
setOpen(true);
|
|
759
795
|
}
|
|
760
|
-
}, [
|
|
796
|
+
}, [resolvedAutoOpen]);
|
|
761
797
|
react.useEffect(() => {
|
|
762
|
-
if (!
|
|
798
|
+
if (!resolvedKeyboardShortcut) return;
|
|
763
799
|
const handler = (e) => {
|
|
764
800
|
if ((e.metaKey || e.ctrlKey) && e.key === shortcutKey) {
|
|
765
801
|
e.preventDefault();
|
|
@@ -768,7 +804,7 @@ function BubbleWidget({
|
|
|
768
804
|
};
|
|
769
805
|
window.addEventListener("keydown", handler);
|
|
770
806
|
return () => window.removeEventListener("keydown", handler);
|
|
771
|
-
}, [
|
|
807
|
+
}, [resolvedKeyboardShortcut, shortcutKey]);
|
|
772
808
|
react.useEffect(() => {
|
|
773
809
|
if (!open) return;
|
|
774
810
|
const id = setTimeout(() => {
|
|
@@ -776,13 +812,23 @@ function BubbleWidget({
|
|
|
776
812
|
}, 50);
|
|
777
813
|
return () => clearTimeout(id);
|
|
778
814
|
}, [open]);
|
|
815
|
+
const definedChatProps = Object.fromEntries(
|
|
816
|
+
Object.entries(chatProps).filter(([, v]) => v !== void 0)
|
|
817
|
+
);
|
|
818
|
+
const mergedConfig = {
|
|
819
|
+
...remoteConfig,
|
|
820
|
+
...definedChatProps,
|
|
821
|
+
// Required fields must always come from chatProps
|
|
822
|
+
agentId: chatProps.agentId,
|
|
823
|
+
agentName: chatProps.agentName
|
|
824
|
+
};
|
|
779
825
|
const handleClose = () => {
|
|
780
826
|
setOpen(false);
|
|
781
827
|
const expires = Date.now() + 24 * 60 * 60 * 1e3;
|
|
782
828
|
localStorage.setItem("wallavi_bubble_dismissed", String(expires));
|
|
783
829
|
};
|
|
784
830
|
const toggleExpanded = () => setExpanded((v) => !v);
|
|
785
|
-
const isLeft =
|
|
831
|
+
const isLeft = resolvedPosition === "bottom-left";
|
|
786
832
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
787
833
|
"div",
|
|
788
834
|
{
|
|
@@ -873,7 +919,7 @@ function BubbleWidget({
|
|
|
873
919
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
874
920
|
ChatWidget,
|
|
875
921
|
{
|
|
876
|
-
...
|
|
922
|
+
...mergedConfig,
|
|
877
923
|
hideCloseButton: true,
|
|
878
924
|
className: cn4("shadow-2xl h-full", panelClassName)
|
|
879
925
|
}
|
|
@@ -903,10 +949,10 @@ function BubbleWidget({
|
|
|
903
949
|
background: open ? "var(--foreground, #19191c)" : "var(--background, #fff)",
|
|
904
950
|
color: open ? "var(--background, #fff)" : "var(--foreground, #19191c)"
|
|
905
951
|
},
|
|
906
|
-
children: open ? /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {}) :
|
|
952
|
+
children: open ? /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {}) : resolvedBubbleIcon ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
907
953
|
"img",
|
|
908
954
|
{
|
|
909
|
-
src:
|
|
955
|
+
src: resolvedBubbleIcon,
|
|
910
956
|
alt: "Open chat",
|
|
911
957
|
style: { width: "100%", height: "100%", objectFit: "cover", display: "block" }
|
|
912
958
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -281,7 +281,7 @@ function ChatHeader({
|
|
|
281
281
|
"header",
|
|
282
282
|
{
|
|
283
283
|
className: "flex items-center justify-between px-4 py-3 shrink-0",
|
|
284
|
-
style: { backgroundColor: headerBg, color: headerText },
|
|
284
|
+
style: { backgroundColor: headerBg, color: headerText, borderBottom: `1px solid ${headerText}18` },
|
|
285
285
|
children: [
|
|
286
286
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 min-w-0", children: [
|
|
287
287
|
/* @__PURE__ */ jsx(Avatar, { style: { width: 32, height: 32, border: `2px solid ${headerText}30` }, children: profilePicture ? /* @__PURE__ */ jsx(AvatarImage, { src: profilePicture, alt: title }) : /* @__PURE__ */ jsx(
|
|
@@ -474,7 +474,7 @@ function ChatMessages({
|
|
|
474
474
|
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
475
475
|
}, [messages]);
|
|
476
476
|
return /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col overflow-y-auto overscroll-contain", children: [
|
|
477
|
-
showGreeting && /* @__PURE__ */ jsxs("div", { className: "flex gap-2.5 items-start px-4 pt-
|
|
477
|
+
showGreeting && /* @__PURE__ */ jsxs("div", { className: "flex gap-2.5 items-start px-4 pt-5", children: [
|
|
478
478
|
/* @__PURE__ */ jsx(Avatar3, { className: "h-7 w-7 shrink-0 mt-0.5 border", children: profilePicture ? /* @__PURE__ */ jsx(AvatarImage3, { src: profilePicture, alt: agentName }) : /* @__PURE__ */ jsx(AvatarFallback3, { className: "text-[10px] font-semibold bg-primary text-primary-foreground", children: agentName.slice(0, 2).toUpperCase() }) }),
|
|
479
479
|
/* @__PURE__ */ jsx("div", { className: "rounded-2xl rounded-tl-sm bg-muted px-4 py-2.5 text-sm leading-relaxed max-w-[82%]", children: initialMessages[0] ?? "Hello! How can I help you today?" })
|
|
480
480
|
] }),
|
|
@@ -684,6 +684,7 @@ function ChatWidget({
|
|
|
684
684
|
);
|
|
685
685
|
}
|
|
686
686
|
var cn4 = (...inputs) => twMerge(clsx(inputs));
|
|
687
|
+
var WALLAVI_API = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_API_URL ?? "https://wallavi-production.up.railway.app" : "https://wallavi-production.up.railway.app";
|
|
687
688
|
function DefaultIcon() {
|
|
688
689
|
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", style: { width: 26, height: 26 }, children: [
|
|
689
690
|
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "12", fill: "currentColor", opacity: 0.12 }),
|
|
@@ -706,17 +707,18 @@ function MinimizeIcon() {
|
|
|
706
707
|
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", style: { width: 12, height: 12 }, children: /* @__PURE__ */ jsx("path", { d: "M4 14h6v6M20 10h-6V4M14 10l7-7M3 21l7-7", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
707
708
|
}
|
|
708
709
|
function BubbleWidget({
|
|
709
|
-
position
|
|
710
|
+
position: positionProp,
|
|
710
711
|
width = 360,
|
|
711
712
|
height = 580,
|
|
712
713
|
expandedWidth = 640,
|
|
713
714
|
expandedHeight = "calc(100vh - 100px)",
|
|
714
|
-
keyboardShortcut = false,
|
|
715
|
+
keyboardShortcut: keyboardShortcutProp = false,
|
|
715
716
|
shortcutKey = "k",
|
|
716
|
-
autoOpen = false,
|
|
717
|
-
bubbleIconUrl,
|
|
717
|
+
autoOpen: autoOpenProp = false,
|
|
718
|
+
bubbleIconUrl: bubbleIconUrlProp,
|
|
718
719
|
bubbleSize = 52,
|
|
719
720
|
panelClassName,
|
|
721
|
+
autoConfig = true,
|
|
720
722
|
// ChatWidgetConfig props
|
|
721
723
|
...chatProps
|
|
722
724
|
}) {
|
|
@@ -724,16 +726,50 @@ function BubbleWidget({
|
|
|
724
726
|
const [expanded, setExpanded] = useState(false);
|
|
725
727
|
const panelRef = useRef(null);
|
|
726
728
|
const autoOpenedRef = useRef(false);
|
|
729
|
+
const [remoteConfig, setRemoteConfig] = useState({});
|
|
730
|
+
const [resolvedBubbleIcon, setResolvedBubbleIcon] = useState(bubbleIconUrlProp);
|
|
731
|
+
const [resolvedAutoOpen, setResolvedAutoOpen] = useState(autoOpenProp);
|
|
732
|
+
const [resolvedKeyboardShortcut, setResolvedKeyboardShortcut] = useState(keyboardShortcutProp);
|
|
733
|
+
const [resolvedPosition, setResolvedPosition] = useState(positionProp ?? "bottom-right");
|
|
727
734
|
useEffect(() => {
|
|
728
|
-
if (!
|
|
735
|
+
if (!autoConfig) return;
|
|
736
|
+
fetch(`${WALLAVI_API}/api/public/widget/${chatProps.agentId}`).then((r) => r.json()).then((body) => {
|
|
737
|
+
const cfg = body?.data ?? {};
|
|
738
|
+
const remote = {};
|
|
739
|
+
if (cfg.profilePicture != null) remote.profilePicture = cfg.profilePicture;
|
|
740
|
+
if (cfg.displayName != null) remote.displayName = cfg.displayName;
|
|
741
|
+
if (cfg.theme) remote.theme = cfg.theme;
|
|
742
|
+
if (cfg.userMessageColor) remote.userMessageColor = cfg.userMessageColor;
|
|
743
|
+
if (Array.isArray(cfg.initialMessages) && cfg.initialMessages.length > 0) remote.initialMessages = cfg.initialMessages;
|
|
744
|
+
if (Array.isArray(cfg.suggestedMessages)) remote.suggestedMessages = cfg.suggestedMessages;
|
|
745
|
+
if (cfg.messagePlaceholder != null) remote.messagePlaceholder = cfg.messagePlaceholder;
|
|
746
|
+
if (cfg.watermark != null) remote.watermark = cfg.watermark;
|
|
747
|
+
if (cfg.footer != null) remote.footer = cfg.footer;
|
|
748
|
+
if (cfg.showThinking != null) remote.showThinking = cfg.showThinking;
|
|
749
|
+
if (cfg.regenerateMessage != null) remote.regenerateMessage = cfg.regenerateMessage;
|
|
750
|
+
setRemoteConfig(remote);
|
|
751
|
+
if (!bubbleIconUrlProp) {
|
|
752
|
+
const icon = cfg.chatIcon || cfg.profilePicture;
|
|
753
|
+
if (icon) setResolvedBubbleIcon(icon);
|
|
754
|
+
}
|
|
755
|
+
if (!autoOpenProp && cfg.autoOpen) setResolvedAutoOpen(true);
|
|
756
|
+
if (!keyboardShortcutProp && cfg.keyboardShortcut) setResolvedKeyboardShortcut(true);
|
|
757
|
+
if (!positionProp && cfg.alignChatBubbleButton) {
|
|
758
|
+
setResolvedPosition(cfg.alignChatBubbleButton === "left" ? "bottom-left" : "bottom-right");
|
|
759
|
+
}
|
|
760
|
+
}).catch(() => {
|
|
761
|
+
});
|
|
762
|
+
}, [autoConfig, chatProps.agentId]);
|
|
763
|
+
useEffect(() => {
|
|
764
|
+
if (!resolvedAutoOpen || autoOpenedRef.current) return;
|
|
729
765
|
const dismissedUntil = Number(localStorage.getItem("wallavi_bubble_dismissed") ?? 0);
|
|
730
766
|
if (dismissedUntil < Date.now()) {
|
|
731
767
|
autoOpenedRef.current = true;
|
|
732
768
|
setOpen(true);
|
|
733
769
|
}
|
|
734
|
-
}, [
|
|
770
|
+
}, [resolvedAutoOpen]);
|
|
735
771
|
useEffect(() => {
|
|
736
|
-
if (!
|
|
772
|
+
if (!resolvedKeyboardShortcut) return;
|
|
737
773
|
const handler = (e) => {
|
|
738
774
|
if ((e.metaKey || e.ctrlKey) && e.key === shortcutKey) {
|
|
739
775
|
e.preventDefault();
|
|
@@ -742,7 +778,7 @@ function BubbleWidget({
|
|
|
742
778
|
};
|
|
743
779
|
window.addEventListener("keydown", handler);
|
|
744
780
|
return () => window.removeEventListener("keydown", handler);
|
|
745
|
-
}, [
|
|
781
|
+
}, [resolvedKeyboardShortcut, shortcutKey]);
|
|
746
782
|
useEffect(() => {
|
|
747
783
|
if (!open) return;
|
|
748
784
|
const id = setTimeout(() => {
|
|
@@ -750,13 +786,23 @@ function BubbleWidget({
|
|
|
750
786
|
}, 50);
|
|
751
787
|
return () => clearTimeout(id);
|
|
752
788
|
}, [open]);
|
|
789
|
+
const definedChatProps = Object.fromEntries(
|
|
790
|
+
Object.entries(chatProps).filter(([, v]) => v !== void 0)
|
|
791
|
+
);
|
|
792
|
+
const mergedConfig = {
|
|
793
|
+
...remoteConfig,
|
|
794
|
+
...definedChatProps,
|
|
795
|
+
// Required fields must always come from chatProps
|
|
796
|
+
agentId: chatProps.agentId,
|
|
797
|
+
agentName: chatProps.agentName
|
|
798
|
+
};
|
|
753
799
|
const handleClose = () => {
|
|
754
800
|
setOpen(false);
|
|
755
801
|
const expires = Date.now() + 24 * 60 * 60 * 1e3;
|
|
756
802
|
localStorage.setItem("wallavi_bubble_dismissed", String(expires));
|
|
757
803
|
};
|
|
758
804
|
const toggleExpanded = () => setExpanded((v) => !v);
|
|
759
|
-
const isLeft =
|
|
805
|
+
const isLeft = resolvedPosition === "bottom-left";
|
|
760
806
|
return /* @__PURE__ */ jsxs(
|
|
761
807
|
"div",
|
|
762
808
|
{
|
|
@@ -847,7 +893,7 @@ function BubbleWidget({
|
|
|
847
893
|
children: /* @__PURE__ */ jsx(
|
|
848
894
|
ChatWidget,
|
|
849
895
|
{
|
|
850
|
-
...
|
|
896
|
+
...mergedConfig,
|
|
851
897
|
hideCloseButton: true,
|
|
852
898
|
className: cn4("shadow-2xl h-full", panelClassName)
|
|
853
899
|
}
|
|
@@ -877,10 +923,10 @@ function BubbleWidget({
|
|
|
877
923
|
background: open ? "var(--foreground, #19191c)" : "var(--background, #fff)",
|
|
878
924
|
color: open ? "var(--background, #fff)" : "var(--foreground, #19191c)"
|
|
879
925
|
},
|
|
880
|
-
children: open ? /* @__PURE__ */ jsx(CloseIcon, {}) :
|
|
926
|
+
children: open ? /* @__PURE__ */ jsx(CloseIcon, {}) : resolvedBubbleIcon ? /* @__PURE__ */ jsx(
|
|
881
927
|
"img",
|
|
882
928
|
{
|
|
883
|
-
src:
|
|
929
|
+
src: resolvedBubbleIcon,
|
|
884
930
|
alt: "Open chat",
|
|
885
931
|
style: { width: "100%", height: "100%", objectFit: "cover", display: "block" }
|
|
886
932
|
}
|