@gtk-js/theme-fluent 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ # @gtk-js/theme-fluent
2
+
3
+ ## 0.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 0982123: Bump all packages past burned npm versions
8
+ - Updated dependencies [0982123]
9
+ - @gtk-js/gtk-css@0.1.1
10
+
11
+ ## 0.0.1
12
+
13
+ ### Patch Changes
14
+
15
+ - @gtk-js/gtk-css@0.2.0
package/build.ts ADDED
@@ -0,0 +1,104 @@
1
+ import { compileGtkCSS } from "@gtk-js/gtk-css/compile";
2
+ import { mkdirSync, unlinkSync, writeFileSync } from "fs";
3
+
4
+ const upstreamDir = new URL("../../upstream/fluent-gtk-theme/src", import.meta.url).pathname;
5
+ const outDir = new URL("dist/", import.meta.url).pathname;
6
+ mkdirSync(outDir, { recursive: true });
7
+
8
+ const sassDir = `${upstreamDir}/_sass`;
9
+
10
+ const schemes = ["light", "dark"] as const;
11
+ const titlebuttons = ["circular", "square"] as const;
12
+ const windows = ["default", "round"] as const;
13
+
14
+ // Accent hex baked in by the SCSS theme() function for $theme: 'default'
15
+ const ACCENT_HEX: Record<"light" | "dark", { hex: string; r: number; g: number; b: number }> = {
16
+ light: { hex: "#1A73E8", r: 26, g: 115, b: 232 },
17
+ dark: { hex: "#3281EA", r: 50, g: 129, b: 234 },
18
+ };
19
+
20
+ /**
21
+ * Adjust .gtk-switch min-width/min-height to match native GTK layout manager.
22
+ *
23
+ * Native GTK computes: switch_width = 2 × slider_measured_width (content + margin).
24
+ * The upstream SCSS sets switch min-width to $small-size (22px), but the native
25
+ * layout manager overrides this to 2 × (12px slider + 5px margin × 2) = 44px.
26
+ * The switch min-height is slider_measured_height = 12px + 5px × 2 = 22px.
27
+ */
28
+ function fixSwitchLayout(css: string): string {
29
+ // Match the first .gtk-switch { ... } block and fix min-width inside it.
30
+ // The compiled CSS has exactly one `.gtk-switch {` rule with min-width: 22px.
31
+ return css.replace(
32
+ /(\.gtk-switch\s*\{[^}]*?)min-width:\s*22px/,
33
+ "$1min-width: 44px;\n min-height: 22px",
34
+ );
35
+ }
36
+
37
+ /**
38
+ * Post-process compiled CSS to replace the baked-in accent hex and all
39
+ * rgba(R,G,B,A) derived forms with CSS custom property references.
40
+ * This allows the accent color to be overridden at runtime.
41
+ */
42
+ function replaceAccentWithVar(css: string, scheme: "light" | "dark"): string {
43
+ const { hex, r, g, b } = ACCENT_HEX[scheme];
44
+
45
+ // Replace bare hex (case-insensitive)
46
+ css = css.replace(new RegExp(hex, "gi"), "var(--fluent-accent)");
47
+
48
+ // Replace rgba(R, G, B, A) derived forms → color-mix(in srgb, var(--fluent-accent) A%, transparent)
49
+ css = css.replace(
50
+ new RegExp(`rgba\\(${r},\\s*${g},\\s*${b},\\s*([\\d.]+)\\)`, "g"),
51
+ (_, a: string) =>
52
+ `color-mix(in srgb, var(--fluent-accent) ${Math.round(parseFloat(a) * 100)}%, transparent)`,
53
+ );
54
+
55
+ return css;
56
+ }
57
+
58
+ const results: Record<string, string> = {};
59
+
60
+ for (const scheme of schemes) {
61
+ const scssEntry = `${upstreamDir}/gtk/4.0/gtk-${scheme === "light" ? "Light" : "Dark"}.scss`;
62
+
63
+ for (const titlebutton of titlebuttons) {
64
+ for (const win of windows) {
65
+ const tweaksTempContent = `
66
+ $panel_style: 'compact';
67
+ $opacity: 'default';
68
+ $window: '${win}';
69
+ $theme: 'default';
70
+ $blur: 'false';
71
+ $outline: 'true';
72
+ $titlebutton: '${titlebutton}';
73
+ `;
74
+ writeFileSync(`${sassDir}/_tweaks-temp.scss`, tweaksTempContent);
75
+
76
+ try {
77
+ let css = await compileGtkCSS(scssEntry, { scheme });
78
+ css = replaceAccentWithVar(css, scheme);
79
+ css = fixSwitchLayout(css);
80
+
81
+ const key = `${scheme}_${titlebutton}_${win}`;
82
+ results[key] = css;
83
+ process.stdout.write(` ${key}: ${css.length}b\n`);
84
+ } finally {
85
+ try {
86
+ unlinkSync(`${sassDir}/_tweaks-temp.scss`);
87
+ } catch {}
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ // Write individual CSS files
94
+ for (const [key, css] of Object.entries(results)) {
95
+ writeFileSync(`${outDir}${key}.css`, css);
96
+ }
97
+
98
+ // Write JS index that exports all variants as named string constants
99
+ const indexLines = Object.keys(results).map(
100
+ (key) => `export { default as ${key} } from "./${key}.css" with { type: "text" };`,
101
+ );
102
+ writeFileSync(`${outDir}index.ts`, indexLines.join("\n") + "\n");
103
+
104
+ console.log(`Built ${Object.keys(results).length} Fluent variants.`);