HEL/helwasm/index.html
2023-01-09 13:53:58 +01:00

173 lines
4.5 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
html {
height: 100%;
}
body {
min-height: 100%;
}
html,
body {
background-color: #000;
width: 100%;
margin: 0;
padding: 0;
font-family: monospace;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.terminal {
height: 100%;
width: 100%;
margin: 0 auto;
color: #fff;
overflow-y: scroll;
padding: 20px;
}
.prompt {
color: #0f0;
}
.form {
display: flex;
width: 100vw;
margin: 0 auto;
}
.input {
background-color: transparent;
border: none;
color: #fff;
outline: none;
flex-grow: 1;
}
.input::placeholder {
color: #666;
}
label {
width: 100%;
white-space: nowrap;
display: inline-flex;
}
.terminal p,
.prompt,
.input {
font-family: monospace;
font-size: 16px;
white-space: pre-wrap;
}
#passwordPrompt {
position: fixed;
top: 50%;
left: 50%;
tranform: translate(-50%, -50%);
backrground-color: white;
border: 1px solid black;
padding: 20px;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="module">
import init, { hel_init, hel_command } from "./pkg/helwasm.js";
init().then(() => {
window.hel = {
hel_init: hel_init,
hel_command: hel_command,
}
});
</script>
<script type="text/babel">
function Terminal() {
const prompt = "> ";
const [input, setInput] = React.useState("");
const [output, setOutput] = React.useState([]);
const [passwordPrompt, setPasswordPrompt] = React.useState(undefined);
const [passwordInput, setPasswordInput] = React.useState("");
const outputRef = React.useRef(null);
React.useEffect(() => {
outputRef.current.scrollIntoView({ behaviour: "smooth" });
}, [output]);
function handleInput(event) {
setInput(event.target.value);
}
function handleSubmit(event) {
event.preventDefault();
const result = executeCommand(input);
setOutput([...output, { prompt: prompt, command: input }, { prompt: "", command: result }]);
setInput("");
}
function handlePasswordInput(event) {
setPasswordInput(event.target.value);
}
function handlePasswordSubmit(event) {
window.hel_current_password_value = passwordInput;
setPasswordPrompt(undefined);
setPasswordInput("");
}
function helReadPassword(prompt) {
window.hel_current_password_value = null;
setPasswordPrompt(prompt);
}
window.hel_read_password = helReadPassword;
function helCurrentPassword(prompt) {
return window.hel_current_password_value;
}
window.hel_current_password = helCurrentPassword;
function executeCommand(command) {
return window.hel.hel_command(command);
}
return (
<div className="terminal">
{output.map(({ prompt, command }, index) => (<p key={index}>{prompt && (<span className="prompt">{prompt}</span>)}{command}</p>))}
<form onSubmit={handleSubmit}>
<label>
<span className="prompt" ref={outputRef}>{prompt}</span>
<input
type="text"
value={input}
onChange={handleInput}
className="input"
autoFocus
/>
</label>
</form>
{passwordPrompt !== undefined && (<form onSubmit={handlePasswordSubmit}><label><span className="prompt">{passwordPrompt}</span><input type="password" value={passwordInput} onChange={handlePasswordInput} className="input" autoFocus /></label></form>)}
</div>
);
}
const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
root.render(<Terminal />);
</script>
</body>
</html>