UNPKG

@botforge/widget

Version:

Official BotForge chatbot widget for easy integration into any website or web application

3 lines (2 loc) 36.1 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react/jsx-runtime"),require("react"),require("react-dom/client")):"function"==typeof define&&define.amd?define(["exports","react/jsx-runtime","react","react-dom/client"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).BotForge={},e.jsxRuntime,e.React,e.ReactDOM)}(this,(function(e,t,o,n){"use strict";function i(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(o){if("default"!==o){var n=Object.getOwnPropertyDescriptor(e,o);Object.defineProperty(t,o,n.get?n:{enumerable:!0,get:function(){return e[o]}})}})),t.default=e,Object.freeze(t)}var r=i(n);const s=({messages:e,onSendMessage:n,onFileUpload:i,onClose:r,onRestart:s,isLoading:a,isConnected:l,config:d,error:c,isInitialized:u,conversationId:g})=>{var h,p,f,x;const[b,v]=o.useState(""),[m,y]=o.useState(!1),w=o.useRef(null),I=o.useRef(null),C=o.useRef(null);o.useEffect((()=>{var e;null===(e=w.current)||void 0===e||e.scrollIntoView({behavior:"smooth"})}),[e]),o.useEffect((()=>{I.current&&u&&I.current.focus()}),[u]);const j=e=>{e.preventDefault(),b.trim()&&!a&&u&&g&&(d.debug&&console.log("[BotForge Widget] Submitting message:",b.trim()),n(b.trim()),v(""))},k=u&&g&&!a,M={width:(null===(h=d.theme)||void 0===h?void 0:h.chatWidth)||"400px",height:(null===(p=d.theme)||void 0===p?void 0:p.chatHeight)||"600px",backgroundColor:"#1f2937",border:"1px solid #374151",borderRadius:"16px",boxShadow:"0 25px 50px -12px rgba(0, 0, 0, 0.25)",display:"flex",flexDirection:"column",marginBottom:"80px",overflow:"hidden",fontFamily:(null===(f=d.theme)||void 0===f?void 0:f.fontFamily)||'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'},F=l?c?"Connection issues - Using offline responses":null:"Offline mode - Limited functionality";return d.debug&&console.log("[BotForge Widget] ChatWindow render:",{messagesCount:e.length,inputValue:b,isLoading:a,isConnected:l,isInitialized:u,conversationId:g,isChatReady:k}),t.jsxs("div",{style:M,children:[t.jsxs("div",{style:{backgroundColor:"#1f2937",color:"#f3f4f6",padding:"20px",display:"flex",justifyContent:"space-between",alignItems:"center",borderBottom:"1px solid #374151"},children:[t.jsxs("div",{children:[t.jsx("div",{style:{fontWeight:"600",fontSize:"18px",color:"#f3f4f6",marginBottom:"4px"},children:d.title||"BotForge Support"}),d.subtitle&&t.jsx("div",{style:{fontSize:"14px",color:"#9ca3af"},children:d.subtitle}),t.jsxs("div",{style:{display:"flex",alignItems:"center",marginTop:"8px",fontSize:"12px",color:l?"#10b981":"#ef4444"},children:[t.jsx("div",{style:{width:"8px",height:"8px",backgroundColor:l?"#10b981":"#ef4444",borderRadius:"50%",marginRight:"6px"}}),l?"Online":"Offline"]})]}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px"},children:[s&&t.jsx("button",{onClick:s,style:{background:"none",border:"none",color:"#9ca3af",fontSize:"18px",cursor:"pointer",padding:"8px",borderRadius:"8px",transition:"all 0.2s ease",display:"flex",alignItems:"center",justifyContent:"center",width:"40px",height:"40px"},onMouseEnter:e=>{e.currentTarget.style.backgroundColor="#374151",e.currentTarget.style.color="#f3f4f6"},onMouseLeave:e=>{e.currentTarget.style.backgroundColor="transparent",e.currentTarget.style.color="#9ca3af"},title:"Restart chat",children:t.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[t.jsx("path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"}),t.jsx("path",{d:"M21 3v5h-5"}),t.jsx("path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"}),t.jsx("path",{d:"M8 16H3v5"})]})}),t.jsx("button",{onClick:r,style:{background:"none",border:"none",color:"#9ca3af",fontSize:"24px",cursor:"pointer",padding:"8px",borderRadius:"8px",transition:"all 0.2s ease",display:"flex",alignItems:"center",justifyContent:"center",width:"40px",height:"40px"},onMouseEnter:e=>{e.currentTarget.style.backgroundColor="#374151",e.currentTarget.style.color="#f3f4f6"},onMouseLeave:e=>{e.currentTarget.style.backgroundColor="transparent",e.currentTarget.style.color="#9ca3af"},children:"×"})]})]}),F&&t.jsxs("div",{style:{padding:"12px 20px",backgroundColor:l?"#fef3c7":"#fee2e2",color:l?"#92400e":"#991b1b",fontSize:"13px",textAlign:"center",display:"flex",alignItems:"center",justifyContent:"center",gap:"8px"},children:[t.jsx("div",{style:{width:"8px",height:"8px",borderRadius:"50%",backgroundColor:l?"#f59e0b":"#ef4444"}}),F]}),t.jsxs("div",{style:{flex:1,overflowY:"auto",padding:"20px",display:"flex",flexDirection:"column",gap:"16px",backgroundColor:"#111827",position:"relative"},onDragOver:d.enableFileUpload?e=>{e.preventDefault(),y(!0)}:void 0,onDragLeave:d.enableFileUpload?e=>{e.preventDefault(),y(!1)}:void 0,onDrop:d.enableFileUpload?e=>{e.preventDefault(),y(!1);const t=e.dataTransfer.files[0];t&&i&&i(t)}:void 0,children:[m&&t.jsx("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,backgroundColor:"rgba(59, 130, 246, 0.1)",border:"2px dashed #3b82f6",display:"flex",alignItems:"center",justifyContent:"center",zIndex:10,borderRadius:"8px"},children:t.jsx("div",{style:{color:"#3b82f6",fontWeight:"600"},children:"Drop file here to upload"})}),0===e.length&&!a&&t.jsx("div",{style:{textAlign:"center",color:"#6b7280",fontSize:"15px",padding:"40px 20px",lineHeight:"1.6"},children:d.greeting||"Hi! I'm your BotForge assistant. I can help you create chatbots, understand features, troubleshoot issues, and more. What would you like to know?"}),e.map((e=>{var o,i,r,s;return t.jsxs("div",{style:{display:"flex",justifyContent:"user"===e.sender?"flex-end":"flex-start",alignItems:"flex-start",gap:"12px"},children:["bot"===e.sender&&t.jsx("div",{style:{width:"32px",height:"32px",backgroundColor:"linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%)",background:"linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%)",borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0,marginTop:"4px"},children:t.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"white",strokeWidth:"2",children:[t.jsx("path",{d:"M12 8V4H8"}),t.jsx("rect",{width:"16",height:"12",x:"4",y:"8",rx:"2"}),t.jsx("path",{d:"m14 8-2 2-2-2"}),t.jsx("path",{d:"M18 12h2"}),t.jsx("path",{d:"M22 12v6"}),t.jsx("path",{d:"M4 12H2"}),t.jsx("path",{d:"M2 12v6"})]})}),t.jsxs("div",{style:{maxWidth:"75%",display:"flex",flexDirection:"column",gap:"8px"},children:[t.jsxs("div",{style:{padding:"12px 16px",borderRadius:"user"===e.sender?"18px 18px 4px 18px":"18px 18px 18px 4px",backgroundColor:"user"===e.sender?"#3b82f6":"#374151",color:"user"===e.sender?"white":"#f3f4f6",fontSize:"14px",lineHeight:"1.5",boxShadow:"0 1px 2px rgba(0, 0, 0, 0.1)",border:e.isError?"1px solid #ef4444":"none",wordWrap:"break-word",position:"relative"},children:[t.jsx("div",{children:e.content}),t.jsxs("div",{style:{fontSize:"11px",opacity:.7,marginTop:"6px",textAlign:"user"===e.sender?"right":"left",display:"flex",justifyContent:"user"===e.sender?"flex-end":"flex-start",alignItems:"center",gap:"6px"},children:[t.jsx("span",{children:(s=e.timestamp,s.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}))}),((null===(o=e.metadata)||void 0===o?void 0:o.fallback)||(null===(i=e.metadata)||void 0===i?void 0:i.offline))&&t.jsx("span",{style:{fontSize:"10px",backgroundColor:"rgba(0, 0, 0, 0.2)",padding:"2px 6px",borderRadius:"6px"},children:"Offline"})]})]}),"bot"===e.sender&&(null===(r=e.metadata)||void 0===r?void 0:r.options)&&t.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"6px"},children:e.metadata.options.map(((e,o)=>t.jsx("button",{onClick:()=>(e=>{d.debug&&console.log("[BotForge Widget] Quick reply selected:",e),n(e)})(e),style:{padding:"8px 12px",backgroundColor:"#4b5563",color:"#f3f4f6",border:"1px solid #6b7280",borderRadius:"8px",fontSize:"13px",cursor:"pointer",transition:"all 0.2s ease",textAlign:"left"},onMouseEnter:e=>{e.currentTarget.style.backgroundColor="#374151",e.currentTarget.style.borderColor="#9ca3af"},onMouseLeave:e=>{e.currentTarget.style.backgroundColor="#4b5563",e.currentTarget.style.borderColor="#6b7280"},children:e},o)))})]}),"user"===e.sender&&t.jsx("div",{style:{width:"32px",height:"32px",backgroundColor:"#3b82f6",borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0,marginTop:"4px"},children:t.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"white",strokeWidth:"2",children:[t.jsx("path",{d:"M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"}),t.jsx("circle",{cx:"12",cy:"7",r:"4"})]})})]},e.id)})),a&&e.length>0&&d.enableTypingIndicator&&t.jsxs("div",{style:{display:"flex",justifyContent:"flex-start",alignItems:"flex-start",gap:"12px"},children:[t.jsx("div",{style:{width:"32px",height:"32px",background:"linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%)",borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0,marginTop:"4px"},children:t.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"white",strokeWidth:"2",children:[t.jsx("path",{d:"M12 8V4H8"}),t.jsx("rect",{width:"16",height:"12",x:"4",y:"8",rx:"2"}),t.jsx("path",{d:"m14 8-2 2-2-2"}),t.jsx("path",{d:"M18 12h2"}),t.jsx("path",{d:"M22 12v6"}),t.jsx("path",{d:"M4 12H2"}),t.jsx("path",{d:"M2 12v6"})]})}),t.jsx("div",{style:{padding:"12px 16px",borderRadius:"18px 18px 18px 4px",backgroundColor:"#374151",boxShadow:"0 1px 2px rgba(0, 0, 0, 0.1)"},children:t.jsxs("div",{style:{display:"flex",gap:"4px",alignItems:"center"},children:[t.jsx("div",{style:{width:"8px",height:"8px",borderRadius:"50%",backgroundColor:"#9ca3af",animation:"pulse 1.5s ease-in-out infinite"}}),t.jsx("div",{style:{width:"8px",height:"8px",borderRadius:"50%",backgroundColor:"#9ca3af",animation:"pulse 1.5s ease-in-out infinite 0.2s"}}),t.jsx("div",{style:{width:"8px",height:"8px",borderRadius:"50%",backgroundColor:"#9ca3af",animation:"pulse 1.5s ease-in-out infinite 0.4s"}})]})})]}),t.jsx("div",{ref:w})]}),t.jsx("div",{style:{padding:"20px",borderTop:"1px solid #374151",backgroundColor:"#1f2937"},children:t.jsxs("form",{onSubmit:j,style:{display:"flex",gap:"12px",alignItems:"flex-end"},children:[t.jsx("div",{style:{flex:1,position:"relative"},children:t.jsx("input",{ref:I,type:"text",value:b,onChange:e=>{v(e.target.value),d.debug&&console.log("[BotForge Widget] Input value changed:",e.target.value)},onKeyPress:e=>{"Enter"!==e.key||e.shiftKey||(e.preventDefault(),j(e))},placeholder:k?d.placeholder||"Ask me about BotForge features, pricing, or how to build chatbots...":"Initializing chat...",disabled:!k,style:{width:"100%",padding:"12px 16px",border:"1px solid #4b5563",borderRadius:"12px",outline:"none",fontSize:"14px",backgroundColor:"#374151",color:"#f3f4f6",fontFamily:"inherit",transition:"border-color 0.2s ease",opacity:k?1:.5,cursor:k?"text":"not-allowed"},onFocus:e=>{k&&(e.currentTarget.style.borderColor="#3b82f6",e.currentTarget.style.boxShadow="0 0 0 3px rgba(59, 130, 246, 0.1)")},onBlur:e=>{e.currentTarget.style.borderColor="#4b5563",e.currentTarget.style.boxShadow="none"}})}),d.enableFileUpload&&t.jsxs(t.Fragment,{children:[t.jsx("button",{type:"button",onClick:()=>{var e;return null===(e=C.current)||void 0===e?void 0:e.click()},disabled:!k,style:{padding:"12px",border:"1px solid #4b5563",borderRadius:"12px",backgroundColor:"#374151",color:"#9ca3af",cursor:k?"pointer":"not-allowed",fontSize:"16px",opacity:k?1:.5,transition:"all 0.2s ease",display:"flex",alignItems:"center",justifyContent:"center",width:"44px",height:"44px"},title:"Upload file",onMouseEnter:e=>{k&&(e.currentTarget.style.backgroundColor="#4b5563",e.currentTarget.style.color="#f3f4f6")},onMouseLeave:e=>{e.currentTarget.style.backgroundColor="#374151",e.currentTarget.style.color="#9ca3af"},children:"📎"}),t.jsx("input",{ref:C,type:"file",onChange:e=>{var t;const o=null===(t=e.target.files)||void 0===t?void 0:t[0];o&&i&&i(o),e.target&&(e.target.value="")},style:{display:"none"},accept:"image/*,.pdf,.doc,.docx,.txt"})]}),t.jsx("button",{type:"submit",disabled:!b.trim()||!k,style:{padding:"12px 20px",border:"none",borderRadius:"12px",backgroundColor:(null===(x=d.theme)||void 0===x?void 0:x.primaryColor)||"#3b82f6",color:"white",cursor:b.trim()&&k?"pointer":"not-allowed",fontSize:"14px",fontWeight:"600",opacity:b.trim()&&k?1:.5,transition:"all 0.2s ease",display:"flex",alignItems:"center",justifyContent:"center",minWidth:"60px",height:"44px"},onMouseEnter:e=>{b.trim()&&k&&(e.currentTarget.style.backgroundColor="#2563eb",e.currentTarget.style.transform="translateY(-1px)")},onMouseLeave:e=>{var t;e.currentTarget.style.backgroundColor=(null===(t=d.theme)||void 0===t?void 0:t.primaryColor)||"#3b82f6",e.currentTarget.style.transform="translateY(0)"},children:k?t.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[t.jsx("path",{d:"m22 2-7 20-4-9-9-4Z"}),t.jsx("path",{d:"M22 2 11 13"})]}):t.jsx("div",{style:{width:"16px",height:"16px",border:"2px solid rgba(255, 255, 255, 0.3)",borderTop:"2px solid white",borderRadius:"50%",animation:"spin 1s linear infinite"}})})]})}),d.showBranding&&t.jsxs("div",{style:{padding:"12px 20px",textAlign:"center",fontSize:"12px",color:"#6b7280",borderTop:"1px solid #374151",backgroundColor:"#1f2937"},children:["Powered by"," ",t.jsx("a",{href:"https://botforge.site",target:"_blank",rel:"noopener noreferrer",style:{color:"#3b82f6",textDecoration:"none",fontWeight:"600"},children:"BotForge"})]}),t.jsx("style",{children:"\n @keyframes pulse {\n 0%, 80%, 100% {\n opacity: 0.3;\n }\n 40% {\n opacity: 1;\n }\n }\n \n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n "})]})},a=({onClick:e,isOpen:o,config:n,hasUnreadMessages:i})=>{var r,s,a;const l=(()=>{var e;switch(null===(e=n.theme)||void 0===e?void 0:e.buttonSize){case"small":return{width:"56px",height:"56px",fontSize:"20px"};case"large":return{width:"72px",height:"72px",fontSize:"28px"};default:return{width:"64px",height:"64px",fontSize:"24px"}}})(),d={...l,borderRadius:"50%",background:"linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%)",border:"none",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 8px 32px rgba(59, 130, 246, 0.3)",transition:"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",position:"relative",color:"white",fontFamily:(null===(r=n.theme)||void 0===r?void 0:r.fontFamily)||"inherit"},c="small"===(null===(s=n.theme)||void 0===s?void 0:s.buttonSize)?"24px":"large"===(null===(a=n.theme)||void 0===a?void 0:a.buttonSize)?"32px":"28px";return t.jsxs(t.Fragment,{children:[t.jsxs("button",{onClick:e,style:d,onMouseEnter:e=>{e.currentTarget.style.transform="scale(1.05) translateY(-2px)",e.currentTarget.style.boxShadow="0 12px 40px rgba(59, 130, 246, 0.4)"},onMouseLeave:e=>{e.currentTarget.style.transform="scale(1) translateY(0)",e.currentTarget.style.boxShadow="0 8px 32px rgba(59, 130, 246, 0.3)"},"aria-label":o?"Close chat":"Open chat",title:o?"Close chat":"Open chat",children:[i&&!o&&t.jsx("div",{style:{position:"absolute",top:"-3px",right:"-3px",width:"16px",height:"16px",backgroundColor:"#ef4444",borderRadius:"50%",border:"2px solid white",animation:"pulse 2s infinite"}}),o?t.jsxs("svg",{width:c,height:c,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[t.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),t.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]}):t.jsxs("svg",{width:c,height:c,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[t.jsx("path",{d:"M12 8V4H8"}),t.jsx("rect",{width:"16",height:"12",x:"4",y:"8",rx:"2"}),t.jsx("path",{d:"m14 8-2 2-2-2"}),t.jsx("path",{d:"M18 12h2"}),t.jsx("path",{d:"M22 12v6"}),t.jsx("path",{d:"M4 12H2"}),t.jsx("path",{d:"M2 12v6"})]})]}),t.jsx("style",{children:"\n @keyframes pulse {\n 0% {\n transform: scale(0.95);\n box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7);\n }\n 70% {\n transform: scale(1);\n box-shadow: 0 0 0 10px rgba(239, 68, 68, 0);\n }\n 100% {\n transform: scale(0.95);\n box-shadow: 0 0 0 0 rgba(239, 68, 68, 0);\n }\n }\n "})]})};class l{constructor(e,t,o,n=!1){if(this.conversationId=null,this.userIdentifier=null,this.debug=!1,this.isInitializing=!1,this.retryCount=0,this.maxRetries=2,this.isOfflineMode=!1,this.connectionCheckInterval=null,this.chatbotId=e,!t)throw new Error("API URL is required for BotForge widget");if(this.baseUrl=t.replace(/\/$/,""),!o)throw new Error("Anonymous key is required for BotForge widget");this.anonKey=o,this.debug=n,n&&console.log("[BotForge Widget] Initialized with API URL:",this.baseUrl),this.startConnectionMonitoring()}log(...e){this.debug&&console.log("[BotForge Widget]",...e)}startConnectionMonitoring(){this.connectionCheckInterval=setInterval((()=>{this.isOfflineMode&&this.checkConnection()}),3e4)}async checkConnection(){try{const e=await fetch(`${this.baseUrl}/functions/v1/widget-chat`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json",Authorization:`Bearer ${this.anonKey}`},body:JSON.stringify({chatbotId:this.chatbotId,action:"get_flow"}),signal:AbortSignal.timeout(5e3)});return!(!e.ok&&401!==e.status)&&(this.isOfflineMode=!1,this.log("Connection restored"),!0)}catch(e){return!1}}async makeRequest(e,t,o=0){if(this.isOfflineMode&&0===o)return this.log("In offline mode, using fallback response"),{success:!1,error:"Offline mode - using fallback response"};const n=`${this.baseUrl}/functions/v1/${e}`;this.log("Making request to:",n,"with data:",t,"attempt:",o+1);try{const i=new AbortController,r=setTimeout((()=>i.abort()),1e4),s={"Content-Type":"application/json",Accept:"application/json"};this.anonKey&&(s.Authorization=`Bearer ${this.anonKey}`);const a=await fetch(n,{method:"POST",headers:s,body:JSON.stringify(t),signal:i.signal});if(clearTimeout(r),this.log("Response status:",a.status),!a.ok){const n=await a.text();if(this.log("Error response:",n),a.status>=500&&o<this.maxRetries)return this.log(`Server error, retrying in ${1e3*(o+1)}ms...`),await new Promise((e=>setTimeout(e,1e3*(o+1)))),this.makeRequest(e,t,o+1);throw o>=this.maxRetries&&(this.isOfflineMode=!0,this.log("Entering offline mode due to repeated failures")),new Error(`HTTP ${a.status}: ${a.statusText}`)}const l=await a.json();return this.log("Response data:",l),this.retryCount=0,this.isOfflineMode=!1,{success:!0,data:l}}catch(n){return this.log("Request failed:",n),("object"==typeof n&&null!==n&&"name"in n&&"AbortError"===n.name||"object"==typeof n&&null!==n&&"message"in n&&(n.message.includes("fetch")||n.message.includes("Failed to fetch")))&&o<this.maxRetries?(this.log(`Network error, retrying in ${2e3*(o+1)}ms...`),await new Promise((e=>setTimeout(e,2e3*(o+1)))),this.makeRequest(e,t,o+1)):(o>=this.maxRetries&&(this.isOfflineMode=!0,this.log("Entering offline mode due to network errors")),{success:!1,error:n instanceof Error?n.message:"Unknown error occurred"})}}async initializeConversation(){if(this.isInitializing){this.log("Initialization already in progress, waiting...");let e=0;for(;this.isInitializing&&e<50;)await new Promise((e=>setTimeout(e,100))),e++;if(this.conversationId&&this.userIdentifier)return{conversationId:this.conversationId,userIdentifier:this.userIdentifier}}if(this.conversationId&&this.userIdentifier)return this.log("Already initialized, returning existing data"),{conversationId:this.conversationId,userIdentifier:this.userIdentifier};this.isInitializing=!0,this.log("Initializing conversation for chatbot:",this.chatbotId);try{const e=await this.makeRequest("widget-chat",{chatbotId:this.chatbotId,action:"initialize",userIdentifier:this.userIdentifier});if(!e.success||!e.data){this.conversationId=`offline-${Date.now()}`,this.userIdentifier=this.userIdentifier||d(),this.log("Using offline initialization:",{conversationId:this.conversationId,userIdentifier:this.userIdentifier});const e={id:"welcome-offline",content:"Hello! I'm currently in offline mode, but I can still help you with basic questions.",sender:"bot",timestamp:new Date,type:"text",metadata:{offline:!0}};return{conversationId:this.conversationId,userIdentifier:this.userIdentifier,welcomeMessage:e}}let t;return this.conversationId=e.data.conversationId,this.userIdentifier=e.data.userIdentifier,this.log("Conversation initialized:",{conversationId:this.conversationId,userIdentifier:this.userIdentifier}),e.data.welcomeMessage&&(t={id:e.data.welcomeMessage.id||"welcome",content:e.data.welcomeMessage.content||"Hello! How can I help you today?",sender:"bot",timestamp:new Date(e.data.welcomeMessage.timestamp||Date.now()),type:"text",metadata:e.data.welcomeMessage.metadata||{}},e.data.welcomeMessage.options&&(t.metadata={...t.metadata,options:e.data.welcomeMessage.options})),{conversationId:this.conversationId,userIdentifier:this.userIdentifier,welcomeMessage:t}}finally{this.isInitializing=!1}}async sendMessage(e,t="text"){var o,n,i,r,s;if(!this.conversationId)throw new Error("Conversation not initialized. Call initializeConversation() first.");this.log("Sending message:",e,"type:",t);const a={id:`user-${Date.now()}`,content:e,sender:"user",timestamp:new Date,type:t};if(this.isOfflineMode){const t=c(e);return this.log("Using offline response for message"),{userMessage:a,botMessage:t}}const l=await this.makeRequest("widget-chat",{chatbotId:this.chatbotId,conversationId:this.conversationId,message:e,messageType:t,userIdentifier:this.userIdentifier,action:"send_message"});if(!l.success||!l.data){const t=c(e);return this.log("Using fallback response due to API failure"),{userMessage:a,botMessage:t}}let d=(null===(o=l.data.botMessage)||void 0===o?void 0:o.metadata)||{};(null===(n=l.data.botMessage)||void 0===n?void 0:n.options)&&(d={...d,options:l.data.botMessage.options});const u={id:(null===(i=l.data.botMessage)||void 0===i?void 0:i.id)||`bot-${Date.now()}`,content:(null===(r=l.data.botMessage)||void 0===r?void 0:r.content)||"I understand. How can I help you further?",sender:"bot",timestamp:new Date((null===(s=l.data.botMessage)||void 0===s?void 0:s.timestamp)||Date.now()),type:"text",metadata:d};return this.log("Messages created:",{userMessage:a,botMessage:u}),{userMessage:a,botMessage:u}}async getChatbotFlow(){this.log("Getting chatbot flow for:",this.chatbotId);const e=await this.makeRequest("widget-chat",{chatbotId:this.chatbotId,action:"get_flow"});return e.success&&e.data?e.data:{flow:{nodes:[{id:"start",type:"start",data:{content:"Hello! How can I help you today?"}}],edges:[]},name:"Offline Bot",description:"Currently in offline mode"}}setUserIdentifier(e){this.userIdentifier=e,this.log("User identifier set to:",e)}getConversationId(){return this.conversationId}getUserIdentifier(){return this.userIdentifier}isOffline(){return this.isOfflineMode}reset(){this.conversationId=null,this.isInitializing=!1,this.retryCount=0,this.log("API client reset - conversation state only")}destroy(){this.reset(),this.connectionCheckInterval&&(clearInterval(this.connectionCheckInterval),this.connectionCheckInterval=null),this.log("API client fully destroyed")}}const d=()=>{const e="botforge-user-id";let t="";try{t=localStorage.getItem(e)||""}catch(e){}if(!t){t=`user-${Date.now()}-${Math.random().toString(36).substr(2,9)}`;try{localStorage.setItem(e,t)}catch(e){}}return t},c=e=>{const t=e.toLowerCase();let o="";if(t.includes("hello")||t.includes("hi")||t.includes("hey"))o="Hello! I'm currently in offline mode, but I'm here to help. What can I assist you with?";else if(t.includes("help")||t.includes("support"))o="I'd be happy to help! While I'm in offline mode, I can provide general assistance. What do you need help with?";else if(t.includes("price")||t.includes("cost")||t.includes("pricing"))o="For current pricing information, please visit our website or contact our sales team when the connection is restored.";else if(t.includes("thank"))o="You're very welcome! Is there anything else I can help you with?";else if(t.includes("bye")||t.includes("goodbye"))o="Goodbye! Feel free to reach out anytime. Have a great day!";else if(t.includes("contact")||t.includes("email")||t.includes("phone"))o="You can reach our support team at support@botforge.site. We'll get back to you as soon as possible!";else if(t.includes("feature")||t.includes("what can you do"))o="I can help with general questions about our services. For detailed feature information, please visit our website or contact support.";else{const e=["I understand your question. While I'm in offline mode, I recommend visiting our website or contacting support for detailed assistance.","Thank you for your message. For the most accurate information, please reach out to our support team at support@botforge.site.","I appreciate you reaching out! For comprehensive help with your inquiry, our support team will be able to assist you better.","I see what you're asking about. Our support team can provide you with detailed information once the connection is restored."];o=e[Math.floor(Math.random()*e.length)]}return{id:`fallback-${Date.now()}`,content:o,sender:"bot",timestamp:new Date,type:"text",metadata:{fallback:!0,offline:!0}}},u={theme:{primaryColor:"#3B82F6",backgroundColor:"#1f2937",textColor:"#f3f4f6",borderRadius:"16px",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',buttonSize:"medium",chatHeight:"600px",chatWidth:"400px",headerColor:"#1f2937",userMessageColor:"#3B82F6",botMessageColor:"#374151"},position:{bottom:"20px",right:"20px"},autoOpen:!1,showBranding:!0,enableFileUpload:!1,enableEmoji:!0,enableTypingIndicator:!0,maxMessages:100,greeting:"Hi! I'm your BotForge assistant. I can help you create chatbots, understand features, troubleshoot issues, and more. What would you like to know?",placeholder:"Ask me about BotForge features, pricing, or how to build chatbots...",title:"BotForge Support",subtitle:"Get instant help",language:"en",debug:!1},g=o.forwardRef(((e,n)=>{var i;const r={...u,...e};if(!r.chatbotId)return console.error("[BotForge Widget] chatbotId is required"),null;if(!r.apiUrl)return console.error("[BotForge Widget] apiUrl is required"),null;if(!r.anonKey)return console.error("[BotForge Widget] anonKey is required"),null;const[g,h]=o.useState(r.autoOpen||!1),[p,f]=o.useState([]),[x,b]=o.useState(!1),[v,m]=o.useState(null),y=o.useRef(null),w=o.useRef(!1),{isConnected:I,isLoading:C,conversationId:j,error:k,isInitialized:M,initializeConversation:F,sendMessage:B,updateUser:S,setIsLoading:z,resetConversation:R}=(({chatbotId:e,apiUrl:t,anonKey:n,user:i,debug:r=!1,onError:s,onMessage:a,onConnectionChange:u})=>{const[g,h]=o.useState(!0),[p,f]=o.useState(!1),[x,b]=o.useState(null),[v,m]=o.useState(null),[y,w]=o.useState(null),[I,C]=o.useState(!1),j=o.useRef(null),k=o.useRef(!1),M=o.useRef(!1);o.useRef(`widget-${e}-${Date.now()}`),o.useEffect((()=>{if(M.current)r&&console.log("[BotForge Widget] API client already exists, skipping creation");else try{if(!t||!n)throw new Error("API URL and anonymous key are required");r&&console.log("[BotForge Widget] Creating API client..."),j.current=new l(e,t,n,r);const o=(null==i?void 0:i.id)||d();j.current.setUserIdentifier(o),m(o),M.current=!0,r&&console.log("[BotForge Widget] API client created successfully")}catch(e){const t=e instanceof Error?e:new Error("Failed to initialize API client");w(t),null==s||s(t),r&&console.error("[BotForge Widget] Failed to initialize API client:",t)}}),[e,t,n,r,null==i?void 0:i.id]),o.useEffect((()=>{if(!j.current)return;const e=setInterval((()=>{if(j.current){const e=!j.current.isOffline();e!==g&&(h(e),null==u||u(e),r&&console.log("[BotForge Widget] Connection status changed:",e?"online":"offline"))}}),5e3);return()=>clearInterval(e)}),[g,r,u]);const F=o.useCallback((async()=>{if(!j.current||I||k.current)return r&&console.log("[BotForge Widget] Skipping initialization:",{hasClient:!!j.current,isInitialized:I,inProgress:k.current}),null;k.current=!0,f(!0),w(null),r&&console.log("[BotForge Widget] Starting conversation initialization...");try{const e=await j.current.initializeConversation();b(e.conversationId),m(e.userIdentifier),C(!0);const t=j.current.isOffline();h(!t),r&&(console.log("[BotForge Widget] Conversation initialized:",e),console.log("[BotForge Widget] React state updated with:",{conversationId:e.conversationId,userIdentifier:e.userIdentifier,isInitialized:!0}));const o=e.welcomeMessage||{id:"welcome-default",content:"Hi! I'm your BotForge assistant. I can help you create chatbots, understand features, troubleshoot issues, and more. What would you like to know?",sender:"bot",timestamp:new Date,type:"text"};return r&&console.log("[BotForge Widget] Returning welcome message:",o),e.followUpMessage&&setTimeout((()=>{r&&console.log("[BotForge Widget] Adding follow-up message:",e.followUpMessage),e.followUpMessage&&(null==a||a(e.followUpMessage))}),1e3),o}catch(e){const t=e instanceof Error?e:new Error("Failed to initialize conversation");return w(t),h(!1),null==s||s(t),r&&console.error("[BotForge Widget] Initialization failed:",t),C(!0),{id:"welcome-fallback",content:"Hello! I'm currently in offline mode, but I can still help you with basic questions.",sender:"bot",timestamp:new Date,type:"text",metadata:{offline:!0}}}finally{f(!1),k.current=!1}}),[r,s,I,a]),B=o.useCallback((async(e,t="text")=>{if(!j.current||!x)throw new Error("Conversation not initialized");r&&console.log("[BotForge Widget] Sending message:",e),f(!0),w(null);try{const o=await j.current.sendMessage(e,t),n=j.current.isOffline();return h(!n),r&&console.log("[BotForge Widget] Message exchange complete:",o),null==a||a(o.userMessage),null==a||a(o.botMessage),o}catch(o){const n=o instanceof Error?o:new Error("Failed to send message");w(n),null==s||s(n),r&&console.error("[BotForge Widget] Send message failed:",n);const i={id:`user-${Date.now()}`,content:e,sender:"user",timestamp:new Date,type:t},l=c(e);return null==a||a(i),null==a||a(l),{userMessage:i,botMessage:l}}finally{f(!1)}}),[x,r,s,a]),S=o.useCallback((e=>{e.id&&j.current&&(j.current.setUserIdentifier(e.id),m(e.id))}),[]),z=o.useCallback((async()=>{if(!j.current)return null;try{return await j.current.getChatbotFlow()}catch(e){const t=e instanceof Error?e:new Error("Failed to get chatbot flow");return w(t),null==s||s(t),null}}),[s]),R=o.useCallback((()=>{r&&console.log("[BotForge Widget] Resetting conversation state only"),b(null),C(!1),h(!0),w(null),k.current=!1,j.current&&j.current.reset()}),[r]);return{isConnected:g,isLoading:p,conversationId:x,userIdentifier:v,error:y,isInitialized:I,setIsLoading:f,initializeConversation:F,sendMessage:B,updateUser:S,getChatbotFlow:z,resetConversation:R}})({chatbotId:r.chatbotId,apiUrl:r.apiUrl,anonKey:r.anonKey,user:r.user,debug:r.debug,onError:e=>{var t,o;null===(o=null===(t=r.events)||void 0===t?void 0:t.onError)||void 0===o||o.call(t,e),r.debug&&console.error("[BotForge Widget] Error:",e)},onMessage:e=>{var t,o,n,i,s,a;r.debug&&console.log("[BotForge Widget] Adding message to UI:",e),f((t=>{const o=[...t,e];return r.maxMessages&&o.length>r.maxMessages?o.slice(-r.maxMessages):o})),g||"bot"!==e.sender||b(!0),null===(o=null===(t=r.events)||void 0===t?void 0:t.onMessage)||void 0===o||o.call(t,e),"user"===e.sender?null===(i=null===(n=r.events)||void 0===n?void 0:n.onUserMessage)||void 0===i||i.call(n,e):null===(a=null===(s=r.events)||void 0===s?void 0:s.onBotMessage)||void 0===a||a.call(s,e)},onConnectionChange:e=>{m(e?null:"Connection lost - using offline mode")}});o.useEffect((()=>{M||w.current||(w.current=!0,r.debug&&console.log("[BotForge Widget] Starting initialization..."),F().then((e=>{var t,o;r.debug&&console.log("[BotForge Widget] Initialization complete, welcome message:",e),e&&(f([e]),r.debug&&console.log("[BotForge Widget] Welcome message added to state")),z(!1),null===(o=null===(t=r.events)||void 0===t?void 0:t.onReady)||void 0===o||o.call(t)})).catch((e=>{z(!1),r.debug&&console.error("[BotForge Widget] Initialization failed:",e)})))}),[M,F,r.events,r.debug]),o.useEffect((()=>{var e,t;r.autoOpen&&!g&&M&&(h(!0),null===(t=null===(e=r.events)||void 0===e?void 0:e.onOpen)||void 0===t||t.call(e))}),[r.autoOpen,g,r.events,M]),o.useEffect((()=>{g&&x&&b(!1)}),[g,x]),o.useEffect((()=>{v&&r.debug&&console.log("[BotForge Widget]",v)}),[v,r.debug]);const W=()=>{var e,t,o,n;const i=!g;h(i),i?(null===(t=null===(e=r.events)||void 0===e?void 0:e.onOpen)||void 0===t||t.call(e),b(!1)):null===(n=null===(o=r.events)||void 0===o?void 0:o.onClose)||void 0===n||n.call(o)},T=async(e,t="text")=>{if(e.trim()){r.debug&&console.log("[BotForge Widget] Sending message:",e);try{await B(e,t)}catch(e){r.debug&&console.error("[BotForge Widget] Failed to send message:",e)}}else r.debug&&console.log("[BotForge Widget] Message send blocked: empty content")};o.useImperativeHandle(n,(()=>({open:()=>{var e,t;h(!0),null===(t=null===(e=r.events)||void 0===e?void 0:e.onOpen)||void 0===t||t.call(e),b(!1)},close:()=>{var e,t;h(!1),null===(t=null===(e=r.events)||void 0===e?void 0:e.onClose)||void 0===t||t.call(e)},toggle:W,sendMessage:async e=>{await T(e)},setUser:e=>{S(e)},isOpen:()=>g,destroy:()=>{R(),f([]),h(!1),w.current=!1},updateConfig:e=>{r.debug&&console.log("[BotForge Widget] Config update requested:",e)}})),[g,T,S,R,r.events,r.debug]);const E={position:"fixed",zIndex:9999,fontFamily:null===(i=r.theme)||void 0===i?void 0:i.fontFamily,...r.position};return r.debug&&console.log("[BotForge Widget] Render state:",{isOpen:g,messagesCount:p.length,isLoading:C,isConnected:I,conversationId:j,isInitialized:M}),t.jsxs("div",{ref:y,style:{...E,...e.style},className:e.className,children:[g&&t.jsx(s,{messages:p,onSendMessage:T,onFileUpload:async e=>{r.enableFileUpload&&await T(`📎 ${e.name}`,"file")},onClose:W,onRestart:()=>{r.debug&&console.log("[BotForge Widget] Restarting conversation..."),f([]),b(!1),R(),w.current=!1,setTimeout((()=>{r.debug&&console.log("[BotForge Widget] Re-initializing after restart..."),w.current=!0,F().then((e=>{e&&f([e]),z(!1)})).catch((e=>{z(!1),r.debug&&console.error("[BotForge Widget] Re-initialization failed:",e)}))}),100)},isLoading:C,isConnected:I,config:r,error:k,isInitialized:M,conversationId:j}),t.jsx(a,{onClick:W,isOpen:g,config:r,hasUnreadMessages:x})]})}));g.displayName="BotForgeWidget";let h=null;const p=e=>{var t,n;if(!e.chatbotId)throw new Error("BotForge: chatbotId is required");h&&(h.api.destroy(),h=null);let i=document.getElementById("botforge-widget-container");i||(i=document.createElement("div"),i.id="botforge-widget-container",i.style.position="fixed",i.style.zIndex="9999",i.style.pointerEvents="none",document.body.appendChild(i));const s=r.createRoot(i);let a=null;const l={open:()=>{var e;return null===(e=null==a?void 0:a.open)||void 0===e?void 0:e.call(a)},close:()=>{var e;return null===(e=null==a?void 0:a.close)||void 0===e?void 0:e.call(a)},toggle:()=>{var e;return null===(e=null==a?void 0:a.toggle)||void 0===e?void 0:e.call(a)},sendMessage:e=>{var t;return null===(t=null==a?void 0:a.sendMessage)||void 0===t?void 0:t.call(a,e)},setUser:e=>{var t;return null===(t=null==a?void 0:a.setUser)||void 0===t?void 0:t.call(a,e)},isOpen:()=>{var e;return(null===(e=null==a?void 0:a.isOpen)||void 0===e?void 0:e.call(a))||!1},destroy:()=>{s.unmount(),i.remove(),h=null},updateConfig:e=>{var t;return null===(t=null==a?void 0:a.updateConfig)||void 0===t?void 0:t.call(a,e)}};return s.render(o.createElement(g,{...e,ref:e=>a=e,style:{pointerEvents:"auto"}})),h={root:s,container:i,api:l},null===(n=null===(t=e.events)||void 0===t?void 0:t.onReady)||void 0===n||n.call(t),l};"undefined"!=typeof window&&(window.BotForge={initBotForge:p,version:"1.0.12"}),e.initBotForge=p})); //# sourceMappingURL=botforge-widget.umd.js.map