Merge pull request 'coporate color system: init' (#388) from feat/corp-theme into main
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
./clan-cli/flake-module.nix
|
./clan-cli/flake-module.nix
|
||||||
./installer/flake-module.nix
|
./installer/flake-module.nix
|
||||||
./ui/flake-module.nix
|
./ui/flake-module.nix
|
||||||
|
./theme/flake-module.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
perSystem = { pkgs, config, ... }: {
|
perSystem = { pkgs, config, ... }: {
|
||||||
|
|||||||
3
pkgs/theme/.editorconfig
Normal file
3
pkgs/theme/.editorconfig
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[*.{js,jsx,ts,tsx,json}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
12
pkgs/theme/.envrc
Normal file
12
pkgs/theme/.envrc
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Because we depend on nixpkgs sources, uploading to builders takes a long time
|
||||||
|
|
||||||
|
source_up
|
||||||
|
|
||||||
|
files=(flake-module.nix package.json package-lock.json)
|
||||||
|
if type nix_direnv_watch_file &>/dev/null; then
|
||||||
|
nix_direnv_watch_file "${files[@]}"
|
||||||
|
else
|
||||||
|
watch_file "${files[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
use flake .#theme --builders ''
|
||||||
43
pkgs/theme/.gitignore
vendored
Normal file
43
pkgs/theme/.gitignore
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# nix
|
||||||
|
.floco
|
||||||
|
src/fonts
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
# Generated api code
|
||||||
|
openapi.json
|
||||||
|
api/
|
||||||
41
pkgs/theme/default.nix
Normal file
41
pkgs/theme/default.nix
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{ floco
|
||||||
|
, system
|
||||||
|
, pkgs
|
||||||
|
, clanPkgs
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
|
||||||
|
lib = floco.lib;
|
||||||
|
|
||||||
|
pjs =
|
||||||
|
let
|
||||||
|
msg = "default.nix: Expected to find `package.json' to lookup " +
|
||||||
|
"package name/version, but no such file exists at: " +
|
||||||
|
(toString ./package.json);
|
||||||
|
in
|
||||||
|
if builtins.pathExists ./package.json then lib.importJSON ./package.json
|
||||||
|
else throw msg;
|
||||||
|
ident = pjs.name;
|
||||||
|
inherit (pjs) version;
|
||||||
|
|
||||||
|
|
||||||
|
fmod = lib.evalModules {
|
||||||
|
modules = [
|
||||||
|
floco.nixosModules.floco
|
||||||
|
{ config.floco.settings = { inherit system; basedir = ./.; }; }
|
||||||
|
./nix/floco-cfg.nix
|
||||||
|
];
|
||||||
|
specialArgs = {
|
||||||
|
inherit pkgs clanPkgs;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# This attrset holds a few derivations related to our package.
|
||||||
|
# We'll expose these below to the CLI.
|
||||||
|
pkg = fmod.config.floco.packages.${ident}.${version};
|
||||||
|
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit pkg fmod;
|
||||||
|
}
|
||||||
18
pkgs/theme/flake-module.nix
Normal file
18
pkgs/theme/flake-module.nix
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{ self, ... }:
|
||||||
|
{
|
||||||
|
perSystem = { self', pkgs, ... }:
|
||||||
|
let
|
||||||
|
inherit (self.inputs) floco;
|
||||||
|
base = pkgs.callPackage ./default.nix { inherit floco; clanPkgs = self'.packages; };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
packages = {
|
||||||
|
theme = base.pkg.global;
|
||||||
|
};
|
||||||
|
devShells.theme = pkgs.callPackage ./shell.nix {
|
||||||
|
inherit pkgs;
|
||||||
|
inherit (base) fmod pkg;
|
||||||
|
clanPkgs = self'.packages;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
962
pkgs/theme/index.html
Normal file
962
pkgs/theme/index.html
Normal file
@@ -0,0 +1,962 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Page Title</title>
|
||||||
|
<style></style>
|
||||||
|
<body>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(13, minmax(0, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #000000;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral0
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #1f1926;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral10
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #342e3c;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral20
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #4b4453;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral30
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #635b6b;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral40
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #7d7485;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral50
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #807788;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral51
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #978d9f;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral60
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #b2a7ba;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral70
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #cec2d5;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral80
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #eadef2;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral90
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #fff7ff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral98
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
neutral100
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(13, minmax(0, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #000000;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red0
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #410006;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red10
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #680010;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red20
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #93001a;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red30
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #bf0026;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red40
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #e82439;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red50
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ff5358;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red60
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ff8986;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red70
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ffb3b0;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red80
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ffdad8;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red90
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ffedeb;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red95
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
red100
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(13, minmax(0, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #000000;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green0
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #0f2000;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green10
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #1d3700;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green20
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #2d5000;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green30
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #3d6a00;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green40
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #4e8500;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green50
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #60a100;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green60
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #74be11;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green70
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #7ac51b;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green72
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #8edb34;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green80
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #a9f850;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green90
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #efffd8;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green98
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
green100
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(13, minmax(0, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #000000;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow0
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #1d1d00;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow10
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #323200;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow20
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #494900;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow30
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #626200;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow40
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #7b7b00;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow50
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #969600;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow60
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #b1b100;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow70
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #cdcd00;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow80
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #e0e01f;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow87
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #eaea2c;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow90
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #fffeac;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow98
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
yellow100
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(13, minmax(0, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #000000;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple0
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #270057;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple10
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #42008a;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple20
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #5e07bd;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple30
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #661bc5;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple33
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #7734d6;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple40
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #9152f1;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple50
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #a974ff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple60
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #bf98ff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple70
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #d5baff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple80
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ecdcff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple90
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
purple100
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(13, minmax(0, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #000000;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue0
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #001d36;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue10
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #003258;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue20
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #00497c;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue30
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #0061a3;
|
||||||
|
color: #fff;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue40
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #1b7ac5;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue50
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #4395e2;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue60
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #62b0fe;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue70
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #9ecaff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue80
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #d1e4ff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue90
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #e9f1ff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue95
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #000;
|
||||||
|
height: 10rem;
|
||||||
|
border: solid 1px grey;
|
||||||
|
display: grid;
|
||||||
|
place-items: end;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
blue100
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
26
pkgs/theme/nix/floco-cfg.nix
Normal file
26
pkgs/theme/nix/floco-cfg.nix
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# ============================================================================ #
|
||||||
|
#
|
||||||
|
# Aggregates configs making them available to `default.nix', `flake.nix',
|
||||||
|
# or other projects that want to consume this module/package as a dependency.
|
||||||
|
#
|
||||||
|
# ---------------------------------------------------------------------------- #
|
||||||
|
{
|
||||||
|
_file = "theme/nix/floco-cfg.nix";
|
||||||
|
imports =
|
||||||
|
let
|
||||||
|
ifExist = builtins.filter builtins.pathExists [
|
||||||
|
./pdefs.nix # Generated `pdefs.nix'
|
||||||
|
./foverrides.nix # Explicit config
|
||||||
|
];
|
||||||
|
in
|
||||||
|
ifExist
|
||||||
|
++ [
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
# ---------------------------------------------------------------------------- #
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# ============================================================================ #
|
||||||
|
|
||||||
12
pkgs/theme/nix/foverrides.nix
Normal file
12
pkgs/theme/nix/foverrides.nix
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{ lib, config, ... }:
|
||||||
|
let
|
||||||
|
pjs = lib.importJSON ../package.json;
|
||||||
|
ident = pjs.name;
|
||||||
|
inherit (pjs) version;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
config.floco.packages.${ident}.${version} =
|
||||||
|
{
|
||||||
|
source = lib.libfloco.cleanLocalSource ../.;
|
||||||
|
};
|
||||||
|
}
|
||||||
90
pkgs/theme/nix/pdefs.nix
Normal file
90
pkgs/theme/nix/pdefs.nix
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
floco = {
|
||||||
|
pdefs = {
|
||||||
|
"@clan/colors" = {
|
||||||
|
"1.0.0" = {
|
||||||
|
depInfo = {
|
||||||
|
"@material/material-color-utilities" = {
|
||||||
|
descriptor = "^0.2.6";
|
||||||
|
pin = "0.2.7";
|
||||||
|
};
|
||||||
|
"@types/node" = {
|
||||||
|
descriptor = "^20.3.2";
|
||||||
|
pin = "20.8.2";
|
||||||
|
};
|
||||||
|
typescript = {
|
||||||
|
descriptor = "^5.1.5";
|
||||||
|
pin = "5.2.2";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
fetchInfo = "path:..";
|
||||||
|
ident = "@clan/colors";
|
||||||
|
lifecycle = {
|
||||||
|
build = true;
|
||||||
|
};
|
||||||
|
ltype = "dir";
|
||||||
|
treeInfo = {
|
||||||
|
"node_modules/@material/material-color-utilities" = {
|
||||||
|
dev = true;
|
||||||
|
key = "@material/material-color-utilities/0.2.7";
|
||||||
|
};
|
||||||
|
"node_modules/@types/node" = {
|
||||||
|
dev = true;
|
||||||
|
key = "@types/node/20.8.2";
|
||||||
|
};
|
||||||
|
"node_modules/typescript" = {
|
||||||
|
dev = true;
|
||||||
|
key = "typescript/5.2.2";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
version = "1.0.0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"@material/material-color-utilities" = {
|
||||||
|
"0.2.7" = {
|
||||||
|
fetchInfo = {
|
||||||
|
narHash = "sha256-hRYXqtkoXHoB30v1hstWz7dO7dNeBb6EJqZG66hHi94=";
|
||||||
|
type = "tarball";
|
||||||
|
url = "https://registry.npmjs.org/@material/material-color-utilities/-/material-color-utilities-0.2.7.tgz";
|
||||||
|
};
|
||||||
|
ident = "@material/material-color-utilities";
|
||||||
|
ltype = "file";
|
||||||
|
treeInfo = { };
|
||||||
|
version = "0.2.7";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"@types/node" = {
|
||||||
|
"20.8.2" = {
|
||||||
|
fetchInfo = {
|
||||||
|
narHash = "sha256-o4hyob1kLnm0OE8Rngm0d6XJxobpMlYSoquusktmLPk=";
|
||||||
|
type = "tarball";
|
||||||
|
url = "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz";
|
||||||
|
};
|
||||||
|
ident = "@types/node";
|
||||||
|
ltype = "file";
|
||||||
|
treeInfo = { };
|
||||||
|
version = "20.8.2";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
typescript = {
|
||||||
|
"5.2.2" = {
|
||||||
|
binInfo = {
|
||||||
|
binPairs = {
|
||||||
|
tsc = "bin/tsc";
|
||||||
|
tsserver = "bin/tsserver";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
fetchInfo = {
|
||||||
|
narHash = "sha256-io9rXH9RLRLB0484ZdvcqblLQquLFUBGxDuwSixWxus=";
|
||||||
|
type = "tarball";
|
||||||
|
url = "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz";
|
||||||
|
};
|
||||||
|
ident = "typescript";
|
||||||
|
ltype = "file";
|
||||||
|
treeInfo = { };
|
||||||
|
version = "5.2.2";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
63
pkgs/theme/package-lock.json
generated
Normal file
63
pkgs/theme/package-lock.json
generated
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"name": "@clan/colors",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 2,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "@clan/colors",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@material/material-color-utilities": "^0.2.6",
|
||||||
|
"@types/node": "^20.3.2",
|
||||||
|
"typescript": "^5.1.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@material/material-color-utilities": {
|
||||||
|
"version": "0.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/material-color-utilities/-/material-color-utilities-0.2.7.tgz",
|
||||||
|
"integrity": "sha512-0FCeqG6WvK4/Cc06F/xXMd/pv4FeisI0c1tUpBbfhA2n9Y8eZEv4Karjbmf2ZqQCPUWMrGp8A571tCjizxoTiQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "20.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz",
|
||||||
|
"integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/typescript": {
|
||||||
|
"version": "5.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||||
|
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"tsc": "bin/tsc",
|
||||||
|
"tsserver": "bin/tsserver"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.17"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@material/material-color-utilities": {
|
||||||
|
"version": "0.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material/material-color-utilities/-/material-color-utilities-0.2.7.tgz",
|
||||||
|
"integrity": "sha512-0FCeqG6WvK4/Cc06F/xXMd/pv4FeisI0c1tUpBbfhA2n9Y8eZEv4Karjbmf2ZqQCPUWMrGp8A571tCjizxoTiQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@types/node": {
|
||||||
|
"version": "20.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz",
|
||||||
|
"integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"typescript": {
|
||||||
|
"version": "5.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||||
|
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
pkgs/theme/package.json
Normal file
23
pkgs/theme/package.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "@clan/colors",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"type": "module",
|
||||||
|
"files": [
|
||||||
|
"colors.json"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"typecheck": "./node_modules/.bin/tsc -p ./tsconfig.json --noEmit",
|
||||||
|
"build": "tsc --build --clean && tsc && node ./build/main.js",
|
||||||
|
"html": "tsc --build --clean && tsc && node ./build/generate.js",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@material/material-color-utilities": "^0.2.6",
|
||||||
|
"typescript": "^5.1.5",
|
||||||
|
"@types/node": "^20.3.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
24
pkgs/theme/shell.nix
Normal file
24
pkgs/theme/shell.nix
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{ fmod
|
||||||
|
, pkg
|
||||||
|
, pkgs
|
||||||
|
, clanPkgs
|
||||||
|
}:
|
||||||
|
pkgs.mkShell {
|
||||||
|
buildInputs = [
|
||||||
|
fmod.config.floco.settings.nodePackage
|
||||||
|
];
|
||||||
|
shellHook = ''
|
||||||
|
ID=${pkg.built.tree}
|
||||||
|
currID=$(cat .floco/.node_modules_id 2> /dev/null)
|
||||||
|
|
||||||
|
mkdir -p .floco
|
||||||
|
if [[ "$ID" != "$currID" || ! -d "node_modules" ]];
|
||||||
|
then
|
||||||
|
${pkgs.rsync}/bin/rsync -a --chmod=ug+w --delete ${pkg.built.tree}/node_modules/ ./node_modules/
|
||||||
|
echo -n $ID > .floco/.node_modules_id
|
||||||
|
echo "floco ok: node_modules updated"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export PATH="$PATH:$(realpath ./node_modules)/.bin"
|
||||||
|
'';
|
||||||
|
}
|
||||||
1507
pkgs/theme/src/colors.json
Normal file
1507
pkgs/theme/src/colors.json
Normal file
File diff suppressed because it is too large
Load Diff
78
pkgs/theme/src/config.ts
Normal file
78
pkgs/theme/src/config.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { AliasMap, BaseColors, HexString } from "./types.js";
|
||||||
|
|
||||||
|
export type PaletteConfig = {
|
||||||
|
baseColors: BaseColors;
|
||||||
|
tones: number[];
|
||||||
|
aliases: AliasMap<"primary" | "secondary" | "error">;
|
||||||
|
common: {
|
||||||
|
// Black and white is always constant
|
||||||
|
// We declare this on the type level
|
||||||
|
white: "#ffffff";
|
||||||
|
black: "#000000";
|
||||||
|
// Some other color constants/reservation
|
||||||
|
[id: string]: HexString;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const config: PaletteConfig = {
|
||||||
|
/** All color shades that are available
|
||||||
|
* This colors are used as "key colors" to generate a tonal palette from 0 to 100
|
||||||
|
* Steps are defined in 'tones'
|
||||||
|
*/
|
||||||
|
baseColors: {
|
||||||
|
neutral: {
|
||||||
|
keyColor: "#807788",
|
||||||
|
tones: [98],
|
||||||
|
},
|
||||||
|
red: {
|
||||||
|
keyColor: "#e82439",
|
||||||
|
tones: [95],
|
||||||
|
},
|
||||||
|
green: {
|
||||||
|
keyColor: "#7AC51B",
|
||||||
|
tones: [98],
|
||||||
|
},
|
||||||
|
yellow: {
|
||||||
|
keyColor: "#E0E01F",
|
||||||
|
tones: [98],
|
||||||
|
},
|
||||||
|
purple: {
|
||||||
|
keyColor: "#661bc5",
|
||||||
|
tones: [],
|
||||||
|
},
|
||||||
|
blue: {
|
||||||
|
keyColor: "#1B7AC5",
|
||||||
|
tones: [95],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
/** Common tones to generate out of all the baseColors
|
||||||
|
* number equals to the amount of light present in the color (HCT Color Space)
|
||||||
|
*/
|
||||||
|
tones: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
|
||||||
|
|
||||||
|
/** create aliases from the color palette
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
*
|
||||||
|
* primary: "blue"
|
||||||
|
* ->
|
||||||
|
* ...
|
||||||
|
* primary40 -> blue40
|
||||||
|
* primary50 -> blue50
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
|
aliases: {
|
||||||
|
primary: "purple",
|
||||||
|
secondary: "green",
|
||||||
|
error: "red",
|
||||||
|
},
|
||||||
|
/** some color names are reserved
|
||||||
|
* typically those colors do not change when switching theme
|
||||||
|
* or are other types of constant in the UI
|
||||||
|
*/
|
||||||
|
common: {
|
||||||
|
white: "#ffffff",
|
||||||
|
black: "#000000",
|
||||||
|
},
|
||||||
|
};
|
||||||
46
pkgs/theme/src/generate.ts
Normal file
46
pkgs/theme/src/generate.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { writeFile } from "fs";
|
||||||
|
import palette from "./colors.json" assert { type: "json" };
|
||||||
|
import { config } from "./config.js";
|
||||||
|
|
||||||
|
type PaletteFile = typeof palette;
|
||||||
|
|
||||||
|
const html = (palette: PaletteFile): string => {
|
||||||
|
const colors = Object.keys(config.baseColors).map((baseName) => {
|
||||||
|
const colors = Object.entries(palette.ref.palette)
|
||||||
|
.filter(([name, _]) => name.includes(baseName))
|
||||||
|
.sort((a, b) => {
|
||||||
|
return a[1].meta.color.shade - b[1].meta.color.shade;
|
||||||
|
})
|
||||||
|
.map(([key, color]) => {
|
||||||
|
console.log({ key, color });
|
||||||
|
return `<div style="background-color:${color.value}; color:${
|
||||||
|
color.meta.color.shade < 48 ? "#fff" : "#000"
|
||||||
|
}; height: 10rem; border:solid 1px grey; display:grid; place-items:end;">${key}</div>`;
|
||||||
|
});
|
||||||
|
return `<div style="display: grid; grid-template-columns: repeat(${13}, minmax(0, 1fr)); gap: 1rem; margin-bottom: 1rem">${colors.join(
|
||||||
|
"\n",
|
||||||
|
)}</div>`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return `<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Page Title</title>
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
${colors.join("\n")}
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
writeFile("index.html", html(palette), (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error({ err });
|
||||||
|
} else {
|
||||||
|
console.log("Exported colors to html");
|
||||||
|
}
|
||||||
|
});
|
||||||
182
pkgs/theme/src/main.ts
Normal file
182
pkgs/theme/src/main.ts
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
#!usr/bin/node
|
||||||
|
import * as fs from "fs";
|
||||||
|
import {
|
||||||
|
argbFromHex,
|
||||||
|
Hct,
|
||||||
|
hexFromArgb,
|
||||||
|
} from "@material/material-color-utilities";
|
||||||
|
import {
|
||||||
|
AliasTokenMap,
|
||||||
|
ColorDesignToken,
|
||||||
|
ColorSet,
|
||||||
|
HexString,
|
||||||
|
RefTokenSystem,
|
||||||
|
TonalPalette,
|
||||||
|
TonalPaletteConfig,
|
||||||
|
TonalPaletteItem,
|
||||||
|
} from "./types.js";
|
||||||
|
import { config } from "./config.js";
|
||||||
|
|
||||||
|
const { baseColors, tones, aliases, common } = config;
|
||||||
|
|
||||||
|
/** Takes a color, tone and name
|
||||||
|
* If a tone is given adjust the lightning level accordingly
|
||||||
|
*
|
||||||
|
* @returns TonalPaletteItem (meta wrapper around HCT)
|
||||||
|
*/
|
||||||
|
const getTonalPaletteItem = (
|
||||||
|
value: HexString,
|
||||||
|
name: string,
|
||||||
|
tone?: number,
|
||||||
|
): TonalPaletteItem => {
|
||||||
|
const aRGB = argbFromHex(value);
|
||||||
|
const color = Hct.fromInt(aRGB);
|
||||||
|
if (tone !== undefined) {
|
||||||
|
color.tone = tone;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
shade: color.tone,
|
||||||
|
name: `${name || color.chroma}${Math.round(color.tone)}`,
|
||||||
|
baseName: name,
|
||||||
|
value: color,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** create a flat list of the cross product from all colors and all tones.
|
||||||
|
*
|
||||||
|
* every color is mapped in the range from 0 to 100
|
||||||
|
* with the steps configure in `config.tones'
|
||||||
|
* additionally the key color is added unmodified
|
||||||
|
* lightning levels are rounded to the next natural number to form the 'name'
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* "blue" x [20.1, 30.3]
|
||||||
|
* ->
|
||||||
|
* [blue20, blue30]
|
||||||
|
*/
|
||||||
|
const mkTonalPalette =
|
||||||
|
(config: TonalPaletteConfig) =>
|
||||||
|
(name: string) =>
|
||||||
|
(keyTone: HexString): TonalPalette => {
|
||||||
|
const { tones } = config;
|
||||||
|
const aRGB = argbFromHex(keyTone);
|
||||||
|
const HctColor = Hct.fromInt(aRGB);
|
||||||
|
const roundedTone = Math.round(HctColor.tone * 100) / 100;
|
||||||
|
|
||||||
|
const localTones = [...tones, roundedTone];
|
||||||
|
|
||||||
|
return localTones.map((t) => getTonalPaletteItem(keyTone, name, t));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a PaletteItem into a hex color. (Wrapped)
|
||||||
|
* Adding meta attributes which avoids any information loss.
|
||||||
|
*/
|
||||||
|
const toDesignTokenContent = (color: TonalPaletteItem): ColorDesignToken => {
|
||||||
|
const { value } = color;
|
||||||
|
return {
|
||||||
|
type: "color",
|
||||||
|
value: hexFromArgb(value.toInt()),
|
||||||
|
meta: {
|
||||||
|
color,
|
||||||
|
date: new Date(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const color: ColorSet = Object.entries(baseColors)
|
||||||
|
.map(([name, baseColor]) => ({
|
||||||
|
name,
|
||||||
|
baseColor,
|
||||||
|
tones: mkTonalPalette({
|
||||||
|
tones: [...tones, ...baseColor.tones].sort((a, b) => a - b),
|
||||||
|
})(name)(baseColor.keyColor),
|
||||||
|
}))
|
||||||
|
.reduce((acc, curr) => {
|
||||||
|
let currTones = curr.tones.reduce(
|
||||||
|
(o, v) => ({
|
||||||
|
...o,
|
||||||
|
[v.name]: toDesignTokenContent(v),
|
||||||
|
}),
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
...currTones,
|
||||||
|
};
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
/** Generate a set of tokens from a given alias mapping
|
||||||
|
*
|
||||||
|
* @param alias A string e.g. Primary -> Blue (Primary is the alias)
|
||||||
|
* @param name A string; Basename of the referenced value (e.g. Blue)
|
||||||
|
* @param colors A set of colors
|
||||||
|
* @returns All aliases from the given color set
|
||||||
|
*/
|
||||||
|
function resolveAlias(
|
||||||
|
alias: string,
|
||||||
|
name: string,
|
||||||
|
colors: ColorSet,
|
||||||
|
): AliasTokenMap {
|
||||||
|
// All colors from the color map belonging to that single alias
|
||||||
|
// Example:
|
||||||
|
// Primary -> "blue"
|
||||||
|
// =>
|
||||||
|
// [ (blue0) , (blue10) , ..., (blue100) ]
|
||||||
|
const all = Object.values(colors)
|
||||||
|
.filter((n) => n.meta.color.name.includes(name))
|
||||||
|
.filter((n) => !n.meta.color.name.includes("."));
|
||||||
|
|
||||||
|
const tokens = all
|
||||||
|
.map((shade) => {
|
||||||
|
const shadeNumber = shade.meta.color.shade;
|
||||||
|
return {
|
||||||
|
name: `${alias}${Math.round(shadeNumber)}`,
|
||||||
|
value: { value: `{ref.palette.${shade.meta.color.name}}` },
|
||||||
|
// propagate the meta attribute of the actual value
|
||||||
|
meta: shade.meta,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
// sort by tone
|
||||||
|
.sort((a, b) => a.meta.color.value.tone - b.meta.color.value.tone)
|
||||||
|
.reduce((acc, { name, value }) => ({ ...acc, [name]: value }), {});
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
const aliasMap = Object.entries(aliases).reduce(
|
||||||
|
(prev, [key, value]) => ({
|
||||||
|
...prev,
|
||||||
|
...resolveAlias(key, value, color),
|
||||||
|
}),
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
|
const commonColors = Object.entries(common)
|
||||||
|
.map(([name, value]) =>
|
||||||
|
toDesignTokenContent(getTonalPaletteItem(value, name)),
|
||||||
|
)
|
||||||
|
.reduce(
|
||||||
|
(acc, val) => ({ ...acc, [val.meta.color.baseName]: val }),
|
||||||
|
{},
|
||||||
|
) as ColorSet;
|
||||||
|
|
||||||
|
const toPaletteToken = (color: ColorSet): RefTokenSystem => ({
|
||||||
|
ref: {
|
||||||
|
palette: color,
|
||||||
|
alias: aliasMap,
|
||||||
|
common: commonColors,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Dump tokens to json file
|
||||||
|
fs.writeFile(
|
||||||
|
"colors.json",
|
||||||
|
JSON.stringify(toPaletteToken(color), null, 2),
|
||||||
|
(err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error({ err });
|
||||||
|
} else {
|
||||||
|
console.log("tokens successfully exported");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
90
pkgs/theme/src/types.ts
Normal file
90
pkgs/theme/src/types.ts
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import { Hct } from "@material/material-color-utilities";
|
||||||
|
|
||||||
|
export type BaseColors = {
|
||||||
|
neutral: BaseColor;
|
||||||
|
red: BaseColor;
|
||||||
|
green: BaseColor;
|
||||||
|
yellow: BaseColor;
|
||||||
|
purple: BaseColor;
|
||||||
|
blue: BaseColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BaseColor = {
|
||||||
|
keyColor: HexString;
|
||||||
|
tones: number[];
|
||||||
|
follows?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ColorSet = { [key: string]: ColorDesignToken };
|
||||||
|
|
||||||
|
/** The resolved alias tokens
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* {
|
||||||
|
* primary: "blue"
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export type AliasMap<T extends string> = {
|
||||||
|
[alias in T]: keyof BaseColors;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The resolved alias tokens
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* {
|
||||||
|
* primary0: "blue40"
|
||||||
|
* primary10: "blue40"
|
||||||
|
* ...
|
||||||
|
* primary100: "blue100"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Unfortunately My Typescript skills lack the ability to express this type any narrower :/
|
||||||
|
*/
|
||||||
|
export type AliasTokenMap = {
|
||||||
|
[alias: string]: { value: string };
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TonalPaletteConfig = {
|
||||||
|
tones: number[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type HexString = string;
|
||||||
|
|
||||||
|
export type TonalPaletteItem = {
|
||||||
|
/**
|
||||||
|
* @example
|
||||||
|
* 20
|
||||||
|
*/
|
||||||
|
shade: number;
|
||||||
|
/**
|
||||||
|
* @example
|
||||||
|
* "blue20"
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
/**
|
||||||
|
* @example
|
||||||
|
* "blue"
|
||||||
|
*/
|
||||||
|
baseName: string;
|
||||||
|
value: Hct;
|
||||||
|
};
|
||||||
|
export type TonalPalette = TonalPaletteItem[];
|
||||||
|
|
||||||
|
export type ColorDesignToken = {
|
||||||
|
type: "color";
|
||||||
|
value: HexString;
|
||||||
|
meta: {
|
||||||
|
color: TonalPaletteItem;
|
||||||
|
date: Date;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RefTokenSystem = {
|
||||||
|
ref: {
|
||||||
|
palette: ColorSet;
|
||||||
|
common: ColorSet;
|
||||||
|
alias: AliasTokenMap;
|
||||||
|
};
|
||||||
|
};
|
||||||
41
pkgs/theme/tsconfig.json
Normal file
41
pkgs/theme/tsconfig.json
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"include": ["src"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||||
|
|
||||||
|
"lib": [
|
||||||
|
"ESNext",
|
||||||
|
"dom"
|
||||||
|
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
|
||||||
|
"module": "NodeNext" /* Specify what module code is generated. */,
|
||||||
|
"rootDir": "src" /* Specify the root folder within your source files. */,
|
||||||
|
"moduleResolution": "nodenext" /* Specify how TypeScript looks up a file from a given module specifier. */,
|
||||||
|
"resolveJsonModule": true /* Enable importing .json files. */,
|
||||||
|
"outDir": "build",
|
||||||
|
|
||||||
|
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
|
||||||
|
|
||||||
|
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
||||||
|
|
||||||
|
/* Type Checking */
|
||||||
|
"strict": true /* Enable all strict type-checking options. */,
|
||||||
|
"noImplicitAny": true /* Enable error reporting for expressions and declarations with an implied 'any' type. */,
|
||||||
|
"strictNullChecks": true /* When type checking, take into account 'null' and 'undefined'. */,
|
||||||
|
"strictFunctionTypes": true /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */,
|
||||||
|
"strictBindCallApply": true /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */,
|
||||||
|
"strictPropertyInitialization": true /* Check for class properties that are declared but not set in the constructor. */,
|
||||||
|
"noImplicitThis": true /* Enable error reporting when 'this' is given the type 'any'. */,
|
||||||
|
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||||
|
"alwaysStrict": true /* Ensure 'use strict' is always emitted. */,
|
||||||
|
"noUnusedLocals": true /* Enable error reporting when local variables aren't read. */,
|
||||||
|
"noUnusedParameters": true /* Raise an error when a function parameter isn't read. */,
|
||||||
|
"exactOptionalPropertyTypes": true /* Interpret optional property types as written, rather than adding 'undefined'. */,
|
||||||
|
"noImplicitReturns": true /* Enable error reporting for codepaths that do not explicitly return in a function. */,
|
||||||
|
"noFallthroughCasesInSwitch": true /* Enable error reporting for fallthrough cases in switch statements. */,
|
||||||
|
"noUncheckedIndexedAccess": true /* Add 'undefined' to a type when accessed using an index. */,
|
||||||
|
"noImplicitOverride": true /* Ensure overriding members in derived classes are marked with an override modifier. */,
|
||||||
|
"noPropertyAccessFromIndexSignature": true /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||||
|
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||||
|
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,5 +2,6 @@
|
|||||||
imports = [
|
imports = [
|
||||||
./pdefs.nix
|
./pdefs.nix
|
||||||
./foverrides.nix
|
./foverrides.nix
|
||||||
|
../../theme/nix/floco-cfg.nix
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,6 +100,12 @@ in
|
|||||||
optional = false;
|
optional = false;
|
||||||
dev = true;
|
dev = true;
|
||||||
};
|
};
|
||||||
|
"node_modules/@clan/colors" = {
|
||||||
|
key = "@clan/colors/1.0.0";
|
||||||
|
link = false;
|
||||||
|
optional = false;
|
||||||
|
dev = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { createTheme } from "@mui/material/styles";
|
import { createTheme } from "@mui/material/styles";
|
||||||
|
|
||||||
|
import colors from "@clan/colors/colors.json";
|
||||||
|
|
||||||
export const darkTheme = createTheme({
|
export const darkTheme = createTheme({
|
||||||
breakpoints: {
|
breakpoints: {
|
||||||
values: {
|
values: {
|
||||||
@@ -15,6 +17,7 @@ export const darkTheme = createTheme({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { palette, common } = colors.ref;
|
||||||
export const lightTheme = createTheme({
|
export const lightTheme = createTheme({
|
||||||
breakpoints: {
|
breakpoints: {
|
||||||
values: {
|
values: {
|
||||||
@@ -27,5 +30,27 @@ export const lightTheme = createTheme({
|
|||||||
},
|
},
|
||||||
palette: {
|
palette: {
|
||||||
mode: "light",
|
mode: "light",
|
||||||
|
background: {
|
||||||
|
default: common.white.value,
|
||||||
|
paper: palette.neutral98.value,
|
||||||
|
},
|
||||||
|
primary: {
|
||||||
|
main: palette.green50.value,
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: palette.green50.value,
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
main: palette.red50.value,
|
||||||
|
},
|
||||||
|
warning: {
|
||||||
|
main: palette.yellow50.value,
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
main: palette.green50.value,
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
main: palette.red50.value,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user