0

I'm currently making an app with vite & WebContainers and have no prior experience with the API or xterm. I followed this tutotial and everything worked well until I decided to add tabs to switch from the terminal, to the editor to the preview box. Then the terminal stopped accepting any input. There weren't any error messages. I didn't change anything to do with the Xterm configuration either. My main.js:

import "./style.css";
import { files } from "./files";
import "xterm/css/xterm.css";
import { Terminal } from "xterm";
import { WebContainer } from "@webcontainer/api";

let WebContainerInstance;

window.addEventListener("load", async () => {
  textareaEl.style.height = `${window.innerHeight}px`;
  
  textareaEl.value = files["index.js"].file.contents;

  textareaEl.addEventListener("input", () => {
    writeIndexJS(textareaEl.currentTarget.value);
  });

  const terminal = new Terminal({
    convertEol: true,
  });
  
  terminal.open(terminalEl);

  WebContainerInstance = await WebContainer.boot();

  await WebContainerInstance.mount(files);

  WebContainerInstance.on("server-ready", (port, url) => {
    iframeEl.src = url;
  });

  startShell(terminal);
});

async function startShell(terminal) {
  const shellProcess = await WebContainerInstance.spawn("jsh");

  shellProcess.output.pipeTo(
    new WritableStream({
      write(data) {
        terminal.write(data);
      },
    })
  );

  const input = shellProcess.input.getWriter();
  
  terminal.onData((data) => {
    input.write(data);
  });
  
  return shellProcess;
}

async function writeIndexJS(content) {
  await WebContainerInstance.fs.writeFile("./index.js", content);
}

document.querySelector("#app").innerHTML = `
 <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0"/>
 
 <div class="header">
  <ul>
    <li id="term"><span class="material-symbols-outlined">terminal</span></li>
    <li id="code"><span class="material-symbols-outlined">code</span></li>
    <li id="prev"><span class="material-symbols-outlined">preview</span></li>
  </ul>
 </div>
 
 <div class="terminal">
 
 </div>
  
  <div class="editor">
   <textarea spellcheck="false"></textarea>
 </div>
 
 <div class="output">
    <iframe src="/load.html">
  </div>
`;

const iframeEl = document.querySelector("iframe");

const textareaEl = document.querySelector("textarea");

const terminalEl = document.querySelector(".terminal");

document.getElementById("term").addEventListener("click", () => {
  textareaEl.style.display = "none";
  iframeEl.style.display = "none";
  terminalEl.style.display = "block";
});

document.getElementById("code").addEventListener("click", () => {
  terminalEl.style.display = "none";
  iframeEl.style.display = "none";
  textareaEl.style.display = "block";
});

document.getElementById("prev").addEventListener("click", () => {
  textareaEl.style.display = "none";
  terminalEl.style.display = "none";
  iframeEl.style.display = "block";
});

Style.css:

@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@900&display=swap");

* {
  margin: 0px;
  padding: 0px;
}

#app {
   height: 100%;
   width: 100%;
}

body {
  background-color: #000000;
}

.header {
  background-color: #191919;
  display: flex;
  width: 100%;
  height: 64px;
}

ul {
  display: flex;
  flex-direction: row;
  align-items: center;
}

li {
  width: 45px;
  height: 45px;
  border-radius: 50%;
  background-color: #000000;
  color: #ffffff;
  display: flex;
  text-decoration: none;
  align-items: center;
  justify-content: center;
  margin: 2px;
}

#app h1 {
   font-family: "Poppins", sans-serif;
   color: #ffffff;
   font-size: clamp(3em, 3.25em, 3.5em);
}

#app h3 {
   font-family: "Poppins", sans-serif;
   color: #ffffff;
}

#app textarea {
  width: 100%;
  color: white;
  background: black;
  display: none;
}


#app iframe {
  height: 100%;
  width: 100%;
  display: none;
}

Thanks!

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105

0 Answers0