@heylock-dev/ui
Version:
Heylock UI React component library
3 lines (2 loc) • 12.9 kB
JavaScript
"use client"
import*as L from"react";import{motion as X,AnimatePresence as ge}from"framer-motion";import*as s from"react";import{twMerge as z}from"tailwind-merge";import*as D from"react";import pe from"heylock";import{jsx as de}from"react/jsx-runtime";var te=D.createContext();function re({children:t,agentKey:r,options:n}){if(!r)throw new Error("HeylockProvider requires an agentKey prop");let e=null;try{e=D.useRef(new pe(r,{suppressWarnings:!0,...n}))}catch(a){throw console.error("Failed to initialize Heylock agent:",a),new Error("HeylockProvider failed to initialize the agent.")}return de(te.Provider,{value:e.current,children:t})}function A(){let t=D.useContext(te);if(typeof t=="undefined")throw new Error("useAgent must be used within a HeylockProvider");return t}import{jsx as b,jsxs as ne}from"react/jsx-runtime";var me=1e3,ye=2e4;function W({disabled:t=!1,disabledText:r="Unavaliable. Please try again later.",respondingText:n="Responding...",theme:e="auto",placeholders:a=["Ask me anything","How can I help you?","Chat with AI"],placeholderInterval:o=5e3,className:c,inputClassName:p,placeholderClassName:d,buttonClassName:v,arrowClassName:F,onChange:B,onSubmit:w,onFocus:V}){let[_,J]=s.useState(!1),[R,P]=s.useState(t),[K,Q]=s.useState(!1),[y,Y]=s.useState(""),[ae,ie]=s.useState(0),[Z,se]=s.useState(0),O=s.useRef(null),U=s.useRef(null),ee=s.useRef(null),f=A();s.useEffect(()=>{c&&typeof c!="string"&&console.error("HeylockInput: 'className' prop must be a string."),p&&typeof p!="string"&&console.error("HeylockInput: 'inputClassName' prop must be a string."),d&&typeof d!="string"&&console.error("HeylockInput: 'placeholderClassName' prop must be a string."),v&&typeof v!="string"&&console.error("HeylockInput: 'buttonClassName' prop must be a string."),F&&typeof F!="string"&&console.error("HeylockInput: 'arrowClassName' prop must be a string."),typeof t!="boolean"&&console.error("HeylockInput: 'disabled' prop must be a boolean."),r&&typeof r!="string"&&console.error("HeylockInput: 'disabledText' prop must be a string."),n&&typeof n!="string"&&console.error("HeylockInput: 'respondingText' prop must be a string.");let i=["light","dark","auto"];i.includes(e)||console.error(`HeylockInput: 'theme' prop must be one of ${i.join(", ")}.`),(!Array.isArray(a)||a.length===0||a.some(u=>typeof u!="string"||u.trim().length===0))&&console.error("HeylockInput: 'placeholders' prop must be a non-empty array of strings."),(typeof o!="number"||!Number.isFinite(o)||o<=0)&&console.error("HeylockInput: 'placeholderInterval' prop must be a positive number (ms)."),B&&typeof B!="function"&&console.error("HeylockInput: 'onChange' prop must be a function."),w&&typeof w!="function"&&console.error("HeylockInput: 'onSubmit' prop must be a function."),V&&typeof V!="function"&&console.error("HeylockInput: 'onFocus' prop must be a function.")},[c,p,d,v,F,t,r,n,e,a,o,B,w,V]),s.useEffect(()=>{if(f.isInitialized)P(f.usageRemaining.messages<=0);else{let i=f.onInitialized(u=>{let g=f.usageRemaining.messages!==null&&f.usageRemaining.messages!==void 0&&f.usageRemaining.messages<=0;P(u?g:!0),i()})}},[]),s.useEffect(()=>{t!==!1&&P(t)},[t]),s.useEffect(()=>(ee.current=setInterval(()=>{se(i=>(i+1)%a.length)},o),()=>{clearInterval(ee.current)}),[]);let M=s.useRef([]),le=i=>{let u=(g=0)=>{requestAnimationFrame(()=>{var h;let E=[];for(let I=0;I<M.current.length;I++){let l=M.current[I];if(l.x<g)E.push(l);else{if(l.r<=0){l.r=0;continue}l.x+=Math.random()>.5?1:-1,l.y+=Math.random()>.5?1:-1,l.r-=.05*Math.random(),E.push(l)}}M.current=E;let H=(h=O.current)==null?void 0:h.getContext("2d");H&&(H.clearRect(g,0,800,800),M.current.forEach(I=>{let{x:l,y:T,r:m,color:x}=I;l>g&&(H.beginPath(),H.rect(l,T,m,m),H.fillStyle=x,H.strokeStyle=x,H.stroke())})),M.current.length>0?u(g-8):(Y(""),J(!1))})};u(i)},ue=s.useCallback(()=>{if(!U.current)return;let i=O.current;if(!i)return;let u=i.getContext("2d");if(!u)return;i.width=800,i.height=800,u.clearRect(0,0,800,800);let g=getComputedStyle(U.current),E=parseFloat(g.getPropertyValue("font-size"));u.font=`${E*2}px ${g.fontFamily}`,u.fillStyle=g.getPropertyValue("text")||"#FFF",u.fillText(y,16,40);let h=u.getImageData(0,0,800,800).data,I=[];for(let l=0;l<800;l++){let T=4*l*800;for(let m=0;m<800;m++){let x=T+4*m;h[x]!==0&&h[x+1]!==0&&h[x+2]!==0&&I.push({x:m,y:l,color:[h[x],h[x+1],h[x+2],h[x+3]]})}}M.current=I.map(({x:l,y:T,color:m})=>({x:l,y:T,r:1,color:`rgba(${m[0]}, ${m[1]}, ${m[2]}, ${m[3]})`}))},[y]);async function ce(i){if(i.preventDefault(),!(Date.now()-ae<me)&&(ie(Date.now()),!(!y.trim()||y.length>ye)&&f.isInitialized)){if(f.usageRemaining.messages!==null&&f.usageRemaining.messages!==void 0&&f.usageRemaining.messages<=0){P(!0);return}if(!(R||_||K)){if(w&&w(i),J(!0),ue(),U.current){let u=M.current.reduce((g,E)=>E.x>g?E.x:g,0);le(u)}Q(!0);for await(let u of f.messageStream(y));Q(!1),f.usageRemaining.messages!==null&&f.usageRemaining.messages!==void 0&&f.usageRemaining.messages<=0&&P(!0)}}}function fe(i){!_&&!R&&(Y(i.target.value),B&&B(i))}return ne("form",{className:z("w-full relative mx-auto backdrop-blur-sm border h-12 rounded-full overflow-hidden transition duration-200",e=="dark"&&"bg-[#0C0C0C]/80 border-[#242424]/90",e=="light"&&"bg-[#F8F8F8]/90 border-[#BEBEBE]/50",e=="auto"&&"bg-[#F8F8F8]/90 dark:bg-[#0C0C0C]/80 border-[#BEBEBE]/50 dark:border-[#242424]/90",c,R&&"cursor-not-allowed opacity-50"),onSubmit:ce,onFocus:V,children:[b("label",{htmlFor:"heylock-chat-input",className:"sr-only",children:"Chat message input"}),b("canvas",{"aria-hidden":"true",className:z("absolute pointer-events-none text-base transform scale-50 top-[20%] left-2 origin-top-left filter invert dark:invert-0 pr-20",_?"opacity-100":"opacity-0"),ref:O}),b("div",{"aria-live":"polite",className:"absolute inset-0 flex items-center rounded-full pointer-events-none",children:b(ge,{mode:"wait",children:!y&&b(X.p,{initial:{y:5,opacity:0},animate:{y:0,opacity:1},exit:{y:-10,opacity:0},transition:{duration:.2,ease:"linear"},className:z("text-base font-normal pl-4 text-left w-[calc(100%-2rem)] truncate",e=="dark"&&"text-white/50",e=="light"&&"text-[#6E6D84]",e=="auto"&&"text-[#6E6D84] dark:text-white/50",d),children:R?r:K?n:a[Z]},`current-placeholder-${Z}`)})}),b("input",{onChange:fe,ref:U,value:y,type:"text",disabled:R,className:z("w-full relative text-base z-50 bg-transparent h-full rounded-full pl-4 pr-20",e=="dark"&&"text-white",e=="light"&&"text-[#242424]",e=="auto"&&"text-[#242424] dark:text-white",p,_&&"text-transparent dark:text-transparent",R&&"cursor-not-allowed opacity-50")}),b("button",{"aria-label":"Send message","aria-disabled":!y||R,disabled:!y||R,type:"submit",className:z("absolute right-2 top-1/2 z-50 -translate-y-1/2 h-8 w-8 rounded-full disabled:bg-transparent transition duration-200 flex items-center justify-center cursor-pointer disabled:cursor-auto",e=="dark"&&"bg-[#242424]",e=="light"&&"bg-[#BEBEBE]/50",e=="auto"&&"bg-[#BEBEBE]/50 dark:bg-[#242424]",v),children:ne(X.svg,{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:z("h-4 w-4",e=="dark"&&"text-gray-300",e=="light"&&"text-[#6e6e6e]",e=="auto"&&"text-[#242424] dark:text-white",F),children:[b("path",{stroke:"none",d:"M0 0h24v24H0z",fill:"none"}),b(X.path,{d:"M5 12l14 0",initial:{strokeDasharray:"50%",strokeDashoffset:"50%"},animate:{strokeDashoffset:y?0:"50%",opacity:y.length>0?1:.4},transition:{duration:.3,ease:"linear"}}),b("path",{d:"M13 18l6 -6"}),b("path",{d:"M13 6l6 6"})]})})]})}import{twMerge as G}from"tailwind-merge";import{AnimatePresence as ke,motion as ve}from"framer-motion";import{twMerge as j}from"tailwind-merge";import{motion as $}from"framer-motion";import*as C from"react";import{jsx as k,jsxs as xe}from"react/jsx-runtime";function q({className:t,userMessageClassName:r,assistantMessageClassName:n}){let e=A(),[a,o]=C.useState([]),c=C.useRef(null);return C.useEffect(()=>{if(t!==void 0&&typeof t!="string")throw new Error("HeylockMessages: 'className' must be a string if provided.");if(r!==void 0&&typeof r!="string")throw new Error("HeylockMessages: 'userMessageClassName' must be a string if provided.");if(n!==void 0&&typeof n!="string")throw new Error("HeylockMessages: 'assistantMessageClassName' must be a string if provided.")},[t,r,n]),C.useEffect(()=>{e.isInitialized===!0&&o(()=>[...e.messageHistory]);let p=v=>{if(o(()=>[...v]),c.current)try{setTimeout(()=>{c.current.scrollTop=c.current.scrollHeight},0)}catch{}},d=e.onMessageHistoryChange(p);return()=>{typeof d=="function"&&d()}},[]),k("div",{className:j("w-full h-full overflow-y-auto",t),ref:c,children:a.map((p,d)=>k($.div,{initial:{opacity:0,x:p.role==="user"?5:-5,scale:.9},animate:{opacity:1,x:0,scale:1},className:j("px-4 py-3 rounded-2xl min-h-12 w-fit max-w-[31rem] mt-4 text-wrap shadow-lg/5",p.role==="user"?j(" bg-gradient-to-t from-[#2F94FF] to-[#45ABFF] text-white ml-auto rounded-br-sm",r):j(" bg-gradient-to-t from-[#F0F0F0] to-[#F2F2F2] text-black rounded-bl-sm",n)),children:p.content.trim().length>0?be(p.content):k(he,{})},"message-"+d))})}function be(t){let r=t.split(/(\*\*[^*]+\*\*)/g);return!t||t.trim()===""||t.trim()==="**"?null:r.map((n,e)=>{if(typeof n!="string")return null;let a=n.match(/^\*\*([^*]+)\*\*$/);return a?!a[1]||!a[1].trim()?null:k("span",{className:"font-medium",children:a[1]},e):n.trim()?k("span",{children:n},e):null})}function he(){let t={initial:{},animate:{transition:{staggerChildren:.2,repeat:1/0,repeatType:"loop",repeatDelay:.2}}},r={initial:{opacity:.2},animate:{opacity:[.2,1,.2],y:[1,-3,1],transition:{duration:1.2,repeat:1/0,ease:"easeInOut"}}};return k("div",{className:"flex items-center space-x-1 px-2 py-2",children:xe($.div,{className:"flex space-x-2",variants:t,initial:"initial",animate:"animate",children:[k($.div,{className:"w-2 h-2 bg-gray-400 rounded-full",variants:r}),k($.div,{className:"w-2 h-2 bg-gray-400 rounded-full",variants:r}),k($.div,{className:"w-2 h-2 bg-gray-400 rounded-full",variants:r})]})})}import{jsx as S,jsxs as N}from"react/jsx-runtime";function oe({className:t="w-[calc(100vw-0.75rem)] left-1/2 -translate-x-1/2 sm:w-[25rem] fixed bottom-4 px-3 sm:right-4 sm:left-auto sm:translate-x-0 z-50",messageContainerClassName:r="h-96 max-h-[calc(100vh-8rem)]",headerClassName:n,disabled:e=!1,closeButtonClassName:a,theme:o="auto",header:c="Chat"}){let[p,d]=L.useState(!1),v=A();L.useEffect(()=>{t&&typeof t!="string"&&console.error("HeylockExpandingChat: 'className' prop must be a string."),typeof e!="boolean"&&console.error("HeylockExpandingChat: 'disabled' prop must be a boolean.");let w=["light","dark","auto"];w.includes(o)||console.error(`HeylockExpandingChat: 'theme' prop must be one of ${w.join(", ")}.`),r&&typeof r!="string"&&console.error("HeylockExpandingChat: 'messageContainerClassName' prop must be a string."),n&&typeof n!="string"&&console.error("HeylockExpandingChat: 'headerClassName' prop must be a string."),a&&typeof a!="string"&&console.error("HeylockExpandingChat: 'closeButtonClassName' prop must be a string."),c&&typeof c!="string"&&console.error("HeylockExpandingChat: 'header' prop must be a string.")},[t,r,n,e,a,o,c]),L.useEffect(()=>{v.onMessageHistoryChange(()=>{d(!0)})},[]);function F(){d(!1)}function B(){d(!0)}return N("div",{className:t,children:[S(ke,{mode:"wait",children:p&&N(ve.div,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},exit:{opacity:0,y:10},className:G("w-full h-94 bg-black/20 backdrop-blur-sm border mb-6 rounded-2xl flex flex-col",o=="dark"&&"bg-[#0C0C0C]/80 border-[#242424]/90",o=="light"&&"bg-[#F8F8F8]/90 border-[#BEBEBE]/50",o=="auto"&&"bg-[#F8F8F8]/90 dark:bg-[#0C0C0C]/80 border-[#BEBEBE]/50 dark:border-[#242424]/90",r),children:[N("div",{className:G("w-full px-4 py-3 border-b flex justify-between items-center",o=="dark"&&"border-[#242424]/90",o=="light"&&"border-[#BEBEBE]/50",o=="auto"&&"border-[#BEBEBE]/50 dark:border-[#242424]/90",n),children:[S("span",{className:"text-[#71707d] dark:text-white/50",children:c}),S("button",{className:G("transition-all duration-150 rounded-sm p-0.5",o=="dark"&&"text-neutral-500 hover:text-white bg-transparent hover:bg-neutral-500/20",o=="light"&&"text-neutral-400 hover:text-[#242424] bg-transparent hover:bg-neutral-400/20",o=="auto"&&"text-neutral-400 dark:text-neutral-500 hover:text-[#242424] dark:hover:text-white bg-transparent hover:bg-neutral-400/20 dark:hover:bg-neutral-500/20",a),"aria-label":"Close chat",type:"button",tabIndex:0,onClick:F,children:S("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:S("path",{d:"M18 6L6 18M6 6l12 12"})})})]}),S(q,{className:"px-2 pb-3"})]})}),S(W,{onFocus:B,disabled:e,theme:o})]})}export{oe as HeylockExpandingChat,W as HeylockInput,q as HeylockMessages,re as HeylockProvider,A as useAgent};