truecanvas 0.6.5 → 0.6.6

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.
@@ -6,7 +6,7 @@ import {
6
6
  responseHeaders,
7
7
  safePath,
8
8
  viewerHtml
9
- } from "../chunk-7KJVGN4O.js";
9
+ } from "../chunk-O6YS366Z.js";
10
10
  export {
11
11
  CHUNK,
12
12
  decodeFrame,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "truecanvas",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "Design with your real React components: a Figma-like canvas for Next.js and Vite where layers are your .tsx and agents edit through MCP.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,2 +0,0 @@
1
- import{i as e,t}from"./react-DB-4Zxce.js";import{A as n,C as r,E as i,O as a,S as o,T as s,_ as c,b as l,g as u,h as d,i as f,j as p,n as m,t as h,v as g,w as _,x as v,y}from"./Menu-TTrH9CSM.js";var b={name:`cloud-download`,size:24,node:[[`path`,{d:`M12 13v8l-4-4`,key:`1f5nwf`}],[`path`,{d:`m12 21 4-4`,key:`1lfcce`}],[`path`,{d:`M4.393 15.269A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.436 8.284`,key:`ui1hmy`}]],aliases:[`download-cloud`]};b.node;var x=n(b),S={name:`cpu`,size:24,node:[[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M17 20v2`,key:`1rnc9c`}],[`path`,{d:`M17 2v2`,key:`11trls`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M2 17h2`,key:`7oei6x`}],[`path`,{d:`M2 7h2`,key:`asdhe0`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`M20 17h2`,key:`1fpfkl`}],[`path`,{d:`M20 7h2`,key:`1o8tra`}],[`path`,{d:`M7 20v2`,key:`4gnj0m`}],[`path`,{d:`M7 2v2`,key:`1i4yhu`}],[`rect`,{x:`4`,y:`4`,width:`16`,height:`16`,rx:`2`,key:`1vbyd7`}],[`rect`,{x:`8`,y:`8`,width:`8`,height:`8`,rx:`1`,key:`z9xiuo`}]]};S.node;var C=n(S),w={name:`folder-open`,size:24,node:[[`path`,{d:`m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2`,key:`usdka0`}]]};w.node;var T=n(w),E={name:`folder-plus`,size:24,node:[[`path`,{d:`M12 10v6`,key:`1bos4e`}],[`path`,{d:`M9 13h6`,key:`1uhe8q`}],[`path`,{d:`M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z`,key:`1kt360`}]]};E.node;var D=n(E),O={name:`folder`,size:24,node:[[`path`,{d:`M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z`,key:`1kt360`}]]};O.node;var k=n(O),A={name:`info`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 16v-4`,key:`1dtifu`}],[`path`,{d:`M12 8h.01`,key:`e9boi3`}]]};A.node;var j=n(A),M={name:`power`,size:24,node:[[`path`,{d:`M12 2v10`,key:`mnfbl`}],[`path`,{d:`M18.4 6.6a9 9 0 1 1-12.77.04`,key:`obofu9`}]]};M.node;var N=n(M),P={name:`triangle-alert`,size:24,node:[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`,key:`wmoenq`}],[`path`,{d:`M12 9v4`,key:`juzpu7`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]],aliases:[`alert-triangle`]};P.node;var F=n(P),I={name:`wand-sparkles`,size:24,node:[[`path`,{d:`m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72`,key:`ul74o6`}],[`path`,{d:`m14 7 3 3`,key:`1r5n42`}],[`path`,{d:`M5 6v4`,key:`ilb8ba`}],[`path`,{d:`M19 14v4`,key:`blhpug`}],[`path`,{d:`M10 2v2`,key:`7u0qdc`}],[`path`,{d:`M7 8H3`,key:`zfb6yr`}],[`path`,{d:`M21 16h-4`,key:`1cnmox`}],[`path`,{d:`M11 3H9`,key:`1obp7u`}]],aliases:[`wand-2`]};I.node;var L=n(I),R=p(),z=e(t(),1),B=u();async function V(e,t){let n=await fetch(e,t===void 0?void 0:{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify(t)}),r=await n.json();if(!n.ok)throw Error(r.error??`Request failed (${n.status})`);return r}var H=e=>e.replace(/^\/home\/[^/]+/,`~`);function U(){let e=(()=>{try{return JSON.parse(localStorage.getItem(`tc:uiTheme`)??`"system"`)}catch{return`system`}})(),t=e===`dark`||e===`system`&&window.matchMedia(`(prefers-color-scheme: dark)`).matches;document.documentElement.dataset.ui=t?`dark`:`light`}function W(){let[e,t]=(0,z.useState)(null),[n,i]=(0,z.useState)(()=>localStorage.getItem(`tc:hubTab`)??`dashboard`),[a,s]=(0,z.useState)(null),[l,u]=(0,z.useState)(!0),f=(0,z.useRef)(0),p=(0,z.useCallback)(()=>{let e=++f.current;V(`/api/hub/state`).then(n=>e===f.current&&t(n)).catch(()=>{})},[]);(0,z.useEffect)(()=>{U();let e=window.matchMedia(`(prefers-color-scheme: dark)`);e.addEventListener(`change`,U),p();let t=new EventSource(`/api/hub/events`);t.onmessage=()=>p(),t.onopen=()=>{u(!0),p()},t.onerror=()=>u(!1);let n=setInterval(p,5e3);return()=>{e.removeEventListener(`change`,U),t.close(),clearInterval(n)}},[p]);let m=(0,z.useMemo)(()=>(e?.projects??[]).filter(e=>e.running),[e]),h=(0,z.useRef)(null);(0,z.useEffect)(()=>{e&&(m.some(e=>e.path===h.current)&&(h.current=null),n!==`dashboard`&&n!==h.current&&!m.some(e=>e.path===n)&&i(`dashboard`))},[e,m,n]),(0,z.useEffect)(()=>{localStorage.setItem(`tc:hubTab`,n),V(`/api/hub/active`,{path:n===`dashboard`?``:n}).catch(()=>{})},[n]);let g=(0,z.useRef)(Date.now()),[_,v]=(0,z.useState)({});(0,z.useEffect)(()=>{let t=e?.focus;if(!t||t.at<=g.current||!m.some(e=>e.path===t.path))return;g.current=t.at,i(t.path);let n=t.canvas;n&&v(e=>({...e,[t.path]:{canvas:n,at:t.at}}))},[e,m]);let y=m.find(e=>e.path===n)?.name;(0,z.useEffect)(()=>{document.title=y?`${y} · Truecanvas`:`Truecanvas`},[y]);let b=async e=>{h.current=e.path,i(e.path);try{await V(`/api/hub/open`,{path:e.path})}catch(e){h.current=null,s(e.message)}p()},x=async e=>{let t=m.findIndex(t=>t.path===e.path);n===e.path&&i(m[t+1]?.path??m[t-1]?.path??`dashboard`);try{await V(`/api/hub/close`,{path:e.path})}catch(e){s(e.message)}p()};(0,z.useEffect)(()=>{let e=e=>{if(!e.ctrlKey)return;let t=[`dashboard`,...m.map(e=>e.path)];if(e.key===`Tab`){e.preventDefault();let r=t.indexOf(n);i(t[(r+(e.shiftKey?-1:1)+t.length)%t.length])}};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[m,n]);let S=m.reduce((e,t)=>e+(t.running?.memory??0),0),[w,T]=(0,z.useState)(!1),[E,D]=(0,z.useState)(!1),O=async()=>{T(!1),await fetch(`/api/hub/quit`,{method:`POST`}).catch(()=>{}),D(!0),setTimeout(()=>window.close(),300)};return(0,z.useEffect)(()=>{let e=e=>{e.ctrlKey&&(e.key===`q`||e.key===`Q`)&&(e.preventDefault(),m.length?T(!0):O())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)}),E?(0,B.jsxs)(`div`,{className:`hub-center`,style:{height:`100%`},children:[(0,B.jsx)(`img`,{src:`/favicon.svg`,width:44,height:44,alt:``}),(0,B.jsx)(`div`,{style:{fontWeight:600,marginTop:6},children:`Truecanvas has quit`}),(0,B.jsx)(`div`,{className:`muted`,children:"You can close this window. Open it again from your app launcher or with `truecanvas`."})]}):(0,B.jsxs)(`div`,{className:`hub`,children:[(0,B.jsxs)(`header`,{className:`tabbar`,role:`tablist`,children:[(0,B.jsxs)(`button`,{role:`tab`,"aria-selected":n===`dashboard`,className:`hub-tab home-tab${n===`dashboard`?` on`:``}`,onClick:()=>i(`dashboard`),children:[(0,B.jsx)(r,{size:14}),(0,B.jsx)(`span`,{children:`Dashboard`})]}),(0,B.jsx)(`span`,{className:`tab-sep`}),(0,B.jsx)(`div`,{className:`tab-strip`,children:m.map(e=>(0,B.jsxs)(`div`,{role:`tab`,tabIndex:0,"aria-selected":n===e.path,className:`hub-tab${n===e.path?` on`:``}`,onClick:()=>i(e.path),onAuxClick:t=>t.button===1&&void x(e),title:H(e.path),children:[e.running?.status===`starting`?(0,B.jsx)(o,{size:14,className:`spin-working`}):e.running?.status===`failed`?(0,B.jsx)(F,{size:14,className:`warn`}):(0,B.jsx)(G,{path:e.path}),(0,B.jsx)(`span`,{className:`label`,children:e.name}),(0,B.jsx)(`button`,{className:`tab-close`,"aria-label":`Close ${e.name}`,onClick:t=>{t.stopPropagation(),x(e)},children:(0,B.jsx)(c,{size:12})})]},e.path))}),(0,B.jsxs)(`div`,{className:`tabbar-right`,children:[S>0&&(0,B.jsx)(d,{label:`Memory used by open projects (app + Truecanvas)`,side:`bottom`,children:(0,B.jsxs)(`span`,{className:`mem-chip`,children:[(0,B.jsx)(C,{size:12}),` `,S>=1024?`${(S/1024).toFixed(1)} GB`:`${S} MB`]})}),(0,B.jsx)(q,{version:e?.version,onQuit:()=>T(!0)})]})]}),w&&(0,B.jsx)(J,{running:m.map(e=>e.name),onCancel:()=>T(!1),onQuit:()=>void O()}),(0,B.jsxs)(`main`,{className:`hub-body`,children:[n===`dashboard`&&e&&(0,B.jsx)(X,{state:e,onOpen:b,refresh:p}),m.map(e=>(0,B.jsx)(Y,{project:e,visible:n===e.path,canvas:_[e.path],onRetry:()=>void b(e)},e.path)),!l&&(0,B.jsxs)(`div`,{className:`banner`,role:`status`,style:{top:12},children:[(0,B.jsx)(o,{size:14,className:`spin-working`}),(0,B.jsx)(`div`,{className:`muted`,children:`Lost connection to Truecanvas. Reconnecting…`})]}),e?.notice&&!a&&(0,B.jsxs)(`div`,{className:`banner`,role:`alert`,style:{top:12},children:[(0,B.jsx)(F,{size:14,className:`warn`}),(0,B.jsx)(`div`,{children:e.notice})]}),a&&(0,B.jsxs)(`div`,{className:`banner`,role:`alert`,style:{top:12},children:[(0,B.jsx)(`span`,{className:`dot`}),(0,B.jsx)(`div`,{children:a}),(0,B.jsx)(`button`,{className:`icon-btn`,"aria-label":`Dismiss`,onClick:()=>s(null),children:(0,B.jsx)(c,{size:14})})]})]})]})}function G({path:e,size:t=14}){let[n,r]=(0,z.useState)(!1);return n?(0,B.jsx)(k,{size:t,className:`folder-icon`}):(0,B.jsx)(`img`,{className:`project-favicon`,src:`/api/hub/icon?path=${encodeURIComponent(e)}`,width:t,height:t,alt:``,onError:()=>r(!0)})}var K=window.truecanvasDesktop;function q({version:e,onQuit:t}){let[n,r]=(0,z.useState)(null),a=K?.version||e||``;return(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(d,{label:a?`Truecanvas ${a}`:`Truecanvas`,side:`bottom`,children:(0,B.jsx)(`button`,{className:`icon-btn app-menu-btn`,"aria-label":`Truecanvas menu`,onClick:e=>{let t=e.currentTarget.getBoundingClientRect();r({x:t.right-220,y:t.bottom+6})},children:(0,B.jsx)(s,{size:16})})}),n&&(0,B.jsx)(h,{x:n.x,y:n.y,onClose:()=>r(null),items:[...a?[{label:`Truecanvas ${a}: what's new`,icon:(0,B.jsx)(j,{size:14}),onSelect:()=>window.open(`https://github.com/Nathandona/truecanvas/releases/tag/v${a}`,`_blank`)}]:[],...K?.checkForUpdates?[{label:`Check for updates`,icon:(0,B.jsx)(i,{size:14}),onSelect:()=>void K.checkForUpdates()}]:[],...a||K?.checkForUpdates?[`sep`]:[],{label:`Reload window`,icon:(0,B.jsx)(y,{size:14}),kbd:`Ctrl+R`,onSelect:()=>location.reload()},`sep`,{label:`Quit Truecanvas`,icon:(0,B.jsx)(N,{size:14}),kbd:`Ctrl+Q`,danger:!0,onSelect:t}]})]})}function J({running:e,onCancel:t,onQuit:n}){return(0,B.jsxs)(f,{title:`Quit Truecanvas?`,role:`alertdialog`,width:380,onClose:t,children:[(0,B.jsx)(`p`,{className:`muted`,children:e.length?`This also stops ${e.length===1?`the app`:`the apps`} it started: ${e.join(`, `)}. Your files are saved as you edit.`:`Your files are saved as you edit.`}),(0,B.jsxs)(`div`,{className:`modal-actions`,children:[(0,B.jsx)(`button`,{className:`btn outline`,onClick:t,children:`Cancel`}),(0,B.jsx)(`button`,{className:`btn danger-solid`,autoFocus:!0,onClick:n,children:`Quit`})]})]})}function Y({project:e,visible:t,canvas:n,onRetry:r}){let i=e.running,a=n?`${i.editor}/?canvas=${encodeURIComponent(n.canvas)}`:`${i.editor}/`;return(0,B.jsxs)(`div`,{className:`project-view`,style:{display:t?`block`:`none`},children:[i.status===`ready`&&(0,B.jsx)(`iframe`,{title:e.name,src:a,allow:`clipboard-read; clipboard-write`},n?.at),i.status===`starting`&&(0,B.jsxs)(`div`,{className:`hub-center`,children:[(0,B.jsx)(o,{size:22,className:`spin-working`}),(0,B.jsxs)(`div`,{className:`muted`,children:[`Starting `,e.name,`…`]}),(0,B.jsx)(`div`,{className:`faint`,children:`Your app and its Truecanvas editor are booting.`})]}),i.status===`failed`&&(0,B.jsxs)(`div`,{className:`hub-center`,children:[(0,B.jsx)(F,{size:22,className:`warn`}),(0,B.jsxs)(`div`,{style:{fontWeight:600},children:[e.name,` didn’t start`]}),(0,B.jsx)(`pre`,{className:`job-log`,style:{maxWidth:640},children:i.error}),(0,B.jsxs)(`button`,{className:`btn primary`,onClick:r,children:[(0,B.jsx)(y,{size:13}),` Try again`]})]})]})}function X({state:e,onOpen:t,refresh:n}){let[r,i]=(0,z.useState)(null),[o,u]=(0,z.useState)(null),[d,f]=(0,z.useState)(null),[p,v]=(0,z.useState)(null),[y,b]=(0,z.useState)(``),[S,C]=(0,z.useState)(null);(0,z.useEffect)(()=>{V(`/api/hub/discover`).then(e=>i(e.found)).catch(()=>i([]))},[e.projects.length]);let w=async(e,t)=>{let n=await V(e,t);v(n)},E=e.projects.filter(e=>!y||`${e.name} ${e.path}`.toLowerCase().includes(y.toLowerCase()));return(0,B.jsxs)(`div`,{className:`dashboard scroll`,children:[(0,B.jsxs)(`div`,{className:`dash-inner`,children:[(0,B.jsxs)(`div`,{className:`dash-head`,children:[(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`h1`,{children:`Projects`}),(0,B.jsx)(`p`,{className:`muted`,children:`Each project is a Next.js or Vite app. Its canvases are .tsx files in the repo.`})]}),(0,B.jsxs)(`div`,{className:`dash-actions`,children:[(0,B.jsxs)(`div`,{className:`field`,style:{width:200},children:[(0,B.jsx)(`span`,{className:`prefix`,children:(0,B.jsx)(g,{size:13})}),(0,B.jsx)(`input`,{value:y,placeholder:`Search projects`,onChange:e=>b(e.target.value)})]}),(0,B.jsxs)(`button`,{className:`btn outline`,onClick:()=>u(`open`),children:[(0,B.jsx)(T,{size:14}),` Open folder`]}),(0,B.jsxs)(`button`,{className:`btn outline`,onClick:()=>u(`clone`),children:[(0,B.jsx)(x,{size:14}),` Clone from GitHub`]}),(0,B.jsxs)(`button`,{className:`btn primary`,onClick:()=>u(`new`),children:[(0,B.jsx)(l,{size:14}),` New project`]})]})]}),E.length===0&&!y&&(0,B.jsxs)(`div`,{className:`dash-empty`,children:[(0,B.jsx)(D,{size:28}),(0,B.jsx)(`div`,{style:{fontWeight:600,marginTop:10},children:`No projects yet`}),(0,B.jsx)(`div`,{className:`muted`,children:`Open a Next.js or Vite app from your computer, clone one from GitHub, or create a new one.`})]}),(0,B.jsx)(`div`,{className:`project-grid`,children:E.map(e=>(0,B.jsxs)(`div`,{className:`project-card${e.running?` live`:``}${e.exists?``:` missing`}`,role:`button`,tabIndex:0,onClick:()=>e.ready&&e.exists&&t(e),onKeyDown:n=>n.key===`Enter`&&e.ready&&t(e),onContextMenu:t=>{t.preventDefault(),C({x:t.clientX,y:t.clientY,p:e})},children:[(0,B.jsxs)(`div`,{className:`card-top`,children:[(0,B.jsx)(`span`,{className:`card-icon`,children:(0,B.jsx)(G,{path:e.path,size:22})}),(0,B.jsx)(`button`,{className:`icon-btn sm`,"aria-label":`Options for ${e.name}`,onClick:t=>{t.stopPropagation();let n=t.currentTarget.getBoundingClientRect();C({x:n.left,y:n.bottom+4,p:e})},children:(0,B.jsx)(s,{size:14})})]}),(0,B.jsx)(`div`,{className:`card-name`,children:e.name}),(0,B.jsx)(`div`,{className:`card-path faint`,children:H(e.path)}),(0,B.jsx)(`div`,{className:`card-meta`,children:e.exists?e.ready?(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(`span`,{className:`faint`,children:[e.canvases,` `,e.canvases===1?`page`:`pages`,` · `,m(e.lastOpened,`long`)]}),e.running&&(0,B.jsxs)(`span`,{className:`live-tag`,children:[(0,B.jsx)(`span`,{className:`live-dot`}),` `,e.running.memory?`${e.running.memory} MB`:`open`]})]}):(0,B.jsxs)(`button`,{className:`btn primary sm-btn`,onClick:t=>{t.stopPropagation(),w(`/api/hub/setup`,{path:e.path})},children:[(0,B.jsx)(L,{size:13}),` Set up Truecanvas`]}):(0,B.jsx)(`span`,{className:`chip`,children:`Folder missing`})})]},e.path))}),r&&r.length>0&&(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`h2`,{children:`Found on this computer`}),(0,B.jsx)(`div`,{className:`found-list`,children:r.map(e=>(0,B.jsxs)(`div`,{className:`found-row`,children:[(0,B.jsx)(G,{path:e.path,size:16}),(0,B.jsx)(`span`,{className:`name`,children:e.name}),(0,B.jsx)(`span`,{className:`faint path`,children:H(e.path)}),(0,B.jsx)(`button`,{className:`btn outline`,onClick:async()=>{await V(`/api/hub/add`,{path:e.path}),n()},children:`Add`})]},e.path))})]})]}),S&&(0,B.jsx)(h,{x:S.x,y:S.y,onClose:()=>C(null),items:[...S.p.ready?[{label:`Open`,icon:(0,B.jsx)(a,{size:14}),onSelect:()=>t(S.p)}]:[],...S.p.ready?[]:[{label:`Set up Truecanvas`,icon:(0,B.jsx)(L,{size:14}),onSelect:()=>void w(`/api/hub/setup`,{path:S.p.path})}],...S.p.ready?[{label:`Pull requests…`,icon:(0,B.jsx)(_,{size:14}),onSelect:()=>f(S.p)}]:[],...S.p.running?[{label:`Stop app`,icon:(0,B.jsx)(N,{size:14}),onSelect:()=>void V(`/api/hub/close`,{path:S.p.path}).then(n)}]:[],`sep`,{label:`Remove from list`,icon:(0,B.jsx)(c,{size:14}),danger:!0,onSelect:()=>void V(`/api/hub/forget`,{path:S.p.path}).then(n)}]}),o===`open`&&(0,B.jsx)(Q,{onClose:()=>u(null),onPick:async e=>{let r=await V(`/api/hub/add`,{path:e});u(null),n(),r.ready&&t({path:r.path})}}),o===`clone`&&(0,B.jsx)($,{onClose:()=>u(null),onClone:async(e,t)=>{u(null),await w(`/api/hub/clone`,{repo:e,parent:t})}}),d&&(0,B.jsx)(ee,{project:d,onClose:()=>f(null),onOpened:()=>{let e=d;f(null),t(e)}}),o===`new`&&(0,B.jsx)(te,{onClose:()=>u(null),onCreate:async(e,t)=>{u(null),await w(`/api/hub/create`,{name:e,parent:t})}}),p&&(0,B.jsx)(ne,{job:p,onClose:e=>{v(null),n(),e&&t({path:e})}})]})}function Z({title:e,children:t,onClose:n,width:r=460}){return(0,B.jsx)(f,{title:e,width:r,onClose:n,children:t})}function Q({onClose:e,onPick:t}){let[n,r]=(0,z.useState)(`~/Github`),[i,a]=(0,z.useState)(null),[o,s]=(0,z.useState)(null),c=e=>void t(e).catch(e=>s(e.message)),[l,u]=(0,z.useState)(null);return(0,z.useEffect)(()=>{let e=!1,t=setTimeout(()=>{V(`/api/hub/ls?path=${encodeURIComponent(n)}`).then(t=>{e||(a(t),u(n),s(null))}).catch(t=>!e&&s(t.message))},150);return()=>{e=!0,clearTimeout(t)}},[n]),(0,B.jsxs)(Z,{title:`Open a project folder`,onClose:e,width:520,children:[(0,B.jsx)(`p`,{className:`muted`,children:`Pick the root of a Next.js or Vite app (the folder with its package.json).`}),(0,B.jsxs)(`div`,{className:`field`,children:[(0,B.jsx)(`span`,{className:`prefix`,children:(0,B.jsx)(k,{size:13})}),(0,B.jsx)(`input`,{autoFocus:!0,value:n,onChange:e=>r(e.target.value),onKeyDown:e=>e.key===`Enter`&&c(i&&l===n?i.path:n),spellCheck:!1})]}),(0,B.jsxs)(`div`,{className:`dir-list`,children:[i&&(0,B.jsxs)(`button`,{className:`dir-row`,onClick:()=>r(`${i.path}/..`),children:[(0,B.jsx)(k,{size:14,className:`faint`}),` ..`]}),i?.dirs.map(e=>(0,B.jsxs)(`button`,{className:`dir-row`,onClick:()=>r(`${i.path}/${e.name}`),onDoubleClick:()=>e.next&&c(`${i.path}/${e.name}`),children:[(0,B.jsx)(k,{size:14,className:e.next?``:`faint`}),(0,B.jsx)(`span`,{children:e.name}),e.next&&(0,B.jsx)(`span`,{className:`chip accent`,children:`App`})]},e.name)),o&&(0,B.jsx)(`div`,{className:`faint`,style:{padding:8},children:o})]}),(0,B.jsxs)(`div`,{className:`modal-actions`,children:[(0,B.jsx)(`button`,{className:`btn outline`,onClick:e,children:`Cancel`}),(0,B.jsxs)(`button`,{className:`btn primary`,onClick:()=>c(i?.path??n),children:[`Open `,i?H(i.path).split(`/`).pop():``]})]})]})}function $({onClose:e,onClone:t}){let[n,r]=(0,z.useState)(null),[i,a]=(0,z.useState)(``),[o,s]=(0,z.useState)(`~/Github`);(0,z.useEffect)(()=>{V(`/api/hub/github/repos`).then(r).catch(e=>r({gh:!1,error:e.message,repos:[]}))},[]);let c=/^(https?:|git@|ssh:|file:)/.test(i.trim())||/^[\w.-]+\/[\w.-]+$/.test(i.trim()),l=(n?.repos??[]).filter(e=>!i||`${e.nameWithOwner} ${e.description??``}`.toLowerCase().includes(i.toLowerCase()));return(0,B.jsxs)(Z,{title:`Clone from GitHub`,onClose:e,width:560,children:[(0,B.jsx)(`p`,{className:`muted`,children:`Clones the repo, installs its dependencies and sets up Truecanvas if it isn't there yet. Then it's one click to open.`}),(0,B.jsxs)(`div`,{className:`field`,children:[(0,B.jsx)(`span`,{className:`prefix`,children:(0,B.jsx)(g,{size:13})}),(0,B.jsx)(`input`,{autoFocus:!0,value:i,placeholder:`Search your repositories, or paste owner/name or a git URL`,onChange:e=>a(e.target.value),onKeyDown:e=>e.key===`Enter`&&c&&t(i.trim(),o),spellCheck:!1})]}),(0,B.jsxs)(`div`,{className:`dir-list`,style:{height:260},children:[n===null&&(0,B.jsx)(`div`,{className:`faint`,style:{padding:10},children:`Loading your repositories…`}),n&&!n.gh&&(0,B.jsxs)(`div`,{className:`faint`,style:{padding:10,lineHeight:1.5},children:[`The GitHub CLI isn't signed in, so your repositories can't be listed. Paste a git URL above, or run `,(0,B.jsx)(`span`,{className:`mono`,children:`gh auth login`}),` in a terminal.`]}),c&&!l.some(e=>e.nameWithOwner===i.trim())&&(0,B.jsxs)(`button`,{className:`dir-row`,onClick:()=>t(i.trim(),o),children:[(0,B.jsx)(x,{size:14}),(0,B.jsxs)(`span`,{children:[`Clone `,(0,B.jsx)(`strong`,{children:i.trim()})]})]}),l.map(e=>(0,B.jsxs)(`button`,{className:`dir-row repo-row`,onClick:()=>t(e.nameWithOwner,o),title:e.description??``,children:[e.isPrivate?(0,B.jsx)(v,{size:13,className:`faint`}):(0,B.jsx)(x,{size:13,className:`faint`}),(0,B.jsx)(`span`,{style:{fontWeight:500},children:e.nameWithOwner}),(0,B.jsx)(`span`,{className:`faint`,style:{marginLeft:`auto`,whiteSpace:`nowrap`},children:m(Date.parse(e.updatedAt),`long`)})]},e.nameWithOwner))]}),(0,B.jsxs)(`div`,{className:`field`,style:{marginTop:10},children:[(0,B.jsx)(`span`,{className:`prefix`,children:(0,B.jsx)(k,{size:13})}),(0,B.jsx)(`input`,{value:o,onChange:e=>s(e.target.value),"aria-label":`Clone into`,spellCheck:!1})]}),(0,B.jsx)(`div`,{className:`modal-actions`,style:{marginTop:12},children:(0,B.jsx)(`button`,{className:`btn outline`,onClick:e,children:`Cancel`})})]})}function ee({project:e,onClose:t,onOpened:n}){let[r,i]=(0,z.useState)(null),[a,s]=(0,z.useState)(null),[c,l]=(0,z.useState)(null);(0,z.useEffect)(()=>{V(`/api/hub/prs?path=${encodeURIComponent(e.path)}`).then(i).catch(e=>i({error:e.message,prs:[]}))},[e.path]);let u=async t=>{s(t),l(null);try{await V(`/api/hub/pr-checkout`,{path:e.path,number:String(t)}),n()}catch(e){l(e.message)}finally{s(null)}};return(0,B.jsxs)(Z,{title:`Pull requests · ${e.name}`,onClose:t,width:560,children:[(0,B.jsx)(`p`,{className:`muted`,children:`Open a pull request to see its design in Truecanvas: its branch is checked out and the canvases show that version.`}),(0,B.jsxs)(`div`,{className:`dir-list`,style:{height:280},children:[r===null&&(0,B.jsx)(`div`,{className:`faint`,style:{padding:10},children:`Loading…`}),r?.error&&(0,B.jsx)(`div`,{className:`faint`,style:{padding:10},children:r.error}),r&&!r.error&&r.prs.length===0&&(0,B.jsx)(`div`,{className:`faint`,style:{padding:10},children:`No open pull requests.`}),r?.prs.map(e=>(0,B.jsxs)(`button`,{className:`dir-row repo-row`,disabled:a!==null,onClick:()=>void u(e.number),children:[a===e.number?(0,B.jsx)(o,{size:14,className:`spin-working`}):(0,B.jsx)(_,{size:14,className:e.isDraft?`faint`:`pr-open`}),(0,B.jsxs)(`span`,{style:{fontWeight:500,overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`},children:[`#`,e.number,` `,e.title]}),(0,B.jsxs)(`span`,{className:`faint`,style:{marginLeft:`auto`,whiteSpace:`nowrap`},children:[e.author?.login,` · `,m(Date.parse(e.updatedAt),`long`)]})]},e.number))]}),c&&(0,B.jsx)(`div`,{className:`hub-error`,children:c}),(0,B.jsx)(`div`,{className:`modal-actions`,style:{marginTop:12},children:(0,B.jsx)(`button`,{className:`btn outline`,onClick:t,children:`Close`})})]})}function te({onClose:e,onCreate:t}){let[n,r]=(0,z.useState)(``),[i,a]=(0,z.useState)(`~/Github`),o=n.trim().toLowerCase().replace(/[^a-z0-9-_]+/g,`-`).replace(/^-+|-+$/g,``);return(0,B.jsxs)(Z,{title:`New project`,onClose:e,children:[(0,B.jsx)(`p`,{className:`muted`,children:`Creates a Next.js app with TypeScript and Tailwind, then sets up Truecanvas in it.`}),(0,B.jsxs)(`div`,{style:{display:`grid`,gap:8},children:[(0,B.jsxs)(`div`,{className:`field`,children:[(0,B.jsx)(`span`,{className:`prefix`,children:`Name`}),(0,B.jsx)(`input`,{autoFocus:!0,value:n,placeholder:`my-app`,onChange:e=>r(e.target.value),onKeyDown:e=>e.key===`Enter`&&o&&t(o,i)})]}),(0,B.jsxs)(`div`,{className:`field`,children:[(0,B.jsx)(`span`,{className:`prefix`,children:`In`}),(0,B.jsx)(`input`,{value:i,onChange:e=>a(e.target.value),spellCheck:!1})]}),o&&(0,B.jsx)(`div`,{className:`faint mono`,children:`${i.replace(/\/$/,``)}/${o}`})]}),(0,B.jsxs)(`div`,{className:`modal-actions`,style:{marginTop:16},children:[(0,B.jsx)(`button`,{className:`btn outline`,onClick:e,children:`Cancel`}),(0,B.jsx)(`button`,{className:`btn primary`,disabled:!o,onClick:()=>t(o,i),children:`Create project`})]})]})}function ne({job:e,onClose:t}){let[n,r]=(0,z.useState)(e),i=(0,z.useRef)(null);return(0,z.useEffect)(()=>{if(n.status!==`running`)return;let e=setInterval(()=>void V(`/api/hub/jobs/${n.id}`).then(r),700);return()=>clearInterval(e)},[n.id,n.status]),(0,z.useEffect)(()=>{i.current?.scrollTo({top:i.current.scrollHeight})},[n.log.length]),(0,z.useEffect)(()=>{if(n.status!==`done`||!n.result)return;let e=setTimeout(()=>t(n.result),700);return()=>clearTimeout(e)},[n.status,n.result]),(0,B.jsxs)(Z,{title:n.title,onClose:()=>n.status!==`running`&&t(),width:600,children:[(0,B.jsxs)(`div`,{className:`job-status`,children:[n.status===`running`?(0,B.jsx)(o,{size:16,className:`spin-working`}):n.status===`done`?(0,B.jsx)(`span`,{className:`live-dot`}):(0,B.jsx)(F,{size:16,className:`warn`}),(0,B.jsx)(`span`,{children:n.status===`running`?`Working… this can take a minute.`:n.status===`done`?`Done.`:`Something went wrong.`})]}),(0,B.jsx)(`pre`,{className:`job-log`,ref:i,children:n.log.slice(-120).join(`
2
- `)}),(0,B.jsx)(`div`,{className:`modal-actions`,children:n.status===`done`&&n.result?(0,B.jsx)(`button`,{className:`btn primary`,onClick:()=>t(n.result),children:`Opening…`}):(0,B.jsx)(`button`,{className:`btn outline`,disabled:n.status===`running`,onClick:()=>t(),children:`Close`})})]})}(0,R.createRoot)(document.getElementById(`root`)).render((0,B.jsx)(W,{}));