ctheme 0.1.4 → 0.1.5

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 (3) hide show
  1. package/README.md +5 -2
  2. package/bin/ctheme.js +126 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -42,6 +42,8 @@ Apply a bundled theme live:
42
42
 
43
43
  ```bash
44
44
  ctheme use solarized
45
+ ctheme use solarized-dark
46
+ ctheme use tide-light
45
47
  ctheme use harbor --default
46
48
  ctheme use velvet --font "Space Mono"
47
49
  ```
@@ -151,13 +153,14 @@ Managed font installs go to:
151
153
 
152
154
  ```text
153
155
  aurora, cobalt, dune, ember, espresso, forest, glacier, harbor,
154
- lotus, mint, mono, neon, noir, obsidian, paper, rose,
155
- solarized, solarized-dark, velvet
156
+ lotus, mint, mono, neon, noir, obsidian, paper, plum, rose,
157
+ sage, solarized, terracotta, tide, velvet
156
158
  ```
157
159
 
158
160
  Bundled themes intentionally vary their font pairings so they do not all feel the same.
159
161
  The npm install bootstrap preinstalls the curated font set those presets rely on, so the bundled themes render correctly immediately on macOS.
160
162
  The default code and terminal font choices are biased toward tighter, denser monospace faces rather than wide-spaced ones.
163
+ Every bundled preset family now has both `-light` and `-dark` variants.
161
164
 
162
165
  ## Contributing
163
166
 
package/bin/ctheme.js CHANGED
@@ -99,7 +99,7 @@ const FONT_CHOICES = {
99
99
  terminal: ["IBM Plex Mono", "Source Code Pro", "JetBrains Mono", "Roboto Mono", "Azeret Mono", "Fira Code", "Ubuntu Mono", "Victor Mono", "DM Mono", "Space Mono"]
100
100
  };
101
101
 
102
- const PRESETS = {
102
+ const BASE_PRESETS = {
103
103
  noir: {
104
104
  fonts: { terminal: "IBM Plex Mono", ui: "Space Grotesk", code: "IBM Plex Mono" },
105
105
  accent: "#79c0ff",
@@ -403,9 +403,75 @@ const PRESETS = {
403
403
  orange: "#ffb86c",
404
404
  purple: "#c77dff",
405
405
  cyan: "#7bdff2"
406
+ },
407
+ tide: {
408
+ fonts: { terminal: "IBM Plex Mono", ui: "Urbanist", code: "IBM Plex Mono" },
409
+ accent: "#2f8fcb",
410
+ bg: "#eef7fb",
411
+ surface: "#f9fdff",
412
+ surfaceAlt: "#dceef7",
413
+ fg: "#183746",
414
+ muted: "#587989",
415
+ dim: "#86a4b2",
416
+ green: "#23836b",
417
+ red: "#d14b5a",
418
+ yellow: "#9a7600",
419
+ orange: "#cc6d1f",
420
+ purple: "#6967ce",
421
+ cyan: "#117e97"
422
+ },
423
+ terracotta: {
424
+ fonts: { terminal: "Source Code Pro", ui: "Instrument Serif", code: "Source Code Pro" },
425
+ accent: "#c96a44",
426
+ bg: "#fff5ef",
427
+ surface: "#fffaf7",
428
+ surfaceAlt: "#f6e3d7",
429
+ fg: "#3d2a22",
430
+ muted: "#7b5d50",
431
+ dim: "#ab8575",
432
+ green: "#4d8657",
433
+ red: "#c45151",
434
+ yellow: "#a67a17",
435
+ orange: "#c96a44",
436
+ purple: "#8b63b8",
437
+ cyan: "#3e8f99"
438
+ },
439
+ plum: {
440
+ fonts: { terminal: "Azeret Mono", ui: "Fraunces", code: "Azeret Mono" },
441
+ accent: "#8a5cf6",
442
+ bg: "#140f1f",
443
+ surface: "#20172f",
444
+ surfaceAlt: "#2c2140",
445
+ fg: "#f4efff",
446
+ muted: "#b7a7d6",
447
+ dim: "#7e71a0",
448
+ green: "#86d39e",
449
+ red: "#ff7ca8",
450
+ yellow: "#e8c45c",
451
+ orange: "#ff9f6c",
452
+ purple: "#bb9cff",
453
+ cyan: "#74d7e8"
454
+ },
455
+ sage: {
456
+ fonts: { terminal: "Roboto Mono", ui: "IBM Plex Sans", code: "Roboto Mono" },
457
+ accent: "#6f9f6f",
458
+ bg: "#f4f7f1",
459
+ surface: "#fbfcf8",
460
+ surfaceAlt: "#e5ecdf",
461
+ fg: "#263126",
462
+ muted: "#647564",
463
+ dim: "#93a293",
464
+ green: "#5b9460",
465
+ red: "#cb5b66",
466
+ yellow: "#a0871a",
467
+ orange: "#bf7645",
468
+ purple: "#7e6dc5",
469
+ cyan: "#4f8f88"
406
470
  }
407
471
  };
408
472
 
473
+ const PRESETS = buildPresetLibrary(BASE_PRESETS);
474
+
409
475
  async function main() {
410
476
  try {
411
477
  const args = process.argv.slice(2);
@@ -541,6 +607,65 @@ Flags for reset:
541
607
  `);
542
608
  }
543
609
 
610
+ function buildPresetLibrary(basePresets) {
611
+ const families = {};
612
+
613
+ for (const [name, palette] of Object.entries(basePresets)) {
614
+ const match = name.match(/^(.*?)-(light|dark)$/);
615
+ const family = match ? match[1] : name;
616
+ const explicitMode = match ? match[2] : "";
617
+ if (!families[family]) {
618
+ families[family] = {};
619
+ }
620
+ if (explicitMode) {
621
+ families[family][explicitMode] = palette;
622
+ } else {
623
+ families[family].base = palette;
624
+ }
625
+ }
626
+
627
+ const presets = {};
628
+ for (const [family, variants] of Object.entries(families)) {
629
+ const basePalette = variants.base || variants.light || variants.dark;
630
+ const baseMode = inferMode(basePalette);
631
+ const lightPalette = variants.light || (baseMode === "light" ? basePalette : derivePaletteVariant(basePalette, "light"));
632
+ const darkPalette = variants.dark || (baseMode === "dark" ? basePalette : derivePaletteVariant(basePalette, "dark"));
633
+
634
+ presets[family] = variants.base || (baseMode === "light" ? lightPalette : darkPalette);
635
+ presets[`${family}-light`] = lightPalette;
636
+ presets[`${family}-dark`] = darkPalette;
637
+ }
638
+ return presets;
639
+ }
640
+
641
+ function derivePaletteVariant(palette, targetMode) {
642
+ const accent = normalizeHex(palette.accent);
643
+ const targetIsLight = targetMode === "light";
644
+ const bg = targetIsLight ? mixHex(accent, "#fffdf8", 0.9) : mixHex(accent, "#090b10", 0.9);
645
+ const surface = targetIsLight ? mixHex(accent, "#ffffff", 0.95) : mixHex(accent, "#141821", 0.86);
646
+ const surfaceAlt = targetIsLight ? mixHex(accent, "#eef1f4", 0.8) : mixHex(accent, "#212735", 0.78);
647
+ const fg = targetIsLight ? mixHex(accent, "#1f252c", 0.88) : mixHex(accent, "#f5f7fb", 0.9);
648
+ const muted = targetIsLight ? mixHex(accent, "#55606f", 0.72) : mixHex(accent, "#b4becc", 0.72);
649
+ const dim = targetIsLight ? mixHex(accent, "#7f8895", 0.72) : mixHex(accent, "#7d8798", 0.62);
650
+
651
+ return {
652
+ ...palette,
653
+ accent,
654
+ bg,
655
+ surface,
656
+ surfaceAlt,
657
+ fg,
658
+ muted,
659
+ dim,
660
+ green: targetIsLight ? mixHex(palette.green, "#3b6f43", 0.45) : mixHex(palette.green, "#8fe3a2", 0.35),
661
+ red: targetIsLight ? mixHex(palette.red, "#a83f4a", 0.35) : mixHex(palette.red, "#ff8ca0", 0.32),
662
+ yellow: targetIsLight ? mixHex(palette.yellow, "#8f6f10", 0.38) : mixHex(palette.yellow, "#f1d87b", 0.32),
663
+ orange: targetIsLight ? mixHex(palette.orange, "#af5b2d", 0.35) : mixHex(palette.orange, "#ffb07a", 0.32),
664
+ purple: targetIsLight ? mixHex(palette.purple, "#6d56b1", 0.35) : mixHex(palette.purple, "#c1a6ff", 0.32),
665
+ cyan: targetIsLight ? mixHex(palette.cyan, "#2f7886", 0.38) : mixHex(palette.cyan, "#82dcea", 0.32)
666
+ };
667
+ }
668
+
544
669
  function runList() {
545
670
  const paths = getThemePaths();
546
671
  const custom = new Set(Object.keys(PRESETS));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctheme",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Theme manager for making terminals look better with colors, fonts, and live profile switching",
5
5
  "license": "MIT",
6
6
  "repository": {