paneful 0.9.11 → 0.9.12

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.
@@ -459,7 +459,7 @@ void main() {
459
459
  bg-accent hover:bg-accent/80
460
460
  text-white rounded-lg transition-colors
461
461
  `,children:"Launch"})]})]})]})}):null}function Pk(){const[t,e]=O.useState(!1),[i,r]=O.useState(!1),[s,n]=O.useState(!1),[o,a]=O.useState(null),[h,l]=O.useState(null),[c,u]=O.useState(null),[d,f]=O.useState(!1),[p,m]=O.useState(null);O.useEffect(()=>{fetch("/api/version").then(A=>A.json()).then(A=>{A.latest&&Dk(A.latest,A.current)&&m({current:A.current,latest:A.latest})}).catch(()=>{})},[]);const x=ae(A=>A.projects),_=ae(A=>A.activeProjectId),g=ae(A=>A.setActiveProject),S=ae(A=>A.addProject),y=ae(A=>A.removeProject),L=ae(A=>A.addTerminalToProject),P=F(A=>A.sidebarOpen),N=F(A=>A.sidebarWidth),B=F(A=>A.setSidebarWidth),U=F(A=>A.toggleSidebar),W=F(A=>A.connectionStatus),V=O.useRef(!1),C=F(A=>A.editorSyncEnabled),w=F(A=>A.toggleEditorSync),b=F(A=>A.gpuRendering),k=F(A=>A.toggleGpuRendering),M=F(A=>A.theme),T=F(A=>A.cycleTheme),E=oe(A=>A.activePorts),R=oe(A=>A.claudeStatus),D=oe(A=>A.gitBranches),j=oe(A=>A.editorNeedsAccessibility),G=gr(A=>A.favourites);gr(A=>A.addFavourite);const q=gr(A=>A.updateFavourite),de=gr(A=>A.removeFavourite),Q=F(A=>A.pendingFavouriteLaunchId),le=F(A=>A.clearPendingFavouriteLaunch),[Z,re]=O.useState(null),[fe,rt]=O.useState(null),oi=O.useCallback(()=>{fetch("/api/cleanup-projects").then(A=>A.json()).then(A=>{A.stale.length===0?(re([]),setTimeout(()=>re(null),2e3)):re(A.stale)}).catch(()=>{})},[]),Ut=O.useCallback(()=>{fetch("/api/cleanup-projects",{method:"POST"}).then(A=>A.json()).then(A=>{for(const Me of Object.values(x))A.removed.includes(Me.name)&&(X.getState().removeProjectLayout(Me.id),y(Me.id));re(null)}).catch(()=>{})},[x,y]),Nt=(A,Me)=>{const Fe=Object.values(x).find(ai=>ai.cwd===Me);if(Fe){g(Fe.id);return}const dt=crypto.randomUUID();S({id:dt,name:A,cwd:Me,terminalIds:[]}),me({type:"project:create",projectId:dt,name:A,cwd:Me}),g(dt)},te=A=>{Kp(A)},Dr=A=>{rt(A)},$l=()=>{fe&&(te(fe),me({type:"project:remove",projectId:fe}),X.getState().removeProjectLayout(fe),y(fe),rt(null))},Br=O.useCallback(A=>{if(!_||!x[_])return;Kp(_);const Fe=A.slots.map(()=>crypto.randomUUID());A.slots.forEach((ai,Il)=>{ai.command.trim()&&Q5(Fe[Il],ai.command+`
462
- `)});const dt=rs(Fe,A.preset);X.getState().setLayout(_,dt),Fe.forEach(ai=>{L(_,ai)}),Fe.length>0&&F.getState().setFocusedTerminal(Fe[0])},[_,x,L]),cs=O.useCallback(A=>{if(!_)return;const Me=X.getState().getLayout(_);ue(Me).length>0?(l(A),n(!0)):Br(A)},[_,Br]);O.useEffect(()=>{if(!Q)return;const A=G[Q];le(),A&&cs(A)},[Q,G,le,cs]);const Mo=A=>{a(A),r(!0)},Ol=(A,Me,Fe)=>{o&&q(o.id,{name:A,preset:Me,slots:Fe}),a(null)},o1=O.useCallback(A=>{A.dataTransfer.types.includes("Files")&&(A.preventDefault(),A.dataTransfer.dropEffect="copy",f(!0))},[]),a1=O.useCallback(A=>{A.currentTarget.contains(A.relatedTarget)||f(!1)},[]),l1=O.useCallback(A=>{A.preventDefault(),V.current=!0;const Me=dt=>{requestAnimationFrame(()=>B(dt.clientX))},Fe=()=>{V.current=!1,window.removeEventListener("mousemove",Me),window.removeEventListener("mouseup",Fe),document.body.style.cursor="",document.body.style.userSelect=""};document.body.style.cursor="col-resize",document.body.style.userSelect="none",window.addEventListener("mousemove",Me),window.addEventListener("mouseup",Fe)},[B]),h1=O.useCallback(A=>{if(f(!1),!A.dataTransfer.types.includes("Files")||A.dataTransfer.files.length===0)return;A.preventDefault(),A.stopPropagation();const Me=s1();if(Me&&Me.length>0){const dt=Me[0],ai=dt.split("/").pop()||A.dataTransfer.files[0].name;u({name:ai,cwd:dt}),e(!0);return}const Fe=A.dataTransfer.files[0];fetch("/api/resolve-path",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:Fe.name,size:Fe.size,lastModified:Fe.lastModified})}).then(dt=>dt.json()).then(dt=>{if(!dt.path||!dt.isDirectory)return;const ai=dt.path,Il=ai.split("/").pop()||Fe.name;u({name:Il,cwd:ai}),e(!0)}).catch(()=>{})},[]);if(!P)return null;const tf=Object.values(x),rf=Object.values(G),c1=(_?x[_]:null)?ue(X.getState().getLayout(_)).length:0;return v.jsxs("div",{className:`relative flex-shrink-0 bg-[var(--surface-1)] border-r border-[var(--border)] flex flex-col h-full ${d?"ring-2 ring-inset ring-[var(--accent)]":""}`,style:{width:N},onDragOver:o1,onDragLeave:a1,onDrop:h1,children:[v.jsx("div",{className:"absolute top-0 right-0 w-1 h-full cursor-col-resize z-10 hover:bg-[var(--accent)] active:bg-[var(--accent)] opacity-0 hover:opacity-40 active:opacity-60 transition-opacity",onMouseDown:l1}),v.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-b border-[var(--border)]",children:[v.jsxs("div",{className:"flex items-center gap-2",children:[v.jsx("span",{className:"text-sm font-semibold tracking-tight text-[var(--text-primary)]",children:"Paneful"}),v.jsx("span",{className:`w-1.5 h-1.5 rounded-full ${W==="connected"?"bg-[var(--success)]":W==="connecting"?"bg-yellow-500 animate-pulse":"bg-[var(--danger)]"}`,title:W})]}),v.jsxs("div",{className:"flex items-center gap-1",children:[v.jsx("button",{onClick:T,className:"p-1 rounded text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)] transition-colors",title:`Theme: ${M}. Click to cycle.`,children:M==="light"?v.jsx(wk,{size:14}):M==="dark"?v.jsx(vk,{size:14}):v.jsx(gk,{size:14})}),v.jsxs("button",{onClick:()=>{w(),me({type:"editor:sync",enabled:!C})},className:`relative p-1 rounded transition-colors ${C?"text-[var(--accent)] hover:bg-[var(--surface-3)]":"text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)]"}`,title:C&&j?"Editor sync needs Accessibility permission. Go to System Settings → Privacy & Security → Accessibility and add paneful-editor-helper (in ~/.paneful). If it's already listed, try toggling it off and on, or removing and re-adding it.":C?"Editor sync ON — auto-switches project based on your active editor. Click to disable.":"Editor sync OFF — click to enable. Requires Accessibility permission for paneful-editor-helper (in ~/.paneful). Go to System Settings → Privacy & Security → Accessibility. After updating paneful, you may need to remove and re-add it.",children:[v.jsx(cl,{size:14}),C&&j&&v.jsx("span",{className:"absolute -top-0.5 -right-0.5 w-2 h-2 rounded-full bg-yellow-500"})]}),v.jsx("button",{onClick:k,className:`p-1 rounded transition-colors ${b?"text-[var(--accent)] hover:bg-[var(--surface-3)]":"text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)]"}`,title:b?"GPU rendering ON — terminals use WebGL. Click to switch to DOM renderer.":"GPU rendering OFF — terminals use DOM renderer. Click to enable WebGL.",children:v.jsx(r1,{size:14})}),v.jsx("button",{onClick:oi,className:"p-1 rounded text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)] transition-colors",title:"Clean up stale projects",children:v.jsx(ak,{size:14})}),v.jsx("button",{onClick:U,className:"p-1 rounded text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)] transition-colors",title:"Hide sidebar",children:v.jsx(t1,{size:14})})]})]}),v.jsx("div",{className:"flex-1 overflow-y-auto py-2",children:tf.length===0&&rf.length===0?v.jsx("div",{className:"px-4 py-8 text-center",children:v.jsx("p",{className:"text-xs text-[var(--text-muted)]",children:"No projects yet"})}):v.jsxs(v.Fragment,{children:[tf.map(A=>{var Me;return v.jsx(bk,{project:A,isActive:A.id===_,hasActivePorts:(((Me=E[A.id])==null?void 0:Me.length)??0)>0,claudeStatus:R[A.id]??null,gitStatus:D[A.id]??null,onClick:()=>g(A.id),onKill:()=>te(A.id),onRemove:()=>Dr(A.id)},A.id)}),v.jsx(Mk,{favourites:rf,onLaunch:cs,onEdit:Mo,onDelete:de})]})}),v.jsxs("div",{className:"mx-3 mb-2 px-3 py-2.5 rounded-lg bg-[var(--surface-2)] text-[10px] text-[var(--text-muted)] leading-relaxed flex flex-col items-center gap-1.5 text-center",children:[v.jsx(pk,{size:12,className:"text-yellow-500"}),"Drag a folder into this sidebar to create a project"]}),v.jsx("div",{className:"p-2 border-t border-[var(--border)]",children:v.jsxs("button",{onClick:()=>e(!0),className:`
462
+ `)});const dt=rs(Fe,A.preset);X.getState().setLayout(_,dt),Fe.forEach(ai=>{L(_,ai)}),Fe.length>0&&F.getState().setFocusedTerminal(Fe[0])},[_,x,L]),cs=O.useCallback(A=>{if(!_)return;const Me=X.getState().getLayout(_);ue(Me).length>0?(l(A),n(!0)):Br(A)},[_,Br]);O.useEffect(()=>{if(!Q)return;const A=G[Q];le(),A&&cs(A)},[Q,G,le,cs]);const Mo=A=>{a(A),r(!0)},Ol=(A,Me,Fe)=>{o&&q(o.id,{name:A,preset:Me,slots:Fe}),a(null)},o1=O.useCallback(A=>{A.dataTransfer.types.includes("Files")&&(A.preventDefault(),A.dataTransfer.dropEffect="copy",f(!0))},[]),a1=O.useCallback(A=>{A.currentTarget.contains(A.relatedTarget)||f(!1)},[]),l1=O.useCallback(A=>{A.preventDefault(),V.current=!0;const Me=dt=>{requestAnimationFrame(()=>B(dt.clientX))},Fe=()=>{V.current=!1,window.removeEventListener("mousemove",Me),window.removeEventListener("mouseup",Fe),document.body.style.cursor="",document.body.style.userSelect=""};document.body.style.cursor="col-resize",document.body.style.userSelect="none",window.addEventListener("mousemove",Me),window.addEventListener("mouseup",Fe)},[B]),h1=O.useCallback(A=>{if(f(!1),!A.dataTransfer.types.includes("Files")||A.dataTransfer.files.length===0)return;A.preventDefault(),A.stopPropagation();const Me=s1();if(Me&&Me.length>0){const dt=Me[0],ai=dt.split("/").pop()||A.dataTransfer.files[0].name;u({name:ai,cwd:dt}),e(!0);return}const Fe=A.dataTransfer.files[0];fetch("/api/resolve-path",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:Fe.name,size:Fe.size,lastModified:Fe.lastModified})}).then(dt=>dt.json()).then(dt=>{if(!dt.path||!dt.isDirectory)return;const ai=dt.path,Il=ai.split("/").pop()||Fe.name;u({name:Il,cwd:ai}),e(!0)}).catch(()=>{})},[]);if(!P)return null;const tf=Object.values(x),rf=Object.values(G),c1=(_?x[_]:null)?ue(X.getState().getLayout(_)).length:0;return v.jsxs("div",{className:`relative flex-shrink-0 bg-[var(--surface-1)] border-r border-[var(--border)] flex flex-col h-full ${d?"ring-2 ring-inset ring-[var(--accent)]":""}`,style:{width:N},onDragOver:o1,onDragLeave:a1,onDrop:h1,children:[v.jsx("div",{className:"absolute top-0 right-0 w-1 h-full cursor-col-resize z-10 hover:bg-[var(--accent)] active:bg-[var(--accent)] opacity-0 hover:opacity-40 active:opacity-60 transition-opacity",onMouseDown:l1}),v.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-b border-[var(--border)]",children:[v.jsxs("div",{className:"flex items-center gap-2",children:[v.jsx("span",{className:"text-sm font-semibold tracking-tight text-[var(--text-primary)]",children:"Paneful"}),v.jsx("span",{className:`w-1.5 h-1.5 rounded-full ${W==="connected"?"bg-[var(--success)]":W==="connecting"?"bg-yellow-500 animate-pulse":"bg-[var(--danger)]"}`,title:W})]}),v.jsxs("div",{className:"flex items-center gap-1",children:[v.jsx("button",{onClick:T,className:"p-1 rounded text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)] transition-colors",title:`Theme: ${M}. Click to cycle.`,children:M==="light"?v.jsx(wk,{size:14}):M==="dark"?v.jsx(vk,{size:14}):v.jsx(gk,{size:14})}),v.jsxs("button",{onClick:()=>{w(),me({type:"editor:sync",enabled:!C})},className:`relative p-1 rounded transition-colors ${C?"text-[var(--accent)] hover:bg-[var(--surface-3)]":"text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)]"}`,title:C&&j?"Editor sync needs Accessibility permission. Go to System Settings → Privacy & Security → Accessibility and add the app you launched paneful from (e.g. Paneful, Terminal, iTerm, VS Code, Cursor). If already listed, try toggling it off and on, or removing and re-adding it.":C?"Editor sync ON — auto-switches project based on your active editor. Click to disable.":"Editor sync OFF — click to enable. Requires Accessibility permission for the app you launched paneful from (e.g. Paneful, Terminal, VS Code, Cursor) in System Settings → Privacy & Security → Accessibility. After updating, you may need to remove and re-add it.",children:[v.jsx(cl,{size:14}),C&&j&&v.jsx("span",{className:"absolute -top-0.5 -right-0.5 w-2 h-2 rounded-full bg-yellow-500"})]}),v.jsx("button",{onClick:k,className:`p-1 rounded transition-colors ${b?"text-[var(--accent)] hover:bg-[var(--surface-3)]":"text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)]"}`,title:b?"GPU rendering ON — terminals use WebGL. Click to switch to DOM renderer.":"GPU rendering OFF — terminals use DOM renderer. Click to enable WebGL.",children:v.jsx(r1,{size:14})}),v.jsx("button",{onClick:oi,className:"p-1 rounded text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)] transition-colors",title:"Clean up stale projects",children:v.jsx(ak,{size:14})}),v.jsx("button",{onClick:U,className:"p-1 rounded text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)] transition-colors",title:"Hide sidebar",children:v.jsx(t1,{size:14})})]})]}),v.jsx("div",{className:"flex-1 overflow-y-auto py-2",children:tf.length===0&&rf.length===0?v.jsx("div",{className:"px-4 py-8 text-center",children:v.jsx("p",{className:"text-xs text-[var(--text-muted)]",children:"No projects yet"})}):v.jsxs(v.Fragment,{children:[tf.map(A=>{var Me;return v.jsx(bk,{project:A,isActive:A.id===_,hasActivePorts:(((Me=E[A.id])==null?void 0:Me.length)??0)>0,claudeStatus:R[A.id]??null,gitStatus:D[A.id]??null,onClick:()=>g(A.id),onKill:()=>te(A.id),onRemove:()=>Dr(A.id)},A.id)}),v.jsx(Mk,{favourites:rf,onLaunch:cs,onEdit:Mo,onDelete:de})]})}),v.jsxs("div",{className:"mx-3 mb-2 px-3 py-2.5 rounded-lg bg-[var(--surface-2)] text-[10px] text-[var(--text-muted)] leading-relaxed flex flex-col items-center gap-1.5 text-center",children:[v.jsx(pk,{size:12,className:"text-yellow-500"}),"Drag a folder into this sidebar to create a project"]}),v.jsx("div",{className:"p-2 border-t border-[var(--border)]",children:v.jsxs("button",{onClick:()=>e(!0),className:`
463
463
  w-full flex items-center justify-center gap-1.5
464
464
  px-3 py-2 text-xs
465
465
  text-[var(--text-secondary)] hover:text-[var(--text-primary)]
@@ -15,7 +15,7 @@
15
15
  document.documentElement.setAttribute('data-theme', t);
16
16
  })();
17
17
  </script>
18
- <script type="module" crossorigin src="/assets/index-DevYzBax.js"></script>
18
+ <script type="module" crossorigin src="/assets/index-B7n_Za-d.js"></script>
19
19
  <link rel="stylesheet" crossorigin href="/assets/index-D4UARMNH.css">
20
20
  </head>
21
21
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paneful",
3
- "version": "0.9.11",
3
+ "version": "0.9.12",
4
4
  "description": "A fast, GPU-accelerated terminal multiplexer in your browser or as a native macOS app. Split panes, organize projects, sync with your editor, detect AI agents.",
5
5
  "type": "module",
6
6
  "bin": {