mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-22 02:34:21 +08:00
Improve the example page. (#780)
This commit is contained in:
parent
b970cb6ea8
commit
6c2b43a2aa
2
.github/workflows/build.yaml
vendored
2
.github/workflows/build.yaml
vendored
@ -216,6 +216,8 @@ jobs:
|
||||
rsync -amv
|
||||
--include='*/'
|
||||
--include='*.html'
|
||||
--include='*.css'
|
||||
--include='*.mjs'
|
||||
--include='*.js'
|
||||
--include='*.wasm'
|
||||
--exclude='*'
|
||||
|
10
.gitignore
vendored
10
.gitignore
vendored
@ -34,14 +34,16 @@
|
||||
!doc/**/*.md
|
||||
|
||||
# examples directory:
|
||||
!examples/**/*.txt
|
||||
!examples/**/*.cpp
|
||||
!examples/**/*.css
|
||||
!examples/**/*.hpp
|
||||
!examples/**/*.ipp
|
||||
!examples/**/*.html
|
||||
!examples/**/*.py
|
||||
!examples/**/*.js
|
||||
!examples/**/*.html.disabled
|
||||
!examples/**/*.ipp
|
||||
!examples/**/*.js
|
||||
!examples/**/*.mjs
|
||||
!examples/**/*.py
|
||||
!examples/**/*.txt
|
||||
|
||||
# include directory:
|
||||
!include/ftxui/**/*.hpp
|
||||
|
@ -21,6 +21,8 @@ if (EMSCRIPTEN)
|
||||
get_property(EXAMPLES GLOBAL PROPERTY FTXUI::EXAMPLES)
|
||||
foreach(file
|
||||
"index.html"
|
||||
"index.mjs"
|
||||
"index.css"
|
||||
"sw.js"
|
||||
"run_webassembly.py")
|
||||
configure_file(${file} ${file})
|
||||
|
107
examples/index.css
Normal file
107
examples/index.css
Normal file
@ -0,0 +1,107 @@
|
||||
@import url(https://fonts.googleapis.com/css?family=Khula:700);
|
||||
|
||||
body {
|
||||
background-color:#EEE;
|
||||
padding:0px;
|
||||
margin:0px;
|
||||
font-family: Khula, Helvetica, sans-serif;
|
||||
font-size: 130%;
|
||||
}
|
||||
|
||||
.page {
|
||||
max-width:1300px;
|
||||
margin: auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
a {
|
||||
box-shadow: inset 0 0 0 0 #54b3d6;
|
||||
color: #0087b9;
|
||||
margin: 0 -.25rem;
|
||||
padding: 0 .25rem;
|
||||
transition: color .3s ease-in-out,
|
||||
box-shadow .3s ease-in-out;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
box-shadow: inset 120px 0 0 0 #54b3d6;
|
||||
color: white;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-decoration: underline;
|
||||
width:100%;
|
||||
background-color: rgba(100,100,255,0.5);
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
#selectExample {
|
||||
flex:1;
|
||||
}
|
||||
|
||||
#selectExample, #selectExample option {
|
||||
font-size: 16px;
|
||||
font-family: sans-serif;
|
||||
font-weight: 700;
|
||||
line-height: 1.3;
|
||||
border:0px;
|
||||
background-color: #bbb;
|
||||
color:black;
|
||||
}
|
||||
|
||||
#selectExample:focus {
|
||||
outline:none;
|
||||
}
|
||||
|
||||
#terminal {
|
||||
width:100%;
|
||||
height 500px;
|
||||
height: calc(clamp(200px, 100vh - 300px, 900px));
|
||||
overflow: hidden;
|
||||
border:none;
|
||||
background-color:black;
|
||||
}
|
||||
|
||||
#terminalContainer {
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0px 2px 10px 0px rgba(0,0,0,0.75),
|
||||
0px 2px 80px 0px rgba(0,0,0,0.50);
|
||||
}
|
||||
|
||||
.fakeButtons {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #000;
|
||||
margin:6px;
|
||||
background-color: #ff3b47;
|
||||
border-color: #9d252b;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.fakeMinimize {
|
||||
left: 11px;
|
||||
background-color: #ffc100;
|
||||
border-color: #9d802c;
|
||||
}
|
||||
|
||||
.fakeZoom {
|
||||
left: 16px;
|
||||
background-color: #00d742;
|
||||
border-color: #049931;
|
||||
}
|
||||
|
||||
.fakeMenu {
|
||||
display:flex;
|
||||
flex-direction: row;
|
||||
width:100%;
|
||||
box-sizing: border-box;
|
||||
height: 25px;
|
||||
background-color: #bbb;
|
||||
color:black;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
}
|
@ -1,173 +1,32 @@
|
||||
<!DOCTYPE html> <html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>FTXUI examples WebAssembly</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/xterm@4.18.0/lib/xterm.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-webgl@0.11.4/lib/xterm-addon-webgl.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.min.js"></script>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>➡️</text></svg>">
|
||||
<link rel="stylesheet" href="index.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@4.11.0/css/xterm.css"></link>
|
||||
<!--Add COOP/COEP via a ServiceWorker to use SharedArrayBuffer-->
|
||||
<script>
|
||||
if ("serviceWorker" in navigator && !window.crossOriginIsolated) {
|
||||
navigator.serviceWorker.register(new URL("./sw.js", location.href)).then(
|
||||
registration => {
|
||||
if (registration.active && !navigator.serviceWorker.controller) {
|
||||
window.location.reload();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
</script>
|
||||
<script type="module" src="index.mjs"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script id="example_script"></script>
|
||||
|
||||
<div class="page">
|
||||
<h1>FTXUI WebAssembly Example </h1>
|
||||
<p>
|
||||
<a href="https://github.com/ArthurSonzogni/FTXUI">FTXUI</a> is a single
|
||||
C++ library for terminal user interface.
|
||||
</p>
|
||||
<p>
|
||||
On this page, you can try all the examples contained in: <a
|
||||
href="https://github.com/ArthurSonzogni/FTXUI/tree/master/examples">./example/</a>
|
||||
Those are compiled using WebAssembly.
|
||||
<a href="https://github.com/ArthurSonzogni/FTXUI">FTXUI</a> is a simple
|
||||
functional C++ library for terminal user interface. <br/>
|
||||
This showcase the: <a href="https://github.com/ArthurSonzogni/FTXUI/tree/master/examples">./example/</a> folder. <br/>
|
||||
</p>
|
||||
|
||||
<div id="terminalContainer">
|
||||
<div class="fakeMenu">
|
||||
<div class="fakeButtons fakeClose"></div>
|
||||
<div class="fakeButtons fakeMinimize"></div>
|
||||
<div class="fakeButtons fakeZoom"></div>
|
||||
<select id="selectExample"></select>
|
||||
</div>
|
||||
<div id="terminal"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script>
|
||||
const example_list = "@EXAMPLES@".split(";");
|
||||
|
||||
const url_search_params = new URLSearchParams(window.location.search);
|
||||
const example = url_search_params.get("file") || "dom/color_gallery";
|
||||
const select = document.getElementById("selectExample");
|
||||
|
||||
for(var i = 0; i < example_list.length; i++) {
|
||||
var opt = example_list[i];
|
||||
var el = document.createElement("option");
|
||||
el.textContent = opt;
|
||||
el.value = opt;
|
||||
select.appendChild(el);
|
||||
}
|
||||
select.selectedIndex = example_list.findIndex(path => path == example) || 0;
|
||||
select.addEventListener("change", () => {
|
||||
location.href = (location.href).split('?')[0] + "?file=" +
|
||||
example_list[select.selectedIndex];
|
||||
});
|
||||
|
||||
let stdin_buffer = [];
|
||||
const stdin = () => {
|
||||
return stdin_buffer.shift() || 0;
|
||||
}
|
||||
|
||||
let stdout_buffer = [];
|
||||
const stdout = code => {
|
||||
if (code == 0) {
|
||||
term.write(new Uint8Array(stdout_buffer));
|
||||
stdout_buffer = [];
|
||||
} else {
|
||||
stdout_buffer.push(code)
|
||||
}
|
||||
}
|
||||
let stderrbuffer = [];
|
||||
const stderr = code => {
|
||||
if (code == 0 || code == 10) {
|
||||
console.error(String.fromCodePoint(...stderrbuffer));
|
||||
stderrbuffer = [];
|
||||
} else {
|
||||
stderrbuffer.push(code)
|
||||
}
|
||||
}
|
||||
const term = new Terminal();
|
||||
const term_element = document.querySelector('#terminal');
|
||||
term.open(term_element);
|
||||
|
||||
const webgl_addon = new (WebglAddon.WebglAddon)();
|
||||
term.loadAddon(webgl_addon);
|
||||
|
||||
const onBinary = e => {
|
||||
for(c of e)
|
||||
stdin_buffer.push(c.charCodeAt(0));
|
||||
}
|
||||
term.onBinary(onBinary);
|
||||
term.onData(onBinary)
|
||||
term.resize(140,43);
|
||||
window.Module = {
|
||||
preRun: () => {
|
||||
FS.init(stdin, stdout, stderr);
|
||||
},
|
||||
postRun: [],
|
||||
onRuntimeInitialized: () => {
|
||||
if (window.Module._ftxui_on_resize == undefined)
|
||||
return;
|
||||
|
||||
const fit_addon = new (FitAddon.FitAddon)();
|
||||
term.loadAddon(fit_addon);
|
||||
fit_addon.fit();
|
||||
const resize_handler = () => {
|
||||
const {cols, rows} = fit_addon.proposeDimensions();
|
||||
term.resize(cols, rows);
|
||||
window.Module._ftxui_on_resize(cols, rows);
|
||||
};
|
||||
const resize_observer = new ResizeObserver(resize_handler);
|
||||
resize_observer.observe(term_element);
|
||||
resize_handler();
|
||||
|
||||
// Disable scrollbar
|
||||
term.write('\x1b[?47h')
|
||||
},
|
||||
};
|
||||
|
||||
const words = example.split('/')
|
||||
words[1] = "ftxui_example_" + words[1] + ".js"
|
||||
document.querySelector("#example_script").src = words.join('/');
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
body {
|
||||
background-color:#EEE;
|
||||
padding:20px;
|
||||
font-family: Helvetica, sans-serif;
|
||||
font-size: 130%;
|
||||
}
|
||||
|
||||
.page {
|
||||
max-width:1300px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
select {
|
||||
display:block;
|
||||
padding: .6em 1.4em .5em .8em;
|
||||
border-radius: 20px 20px 0px 0px;
|
||||
font-size: 16px;
|
||||
font-family: sans-serif;
|
||||
font-weight: 700;
|
||||
|
||||
color: #444;
|
||||
line-height: 1.3;
|
||||
background-color:black;
|
||||
border:0px;
|
||||
color:white;
|
||||
transition: color 0.2s linear;
|
||||
transition: background-color 0.2s linear;
|
||||
}
|
||||
|
||||
#terminal {
|
||||
width:100%;
|
||||
height: 500px;
|
||||
height: calc(clamp(200px, 100vh - 300px, 900px));
|
||||
overflow: hidden;
|
||||
border:none;
|
||||
padding:auto;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</html>
|
||||
|
102
examples/index.mjs
Normal file
102
examples/index.mjs
Normal file
@ -0,0 +1,102 @@
|
||||
import xterm from 'https://cdn.jsdelivr.net/npm/xterm@4.18.0/+esm'
|
||||
import xterm_addon_webgl from 'https://cdn.jsdelivr.net/npm/xterm-addon-webgl@0.11.4/+esm'
|
||||
import xterm_addon_fit from 'https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.5.0/+esm'
|
||||
|
||||
// Add COOP/COEP via a ServiceWorker to use SharedArrayBuffer
|
||||
if ("serviceWorker" in navigator && !window.crossOriginIsolated) {
|
||||
const url_sw = new URL("./sw.js", location.href);
|
||||
const registration = await navigator.serviceWorker.register(url_sw);
|
||||
if (registration.active && !navigator.serviceWorker.controller) {
|
||||
window.location.reload(); // Reload to ensure the COOP/COEP headers are set.
|
||||
}
|
||||
}
|
||||
|
||||
const example_list = "@EXAMPLES@".split(";");
|
||||
const url_search_params = new URLSearchParams(window.location.search);
|
||||
|
||||
const select = document.getElementById("selectExample");
|
||||
for(const example of example_list) {
|
||||
const option = document.createElement("option");
|
||||
option.textContent = example;
|
||||
option.value = example;
|
||||
select.appendChild(option);
|
||||
}
|
||||
const example = url_search_params.get("file") || "dom/color_gallery";
|
||||
select.selectedIndex = example_list.findIndex(path => path == example) || 0;
|
||||
select.addEventListener("change", () => {
|
||||
history.pushState({}, "", "?file=" + example_list[select.selectedIndex]);
|
||||
location.reload();
|
||||
});
|
||||
|
||||
const term_element = document.querySelector('#terminal');
|
||||
const term = new xterm.Terminal();
|
||||
term.options.scrollback = 0;
|
||||
term.open(term_element);
|
||||
const fit_addon = new xterm_addon_fit.FitAddon();
|
||||
const webgl_addon = new xterm_addon_webgl.WebglAddon();
|
||||
term.loadAddon(webgl_addon);
|
||||
term.loadAddon(fit_addon);
|
||||
|
||||
const stdin_buffer = [];
|
||||
const stdout_buffer = [];
|
||||
const stderr_buffer = [];
|
||||
|
||||
const stdin = () => {
|
||||
return stdin_buffer.shift() || 0;
|
||||
}
|
||||
|
||||
const stdout = code => {
|
||||
if (code == 0) {
|
||||
term.write(new Uint8Array(stdout_buffer));
|
||||
stdout_buffer.length = 0;
|
||||
} else {
|
||||
stdout_buffer.push(code)
|
||||
}
|
||||
}
|
||||
|
||||
const stderr = code => {
|
||||
if (code == 0 || code == 10) {
|
||||
console.error(String.fromCodePoint(...stderr_buffer));
|
||||
stderr_buffer = [];
|
||||
} else {
|
||||
stderr_buffer.push(code)
|
||||
}
|
||||
}
|
||||
|
||||
const onBinary = e => {
|
||||
for(const c of e)
|
||||
stdin_buffer.push(c.charCodeAt(0));
|
||||
}
|
||||
|
||||
term.onBinary(onBinary);
|
||||
term.onData(onBinary)
|
||||
term.resize(140,43);
|
||||
|
||||
window.Module = {
|
||||
preRun: () => {
|
||||
FS.init(stdin, stdout, stderr);
|
||||
},
|
||||
postRun: [],
|
||||
onRuntimeInitialized: () => {
|
||||
if (window.Module._ftxui_on_resize == undefined)
|
||||
return;
|
||||
fit_addon.fit();
|
||||
|
||||
const resize_handler = () => {
|
||||
const {cols, rows} = fit_addon.proposeDimensions();
|
||||
term.resize(cols, rows);
|
||||
window.Module._ftxui_on_resize(cols, rows);
|
||||
fit_addon.fit();
|
||||
};
|
||||
const resize_observer = new ResizeObserver(resize_handler);
|
||||
resize_observer.observe(term_element);
|
||||
resize_handler();
|
||||
|
||||
// Disable scrollbar
|
||||
//term.write('\x1b[?47h')
|
||||
},
|
||||
};
|
||||
|
||||
const words = example.split('/')
|
||||
words[1] = "ftxui_example_" + words[1] + ".js"
|
||||
document.querySelector("#example_script").src = words.join('/');
|
Loading…
Reference in New Issue
Block a user