tmux-weblink 0.3.1 → 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.
@@ -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-BXEES47M.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()});
@@ -1,4 +1,4 @@
1
- const O="https://esm.sh/ghostty-web@0.4.0";let m;function q(){return m||(document.querySelector("link[data-tmux-web-xterm-css]")?m=Promise.resolve():(m=new Promise(t=>{const n=document.createElement("link");n.rel="stylesheet",n.href="/assets/xterm.css",n.setAttribute("data-tmux-web-xterm-css",""),n.addEventListener("load",()=>t(),{once:!0}),n.addEventListener("error",()=>t(),{once:!0}),document.head.appendChild(n)}),m))}class B{terminal;fitAddon;container;constructor(t,n,r){this.container=t,this.terminal=n,this.fitAddon=r,this.terminal.loadAddon(this.fitAddon),this.terminal.open(t)}static async create(t,n,r){const[{Terminal:a},{FitAddon:f}]=await Promise.all([import("@xterm/xterm"),import("@xterm/addon-fit"),q()]),b=new a({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:n,convertEol:!1,theme:r});return new B(t,b,new f)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(t){return new Promise(n=>this.terminal.write(t,n))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(t){this.terminal.scrollToLine(Math.max(0,t))}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){const t=R(this.container);return t.width<=0||t.height<=0?!1:(this.fitAddon.fit(),!0)}focus(){this.terminal.focus()}pasteText(t){this.terminal.paste(t)}input(t){this.terminal.input(t,!1)}onData(t){this.terminal.onData(t),this.terminal.onBinary(t)}onResize(t){this.terminal.onResize(t)}onScroll(t){this.terminal.onScroll(t)}attachCustomKeyEventHandler(t){this.terminal.attachCustomKeyEventHandler(t)}isFocused(){const t=document.activeElement;return!!t&&(t===this.container||this.container.contains(t))}}class F{terminal;container;colsValue=80;rowsValue=24;charW=0;charH=0;resizeCallbacks=[];constructor(t,n){this.container=t,this.terminal=n,this.terminal.open(t)}static async create(t,n,r){const a=await import(O);await a.init();const f=new a.Terminal({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:n,convertEol:!1,theme:r});return new F(t,f)}get cols(){return this.colsValue}get rows(){return this.rowsValue}write(t){return new Promise(n=>this.terminal.write(t,n))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom?.()}scrollToLine(t){this.terminal.scrollToLine?.(Math.max(0,t))}isNearScrollbackTop(){const t=this.terminal.buffer?.active;return t?t.viewportY>=t.baseY:!1}viewportY(){return this.terminal.buffer?.active?.viewportY??0}baseY(){return this.terminal.buffer?.active?.baseY??0}fit(){const t=R(this.container);if(t.width<=0||t.height<=0)return!1;this.updateCellMetrics(!this.charW||!this.charH);const n=Math.floor(t.width/this.charW),r=Math.floor(t.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(const a of this.resizeCallbacks)a({cols:n,rows:r})}return!0}focus(){(this.terminal.textarea||this.container.querySelector("textarea")||this.container)?.focus?.()}pasteText(t){const n=this.terminal.getMode?.(2004)??!1;this.input(n?"\x1B[200~"+t+"\x1B[201~":t)}input(t){this.terminal.input?.(t,!1)}onData(t){this.terminal.onData(n=>t(n))}onResize(t){this.resizeCallbacks.push(t)}onScroll(t){this.terminal.onScroll(t)}attachCustomKeyEventHandler(t){this.terminal.attachCustomKeyEventHandler(t)}isFocused(){const t=document.activeElement;return!!t&&(t===this.container||t===this.terminal.textarea||this.container.contains(t))}updateCellMetrics(t=!1){const n=this.container.querySelector("canvas");if(n instanceof HTMLElement&&n.offsetWidth>0&&n.offsetHeight>0&&this.colsValue>0&&this.rowsValue>0){const r=n.offsetWidth/this.colsValue,a=n.offsetHeight/this.rowsValue;(t||!this.charW||!this.charH)&&(this.charW=r,this.charH=a)}(!this.charW||!this.charH)&&(this.charW=9,this.charH=18)}}const A=window.__TMUX_WEB_TERMINAL__;if(!A)throw new Error("missing tmux-web terminal config");const u=A,H=document.getElementById("terminal-container");if(!H)throw new Error("missing terminal container");const o=H;function J(){const e=document.createElement("div");e.textContent="ghostty-web unavailable \u2014 using xterm.js",e.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(e),setTimeout(()=>e.remove(),6e3)}async function G(){if(u.renderer==="ghostty")try{return await F.create(o,u.scrollback,u.theme)}catch(e){console.error("[tmux-web] ghostty-web failed to load; falling back to xterm.js:",e),J()}return B.create(o,u.scrollback,u.theme)}const i=await G();let c,v=0,C,s=null,P=0,d="connecting",x=0,T=!1,E=[],h="";function Q(){return E.join("")+h}async function Z(e,t=0){const n=e?i.viewportY():0,r=e?i.baseY():0,a=Q();if(i.reset(),!a){e||i.scrollToBottom();return}await i.write(a),e?i.scrollToLine(r+n+t):i.scrollToBottom()}function $(e){let t;try{t=JSON.parse(e)}catch{d==="live"&&(h+=e,i.write(e));return}if(t.type==="auth.required"){const n=localStorage.getItem("tmux-web-token");n?g({type:"auth.token",token:n}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(t.type==="auth.ok"){t.token&&localStorage.setItem("tmux-web-token",t.token),S(!0),w=1e3,p(),g({type:"resize",cols:i.cols,rows:i.rows}),l();return}if(t.type==="auth.failed"){if(S(!1),t.permanentLock||t.retryAfterMs&&t.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(t.message);return}const n=document.createElement("div");n.textContent="Auth failed: "+t.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(t.type==="snapshot"&&typeof t.data=="string"){E=[t.data],h="",x=typeof t.lines=="number"?t.lines:u.terminal.initialLines,d="live",i.reset(),i.write(t.data).then(()=>i.scrollToBottom());return}if(t.type==="window_changed"&&typeof t.activeIndex=="number"){const n=new URL(location.href);n.searchParams.get("window")!==String(t.activeIndex)&&(n.searchParams.set("window",String(t.activeIndex)),history.replaceState(history.state,"",n)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:t.windows}));return}if(t.type==="history"&&typeof t.data=="string"){T=!1,t.lines>0&&t.data&&(E.unshift(t.data),x+=t.lines,Z(!0,t.lines));return}if(t.type==="data"&&typeof t.data=="string"){if(d==="connecting"){d="live",h=t.data,i.write(t.data);return}d==="live"&&(h+=t.data,i.write(t.data))}}function R(e){const t=e.getBoundingClientRect(),n=window.visualViewport;return n?{width:Math.min(t.width,n.width),height:Math.max(0,Math.min(t.height,n.height-Math.max(0,t.top)))}:t}function p(){return i.fit()}function Y(){o.classList.remove("terminal-pending")}function l(){v&&cancelAnimationFrame(v),C&&clearTimeout(C),p(),v=requestAnimationFrame(()=>{v=0,p()&&Y()}),C=setTimeout(()=>{p()&&Y()},120)}function V(){l(),setTimeout(l,50),setTimeout(l,150),setTimeout(l,300)}const N=document.getElementById("status-dot"),k=document.getElementById("status-text");function S(e){N&&(N.className="dot"+(e?" connected":"")),k&&(k.textContent=e?"connected":"reconnecting")}const tt=location.protocol==="https:"?"wss:":"ws:",et=tt+"//"+location.host+"/ws/"+encodeURIComponent(u.sessionName),nt="/api/session/"+encodeURIComponent(u.sessionName)+"/upload";let w=1e3;const rt=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function g(e){c?.readyState===WebSocket.OPEN&&c.send(JSON.stringify(e))}function K(){let e=et;const t=localStorage.getItem("tmux-web-token");t&&(e+=(e.includes("?")?"&":"?")+"token="+encodeURIComponent(t)),c=new WebSocket(e),c.onopen=()=>{d="connecting",x=0,T=!1,E=[],h="",i.reset(),w=1e3},c.onmessage=n=>{typeof n.data=="string"&&$(n.data)},c.onclose=()=>{S(!1),d="connecting",setTimeout(()=>{w=Math.min(w*2,1e4),K()},w)},c.onerror=()=>c?.close()}function L(e){g({type:"input",data:e})}function it(e){L(e)}function U(e){return e.split(`\r
1
+ const q="https://esm.sh/ghostty-web@0.4.0",J=/\x1b\](?:10|11|110|111|104)(?:;[^\x07\x1b]*)?\x1b?(?:\\|\x07)/g;function v(e){return e.replace(J,"")}let m;function G(){return m||(document.querySelector("link[data-tmux-web-xterm-css]")?m=Promise.resolve():(m=new Promise(t=>{const n=document.createElement("link");n.rel="stylesheet",n.href="/assets/xterm.css",n.setAttribute("data-tmux-web-xterm-css",""),n.addEventListener("load",()=>t(),{once:!0}),n.addEventListener("error",()=>t(),{once:!0}),document.head.appendChild(n)}),m))}class F{terminal;fitAddon;container;constructor(t,n,r){this.container=t,this.terminal=n,this.fitAddon=r,this.terminal.loadAddon(this.fitAddon),this.terminal.open(t)}static async create(t,n,r){const[{Terminal:a},{FitAddon:d}]=await Promise.all([import("@xterm/xterm"),import("@xterm/addon-fit"),G()]),b=new a({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:n,convertEol:!1,theme:r});return new F(t,b,new d)}get cols(){return this.terminal.cols}get rows(){return this.terminal.rows}write(t){return new Promise(n=>this.terminal.write(t,n))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom()}scrollToLine(t){this.terminal.scrollToLine(Math.max(0,t))}isNearScrollbackTop(){return this.terminal.buffer.active.viewportY<=1}viewportY(){return this.terminal.buffer.active.viewportY}baseY(){return this.terminal.buffer.active.baseY}fit(){const t=V(this.container);return t.width<=0||t.height<=0?!1:(this.fitAddon.fit(),!0)}focus(){this.terminal.focus()}pasteText(t){this.terminal.paste(t)}input(t){this.terminal.input(t,!1)}onData(t){this.terminal.onData(t),this.terminal.onBinary(t)}onResize(t){this.terminal.onResize(t)}onScroll(t){this.terminal.onScroll(t)}attachCustomKeyEventHandler(t){this.terminal.attachCustomKeyEventHandler(t)}isFocused(){const t=document.activeElement;return!!t&&(t===this.container||this.container.contains(t))}}class W{terminal;container;colsValue=80;rowsValue=24;charW=0;charH=0;resizeCallbacks=[];constructor(t,n){this.container=t,this.terminal=n,this.terminal.open(t)}static async create(t,n,r){const a=await import(q);await a.init();const d=new a.Terminal({fontSize:14,fontFamily:"'JetBrains Mono', 'SF Mono', 'Menlo', monospace",cursorBlink:!0,cursorStyle:"bar",scrollback:n,convertEol:!1,theme:r});return new W(t,d)}get cols(){return this.colsValue}get rows(){return this.rowsValue}write(t){return new Promise(n=>this.terminal.write(t,n))}reset(){this.terminal.reset()}scrollToBottom(){this.terminal.scrollToBottom?.()}scrollToLine(t){this.terminal.scrollToLine?.(Math.max(0,t))}isNearScrollbackTop(){const t=this.terminal.buffer?.active;return t?t.viewportY>=t.baseY:!1}viewportY(){return this.terminal.buffer?.active?.viewportY??0}baseY(){return this.terminal.buffer?.active?.baseY??0}fit(){const t=V(this.container);if(t.width<=0||t.height<=0)return!1;this.updateCellMetrics(!this.charW||!this.charH);const n=Math.floor(t.width/this.charW),r=Math.floor(t.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(const a of this.resizeCallbacks)a({cols:n,rows:r})}return!0}focus(){(this.terminal.textarea||this.container.querySelector("textarea")||this.container)?.focus?.()}pasteText(t){const n=this.terminal.getMode?.(2004)??!1;this.input(n?"\x1B[200~"+t+"\x1B[201~":t)}input(t){this.terminal.input?.(t,!1)}onData(t){this.terminal.onData(n=>t(n))}onResize(t){this.resizeCallbacks.push(t)}onScroll(t){this.terminal.onScroll(t)}attachCustomKeyEventHandler(t){this.terminal.attachCustomKeyEventHandler(t)}isFocused(){const t=document.activeElement;return!!t&&(t===this.container||t===this.terminal.textarea||this.container.contains(t))}updateCellMetrics(t=!1){const n=this.container.querySelector("canvas");if(n instanceof HTMLElement&&n.offsetWidth>0&&n.offsetHeight>0&&this.colsValue>0&&this.rowsValue>0){const r=n.offsetWidth/this.colsValue,a=n.offsetHeight/this.rowsValue;(t||!this.charW||!this.charH)&&(this.charW=r,this.charH=a)}(!this.charW||!this.charH)&&(this.charW=9,this.charH=18)}}const R=window.__TMUX_WEB_TERMINAL__;if(!R)throw new Error("missing tmux-web terminal config");const u=R,H=document.getElementById("terminal-container");if(!H)throw new Error("missing terminal container");const o=H;function Q(){const e=document.createElement("div");e.textContent="ghostty-web unavailable \u2014 using xterm.js",e.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(e),setTimeout(()=>e.remove(),6e3)}async function Z(){if(u.renderer==="ghostty")try{return await W.create(o,u.scrollback,u.theme)}catch(e){console.error("[tmux-web] ghostty-web failed to load; falling back to xterm.js:",e),Q()}return F.create(o,u.scrollback,u.theme)}const i=await Z();let c,x=0,P,s=null,Y=0,f="connecting",T=0,E=!1,k=[],h="";function $(){return k.join("")+h}async function tt(e,t=0){const n=e?i.viewportY():0,r=e?i.baseY():0,a=v($());if(i.reset(),!a){e||i.scrollToBottom();return}await i.write(a),e?i.scrollToLine(r+n+t):i.scrollToBottom()}function et(e){let t;try{t=JSON.parse(e)}catch{f==="live"&&(h+=e,i.write(v(e)));return}if(t.type==="auth.required"){const n=localStorage.getItem("tmux-web-token");n?g({type:"auth.token",token:n}):location.href="/login?returnTo="+encodeURIComponent(location.pathname+location.search);return}if(t.type==="auth.ok"){t.token&&localStorage.setItem("tmux-web-token",t.token),L(!0),w=1e3,p(),g({type:"resize",cols:i.cols,rows:i.rows}),l();return}if(t.type==="auth.failed"){if(L(!1),t.permanentLock||t.retryAfterMs&&t.retryAfterMs>6e4){localStorage.removeItem("tmux-web-token"),location.href="/login?error="+encodeURIComponent(t.message);return}const n=document.createElement("div");n.textContent="Auth failed: "+t.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(t.type==="snapshot"&&typeof t.data=="string"){const n=v(t.data);k=[n],h="",T=typeof t.lines=="number"?t.lines:u.terminal.initialLines,f="live",i.reset(),i.write(n).then(()=>i.scrollToBottom());return}if(t.type==="window_changed"&&typeof t.activeIndex=="number"){const n=new URL(location.href);n.searchParams.get("window")!==String(t.activeIndex)&&(n.searchParams.set("window",String(t.activeIndex)),history.replaceState(history.state,"",n)),window.dispatchEvent(new CustomEvent("tmux:windows",{detail:t.windows}));return}if(t.type==="history"&&typeof t.data=="string"){E=!1,t.lines>0&&t.data&&(k.unshift(t.data),T+=t.lines,tt(!0,t.lines));return}if(t.type==="data"&&typeof t.data=="string"){const n=v(t.data);if(f==="connecting"){f="live",h=n,i.write(n);return}f==="live"&&(h+=n,i.write(n))}}function V(e){const t=e.getBoundingClientRect(),n=window.visualViewport;return n?{width:Math.min(t.width,n.width),height:Math.max(0,Math.min(t.height,n.height-Math.max(0,t.top)))}:t}function p(){return i.fit()}function I(){o.classList.remove("terminal-pending")}function l(){x&&cancelAnimationFrame(x),P&&clearTimeout(P),p(),x=requestAnimationFrame(()=>{x=0,p()&&I()}),P=setTimeout(()=>{p()&&I()},120)}function N(){l(),setTimeout(l,50),setTimeout(l,150),setTimeout(l,300)}const O=document.getElementById("status-dot"),S=document.getElementById("status-text");function L(e){O&&(O.className="dot"+(e?" connected":"")),S&&(S.textContent=e?"connected":"reconnecting")}const nt=location.protocol==="https:"?"wss:":"ws:",rt=nt+"//"+location.host+"/ws/"+encodeURIComponent(u.sessionName),it="/api/session/"+encodeURIComponent(u.sessionName)+"/upload";let w=1e3;const ot=/^((?!chrome|android|crios|fxios|edgios).)*safari/i.test(navigator.userAgent);function g(e){c?.readyState===WebSocket.OPEN&&c.send(JSON.stringify(e))}function _(){let e=rt;const t=localStorage.getItem("tmux-web-token");t&&(e+=(e.includes("?")?"&":"?")+"token="+encodeURIComponent(t)),c=new WebSocket(e),c.onopen=()=>{f="connecting",T=0,E=!1,k=[],h="",i.reset(),w=1e3},c.onmessage=n=>{typeof n.data=="string"&&et(n.data)},c.onclose=()=>{L(!1),f="connecting",setTimeout(()=>{w=Math.min(w*2,1e4),_()},w)},c.onerror=()=>c?.close()}function C(e){g({type:"input",data:e})}function at(e){C(e)}function K(e){return e.split(`\r
2
2
  `).join(`
3
3
  `).split(`
4
- `).join("\r")}function X(e){return typeof e=="string"&&e.startsWith("image/")}function _(e){return e?.files?.length?e.files[0]??null:null}function ot(e){if(!e?.items)return null;for(let t=0;t<e.items.length;t++){const n=e.items[t];if(n?.kind==="file"&&X(n.type))return n.getAsFile()}return null}function D(e){e&&k?k.textContent=e:S(c?.readyState===WebSocket.OPEN)}async function at(e){const t=new FormData,n=e instanceof File&&e.name?e.name:"upload";t.append("file",e,n);const r=localStorage.getItem("tmux-web-token"),a={};r&&(a.Authorization="Bearer "+r);const f=await fetch(nt,{method:"POST",body:t,headers:a});if(!f.ok){let W="upload failed";try{const z=await f.json();z.error&&(W=z.error)}catch{}throw new Error(W)}const b=await f.json();if(!b.path)throw new Error("no path in response");return b.path}async function I(e){try{D("uploading...");const t=await at(e);it(t),D(null)}catch(t){console.warn("image upload:",t),D("upload failed"),setTimeout(()=>D(null),2e3)}}i.onData(e=>L(e)),i.onResize(({cols:e,rows:t})=>g({type:"resize",cols:e,rows:t})),window.tmuxWeb={sendInput:L,focusTerminal:j},i.onScroll(()=>{d!=="live"||T||!i.isNearScrollbackTop()||(T=!0,g({type:"load_history",before:x}))}),i.attachCustomKeyEventHandler(e=>e.type!=="keydown"?!0:(e.ctrlKey||e.metaKey)&&e.code==="KeyV"?(e.preventDefault(),(async()=>{try{if(navigator.clipboard?.read){const t=await navigator.clipboard.read();for(const n of t)for(const r of n.types)if(X(r)){const a=await n.getType(r);await I(a);return}}}catch{}try{const t=await navigator.clipboard?.readText();t&&i.pasteText(U(t))}catch{}})(),!1):!0);let M=0;async function st(e){const t=ot(e.clipboardData);if(t){e.preventDefault(),e.stopPropagation();const a=Date.now();if(a-M<50)return;M=a,await I(t);return}const n=e.clipboardData?.getData("text/plain");if(!n)return;e.preventDefault(),e.stopPropagation();const r=Date.now();r-M<50||(M=r,i.pasteText(U(n)))}o.addEventListener("paste",st);let y=0;o.addEventListener("dragenter",e=>{e.preventDefault(),y++,_(e.dataTransfer)&&o.classList.add("terminal-drag-over")}),o.addEventListener("dragover",e=>{e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="copy")}),o.addEventListener("dragleave",e=>{e.preventDefault(),y--,y<=0&&(y=0,o.classList.remove("terminal-drag-over"))}),o.addEventListener("drop",async e=>{e.preventDefault(),y=0,o.classList.remove("terminal-drag-over");const t=_(e.dataTransfer);t&&await I(t)}),document.addEventListener("keydown",e=>{!rt||e.key!=="Escape"||e.defaultPrevented||e.repeat||e.metaKey||e.ctrlKey||e.altKey||i.isFocused()&&(e.preventDefault(),e.stopPropagation(),L("\x1B"))},!0);function lt(e,t,n){(o.querySelector(".xterm-screen")??o).dispatchEvent(new WheelEvent("wheel",{deltaY:e,deltaMode:WheelEvent.DOM_DELTA_PIXEL,clientX:t,clientY:n,bubbles:!0,cancelable:!0}))}function j(){i.focus(),V()}o.addEventListener("touchstart",e=>{if(e.touches.length!==1){s=null;return}const t=e.touches[0];t&&(s={startX:t.clientX,startY:t.clientY,lastX:t.clientX,lastY:t.clientY,scrolling:!1},e.stopPropagation())},{passive:!0,capture:!0}),o.addEventListener("touchmove",e=>{if(!s||e.touches.length!==1)return;const t=e.touches[0];if(!t)return;const n=t.clientY-s.startY,r=t.clientX-s.startX;if(!s.scrolling){if(Math.abs(n)<8||Math.abs(n)<Math.abs(r))return;s.scrolling=!0,P=Date.now()+500}e.preventDefault(),e.stopPropagation(),lt(-(t.clientY-s.lastY),t.clientX,t.clientY),s.lastX=t.clientX,s.lastY=t.clientY},{passive:!1,capture:!0}),o.addEventListener("touchend",e=>{if(!s)return;const t=s.scrolling;s=null,e.stopPropagation(),t?(P=Date.now()+500,e.preventDefault()):j()},{passive:!1,capture:!0}),o.addEventListener("touchcancel",e=>{s=null,e.stopPropagation()},{passive:!0,capture:!0}),o.addEventListener("pointerup",e=>{e.pointerType==="touch"&&Date.now()<P&&(e.preventDefault(),e.stopPropagation())},!0),window.addEventListener("resize",l),window.visualViewport?.addEventListener("resize",l),window.visualViewport?.addEventListener("scroll",l),new ResizeObserver(l).observe(o),document.fonts?.ready.then(()=>{l(),setTimeout(l,50),setTimeout(l,200)}),o.addEventListener("focusin",V,!0),requestAnimationFrame(()=>{p()&&Y(),K(),l()});
4
+ `).join("\r")}function U(e){return typeof e=="string"&&e.startsWith("image/")}function X(e){return e?.files?.length?e.files[0]??null:null}function st(e){if(!e?.items)return null;for(let t=0;t<e.items.length;t++){const n=e.items[t];if(n?.kind==="file"&&U(n.type))return n.getAsFile()}return null}function D(e){e&&S?S.textContent=e:L(c?.readyState===WebSocket.OPEN)}async function lt(e){const t=new FormData,n=e instanceof File&&e.name?e.name:"upload";t.append("file",e,n);const r=localStorage.getItem("tmux-web-token"),a={};r&&(a.Authorization="Bearer "+r);const d=await fetch(it,{method:"POST",body:t,headers:a});if(!d.ok){let z="upload failed";try{const A=await d.json();A.error&&(z=A.error)}catch{}throw new Error(z)}const b=await d.json();if(!b.path)throw new Error("no path in response");return b.path}async function B(e){try{D("uploading...");const t=await lt(e);at(t),D(null)}catch(t){console.warn("image upload:",t),D("upload failed"),setTimeout(()=>D(null),2e3)}}i.onData(e=>C(e)),i.onResize(({cols:e,rows:t})=>g({type:"resize",cols:e,rows:t})),window.tmuxWeb={sendInput:C,focusTerminal:j},i.onScroll(()=>{f!=="live"||E||!i.isNearScrollbackTop()||(E=!0,g({type:"load_history",before:T}))}),i.attachCustomKeyEventHandler(e=>e.type!=="keydown"?!0:(e.ctrlKey||e.metaKey)&&e.code==="KeyV"?(e.preventDefault(),(async()=>{try{if(navigator.clipboard?.read){const t=await navigator.clipboard.read();for(const n of t)for(const r of n.types)if(U(r)){const a=await n.getType(r);await B(a);return}}}catch{}try{const t=await navigator.clipboard?.readText();t&&i.pasteText(K(t))}catch{}})(),!1):!0);let M=0;async function ct(e){const t=st(e.clipboardData);if(t){e.preventDefault(),e.stopPropagation();const a=Date.now();if(a-M<50)return;M=a,await B(t);return}const n=e.clipboardData?.getData("text/plain");if(!n)return;e.preventDefault(),e.stopPropagation();const r=Date.now();r-M<50||(M=r,i.pasteText(K(n)))}o.addEventListener("paste",ct);let y=0;o.addEventListener("dragenter",e=>{e.preventDefault(),y++,X(e.dataTransfer)&&o.classList.add("terminal-drag-over")}),o.addEventListener("dragover",e=>{e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="copy")}),o.addEventListener("dragleave",e=>{e.preventDefault(),y--,y<=0&&(y=0,o.classList.remove("terminal-drag-over"))}),o.addEventListener("drop",async e=>{e.preventDefault(),y=0,o.classList.remove("terminal-drag-over");const t=X(e.dataTransfer);t&&await B(t)}),document.addEventListener("keydown",e=>{!ot||e.key!=="Escape"||e.defaultPrevented||e.repeat||e.metaKey||e.ctrlKey||e.altKey||i.isFocused()&&(e.preventDefault(),e.stopPropagation(),C("\x1B"))},!0);function ut(e,t,n){(o.querySelector(".xterm-screen")??o).dispatchEvent(new WheelEvent("wheel",{deltaY:e,deltaMode:WheelEvent.DOM_DELTA_PIXEL,clientX:t,clientY:n,bubbles:!0,cancelable:!0}))}function j(){i.focus(),N()}o.addEventListener("touchstart",e=>{if(e.touches.length!==1){s=null;return}const t=e.touches[0];t&&(s={startX:t.clientX,startY:t.clientY,lastX:t.clientX,lastY:t.clientY,scrolling:!1},e.stopPropagation())},{passive:!0,capture:!0}),o.addEventListener("touchmove",e=>{if(!s||e.touches.length!==1)return;const t=e.touches[0];if(!t)return;const n=t.clientY-s.startY,r=t.clientX-s.startX;if(!s.scrolling){if(Math.abs(n)<8||Math.abs(n)<Math.abs(r))return;s.scrolling=!0,Y=Date.now()+500}e.preventDefault(),e.stopPropagation(),ut(-(t.clientY-s.lastY),t.clientX,t.clientY),s.lastX=t.clientX,s.lastY=t.clientY},{passive:!1,capture:!0}),o.addEventListener("touchend",e=>{if(!s)return;const t=s.scrolling;s=null,e.stopPropagation(),t?(Y=Date.now()+500,e.preventDefault()):j()},{passive:!1,capture:!0}),o.addEventListener("touchcancel",e=>{s=null,e.stopPropagation()},{passive:!0,capture:!0}),o.addEventListener("pointerup",e=>{e.pointerType==="touch"&&Date.now()<Y&&(e.preventDefault(),e.stopPropagation())},!0),window.addEventListener("resize",l),window.visualViewport?.addEventListener("resize",l),window.visualViewport?.addEventListener("scroll",l),new ResizeObserver(l).observe(o),document.fonts?.ready.then(()=>{l(),setTimeout(l,50),setTimeout(l,200)}),o.addEventListener("focusin",N,!0),requestAnimationFrame(()=>{p()&&I(),_(),l()});
@@ -0,0 +1,253 @@
1
+ function s(){return`
2
+ #terminal-layout {
3
+ display: flex;
4
+ flex: 1;
5
+ min-height: 0;
6
+ overflow: hidden;
7
+ }
8
+ #session-sidebar {
9
+ width: 220px;
10
+ flex-shrink: 0;
11
+ background: var(--panel-bg);
12
+ border-right: 1px solid var(--panel-border);
13
+ display: flex;
14
+ flex-direction: column;
15
+ overflow: hidden;
16
+ transition: width 0.2s ease, border-color 0.2s ease;
17
+ }
18
+ #session-sidebar.collapsed {
19
+ width: 0;
20
+ border-right-color: transparent;
21
+ }
22
+ #session-sidebar .sidebar-header {
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: space-between;
26
+ padding: 10px 12px;
27
+ border-bottom: 1px solid var(--panel-border);
28
+ font-size: var(--text-xs);
29
+ font-weight: 600;
30
+ letter-spacing: 0.05em;
31
+ text-transform: uppercase;
32
+ color: var(--panel-accent);
33
+ font-family: var(--font-mono);
34
+ flex-shrink: 0;
35
+ }
36
+ #session-sidebar .sidebar-list {
37
+ flex: 1;
38
+ overflow-y: auto;
39
+ padding: 8px 0;
40
+ scrollbar-width: thin;
41
+ scrollbar-color: var(--panel-border) transparent;
42
+ }
43
+ #session-sidebar .sidebar-list::-webkit-scrollbar { width: 4px; }
44
+ #session-sidebar .sidebar-list::-webkit-scrollbar-track { background: transparent; }
45
+ #session-sidebar .sidebar-list::-webkit-scrollbar-thumb {
46
+ background: var(--panel-border); border-radius: 2px;
47
+ }
48
+ #session-sidebar .sidebar-list::-webkit-scrollbar-thumb:hover { background: var(--panel-muted); }
49
+ #session-sidebar .sidebar-empty {
50
+ padding: 16px;
51
+ text-align: center;
52
+ color: var(--panel-muted);
53
+ font-size: var(--text-xs);
54
+ font-family: var(--font-mono);
55
+ }
56
+ #session-sidebar .sidebar-row {
57
+ display: flex;
58
+ align-items: center;
59
+ gap: 8px;
60
+ width: 100%;
61
+ min-height: 40px;
62
+ padding: 8px 12px;
63
+ background: none;
64
+ border: none;
65
+ border-bottom: 1px solid var(--panel-border);
66
+ color: var(--page-fg);
67
+ cursor: pointer;
68
+ text-align: left;
69
+ font-family: var(--font-mono);
70
+ font-size: var(--text-sm);
71
+ transition: background 0.15s;
72
+ text-decoration: none;
73
+ }
74
+ #session-sidebar .sidebar-row:last-child { border-bottom: none; }
75
+ #session-sidebar .sidebar-row:hover { background: color-mix(in srgb, var(--panel-accent) 8%, transparent); }
76
+ #session-sidebar .sidebar-row.current {
77
+ background: color-mix(in srgb, var(--panel-accent) 12%, transparent);
78
+ color: var(--panel-accent);
79
+ font-weight: 500;
80
+ }
81
+ #session-sidebar .sidebar-row-name {
82
+ flex: 1;
83
+ min-width: 0;
84
+ overflow: hidden;
85
+ text-overflow: ellipsis;
86
+ white-space: nowrap;
87
+ }
88
+ #session-sidebar .sidebar-row-dot {
89
+ width: 8px;
90
+ height: 8px;
91
+ border-radius: 50%;
92
+ background: var(--panel-muted);
93
+ flex-shrink: 0;
94
+ }
95
+ #session-sidebar .sidebar-row.current .sidebar-row-dot { background: var(--panel-accent); }
96
+ #session-sidebar .sidebar-row.attached .sidebar-row-dot { background: var(--panel-success); }
97
+ #session-sidebar-toggle {
98
+ display: none;
99
+ align-items: center;
100
+ justify-content: center;
101
+ background: none;
102
+ border: none;
103
+ color: var(--panel-muted);
104
+ cursor: pointer;
105
+ min-width: 44px;
106
+ min-height: 44px;
107
+ padding: 8px;
108
+ border-radius: 10px;
109
+ transition: color 0.15s, background 0.15s;
110
+ font-size: var(--text-sm);
111
+ }
112
+ #session-sidebar-toggle:hover { color: var(--panel-accent); background: color-mix(in srgb, var(--panel-accent) 8%, transparent); }
113
+ #session-sidebar-toggle svg { width: 18px; height: 18px; fill: currentColor; }
114
+ @media (max-width: 768px) {
115
+ #session-sidebar {
116
+ position: fixed;
117
+ left: 0;
118
+ top: 0;
119
+ height: 100%;
120
+ z-index: 1000;
121
+ width: min(280px, 80vw);
122
+ transform: translateX(-100%);
123
+ transition: transform 0.25s ease;
124
+ }
125
+ #session-sidebar.open { transform: translateX(0); }
126
+ #session-sidebar.collapsed { width: min(280px, 80vw); }
127
+ #session-sidebar-backdrop {
128
+ position: fixed;
129
+ inset: 0;
130
+ background: rgba(0,0,0,0.45);
131
+ z-index: 999;
132
+ opacity: 0;
133
+ pointer-events: none;
134
+ transition: opacity 0.2s ease;
135
+ }
136
+ #session-sidebar-backdrop.open { opacity: 1; pointer-events: auto; }
137
+ #session-sidebar-toggle { display: flex; }
138
+ }
139
+ @media (min-width: 769px) {
140
+ #session-sidebar-backdrop { display: none; }
141
+ }
142
+ `}function i(e){return`
143
+ <div id="session-sidebar-backdrop"></div>
144
+ <aside id="session-sidebar" aria-label="Sessions">
145
+ <div class="sidebar-header">
146
+ <span>Sessions</span>
147
+ <button type="button" id="session-sidebar-close" class="header-icon-btn" aria-label="Close sessions">\xD7</button>
148
+ </div>
149
+ <div class="sidebar-list" id="session-sidebar-list">
150
+ <div class="sidebar-empty">Loading sessions\u2026</div>
151
+ </div>
152
+ </aside>`}function n(e){return`
153
+ (function () {
154
+ const SIDEBAR_CURRENT = ${JSON.stringify(e)};
155
+ const sidebar = document.getElementById('session-sidebar');
156
+ const backdrop = document.getElementById('session-sidebar-backdrop');
157
+ const list = document.getElementById('session-sidebar-list');
158
+ const toggleBtn = document.getElementById('session-sidebar-toggle');
159
+ const closeBtn = document.getElementById('session-sidebar-close');
160
+
161
+ function isMobile() {
162
+ return window.innerWidth <= 768;
163
+ }
164
+
165
+ function openSidebar() {
166
+ if (isMobile()) {
167
+ sidebar.classList.add('open');
168
+ backdrop.classList.add('open');
169
+ } else {
170
+ sidebar.classList.remove('collapsed');
171
+ try { localStorage.setItem('tmux-web:session-sidebar', 'open'); } catch {}
172
+ }
173
+ }
174
+
175
+ function closeSidebar() {
176
+ if (isMobile()) {
177
+ sidebar.classList.remove('open');
178
+ backdrop.classList.remove('open');
179
+ } else {
180
+ sidebar.classList.add('collapsed');
181
+ try { localStorage.setItem('tmux-web:session-sidebar', 'collapsed'); } catch {}
182
+ }
183
+ }
184
+
185
+ function toggleSidebar() {
186
+ if (isMobile()) {
187
+ sidebar.classList.contains('open') ? closeSidebar() : openSidebar();
188
+ } else {
189
+ sidebar.classList.contains('collapsed') ? openSidebar() : closeSidebar();
190
+ }
191
+ }
192
+
193
+ function renderSessions(sessions) {
194
+ list.innerHTML = '';
195
+ if (!sessions || !sessions.length) {
196
+ list.innerHTML = '<div class="sidebar-empty">No tmux sessions</div>';
197
+ return;
198
+ }
199
+ sessions.forEach((session) => {
200
+ const row = document.createElement('a');
201
+ row.className = 'sidebar-row' +
202
+ (session.name === SIDEBAR_CURRENT ? ' current' : '') +
203
+ (session.attached ? ' attached' : '');
204
+ row.href = '/s/' + encodeURIComponent(session.name);
205
+ row.title = session.name + ' \xB7 ' + session.windows + ' window' + (session.windows === 1 ? '' : 's');
206
+
207
+ const dot = document.createElement('span');
208
+ dot.className = 'sidebar-row-dot';
209
+
210
+ const name = document.createElement('span');
211
+ name.className = 'sidebar-row-name';
212
+ name.textContent = session.name;
213
+
214
+ row.appendChild(dot);
215
+ row.appendChild(name);
216
+ list.appendChild(row);
217
+ });
218
+ }
219
+
220
+ function renderSidebar() {
221
+ const cfg = window.__TMUX_WEB_TERMINAL__;
222
+ const data = cfg && cfg.sidebarSessions ? cfg.sidebarSessions : { pinned: [], recent: [] };
223
+ const sessions = (data.recent || []).concat(data.pinned ? data.pinned.map((p) => ({
224
+ name: p.sessionName,
225
+ windows: p.windows ?? 0,
226
+ attached: p.attached ?? false,
227
+ })) : []);
228
+ const seen = new Set();
229
+ const unique = [];
230
+ sessions.forEach((s) => { if (!seen.has(s.name)) { seen.add(s.name); unique.push(s); } });
231
+ unique.sort((a, b) => {
232
+ if (a.name === SIDEBAR_CURRENT) return -1;
233
+ if (b.name === SIDEBAR_CURRENT) return 1;
234
+ return a.name.localeCompare(b.name);
235
+ });
236
+ renderSessions(unique);
237
+ }
238
+
239
+ if (toggleBtn) toggleBtn.addEventListener('click', toggleSidebar);
240
+ if (closeBtn) closeBtn.addEventListener('click', closeSidebar);
241
+ if (backdrop) backdrop.addEventListener('click', closeSidebar);
242
+
243
+ // Restore desktop collapsed state.
244
+ try {
245
+ const saved = localStorage.getItem('tmux-web:session-sidebar');
246
+ if (saved === 'collapsed' && !isMobile()) sidebar.classList.add('collapsed');
247
+ } catch {}
248
+
249
+ renderSidebar();
250
+ })();
251
+ `}function o(){return`<button type="button" id="session-sidebar-toggle" class="header-icon-btn" title="Toggle sessions sidebar" aria-label="Toggle sessions sidebar">
252
+ <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></svg>
253
+ </button>`}export{s as sessionSidebarCSS,i as sessionSidebarHTML,n as sessionSidebarScript,o as sessionSidebarToggleButtonHTML};
@@ -1 +1 @@
1
- const e={template:"warm-clay",shell:{pageBg:"#faf8f5",pageFg:"#2d2926",panelBg:"#ffffff",panelBorder:"#ebe5df",panelMuted:"#7b726b",panelAccent:"#b86b52",panelAccentOn:"#ffffff",panelSuccess:"#6b9e7c",terminalBg:"#2b2623",headerGradient:"linear-gradient(180deg, rgba(255,255,255,0.98), rgba(250,248,245,0.98))"},terminal:{foreground:"#e8e2dc",background:"#2b2623",cursor:"#e8e2dc",cursorAccent:"#2b2623",selectionBackground:"rgba(184, 107, 82, 0.35)",selectionForeground:"#e8e2dc",black:"#2b2623",red:"#d88a8a",green:"#8fc49f",yellow:"#e0c28a",blue:"#8ab4d8",magenta:"#c9a5c9",cyan:"#8ad0d0",white:"#d8d0c8",brightBlack:"#4a433e",brightRed:"#e8a0a0",brightGreen:"#a5d6b2",brightYellow:"#efd69a",brightBlue:"#a5c8e8",brightMagenta:"#d9b8d9",brightCyan:"#a0dede",brightWhite:"#f5f0eb"}};export{e as warmClayTheme};
1
+ const e={template:"warm-clay",shell:{pageBg:"#faf8f5",pageFg:"#2d2926",panelBg:"#ffffff",panelBorder:"#ebe5df",panelMuted:"#7b726b",panelAccent:"#b86b52",panelAccentOn:"#ffffff",panelSuccess:"#6b9e7c",terminalBg:"#faf8f5",headerGradient:"linear-gradient(180deg, rgba(255,255,255,0.98), rgba(250,248,245,0.98))"},terminal:{foreground:"#2d2926",background:"#faf8f5",cursor:"#2d2926",cursorAccent:"#faf8f5",selectionBackground:"rgba(184, 107, 82, 0.35)",selectionForeground:"#2d2926",black:"#2d2926",red:"#b94a4a",green:"#3d7a4f",yellow:"#9a7a2f",blue:"#3b6b9e",magenta:"#8a5a8a",cyan:"#2f8a8a",white:"#7b726b",brightBlack:"#5a524c",brightRed:"#c94f4f",brightGreen:"#4a9060",brightYellow:"#b08630",brightBlue:"#4477b0",brightMagenta:"#9c6a9c",brightCyan:"#389898",brightWhite:"#2d2926"}};export{e as warmClayTheme};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmux-weblink",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Access your tmux sessions from the browser. A continuation of tmux-web and persalink.",
5
5
  "type": "module",
6
6
  "bin": {