react-sigma-chatbox 1.0.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/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # React Sigma Chatbox ✨
2
+
3
+ A high-performance, modern React Chatbox UI library inspired by the Bitu AI assistant (FPT Shop). It features a sleek design, support for product carousels, quick replies, and built-in compatibility with the Gemini AI streaming API.
4
+
5
+ ---
6
+
7
+ ## 🚀 Development Setup
8
+
9
+ If you have cloned this repository and want to run the demo or continue development:
10
+
11
+ 1. **Install dependencies:**
12
+ ```bash
13
+ npm install
14
+ ```
15
+
16
+ 2. **Run the development server:**
17
+ ```bash
18
+ npm run dev
19
+ ```
20
+ The demo application will be available at `http://localhost:5173`.
21
+
22
+ 3. **Build the library:**
23
+ ```bash
24
+ npm run build
25
+ ```
26
+ This generates the `dist` folder containing the compiled library (`index.mjs`, `index.js`) and the bundled CSS (`react-sigma-chatbox.css`).
27
+
28
+ ---
29
+
30
+ ## 📦 Integrating into Another Local Project
31
+
32
+ ### 1. Link or Copy the Library
33
+ You can use the library in your other local projects before it's published to NPM:
34
+
35
+ **Option A: NPM Link**
36
+ 1. In the `react-sigma-chatbox` directory: `npm link`
37
+ 2. In your target project directory: `npm link react-sigma-chatbox`
38
+
39
+ **Option B: Manual Copy**
40
+ Copy the `dist` folder directly into your project and import from it.
41
+
42
+ ### 2. Tailwind CSS Configuration
43
+ To ensure the chatbox styles are correctly applied in your target project, update your `tailwind.config.js`:
44
+
45
+ ```javascript
46
+ /** @type {import('tailwindcss').Config} */
47
+ export default {
48
+ content: [
49
+ "./src/**/*.{js,ts,jsx,tsx}",
50
+ "./node_modules/react-sigma-chatbox/**/*.{js,ts,jsx,tsx}",
51
+ ],
52
+ theme: {
53
+ extend: {},
54
+ },
55
+ plugins: [],
56
+ }
57
+ ```
58
+
59
+ ### 3. Import Styles
60
+ Import the library's stylesheet in your entry file (e.g., `main.tsx` or `App.tsx`):
61
+ ```typescript
62
+ import 'react-sigma-chatbox/dist/react-sigma-chatbox.css';
63
+ ```
64
+
65
+ ---
66
+
67
+ ## 🛠 Basic & Streaming Usage
68
+
69
+ The `Chatbox` component is highly flexible and handles logic through a `threadId` (unique session ID) and a `language` parameter (en, vi, ja). Both change or get passed whenever the user interacts with the UI.
70
+
71
+ ### Option 1: Standard Text Response (Plain Text or Markdown)
72
+ You can choose to render responses as plain text (default) or basic Markdown (Bold, Lists, etc.).
73
+
74
+ ```tsx
75
+ import { Language } from 'react-sigma-chatbox';
76
+
77
+ const config = {
78
+ // ... other config
79
+ renderMarkdown: true // Set to true to enable Markdown rendering
80
+ };
81
+
82
+ // Handler now receives (userInput, threadId, language)
83
+ const handleSimpleAi = async (userInput: string, threadId: string, language: Language) => {
84
+ console.log(`Session ID: ${threadId}, Selected Language: ${language}`);
85
+
86
+ if (language === 'vi') {
87
+ return "Xin chào! Tôi là **trợ lý AI**. Tôi có thể giúp gì cho bạn?";
88
+ }
89
+ return "Hello! I am your **AI assistant**. How can I help you today?";
90
+ };
91
+
92
+ <Chatbox onGetAiResponse={handleSimpleAi} config={config} />
93
+ ```
94
+
95
+ ### Option 2: Streaming Response (Async Generator)
96
+ Use this for real-time "typing" effects.
97
+
98
+ ```tsx
99
+ async function* handleStreamingAi(userInput: string, threadId: string, language: Language) {
100
+ const chunks = language === 'ja'
101
+ ? ["こんにちは!", "私は **Sigma AI** です。", "何かお手伝いしましょうか?"]
102
+ : ["Hello! ", "I am **Sigma AI**. ", "How can I help?"];
103
+
104
+ for (const chunk of chunks) {
105
+ await new Promise(r => setTimeout(r, 150));
106
+ yield chunk;
107
+ }
108
+ }
109
+
110
+ <Chatbox onGetAiResponse={handleStreamingAi} config={config} />
111
+ ```
112
+
113
+ ### Option 3: Product Carousel Response
114
+ You can return an object containing products to show a carousel.
115
+ ```tsx
116
+ const handleProductSearch = async (userInput: string, threadId: string, language: Language) => {
117
+ return {
118
+ text: language === 'vi' ? "Xem các mẫu **iPhone** mới nhất:" : "Check out our latest **iPhone** models:",
119
+ products: [
120
+ {
121
+ id: 'ip15',
122
+ name: 'iPhone 15 Pro Max',
123
+ price: '29.990.000₫',
124
+ image: 'https://fptshop.com.vn/img/products/iphone-15-pro-max.png',
125
+ description: 'The ultimate iPhone.'
126
+ }
127
+ ]
128
+ };
129
+ };
130
+ ```
131
+
132
+ ---
133
+
134
+ ## ⚙️ Component Configuration
135
+
136
+ ### Chatbox Props
137
+ | Prop | Type | Description |
138
+ | :--- | :--- | :--- |
139
+ | `config` | `ChatboxConfig` | Object containing UI branding and initial messages. |
140
+ | `onGetAiResponse` | `AiResponseHandler` | Logic handler receiving `(userInput, threadId, language)`. |
141
+
142
+ ### ChatboxConfig Fields
143
+ | Field | Type | Description |
144
+ | :--- | :--- | :--- |
145
+ | `primaryColor` | `string` | Hex color used for accents and user bubbles. |
146
+ | `botName` | `string` | The display name shown in the header. |
147
+ | `welcomeMessage` | `string` | Initial message sent by the bot. |
148
+ | `placeholder` | `string` | Input field placeholder. |
149
+ | `avatarUrl` | `string` | URL for the bot icon. |
150
+ | `quickReplies` | `string[]` | One-tap answer buttons. |
151
+ | `renderMarkdown` | `boolean` | Enable Markdown support for AI messages. |
152
+
153
+ ---
154
+
155
+ ## 📄 License
156
+ MIT
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import { Language } from '../../types';
3
+ interface ChatHeaderProps {
4
+ title: string;
5
+ primaryColor: string;
6
+ onClose: () => void;
7
+ onReset: () => void;
8
+ onToggleExpand: () => void;
9
+ isExpanded: boolean;
10
+ language: Language;
11
+ onLanguageChange: (lang: Language) => void;
12
+ }
13
+ export declare const ChatHeader: React.FC<ChatHeaderProps>;
14
+ export {};
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ interface ChatInputProps {
3
+ placeholder: string;
4
+ onSendMessage: (text: string) => void;
5
+ primaryColor: string;
6
+ }
7
+ export declare const ChatInput: React.FC<ChatInputProps>;
8
+ export {};
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { Message } from '../../types';
3
+ interface ChatMessagesProps {
4
+ messages: Message[];
5
+ isLoading: boolean;
6
+ quickReplies: string[];
7
+ onQuickReply: (reply: string) => void;
8
+ primaryColor: string;
9
+ renderMarkdown?: boolean;
10
+ }
11
+ export declare const ChatMessages: React.FC<ChatMessagesProps>;
12
+ export {};
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { ChatboxConfig, AiResponseHandler } from '../../types';
3
+ interface ChatboxProps {
4
+ config: ChatboxConfig;
5
+ onGetAiResponse: AiResponseHandler;
6
+ }
7
+ export declare const Chatbox: React.FC<ChatboxProps>;
8
+ export {};
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface FloatingButtonProps {
3
+ isOpen: boolean;
4
+ onClick: () => void;
5
+ primaryColor: string;
6
+ className?: string;
7
+ }
8
+ export declare const FloatingButton: React.FC<FloatingButtonProps>;
9
+ export {};
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { Product } from '../../types';
3
+ interface ProductCardProps {
4
+ product: Product;
5
+ primaryColor: string;
6
+ }
7
+ export declare const ProductCard: React.FC<ProductCardProps>;
8
+ export {};
@@ -0,0 +1,3 @@
1
+ import './style.css';
2
+ export * from './components/Chatbox/Chatbox';
3
+ export * from './types';
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ (function(N,f){typeof exports=="object"&&typeof module<"u"?f(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],f):(N=typeof globalThis<"u"?globalThis:N||self,f(N.ReactSigmaChatbox={},N.React))})(this,(function(N,f){"use strict";var U={exports:{}},P={};/**
2
+ * @license React
3
+ * react-jsx-runtime.production.js
4
+ *
5
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */var Q;function ae(){if(Q)return P;Q=1;var r=Symbol.for("react.transitional.element"),d=Symbol.for("react.fragment");function o(s,a,l){var m=null;if(l!==void 0&&(m=""+l),a.key!==void 0&&(m=""+a.key),"key"in a){l={};for(var i in a)i!=="key"&&(l[i]=a[i])}else l=a;return a=l.ref,{$$typeof:r,type:s,key:m,ref:a!==void 0?a:null,props:l}}return P.Fragment=d,P.jsx=o,P.jsxs=o,P}var M={};/**
10
+ * @license React
11
+ * react-jsx-runtime.development.js
12
+ *
13
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
14
+ *
15
+ * This source code is licensed under the MIT license found in the
16
+ * LICENSE file in the root directory of this source tree.
17
+ */var Z;function oe(){return Z||(Z=1,process.env.NODE_ENV!=="production"&&(function(){function r(t){if(t==null)return null;if(typeof t=="function")return t.$$typeof===A?null:t.displayName||t.name||null;if(typeof t=="string")return t;switch(t){case E:return"Fragment";case F:return"Profiler";case _:return"StrictMode";case D:return"Suspense";case J:return"SuspenseList";case T:return"Activity"}if(typeof t=="object")switch(typeof t.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),t.$$typeof){case R:return"Portal";case V:return t.displayName||"Context";case B:return(t._context.displayName||"Context")+".Consumer";case k:var n=t.render;return t=t.displayName,t||(t=n.displayName||n.name||"",t=t!==""?"ForwardRef("+t+")":"ForwardRef"),t;case w:return n=t.displayName||null,n!==null?n:r(t.type)||"Memo";case v:n=t._payload,t=t._init;try{return r(t(n))}catch{}}return null}function d(t){return""+t}function o(t){try{d(t);var n=!1}catch{n=!0}if(n){n=console;var u=n.error,h=typeof Symbol=="function"&&Symbol.toStringTag&&t[Symbol.toStringTag]||t.constructor.name||"Object";return u.call(n,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",h),d(t)}}function s(t){if(t===E)return"<>";if(typeof t=="object"&&t!==null&&t.$$typeof===v)return"<...>";try{var n=r(t);return n?"<"+n+">":"<...>"}catch{return"<...>"}}function a(){var t=W.A;return t===null?null:t.getOwner()}function l(){return Error("react-stack-top-frame")}function m(t){if(O.call(t,"key")){var n=Object.getOwnPropertyDescriptor(t,"key").get;if(n&&n.isReactWarning)return!1}return t.key!==void 0}function i(t,n){function u(){ee||(ee=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",n))}u.isReactWarning=!0,Object.defineProperty(t,"key",{get:u,configurable:!0})}function c(){var t=r(this.type);return te[t]||(te[t]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),t=this.props.ref,t!==void 0?t:null}function p(t,n,u,h,X,G){var x=u.ref;return t={$$typeof:C,type:t,key:n,props:u,_owner:h},(x!==void 0?x:null)!==null?Object.defineProperty(t,"ref",{enumerable:!1,get:c}):Object.defineProperty(t,"ref",{enumerable:!1,value:null}),t._store={},Object.defineProperty(t._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(t,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(t,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:X}),Object.defineProperty(t,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:G}),Object.freeze&&(Object.freeze(t.props),Object.freeze(t)),t}function b(t,n,u,h,X,G){var x=n.children;if(x!==void 0)if(h)if(Y(x)){for(h=0;h<x.length;h++)S(x[h]);Object.freeze&&Object.freeze(x)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else S(x);if(O.call(n,"key")){x=r(t);var I=Object.keys(n).filter(function(fe){return fe!=="key"});h=0<I.length?"{key: someKey, "+I.join(": ..., ")+": ...}":"{key: someKey}",se[x+h]||(I=0<I.length?"{"+I.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
18
+ let props = %s;
19
+ <%s {...props} />
20
+ React keys must be passed directly to JSX without using spread:
21
+ let props = %s;
22
+ <%s key={someKey} {...props} />`,h,x,I,x),se[x+h]=!0)}if(x=null,u!==void 0&&(o(u),x=""+u),m(n)&&(o(n.key),x=""+n.key),"key"in n){u={};for(var $ in n)$!=="key"&&(u[$]=n[$])}else u=n;return x&&i(u,typeof t=="function"?t.displayName||t.name||"Unknown":t),p(t,x,u,a(),X,G)}function S(t){L(t)?t._store&&(t._store.validated=1):typeof t=="object"&&t!==null&&t.$$typeof===v&&(t._payload.status==="fulfilled"?L(t._payload.value)&&t._payload.value._store&&(t._payload.value._store.validated=1):t._store&&(t._store.validated=1))}function L(t){return typeof t=="object"&&t!==null&&t.$$typeof===C}var j=f,C=Symbol.for("react.transitional.element"),R=Symbol.for("react.portal"),E=Symbol.for("react.fragment"),_=Symbol.for("react.strict_mode"),F=Symbol.for("react.profiler"),B=Symbol.for("react.consumer"),V=Symbol.for("react.context"),k=Symbol.for("react.forward_ref"),D=Symbol.for("react.suspense"),J=Symbol.for("react.suspense_list"),w=Symbol.for("react.memo"),v=Symbol.for("react.lazy"),T=Symbol.for("react.activity"),A=Symbol.for("react.client.reference"),W=j.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,O=Object.prototype.hasOwnProperty,Y=Array.isArray,H=console.createTask?console.createTask:function(){return null};j={react_stack_bottom_frame:function(t){return t()}};var ee,te={},re=j.react_stack_bottom_frame.bind(j,l)(),ne=H(s(l)),se={};M.Fragment=E,M.jsx=function(t,n,u){var h=1e4>W.recentlyCreatedOwnerStacks++;return b(t,n,u,!1,h?Error("react-stack-top-frame"):re,h?H(s(t)):ne)},M.jsxs=function(t,n,u){var h=1e4>W.recentlyCreatedOwnerStacks++;return b(t,n,u,!0,h?Error("react-stack-top-frame"):re,h?H(s(t)):ne)}})()),M}var K;function le(){return K||(K=1,process.env.NODE_ENV==="production"?U.exports=ae():U.exports=oe()),U.exports}var e=le(),y=(r=>(r.TEXT="text",r.PRODUCT_LIST="product_list",r.LOADING="loading",r))(y||{}),g=(r=>(r.USER="user",r.AI="ai",r))(g||{});const ie=({title:r,primaryColor:d,onClose:o,onReset:s,onToggleExpand:a,isExpanded:l,language:m,onLanguageChange:i})=>{const c=[{value:"en",label:"EN"},{value:"vi",label:"VI"},{value:"ja",label:"JA"}];return e.jsxs("div",{className:"px-4 py-3 flex items-center justify-between border-b border-red-50/50 sticky top-0 z-10 bg-[#fff1f2]/90 backdrop-blur-sm",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-8 h-8 rounded-full overflow-hidden bg-white p-0.5 shadow-sm",children:e.jsx("img",{src:"https://fptshop.com.vn/img/bitu/bitu-avatar.png",onError:p=>p.currentTarget.src="https://cdn-icons-png.flaticon.com/512/4712/4712035.png",className:"w-full h-full object-contain",alt:"Bot Icon"})}),e.jsxs("div",{className:"flex flex-col",children:[e.jsxs("h3",{className:"font-bold text-[#1a2b56] text-[14px] leading-tight tracking-tight flex items-center gap-1",children:[r," ",e.jsx("span",{className:"text-red-400 text-[10px]",children:"✨"})]}),e.jsxs("span",{className:"text-[10px] text-green-500 font-medium flex items-center gap-1",children:[e.jsx("span",{className:"w-1.5 h-1.5 bg-green-500 rounded-full animate-pulse"}),"Online"]})]})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsxs("div",{className:"relative group mr-1",children:[e.jsx("select",{value:m,onChange:p=>i(p.target.value),className:"appearance-none bg-white/50 border border-gray-200 rounded-lg px-2 pr-5 py-1 text-[10px] font-black text-indigo-600 cursor-pointer hover:bg-white transition-all focus:outline-none focus:ring-2 focus:ring-indigo-100 uppercase",title:"Select language",children:c.map(p=>e.jsx("option",{value:p.value,className:"font-sans font-bold",children:p.label},p.value))}),e.jsx("div",{className:"absolute right-1.5 top-1/2 -translate-y-1/2 pointer-events-none text-indigo-400",children:e.jsx("svg",{width:"8",height:"8",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"4",strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("path",{d:"m6 9 6 6 6-6"})})})]}),e.jsx("button",{onClick:s,className:"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-white/60 text-gray-500 hover:text-indigo-600 transition-all",title:"Reset chat",children:e.jsxs("svg",{width:"15",height:"15",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"}),e.jsx("path",{d:"M21 3v5h-5"}),e.jsx("path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"}),e.jsx("path",{d:"M8 16H3v5"})]})}),e.jsx("button",{onClick:a,className:"w-8 h-8 hidden md:flex items-center justify-center rounded-lg hover:bg-white/60 text-gray-500 hover:text-indigo-600 transition-all",title:l?"Collapse":"Expand",children:l?e.jsxs("svg",{width:"15",height:"15",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("path",{d:"M4 14h6v6"}),e.jsx("path",{d:"M20 10h-6V4"}),e.jsx("path",{d:"M14 10l7-7"}),e.jsx("path",{d:"M10 14l-7 7"})]}):e.jsxs("svg",{width:"15",height:"15",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("path",{d:"M15 3h6v6"}),e.jsx("path",{d:"M9 21H3v-6"}),e.jsx("path",{d:"M21 3l-7 7"}),e.jsx("path",{d:"M3 21l7-7"})]})}),e.jsx("button",{onClick:o,className:"w-8 h-8 flex items-center justify-center rounded-lg hover:bg-red-50 text-gray-500 hover:text-red-500 transition-all",title:"Close",children:e.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("path",{d:"M18 6 6 18"}),e.jsx("path",{d:"M6 6l12 12"})]})})]})]})},ce=({product:r,primaryColor:d})=>e.jsxs("div",{className:"min-w-[170px] max-w-[170px] bg-white rounded-xl border border-gray-50 shadow-sm overflow-hidden flex flex-col hover:shadow-lg transition-all duration-300 group",children:[e.jsxs("div",{className:"relative h-32 w-full bg-white flex items-center justify-center p-2",children:[e.jsx("img",{src:r.image,alt:r.name,className:"h-full w-full object-contain group-hover:scale-105 transition-transform duration-500"}),r.discount&&e.jsx("div",{className:"absolute top-2 left-2 bg-red-600 text-white text-[9px] font-bold px-1.5 py-0.5 rounded-md shadow-sm",children:r.discount})]}),e.jsxs("div",{className:"p-3 flex-1 flex flex-col justify-between border-t border-gray-50",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"text-[11px] font-bold text-gray-800 line-clamp-2 min-h-[30px] mb-1.5 group-hover:text-red-600 transition-colors",children:r.name}),e.jsxs("div",{className:"mb-2",children:[e.jsx("span",{className:"text-red-600 font-extrabold text-[13px]",children:r.price}),r.oldPrice&&e.jsx("span",{className:"text-[10px] text-gray-400 line-through ml-1 block opacity-60",children:r.oldPrice})]})]}),e.jsx("button",{className:"w-full py-1.5 rounded-lg text-[11px] font-bold border transition-all duration-300 active:scale-95 shadow-sm",style:{borderColor:d,color:d},onMouseEnter:o=>{o.currentTarget.style.backgroundColor=d,o.currentTarget.style.color="white"},onMouseLeave:o=>{o.currentTarget.style.backgroundColor="transparent",o.currentTarget.style.color=d},children:"Chọn mua"})]})]}),z=r=>{const d=/(\*\*.*?\*\*|\[.*?\]\(.*?\))/g;return r.split(d).map((s,a)=>{if(s.startsWith("**")&&s.endsWith("**")){const m=s.slice(2,-2);return e.jsx("strong",{className:"font-bold text-gray-900",children:m},a)}const l=s.match(/\[(.*?)\]\((.*?)\)/);if(l){const[m,i,c]=l;return e.jsx("a",{href:c,target:"_blank",rel:"noopener noreferrer",className:"text-blue-600 hover:underline break-all font-semibold",children:i},a)}return s})},de=({text:r})=>{const d=r.split(`
23
+ `);return e.jsx("div",{className:"markdown-body space-y-1.5",children:d.map((o,s)=>{const a=o.trim(),l=a.match(/^(#{1,4})\s+(.*)$/);if(l){const i=l[1].length,c=l[2],p=i===1?"text-lg font-bold mb-3 mt-1":i===2?"text-md font-bold mb-2 mt-1":"text-[14px] font-bold mb-1.5 mt-0.5 text-gray-900 uppercase tracking-wide";return e.jsx("div",{className:p,children:z(c)},s)}const m=a.match(/^[*+-]\s+(.*)$/);if(m){const i=m[1];return e.jsxs("div",{className:"flex gap-2.5 pl-1 mb-2 items-start",children:[e.jsx("span",{className:"text-gray-400 flex-shrink-0 mt-1.5 w-1 h-1 bg-gray-400 rounded-full"}),e.jsx("div",{className:"flex-1 leading-relaxed text-gray-800",children:z(i)})]},s)}return a===""?e.jsx("div",{className:"h-3"},s):e.jsx("div",{className:"mb-1 leading-relaxed text-gray-800",children:z(o)},s)})})},ue=({messages:r,isLoading:d,quickReplies:o,onQuickReply:s,primaryColor:a,renderMarkdown:l=!1})=>{const m="https://fptshop.com.vn/img/bitu/bitu-avatar.png",i="https://cdn-icons-png.flaticon.com/512/4712/4712035.png";return e.jsxs("div",{className:"flex flex-col gap-8 pb-4",children:[e.jsxs("div",{className:"flex flex-col items-center justify-center py-8 text-center animate-msg",children:[e.jsx("div",{className:"relative mb-5",children:e.jsx("div",{className:"w-24 h-24 flex items-center justify-center",children:e.jsx("img",{src:m,onError:c=>c.currentTarget.src=i,className:"w-full h-full object-contain",alt:"Sigma AI Hero"})})}),e.jsxs("h2",{className:"text-xl font-bold text-[#1a2b56] flex items-center justify-center gap-1",children:["Sigma ",e.jsx("span",{className:"bg-indigo-600 text-white text-[10px] px-1.5 py-0.5 rounded-md leading-none ml-1 uppercase font-bold tracking-tight",children:"AI"})]}),e.jsxs("div",{className:"text-[14px] text-gray-600 mt-3 leading-relaxed px-4",children:[e.jsxs("p",{children:[e.jsx("span",{className:"font-bold text-gray-800",children:"Sigma Assistant"})," hỗ trợ bạn mọi lúc mọi nơi"]}),e.jsx("p",{children:"Tăng cường hiệu suất với AI thông minh"})]})]}),r.map((c,p)=>e.jsxs("div",{className:`flex flex-col animate-msg ${c.sender===g.USER?"items-end":"items-start"}`,style:{animationDelay:`${p*.05}s`},children:[c.sender===g.AI&&e.jsxs("div",{className:"flex items-center gap-1.5 mb-2 ml-1",children:[e.jsx("img",{src:m,onError:b=>b.currentTarget.src=i,className:"w-4 h-4 object-contain",alt:"AI"}),e.jsx("span",{className:"text-[11px] font-bold text-gray-400 uppercase tracking-widest",children:"AI Agent"})]}),e.jsxs("div",{className:`flex flex-col ${c.sender===g.USER?"items-end":"items-start"} max-w-[94%]`,children:[e.jsx("div",{className:`px-4 py-3 rounded-[18px] text-[14px] shadow-sm border border-black/[0.03] ${c.sender===g.USER?"bg-indigo-600 text-white rounded-tr-none whitespace-pre-line shadow-indigo-100":"bg-white text-gray-800 border-none rounded-tl-none"} ${!l||c.sender===g.USER?"whitespace-pre-line":""}`,children:l&&c.sender===g.AI?e.jsx(de,{text:c.content}):c.content}),c.type===y.PRODUCT_LIST&&c.products&&e.jsx("div",{className:"w-full mt-4 flex gap-4 overflow-x-auto pb-4 pt-1 no-scrollbar snap-x",children:c.products.map(b=>e.jsx("div",{className:"product-card-snap",children:e.jsx(ce,{product:b,primaryColor:a})},b.id))}),p===0&&r.length===1&&c.sender===g.AI&&e.jsx("div",{className:"mt-5 flex flex-wrap gap-2.5 w-full",children:o.map((b,S)=>e.jsx("button",{onClick:()=>s(b),className:"px-4 py-2 rounded-full text-[13px] font-semibold border border-transparent bg-white text-gray-600 hover:text-indigo-600 hover:border-indigo-100 transition-all duration-200 shadow-sm active:scale-95",children:b},S))})]})]},c.id)),d&&e.jsxs("div",{className:"flex flex-col gap-1.5 items-start animate-msg",children:[e.jsx("div",{className:"flex items-center gap-1.5 ml-1",children:e.jsx("img",{src:m,onError:c=>c.currentTarget.src=i,className:"w-4 h-4 object-contain",alt:"AI Loading"})}),e.jsxs("div",{className:"flex gap-1.5 bg-white px-4 py-3 rounded-[18px] rounded-tl-none border-none shadow-sm",children:[e.jsx("span",{className:"w-2 h-2 bg-indigo-300 rounded-full animate-sigma-bounce"}),e.jsx("span",{className:"w-2 h-2 bg-indigo-300 rounded-full animate-sigma-bounce [animation-delay:0.2s]"}),e.jsx("span",{className:"w-2 h-2 bg-indigo-300 rounded-full animate-sigma-bounce [animation-delay:0.4s]"})]})]})]})},me=({placeholder:r,onSendMessage:d,primaryColor:o})=>{const[s,a]=f.useState(""),l=()=>{s.trim()&&(d(s),a(""))},m=i=>{i.key==="Enter"&&!i.shiftKey&&(i.preventDefault(),l())};return e.jsx("div",{className:"p-1",children:e.jsxs("div",{className:"relative flex items-center bg-gray-50/50 rounded-2xl border border-gray-100 focus-within:border-indigo-100 focus-within:bg-white transition-all duration-200 pr-2 pl-3 py-1",children:[e.jsx("textarea",{value:s,onChange:i=>a(i.target.value),onKeyDown:m,placeholder:r,rows:1,className:"w-full bg-transparent border-none outline-none focus:ring-0 text-[14px] text-gray-700 font-normal py-3 px-1 resize-none chat-scrollbar min-h-[44px] max-h-[120px] leading-relaxed placeholder:text-gray-400",style:{fontWeight:400}}),e.jsx("button",{onClick:l,disabled:!s.trim(),className:`w-9 h-9 rounded-xl flex-shrink-0 flex items-center justify-center transition-all duration-300 shadow-sm ${s.trim()?"bg-indigo-600 text-white hover:bg-indigo-700 active:scale-95":"bg-gray-200 text-gray-400 cursor-not-allowed"}`,children:e.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("path",{d:"m5 12 7-7 7 7"}),e.jsx("path",{d:"M12 19V5"})]})})]})})},he=({isOpen:r,onClick:d,primaryColor:o,className:s=""})=>e.jsx("div",{className:`fixed bottom-4 right-4 md:bottom-6 md:right-6 z-[100] ${s}`,children:e.jsx("button",{onClick:d,className:`w-12 h-12 bg-white rounded-2xl shadow-lg flex items-center justify-center border transition-all duration-300 overflow-hidden ${r?"border-indigo-500 ring-4 ring-indigo-50 scale-105 rotate-0":"border-slate-100 hover:scale-110 hover:shadow-xl"}`,children:e.jsx("img",{src:"https://fptshop.com.vn/img/bitu/bitu-avatar.png",className:"w-10 h-10 object-contain",alt:"Bitu",onError:a=>a.currentTarget.src="https://cdn-icons-png.flaticon.com/512/4712/4712035.png"})})}),q=()=>Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15),xe=({config:r,onGetAiResponse:d})=>{const[o,s]=f.useState(!1),[a,l]=f.useState(!1),[m,i]=f.useState(!1),[c,p]=f.useState(q()),[b,S]=f.useState("en"),[L,j]=f.useState([{id:"welcome",type:y.TEXT,sender:g.AI,content:r.welcomeMessage,timestamp:new Date}]),[C,R]=f.useState(!1),E=f.useRef(null),_=f.useRef(0);f.useEffect(()=>{if(o){const k=setTimeout(()=>i(!0),50);return()=>clearTimeout(k)}else i(!1)},[o]),f.useEffect(()=>{E.current&&o&&(E.current.scrollTop=E.current.scrollHeight)},[L,o,C]);const F=async k=>{if(!k.trim()||C)return;const D=++_.current,J={id:`user-${Date.now()}`,type:y.TEXT,sender:g.USER,content:k,timestamp:new Date};j(w=>[...w,J]),R(!0);try{const w=d(k,c,b);if(w&&typeof w=="object"&&Symbol.asyncIterator in w){let v="",T=!1;const A=`ai-${Date.now()}`;for await(const W of w){if(D!==_.current)return;T||(j(O=>[...O,{id:A,type:y.TEXT,sender:g.AI,content:"",timestamp:new Date}]),R(!1),T=!0),v+=W,j(O=>O.map(Y=>Y.id===A?{...Y,content:v}:Y))}}else{const v=await w;if(D!==_.current)return;R(!1);const T=typeof v=="string"?{text:v,products:void 0}:v;j(A=>[...A,{id:`ai-${Date.now()}`,type:T.products?y.PRODUCT_LIST:y.TEXT,sender:g.AI,content:T.text,products:T.products,timestamp:new Date}])}}catch(w){if(D!==_.current)return;console.error("Chatbox Error:",w),R(!1),j(v=>[...v,{id:`err-${Date.now()}`,type:y.TEXT,sender:g.AI,content:"Hệ thống đang bận, vui lòng thử lại sau.",timestamp:new Date}])}},B=()=>{_.current++,p(q()),j([{id:"welcome",type:y.TEXT,sender:g.AI,content:r.welcomeMessage,timestamp:new Date}]),R(!1),l(!1)},V=`
24
+ fixed z-[99] overflow-hidden flex flex-col border border-white/40 shadow-2xl bg-white animate-chat-pop
25
+ ${m?"transition-[width,height,border-radius,right,bottom] duration-300 ease-in-out":""}
26
+ ${a?"bottom-0 right-0 w-full h-full md:bottom-6 md:right-28 md:w-[850px] md:h-[85vh] rounded-none md:rounded-[32px]":"bottom-0 right-0 w-full h-[80vh] md:bottom-6 md:right-28 md:w-[380px] md:h-[580px] rounded-t-[28px] md:rounded-[28px]"}
27
+ `;return e.jsxs(e.Fragment,{children:[e.jsx(he,{isOpen:o,onClick:()=>s(!o),primaryColor:r.primaryColor,className:o?"hidden md:flex":"flex"}),o&&e.jsxs("div",{className:V,style:{left:"auto"},children:[e.jsx(ie,{title:r.botName,primaryColor:r.primaryColor,onClose:()=>s(!1),onReset:B,onToggleExpand:()=>l(!a),isExpanded:a,language:b,onLanguageChange:S}),e.jsx("div",{className:"flex-1 overflow-y-auto chat-scrollbar px-5 py-5 bg-slate-50/30",ref:E,children:e.jsx(ue,{messages:L,isLoading:C,quickReplies:r.quickReplies,onQuickReply:k=>F(k),primaryColor:r.primaryColor,renderMarkdown:r.renderMarkdown})}),e.jsx("div",{className:"bg-white p-3 border-t border-slate-100",children:e.jsx(me,{placeholder:r.placeholder,onSendMessage:F,primaryColor:r.primaryColor})})]})]})};N.Chatbox=xe,N.MessageType=y,N.SenderType=g,Object.defineProperty(N,Symbol.toStringTag,{value:"Module"})}));
package/dist/index.mjs ADDED
@@ -0,0 +1,733 @@
1
+ import le, { useState as E, useRef as ee, useEffect as te } from "react";
2
+ var U = { exports: {} }, $ = {};
3
+ /**
4
+ * @license React
5
+ * react-jsx-runtime.production.js
6
+ *
7
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
8
+ *
9
+ * This source code is licensed under the MIT license found in the
10
+ * LICENSE file in the root directory of this source tree.
11
+ */
12
+ var re;
13
+ function ie() {
14
+ if (re) return $;
15
+ re = 1;
16
+ var r = Symbol.for("react.transitional.element"), d = Symbol.for("react.fragment");
17
+ function o(s, a, l) {
18
+ var m = null;
19
+ if (l !== void 0 && (m = "" + l), a.key !== void 0 && (m = "" + a.key), "key" in a) {
20
+ l = {};
21
+ for (var i in a)
22
+ i !== "key" && (l[i] = a[i]);
23
+ } else l = a;
24
+ return a = l.ref, {
25
+ $$typeof: r,
26
+ type: s,
27
+ key: m,
28
+ ref: a !== void 0 ? a : null,
29
+ props: l
30
+ };
31
+ }
32
+ return $.Fragment = d, $.jsx = o, $.jsxs = o, $;
33
+ }
34
+ var D = {};
35
+ /**
36
+ * @license React
37
+ * react-jsx-runtime.development.js
38
+ *
39
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
40
+ *
41
+ * This source code is licensed under the MIT license found in the
42
+ * LICENSE file in the root directory of this source tree.
43
+ */
44
+ var ne;
45
+ function ce() {
46
+ return ne || (ne = 1, process.env.NODE_ENV !== "production" && (function() {
47
+ function r(t) {
48
+ if (t == null) return null;
49
+ if (typeof t == "function")
50
+ return t.$$typeof === A ? null : t.displayName || t.name || null;
51
+ if (typeof t == "string") return t;
52
+ switch (t) {
53
+ case N:
54
+ return "Fragment";
55
+ case W:
56
+ return "Profiler";
57
+ case R:
58
+ return "StrictMode";
59
+ case P:
60
+ return "Suspense";
61
+ case X:
62
+ return "SuspenseList";
63
+ case k:
64
+ return "Activity";
65
+ }
66
+ if (typeof t == "object")
67
+ switch (typeof t.tag == "number" && console.error(
68
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
69
+ ), t.$$typeof) {
70
+ case T:
71
+ return "Portal";
72
+ case q:
73
+ return t.displayName || "Context";
74
+ case F:
75
+ return (t._context.displayName || "Context") + ".Consumer";
76
+ case w:
77
+ var n = t.render;
78
+ return t = t.displayName, t || (t = n.displayName || n.name || "", t = t !== "" ? "ForwardRef(" + t + ")" : "ForwardRef"), t;
79
+ case j:
80
+ return n = t.displayName || null, n !== null ? n : r(t.type) || "Memo";
81
+ case b:
82
+ n = t._payload, t = t._init;
83
+ try {
84
+ return r(t(n));
85
+ } catch {
86
+ }
87
+ }
88
+ return null;
89
+ }
90
+ function d(t) {
91
+ return "" + t;
92
+ }
93
+ function o(t) {
94
+ try {
95
+ d(t);
96
+ var n = !1;
97
+ } catch {
98
+ n = !0;
99
+ }
100
+ if (n) {
101
+ n = console;
102
+ var u = n.error, h = typeof Symbol == "function" && Symbol.toStringTag && t[Symbol.toStringTag] || t.constructor.name || "Object";
103
+ return u.call(
104
+ n,
105
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
106
+ h
107
+ ), d(t);
108
+ }
109
+ }
110
+ function s(t) {
111
+ if (t === N) return "<>";
112
+ if (typeof t == "object" && t !== null && t.$$typeof === b)
113
+ return "<...>";
114
+ try {
115
+ var n = r(t);
116
+ return n ? "<" + n + ">" : "<...>";
117
+ } catch {
118
+ return "<...>";
119
+ }
120
+ }
121
+ function a() {
122
+ var t = M.A;
123
+ return t === null ? null : t.getOwner();
124
+ }
125
+ function l() {
126
+ return Error("react-stack-top-frame");
127
+ }
128
+ function m(t) {
129
+ if (S.call(t, "key")) {
130
+ var n = Object.getOwnPropertyDescriptor(t, "key").get;
131
+ if (n && n.isReactWarning) return !1;
132
+ }
133
+ return t.key !== void 0;
134
+ }
135
+ function i(t, n) {
136
+ function u() {
137
+ H || (H = !0, console.error(
138
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
139
+ n
140
+ ));
141
+ }
142
+ u.isReactWarning = !0, Object.defineProperty(t, "key", {
143
+ get: u,
144
+ configurable: !0
145
+ });
146
+ }
147
+ function c() {
148
+ var t = r(this.type);
149
+ return G[t] || (G[t] = !0, console.error(
150
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
151
+ )), t = this.props.ref, t !== void 0 ? t : null;
152
+ }
153
+ function f(t, n, u, h, Y, B) {
154
+ var x = u.ref;
155
+ return t = {
156
+ $$typeof: C,
157
+ type: t,
158
+ key: n,
159
+ props: u,
160
+ _owner: h
161
+ }, (x !== void 0 ? x : null) !== null ? Object.defineProperty(t, "ref", {
162
+ enumerable: !1,
163
+ get: c
164
+ }) : Object.defineProperty(t, "ref", { enumerable: !1, value: null }), t._store = {}, Object.defineProperty(t._store, "validated", {
165
+ configurable: !1,
166
+ enumerable: !1,
167
+ writable: !0,
168
+ value: 0
169
+ }), Object.defineProperty(t, "_debugInfo", {
170
+ configurable: !1,
171
+ enumerable: !1,
172
+ writable: !0,
173
+ value: null
174
+ }), Object.defineProperty(t, "_debugStack", {
175
+ configurable: !1,
176
+ enumerable: !1,
177
+ writable: !0,
178
+ value: Y
179
+ }), Object.defineProperty(t, "_debugTask", {
180
+ configurable: !1,
181
+ enumerable: !1,
182
+ writable: !0,
183
+ value: B
184
+ }), Object.freeze && (Object.freeze(t.props), Object.freeze(t)), t;
185
+ }
186
+ function g(t, n, u, h, Y, B) {
187
+ var x = n.children;
188
+ if (x !== void 0)
189
+ if (h)
190
+ if (L(x)) {
191
+ for (h = 0; h < x.length; h++)
192
+ _(x[h]);
193
+ Object.freeze && Object.freeze(x);
194
+ } else
195
+ console.error(
196
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
197
+ );
198
+ else _(x);
199
+ if (S.call(n, "key")) {
200
+ x = r(t);
201
+ var I = Object.keys(n).filter(function(oe) {
202
+ return oe !== "key";
203
+ });
204
+ h = 0 < I.length ? "{key: someKey, " + I.join(": ..., ") + ": ...}" : "{key: someKey}", K[x + h] || (I = 0 < I.length ? "{" + I.join(": ..., ") + ": ...}" : "{}", console.error(
205
+ `A props object containing a "key" prop is being spread into JSX:
206
+ let props = %s;
207
+ <%s {...props} />
208
+ React keys must be passed directly to JSX without using spread:
209
+ let props = %s;
210
+ <%s key={someKey} {...props} />`,
211
+ h,
212
+ x,
213
+ I,
214
+ x
215
+ ), K[x + h] = !0);
216
+ }
217
+ if (x = null, u !== void 0 && (o(u), x = "" + u), m(n) && (o(n.key), x = "" + n.key), "key" in n) {
218
+ u = {};
219
+ for (var V in n)
220
+ V !== "key" && (u[V] = n[V]);
221
+ } else u = n;
222
+ return x && i(
223
+ u,
224
+ typeof t == "function" ? t.displayName || t.name || "Unknown" : t
225
+ ), f(
226
+ t,
227
+ x,
228
+ u,
229
+ a(),
230
+ Y,
231
+ B
232
+ );
233
+ }
234
+ function _(t) {
235
+ O(t) ? t._store && (t._store.validated = 1) : typeof t == "object" && t !== null && t.$$typeof === b && (t._payload.status === "fulfilled" ? O(t._payload.value) && t._payload.value._store && (t._payload.value._store.validated = 1) : t._store && (t._store.validated = 1));
236
+ }
237
+ function O(t) {
238
+ return typeof t == "object" && t !== null && t.$$typeof === C;
239
+ }
240
+ var v = le, C = Symbol.for("react.transitional.element"), T = Symbol.for("react.portal"), N = Symbol.for("react.fragment"), R = Symbol.for("react.strict_mode"), W = Symbol.for("react.profiler"), F = Symbol.for("react.consumer"), q = Symbol.for("react.context"), w = Symbol.for("react.forward_ref"), P = Symbol.for("react.suspense"), X = Symbol.for("react.suspense_list"), j = Symbol.for("react.memo"), b = Symbol.for("react.lazy"), k = Symbol.for("react.activity"), A = Symbol.for("react.client.reference"), M = v.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, S = Object.prototype.hasOwnProperty, L = Array.isArray, z = console.createTask ? console.createTask : function() {
241
+ return null;
242
+ };
243
+ v = {
244
+ react_stack_bottom_frame: function(t) {
245
+ return t();
246
+ }
247
+ };
248
+ var H, G = {}, Q = v.react_stack_bottom_frame.bind(
249
+ v,
250
+ l
251
+ )(), Z = z(s(l)), K = {};
252
+ D.Fragment = N, D.jsx = function(t, n, u) {
253
+ var h = 1e4 > M.recentlyCreatedOwnerStacks++;
254
+ return g(
255
+ t,
256
+ n,
257
+ u,
258
+ !1,
259
+ h ? Error("react-stack-top-frame") : Q,
260
+ h ? z(s(t)) : Z
261
+ );
262
+ }, D.jsxs = function(t, n, u) {
263
+ var h = 1e4 > M.recentlyCreatedOwnerStacks++;
264
+ return g(
265
+ t,
266
+ n,
267
+ u,
268
+ !0,
269
+ h ? Error("react-stack-top-frame") : Q,
270
+ h ? z(s(t)) : Z
271
+ );
272
+ };
273
+ })()), D;
274
+ }
275
+ var se;
276
+ function de() {
277
+ return se || (se = 1, process.env.NODE_ENV === "production" ? U.exports = ie() : U.exports = ce()), U.exports;
278
+ }
279
+ var e = de(), y = /* @__PURE__ */ ((r) => (r.TEXT = "text", r.PRODUCT_LIST = "product_list", r.LOADING = "loading", r))(y || {}), p = /* @__PURE__ */ ((r) => (r.USER = "user", r.AI = "ai", r))(p || {});
280
+ const ue = ({
281
+ title: r,
282
+ primaryColor: d,
283
+ onClose: o,
284
+ onReset: s,
285
+ onToggleExpand: a,
286
+ isExpanded: l,
287
+ language: m,
288
+ onLanguageChange: i
289
+ }) => {
290
+ const c = [
291
+ { value: "en", label: "EN" },
292
+ { value: "vi", label: "VI" },
293
+ { value: "ja", label: "JA" }
294
+ ];
295
+ return /* @__PURE__ */ e.jsxs(
296
+ "div",
297
+ {
298
+ className: "px-4 py-3 flex items-center justify-between border-b border-red-50/50 sticky top-0 z-10 bg-[#fff1f2]/90 backdrop-blur-sm",
299
+ children: [
300
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2", children: [
301
+ /* @__PURE__ */ e.jsx("div", { className: "w-8 h-8 rounded-full overflow-hidden bg-white p-0.5 shadow-sm", children: /* @__PURE__ */ e.jsx(
302
+ "img",
303
+ {
304
+ src: "https://fptshop.com.vn/img/bitu/bitu-avatar.png",
305
+ onError: (f) => f.currentTarget.src = "https://cdn-icons-png.flaticon.com/512/4712/4712035.png",
306
+ className: "w-full h-full object-contain",
307
+ alt: "Bot Icon"
308
+ }
309
+ ) }),
310
+ /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col", children: [
311
+ /* @__PURE__ */ e.jsxs("h3", { className: "font-bold text-[#1a2b56] text-[14px] leading-tight tracking-tight flex items-center gap-1", children: [
312
+ r,
313
+ " ",
314
+ /* @__PURE__ */ e.jsx("span", { className: "text-red-400 text-[10px]", children: "✨" })
315
+ ] }),
316
+ /* @__PURE__ */ e.jsxs("span", { className: "text-[10px] text-green-500 font-medium flex items-center gap-1", children: [
317
+ /* @__PURE__ */ e.jsx("span", { className: "w-1.5 h-1.5 bg-green-500 rounded-full animate-pulse" }),
318
+ "Online"
319
+ ] })
320
+ ] })
321
+ ] }),
322
+ /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1", children: [
323
+ /* @__PURE__ */ e.jsxs("div", { className: "relative group mr-1", children: [
324
+ /* @__PURE__ */ e.jsx(
325
+ "select",
326
+ {
327
+ value: m,
328
+ onChange: (f) => i(f.target.value),
329
+ className: "appearance-none bg-white/50 border border-gray-200 rounded-lg px-2 pr-5 py-1 text-[10px] font-black text-indigo-600 cursor-pointer hover:bg-white transition-all focus:outline-none focus:ring-2 focus:ring-indigo-100 uppercase",
330
+ title: "Select language",
331
+ children: c.map((f) => /* @__PURE__ */ e.jsx("option", { value: f.value, className: "font-sans font-bold", children: f.label }, f.value))
332
+ }
333
+ ),
334
+ /* @__PURE__ */ e.jsx("div", { className: "absolute right-1.5 top-1/2 -translate-y-1/2 pointer-events-none text-indigo-400", children: /* @__PURE__ */ e.jsx("svg", { width: "8", height: "8", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ e.jsx("path", { d: "m6 9 6 6 6-6" }) }) })
335
+ ] }),
336
+ /* @__PURE__ */ e.jsx(
337
+ "button",
338
+ {
339
+ onClick: s,
340
+ className: "w-8 h-8 flex items-center justify-center rounded-lg hover:bg-white/60 text-gray-500 hover:text-indigo-600 transition-all",
341
+ title: "Reset chat",
342
+ children: /* @__PURE__ */ e.jsxs("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
343
+ /* @__PURE__ */ e.jsx("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }),
344
+ /* @__PURE__ */ e.jsx("path", { d: "M21 3v5h-5" }),
345
+ /* @__PURE__ */ e.jsx("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }),
346
+ /* @__PURE__ */ e.jsx("path", { d: "M8 16H3v5" })
347
+ ] })
348
+ }
349
+ ),
350
+ /* @__PURE__ */ e.jsx(
351
+ "button",
352
+ {
353
+ onClick: a,
354
+ className: "w-8 h-8 hidden md:flex items-center justify-center rounded-lg hover:bg-white/60 text-gray-500 hover:text-indigo-600 transition-all",
355
+ title: l ? "Collapse" : "Expand",
356
+ children: l ? /* @__PURE__ */ e.jsxs("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
357
+ /* @__PURE__ */ e.jsx("path", { d: "M4 14h6v6" }),
358
+ /* @__PURE__ */ e.jsx("path", { d: "M20 10h-6V4" }),
359
+ /* @__PURE__ */ e.jsx("path", { d: "M14 10l7-7" }),
360
+ /* @__PURE__ */ e.jsx("path", { d: "M10 14l-7 7" })
361
+ ] }) : /* @__PURE__ */ e.jsxs("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
362
+ /* @__PURE__ */ e.jsx("path", { d: "M15 3h6v6" }),
363
+ /* @__PURE__ */ e.jsx("path", { d: "M9 21H3v-6" }),
364
+ /* @__PURE__ */ e.jsx("path", { d: "M21 3l-7 7" }),
365
+ /* @__PURE__ */ e.jsx("path", { d: "M3 21l7-7" })
366
+ ] })
367
+ }
368
+ ),
369
+ /* @__PURE__ */ e.jsx(
370
+ "button",
371
+ {
372
+ onClick: o,
373
+ className: "w-8 h-8 flex items-center justify-center rounded-lg hover:bg-red-50 text-gray-500 hover:text-red-500 transition-all",
374
+ title: "Close",
375
+ children: /* @__PURE__ */ e.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
376
+ /* @__PURE__ */ e.jsx("path", { d: "M18 6 6 18" }),
377
+ /* @__PURE__ */ e.jsx("path", { d: "M6 6l12 12" })
378
+ ] })
379
+ }
380
+ )
381
+ ] })
382
+ ]
383
+ }
384
+ );
385
+ }, me = ({ product: r, primaryColor: d }) => /* @__PURE__ */ e.jsxs("div", { className: "min-w-[170px] max-w-[170px] bg-white rounded-xl border border-gray-50 shadow-sm overflow-hidden flex flex-col hover:shadow-lg transition-all duration-300 group", children: [
386
+ /* @__PURE__ */ e.jsxs("div", { className: "relative h-32 w-full bg-white flex items-center justify-center p-2", children: [
387
+ /* @__PURE__ */ e.jsx(
388
+ "img",
389
+ {
390
+ src: r.image,
391
+ alt: r.name,
392
+ className: "h-full w-full object-contain group-hover:scale-105 transition-transform duration-500"
393
+ }
394
+ ),
395
+ r.discount && /* @__PURE__ */ e.jsx("div", { className: "absolute top-2 left-2 bg-red-600 text-white text-[9px] font-bold px-1.5 py-0.5 rounded-md shadow-sm", children: r.discount })
396
+ ] }),
397
+ /* @__PURE__ */ e.jsxs("div", { className: "p-3 flex-1 flex flex-col justify-between border-t border-gray-50", children: [
398
+ /* @__PURE__ */ e.jsxs("div", { children: [
399
+ /* @__PURE__ */ e.jsx("h4", { className: "text-[11px] font-bold text-gray-800 line-clamp-2 min-h-[30px] mb-1.5 group-hover:text-red-600 transition-colors", children: r.name }),
400
+ /* @__PURE__ */ e.jsxs("div", { className: "mb-2", children: [
401
+ /* @__PURE__ */ e.jsx("span", { className: "text-red-600 font-extrabold text-[13px]", children: r.price }),
402
+ r.oldPrice && /* @__PURE__ */ e.jsx("span", { className: "text-[10px] text-gray-400 line-through ml-1 block opacity-60", children: r.oldPrice })
403
+ ] })
404
+ ] }),
405
+ /* @__PURE__ */ e.jsx(
406
+ "button",
407
+ {
408
+ className: "w-full py-1.5 rounded-lg text-[11px] font-bold border transition-all duration-300 active:scale-95 shadow-sm",
409
+ style: { borderColor: d, color: d },
410
+ onMouseEnter: (o) => {
411
+ o.currentTarget.style.backgroundColor = d, o.currentTarget.style.color = "white";
412
+ },
413
+ onMouseLeave: (o) => {
414
+ o.currentTarget.style.backgroundColor = "transparent", o.currentTarget.style.color = d;
415
+ },
416
+ children: "Chọn mua"
417
+ }
418
+ )
419
+ ] })
420
+ ] }), J = (r) => {
421
+ const d = /(\*\*.*?\*\*|\[.*?\]\(.*?\))/g;
422
+ return r.split(d).map((s, a) => {
423
+ if (s.startsWith("**") && s.endsWith("**")) {
424
+ const m = s.slice(2, -2);
425
+ return /* @__PURE__ */ e.jsx("strong", { className: "font-bold text-gray-900", children: m }, a);
426
+ }
427
+ const l = s.match(/\[(.*?)\]\((.*?)\)/);
428
+ if (l) {
429
+ const [m, i, c] = l;
430
+ return /* @__PURE__ */ e.jsx(
431
+ "a",
432
+ {
433
+ href: c,
434
+ target: "_blank",
435
+ rel: "noopener noreferrer",
436
+ className: "text-blue-600 hover:underline break-all font-semibold",
437
+ children: i
438
+ },
439
+ a
440
+ );
441
+ }
442
+ return s;
443
+ });
444
+ }, he = ({ text: r }) => {
445
+ const d = r.split(`
446
+ `);
447
+ return /* @__PURE__ */ e.jsx("div", { className: "markdown-body space-y-1.5", children: d.map((o, s) => {
448
+ const a = o.trim(), l = a.match(/^(#{1,4})\s+(.*)$/);
449
+ if (l) {
450
+ const i = l[1].length, c = l[2], f = i === 1 ? "text-lg font-bold mb-3 mt-1" : i === 2 ? "text-md font-bold mb-2 mt-1" : "text-[14px] font-bold mb-1.5 mt-0.5 text-gray-900 uppercase tracking-wide";
451
+ return /* @__PURE__ */ e.jsx("div", { className: f, children: J(c) }, s);
452
+ }
453
+ const m = a.match(/^[*+-]\s+(.*)$/);
454
+ if (m) {
455
+ const i = m[1];
456
+ return /* @__PURE__ */ e.jsxs("div", { className: "flex gap-2.5 pl-1 mb-2 items-start", children: [
457
+ /* @__PURE__ */ e.jsx("span", { className: "text-gray-400 flex-shrink-0 mt-1.5 w-1 h-1 bg-gray-400 rounded-full" }),
458
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1 leading-relaxed text-gray-800", children: J(i) })
459
+ ] }, s);
460
+ }
461
+ return a === "" ? /* @__PURE__ */ e.jsx("div", { className: "h-3" }, s) : /* @__PURE__ */ e.jsx("div", { className: "mb-1 leading-relaxed text-gray-800", children: J(o) }, s);
462
+ }) });
463
+ }, xe = ({
464
+ messages: r,
465
+ isLoading: d,
466
+ quickReplies: o,
467
+ onQuickReply: s,
468
+ primaryColor: a,
469
+ renderMarkdown: l = !1
470
+ }) => {
471
+ const m = "https://fptshop.com.vn/img/bitu/bitu-avatar.png", i = "https://cdn-icons-png.flaticon.com/512/4712/4712035.png";
472
+ return /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col gap-8 pb-4", children: [
473
+ /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col items-center justify-center py-8 text-center animate-msg", children: [
474
+ /* @__PURE__ */ e.jsx("div", { className: "relative mb-5", children: /* @__PURE__ */ e.jsx("div", { className: "w-24 h-24 flex items-center justify-center", children: /* @__PURE__ */ e.jsx(
475
+ "img",
476
+ {
477
+ src: m,
478
+ onError: (c) => c.currentTarget.src = i,
479
+ className: "w-full h-full object-contain",
480
+ alt: "Sigma AI Hero"
481
+ }
482
+ ) }) }),
483
+ /* @__PURE__ */ e.jsxs("h2", { className: "text-xl font-bold text-[#1a2b56] flex items-center justify-center gap-1", children: [
484
+ "Sigma ",
485
+ /* @__PURE__ */ e.jsx("span", { className: "bg-indigo-600 text-white text-[10px] px-1.5 py-0.5 rounded-md leading-none ml-1 uppercase font-bold tracking-tight", children: "AI" })
486
+ ] }),
487
+ /* @__PURE__ */ e.jsxs("div", { className: "text-[14px] text-gray-600 mt-3 leading-relaxed px-4", children: [
488
+ /* @__PURE__ */ e.jsxs("p", { children: [
489
+ /* @__PURE__ */ e.jsx("span", { className: "font-bold text-gray-800", children: "Sigma Assistant" }),
490
+ " hỗ trợ bạn mọi lúc mọi nơi"
491
+ ] }),
492
+ /* @__PURE__ */ e.jsx("p", { children: "Tăng cường hiệu suất với AI thông minh" })
493
+ ] })
494
+ ] }),
495
+ r.map((c, f) => /* @__PURE__ */ e.jsxs(
496
+ "div",
497
+ {
498
+ className: `flex flex-col animate-msg ${c.sender === p.USER ? "items-end" : "items-start"}`,
499
+ style: { animationDelay: `${f * 0.05}s` },
500
+ children: [
501
+ c.sender === p.AI && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-1.5 mb-2 ml-1", children: [
502
+ /* @__PURE__ */ e.jsx(
503
+ "img",
504
+ {
505
+ src: m,
506
+ onError: (g) => g.currentTarget.src = i,
507
+ className: "w-4 h-4 object-contain",
508
+ alt: "AI"
509
+ }
510
+ ),
511
+ /* @__PURE__ */ e.jsx("span", { className: "text-[11px] font-bold text-gray-400 uppercase tracking-widest", children: "AI Agent" })
512
+ ] }),
513
+ /* @__PURE__ */ e.jsxs("div", { className: `flex flex-col ${c.sender === p.USER ? "items-end" : "items-start"} max-w-[94%]`, children: [
514
+ /* @__PURE__ */ e.jsx(
515
+ "div",
516
+ {
517
+ className: `px-4 py-3 rounded-[18px] text-[14px] shadow-sm border border-black/[0.03] ${c.sender === p.USER ? "bg-indigo-600 text-white rounded-tr-none whitespace-pre-line shadow-indigo-100" : "bg-white text-gray-800 border-none rounded-tl-none"} ${!l || c.sender === p.USER ? "whitespace-pre-line" : ""}`,
518
+ children: l && c.sender === p.AI ? /* @__PURE__ */ e.jsx(he, { text: c.content }) : c.content
519
+ }
520
+ ),
521
+ c.type === y.PRODUCT_LIST && c.products && /* @__PURE__ */ e.jsx("div", { className: "w-full mt-4 flex gap-4 overflow-x-auto pb-4 pt-1 no-scrollbar snap-x", children: c.products.map((g) => /* @__PURE__ */ e.jsx("div", { className: "product-card-snap", children: /* @__PURE__ */ e.jsx(me, { product: g, primaryColor: a }) }, g.id)) }),
522
+ f === 0 && r.length === 1 && c.sender === p.AI && /* @__PURE__ */ e.jsx("div", { className: "mt-5 flex flex-wrap gap-2.5 w-full", children: o.map((g, _) => /* @__PURE__ */ e.jsx(
523
+ "button",
524
+ {
525
+ onClick: () => s(g),
526
+ className: "px-4 py-2 rounded-full text-[13px] font-semibold border border-transparent bg-white text-gray-600 hover:text-indigo-600 hover:border-indigo-100 transition-all duration-200 shadow-sm active:scale-95",
527
+ children: g
528
+ },
529
+ _
530
+ )) })
531
+ ] })
532
+ ]
533
+ },
534
+ c.id
535
+ )),
536
+ d && /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col gap-1.5 items-start animate-msg", children: [
537
+ /* @__PURE__ */ e.jsx("div", { className: "flex items-center gap-1.5 ml-1", children: /* @__PURE__ */ e.jsx(
538
+ "img",
539
+ {
540
+ src: m,
541
+ onError: (c) => c.currentTarget.src = i,
542
+ className: "w-4 h-4 object-contain",
543
+ alt: "AI Loading"
544
+ }
545
+ ) }),
546
+ /* @__PURE__ */ e.jsxs("div", { className: "flex gap-1.5 bg-white px-4 py-3 rounded-[18px] rounded-tl-none border-none shadow-sm", children: [
547
+ /* @__PURE__ */ e.jsx("span", { className: "w-2 h-2 bg-indigo-300 rounded-full animate-sigma-bounce" }),
548
+ /* @__PURE__ */ e.jsx("span", { className: "w-2 h-2 bg-indigo-300 rounded-full animate-sigma-bounce [animation-delay:0.2s]" }),
549
+ /* @__PURE__ */ e.jsx("span", { className: "w-2 h-2 bg-indigo-300 rounded-full animate-sigma-bounce [animation-delay:0.4s]" })
550
+ ] })
551
+ ] })
552
+ ] });
553
+ }, fe = ({ placeholder: r, onSendMessage: d, primaryColor: o }) => {
554
+ const [s, a] = E(""), l = () => {
555
+ s.trim() && (d(s), a(""));
556
+ }, m = (i) => {
557
+ i.key === "Enter" && !i.shiftKey && (i.preventDefault(), l());
558
+ };
559
+ return /* @__PURE__ */ e.jsx("div", { className: "p-1", children: /* @__PURE__ */ e.jsxs("div", { className: "relative flex items-center bg-gray-50/50 rounded-2xl border border-gray-100 focus-within:border-indigo-100 focus-within:bg-white transition-all duration-200 pr-2 pl-3 py-1", children: [
560
+ /* @__PURE__ */ e.jsx(
561
+ "textarea",
562
+ {
563
+ value: s,
564
+ onChange: (i) => a(i.target.value),
565
+ onKeyDown: m,
566
+ placeholder: r,
567
+ rows: 1,
568
+ className: "w-full bg-transparent border-none outline-none focus:ring-0 text-[14px] text-gray-700 font-normal py-3 px-1 resize-none chat-scrollbar min-h-[44px] max-h-[120px] leading-relaxed placeholder:text-gray-400",
569
+ style: { fontWeight: 400 }
570
+ }
571
+ ),
572
+ /* @__PURE__ */ e.jsx(
573
+ "button",
574
+ {
575
+ onClick: l,
576
+ disabled: !s.trim(),
577
+ className: `w-9 h-9 rounded-xl flex-shrink-0 flex items-center justify-center transition-all duration-300 shadow-sm ${s.trim() ? "bg-indigo-600 text-white hover:bg-indigo-700 active:scale-95" : "bg-gray-200 text-gray-400 cursor-not-allowed"}`,
578
+ children: /* @__PURE__ */ e.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: [
579
+ /* @__PURE__ */ e.jsx("path", { d: "m5 12 7-7 7 7" }),
580
+ /* @__PURE__ */ e.jsx("path", { d: "M12 19V5" })
581
+ ] })
582
+ }
583
+ )
584
+ ] }) });
585
+ }, pe = ({ isOpen: r, onClick: d, primaryColor: o, className: s = "" }) => /* @__PURE__ */ e.jsx("div", { className: `fixed bottom-4 right-4 md:bottom-6 md:right-6 z-[100] ${s}`, children: /* @__PURE__ */ e.jsx(
586
+ "button",
587
+ {
588
+ onClick: d,
589
+ className: `w-12 h-12 bg-white rounded-2xl shadow-lg flex items-center justify-center border transition-all duration-300 overflow-hidden ${r ? "border-indigo-500 ring-4 ring-indigo-50 scale-105 rotate-0" : "border-slate-100 hover:scale-110 hover:shadow-xl"}`,
590
+ children: /* @__PURE__ */ e.jsx(
591
+ "img",
592
+ {
593
+ src: "https://fptshop.com.vn/img/bitu/bitu-avatar.png",
594
+ className: "w-10 h-10 object-contain",
595
+ alt: "Bitu",
596
+ onError: (a) => a.currentTarget.src = "https://cdn-icons-png.flaticon.com/512/4712/4712035.png"
597
+ }
598
+ )
599
+ }
600
+ ) }), ae = () => Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15), be = ({ config: r, onGetAiResponse: d }) => {
601
+ const [o, s] = E(!1), [a, l] = E(!1), [m, i] = E(!1), [c, f] = E(ae()), [g, _] = E("en"), [O, v] = E([
602
+ {
603
+ id: "welcome",
604
+ type: y.TEXT,
605
+ sender: p.AI,
606
+ content: r.welcomeMessage,
607
+ timestamp: /* @__PURE__ */ new Date()
608
+ }
609
+ ]), [C, T] = E(!1), N = ee(null), R = ee(0);
610
+ te(() => {
611
+ if (o) {
612
+ const w = setTimeout(() => i(!0), 50);
613
+ return () => clearTimeout(w);
614
+ } else
615
+ i(!1);
616
+ }, [o]), te(() => {
617
+ N.current && o && (N.current.scrollTop = N.current.scrollHeight);
618
+ }, [O, o, C]);
619
+ const W = async (w) => {
620
+ if (!w.trim() || C) return;
621
+ const P = ++R.current, X = {
622
+ id: `user-${Date.now()}`,
623
+ type: y.TEXT,
624
+ sender: p.USER,
625
+ content: w,
626
+ timestamp: /* @__PURE__ */ new Date()
627
+ };
628
+ v((j) => [...j, X]), T(!0);
629
+ try {
630
+ const j = d(w, c, g);
631
+ if (j && typeof j == "object" && Symbol.asyncIterator in j) {
632
+ let b = "", k = !1;
633
+ const A = `ai-${Date.now()}`;
634
+ for await (const M of j) {
635
+ if (P !== R.current) return;
636
+ k || (v((S) => [...S, {
637
+ id: A,
638
+ type: y.TEXT,
639
+ sender: p.AI,
640
+ content: "",
641
+ timestamp: /* @__PURE__ */ new Date()
642
+ }]), T(!1), k = !0), b += M, v((S) => S.map(
643
+ (L) => L.id === A ? { ...L, content: b } : L
644
+ ));
645
+ }
646
+ } else {
647
+ const b = await j;
648
+ if (P !== R.current) return;
649
+ T(!1);
650
+ const k = typeof b == "string" ? { text: b, products: void 0 } : b;
651
+ v((A) => [...A, {
652
+ id: `ai-${Date.now()}`,
653
+ type: k.products ? y.PRODUCT_LIST : y.TEXT,
654
+ sender: p.AI,
655
+ content: k.text,
656
+ products: k.products,
657
+ timestamp: /* @__PURE__ */ new Date()
658
+ }]);
659
+ }
660
+ } catch (j) {
661
+ if (P !== R.current) return;
662
+ console.error("Chatbox Error:", j), T(!1), v((b) => [...b, {
663
+ id: `err-${Date.now()}`,
664
+ type: y.TEXT,
665
+ sender: p.AI,
666
+ content: "Hệ thống đang bận, vui lòng thử lại sau.",
667
+ timestamp: /* @__PURE__ */ new Date()
668
+ }]);
669
+ }
670
+ }, F = () => {
671
+ R.current++, f(ae()), v([{
672
+ id: "welcome",
673
+ type: y.TEXT,
674
+ sender: p.AI,
675
+ content: r.welcomeMessage,
676
+ timestamp: /* @__PURE__ */ new Date()
677
+ }]), T(!1), l(!1);
678
+ }, q = `
679
+ fixed z-[99] overflow-hidden flex flex-col border border-white/40 shadow-2xl bg-white animate-chat-pop
680
+ ${m ? "transition-[width,height,border-radius,right,bottom] duration-300 ease-in-out" : ""}
681
+ ${a ? "bottom-0 right-0 w-full h-full md:bottom-6 md:right-28 md:w-[850px] md:h-[85vh] rounded-none md:rounded-[32px]" : "bottom-0 right-0 w-full h-[80vh] md:bottom-6 md:right-28 md:w-[380px] md:h-[580px] rounded-t-[28px] md:rounded-[28px]"}
682
+ `;
683
+ return /* @__PURE__ */ e.jsxs(e.Fragment, { children: [
684
+ /* @__PURE__ */ e.jsx(
685
+ pe,
686
+ {
687
+ isOpen: o,
688
+ onClick: () => s(!o),
689
+ primaryColor: r.primaryColor,
690
+ className: o ? "hidden md:flex" : "flex"
691
+ }
692
+ ),
693
+ o && /* @__PURE__ */ e.jsxs("div", { className: q, style: { left: "auto" }, children: [
694
+ /* @__PURE__ */ e.jsx(
695
+ ue,
696
+ {
697
+ title: r.botName,
698
+ primaryColor: r.primaryColor,
699
+ onClose: () => s(!1),
700
+ onReset: F,
701
+ onToggleExpand: () => l(!a),
702
+ isExpanded: a,
703
+ language: g,
704
+ onLanguageChange: _
705
+ }
706
+ ),
707
+ /* @__PURE__ */ e.jsx("div", { className: "flex-1 overflow-y-auto chat-scrollbar px-5 py-5 bg-slate-50/30", ref: N, children: /* @__PURE__ */ e.jsx(
708
+ xe,
709
+ {
710
+ messages: O,
711
+ isLoading: C,
712
+ quickReplies: r.quickReplies,
713
+ onQuickReply: (w) => W(w),
714
+ primaryColor: r.primaryColor,
715
+ renderMarkdown: r.renderMarkdown
716
+ }
717
+ ) }),
718
+ /* @__PURE__ */ e.jsx("div", { className: "bg-white p-3 border-t border-slate-100", children: /* @__PURE__ */ e.jsx(
719
+ fe,
720
+ {
721
+ placeholder: r.placeholder,
722
+ onSendMessage: W,
723
+ primaryColor: r.primaryColor
724
+ }
725
+ ) })
726
+ ] })
727
+ ] });
728
+ };
729
+ export {
730
+ be as Chatbox,
731
+ y as MessageType,
732
+ p as SenderType
733
+ };
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.chat-scrollbar::-webkit-scrollbar{width:5px}.chat-scrollbar::-webkit-scrollbar-track{background:transparent}.chat-scrollbar::-webkit-scrollbar-thumb{background:#e5e7eb;border-radius:10px}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.bottom-0{bottom:0}.bottom-4{bottom:1rem}.left-2{left:.5rem}.right-0{right:0}.right-1\.5{right:.375rem}.right-4{right:1rem}.top-0{top:0}.top-1\/2{top:50%}.top-2{top:.5rem}.z-10{z-index:10}.z-\[100\]{z-index:100}.z-\[99\]{z-index:99}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-5{margin-bottom:1.25rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.mr-1{margin-right:.25rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.flex{display:flex}.hidden{display:none}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-2{height:.5rem}.h-24{height:6rem}.h-3{height:.75rem}.h-32{height:8rem}.h-4{height:1rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[80vh\]{height:80vh}.h-full{height:100%}.max-h-\[120px\]{max-height:120px}.min-h-\[30px\]{min-height:30px}.min-h-\[44px\]{min-height:44px}.min-h-screen{min-height:100vh}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-2{width:.5rem}.w-24{width:6rem}.w-4{width:1rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-full{width:100%}.min-w-\[170px\]{min-width:170px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-\[170px\]{max-width:170px}.max-w-\[94\%\]{max-width:94%}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-0{--tw-rotate: 0deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-105{--tw-scale-x: 1.05;--tw-scale-y: 1.05;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.snap-x{scroll-snap-type:x var(--tw-scroll-snap-strictness)}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.whitespace-pre-line{white-space:pre-line}.break-all{word-break:break-all}.rounded-2xl{border-radius:1rem}.rounded-3xl{border-radius:1.5rem}.rounded-\[18px\]{border-radius:18px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-xl{border-radius:.75rem}.rounded-t-\[28px\]{border-top-left-radius:28px;border-top-right-radius:28px}.rounded-tl-none{border-top-left-radius:0}.rounded-tr-none{border-top-right-radius:0}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-none{border-style:none}.border-black\/\[0\.03\]{border-color:#00000008}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-50{--tw-border-opacity: 1;border-color:rgb(249 250 251 / var(--tw-border-opacity, 1))}.border-indigo-500{--tw-border-opacity: 1;border-color:rgb(99 102 241 / var(--tw-border-opacity, 1))}.border-red-50\/50{border-color:#fef2f280}.border-slate-100{--tw-border-opacity: 1;border-color:rgb(241 245 249 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.border-white\/40{border-color:#fff6}.bg-\[\#fff1f2\]\/90{background-color:#fff1f2e6}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-400{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))}.bg-gray-50\/50{background-color:#f9fafb80}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-indigo-300{--tw-bg-opacity: 1;background-color:rgb(165 180 252 / var(--tw-bg-opacity, 1))}.bg-indigo-600{--tw-bg-opacity: 1;background-color:rgb(79 70 229 / var(--tw-bg-opacity, 1))}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-slate-50{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.bg-slate-50\/30{background-color:#f8fafc4d}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/50{background-color:#ffffff80}.object-contain{-o-object-fit:contain;object-fit:contain}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-4{padding-bottom:1rem}.pl-1{padding-left:.25rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pr-5{padding-right:1.25rem}.pt-1{padding-top:.25rem}.text-center{text-align:center}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[9px\]{font-size:9px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-black{font-weight:900}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-widest{letter-spacing:.1em}.text-\[\#1a2b56\]{--tw-text-opacity: 1;color:rgb(26 43 86 / var(--tw-text-opacity, 1))}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-indigo-400{--tw-text-opacity: 1;color:rgb(129 140 248 / var(--tw-text-opacity, 1))}.text-indigo-500{--tw-text-opacity: 1;color:rgb(99 102 241 / var(--tw-text-opacity, 1))}.text-indigo-600{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.line-through{text-decoration-line:line-through}.opacity-60{opacity:.6}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-indigo-100{--tw-shadow-color: #e0e7ff;--tw-shadow: var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-4{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-indigo-50{--tw-ring-opacity: 1;--tw-ring-color: rgb(238 242 255 / var(--tw-ring-opacity, 1))}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\[width\,height\,border-radius\,right\,bottom\]{transition-property:width,height,border-radius,right,bottom;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.product-card-snap{scroll-snap-align:start}.\[animation-delay\:0\.2s\]{animation-delay:.2s}.\[animation-delay\:0\.4s\]{animation-delay:.4s}@keyframes chat-pop{0%{transform:scale(.9) translateY(20px);opacity:0}to{transform:scale(1) translateY(0);opacity:1}}@keyframes msg-fade-in{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes sigma-bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-4px)}}.animate-chat-pop{animation:chat-pop .4s cubic-bezier(.34,1.56,.64,1) forwards}.animate-msg{animation:msg-fade-in .3s ease-out forwards}.animate-sigma-bounce{animation:sigma-bounce .6s infinite}.placeholder\:text-gray-400::-moz-placeholder{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.placeholder\:text-gray-400::placeholder{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.focus-within\:border-indigo-100:focus-within{--tw-border-opacity: 1;border-color:rgb(224 231 255 / var(--tw-border-opacity, 1))}.focus-within\:bg-white:focus-within{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.hover\:scale-110:hover{--tw-scale-x: 1.1;--tw-scale-y: 1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-indigo-100:hover{--tw-border-opacity: 1;border-color:rgb(224 231 255 / var(--tw-border-opacity, 1))}.hover\:bg-indigo-700:hover{--tw-bg-opacity: 1;background-color:rgb(67 56 202 / var(--tw-bg-opacity, 1))}.hover\:bg-red-50:hover{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.hover\:bg-white:hover{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.hover\:bg-white\/60:hover{background-color:#fff9}.hover\:text-indigo-600:hover{--tw-text-opacity: 1;color:rgb(79 70 229 / var(--tw-text-opacity, 1))}.hover\:text-red-500:hover{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:shadow-lg:hover{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:shadow-xl:hover{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-0:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-indigo-100:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(224 231 255 / var(--tw-ring-opacity, 1))}.active\:scale-95:active{--tw-scale-x: .95;--tw-scale-y: .95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:scale-105{--tw-scale-x: 1.05;--tw-scale-y: 1.05;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}@media(min-width:768px){.md\:bottom-6{bottom:1.5rem}.md\:right-28{right:7rem}.md\:right-6{right:1.5rem}.md\:flex{display:flex}.md\:h-\[580px\]{height:580px}.md\:h-\[85vh\]{height:85vh}.md\:w-\[380px\]{width:380px}.md\:w-\[850px\]{width:850px}.md\:rounded-\[28px\]{border-radius:28px}.md\:rounded-\[32px\]{border-radius:32px}.md\:text-6xl{font-size:3.75rem;line-height:1}}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,48 @@
1
+ export declare enum MessageType {
2
+ TEXT = "text",
3
+ PRODUCT_LIST = "product_list",
4
+ LOADING = "loading"
5
+ }
6
+ export declare enum SenderType {
7
+ USER = "user",
8
+ AI = "ai"
9
+ }
10
+ export type Language = 'en' | 'vi' | 'ja';
11
+ export interface Product {
12
+ id: string;
13
+ name: string;
14
+ image: string;
15
+ price: string;
16
+ oldPrice?: string;
17
+ discount?: string;
18
+ description: string;
19
+ }
20
+ export interface Message {
21
+ id: string;
22
+ type: MessageType;
23
+ sender: SenderType;
24
+ content: string;
25
+ products?: Product[];
26
+ timestamp: Date;
27
+ }
28
+ export interface ChatboxConfig {
29
+ primaryColor: string;
30
+ botName: string;
31
+ welcomeMessage: string;
32
+ placeholder: string;
33
+ avatarUrl: string;
34
+ quickReplies: string[];
35
+ /**
36
+ * Nếu true, tin nhắn từ AI sẽ được render hỗ trợ định dạng Markdown cơ bản.
37
+ * Mặc định là false (văn bản thuần túy).
38
+ */
39
+ renderMarkdown?: boolean;
40
+ }
41
+ /**
42
+ * Flexible handler for AI responses.
43
+ * Receives threadId and selected language.
44
+ */
45
+ export type AiResponseHandler = (userInput: string, threadId: string, language: Language) => Promise<string | {
46
+ text: string;
47
+ products?: Product[];
48
+ }> | AsyncGenerator<string>;
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "react-sigma-chatbox",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "A high-quality React chatbox library featuring product cards, quick replies, and AI integration.",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.mjs",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.js"
14
+ },
15
+ "./dist/react-sigma-chatbox.css": "./dist/react-sigma-chatbox.css"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "dev": "vite",
22
+ "build": "vite build && tsc --emitDeclarationOnly",
23
+ "preview": "vite preview",
24
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
25
+ },
26
+ "keywords": [
27
+ "react",
28
+ "chatbox",
29
+ "sigma",
30
+ "ai-assistant",
31
+ "ui-library",
32
+ "gemini-api"
33
+ ],
34
+ "author": "Your Name",
35
+ "license": "MIT",
36
+ "peerDependencies": {
37
+ "react": "^18.0.0 || ^19.0.0",
38
+ "react-dom": "^18.0.0 || ^19.0.0"
39
+ },
40
+ "dependencies": {
41
+ "@google/genai": "^1.34.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/react": "^19.0.0",
45
+ "@types/react-dom": "^19.0.0",
46
+ "@types/node": "^22.0.0",
47
+ "typescript": "^5.0.0",
48
+ "vite": "^6.0.0",
49
+ "vite-plugin-dts": "^4.0.0",
50
+ "@vitejs/plugin-react": "^4.3.0",
51
+ "tailwindcss": "^3.4.0",
52
+ "autoprefixer": "^10.4.0",
53
+ "postcss": "^8.4.0"
54
+ }
55
+ }