thikanaa 0.1.7 → 0.1.8

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.
Binary file
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var I=Object.defineProperty;var W=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var F=Object.prototype.hasOwnProperty;var K=(l,n)=>{for(var g in n)I(l,g,{get:n[g],enumerable:!0})},U=(l,n,g,u)=>{if(n&&typeof n=="object"||typeof n=="function")for(let d of q(n))!F.call(l,d)&&d!==g&&I(l,d,{get:()=>n[d],enumerable:!(u=W(n,d))||u.enumerable});return l};var G=l=>U(I({},"__esModule",{value:!0}),l);var X={};K(X,{ChatPopup:()=>V});module.exports=G(X);var t=require("react");var s=require("react/jsx-runtime"),V=({systemPrompt:l,portfolioData:n,apiUrl:g="https://thikana.malaymishra.com/chatbot",assistantName:u="Thikana",initialMessage:d,model:C,messages:p,onMessageSend:D,onResponseReceive:x,mockMode:H=!1,position:j="relative"})=>{let[h,E]=(0,t.useState)(""),[b,f]=(0,t.useState)([]),[w,L]=(0,t.useState)(!1),[R,$]=(0,t.useState)(null),[P,N]=(0,t.useState)({width:330,height:480}),[y,T]=(0,t.useState)(!1),v=(0,t.useRef)(null),m=(0,t.useRef)(null),z=(0,t.useRef)(null),k=p||b,O=n||R;(0,t.useEffect)(()=>{if((!p||p.length===0)&&b.length===0){let e=localStorage.getItem("messages");f(e?JSON.parse(e):[{role:"assistant",content:d||`Hi this is ${u}! How can I help you today?`}])}},[p,d,u,b.length]),(0,t.useEffect)(()=>{n||(async()=>{try{let a=await(await fetch("https://raw.githubusercontent.com/hi-malay/portfolio-data/refs/heads/main/scrapped_data.json")).json();$(a)}catch(o){console.error("Error fetching portfolio data:",o)}})()},[n]);let A=()=>{z.current?.scrollIntoView({behavior:"smooth"})};(0,t.useEffect)(()=>{A()},[k]);let B=async e=>{if(H){await new Promise(r=>setTimeout(r,1e3));let i=["That's an interesting question! Let me help you with that.","I understand what you're asking. Here's what I think...","Great question! Based on what you've told me, I'd suggest...","Let me break that down for you.","I'm here to help! Here's my take on that..."],c=i[Math.floor(Math.random()*i.length)];return x&&x(c),c}let o=await fetch(g,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({messages:e,portfolioData:O,systemPrompt:l,model:C})});if(!o.ok){let i=await o.json();throw new Error(i.error||"Failed to get AI response")}let a=await o.json();return x&&x(a.text),a.text},S=async e=>{if(!e.trim()||w)return;let o={role:"user",content:e};D&&D(o);let a=[...k,o];p||f(a),E(""),L(!0);try{let c={role:"assistant",content:await B(a)},r=[...a,c];p||(f(r),localStorage.setItem("messages",JSON.stringify(r)))}catch(i){console.error("Error calling AI:",i);let c={role:"assistant",content:"Sorry, I encountered an error. Please try again later."},r=[...a,c];p||(f(r),localStorage.setItem("messages",JSON.stringify(r)))}finally{L(!1)}};(0,t.useEffect)(()=>{m.current&&(m.current.style.height="auto",m.current.style.height=`${Math.min(m.current.scrollHeight,100)}px`)},[h]);let J=(0,t.useCallback)(e=>{e.preventDefault(),T(!0)},[]);return(0,t.useEffect)(()=>{if(!y)return;let e=a=>{if(!v.current)return;let i=v.current.getBoundingClientRect(),c=i.right-a.clientX,r=i.bottom-a.clientY;c>250&&c<800&&N(M=>({...M,width:c})),r>300&&r<800&&N(M=>({...M,height:r}))},o=()=>{T(!1)};return window.addEventListener("mousemove",e),window.addEventListener("mouseup",o),()=>{window.removeEventListener("mousemove",e),window.removeEventListener("mouseup",o)}},[y]),(0,s.jsxs)("div",{ref:v,className:`chat-popup-wrapper ${y?"resizing":""}`,style:{width:`${P.width}px`,height:`${P.height}px`,position:j},children:[(0,s.jsx)("div",{className:"stretch-icon",onMouseDown:J}),(0,s.jsxs)("div",{className:"messages-container",children:[k.map((e,o)=>(0,s.jsx)("div",{className:`message ${e.role==="user"?"user":"ai"}`,children:e.content},o)),w&&(0,s.jsx)("div",{className:"message ai loading",children:"Thinking..."}),(0,s.jsx)("div",{ref:z})]}),(0,s.jsxs)("div",{className:"input-container",children:[(0,s.jsx)("textarea",{ref:m,rows:1,placeholder:"What's on your mind?",value:h,onKeyDown:e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),S(h))},onChange:e=>E(e.target.value)}),(0,s.jsx)("button",{onClick:()=>S(h),disabled:!h.trim()||w,className:"send-button",children:(0,s.jsxs)("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,s.jsx)("line",{x1:"22",y1:"2",x2:"11",y2:"13"}),(0,s.jsx)("polygon",{points:"22 2 15 22 11 13 2 9 22 2"})]})})]})]})};0&&(module.exports={ChatPopup});
1
+ "use strict";var q=Object.create;var D=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var z=Object.getPrototypeOf,Q=Object.prototype.hasOwnProperty;var F=(n,r)=>{for(var c in r)D(n,c,{get:r[c],enumerable:!0})},R=(n,r,c,f)=>{if(r&&typeof r=="object"||typeof r=="function")for(let d of B(r))!Q.call(n,d)&&d!==c&&D(n,d,{get:()=>r[d],enumerable:!(f=G(r,d))||f.enumerable});return n};var ee=(n,r,c)=>(c=n!=null?q(z(n)):{},R(r||!n||!n.__esModule?D(c,"default",{value:n,enumerable:!0}):c,n)),te=n=>R(D({},"__esModule",{value:!0}),n);var ae={};F(ae,{ChatPopup:()=>ne});module.exports=te(ae);var t=require("react");var C=ee(require("next/image"));var S="./chatbot-black-HLEKK2J4.png";var o=require("react/jsx-runtime"),ne=({systemPrompt:n,portfolioData:r,apiUrl:c="https://thikana.malaymishra.com/chatbot",assistantName:f="Thikana",initialMessage:d,model:W,messages:g,onMessageSend:k,onResponseReceive:m,mockMode:j=!1,position:A="relative"})=>{let[h,T]=(0,t.useState)(""),[w,u]=(0,t.useState)([]),[b,L]=(0,t.useState)(!1),[X,V]=(0,t.useState)(null),[M,P]=(0,t.useState)({width:330,height:480}),[I,$]=(0,t.useState)(!1),[J,K]=(0,t.useState)(!1),x=(0,t.useRef)(null);(0,t.useEffect)(()=>{function e(a){x.current&&!x.current.contains(a.target)&&K(!1)}return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[]);let H=(0,t.useRef)(null),v=(0,t.useRef)(null),_=(0,t.useRef)(null),O=g||w,E=r||X;(0,t.useEffect)(()=>{if((!g||g.length===0)&&w.length===0){let e=localStorage.getItem("messages");u(e?JSON.parse(e):[{role:"assistant",content:d||`Hi this is ${f}! How can I help you today?`}])}},[g,d,f,w.length]),(0,t.useEffect)(()=>{r||(async()=>{try{let s=await(await fetch("https://raw.githubusercontent.com/hi-malay/portfolio-data/refs/heads/main/scrapped_data.json")).json();V(s)}catch(a){console.error("Error fetching portfolio data:",a)}})()},[r]);let Z=()=>{_.current?.scrollIntoView({behavior:"smooth"})};(0,t.useEffect)(()=>{Z()},[O]);let Y=async e=>{if(j){await new Promise(i=>setTimeout(i,1e3));let l=["That's an interesting question! Let me help you with that.","I understand what you're asking. Here's what I think...","Great question! Based on what you've told me, I'd suggest...","Let me break that down for you.","I'm here to help! Here's my take on that..."],p=l[Math.floor(Math.random()*l.length)];return m&&m(p),p}let a=await fetch(c,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({messages:e,portfolioData:E,systemPrompt:n,model:W})});if(!a.ok){let l=await a.json();throw new Error(l.error||"Failed to get AI response")}let s=await a.json();return m&&m(s.text),s.text},N=async e=>{if(!e.trim()||b)return;let a={role:"user",content:e};k&&k(a);let s=[...O,a];g||u(s),T(""),L(!0);try{let p={role:"assistant",content:await Y(s)},i=[...s,p];g||(u(i),localStorage.setItem("messages",JSON.stringify(i)))}catch(l){console.error("Error calling AI:",l);let p={role:"assistant",content:"Sorry, I encountered an error. Please try again later."},i=[...s,p];g||(u(i),localStorage.setItem("messages",JSON.stringify(i)))}finally{L(!1)}};(0,t.useEffect)(()=>{v.current&&(v.current.style.height="auto",v.current.style.height=`${Math.min(v.current.scrollHeight,100)}px`)},[h]);let U=(0,t.useCallback)(e=>{e.preventDefault(),$(!0)},[]);return(0,t.useEffect)(()=>{if(!I)return;let e=s=>{if(!H.current)return;let l=H.current.getBoundingClientRect(),p=l.right-s.clientX,i=l.bottom-s.clientY;p>250&&p<800&&P(y=>({...y,width:p})),i>300&&i<800&&P(y=>({...y,height:i}))},a=()=>{$(!1)};return window.addEventListener("mousemove",e),window.addEventListener("mouseup",a),()=>{window.removeEventListener("mousemove",e),window.removeEventListener("mouseup",a)}},[I]),(0,o.jsxs)("div",{className:"chatbot-container",ref:x,children:[J&&(0,o.jsx)("div",{className:"chatbot-popup",children:(0,o.jsxs)("div",{ref:H,className:`chat-popup-wrapper ${I?"resizing":""}`,style:{width:`${M.width}px`,height:`${M.height}px`,position:A},children:[(0,o.jsx)("div",{className:"stretch-icon",onMouseDown:U}),(0,o.jsxs)("div",{className:"messages-container",children:[O.map((e,a)=>(0,o.jsx)("div",{className:`message ${e.role==="user"?"user":"ai"}`,children:e.content},a)),b&&(0,o.jsx)("div",{className:"message ai loading",children:"Thinking..."}),(0,o.jsx)("div",{ref:_})]}),(0,o.jsxs)("div",{className:"input-container",children:[(0,o.jsx)("textarea",{ref:v,rows:1,placeholder:"What's on your mind?",value:h,onKeyDown:e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),N(h))},onChange:e=>T(e.target.value)}),(0,o.jsx)("button",{onClick:()=>N(h),disabled:!h.trim()||b,className:"send-button",children:(0,o.jsxs)("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,o.jsx)("line",{x1:"22",y1:"2",x2:"11",y2:"13"}),(0,o.jsx)("polygon",{points:"22 2 15 22 11 13 2 9 22 2"})]})})]})]})}),(0,o.jsx)(C.default,{onClick:()=>K(e=>!e),className:"chatbot-icon",alt:"chatbot",src:S})]})};0&&(module.exports={ChatPopup});
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/chat-popup.tsx"],"sourcesContent":["export * from \"./components/chat-popup\";\n","import React, { useState, useRef, useEffect, useCallback } from \"react\";\nimport \"./chat-popup.css\";\n\ntype Message = {\n role: \"user\" | \"assistant\" | \"system\";\n content: string;\n};\n\nexport interface ChatPopupProps {\n systemPrompt?: string;\n portfolioData?: any;\n apiUrl?: string;\n assistantName?: string;\n initialMessage?: string;\n model?: string;\n messages?: Message[];\n onMessageSend?: (message: Message) => void;\n onResponseReceive?: (response: string) => void;\n mockMode?: boolean; // If true, uses mock responses instead of API calls\n position?: \"fixed\" | \"relative\"; // Position style for the wrapper\n}\n\nexport const ChatPopup = ({\n systemPrompt,\n portfolioData: externalPortfolioData,\n apiUrl = \"https://thikana.malaymishra.com/chatbot\",\n assistantName = \"Thikana\",\n initialMessage,\n model,\n messages: externalMessages,\n onMessageSend,\n onResponseReceive,\n mockMode = false,\n position = \"relative\",\n}: ChatPopupProps) => {\n const [input, setInput] = useState<string>(\"\");\n const [internalMessages, setInternalMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [internalPortfolioData, setInternalPortfolioData] = useState<any>(null);\n const [dimensions, setDimensions] = useState({ width: 330, height: 480 });\n const [isResizing, setIsResizing] = useState(false);\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n const activeMessages = externalMessages || internalMessages;\n const activePortfolioData = externalPortfolioData || internalPortfolioData;\n\n useEffect(() => {\n if (!externalMessages || externalMessages.length === 0) {\n if (internalMessages.length === 0) {\n const saved = localStorage.getItem(\"messages\");\n if (saved) {\n setInternalMessages(JSON.parse(saved));\n } else {\n setInternalMessages([\n {\n role: \"assistant\",\n content:\n initialMessage ||\n `Hi this is ${assistantName}! How can I help you today?`,\n },\n ]);\n }\n }\n }\n }, [\n externalMessages,\n initialMessage,\n assistantName,\n internalMessages.length,\n ]);\n\n useEffect(() => {\n if (!externalPortfolioData) {\n const fetchPortfolioData = async () => {\n try {\n const response = await fetch(\n \"https://raw.githubusercontent.com/hi-malay/portfolio-data/refs/heads/main/scrapped_data.json\",\n );\n const data = await response.json();\n setInternalPortfolioData(data);\n } catch (error) {\n console.error(\"Error fetching portfolio data:\", error);\n }\n };\n fetchPortfolioData();\n }\n }, [externalPortfolioData]);\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n };\n\n useEffect(() => {\n scrollToBottom();\n }, [activeMessages]);\n\n const getAIResponse = async (currentMessages: Message[]): Promise<string> => {\n // Mock mode for testing without API\n if (mockMode) {\n await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate API delay\n const mockResponses = [\n \"That's an interesting question! Let me help you with that.\",\n \"I understand what you're asking. Here's what I think...\",\n \"Great question! Based on what you've told me, I'd suggest...\",\n \"Let me break that down for you.\",\n \"I'm here to help! Here's my take on that...\",\n ];\n const response =\n mockResponses[Math.floor(Math.random() * mockResponses.length)];\n if (onResponseReceive) onResponseReceive(response);\n return response;\n }\n\n const response = await fetch(apiUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n messages: currentMessages,\n portfolioData: activePortfolioData,\n systemPrompt,\n model,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json();\n throw new Error(errorData.error || \"Failed to get AI response\");\n }\n\n const data = await response.json();\n if (onResponseReceive) onResponseReceive(data.text);\n return data.text;\n };\n\n const callModel = async (userInput: string) => {\n if (!userInput.trim() || isLoading) return;\n\n const userMessage: Message = { role: \"user\", content: userInput };\n if (onMessageSend) onMessageSend(userMessage);\n\n const newMessages = [...activeMessages, userMessage];\n\n if (!externalMessages) {\n setInternalMessages(newMessages);\n }\n\n setInput(\"\");\n setIsLoading(true);\n\n try {\n const text = await getAIResponse(newMessages);\n\n const assistantMessage: Message = {\n role: \"assistant\",\n content: text,\n };\n\n const updatedMessages = [...newMessages, assistantMessage];\n if (!externalMessages) {\n setInternalMessages(updatedMessages);\n localStorage.setItem(\"messages\", JSON.stringify(updatedMessages));\n }\n } catch (error) {\n console.error(\"Error calling AI:\", error);\n const defaultFailMessage: Message = {\n role: \"assistant\",\n content: \"Sorry, I encountered an error. Please try again later.\",\n };\n const updatedMessages = [...newMessages, defaultFailMessage];\n if (!externalMessages) {\n setInternalMessages(updatedMessages);\n localStorage.setItem(\"messages\", JSON.stringify(updatedMessages));\n }\n } finally {\n setIsLoading(false);\n }\n };\n\n useEffect(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = \"auto\";\n textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 100)}px`;\n }\n }, [input]);\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n setIsResizing(true);\n }, []);\n\n useEffect(() => {\n if (!isResizing) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!wrapperRef.current) return;\n\n const rect = wrapperRef.current.getBoundingClientRect();\n const newWidth = rect.right - e.clientX;\n const newHeight = rect.bottom - e.clientY;\n\n if (newWidth > 250 && newWidth < 800) {\n setDimensions((prev) => ({ ...prev, width: newWidth }));\n }\n if (newHeight > 300 && newHeight < 800) {\n setDimensions((prev) => ({ ...prev, height: newHeight }));\n }\n };\n\n const handleMouseUp = () => {\n setIsResizing(false);\n };\n\n window.addEventListener(\"mousemove\", handleMouseMove);\n window.addEventListener(\"mouseup\", handleMouseUp);\n\n return () => {\n window.removeEventListener(\"mousemove\", handleMouseMove);\n window.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }, [isResizing]);\n\n return (\n <div\n ref={wrapperRef}\n className={`chat-popup-wrapper ${isResizing ? \"resizing\" : \"\"}`}\n style={{\n width: `${dimensions.width}px`,\n height: `${dimensions.height}px`,\n position: position,\n }}\n >\n <div className=\"stretch-icon\" onMouseDown={handleMouseDown}></div>\n <div className=\"messages-container\">\n {activeMessages.map((msg: Message, index: number) => (\n <div\n key={index}\n className={`message ${msg.role === \"user\" ? \"user\" : \"ai\"}`}\n >\n {msg.content}\n </div>\n ))}\n {isLoading && <div className=\"message ai loading\">Thinking...</div>}\n <div ref={messagesEndRef} />\n </div>\n\n <div className=\"input-container\">\n <textarea\n ref={textareaRef}\n rows={1}\n placeholder=\"What's on your mind?\"\n value={input}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n callModel(input);\n }\n }}\n onChange={(e) => setInput(e.target.value)}\n />\n <button\n onClick={() => callModel(input)}\n disabled={!input.trim() || isLoading}\n className=\"send-button\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n </button>\n </div>\n </div>\n );\n};\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,eAAAE,IAAA,eAAAC,EAAAH,GCAA,IAAAI,EAAgE,iBA6O1D,IAAAC,EAAA,6BAvNOC,EAAY,CAAC,CACxB,aAAAC,EACA,cAAeC,EACf,OAAAC,EAAS,0CACT,cAAAC,EAAgB,UAChB,eAAAC,EACA,MAAAC,EACA,SAAUC,EACV,cAAAC,EACA,kBAAAC,EACA,SAAAC,EAAW,GACX,SAAAC,EAAW,UACb,IAAsB,CACpB,GAAM,CAACC,EAAOC,CAAQ,KAAI,YAAiB,EAAE,EACvC,CAACC,EAAkBC,CAAmB,KAAI,YAAoB,CAAC,CAAC,EAChE,CAACC,EAAWC,CAAY,KAAI,YAAS,EAAK,EAC1C,CAACC,EAAuBC,CAAwB,KAAI,YAAc,IAAI,EACtE,CAACC,EAAYC,CAAa,KAAI,YAAS,CAAE,MAAO,IAAK,OAAQ,GAAI,CAAC,EAClE,CAACC,EAAYC,CAAa,KAAI,YAAS,EAAK,EAE5CC,KAAa,UAAuB,IAAI,EAExCC,KAAc,UAA4B,IAAI,EAC9CC,KAAiB,UAAuB,IAAI,EAE5CC,EAAiBpB,GAAoBO,EACrCc,EAAsB1B,GAAyBgB,KAErD,aAAU,IAAM,CACd,IAAI,CAACX,GAAoBA,EAAiB,SAAW,IAC/CO,EAAiB,SAAW,EAAG,CACjC,IAAMe,EAAQ,aAAa,QAAQ,UAAU,EAE3Cd,EADEc,EACkB,KAAK,MAAMA,CAAK,EAEhB,CAClB,CACE,KAAM,YACN,QACExB,GACA,cAAcD,CAAa,6BAC/B,CACF,CATqC,CAWzC,CAEJ,EAAG,CACDG,EACAF,EACAD,EACAU,EAAiB,MACnB,CAAC,KAED,aAAU,IAAM,CACTZ,IACwB,SAAY,CACrC,GAAI,CAIF,IAAM4B,EAAO,MAHI,MAAM,MACrB,8FACF,GAC4B,KAAK,EACjCX,EAAyBW,CAAI,CAC/B,OAASC,EAAO,CACd,QAAQ,MAAM,iCAAkCA,CAAK,CACvD,CACF,GACmB,CAEvB,EAAG,CAAC7B,CAAqB,CAAC,EAE1B,IAAM8B,EAAiB,IAAM,CAC3BN,EAAe,SAAS,eAAe,CAAE,SAAU,QAAS,CAAC,CAC/D,KAEA,aAAU,IAAM,CACdM,EAAe,CACjB,EAAG,CAACL,CAAc,CAAC,EAEnB,IAAMM,EAAgB,MAAOC,GAAgD,CAE3E,GAAIxB,EAAU,CACZ,MAAM,IAAI,QAASyB,GAAY,WAAWA,EAAS,GAAI,CAAC,EACxD,IAAMC,EAAgB,CACpB,6DACA,0DACA,+DACA,kCACA,6CACF,EACMC,EACJD,EAAc,KAAK,MAAM,KAAK,OAAO,EAAIA,EAAc,MAAM,CAAC,EAChE,OAAI3B,GAAmBA,EAAkB4B,CAAQ,EAC1CA,CACT,CAEA,IAAMA,EAAW,MAAM,MAAMlC,EAAQ,CACnC,OAAQ,OACR,QAAS,CACP,eAAgB,kBAClB,EACA,KAAM,KAAK,UAAU,CACnB,SAAU+B,EACV,cAAeN,EACf,aAAA3B,EACA,MAAAK,CACF,CAAC,CACH,CAAC,EAED,GAAI,CAAC+B,EAAS,GAAI,CAChB,IAAMC,EAAY,MAAMD,EAAS,KAAK,EACtC,MAAM,IAAI,MAAMC,EAAU,OAAS,2BAA2B,CAChE,CAEA,IAAMR,EAAO,MAAMO,EAAS,KAAK,EACjC,OAAI5B,GAAmBA,EAAkBqB,EAAK,IAAI,EAC3CA,EAAK,IACd,EAEMS,EAAY,MAAOC,GAAsB,CAC7C,GAAI,CAACA,EAAU,KAAK,GAAKxB,EAAW,OAEpC,IAAMyB,EAAuB,CAAE,KAAM,OAAQ,QAASD,CAAU,EAC5DhC,GAAeA,EAAciC,CAAW,EAE5C,IAAMC,EAAc,CAAC,GAAGf,EAAgBc,CAAW,EAE9ClC,GACHQ,EAAoB2B,CAAW,EAGjC7B,EAAS,EAAE,EACXI,EAAa,EAAI,EAEjB,GAAI,CAGF,IAAM0B,EAA4B,CAChC,KAAM,YACN,QAJW,MAAMV,EAAcS,CAAW,CAK5C,EAEME,EAAkB,CAAC,GAAGF,EAAaC,CAAgB,EACpDpC,IACHQ,EAAoB6B,CAAe,EACnC,aAAa,QAAQ,WAAY,KAAK,UAAUA,CAAe,CAAC,EAEpE,OAASb,EAAO,CACd,QAAQ,MAAM,oBAAqBA,CAAK,EACxC,IAAMc,EAA8B,CAClC,KAAM,YACN,QAAS,wDACX,EACMD,EAAkB,CAAC,GAAGF,EAAaG,CAAkB,EACtDtC,IACHQ,EAAoB6B,CAAe,EACnC,aAAa,QAAQ,WAAY,KAAK,UAAUA,CAAe,CAAC,EAEpE,QAAE,CACA3B,EAAa,EAAK,CACpB,CACF,KAEA,aAAU,IAAM,CACVQ,EAAY,UACdA,EAAY,QAAQ,MAAM,OAAS,OACnCA,EAAY,QAAQ,MAAM,OAAS,GAAG,KAAK,IAAIA,EAAY,QAAQ,aAAc,GAAG,CAAC,KAEzF,EAAG,CAACb,CAAK,CAAC,EAEV,IAAMkC,KAAkB,eAAa,GAAwB,CAC3D,EAAE,eAAe,EACjBvB,EAAc,EAAI,CACpB,EAAG,CAAC,CAAC,EAEL,sBAAU,IAAM,CACd,GAAI,CAACD,EAAY,OAEjB,IAAMyB,EAAmBC,GAAkB,CACzC,GAAI,CAACxB,EAAW,QAAS,OAEzB,IAAMyB,EAAOzB,EAAW,QAAQ,sBAAsB,EAChD0B,EAAWD,EAAK,MAAQD,EAAE,QAC1BG,EAAYF,EAAK,OAASD,EAAE,QAE9BE,EAAW,KAAOA,EAAW,KAC/B7B,EAAe+B,IAAU,CAAE,GAAGA,EAAM,MAAOF,CAAS,EAAE,EAEpDC,EAAY,KAAOA,EAAY,KACjC9B,EAAe+B,IAAU,CAAE,GAAGA,EAAM,OAAQD,CAAU,EAAE,CAE5D,EAEME,EAAgB,IAAM,CAC1B9B,EAAc,EAAK,CACrB,EAEA,cAAO,iBAAiB,YAAawB,CAAe,EACpD,OAAO,iBAAiB,UAAWM,CAAa,EAEzC,IAAM,CACX,OAAO,oBAAoB,YAAaN,CAAe,EACvD,OAAO,oBAAoB,UAAWM,CAAa,CACrD,CACF,EAAG,CAAC/B,CAAU,CAAC,KAGb,QAAC,OACC,IAAKE,EACL,UAAW,sBAAsBF,EAAa,WAAa,EAAE,GAC7D,MAAO,CACL,MAAO,GAAGF,EAAW,KAAK,KAC1B,OAAQ,GAAGA,EAAW,MAAM,KAC5B,SAAUT,CACZ,EAEA,oBAAC,OAAI,UAAU,eAAe,YAAamC,EAAiB,KAC5D,QAAC,OAAI,UAAU,qBACZ,UAAAnB,EAAe,IAAI,CAAC2B,EAAcC,OACjC,OAAC,OAEC,UAAW,WAAWD,EAAI,OAAS,OAAS,OAAS,IAAI,GAExD,SAAAA,EAAI,SAHAC,CAIP,CACD,EACAvC,MAAa,OAAC,OAAI,UAAU,qBAAqB,uBAAW,KAC7D,OAAC,OAAI,IAAKU,EAAgB,GAC5B,KAEA,QAAC,OAAI,UAAU,kBACb,oBAAC,YACC,IAAKD,EACL,KAAM,EACN,YAAY,uBACZ,MAAOb,EACP,UAAY,GAAM,CACZ,EAAE,MAAQ,SAAW,CAAC,EAAE,WAC1B,EAAE,eAAe,EACjB2B,EAAU3B,CAAK,EAEnB,EACA,SAAW,GAAMC,EAAS,EAAE,OAAO,KAAK,EAC1C,KACA,OAAC,UACC,QAAS,IAAM0B,EAAU3B,CAAK,EAC9B,SAAU,CAACA,EAAM,KAAK,GAAKI,EAC3B,UAAU,cAEV,oBAAC,OACC,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAY,IACZ,cAAc,QACd,eAAe,QAEf,oBAAC,QAAK,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,KACrC,OAAC,WAAQ,OAAO,4BAA4B,GAC9C,EACF,GACF,GACF,CAEJ","names":["index_exports","__export","ChatPopup","__toCommonJS","import_react","import_jsx_runtime","ChatPopup","systemPrompt","externalPortfolioData","apiUrl","assistantName","initialMessage","model","externalMessages","onMessageSend","onResponseReceive","mockMode","position","input","setInput","internalMessages","setInternalMessages","isLoading","setIsLoading","internalPortfolioData","setInternalPortfolioData","dimensions","setDimensions","isResizing","setIsResizing","wrapperRef","textareaRef","messagesEndRef","activeMessages","activePortfolioData","saved","data","error","scrollToBottom","getAIResponse","currentMessages","resolve","mockResponses","response","errorData","callModel","userInput","userMessage","newMessages","assistantMessage","updatedMessages","defaultFailMessage","handleMouseDown","handleMouseMove","e","rect","newWidth","newHeight","prev","handleMouseUp","msg","index"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/chat-popup.tsx"],"sourcesContent":["export * from \"./components/chat-popup\";\n","import React, { useState, useRef, useEffect, useCallback } from \"react\";\nimport \"./chat-popup.css\";\nimport Image from \"next/image\";\nimport chatbot from \"../assets/chatbot-black.png\";\n\ntype Message = {\n role: \"user\" | \"assistant\" | \"system\";\n content: string;\n};\n\nexport interface ChatPopupProps {\n systemPrompt?: string;\n portfolioData?: any;\n apiUrl?: string;\n assistantName?: string;\n initialMessage?: string;\n model?: string;\n messages?: Message[];\n onMessageSend?: (message: Message) => void;\n onResponseReceive?: (response: string) => void;\n mockMode?: boolean; // If true, uses mock responses instead of API calls\n position?: \"fixed\" | \"relative\"; // Position style for the wrapper\n}\n\nexport const ChatPopup = ({\n systemPrompt,\n portfolioData: externalPortfolioData,\n apiUrl = \"https://thikana.malaymishra.com/chatbot\",\n assistantName = \"Thikana\",\n initialMessage,\n model,\n messages: externalMessages,\n onMessageSend,\n onResponseReceive,\n mockMode = false,\n position = \"relative\",\n}: ChatPopupProps) => {\n const [input, setInput] = useState<string>(\"\");\n const [internalMessages, setInternalMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [internalPortfolioData, setInternalPortfolioData] = useState<any>(null);\n const [dimensions, setDimensions] = useState({ width: 330, height: 480 });\n const [isResizing, setIsResizing] = useState(false);\n const [openPopup, setOpenPopup] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (\n containerRef.current &&\n !containerRef.current.contains(event.target as Node)\n ) {\n setOpenPopup(false);\n }\n }\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, []);\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n const activeMessages = externalMessages || internalMessages;\n const activePortfolioData = externalPortfolioData || internalPortfolioData;\n\n useEffect(() => {\n if (!externalMessages || externalMessages.length === 0) {\n if (internalMessages.length === 0) {\n const saved = localStorage.getItem(\"messages\");\n if (saved) {\n setInternalMessages(JSON.parse(saved));\n } else {\n setInternalMessages([\n {\n role: \"assistant\",\n content:\n initialMessage ||\n `Hi this is ${assistantName}! How can I help you today?`,\n },\n ]);\n }\n }\n }\n }, [\n externalMessages,\n initialMessage,\n assistantName,\n internalMessages.length,\n ]);\n\n useEffect(() => {\n if (!externalPortfolioData) {\n const fetchPortfolioData = async () => {\n try {\n const response = await fetch(\n \"https://raw.githubusercontent.com/hi-malay/portfolio-data/refs/heads/main/scrapped_data.json\",\n );\n const data = await response.json();\n setInternalPortfolioData(data);\n } catch (error) {\n console.error(\"Error fetching portfolio data:\", error);\n }\n };\n fetchPortfolioData();\n }\n }, [externalPortfolioData]);\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n };\n\n useEffect(() => {\n scrollToBottom();\n }, [activeMessages]);\n\n const getAIResponse = async (currentMessages: Message[]): Promise<string> => {\n // Mock mode for testing without API\n if (mockMode) {\n await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate API delay\n const mockResponses = [\n \"That's an interesting question! Let me help you with that.\",\n \"I understand what you're asking. Here's what I think...\",\n \"Great question! Based on what you've told me, I'd suggest...\",\n \"Let me break that down for you.\",\n \"I'm here to help! Here's my take on that...\",\n ];\n const response =\n mockResponses[Math.floor(Math.random() * mockResponses.length)];\n if (onResponseReceive) onResponseReceive(response);\n return response;\n }\n\n const response = await fetch(apiUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n messages: currentMessages,\n portfolioData: activePortfolioData,\n systemPrompt,\n model,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json();\n throw new Error(errorData.error || \"Failed to get AI response\");\n }\n\n const data = await response.json();\n if (onResponseReceive) onResponseReceive(data.text);\n return data.text;\n };\n\n const callModel = async (userInput: string) => {\n if (!userInput.trim() || isLoading) return;\n\n const userMessage: Message = { role: \"user\", content: userInput };\n if (onMessageSend) onMessageSend(userMessage);\n\n const newMessages = [...activeMessages, userMessage];\n\n if (!externalMessages) {\n setInternalMessages(newMessages);\n }\n\n setInput(\"\");\n setIsLoading(true);\n\n try {\n const text = await getAIResponse(newMessages);\n\n const assistantMessage: Message = {\n role: \"assistant\",\n content: text,\n };\n\n const updatedMessages = [...newMessages, assistantMessage];\n if (!externalMessages) {\n setInternalMessages(updatedMessages);\n localStorage.setItem(\"messages\", JSON.stringify(updatedMessages));\n }\n } catch (error) {\n console.error(\"Error calling AI:\", error);\n const defaultFailMessage: Message = {\n role: \"assistant\",\n content: \"Sorry, I encountered an error. Please try again later.\",\n };\n const updatedMessages = [...newMessages, defaultFailMessage];\n if (!externalMessages) {\n setInternalMessages(updatedMessages);\n localStorage.setItem(\"messages\", JSON.stringify(updatedMessages));\n }\n } finally {\n setIsLoading(false);\n }\n };\n\n useEffect(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = \"auto\";\n textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 100)}px`;\n }\n }, [input]);\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n setIsResizing(true);\n }, []);\n\n useEffect(() => {\n if (!isResizing) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!wrapperRef.current) return;\n\n const rect = wrapperRef.current.getBoundingClientRect();\n const newWidth = rect.right - e.clientX;\n const newHeight = rect.bottom - e.clientY;\n\n if (newWidth > 250 && newWidth < 800) {\n setDimensions((prev) => ({ ...prev, width: newWidth }));\n }\n if (newHeight > 300 && newHeight < 800) {\n setDimensions((prev) => ({ ...prev, height: newHeight }));\n }\n };\n\n const handleMouseUp = () => {\n setIsResizing(false);\n };\n\n window.addEventListener(\"mousemove\", handleMouseMove);\n window.addEventListener(\"mouseup\", handleMouseUp);\n\n return () => {\n window.removeEventListener(\"mousemove\", handleMouseMove);\n window.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }, [isResizing]);\n\n return (\n <div className=\"chatbot-container\" ref={containerRef}>\n {openPopup && (\n <div className=\"chatbot-popup\">\n <div\n ref={wrapperRef}\n className={`chat-popup-wrapper ${isResizing ? \"resizing\" : \"\"}`}\n style={{\n width: `${dimensions.width}px`,\n height: `${dimensions.height}px`,\n position: position,\n }}\n >\n <div className=\"stretch-icon\" onMouseDown={handleMouseDown}></div>\n <div className=\"messages-container\">\n {activeMessages.map((msg: Message, index: number) => (\n <div\n key={index}\n className={`message ${msg.role === \"user\" ? \"user\" : \"ai\"}`}\n >\n {msg.content}\n </div>\n ))}\n {isLoading && (\n <div className=\"message ai loading\">Thinking...</div>\n )}\n <div ref={messagesEndRef} />\n </div>\n\n <div className=\"input-container\">\n <textarea\n ref={textareaRef}\n rows={1}\n placeholder=\"What's on your mind?\"\n value={input}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n callModel(input);\n }\n }}\n onChange={(e) => setInput(e.target.value)}\n />\n <button\n onClick={() => callModel(input)}\n disabled={!input.trim() || isLoading}\n className=\"send-button\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n </button>\n </div>\n </div>\n </div>\n )}\n\n <Image\n onClick={() => setOpenPopup((prev) => !prev)}\n className=\"chatbot-icon\"\n alt=\"chatbot\"\n src={chatbot}\n />\n </div>\n );\n};\n"],"mappings":"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","names":["index_exports","__export","ChatPopup","__toCommonJS","import_react","import_image","import_jsx_runtime","ChatPopup","systemPrompt","externalPortfolioData","apiUrl","assistantName","initialMessage","model","externalMessages","onMessageSend","onResponseReceive","mockMode","position","input","setInput","internalMessages","setInternalMessages","isLoading","setIsLoading","internalPortfolioData","setInternalPortfolioData","dimensions","setDimensions","isResizing","setIsResizing","openPopup","setOpenPopup","containerRef","handleClickOutside","event","wrapperRef","textareaRef","messagesEndRef","activeMessages","activePortfolioData","saved","data","error","scrollToBottom","getAIResponse","currentMessages","resolve","mockResponses","response","errorData","callModel","userInput","userMessage","newMessages","assistantMessage","updatedMessages","defaultFailMessage","handleMouseDown","handleMouseMove","e","rect","newWidth","newHeight","prev","handleMouseUp","msg","index","Image","chatbot_black_default"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{useState as c,useRef as k,useEffect as g,useCallback as F}from"react";import{jsx as r,jsxs as h}from"react/jsx-runtime";var Y=({systemPrompt:C,portfolioData:f,apiUrl:H="https://thikana.malaymishra.com/chatbot",assistantName:M="Thikana",initialMessage:I,model:j,messages:i,onMessageSend:D,onResponseReceive:u,mockMode:R=!1,position:$="relative"})=>{let[l,E]=c(""),[m,d]=c([]),[x,L]=c(!1),[O,A]=c(null),[P,N]=c({width:330,height:480}),[b,T]=c(!1),w=k(null),p=k(null),z=k(null),y=i||m,B=f||O;g(()=>{if((!i||i.length===0)&&m.length===0){let e=localStorage.getItem("messages");d(e?JSON.parse(e):[{role:"assistant",content:I||`Hi this is ${M}! How can I help you today?`}])}},[i,I,M,m.length]),g(()=>{f||(async()=>{try{let o=await(await fetch("https://raw.githubusercontent.com/hi-malay/portfolio-data/refs/heads/main/scrapped_data.json")).json();A(o)}catch(t){console.error("Error fetching portfolio data:",t)}})()},[f]);let J=()=>{z.current?.scrollIntoView({behavior:"smooth"})};g(()=>{J()},[y]);let W=async e=>{if(R){await new Promise(s=>setTimeout(s,1e3));let n=["That's an interesting question! Let me help you with that.","I understand what you're asking. Here's what I think...","Great question! Based on what you've told me, I'd suggest...","Let me break that down for you.","I'm here to help! Here's my take on that..."],a=n[Math.floor(Math.random()*n.length)];return u&&u(a),a}let t=await fetch(H,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({messages:e,portfolioData:B,systemPrompt:C,model:j})});if(!t.ok){let n=await t.json();throw new Error(n.error||"Failed to get AI response")}let o=await t.json();return u&&u(o.text),o.text},S=async e=>{if(!e.trim()||x)return;let t={role:"user",content:e};D&&D(t);let o=[...y,t];i||d(o),E(""),L(!0);try{let a={role:"assistant",content:await W(o)},s=[...o,a];i||(d(s),localStorage.setItem("messages",JSON.stringify(s)))}catch(n){console.error("Error calling AI:",n);let a={role:"assistant",content:"Sorry, I encountered an error. Please try again later."},s=[...o,a];i||(d(s),localStorage.setItem("messages",JSON.stringify(s)))}finally{L(!1)}};g(()=>{p.current&&(p.current.style.height="auto",p.current.style.height=`${Math.min(p.current.scrollHeight,100)}px`)},[l]);let q=F(e=>{e.preventDefault(),T(!0)},[]);return g(()=>{if(!b)return;let e=o=>{if(!w.current)return;let n=w.current.getBoundingClientRect(),a=n.right-o.clientX,s=n.bottom-o.clientY;a>250&&a<800&&N(v=>({...v,width:a})),s>300&&s<800&&N(v=>({...v,height:s}))},t=()=>{T(!1)};return window.addEventListener("mousemove",e),window.addEventListener("mouseup",t),()=>{window.removeEventListener("mousemove",e),window.removeEventListener("mouseup",t)}},[b]),h("div",{ref:w,className:`chat-popup-wrapper ${b?"resizing":""}`,style:{width:`${P.width}px`,height:`${P.height}px`,position:$},children:[r("div",{className:"stretch-icon",onMouseDown:q}),h("div",{className:"messages-container",children:[y.map((e,t)=>r("div",{className:`message ${e.role==="user"?"user":"ai"}`,children:e.content},t)),x&&r("div",{className:"message ai loading",children:"Thinking..."}),r("div",{ref:z})]}),h("div",{className:"input-container",children:[r("textarea",{ref:p,rows:1,placeholder:"What's on your mind?",value:l,onKeyDown:e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),S(l))},onChange:e=>E(e.target.value)}),r("button",{onClick:()=>S(l),disabled:!l.trim()||x,className:"send-button",children:h("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[r("line",{x1:"22",y1:"2",x2:"11",y2:"13"}),r("polygon",{points:"22 2 15 22 11 13 2 9 22 2"})]})})]})]})};export{Y as ChatPopup};
1
+ import{useState as c,useRef as u,useEffect as l,useCallback as G}from"react";import B from"next/image";var R="./chatbot-black-HLEKK2J4.png";import{jsx as s,jsxs as f}from"react/jsx-runtime";var re=({systemPrompt:S,portfolioData:v,apiUrl:C="https://thikana.malaymishra.com/chatbot",assistantName:O="Thikana",initialMessage:y,model:W,messages:i,onMessageSend:k,onResponseReceive:h,mockMode:j=!1,position:A="relative"})=>{let[p,T]=c(""),[m,d]=c([]),[D,L]=c(!1),[X,V]=c(null),[M,P]=c({width:330,height:480}),[w,$]=c(!1),[J,K]=c(!1),b=u(null);l(()=>{function e(t){b.current&&!b.current.contains(t.target)&&K(!1)}return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e)}},[]);let I=u(null),g=u(null),_=u(null),x=i||m,E=v||X;l(()=>{if((!i||i.length===0)&&m.length===0){let e=localStorage.getItem("messages");d(e?JSON.parse(e):[{role:"assistant",content:y||`Hi this is ${O}! How can I help you today?`}])}},[i,y,O,m.length]),l(()=>{v||(async()=>{try{let o=await(await fetch("https://raw.githubusercontent.com/hi-malay/portfolio-data/refs/heads/main/scrapped_data.json")).json();V(o)}catch(t){console.error("Error fetching portfolio data:",t)}})()},[v]);let Z=()=>{_.current?.scrollIntoView({behavior:"smooth"})};l(()=>{Z()},[x]);let Y=async e=>{if(j){await new Promise(n=>setTimeout(n,1e3));let a=["That's an interesting question! Let me help you with that.","I understand what you're asking. Here's what I think...","Great question! Based on what you've told me, I'd suggest...","Let me break that down for you.","I'm here to help! Here's my take on that..."],r=a[Math.floor(Math.random()*a.length)];return h&&h(r),r}let t=await fetch(C,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({messages:e,portfolioData:E,systemPrompt:S,model:W})});if(!t.ok){let a=await t.json();throw new Error(a.error||"Failed to get AI response")}let o=await t.json();return h&&h(o.text),o.text},N=async e=>{if(!e.trim()||D)return;let t={role:"user",content:e};k&&k(t);let o=[...x,t];i||d(o),T(""),L(!0);try{let r={role:"assistant",content:await Y(o)},n=[...o,r];i||(d(n),localStorage.setItem("messages",JSON.stringify(n)))}catch(a){console.error("Error calling AI:",a);let r={role:"assistant",content:"Sorry, I encountered an error. Please try again later."},n=[...o,r];i||(d(n),localStorage.setItem("messages",JSON.stringify(n)))}finally{L(!1)}};l(()=>{g.current&&(g.current.style.height="auto",g.current.style.height=`${Math.min(g.current.scrollHeight,100)}px`)},[p]);let U=G(e=>{e.preventDefault(),$(!0)},[]);return l(()=>{if(!w)return;let e=o=>{if(!I.current)return;let a=I.current.getBoundingClientRect(),r=a.right-o.clientX,n=a.bottom-o.clientY;r>250&&r<800&&P(H=>({...H,width:r})),n>300&&n<800&&P(H=>({...H,height:n}))},t=()=>{$(!1)};return window.addEventListener("mousemove",e),window.addEventListener("mouseup",t),()=>{window.removeEventListener("mousemove",e),window.removeEventListener("mouseup",t)}},[w]),f("div",{className:"chatbot-container",ref:b,children:[J&&s("div",{className:"chatbot-popup",children:f("div",{ref:I,className:`chat-popup-wrapper ${w?"resizing":""}`,style:{width:`${M.width}px`,height:`${M.height}px`,position:A},children:[s("div",{className:"stretch-icon",onMouseDown:U}),f("div",{className:"messages-container",children:[x.map((e,t)=>s("div",{className:`message ${e.role==="user"?"user":"ai"}`,children:e.content},t)),D&&s("div",{className:"message ai loading",children:"Thinking..."}),s("div",{ref:_})]}),f("div",{className:"input-container",children:[s("textarea",{ref:g,rows:1,placeholder:"What's on your mind?",value:p,onKeyDown:e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),N(p))},onChange:e=>T(e.target.value)}),s("button",{onClick:()=>N(p),disabled:!p.trim()||D,className:"send-button",children:f("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s("line",{x1:"22",y1:"2",x2:"11",y2:"13"}),s("polygon",{points:"22 2 15 22 11 13 2 9 22 2"})]})})]})]})}),s(B,{onClick:()=>K(e=>!e),className:"chatbot-icon",alt:"chatbot",src:R})]})};export{re as ChatPopup};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/chat-popup.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from \"react\";\nimport \"./chat-popup.css\";\n\ntype Message = {\n role: \"user\" | \"assistant\" | \"system\";\n content: string;\n};\n\nexport interface ChatPopupProps {\n systemPrompt?: string;\n portfolioData?: any;\n apiUrl?: string;\n assistantName?: string;\n initialMessage?: string;\n model?: string;\n messages?: Message[];\n onMessageSend?: (message: Message) => void;\n onResponseReceive?: (response: string) => void;\n mockMode?: boolean; // If true, uses mock responses instead of API calls\n position?: \"fixed\" | \"relative\"; // Position style for the wrapper\n}\n\nexport const ChatPopup = ({\n systemPrompt,\n portfolioData: externalPortfolioData,\n apiUrl = \"https://thikana.malaymishra.com/chatbot\",\n assistantName = \"Thikana\",\n initialMessage,\n model,\n messages: externalMessages,\n onMessageSend,\n onResponseReceive,\n mockMode = false,\n position = \"relative\",\n}: ChatPopupProps) => {\n const [input, setInput] = useState<string>(\"\");\n const [internalMessages, setInternalMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [internalPortfolioData, setInternalPortfolioData] = useState<any>(null);\n const [dimensions, setDimensions] = useState({ width: 330, height: 480 });\n const [isResizing, setIsResizing] = useState(false);\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n const activeMessages = externalMessages || internalMessages;\n const activePortfolioData = externalPortfolioData || internalPortfolioData;\n\n useEffect(() => {\n if (!externalMessages || externalMessages.length === 0) {\n if (internalMessages.length === 0) {\n const saved = localStorage.getItem(\"messages\");\n if (saved) {\n setInternalMessages(JSON.parse(saved));\n } else {\n setInternalMessages([\n {\n role: \"assistant\",\n content:\n initialMessage ||\n `Hi this is ${assistantName}! How can I help you today?`,\n },\n ]);\n }\n }\n }\n }, [\n externalMessages,\n initialMessage,\n assistantName,\n internalMessages.length,\n ]);\n\n useEffect(() => {\n if (!externalPortfolioData) {\n const fetchPortfolioData = async () => {\n try {\n const response = await fetch(\n \"https://raw.githubusercontent.com/hi-malay/portfolio-data/refs/heads/main/scrapped_data.json\",\n );\n const data = await response.json();\n setInternalPortfolioData(data);\n } catch (error) {\n console.error(\"Error fetching portfolio data:\", error);\n }\n };\n fetchPortfolioData();\n }\n }, [externalPortfolioData]);\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n };\n\n useEffect(() => {\n scrollToBottom();\n }, [activeMessages]);\n\n const getAIResponse = async (currentMessages: Message[]): Promise<string> => {\n // Mock mode for testing without API\n if (mockMode) {\n await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate API delay\n const mockResponses = [\n \"That's an interesting question! Let me help you with that.\",\n \"I understand what you're asking. Here's what I think...\",\n \"Great question! Based on what you've told me, I'd suggest...\",\n \"Let me break that down for you.\",\n \"I'm here to help! Here's my take on that...\",\n ];\n const response =\n mockResponses[Math.floor(Math.random() * mockResponses.length)];\n if (onResponseReceive) onResponseReceive(response);\n return response;\n }\n\n const response = await fetch(apiUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n messages: currentMessages,\n portfolioData: activePortfolioData,\n systemPrompt,\n model,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json();\n throw new Error(errorData.error || \"Failed to get AI response\");\n }\n\n const data = await response.json();\n if (onResponseReceive) onResponseReceive(data.text);\n return data.text;\n };\n\n const callModel = async (userInput: string) => {\n if (!userInput.trim() || isLoading) return;\n\n const userMessage: Message = { role: \"user\", content: userInput };\n if (onMessageSend) onMessageSend(userMessage);\n\n const newMessages = [...activeMessages, userMessage];\n\n if (!externalMessages) {\n setInternalMessages(newMessages);\n }\n\n setInput(\"\");\n setIsLoading(true);\n\n try {\n const text = await getAIResponse(newMessages);\n\n const assistantMessage: Message = {\n role: \"assistant\",\n content: text,\n };\n\n const updatedMessages = [...newMessages, assistantMessage];\n if (!externalMessages) {\n setInternalMessages(updatedMessages);\n localStorage.setItem(\"messages\", JSON.stringify(updatedMessages));\n }\n } catch (error) {\n console.error(\"Error calling AI:\", error);\n const defaultFailMessage: Message = {\n role: \"assistant\",\n content: \"Sorry, I encountered an error. Please try again later.\",\n };\n const updatedMessages = [...newMessages, defaultFailMessage];\n if (!externalMessages) {\n setInternalMessages(updatedMessages);\n localStorage.setItem(\"messages\", JSON.stringify(updatedMessages));\n }\n } finally {\n setIsLoading(false);\n }\n };\n\n useEffect(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = \"auto\";\n textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 100)}px`;\n }\n }, [input]);\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n setIsResizing(true);\n }, []);\n\n useEffect(() => {\n if (!isResizing) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!wrapperRef.current) return;\n\n const rect = wrapperRef.current.getBoundingClientRect();\n const newWidth = rect.right - e.clientX;\n const newHeight = rect.bottom - e.clientY;\n\n if (newWidth > 250 && newWidth < 800) {\n setDimensions((prev) => ({ ...prev, width: newWidth }));\n }\n if (newHeight > 300 && newHeight < 800) {\n setDimensions((prev) => ({ ...prev, height: newHeight }));\n }\n };\n\n const handleMouseUp = () => {\n setIsResizing(false);\n };\n\n window.addEventListener(\"mousemove\", handleMouseMove);\n window.addEventListener(\"mouseup\", handleMouseUp);\n\n return () => {\n window.removeEventListener(\"mousemove\", handleMouseMove);\n window.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }, [isResizing]);\n\n return (\n <div\n ref={wrapperRef}\n className={`chat-popup-wrapper ${isResizing ? \"resizing\" : \"\"}`}\n style={{\n width: `${dimensions.width}px`,\n height: `${dimensions.height}px`,\n position: position,\n }}\n >\n <div className=\"stretch-icon\" onMouseDown={handleMouseDown}></div>\n <div className=\"messages-container\">\n {activeMessages.map((msg: Message, index: number) => (\n <div\n key={index}\n className={`message ${msg.role === \"user\" ? \"user\" : \"ai\"}`}\n >\n {msg.content}\n </div>\n ))}\n {isLoading && <div className=\"message ai loading\">Thinking...</div>}\n <div ref={messagesEndRef} />\n </div>\n\n <div className=\"input-container\">\n <textarea\n ref={textareaRef}\n rows={1}\n placeholder=\"What's on your mind?\"\n value={input}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n callModel(input);\n }\n }}\n onChange={(e) => setInput(e.target.value)}\n />\n <button\n onClick={() => callModel(input)}\n disabled={!input.trim() || isLoading}\n className=\"send-button\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n </button>\n </div>\n </div>\n );\n};\n"],"mappings":"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","names":["useState","useRef","useEffect","useCallback","jsx","jsxs","ChatPopup","systemPrompt","externalPortfolioData","apiUrl","assistantName","initialMessage","model","externalMessages","onMessageSend","onResponseReceive","mockMode","position","input","setInput","useState","internalMessages","setInternalMessages","isLoading","setIsLoading","internalPortfolioData","setInternalPortfolioData","dimensions","setDimensions","isResizing","setIsResizing","wrapperRef","useRef","textareaRef","messagesEndRef","activeMessages","activePortfolioData","useEffect","saved","data","error","scrollToBottom","getAIResponse","currentMessages","resolve","mockResponses","response","errorData","callModel","userInput","userMessage","newMessages","assistantMessage","updatedMessages","defaultFailMessage","handleMouseDown","useCallback","handleMouseMove","e","rect","newWidth","newHeight","prev","handleMouseUp","msg","index"]}
1
+ {"version":3,"sources":["../src/components/chat-popup.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from \"react\";\nimport \"./chat-popup.css\";\nimport Image from \"next/image\";\nimport chatbot from \"../assets/chatbot-black.png\";\n\ntype Message = {\n role: \"user\" | \"assistant\" | \"system\";\n content: string;\n};\n\nexport interface ChatPopupProps {\n systemPrompt?: string;\n portfolioData?: any;\n apiUrl?: string;\n assistantName?: string;\n initialMessage?: string;\n model?: string;\n messages?: Message[];\n onMessageSend?: (message: Message) => void;\n onResponseReceive?: (response: string) => void;\n mockMode?: boolean; // If true, uses mock responses instead of API calls\n position?: \"fixed\" | \"relative\"; // Position style for the wrapper\n}\n\nexport const ChatPopup = ({\n systemPrompt,\n portfolioData: externalPortfolioData,\n apiUrl = \"https://thikana.malaymishra.com/chatbot\",\n assistantName = \"Thikana\",\n initialMessage,\n model,\n messages: externalMessages,\n onMessageSend,\n onResponseReceive,\n mockMode = false,\n position = \"relative\",\n}: ChatPopupProps) => {\n const [input, setInput] = useState<string>(\"\");\n const [internalMessages, setInternalMessages] = useState<Message[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [internalPortfolioData, setInternalPortfolioData] = useState<any>(null);\n const [dimensions, setDimensions] = useState({ width: 330, height: 480 });\n const [isResizing, setIsResizing] = useState(false);\n const [openPopup, setOpenPopup] = useState(false);\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (\n containerRef.current &&\n !containerRef.current.contains(event.target as Node)\n ) {\n setOpenPopup(false);\n }\n }\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, []);\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n\n const activeMessages = externalMessages || internalMessages;\n const activePortfolioData = externalPortfolioData || internalPortfolioData;\n\n useEffect(() => {\n if (!externalMessages || externalMessages.length === 0) {\n if (internalMessages.length === 0) {\n const saved = localStorage.getItem(\"messages\");\n if (saved) {\n setInternalMessages(JSON.parse(saved));\n } else {\n setInternalMessages([\n {\n role: \"assistant\",\n content:\n initialMessage ||\n `Hi this is ${assistantName}! How can I help you today?`,\n },\n ]);\n }\n }\n }\n }, [\n externalMessages,\n initialMessage,\n assistantName,\n internalMessages.length,\n ]);\n\n useEffect(() => {\n if (!externalPortfolioData) {\n const fetchPortfolioData = async () => {\n try {\n const response = await fetch(\n \"https://raw.githubusercontent.com/hi-malay/portfolio-data/refs/heads/main/scrapped_data.json\",\n );\n const data = await response.json();\n setInternalPortfolioData(data);\n } catch (error) {\n console.error(\"Error fetching portfolio data:\", error);\n }\n };\n fetchPortfolioData();\n }\n }, [externalPortfolioData]);\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n };\n\n useEffect(() => {\n scrollToBottom();\n }, [activeMessages]);\n\n const getAIResponse = async (currentMessages: Message[]): Promise<string> => {\n // Mock mode for testing without API\n if (mockMode) {\n await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate API delay\n const mockResponses = [\n \"That's an interesting question! Let me help you with that.\",\n \"I understand what you're asking. Here's what I think...\",\n \"Great question! Based on what you've told me, I'd suggest...\",\n \"Let me break that down for you.\",\n \"I'm here to help! Here's my take on that...\",\n ];\n const response =\n mockResponses[Math.floor(Math.random() * mockResponses.length)];\n if (onResponseReceive) onResponseReceive(response);\n return response;\n }\n\n const response = await fetch(apiUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n messages: currentMessages,\n portfolioData: activePortfolioData,\n systemPrompt,\n model,\n }),\n });\n\n if (!response.ok) {\n const errorData = await response.json();\n throw new Error(errorData.error || \"Failed to get AI response\");\n }\n\n const data = await response.json();\n if (onResponseReceive) onResponseReceive(data.text);\n return data.text;\n };\n\n const callModel = async (userInput: string) => {\n if (!userInput.trim() || isLoading) return;\n\n const userMessage: Message = { role: \"user\", content: userInput };\n if (onMessageSend) onMessageSend(userMessage);\n\n const newMessages = [...activeMessages, userMessage];\n\n if (!externalMessages) {\n setInternalMessages(newMessages);\n }\n\n setInput(\"\");\n setIsLoading(true);\n\n try {\n const text = await getAIResponse(newMessages);\n\n const assistantMessage: Message = {\n role: \"assistant\",\n content: text,\n };\n\n const updatedMessages = [...newMessages, assistantMessage];\n if (!externalMessages) {\n setInternalMessages(updatedMessages);\n localStorage.setItem(\"messages\", JSON.stringify(updatedMessages));\n }\n } catch (error) {\n console.error(\"Error calling AI:\", error);\n const defaultFailMessage: Message = {\n role: \"assistant\",\n content: \"Sorry, I encountered an error. Please try again later.\",\n };\n const updatedMessages = [...newMessages, defaultFailMessage];\n if (!externalMessages) {\n setInternalMessages(updatedMessages);\n localStorage.setItem(\"messages\", JSON.stringify(updatedMessages));\n }\n } finally {\n setIsLoading(false);\n }\n };\n\n useEffect(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = \"auto\";\n textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 100)}px`;\n }\n }, [input]);\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n setIsResizing(true);\n }, []);\n\n useEffect(() => {\n if (!isResizing) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n if (!wrapperRef.current) return;\n\n const rect = wrapperRef.current.getBoundingClientRect();\n const newWidth = rect.right - e.clientX;\n const newHeight = rect.bottom - e.clientY;\n\n if (newWidth > 250 && newWidth < 800) {\n setDimensions((prev) => ({ ...prev, width: newWidth }));\n }\n if (newHeight > 300 && newHeight < 800) {\n setDimensions((prev) => ({ ...prev, height: newHeight }));\n }\n };\n\n const handleMouseUp = () => {\n setIsResizing(false);\n };\n\n window.addEventListener(\"mousemove\", handleMouseMove);\n window.addEventListener(\"mouseup\", handleMouseUp);\n\n return () => {\n window.removeEventListener(\"mousemove\", handleMouseMove);\n window.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }, [isResizing]);\n\n return (\n <div className=\"chatbot-container\" ref={containerRef}>\n {openPopup && (\n <div className=\"chatbot-popup\">\n <div\n ref={wrapperRef}\n className={`chat-popup-wrapper ${isResizing ? \"resizing\" : \"\"}`}\n style={{\n width: `${dimensions.width}px`,\n height: `${dimensions.height}px`,\n position: position,\n }}\n >\n <div className=\"stretch-icon\" onMouseDown={handleMouseDown}></div>\n <div className=\"messages-container\">\n {activeMessages.map((msg: Message, index: number) => (\n <div\n key={index}\n className={`message ${msg.role === \"user\" ? \"user\" : \"ai\"}`}\n >\n {msg.content}\n </div>\n ))}\n {isLoading && (\n <div className=\"message ai loading\">Thinking...</div>\n )}\n <div ref={messagesEndRef} />\n </div>\n\n <div className=\"input-container\">\n <textarea\n ref={textareaRef}\n rows={1}\n placeholder=\"What's on your mind?\"\n value={input}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n callModel(input);\n }\n }}\n onChange={(e) => setInput(e.target.value)}\n />\n <button\n onClick={() => callModel(input)}\n disabled={!input.trim() || isLoading}\n className=\"send-button\"\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n </button>\n </div>\n </div>\n </div>\n )}\n\n <Image\n onClick={() => setOpenPopup((prev) => !prev)}\n className=\"chatbot-icon\"\n alt=\"chatbot\"\n src={chatbot}\n />\n </div>\n );\n};\n"],"mappings":"AAAA,OAAgB,YAAAA,EAAU,UAAAC,EAAQ,aAAAC,EAAW,eAAAC,MAAmB,QAEhE,OAAOC,MAAW,a,qCAkQN,cAAAC,EACA,QAAAC,MADA,oBA5OL,IAAMC,GAAY,CAAC,CACxB,aAAAC,EACA,cAAeC,EACf,OAAAC,EAAS,0CACT,cAAAC,EAAgB,UAChB,eAAAC,EACA,MAAAC,EACA,SAAUC,EACV,cAAAC,EACA,kBAAAC,EACA,SAAAC,EAAW,GACX,SAAAC,EAAW,UACb,IAAsB,CACpB,GAAM,CAACC,EAAOC,CAAQ,EAAIC,EAAiB,EAAE,EACvC,CAACC,EAAkBC,CAAmB,EAAIF,EAAoB,CAAC,CAAC,EAChE,CAACG,EAAWC,CAAY,EAAIJ,EAAS,EAAK,EAC1C,CAACK,EAAuBC,CAAwB,EAAIN,EAAc,IAAI,EACtE,CAACO,EAAYC,CAAa,EAAIR,EAAS,CAAE,MAAO,IAAK,OAAQ,GAAI,CAAC,EAClE,CAACS,EAAYC,CAAa,EAAIV,EAAS,EAAK,EAC5C,CAACW,EAAWC,CAAY,EAAIZ,EAAS,EAAK,EAC1Ca,EAAeC,EAAuB,IAAI,EAEhDC,EAAU,IAAM,CACd,SAASC,EAAmBC,EAAmB,CAE3CJ,EAAa,SACb,CAACA,EAAa,QAAQ,SAASI,EAAM,MAAc,GAEnDL,EAAa,EAAK,CAEtB,CAEA,gBAAS,iBAAiB,YAAaI,CAAkB,EAClD,IAAM,CACX,SAAS,oBAAoB,YAAaA,CAAkB,CAC9D,CACF,EAAG,CAAC,CAAC,EAEL,IAAME,EAAaJ,EAAuB,IAAI,EAExCK,EAAcL,EAA4B,IAAI,EAC9CM,EAAiBN,EAAuB,IAAI,EAE5CO,EAAiB5B,GAAoBQ,EACrCqB,EAAsBlC,GAAyBiB,EAErDU,EAAU,IAAM,CACd,IAAI,CAACtB,GAAoBA,EAAiB,SAAW,IAC/CQ,EAAiB,SAAW,EAAG,CACjC,IAAMsB,EAAQ,aAAa,QAAQ,UAAU,EAE3CrB,EADEqB,EACkB,KAAK,MAAMA,CAAK,EAEhB,CAClB,CACE,KAAM,YACN,QACEhC,GACA,cAAcD,CAAa,6BAC/B,CACF,CATqC,CAWzC,CAEJ,EAAG,CACDG,EACAF,EACAD,EACAW,EAAiB,MACnB,CAAC,EAEDc,EAAU,IAAM,CACT3B,IACwB,SAAY,CACrC,GAAI,CAIF,IAAMoC,EAAO,MAHI,MAAM,MACrB,8FACF,GAC4B,KAAK,EACjClB,EAAyBkB,CAAI,CAC/B,OAASC,EAAO,CACd,QAAQ,MAAM,iCAAkCA,CAAK,CACvD,CACF,GACmB,CAEvB,EAAG,CAACrC,CAAqB,CAAC,EAE1B,IAAMsC,EAAiB,IAAM,CAC3BN,EAAe,SAAS,eAAe,CAAE,SAAU,QAAS,CAAC,CAC/D,EAEAL,EAAU,IAAM,CACdW,EAAe,CACjB,EAAG,CAACL,CAAc,CAAC,EAEnB,IAAMM,EAAgB,MAAOC,GAAgD,CAE3E,GAAIhC,EAAU,CACZ,MAAM,IAAI,QAASiC,GAAY,WAAWA,EAAS,GAAI,CAAC,EACxD,IAAMC,EAAgB,CACpB,6DACA,0DACA,+DACA,kCACA,6CACF,EACMC,EACJD,EAAc,KAAK,MAAM,KAAK,OAAO,EAAIA,EAAc,MAAM,CAAC,EAChE,OAAInC,GAAmBA,EAAkBoC,CAAQ,EAC1CA,CACT,CAEA,IAAMA,EAAW,MAAM,MAAM1C,EAAQ,CACnC,OAAQ,OACR,QAAS,CACP,eAAgB,kBAClB,EACA,KAAM,KAAK,UAAU,CACnB,SAAUuC,EACV,cAAeN,EACf,aAAAnC,EACA,MAAAK,CACF,CAAC,CACH,CAAC,EAED,GAAI,CAACuC,EAAS,GAAI,CAChB,IAAMC,EAAY,MAAMD,EAAS,KAAK,EACtC,MAAM,IAAI,MAAMC,EAAU,OAAS,2BAA2B,CAChE,CAEA,IAAMR,EAAO,MAAMO,EAAS,KAAK,EACjC,OAAIpC,GAAmBA,EAAkB6B,EAAK,IAAI,EAC3CA,EAAK,IACd,EAEMS,EAAY,MAAOC,GAAsB,CAC7C,GAAI,CAACA,EAAU,KAAK,GAAK/B,EAAW,OAEpC,IAAMgC,EAAuB,CAAE,KAAM,OAAQ,QAASD,CAAU,EAC5DxC,GAAeA,EAAcyC,CAAW,EAE5C,IAAMC,EAAc,CAAC,GAAGf,EAAgBc,CAAW,EAE9C1C,GACHS,EAAoBkC,CAAW,EAGjCrC,EAAS,EAAE,EACXK,EAAa,EAAI,EAEjB,GAAI,CAGF,IAAMiC,EAA4B,CAChC,KAAM,YACN,QAJW,MAAMV,EAAcS,CAAW,CAK5C,EAEME,EAAkB,CAAC,GAAGF,EAAaC,CAAgB,EACpD5C,IACHS,EAAoBoC,CAAe,EACnC,aAAa,QAAQ,WAAY,KAAK,UAAUA,CAAe,CAAC,EAEpE,OAASb,EAAO,CACd,QAAQ,MAAM,oBAAqBA,CAAK,EACxC,IAAMc,EAA8B,CAClC,KAAM,YACN,QAAS,wDACX,EACMD,EAAkB,CAAC,GAAGF,EAAaG,CAAkB,EACtD9C,IACHS,EAAoBoC,CAAe,EACnC,aAAa,QAAQ,WAAY,KAAK,UAAUA,CAAe,CAAC,EAEpE,QAAE,CACAlC,EAAa,EAAK,CACpB,CACF,EAEAW,EAAU,IAAM,CACVI,EAAY,UACdA,EAAY,QAAQ,MAAM,OAAS,OACnCA,EAAY,QAAQ,MAAM,OAAS,GAAG,KAAK,IAAIA,EAAY,QAAQ,aAAc,GAAG,CAAC,KAEzF,EAAG,CAACrB,CAAK,CAAC,EAEV,IAAM0C,EAAkBC,EAAa,GAAwB,CAC3D,EAAE,eAAe,EACjB/B,EAAc,EAAI,CACpB,EAAG,CAAC,CAAC,EAEL,OAAAK,EAAU,IAAM,CACd,GAAI,CAACN,EAAY,OAEjB,IAAMiC,EAAmBC,GAAkB,CACzC,GAAI,CAACzB,EAAW,QAAS,OAEzB,IAAM0B,EAAO1B,EAAW,QAAQ,sBAAsB,EAChD2B,EAAWD,EAAK,MAAQD,EAAE,QAC1BG,EAAYF,EAAK,OAASD,EAAE,QAE9BE,EAAW,KAAOA,EAAW,KAC/BrC,EAAeuC,IAAU,CAAE,GAAGA,EAAM,MAAOF,CAAS,EAAE,EAEpDC,EAAY,KAAOA,EAAY,KACjCtC,EAAeuC,IAAU,CAAE,GAAGA,EAAM,OAAQD,CAAU,EAAE,CAE5D,EAEME,EAAgB,IAAM,CAC1BtC,EAAc,EAAK,CACrB,EAEA,cAAO,iBAAiB,YAAagC,CAAe,EACpD,OAAO,iBAAiB,UAAWM,CAAa,EAEzC,IAAM,CACX,OAAO,oBAAoB,YAAaN,CAAe,EACvD,OAAO,oBAAoB,UAAWM,CAAa,CACrD,CACF,EAAG,CAACvC,CAAU,CAAC,EAGbxB,EAAC,OAAI,UAAU,oBAAoB,IAAK4B,EACrC,UAAAF,GACC3B,EAAC,OAAI,UAAU,gBACb,SAAAC,EAAC,OACC,IAAKiC,EACL,UAAW,sBAAsBT,EAAa,WAAa,EAAE,GAC7D,MAAO,CACL,MAAO,GAAGF,EAAW,KAAK,KAC1B,OAAQ,GAAGA,EAAW,MAAM,KAC5B,SAAUV,CACZ,EAEA,UAAAb,EAAC,OAAI,UAAU,eAAe,YAAawD,EAAiB,EAC5DvD,EAAC,OAAI,UAAU,qBACZ,UAAAoC,EAAe,IAAI,CAAC4B,EAAcC,IACjClE,EAAC,OAEC,UAAW,WAAWiE,EAAI,OAAS,OAAS,OAAS,IAAI,GAExD,SAAAA,EAAI,SAHAC,CAIP,CACD,EACA/C,GACCnB,EAAC,OAAI,UAAU,qBAAqB,uBAAW,EAEjDA,EAAC,OAAI,IAAKoC,EAAgB,GAC5B,EAEAnC,EAAC,OAAI,UAAU,kBACb,UAAAD,EAAC,YACC,IAAKmC,EACL,KAAM,EACN,YAAY,uBACZ,MAAOrB,EACP,UAAY,GAAM,CACZ,EAAE,MAAQ,SAAW,CAAC,EAAE,WAC1B,EAAE,eAAe,EACjBmC,EAAUnC,CAAK,EAEnB,EACA,SAAW,GAAMC,EAAS,EAAE,OAAO,KAAK,EAC1C,EACAf,EAAC,UACC,QAAS,IAAMiD,EAAUnC,CAAK,EAC9B,SAAU,CAACA,EAAM,KAAK,GAAKK,EAC3B,UAAU,cAEV,SAAAlB,EAAC,OACC,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACL,OAAO,eACP,YAAY,IACZ,cAAc,QACd,eAAe,QAEf,UAAAD,EAAC,QAAK,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,EACrCA,EAAC,WAAQ,OAAO,4BAA4B,GAC9C,EACF,GACF,GACF,EACF,EAGFA,EAACmE,EAAA,CACC,QAAS,IAAMvC,EAAcmC,GAAS,CAACA,CAAI,EAC3C,UAAU,eACV,IAAI,UACJ,IAAKK,EACP,GACF,CAEJ","names":["useState","useRef","useEffect","useCallback","Image","jsx","jsxs","ChatPopup","systemPrompt","externalPortfolioData","apiUrl","assistantName","initialMessage","model","externalMessages","onMessageSend","onResponseReceive","mockMode","position","input","setInput","useState","internalMessages","setInternalMessages","isLoading","setIsLoading","internalPortfolioData","setInternalPortfolioData","dimensions","setDimensions","isResizing","setIsResizing","openPopup","setOpenPopup","containerRef","useRef","useEffect","handleClickOutside","event","wrapperRef","textareaRef","messagesEndRef","activeMessages","activePortfolioData","saved","data","error","scrollToBottom","getAIResponse","currentMessages","resolve","mockResponses","response","errorData","callModel","userInput","userMessage","newMessages","assistantMessage","updatedMessages","defaultFailMessage","handleMouseDown","useCallback","handleMouseMove","e","rect","newWidth","newHeight","prev","handleMouseUp","msg","index","Image","chatbot_black_default"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thikanaa",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "A beautiful, AI-powered chat popup component for React and Next.js applications",
5
5
  "keywords": [
6
6
  "react",