PageSourceSearch

https://socialnex.ai/assets/mock-stitch-D1VYN8uU.js

js socialnex.ai collected 2026-10-05 15:08:56 UTC 25,658 bytes, 1 lines download raw bytes

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.