Page MenuHomeSealhub

No OneTemporary

diff --git a/src/builders/colors-builder.ts b/src/builders/colors-builder.ts
index 6f89259..5748a73 100644
--- a/src/builders/colors-builder.ts
+++ b/src/builders/colors-builder.ts
@@ -1,461 +1,466 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { build } from "esbuild";
import tempfile from "tempfile";
import { promises as fs } from "fs";
import { resolve } from "path";
import { colord } from "colord";
import { formatWithPrettier } from "../utils/prettier.js";
import { Builder } from "./builder.js";
import { exec } from "../utils/exec.js";
import { APP_BACK_ALIVE_SIGNAL } from "../notifier.js";
export const COLORS_TS_PATH = "src/back/colors.ts"; // keeping it in src/back instead of just src to make typescript hints work there
export const COLORS_CSS_PATH = "src/colors.css";
export const COLORS_HTML_PATH = "public/dist/colors.html";
export class ColorsBuilder extends Builder {
getName(): string {
return "colors";
}
ownsFile(file_path: string) {
return file_path == COLORS_TS_PATH;
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
async dispose(): Promise<void> {}
async _build() {
const outfile = tempfile({ extension: "mjs" });
await build({
entryPoints: [COLORS_TS_PATH],
bundle: true,
format: "esm",
outfile,
});
await fs.appendFile(
outfile,
/* HTML */ `<script>
console.log(
JSON.stringify(
Object.fromEntries(
Object.entries(colors).map(
([group_name, group]) => [
group_name,
Object.fromEntries(
Object.entries(group).map(
([color_name, color]) => {
const shades = [];
for (let i = 0; i <= 9; i++) {
shades.push(
shade(color, i)
);
}
return [
color_name,
{ color, shades },
];
}
)
),
]
)
)
)
);
</script>`.replaceAll(/<\/?script>/g, "") // <script> helps Prettier format this snippet
);
const output = await exec("node", [outfile]);
const color_groups = JSON.parse(output.stdout) as Record<
string,
Record<string, { color: string; shades: string[] }>
>;
let css_colors = "";
let html_colors = "";
function html_color_box({
color,
shade_no,
name,
group_name,
is_main = false,
}: {
color: string;
shade_no: string;
name: string;
group_name: string;
is_main?: boolean;
}) {
const c = colord(color);
return /* HTML */ `<div
class="color-box ${c.isDark() ? "is-dark" : ""} ${is_main
? "is-main"
: ""} ${c.toHsl().l > 90 ? "is-almost-white" : ""}"
style="background-color: ${color}; order: ${parseInt(shade_no)}"
data-color-name="${name}"
data-color-group-name="${group_name}"
data-color-shade-number="${shade_no}"
>
<span class="hex">${c.toHex()}</span>
</div>`;
}
for (const group_name of Object.keys(color_groups).sort((key) =>
key == "brand" ? -1 : 11
)) {
html_colors += `<h2>${group_name}</h2><div class="group">`;
const colors = color_groups[group_name];
for (const [color_name, color_info] of Object.entries(colors)) {
html_colors += `<h3>${color_name}</h3><div class="shades">`;
const main_color = color_info.color;
css_colors += `--color-${group_name}-${color_name}: ${main_color};`;
const main_l = colord(main_color).toHsl().l;
html_colors += html_color_box({
color: main_color,
name: color_name,
shade_no: Math.round((main_l - (main_l % 10)) / 10)
.toString()
.padStart(2, "0"),
is_main: true,
group_name,
});
color_info.shades.forEach((shaded_color, index) => {
const shade_no = index.toString().padStart(2, "0");
css_colors += `--color-${group_name}-${color_name}-${shade_no}: ${shaded_color};`;
if (
Math.abs(
colord(shaded_color).toHsl().l -
colord(main_color).toHsl().l
) < 10
) {
// this color is already in HTML as the main color, skipping adding it to html to avoid duplication
return;
}
html_colors += html_color_box({
color: shaded_color,
shade_no,
name: color_name,
group_name,
});
});
html_colors += `</div>`;
}
html_colors += "</div>";
}
const css = await formatWithPrettier(
`/* DO NOT EDIT! This file is automatically generated by sealgen */
:root {
${css_colors}
}`,
"css"
);
function makeDemoPair(
fg: string,
bg: string,
text: string,
classname = ""
) {
return /* HTML */ ` <div
class="pair ${classname}"
data-fg="${fg}"
data-bg="${bg}"
style="background-color: ${bg}; color: ${fg}"
>
<span>${text}</span>
</div>`;
}
const html = await formatWithPrettier(
/* HTML */ `<!DOCTYPE html>
<html>
<head>
<title>Color palettes</title>
<style>
${css}
</style>
<style>
* {
font-family: sans-serif;
}
.shades {
display: flex;
}
.color-box {
width: 100px;
height: 100px;
transition: transform 50ms;
transition-timing-function: ease-in-out;
transform: scale(1);
cursor: pointer;
&:hover {
transform: scale(1.1);
z-index: 2;
.hex {
visibility: visible;
}
}
&.is-main {
height: 116px;
width: 116px;
margin-top: -8px;
box-shadow: 0px 0px 6px 2px white;
z-index: 1;
&:before {
font-weight: bold;
}
}
&.is-almost-white.is-main {
box-shadow: 0px 0px 6px 1px #00000078;
}
.hex {
padding: 8px;
font-family: Menlo, Consolas, Monaco,
Liberation Mono, Lucida Console,
monospace;
opacity: 0.5;
visibility: hidden;
}
&.is-dark .hex {
color: white;
}
}
.color-box:before {
content: attr(data-color-shade-number);
box-sizing: border-box;
display: block;
color: black;
font-size: 14px;
width: 100%;
padding: 10px;
opacity: 0.3;
}
.color-box.is-dark:before {
color: white;
}
@keyframes float-up {
from {
transform: translateY(0);
opacity: 1;
}
to {
transform: translateY(-20px);
opacity: 0;
}
}
.toast {
background-color: black;
position: absolute;
color: white;
border-radius: 8px;
padding: 8px;
animation: float-up 800ms;
animation-timing-function: ease-out;
z-index: 3;
}
.container {
width: 100vw;
display: flex;
flex-flow: row wrap;
gap: 16px;
@media (max-width: 1400px) {
.demo {
order: 1;
}
.pallete {
order: 2;
}
}
.canvas {
background-color: var(--color-brand-canvas);
display: flex;
flex-flow: column;
border: 1px dashed gray;
color: gray;
gap: 8px;
padding: 8px;
& > * {
padding: 8px;
color: black;
}
.pair.single span {
opacity: 0.5;
}
.pair.link span {
text-decoration: underline;
}
}
}
</style>
</head>
<body>
<div class="container">
<div class="pallete">${html_colors}</div>
<div class="demo">
<div class="canvas">
<span>canvas</span>
+ ${makeDemoPair(
+ "var(--color-brand-text-fg)",
+ "var(--color-brand-canvas)",
+ "text-fg on canvas"
+ )}
${makeDemoPair(
"var(--color-brand-text-fg)",
"var(--color-brand-text-bg)",
"text-fg on text-bg"
)}
${makeDemoPair(
"var(--color-brand-text-accent)",
"var(--color-brand-text-bg)",
"text-accent on text-bg"
)}
${makeDemoPair(
"var(--color-brand-link-fg)",
"var(--color-brand-text-bg)",
"link-fg on text-bg",
"link"
)}
${makeDemoPair(
"",
"var(--color-brand-accent)",
"accent",
"single"
)}
${makeDemoPair(
"",
"var(--color-brand-accent2)",
"accent2",
"single"
)}
${makeDemoPair(
"var(--color-brand-text-on-accent)",
"var(--color-brand-accent)",
"text-on-accent on accent"
)}
${makeDemoPair(
"var(--color-brand-text-on-accent2)",
"var(--color-brand-accent2)",
"text-on-accent2 on accent2"
)}
${makeDemoPair(
"var(--color-brand-link-on-accent)",
"var(--color-brand-accent)",
"link-on-accent on accent",
"link"
)}
${makeDemoPair(
"var(--color-brand-link-on-accent2)",
"var(--color-brand-accent2)",
"link-on-accent2 on accent2",
"link"
)}
</div>
</div>
</div>
</body>
<script>
function pop_toast() {
const toast = document.createElement("div");
document.body.appendChild(toast);
toast.classList.add("toast");
toast.textContent = "Copied!";
toast.style.setProperty(
"top",
event.clientY +
document.scrollingElement.scrollTop -
40 +
"px"
);
toast.style.setProperty(
"left",
event.clientX + "px"
);
toast.addEventListener("animationend", () => {
toast.remove();
});
}
document.addEventListener("click", (event) => {
const box = event.target.closest(".color-box");
if (box) {
const css_var = box.classList.contains(
"is-main"
)
? \`var(--color-\${box.getAttribute(
"data-color-group-name"
)}-\${box.getAttribute(
"data-color-name"
)})\`
: \`var(--color-\${box.getAttribute(
"data-color-group-name"
)}-\${box.getAttribute(
"data-color-name"
)}-\${box.getAttribute(
"data-color-shade-number"
)})\`;
navigator.clipboard.writeText(css_var);
pop_toast();
}
const pair = event.target.closest(".pair");
if (pair) {
let to_copy = "";
if (pair.classList.contains("single")) {
to_copy = pair.getAttribute("data-bg");
} else {
to_copy = \`background-color: \${pair.getAttribute(
"data-bg"
)};\\ncolor: \${pair.getAttribute(
"data-fg"
)};\`;
}
navigator.clipboard.writeText(to_copy);
pop_toast();
}
});
</script>
<script>
(async function () {
const response = await (
await fetch("/dist/notifier.json")
).json();
const ws = new WebSocket(
\`http://localhost:\${response.port}\`
);
ws.addEventListener("message", (event) => {
console.log(event);
if (event.data == "${APP_BACK_ALIVE_SIGNAL}") {
document.location = document.location; // refresh
}
});
})();
</script>
</html>`,
"html"
);
await Promise.all([
fs.writeFile(resolve(this.project_dir, COLORS_CSS_PATH), css),
fs.writeFile(resolve(this.project_dir, COLORS_HTML_PATH), html),
]);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Feb 25, 16:19 (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
610593
Default Alt Text
(11 KB)

Event Timeline