tmux-weblink 1.1.2 → 1.1.4
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{a as
|
|
2
|
-
<span>${
|
|
3
|
-
<button class="session-edit-btn" data-session="${
|
|
4
|
-
`,a.addEventListener("click",
|
|
1
|
+
import{a as R}from"./chunk-O3DBTEWH.js";var g=window.__TMUX_WEB_SHELL__,i=null,r=null,V="sessions",p="",C="",x="",S="",l=document.getElementById("sidebar-content"),E=document.getElementById("main-placeholder"),y=document.getElementById("terminal-container"),I=document.getElementById("file-editor"),$=document.getElementById("fe-path"),o=document.getElementById("fe-status"),L=document.getElementById("fe-content"),u=document.getElementById("fe-save"),J=document.getElementById("fe-delete"),U=document.getElementById("fe-back"),N=document.getElementById("fe-new-name"),q=document.getElementById("fe-new-btn"),M=document.getElementById("settings-backdrop"),j=document.getElementById("settings-popover"),O=document.querySelector(".sidebar");function A(){return window.matchMedia("(max-width: 640px)").matches}function z(){A()&&O.classList.add("collapsed")}function _(){O.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{_(),F("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{_(),F("files")});function F(e){V=e,document.querySelectorAll(".mode-btn").forEach(n=>n.classList.remove("active"));let t=document.getElementById(e==="sessions"?"mode-sessions":"mode-files");t&&t.classList.add("active"),e==="sessions"?b():W()}async function b(){l.innerHTML='<div class="sidebar-section-label">Sessions</div><button class="new-session-sidebar-btn" id="ns-btn">+ New Session</button>';try{let t=(await(await fetch("/api/sidebar/sessions")).json()).recent||[];for(let n of t){let a=document.createElement("div");a.className="session-item"+(n.name===r?" active":""),a.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${n.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
|
|
2
|
+
<span>${w(n.name)}</span>
|
|
3
|
+
<button class="session-edit-btn" data-session="${w(n.name)}" title="Edit session"><svg viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg></button>
|
|
4
|
+
`,a.addEventListener("click",f=>{f.target.closest(".session-edit-btn")||H(n.name)}),l.appendChild(a);let s=a.querySelector(".session-edit-btn");s&&s.addEventListener("click",f=>{f.stopPropagation(),Q(n.name,s)})}}catch{l.innerHTML+='<div class="file-tree-empty">Failed to load sessions</div>'}let e=document.getElementById("ns-btn");e&&e.addEventListener("click",()=>document.getElementById("new-session-modal")?.classList.add("open"))}function w(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}async function H(e){if(!(r===e&&i)){I.style.display="none",E.style.display="none",y.style.display="",y.classList.add("terminal-pending"),z(),i&&(i.destroy(),i=null),r=e;try{i=await R(y,e,{terminal:g.terminal,scrollback:g.scrollback,theme:g.theme,renderer:g.renderer})}catch(t){console.error("[shell] terminal init failed:",t);let n=t&&typeof t=="object"&&"message"in t?t.message:String(t);y.textContent="Failed to open terminal for "+e+": "+n,y.classList.remove("terminal-pending")}}}var T=[];function W(){if(T=g.fsRoots||[],T.length===0){if(r){K(r);return}l.innerHTML='<div class="file-tree-info">Open a session first, then switch to Files to browse its directory.</div>';return}l.innerHTML="";for(let e of T){let t=document.createElement("div");t.className="file-tree-item",t.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${w(e)}`,t.addEventListener("click",()=>v(e)),l.appendChild(t)}}async function K(e){l.innerHTML='<div class="file-tree-empty">Loading...</div>';try{let t=await(await fetch("/api/fs/session-path?session="+encodeURIComponent(e))).json();t.path?v(t.path):l.innerHTML='<div class="file-tree-info">Could not determine session directory.</div>'}catch{l.innerHTML='<div class="file-tree-error">Failed to get session directory</div>'}}async function v(e){p=e,l.innerHTML='<div class="file-tree-empty">Loading...</div>';try{let t=await(await fetch("/api/fs/list?path="+encodeURIComponent(e))).json();l.innerHTML="";let n=X(e);if(n&&!T.some(s=>e===s)){let s=document.createElement("div");s.className="file-tree-item",s.innerHTML="..",s.addEventListener("click",()=>v(n)),l.appendChild(s)}if(t.dirs)for(let s of t.dirs){let f=s.split("/").pop()||s.split("\\").pop(),c=document.createElement("div");c.className="file-tree-item",c.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${w(f)}`,c.addEventListener("click",()=>v(s)),l.appendChild(c)}else l.innerHTML="";let a=t.files||[];for(let s of a){let f=s.split("/").pop()||s.split("\\").pop(),c=document.createElement("div");c.className="file-tree-item file",c.innerHTML=`<span class="file-icon">\u{1F4C4}</span> ${w(f)}`,c.addEventListener("click",()=>Z(s)),l.appendChild(c)}}catch{l.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function X(e){let t=e.lastIndexOf("/");return t<=0?null:e.substring(0,t)}async function Z(e){C=e,y.style.display="none",i&&(i.destroy(),i=null,r=null),z(),E.style.display="none",I.style.display="flex",$.textContent=e,o.textContent="Loading...",u.style.display="none";try{let t=await fetch("/api/file?path="+encodeURIComponent(e));if(!t.ok){let a=await t.json();o.textContent=a.error||"Failed to load",L.value="";return}let n=await t.json();L.value=n.content,x=n.content,S=n.content,o.textContent=n.size+" bytes",u.style.display=""}catch{o.textContent="Failed to load",L.value=""}}L.addEventListener("input",()=>{x=L.value}),u.addEventListener("click",async()=>{u.textContent="Saving...",u.disabled=!0;try{let e=await fetch("/api/file",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:C,content:x})});if(!e.ok){let t=await e.json();o.textContent=t.error||"Save failed";return}S=x,o.textContent="Saved"}catch{o.textContent="Save failed"}finally{u.disabled=!1,u.textContent="Save"}}),J.addEventListener("click",async()=>{if(confirm("Delete "+C+"?"))try{let e=await fetch("/api/file/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:C})});if(!e.ok){let t=await e.json();o.textContent=t.error||"Delete failed";return}I.style.display="none",E.style.display="flex",p&&v(p)}catch{o.textContent="Delete failed"}}),U.addEventListener("click",()=>{I.style.display="none",E.style.display="flex",p&&v(p)}),q.addEventListener("click",async()=>{let e=N.value.trim();if(!e)return;let t=p+"/"+e;try{let n=await fetch("/api/file/touch",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!n.ok){let a=await n.json();o.textContent=a.error||"Create failed";return}N.value="",p&&v(p)}catch{o.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{let e=j.classList.toggle("open");M.classList.toggle("open",e)}),M.addEventListener("click",()=>{j.classList.remove("open"),M.classList.remove("open")});var h="",k=document.createElement("div");k.className="session-popover-backdrop",document.body.appendChild(k);var m=document.createElement("div");m.id="session-popover",m.className="session-popover",m.style.display="none",m.innerHTML=`<div class="sp-field">
|
|
5
5
|
<label>Rename session</label>
|
|
6
6
|
<input type="text" id="sp-name" />
|
|
7
7
|
</div>
|
|
@@ -10,4 +10,5 @@ import{a as F}from"./chunk-O3DBTEWH.js";var h=window.__TMUX_WEB_SHELL__,l=null,c
|
|
|
10
10
|
<button class="btn" id="sp-cancel">Cancel</button>
|
|
11
11
|
</div>
|
|
12
12
|
<hr class="sp-divider" />
|
|
13
|
-
<button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(
|
|
13
|
+
<button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(m);function G(e){let t=e.getBoundingClientRect();m.style.top=t.bottom+4+"px",m.style.left=Math.max(8,Math.min(t.left,window.innerWidth-240))+"px"}function Q(e,t){h=e;let n=document.getElementById("sp-name");n.value=e,k.classList.add("open"),m.style.display="block",G(t),setTimeout(()=>n.focus(),50)}function B(){k.classList.remove("open"),m.style.display="none"}k.addEventListener("click",B),document.getElementById("sp-save").addEventListener("click",async()=>{let e=document.getElementById("sp-name").value.trim();if(!e||e===h){B();return}try{if(!(await fetch("/api/sessions/rename",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({oldName:h,newName:e})})).ok)return;B(),b(),r===h&&H(e)}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(confirm('Delete session "'+h+'"?'))try{if(!(await fetch("/api/sessions/kill",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:h})})).ok)return;B(),r===h&&(i&&(i.destroy(),i=null),r=null,y.style.display="none",E.style.display="flex"),b()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",B);var Y={esc:"\x1B",tab:" ","s-tab":"\x1B[Z",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",space:" ","ctrl-c":"","ctrl-d":"",enter:"\r",exit:"exit\r",yes:"yes\r"};document.getElementById("mobile-keys").addEventListener("click",e=>{let t=e.target.closest("button[data-key]");if(!t||!i)return;let n=Y[t.dataset.key];n&&(i.sendInput(n),i.focus())});var d=document.getElementById("mk-input"),D=document.getElementById("mk-send");function P(){if(!d||!i)return;let e=d.value;e&&(i.sendInput(e+"\r"),d.value="",d.rows=1,i.focus())}d&&(d.addEventListener("input",()=>{d.rows=1;let e=d.value.split(`
|
|
14
|
+
`).length;d.rows=Math.min(e,4)}),d.addEventListener("keydown",e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),P())})),D&&D.addEventListener("click",P),window.__openSession=H,window.__refreshSidebar=b,b();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{initTerminal as
|
|
2
|
-
<span>${
|
|
3
|
-
<button class="session-edit-btn" data-session="${
|
|
4
|
-
`,
|
|
1
|
+
import{initTerminal as V}from"./terminal-core.js";const b=window.__TMUX_WEB_SHELL__;let s=null,d=null,$="sessions",u="",B="",S="",N="";const i=document.getElementById("sidebar-content"),E=document.getElementById("main-placeholder"),y=document.getElementById("terminal-container"),I=document.getElementById("file-editor"),q=document.getElementById("fe-path"),c=document.getElementById("fe-status"),L=document.getElementById("fe-content"),v=document.getElementById("fe-save"),J=document.getElementById("fe-delete"),U=document.getElementById("fe-back"),F=document.getElementById("fe-new-name"),A=document.getElementById("fe-new-btn"),T=document.getElementById("settings-backdrop"),j=document.getElementById("settings-popover"),D=document.querySelector(".sidebar");function W(){return window.matchMedia("(max-width: 640px)").matches}function O(){W()&&D.classList.add("collapsed")}function P(){D.classList.remove("collapsed")}document.getElementById("mode-sessions").addEventListener("click",()=>{P(),z("sessions")}),document.getElementById("mode-files").addEventListener("click",()=>{P(),z("files")});function z(e){$=e,document.querySelectorAll(".mode-btn").forEach(n=>n.classList.remove("active"));const t=document.getElementById(e==="sessions"?"mode-sessions":"mode-files");t&&t.classList.add("active"),e==="sessions"?w():K()}async function w(){i.innerHTML='<div class="sidebar-section-label">Sessions</div><button class="new-session-sidebar-btn" id="ns-btn">+ New Session</button>';try{const m=(await(await fetch("/api/sidebar/sessions")).json()).recent||[];for(const f of m){const o=document.createElement("div");o.className="session-item"+(f.name===d?" active":""),o.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor"><path d="${f.attached?"M19 4H5a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2zm0 14H5V6h14v12z":"M4 6h16v2H4V6zm0 5h16v2H4v-2zm0 5h16v2H4v-2z"}"></svg>
|
|
2
|
+
<span>${k(f.name)}</span>
|
|
3
|
+
<button class="session-edit-btn" data-session="${k(f.name)}" title="Edit session"><svg viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a1 1 0 000-1.41l-2.34-2.34a1 1 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg></button>
|
|
4
|
+
`,o.addEventListener("click",l=>{l.target.closest(".session-edit-btn")||H(f.name)}),i.appendChild(o);const a=o.querySelector(".session-edit-btn");a&&a.addEventListener("click",l=>{l.stopPropagation(),Y(f.name,a)})}}catch{i.innerHTML+='<div class="file-tree-empty">Failed to load sessions</div>'}const e=document.getElementById("ns-btn");e&&e.addEventListener("click",()=>document.getElementById("new-session-modal")?.classList.add("open"))}function k(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}async function H(e){if(!(d===e&&s)){I.style.display="none",E.style.display="none",y.style.display="",y.classList.add("terminal-pending"),O(),s&&(s.destroy(),s=null),d=e;try{s=await V(y,e,{terminal:b.terminal,scrollback:b.scrollback,theme:b.theme,renderer:b.renderer})}catch(t){console.error("[shell] terminal init failed:",t);const n=t&&typeof t=="object"&&"message"in t?t.message:String(t);y.textContent="Failed to open terminal for "+e+": "+n,y.classList.remove("terminal-pending")}}}let M=[];function K(){if(M=b.fsRoots||[],M.length===0){if(d){X(d);return}i.innerHTML='<div class="file-tree-info">Open a session first, then switch to Files to browse its directory.</div>';return}i.innerHTML="";for(const e of M){const t=document.createElement("div");t.className="file-tree-item",t.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${k(e)}`,t.addEventListener("click",()=>h(e)),i.appendChild(t)}}async function X(e){i.innerHTML='<div class="file-tree-empty">Loading...</div>';try{const n=await(await fetch("/api/fs/session-path?session="+encodeURIComponent(e))).json();n.path?h(n.path):i.innerHTML='<div class="file-tree-info">Could not determine session directory.</div>'}catch{i.innerHTML='<div class="file-tree-error">Failed to get session directory</div>'}}async function h(e){u=e,i.innerHTML='<div class="file-tree-empty">Loading...</div>';try{const n=await(await fetch("/api/fs/list?path="+encodeURIComponent(e))).json();i.innerHTML="";const m=Z(e);if(m&&!M.some(a=>e===a)){const a=document.createElement("div");a.className="file-tree-item",a.innerHTML="..",a.addEventListener("click",()=>h(m)),i.appendChild(a)}if(n.dirs)for(const o of n.dirs){const a=o.split("/").pop()||o.split("\\").pop(),l=document.createElement("div");l.className="file-tree-item",l.innerHTML=`<svg viewBox="0 0 24 24" fill="currentColor" class="file-icon"><path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></svg> ${k(a)}`,l.addEventListener("click",()=>h(o)),i.appendChild(l)}else i.innerHTML="";const f=n.files||[];for(const o of f){const a=o.split("/").pop()||o.split("\\").pop(),l=document.createElement("div");l.className="file-tree-item file",l.innerHTML=`<span class="file-icon">\u{1F4C4}</span> ${k(a)}`,l.addEventListener("click",()=>G(o)),i.appendChild(l)}}catch{i.innerHTML='<div class="file-tree-error">Failed to load directory</div>'}}function Z(e){const t=e.lastIndexOf("/");return t<=0?null:e.substring(0,t)}async function G(e){B=e,y.style.display="none",s&&(s.destroy(),s=null,d=null),O(),E.style.display="none",I.style.display="flex",q.textContent=e,c.textContent="Loading...",v.style.display="none";try{const t=await fetch("/api/file?path="+encodeURIComponent(e));if(!t.ok){const m=await t.json();c.textContent=m.error||"Failed to load",L.value="";return}const n=await t.json();L.value=n.content,S=n.content,N=n.content,c.textContent=n.size+" bytes",v.style.display=""}catch{c.textContent="Failed to load",L.value=""}}L.addEventListener("input",()=>{S=L.value}),v.addEventListener("click",async()=>{v.textContent="Saving...",v.disabled=!0;try{const e=await fetch("/api/file",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:B,content:S})});if(!e.ok){const t=await e.json();c.textContent=t.error||"Save failed";return}N=S,c.textContent="Saved"}catch{c.textContent="Save failed"}finally{v.disabled=!1,v.textContent="Save"}}),J.addEventListener("click",async()=>{if(confirm("Delete "+B+"?"))try{const e=await fetch("/api/file/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:B})});if(!e.ok){const t=await e.json();c.textContent=t.error||"Delete failed";return}I.style.display="none",E.style.display="flex",u&&h(u)}catch{c.textContent="Delete failed"}}),U.addEventListener("click",()=>{I.style.display="none",E.style.display="flex",u&&h(u)}),A.addEventListener("click",async()=>{const e=F.value.trim();if(!e)return;const t=u+"/"+e;try{const n=await fetch("/api/file/touch",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t})});if(!n.ok){const m=await n.json();c.textContent=m.error||"Create failed";return}F.value="",u&&h(u)}catch{c.textContent="Create failed"}}),document.getElementById("mode-settings").addEventListener("click",()=>{const e=j.classList.toggle("open");T.classList.toggle("open",e)}),T.addEventListener("click",()=>{j.classList.remove("open"),T.classList.remove("open")});let g="";const C=document.createElement("div");C.className="session-popover-backdrop",document.body.appendChild(C);const p=document.createElement("div");p.id="session-popover",p.className="session-popover",p.style.display="none",p.innerHTML=`<div class="sp-field">
|
|
5
5
|
<label>Rename session</label>
|
|
6
6
|
<input type="text" id="sp-name" />
|
|
7
7
|
</div>
|
|
@@ -10,4 +10,5 @@ import{initTerminal as z}from"./terminal-core.js";const g=window.__TMUX_WEB_SHEL
|
|
|
10
10
|
<button class="btn" id="sp-cancel">Cancel</button>
|
|
11
11
|
</div>
|
|
12
12
|
<hr class="sp-divider" />
|
|
13
|
-
<button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(
|
|
13
|
+
<button class="btn danger" id="sp-delete">Delete session</button>`,document.body.appendChild(p);function Q(e){const t=e.getBoundingClientRect();p.style.top=t.bottom+4+"px",p.style.left=Math.max(8,Math.min(t.left,window.innerWidth-240))+"px"}function Y(e,t){g=e;const n=document.getElementById("sp-name");n.value=e,C.classList.add("open"),p.style.display="block",Q(t),setTimeout(()=>n.focus(),50)}function x(){C.classList.remove("open"),p.style.display="none"}C.addEventListener("click",x),document.getElementById("sp-save").addEventListener("click",async()=>{const e=document.getElementById("sp-name").value.trim();if(!e||e===g){x();return}try{if(!(await fetch("/api/sessions/rename",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({oldName:g,newName:e})})).ok)return;x(),w(),d===g&&H(e)}catch{}}),document.getElementById("sp-delete").addEventListener("click",async()=>{if(confirm('Delete session "'+g+'"?'))try{if(!(await fetch("/api/sessions/kill",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:g})})).ok)return;x(),d===g&&(s&&(s.destroy(),s=null),d=null,y.style.display="none",E.style.display="flex"),w()}catch{}}),document.getElementById("sp-cancel").addEventListener("click",x);const ee={esc:"\x1B",tab:" ","s-tab":"\x1B[Z",up:"\x1B[A",down:"\x1B[B",left:"\x1B[D",right:"\x1B[C",space:" ","ctrl-c":"","ctrl-d":"",enter:"\r",exit:"exit\r",yes:"yes\r"};document.getElementById("mobile-keys").addEventListener("click",e=>{const t=e.target.closest("button[data-key]");if(!t||!s)return;const n=ee[t.dataset.key];n&&(s.sendInput(n),s.focus())});const r=document.getElementById("mk-input"),R=document.getElementById("mk-send");function _(){if(!r||!s)return;const e=r.value;e&&(s.sendInput(e+"\r"),r.value="",r.rows=1,s.focus())}r&&(r.addEventListener("input",()=>{r.rows=1;const e=r.value.split(`
|
|
14
|
+
`).length;r.rows=Math.min(e,4)}),r.addEventListener("keydown",e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),_())})),R&&R.addEventListener("click",_),window.__openSession=H,window.__refreshSidebar=w,w();
|
package/dist/lib/pages/shell.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{cssVarsStyle as
|
|
1
|
+
import{cssVarsStyle as x}from"../theme.js";import{commandbarCSS as g,commandbarHTML as m,commandbarScript as f}from"../commandbar.js";import{newSessionModalCSS as u,newSessionModalHTML as v,newSessionModalScript as h,reducedMotion as y}from"../shared-layout.js";import{icon as n}from"../icons.js";function C(o){return o.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function a(o="var(--panel-accent)"){return`box-shadow: 0 0 0 2px ${o}; outline: none;`}function _(o){const{theme:e,commandbarEnabled:t,commandbarSessions:s,agentsEnabled:r,fsRoots:l,terminalCfg:d,renderer:i,scrollback:p}=o,c=`
|
|
2
2
|
*, *::before, *::after { box-sizing: border-box; }
|
|
3
3
|
html, body {
|
|
4
4
|
background: var(--page-bg); color: var(--page-fg);
|
|
@@ -26,7 +26,7 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as x,commandbarH
|
|
|
26
26
|
/* \u2500\u2500 App layout \u2500\u2500 */
|
|
27
27
|
.app-layout {
|
|
28
28
|
display: flex;
|
|
29
|
-
height:
|
|
29
|
+
height: 100dvh;
|
|
30
30
|
padding-top: 48px;
|
|
31
31
|
transition: height 0.05s;
|
|
32
32
|
}
|
|
@@ -284,6 +284,32 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as x,commandbarH
|
|
|
284
284
|
touch-action: manipulation; user-select: none;
|
|
285
285
|
}
|
|
286
286
|
.mobile-keys button:active { opacity: 0.55; }
|
|
287
|
+
.mobile-keys .mk-input {
|
|
288
|
+
display: flex; gap: 4px; flex: 1 1 100%;
|
|
289
|
+
}
|
|
290
|
+
.mobile-keys .mk-input textarea {
|
|
291
|
+
flex: 1; resize: none; box-sizing: border-box;
|
|
292
|
+
min-height: 38px; max-height: 80px;
|
|
293
|
+
background: var(--terminal-bg, rgba(0,0,0,0.28));
|
|
294
|
+
color: var(--page-fg);
|
|
295
|
+
border: 1px solid var(--panel-border);
|
|
296
|
+
border-radius: 8px; padding: 6px 10px;
|
|
297
|
+
font-family: var(--font-mono); font-size: var(--text-base); line-height: 1.4;
|
|
298
|
+
outline: none;
|
|
299
|
+
}
|
|
300
|
+
.mobile-keys .mk-input textarea:focus {
|
|
301
|
+
border-color: var(--panel-accent);
|
|
302
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--panel-accent) 12%, transparent);
|
|
303
|
+
}
|
|
304
|
+
.mobile-keys .mk-input textarea::placeholder { color: var(--panel-muted); opacity: 0.6; }
|
|
305
|
+
.mobile-keys .mk-input button {
|
|
306
|
+
min-width: 44px;
|
|
307
|
+
border: 1px solid var(--panel-success); color: var(--panel-success);
|
|
308
|
+
background: var(--page-bg);
|
|
309
|
+
}
|
|
310
|
+
.mobile-keys .mk-input button:hover {
|
|
311
|
+
background: color-mix(in srgb, var(--panel-success) 12%, transparent);
|
|
312
|
+
}
|
|
287
313
|
@media (max-width: 640px) {
|
|
288
314
|
.mobile-keys { display: flex; }
|
|
289
315
|
}
|
|
@@ -301,16 +327,16 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as x,commandbarH
|
|
|
301
327
|
.file-roots-list li svg { width: 20px; height: 20px; flex-shrink: 0; fill: var(--panel-accent); }
|
|
302
328
|
|
|
303
329
|
/* \u2500\u2500 Commandbar \u2500\u2500 */
|
|
304
|
-
${t?
|
|
330
|
+
${t?g():""}
|
|
305
331
|
${y()}
|
|
306
|
-
${
|
|
332
|
+
${u()}
|
|
307
333
|
@media (max-width: 640px) {
|
|
308
334
|
.app-layout { flex-direction: column; }
|
|
309
335
|
.sidebar { flex: 0 0 auto; border-right: none; border-bottom: 1px solid var(--panel-border); transition: max-height 0.2s; }
|
|
310
336
|
.sidebar.collapsed .sidebar-content { display: none; }
|
|
311
337
|
.sidebar.collapsed { max-height: 48px; overflow: hidden; }
|
|
312
338
|
}
|
|
313
|
-
`,k=JSON.stringify(e.terminal).replace(/</g,"\\u003c"),b=JSON.stringify({terminal:
|
|
339
|
+
`,k=JSON.stringify(e.terminal).replace(/</g,"\\u003c"),b=JSON.stringify({terminal:d,scrollback:p,theme:e.terminal,renderer:i,fsRoots:l,agentsEnabled:r,commandbarEnabled:t}).replace(/</g,"\\u003c");return`<!DOCTYPE html>
|
|
314
340
|
<html lang="en">
|
|
315
341
|
<head>
|
|
316
342
|
<meta charset="UTF-8" />
|
|
@@ -318,7 +344,7 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as x,commandbarH
|
|
|
318
344
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
319
345
|
<title>tmux-weblink</title>
|
|
320
346
|
<style>
|
|
321
|
-
${
|
|
347
|
+
${x(e.shell)}
|
|
322
348
|
${c}
|
|
323
349
|
</style>
|
|
324
350
|
</head>
|
|
@@ -344,7 +370,7 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as x,commandbarH
|
|
|
344
370
|
<header class="fixed-header">
|
|
345
371
|
<div class="brand"><a href="/">tmux<span>-weblink</span></a></div>
|
|
346
372
|
<div class="header-actions">
|
|
347
|
-
${t?`<button class="header-btn" id="cmdbar-btn" title="Search" aria-label="Search">${
|
|
373
|
+
${t?`<button class="header-btn" id="cmdbar-btn" title="Search" aria-label="Search">${n("search")}</button>`:""}
|
|
348
374
|
</div>
|
|
349
375
|
</header>
|
|
350
376
|
|
|
@@ -352,9 +378,9 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as x,commandbarH
|
|
|
352
378
|
<aside class="sidebar">
|
|
353
379
|
<div class="sidebar-content" id="sidebar-content"></div>
|
|
354
380
|
<div class="sidebar-footer">
|
|
355
|
-
<button class="mode-btn active" id="mode-sessions" title="Sessions">${
|
|
356
|
-
<button class="mode-btn" id="mode-files" title="Files">${
|
|
357
|
-
<button class="mode-btn" id="mode-settings" title="Settings">${
|
|
381
|
+
<button class="mode-btn active" id="mode-sessions" title="Sessions">${n("sessions",'width="20" height="20"')}</button>
|
|
382
|
+
<button class="mode-btn" id="mode-files" title="Files">${n("folder",'width="20" height="20"')}</button>
|
|
383
|
+
<button class="mode-btn" id="mode-settings" title="Settings">${n("settings",'width="20" height="20"')}</button>
|
|
358
384
|
</div>
|
|
359
385
|
</aside>
|
|
360
386
|
|
|
@@ -380,6 +406,10 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as x,commandbarH
|
|
|
380
406
|
</div>
|
|
381
407
|
</div>
|
|
382
408
|
<div class="mobile-keys" id="mobile-keys">
|
|
409
|
+
<div class="mk-input">
|
|
410
|
+
<textarea id="mk-input" placeholder="Type or voice input\u2026" autocapitalize="off" autocomplete="off" autocorrect="off" spellcheck="false" rows="1"></textarea>
|
|
411
|
+
<button id="mk-send" type="button" title="Send (Enter)">⏎</button>
|
|
412
|
+
</div>
|
|
383
413
|
<button data-key="esc">ESC</button>
|
|
384
414
|
<button data-key="tab">Tab</button>
|
|
385
415
|
<button data-key="s-tab">S-Tab</button>
|
|
@@ -392,6 +422,7 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as x,commandbarH
|
|
|
392
422
|
<button data-key="ctrl-d">Ctrl-D</button>
|
|
393
423
|
<button data-key="enter">\u21B5 Enter</button>
|
|
394
424
|
<button data-key="exit">Exit</button>
|
|
425
|
+
<button data-key="yes">Yes</button>
|
|
395
426
|
</div>
|
|
396
427
|
</main>
|
|
397
428
|
</div>
|
|
@@ -444,7 +475,7 @@ import{cssVarsStyle as g}from"../theme.js";import{commandbarCSS as x,commandbarH
|
|
|
444
475
|
})();
|
|
445
476
|
</script>
|
|
446
477
|
|
|
447
|
-
${
|
|
478
|
+
${v()}
|
|
448
479
|
${t?m():""}
|
|
449
480
|
|
|
450
481
|
<script>
|
|
@@ -458,7 +489,7 @@ window.__onSessionCreated = async function(name) {
|
|
|
458
489
|
await window.__refreshSidebar();
|
|
459
490
|
window.__openSession(name);
|
|
460
491
|
};
|
|
461
|
-
${
|
|
492
|
+
${h("__onSessionCreated")}
|
|
462
493
|
</script>
|
|
463
494
|
<script>
|
|
464
495
|
// Sync app-layout height to visual viewport so mobile keyboard doesn't overlap
|