@beyondcorp/beyond-ui 1.3.2 → 1.3.6

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.
@@ -15,10 +15,12 @@ export interface ChatWidgetProps extends VariantProps<typeof chatWidgetVariants>
15
15
  title?: string;
16
16
  subtitle?: string;
17
17
  greeting?: string;
18
+ messages?: Message[];
18
19
  onSendMessage?: (message: string) => Promise<void> | void;
19
20
  headerClassName?: string;
20
21
  triggerButtonClassName?: string;
21
22
  userMessageClassName?: string;
23
+ defaultOpen?: boolean;
22
24
  }
23
25
  export declare const ChatWidget: React.FC<ChatWidgetProps>;
24
26
  export {};
@@ -24,14 +24,15 @@ const chatWidgetVariants = cva("z-50 flex flex-col transition-all duration-300 e
24
24
  strategy: "fixed",
25
25
  },
26
26
  });
27
- const ChatWidget = ({ className, position, strategy, title = "Support", subtitle = "We typically reply in a few minutes", greeting = "Hello! How can we help you today?", onSendMessage, headerClassName, triggerButtonClassName, userMessageClassName, }) => {
28
- const [isOpen, setIsOpen] = useState(false);
27
+ const ChatWidget = ({ className, position, strategy, title = "Support", subtitle = "We typically reply in a few minutes", greeting = "Hello! How can we help you today?", messages: externalMessages, onSendMessage, headerClassName, triggerButtonClassName, userMessageClassName, defaultOpen = false, }) => {
28
+ const [isOpen, setIsOpen] = useState(defaultOpen);
29
29
  const [inputValue, setInputValue] = useState("");
30
30
  const [isTyping, setIsTyping] = useState(false);
31
31
  const messagesEndRef = useRef(null);
32
32
  const [messages, setMessages] = useState([
33
33
  { id: "1", content: greeting, sender: "ai", timestamp: new Date() },
34
34
  ]);
35
+ const displayMessages = externalMessages || messages;
35
36
  const scrollToBottom = () => {
36
37
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
37
38
  };
@@ -39,40 +40,52 @@ const ChatWidget = ({ className, position, strategy, title = "Support", subtitle
39
40
  if (isOpen) {
40
41
  scrollToBottom();
41
42
  }
42
- }, [isOpen, messages, isTyping]);
43
+ }, [isOpen, displayMessages, isTyping]);
43
44
  const handleSend = async () => {
44
45
  if (!inputValue.trim())
45
46
  return;
46
- const newUserMessage = {
47
- id: Date.now().toString(),
48
- content: inputValue,
49
- sender: "user",
50
- timestamp: new Date(),
51
- };
52
- setMessages((prev) => [...prev, newUserMessage]);
47
+ const messageContent = inputValue;
53
48
  setInputValue("");
54
- setIsTyping(true);
55
- if (onSendMessage) {
56
- await onSendMessage(newUserMessage.content);
49
+ if (externalMessages && onSendMessage) {
50
+ setIsTyping(true);
51
+ try {
52
+ await onSendMessage(messageContent);
53
+ }
54
+ catch (err) {
55
+ console.error("ChatWidget: error sending message", err);
56
+ }
57
57
  setIsTyping(false);
58
58
  }
59
59
  else {
60
- // Default fallback mock response
61
- setTimeout(() => {
62
- setMessages((prev) => [
63
- ...prev,
64
- {
65
- id: (Date.now() + 1).toString(),
66
- content: "Thanks for reaching out! A representative will be with you shortly.",
67
- sender: "ai",
68
- timestamp: new Date(),
69
- },
70
- ]);
60
+ const newUserMessage = {
61
+ id: Date.now().toString(),
62
+ content: messageContent,
63
+ sender: "user",
64
+ timestamp: new Date(),
65
+ };
66
+ setMessages((prev) => [...prev, newUserMessage]);
67
+ setIsTyping(true);
68
+ if (onSendMessage) {
69
+ await onSendMessage(messageContent);
71
70
  setIsTyping(false);
72
- }, 1500);
71
+ }
72
+ else {
73
+ setTimeout(() => {
74
+ setMessages((prev) => [
75
+ ...prev,
76
+ {
77
+ id: (Date.now() + 1).toString(),
78
+ content: "Thanks for reaching out! A representative will be with you shortly.",
79
+ sender: "ai",
80
+ timestamp: new Date(),
81
+ },
82
+ ]);
83
+ setIsTyping(false);
84
+ }, 1500);
85
+ }
73
86
  }
74
87
  };
75
- return (jsxs("div", { className: cn(chatWidgetVariants({ position, strategy }), className), children: [isOpen && (jsxs(Card, { className: "w-80 sm:w-96 h-[32rem] mb-4 flex flex-col shadow-2xl border-gray-200 dark:border-gray-800 animate-in slide-in-from-bottom-4 fade-in overflow-hidden", children: [jsxs(CardHeader, { className: cn("bg-primary-600 dark:bg-primary-700 text-white p-4 flex flex-row items-center justify-between rounded-none rounded-t-lg", headerClassName), children: [jsxs("div", { className: "flex items-center space-x-3", children: [jsx(Avatar, { size: "sm", className: "border border-white/20", children: jsx(AvatarFallback, { className: "bg-black/20 text-white", children: jsx(Bot, { size: 16 }) }) }), jsxs("div", { children: [jsx(CardTitle, { className: "text-white text-base font-semibold", children: title }), jsx("p", { className: "text-white/80 text-xs font-normal", children: subtitle })] })] }), jsx(Button, { variant: "ghost", size: "sm", className: "text-white hover:bg-black/20 hover:text-white rounded-full p-2 h-8 w-8", onClick: () => setIsOpen(false), children: jsx(X, { size: 16 }) })] }), jsxs(CardContent, { className: "flex-1 overflow-y-auto p-4 space-y-4 bg-gray-50 dark:bg-gray-900/50", children: [messages.map((msg) => {
88
+ return (jsxs("div", { className: cn(chatWidgetVariants({ position, strategy }), className), children: [isOpen && (jsxs(Card, { className: "w-80 sm:w-96 h-[32rem] mb-4 flex flex-col shadow-2xl border-gray-200 dark:border-gray-800 animate-in slide-in-from-bottom-4 fade-in overflow-hidden", children: [jsxs(CardHeader, { className: cn("bg-primary-600 dark:bg-primary-700 text-white p-4 flex flex-row items-center justify-between rounded-none rounded-t-lg", headerClassName), children: [jsxs("div", { className: "flex items-center space-x-3", children: [jsx(Avatar, { size: "sm", className: "border border-white/20", children: jsx(AvatarFallback, { className: "bg-black/20 text-white", children: jsx(Bot, { size: 16 }) }) }), jsxs("div", { children: [jsx(CardTitle, { className: "text-white text-base font-semibold", children: title }), jsx("p", { className: "text-white/80 text-xs font-normal", children: subtitle })] })] }), jsx(Button, { variant: "ghost", size: "sm", className: "text-white hover:bg-black/20 hover:text-white rounded-full p-2 h-8 w-8", onClick: () => setIsOpen(false), children: jsx(X, { size: 16 }) })] }), jsxs(CardContent, { className: "flex-1 overflow-y-auto p-4 space-y-4 bg-gray-50 dark:bg-gray-900/50", children: [displayMessages.map((msg) => {
76
89
  const isUser = msg.sender === "user";
77
90
  return (jsx("div", { className: cn("flex", isUser ? "justify-end" : "justify-start"), children: jsx("div", { className: cn("max-w-[85%] rounded-2xl px-4 py-2.5 text-sm", isUser
78
91
  ? cn("bg-primary-600 text-white rounded-tr-sm", userMessageClassName)
@@ -1 +1 @@
1
- {"version":3,"file":"ChatWidget.js","sources":["../../../src/components/ChatWidget/ChatWidget.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useState, useRef, useEffect } from \"react\";\nimport { MessageCircle, X, Send, Bot } from \"lucide-react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button\";\nimport { Input } from \"../Input\";\nimport { Card, CardHeader, CardTitle, CardContent } from \"../Card\";\nimport { Avatar, AvatarFallback } from \"../Avatar\";\n\nconst chatWidgetVariants = cva(\n \"z-50 flex flex-col transition-all duration-300 ease-in-out\",\n {\n variants: {\n position: {\n \"bottom-right\": \"bottom-4 right-4 items-end\",\n \"bottom-left\": \"bottom-4 left-4 items-start\",\n },\n strategy: {\n fixed: \"fixed\",\n absolute: \"absolute\",\n },\n },\n defaultVariants: {\n position: \"bottom-right\",\n strategy: \"fixed\",\n },\n }\n);\n\nexport interface Message {\n id: string;\n content: string;\n sender: \"user\" | \"agent\" | \"ai\";\n timestamp: Date;\n}\n\nexport interface ChatWidgetProps extends VariantProps<typeof chatWidgetVariants> {\n className?: string;\n title?: string;\n subtitle?: string;\n greeting?: string;\n onSendMessage?: (message: string) => Promise<void> | void;\n headerClassName?: string;\n triggerButtonClassName?: string;\n userMessageClassName?: string;\n}\n\nexport const ChatWidget: React.FC<ChatWidgetProps> = ({\n className,\n position,\n strategy,\n title = \"Support\",\n subtitle = \"We typically reply in a few minutes\",\n greeting = \"Hello! How can we help you today?\",\n onSendMessage,\n headerClassName,\n triggerButtonClassName,\n userMessageClassName,\n}) => {\n const [isOpen, setIsOpen] = useState(false);\n const [inputValue, setInputValue] = useState(\"\");\n const [isTyping, setIsTyping] = useState(false);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n const [messages, setMessages] = useState<Message[]>([\n { id: \"1\", content: greeting, sender: \"ai\", timestamp: new Date() },\n ]);\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n };\n\n useEffect(() => {\n if (isOpen) {\n scrollToBottom();\n }\n }, [isOpen, messages, isTyping]);\n\n const handleSend = async () => {\n if (!inputValue.trim()) return;\n\n const newUserMessage: Message = {\n id: Date.now().toString(),\n content: inputValue,\n sender: \"user\",\n timestamp: new Date(),\n };\n\n setMessages((prev) => [...prev, newUserMessage]);\n setInputValue(\"\");\n setIsTyping(true);\n\n if (onSendMessage) {\n await onSendMessage(newUserMessage.content);\n setIsTyping(false);\n } else {\n // Default fallback mock response\n setTimeout(() => {\n setMessages((prev) => [\n ...prev,\n {\n id: (Date.now() + 1).toString(),\n content: \"Thanks for reaching out! A representative will be with you shortly.\",\n sender: \"ai\",\n timestamp: new Date(),\n },\n ]);\n setIsTyping(false);\n }, 1500);\n }\n };\n\n return (\n <div className={cn(chatWidgetVariants({ position, strategy }), className)}>\n {/* Chat Window */}\n {isOpen && (\n <Card className=\"w-80 sm:w-96 h-[32rem] mb-4 flex flex-col shadow-2xl border-gray-200 dark:border-gray-800 animate-in slide-in-from-bottom-4 fade-in overflow-hidden\">\n <CardHeader className={cn(\"bg-primary-600 dark:bg-primary-700 text-white p-4 flex flex-row items-center justify-between rounded-none rounded-t-lg\", headerClassName)}>\n <div className=\"flex items-center space-x-3\">\n <Avatar size=\"sm\" className=\"border border-white/20\">\n <AvatarFallback className=\"bg-black/20 text-white\">\n <Bot size={16} />\n </AvatarFallback>\n </Avatar>\n <div>\n <CardTitle className=\"text-white text-base font-semibold\">{title}</CardTitle>\n <p className=\"text-white/80 text-xs font-normal\">{subtitle}</p>\n </div>\n </div>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-white hover:bg-black/20 hover:text-white rounded-full p-2 h-8 w-8\"\n onClick={() => setIsOpen(false)}\n >\n <X size={16} />\n </Button>\n </CardHeader>\n\n <CardContent className=\"flex-1 overflow-y-auto p-4 space-y-4 bg-gray-50 dark:bg-gray-900/50\">\n {messages.map((msg) => {\n const isUser = msg.sender === \"user\";\n return (\n <div key={msg.id} className={cn(\"flex\", isUser ? \"justify-end\" : \"justify-start\")}>\n <div\n className={cn(\n \"max-w-[85%] rounded-2xl px-4 py-2.5 text-sm\",\n isUser\n ? cn(\"bg-primary-600 text-white rounded-tr-sm\", userMessageClassName)\n : \"bg-white dark:bg-gray-800 border border-gray-100 dark:border-gray-700 text-gray-900 dark:text-gray-100 rounded-tl-sm shadow-sm\"\n )}\n >\n {msg.content}\n </div>\n </div>\n );\n })}\n {isTyping && (\n <div className=\"flex justify-start\">\n <div className=\"bg-white dark:bg-gray-800 border border-gray-100 dark:border-gray-700 rounded-2xl rounded-tl-sm px-4 py-3.5 shadow-sm flex space-x-1.5 items-center\">\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: \"0ms\" }} />\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: \"150ms\" }} />\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: \"300ms\" }} />\n </div>\n </div>\n )}\n <div ref={messagesEndRef} />\n </CardContent>\n\n <div className=\"p-3 bg-white dark:bg-gray-900 border-t border-gray-100 dark:border-gray-800\">\n <form onSubmit={(e) => { e.preventDefault(); handleSend(); }} className=\"flex items-center space-x-2\">\n <Input value={inputValue} onChange={(e) => setInputValue(e.target.value)} placeholder=\"Type your message...\" className=\"flex-1\" />\n <Button type=\"submit\" variant=\"primary\" size=\"sm\" disabled={!inputValue.trim()} className=\"h-10 w-10 p-0 rounded-full flex-shrink-0\">\n <Send size={16} className=\"ml-1\" />\n </Button>\n </form>\n </div>\n </Card>\n )}\n\n {/* Floating Toggle Button */}\n <Button onClick={() => setIsOpen(!isOpen)} className={cn(\"h-14 w-14 rounded-full shadow-lg hover:shadow-xl bg-primary-600 hover:bg-primary-700 text-white transition-transform hover:scale-105 flex items-center justify-center p-0\", triggerButtonClassName)}>\n {isOpen ? <X size={24} /> : <MessageCircle size={24} />}\n </Button>\n </div>\n );\n};"],"names":["_jsxs","_jsx"],"mappings":";;;;;;;;;;AAUA,MAAM,kBAAkB,GAAG,GAAG,CAC5B,4DAA4D,EAC5D;AACE,IAAA,QAAQ,EAAE;AACR,QAAA,QAAQ,EAAE;AACR,YAAA,cAAc,EAAE,4BAA4B;AAC5C,YAAA,aAAa,EAAE,6BAA6B;AAC7C,SAAA;AACD,QAAA,QAAQ,EAAE;AACR,YAAA,KAAK,EAAE,OAAO;AACd,YAAA,QAAQ,EAAE,UAAU;AACrB,SAAA;AACF,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,QAAQ,EAAE,cAAc;AACxB,QAAA,QAAQ,EAAE,OAAO;AAClB,KAAA;AACF,CAAA,CACF;AAoBM,MAAM,UAAU,GAA8B,CAAC,EACpD,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,KAAK,GAAG,SAAS,EACjB,QAAQ,GAAG,qCAAqC,EAChD,QAAQ,GAAG,mCAAmC,EAC9C,aAAa,EACb,eAAe,EACf,sBAAsB,EACtB,oBAAoB,GACrB,KAAI;IACH,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC3C,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC;IAChD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;AAC/C,IAAA,MAAM,cAAc,GAAG,MAAM,CAAiB,IAAI,CAAC;AAEnD,IAAA,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAY;AAClD,QAAA,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE;AACpE,KAAA,CAAC;IAEF,MAAM,cAAc,GAAG,MAAK;QAC1B,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAChE,IAAA,CAAC;IAED,SAAS,CAAC,MAAK;QACb,IAAI,MAAM,EAAE;AACV,YAAA,cAAc,EAAE;QAClB;IACF,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAEhC,IAAA,MAAM,UAAU,GAAG,YAAW;AAC5B,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;YAAE;AAExB,QAAA,MAAM,cAAc,GAAY;AAC9B,YAAA,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;AACzB,YAAA,OAAO,EAAE,UAAU;AACnB,YAAA,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB;AAED,QAAA,WAAW,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,cAAc,CAAC,CAAC;QAChD,aAAa,CAAC,EAAE,CAAC;QACjB,WAAW,CAAC,IAAI,CAAC;QAEjB,IAAI,aAAa,EAAE;AACjB,YAAA,MAAM,aAAa,CAAC,cAAc,CAAC,OAAO,CAAC;YAC3C,WAAW,CAAC,KAAK,CAAC;QACpB;aAAO;;YAEL,UAAU,CAAC,MAAK;AACd,gBAAA,WAAW,CAAC,CAAC,IAAI,KAAK;AACpB,oBAAA,GAAG,IAAI;AACP,oBAAA;wBACE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE;AAC/B,wBAAA,OAAO,EAAE,qEAAqE;AAC9E,wBAAA,MAAM,EAAE,IAAI;wBACZ,SAAS,EAAE,IAAI,IAAI,EAAE;AACtB,qBAAA;AACF,iBAAA,CAAC;gBACF,WAAW,CAAC,KAAK,CAAC;YACpB,CAAC,EAAE,IAAI,CAAC;QACV;AACF,IAAA,CAAC;AAED,IAAA,QACEA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,EAAE,CAAC,kBAAkB,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,CAAC,EAAA,QAAA,EAAA,CAEtE,MAAM,KACLA,IAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,qJAAqJ,EAAA,QAAA,EAAA,CACnKA,IAAA,CAAC,UAAU,EAAA,EAAC,SAAS,EAAE,EAAE,CAAC,wHAAwH,EAAE,eAAe,CAAC,EAAA,QAAA,EAAA,CAClKA,cAAK,SAAS,EAAC,6BAA6B,EAAA,QAAA,EAAA,CAC1CC,GAAA,CAAC,MAAM,EAAA,EAAC,IAAI,EAAC,IAAI,EAAC,SAAS,EAAC,wBAAwB,EAAA,QAAA,EAClDA,GAAA,CAAC,cAAc,IAAC,SAAS,EAAC,wBAAwB,EAAA,QAAA,EAChDA,IAAC,GAAG,EAAA,EAAC,IAAI,EAAE,EAAE,EAAA,CAAI,EAAA,CACF,EAAA,CACV,EACTD,IAAA,CAAA,KAAA,EAAA,EAAA,QAAA,EAAA,CACEC,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAC,oCAAoC,EAAA,QAAA,EAAE,KAAK,EAAA,CAAa,EAC7EA,GAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAC,mCAAmC,EAAA,QAAA,EAAE,QAAQ,EAAA,CAAK,CAAA,EAAA,CAC3D,CAAA,EAAA,CACF,EACNA,GAAA,CAAC,MAAM,EAAA,EACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,IAAI,EACT,SAAS,EAAC,wEAAwE,EAClF,OAAO,EAAE,MAAM,SAAS,CAAC,KAAK,CAAC,EAAA,QAAA,EAE/BA,GAAA,CAAC,CAAC,EAAA,EAAC,IAAI,EAAE,EAAE,EAAA,CAAI,EAAA,CACR,CAAA,EAAA,CACE,EAEbD,IAAA,CAAC,WAAW,EAAA,EAAC,SAAS,EAAC,qEAAqE,EAAA,QAAA,EAAA,CACzF,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,KAAI;AACpB,gCAAA,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,KAAK,MAAM;gCACpC,QACEC,GAAA,CAAA,KAAA,EAAA,EAAkB,SAAS,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,eAAe,CAAC,EAAA,QAAA,EAC/EA,GAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAE,EAAE,CACX,6CAA6C,EAC7C;AACE,8CAAE,EAAE,CAAC,yCAAyC,EAAE,oBAAoB;AACpE,8CAAE,gIAAgI,CACrI,EAAA,QAAA,EAEA,GAAG,CAAC,OAAO,EAAA,CACR,EAAA,EAVE,GAAG,CAAC,EAAE,CAWV;4BAEV,CAAC,CAAC,EACD,QAAQ,KACPA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,oBAAoB,EAAA,QAAA,EACjCD,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,qJAAqJ,EAAA,QAAA,EAAA,CAClKC,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,qDAAqD,EAAC,KAAK,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,EAAA,CAAI,EACzGA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,qDAAqD,EAAC,KAAK,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,EAAA,CAAI,EAC3GA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,qDAAqD,EAAC,KAAK,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,EAAA,CAAI,CAAA,EAAA,CACvG,EAAA,CACF,CACP,EACDA,aAAK,GAAG,EAAE,cAAc,EAAA,CAAI,CAAA,EAAA,CAChB,EAEdA,aAAK,SAAS,EAAC,6EAA6E,EAAA,QAAA,EAC1FD,IAAA,CAAA,MAAA,EAAA,EAAM,QAAQ,EAAE,CAAC,CAAC,KAAI,EAAG,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAC,6BAA6B,aACnGC,GAAA,CAAC,KAAK,EAAA,EAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,WAAW,EAAC,sBAAsB,EAAC,SAAS,EAAC,QAAQ,EAAA,CAAG,EAClIA,GAAA,CAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,SAAS,EAAC,IAAI,EAAC,IAAI,EAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,SAAS,EAAC,0CAA0C,EAAA,QAAA,EAClIA,GAAA,CAAC,IAAI,EAAA,EAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAC,MAAM,GAAG,EAAA,CAC5B,CAAA,EAAA,CACJ,EAAA,CACH,CAAA,EAAA,CACD,CACR,EAGDA,IAAC,MAAM,EAAA,EAAC,OAAO,EAAE,MAAM,SAAS,CAAC,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,2KAA2K,EAAE,sBAAsB,CAAC,EAAA,QAAA,EAC1P,MAAM,GAAGA,GAAA,CAAC,CAAC,EAAA,EAAC,IAAI,EAAE,EAAE,EAAA,CAAI,GAAGA,GAAA,CAAC,aAAa,EAAA,EAAC,IAAI,EAAE,EAAE,EAAA,CAAI,EAAA,CAChD,CAAA,EAAA,CACL;AAEV;;;;"}
1
+ {"version":3,"file":"ChatWidget.js","sources":["../../../src/components/ChatWidget/ChatWidget.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useState, useRef, useEffect } from \"react\";\nimport { MessageCircle, X, Send, Bot } from \"lucide-react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button\";\nimport { Input } from \"../Input\";\nimport { Card, CardHeader, CardTitle, CardContent } from \"../Card\";\nimport { Avatar, AvatarFallback } from \"../Avatar\";\n\nconst chatWidgetVariants = cva(\n \"z-50 flex flex-col transition-all duration-300 ease-in-out\",\n {\n variants: {\n position: {\n \"bottom-right\": \"bottom-4 right-4 items-end\",\n \"bottom-left\": \"bottom-4 left-4 items-start\",\n },\n strategy: {\n fixed: \"fixed\",\n absolute: \"absolute\",\n },\n },\n defaultVariants: {\n position: \"bottom-right\",\n strategy: \"fixed\",\n },\n }\n);\n\nexport interface Message {\n id: string;\n content: string;\n sender: \"user\" | \"agent\" | \"ai\";\n timestamp: Date;\n}\n\nexport interface ChatWidgetProps extends VariantProps<typeof chatWidgetVariants> {\n className?: string;\n title?: string;\n subtitle?: string;\n greeting?: string;\n messages?: Message[];\n onSendMessage?: (message: string) => Promise<void> | void;\n headerClassName?: string;\n triggerButtonClassName?: string;\n userMessageClassName?: string;\n defaultOpen?: boolean;\n}\n\nexport const ChatWidget: React.FC<ChatWidgetProps> = ({\n className,\n position,\n strategy,\n title = \"Support\",\n subtitle = \"We typically reply in a few minutes\",\n greeting = \"Hello! How can we help you today?\",\n messages: externalMessages,\n onSendMessage,\n headerClassName,\n triggerButtonClassName,\n userMessageClassName,\n defaultOpen = false,\n}) => {\n const [isOpen, setIsOpen] = useState(defaultOpen);\n const [inputValue, setInputValue] = useState(\"\");\n const [isTyping, setIsTyping] = useState(false);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n const [messages, setMessages] = useState<Message[]>([\n { id: \"1\", content: greeting, sender: \"ai\", timestamp: new Date() },\n ]);\n\n const displayMessages = externalMessages || messages;\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n };\n\n useEffect(() => {\n if (isOpen) {\n scrollToBottom();\n }\n }, [isOpen, displayMessages, isTyping]);\n\n const handleSend = async () => {\n if (!inputValue.trim()) return;\n\n const messageContent = inputValue;\n setInputValue(\"\");\n \n if (externalMessages && onSendMessage) {\n setIsTyping(true);\n try {\n await onSendMessage(messageContent);\n } catch (err) {\n console.error(\"ChatWidget: error sending message\", err);\n }\n setIsTyping(false);\n } else {\n const newUserMessage: Message = {\n id: Date.now().toString(),\n content: messageContent,\n sender: \"user\",\n timestamp: new Date(),\n };\n setMessages((prev) => [...prev, newUserMessage]);\n setIsTyping(true);\n if (onSendMessage) {\n await onSendMessage(messageContent);\n setIsTyping(false);\n } else {\n setTimeout(() => {\n setMessages((prev) => [\n ...prev,\n {\n id: (Date.now() + 1).toString(),\n content: \"Thanks for reaching out! A representative will be with you shortly.\",\n sender: \"ai\",\n timestamp: new Date(),\n },\n ]);\n setIsTyping(false);\n }, 1500);\n }\n }\n };\n\n return (\n <div className={cn(chatWidgetVariants({ position, strategy }), className)}>\n {/* Chat Window */}\n {isOpen && (\n <Card className=\"w-80 sm:w-96 h-[32rem] mb-4 flex flex-col shadow-2xl border-gray-200 dark:border-gray-800 animate-in slide-in-from-bottom-4 fade-in overflow-hidden\">\n <CardHeader className={cn(\"bg-primary-600 dark:bg-primary-700 text-white p-4 flex flex-row items-center justify-between rounded-none rounded-t-lg\", headerClassName)}>\n <div className=\"flex items-center space-x-3\">\n <Avatar size=\"sm\" className=\"border border-white/20\">\n <AvatarFallback className=\"bg-black/20 text-white\">\n <Bot size={16} />\n </AvatarFallback>\n </Avatar>\n <div>\n <CardTitle className=\"text-white text-base font-semibold\">{title}</CardTitle>\n <p className=\"text-white/80 text-xs font-normal\">{subtitle}</p>\n </div>\n </div>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"text-white hover:bg-black/20 hover:text-white rounded-full p-2 h-8 w-8\"\n onClick={() => setIsOpen(false)}\n >\n <X size={16} />\n </Button>\n </CardHeader>\n\n <CardContent className=\"flex-1 overflow-y-auto p-4 space-y-4 bg-gray-50 dark:bg-gray-900/50\">\n {displayMessages.map((msg) => {\n const isUser = msg.sender === \"user\";\n return (\n <div key={msg.id} className={cn(\"flex\", isUser ? \"justify-end\" : \"justify-start\")}>\n <div\n className={cn(\n \"max-w-[85%] rounded-2xl px-4 py-2.5 text-sm\",\n isUser\n ? cn(\"bg-primary-600 text-white rounded-tr-sm\", userMessageClassName)\n : \"bg-white dark:bg-gray-800 border border-gray-100 dark:border-gray-700 text-gray-900 dark:text-gray-100 rounded-tl-sm shadow-sm\"\n )}\n >\n {msg.content}\n </div>\n </div>\n );\n })}\n {isTyping && (\n <div className=\"flex justify-start\">\n <div className=\"bg-white dark:bg-gray-800 border border-gray-100 dark:border-gray-700 rounded-2xl rounded-tl-sm px-4 py-3.5 shadow-sm flex space-x-1.5 items-center\">\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: \"0ms\" }} />\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: \"150ms\" }} />\n <div className=\"w-1.5 h-1.5 bg-gray-400 rounded-full animate-bounce\" style={{ animationDelay: \"300ms\" }} />\n </div>\n </div>\n )}\n <div ref={messagesEndRef} />\n </CardContent>\n\n <div className=\"p-3 bg-white dark:bg-gray-900 border-t border-gray-100 dark:border-gray-800\">\n <form onSubmit={(e) => { e.preventDefault(); handleSend(); }} className=\"flex items-center space-x-2\">\n <Input value={inputValue} onChange={(e) => setInputValue(e.target.value)} placeholder=\"Type your message...\" className=\"flex-1\" />\n <Button type=\"submit\" variant=\"primary\" size=\"sm\" disabled={!inputValue.trim()} className=\"h-10 w-10 p-0 rounded-full flex-shrink-0\">\n <Send size={16} className=\"ml-1\" />\n </Button>\n </form>\n </div>\n </Card>\n )}\n\n {/* Floating Toggle Button */}\n <Button onClick={() => setIsOpen(!isOpen)} className={cn(\"h-14 w-14 rounded-full shadow-lg hover:shadow-xl bg-primary-600 hover:bg-primary-700 text-white transition-transform hover:scale-105 flex items-center justify-center p-0\", triggerButtonClassName)}>\n {isOpen ? <X size={24} /> : <MessageCircle size={24} />}\n </Button>\n </div>\n );\n};"],"names":["_jsxs","_jsx"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beyondcorp/beyond-ui",
3
- "version": "1.3.02",
3
+ "version": "1.3.06",
4
4
  "description": "A comprehensive React UI component library built with TypeScript, TailwindCSS, and CVA",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",