1import{r as e,j as n}from"./react-vendor-hAxFZxNQ.js";import{f as t,c as s,ai as l,$ as a,a0 as r,a1 as o,a2 as i,al as c,X as d,aL as m,bZ as u,as as h,e as x,i as p,b_ as f,bA as g,b$ as v,c0 as b,C as y,c1 as w,c2 as j}from"./main-C-ofR5-x.js";import"./ui-DlHKYJvh.js";const N=e.createContext(null);function S({children:t}){const[s,l]=e.useState([]),[a,r]=e.useState(!1),[o,i]=e.useState(""),[c,d]=e.useState(""),[m,u]=e.useState(null),[h,x]=e.useState(null),p=e.useCallback(e=>{const n={...e,id:"undefined"!=typeof crypto&&crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).substring(2,11)}`,timestamp:new Date};l(e=>[...e,n])},[]),f=e.useCallback(e=>{l(n=>{if(0===n.length)return n;const t=[...n];return t[t.length-1]={...t[t.length-1],content:e},t})},[]),g=e.useCallback(()=>{l([])},[]);return n.jsx(N.Provider,{value:{messages:s,isStreaming:a,html:o,css:c,selectedElement:m,pendingImage:h,addMessage:p,updateLastMessage:f,setHtml:i,setCss:d,setSelectedElement:u,setIsStreaming:r,setPendingImage:x,clearConversation:g},children:t})}function C(){const n=e.useContext(N);if(!n)throw new Error("useStitch must be used within a StitchProvider");return n}function L(e){const n=(new Date).getTime()-e.getTime(),t=Math.floor(n/6e4);return t<1?"just now":t<60?`${t}m ago`:t<1440?`${Math.floor(t/60)}h ago`:`${Math.floor(t/1440)}d ago`}function E({language:t,code:d}){const[m,u]=e.useState(!1),[h,x]=e.useState(!1),p=d.split("\n"),f=p.length,g=p.slice(0,3).join("\n"),v=f>3;return n.jsxs(n.Fragment,{children:[n.jsxs("div",{className:"my-2 rounded-md border bg-muted/50 overflow-hidden",children:[n.jsxs("div",{className:"flex items-center justify-between px-3 py-1.5 border-b bg-muted/50",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(s,{name:"Code",className:"h-3.5 w-3.5 text-muted-foreground"}),n.jsx("span",{className:"text-xs text-muted-foreground font-medium",children:t||"code"}),n.jsxs("span",{className:"text-xs text-muted-foreground",children:["(",f," lines)"]})]}),n.jsxs(l,{variant:"ghost",size:"sm",className:"h-6 px-2 text-xs",onClick:()=>u(!0),children:[n.jsx(s,{name:"Maximize2",className:"h-3 w-3 mr-1"}),"View"]}
1)]}),n.jsx("pre",{className:"p-3 text-xs overflow-hidden",children:n.jsxs("code",{className:"text-muted-foreground",children:[g,v&&"\n..."]})})]}),n.jsx(a,{open:m,onOpenChange:u,children:n.jsxs(r,{className:"max-w-3xl max-h-[80vh] flex flex-col",children:[n.jsxs(o,{children:[n.jsxs(i,{className:"flex items-center gap-2",children:[n.jsx(s,{name:"Code",className:"h-4 w-4"}),t||"Code",n.jsxs("span",{className:"text-sm font-normal text-muted-foreground",children:["(",f," lines)"]})]}),n.jsx(c,{className:"sr-only",children:"Generated code from AI response"})]}),n.jsxs("div",{className:"flex-1 overflow-auto rounded-md border bg-muted/30",children:[n.jsx("div",{className:"flex items-center justify-end px-3 py-2 border-b",children:n.jsxs(l,{variant:"outline",size:"sm",className:"h-7",onClick:async()=>{await navigator.clipboard.writeText(d),x(!0),setTimeout(()=>x(!1),2e3)},children:[n.jsx(s,{name:h?"Check":"Copy",className:"h-3.5 w-3.5 mr-1.5"}),h?"Copied!":"Copy"]})}),n.jsx("pre",{className:"p-4 overflow-auto text-sm",children:n.jsx("code",{children:d})})]})]})})]})}function k(e){const t=/```(\w*)\n?([\s\S]*?)```/g,s=[];let l,a=0;for(;null!==(l=t.exec(e));){l.index>a&&s.push(n.jsx("span",{children:e.slice(a,l.index)},`text-${a}`));const t=l[1]||"",r=l[2].trim();s.push(n.jsx(E,{language:t,code:r},`code-${l.index}`)),a=l.index+l[0].length}return a<e.length&&s.push(n.jsx("span",{children:e.slice(a)},`text-${a}`)),s.length>0?s:[n.jsx("span",{children:e},"content")]}function O({message:e}){const s="user"===e.role;return"system"===e.role?n.jsx("div",{className:"flex justify-center py-2",children:n.jsx("div",{className:"rounded-md bg-muted/50 px-3 py-1 text-xs text-muted-foreground",children:e.content})}):n.jsx("div",{className:t("flex w-full",s?"justify-end":"justify-start"),children:n.jsxs("div",{className:t("max-w-[80%] rounded-lg px-4 py-2",s?"bg-primary text-primary-foreground":"bg-muted text-foreground"),children:[n.jsx("div",{className:"whitespace-pre-wrap break-words",children:k(e.content)}),n.jsx("div",{className:t("mt-1 text-xs",s?"text-primary-foreground/70":"text-muted-foreground"),children:L(e.timestamp)})]})})}function T({onSend:t,disabled:a=!1,placeholder:r="Describe your design..."}){const[o,i]=e.useState(""),[c,f]=e.useState(!1),g=e.useRef(null),v=e.useRef(null),{pendingImage:b,setPendingImage:y}=C();e.useEffect(()=>{const e=g.current;if(!e)return;e.style.height="auto";const n=Math.min(e.scrollHeight,200);e.style.height=`${n}px`},[o]);const w=()=>{const e=o.trim();e&&!a&&(t(e),i(""))};return n.jsxs("div",{className:"flex flex-col gap-2",children:[b&&n.jsxs("div",{className:"relative inline-block w-fit",children:[n.jsx("img",{src:b.base64,alt:b.name,className:"h-16 w-auto rounded border object-cover"}),n.jsx("button",{type:"button","aria-label":"Remove image",onClick:()=>{y(null)},className:"absolute -right-2 -top-2 rounded-full bg-destructive p-0.5 text-destructive-foreground hover:bg-destructive/90",children:n.jsx(d,{className:"h-3 w-3"})})]}),n.jsxs("div",{className:"flex items-end gap-2",children:[n.jsx("input",{ref:v,type:"file",accept:"image/*",onChange:async e=>{const n=e.target.files?.[0];if(n){f(!0);try{const e=await function(e){return new Promise((n,t)=>{const s=new FileReader;s.onload=()=>n(s.result),s.onerror=t,s.readAsDataURL(e)})}(n),t=new FormData;t.append("image",n);const s=await fetch(x("/api/v1/upload/image/"),{method:"POST",credentials:"include",headers:{"X-CSRFToken":p()||""},body:t});if(!s.ok)throw new Error("Upload failed");const l={url:(await s.json()).url,base64:e,name:n.name};y(l)}catch(t){}finally{f(!1),v.current&&(v.current.value="")}}},className:"hidden"}),n.jsx(l,{type:"button",variant:"outline",size:"icon",onClick:()=>{v.current?.click()},disabled:a||c,className:"shrink-0",children:c?n.jsx(m,{className:"h-4 w-4 animate-spin"}):n.jsx(u,{className:"h-4 w-4"})}),n.jsx(h,{ref:g,value:o,onChange:e=>{i(e.target.value)},onKeyDown:e=>{"Enter"!==e.key||e.shiftKey||(e.preventDefault(),w())},placeholder:r,disabled:a,className:"min-h-[44px] max-h-[200px] resize-none",rows:1}),n.jsx(l,{onClick:w,disabled:a||!o.trim(),size:"icon",className:"shrink-0",children:n.jsx(s,{name:"Send",className:"h-4 w-4"})})]})]})}function M(){const{selectedElement:t,setSelectedElement:s}=C(),a=e.useMemo(()=>t?`<!DOCTYPE html>\n<html>\n<head>\n <meta charset="UTF-8">\n <script src="https://cdn.tailwindcss.com"><\/script>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100%;\n padding: 8px;\n background: repeating-conic-gradient(#e5e7eb 0% 25%, #f3f4f6 0% 50%) 50% / 16px 16px;\n }\n body > * {\n max-width: 100%;\n box-shadow: 0 0 0 1px rgba(0,0,0,0.1);\n }\n </style>\n</head>\n<body>${t.outerHTML}</body>\n</html>`:"",[t]);return t?n.jsxs("div",{className:"shrink-0 border-t bg-muted/30 px-4 py-2",children:[n.jsxs("div",{className:"flex items-center justify-between mb-2",children:[n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(f,{className:"h-3.5 w-3.5 text-green-600"}),n.jsx("span",{className:"text-xs text-muted-foreground",children:"Changes apply to"}),n.jsx("span",{className:"rounded bg-green-100 dark:bg-green-900/30 px-1.5 py-0.5 text-xs font-medium text-green-700 dark:text-green-400",children:`<${t.tagName.toLowerCase()}>`})]}),n.jsxs(l,{variant:"ghost",size:"icon",className:"h-5 w-5",onClick:()=>s(null),children:[n.jsx(d,{className:"h-3.5 w-3.5"}),n.jsx("span",{className:"sr-only",children:"Clear selection"})]})]}),n.jsx("div",{className:"relative rounded border overflow-hidden",style:{height:"80px"},children:n.jsx("iframe",{srcDoc:a,sandbox:"allow-scripts",className:"absolute inset-0 w-full h-full border-0 pointer-events-none",title:"Selected element preview"})})]}):null}function _(){const{messages:t,isStreaming:s,html:l,addMessage:a,updateLastMessage:r,setHtml:o,setIsStreaming:i,selectedElement:c,setSelectedElement:d,pendingImage:m,setPendingImage:u}=C(),h=e.useRef(null);return e.useEffect(()=>{h.current?.scrollIntoView({behavior:"smooth"})},[t]),n.jsxs("div",{className:"flex h-full w-[400px] flex-col overflow-hidden border-r",children:[n.jsxs("div",{className:"shrink-0 border-b px-4 py-2.5 flex items-center gap-2",children:[n.jsx(g,{className:"h-4 w-4 text-muted-foreground"}),n.jsx("span",{className:"text-sm font-medium text-foreground",children:"Chat"}),n.jsx("span",{className:"text-xs text-muted-foreground",children:"â describe what you want"})]}),n.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto p-4",children:0===t.length?n.jsx("div",{className:"flex h-full items-center justify-center",children:n.jsx("p",{className:"text-muted-foreground",children:"Start a conversation..."})}):n.jsxs("div",{className:"space-y-4",children:[t.map(e=>n.jsx(O,{message:e},e.id)),s&&n.jsx("div",{className:"flex justify-start",children:n.jsx("div",{className:"rounded-lg bg-muted px-4 py-2 text-muted-foreground",children:"AI is thinking..."})}),n.jsx("div",{ref:h})]})}),n.jsx(M,{}),n.jsx("div",{className:"shrink-0 border-t p-4",children:n.jsx(T,{onSend:async e=>{let n=e;c&&(n=`${e}\n\nSelected element:\n- Tag: <${c.tagName}>\n- Selector: ${c.selector}\n- HTML:\n\`\`\`html\n${c.outerHTML}\n\`\`\``),m&&(n=`${n}\n\nI've attached an image. The image URL for use in HTML is: ${m.url}`),a({role:"user",content:e}),c&&d(null);const t=m;m&&u(null),i(!0),a({role:"assistant",content:""});try{const e=await fetch(x("/api/v1/ai/stitch/chat/"),{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({messages:[{role:"user",content:n}],current_html:l,selected_element:c,image:t?{base64:t.base64,url:t.url}:null})});if(!e.ok)throw new Error("API request failed");const s=e.body?.getReader(),a=new TextDecoder;let i="";for(;s;){const{done:e,value:n}=await s.read();if(e)break;const t=a.decode(n).split("\n");for(const s of t)if(s.startsWith("data: ")){const e=s.slice(6);if("[DONE]"===e)continue;try{const n=JSON.parse(e);n.content&&(i+=n.content,r(i))}catch{}}}const{html:d}=function(e){const n={html:null,css:null},t=/```(?:html|HTML)\n([\s\S]*?)```/g;let s;for(;null!==(s=t.exec(e));)n.html=s[1].trim();const l=/```(?:css|CSS)\n([\s\S]*?)```/g;let a;for(;null!==(a=l.exec(e));)n.css=a[1].trim();if(null===n.html){const t=/```\n([\s\S]*?)```/g;let s;for(;null!==(s=t.exec(e));){const e=s[1].trim();(e.startsWith("<")||e.includes("class="))&&(n.html=e)}}return n}(i);d&&o(d)}catch(s){r("Sorry, there was an error generating the response. Please try again.")}finally{i(!1)}},disabled:s,placeholder:c?"What do you want changed about this?":"Describe your design..."})})]})}function I({html:t,isStreaming:s}){const d=e.useRef(null),{setSelectedElement:u,selectedElement:h}=C(),[x,p]=e.useState(!1),[g,j]=e.useState(!1);e.useEffect(()=>{!h&&d.current?.contentWindow&&d.current.contentWindow.postMessage({type:"CLEAR_SELECTION"},"*")},[h]);const N=e.useMemo(()=>t.trim()?`<!DOCTYPE html>\n<html>\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <script src="https://cdn.tailwindcss.com"><\/script>\n</head>\n<body style="margin: 0; padding: 16px;">\n${t}\n<script>
1\n(function() {\n 'use strict';\n\n // Picker is always enabled - no toggle needed\n let hoverOverlay = null;\n let hoverLabel = null;\n let selectedOverlay = null;\n let selectedLabel = null;\n let currentElement = null;\n let selectedElement = null;\n\n // Create the overlay elements (hover + selected)\n function createOverlays() {\n // Add keyframes for pulsing border\n const style = document.createElement('style');\n style.textContent = \`\n @keyframes __stitch-pulse__ {\n 0%, 100% {\n border-color: rgba(0, 0, 0, 0.9);\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.9), inset 0 0 0 1px rgba(255, 255, 255, 0.3);\n }\n 50% {\n border-color: rgba(255, 255, 255, 0.9);\n box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.9), inset 0 0 0 1px rgba(0, 0, 0, 0.3);\n }\n }\n \`;\n document.head.appendChild(style);\n\n // Hover overlay (pulsing)\n hoverOverlay = document.createElement('div');\n hoverOverlay.id = '__stitch-picker-overlay__';\n hoverOverlay.style.cssText = \`\n position: fixed;\n pointer-events: none;\n background-color: rgba(128, 128, 128, 0.05);\n border: 2px solid rgba(0, 0, 0, 0.9);\n border-radius: 2px;\n z-index: 999999;\n display: none;\n animation: __stitch-pulse__ 1s ease-in-out infinite;\n \`;\n document.body.appendChild(hoverOverlay);\n\n // Selected overlay (solid green)\n selectedOverlay = document.createElement('div');\n selectedOverlay.id = '__stitch-picker-selected__';\n selectedOverlay.style.cssText = \`\n position: fixed;\n pointer-events: none;\n background-color: rgba(34, 197, 94, 0.1);\n border: 2px solid rgba(34, 197, 94, 0.9);\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.9);\n border-radius: 2px;\n z-index: 999998;\n display: none;\n \`;\n document.body.appendChild(selectedOverlay);\n }\n\n // Create the label elements (hover + selected)\n function createLabels() {\n // Hover label\n hoverLabel = document.createElement('div');\n hoverLabel.id = '__stitch-picker-label__';\n hoverLabel.style.cssText = \`\n position: fixed;\n pointer-events: none;\n background-color: rgba(0, 0, 0, 0.85);\n color: white;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 2px;\n border: 1px solid rgba(255, 255, 255, 0.5);\n z-index: 1000000;\n display: none;\n white-space: nowrap;\n max-width: 300px;\n overflow: hidden;\n text-overflow: ellipsis;\n \`;\n document.body.appendChild(hoverLabel);\n\n // Selected label\n selectedLabel = document.createElement('div');\n selectedLabel.id = '__stitch-picker-selected-label__';\n selectedLabel.style.cssText = \`\n position: fixed;\n pointer-events: none;\n background-color: rgba(34, 197, 94, 0.95);\n color: white;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 2px;\n z-index: 999999;\n display: none;\n white-space: nowrap;\n max-width: 300px;\n overflow: hidden;\n text-overflow: ellipsis;\n \`;\n document.body.appendChild(selectedLabel);\n }\n\n // Generate a simple CSS selector for an element\n function generateSelector(element) {\n if (!element || element === document.body || element === document.documentElement) {\n return '';\n }\n\n // If element has an id, use it\n if (element.id) {\n return '#' + CSS.escape(element.id);\n }\n\n // Build selector with tag and classes\n let selector = element.tagName.toLowerCase();\n\n if (element.classList && element.classList.length > 0) {\n const classes = Array.from(element.classList)\n .filter(c => !c.startsWith('__stitch-'))\n .slice(0, 3) // Limit to 3 classes\n .map(c => '.' + CSS.escape(c))\n .join('');\n selector += classes;\n }\n\n // Check if selector is unique\n try {\n const matches = document.querySelectorAll(selector);\n if (matches.length === 1) {\n return selector;\n }\n } catch (e) {\n // Invalid selector, continue building path\n }\n\n // Walk up parents to build a more specific path\n const parent = element.parentElement;\n if (parent && parent !== document.body && parent !== document.documentElement) {\n const parentSelector = generateSelector(parent);\n if (parentSelector) {\n // Add nth-child if needed for uniqueness\n const siblings = Array.from(parent.children).filter(\n child => child.tagName === element.tagName\n );\n if (siblings.length > 1) {\n const index = siblings.indexOf(element) + 1;\n selector += ':nth-of-type(' + index + ')';\n }\n return parentSelector + ' > ' + selector;\n }\n }\n\n return selector;\n }\n\n // Get all attributes of an element\n function getAttributes(element) {\n const attrs = {};\n for (const attr of element.attributes) {\n attrs[attr.name] = attr.value;\n }\n return attrs;\n }\n\n // Get element info\n function getElementInfo(element) {\n return {\n selector: generateSelector(element),\n tagName: element.tagName.toLowerCase(),\n outerHTML: element.outerHTML,\n attributes: getAttributes(element)\n };\n }\n\n // Get label text for an element\n function getLabelText(element) {\n let text = element.tagName.toLowerCase();\n\n if (element.classList && element.classList.length > 0) {\n const classes = Array.from(element.classList)\n .filter(c => !c.startsWith('__stitch-'))\n .slice(0, 2)\n .join('.');\n if (classes) {\n text += '.' + classes;\n }\n }
1\n\n if (element.id) {\n text = element.tagName.toLowerCase() + '#' + element.id;\n }\n\n return text;\n }\n\n // Update hover overlay position\n function updateHoverOverlay(element) {\n if (!hoverOverlay || !hoverLabel) return;\n\n if (!element || element === document.body || element === document.documentElement || element === selectedElement) {\n hoverOverlay.style.display = 'none';\n hoverLabel.style.display = 'none';\n currentElement = null;\n return;\n }\n\n const rect = element.getBoundingClientRect();\n\n // Update overlay\n hoverOverlay.style.display = 'block';\n hoverOverlay.style.top = rect.top + 'px';\n hoverOverlay.style.left = rect.left + 'px';\n hoverOverlay.style.width = rect.width + 'px';\n hoverOverlay.style.height = rect.height + 'px';\n\n // Update label\n hoverLabel.style.display = 'block';\n hoverLabel.textContent = getLabelText(element);\n\n // Position label above the element\n const labelTop = rect.top - 22;\n if (labelTop < 0) {\n hoverLabel.style.top = (rect.bottom + 4) + 'px';\n } else {\n hoverLabel.style.top = labelTop + 'px';\n }\n hoverLabel.style.left = Math.max(0, rect.left) + 'px';\n\n currentElement = element;\n }\n\n // Update selected overlay position\n function updateSelectedOverlay() {\n if (!selectedOverlay || !selectedLabel || !selectedElement) {\n if (selectedOverlay) selectedOverlay.style.display = 'none';\n if (selectedLabel) selectedLabel.style.display = 'none';\n return;\n }\n\n const rect = selectedElement.getBoundingClientRect();\n\n // Update overlay\n selectedOverlay.style.display = 'block';\n selectedOverlay.style.top = rect.top + 'px';\n selectedOverlay.style.left = rect.left + 'px';\n selectedOverlay.style.width = rect.width + 'px';\n selectedOverlay.style.height = rect.height + 'px';\n\n // Update label\n selectedLabel.style.display = 'block';\n selectedLabel.textContent = 'â ' + getLabelText(selectedElement);\n\n // Position label above the element\n const labelTop = rect.top - 22;\n if (labelTop < 0) {\n selectedLabel.style.top = (rect.bottom + 4) + 'px';\n } else {\n selectedLabel.style.top = labelTop + 'px';\n }\n selectedLabel.style.left = Math.max(0, rect.left) + 'px';\n }\n\n // Handle mousemove\n function handleMouseMove(event) {\n const target = event.target;\n\n // Ignore our own elements\n if (target.id && target.id.startsWith('__stitch-picker')) {\n return;\n }\n\n updateHoverOverlay(target);\n }\n\n // Handle click\n function handleClick(event) {\n const target = event.target;\n\n // Ignore our own elements\n if (target.id && target.id.startsWith('__stitch-picker')) {\n return;\n }\n\n // Ignore body and html\n if (target === document.body || target === document.documentElement) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n\n // Set selected element and update overlay\n selectedElement = target;\n updateSelectedOverlay();\n\n // Hide hover overlay since this element is now selected\n hoverOverlay.style.display = 'none';\n hoverLabel.style.display = 'none';\n\n const elementInfo = getElementInfo(target);\n\n // Send message to parent\n window.parent.postMessage({\n type: 'ELEMENT_SELECTED',\n payload: elementInfo\n }, '*');\n }\n\n // Handle message from parent to clear selection\n function handleMessage(event) {\n if (event.data && event.data.type === 'CLEAR_SELECTION') {\n selectedElement = null;\n updateSelectedOverlay();\n }\n }\n\n // Initialize\n function init() {\n // Create overlays and labels\n createOverlays();\n createLabels();\n\n // Set cursor to indicate clickable\n document.body.style.cursor = 'crosshair';\n\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n window.addEventListener('message', handleMessage);\n\n // Update selected overlay on scroll/resize\n window.addEventListener('scroll', updateSelectedOverlay, true);\n window.addEventListener('resize', updateSelectedOverlay);\n\n // Notify parent that picker is ready\n window.parent.postMessage({ type: 'PICKER_READY' }, '*');\n }\n\n // Wait for DOM ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', init);\n } else {\n init();\n }\n})();\n<\/script>\n</body>\n</html>`:"",[t]);return e.useEffect(()=>{function e(e){if(e.source!==d.current?.contentWindow)return;const n=e.data;n&&"object"==typeof n&&"ELEMENT_SELECTED"===n.type&&u(n.payload)}return window.addEventListener("message",e),()=>window.removeEventListener("message",e)},[u]),n.jsxs("div",{className:"flex h-full flex-col overflow-hidden",children:[n.jsxs("div",{className:"shrink-0 border-b px-4 py-2.5 flex items-center gap-2",children:[n.jsx(v,{className:"h-4 w-4 text-muted-foreground"}),n.jsx("span",{className:"text-sm font-medium text-foreground",children:"Preview"}),n.jsxs("span",{className:"text-xs text-muted-foreground flex items-center gap-1",children:["â ",n.jsx(f,{className:"h-3 w-3"})," click to select"]}),t&&n.jsx("div",{className:"ml-auto flex items-center",children:n.jsxs(l,{variant:"ghost",size:"sm",className:"h-7 px-2 text-xs",onClick:()=>p(!0),children:[n.jsx(b,{className:"h-3.5 w-3.5 mr-1"}),"View Code"]})})]}),n.jsxs("div",{className:"relative flex-1 overflow-auto",children:[N?n.jsx("iframe",{ref:d,srcDoc:N,sandbox:"allow-scripts",className:"absolute inset-0 h-full w-full border-0 bg-white",title:"Preview"}):n.jsx("div",{className:"flex h-full items-center justify-center text-muted-foreground",children:"Preview will appear here"}),s&&n.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-background/50 backdrop-blur-sm",children:n.jsxs("div",{className:"flex items-center gap-2 rounded-lg bg-background px-4 py-2 shadow-lg border",children:[n.jsx(m,{className:"h-4 w-4 animate-spin text-primary"}),n.jsx("span",{className:"text-sm font-medium",children:"Generating..."})]})})]}),n.jsx(a,{open:x,onOpenChange:p,children:n.jsxs(r,{className:"max-w-3xl max-h-[80vh] flex flex-col",children:[n.jsxs(o,{children:[n.jsxs(i,{className:"flex items-center gap-2",children:[n.jsx(b,{className:"h-4 w-4"}),"HTML Code",n.jsxs("span",{className:"text-sm font-normal text-muted-foreground",children:["(",t.split("\n").length," lines)"]})]}),n.jsx(c,{className:"sr-only",children:"Generated HTML code"})]}),n.jsxs("div",{className:"flex-1 overflow-auto rounded-md border bg-muted/30",children:[n.jsx("div",{className:"flex items-center justify-end px-3 py-2 border-b",children:n.jsxs(l,{variant:"outline",size:"sm",className:"h-7",onClick:async()=>{await navigator.clipboard.writeText(t),j(!0),setTimeout(()=>j(!1),2e3)},children:[g?n.jsx(y,{className:"h-3.5 w-3.5 mr-1.5"}):n.jsx(w,{className:"h-3.5 w-3.5 mr-1.5"}),g?"Copied!":"Copy"]})}),n.jsx("pre",{className:"p-4 overflow-auto text-sm",children:n.jsx("code",{children:t})})]})]})})]})}function D(){const{html:e,isStreaming:t}=C();return n.jsxs("div",{className:"flex h-full flex-row overflow-hidden",children:[n.jsx(_,{}),n.jsx("div",{className:"flex-1 h-full overflow-hidden",children:n.jsx(I,{html:e,isStreaming:t})})]})}function z(){return n.jsx(S,{children:n.jsx(D,{})})}function H(){const[t,d]=e.useState(!1);return n.jsxs("div",{className:"container mx-auto px-4 py-8",children:[n.jsxs("div",{className:"mb-8",children:[n.jsx("h1",{className:"text-3xl font-bold",children:"Stitch Designer"}),n.jsx("p",{className:"mt-2 text-muted-foreground",children:"AI-powered design tool for creating and editing UI components"})]}),n.jsxs(a,{open:t,onOpenChange:d,children:[n.jsx(j,{asChild:!0,children:n.jsxs(l,{size:"lg",children:[n.jsx(s,{name:"Wand2",className:"mr-2 h-5 w-5"}),"Open Designer"]})}),n.jsxs(r,{className:"h-[90vh] max-w-[95vw] w-[1400px] overflow-hidden p-0",hideClose:!0,children:[n.jsxs(o,{className:"sr-only",children:[n.jsx(i,{children:"Stitch Designer"}),n.jsx(c,{children:"AI-powered design tool"})]}),n.jsx(z,{})]})]})]})}export{H as component};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.