paneful 0.2.0 → 0.3.0

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.
@@ -237,24 +237,37 @@ function startServer(devMode, port) {
237
237
  }
238
238
  return best?.path ?? candidates[0];
239
239
  };
240
+ const respond = (resolved) => {
241
+ if (!resolved) {
242
+ res.json({ path: null });
243
+ return;
244
+ }
245
+ try {
246
+ const isDirectory = fs.statSync(resolved).isDirectory();
247
+ res.json({ path: resolved, isDirectory });
248
+ }
249
+ catch {
250
+ res.json({ path: resolved, isDirectory: false });
251
+ }
252
+ };
240
253
  if (process.platform === 'darwin') {
241
254
  execFile('mdfind', [`kMDItemFSName == '${name.replace(/'/g, "\\'")}'`], (err, stdout) => {
242
255
  if (err) {
243
- res.json({ path: null });
256
+ respond(null);
244
257
  return;
245
258
  }
246
259
  const candidates = stdout.trim().split('\n').filter(Boolean);
247
- res.json({ path: findBest(candidates) });
260
+ respond(findBest(candidates));
248
261
  });
249
262
  }
250
263
  else {
251
264
  execFile('locate', ['-l', '20', '-b', `\\${name}`], (err, stdout) => {
252
265
  if (err) {
253
- res.json({ path: null });
266
+ respond(null);
254
267
  return;
255
268
  }
256
269
  const candidates = stdout.trim().split('\n').filter(Boolean);
257
- res.json({ path: findBest(candidates) });
270
+ respond(findBest(candidates));
258
271
  });
259
272
  }
260
273
  });
@@ -275,7 +275,7 @@ WARNING: This link could potentially be dangerous`)){const o=window.open();if(o)
275
275
  bg-accent hover:bg-accent/80
276
276
  text-white rounded-lg transition-colors
277
277
  `,children:"Launch"})]})]})]})}):null}function xp(){const[e,t]=Y.useState(!1),[r,i]=Y.useState(!1),[n,h]=Y.useState(!1),[m,a]=Y.useState(null),[c,f]=Y.useState(null),[g,d]=Y.useState(null),[_,S]=Y.useState(!1),[w,p]=Y.useState(null);Y.useEffect(()=>{fetch("/api/version").then(F=>F.json()).then(F=>{F.latest&&kp(F.latest,F.current)&&p({current:F.current,latest:F.latest})}).catch(()=>{})},[]);const u=ye(F=>F.projects),o=ye(F=>F.activeProjectId),s=ye(F=>F.setActiveProject),l=ye(F=>F.addProject),v=ye(F=>F.removeProject),C=ye(F=>F.addTerminalToProject),x=le(F=>F.sidebarOpen),k=le(F=>F.toggleSidebar),y=le(F=>F.connectionStatus),b=ii(F=>F.favourites);ii(F=>F.addFavourite);const R=ii(F=>F.updateFavourite),A=ii(F=>F.removeFavourite),B=(F,I)=>{const L=crypto.randomUUID();l({id:L,name:F,cwd:I,terminalIds:[]}),Ke({type:"project:create",projectId:L,name:F,cwd:I}),s(L)},T=F=>{tc(F)},j=F=>{T(F),Ke({type:"project:remove",projectId:F}),re.getState().removeProjectLayout(F),v(F)},z=F=>{if(!o||!u[o])return;tc(o);const L=F.slots.map(()=>crypto.randomUUID());F.slots.forEach((H,X)=>{H.command.trim()&&q_(L[X],H.command+`
278
- `)});const U=Ai(L,F.preset);re.getState().setLayout(o,U),L.forEach(H=>{C(o,H)}),L.length>0&&le.getState().setFocusedTerminal(L[0])},K=F=>{if(!o)return;const I=re.getState().getLayout(o);me(I).length>0?(f(F),h(!0)):z(F)},q=F=>{a(F),i(!0)},N=(F,I,L)=>{m&&R(m.id,{name:F,preset:I,slots:L}),a(null)},E=Y.useCallback(F=>{F.dataTransfer.types.includes("Files")&&(F.preventDefault(),F.dataTransfer.dropEffect="copy",S(!0))},[]),D=Y.useCallback(F=>{F.currentTarget.contains(F.relatedTarget)||S(!1)},[]),P=Y.useCallback(F=>{if(S(!1),!F.dataTransfer.types.includes("Files")||F.dataTransfer.files.length===0)return;F.preventDefault(),F.stopPropagation();const I=F.dataTransfer.files[0];fetch("/api/resolve-path",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:I.name,size:I.size,lastModified:I.lastModified})}).then(L=>L.json()).then(L=>{const U=L.path||I.name,H=U.split("/").pop()||I.name;d({name:H,cwd:U}),t(!0)}).catch(()=>{d({name:I.name,cwd:"~"}),t(!0)})},[]);if(!x)return null;const O=Object.values(u),W=Object.values(b),J=(o?u[o]:null)?me(re.getState().getLayout(o)).length:0;return M.jsxs("div",{className:`w-56 flex-shrink-0 bg-[var(--surface-1)] border-r border-[var(--border)] flex flex-col h-full ${_?"ring-2 ring-inset ring-[var(--accent)]":""}`,onDragOver:E,onDragLeave:D,onDrop:P,children:[M.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-b border-[var(--border)]",children:[M.jsxs("div",{className:"flex items-center gap-2",children:[M.jsx("span",{className:"text-sm font-semibold tracking-tight text-[var(--text-primary)]",children:"Paneful"}),M.jsx("span",{className:`w-1.5 h-1.5 rounded-full ${y==="connected"?"bg-[var(--success)]":y==="connecting"?"bg-yellow-500 animate-pulse":"bg-[var(--danger)]"}`,title:y})]}),M.jsx("button",{onClick:k,className:"p-1 rounded text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)] transition-colors",title:"Hide sidebar",children:M.jsx(hp,{size:14})})]}),M.jsx("div",{className:"flex-1 overflow-y-auto py-2",children:O.length===0&&W.length===0?M.jsx("div",{className:"px-4 py-8 text-center",children:M.jsx("p",{className:"text-xs text-[var(--text-muted)]",children:"No projects yet"})}):M.jsxs(M.Fragment,{children:[O.map(F=>M.jsx(vp,{project:F,isActive:F.id===o,onClick:()=>s(F.id),onKill:()=>T(F.id),onRemove:()=>j(F.id)},F.id)),M.jsx(yp,{favourites:W,onLaunch:K,onEdit:q,onDelete:A})]})}),M.jsx("div",{className:"p-2 border-t border-[var(--border)]",children:M.jsxs("button",{onClick:()=>t(!0),className:`
278
+ `)});const U=Ai(L,F.preset);re.getState().setLayout(o,U),L.forEach(H=>{C(o,H)}),L.length>0&&le.getState().setFocusedTerminal(L[0])},K=F=>{if(!o)return;const I=re.getState().getLayout(o);me(I).length>0?(f(F),h(!0)):z(F)},q=F=>{a(F),i(!0)},N=(F,I,L)=>{m&&R(m.id,{name:F,preset:I,slots:L}),a(null)},E=Y.useCallback(F=>{F.dataTransfer.types.includes("Files")&&(F.preventDefault(),F.dataTransfer.dropEffect="copy",S(!0))},[]),D=Y.useCallback(F=>{F.currentTarget.contains(F.relatedTarget)||S(!1)},[]),P=Y.useCallback(F=>{if(S(!1),!F.dataTransfer.types.includes("Files")||F.dataTransfer.files.length===0)return;F.preventDefault(),F.stopPropagation();const I=F.dataTransfer.files[0];fetch("/api/resolve-path",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:I.name,size:I.size,lastModified:I.lastModified})}).then(L=>L.json()).then(L=>{if(!L.path||!L.isDirectory)return;const U=L.path,H=U.split("/").pop()||I.name;d({name:H,cwd:U}),t(!0)}).catch(()=>{})},[]);if(!x)return null;const O=Object.values(u),W=Object.values(b),J=(o?u[o]:null)?me(re.getState().getLayout(o)).length:0;return M.jsxs("div",{className:`w-56 flex-shrink-0 bg-[var(--surface-1)] border-r border-[var(--border)] flex flex-col h-full ${_?"ring-2 ring-inset ring-[var(--accent)]":""}`,onDragOver:E,onDragLeave:D,onDrop:P,children:[M.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-b border-[var(--border)]",children:[M.jsxs("div",{className:"flex items-center gap-2",children:[M.jsx("span",{className:"text-sm font-semibold tracking-tight text-[var(--text-primary)]",children:"Paneful"}),M.jsx("span",{className:`w-1.5 h-1.5 rounded-full ${y==="connected"?"bg-[var(--success)]":y==="connecting"?"bg-yellow-500 animate-pulse":"bg-[var(--danger)]"}`,title:y})]}),M.jsx("button",{onClick:k,className:"p-1 rounded text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--surface-3)] transition-colors",title:"Hide sidebar",children:M.jsx(hp,{size:14})})]}),M.jsx("div",{className:"flex-1 overflow-y-auto py-2",children:O.length===0&&W.length===0?M.jsx("div",{className:"px-4 py-8 text-center",children:M.jsx("p",{className:"text-xs text-[var(--text-muted)]",children:"No projects yet"})}):M.jsxs(M.Fragment,{children:[O.map(F=>M.jsx(vp,{project:F,isActive:F.id===o,onClick:()=>s(F.id),onKill:()=>T(F.id),onRemove:()=>j(F.id)},F.id)),M.jsx(yp,{favourites:W,onLaunch:K,onEdit:q,onDelete:A})]})}),M.jsx("div",{className:"p-2 border-t border-[var(--border)]",children:M.jsxs("button",{onClick:()=>t(!0),className:`
279
279
  w-full flex items-center justify-center gap-1.5
280
280
  px-3 py-2 text-xs
281
281
  text-[var(--text-secondary)] hover:text-[var(--text-primary)]
@@ -8,7 +8,7 @@
8
8
  <link rel="icon" type="image/png" sizes="192x192" href="/icon-192.png" />
9
9
  <link rel="apple-touch-icon" href="/icon-192.png" />
10
10
  <title>Paneful</title>
11
- <script type="module" crossorigin src="/assets/index-C9HSp7rK.js"></script>
11
+ <script type="module" crossorigin src="/assets/index-CrVFgHgr.js"></script>
12
12
  <link rel="stylesheet" crossorigin href="/assets/index-BfmevawE.css">
13
13
  </head>
14
14
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paneful",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Browser-based terminal multiplexer with tmux-style pane management",
5
5
  "type": "module",
6
6
  "bin": {