@waniwani/sdk 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat/embed.js +150 -0
- package/dist/chat/embed.js.map +1 -0
- package/dist/chat/index.d.ts +68 -0
- package/dist/chat/index.js +44 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/mcp/react.js +6 -6
- package/dist/mcp/react.js.map +1 -1
- package/package.json +18 -2
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface ChatTheme {
|
|
4
|
+
/** Primary brand color (bubble, send button, user messages) */
|
|
5
|
+
primaryColor?: string;
|
|
6
|
+
/** Primary text color on primary background */
|
|
7
|
+
primaryForeground?: string;
|
|
8
|
+
/** Chat panel background */
|
|
9
|
+
backgroundColor?: string;
|
|
10
|
+
/** Default text color */
|
|
11
|
+
textColor?: string;
|
|
12
|
+
/** Secondary/muted text */
|
|
13
|
+
mutedColor?: string;
|
|
14
|
+
/** Border color */
|
|
15
|
+
borderColor?: string;
|
|
16
|
+
/** Assistant message bubble background */
|
|
17
|
+
assistantBubbleColor?: string;
|
|
18
|
+
/** User message bubble background */
|
|
19
|
+
userBubbleColor?: string;
|
|
20
|
+
/** Input field background */
|
|
21
|
+
inputBackgroundColor?: string;
|
|
22
|
+
/** Border radius for the panel (px) */
|
|
23
|
+
borderRadius?: number;
|
|
24
|
+
/** Border radius for message bubbles (px) */
|
|
25
|
+
messageBorderRadius?: number;
|
|
26
|
+
/** Font family */
|
|
27
|
+
fontFamily?: string;
|
|
28
|
+
}
|
|
29
|
+
interface ChatWidgetProps {
|
|
30
|
+
/** WaniWani project API key */
|
|
31
|
+
apiKey?: string;
|
|
32
|
+
/** Chat API endpoint URL. Defaults to WaniWani hosted endpoint */
|
|
33
|
+
api?: string;
|
|
34
|
+
/** Initial greeting shown before user types */
|
|
35
|
+
welcomeMessage?: string;
|
|
36
|
+
/** Header title */
|
|
37
|
+
title?: string;
|
|
38
|
+
/** Header subtitle */
|
|
39
|
+
subtitle?: string;
|
|
40
|
+
/** Theme overrides */
|
|
41
|
+
theme?: ChatTheme;
|
|
42
|
+
/** Additional headers to send with chat API requests */
|
|
43
|
+
headers?: Record<string, string>;
|
|
44
|
+
/** Additional body fields to send with each chat request */
|
|
45
|
+
body?: Record<string, unknown>;
|
|
46
|
+
/** Chat panel width in pixels */
|
|
47
|
+
width?: number;
|
|
48
|
+
/** Chat panel height in pixels */
|
|
49
|
+
height?: number;
|
|
50
|
+
/** Callback fired when a message is sent */
|
|
51
|
+
onMessageSent?: (message: string) => void;
|
|
52
|
+
/** Callback fired when a response is received */
|
|
53
|
+
onResponseReceived?: () => void;
|
|
54
|
+
}
|
|
55
|
+
interface ChatEmbedConfig extends Omit<ChatWidgetProps, "onMessageSent" | "onResponseReceived"> {
|
|
56
|
+
/** DOM element to mount into (defaults to document.body) */
|
|
57
|
+
container?: HTMLElement;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
declare function ChatWidget(props: ChatWidgetProps & {
|
|
61
|
+
_shadowRoot?: ShadowRoot;
|
|
62
|
+
}): react_jsx_runtime.JSX.Element;
|
|
63
|
+
|
|
64
|
+
declare const DEFAULT_THEME: Required<ChatTheme>;
|
|
65
|
+
declare function mergeTheme(userTheme?: ChatTheme): Required<ChatTheme>;
|
|
66
|
+
declare function themeToCSSProperties(theme: Required<ChatTheme>): Record<string, string>;
|
|
67
|
+
|
|
68
|
+
export { type ChatEmbedConfig, type ChatTheme, ChatWidget, type ChatWidgetProps, DEFAULT_THEME, mergeTheme, themeToCSSProperties };
|
|
@@ -0,0 +1,44 @@
|
|
|
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};
|
|
44
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"]}
|
package/dist/mcp/react.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import{a as $}from"../chunk-SCDEAZN4.js";import{b as T}from"../chunk-OVQDB7QX.js";import{Fragment as
|
|
2
|
+
import{a as $}from"../chunk-SCDEAZN4.js";import{b as T}from"../chunk-OVQDB7QX.js";import{Fragment as Se,jsx as E,jsxs as Te}from"react/jsx-runtime";function Ce({baseUrl:e}){return Te(Se,{children:[E("base",{href:e}),E("script",{children:`window.innerBaseUrl = ${JSON.stringify(e)}`}),E("script",{children:'window.__isChatGptApp = typeof window.openai !== "undefined";'}),E("script",{children:"("+(()=>{let t=window.innerBaseUrl,i=document.documentElement;new MutationObserver(m=>{m.forEach(n=>{if(n.type==="attributes"&&n.target===i){let s=n.attributeName;s&&s!=="suppresshydrationwarning"&&s!=="class"&&s!=="style"&&i.removeAttribute(s)}})}).observe(i,{attributes:!0,attributeOldValue:!0});let u=history.replaceState;history.replaceState=(m,n,s)=>{let r=new URL(s??"",window.location.href),h=r.pathname+r.search+r.hash;u.call(history,n,h)};let p=history.pushState;history.pushState=(m,n,s)=>{let r=new URL(s??"",window.location.href),h=r.pathname+r.search+r.hash;p.call(history,n,h)};let g=new URL(t).origin,f=window.self!==window.top;if(window.addEventListener("click",m=>{let n=m?.target?.closest("a");if(!n||!n.href)return;let s=new URL(n.href,window.location.href);if(s.origin!==window.location.origin&&s.origin!==g)try{window.openai&&(window.openai?.openExternal({href:n.href}),m.preventDefault())}catch{console.warn("openExternal failed, likely not in OpenAI client")}},!0),f&&window.location.origin!==g){let m=window.fetch;window.fetch=(n,s)=>{let r;if(typeof n=="string"||n instanceof URL?r=new URL(n,window.location.href):r=new URL(n.url,window.location.href),r.origin===g)return typeof n=="string"||n instanceof URL?n=r.toString():n=new Request(r.toString(),n),m.call(window,n,{...s,mode:"cors"});if(r.origin===window.location.origin){let h=new URL(t);return h.pathname=r.pathname,h.search=r.search,h.hash=r.hash,r=h,typeof n=="string"||n instanceof URL?n=r.toString():n=new Request(r.toString(),n),m.call(window,n,{...s,mode:"cors"})}return m.call(window,n,s)}}}).toString()+")()"})]})}import{useCallback as w,useEffect as M,useRef as K,useState as b}from"react";var J={theme:"dark",userAgent:{device:{type:"desktop"},capabilities:{hover:!0,touch:!1}},locale:"en",maxHeight:800,displayMode:"inline",safeArea:{insets:{top:0,bottom:0,left:0,right:0}},toolInput:{},toolOutput:null,toolResponseMetadata:null,widgetState:null},N={...J};function R(e){typeof window>"u"||window.openai||(N={...J,toolOutput:e??null},window.openai={...N,requestDisplayMode:async({mode:t})=>(v("displayMode",t),{mode:t}),callTool:async(t,i)=>(console.log(`[DevMode] callTool: ${t}`,i),{result:JSON.stringify({mock:!0,tool:t,args:i})}),sendFollowUpMessage:async({prompt:t})=>{console.log(`[DevMode] sendFollowUpMessage: ${t}`)},openExternal:({href:t})=>{console.log(`[DevMode] openExternal: ${t}`),window.open(t,"_blank")},setWidgetState:async t=>{v("widgetState",t)}},window.dispatchEvent(new T({globals:N})))}function v(e,t){typeof window>"u"||!window.openai||(N[e]=t,window.openai[e]=t,window.dispatchEvent(new T({globals:{[e]:t}})))}function L(){return{...N}}function W(e){v("toolOutput",e)}function O(e){v("displayMode",e)}function A(e){v("theme",e)}import{Fragment as B,jsx as o,jsxs as l}from"react/jsx-runtime";var U=150;function q({className:e}){return l("svg",{className:e,viewBox:"0 0 24 24",fill:"none",role:"img","aria-label":"Dev Controls",children:[o("rect",{x:"4",y:"4",width:"10",height:"10",rx:"2",stroke:"currentColor",strokeWidth:"1.5"}),o("rect",{x:"10",y:"10",width:"10",height:"10",rx:"2",stroke:"currentColor",strokeWidth:"1.5",fill:"currentColor",fillOpacity:"0.15"})]})}function Ne({className:e}){return o("svg",{"aria-hidden":"true",className:e,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:o("path",{d:"M18 6L6 18M6 6l12 12"})})}function Re({className:e}){return o("svg",{"aria-hidden":"true",className:e,viewBox:"0 0 16 16",fill:"none",children:o("rect",{x:"2",y:"4",width:"12",height:"8",rx:"1.5",stroke:"currentColor",strokeWidth:"1.25"})})}function We({className:e}){return l("svg",{"aria-hidden":"true",className:e,viewBox:"0 0 16 16",fill:"none",children:[o("rect",{x:"1.5",y:"3",width:"13",height:"10",rx:"1.5",stroke:"currentColor",strokeWidth:"1.25"}),o("rect",{x:"8.5",y:"7",width:"5",height:"4",rx:"0.75",fill:"currentColor"})]})}function Oe({className:e}){return o("svg",{"aria-hidden":"true",className:e,viewBox:"0 0 16 16",fill:"none",children:o("path",{d:"M2 5.5V3.5C2 2.95 2.45 2.5 3 2.5H5.5M10.5 2.5H13C13.55 2.5 14 2.95 14 3.5V5.5M14 10.5V12.5C14 13.05 13.55 13.5 13 13.5H10.5M5.5 13.5H3C2.45 13.5 2 13.05 2 12.5V10.5",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round",strokeLinejoin:"round"})})}function Ae({className:e}){return l("svg",{"aria-hidden":"true",className:e,viewBox:"0 0 16 16",fill:"none",children:[o("circle",{cx:"8",cy:"8",r:"2.5",stroke:"currentColor",strokeWidth:"1.25"}),o("path",{d:"M8 2v1.5M8 12.5V14M2 8h1.5M12.5 8H14M4.11 4.11l1.06 1.06M10.83 10.83l1.06 1.06M4.11 11.89l1.06-1.06M10.83 5.17l1.06-1.06",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round"})]})}function De({className:e}){return o("svg",{"aria-hidden":"true",className:e,viewBox:"0 0 16 16",fill:"none",children:o("path",{d:"M13.5 9.5a5.5 5.5 0 01-7-7 5.5 5.5 0 107 7z",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round",strokeLinejoin:"round"})})}function Ie({className:e}){return l("svg",{"aria-hidden":"true",className:e,viewBox:"0 0 16 16",fill:"none",children:[o("path",{d:"M2.5 8a5.5 5.5 0 019.37-3.9M13.5 8a5.5 5.5 0 01-9.37 3.9",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round"}),o("path",{d:"M12.5 2v3h-3M3.5 14v-3h3",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round",strokeLinejoin:"round"})]})}var Ee=`
|
|
3
3
|
@keyframes devPanelSlideIn {
|
|
4
4
|
0% {
|
|
5
5
|
opacity: 0;
|
|
@@ -47,22 +47,22 @@ import{a as $}from"../chunk-SCDEAZN4.js";import{b as T}from"../chunk-OVQDB7QX.js
|
|
|
47
47
|
.dev-json-editor::-webkit-scrollbar-thumb:hover {
|
|
48
48
|
background: rgba(255, 255, 255, 0.15);
|
|
49
49
|
}
|
|
50
|
-
`;function Y({defaultProps:e,widgetPaths:t,children:i}){let[
|
|
50
|
+
`;function Y({defaultProps:e,widgetPaths:t,children:i}){let[c,u]=b(!1),[p,g]=b(!1);return M(()=>{if(new URLSearchParams(window.location.search).get("platform")==="mcp-apps"){u(!0);return}if(t&&t.length>0){let m=window.location.pathname,n=t.some(s=>m===s||m.startsWith(`${s}/`));g(n),n&&R(e)}else R(e),g(!0);u(!0)},[e,t]),c?p?l(B,{children:[o(Le,{children:i}),o(Ue,{defaultProps:e})]}):o(B,{children:i}):null}function Le({children:e}){return o("div",{className:"min-h-screen bg-[#212121] flex items-center justify-center p-8",children:o("div",{className:"relative w-full max-w-md overflow-hidden rounded-2xl sm:rounded-3xl border border-[#414141]",style:{boxShadow:"0px 0px 0px 1px #414141, 0px 4px 14px rgba(0,0,0,0.24)"},children:e})})}function V({options:e,value:t,onChange:i}){let c=e.findIndex(u=>u.value===t);return l("div",{className:"relative flex p-0.5 rounded-lg",style:{background:"rgba(255, 255, 255, 0.04)",border:"1px solid rgba(255, 255, 255, 0.06)"},children:[o("div",{className:"absolute top-0.5 bottom-0.5 rounded-md transition-transform duration-150 ease-out",style:{width:`calc(${100/e.length}% - 2px)`,left:"2px",transform:`translateX(calc(${c*100}% + ${c*2}px))`,background:"rgba(255, 255, 255, 0.1)"}}),e.map(u=>l("button",{type:"button",onClick:()=>i(u.value),className:`
|
|
51
51
|
relative z-10 flex-1 flex items-center justify-center gap-1.5 px-2 py-1.5
|
|
52
52
|
text-xs font-medium rounded-md transition-colors duration-150
|
|
53
53
|
${t===u.value?"text-white":"text-gray-400 hover:text-gray-300"}
|
|
54
|
-
`,children:[u.icon,o("span",{className:"capitalize",children:u.label})]},u.value))]})}function Ue({defaultProps:e}){let[t,i]=b(()=>typeof window>"u"?!1:localStorage.getItem("dev-controls-open")==="true"),[
|
|
54
|
+
`,children:[u.icon,o("span",{className:"capitalize",children:u.label})]},u.value))]})}function Ue({defaultProps:e}){let[t,i]=b(()=>typeof window>"u"?!1:localStorage.getItem("dev-controls-open")==="true"),[c,u]=b(!1),[p,g]=b(t),[f,m]=b("inline"),[n,s]=b("dark"),[r,h]=b(!1),[P,z]=b(()=>JSON.stringify(e??{},null,2)),[C,H]=b(null),S=K(null),he=K(null),j=K(null);M(()=>{let a=L();m(a.displayMode),s(a.theme)},[]),M(()=>{typeof window>"u"||(window.openai||(window.openai={}),window.openai.safeArea={insets:{top:0,bottom:r?U:0,left:0,right:0}},window.dispatchEvent(new T({globals:{safeArea:window.openai.safeArea}})))},[r]),M(()=>{localStorage.setItem("dev-controls-open",String(t))},[t]);let G=w(()=>{g(!0),requestAnimationFrame(()=>{i(!0)})},[]),y=w(()=>{u(!0),i(!1),setTimeout(()=>{g(!1),u(!1)},150)},[]),F=w(()=>{t?y():G()},[t,G,y]);M(()=>{let a=x=>{(x.metaKey||x.ctrlKey)&&x.shiftKey&&x.key==="d"&&(x.preventDefault(),F()),x.key==="Escape"&&t&&y()};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[t,F,y]),M(()=>{if(!t)return;let a=x=>{j.current&&!j.current.contains(x.target)&&y()};return document.addEventListener("mousedown",a),()=>document.removeEventListener("mousedown",a)},[t,y]);let xe=w(a=>{m(a),O(a)},[]),be=w(a=>{s(a),A(a)},[]),I=w(a=>{try{let x=JSON.parse(a);H(null),W(x)}catch{H("Invalid JSON")}},[]),we=w(a=>{z(a),S.current&&clearTimeout(S.current),S.current=setTimeout(()=>{I(a)},500)},[I]),ye=w(()=>{S.current&&clearTimeout(S.current),I(P)},[I,P]),ve=w(()=>{let a=JSON.stringify(e??{},null,2);z(a),H(null),W(e??{}),m("inline"),O("inline"),s("dark"),A("dark")},[e]),ke=[{value:"inline",label:"inline",icon:o(Re,{className:"w-3.5 h-3.5"})},{value:"pip",label:"pip",icon:o(We,{className:"w-3.5 h-3.5"})},{value:"fullscreen",label:"full",icon:o(Oe,{className:"w-3.5 h-3.5"})}],Me=[{value:"light",label:"light",icon:o(Ae,{className:"w-3.5 h-3.5"})},{value:"dark",label:"dark",icon:o(De,{className:"w-3.5 h-3.5"})}];return l(B,{children:[o("style",{dangerouslySetInnerHTML:{__html:Ee}}),l("div",{ref:j,className:"fixed bottom-4 right-4 z-[9999] font-['Inter',_system-ui,_sans-serif]",children:[l("button",{type:"button",onClick:F,className:"group relative flex items-center justify-center w-11 h-11 rounded-xl transition-all duration-200 ease-out hover:scale-105 active:scale-95",style:{background:"rgba(14, 14, 16, 0.95)",backdropFilter:"blur(16px)",WebkitBackdropFilter:"blur(16px)",border:"1px solid rgba(255, 255, 255, 0.08)",boxShadow:`
|
|
55
55
|
0 4px 12px rgba(0, 0, 0, 0.4),
|
|
56
56
|
0 0 0 1px rgba(255, 255, 255, 0.05),
|
|
57
57
|
inset 0 1px 0 rgba(255, 255, 255, 0.04)
|
|
58
|
-
`},"aria-label":"Toggle Dev Controls","aria-expanded":t,children:[o(q,{className:`w-5 h-5 transition-all duration-200 ${t?"text-indigo-400 scale-110":"text-gray-300 group-hover:text-white"}`}),o("div",{className:"absolute inset-0 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none",style:{background:"radial-gradient(circle at center, rgba(99, 102, 241, 0.15) 0%, transparent 70%)"}})]}),
|
|
58
|
+
`},"aria-label":"Toggle Dev Controls","aria-expanded":t,children:[o(q,{className:`w-5 h-5 transition-all duration-200 ${t?"text-indigo-400 scale-110":"text-gray-300 group-hover:text-white"}`}),o("div",{className:"absolute inset-0 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none",style:{background:"radial-gradient(circle at center, rgba(99, 102, 241, 0.15) 0%, transparent 70%)"}})]}),p&&l("div",{ref:he,className:`absolute bottom-14 right-0 w-80 ${t&&!c?"dev-panel-enter":"dev-panel-exit"}`,style:{maxHeight:"calc(100vh - 120px)",background:"rgba(14, 14, 16, 0.92)",backdropFilter:"blur(24px)",WebkitBackdropFilter:"blur(24px)",border:"1px solid rgba(255, 255, 255, 0.06)",borderRadius:"16px",boxShadow:`
|
|
59
59
|
0 25px 50px -12px rgba(0, 0, 0, 0.6),
|
|
60
60
|
0 0 0 1px rgba(255, 255, 255, 0.05),
|
|
61
61
|
inset 0 1px 0 rgba(255, 255, 255, 0.04)
|
|
62
|
-
`},children:[
|
|
62
|
+
`},children:[l("div",{className:"flex items-center justify-between px-4 py-3",style:{borderBottom:"1px solid rgba(255, 255, 255, 0.06)"},children:[l("div",{className:"flex items-center gap-2",children:[o(q,{className:"w-4 h-4 text-gray-400"}),o("span",{className:"text-sm font-medium text-white",children:"Dev Controls"})]}),l("div",{className:"flex items-center gap-2",children:[o("span",{className:"text-[10px] font-medium text-gray-500 px-1.5 py-0.5 rounded",style:{background:"rgba(255, 255, 255, 0.04)",border:"1px solid rgba(255, 255, 255, 0.06)"},children:typeof navigator<"u"&&navigator.platform?.includes("Mac")?"\u2318\u21E7D":"Ctrl+Shift+D"}),o("button",{type:"button",onClick:y,className:"p-1 rounded-md text-gray-500 hover:text-gray-300 hover:bg-white/5 transition-colors",children:o(Ne,{className:"w-4 h-4"})})]})]}),l("div",{className:"p-4 space-y-5 overflow-y-auto",style:{maxHeight:"calc(100vh - 200px)"},children:[l("div",{children:[o("label",{htmlFor:"display-mode",className:"text-[11px] font-medium uppercase tracking-wider text-gray-500 block mb-2",children:"Display Mode"}),o(V,{options:ke,value:f,onChange:xe})]}),l("div",{children:[o("label",{htmlFor:"theme",className:"text-[11px] font-medium uppercase tracking-wider text-gray-500 block mb-2",children:"Theme"}),o(V,{options:Me,value:n,onChange:be})]}),l("div",{children:[o("label",{htmlFor:"safe-area",className:"text-[11px] font-medium uppercase tracking-wider text-gray-500 block mb-2",children:"Safe Area (Chat Input)"}),l("button",{type:"button",onClick:()=>h(!r),className:`w-full flex items-center justify-between px-3 py-2.5 rounded-lg text-xs font-medium transition-all duration-150 ${r?"text-emerald-400":"text-gray-400"}`,style:{background:r?"rgba(34, 197, 94, 0.1)":"rgba(255, 255, 255, 0.04)",border:r?"1px solid rgba(34, 197, 94, 0.3)":"1px solid rgba(255, 255, 255, 0.06)"},children:[o("span",{children:"Mock ChatGPT Input Bar"}),o("span",{className:`px-2 py-0.5 rounded text-[10px] font-semibold ${r?"bg-emerald-500/20 text-emerald-400":"bg-gray-500/20 text-gray-500"}`,children:r?"ON":"OFF"})]}),r&&l("p",{className:"text-[10px] text-gray-500 mt-1.5",children:["bottom: ",U,"px"]})]}),l("div",{children:[o("label",{htmlFor:"widget-props",className:"text-[11px] font-medium uppercase tracking-wider text-gray-500 block mb-2",children:"Widget Props"}),o("textarea",{value:P,onChange:a=>we(a.target.value),onBlur:ye,className:"dev-json-editor w-full min-h-[160px] text-xs text-gray-200 p-3 rounded-lg resize-none focus:outline-none transition-colors",style:{background:"rgba(0, 0, 0, 0.3)",border:C?"1px solid rgba(239, 68, 68, 0.5)":"1px solid rgba(255, 255, 255, 0.06)",fontFamily:"'JetBrains Mono', 'SF Mono', 'Fira Code', monospace",lineHeight:1.6},onFocus:a=>{C||(a.target.style.borderColor="rgba(99, 102, 241, 0.5)")},onBlurCapture:a=>{C||(a.target.style.borderColor="rgba(255, 255, 255, 0.06)")},spellCheck:!1}),C&&l("p",{className:"text-red-400 text-[11px] mt-1.5 flex items-center gap-1",children:[o("svg",{"aria-hidden":"true","aria-label":"Error",className:"w-3 h-3",viewBox:"0 0 16 16",fill:"currentColor",children:o("path",{d:"M8 1.5a6.5 6.5 0 100 13 6.5 6.5 0 000-13zM7 4.5h2v4H7v-4zm0 5h2v2H7v-2z"})}),C]})]}),l("button",{type:"button",onClick:ve,className:"w-full flex items-center justify-center gap-2 px-3 py-2 rounded-lg text-xs font-medium text-gray-400 transition-all duration-150 hover:text-gray-200",style:{background:"rgba(255, 255, 255, 0.04)",border:"1px solid rgba(255, 255, 255, 0.06)"},onMouseEnter:a=>{a.currentTarget.style.background="rgba(255, 255, 255, 0.08)",a.currentTarget.style.borderColor="rgba(255, 255, 255, 0.1)"},onMouseLeave:a=>{a.currentTarget.style.background="rgba(255, 255, 255, 0.04)",a.currentTarget.style.borderColor="rgba(255, 255, 255, 0.06)"},children:[o(Ie,{className:"w-3.5 h-3.5"}),"Reset to Defaults"]})]})]})]}),r&&l("div",{className:"fixed bottom-0 left-0 right-0 z-[9998] flex items-center justify-center pointer-events-none",style:{height:`${U}px`,background:"linear-gradient(to top, #1a1a1a 0%, #1a1a1a 80%, transparent 100%)"},children:[l("div",{className:"w-full max-w-2xl mx-4 px-4 py-3 rounded-2xl bg-[#2f2f2f] border border-[#424242] flex items-center gap-3",children:[o("div",{className:"w-8 h-8 rounded-full bg-[#424242] flex items-center justify-center",children:o("svg",{"aria-hidden":"true",className:"w-4 h-4 text-gray-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:o("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 4v16m8-8H4"})})}),o("div",{className:"flex-1 text-gray-400 text-sm",children:"Ask anything..."}),o("div",{className:"w-8 h-8 rounded-full bg-[#424242] flex items-center justify-center",children:o("svg",{"aria-hidden":"true",className:"w-4 h-4 text-gray-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:o("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z"})})})]}),l("div",{className:"absolute bottom-1 text-[10px] text-gray-600 font-mono",children:["Mock SafeArea: bottom=",U,"px"]})]})]})}import{useCallback as Fe}from"react";import D,{createContext as Pe,useCallback as Q,useContext as He,useEffect as Z,useState as _,useSyncExternalStore as je}from"react";async function X(){let{detectPlatform:e}=await import("../platform-4QZXTYT5.js");if(e()==="openai"){let{OpenAIWidgetClient:i}=await import("../openai-client-UL6T463M.js");return new i}else{let{MCPAppsWidgetClient:i}=await import("../mcp-apps-client-DZ3L5O3U.js");return new i}}var ee=Pe(null);function te({children:e,loading:t=null,onError:i}){let[c,u]=_(null),[p,g]=_(null),[f,m]=_(!0);return Z(()=>{let n=!0;async function s(){try{let r=await X();await r.connect(),n&&(u(r),m(!1))}catch(r){n&&(console.log("error",r),g(r instanceof Error?r:new Error(String(r))),m(!1))}}return s(),()=>{n=!1}},[]),Z(()=>{if(!c)return;let n=s=>{document.documentElement.classList.toggle("dark",s==="dark")};return n(c.getTheme()),c.onThemeChange(n)},[c]),p&&i?D.createElement(D.Fragment,null,i(p)):f||!c?D.createElement(D.Fragment,null,t):D.createElement(ee.Provider,{value:c},e)}function d(e){let t=He(ee);if(!t)throw new Error("useWidgetClient must be used within a WidgetProvider");let i=Q(p=>e==="toolOutput"?t.onToolResult(()=>p()):e==="theme"?t.onThemeChange(()=>p()):e==="displayMode"?t.onDisplayModeChange(()=>p()):e==="safeArea"?t.onSafeAreaChange(()=>p()):e==="maxHeight"?t.onMaxHeightChange(()=>p()):e==="toolResponseMetadata"?t.onToolResponseMetadataChange(()=>p()):e==="widgetState"?t.onWidgetStateChange(()=>p()):()=>{},[t,e]),c=Q(()=>e==="toolOutput"?t.getToolOutput():e==="theme"?t.getTheme():e==="displayMode"?t.getDisplayMode():e==="locale"?t.getLocale():e==="safeArea"?t.getSafeArea():e==="maxHeight"?t.getMaxHeight():e==="toolResponseMetadata"?t.getToolResponseMetadata():e==="widgetState"?t.getWidgetState():null,[t,e]),u=je(i,c,c);return e?u:t}function oe(){let e=d();return Fe((t,i)=>e.callTool(t,i),[e])}function ne(){return d("displayMode")}import{useSyncExternalStore as Ke}from"react";function re(){return Ke(()=>()=>{},()=>typeof window>"u"?!1:window.__isChatGptApp===!0,()=>!1)}function ae(){return d("locale")}function ie(){return d("maxHeight")}import{useCallback as Be}from"react";function se(){let e=d();return Be(t=>e.openExternal(t),[e])}import{useCallback as _e}from"react";function le(){let e=d();return _e(t=>e.requestDisplayMode(t),[e])}function de(){return d("safeArea")}import{useCallback as ze}from"react";function ue(){let e=d();return ze(t=>e.sendFollowUp(t),[e])}function ce(){return d("theme")}function pe(){return d("toolOutput")}function me(){return d("toolResponseMetadata")}import{useCallback as Ge,useEffect as $e,useState as Je}from"react";function ge(e){let t=d("widgetState"),[i,c]=Je(()=>t??(typeof e=="function"?e():e??null));$e(()=>{c(t)},[t]);let u=Ge(p=>{c(g=>{let f=typeof p=="function"?p(g):p;return $()==="openai"&&f!=null&&window.openai?.setWidgetState(f),f})},[]);return[i,u]}import{jsx as k,jsxs as fe}from"react/jsx-runtime";var qe=()=>fe("div",{className:"flex flex-col items-center justify-center h-full min-h-[120px] gap-4",children:[fe("div",{className:"flex gap-2",children:[k("div",{className:"w-3 h-3 rounded-full bg-gradient-to-r from-blue-400 to-cyan-400 animate-bounce [animation-delay:-0.3s]"}),k("div",{className:"w-3 h-3 rounded-full bg-gradient-to-r from-cyan-400 to-teal-400 animate-bounce [animation-delay:-0.15s]"}),k("div",{className:"w-3 h-3 rounded-full bg-gradient-to-r from-teal-400 to-emerald-400 animate-bounce"})]}),k("p",{className:"text-sm font-medium text-transparent bg-clip-text bg-gradient-to-r from-slate-400 via-slate-200 to-slate-400 bg-[length:200%_100%] animate-[shimmer_1.5s_ease-in-out_infinite]",children:"Loading widget..."}),k("div",{className:"absolute inset-0 flex items-center justify-center pointer-events-none",children:k("div",{className:"w-16 h-16 rounded-full border-2 border-blue-400/20 animate-ping"})}),k("style",{children:`
|
|
63
63
|
@keyframes shimmer {
|
|
64
64
|
0% { background-position: 200% 0; }
|
|
65
65
|
100% { background-position: -200% 0; }
|
|
66
66
|
}
|
|
67
|
-
`})]});export{Y as DevModeProvider,
|
|
67
|
+
`})]});export{Y as DevModeProvider,Ce as InitializeNextJsInChatGpt,qe as LoadingWidget,te as WidgetProvider,L as getMockState,R as initializeMockOpenAI,O as updateMockDisplayMode,v as updateMockGlobal,A as updateMockTheme,W as updateMockToolOutput,oe as useCallTool,ne as useDisplayMode,re as useIsChatGptApp,ae as useLocale,ie as useMaxHeight,se as useOpenExternal,le as useRequestDisplayMode,de as useSafeArea,ue as useSendFollowUp,ce as useTheme,pe as useToolOutput,me as useToolResponseMetadata,d as useWidgetClient,ge as useWidgetState};
|
|
68
68
|
//# sourceMappingURL=react.js.map
|