@waniwani/sdk 0.0.8 → 0.0.10

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.
@@ -33,36 +33,28 @@ interface ChatWidgetProps {
33
33
  api?: string;
34
34
  /** Initial greeting shown before user types */
35
35
  welcomeMessage?: string;
36
- /** Header title */
37
- title?: string;
38
- /** Header subtitle */
39
- subtitle?: string;
40
36
  /** Theme overrides */
41
37
  theme?: ChatTheme;
42
38
  /** Additional headers to send with chat API requests */
43
39
  headers?: Record<string, string>;
44
40
  /** Additional body fields to send with each chat request */
45
41
  body?: Record<string, unknown>;
46
- /** Chat panel width in pixels */
42
+ /** Chat bar width in pixels. Defaults to 600. */
47
43
  width?: number;
48
- /** Chat panel height in pixels */
49
- height?: number;
44
+ /** Max height of the expanded messages panel in pixels. Defaults to 400. */
45
+ expandedHeight?: number;
46
+ /** Enable file attachments in the input. Defaults to false. */
47
+ allowAttachments?: boolean;
50
48
  /** Callback fired when a message is sent */
51
49
  onMessageSent?: (message: string) => void;
52
50
  /** Callback fired when a response is received */
53
51
  onResponseReceived?: () => void;
54
52
  }
55
- interface ChatEmbedConfig extends Omit<ChatWidgetProps, "onMessageSent" | "onResponseReceived"> {
56
- /** DOM element to mount into (defaults to document.body) */
57
- container?: HTMLElement;
58
- }
59
53
 
60
- declare function ChatWidget(props: ChatWidgetProps & {
61
- _shadowRoot?: ShadowRoot;
62
- }): react_jsx_runtime.JSX.Element;
54
+ declare function ChatWidget(props: ChatWidgetProps): react_jsx_runtime.JSX.Element;
63
55
 
64
56
  declare const DEFAULT_THEME: Required<ChatTheme>;
65
57
  declare function mergeTheme(userTheme?: ChatTheme): Required<ChatTheme>;
66
58
  declare function themeToCSSProperties(theme: Required<ChatTheme>): Record<string, string>;
67
59
 
68
- export { type ChatEmbedConfig, type ChatTheme, ChatWidget, type ChatWidgetProps, DEFAULT_THEME, mergeTheme, themeToCSSProperties };
60
+ export { type ChatTheme, ChatWidget, type ChatWidgetProps, DEFAULT_THEME, mergeTheme, themeToCSSProperties };
@@ -1,44 +1,3 @@
1
1
  "use client";
2
- import{useChat as xe}from"@ai-sdk/react";import{DefaultChatTransport as ve}from"ai";import{useCallback as Ce,useEffect as j,useRef as S,useState as ke}from"react";import{useCallback as f,useRef as se}from"react";function H(r){let e=se(r);e.current=r;let a=f((l,s)=>{let{apiKey:u,baseUrl:c="https://app.waniwani.ai"}=e.current;u&&fetch(`${c}/api/mcp/events`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${u}`},body:JSON.stringify({event:l,properties:s})}).catch(()=>{})},[]),n=f(()=>{a("tool.called",{name:"chat.opened",type:"other"})},[a]),t=f(()=>{a("tool.called",{name:"chat.message_sent",type:"other"})},[a]),i=f(()=>{a("tool.called",{name:"chat.response_received",type:"other"})},[a]);return{trackChatOpened:n,trackMessageSent:t,trackResponseReceived:i}}function B(){return`
3
- /* WaniWani Chat Widget Reset & Styles */
4
- *,
5
- *::before,
6
- *::after {
7
- box-sizing: border-box;
8
- margin: 0;
9
- padding: 0;
10
- }
11
-
12
- @keyframes ww-fade-in {
13
- from { opacity: 0; }
14
- to { opacity: 1; }
15
- }
16
-
17
- @keyframes ww-bounce {
18
- 0%, 60%, 100% { transform: translateY(0); }
19
- 30% { transform: translateY(-4px); }
20
- }
21
-
22
- @keyframes ww-pulse {
23
- 0%, 100% { opacity: 0.4; }
24
- 50% { opacity: 1; }
25
- }
26
-
27
- /* Scrollbar */
28
- .ww-scrollbar::-webkit-scrollbar {
29
- width: 4px;
30
- }
31
- .ww-scrollbar::-webkit-scrollbar-track {
32
- background: transparent;
33
- }
34
- .ww-scrollbar::-webkit-scrollbar-thumb {
35
- background: var(--ww-border);
36
- border-radius: 4px;
37
- }
38
- .ww-scrollbar::-webkit-scrollbar-thumb:hover {
39
- background: var(--ww-muted);
40
- }
41
- `.trim()}var W={primaryColor:"#6366f1",primaryForeground:"#ffffff",backgroundColor:"#ffffff",textColor:"#1f2937",mutedColor:"#6b7280",borderColor:"#e5e7eb",assistantBubbleColor:"#f3f4f6",userBubbleColor:"#6366f1",inputBackgroundColor:"#f9fafb",borderRadius:16,messageBorderRadius:12,fontFamily:"system-ui, -apple-system, 'Segoe UI', sans-serif"},oe={primaryColor:"--ww-primary",primaryForeground:"--ww-primary-fg",backgroundColor:"--ww-bg",textColor:"--ww-text",mutedColor:"--ww-muted",borderColor:"--ww-border",assistantBubbleColor:"--ww-assistant-bubble",userBubbleColor:"--ww-user-bubble",inputBackgroundColor:"--ww-input-bg",borderRadius:"--ww-radius",messageBorderRadius:"--ww-msg-radius",fontFamily:"--ww-font"};function b(r){return{...W,...r}}function y(r){let e={};for(let[a,n]of Object.entries(oe)){let t=r[a];e[n]=typeof t=="number"?`${t}px`:String(t)}return e}import{jsx as x,jsxs as ie}from"react/jsx-runtime";function L(r){let{title:e,subtitle:a}=r;return x("div",{style:{display:"flex",alignItems:"center",padding:"14px 16px",borderBottom:"1px solid var(--ww-border)",backgroundColor:"var(--ww-primary)",color:"var(--ww-primary-fg)",borderRadius:"var(--ww-radius) var(--ww-radius) 0 0"},children:ie("div",{style:{display:"flex",flexDirection:"column",gap:"2px"},children:[x("span",{style:{fontWeight:600,fontSize:"15px"},children:e}),a&&x("span",{style:{fontSize:"12px",opacity:.85},children:a})]})})}import{useCallback as le,useEffect as pe,useRef as de}from"react";import{jsx as w,jsxs as _}from"react/jsx-runtime";var A={xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",strokeWidth:1.5,stroke:"currentColor","aria-hidden":"true",role:"img"};function U(r){let e=r.size??20;return _("svg",{...A,width:e,height:e,children:[w("title",{children:"Send"}),w("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5"})]})}function F(r){let e=r.size??14;return _("svg",{...A,width:e,height:e,children:[w("title",{children:"Tool"}),w("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M11.42 15.17 17.25 21A2.652 2.652 0 0 0 21 17.25l-5.877-5.877M11.42 15.17l2.496-3.03c.317-.384.74-.626 1.208-.766M11.42 15.17l-4.655 5.653a2.548 2.548 0 1 1-3.586-3.586l6.837-5.63m5.108-.233c.55-.164 1.163-.188 1.743-.14a4.5 4.5 0 0 0 4.486-6.336l-3.276 3.277a3.004 3.004 0 0 1-2.25-2.25l3.276-3.276a4.5 4.5 0 0 0-6.336 4.486c.048.58.024 1.194-.14 1.743"})]})}import{jsx as v,jsxs as ue}from"react/jsx-runtime";function $(r){let{value:e,onChange:a,onSend:n,disabled:t}=r,i=de(null),l=le(s=>{s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),!t&&e.trim()&&n())},[t,e,n]);return pe(()=>{let s=i.current;s&&(s.style.height="auto",s.style.height=`${Math.min(s.scrollHeight,120)}px`)},[]),ue("div",{style:{display:"flex",alignItems:"flex-end",gap:"8px",padding:"12px 16px",borderTop:"1px solid var(--ww-border)",backgroundColor:"var(--ww-bg)"},children:[v("textarea",{ref:i,value:e,onChange:s=>a(s.target.value),onKeyDown:l,disabled:t,placeholder:"Type a message...",rows:1,style:{flex:1,resize:"none",border:"1px solid var(--ww-border)",borderRadius:"8px",padding:"8px 12px",fontSize:"14px",lineHeight:1.5,fontFamily:"var(--ww-font)",backgroundColor:"var(--ww-input-bg)",color:"var(--ww-text)",outline:"none",maxHeight:"120px",transition:"border-color 0.15s"},onFocus:s=>{s.currentTarget.style.borderColor="var(--ww-primary)"},onBlur:s=>{s.currentTarget.style.borderColor="var(--ww-border)"}}),v("button",{type:"button",onClick:n,disabled:t||!e.trim(),style:{display:"flex",alignItems:"center",justifyContent:"center",width:"36px",height:"36px",borderRadius:"8px",border:"none",backgroundColor:t||!e.trim()?"var(--ww-border)":"var(--ww-primary)",color:t||!e.trim()?"var(--ww-muted)":"var(--ww-primary-fg)",cursor:t||!e.trim()?"not-allowed":"pointer",transition:"background-color 0.15s, color 0.15s",flexShrink:0},"aria-label":"Send message",children:v(U,{size:18})})]})}import{useEffect as he,useRef as be}from"react";import{Fragment as V,jsx as o}from"react/jsx-runtime";function N(r){let e=r.text.split(/\n\n+/);return o(V,{children:e.map((a,n)=>o(ce,{block:a.trim()},n))})}function ce(r){let{block:e}=r;if(e.startsWith("```")){let n=e.split(`
42
- `).slice(1,-1).join(`
43
- `);return o("pre",{style:{backgroundColor:"var(--ww-border)",borderRadius:"6px",padding:"8px 12px",overflowX:"auto",fontSize:"13px",lineHeight:1.5,margin:"4px 0"},children:o("code",{children:n})})}if(/^[-*]\s/.test(e)){let a=e.split(/\n/).filter(n=>/^[-*]\s/.test(n));return o("ul",{style:{paddingLeft:"20px",margin:"4px 0"},children:a.map((n,t)=>o("li",{children:o(K,{text:n.replace(/^[-*]\s/,"")})},t))})}return o("p",{style:{margin:"4px 0",lineHeight:1.5},children:o(K,{text:e})})}function K(r){let e=fe(r.text);return o(V,{children:e.map((a,n)=>o(ge,{part:a},n))})}function ge(r){let{part:e}=r;return e.type==="text"?o("span",{children:e.value}):e.type==="bold"?o("strong",{style:{fontWeight:600},children:e.value}):e.type==="italic"?o("em",{children:e.value}):e.type==="code"?o("code",{style:{backgroundColor:"var(--ww-border)",borderRadius:"3px",padding:"1px 4px",fontSize:"0.9em"},children:e.value}):e.type==="link"?o("a",{href:e.href,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--ww-primary)",textDecoration:"underline"},children:e.value}):null}function fe(r){let e=[],a=/`([^`]+)`|\*\*([^*]+)\*\*|\*([^*]+)\*|\[([^\]]+)\]\(([^)]+)\)/g,n=0,t;for(t=a.exec(r);t!==null;)t.index>n&&e.push({type:"text",value:r.slice(n,t.index)}),t[1]!=null?e.push({type:"code",value:t[1]}):t[2]!=null?e.push({type:"bold",value:t[2]}):t[3]!=null?e.push({type:"italic",value:t[3]}):t[4]!=null&&t[5]!=null&&e.push({type:"link",value:t[4],href:t[5]}),n=t.index+t[0].length,t=a.exec(r);return n<r.length&&e.push({type:"text",value:r.slice(n)}),e}import{jsx as p,jsxs as me}from"react/jsx-runtime";function O(r){let{message:e}=r,a=e.role==="user";return p("div",{style:{display:"flex",justifyContent:a?"flex-end":"flex-start",marginBottom:"8px",animation:"ww-fade-in 0.2s ease-out"},children:p("div",{style:{maxWidth:"85%",padding:"10px 14px",borderRadius:a?"var(--ww-msg-radius) var(--ww-msg-radius) 4px var(--ww-msg-radius)":"var(--ww-msg-radius) var(--ww-msg-radius) var(--ww-msg-radius) 4px",backgroundColor:a?"var(--ww-user-bubble)":"var(--ww-assistant-bubble)",color:a?"var(--ww-primary-fg)":"var(--ww-text)",fontSize:"14px",lineHeight:1.5,wordBreak:"break-word"},children:e.parts.map((n,t)=>p(we,{part:n,isUser:a},t))})})}function we(r){let{part:e,isUser:a}=r;if(e.type==="text"&&e.text)return a?p("span",{children:e.text}):p(N,{text:e.text});if(e.type.startsWith("tool-")||e.type==="tool-invocation"){let n=e.toolName??e.type.replace("tool-",""),t=e.state==="input-streaming"||e.state==="input-available";return me("div",{style:{display:"flex",alignItems:"center",gap:"6px",padding:"4px 0",fontSize:"12px",color:"var(--ww-muted)",fontStyle:"italic"},children:[p(F,{size:12}),p("span",{children:t?`Using ${n}...`:`Used ${n}`}),t&&p("span",{style:{animation:"ww-pulse 1.5s ease-in-out infinite"},children:"..."})]})}return null}import{jsx as d,jsxs as q}from"react/jsx-runtime";function G(r){let{messages:e,status:a,welcomeMessage:n}=r,t=be(null);he(()=>{t.current&&(t.current.scrollTop=t.current.scrollHeight)},[]);let i=a==="submitted"||a==="streaming";return q("div",{ref:t,className:"ww-scrollbar",style:{flex:1,overflowY:"auto",padding:"16px",display:"flex",flexDirection:"column"},children:[n&&e.length===0&&d("div",{style:{display:"flex",justifyContent:"flex-start",marginBottom:"8px"},children:d("div",{style:{maxWidth:"85%",padding:"10px 14px",borderRadius:"var(--ww-msg-radius) var(--ww-msg-radius) var(--ww-msg-radius) 4px",backgroundColor:"var(--ww-assistant-bubble)",color:"var(--ww-text)",fontSize:"14px",lineHeight:1.5},children:n})}),e.map(l=>d(O,{message:l},l.id)),i&&d("div",{style:{display:"flex",justifyContent:"flex-start",marginBottom:"8px"},children:q("div",{style:{padding:"10px 14px",borderRadius:"var(--ww-msg-radius) var(--ww-msg-radius) var(--ww-msg-radius) 4px",backgroundColor:"var(--ww-assistant-bubble)",display:"flex",gap:"4px",alignItems:"center"},children:[d(C,{delay:"0s"}),d(C,{delay:"0.15s"}),d(C,{delay:"0.3s"})]})})]})}function C(r){return d("span",{style:{width:"6px",height:"6px",borderRadius:"50%",backgroundColor:"var(--ww-muted)",animation:"ww-bounce 1.2s ease-in-out infinite",animationDelay:r.delay}})}import{jsx as k,jsxs as ye}from"react/jsx-runtime";function Y(r){let{messages:e,input:a,onInputChange:n,onSend:t,status:i,title:l,subtitle:s,welcomeMessage:u,width:c,height:m}=r;return ye("div",{className:"ww-panel",style:{width:`${c}px`,height:`${m}px`,display:"flex",flexDirection:"column",backgroundColor:"var(--ww-bg)",borderRadius:"var(--ww-radius)",border:"1px solid var(--ww-border)",boxShadow:"0 20px 60px -12px rgba(0, 0, 0, 0.15), 0 8px 20px -8px rgba(0, 0, 0, 0.1)",overflow:"hidden",fontFamily:"var(--ww-font)"},children:[k(L,{title:l,subtitle:s}),k(G,{messages:e,status:i,welcomeMessage:u}),k($,{value:a,onChange:n,onSend:t,disabled:i!=="ready"})]})}import{jsx as J}from"react/jsx-runtime";var Se="https://app.waniwani.ai/api/chat";function Me(r){let{apiKey:e,api:a=Se,welcomeMessage:n,title:t="Chat",subtitle:i,theme:l,headers:s,body:u,width:c=400,height:m=600,onMessageSent:M,onResponseReceived:X,_shadowRoot:h}=r,Z=b(l),Q=y(Z),{trackChatOpened:R,trackMessageSent:T,trackResponseReceived:ee}=H({apiKey:e}),te=S(new ve({api:a,headers:{...s,...e?{"x-waniwani-api-key":e}:{}},body:u})),{messages:re,sendMessage:P,status:ae}=xe({transport:te.current,onFinish(){ee(),X?.()}}),[g,I]=ke(""),ne=Ce(()=>{g.trim()&&(P({text:g}),T(),M?.(g),I(""))},[g,P,T,M]),E=S(!1);j(()=>{if(h&&!E.current){E.current=!0;let D=document.createElement("style");D.textContent=B(),h.appendChild(D)}},[h]);let z=S(!1);return j(()=>{z.current||(z.current=!0,R())},[R]),J("div",{style:Q,"data-waniwani-chat":"",children:J(Y,{messages:re,input:g,onInputChange:I,onSend:ne,status:ae,title:t,subtitle:i,welcomeMessage:n,width:c,height:m})})}export{Me as ChatWidget,W as DEFAULT_THEME,b as mergeTheme,y as themeToCSSProperties};
2
+ import{useChat as ut}from"@ai-sdk/react";import{DefaultChatTransport as ct}from"ai";import{useCallback as Z,useEffect as dt,useRef as we,useState as Ie}from"react";import{FileIcon as Re}from"lucide-react";import{clsx as He}from"clsx";import{twMerge as Ae}from"tailwind-merge";function s(...e){return Ae(He(e))}import{jsx as U,jsxs as Be}from"react/jsx-runtime";var ee=({files:e,className:t,...o})=>e.length===0?null:U("div",{className:s("flex flex-wrap gap-1.5",t),...o,children:e.map((r,n)=>U(Fe,{file:r},n))});function Fe({file:e}){return e.mediaType?.startsWith("image/")&&e.url?U("img",{src:e.url,alt:e.filename??"attachment",className:"h-16 max-w-32 rounded object-cover"}):Be("span",{className:"inline-flex items-center gap-1.5 rounded bg-background/20 px-2 py-1 text-xs",children:[U(Re,{className:"size-3 shrink-0"}),U("span",{className:"max-w-24 truncate",children:e.filename??"file"})]})}import{ArrowDownIcon as De}from"lucide-react";import{useCallback as Ue}from"react";import{StickToBottom as te,useStickToBottomContext as ze}from"use-stick-to-bottom";import{jsx as Se}from"react/jsx-runtime";var B=({className:e,variant:t="default",size:o="default",type:r="button",...n})=>Se("button",{type:r,className:s("inline-flex cursor-pointer items-center justify-center rounded-md font-medium transition-colors disabled:pointer-events-none disabled:opacity-50",t==="default"&&"bg-primary text-primary-foreground hover:bg-primary/90",t==="outline"&&"border border-border bg-background hover:bg-accent hover:text-accent-foreground",t==="ghost"&&"hover:bg-accent hover:text-accent-foreground",o==="default"&&"h-9 px-4 py-2 text-sm",o==="sm"&&"h-8 px-3 text-xs",o==="icon"&&"size-9",o==="icon-sm"&&"size-7",e),...n});import{jsx as q}from"react/jsx-runtime";var oe=({className:e,...t})=>q(te,{className:s("relative flex-1 overflow-y-hidden",e),initial:"smooth",resize:"smooth",role:"log",...t}),re=({className:e,...t})=>q(te.Content,{className:s("flex flex-col gap-8 p-4",e),...t}),ne=({className:e,...t})=>{let{isAtBottom:o,scrollToBottom:r}=ze(),n=Ue(()=>{r()},[r]);return!o&&q(B,{className:s("absolute bottom-4 left-[50%] translate-x-[-50%] rounded-full",e),onClick:n,size:"icon",variant:"outline",...t,children:q(De,{className:"size-4"})})};import{jsx as se}from"react/jsx-runtime";var K=({className:e,size:t=5,...o})=>se("div",{className:s("flex items-center gap-1",e),...o,children:[0,1,2].map(r=>se("div",{className:"rounded-full bg-muted-foreground/60",style:{width:t,height:t,animation:"ww-pulse 1.4s ease-in-out infinite",animationDelay:`${r*.2}s`}},r))});import{cjk as Oe}from"@streamdown/cjk";import{code as We}from"@streamdown/code";import{memo as qe}from"react";import{Streamdown as Ve}from"streamdown";import{jsx as $}from"react/jsx-runtime";var V=({className:e,from:t,...o})=>$("div",{className:s("group flex w-full max-w-[95%] flex-col gap-2",t==="user"?"is-user ml-auto justify-end":"is-assistant",e),...o}),j=({children:e,className:t,...o})=>$("div",{className:s("flex w-fit min-w-0 max-w-full flex-col gap-2 overflow-hidden text-sm","group-[.is-user]:ml-auto group-[.is-user]:rounded-lg group-[.is-user]:bg-primary group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:text-primary-foreground","group-[.is-assistant]:rounded-lg group-[.is-assistant]:bg-accent group-[.is-assistant]:px-4 group-[.is-assistant]:py-3 group-[.is-assistant]:text-foreground",t),...o,children:e}),je={cjk:Oe,code:We},_=qe(({className:e,...t})=>$(Ve,{className:s("size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",e),plugins:je,...t}),(e,t)=>e.children===t.children);_.displayName="MessageResponse";import{ArrowUpIcon as _e,LoaderIcon as Ke,PaperclipIcon as $e,SquareIcon as Je,XIcon as Xe}from"lucide-react";import{nanoid as Ge}from"nanoid";import{createContext as Qe,useCallback as M,useContext as Ye,useEffect as J,useMemo as Ze,useRef as X,useState as ae}from"react";import{jsx as h,jsxs as de}from"react/jsx-runtime";var et=async e=>{try{let o=await(await fetch(e)).blob();return new Promise(r=>{let n=new FileReader;n.onloadend=()=>r(n.result),n.onerror=()=>r(null),n.readAsDataURL(o)})}catch{return null}},ie=Qe(null),le=()=>{let e=Ye(ie);if(!e)throw new Error("usePromptInputAttachments must be used within a PromptInput");return e},pe=({className:e,accept:t,multiple:o,globalDrop:r,maxFiles:n,maxFileSize:l,onSubmit:g,children:b,...w})=>{let v=X(null),d=X(null),[c,y]=ae([]),H=X(c);J(()=>{H.current=c},[c]);let P=M(()=>{v.current?.click()},[]),I=M(a=>{let x=[...a];if(x.length===0)return;let f=L=>l?L.size<=l:!0,C=x.filter(f);y(L=>{let N=typeof n=="number"?Math.max(0,n-L.length):void 0,T=typeof N=="number"?C.slice(0,N):C;return[...L,...T.map(k=>({filename:k.name,id:Ge(),mediaType:k.type,type:"file",url:URL.createObjectURL(k)}))]})},[n,l]),A=M(a=>{y(x=>{let f=x.find(C=>C.id===a);return f?.url&&URL.revokeObjectURL(f.url),x.filter(C=>C.id!==a)})},[]),R=M(()=>{y(a=>{for(let x of a)x.url&&URL.revokeObjectURL(x.url);return[]})},[]);J(()=>()=>{for(let a of H.current)a.url&&URL.revokeObjectURL(a.url)},[]);let z=M(a=>{a.currentTarget.files&&I(a.currentTarget.files),a.currentTarget.value=""},[I]);J(()=>{if(!r)return;let a=f=>{f.dataTransfer?.types?.includes("Files")&&f.preventDefault()},x=f=>{f.dataTransfer?.types?.includes("Files")&&f.preventDefault(),f.dataTransfer?.files&&f.dataTransfer.files.length>0&&I(f.dataTransfer.files)};return document.addEventListener("dragover",a),document.addEventListener("drop",x),()=>{document.removeEventListener("dragover",a),document.removeEventListener("drop",x)}},[I,r]);let D=M(async a=>{a.preventDefault();let x=a.currentTarget,C=new FormData(x).get("message")||"";x.reset();let L=await Promise.all(c.map(async({id:N,...T})=>{if(T.url?.startsWith("blob:")){let k=await et(T.url);return{...T,url:k??T.url}}return T}));try{let N=g({files:L,text:C},a);N instanceof Promise&&await N,R()}catch{}},[c,g,R]),O=Ze(()=>({add:I,clear:R,files:c,openFileDialog:P,remove:A}),[c,I,A,R,P]);return de(ie.Provider,{value:O,children:[h("input",{accept:t,"aria-label":"Upload files",className:"hidden",multiple:o,onChange:z,ref:v,title:"Upload files",type:"file"}),h("form",{className:s("flex w-full flex-col rounded-lg border border-border bg-background",e),onSubmit:D,ref:d,...w,children:b})]})};var me=({onChange:e,onKeyDown:t,className:o,placeholder:r="What would you like to know?",...n})=>{let l=le(),[g,b]=ae(!1),w=M(d=>{if(t?.(d),!d.defaultPrevented){if(d.key==="Enter"){if(g||d.nativeEvent.isComposing||d.shiftKey)return;d.preventDefault();let{form:c}=d.currentTarget;if(c?.querySelector('button[type="submit"]')?.disabled)return;c?.requestSubmit()}if(d.key==="Backspace"&&d.currentTarget.value===""&&l.files.length>0){d.preventDefault();let c=l.files.at(-1);c&&l.remove(c.id)}}},[t,g,l]),v=M(d=>{let c=d.clipboardData?.items;if(!c)return;let y=[];for(let H of c)if(H.kind==="file"){let P=H.getAsFile();P&&y.push(P)}y.length>0&&(d.preventDefault(),l.add(y))},[l]);return h("textarea",{className:s("field-sizing-content max-h-48 min-h-16 w-full resize-none border-0 bg-transparent px-3 py-3 text-sm outline-none placeholder:text-muted-foreground",o),name:"message",onCompositionEnd:()=>b(!1),onCompositionStart:()=>b(!0),onKeyDown:w,onPaste:v,placeholder:r,onChange:e,...n})},ue=({className:e,status:t,onStop:o,onClick:r,children:n,...l})=>{let g=t==="submitted"||t==="streaming",b=h(_e,{className:"size-4"});t==="submitted"?b=h(Ke,{className:"size-4 animate-spin"}):t==="streaming"&&(b=h(Je,{className:"size-4"}));let w=M(v=>{if(g&&o){v.preventDefault(),o();return}r?.(v)},[g,o,r]);return h(B,{"aria-label":g?"Stop":"Submit",className:s(e),onClick:w,size:"icon-sm",type:g&&o?"button":"submit",variant:"default",...l,children:n??b})},ce=({className:e,children:t,...o})=>{let r=le();return r.files.length>0?de(B,{className:s("group relative",e),onClick:()=>r.clear(),size:"icon-sm",type:"button",variant:"ghost","aria-label":"Remove all attachments",...o,children:[h("span",{className:"flex size-5 items-center justify-center rounded-full bg-primary text-[10px] font-medium text-primary-foreground transition-opacity group-hover:opacity-0",children:r.files.length}),h(Xe,{className:"absolute size-4 opacity-0 transition-opacity group-hover:opacity-100"})]}):h(B,{className:s(e),onClick:()=>r.openFileDialog(),size:"icon-sm",type:"button",variant:"ghost",...o,children:t??h($e,{className:"size-4"})})};import{CheckCircleIcon as fe,ChevronDownIcon as tt,CircleIcon as ot,ClockIcon as ge,WrenchIcon as rt,XCircleIcon as xe}from"lucide-react";import{createContext as nt,isValidElement as st,useContext as be,useState as at}from"react";import{jsx as i,jsxs as S}from"react/jsx-runtime";var G=nt({open:!1,toggle:()=>{}}),he=({className:e,defaultOpen:t=!1,children:o,...r})=>{let[n,l]=at(t);return i(G.Provider,{value:{open:n,toggle:()=>l(g=>!g)},children:i("div",{className:s("mb-4 w-full rounded-md border border-border",e),"data-state":n?"open":"closed",...r,children:o})})},it={"approval-requested":"Awaiting Approval","approval-responded":"Responded","input-available":"Running","input-streaming":"Pending","output-available":"Completed","output-denied":"Denied","output-error":"Error"},lt={"approval-requested":i(ge,{className:"size-4 text-yellow-600"}),"approval-responded":i(fe,{className:"size-4 text-blue-600"}),"input-available":i(ge,{className:"size-4 animate-pulse"}),"input-streaming":i(ot,{className:"size-4"}),"output-available":i(fe,{className:"size-4 text-green-600"}),"output-denied":i(xe,{className:"size-4 text-orange-600"}),"output-error":i(xe,{className:"size-4 text-red-600"})},pt=e=>S("span",{className:"inline-flex items-center gap-1.5 rounded-full border border-border bg-muted px-2 py-0.5 text-xs text-muted-foreground",children:[lt[e],it[e]]}),ve=({className:e,title:t,state:o,...r})=>{let{open:n,toggle:l}=be(G);return S("button",{type:"button",onClick:l,className:s("flex w-full items-center justify-between gap-4 p-3",e),"aria-expanded":n,...r,children:[S("div",{className:"flex items-center gap-2",children:[i(rt,{className:"size-4 text-muted-foreground"}),i("span",{className:"text-sm font-medium",children:t}),pt(o)]}),i(tt,{className:s("size-4 text-muted-foreground transition-transform",n&&"rotate-180")})]})},ye=({className:e,children:t,...o})=>{let{open:r}=be(G);return r?i("div",{className:s("space-y-4 p-4",e),...o,children:t}):null},Pe=({className:e,input:t,...o})=>S("div",{className:s("space-y-2 overflow-hidden",e),...o,children:[i("h4",{className:"text-xs font-medium uppercase tracking-wide text-muted-foreground",children:"Parameters"}),i("pre",{className:"overflow-x-auto rounded-md bg-muted/50 p-3 text-xs",children:i("code",{children:JSON.stringify(t,null,2)})})]}),Ce=({className:e,output:t,errorText:o,...r})=>{if(!(t||o))return null;let n;return typeof t=="object"&&!st(t)?n=i("pre",{className:"overflow-x-auto p-3 text-xs",children:i("code",{children:JSON.stringify(t,null,2)})}):typeof t=="string"?n=i("pre",{className:"overflow-x-auto p-3 text-xs",children:i("code",{children:t})}):n=i("div",{className:"p-3",children:t}),S("div",{className:s("space-y-2",e),...r,children:[i("h4",{className:"text-xs font-medium uppercase tracking-wide text-muted-foreground",children:o?"Error":"Result"}),S("div",{className:s("overflow-x-auto rounded-md text-xs",o?"bg-destructive/10 text-destructive":"bg-muted/50 text-foreground"),children:[o&&i("div",{className:"p-3",children:o}),n]})]})};var Te={primaryColor:"#6366f1",primaryForeground:"#ffffff",backgroundColor:"#ffffff",textColor:"#1f2937",mutedColor:"#6b7280",borderColor:"#e5e7eb",assistantBubbleColor:"#f3f4f6",userBubbleColor:"#6366f1",inputBackgroundColor:"#f9fafb",borderRadius:16,messageBorderRadius:12,fontFamily:"system-ui, -apple-system, 'Segoe UI', sans-serif"},mt={primaryColor:["--ww-primary","--color-primary"],primaryForeground:["--ww-primary-fg","--color-primary-foreground"],backgroundColor:["--ww-bg","--color-background"],textColor:["--ww-text","--color-foreground","--color-accent-foreground"],mutedColor:["--ww-muted","--color-muted-foreground"],borderColor:["--ww-border","--color-border"],assistantBubbleColor:["--ww-assistant-bubble","--color-accent"],userBubbleColor:["--ww-user-bubble"],inputBackgroundColor:["--ww-input-bg","--color-input"],borderRadius:["--ww-radius","--radius"],messageBorderRadius:["--ww-msg-radius"],fontFamily:["--ww-font"]};function Q(e){return{...Te,...e}}function Y(e){let t={};for(let[o,r]of Object.entries(mt)){let n=e[o],l=typeof n=="number"?`${n}px`:String(n);for(let g of r)t[g]=l}return t}import{jsx as u,jsxs as E}from"react/jsx-runtime";function ft(e){let{api:t="https://app.waniwani.ai/api/chat",welcomeMessage:o,theme:r,headers:n,body:l,width:g=600,expandedHeight:b=400,allowAttachments:w=!1,onMessageSent:v,onResponseReceived:d}=e,c=Q(r),y=Y(c),H=we(new ct({api:t,headers:{...n},body:l})),{messages:P,sendMessage:I,status:A}=ut({transport:H.current,onFinish(){d?.()}}),[R,z]=Ie(""),[D,O]=Ie(!1),a=we(null),x=P.length>0,f=D;dt(()=>{if(!D)return;let m=F=>{a.current&&!a.current.contains(F.target)&&O(!1)};return document.addEventListener("mousedown",m),()=>document.removeEventListener("mousedown",m)},[D]);let C=Z(m=>{let F=!!m.text?.trim(),W=!!m.files?.length;(F||W)&&(I({text:m.text||"",files:m.files}),v?.(m.text||""),z(""))},[I,v]),L=Z(m=>{z(m.target.value)},[]),N=Z(()=>{O(!0)},[]),T=A==="submitted"||A==="streaming",k=P[P.length-1],Me=T&&(!x||k.role==="user");return E("div",{ref:a,style:{...y,width:g},"data-waniwani-chat":"",className:"flex flex-col font-[family-name:var(--ww-font)] text-foreground",children:[u("div",{className:s("overflow-hidden bg-background/80 backdrop-blur-xl transition-all duration-300 ease-out",f?"opacity-100 translate-y-0":"opacity-0 translate-y-2 pointer-events-none max-h-0"),style:{...f?{maxHeight:b}:void 0,maskImage:"linear-gradient(to bottom, transparent, black 24px, black calc(100% - 16px), transparent), linear-gradient(to right, transparent, black 16px, black calc(100% - 16px), transparent)",maskComposite:"intersect",WebkitMaskImage:"linear-gradient(to bottom, transparent, black 24px, black calc(100% - 16px), transparent), linear-gradient(to right, transparent, black 16px, black calc(100% - 16px), transparent)",WebkitMaskComposite:"source-in"},children:E(oe,{className:"flex-1",style:{height:b},children:[E(re,{children:[o&&u(V,{from:"assistant",children:u(j,{children:u(_,{children:o})})}),P.map(m=>{let F=m.parts.filter(p=>p.type==="text"),W=m.parts.filter(p=>p.type==="file"),Le=m.parts.filter(p=>"toolCallId"in p),Ne=m===k&&m.role==="assistant",ke=F.length>0;return E(V,{from:m.role,children:[Le.map(p=>E(he,{defaultOpen:p.state==="output-available",children:[u(ve,{title:p.title??p.type.replace("tool-",""),state:p.state}),E(ye,{children:[u(Pe,{input:p.input}),"output"in p&&p.output!==void 0&&u(Ce,{output:p.output,errorText:"errorText"in p?p.errorText:void 0})]})]},p.toolCallId)),E(j,{children:[W.length>0&&u(ee,{files:W}),ke?F.map((p,Ee)=>u(_,{children:p.type==="text"?p.text:""},`${m.id}-${Ee}`)):Ne&&T&&u(K,{})]})]},m.id)}),Me&&u(V,{from:"assistant",children:u(j,{children:u(K,{})})})]}),u(ne,{})]})}),u("div",{className:"shrink-0",children:u(pe,{onSubmit:C,globalDrop:w,multiple:w,className:s("rounded-[var(--ww-radius)] shadow-sm transition-all duration-300 ease-out"),children:E("div",{className:"flex items-center gap-1 px-3 py-2",children:[w&&u(ce,{}),u(me,{onChange:L,value:R,placeholder:"Type a message...",onFocus:N,className:"min-h-0 py-1.5 px-2"}),u(ue,{status:A})]})})})]})}export{ft as ChatWidget,Te as DEFAULT_THEME,Q as mergeTheme,Y as themeToCSSProperties};
44
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/chat/components/chat-widget.tsx","../../src/chat/hooks/use-chat-tracking.ts","../../src/chat/styles.ts","../../src/chat/theme.ts","../../src/chat/components/chat-header.tsx","../../src/chat/components/chat-input.tsx","../../src/chat/icons.tsx","../../src/chat/components/chat-messages.tsx","../../src/chat/components/chat-markdown.tsx","../../src/chat/components/chat-message.tsx","../../src/chat/components/chat-panel.tsx"],"sourcesContent":["\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport } from \"ai\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { ChatWidgetProps } from \"../@types\";\nimport { useChatTracking } from \"../hooks/use-chat-tracking\";\nimport { buildStyleSheet } from \"../styles\";\nimport { mergeTheme, themeToCSSProperties } from \"../theme\";\nimport { ChatPanel } from \"./chat-panel\";\n\nconst DEFAULT_API = \"https://app.waniwani.ai/api/chat\";\n\nexport function ChatWidget(\n\tprops: ChatWidgetProps & { _shadowRoot?: ShadowRoot },\n) {\n\tconst {\n\t\tapiKey,\n\t\tapi = DEFAULT_API,\n\t\twelcomeMessage,\n\t\ttitle = \"Chat\",\n\t\tsubtitle,\n\t\ttheme: userTheme,\n\t\theaders: userHeaders,\n\t\tbody,\n\t\twidth = 400,\n\t\theight = 600,\n\t\tonMessageSent,\n\t\tonResponseReceived,\n\t\t_shadowRoot,\n\t} = props;\n\n\tconst resolvedTheme = mergeTheme(userTheme);\n\tconst cssVars = themeToCSSProperties(resolvedTheme);\n\n\tconst { trackChatOpened, trackMessageSent, trackResponseReceived } =\n\t\tuseChatTracking({ apiKey });\n\n\tconst transportRef = useRef(\n\t\tnew DefaultChatTransport({\n\t\t\tapi,\n\t\t\theaders: {\n\t\t\t\t...userHeaders,\n\t\t\t\t...(apiKey ? { \"x-waniwani-api-key\": apiKey } : {}),\n\t\t\t},\n\t\t\tbody,\n\t\t}),\n\t);\n\n\tconst { messages, sendMessage, status } = useChat({\n\t\ttransport: transportRef.current,\n\t\tonFinish() {\n\t\t\ttrackResponseReceived();\n\t\t\tonResponseReceived?.();\n\t\t},\n\t});\n\n\tconst [input, setInput] = useState(\"\");\n\n\tconst handleSend = useCallback(() => {\n\t\tif (!input.trim()) return;\n\t\tsendMessage({ text: input });\n\t\ttrackMessageSent();\n\t\tonMessageSent?.(input);\n\t\tsetInput(\"\");\n\t}, [input, sendMessage, trackMessageSent, onMessageSent]);\n\n\t// Inject stylesheet into shadow root for embed mode\n\tconst styleInjected = useRef(false);\n\tuseEffect(() => {\n\t\tif (_shadowRoot && !styleInjected.current) {\n\t\t\tstyleInjected.current = true;\n\t\t\tconst style = document.createElement(\"style\");\n\t\t\tstyle.textContent = buildStyleSheet();\n\t\t\t_shadowRoot.appendChild(style);\n\t\t}\n\t}, [_shadowRoot]);\n\n\t// Track chat opened on mount\n\tconst tracked = useRef(false);\n\tuseEffect(() => {\n\t\tif (!tracked.current) {\n\t\t\ttracked.current = true;\n\t\t\ttrackChatOpened();\n\t\t}\n\t}, [trackChatOpened]);\n\n\treturn (\n\t\t<div style={cssVars} data-waniwani-chat=\"\">\n\t\t\t<ChatPanel\n\t\t\t\tmessages={messages}\n\t\t\t\tinput={input}\n\t\t\t\tonInputChange={setInput}\n\t\t\t\tonSend={handleSend}\n\t\t\t\tstatus={status}\n\t\t\t\ttitle={title}\n\t\t\t\tsubtitle={subtitle}\n\t\t\t\twelcomeMessage={welcomeMessage}\n\t\t\t\twidth={width}\n\t\t\t\theight={height}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n","import { useCallback, useRef } from \"react\";\n\ninterface TrackingConfig {\n\tapiKey?: string;\n\tbaseUrl?: string;\n}\n\n/**\n * Lightweight browser-compatible tracking hook for chat events.\n * Fires events to the WaniWani API without requiring the full tracking client\n * (which depends on process.env).\n */\nexport function useChatTracking(config: TrackingConfig) {\n\tconst configRef = useRef(config);\n\tconfigRef.current = config;\n\n\tconst trackEvent = useCallback(\n\t\t(event: string, properties?: Record<string, unknown>) => {\n\t\t\tconst { apiKey, baseUrl = \"https://app.waniwani.ai\" } = configRef.current;\n\t\t\tif (!apiKey) return;\n\n\t\t\tfetch(`${baseUrl}/api/mcp/events`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tevent,\n\t\t\t\t\tproperties,\n\t\t\t\t}),\n\t\t\t}).catch(() => {\n\t\t\t\t// Silently fail - tracking should never break the chat\n\t\t\t});\n\t\t},\n\t\t[],\n\t);\n\n\tconst trackChatOpened = useCallback(() => {\n\t\ttrackEvent(\"tool.called\", { name: \"chat.opened\", type: \"other\" });\n\t}, [trackEvent]);\n\n\tconst trackMessageSent = useCallback(() => {\n\t\ttrackEvent(\"tool.called\", { name: \"chat.message_sent\", type: \"other\" });\n\t}, [trackEvent]);\n\n\tconst trackResponseReceived = useCallback(() => {\n\t\ttrackEvent(\"tool.called\", {\n\t\t\tname: \"chat.response_received\",\n\t\t\ttype: \"other\",\n\t\t});\n\t}, [trackEvent]);\n\n\treturn { trackChatOpened, trackMessageSent, trackResponseReceived };\n}\n","export function buildStyleSheet(): string {\n\treturn `\n/* WaniWani Chat Widget Reset & Styles */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n\n@keyframes ww-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes ww-bounce {\n 0%, 60%, 100% { transform: translateY(0); }\n 30% { transform: translateY(-4px); }\n}\n\n@keyframes ww-pulse {\n 0%, 100% { opacity: 0.4; }\n 50% { opacity: 1; }\n}\n\n/* Scrollbar */\n.ww-scrollbar::-webkit-scrollbar {\n width: 4px;\n}\n.ww-scrollbar::-webkit-scrollbar-track {\n background: transparent;\n}\n.ww-scrollbar::-webkit-scrollbar-thumb {\n background: var(--ww-border);\n border-radius: 4px;\n}\n.ww-scrollbar::-webkit-scrollbar-thumb:hover {\n background: var(--ww-muted);\n}\n`.trim();\n}\n","import type { ChatTheme } from \"./@types\";\n\nexport const DEFAULT_THEME: Required<ChatTheme> = {\n\tprimaryColor: \"#6366f1\",\n\tprimaryForeground: \"#ffffff\",\n\tbackgroundColor: \"#ffffff\",\n\ttextColor: \"#1f2937\",\n\tmutedColor: \"#6b7280\",\n\tborderColor: \"#e5e7eb\",\n\tassistantBubbleColor: \"#f3f4f6\",\n\tuserBubbleColor: \"#6366f1\",\n\tinputBackgroundColor: \"#f9fafb\",\n\tborderRadius: 16,\n\tmessageBorderRadius: 12,\n\tfontFamily: \"system-ui, -apple-system, 'Segoe UI', sans-serif\",\n};\n\nconst CSS_VAR_MAP: Record<keyof ChatTheme, string> = {\n\tprimaryColor: \"--ww-primary\",\n\tprimaryForeground: \"--ww-primary-fg\",\n\tbackgroundColor: \"--ww-bg\",\n\ttextColor: \"--ww-text\",\n\tmutedColor: \"--ww-muted\",\n\tborderColor: \"--ww-border\",\n\tassistantBubbleColor: \"--ww-assistant-bubble\",\n\tuserBubbleColor: \"--ww-user-bubble\",\n\tinputBackgroundColor: \"--ww-input-bg\",\n\tborderRadius: \"--ww-radius\",\n\tmessageBorderRadius: \"--ww-msg-radius\",\n\tfontFamily: \"--ww-font\",\n};\n\nexport function mergeTheme(userTheme?: ChatTheme): Required<ChatTheme> {\n\treturn { ...DEFAULT_THEME, ...userTheme };\n}\n\nexport function themeToCSSProperties(\n\ttheme: Required<ChatTheme>,\n): Record<string, string> {\n\tconst vars: Record<string, string> = {};\n\tfor (const [key, cssVar] of Object.entries(CSS_VAR_MAP)) {\n\t\tconst value = theme[key as keyof ChatTheme];\n\t\tvars[cssVar] = typeof value === \"number\" ? `${value}px` : String(value);\n\t}\n\treturn vars;\n}\n","interface ChatHeaderProps {\n\ttitle: string;\n\tsubtitle?: string;\n}\n\nexport function ChatHeader(props: ChatHeaderProps) {\n\tconst { title, subtitle } = props;\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tdisplay: \"flex\",\n\t\t\t\talignItems: \"center\",\n\t\t\t\tpadding: \"14px 16px\",\n\t\t\t\tborderBottom: \"1px solid var(--ww-border)\",\n\t\t\t\tbackgroundColor: \"var(--ww-primary)\",\n\t\t\t\tcolor: \"var(--ww-primary-fg)\",\n\t\t\t\tborderRadius: \"var(--ww-radius) var(--ww-radius) 0 0\",\n\t\t\t}}\n\t\t>\n\t\t\t<div style={{ display: \"flex\", flexDirection: \"column\", gap: \"2px\" }}>\n\t\t\t\t<span style={{ fontWeight: 600, fontSize: \"15px\" }}>{title}</span>\n\t\t\t\t{subtitle && (\n\t\t\t\t\t<span style={{ fontSize: \"12px\", opacity: 0.85 }}>{subtitle}</span>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import type React from \"react\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport { SendIcon } from \"../icons\";\n\ninterface ChatInputProps {\n\tvalue: string;\n\tonChange: (value: string) => void;\n\tonSend: () => void;\n\tdisabled: boolean;\n}\n\nexport function ChatInput(props: ChatInputProps) {\n\tconst { value, onChange, onSend, disabled } = props;\n\tconst textareaRef = useRef<HTMLTextAreaElement>(null);\n\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n\t\t\tif (e.key === \"Enter\" && !e.shiftKey) {\n\t\t\t\te.preventDefault();\n\t\t\t\tif (!disabled && value.trim()) {\n\t\t\t\t\tonSend();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[disabled, value, onSend],\n\t);\n\n\t// Auto-resize textarea\n\tuseEffect(() => {\n\t\tconst textarea = textareaRef.current;\n\t\tif (textarea) {\n\t\t\ttextarea.style.height = \"auto\";\n\t\t\ttextarea.style.height = `${Math.min(textarea.scrollHeight, 120)}px`;\n\t\t}\n\t}, []);\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tdisplay: \"flex\",\n\t\t\t\talignItems: \"flex-end\",\n\t\t\t\tgap: \"8px\",\n\t\t\t\tpadding: \"12px 16px\",\n\t\t\t\tborderTop: \"1px solid var(--ww-border)\",\n\t\t\t\tbackgroundColor: \"var(--ww-bg)\",\n\t\t\t}}\n\t\t>\n\t\t\t<textarea\n\t\t\t\tref={textareaRef}\n\t\t\t\tvalue={value}\n\t\t\t\tonChange={(e) => onChange(e.target.value)}\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tplaceholder=\"Type a message...\"\n\t\t\t\trows={1}\n\t\t\t\tstyle={{\n\t\t\t\t\tflex: 1,\n\t\t\t\t\tresize: \"none\",\n\t\t\t\t\tborder: \"1px solid var(--ww-border)\",\n\t\t\t\t\tborderRadius: \"8px\",\n\t\t\t\t\tpadding: \"8px 12px\",\n\t\t\t\t\tfontSize: \"14px\",\n\t\t\t\t\tlineHeight: 1.5,\n\t\t\t\t\tfontFamily: \"var(--ww-font)\",\n\t\t\t\t\tbackgroundColor: \"var(--ww-input-bg)\",\n\t\t\t\t\tcolor: \"var(--ww-text)\",\n\t\t\t\t\toutline: \"none\",\n\t\t\t\t\tmaxHeight: \"120px\",\n\t\t\t\t\ttransition: \"border-color 0.15s\",\n\t\t\t\t}}\n\t\t\t\tonFocus={(e) => {\n\t\t\t\t\te.currentTarget.style.borderColor = \"var(--ww-primary)\";\n\t\t\t\t}}\n\t\t\t\tonBlur={(e) => {\n\t\t\t\t\te.currentTarget.style.borderColor = \"var(--ww-border)\";\n\t\t\t\t}}\n\t\t\t/>\n\t\t\t<button\n\t\t\t\ttype=\"button\"\n\t\t\t\tonClick={onSend}\n\t\t\t\tdisabled={disabled || !value.trim()}\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\tjustifyContent: \"center\",\n\t\t\t\t\twidth: \"36px\",\n\t\t\t\t\theight: \"36px\",\n\t\t\t\t\tborderRadius: \"8px\",\n\t\t\t\t\tborder: \"none\",\n\t\t\t\t\tbackgroundColor:\n\t\t\t\t\t\tdisabled || !value.trim()\n\t\t\t\t\t\t\t? \"var(--ww-border)\"\n\t\t\t\t\t\t\t: \"var(--ww-primary)\",\n\t\t\t\t\tcolor:\n\t\t\t\t\t\tdisabled || !value.trim()\n\t\t\t\t\t\t\t? \"var(--ww-muted)\"\n\t\t\t\t\t\t\t: \"var(--ww-primary-fg)\",\n\t\t\t\t\tcursor: disabled || !value.trim() ? \"not-allowed\" : \"pointer\",\n\t\t\t\t\ttransition: \"background-color 0.15s, color 0.15s\",\n\t\t\t\t\tflexShrink: 0,\n\t\t\t\t}}\n\t\t\t\taria-label=\"Send message\"\n\t\t\t>\n\t\t\t\t<SendIcon size={18} />\n\t\t\t</button>\n\t\t</div>\n\t);\n}\n","import type React from \"react\";\n\nconst iconProps: React.SVGProps<SVGSVGElement> = {\n\txmlns: \"http://www.w3.org/2000/svg\",\n\tfill: \"none\",\n\tviewBox: \"0 0 24 24\",\n\tstrokeWidth: 1.5,\n\tstroke: \"currentColor\",\n\t\"aria-hidden\": \"true\",\n\trole: \"img\",\n};\n\nexport function SendIcon(props: { size?: number }) {\n\tconst size = props.size ?? 20;\n\treturn (\n\t\t<svg {...iconProps} width={size} height={size}>\n\t\t\t<title>Send</title>\n\t\t\t<path\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\td=\"M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n\nexport function ToolIcon(props: { size?: number }) {\n\tconst size = props.size ?? 14;\n\treturn (\n\t\t<svg {...iconProps} width={size} height={size}>\n\t\t\t<title>Tool</title>\n\t\t\t<path\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\td=\"M11.42 15.17 17.25 21A2.652 2.652 0 0 0 21 17.25l-5.877-5.877M11.42 15.17l2.496-3.03c.317-.384.74-.626 1.208-.766M11.42 15.17l-4.655 5.653a2.548 2.548 0 1 1-3.586-3.586l6.837-5.63m5.108-.233c.55-.164 1.163-.188 1.743-.14a4.5 4.5 0 0 0 4.486-6.336l-3.276 3.277a3.004 3.004 0 0 1-2.25-2.25l3.276-3.276a4.5 4.5 0 0 0-6.336 4.486c.048.58.024 1.194-.14 1.743\"\n\t\t\t/>\n\t\t</svg>\n\t);\n}\n","import { useEffect, useRef } from \"react\";\nimport { ChatMessage } from \"./chat-message\";\n\ninterface MessagePart {\n\ttype: string;\n\ttext?: string;\n\t[key: string]: unknown;\n}\n\ninterface Message {\n\tid: string;\n\trole: string;\n\tparts: MessagePart[];\n}\n\ninterface ChatMessagesProps {\n\tmessages: Message[];\n\tstatus: string;\n\twelcomeMessage?: string;\n}\n\nexport function ChatMessages(props: ChatMessagesProps) {\n\tconst { messages, status, welcomeMessage } = props;\n\tconst scrollRef = useRef<HTMLDivElement>(null);\n\n\tuseEffect(() => {\n\t\tif (scrollRef.current) {\n\t\t\tscrollRef.current.scrollTop = scrollRef.current.scrollHeight;\n\t\t}\n\t}, []);\n\n\tconst showTyping = status === \"submitted\" || status === \"streaming\";\n\n\treturn (\n\t\t<div\n\t\t\tref={scrollRef}\n\t\t\tclassName=\"ww-scrollbar\"\n\t\t\tstyle={{\n\t\t\t\tflex: 1,\n\t\t\t\toverflowY: \"auto\",\n\t\t\t\tpadding: \"16px\",\n\t\t\t\tdisplay: \"flex\",\n\t\t\t\tflexDirection: \"column\",\n\t\t\t}}\n\t\t>\n\t\t\t{welcomeMessage && messages.length === 0 && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\tjustifyContent: \"flex-start\",\n\t\t\t\t\t\tmarginBottom: \"8px\",\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tmaxWidth: \"85%\",\n\t\t\t\t\t\t\tpadding: \"10px 14px\",\n\t\t\t\t\t\t\tborderRadius:\n\t\t\t\t\t\t\t\t\"var(--ww-msg-radius) var(--ww-msg-radius) var(--ww-msg-radius) 4px\",\n\t\t\t\t\t\t\tbackgroundColor: \"var(--ww-assistant-bubble)\",\n\t\t\t\t\t\t\tcolor: \"var(--ww-text)\",\n\t\t\t\t\t\t\tfontSize: \"14px\",\n\t\t\t\t\t\t\tlineHeight: 1.5,\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{welcomeMessage}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{messages.map((message) => (\n\t\t\t\t<ChatMessage key={message.id} message={message} />\n\t\t\t))}\n\n\t\t\t{showTyping && (\n\t\t\t\t<div\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\tjustifyContent: \"flex-start\",\n\t\t\t\t\t\tmarginBottom: \"8px\",\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tpadding: \"10px 14px\",\n\t\t\t\t\t\t\tborderRadius:\n\t\t\t\t\t\t\t\t\"var(--ww-msg-radius) var(--ww-msg-radius) var(--ww-msg-radius) 4px\",\n\t\t\t\t\t\t\tbackgroundColor: \"var(--ww-assistant-bubble)\",\n\t\t\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\t\t\tgap: \"4px\",\n\t\t\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TypingDot delay=\"0s\" />\n\t\t\t\t\t\t<TypingDot delay=\"0.15s\" />\n\t\t\t\t\t\t<TypingDot delay=\"0.3s\" />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction TypingDot(props: { delay: string }) {\n\treturn (\n\t\t<span\n\t\t\tstyle={{\n\t\t\t\twidth: \"6px\",\n\t\t\t\theight: \"6px\",\n\t\t\t\tborderRadius: \"50%\",\n\t\t\t\tbackgroundColor: \"var(--ww-muted)\",\n\t\t\t\tanimation: `ww-bounce 1.2s ease-in-out infinite`,\n\t\t\t\tanimationDelay: props.delay,\n\t\t\t}}\n\t\t/>\n\t);\n}\n","/**\n * Minimal markdown renderer. Handles bold, italic, inline code, code blocks,\n * links, and unordered lists. No external dependencies.\n */\nexport function ChatMarkdown(props: { text: string }) {\n\tconst blocks = props.text.split(/\\n\\n+/);\n\n\treturn (\n\t\t<>\n\t\t\t{blocks.map((block, i) => (\n\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: static parsed text blocks\n\t\t\t\t<MarkdownBlock key={i} block={block.trim()} />\n\t\t\t))}\n\t\t</>\n\t);\n}\n\nfunction MarkdownBlock(props: { block: string }) {\n\tconst { block } = props;\n\n\t// Code block\n\tif (block.startsWith(\"```\")) {\n\t\tconst lines = block.split(\"\\n\");\n\t\tconst code = lines.slice(1, -1).join(\"\\n\");\n\t\treturn (\n\t\t\t<pre\n\t\t\t\tstyle={{\n\t\t\t\t\tbackgroundColor: \"var(--ww-border)\",\n\t\t\t\t\tborderRadius: \"6px\",\n\t\t\t\t\tpadding: \"8px 12px\",\n\t\t\t\t\toverflowX: \"auto\",\n\t\t\t\t\tfontSize: \"13px\",\n\t\t\t\t\tlineHeight: 1.5,\n\t\t\t\t\tmargin: \"4px 0\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<code>{code}</code>\n\t\t\t</pre>\n\t\t);\n\t}\n\n\t// Unordered list\n\tif (/^[-*]\\s/.test(block)) {\n\t\tconst items = block.split(/\\n/).filter((l) => /^[-*]\\s/.test(l));\n\t\treturn (\n\t\t\t<ul style={{ paddingLeft: \"20px\", margin: \"4px 0\" }}>\n\t\t\t\t{items.map((item, i) => (\n\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: static list items\n\t\t\t\t\t<li key={i}>\n\t\t\t\t\t\t<InlineMarkdown text={item.replace(/^[-*]\\s/, \"\")} />\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t);\n\t}\n\n\t// Paragraph\n\treturn (\n\t\t<p style={{ margin: \"4px 0\", lineHeight: 1.5 }}>\n\t\t\t<InlineMarkdown text={block} />\n\t\t</p>\n\t);\n}\n\nfunction InlineMarkdown(props: { text: string }) {\n\tconst parts = parseInline(props.text);\n\treturn (\n\t\t<>\n\t\t\t{parts.map((part, i) => (\n\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: static inline parsed parts\n\t\t\t\t<InlinePart key={i} part={part} />\n\t\t\t))}\n\t\t</>\n\t);\n}\n\nfunction InlinePart(props: { part: InlinePartData }) {\n\tconst { part } = props;\n\tif (part.type === \"text\") return <span>{part.value}</span>;\n\tif (part.type === \"bold\")\n\t\treturn <strong style={{ fontWeight: 600 }}>{part.value}</strong>;\n\tif (part.type === \"italic\") return <em>{part.value}</em>;\n\tif (part.type === \"code\")\n\t\treturn (\n\t\t\t<code\n\t\t\t\tstyle={{\n\t\t\t\t\tbackgroundColor: \"var(--ww-border)\",\n\t\t\t\t\tborderRadius: \"3px\",\n\t\t\t\t\tpadding: \"1px 4px\",\n\t\t\t\t\tfontSize: \"0.9em\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{part.value}\n\t\t\t</code>\n\t\t);\n\tif (part.type === \"link\")\n\t\treturn (\n\t\t\t<a\n\t\t\t\thref={part.href}\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\tstyle={{\n\t\t\t\t\tcolor: \"var(--ww-primary)\",\n\t\t\t\t\ttextDecoration: \"underline\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{part.value}\n\t\t\t</a>\n\t\t);\n\treturn null;\n}\n\ntype InlinePartData =\n\t| { type: \"text\"; value: string }\n\t| { type: \"bold\"; value: string }\n\t| { type: \"italic\"; value: string }\n\t| { type: \"code\"; value: string }\n\t| { type: \"link\"; value: string; href: string };\n\nfunction parseInline(text: string): InlinePartData[] {\n\tconst parts: InlinePartData[] = [];\n\t// Match: `code`, **bold**, *italic*, [text](url)\n\tconst regex =\n\t\t/`([^`]+)`|\\*\\*([^*]+)\\*\\*|\\*([^*]+)\\*|\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n\tlet lastIndex = 0;\n\tlet match: RegExpExecArray | null;\n\n\tmatch = regex.exec(text);\n\twhile (match !== null) {\n\t\tif (match.index > lastIndex) {\n\t\t\tparts.push({ type: \"text\", value: text.slice(lastIndex, match.index) });\n\t\t}\n\n\t\tif (match[1] != null) {\n\t\t\tparts.push({ type: \"code\", value: match[1] });\n\t\t} else if (match[2] != null) {\n\t\t\tparts.push({ type: \"bold\", value: match[2] });\n\t\t} else if (match[3] != null) {\n\t\t\tparts.push({ type: \"italic\", value: match[3] });\n\t\t} else if (match[4] != null && match[5] != null) {\n\t\t\tparts.push({ type: \"link\", value: match[4], href: match[5] });\n\t\t}\n\n\t\tlastIndex = match.index + match[0].length;\n\t\tmatch = regex.exec(text);\n\t}\n\n\tif (lastIndex < text.length) {\n\t\tparts.push({ type: \"text\", value: text.slice(lastIndex) });\n\t}\n\n\treturn parts;\n}\n","import { ToolIcon } from \"../icons\";\nimport { ChatMarkdown } from \"./chat-markdown\";\n\ninterface MessagePart {\n\ttype: string;\n\ttext?: string;\n\ttoolName?: string;\n\tstate?: string;\n\t[key: string]: unknown;\n}\n\ninterface Message {\n\tid: string;\n\trole: string;\n\tparts: MessagePart[];\n}\n\nexport function ChatMessage(props: { message: Message }) {\n\tconst { message } = props;\n\tconst isUser = message.role === \"user\";\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tdisplay: \"flex\",\n\t\t\t\tjustifyContent: isUser ? \"flex-end\" : \"flex-start\",\n\t\t\t\tmarginBottom: \"8px\",\n\t\t\t\tanimation: \"ww-fade-in 0.2s ease-out\",\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tmaxWidth: \"85%\",\n\t\t\t\t\tpadding: \"10px 14px\",\n\t\t\t\t\tborderRadius: isUser\n\t\t\t\t\t\t? \"var(--ww-msg-radius) var(--ww-msg-radius) 4px var(--ww-msg-radius)\"\n\t\t\t\t\t\t: \"var(--ww-msg-radius) var(--ww-msg-radius) var(--ww-msg-radius) 4px\",\n\t\t\t\t\tbackgroundColor: isUser\n\t\t\t\t\t\t? \"var(--ww-user-bubble)\"\n\t\t\t\t\t\t: \"var(--ww-assistant-bubble)\",\n\t\t\t\t\tcolor: isUser ? \"var(--ww-primary-fg)\" : \"var(--ww-text)\",\n\t\t\t\t\tfontSize: \"14px\",\n\t\t\t\t\tlineHeight: 1.5,\n\t\t\t\t\twordBreak: \"break-word\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{message.parts.map((part, i) => (\n\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: message parts are append-only\n\t\t\t\t\t<MessagePartRenderer key={i} part={part} isUser={isUser} />\n\t\t\t\t))}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction MessagePartRenderer(props: { part: MessagePart; isUser: boolean }) {\n\tconst { part, isUser } = props;\n\n\tif (part.type === \"text\" && part.text) {\n\t\treturn isUser ? (\n\t\t\t<span>{part.text}</span>\n\t\t) : (\n\t\t\t<ChatMarkdown text={part.text} />\n\t\t);\n\t}\n\n\tif (part.type.startsWith(\"tool-\") || part.type === \"tool-invocation\") {\n\t\tconst toolName = part.toolName ?? part.type.replace(\"tool-\", \"\");\n\t\tconst isLoading =\n\t\t\tpart.state === \"input-streaming\" || part.state === \"input-available\";\n\n\t\treturn (\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tdisplay: \"flex\",\n\t\t\t\t\talignItems: \"center\",\n\t\t\t\t\tgap: \"6px\",\n\t\t\t\t\tpadding: \"4px 0\",\n\t\t\t\t\tfontSize: \"12px\",\n\t\t\t\t\tcolor: \"var(--ww-muted)\",\n\t\t\t\t\tfontStyle: \"italic\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<ToolIcon size={12} />\n\t\t\t\t<span>{isLoading ? `Using ${toolName}...` : `Used ${toolName}`}</span>\n\t\t\t\t{isLoading && (\n\t\t\t\t\t<span style={{ animation: \"ww-pulse 1.5s ease-in-out infinite\" }}>\n\t\t\t\t\t\t...\n\t\t\t\t\t</span>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn null;\n}\n","import { ChatHeader } from \"./chat-header\";\nimport { ChatInput } from \"./chat-input\";\nimport { ChatMessages } from \"./chat-messages\";\n\ninterface MessagePart {\n\ttype: string;\n\ttext?: string;\n\t[key: string]: unknown;\n}\n\ninterface Message {\n\tid: string;\n\trole: string;\n\tparts: MessagePart[];\n}\n\ninterface ChatPanelProps {\n\tmessages: Message[];\n\tinput: string;\n\tonInputChange: (value: string) => void;\n\tonSend: () => void;\n\tstatus: string;\n\ttitle: string;\n\tsubtitle?: string;\n\twelcomeMessage?: string;\n\twidth: number;\n\theight: number;\n}\n\nexport function ChatPanel(props: ChatPanelProps) {\n\tconst {\n\t\tmessages,\n\t\tinput,\n\t\tonInputChange,\n\t\tonSend,\n\t\tstatus,\n\t\ttitle,\n\t\tsubtitle,\n\t\twelcomeMessage,\n\t\twidth,\n\t\theight,\n\t} = props;\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"ww-panel\"\n\t\t\tstyle={{\n\t\t\t\twidth: `${width}px`,\n\t\t\t\theight: `${height}px`,\n\t\t\t\tdisplay: \"flex\",\n\t\t\t\tflexDirection: \"column\",\n\t\t\t\tbackgroundColor: \"var(--ww-bg)\",\n\t\t\t\tborderRadius: \"var(--ww-radius)\",\n\t\t\t\tborder: \"1px solid var(--ww-border)\",\n\t\t\t\tboxShadow:\n\t\t\t\t\t\"0 20px 60px -12px rgba(0, 0, 0, 0.15), 0 8px 20px -8px rgba(0, 0, 0, 0.1)\",\n\t\t\t\toverflow: \"hidden\",\n\t\t\t\tfontFamily: \"var(--ww-font)\",\n\t\t\t}}\n\t\t>\n\t\t\t<ChatHeader title={title} subtitle={subtitle} />\n\t\t\t<ChatMessages\n\t\t\t\tmessages={messages}\n\t\t\t\tstatus={status}\n\t\t\t\twelcomeMessage={welcomeMessage}\n\t\t\t/>\n\t\t\t<ChatInput\n\t\t\t\tvalue={input}\n\t\t\t\tonChange={onInputChange}\n\t\t\t\tonSend={onSend}\n\t\t\t\tdisabled={status !== \"ready\"}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n"],"mappings":"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","names":["useChat","DefaultChatTransport","useCallback","useEffect","useRef","useState","useCallback","useRef","useChatTracking","config","configRef","trackEvent","event","properties","apiKey","baseUrl","trackChatOpened","trackMessageSent","trackResponseReceived","buildStyleSheet","DEFAULT_THEME","CSS_VAR_MAP","mergeTheme","userTheme","themeToCSSProperties","theme","vars","key","cssVar","value","jsx","jsxs","ChatHeader","props","title","subtitle","useCallback","useEffect","useRef","jsx","jsxs","iconProps","SendIcon","props","size","ToolIcon","jsx","jsxs","ChatInput","props","value","onChange","onSend","disabled","textareaRef","useRef","handleKeyDown","useCallback","e","useEffect","textarea","SendIcon","useEffect","useRef","Fragment","jsx","ChatMarkdown","props","blocks","block","i","MarkdownBlock","code","items","l","item","InlineMarkdown","parts","parseInline","part","InlinePart","text","regex","lastIndex","match","jsx","jsxs","ChatMessage","props","message","isUser","part","i","MessagePartRenderer","ChatMarkdown","toolName","isLoading","ToolIcon","jsx","jsxs","ChatMessages","props","messages","status","welcomeMessage","scrollRef","useRef","useEffect","showTyping","message","ChatMessage","TypingDot","jsx","jsxs","ChatPanel","props","messages","input","onInputChange","onSend","status","title","subtitle","welcomeMessage","width","height","ChatHeader","ChatMessages","ChatInput","jsx","DEFAULT_API","ChatWidget","props","apiKey","api","welcomeMessage","title","subtitle","userTheme","userHeaders","body","width","height","onMessageSent","onResponseReceived","_shadowRoot","resolvedTheme","mergeTheme","cssVars","themeToCSSProperties","trackChatOpened","trackMessageSent","trackResponseReceived","useChatTracking","transportRef","useRef","DefaultChatTransport","messages","sendMessage","status","useChat","input","setInput","useState","handleSend","useCallback","styleInjected","useEffect","style","buildStyleSheet","tracked","ChatPanel"]}
1
+ {"version":3,"sources":["../../src/chat/components/chat-widget.tsx","../../src/chat/ai-elements/attachments.tsx","../../src/chat/lib/utils.ts","../../src/chat/ai-elements/conversation.tsx","../../src/chat/ui/button.tsx","../../src/chat/ai-elements/loader.tsx","../../src/chat/ai-elements/message.tsx","../../src/chat/ai-elements/prompt-input.tsx","../../src/chat/ai-elements/tool.tsx","../../src/chat/theme.ts"],"sourcesContent":["\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport type { ToolUIPart } from \"ai\";\nimport { DefaultChatTransport } from \"ai\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { ChatWidgetProps } from \"../@types\";\nimport { Attachments } from \"../ai-elements/attachments\";\nimport {\n\tConversation,\n\tConversationContent,\n\tConversationScrollButton,\n} from \"../ai-elements/conversation\";\nimport { Loader } from \"../ai-elements/loader\";\nimport {\n\tMessage,\n\tMessageContent,\n\tMessageResponse,\n} from \"../ai-elements/message\";\nimport type { PromptInputMessage } from \"../ai-elements/prompt-input\";\nimport {\n\tPromptInput,\n\tPromptInputAddAttachments,\n\tPromptInputSubmit,\n\tPromptInputTextarea,\n} from \"../ai-elements/prompt-input\";\nimport {\n\tTool,\n\tToolContent,\n\tToolHeader,\n\tToolInput,\n\tToolOutput,\n} from \"../ai-elements/tool\";\nimport { cn } from \"../lib/utils\";\nimport { mergeTheme, themeToCSSProperties } from \"../theme\";\n\nexport function ChatWidget(props: ChatWidgetProps) {\n\tconst {\n\t\tapi = \"https://app.waniwani.ai/api/chat\",\n\t\twelcomeMessage,\n\t\ttheme: userTheme,\n\t\theaders: userHeaders,\n\t\tbody,\n\t\twidth = 600,\n\t\texpandedHeight = 400,\n\t\tallowAttachments = false,\n\t\tonMessageSent,\n\t\tonResponseReceived,\n\t} = props;\n\n\tconst resolvedTheme = mergeTheme(userTheme);\n\tconst cssVars = themeToCSSProperties(resolvedTheme);\n\n\tconst transportRef = useRef(\n\t\tnew DefaultChatTransport({\n\t\t\tapi,\n\t\t\theaders: {\n\t\t\t\t...userHeaders,\n\t\t\t},\n\t\t\tbody,\n\t\t}),\n\t);\n\n\tconst { messages, sendMessage, status } = useChat({\n\t\ttransport: transportRef.current,\n\t\tonFinish() {\n\t\t\tonResponseReceived?.();\n\t\t},\n\t});\n\n\tconst [text, setText] = useState(\"\");\n\tconst [isFocused, setIsFocused] = useState(false);\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\n\tconst hasMessages = messages.length > 0;\n\tconst isExpanded = isFocused;\n\n\t// Close on outside click\n\tuseEffect(() => {\n\t\tif (!isFocused) return;\n\t\tconst handleClickOutside = (e: MouseEvent) => {\n\t\t\tif (\n\t\t\t\tcontainerRef.current &&\n\t\t\t\t!containerRef.current.contains(e.target as Node)\n\t\t\t) {\n\t\t\t\tsetIsFocused(false);\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener(\"mousedown\", handleClickOutside);\n\t\treturn () => document.removeEventListener(\"mousedown\", handleClickOutside);\n\t}, [isFocused]);\n\n\tconst handleSubmit = useCallback(\n\t\t(message: PromptInputMessage) => {\n\t\t\tconst hasText = Boolean(message.text?.trim());\n\t\t\tconst hasFiles = Boolean(message.files?.length);\n\t\t\tif (!(hasText || hasFiles)) return;\n\n\t\t\tsendMessage({\n\t\t\t\ttext: message.text || \"\",\n\t\t\t\tfiles: message.files,\n\t\t\t});\n\n\t\t\tonMessageSent?.(message.text || \"\");\n\t\t\tsetText(\"\");\n\t\t},\n\t\t[sendMessage, onMessageSent],\n\t);\n\n\tconst handleTextChange = useCallback(\n\t\t(e: React.ChangeEvent<HTMLTextAreaElement>) => {\n\t\t\tsetText(e.target.value);\n\t\t},\n\t\t[],\n\t);\n\n\tconst handleFocus = useCallback(() => {\n\t\tsetIsFocused(true);\n\t}, []);\n\n\tconst isLoading = status === \"submitted\" || status === \"streaming\";\n\tconst lastMessage = messages[messages.length - 1];\n\t// Show a standalone loader bubble only when waiting and no assistant message exists yet\n\tconst showLoaderBubble =\n\t\tisLoading && (!hasMessages || lastMessage.role === \"user\");\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tstyle={{ ...cssVars, width }}\n\t\t\tdata-waniwani-chat=\"\"\n\t\t\tclassName=\"flex flex-col font-[family-name:var(--ww-font)] text-foreground\"\n\t\t>\n\t\t\t{/* Messages panel — fades up on expand */}\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"overflow-hidden bg-background/80 backdrop-blur-xl transition-all duration-300 ease-out\",\n\t\t\t\t\tisExpanded\n\t\t\t\t\t\t? \"opacity-100 translate-y-0\"\n\t\t\t\t\t\t: \"opacity-0 translate-y-2 pointer-events-none max-h-0\",\n\t\t\t\t)}\n\t\t\t\tstyle={{\n\t\t\t\t\t...(isExpanded ? { maxHeight: expandedHeight } : undefined),\n\t\t\t\t\tmaskImage:\n\t\t\t\t\t\t\"linear-gradient(to bottom, transparent, black 24px, black calc(100% - 16px), transparent), linear-gradient(to right, transparent, black 16px, black calc(100% - 16px), transparent)\",\n\t\t\t\t\tmaskComposite: \"intersect\",\n\t\t\t\t\tWebkitMaskImage:\n\t\t\t\t\t\t\"linear-gradient(to bottom, transparent, black 24px, black calc(100% - 16px), transparent), linear-gradient(to right, transparent, black 16px, black calc(100% - 16px), transparent)\",\n\t\t\t\t\tWebkitMaskComposite: \"source-in\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<Conversation className=\"flex-1\" style={{ height: expandedHeight }}>\n\t\t\t\t\t<ConversationContent>\n\t\t\t\t\t\t{welcomeMessage && (\n\t\t\t\t\t\t\t<Message from=\"assistant\">\n\t\t\t\t\t\t\t\t<MessageContent>\n\t\t\t\t\t\t\t\t\t<MessageResponse>{welcomeMessage}</MessageResponse>\n\t\t\t\t\t\t\t\t</MessageContent>\n\t\t\t\t\t\t\t</Message>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{messages.map((message) => {\n\t\t\t\t\t\t\tconst textParts = message.parts.filter((p) => p.type === \"text\");\n\t\t\t\t\t\t\tconst fileParts = message.parts.filter((p) => p.type === \"file\");\n\t\t\t\t\t\t\tconst toolParts = message.parts.filter(\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\tp,\n\t\t\t\t\t\t\t\t): p is typeof p & {\n\t\t\t\t\t\t\t\t\ttoolCallId: string;\n\t\t\t\t\t\t\t\t\tstate: ToolUIPart[\"state\"];\n\t\t\t\t\t\t\t\t\tinput: unknown;\n\t\t\t\t\t\t\t\t\ttitle?: string;\n\t\t\t\t\t\t\t\t} => \"toolCallId\" in p,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tconst isLastAssistant =\n\t\t\t\t\t\t\t\tmessage === lastMessage && message.role === \"assistant\";\n\t\t\t\t\t\t\tconst hasTextContent = textParts.length > 0;\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<Message from={message.role} key={message.id}>\n\t\t\t\t\t\t\t\t\t{toolParts.map((part) => (\n\t\t\t\t\t\t\t\t\t\t<Tool\n\t\t\t\t\t\t\t\t\t\t\tkey={part.toolCallId}\n\t\t\t\t\t\t\t\t\t\t\tdefaultOpen={part.state === \"output-available\"}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<ToolHeader\n\t\t\t\t\t\t\t\t\t\t\t\ttitle={part.title ?? part.type.replace(\"tool-\", \"\")}\n\t\t\t\t\t\t\t\t\t\t\t\tstate={part.state}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t<ToolContent>\n\t\t\t\t\t\t\t\t\t\t\t\t<ToolInput input={part.input} />\n\t\t\t\t\t\t\t\t\t\t\t\t{\"output\" in part && part.output !== undefined && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<ToolOutput\n\t\t\t\t\t\t\t\t\t\t\t\t\t\toutput={part.output}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\terrorText={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"errorText\" in part ? part.errorText : undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</ToolContent>\n\t\t\t\t\t\t\t\t\t\t</Tool>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t<MessageContent>\n\t\t\t\t\t\t\t\t\t\t{fileParts.length > 0 && <Attachments files={fileParts} />}\n\t\t\t\t\t\t\t\t\t\t{hasTextContent\n\t\t\t\t\t\t\t\t\t\t\t? textParts.map((part, i) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageResponse key={`${message.id}-${i}`}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{part.type === \"text\" ? part.text : \"\"}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</MessageResponse>\n\t\t\t\t\t\t\t\t\t\t\t\t))\n\t\t\t\t\t\t\t\t\t\t\t: isLastAssistant && isLoading && <Loader />}\n\t\t\t\t\t\t\t\t\t</MessageContent>\n\t\t\t\t\t\t\t\t</Message>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t\t{showLoaderBubble && (\n\t\t\t\t\t\t\t<Message from=\"assistant\">\n\t\t\t\t\t\t\t\t<MessageContent>\n\t\t\t\t\t\t\t\t\t<Loader />\n\t\t\t\t\t\t\t\t</MessageContent>\n\t\t\t\t\t\t\t</Message>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</ConversationContent>\n\t\t\t\t\t<ConversationScrollButton />\n\t\t\t\t</Conversation>\n\t\t\t</div>\n\n\t\t\t{/* Input bar — always visible */}\n\t\t\t<div className=\"shrink-0\">\n\t\t\t\t<PromptInput\n\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\tglobalDrop={allowAttachments}\n\t\t\t\t\tmultiple={allowAttachments}\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"rounded-[var(--ww-radius)] shadow-sm transition-all duration-300 ease-out\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<div className=\"flex items-center gap-1 px-3 py-2\">\n\t\t\t\t\t\t{allowAttachments && <PromptInputAddAttachments />}\n\t\t\t\t\t\t<PromptInputTextarea\n\t\t\t\t\t\t\tonChange={handleTextChange}\n\t\t\t\t\t\t\tvalue={text}\n\t\t\t\t\t\t\tplaceholder=\"Type a message...\"\n\t\t\t\t\t\t\tonFocus={handleFocus}\n\t\t\t\t\t\t\tclassName=\"min-h-0 py-1.5 px-2\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<PromptInputSubmit status={status} />\n\t\t\t\t\t</div>\n\t\t\t\t</PromptInput>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","\"use client\";\n\nimport type { FileUIPart } from \"ai\";\nimport { FileIcon } from \"lucide-react\";\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"../lib/utils\";\n\n// ============================================================================\n// Attachments (inline list for chat bubbles)\n// ============================================================================\n\nexport type AttachmentsProps = HTMLAttributes<HTMLDivElement> & {\n\tfiles: FileUIPart[];\n};\n\nexport const Attachments = ({\n\tfiles,\n\tclassName,\n\t...props\n}: AttachmentsProps) => {\n\tif (files.length === 0) return null;\n\n\treturn (\n\t\t<div className={cn(\"flex flex-wrap gap-1.5\", className)} {...props}>\n\t\t\t{files.map((file, i) => (\n\t\t\t\t<AttachmentItem key={i} file={file} />\n\t\t\t))}\n\t\t</div>\n\t);\n};\n\n// ============================================================================\n// AttachmentItem\n// ============================================================================\n\nfunction AttachmentItem({ file }: { file: FileUIPart }) {\n\tconst isImage = file.mediaType?.startsWith(\"image/\");\n\n\tif (isImage && file.url) {\n\t\treturn (\n\t\t\t<img\n\t\t\t\tsrc={file.url}\n\t\t\t\talt={file.filename ?? \"attachment\"}\n\t\t\t\tclassName=\"h-16 max-w-32 rounded object-cover\"\n\t\t\t/>\n\t\t);\n\t}\n\n\treturn (\n\t\t<span className=\"inline-flex items-center gap-1.5 rounded bg-background/20 px-2 py-1 text-xs\">\n\t\t\t<FileIcon className=\"size-3 shrink-0\" />\n\t\t\t<span className=\"max-w-24 truncate\">{file.filename ?? \"file\"}</span>\n\t\t</span>\n\t);\n}\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","\"use client\";\n\nimport { ArrowDownIcon } from \"lucide-react\";\nimport type { ComponentProps } from \"react\";\nimport { useCallback } from \"react\";\nimport { StickToBottom, useStickToBottomContext } from \"use-stick-to-bottom\";\nimport { cn } from \"../lib/utils\";\nimport { Button } from \"../ui/button\";\n\nexport type ConversationProps = ComponentProps<typeof StickToBottom>;\n\nexport const Conversation = ({ className, ...props }: ConversationProps) => (\n\t<StickToBottom\n\t\tclassName={cn(\"relative flex-1 overflow-y-hidden\", className)}\n\t\tinitial=\"smooth\"\n\t\tresize=\"smooth\"\n\t\trole=\"log\"\n\t\t{...props}\n\t/>\n);\n\nexport type ConversationContentProps = ComponentProps<\n\ttypeof StickToBottom.Content\n>;\n\nexport const ConversationContent = ({\n\tclassName,\n\t...props\n}: ConversationContentProps) => (\n\t<StickToBottom.Content\n\t\tclassName={cn(\"flex flex-col gap-8 p-4\", className)}\n\t\t{...props}\n\t/>\n);\n\nexport type ConversationScrollButtonProps = ComponentProps<typeof Button>;\n\nexport const ConversationScrollButton = ({\n\tclassName,\n\t...props\n}: ConversationScrollButtonProps) => {\n\tconst { isAtBottom, scrollToBottom } = useStickToBottomContext();\n\n\tconst handleScrollToBottom = useCallback(() => {\n\t\tscrollToBottom();\n\t}, [scrollToBottom]);\n\n\treturn (\n\t\t!isAtBottom && (\n\t\t\t<Button\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"absolute bottom-4 left-[50%] translate-x-[-50%] rounded-full\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tonClick={handleScrollToBottom}\n\t\t\t\tsize=\"icon\"\n\t\t\t\tvariant=\"outline\"\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<ArrowDownIcon className=\"size-4\" />\n\t\t\t</Button>\n\t\t)\n\t);\n};\n","\"use client\";\n\nimport type { ComponentProps } from \"react\";\nimport { cn } from \"../lib/utils\";\n\nexport type ButtonProps = ComponentProps<\"button\"> & {\n\tvariant?: \"default\" | \"outline\" | \"ghost\";\n\tsize?: \"default\" | \"sm\" | \"icon\" | \"icon-sm\";\n};\n\nexport const Button = ({\n\tclassName,\n\tvariant = \"default\",\n\tsize = \"default\",\n\ttype = \"button\",\n\t...props\n}: ButtonProps) => (\n\t<button\n\t\ttype={type}\n\t\tclassName={cn(\n\t\t\t\"inline-flex cursor-pointer items-center justify-center rounded-md font-medium transition-colors disabled:pointer-events-none disabled:opacity-50\",\n\t\t\tvariant === \"default\" &&\n\t\t\t\t\"bg-primary text-primary-foreground hover:bg-primary/90\",\n\t\t\tvariant === \"outline\" &&\n\t\t\t\t\"border border-border bg-background hover:bg-accent hover:text-accent-foreground\",\n\t\t\tvariant === \"ghost\" && \"hover:bg-accent hover:text-accent-foreground\",\n\t\t\tsize === \"default\" && \"h-9 px-4 py-2 text-sm\",\n\t\t\tsize === \"sm\" && \"h-8 px-3 text-xs\",\n\t\t\tsize === \"icon\" && \"size-9\",\n\t\t\tsize === \"icon-sm\" && \"size-7\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\n","\"use client\";\n\nimport type { HTMLAttributes } from \"react\";\nimport { cn } from \"../lib/utils\";\n\nexport type LoaderProps = HTMLAttributes<HTMLDivElement> & {\n\tsize?: number;\n};\n\nexport const Loader = ({ className, size = 5, ...props }: LoaderProps) => (\n\t<div className={cn(\"flex items-center gap-1\", className)} {...props}>\n\t\t{[0, 1, 2].map((i) => (\n\t\t\t<div\n\t\t\t\tkey={i}\n\t\t\t\tclassName=\"rounded-full bg-muted-foreground/60\"\n\t\t\t\tstyle={{\n\t\t\t\t\twidth: size,\n\t\t\t\t\theight: size,\n\t\t\t\t\tanimation: \"ww-pulse 1.4s ease-in-out infinite\",\n\t\t\t\t\tanimationDelay: `${i * 0.2}s`,\n\t\t\t\t}}\n\t\t\t/>\n\t\t))}\n\t</div>\n);\n","\"use client\";\n\nimport { cjk } from \"@streamdown/cjk\";\nimport { code } from \"@streamdown/code\";\nimport type { UIMessage } from \"ai\";\nimport type { ComponentProps, HTMLAttributes } from \"react\";\nimport { memo } from \"react\";\nimport { Streamdown } from \"streamdown\";\nimport { cn } from \"../lib/utils\";\n\nexport type MessageProps = HTMLAttributes<HTMLDivElement> & {\n\tfrom: UIMessage[\"role\"];\n};\n\nexport const Message = ({ className, from, ...props }: MessageProps) => (\n\t<div\n\t\tclassName={cn(\n\t\t\t\"group flex w-full max-w-[95%] flex-col gap-2\",\n\t\t\tfrom === \"user\" ? \"is-user ml-auto justify-end\" : \"is-assistant\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\n\nexport type MessageContentProps = HTMLAttributes<HTMLDivElement>;\n\nexport const MessageContent = ({\n\tchildren,\n\tclassName,\n\t...props\n}: MessageContentProps) => (\n\t<div\n\t\tclassName={cn(\n\t\t\t\"flex w-fit min-w-0 max-w-full flex-col gap-2 overflow-hidden text-sm\",\n\t\t\t\"group-[.is-user]:ml-auto group-[.is-user]:rounded-lg group-[.is-user]:bg-primary group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:text-primary-foreground\",\n\t\t\t\"group-[.is-assistant]:rounded-lg group-[.is-assistant]:bg-accent group-[.is-assistant]:px-4 group-[.is-assistant]:py-3 group-[.is-assistant]:text-foreground\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t{children}\n\t</div>\n);\n\nexport type MessageResponseProps = ComponentProps<typeof Streamdown>;\n\nconst streamdownPlugins = { cjk, code };\n\nexport const MessageResponse = memo(\n\t({ className, ...props }: MessageResponseProps) => (\n\t\t<Streamdown\n\t\t\tclassName={cn(\n\t\t\t\t\"size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tplugins={streamdownPlugins}\n\t\t\t{...props}\n\t\t/>\n\t),\n\t(prevProps, nextProps) => prevProps.children === nextProps.children,\n);\n\nMessageResponse.displayName = \"MessageResponse\";\n","\"use client\";\n\nimport type { ChatStatus, FileUIPart } from \"ai\";\nimport {\n\tArrowUpIcon,\n\tLoaderIcon,\n\tPaperclipIcon,\n\tSquareIcon,\n\tXIcon,\n} from \"lucide-react\";\nimport { nanoid } from \"nanoid\";\nimport type {\n\tChangeEvent,\n\tClipboardEventHandler,\n\tComponentProps,\n\tFormEvent,\n\tFormEventHandler,\n\tHTMLAttributes,\n\tKeyboardEventHandler,\n} from \"react\";\nimport {\n\tcreateContext,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Button } from \"../ui/button\";\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst convertBlobUrlToDataUrl = async (url: string): Promise<string | null> => {\n\ttry {\n\t\tconst response = await fetch(url);\n\t\tconst blob = await response.blob();\n\t\treturn new Promise((resolve) => {\n\t\t\tconst reader = new FileReader();\n\t\t\treader.onloadend = () => resolve(reader.result as string);\n\t\t\treader.onerror = () => resolve(null);\n\t\t\treader.readAsDataURL(blob);\n\t\t});\n\t} catch {\n\t\treturn null;\n\t}\n};\n\n// ============================================================================\n// Attachments Context\n// ============================================================================\n\nexport interface AttachmentsContext {\n\tfiles: (FileUIPart & { id: string })[];\n\tadd: (files: File[] | FileList) => void;\n\tremove: (id: string) => void;\n\tclear: () => void;\n\topenFileDialog: () => void;\n}\n\nconst LocalAttachmentsContext = createContext<AttachmentsContext | null>(null);\n\nexport const usePromptInputAttachments = () => {\n\tconst context = useContext(LocalAttachmentsContext);\n\tif (!context) {\n\t\tthrow new Error(\n\t\t\t\"usePromptInputAttachments must be used within a PromptInput\",\n\t\t);\n\t}\n\treturn context;\n};\n\n// ============================================================================\n// PromptInput Message Type\n// ============================================================================\n\nexport interface PromptInputMessage {\n\ttext: string;\n\tfiles: FileUIPart[];\n}\n\n// ============================================================================\n// PromptInput\n// ============================================================================\n\nexport type PromptInputProps = Omit<\n\tHTMLAttributes<HTMLFormElement>,\n\t\"onSubmit\"\n> & {\n\taccept?: string;\n\tmultiple?: boolean;\n\tglobalDrop?: boolean;\n\tmaxFiles?: number;\n\tmaxFileSize?: number;\n\tonSubmit: (\n\t\tmessage: PromptInputMessage,\n\t\tevent: FormEvent<HTMLFormElement>,\n\t) => void | Promise<void>;\n};\n\nexport const PromptInput = ({\n\tclassName,\n\taccept,\n\tmultiple,\n\tglobalDrop,\n\tmaxFiles,\n\tmaxFileSize,\n\tonSubmit,\n\tchildren,\n\t...props\n}: PromptInputProps) => {\n\tconst inputRef = useRef<HTMLInputElement | null>(null);\n\tconst formRef = useRef<HTMLFormElement | null>(null);\n\tconst [items, setItems] = useState<(FileUIPart & { id: string })[]>([]);\n\tconst filesRef = useRef(items);\n\n\tuseEffect(() => {\n\t\tfilesRef.current = items;\n\t}, [items]);\n\n\tconst openFileDialog = useCallback(() => {\n\t\tinputRef.current?.click();\n\t}, []);\n\n\tconst add = useCallback(\n\t\t(fileList: File[] | FileList) => {\n\t\t\tconst incoming = [...fileList];\n\t\t\tif (incoming.length === 0) return;\n\n\t\t\tconst withinSize = (f: File) =>\n\t\t\t\tmaxFileSize ? f.size <= maxFileSize : true;\n\t\t\tconst valid = incoming.filter(withinSize);\n\n\t\t\tsetItems((prev) => {\n\t\t\t\tconst capacity =\n\t\t\t\t\ttypeof maxFiles === \"number\"\n\t\t\t\t\t\t? Math.max(0, maxFiles - prev.length)\n\t\t\t\t\t\t: undefined;\n\t\t\t\tconst capped =\n\t\t\t\t\ttypeof capacity === \"number\" ? valid.slice(0, capacity) : valid;\n\t\t\t\treturn [\n\t\t\t\t\t...prev,\n\t\t\t\t\t...capped.map((file) => ({\n\t\t\t\t\t\tfilename: file.name,\n\t\t\t\t\t\tid: nanoid(),\n\t\t\t\t\t\tmediaType: file.type,\n\t\t\t\t\t\ttype: \"file\" as const,\n\t\t\t\t\t\turl: URL.createObjectURL(file),\n\t\t\t\t\t})),\n\t\t\t\t];\n\t\t\t});\n\t\t},\n\t\t[maxFiles, maxFileSize],\n\t);\n\n\tconst remove = useCallback((id: string) => {\n\t\tsetItems((prev) => {\n\t\t\tconst found = prev.find((f) => f.id === id);\n\t\t\tif (found?.url) URL.revokeObjectURL(found.url);\n\t\t\treturn prev.filter((f) => f.id !== id);\n\t\t});\n\t}, []);\n\n\tconst clear = useCallback(() => {\n\t\tsetItems((prev) => {\n\t\t\tfor (const f of prev) {\n\t\t\t\tif (f.url) URL.revokeObjectURL(f.url);\n\t\t\t}\n\t\t\treturn [];\n\t\t});\n\t}, []);\n\n\t// Cleanup blob URLs on unmount\n\tuseEffect(\n\t\t() => () => {\n\t\t\tfor (const f of filesRef.current) {\n\t\t\t\tif (f.url) URL.revokeObjectURL(f.url);\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\n\tconst handleChange = useCallback(\n\t\t(event: ChangeEvent<HTMLInputElement>) => {\n\t\t\tif (event.currentTarget.files) {\n\t\t\t\tadd(event.currentTarget.files);\n\t\t\t}\n\t\t\tevent.currentTarget.value = \"\";\n\t\t},\n\t\t[add],\n\t);\n\n\t// Global drop support\n\tuseEffect(() => {\n\t\tif (!globalDrop) return;\n\t\tconst onDragOver = (e: DragEvent) => {\n\t\t\tif (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n\t\t};\n\t\tconst onDrop = (e: DragEvent) => {\n\t\t\tif (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n\t\t\tif (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\n\t\t\t\tadd(e.dataTransfer.files);\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener(\"dragover\", onDragOver);\n\t\tdocument.addEventListener(\"drop\", onDrop);\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"dragover\", onDragOver);\n\t\t\tdocument.removeEventListener(\"drop\", onDrop);\n\t\t};\n\t}, [add, globalDrop]);\n\n\tconst handleSubmit: FormEventHandler<HTMLFormElement> = useCallback(\n\t\tasync (event) => {\n\t\t\tevent.preventDefault();\n\t\t\tconst form = event.currentTarget;\n\t\t\tconst formData = new FormData(form);\n\t\t\tconst text = (formData.get(\"message\") as string) || \"\";\n\n\t\t\tform.reset();\n\n\t\t\tconst convertedFiles: FileUIPart[] = await Promise.all(\n\t\t\t\titems.map(async ({ id: _id, ...item }) => {\n\t\t\t\t\tif (item.url?.startsWith(\"blob:\")) {\n\t\t\t\t\t\tconst dataUrl = await convertBlobUrlToDataUrl(item.url);\n\t\t\t\t\t\treturn { ...item, url: dataUrl ?? item.url };\n\t\t\t\t\t}\n\t\t\t\t\treturn item;\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\tconst result = onSubmit({ files: convertedFiles, text }, event);\n\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\tawait result;\n\t\t\t\t}\n\t\t\t\tclear();\n\t\t\t} catch {\n\t\t\t\t// Don't clear on error\n\t\t\t}\n\t\t},\n\t\t[items, onSubmit, clear],\n\t);\n\n\tconst attachmentsCtx = useMemo<AttachmentsContext>(\n\t\t() => ({\n\t\t\tadd,\n\t\t\tclear,\n\t\t\tfiles: items,\n\t\t\topenFileDialog,\n\t\t\tremove,\n\t\t}),\n\t\t[items, add, remove, clear, openFileDialog],\n\t);\n\n\treturn (\n\t\t<LocalAttachmentsContext.Provider value={attachmentsCtx}>\n\t\t\t<input\n\t\t\t\taccept={accept}\n\t\t\t\taria-label=\"Upload files\"\n\t\t\t\tclassName=\"hidden\"\n\t\t\t\tmultiple={multiple}\n\t\t\t\tonChange={handleChange}\n\t\t\t\tref={inputRef}\n\t\t\t\ttitle=\"Upload files\"\n\t\t\t\ttype=\"file\"\n\t\t\t/>\n\t\t\t<form\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"flex w-full flex-col rounded-lg border border-border bg-background\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\tref={formRef}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</form>\n\t\t</LocalAttachmentsContext.Provider>\n\t);\n};\n\n// ============================================================================\n// Layout Components\n// ============================================================================\n\nexport type PromptInputHeaderProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputHeader = ({\n\tclassName,\n\t...props\n}: PromptInputHeaderProps) => (\n\t<div className={cn(\"flex flex-wrap gap-1 px-3 pt-3\", className)} {...props} />\n);\n\nexport type PromptInputBodyProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputBody = ({\n\tclassName,\n\t...props\n}: PromptInputBodyProps) => (\n\t<div className={cn(\"contents\", className)} {...props} />\n);\n\nexport type PromptInputFooterProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputFooter = ({\n\tclassName,\n\t...props\n}: PromptInputFooterProps) => (\n\t<div\n\t\tclassName={cn(\n\t\t\t\"flex items-center justify-between gap-1 px-3 pb-3\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\n\nexport type PromptInputToolsProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputTools = ({\n\tclassName,\n\t...props\n}: PromptInputToolsProps) => (\n\t<div\n\t\tclassName={cn(\"flex min-w-0 items-center gap-1\", className)}\n\t\t{...props}\n\t/>\n);\n\n// ============================================================================\n// Textarea\n// ============================================================================\n\nexport type PromptInputTextareaProps = ComponentProps<\"textarea\">;\n\nexport const PromptInputTextarea = ({\n\tonChange,\n\tonKeyDown,\n\tclassName,\n\tplaceholder = \"What would you like to know?\",\n\t...props\n}: PromptInputTextareaProps) => {\n\tconst attachments = usePromptInputAttachments();\n\tconst [isComposing, setIsComposing] = useState(false);\n\n\tconst handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = useCallback(\n\t\t(e) => {\n\t\t\tonKeyDown?.(e);\n\t\t\tif (e.defaultPrevented) return;\n\n\t\t\tif (e.key === \"Enter\") {\n\t\t\t\tif (isComposing || e.nativeEvent.isComposing) return;\n\t\t\t\tif (e.shiftKey) return;\n\t\t\t\te.preventDefault();\n\n\t\t\t\tconst { form } = e.currentTarget;\n\t\t\t\tconst submitButton = form?.querySelector(\n\t\t\t\t\t'button[type=\"submit\"]',\n\t\t\t\t) as HTMLButtonElement | null;\n\t\t\t\tif (submitButton?.disabled) return;\n\t\t\t\tform?.requestSubmit();\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\te.key === \"Backspace\" &&\n\t\t\t\te.currentTarget.value === \"\" &&\n\t\t\t\tattachments.files.length > 0\n\t\t\t) {\n\t\t\t\te.preventDefault();\n\t\t\t\tconst lastAttachment = attachments.files.at(-1);\n\t\t\t\tif (lastAttachment) attachments.remove(lastAttachment.id);\n\t\t\t}\n\t\t},\n\t\t[onKeyDown, isComposing, attachments],\n\t);\n\n\tconst handlePaste: ClipboardEventHandler<HTMLTextAreaElement> = useCallback(\n\t\t(event) => {\n\t\t\tconst items = event.clipboardData?.items;\n\t\t\tif (!items) return;\n\n\t\t\tconst files: File[] = [];\n\t\t\tfor (const item of items) {\n\t\t\t\tif (item.kind === \"file\") {\n\t\t\t\t\tconst file = item.getAsFile();\n\t\t\t\t\tif (file) files.push(file);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (files.length > 0) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tattachments.add(files);\n\t\t\t}\n\t\t},\n\t\t[attachments],\n\t);\n\n\treturn (\n\t\t<textarea\n\t\t\tclassName={cn(\n\t\t\t\t\"field-sizing-content max-h-48 min-h-16 w-full resize-none border-0 bg-transparent px-3 py-3 text-sm outline-none placeholder:text-muted-foreground\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tname=\"message\"\n\t\t\tonCompositionEnd={() => setIsComposing(false)}\n\t\t\tonCompositionStart={() => setIsComposing(true)}\n\t\t\tonKeyDown={handleKeyDown}\n\t\t\tonPaste={handlePaste}\n\t\t\tplaceholder={placeholder}\n\t\t\tonChange={onChange}\n\t\t\t{...props}\n\t\t/>\n\t);\n};\n\n// ============================================================================\n// Submit Button\n// ============================================================================\n\nexport type PromptInputSubmitProps = ComponentProps<typeof Button> & {\n\tstatus?: ChatStatus;\n\tonStop?: () => void;\n};\n\nexport const PromptInputSubmit = ({\n\tclassName,\n\tstatus,\n\tonStop,\n\tonClick,\n\tchildren,\n\t...props\n}: PromptInputSubmitProps) => {\n\tconst isGenerating = status === \"submitted\" || status === \"streaming\";\n\n\tlet Icon = <ArrowUpIcon className=\"size-4\" />;\n\tif (status === \"submitted\") {\n\t\tIcon = <LoaderIcon className=\"size-4 animate-spin\" />;\n\t} else if (status === \"streaming\") {\n\t\tIcon = <SquareIcon className=\"size-4\" />;\n\t}\n\n\tconst handleClick = useCallback(\n\t\t(e: React.MouseEvent<HTMLButtonElement>) => {\n\t\t\tif (isGenerating && onStop) {\n\t\t\t\te.preventDefault();\n\t\t\t\tonStop();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tonClick?.(e);\n\t\t},\n\t\t[isGenerating, onStop, onClick],\n\t);\n\n\treturn (\n\t\t<Button\n\t\t\taria-label={isGenerating ? \"Stop\" : \"Submit\"}\n\t\t\tclassName={cn(className)}\n\t\t\tonClick={handleClick}\n\t\t\tsize=\"icon-sm\"\n\t\t\ttype={isGenerating && onStop ? \"button\" : \"submit\"}\n\t\t\tvariant=\"default\"\n\t\t\t{...props}\n\t\t>\n\t\t\t{children ?? Icon}\n\t\t</Button>\n\t);\n};\n\n// ============================================================================\n// Attachment Add Button (simple file picker, no Radix dropdown)\n// ============================================================================\n\nexport type PromptInputAddAttachmentsProps = ComponentProps<typeof Button>;\n\nexport const PromptInputAddAttachments = ({\n\tclassName,\n\tchildren,\n\t...props\n}: PromptInputAddAttachmentsProps) => {\n\tconst attachments = usePromptInputAttachments();\n\tconst hasFiles = attachments.files.length > 0;\n\n\tif (hasFiles) {\n\t\treturn (\n\t\t\t<Button\n\t\t\t\tclassName={cn(\"group relative\", className)}\n\t\t\t\tonClick={() => attachments.clear()}\n\t\t\t\tsize=\"icon-sm\"\n\t\t\t\ttype=\"button\"\n\t\t\t\tvariant=\"ghost\"\n\t\t\t\taria-label=\"Remove all attachments\"\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<span className=\"flex size-5 items-center justify-center rounded-full bg-primary text-[10px] font-medium text-primary-foreground transition-opacity group-hover:opacity-0\">\n\t\t\t\t\t{attachments.files.length}\n\t\t\t\t</span>\n\t\t\t\t<XIcon className=\"absolute size-4 opacity-0 transition-opacity group-hover:opacity-100\" />\n\t\t\t</Button>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Button\n\t\t\tclassName={cn(className)}\n\t\t\tonClick={() => attachments.openFileDialog()}\n\t\t\tsize=\"icon-sm\"\n\t\t\ttype=\"button\"\n\t\t\tvariant=\"ghost\"\n\t\t\t{...props}\n\t\t>\n\t\t\t{children ?? <PaperclipIcon className=\"size-4\" />}\n\t\t</Button>\n\t);\n};\n","\"use client\";\n\nimport type { ToolUIPart } from \"ai\";\nimport {\n\tCheckCircleIcon,\n\tChevronDownIcon,\n\tCircleIcon,\n\tClockIcon,\n\tWrenchIcon,\n\tXCircleIcon,\n} from \"lucide-react\";\nimport type { ComponentProps, HTMLAttributes, ReactNode } from \"react\";\nimport { createContext, isValidElement, useContext, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\n\n// ============================================================================\n// Collapsible Context (lightweight, no Radix dependency)\n// ============================================================================\n\nconst ToolOpenContext = createContext<{\n\topen: boolean;\n\ttoggle: () => void;\n}>({ open: false, toggle: () => {} });\n\n// ============================================================================\n// Tool\n// ============================================================================\n\nexport type ToolProps = HTMLAttributes<HTMLDivElement> & {\n\tdefaultOpen?: boolean;\n};\n\nexport const Tool = ({\n\tclassName,\n\tdefaultOpen = false,\n\tchildren,\n\t...props\n}: ToolProps) => {\n\tconst [open, setOpen] = useState(defaultOpen);\n\treturn (\n\t\t<ToolOpenContext.Provider\n\t\t\tvalue={{ open, toggle: () => setOpen((o) => !o) }}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={cn(\"mb-4 w-full rounded-md border border-border\", className)}\n\t\t\t\tdata-state={open ? \"open\" : \"closed\"}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</ToolOpenContext.Provider>\n\t);\n};\n\n// ============================================================================\n// Status helpers\n// ============================================================================\n\nconst statusLabels: Record<ToolUIPart[\"state\"], string> = {\n\t\"approval-requested\": \"Awaiting Approval\",\n\t\"approval-responded\": \"Responded\",\n\t\"input-available\": \"Running\",\n\t\"input-streaming\": \"Pending\",\n\t\"output-available\": \"Completed\",\n\t\"output-denied\": \"Denied\",\n\t\"output-error\": \"Error\",\n};\n\nconst statusIcons: Record<ToolUIPart[\"state\"], ReactNode> = {\n\t\"approval-requested\": <ClockIcon className=\"size-4 text-yellow-600\" />,\n\t\"approval-responded\": <CheckCircleIcon className=\"size-4 text-blue-600\" />,\n\t\"input-available\": <ClockIcon className=\"size-4 animate-pulse\" />,\n\t\"input-streaming\": <CircleIcon className=\"size-4\" />,\n\t\"output-available\": <CheckCircleIcon className=\"size-4 text-green-600\" />,\n\t\"output-denied\": <XCircleIcon className=\"size-4 text-orange-600\" />,\n\t\"output-error\": <XCircleIcon className=\"size-4 text-red-600\" />,\n};\n\nexport const getStatusBadge = (state: ToolUIPart[\"state\"]) => (\n\t<span className=\"inline-flex items-center gap-1.5 rounded-full border border-border bg-muted px-2 py-0.5 text-xs text-muted-foreground\">\n\t\t{statusIcons[state]}\n\t\t{statusLabels[state]}\n\t</span>\n);\n\n// ============================================================================\n// ToolHeader\n// ============================================================================\n\nexport type ToolHeaderProps = ComponentProps<\"button\"> & {\n\ttitle?: string;\n\tstate: ToolUIPart[\"state\"];\n};\n\nexport const ToolHeader = ({\n\tclassName,\n\ttitle,\n\tstate,\n\t...props\n}: ToolHeaderProps) => {\n\tconst { open, toggle } = useContext(ToolOpenContext);\n\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tonClick={toggle}\n\t\t\tclassName={cn(\n\t\t\t\t\"flex w-full items-center justify-between gap-4 p-3\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\taria-expanded={open}\n\t\t\t{...props}\n\t\t>\n\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t<WrenchIcon className=\"size-4 text-muted-foreground\" />\n\t\t\t\t<span className=\"text-sm font-medium\">{title}</span>\n\t\t\t\t{getStatusBadge(state)}\n\t\t\t</div>\n\t\t\t<ChevronDownIcon\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"size-4 text-muted-foreground transition-transform\",\n\t\t\t\t\topen && \"rotate-180\",\n\t\t\t\t)}\n\t\t\t/>\n\t\t</button>\n\t);\n};\n\n// ============================================================================\n// ToolContent\n// ============================================================================\n\nexport type ToolContentProps = HTMLAttributes<HTMLDivElement>;\n\nexport const ToolContent = ({\n\tclassName,\n\tchildren,\n\t...props\n}: ToolContentProps) => {\n\tconst { open } = useContext(ToolOpenContext);\n\n\tif (!open) return null;\n\n\treturn (\n\t\t<div className={cn(\"space-y-4 p-4\", className)} {...props}>\n\t\t\t{children}\n\t\t</div>\n\t);\n};\n\n// ============================================================================\n// ToolInput\n// ============================================================================\n\nexport type ToolInputProps = HTMLAttributes<HTMLDivElement> & {\n\tinput: ToolUIPart[\"input\"];\n};\n\nexport const ToolInput = ({ className, input, ...props }: ToolInputProps) => (\n\t<div className={cn(\"space-y-2 overflow-hidden\", className)} {...props}>\n\t\t<h4 className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n\t\t\tParameters\n\t\t</h4>\n\t\t<pre className=\"overflow-x-auto rounded-md bg-muted/50 p-3 text-xs\">\n\t\t\t<code>{JSON.stringify(input, null, 2)}</code>\n\t\t</pre>\n\t</div>\n);\n\n// ============================================================================\n// ToolOutput\n// ============================================================================\n\nexport type ToolOutputProps = HTMLAttributes<HTMLDivElement> & {\n\toutput: ToolUIPart[\"output\"];\n\terrorText: ToolUIPart[\"errorText\"];\n};\n\nexport const ToolOutput = ({\n\tclassName,\n\toutput,\n\terrorText,\n\t...props\n}: ToolOutputProps) => {\n\tif (!(output || errorText)) return null;\n\n\tlet rendered: ReactNode;\n\n\tif (typeof output === \"object\" && !isValidElement(output)) {\n\t\trendered = (\n\t\t\t<pre className=\"overflow-x-auto p-3 text-xs\">\n\t\t\t\t<code>{JSON.stringify(output, null, 2)}</code>\n\t\t\t</pre>\n\t\t);\n\t} else if (typeof output === \"string\") {\n\t\trendered = (\n\t\t\t<pre className=\"overflow-x-auto p-3 text-xs\">\n\t\t\t\t<code>{output}</code>\n\t\t\t</pre>\n\t\t);\n\t} else {\n\t\trendered = <div className=\"p-3\">{output as ReactNode}</div>;\n\t}\n\n\treturn (\n\t\t<div className={cn(\"space-y-2\", className)} {...props}>\n\t\t\t<h4 className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n\t\t\t\t{errorText ? \"Error\" : \"Result\"}\n\t\t\t</h4>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"overflow-x-auto rounded-md text-xs\",\n\t\t\t\t\terrorText\n\t\t\t\t\t\t? \"bg-destructive/10 text-destructive\"\n\t\t\t\t\t\t: \"bg-muted/50 text-foreground\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{errorText && <div className=\"p-3\">{errorText}</div>}\n\t\t\t\t{rendered}\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n","import type { ChatTheme } from \"./@types\";\n\nexport const DEFAULT_THEME: Required<ChatTheme> = {\n\tprimaryColor: \"#6366f1\",\n\tprimaryForeground: \"#ffffff\",\n\tbackgroundColor: \"#ffffff\",\n\ttextColor: \"#1f2937\",\n\tmutedColor: \"#6b7280\",\n\tborderColor: \"#e5e7eb\",\n\tassistantBubbleColor: \"#f3f4f6\",\n\tuserBubbleColor: \"#6366f1\",\n\tinputBackgroundColor: \"#f9fafb\",\n\tborderRadius: 16,\n\tmessageBorderRadius: 12,\n\tfontFamily: \"system-ui, -apple-system, 'Segoe UI', sans-serif\",\n};\n\nconst CSS_VAR_MAP: Record<keyof ChatTheme, string[]> = {\n\tprimaryColor: [\"--ww-primary\", \"--color-primary\"],\n\tprimaryForeground: [\"--ww-primary-fg\", \"--color-primary-foreground\"],\n\tbackgroundColor: [\"--ww-bg\", \"--color-background\"],\n\ttextColor: [\"--ww-text\", \"--color-foreground\", \"--color-accent-foreground\"],\n\tmutedColor: [\"--ww-muted\", \"--color-muted-foreground\"],\n\tborderColor: [\"--ww-border\", \"--color-border\"],\n\tassistantBubbleColor: [\"--ww-assistant-bubble\", \"--color-accent\"],\n\tuserBubbleColor: [\"--ww-user-bubble\"],\n\tinputBackgroundColor: [\"--ww-input-bg\", \"--color-input\"],\n\tborderRadius: [\"--ww-radius\", \"--radius\"],\n\tmessageBorderRadius: [\"--ww-msg-radius\"],\n\tfontFamily: [\"--ww-font\"],\n};\n\nexport function mergeTheme(userTheme?: ChatTheme): Required<ChatTheme> {\n\treturn { ...DEFAULT_THEME, ...userTheme };\n}\n\nexport function themeToCSSProperties(\n\ttheme: Required<ChatTheme>,\n): Record<string, string> {\n\tconst vars: Record<string, string> = {};\n\tfor (const [key, cssVars] of Object.entries(CSS_VAR_MAP)) {\n\t\tconst value = theme[key as keyof ChatTheme];\n\t\tconst resolved = typeof value === \"number\" ? `${value}px` : String(value);\n\t\tfor (const cssVar of cssVars) {\n\t\t\tvars[cssVar] = resolved;\n\t\t}\n\t}\n\treturn vars;\n}\n"],"mappings":"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","names":["useChat","DefaultChatTransport","useCallback","useEffect","useRef","useState","FileIcon","clsx","twMerge","cn","inputs","jsx","jsxs","Attachments","files","className","props","cn","file","i","AttachmentItem","FileIcon","ArrowDownIcon","useCallback","StickToBottom","useStickToBottomContext","jsx","Button","className","variant","size","type","props","cn","jsx","Conversation","className","props","StickToBottom","cn","ConversationContent","ConversationScrollButton","isAtBottom","scrollToBottom","useStickToBottomContext","handleScrollToBottom","useCallback","Button","ArrowDownIcon","jsx","Loader","className","size","props","cn","i","cjk","code","memo","Streamdown","jsx","Message","className","from","props","cn","MessageContent","children","streamdownPlugins","cjk","code","MessageResponse","memo","Streamdown","prevProps","nextProps","ArrowUpIcon","LoaderIcon","PaperclipIcon","SquareIcon","XIcon","nanoid","createContext","useCallback","useContext","useEffect","useMemo","useRef","useState","jsx","jsxs","convertBlobUrlToDataUrl","url","blob","resolve","reader","LocalAttachmentsContext","createContext","usePromptInputAttachments","context","useContext","PromptInput","className","accept","multiple","globalDrop","maxFiles","maxFileSize","onSubmit","children","props","inputRef","useRef","formRef","items","setItems","useState","filesRef","useEffect","openFileDialog","useCallback","add","fileList","incoming","withinSize","f","valid","prev","capacity","capped","file","nanoid","remove","id","found","clear","handleChange","event","onDragOver","e","onDrop","handleSubmit","form","text","convertedFiles","_id","item","dataUrl","result","attachmentsCtx","useMemo","cn","PromptInputTextarea","onChange","onKeyDown","className","placeholder","props","attachments","usePromptInputAttachments","isComposing","setIsComposing","useState","handleKeyDown","useCallback","e","form","lastAttachment","handlePaste","event","items","files","item","file","jsx","cn","PromptInputSubmit","status","onStop","onClick","children","isGenerating","Icon","ArrowUpIcon","LoaderIcon","SquareIcon","handleClick","Button","PromptInputAddAttachments","jsxs","XIcon","PaperclipIcon","CheckCircleIcon","ChevronDownIcon","CircleIcon","ClockIcon","WrenchIcon","XCircleIcon","createContext","isValidElement","useContext","useState","jsx","jsxs","ToolOpenContext","createContext","Tool","className","defaultOpen","children","props","open","setOpen","useState","o","cn","statusLabels","statusIcons","ClockIcon","CheckCircleIcon","CircleIcon","XCircleIcon","getStatusBadge","state","ToolHeader","title","toggle","useContext","WrenchIcon","ChevronDownIcon","ToolContent","ToolInput","input","ToolOutput","output","errorText","rendered","isValidElement","DEFAULT_THEME","CSS_VAR_MAP","mergeTheme","userTheme","themeToCSSProperties","theme","vars","key","cssVars","value","resolved","cssVar","jsx","jsxs","ChatWidget","props","api","welcomeMessage","userTheme","userHeaders","body","width","expandedHeight","allowAttachments","onMessageSent","onResponseReceived","resolvedTheme","mergeTheme","cssVars","themeToCSSProperties","transportRef","useRef","DefaultChatTransport","messages","sendMessage","status","useChat","text","setText","useState","isFocused","setIsFocused","containerRef","hasMessages","isExpanded","useEffect","handleClickOutside","e","handleSubmit","useCallback","message","hasText","hasFiles","handleTextChange","handleFocus","isLoading","lastMessage","showLoaderBubble","cn","Conversation","ConversationContent","Message","MessageContent","MessageResponse","textParts","fileParts","toolParts","isLastAssistant","hasTextContent","part","Tool","ToolHeader","ToolContent","ToolInput","ToolOutput","Attachments","i","Loader","ConversationScrollButton","PromptInput","PromptInputAddAttachments","PromptInputTextarea","PromptInputSubmit"]}
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:""}}}@layer theme{:root,:host{--font-sans:var(--ww-font,system-ui,-apple-system,"Segoe UI",sans-serif);--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-400:oklch(70.4% .191 22.216);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-orange-600:oklch(64.6% .222 41.116);--color-yellow-600:oklch(68.1% .162 75.834);--color-green-600:oklch(62.7% .194 149.214);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-teal-400:oklch(77.7% .152 181.912);--color-cyan-400:oklch(78.9% .154 211.53);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-600:oklch(54.6% .245 262.881);--color-indigo-400:oklch(67.3% .182 276.935);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-400:oklch(70.4% .04 256.788);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height:calc(1.5/1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25/1.875);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wide:.025em;--tracking-wider:.05em;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0,0,.2,1)infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--animate-bounce:bounce 1s infinite;--blur-sm:8px;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--radius:var(--ww-radius,16px);--color-background:var(--ww-bg,#fff);--color-foreground:var(--ww-text,#1f2937);--color-primary:var(--ww-primary,#6366f1);--color-primary-foreground:var(--ww-primary-fg,#fff);--color-muted:var(--ww-muted-bg,#f1f5f9);--color-muted-foreground:var(--ww-muted,#6b7280);--color-border:var(--ww-border,#e5e7eb);--color-input:var(--ww-input-bg,#f9fafb);--color-accent:var(--ww-assistant-bubble,#f3f4f6);--color-accent-foreground:var(--ww-text,#1f2937)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing)*0)}.top-0\.5{top:calc(var(--spacing)*.5)}.top-4{top:calc(var(--spacing)*4)}.top-full{top:100%}.right-0{right:calc(var(--spacing)*0)}.right-2{right:calc(var(--spacing)*2)}.right-4{right:calc(var(--spacing)*4)}.bottom-0{bottom:calc(var(--spacing)*0)}.bottom-0\.5{bottom:calc(var(--spacing)*.5)}.bottom-1{bottom:calc(var(--spacing)*1)}.bottom-2{bottom:calc(var(--spacing)*2)}.bottom-4{bottom:calc(var(--spacing)*4)}.bottom-14{bottom:calc(var(--spacing)*14)}.left-0{left:calc(var(--spacing)*0)}.left-2{left:calc(var(--spacing)*2)}.left-4{left:calc(var(--spacing)*4)}.left-\[50\%\]{left:50%}.z-10{z-index:10}.z-50{z-index:50}.z-\[9998\]{z-index:9998}.z-\[9999\]{z-index:9999}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mx-4{margin-inline:calc(var(--spacing)*4)}.my-4{margin-block:calc(var(--spacing)*4)}.my-6{margin-block:calc(var(--spacing)*6)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-6{margin-top:calc(var(--spacing)*6)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.list-item{display:list-item}.table{display:table}.table-cell{display:table-cell}.table-row{display:table-row}.field-sizing-content{field-sizing:content}.size-3{width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.size-4{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.size-5{width:calc(var(--spacing)*5);height:calc(var(--spacing)*5)}.size-7{width:calc(var(--spacing)*7);height:calc(var(--spacing)*7)}.size-9{width:calc(var(--spacing)*9);height:calc(var(--spacing)*9)}.size-full{width:100%;height:100%}.h-3{height:calc(var(--spacing)*3)}.h-3\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-11{height:calc(var(--spacing)*11)}.h-16{height:calc(var(--spacing)*16)}.h-\[46px\]{height:46px}.h-auto{height:auto}.h-full{height:100%}.max-h-0{max-height:calc(var(--spacing)*0)}.max-h-32{max-height:calc(var(--spacing)*32)}.max-h-48{max-height:calc(var(--spacing)*48)}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-16{min-height:calc(var(--spacing)*16)}.min-h-28{min-height:calc(var(--spacing)*28)}.min-h-\[120px\]{min-height:120px}.min-h-\[160px\]{min-height:160px}.min-h-\[200px\]{min-height:200px}.min-h-screen{min-height:100vh}.w-3{width:calc(var(--spacing)*3)}.w-3\.5{width:calc(var(--spacing)*3.5)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-8{width:calc(var(--spacing)*8)}.w-11{width:calc(var(--spacing)*11)}.w-16{width:calc(var(--spacing)*16)}.w-80{width:calc(var(--spacing)*80)}.w-fit{width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-24{max-width:calc(var(--spacing)*24)}.max-w-32{max-width:calc(var(--spacing)*32)}.max-w-\[95\%\]{max-width:95%}.max-w-full{max-width:100%}.max-w-md{max-width:var(--container-md)}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-\[120px\]{min-width:120px}.flex-1{flex:1}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.origin-center{transform-origin:50%}.translate-x-\[-50\%\]{--tw-translate-x:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-0{--tw-translate-y:calc(var(--spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-2{--tw-translate-y:calc(var(--spacing)*2);translate:var(--tw-translate-x)var(--tw-translate-y)}.scale-110{--tw-scale-x:110%;--tw-scale-y:110%;--tw-scale-z:110%;scale:var(--tw-scale-x)var(--tw-scale-y)}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-\[shimmer_1\.5s_ease-in-out_infinite\]{animation:1.5s ease-in-out infinite shimmer}.animate-bounce{animation:var(--animate-bounce)}.animate-ping{animation:var(--animate-ping)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-none{resize:none}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.appearance-none{appearance:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-8{gap:calc(var(--spacing)*8)}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*2)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-x-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px*var(--tw-divide-y-reverse));border-bottom-width:calc(1px*calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-border>:not(:last-child)){border-color:var(--color-border)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-hidden{overflow-y:hidden}.rounded{border-radius:var(--radius)}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-\[var\(--ww-radius\)\]{border-radius:var(--ww-radius)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-\[\#414141\]{border-color:#414141}.border-\[\#424242\]{border-color:#424242}.border-blue-400\/20{border-color:#54a2ff33}@supports (color:color-mix(in lab, red, red)){.border-blue-400\/20{border-color:color-mix(in oklab,var(--color-blue-400)20%,transparent)}}.border-border{border-color:var(--color-border)}.border-current{border-color:currentColor}.border-muted-foreground\/30{border-color:var(--color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.border-muted-foreground\/30{border-color:color-mix(in oklab,var(--color-muted-foreground)30%,transparent)}}.border-red-200{border-color:var(--color-red-200)}.bg-\[\#2f2f2f\]{background-color:#2f2f2f}.bg-\[\#212121\]{background-color:#212121}.bg-\[\#424242\]{background-color:#424242}.bg-background,.bg-background\/20{background-color:var(--color-background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/20{background-color:color-mix(in oklab,var(--color-background)20%,transparent)}}.bg-background\/50{background-color:var(--color-background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/50{background-color:color-mix(in oklab,var(--color-background)50%,transparent)}}.bg-background\/80{background-color:var(--color-background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/80{background-color:color-mix(in oklab,var(--color-background)80%,transparent)}}.bg-background\/90{background-color:var(--color-background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/90{background-color:color-mix(in oklab,var(--color-background)90%,transparent)}}.bg-background\/95{background-color:var(--color-background)}@supports (color:color-mix(in lab, red, red)){.bg-background\/95{background-color:color-mix(in oklab,var(--color-background)95%,transparent)}}.bg-black\/10{background-color:#0000001a}@supports (color:color-mix(in lab, red, red)){.bg-black\/10{background-color:color-mix(in oklab,var(--color-black)10%,transparent)}}.bg-emerald-500\/20{background-color:#00bb7f33}@supports (color:color-mix(in lab, red, red)){.bg-emerald-500\/20{background-color:color-mix(in oklab,var(--color-emerald-500)20%,transparent)}}.bg-gray-500\/20{background-color:#6a728233}@supports (color:color-mix(in lab, red, red)){.bg-gray-500\/20{background-color:color-mix(in oklab,var(--color-gray-500)20%,transparent)}}.bg-muted{background-color:var(--color-muted)}.bg-muted-foreground\/60{background-color:var(--color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\/60{background-color:color-mix(in oklab,var(--color-muted-foreground)60%,transparent)}}.bg-muted\/40{background-color:var(--color-muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/40{background-color:color-mix(in oklab,var(--color-muted)40%,transparent)}}.bg-muted\/50{background-color:var(--color-muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/50{background-color:color-mix(in oklab,var(--color-muted)50%,transparent)}}.bg-muted\/80{background-color:var(--color-muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\/80{background-color:color-mix(in oklab,var(--color-muted)80%,transparent)}}.bg-primary{background-color:var(--color-primary)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-transparent{background-color:#0000}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-blue-400{--tw-gradient-from:var(--color-blue-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.from-cyan-400{--tw-gradient-from:var(--color-cyan-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.from-slate-400{--tw-gradient-from:var(--color-slate-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.from-teal-400{--tw-gradient-from:var(--color-teal-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.via-slate-200{--tw-gradient-via:var(--color-slate-200);--tw-gradient-via-stops:var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-via)var(--tw-gradient-via-position),var(--tw-gradient-to)var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.to-cyan-400{--tw-gradient-to:var(--color-cyan-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-emerald-400{--tw-gradient-to:var(--color-emerald-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-slate-400{--tw-gradient-to:var(--color-slate-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-teal-400{--tw-gradient-to:var(--color-teal-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.bg-\[length\:200\%_100\%\]{background-size:200% 100%}.bg-clip-text{-webkit-background-clip:text;background-clip:text}.object-cover{object-fit:cover}.p-0\.5{padding:calc(var(--spacing)*.5)}.p-1{padding:calc(var(--spacing)*1)}.p-1\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-12{padding-block:calc(var(--spacing)*12)}.pt-3{padding-top:calc(var(--spacing)*3)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pl-4{padding-left:calc(var(--spacing)*4)}.text-center{text-align:center}.text-left{text-align:left}.font-\[\'Inter\'\,_system-ui\,_sans-serif\]{font-family:Inter,system-ui,sans-serif}.font-\[family-name\:var\(--ww-font\)\]{font-family:var(--ww-font)}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.wrap-anywhere{overflow-wrap:anywhere}.break-all{word-break:break-all}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.text-blue-600{color:var(--color-blue-600)}.text-emerald-400{color:var(--color-emerald-400)}.text-foreground{color:var(--color-foreground)}.text-gray-200{color:var(--color-gray-200)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-green-600{color:var(--color-green-600)}.text-indigo-400{color:var(--color-indigo-400)}.text-muted-foreground{color:var(--color-muted-foreground)}.text-orange-600{color:var(--color-orange-600)}.text-primary{color:var(--color-primary)}.text-primary-foreground{color:var(--color-primary-foreground)}.text-red-400{color:var(--color-red-400)}.text-red-600{color:var(--color-red-600)}.text-red-700{color:var(--color-red-700)}.text-red-800{color:var(--color-red-800)}.text-transparent{color:#0000}.text-white{color:var(--color-white)}.text-yellow-600{color:var(--color-yellow-600)}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.underline{text-decoration-line:underline}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.backdrop-blur-xl{--tw-backdrop-blur:blur(var(--blur-xl));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.\[animation-delay\:-0\.3s\]{animation-delay:-.3s}.\[animation-delay\:-0\.15s\]{animation-delay:-.15s}.\[counter-increment\:line_0\]{counter-increment:line 0}.\[counter-reset\:line\]{counter-reset:line}@media (hover:hover){.group-hover\:block:is(:where(.group):hover *){display:block}.group-hover\:text-white:is(:where(.group):hover *){color:var(--color-white)}.group-hover\:opacity-0:is(:where(.group):hover *){opacity:0}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.group-\[\.is-assistant\]\:rounded-lg:is(:where(.group).is-assistant *){border-radius:var(--radius-lg)}.group-\[\.is-assistant\]\:bg-accent:is(:where(.group).is-assistant *){background-color:var(--color-accent)}.group-\[\.is-assistant\]\:px-4:is(:where(.group).is-assistant *){padding-inline:calc(var(--spacing)*4)}.group-\[\.is-assistant\]\:py-3:is(:where(.group).is-assistant *){padding-block:calc(var(--spacing)*3)}.group-\[\.is-assistant\]\:text-foreground:is(:where(.group).is-assistant *){color:var(--color-foreground)}.group-\[\.is-user\]\:ml-auto:is(:where(.group).is-user *){margin-left:auto}.group-\[\.is-user\]\:rounded-lg:is(:where(.group).is-user *){border-radius:var(--radius-lg)}.group-\[\.is-user\]\:bg-primary:is(:where(.group).is-user *){background-color:var(--color-primary)}.group-\[\.is-user\]\:px-4:is(:where(.group).is-user *){padding-inline:calc(var(--spacing)*4)}.group-\[\.is-user\]\:py-3:is(:where(.group).is-user *){padding-block:calc(var(--spacing)*3)}.group-\[\.is-user\]\:text-primary-foreground:is(:where(.group).is-user *){color:var(--color-primary-foreground)}.placeholder\:text-muted-foreground::placeholder{color:var(--color-muted-foreground)}.before\:mr-4:before{content:var(--tw-content);margin-right:calc(var(--spacing)*4)}.before\:inline-block:before{content:var(--tw-content);display:inline-block}.before\:w-6:before{content:var(--tw-content);width:calc(var(--spacing)*6)}.before\:text-right:before{content:var(--tw-content);text-align:right}.before\:font-mono:before{content:var(--tw-content);font-family:var(--font-mono)}.before\:text-\[13px\]:before{content:var(--tw-content);font-size:13px}.before\:text-muted-foreground\/50:before{content:var(--tw-content);color:var(--color-muted-foreground)}@supports (color:color-mix(in lab, red, red)){.before\:text-muted-foreground\/50:before{color:color-mix(in oklab,var(--color-muted-foreground)50%,transparent)}}.before\:content-\[counter\(line\)\]:before{--tw-content:counter(line);content:var(--tw-content)}.before\:select-none:before{content:var(--tw-content);-webkit-user-select:none;user-select:none}.before\:\[counter-increment\:line\]:before{content:var(--tw-content);counter-increment:line}:is(.\*\:first\:mt-0>*):first-child{margin-top:calc(var(--spacing)*0)}:is(.\*\:last\:mb-0>*):last-child{margin-bottom:calc(var(--spacing)*0)}:is(.\*\:last\:after\:inline>*):last-child:after{content:var(--tw-content);display:inline}:is(.\*\:last\:after\:align-baseline>*):last-child:after{content:var(--tw-content);vertical-align:baseline}:is(.\*\:last\:after\:content-\(--streamdown-caret\)>*):last-child:after{--tw-content:var(--streamdown-caret);content:var(--tw-content)}@media (hover:hover){.hover\:scale-105:hover{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}.hover\:bg-accent:hover{background-color:var(--color-accent)}.hover\:bg-background:hover{background-color:var(--color-background)}.hover\:bg-muted:hover,.hover\:bg-muted\/40:hover{background-color:var(--color-muted)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/40:hover{background-color:color-mix(in oklab,var(--color-muted)40%,transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--color-primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab,var(--color-primary)90%,transparent)}}.hover\:bg-white\/5:hover{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/5:hover{background-color:color-mix(in oklab,var(--color-white)5%,transparent)}}.hover\:text-accent-foreground:hover{color:var(--color-accent-foreground)}.hover\:text-foreground:hover{color:var(--color-foreground)}.hover\:text-gray-200:hover{color:var(--color-gray-200)}.hover\:text-gray-300:hover{color:var(--color-gray-300)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.active\:scale-95:active{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x)var(--tw-scale-y)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width:40rem){.sm\:rounded-3xl{border-radius:var(--radius-3xl)}}@media (prefers-color-scheme:dark){.dark\:bg-\(--shiki-dark-bg\)\!{background-color:var(--shiki-dark-bg)!important}.dark\:text-\(--shiki-dark\)\!{color:var(--shiki-dark)!important}}.\[\&_svg\]\:h-auto svg{height:auto}.\[\&_svg\]\:w-auto svg{width:auto}.\[\&\>\*\:first-child\]\:mt-0>:first-child{margin-top:calc(var(--spacing)*0)}.\[\&\>\*\:last-child\]\:mb-0>:last-child{margin-bottom:calc(var(--spacing)*0)}.\[\&\>p\]\:inline>p{display:inline}li .\[li_\&\]\:pl-6{padding-left:calc(var(--spacing)*6)}}@keyframes ww-pulse{0%,80%,to{opacity:.3;transform:scale(.8)}40%{opacity:1;transform:scale(1)}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes pulse{50%{opacity:.5}}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}}