@silvery/theme 0.3.0

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.
Files changed (47) hide show
  1. package/package.json +36 -0
  2. package/src/ThemeContext.tsx +62 -0
  3. package/src/alias.ts +94 -0
  4. package/src/auto-generate.ts +126 -0
  5. package/src/builder.ts +218 -0
  6. package/src/cli.ts +275 -0
  7. package/src/color.ts +142 -0
  8. package/src/contrast.ts +75 -0
  9. package/src/css.ts +51 -0
  10. package/src/derive.ts +167 -0
  11. package/src/detect.ts +263 -0
  12. package/src/export/base16.ts +64 -0
  13. package/src/generate.ts +79 -0
  14. package/src/generators.ts +255 -0
  15. package/src/import/base16.ts +150 -0
  16. package/src/import/types.ts +47 -0
  17. package/src/index.ts +2 -0
  18. package/src/palettes/ayu.ts +92 -0
  19. package/src/palettes/catppuccin.ts +118 -0
  20. package/src/palettes/dracula.ts +34 -0
  21. package/src/palettes/edge.ts +63 -0
  22. package/src/palettes/everforest.ts +63 -0
  23. package/src/palettes/gruvbox.ts +62 -0
  24. package/src/palettes/horizon.ts +35 -0
  25. package/src/palettes/index.ts +293 -0
  26. package/src/palettes/kanagawa.ts +91 -0
  27. package/src/palettes/material.ts +64 -0
  28. package/src/palettes/modus.ts +63 -0
  29. package/src/palettes/monokai.ts +64 -0
  30. package/src/palettes/moonfly.ts +35 -0
  31. package/src/palettes/nightfly.ts +35 -0
  32. package/src/palettes/nightfox.ts +63 -0
  33. package/src/palettes/nord.ts +34 -0
  34. package/src/palettes/one-dark.ts +34 -0
  35. package/src/palettes/oxocarbon.ts +63 -0
  36. package/src/palettes/palenight.ts +36 -0
  37. package/src/palettes/rose-pine.ts +90 -0
  38. package/src/palettes/snazzy.ts +35 -0
  39. package/src/palettes/solarized.ts +62 -0
  40. package/src/palettes/sonokai.ts +35 -0
  41. package/src/palettes/tokyo-night.ts +90 -0
  42. package/src/resolve.ts +44 -0
  43. package/src/state.ts +58 -0
  44. package/src/theme.ts +148 -0
  45. package/src/types.ts +223 -0
  46. package/src/validate-theme.ts +100 -0
  47. package/src/validate.ts +56 -0
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Nightfox palettes — rich, vibrant themes for Neovim.
3
+ * Source: https://github.com/EdenEast/nightfox.nvim
4
+ */
5
+
6
+ import type { ColorPalette } from "../types"
7
+ import { brighten } from "../color"
8
+
9
+ /** Nightfox — dark blue-toned variant. */
10
+ export const nightfox: ColorPalette = {
11
+ name: "nightfox",
12
+ dark: true,
13
+ black: "#131A24",
14
+ red: "#C94F6D",
15
+ green: "#81B29A",
16
+ yellow: "#DBC074",
17
+ blue: "#719CD6",
18
+ magenta: "#9D79D6",
19
+ cyan: "#63CDCF",
20
+ white: "#71839B",
21
+ brightBlack: "#212E3F",
22
+ brightRed: "#F4A261",
23
+ brightGreen: brighten("#81B29A", 0.15),
24
+ brightYellow: brighten("#DBC074", 0.15),
25
+ brightBlue: brighten("#719CD6", 0.15),
26
+ brightMagenta: "#D67AD2",
27
+ brightCyan: brighten("#63CDCF", 0.15),
28
+ brightWhite: "#CDCECF",
29
+ foreground: "#CDCECF",
30
+ background: "#192330",
31
+ cursorColor: "#CDCECF",
32
+ cursorText: "#192330",
33
+ selectionBackground: "#39506D",
34
+ selectionForeground: "#CDCECF",
35
+ }
36
+
37
+ /** Dawnfox — warm light variant inspired by Rose Pine Dawn. */
38
+ export const dawnfox: ColorPalette = {
39
+ name: "dawnfox",
40
+ dark: false,
41
+ black: "#EBE5DF",
42
+ red: "#B4637A",
43
+ green: "#618774",
44
+ yellow: "#EA9D34",
45
+ blue: "#286983",
46
+ magenta: "#907AA9",
47
+ cyan: "#56949F",
48
+ white: "#A8A3B3",
49
+ brightBlack: "#EBE0DF",
50
+ brightRed: "#D7827E",
51
+ brightGreen: brighten("#618774", 0.15),
52
+ brightYellow: brighten("#EA9D34", 0.15),
53
+ brightBlue: brighten("#286983", 0.15),
54
+ brightMagenta: "#D685AF",
55
+ brightCyan: brighten("#56949F", 0.15),
56
+ brightWhite: "#575279",
57
+ foreground: "#575279",
58
+ background: "#FAF4ED",
59
+ cursorColor: "#575279",
60
+ cursorText: "#FAF4ED",
61
+ selectionBackground: "#BDBFC9",
62
+ selectionForeground: "#575279",
63
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Nord palette — Arctic, north-bluish clean.
3
+ */
4
+
5
+ import type { ColorPalette } from "../types"
6
+ import { brighten } from "../color"
7
+
8
+ /** Nord — the classic dark arctic theme. */
9
+ export const nord: ColorPalette = {
10
+ name: "nord",
11
+ dark: true,
12
+ black: "#2E3440",
13
+ red: "#BF616A",
14
+ green: "#A3BE8C",
15
+ yellow: "#EBCB8B",
16
+ blue: "#5E81AC",
17
+ magenta: "#B48EAD",
18
+ cyan: "#8FBCBB",
19
+ white: "#D8DEE9",
20
+ brightBlack: "#3B4252",
21
+ brightRed: "#D08770",
22
+ brightGreen: brighten("#A3BE8C", 0.15),
23
+ brightYellow: brighten("#EBCB8B", 0.15),
24
+ brightBlue: brighten("#5E81AC", 0.15),
25
+ brightMagenta: "#B48EAD",
26
+ brightCyan: brighten("#8FBCBB", 0.15),
27
+ brightWhite: "#ECEFF4",
28
+ foreground: "#ECEFF4",
29
+ background: "#2E3440",
30
+ cursorColor: "#ECEFF4",
31
+ cursorText: "#2E3440",
32
+ selectionBackground: "#4C566A",
33
+ selectionForeground: "#ECEFF4",
34
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * One Dark palette — Atom's iconic dark theme.
3
+ */
4
+
5
+ import type { ColorPalette } from "../types"
6
+ import { brighten } from "../color"
7
+
8
+ /** One Dark — the classic Atom editor theme. */
9
+ export const oneDark: ColorPalette = {
10
+ name: "one-dark",
11
+ dark: true,
12
+ black: "#21252B",
13
+ red: "#E06C75",
14
+ green: "#98C379",
15
+ yellow: "#E5C07B",
16
+ blue: "#61AFEF",
17
+ magenta: "#C678DD",
18
+ cyan: "#56B6C2",
19
+ white: "#ABB2BF",
20
+ brightBlack: "#2C313A",
21
+ brightRed: "#D19A66",
22
+ brightGreen: brighten("#98C379", 0.15),
23
+ brightYellow: brighten("#E5C07B", 0.15),
24
+ brightBlue: brighten("#61AFEF", 0.15),
25
+ brightMagenta: "#E06C75",
26
+ brightCyan: brighten("#56B6C2", 0.15),
27
+ brightWhite: "#ABB2BF",
28
+ foreground: "#ABB2BF",
29
+ background: "#282C34",
30
+ cursorColor: "#ABB2BF",
31
+ cursorText: "#282C34",
32
+ selectionBackground: "#5C6370",
33
+ selectionForeground: "#ABB2BF",
34
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Oxocarbon palettes — IBM Carbon Design-inspired theme.
3
+ * Source: https://github.com/nyoom-engineering/oxocarbon.nvim
4
+ */
5
+
6
+ import type { ColorPalette } from "../types"
7
+ import { brighten } from "../color"
8
+
9
+ /** Oxocarbon Dark — IBM Carbon-inspired dark variant. */
10
+ export const oxocarbonDark: ColorPalette = {
11
+ name: "oxocarbon-dark",
12
+ dark: true,
13
+ black: "#131313",
14
+ red: "#EE5396",
15
+ green: "#42BE65",
16
+ yellow: "#82CFFF",
17
+ blue: "#78A9FF",
18
+ magenta: "#BE95FF",
19
+ cyan: "#08BDBA",
20
+ white: "#5C5C5C",
21
+ brightBlack: "#2A2A2A",
22
+ brightRed: "#FF7EB6",
23
+ brightGreen: brighten("#42BE65", 0.15),
24
+ brightYellow: brighten("#82CFFF", 0.15),
25
+ brightBlue: brighten("#78A9FF", 0.15),
26
+ brightMagenta: "#FF7EB6",
27
+ brightCyan: brighten("#08BDBA", 0.15),
28
+ brightWhite: "#F3F3F3",
29
+ foreground: "#F3F3F3",
30
+ background: "#161616",
31
+ cursorColor: "#F3F3F3",
32
+ cursorText: "#161616",
33
+ selectionBackground: "#404040",
34
+ selectionForeground: "#F3F3F3",
35
+ }
36
+
37
+ /** Oxocarbon Light — IBM Carbon-inspired light variant. */
38
+ export const oxocarbonLight: ColorPalette = {
39
+ name: "oxocarbon-light",
40
+ dark: false,
41
+ black: "#F3F3F3",
42
+ red: "#EE5396",
43
+ green: "#42BE65",
44
+ yellow: "#FFAB91",
45
+ blue: "#0F62FE",
46
+ magenta: "#BE95FF",
47
+ cyan: "#08BDBA",
48
+ white: "#90A4AE",
49
+ brightBlack: "#D5D5D5",
50
+ brightRed: "#FF6F00",
51
+ brightGreen: brighten("#42BE65", 0.15),
52
+ brightYellow: brighten("#FFAB91", 0.15),
53
+ brightBlue: brighten("#0F62FE", 0.15),
54
+ brightMagenta: "#FF7EB6",
55
+ brightCyan: brighten("#08BDBA", 0.15),
56
+ brightWhite: "#37474F",
57
+ foreground: "#37474F",
58
+ background: "#FFFFFF",
59
+ cursorColor: "#37474F",
60
+ cursorText: "#FFFFFF",
61
+ selectionBackground: "#525252",
62
+ selectionForeground: "#37474F",
63
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Palenight palette — Material Palenight variant.
3
+ * Source: https://github.com/kaicataldo/material.vim (palenight style)
4
+ * Reference: https://github.com/JonathanSpeek/palenight-iterm2
5
+ */
6
+
7
+ import type { ColorPalette } from "../types"
8
+ import { brighten } from "../color"
9
+
10
+ /** Palenight — the soft, purple-tinted Material dark variant. */
11
+ export const palenight: ColorPalette = {
12
+ name: "palenight",
13
+ dark: true,
14
+ black: "#1c1f2b", // line_highlight (deepest)
15
+ red: "#f07178",
16
+ green: "#c3e88d",
17
+ yellow: "#ffcb6b",
18
+ blue: "#82aaff",
19
+ magenta: "#c792ea",
20
+ cyan: "#89ddff", // cyan
21
+ white: "#676e95", // comments
22
+ brightBlack: "#343b51", // selection
23
+ brightRed: "#f78c6c",
24
+ brightGreen: brighten("#c3e88d", 0.15),
25
+ brightYellow: brighten("#ffcb6b", 0.15),
26
+ brightBlue: brighten("#82aaff", 0.15),
27
+ brightMagenta: "#ff5370",
28
+ brightCyan: brighten("#89ddff", 0.15),
29
+ brightWhite: "#a6accd", // foreground
30
+ foreground: "#a6accd", // foreground
31
+ background: "#292d3e", // background
32
+ cursorColor: "#a6accd", // foreground
33
+ cursorText: "#292d3e", // background
34
+ selectionBackground: "#4e5579", // guides/invisibles
35
+ selectionForeground: "#a6accd", // foreground
36
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Rosé Pine palettes — all natural pine, faux fur and a bit of soho vibes.
3
+ */
4
+
5
+ import type { ColorPalette } from "../types"
6
+ import { brighten } from "../color"
7
+
8
+ /** Rosé Pine — the main dark variant. */
9
+ export const rosePine: ColorPalette = {
10
+ name: "rose-pine",
11
+ dark: true,
12
+ black: "#191724",
13
+ red: "#EB6F92",
14
+ green: "#31748F",
15
+ yellow: "#F6C177",
16
+ blue: "#3E8FB0",
17
+ magenta: "#C4A7E7",
18
+ cyan: "#9CCFD8",
19
+ white: "#908CAA",
20
+ brightBlack: "#26233A",
21
+ brightRed: "#EA9A97",
22
+ brightGreen: brighten("#31748F", 0.15),
23
+ brightYellow: brighten("#F6C177", 0.15),
24
+ brightBlue: brighten("#3E8FB0", 0.15),
25
+ brightMagenta: "#EBBCBA",
26
+ brightCyan: brighten("#9CCFD8", 0.15),
27
+ brightWhite: "#E0DEF4",
28
+ foreground: "#E0DEF4",
29
+ background: "#1F1D2E",
30
+ cursorColor: "#E0DEF4",
31
+ cursorText: "#1F1D2E",
32
+ selectionBackground: "#6E6A86",
33
+ selectionForeground: "#E0DEF4",
34
+ }
35
+
36
+ /** Rosé Pine Moon — slightly lighter dark variant. */
37
+ export const rosePineMoon: ColorPalette = {
38
+ name: "rose-pine-moon",
39
+ dark: true,
40
+ black: "#232136",
41
+ red: "#EB6F92",
42
+ green: "#3E8FB0",
43
+ yellow: "#F6C177",
44
+ blue: "#3E8FB0",
45
+ magenta: "#C4A7E7",
46
+ cyan: "#9CCFD8",
47
+ white: "#908CAA",
48
+ brightBlack: "#393552",
49
+ brightRed: "#EA9A97",
50
+ brightGreen: brighten("#3E8FB0", 0.15),
51
+ brightYellow: brighten("#F6C177", 0.15),
52
+ brightBlue: brighten("#3E8FB0", 0.15),
53
+ brightMagenta: "#EA9A97",
54
+ brightCyan: brighten("#9CCFD8", 0.15),
55
+ brightWhite: "#E0DEF4",
56
+ foreground: "#E0DEF4",
57
+ background: "#2A273F",
58
+ cursorColor: "#E0DEF4",
59
+ cursorText: "#2A273F",
60
+ selectionBackground: "#6E6A86",
61
+ selectionForeground: "#E0DEF4",
62
+ }
63
+
64
+ /** Rosé Pine Dawn — the light variant. */
65
+ export const rosePineDawn: ColorPalette = {
66
+ name: "rose-pine-dawn",
67
+ dark: false,
68
+ black: "#FAF4ED",
69
+ red: "#B4637A",
70
+ green: "#286983",
71
+ yellow: "#EA9D34",
72
+ blue: "#286983",
73
+ magenta: "#907AA9",
74
+ cyan: "#56949F",
75
+ white: "#797593",
76
+ brightBlack: "#F2E9E1",
77
+ brightRed: "#D7827E",
78
+ brightGreen: brighten("#286983", 0.15),
79
+ brightYellow: brighten("#EA9D34", 0.15),
80
+ brightBlue: brighten("#286983", 0.15),
81
+ brightMagenta: "#D7827E",
82
+ brightCyan: brighten("#56949F", 0.15),
83
+ brightWhite: "#575279",
84
+ foreground: "#575279",
85
+ background: "#FFFAF3",
86
+ cursorColor: "#575279",
87
+ cursorText: "#FFFAF3",
88
+ selectionBackground: "#9893A5",
89
+ selectionForeground: "#575279",
90
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Snazzy palette — elegant dark theme with vivid colors.
3
+ * Source: https://github.com/sindresorhus/hyper-snazzy
4
+ */
5
+
6
+ import type { ColorPalette } from "../types"
7
+ import { brighten } from "../color"
8
+
9
+ /** Snazzy — clean dark theme by Sindre Sorhus. */
10
+ export const snazzy: ColorPalette = {
11
+ name: "snazzy",
12
+ dark: true,
13
+ black: "#222430", // border color (deepest)
14
+ red: "#ff5c57",
15
+ green: "#5af78e",
16
+ yellow: "#f3f99d",
17
+ blue: "#57c7ff",
18
+ magenta: "#b267e6", // interpolated purple (between magenta and blue)
19
+ cyan: "#9aedfe", // cyan
20
+ white: "#97979b", // cursor/secondary text
21
+ brightBlack: "#34353e", // slightly raised (interpolated)
22
+ brightRed: "#ff9f43", // snazzy bright orange (warm interpolation)
23
+ brightGreen: brighten("#5af78e", 0.15),
24
+ brightYellow: brighten("#f3f99d", 0.15),
25
+ brightBlue: brighten("#57c7ff", 0.15),
26
+ brightMagenta: "#ff6ac1", // magenta
27
+ brightCyan: brighten("#9aedfe", 0.15),
28
+ brightWhite: "#eff0eb", // foreground
29
+ foreground: "#eff0eb", // foreground
30
+ background: "#282a36", // background
31
+ cursorColor: "#eff0eb", // foreground
32
+ cursorText: "#282a36", // background
33
+ selectionBackground: "#686868", // light black / muted chrome
34
+ selectionForeground: "#eff0eb", // foreground
35
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Solarized palettes — precision colors for machines and people.
3
+ */
4
+
5
+ import type { ColorPalette } from "../types"
6
+ import { brighten } from "../color"
7
+
8
+ /** Solarized Dark — Ethan Schoonover's classic dark variant. */
9
+ export const solarizedDark: ColorPalette = {
10
+ name: "solarized-dark",
11
+ dark: true,
12
+ black: "#002B36",
13
+ red: "#DC322F",
14
+ green: "#859900",
15
+ yellow: "#B58900",
16
+ blue: "#268BD2",
17
+ magenta: "#6C71C4",
18
+ cyan: "#2AA198",
19
+ white: "#839496",
20
+ brightBlack: "#586E75",
21
+ brightRed: "#CB4B16",
22
+ brightGreen: brighten("#859900", 0.15),
23
+ brightYellow: brighten("#B58900", 0.15),
24
+ brightBlue: brighten("#268BD2", 0.15),
25
+ brightMagenta: "#D33682",
26
+ brightCyan: brighten("#2AA198", 0.15),
27
+ brightWhite: "#FDF6E3",
28
+ foreground: "#FDF6E3",
29
+ background: "#073642",
30
+ cursorColor: "#FDF6E3",
31
+ cursorText: "#073642",
32
+ selectionBackground: "#657B83",
33
+ selectionForeground: "#FDF6E3",
34
+ }
35
+
36
+ /** Solarized Light — Ethan Schoonover's classic light variant. */
37
+ export const solarizedLight: ColorPalette = {
38
+ name: "solarized-light",
39
+ dark: false,
40
+ black: "#FDF6E3",
41
+ red: "#DC322F",
42
+ green: "#859900",
43
+ yellow: "#B58900",
44
+ blue: "#268BD2",
45
+ magenta: "#6C71C4",
46
+ cyan: "#2AA198",
47
+ white: "#657B83",
48
+ brightBlack: "#DDD6C1",
49
+ brightRed: "#CB4B16",
50
+ brightGreen: brighten("#859900", 0.15),
51
+ brightYellow: brighten("#B58900", 0.15),
52
+ brightBlue: brighten("#268BD2", 0.15),
53
+ brightMagenta: "#D33682",
54
+ brightCyan: brighten("#2AA198", 0.15),
55
+ brightWhite: "#073642",
56
+ foreground: "#073642",
57
+ background: "#EEE8D5",
58
+ cursorColor: "#073642",
59
+ cursorText: "#EEE8D5",
60
+ selectionBackground: "#93A1A1",
61
+ selectionForeground: "#073642",
62
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Sonokai palette — high-contrast vivid theme (Monokai Pro-inspired).
3
+ * Source: https://github.com/sainnhe/sonokai (default style)
4
+ */
5
+
6
+ import type { ColorPalette } from "../types"
7
+ import { brighten } from "../color"
8
+
9
+ /** Sonokai — vivid dark theme with Monokai-inspired accents. */
10
+ export const sonokai: ColorPalette = {
11
+ name: "sonokai",
12
+ dark: true,
13
+ black: "#181819",
14
+ red: "#FC5D7C",
15
+ green: "#9ED072",
16
+ yellow: "#E7C664",
17
+ blue: "#76CCE0",
18
+ magenta: "#B39DF3",
19
+ cyan: "#76CCE0",
20
+ white: "#7F8490",
21
+ brightBlack: "#33353F",
22
+ brightRed: "#F39660",
23
+ brightGreen: brighten("#9ED072", 0.15),
24
+ brightYellow: brighten("#E7C664", 0.15),
25
+ brightBlue: brighten("#76CCE0", 0.15),
26
+ brightMagenta: "#FC5D7C",
27
+ brightCyan: brighten("#76CCE0", 0.15),
28
+ brightWhite: "#E2E2E3",
29
+ foreground: "#E2E2E3",
30
+ background: "#2C2E34",
31
+ cursorColor: "#E2E2E3",
32
+ cursorText: "#2C2E34",
33
+ selectionBackground: "#414550",
34
+ selectionForeground: "#E2E2E3",
35
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Tokyo Night palette — a clean dark theme inspired by Tokyo city lights.
3
+ */
4
+
5
+ import type { ColorPalette } from "../types"
6
+ import { brighten } from "../color"
7
+
8
+ /** Tokyo Night — the default dark variant. */
9
+ export const tokyoNight: ColorPalette = {
10
+ name: "tokyo-night",
11
+ dark: true,
12
+ black: "#1A1B26",
13
+ red: "#F7768E",
14
+ green: "#9ECE6A",
15
+ yellow: "#E0AF68",
16
+ blue: "#7AA2F7",
17
+ magenta: "#BB9AF7",
18
+ cyan: "#73DACA",
19
+ white: "#A9B1D6",
20
+ brightBlack: "#292E42",
21
+ brightRed: "#FF9E64",
22
+ brightGreen: brighten("#9ECE6A", 0.15),
23
+ brightYellow: brighten("#E0AF68", 0.15),
24
+ brightBlue: brighten("#7AA2F7", 0.15),
25
+ brightMagenta: "#FF007C",
26
+ brightCyan: brighten("#73DACA", 0.15),
27
+ brightWhite: "#C0CAF5",
28
+ foreground: "#C0CAF5",
29
+ background: "#24283B",
30
+ cursorColor: "#C0CAF5",
31
+ cursorText: "#24283B",
32
+ selectionBackground: "#545C7E",
33
+ selectionForeground: "#C0CAF5",
34
+ }
35
+
36
+ /** Tokyo Night Storm — slightly lighter background. */
37
+ export const tokyoNightStorm: ColorPalette = {
38
+ name: "tokyo-night-storm",
39
+ dark: true,
40
+ black: "#1F2335",
41
+ red: "#F7768E",
42
+ green: "#9ECE6A",
43
+ yellow: "#E0AF68",
44
+ blue: "#7AA2F7",
45
+ magenta: "#BB9AF7",
46
+ cyan: "#73DACA",
47
+ white: "#A9B1D6",
48
+ brightBlack: "#292E42",
49
+ brightRed: "#FF9E64",
50
+ brightGreen: brighten("#9ECE6A", 0.15),
51
+ brightYellow: brighten("#E0AF68", 0.15),
52
+ brightBlue: brighten("#7AA2F7", 0.15),
53
+ brightMagenta: "#FF007C",
54
+ brightCyan: brighten("#73DACA", 0.15),
55
+ brightWhite: "#C0CAF5",
56
+ foreground: "#C0CAF5",
57
+ background: "#24283B",
58
+ cursorColor: "#C0CAF5",
59
+ cursorText: "#24283B",
60
+ selectionBackground: "#545C7E",
61
+ selectionForeground: "#C0CAF5",
62
+ }
63
+
64
+ /** Tokyo Night Day — the light variant. */
65
+ export const tokyoNightDay: ColorPalette = {
66
+ name: "tokyo-night-day",
67
+ dark: false,
68
+ black: "#E1E2E7",
69
+ red: "#F52A65",
70
+ green: "#587539",
71
+ yellow: "#8C6C3E",
72
+ blue: "#2E7DE9",
73
+ magenta: "#9854F1",
74
+ cyan: "#118C74",
75
+ white: "#6172B0",
76
+ brightBlack: "#C4C5CB",
77
+ brightRed: "#B15C00",
78
+ brightGreen: brighten("#587539", 0.15),
79
+ brightYellow: brighten("#8C6C3E", 0.15),
80
+ brightBlue: brighten("#2E7DE9", 0.15),
81
+ brightMagenta: "#F52A65",
82
+ brightCyan: brighten("#118C74", 0.15),
83
+ brightWhite: "#3760BF",
84
+ foreground: "#3760BF",
85
+ background: "#D5D6DB",
86
+ cursorColor: "#3760BF",
87
+ cursorText: "#D5D6DB",
88
+ selectionBackground: "#9699A3",
89
+ selectionForeground: "#3760BF",
90
+ }
package/src/resolve.ts ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Token resolution — resolves `$token` strings against a Theme.
3
+ *
4
+ * All theme property names are lowercase, no hyphens (e.g. `surfacebg`).
5
+ * Hyphens in token strings are stripped for lookup: `$surface-bg` → `surfacebg`.
6
+ * This allows both `$surfacebg` and `$surface-bg` to resolve identically.
7
+ */
8
+
9
+ import type { Theme } from "./types"
10
+
11
+ /** Color-typed keys of Theme (excludes metadata and palette). */
12
+ type ThemeColorKey = Exclude<keyof Theme, "name" | "palette">
13
+
14
+ /**
15
+ * Resolve a color value — if it starts with `$`, look up the token in the theme.
16
+ *
17
+ * Supports:
18
+ * - Named tokens: `$primary`, `$fg`, `$border`, `$muted`, etc.
19
+ * - Compound tokens: `$surfacebg`, `$mutedbg`, `$disabledfg`, etc.
20
+ * - Hyphenated tokens: `$surface-bg` → strips hyphens → `surfacebg`
21
+ * - Palette colors: `$color0` through `$color15`
22
+ *
23
+ * Returns `undefined` for `undefined` input. Non-`$` strings pass through unchanged.
24
+ * Unknown tokens pass through as-is.
25
+ */
26
+ export function resolveThemeColor(color: string | undefined, theme: Theme): string | undefined {
27
+ if (!color) return undefined
28
+ if (!color.startsWith("$")) return color
29
+
30
+ const token = color.slice(1)
31
+
32
+ // Palette colors: $color0 through $color15
33
+ if (token.startsWith("color")) {
34
+ const idx = parseInt(token.slice(5), 10)
35
+ if (idx >= 0 && idx < 16 && theme.palette && idx < theme.palette.length) {
36
+ return theme.palette[idx]
37
+ }
38
+ }
39
+
40
+ // Strip hyphens for lookup (supports both $surfacebg and $surface-bg)
41
+ const key = token.replace(/-/g, "") as ThemeColorKey
42
+ const val = theme[key]
43
+ return typeof val === "string" ? val : color
44
+ }
package/src/state.ts ADDED
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Active theme state — module-level for pipeline access.
3
+ *
4
+ * This module has side effects (global mutable state).
5
+ * Marked in package.json sideEffects for tree-shaking.
6
+ *
7
+ * Usage is optional — standalone users pass Theme objects explicitly
8
+ * to resolveThemeColor(token, theme). The global state exists for
9
+ * silvery's render pipeline where React context isn't accessible.
10
+ */
11
+
12
+ import type { Theme } from "./types"
13
+ import { ansi16DarkTheme } from "./palettes/index"
14
+
15
+ // ============================================================================
16
+ // Active Theme
17
+ // ============================================================================
18
+
19
+ /**
20
+ * The currently active theme, set by ThemeProvider during render.
21
+ * Used by parseColor() to resolve $token strings without React context access.
22
+ */
23
+ let _activeTheme: Theme = ansi16DarkTheme
24
+
25
+ /** Set the active theme (called by ThemeProvider). */
26
+ export function setActiveTheme(theme: Theme): void {
27
+ _activeTheme = theme
28
+ }
29
+
30
+ /** Get the active theme (called by parseColor in render-helpers). */
31
+ export function getActiveTheme(): Theme {
32
+ return _contextStack.length > 0 ? _contextStack[_contextStack.length - 1]! : _activeTheme
33
+ }
34
+
35
+ // ============================================================================
36
+ // Context Theme Stack (per-subtree overrides during content phase)
37
+ // ============================================================================
38
+
39
+ /**
40
+ * Stack of per-subtree theme overrides, pushed/popped during content phase
41
+ * tree walk. When a Box has a `theme` prop, its theme is pushed before
42
+ * rendering children and popped after. getActiveTheme() checks this stack
43
+ * first, falling back to _activeTheme.
44
+ *
45
+ * This enables CSS custom property-like cascading: the nearest ancestor
46
+ * Box with a theme prop determines $token resolution for its subtree.
47
+ */
48
+ const _contextStack: Theme[] = []
49
+
50
+ /** Push a context theme (called by content phase for Box nodes with theme prop). */
51
+ export function pushContextTheme(theme: Theme): void {
52
+ _contextStack.push(theme)
53
+ }
54
+
55
+ /** Pop a context theme (called by content phase after processing Box subtree). */
56
+ export function popContextTheme(): void {
57
+ _contextStack.pop()
58
+ }