tmux-weblink 0.3.0 → 0.3.2

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 CHANGED
@@ -20,7 +20,7 @@ npx tmux-weblink
20
20
  # Interactive setup (command bar, agents page)
21
21
  tmux-weblink setup
22
22
 
23
- # Start on default port 3000
23
+ # Start on default port 21000
24
24
  tmux-weblink
25
25
 
26
26
  # Custom port
@@ -39,7 +39,7 @@ TMUX_WEB_TERMINAL_RENDERER=ghostty tmux-weblink
39
39
  TMUX_WEB_INITIAL_LINES=1000 TMUX_WEB_HISTORY_CHUNK=500 tmux-weblink
40
40
  ```
41
41
 
42
- Then open `http://localhost:3000` in your browser. You'll see a list of active tmux sessions — click one to attach.
42
+ Then open `http://localhost:21000` in your browser. You'll see a list of active tmux sessions — click one to attach.
43
43
 
44
44
  ## Documentation
45
45
 
@@ -1,4 +1,4 @@
1
- var O="https://esm.sh/ghostty-web@0.4.0",y;function U(){return y||(document.querySelector("link[data-tmux-web-xterm-css]")?y=Promise.resolve():(y=new Promise(t=>{let e=document.createElement("link");e.rel="stylesheet",e.href="/assets/xterm.css",e.setAttribute("data-tmux-web-xterm-css",""),e.addEventListener("load",()=>t(),{once:!0}),e.addEventListener("error",()=>t(),{once:!0}),document.head.appendChild(e)}),y))}var J=class j{terminal;fitAddon;container;constructor(e,n,r){this.container=e,this.terminal=n,this.fitAddon=r,this.terminal.loadAddon(this.fitAddon),this.terminal.open(e)}static async create(e,n,r){let[{Terminal:o},{FitAddon:h}]=await Promise.all([import("./xterm-NI46XXQY.js"),import("./addon-fit-D5N335P2.js"),U()]),g=new o({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:n,convertEol:!1,theme:r});return new j(e,g,new h)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(e){return new Promise(n=>this.terminal.write(e,n))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(e){this.terminal.scrollToLine(Math.max(0,e))}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){let e=V(this.container);return e.width<=0||e.height<=0?!1:(this.fitAddon.fit(),!0)}focus(){this.terminal.focus()}pasteText(e){this.terminal.paste(e)}input(e){this.terminal.input(e,!1)}onData(e){this.terminal.onData(e),this.terminal.onBinary(e)}onResize(e){this.terminal.onResize(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){let e=document.activeElement;return!!e&&(e===this.container||this.container.contains(e))}},G=class q{terminal;container;colsValue=80;rowsValue=24;charW=0;charH=0;resizeCallbacks=[];constructor(e,n){this.container=e,this.terminal=n,this.terminal.open(e)}static async create(e,n,r){let o=await import(O);await o.init();let h=new o.Terminal({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:n,convertEol:!1,theme:r});return new q(e,h)}get cols(){return this.colsValue}get rows(){return this.rowsValue}write(e){return new Promise(n=>this.terminal.write(e,n))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom?.()}scrollToLine(e){this.terminal.scrollToLine?.(Math.max(0,e))}isNearScrollbackTop(){let e=this.terminal.buffer?.active;return e?e.viewportY>=e.baseY:!1}viewportY(){return this.terminal.buffer?.active?.viewportY??0}baseY(){return this.terminal.buffer?.active?.baseY??0}fit(){let e=V(this.container);if(e.width<=0||e.height<=0)return!1;this.updateCellMetrics(!this.charW||!this.charH);let n=Math.floor(e.width/this.charW),r=Math.floor(e.height/this.charH);if(n<10||r<5)return!1;if(n!==this.colsValue||r!==this.rowsValue){this.colsValue=n,this.rowsValue=r,this.terminal.resize(n,r);for(let o of this.resizeCallbacks)o({cols:n,rows:r})}return!0}focus(){(this.terminal.textarea||this.container.querySelector("textarea")||this.container)?.focus?.()}pasteText(e){let n=this.terminal.getMode?.(2004)??!1;this.input(n?"\x1B[200~"+e+"\x1B[201~":e)}input(e){this.terminal.input?.(e,!1)}onData(e){this.terminal.onData(n=>e(n))}onResize(e){this.resizeCallbacks.push(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){let e=document.activeElement;return!!e&&(e===this.container||e===this.terminal.textarea||this.container.contains(e))}updateCellMetrics(e=!1){let n=this.container.querySelector("canvas");if(n instanceof HTMLElement&&n.offsetWidth>0&&n.offsetHeight>0&&this.colsValue>0&&this.rowsValue>0){let r=n.offsetWidth/this.colsValue,o=n.offsetHeight/this.rowsValue;(e||!this.charW||!this.charH)&&(this.charW=r,this.charH=o)}(!this.charW||!this.charH)&&(this.charW=9,this.charH=18)}},A=window.__TMUX_WEB_TERMINAL__;if(!A)throw new Error("missing tmux-web terminal config");var u=A,W=document.getElementById("terminal-container");if(!W)throw new Error("missing terminal container");var i=W;function Q(){let t=document.createElement("div");t.textContent="ghostty-web unavailable \u2014 using xterm.js",t.style.cssText='position:fixed;bottom:12px;right:12px;z-index:2000;background:rgba(0,0,0,0.85);color:#fbbf24;font:12px/1.4 "JetBrains Mono",monospace;padding:8px 12px;border:1px solid rgba(251,191,36,0.4);border-radius:6px;',document.body.appendChild(t),setTimeout(()=>t.remove(),6e3)}async function Z(){if(u.renderer==="ghostty")try{return await G.create(i,u.scrollback,u.theme)}catch(t){console.error("[tmux-web] ghostty-web failed to load; falling back to xterm.js:",t),Q()}return J.create(i,u.scrollback,u.theme)}var a=await Z(),c,b=0,Y,s=null,C=0,d="connecting",x=0,E=!1,T=[],m="";function $(){return T.join("")+m}async function ee(t,e=0){let n=t?a.viewportY():0,r=t?a.baseY():0,o=$();if(a.reset(),!o){t||a.scrollToBottom();return}await a.write(o),t?a.scrollToLine(r+n+e):a.scrollToBottom()}function te(t){let e;try{e=JSON.parse(t)}catch{d==="live"&&(m+=t,a.write(t));return}if(e.type==="auth.required"){let n=localStorage.getItem("tmux-web-token");n?w({type:"auth.token",token:n}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(e.type==="auth.ok"){e.token&&localStorage.setItem("tmux-web-token",e.token),S(!0),f=1e3,p(),w({type:"resize",cols:a.cols,rows:a.rows}),l();return}if(e.type==="auth.failed"){if(S(!1),e.permanentLock||e.retryAfterMs&&e.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(e.message);return}let n=document.createElement("div");n.textContent="Auth failed: "+e.message,n.style.cssText='position:fixed;top:12px;right:12px;z-index:2000;background:rgba(0,0,0,0.85);color:#f87171;font:12px/1.4 "JetBrains Mono",monospace;padding:8px 12px;border:1px solid rgba(248,113,113,0.4);border-radius:6px;',document.body.appendChild(n),setTimeout(()=>n.remove(),4e3);return}if(e.type==="snapshot"&&typeof e.data=="string"){T=[e.data],m="",x=typeof e.lines=="number"?e.lines:u.terminal.initialLines,d="live",a.reset(),a.write(e.data).then(()=>a.scrollToBottom());return}if(e.type==="window_changed"&&typeof e.activeIndex=="number"){let n=new URL(location.href);n.searchParams.get("window")!==String(e.activeIndex)&&(n.searchParams.set("window",String(e.activeIndex)),history.replaceState(history.state,"",n)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:e.windows}));return}if(e.type==="history"&&typeof e.data=="string"){E=!1,e.lines>0&&e.data&&(T.unshift(e.data),x+=e.lines,ee(!0,e.lines));return}if(e.type==="data"&&typeof e.data=="string"){if(d==="connecting"){d="live",m=e.data,a.write(e.data);return}d==="live"&&(m+=e.data,a.write(e.data))}}function V(t){let e=t.getBoundingClientRect(),n=window.visualViewport;return n?{width:Math.min(e.width,n.width),height:Math.max(0,Math.min(e.height,n.height-Math.max(0,e.top)))}:e}function p(){return a.fit()}function B(){i.classList.remove("terminal-pending")}function l(){b&&cancelAnimationFrame(b),Y&&clearTimeout(Y),p(),b=requestAnimationFrame(()=>{b=0,p()&&B()}),Y=setTimeout(()=>{p()&&B()},120)}function H(){l(),setTimeout(l,50),setTimeout(l,150),setTimeout(l,300)}var F=document.getElementById("status-dot"),k=document.getElementById("status-text");function S(t){F&&(F.className="dot"+(t?" connected":"")),k&&(k.textContent=t?"connected":"reconnecting")}var ne=location.protocol==="https:"?"wss:":"ws:",re=ne+"//"+location.host+"/ws/"+encodeURIComponent(u.sessionName),ae="/api/session/"+encodeURIComponent(u.sessionName)+"/upload",f=1e3,ie=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function w(t){c?.readyState===WebSocket.OPEN&&c.send(JSON.stringify(t))}function R(){let t=re,e=localStorage.getItem("tmux-web-token");e&&(t+=(t.includes("?")?"&":"?")+"token="+encodeURIComponent(e)),c=new WebSocket(t),c.onopen=()=>{d="connecting",x=0,E=!1,T=[],m="",a.reset(),f=1e3},c.onmessage=n=>{typeof n.data=="string"&&te(n.data)},c.onclose=()=>{S(!1),d="connecting",setTimeout(()=>{f=Math.min(f*2,1e4),R()},f)},c.onerror=()=>c?.close()}function L(t){w({type:"input",data:t})}function oe(t){L(t)}function X(t){return t.split(`\r
1
+ var U="https://esm.sh/ghostty-web@0.4.0",J=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function y(t){return t.replace(J,"")}var b;function G(){return b||(document.querySelector("link[data-tmux-web-xterm-css]")?b=Promise.resolve():(b=new Promise(t=>{let e=document.createElement("link");e.rel="stylesheet",e.href="/assets/xterm.css",e.setAttribute("data-tmux-web-xterm-css",""),e.addEventListener("load",()=>t(),{once:!0}),e.addEventListener("error",()=>t(),{once:!0}),document.head.appendChild(e)}),b))}var Q=class q{terminal;fitAddon;container;constructor(e,n,r){this.container=e,this.terminal=n,this.fitAddon=r,this.terminal.loadAddon(this.fitAddon),this.terminal.open(e)}static async create(e,n,r){let[{Terminal:o},{FitAddon:h}]=await Promise.all([import("./xterm-BXEES47M.js"),import("./addon-fit-D5N335P2.js"),G()]),g=new o({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:n,convertEol:!1,theme:r});return new q(e,g,new h)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(e){return new Promise(n=>this.terminal.write(e,n))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(e){this.terminal.scrollToLine(Math.max(0,e))}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){let e=H(this.container);return e.width<=0||e.height<=0?!1:(this.fitAddon.fit(),!0)}focus(){this.terminal.focus()}pasteText(e){this.terminal.paste(e)}input(e){this.terminal.input(e,!1)}onData(e){this.terminal.onData(e),this.terminal.onBinary(e)}onResize(e){this.terminal.onResize(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){let e=document.activeElement;return!!e&&(e===this.container||this.container.contains(e))}},Z=class O{terminal;container;colsValue=80;rowsValue=24;charW=0;charH=0;resizeCallbacks=[];constructor(e,n){this.container=e,this.terminal=n,this.terminal.open(e)}static async create(e,n,r){let o=await import(U);await o.init();let h=new o.Terminal({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:n,convertEol:!1,theme:r});return new O(e,h)}get cols(){return this.colsValue}get rows(){return this.rowsValue}write(e){return new Promise(n=>this.terminal.write(e,n))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom?.()}scrollToLine(e){this.terminal.scrollToLine?.(Math.max(0,e))}isNearScrollbackTop(){let e=this.terminal.buffer?.active;return e?e.viewportY>=e.baseY:!1}viewportY(){return this.terminal.buffer?.active?.viewportY??0}baseY(){return this.terminal.buffer?.active?.baseY??0}fit(){let e=H(this.container);if(e.width<=0||e.height<=0)return!1;this.updateCellMetrics(!this.charW||!this.charH);let n=Math.floor(e.width/this.charW),r=Math.floor(e.height/this.charH);if(n<10||r<5)return!1;if(n!==this.colsValue||r!==this.rowsValue){this.colsValue=n,this.rowsValue=r,this.terminal.resize(n,r);for(let o of this.resizeCallbacks)o({cols:n,rows:r})}return!0}focus(){(this.terminal.textarea||this.container.querySelector("textarea")||this.container)?.focus?.()}pasteText(e){let n=this.terminal.getMode?.(2004)??!1;this.input(n?"\x1B[200~"+e+"\x1B[201~":e)}input(e){this.terminal.input?.(e,!1)}onData(e){this.terminal.onData(n=>e(n))}onResize(e){this.resizeCallbacks.push(e)}onScroll(e){this.terminal.onScroll(e)}attachCustomKeyEventHandler(e){this.terminal.attachCustomKeyEventHandler(e)}isFocused(){let e=document.activeElement;return!!e&&(e===this.container||e===this.terminal.textarea||this.container.contains(e))}updateCellMetrics(e=!1){let n=this.container.querySelector("canvas");if(n instanceof HTMLElement&&n.offsetWidth>0&&n.offsetHeight>0&&this.colsValue>0&&this.rowsValue>0){let r=n.offsetWidth/this.colsValue,o=n.offsetHeight/this.rowsValue;(e||!this.charW||!this.charH)&&(this.charW=r,this.charH=o)}(!this.charW||!this.charH)&&(this.charW=9,this.charH=18)}},W=window.__TMUX_WEB_TERMINAL__;if(!W)throw new Error("missing tmux-web terminal config");var u=W,V=document.getElementById("terminal-container");if(!V)throw new Error("missing terminal container");var i=V;function $(){let t=document.createElement("div");t.textContent="ghostty-web unavailable \u2014 using xterm.js",t.style.cssText='position:fixed;bottom:12px;right:12px;z-index:2000;background:rgba(0,0,0,0.85);color:#fbbf24;font:12px/1.4 "JetBrains Mono",monospace;padding:8px 12px;border:1px solid rgba(251,191,36,0.4);border-radius:6px;',document.body.appendChild(t),setTimeout(()=>t.remove(),6e3)}async function ee(){if(u.renderer==="ghostty")try{return await Z.create(i,u.scrollback,u.theme)}catch(t){console.error("[tmux-web] ghostty-web failed to load; falling back to xterm.js:",t),$()}return Q.create(i,u.scrollback,u.theme)}var a=await ee(),c,x=0,C,s=null,B=0,d="connecting",E=0,T=!1,k=[],m="";function te(){return k.join("")+m}async function ne(t,e=0){let n=t?a.viewportY():0,r=t?a.baseY():0,o=y(te());if(a.reset(),!o){t||a.scrollToBottom();return}await a.write(o),t?a.scrollToLine(r+n+e):a.scrollToBottom()}function re(t){let e;try{e=JSON.parse(t)}catch{d==="live"&&(m+=t,a.write(y(t)));return}if(e.type==="auth.required"){let n=localStorage.getItem("tmux-web-token");n?w({type:"auth.token",token:n}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(e.type==="auth.ok"){e.token&&localStorage.setItem("tmux-web-token",e.token),L(!0),f=1e3,p(),w({type:"resize",cols:a.cols,rows:a.rows}),l();return}if(e.type==="auth.failed"){if(L(!1),e.permanentLock||e.retryAfterMs&&e.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(e.message);return}let n=document.createElement("div");n.textContent="Auth failed: "+e.message,n.style.cssText='position:fixed;top:12px;right:12px;z-index:2000;background:rgba(0,0,0,0.85);color:#f87171;font:12px/1.4 "JetBrains Mono",monospace;padding:8px 12px;border:1px solid rgba(248,113,113,0.4);border-radius:6px;',document.body.appendChild(n),setTimeout(()=>n.remove(),4e3);return}if(e.type==="snapshot"&&typeof e.data=="string"){let n=y(e.data);k=[n],m="",E=typeof e.lines=="number"?e.lines:u.terminal.initialLines,d="live",a.reset(),a.write(n).then(()=>a.scrollToBottom());return}if(e.type==="window_changed"&&typeof e.activeIndex=="number"){let n=new URL(location.href);n.searchParams.get("window")!==String(e.activeIndex)&&(n.searchParams.set("window",String(e.activeIndex)),history.replaceState(history.state,"",n)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:e.windows}));return}if(e.type==="history"&&typeof e.data=="string"){T=!1,e.lines>0&&e.data&&(k.unshift(e.data),E+=e.lines,ne(!0,e.lines));return}if(e.type==="data"&&typeof e.data=="string"){let n=y(e.data);if(d==="connecting"){d="live",m=n,a.write(n);return}d==="live"&&(m+=n,a.write(n))}}function H(t){let e=t.getBoundingClientRect(),n=window.visualViewport;return n?{width:Math.min(e.width,n.width),height:Math.max(0,Math.min(e.height,n.height-Math.max(0,e.top)))}:e}function p(){return a.fit()}function P(){i.classList.remove("terminal-pending")}function l(){x&&cancelAnimationFrame(x),C&&clearTimeout(C),p(),x=requestAnimationFrame(()=>{x=0,p()&&P()}),C=setTimeout(()=>{p()&&P()},120)}function F(){l(),setTimeout(l,50),setTimeout(l,150),setTimeout(l,300)}var R=document.getElementById("status-dot"),S=document.getElementById("status-text");function L(t){R&&(R.className="dot"+(t?" connected":"")),S&&(S.textContent=t?"connected":"reconnecting")}var ae=location.protocol==="https:"?"wss:":"ws:",ie=ae+"//"+location.host+"/ws/"+encodeURIComponent(u.sessionName),oe="/api/session/"+encodeURIComponent(u.sessionName)+"/upload",f=1e3,se=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function w(t){c?.readyState===WebSocket.OPEN&&c.send(JSON.stringify(t))}function X(){let t=ie,e=localStorage.getItem("tmux-web-token");e&&(t+=(t.includes("?")?"&":"?")+"token="+encodeURIComponent(e)),c=new WebSocket(t),c.onopen=()=>{d="connecting",E=0,T=!1,k=[],m="",a.reset(),f=1e3},c.onmessage=n=>{typeof n.data=="string"&&re(n.data)},c.onclose=()=>{L(!1),d="connecting",setTimeout(()=>{f=Math.min(f*2,1e4),X()},f)},c.onerror=()=>c?.close()}function M(t){w({type:"input",data:t})}function le(t){M(t)}function K(t){return t.split(`\r
2
2
  `).join(`
3
3
  `).split(`
4
- `).join("\r")}function K(t){return typeof t=="string"&&t.startsWith("image/")}function N(t){return t?.files?.length?t.files[0]??null:null}function se(t){if(!t?.items)return null;for(let e=0;e<t.items.length;e++){let n=t.items[e];if(n?.kind==="file"&&K(n.type))return n.getAsFile()}return null}function M(t){t&&k?k.textContent=t:S(c?.readyState===WebSocket.OPEN)}async function le(t){let e=new FormData,n=t instanceof File&&t.name?t.name:"upload";e.append("file",t,n);let r=localStorage.getItem("tmux-web-token"),o={};r&&(o.Authorization="Bearer "+r);let h=await fetch(ae,{method:"POST",body:e,headers:o});if(!h.ok){let I="upload failed";try{let z=await h.json();z.error&&(I=z.error)}catch{}throw new Error(I)}let g=await h.json();if(!g.path)throw new Error("no path in response");return g.path}async function P(t){try{M("uploading...");let e=await le(t);oe(e),M(null)}catch(e){console.warn("image upload:",e),M("upload failed"),setTimeout(()=>M(null),2e3)}}a.onData(t=>L(t)),a.onResize(({cols:t,rows:e})=>w({type:"resize",cols:t,rows:e})),window.tmuxWeb={sendInput:L,focusTerminal:_},a.onScroll(()=>{d!=="live"||E||!a.isNearScrollbackTop()||(E=!0,w({type:"load_history",before:x}))}),a.attachCustomKeyEventHandler(t=>t.type!=="keydown"?!0:(t.ctrlKey||t.metaKey)&&t.code==="KeyV"?(t.preventDefault(),(async()=>{try{if(navigator.clipboard?.read){let e=await navigator.clipboard.read();for(let n of e)for(let r of n.types)if(K(r)){let o=await n.getType(r);await P(o);return}}}catch{}try{let e=await navigator.clipboard?.readText();e&&a.pasteText(X(e))}catch{}})(),!1):!0);var D=0;async function ce(t){let e=se(t.clipboardData);if(e){t.preventDefault(),t.stopPropagation();let o=Date.now();if(o-D<50)return;D=o,await P(e);return}let n=t.clipboardData?.getData("text/plain");if(!n)return;t.preventDefault(),t.stopPropagation();let r=Date.now();r-D<50||(D=r,a.pasteText(X(n)))}i.addEventListener("paste",ce);var v=0;i.addEventListener("dragenter",t=>{t.preventDefault(),v++,N(t.dataTransfer)&&i.classList.add("terminal-drag-over")}),i.addEventListener("dragover",t=>{t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy")}),i.addEventListener("dragleave",t=>{t.preventDefault(),v--,v<=0&&(v=0,i.classList.remove("terminal-drag-over"))}),i.addEventListener("drop",async t=>{t.preventDefault(),v=0,i.classList.remove("terminal-drag-over");let e=N(t.dataTransfer);e&&await P(e)}),document.addEventListener("keydown",t=>{!ie||t.key!=="Escape"||t.defaultPrevented||t.repeat||t.metaKey||t.ctrlKey||t.altKey||a.isFocused()&&(t.preventDefault(),t.stopPropagation(),L("\x1B"))},!0);function ue(t,e,n){(i.querySelector(".xterm-screen")??i).dispatchEvent(new WheelEvent("wheel",{deltaY:t,deltaMode:WheelEvent.DOM_DELTA_PIXEL,clientX:e,clientY:n,bubbles:!0,cancelable:!0}))}function _(){a.focus(),H()}i.addEventListener("touchstart",t=>{if(t.touches.length!==1){s=null;return}let e=t.touches[0];e&&(s={startX:e.clientX,startY:e.clientY,lastX:e.clientX,lastY:e.clientY,scrolling:!1},t.stopPropagation())},{passive:!0,capture:!0}),i.addEventListener("touchmove",t=>{if(!s||t.touches.length!==1)return;let e=t.touches[0];if(!e)return;let n=e.clientY-s.startY,r=e.clientX-s.startX;if(!s.scrolling){if(Math.abs(n)<8||Math.abs(n)<Math.abs(r))return;s.scrolling=!0,C=Date.now()+500}t.preventDefault(),t.stopPropagation(),ue(-(e.clientY-s.lastY),e.clientX,e.clientY),s.lastX=e.clientX,s.lastY=e.clientY},{passive:!1,capture:!0}),i.addEventListener("touchend",t=>{if(!s)return;let e=s.scrolling;s=null,t.stopPropagation(),e?(C=Date.now()+500,t.preventDefault()):_()},{passive:!1,capture:!0}),i.addEventListener("touchcancel",t=>{s=null,t.stopPropagation()},{passive:!0,capture:!0}),i.addEventListener("pointerup",t=>{t.pointerType==="touch"&&Date.now()<C&&(t.preventDefault(),t.stopPropagation())},!0),window.addEventListener("resize",l),window.visualViewport?.addEventListener("resize",l),window.visualViewport?.addEventListener("scroll",l),new ResizeObserver(l).observe(i),document.fonts?.ready.then(()=>{l(),setTimeout(l,50),setTimeout(l,200)}),i.addEventListener("focusin",H,!0),requestAnimationFrame(()=>{p()&&B(),R(),l()});
4
+ `).join("\r")}function N(t){return typeof t=="string"&&t.startsWith("image/")}function _(t){return t?.files?.length?t.files[0]??null:null}function ce(t){if(!t?.items)return null;for(let e=0;e<t.items.length;e++){let n=t.items[e];if(n?.kind==="file"&&N(n.type))return n.getAsFile()}return null}function D(t){t&&S?S.textContent=t:L(c?.readyState===WebSocket.OPEN)}async function ue(t){let e=new FormData,n=t instanceof File&&t.name?t.name:"upload";e.append("file",t,n);let r=localStorage.getItem("tmux-web-token"),o={};r&&(o.Authorization="Bearer "+r);let h=await fetch(oe,{method:"POST",body:e,headers:o});if(!h.ok){let z="upload failed";try{let A=await h.json();A.error&&(z=A.error)}catch{}throw new Error(z)}let g=await h.json();if(!g.path)throw new Error("no path in response");return g.path}async function I(t){try{D("uploading...");let e=await ue(t);le(e),D(null)}catch(e){console.warn("image upload:",e),D("upload failed"),setTimeout(()=>D(null),2e3)}}a.onData(t=>M(t)),a.onResize(({cols:t,rows:e})=>w({type:"resize",cols:t,rows:e})),window.tmuxWeb={sendInput:M,focusTerminal:j},a.onScroll(()=>{d!=="live"||T||!a.isNearScrollbackTop()||(T=!0,w({type:"load_history",before:E}))}),a.attachCustomKeyEventHandler(t=>t.type!=="keydown"?!0:(t.ctrlKey||t.metaKey)&&t.code==="KeyV"?(t.preventDefault(),(async()=>{try{if(navigator.clipboard?.read){let e=await navigator.clipboard.read();for(let n of e)for(let r of n.types)if(N(r)){let o=await n.getType(r);await I(o);return}}}catch{}try{let e=await navigator.clipboard?.readText();e&&a.pasteText(K(e))}catch{}})(),!1):!0);var Y=0;async function de(t){let e=ce(t.clipboardData);if(e){t.preventDefault(),t.stopPropagation();let o=Date.now();if(o-Y<50)return;Y=o,await I(e);return}let n=t.clipboardData?.getData("text/plain");if(!n)return;t.preventDefault(),t.stopPropagation();let r=Date.now();r-Y<50||(Y=r,a.pasteText(K(n)))}i.addEventListener("paste",de);var v=0;i.addEventListener("dragenter",t=>{t.preventDefault(),v++,_(t.dataTransfer)&&i.classList.add("terminal-drag-over")}),i.addEventListener("dragover",t=>{t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy")}),i.addEventListener("dragleave",t=>{t.preventDefault(),v--,v<=0&&(v=0,i.classList.remove("terminal-drag-over"))}),i.addEventListener("drop",async t=>{t.preventDefault(),v=0,i.classList.remove("terminal-drag-over");let e=_(t.dataTransfer);e&&await I(e)}),document.addEventListener("keydown",t=>{!se||t.key!=="Escape"||t.defaultPrevented||t.repeat||t.metaKey||t.ctrlKey||t.altKey||a.isFocused()&&(t.preventDefault(),t.stopPropagation(),M("\x1B"))},!0);function he(t,e,n){(i.querySelector(".xterm-screen")??i).dispatchEvent(new WheelEvent("wheel",{deltaY:t,deltaMode:WheelEvent.DOM_DELTA_PIXEL,clientX:e,clientY:n,bubbles:!0,cancelable:!0}))}function j(){a.focus(),F()}i.addEventListener("touchstart",t=>{if(t.touches.length!==1){s=null;return}let e=t.touches[0];e&&(s={startX:e.clientX,startY:e.clientY,lastX:e.clientX,lastY:e.clientY,scrolling:!1},t.stopPropagation())},{passive:!0,capture:!0}),i.addEventListener("touchmove",t=>{if(!s||t.touches.length!==1)return;let e=t.touches[0];if(!e)return;let n=e.clientY-s.startY,r=e.clientX-s.startX;if(!s.scrolling){if(Math.abs(n)<8||Math.abs(n)<Math.abs(r))return;s.scrolling=!0,B=Date.now()+500}t.preventDefault(),t.stopPropagation(),he(-(e.clientY-s.lastY),e.clientX,e.clientY),s.lastX=e.clientX,s.lastY=e.clientY},{passive:!1,capture:!0}),i.addEventListener("touchend",t=>{if(!s)return;let e=s.scrolling;s=null,t.stopPropagation(),e?(B=Date.now()+500,t.preventDefault()):j()},{passive:!1,capture:!0}),i.addEventListener("touchcancel",t=>{s=null,t.stopPropagation()},{passive:!0,capture:!0}),i.addEventListener("pointerup",t=>{t.pointerType==="touch"&&Date.now()<B&&(t.preventDefault(),t.stopPropagation())},!0),window.addEventListener("resize",l),window.visualViewport?.addEventListener("resize",l),window.visualViewport?.addEventListener("scroll",l),new ResizeObserver(l).observe(i),document.fonts?.ready.then(()=>{l(),setTimeout(l,50),setTimeout(l,200)}),i.addEventListener("focusin",F,!0),requestAnimationFrame(()=>{p()&&P(),X(),l()});