Terminal Web Component
:) WIP
by Nicholas Berlette
HTML
<div class="outer" data-theme="dark">
<section class="inner">
<div class="relative">
<v-terminal id="terminal" title="/usr/bin/bash" class="dark terminal">
<ul aria-label="Code Tabs" class="hidden" role="tablist"><li role="presentation"><button class="lume-code-tab is-active" aria-controls="panel-4-1" aria-selected="true" id="tab-4-1" role="tab" tabindex="0">custom.tsx</button></li></ul>
<div class="w-full absolute top-12 left-0 right-0 bottom-0 line-numbers-bg">
<!-- start user code -->
<pre class="code-outer overflow-x-auto !leading-5.5 h-full w-full block"><code class="code"><span class="line"><span style="color: #db889a;">is</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">string</span><span style="color: #D8DEE9FF">(</span><span style="color: #A3BE8C">value</span><span style="color: #ECEFF499">: unknown</span><span style="color: #D8DEE9FF">)</span> <span style="color: #81A1C1">=></span> <span style="color: #A3BE8C">value</span> <span style="color: #ECEFF499">is</span> <span style="color: #d4976c">string</span><span style="color:#ECEFF499">;</span></span><span class="line"><span style="color: #db889a;">is</span><span style="color: #ECEFF4">.</span><span style="color: #d4976c;">assert</span><span style="color: #ECEFF4">.</span><span style="color: #88C0D0">string</span><span style="color: #D8DEE9FF">(</span><span style="color: #A3BE8C">value</span><span style="color: #ECEFF499">: unknown</span><span style="color: #D8DEE9FF">)</span> <span style="color: #81A1C1">=></span> <span style="color: #d4976c">asserts</span> <span style="color: #A3BE8C">value</span> <span style="color: #ECEFF499">is</span> <span style="color: #d4976c">string</span><span style="color:#ECEFF499">;</span></span></code></pre>
<!-- end user code -->
</div>
</v-terminal>
<v-terminal id="terminal2" title="/usr/bin/bash" class="dark terminal">
<ul...
SCSS
:root {
--light-bg-1: #f0f0f0;
--light-bg-2: #cfcfcf;
--light-bg-3: #ececec;
--light-bg-4: #9ab;
--light-bg-alpha-1: #fff6;
--light-text-1: #000;
--light-text-2: #123;
--light-text-3: #000a;
--light-text-4: #456;
--light-border-1: #0004;
--light-border-2: #0003;
--light-shadow-4: #0004;
--light-btn-shadow: #00000019;
/* backgrounds (dark) */
--dark-bg-1: #111518;
--dark-bg-2: #111827;
--dark-bg-3: #20262e;
--dark-bg-4: #234;
--dark-bg-alpha-1: #ffffff05;
--dark-text-1: #fff;
--dark-text-2: #ddd;
--dark-text-3: #fffa;
--dark-text-4: #789;
--dark-border-1: #000a;
--dark-border-2: #fff3;
--dark-shadow-4: #000;
/* shadows */
--shadow-1: #0004;
--shadow-2: #0003;
--shadow-3: #0002;
--shadow-4: #0004;
}
:root:not(.light) {
/* defaults */
--bg-1: var(--dark-bg-1);
--bg-2: var(--dark-bg-2);
--bg-3: var(--dark-bg-3);
--bg-4: var(--dark-bg-4);
--bg-alpha-1: var(--dark-bg-alpha-1);
--text-1: var(--dark-text-1);
--text-2: var(--dark-text-2);
--text-3: var(--dark-text-3);
--text-4: var(--dark-text-4);
--border-1: var(--dark-border-1);
--border-2: var(--dark-border-2);
}
.dark {
/* backgrounds (dark) */
--bg-1: #111518;
--bg-2: #111827;
--bg-3: #20262e;
--bg-4: #234;
--bg-alpha-1: #ffffff05;
--text-1: #fff;
--text-2: #ddd;
--text-3: #fffa;
--text-4: #789;
--border-1: #000a;
--border-2: #fff3;
--shadow-4: #000;
}
.light {
--bg-1: #f0f0f0;
--bg-2: #cfcfcf;
--bg-3: #ececec;
--bg-4: #9ab;
--bg-alpha-1: #fff6;
--text-1: #000;
--text-2: #123;
--text-3: #000a;
--text-4: #456;
--border-1: #0004;
--border-2: #0003;
--shadow-4: #0004;
--btn-shadow: #00000019;
}
@keyframes morph {
50% {
--transform: scale(1.2) translateZ(150%);
}
}
@keyframes wobble {
50% {
--transform: var(--transform) rotate3d(0.2turn, -0.3turn, 1.5turn);
}
}
.bg-container {
--transform: scale(1);
animation: morph 10s ease-in infinite 2s both alternate,...
JavaScript
const $ctor = function (expressionSyntax) {
try {
return $Function('"use strict"; return (' + expressionSyntax + ').constructor;')();
} catch (e) {}
};
const sugar = {
on: function(names, fn) {
names
.split(' ')
.forEach(name =>
this.addEventListener(name, fn));
return this;
},
off: function(names, fn) {
names
.split(' ')
.forEach(name =>
this.removeEventListener(name, fn));
return this;
},
attr: function(attr, val) {
if (val === undefined) return this.getAttribute(attr);
val == null ?
this.removeAttribute(attr) :
this.setAttribute(attr, val || '')
return this;
}
}
window.$ = function $(query, $context = document) {
let $nodes = query instanceof NodeList || Array.isArray(query) ?
query :
query instanceof HTMLElement || query instanceof SVGElement ?
[query] :
$context.querySelectorAll(query);
if (!$nodes.length) $nodes = [];
const azucar = Array.from($nodes, $el => Object.assign($el, sugar));
return Object.assign(azucar, {
on: function(names, fn) {
return (this.forEach($el => $el.on(names, fn)), this);
},
off: function(names, fn) {
return (this.forEach($el => $el.off(names, fn)), this);
},
attr: function(attrs, val) {
if (typeof attrs === 'string' && val === undefined) {
return this[0].attr(attrs);
} else if (typeof attrs === 'object') {
this.forEach($el =>
Object.entries(attrs)
.forEach(([key, val]) =>
$el.attr(key, val)));
} else if (
typeof attrs == 'string' &&
(val || val == null || val == '')
) {
this.forEach($el => $el.attr(attrs, val));
}
return this;
}
})
}
class Terminal extends HTMLElement {
constructor() {
super();
/* const template = document
.getElementById('element-details-template')
.content;
const shadowRoot = this.attachShadow({mode:...