New main site, maybe?
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
node_modules/
|
||||
package-lock.json
|
||||
output/
|
12
debug.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
const express = require("express");
|
||||
const app = express();
|
||||
|
||||
app.use(
|
||||
express.static("output", {
|
||||
extensions: ["html"],
|
||||
index: "index.html",
|
||||
redirect: true,
|
||||
})
|
||||
);
|
||||
|
||||
app.listen(3000);
|
30
embeds/loader.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
<div
|
||||
style="
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: var(--background-color);
|
||||
color: var(--color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
z-index: 1000;
|
||||
font-family: sans-serif;
|
||||
"
|
||||
id="loading"
|
||||
>
|
||||
<div>
|
||||
<h1>Loading...</h1>
|
||||
<h2>Please wait.</h2>
|
||||
<p>If this page does not load, try enabling JavaScript.</p>
|
||||
<small>(This site won't work well without it.)</small>
|
||||
<script>
|
||||
window.addEventListener("load", function () {
|
||||
document.querySelector("#loading").style.display = "none";
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
7
embeds/nav.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
<section>
|
||||
<p>
|
||||
<a href="/">Home</a> - <a href="/projects/">Projects</a> -
|
||||
<a href="/about/">About</a> -
|
||||
<a href="/site/">Site Information</a>
|
||||
</p>
|
||||
</section>
|
25
gulpfile.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
const { src, dest } = require("gulp");
|
||||
const through2 = require("through2");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
exports.default = () => {
|
||||
return src("views/**/*")
|
||||
.pipe(
|
||||
through2.obj(function (file, _, cb) {
|
||||
if (file.isBuffer()) {
|
||||
file.contents = Buffer.from(
|
||||
file.contents
|
||||
.toString()
|
||||
.replace(/<\$ (.*?) \$>/gm, function (m, g1) {
|
||||
return fs.readFileSync(path.join(__dirname, "embeds", g1), {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
cb(null, file);
|
||||
})
|
||||
)
|
||||
.pipe(dest("output/"));
|
||||
};
|
14
package.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "projects-windowed",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"dev": "nodemon --exec 'gulp;node debug.js' --ext '*' --ignore 'output/*'"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gulp": "^4.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "^4.18.2",
|
||||
"through2": "^4.0.2"
|
||||
}
|
||||
}
|
41
views/about/index.html
Normal file
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>MeowcaTheoRange</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="/styles/normal.css" />
|
||||
<link rel="stylesheet" href="/styles/style.css" />
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Lexend+Deca:wght@100;200;300;400;500;600;700;800;900&display=swap");
|
||||
|
||||
:root {
|
||||
--base-scale: 16px;
|
||||
|
||||
--background-color: hsl(195, 100%, 15%);
|
||||
--color: hsl(195, 100%, 85%);
|
||||
--accent-color: hsl(195, 100%, 50%);
|
||||
--accent-color-fg: hsl(195, 100%, 95%);
|
||||
--font-family: "Lexend Deca";
|
||||
--document-width: 40em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<section>
|
||||
<h1>About</h1>
|
||||
<p>More about me.</p>
|
||||
</section>
|
||||
<$ nav.html $>
|
||||
</header>
|
||||
<main>
|
||||
<section>
|
||||
<h2>WIP</h2>
|
||||
</section>
|
||||
</main>
|
||||
<section id="accessibility"></section>
|
||||
<script src="/scripts/windows.js"></script>
|
||||
<script src="/scripts/accessibility.js"></script>
|
||||
</body>
|
||||
</html>
|
80
views/index.html
Executable file
|
@ -0,0 +1,80 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>MeowcaTheoRange</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="/styles/normal.css" />
|
||||
<link rel="stylesheet" href="/styles/style.css" />
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Lexend+Deca:wght@100;200;300;400;500;600;700;800;900&display=swap");
|
||||
|
||||
:root {
|
||||
--base-scale: 16px;
|
||||
|
||||
--background-color: hsl(195, 100%, 15%);
|
||||
--color: hsl(195, 100%, 85%);
|
||||
--accent-color: hsl(195, 100%, 50%);
|
||||
--accent-color-fg: hsl(195, 100%, 95%);
|
||||
--font-family: "Lexend Deca";
|
||||
--document-width: 40em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<section>
|
||||
<h1>ABTMTR.LINK</h1>
|
||||
</section>
|
||||
<$ nav.html $>
|
||||
</header>
|
||||
<main>
|
||||
<section>
|
||||
<h2>Welcome! 👋</h2>
|
||||
<p>I'm MeowcaTheoRange.</p>
|
||||
<p>
|
||||
I'm a web developer, Fediverse enthusiast, and compulsory Minnesotan.
|
||||
</p>
|
||||
<p>I run this domain and all of the services on it!</p>
|
||||
</section>
|
||||
<section>
|
||||
<h2>What I like doing</h2>
|
||||
<p>
|
||||
My favourite hobbies are <b>programming</b>, <b>drawing</b>,
|
||||
<b>occasionally making small bits of music</b>,
|
||||
<b>obsessing over fonts</b>, and <b>being pedantic</b>.
|
||||
</p>
|
||||
</section>
|
||||
<section>
|
||||
<h2>What I'd like you to know about me</h2>
|
||||
<ul>
|
||||
<li>Please be patient with me.</li>
|
||||
<li>
|
||||
Please be understanding! Ask me for clarification if required.
|
||||
</li>
|
||||
<li>
|
||||
I don't really like small talk - keep if brief if you want to check
|
||||
up on me, please.
|
||||
</li>
|
||||
<li>
|
||||
I'm not one to pick sides at first, usually. Being an "all or
|
||||
nothing" kind of person isn't my thing, and if you don't like that,
|
||||
feel free to tell me why your side is good.
|
||||
</li>
|
||||
<li>
|
||||
I like getting tangled up in drama, but I'm not a spiteful person -
|
||||
I'm usually only in it for the correlations.
|
||||
</li>
|
||||
<li>
|
||||
You may see me hyperfixate on random stuff, like
|
||||
<a href="#">certain fonts</a>
|
||||
or public transit.
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
<section id="accessibility"></section>
|
||||
<script src="/scripts/windows.js"></script>
|
||||
<script src="/scripts/accessibility.js"></script>
|
||||
</body>
|
||||
</html>
|
80
views/projects/hex/index.html
Executable file
|
@ -0,0 +1,80 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>HexFlagGen</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="/styles/normal.css" />
|
||||
<link rel="stylesheet" href="/styles/style.css" />
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Lexend+Deca:wght@100;200;300;400;500;600;700;800;900&display=swap");
|
||||
|
||||
:root {
|
||||
--base-scale: 16px;
|
||||
|
||||
--background-color: hsl(0, 0%, 15%);
|
||||
--color: hsl(0, 0%, 85%);
|
||||
--accent-color: #808080;
|
||||
--accent-color-fg: hsl(0, 0%, 95%);
|
||||
--font-family: "Lexend Deca";
|
||||
--document-width: 40em;
|
||||
|
||||
--border-style: 0.0625em solid var(--color);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<$ loader.html $>
|
||||
<section>
|
||||
<h1>HexFlagGen</h1>
|
||||
<p>Make a flag out of the hexadecimal bytes of your choice.</p>
|
||||
</section>
|
||||
<hr />
|
||||
<section>
|
||||
<label for="data">Generator string</label><br />
|
||||
<input
|
||||
type="text"
|
||||
id="data"
|
||||
value="5BCEFAF5A9B8FFFFFFF5A9B85BCEFABA53"
|
||||
style="width: 100%"
|
||||
/><br />
|
||||
<button id="generateButton">Generate!</button>
|
||||
</section>
|
||||
<section>
|
||||
<input
|
||||
type="number"
|
||||
id="size_width"
|
||||
style="width: 8ch"
|
||||
min="0"
|
||||
max="3000"
|
||||
value="300"
|
||||
/>
|
||||
<label for="size_width">Width (px)</label><br />
|
||||
<input
|
||||
type="number"
|
||||
id="size_height"
|
||||
style="width: 8ch"
|
||||
min="0"
|
||||
max="3000"
|
||||
value="200"
|
||||
/>
|
||||
<label for="size_height">Height (px)</label><br />
|
||||
<select id="flag_type">
|
||||
<option value="horiz">Horizontal</option>
|
||||
<option value="vert" selected>Vertical</option>
|
||||
</select>
|
||||
<label for="flag_type">Flag type</label>
|
||||
</section>
|
||||
<hr />
|
||||
<section>
|
||||
<p>
|
||||
Hex: <code><span id="hexdisplay">...</span></code>
|
||||
</p>
|
||||
<canvas id="canvas" width="300" height="200"></canvas>
|
||||
</section>
|
||||
<section id="accessibility"></section>
|
||||
<script src="scripts/index.js"></script>
|
||||
<script src="/scripts/accessibility.js"></script>
|
||||
<script src="/scripts/interface.js"></script>
|
||||
</body>
|
||||
</html>
|
117
views/projects/hex/scripts/index.js
Executable file
|
@ -0,0 +1,117 @@
|
|||
const canvas = document.getElementById("canvas");
|
||||
const data = document.getElementById("data");
|
||||
const generateButton = document.getElementById("generateButton");
|
||||
const hexdisplay = document.getElementById("hexdisplay");
|
||||
|
||||
const size_width = document.getElementById("size_width");
|
||||
const size_height = document.getElementById("size_height");
|
||||
const flag_type = document.getElementById("flag_type");
|
||||
|
||||
const root = document.querySelector(":root");
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
function getData() {
|
||||
data.value = data.value.toUpperCase().replace(/[^0-9A-F]*/g, "");
|
||||
|
||||
var hexValue = data.value.match(/.{1,2}/g).map((x) => x.padStart(2, "0"));
|
||||
|
||||
hexdisplay.innerHTML = hexValue.join(" ");
|
||||
|
||||
createFlag(
|
||||
hexValue.join("").match(/.{1,6}/g),
|
||||
size_width.value,
|
||||
size_height.value,
|
||||
flag_type.value
|
||||
);
|
||||
var ac = averageColors(hexValue);
|
||||
console.log(ac);
|
||||
root.style.setProperty(
|
||||
"--background-color",
|
||||
arrayToColor(darkenColor(ac, 70))
|
||||
);
|
||||
root.style.setProperty("--color", arrayToColor(lightenColor(ac, 70)));
|
||||
root.style.setProperty("--accent-color", arrayToColor(ac));
|
||||
root.style.setProperty(
|
||||
"--accent-color-fg",
|
||||
arrayToColor(lightenColor(ac, 90))
|
||||
);
|
||||
|
||||
propagateStyles(getComputedStyle(root));
|
||||
}
|
||||
generateButton.addEventListener("click", getData);
|
||||
|
||||
function averageColors(hex) {
|
||||
var averageSet = [[], [], []];
|
||||
hex.forEach((number, index) => {
|
||||
averageSet[index % 3].push(parseInt(number, 16));
|
||||
});
|
||||
return averageSet.map((array) =>
|
||||
Math.floor(array.reduce((a, b) => a + b) / array.length)
|
||||
);
|
||||
}
|
||||
|
||||
function createFlag(hex, w, h, type) {
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
|
||||
// Initialize stuff
|
||||
|
||||
var width = ctx.canvas.width;
|
||||
var height = ctx.canvas.height;
|
||||
var textHeight = 24;
|
||||
ctx.font = `${textHeight}px "Lexend Deca"`;
|
||||
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
|
||||
console.log(hex);
|
||||
|
||||
var hexColors = [];
|
||||
var excessHex = "";
|
||||
|
||||
hex.forEach((compound) => {
|
||||
if (compound.length < 6) excessHex = compound;
|
||||
else hexColors.push(compound);
|
||||
});
|
||||
|
||||
var rectWidth = width / hexColors.length;
|
||||
var rectHeight = height / hexColors.length;
|
||||
for (color in hexColors) {
|
||||
ctx.fillStyle = "#" + hexColors[color];
|
||||
if (type === "horiz") ctx.fillRect(rectWidth * color, 0, rectWidth, height);
|
||||
else if (type === "vert")
|
||||
ctx.fillRect(0, rectHeight * color, width, rectHeight);
|
||||
}
|
||||
if (excessHex.length > 0) {
|
||||
var text = "+ " + excessHex.match(/.{1,2}/g).join(" ");
|
||||
var textWidth = ctx.measureText(text).width;
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.lineWidth = 4;
|
||||
ctx.fillStyle = "white";
|
||||
ctx.strokeText(text, width - (textWidth + 8), height - textHeight / 2);
|
||||
ctx.fillText(text, width - (textWidth + 8), height - textHeight / 2);
|
||||
}
|
||||
}
|
||||
|
||||
const clamp = (n, mi, ma) => Math.max(mi, Math.min(n, ma));
|
||||
|
||||
function lightenColor(color, mult) {
|
||||
return [
|
||||
clamp(color[0] + (mult / 100) * (255 - color[0]), 0, 255),
|
||||
clamp(color[1] + (mult / 100) * (255 - color[1]), 0, 255),
|
||||
clamp(color[2] + (mult / 100) * (255 - color[2]), 0, 255),
|
||||
];
|
||||
}
|
||||
function darkenColor(color, mult) {
|
||||
return [
|
||||
clamp(color[0] - (mult / 100) * color[0], 0, 255),
|
||||
clamp(color[1] - (mult / 100) * color[1], 0, 255),
|
||||
clamp(color[2] - (mult / 100) * color[2], 0, 255),
|
||||
];
|
||||
}
|
||||
|
||||
function arrayToColor(color) {
|
||||
return (
|
||||
"#" + color.map((x) => Math.floor(x).toString(16).padStart(2, "0")).join("")
|
||||
);
|
||||
}
|
51
views/projects/index.html
Executable file
|
@ -0,0 +1,51 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Project Windows</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="/styles/normal.css" />
|
||||
<link rel="stylesheet" href="/styles/style.css" />
|
||||
<link rel="stylesheet" href="/styles/windows.css" />
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Lexend+Deca:wght@100;200;300;400;500;600;700;800;900&display=swap");
|
||||
|
||||
:root {
|
||||
--base-scale: 16px;
|
||||
|
||||
--background-color: hsl(15, 100%, 15%);
|
||||
--color: hsl(15, 100%, 85%);
|
||||
--accent-color: hsl(15, 100%, 50%);
|
||||
--accent-color-fg: hsl(15, 100%, 95%);
|
||||
--font-family: "Lexend Deca";
|
||||
--document-width: 40em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<$ loader.html $>
|
||||
<section>
|
||||
<h1>Projects</h1>
|
||||
<p>Various projects I've made.</p>
|
||||
</section>
|
||||
<$ nav.html $>
|
||||
<section>
|
||||
<button
|
||||
onclick="
|
||||
new WindowObject(document.getElementById('WindowHolder'), '/projects/hex')"
|
||||
>
|
||||
Open Hex
|
||||
</button>
|
||||
<button
|
||||
onclick="
|
||||
new WindowObject(document.getElementById('WindowHolder'), '/projects/woz')"
|
||||
>
|
||||
Open Woz
|
||||
</button>
|
||||
</section>
|
||||
<section id="accessibility"></section>
|
||||
<div id="WindowHolder"></div>
|
||||
<script src="/scripts/windows.js"></script>
|
||||
<script src="/scripts/accessibility.js"></script>
|
||||
</body>
|
||||
</html>
|
82
views/projects/woz/index.html
Executable file
|
@ -0,0 +1,82 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>WozSteamGem</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="/styles/normal.css" />
|
||||
<link rel="stylesheet" href="/styles/style.css" />
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Lexend+Deca:wght@100;200;300;400;500;600;700;800;900&display=swap");
|
||||
|
||||
:root {
|
||||
--base-scale: 16px;
|
||||
|
||||
--background-color: hsl(232, 95%, 15%);
|
||||
--color: hsl(232, 95%, 85%);
|
||||
--accent-color: #3a55fa;
|
||||
--accent-color-fg: hsl(232, 95%, 95%);
|
||||
--font-family: "Lexend Deca";
|
||||
--document-width: 40em;
|
||||
|
||||
--border-style: 0.0625em solid var(--color);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<$ loader.html $>
|
||||
<section>
|
||||
<h1>WozSteamGem</h1>
|
||||
<p>Make a Scott The Woz thumbnail out of any Steam game.</p>
|
||||
</section>
|
||||
<hr />
|
||||
<section>
|
||||
<input
|
||||
type="number"
|
||||
id="steam_game"
|
||||
style="width: 8ch"
|
||||
min="10"
|
||||
value="620"
|
||||
/>
|
||||
<label for="steam_game">Steam Game ID</label><br />
|
||||
<button id="generateButton">Generate!</button>
|
||||
</section>
|
||||
<section>
|
||||
<label for="scott_index">Extras</label><br />
|
||||
<input
|
||||
type="number"
|
||||
id="scott_index"
|
||||
style="width: 8ch"
|
||||
min="0"
|
||||
max="9"
|
||||
value="0"
|
||||
/>
|
||||
<label for="scott_index">Scott Index</label>
|
||||
<small>
|
||||
<label for="stash" class="checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="stash"
|
||||
onchange="scott_index.disabled = event.target.checked"
|
||||
/>
|
||||
<span class="checkbox">O</span>
|
||||
Scott's Stash
|
||||
</label></small
|
||||
><br />
|
||||
<select id="align">
|
||||
<option value="left">Left</option>
|
||||
<option value="center" selected>Center</option>
|
||||
<option value="right">Right</option>
|
||||
</select>
|
||||
<label for="align">Background Alignment</label>
|
||||
</section>
|
||||
<hr />
|
||||
<section>
|
||||
<canvas id="canvas" width="1280" height="720"></canvas>
|
||||
</section>
|
||||
<section id="accessibility"></section>
|
||||
<script src="scripts/index.js"></script>
|
||||
<script src="/scripts/accessibility.js"></script>
|
||||
<script src="/scripts/interface.js"></script>
|
||||
</body>
|
||||
</html>
|
BIN
views/projects/woz/public/woz0.png
Executable file
After Width: | Height: | Size: 453 KiB |
BIN
views/projects/woz/public/woz1.png
Executable file
After Width: | Height: | Size: 821 KiB |
BIN
views/projects/woz/public/woz2.png
Executable file
After Width: | Height: | Size: 677 KiB |
BIN
views/projects/woz/public/woz3.png
Executable file
After Width: | Height: | Size: 827 KiB |
BIN
views/projects/woz/public/woz4.png
Executable file
After Width: | Height: | Size: 740 KiB |
BIN
views/projects/woz/public/woz5.png
Executable file
After Width: | Height: | Size: 687 KiB |
BIN
views/projects/woz/public/woz6.png
Executable file
After Width: | Height: | Size: 515 KiB |
BIN
views/projects/woz/public/woz7.png
Executable file
After Width: | Height: | Size: 515 KiB |
BIN
views/projects/woz/public/woz8.png
Executable file
After Width: | Height: | Size: 359 KiB |
BIN
views/projects/woz/public/woz9.png
Executable file
After Width: | Height: | Size: 295 KiB |
BIN
views/projects/woz/public/wozstash.png
Executable file
After Width: | Height: | Size: 128 KiB |
81
views/projects/woz/scripts/index.js
Executable file
|
@ -0,0 +1,81 @@
|
|||
const canvas = document.getElementById("canvas");
|
||||
const data = document.getElementById("data");
|
||||
const generateButton = document.getElementById("generateButton");
|
||||
const hexdisplay = document.getElementById("hexdisplay");
|
||||
|
||||
const steam_game = document.getElementById("steam_game");
|
||||
const scott_index = document.getElementById("scott_index");
|
||||
const stash = document.getElementById("stash");
|
||||
const align = document.getElementById("align");
|
||||
|
||||
const root = document.querySelector(":root");
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
async function loadImage(url) {
|
||||
return new Promise((r) => {
|
||||
let img = new Image();
|
||||
img.onload = () => r(img);
|
||||
img.src = url;
|
||||
});
|
||||
}
|
||||
|
||||
async function getScott() {
|
||||
var gameID = steam_game.value;
|
||||
var scottID = scott_index.value;
|
||||
var alignment = align.value;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
var hero = await loadImage(
|
||||
`https://cdn.cloudflare.steamstatic.com/steam/apps/${gameID}/library_hero.jpg`
|
||||
).catch(() => "404");
|
||||
var scott = await loadImage(
|
||||
stash.checked ? `public/wozstash.png` : `public/woz${scottID}.png`
|
||||
).catch(() => "404");
|
||||
var logo = await loadImage(
|
||||
`https://cdn.cloudflare.steamstatic.com/steam/apps/${gameID}/logo.png`
|
||||
).catch(() => "404");
|
||||
|
||||
if (scott === "404") {
|
||||
console.log("Scott error: " + scottID);
|
||||
return `Scott ID ${scottID} does not exist.`;
|
||||
}
|
||||
if (hero === "404" || logo === "404") {
|
||||
console.log("404 error: " + gameID);
|
||||
return `Steam ID ${gameID} does not have logo, hero image, or does not exist.`;
|
||||
}
|
||||
var xalign;
|
||||
switch (alignment) {
|
||||
case "left":
|
||||
xalign = 0;
|
||||
break;
|
||||
case "right":
|
||||
xalign = -950;
|
||||
break;
|
||||
default:
|
||||
xalign = -505;
|
||||
break;
|
||||
}
|
||||
console.log("Generating: " + gameID);
|
||||
ctx.drawImage(hero, xalign, 0, 2229, 720);
|
||||
ctx.drawImage(scott, 0, 0, 1280, 720);
|
||||
|
||||
const newHeight = 800 / (logo.width / logo.height);
|
||||
ctx.fillStyle = "#000";
|
||||
ctx.shadowColor = "#000";
|
||||
ctx.shadowBlur = 16;
|
||||
|
||||
if (stash.checked)
|
||||
ctx.drawImage(
|
||||
logo,
|
||||
400,
|
||||
Math.min(560 - newHeight / 2, 669 - newHeight),
|
||||
800,
|
||||
newHeight
|
||||
);
|
||||
else
|
||||
ctx.drawImage(logo, 64, Math.max(240 - newHeight / 2, 32), 800, newHeight);
|
||||
}
|
||||
|
||||
generateButton.addEventListener("click", getScott);
|
68
views/scripts/accessibility.js
Executable file
|
@ -0,0 +1,68 @@
|
|||
var accScale;
|
||||
var accBase;
|
||||
|
||||
function createAccessibilityNodes() {
|
||||
document.querySelector("#accessibility").innerHTML = `<fieldset>
|
||||
<legend>Accessibility controls</legend>
|
||||
<label for="size_width">
|
||||
<input
|
||||
id="acc-scale"
|
||||
type="number"
|
||||
style="width: 8ch"
|
||||
min="8"
|
||||
max="48"
|
||||
value="16"
|
||||
/>
|
||||
UI scale</label><br />
|
||||
<label for="acc-base" class="checkbox">
|
||||
<input id="acc-base" type="checkbox" id="acc-base" />
|
||||
<span class="checkbox">◉</span>
|
||||
Base style (requires reload)
|
||||
</label>
|
||||
</fieldset>`;
|
||||
|
||||
accScale = document.getElementById("acc-scale");
|
||||
accBase = document.getElementById("acc-base");
|
||||
|
||||
accScale.addEventListener("change", function (e) {
|
||||
window.localStorage.setItem("acc-scale", e.target.value);
|
||||
changeScale(e.target.value);
|
||||
});
|
||||
|
||||
accBase.addEventListener("change", function (e) {
|
||||
window.localStorage.setItem("acc-base", e.target.checked);
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener("load", (e) => initializeChanges(e, true));
|
||||
|
||||
// on localStorage change
|
||||
window.addEventListener("storage", initializeChanges);
|
||||
|
||||
let prevBase; // previous base, for reload check
|
||||
|
||||
function initializeChanges(_, loading) {
|
||||
if (window.frameElement == null) createAccessibilityNodes();
|
||||
|
||||
const scale = window.localStorage.getItem("acc-scale");
|
||||
const base = window.localStorage.getItem("acc-base");
|
||||
changeScale(scale);
|
||||
|
||||
if (loading) {
|
||||
prevBase = base;
|
||||
changeBase(base === "true");
|
||||
} else if (base != prevBase) window.location.reload();
|
||||
|
||||
if (scale != null && accScale != null) accScale.value = scale;
|
||||
if (base != null && accBase != null) accBase.checked = base === "true";
|
||||
}
|
||||
|
||||
function changeScale(scale) {
|
||||
document.documentElement.style.setProperty("--base-scale", scale + "px");
|
||||
}
|
||||
|
||||
function changeBase(base) {
|
||||
if (base) document.documentElement.classList.add("base");
|
||||
else document.documentElement.classList.remove("base");
|
||||
}
|
22
views/scripts/interface.js
Executable file
|
@ -0,0 +1,22 @@
|
|||
function propagateStyles(rootStyles) {
|
||||
if (window.frameElement == null) return;
|
||||
const wfParent = window.frameElement.parentElement;
|
||||
wfParent.style.setProperty(
|
||||
"--background-color",
|
||||
rootStyles.getPropertyValue("--background-color")
|
||||
);
|
||||
wfParent.style.setProperty("--color", rootStyles.getPropertyValue("--color"));
|
||||
wfParent.style.setProperty(
|
||||
"--accent-color",
|
||||
rootStyles.getPropertyValue("--accent-color")
|
||||
);
|
||||
wfParent.style.setProperty(
|
||||
"--accent-color-fg",
|
||||
rootStyles.getPropertyValue("--accent-color-fg")
|
||||
);
|
||||
wfParent.style.setProperty("--border-style", "0.0625em solid var(--color)");
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
propagateStyles(getComputedStyle(document.documentElement));
|
||||
});
|
223
views/scripts/windows.js
Executable file
|
@ -0,0 +1,223 @@
|
|||
class WindowObject {
|
||||
windowObject;
|
||||
|
||||
windowManager;
|
||||
windowManagerLabel;
|
||||
windowContent;
|
||||
|
||||
#orig_mousePosX;
|
||||
#orig_mousePosY;
|
||||
#orig_selfPosX;
|
||||
#orig_selfPosY;
|
||||
#isDragging;
|
||||
|
||||
constructor(parent, content) {
|
||||
this.parentElement = parent;
|
||||
this.windowObject = WindowObject.createWindow(this, content);
|
||||
this.parentElement.appendChild(this.windowObject);
|
||||
|
||||
WindowObject.raiseWindow(this.windowObject);
|
||||
|
||||
this.windowManager = this.windowObject.querySelector(".window-manager");
|
||||
this.windowManagerLabel = this.windowObject.querySelector(
|
||||
".window-manager-label"
|
||||
);
|
||||
this.windowContent = this.windowObject.querySelector(".window-content");
|
||||
|
||||
this.windowManager.addEventListener("mousedown", (e) =>
|
||||
this.event__dragMouseDown(e)
|
||||
);
|
||||
this.windowManager.addEventListener("mousemove", (e) =>
|
||||
this.event__dragMouseMove(e)
|
||||
);
|
||||
this.windowManager.addEventListener("mouseup", (e) =>
|
||||
this.event__dragMouseUp(e)
|
||||
);
|
||||
this.windowManager.addEventListener("mouseout", (e) =>
|
||||
this.event__dragMouseMove(e)
|
||||
);
|
||||
|
||||
this.windowObject.addEventListener("mousedown", (e) =>
|
||||
WindowObject.raiseWindow(this.windowObject)
|
||||
);
|
||||
|
||||
this.windowContent.addEventListener("load", () => {
|
||||
this.title = this.windowContent.contentWindow.document.title;
|
||||
this.windowManager
|
||||
.querySelector(".window-new-button")
|
||||
.addEventListener("click", () => {
|
||||
window.open(this.content);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
get title() {
|
||||
return this.windowManagerLabel.textContent;
|
||||
}
|
||||
|
||||
get content() {
|
||||
return this.windowContent.src;
|
||||
}
|
||||
|
||||
set title(content) {
|
||||
this.windowManagerLabel.textContent = content;
|
||||
}
|
||||
|
||||
set content(src) {
|
||||
this.windowContent.src = src;
|
||||
}
|
||||
|
||||
minimizeWindow() {
|
||||
if (this.windowObject.classList.contains("minimized")) {
|
||||
this.windowObject.classList.remove("minimized");
|
||||
|
||||
WindowObject.raiseWindow(this.windowObject);
|
||||
} else {
|
||||
this.windowObject.classList.add("minimized");
|
||||
this.windowObject.style.zIndex = 50;
|
||||
}
|
||||
}
|
||||
|
||||
maximizeWindow() {
|
||||
this.windowObject.classList.toggle("maximized");
|
||||
|
||||
WindowObject.raiseWindow(this.windowObject);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.windowObject.classList.add("closed");
|
||||
setTimeout(() => {
|
||||
this.windowObject.remove();
|
||||
var someWindow = this.parentElement.querySelector(
|
||||
`.window-object:last-child`
|
||||
);
|
||||
if (someWindow != null) WindowObject.raiseWindow(someWindow);
|
||||
}, 250);
|
||||
}
|
||||
|
||||
event__dragMouseDown(e) {
|
||||
e.preventDefault();
|
||||
|
||||
this.#orig_mousePosX = e.clientX;
|
||||
this.#orig_mousePosY = e.clientY;
|
||||
this.#orig_selfPosX = this.windowObject.offsetLeft;
|
||||
this.#orig_selfPosY = this.windowObject.offsetTop;
|
||||
this.windowContent.style.userSelect = "none";
|
||||
this.windowContent.style.pointerEvents = "none";
|
||||
this.windowManager.style.cursor = "move";
|
||||
this.#isDragging = true;
|
||||
if (this.windowObject.style.zIndex != 100)
|
||||
WindowObject.raiseWindow(this.windowObject);
|
||||
}
|
||||
|
||||
event__dragMouseUp(e) {
|
||||
e.preventDefault();
|
||||
|
||||
this.#orig_mousePosX = 0;
|
||||
this.#orig_mousePosY = 0;
|
||||
this.windowContent.style.userSelect = "auto";
|
||||
this.windowContent.style.pointerEvents = "auto";
|
||||
this.windowManager.style.cursor = "default";
|
||||
this.#isDragging = false;
|
||||
}
|
||||
|
||||
event__dragMouseMove(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (this.#isDragging) {
|
||||
this.windowObject.style.left =
|
||||
this.#orig_selfPosX - (this.#orig_mousePosX - e.clientX) + "px";
|
||||
this.windowObject.style.top =
|
||||
this.#orig_selfPosY - (this.#orig_mousePosY - e.clientY) + "px";
|
||||
}
|
||||
}
|
||||
|
||||
static raiseWindow(windowObj) {
|
||||
windowObj.parentElement.querySelectorAll(".window-object").forEach((x) => {
|
||||
if (x.style.zIndex > 50) x.style.zIndex -= 1;
|
||||
x.classList.add("unfocused");
|
||||
});
|
||||
windowObj.style.zIndex = 100;
|
||||
windowObj.classList.remove("unfocused");
|
||||
windowObj.focus();
|
||||
}
|
||||
|
||||
static createWindow(windowRef, content) {
|
||||
const windowObject = document.createElement("div");
|
||||
windowObject.classList.add("window-object");
|
||||
|
||||
{
|
||||
const windowManager = document.createElement("div");
|
||||
windowManager.classList.add("window-manager");
|
||||
|
||||
{
|
||||
const windowManagerStart = document.createElement("div");
|
||||
windowManagerStart.classList.add("window-manager-start");
|
||||
|
||||
{
|
||||
const windowManagerLabel = document.createElement("span");
|
||||
windowManagerLabel.textContent = "";
|
||||
windowManagerLabel.classList.add("window-manager-label");
|
||||
|
||||
windowManagerStart.appendChild(windowManagerLabel);
|
||||
}
|
||||
|
||||
windowManager.appendChild(windowManagerStart);
|
||||
}
|
||||
|
||||
{
|
||||
const windowManagerEnd = document.createElement("div");
|
||||
windowManagerEnd.classList.add("window-manager-end");
|
||||
|
||||
{
|
||||
const windowNewButton = document.createElement("button");
|
||||
windowNewButton.innerHTML = "open_in_new";
|
||||
windowNewButton.classList.add("window-new-button");
|
||||
|
||||
windowManagerEnd.appendChild(windowNewButton);
|
||||
}
|
||||
|
||||
{
|
||||
const windowMaximizeButton = document.createElement("button");
|
||||
windowMaximizeButton.innerHTML = "maximize";
|
||||
windowMaximizeButton.classList.add("window-maximize-button");
|
||||
windowMaximizeButton.ariaHidden = true; // esoteric operation to screen-reader users
|
||||
windowMaximizeButton.addEventListener("click", () =>
|
||||
windowRef.maximizeWindow()
|
||||
);
|
||||
|
||||
windowManagerEnd.appendChild(windowMaximizeButton);
|
||||
}
|
||||
|
||||
{
|
||||
const windowDestroyButton = document.createElement("button");
|
||||
windowDestroyButton.innerHTML = "close";
|
||||
windowDestroyButton.classList.add("window-destroy-button");
|
||||
windowDestroyButton.ariaHidden = true;
|
||||
windowDestroyButton.addEventListener("click", () =>
|
||||
windowRef.destroy()
|
||||
);
|
||||
|
||||
windowManagerEnd.appendChild(windowDestroyButton);
|
||||
}
|
||||
|
||||
windowManager.appendChild(windowManagerEnd);
|
||||
}
|
||||
|
||||
windowObject.appendChild(windowManager);
|
||||
}
|
||||
|
||||
{
|
||||
const windowContent = document.createElement("iframe");
|
||||
windowContent.classList.add("window-content");
|
||||
|
||||
{
|
||||
windowContent.src = content;
|
||||
}
|
||||
|
||||
windowObject.appendChild(windowContent);
|
||||
}
|
||||
|
||||
return windowObject;
|
||||
}
|
||||
}
|
64
views/site/index.html
Normal file
|
@ -0,0 +1,64 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>MeowcaTheoRange</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="stylesheet" href="/styles/normal.css" />
|
||||
<link rel="stylesheet" href="/styles/style.css" />
|
||||
<style>
|
||||
@import url("https://fonts.googleapis.com/css2?family=Lexend+Deca:wght@100;200;300;400;500;600;700;800;900&display=swap");
|
||||
|
||||
:root {
|
||||
--base-scale: 16px;
|
||||
|
||||
--background-color: hsl(195, 100%, 15%);
|
||||
--color: hsl(195, 100%, 85%);
|
||||
--accent-color: hsl(195, 100%, 50%);
|
||||
--accent-color-fg: hsl(195, 100%, 95%);
|
||||
--font-family: "Lexend Deca";
|
||||
--document-width: 40em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<section>
|
||||
<h1>Site Information</h1>
|
||||
</section>
|
||||
<$ nav.html $>
|
||||
</header>
|
||||
<main>
|
||||
<section>
|
||||
<h2>What happened to the previous site?</h2>
|
||||
<p>
|
||||
The previous site kinda sucked. It depended on client-side React for
|
||||
the most basic of things, and was just overall kind of a mess of TSX
|
||||
everywhere.
|
||||
</p>
|
||||
<p>
|
||||
This site is represented semi-statically, which means there's nothing
|
||||
new being generated on the backend.<br />
|
||||
This site does not use React either, so everything the frontend runs
|
||||
is vanilla JavaScript.
|
||||
</p>
|
||||
<h2>
|
||||
What's with the <b>accessibility controls</b> on every page of the
|
||||
site?
|
||||
</h2>
|
||||
<p>
|
||||
Just because. If you want to make the text bigger or get rid of the
|
||||
colors, you have that panel.
|
||||
</p>
|
||||
<h2>What font are you using for this site?</h2>
|
||||
<p>
|
||||
<b>Lexend Deca</b>, or your <b>system's default sans-serif font</b>,
|
||||
depending on if you're using Base style.
|
||||
</p>
|
||||
</section>
|
||||
</main>
|
||||
<section id="accessibility"></section>
|
||||
<script src="/scripts/windows.js"></script>
|
||||
<script src="/scripts/accessibility.js"></script>
|
||||
</body>
|
||||
</html>
|
260
views/styles/normal.css
Executable file
|
@ -0,0 +1,260 @@
|
|||
@import url("https://necolas.github.io/normalize.css/8.0.1/normalize.css");
|
||||
|
||||
/* Document form */
|
||||
|
||||
:root {
|
||||
--base-scale: 16px;
|
||||
|
||||
--background-color: hsl(0, 0%, 15%);
|
||||
--color: hsl(0, 0%, 85%);
|
||||
--accent-color: #808080;
|
||||
--accent-color-fg: hsl(0, 0%, 95%);
|
||||
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||
"Segoe UI Symbol";
|
||||
--document-width: 40em;
|
||||
|
||||
--border-style: 0.0625em solid var(--color);
|
||||
}
|
||||
|
||||
body {
|
||||
width: 100vw;
|
||||
max-width: var(--document-width);
|
||||
margin: auto;
|
||||
padding-inline: 0.5em;
|
||||
padding-block: 0.5em;
|
||||
}
|
||||
|
||||
html.base {
|
||||
--background-color: #fff !important;
|
||||
--color: #000 !important;
|
||||
--accent-color: #000 !important;
|
||||
--accent-color-fg: #fff !important;
|
||||
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||
"Segoe UI Symbol" !important;
|
||||
--document-width: 40em;
|
||||
|
||||
--border-style: 0.0625em solid var(--color);
|
||||
}
|
||||
|
||||
html.base body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Size and type normalize */
|
||||
|
||||
html {
|
||||
font-size: var(--base-scale);
|
||||
background-color: var(--background-color);
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
main {
|
||||
margin-block: 1em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
line-height: 1.5em;
|
||||
margin: 0;
|
||||
margin-block: 0.125em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5em;
|
||||
line-height: 1.25em;
|
||||
margin: 0;
|
||||
margin-block: 0.25em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.1em;
|
||||
line-height: 1.25em;
|
||||
margin: 0;
|
||||
margin-block: 0.25em;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1em;
|
||||
line-height: 1.25em;
|
||||
margin-inline: 0;
|
||||
margin-block: 0.5em;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
padding: 0;
|
||||
padding-inline-start: 1em;
|
||||
margin: 0;
|
||||
margin-block: 0.5em;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-inline: 0;
|
||||
margin-block: 0.5em;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
big {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 1em;
|
||||
line-height: 1.25em;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-top: var(--border-style);
|
||||
background-color: transparent;
|
||||
margin-inline: 0;
|
||||
margin-block: 0.25em;
|
||||
}
|
||||
|
||||
/* Form normalize */
|
||||
|
||||
html {
|
||||
font-family: var(--font-family);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
*:focus {
|
||||
outline: 2px solid var(--accent-color-fg);
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: var(--border-style);
|
||||
padding-inline: 0.5em;
|
||||
padding-block: 0.25em;
|
||||
margin-inline: 0;
|
||||
margin-block: 0.5em;
|
||||
font-size: 1em;
|
||||
background-color: var(--background-color);
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
/* Interactive normalize */
|
||||
|
||||
a {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
a:active {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
border: var(--border-style);
|
||||
padding-inline: 0.5em;
|
||||
padding-block: 0.25em;
|
||||
margin-inline: 0;
|
||||
margin-block: 0.25em;
|
||||
font-size: 1em;
|
||||
background-color: var(--background-color);
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
input:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
button,
|
||||
input[type="button"],
|
||||
input[type="submit"],
|
||||
input[type="reset"] {
|
||||
border: var(--border-style);
|
||||
padding-inline: 0.5em;
|
||||
padding-block: 0.25em;
|
||||
margin-inline: 0;
|
||||
margin-block: 0.25em;
|
||||
font-size: 1em;
|
||||
font-family: inherit;
|
||||
background-color: var(--accent-color);
|
||||
color: var(--accent-color-fg);
|
||||
}
|
||||
|
||||
button[data-outlined],
|
||||
input[type="button"][data-outlined],
|
||||
input[type="submit"][data-outlined],
|
||||
input[type="reset"][data-outlined] {
|
||||
border: var(--border-style);
|
||||
background-color: var(--background-color);
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
button:hover,
|
||||
input[type="button"]:hover,
|
||||
input[type="submit"]:hover,
|
||||
input[type="reset"]:hover,
|
||||
button:focus,
|
||||
input[type="button"]:focus,
|
||||
input[type="submit"]:focus,
|
||||
input[type="reset"]:focus {
|
||||
opacity: 0.8;
|
||||
}
|
||||
button:active,
|
||||
input[type="button"]:active,
|
||||
input[type="submit"]:active,
|
||||
input[type="reset"]:active {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* -- Checkbox styling */
|
||||
|
||||
label.checkbox {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin-inline: 0;
|
||||
margin-block: 0.25em;
|
||||
}
|
||||
|
||||
label.checkbox input[type="checkbox"] {
|
||||
/* visibility: hidden; */
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
label.checkbox input[type="checkbox"] + span.checkbox {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
line-height: 1em;
|
||||
padding-inline: 0.25em;
|
||||
padding-block: 0.25em;
|
||||
box-sizing: content-box;
|
||||
border: var(--border-style);
|
||||
color: transparent;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
label.checkbox input[type="checkbox"]:focus + span.checkbox {
|
||||
outline: 2px solid var(--accent-color-fg);
|
||||
}
|
||||
|
||||
label.checkbox input[type="checkbox"]:checked + span.checkbox {
|
||||
background-color: var(--accent-color);
|
||||
border: var(--border-style);
|
||||
color: var(--accent-color-fg);
|
||||
}
|
11
views/styles/style.css
Normal file
|
@ -0,0 +1,11 @@
|
|||
#accessibility {
|
||||
position: sticky;
|
||||
bottom: 1em;
|
||||
left: 1em;
|
||||
background-color: var(--background-color);
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
#accessibility fieldset {
|
||||
margin-block: 0;
|
||||
}
|
147
views/styles/windows.css
Executable file
|
@ -0,0 +1,147 @@
|
|||
@import url("https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0");
|
||||
|
||||
@keyframes appear {
|
||||
from {
|
||||
scale: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
scale: 1;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
div.window-object {
|
||||
display: grid;
|
||||
grid-template-rows: max-content auto;
|
||||
grid-gap: 0.25em;
|
||||
position: fixed;
|
||||
top: calc(50vh - 150px);
|
||||
left: calc(50vw - 200px);
|
||||
width: 400px;
|
||||
height: 300px;
|
||||
|
||||
min-width: 10em;
|
||||
min-height: 2em;
|
||||
background-color: var(--accent-color);
|
||||
color: var(--accent-color-fg);
|
||||
border: var(--border-style);
|
||||
resize: both;
|
||||
overflow: hidden;
|
||||
padding: 0.25em;
|
||||
/* padding: 0.5em; */
|
||||
transition: opacity 0.25s, scale 0.25s;
|
||||
|
||||
scale: 1;
|
||||
opacity: 1;
|
||||
animation-name: appear;
|
||||
animation-duration: 0.25s;
|
||||
}
|
||||
|
||||
div.window-object.unfocused {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
div.window-object.closed {
|
||||
scale: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
div.window-object.minimized {
|
||||
top: auto !important;
|
||||
bottom: 0;
|
||||
left: 0 !important;
|
||||
max-width: 20em !important;
|
||||
width: 20em !important;
|
||||
min-width: 20em !important;
|
||||
max-height: 2.5em !important;
|
||||
height: 2.5em !important;
|
||||
min-height: 2.5em !important;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
div.window-object.minimized > div.window-manager {
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
div.window-object.minimized > iframe.window-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.window-object.maximized {
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
max-width: 100vw !important;
|
||||
width: 100vw !important;
|
||||
min-width: 100vw !important;
|
||||
max-height: 100vh !important;
|
||||
height: 100vh !important;
|
||||
min-height: 100vh !important;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
div.window-object.maximized > div.window-manager {
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
div.window-object > div.window-manager {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
grid-template-columns: auto max-content;
|
||||
vertical-align: middle;
|
||||
height: 1.5em;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
div.window-object > div.window-manager > div {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
vertical-align: middle;
|
||||
height: 100%;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
div.window-object > div.window-manager > div.window-manager-start {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
div.window-object
|
||||
> div.window-manager
|
||||
> div.window-manager-start
|
||||
> span.window-manager-label {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
line-height: 1.5em;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
div.window-object > div.window-manager > div.window-manager-end {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
div.window-object > div.window-manager > div > button {
|
||||
height: 1.5em;
|
||||
width: 1.5em;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-inline-start: 0.25em;
|
||||
box-sizing: border-box;
|
||||
border: var(--border-style);
|
||||
background-color: var(--accent-color);
|
||||
color: var(--accent-color-fg);
|
||||
font-family: "Material Symbols Outlined";
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
font-size: 1em;
|
||||
line-height: 0.5em;
|
||||
}
|
||||
|
||||
div.window-object > iframe.window-content {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: none;
|
||||
}
|