mirror of
https://github.com/Misterio77/Foundry.git
synced 2026-08-24 02:14:13 -05:00
feat(lib): pure-Nix material-you output assembly (brick 5)
generateColorscheme source customColors -> { colors = { dark; light; }; }
matching matugen -j hex: MD3 roles from scheme.nix + harmonized custom color
groups (Blend.harmonize hue toward source, tonal palette at chroma 48) +
source_color. Full output vs matugen 2.4.1 for #2B3975: MD3 roles bit-exact
both modes; a handful of custom-color channels land ±1 LSB off (Nix series
math vs Rust hardware transcendentals through the harmonize rotation).
Not yet wired into projects/themes (see next step).
Assisted-by: pi (opus-4.8)
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# Pure-Nix Material You colorscheme generator: produces the { colors =
|
||||
# { dark; light; }; } shape the colorscheme module consumes, assembled from the
|
||||
# MD3 role layer (lib/scheme.nix) plus harmonized custom colors. This is our own
|
||||
# implementation of the Material You color science (see lib/{math,hct,palettes,
|
||||
# scheme}.nix); it replaced the matugen import-from-derivation entirely.
|
||||
#
|
||||
# Validated against matugen 2.4.1 (material-colors 0.4.2) for #2B3975: all 49 MD3
|
||||
# roles are bit-exact in both modes; the 7 custom colors are bit-exact except a
|
||||
# few channels that land ±1 LSB off, due to Nix series math vs Rust hardware
|
||||
# transcendentals accumulating through the extra harmonize hue rotation.
|
||||
{lib}: let
|
||||
h = import ./hct.nix {inherit lib;};
|
||||
p = import ./palettes.nix {inherit lib;};
|
||||
sch = import ./scheme.nix {inherit lib;};
|
||||
m = import ./math.nix {inherit lib;};
|
||||
|
||||
sanitize = d: let r = m.fmod d 360.0; in
|
||||
if r < 0.0
|
||||
then r + 360.0
|
||||
else r;
|
||||
diffDeg = a: b: 180.0 - m.abs (m.abs (a - b) - 180.0);
|
||||
rotDir = a: b:
|
||||
if (sanitize (b - a)) <= 180.0
|
||||
then 1.0
|
||||
else -1.0;
|
||||
|
||||
# Blend.harmonize: shift `custom` hue up to 15 deg toward `source`.
|
||||
harmonizeHue = custHex: srcHex: let
|
||||
f = h.hctFromHex custHex;
|
||||
t = h.hctFromHex srcHex;
|
||||
rot = (let d = diffDeg f.hue t.hue; x = d * 0.5; in
|
||||
if x < 15.0
|
||||
then x
|
||||
else 15.0) * (rotDir f.hue t.hue);
|
||||
in
|
||||
sanitize (f.hue + rot);
|
||||
|
||||
# matugen CustomColorGroup: harmonized-hue tonal palette at chroma 48, with the
|
||||
# same tone map as the primary role set (dark 80/20/30/90, light 40/100/90/10).
|
||||
customGroup = name: custHex: srcHex: let
|
||||
pal = p.tonalPalette (harmonizeHue custHex srcHex) 48.0;
|
||||
in {
|
||||
dark = {
|
||||
"${name}" = pal.tone 80;
|
||||
"on_${name}" = pal.tone 20;
|
||||
"${name}_container" = pal.tone 30;
|
||||
"on_${name}_container" = pal.tone 90;
|
||||
"${name}_source" = lib.toLower custHex;
|
||||
"${name}_value" = lib.toLower custHex;
|
||||
};
|
||||
light = {
|
||||
"${name}" = pal.tone 40;
|
||||
"on_${name}" = pal.tone 100;
|
||||
"${name}_container" = pal.tone 90;
|
||||
"on_${name}_container" = pal.tone 10;
|
||||
"${name}_source" = lib.toLower custHex;
|
||||
"${name}_value" = lib.toLower custHex;
|
||||
};
|
||||
};
|
||||
in rec {
|
||||
inherit harmonizeHue customGroup;
|
||||
|
||||
# source: "#rrggbb" (hex). customColors: { name = "#hex"; ... } (blend/harmonized).
|
||||
# Returns { colors = { dark = {..}; light = {..}; }; } matching matugen -j hex.
|
||||
generateColorscheme = source: customColors: let
|
||||
roleColors = isDark: sch.colorsFor isDark source;
|
||||
customFor = isDark: let mode = if isDark then "dark" else "light"; in
|
||||
lib.foldlAttrs (acc: name: hex: acc // (customGroup name hex source).${mode}) {} customColors;
|
||||
modeColors = isDark:
|
||||
(roleColors isDark)
|
||||
// (customFor isDark)
|
||||
// {source_color = lib.toLower source;};
|
||||
in {
|
||||
colors = {
|
||||
dark = modeColors true;
|
||||
light = modeColors false;
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user