truecanvas 0.6.4 → 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.
- package/README.md +1 -1
- package/dist/{chunk-56Z2KSBF.js → chunk-O6YS366Z.js} +71 -7
- package/dist/{chunk-FJO64PGM.js → chunk-S5PJFVUC.js} +14 -3
- package/dist/cli.js +396 -174
- package/dist/editor/assets/{Menu-ikkNcA3s.css → Menu-1oiiMScp.css} +1 -1
- package/dist/editor/assets/hub-JHnH5D_d.js +2 -0
- package/dist/editor/assets/main-NN-va8GV.js +27 -0
- package/dist/editor/hub.html +3 -3
- package/dist/editor/index.html +3 -3
- package/dist/hub.d.ts +1 -0
- package/dist/hub.js +1 -1
- package/dist/share/index.d.ts +1 -1
- package/dist/share/index.js +1 -1
- package/package.json +1 -1
- package/dist/editor/assets/hub-C_YkICvy.js +0 -2
- package/dist/editor/assets/main-Dx3BpXRE.js +0 -27
- /package/dist/editor/assets/{Menu-TTrH9CSM.js → Menu-BCzLjvGk.js} +0 -0
package/dist/share/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* frozen frames out at their canvas positions, with pan and zoom (drag,
|
|
4
4
|
* wheel, pinch, keys). Frames are sandboxed iframes without scripts, under a
|
|
5
5
|
* transparent layer that takes every pointer event. When the version has a
|
|
6
|
-
* live site, each frame gets a "
|
|
6
|
+
* live site, each frame gets a "Full screen" button: the real site in a
|
|
7
7
|
* device-sized window, scripts and animations included, on its own origin.
|
|
8
8
|
* Self-contained: no
|
|
9
9
|
* build step, no dependencies, so the same file works locally and on a
|
package/dist/share/index.js
CHANGED
package/package.json
CHANGED
|
@@ -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,{}));
|