claude-scope 0.6.0 → 0.6.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.
Files changed (2) hide show
  1. package/dist/claude-scope.cjs +922 -236
  2. package/package.json +2 -2
@@ -275,6 +275,569 @@ function createGit(cwd) {
275
275
  return new NativeGit(cwd);
276
276
  }
277
277
 
278
+ // src/ui/utils/colors.ts
279
+ var reset = "\x1B[0m";
280
+ var red = "\x1B[31m";
281
+ var gray = "\x1B[90m";
282
+ var lightGray = "\x1B[37m";
283
+ var bold = "\x1B[1m";
284
+ function colorize(text, color) {
285
+ return `${color}${text}${reset}`;
286
+ }
287
+
288
+ // src/ui/theme/helpers.ts
289
+ function rgb(r, g, b) {
290
+ return `\x1B[38;2;${r};${g};${b}m`;
291
+ }
292
+ function createBaseColors(params) {
293
+ return {
294
+ text: params.modelColor,
295
+ muted: params.durationColor,
296
+ accent: params.accentColor,
297
+ border: params.durationColor
298
+ };
299
+ }
300
+ function createSemanticColors(params) {
301
+ return {
302
+ success: params.contextLow,
303
+ warning: params.contextMedium,
304
+ error: params.contextHigh,
305
+ info: params.branchColor
306
+ };
307
+ }
308
+ function createThemeColors(params) {
309
+ const base = createBaseColors({
310
+ modelColor: params.model,
311
+ durationColor: params.duration,
312
+ accentColor: params.accent
313
+ });
314
+ const semantic = createSemanticColors({
315
+ contextLow: params.contextLow,
316
+ contextMedium: params.contextMedium,
317
+ contextHigh: params.contextHigh,
318
+ branchColor: params.branch
319
+ });
320
+ return {
321
+ base,
322
+ semantic,
323
+ git: {
324
+ branch: params.branch,
325
+ changes: params.changes
326
+ },
327
+ context: {
328
+ low: params.contextLow,
329
+ medium: params.contextMedium,
330
+ high: params.contextHigh,
331
+ bar: params.contextLow
332
+ },
333
+ lines: {
334
+ added: params.linesAdded,
335
+ removed: params.linesRemoved
336
+ },
337
+ cost: {
338
+ amount: params.cost,
339
+ currency: params.cost
340
+ },
341
+ duration: {
342
+ value: params.duration,
343
+ unit: params.duration
344
+ },
345
+ model: {
346
+ name: params.model,
347
+ version: params.model
348
+ },
349
+ poker: {
350
+ participating: params.model,
351
+ nonParticipating: params.duration,
352
+ result: params.accent
353
+ }
354
+ };
355
+ }
356
+
357
+ // src/ui/theme/gray-theme.ts
358
+ var GRAY_THEME = {
359
+ name: "gray",
360
+ description: "Neutral gray theme for minimal color distraction",
361
+ colors: createThemeColors({
362
+ branch: gray,
363
+ changes: gray,
364
+ contextLow: gray,
365
+ contextMedium: gray,
366
+ contextHigh: gray,
367
+ linesAdded: gray,
368
+ linesRemoved: gray,
369
+ cost: gray,
370
+ model: gray,
371
+ duration: gray,
372
+ accent: gray
373
+ })
374
+ };
375
+
376
+ // src/ui/theme/themes/catppuccin-mocha-theme.ts
377
+ var CATPPUCCIN_MOCHA_THEME = {
378
+ name: "catppuccin-mocha",
379
+ description: "Soothing pastel theme",
380
+ colors: createThemeColors({
381
+ branch: rgb(137, 180, 250),
382
+ // Blue
383
+ changes: rgb(166, 227, 161),
384
+ // Green
385
+ contextLow: rgb(166, 227, 161),
386
+ // Green
387
+ contextMedium: rgb(238, 212, 159),
388
+ // Yellow
389
+ contextHigh: rgb(243, 139, 168),
390
+ // Red
391
+ linesAdded: rgb(166, 227, 161),
392
+ // Green
393
+ linesRemoved: rgb(243, 139, 168),
394
+ // Red
395
+ cost: rgb(245, 224, 220),
396
+ // Rosewater
397
+ model: rgb(203, 166, 247),
398
+ // Mauve
399
+ duration: rgb(147, 153, 178),
400
+ // Text gray
401
+ accent: rgb(243, 139, 168)
402
+ // Pink
403
+ })
404
+ };
405
+
406
+ // src/ui/theme/themes/cyberpunk-neon-theme.ts
407
+ var CYBERPUNK_NEON_THEME = {
408
+ name: "cyberpunk-neon",
409
+ description: "High-contrast neon cyberpunk aesthetic",
410
+ colors: createThemeColors({
411
+ branch: rgb(0, 191, 255),
412
+ // Cyan neon
413
+ changes: rgb(255, 0, 122),
414
+ // Magenta neon
415
+ contextLow: rgb(0, 255, 122),
416
+ // Green neon
417
+ contextMedium: rgb(255, 214, 0),
418
+ // Yellow neon
419
+ contextHigh: rgb(255, 0, 122),
420
+ // Magenta neon
421
+ linesAdded: rgb(0, 255, 122),
422
+ // Green neon
423
+ linesRemoved: rgb(255, 0, 122),
424
+ // Magenta neon
425
+ cost: rgb(255, 111, 97),
426
+ // Orange neon
427
+ model: rgb(140, 27, 255),
428
+ // Purple neon
429
+ duration: rgb(0, 191, 255),
430
+ // Cyan neon
431
+ accent: rgb(255, 0, 122)
432
+ // Magenta neon
433
+ })
434
+ };
435
+
436
+ // src/ui/theme/themes/dracula-theme.ts
437
+ var DRACULA_THEME = {
438
+ name: "dracula",
439
+ description: "Purple/pink accent theme",
440
+ colors: createThemeColors({
441
+ branch: rgb(189, 147, 249),
442
+ // Purple
443
+ changes: rgb(139, 233, 253),
444
+ // Cyan
445
+ contextLow: rgb(80, 250, 123),
446
+ // Green
447
+ contextMedium: rgb(241, 250, 140),
448
+ // Yellow
449
+ contextHigh: rgb(255, 85, 85),
450
+ // Red
451
+ linesAdded: rgb(80, 250, 123),
452
+ // Green
453
+ linesRemoved: rgb(255, 85, 85),
454
+ // Red
455
+ cost: rgb(255, 184, 108),
456
+ // Orange
457
+ model: rgb(98, 114, 164),
458
+ // Comment gray
459
+ duration: rgb(68, 71, 90),
460
+ // Selection gray
461
+ accent: rgb(189, 147, 249)
462
+ // Purple
463
+ })
464
+ };
465
+
466
+ // src/ui/theme/themes/dusty-sage-theme.ts
467
+ var DUSTY_SAGE_THEME = {
468
+ name: "dusty-sage",
469
+ description: "Earthy muted greens with peaceful forest fog aesthetic",
470
+ colors: createThemeColors({
471
+ branch: rgb(120, 140, 130),
472
+ // Dusty green
473
+ changes: rgb(135, 145, 140),
474
+ // Sage gray
475
+ contextLow: rgb(135, 145, 140),
476
+ // Subtle sage (low)
477
+ contextMedium: rgb(150, 160, 145),
478
+ // Medium sage
479
+ contextHigh: rgb(165, 175, 160),
480
+ // Light sage (high)
481
+ linesAdded: rgb(135, 145, 140),
482
+ linesRemoved: rgb(135, 145, 140),
483
+ cost: rgb(156, 163, 175),
484
+ model: rgb(148, 163, 184),
485
+ duration: rgb(120, 130, 140),
486
+ accent: rgb(120, 140, 130)
487
+ })
488
+ };
489
+
490
+ // src/ui/theme/themes/github-dark-dimmed-theme.ts
491
+ var GITHUB_DARK_DIMMED_THEME = {
492
+ name: "github-dark-dimmed",
493
+ description: "GitHub's official dark theme (dimmed)",
494
+ colors: createThemeColors({
495
+ branch: rgb(88, 166, 255),
496
+ // GitHub blue
497
+ changes: rgb(156, 220, 254),
498
+ // Light blue
499
+ contextLow: rgb(35, 134, 54),
500
+ // GitHub green
501
+ contextMedium: rgb(210, 153, 34),
502
+ // GitHub orange
503
+ contextHigh: rgb(248, 81, 73),
504
+ // GitHub red
505
+ linesAdded: rgb(35, 134, 54),
506
+ // GitHub green
507
+ linesRemoved: rgb(248, 81, 73),
508
+ // GitHub red
509
+ cost: rgb(163, 113, 247),
510
+ // Purple
511
+ model: rgb(201, 209, 217),
512
+ // Gray
513
+ duration: rgb(110, 118, 129),
514
+ // Dark gray
515
+ accent: rgb(88, 166, 255)
516
+ // GitHub blue
517
+ })
518
+ };
519
+
520
+ // src/ui/theme/themes/monokai-theme.ts
521
+ var MONOKAI_THEME = {
522
+ name: "monokai",
523
+ description: "Vibrant, high-contrast",
524
+ colors: createThemeColors({
525
+ branch: rgb(102, 217, 239),
526
+ // Cyan
527
+ changes: rgb(249, 26, 114),
528
+ // Pink
529
+ contextLow: rgb(166, 226, 46),
530
+ // Green
531
+ contextMedium: rgb(253, 151, 31),
532
+ // Orange
533
+ contextHigh: rgb(249, 26, 114),
534
+ // Pink
535
+ linesAdded: rgb(166, 226, 46),
536
+ // Green
537
+ linesRemoved: rgb(249, 26, 114),
538
+ // Pink
539
+ cost: rgb(254, 128, 25),
540
+ // Bright orange
541
+ model: rgb(174, 129, 255),
542
+ // Purple
543
+ duration: rgb(102, 217, 239),
544
+ // Cyan
545
+ accent: rgb(249, 26, 114)
546
+ // Pink
547
+ })
548
+ };
549
+
550
+ // src/ui/theme/themes/muted-gray-theme.ts
551
+ var MUTED_GRAY_THEME = {
552
+ name: "muted-gray",
553
+ description: "Very subtle grays with almost invisible progress bar",
554
+ colors: createThemeColors({
555
+ branch: rgb(156, 163, 175),
556
+ // Slate gray
557
+ changes: rgb(148, 163, 184),
558
+ // Lighter slate
559
+ contextLow: rgb(148, 163, 184),
560
+ // Subtle gray (low)
561
+ contextMedium: rgb(160, 174, 192),
562
+ // Medium gray
563
+ contextHigh: rgb(175, 188, 201),
564
+ // Light gray (high)
565
+ linesAdded: rgb(148, 163, 184),
566
+ linesRemoved: rgb(148, 163, 184),
567
+ cost: rgb(156, 163, 175),
568
+ model: rgb(148, 163, 184),
569
+ duration: rgb(107, 114, 128),
570
+ accent: rgb(156, 163, 175)
571
+ })
572
+ };
573
+
574
+ // src/ui/theme/themes/nord-theme.ts
575
+ var NORD_THEME = {
576
+ name: "nord",
577
+ description: "Arctic, north-bluish color palette",
578
+ colors: createThemeColors({
579
+ branch: rgb(136, 192, 208),
580
+ // Nordic cyan
581
+ changes: rgb(143, 188, 187),
582
+ // Nordic blue-gray
583
+ contextLow: rgb(163, 190, 140),
584
+ // Nordic green
585
+ contextMedium: rgb(235, 203, 139),
586
+ // Nordic yellow
587
+ contextHigh: rgb(191, 97, 106),
588
+ // Nordic red
589
+ linesAdded: rgb(163, 190, 140),
590
+ // Nordic green
591
+ linesRemoved: rgb(191, 97, 106),
592
+ // Nordic red
593
+ cost: rgb(216, 222, 233),
594
+ // Nordic white
595
+ model: rgb(129, 161, 193),
596
+ // Nordic blue
597
+ duration: rgb(94, 129, 172),
598
+ // Nordic dark blue
599
+ accent: rgb(136, 192, 208)
600
+ // Nordic cyan
601
+ })
602
+ };
603
+
604
+ // src/ui/theme/themes/one-dark-pro-theme.ts
605
+ var ONE_DARK_PRO_THEME = {
606
+ name: "one-dark-pro",
607
+ description: "Atom's iconic theme",
608
+ colors: createThemeColors({
609
+ branch: rgb(97, 175, 239),
610
+ // Blue
611
+ changes: rgb(152, 195, 121),
612
+ // Green
613
+ contextLow: rgb(152, 195, 121),
614
+ // Green
615
+ contextMedium: rgb(229, 192, 123),
616
+ // Yellow
617
+ contextHigh: rgb(224, 108, 117),
618
+ // Red
619
+ linesAdded: rgb(152, 195, 121),
620
+ // Green
621
+ linesRemoved: rgb(224, 108, 117),
622
+ // Red
623
+ cost: rgb(209, 154, 102),
624
+ // Orange
625
+ model: rgb(171, 178, 191),
626
+ // Gray
627
+ duration: rgb(125, 148, 173),
628
+ // Dark gray
629
+ accent: rgb(97, 175, 239)
630
+ // Blue
631
+ })
632
+ };
633
+
634
+ // src/ui/theme/themes/professional-blue-theme.ts
635
+ var PROFESSIONAL_BLUE_THEME = {
636
+ name: "professional-blue",
637
+ description: "Clean, business-oriented blue color scheme",
638
+ colors: createThemeColors({
639
+ branch: rgb(37, 99, 235),
640
+ // Royal blue
641
+ changes: rgb(148, 163, 184),
642
+ // Slate gray
643
+ contextLow: rgb(96, 165, 250),
644
+ // Light blue
645
+ contextMedium: rgb(251, 191, 36),
646
+ // Amber
647
+ contextHigh: rgb(248, 113, 113),
648
+ // Red
649
+ linesAdded: rgb(74, 222, 128),
650
+ // Green
651
+ linesRemoved: rgb(248, 113, 113),
652
+ // Red
653
+ cost: rgb(251, 146, 60),
654
+ // Orange
655
+ model: rgb(167, 139, 250),
656
+ // Purple
657
+ duration: rgb(203, 213, 225),
658
+ // Light gray
659
+ accent: rgb(37, 99, 235)
660
+ // Royal blue
661
+ })
662
+ };
663
+
664
+ // src/ui/theme/themes/rose-pine-theme.ts
665
+ var ROSE_PINE_THEME = {
666
+ name: "rose-pine",
667
+ description: "Rose/violet themed",
668
+ colors: createThemeColors({
669
+ branch: rgb(156, 207, 216),
670
+ // Pine cyan
671
+ changes: rgb(235, 188, 186),
672
+ // Rose
673
+ contextLow: rgb(156, 207, 216),
674
+ // Pine cyan
675
+ contextMedium: rgb(233, 201, 176),
676
+ // Pine beige
677
+ contextHigh: rgb(235, 111, 146),
678
+ // Pine red
679
+ linesAdded: rgb(156, 207, 216),
680
+ // Pine cyan
681
+ linesRemoved: rgb(235, 111, 146),
682
+ // Pine red
683
+ cost: rgb(226, 185, 218),
684
+ // Pine pink
685
+ model: rgb(224, 208, 245),
686
+ // Pine violet
687
+ duration: rgb(148, 137, 176),
688
+ // Pine mute
689
+ accent: rgb(235, 111, 146)
690
+ // Pine red
691
+ })
692
+ };
693
+
694
+ // src/ui/theme/themes/semantic-classic-theme.ts
695
+ var SEMANTIC_CLASSIC_THEME = {
696
+ name: "semantic-classic",
697
+ description: "Industry-standard semantic colors for maximum clarity",
698
+ colors: createThemeColors({
699
+ branch: rgb(59, 130, 246),
700
+ // Blue
701
+ changes: rgb(107, 114, 128),
702
+ // Gray
703
+ contextLow: rgb(34, 197, 94),
704
+ // Green
705
+ contextMedium: rgb(234, 179, 8),
706
+ // Yellow
707
+ contextHigh: rgb(239, 68, 68),
708
+ // Red
709
+ linesAdded: rgb(34, 197, 94),
710
+ // Green
711
+ linesRemoved: rgb(239, 68, 68),
712
+ // Red
713
+ cost: rgb(249, 115, 22),
714
+ // Orange
715
+ model: rgb(99, 102, 241),
716
+ // Indigo
717
+ duration: rgb(107, 114, 128),
718
+ // Gray
719
+ accent: rgb(59, 130, 246)
720
+ // Blue
721
+ })
722
+ };
723
+
724
+ // src/ui/theme/themes/slate-blue-theme.ts
725
+ var SLATE_BLUE_THEME = {
726
+ name: "slate-blue",
727
+ description: "Calm blue-grays with gentle ocean tones",
728
+ colors: createThemeColors({
729
+ branch: rgb(100, 116, 139),
730
+ // Cool slate
731
+ changes: rgb(148, 163, 184),
732
+ // Neutral slate
733
+ contextLow: rgb(148, 163, 184),
734
+ // Subtle slate-blue (low)
735
+ contextMedium: rgb(160, 174, 192),
736
+ // Medium slate
737
+ contextHigh: rgb(175, 188, 201),
738
+ // Light slate (high)
739
+ linesAdded: rgb(148, 163, 184),
740
+ linesRemoved: rgb(148, 163, 184),
741
+ cost: rgb(156, 163, 175),
742
+ model: rgb(148, 163, 184),
743
+ duration: rgb(100, 116, 139),
744
+ accent: rgb(100, 116, 139)
745
+ })
746
+ };
747
+
748
+ // src/ui/theme/themes/solarized-dark-theme.ts
749
+ var SOLARIZED_DARK_THEME = {
750
+ name: "solarized-dark",
751
+ description: "Precise CIELAB lightness",
752
+ colors: createThemeColors({
753
+ branch: rgb(38, 139, 210),
754
+ // Blue
755
+ changes: rgb(133, 153, 0),
756
+ // Olive
757
+ contextLow: rgb(133, 153, 0),
758
+ // Olive
759
+ contextMedium: rgb(181, 137, 0),
760
+ // Yellow
761
+ contextHigh: rgb(220, 50, 47),
762
+ // Red
763
+ linesAdded: rgb(133, 153, 0),
764
+ // Olive
765
+ linesRemoved: rgb(220, 50, 47),
766
+ // Red
767
+ cost: rgb(203, 75, 22),
768
+ // Orange
769
+ model: rgb(131, 148, 150),
770
+ // Base0
771
+ duration: rgb(88, 110, 117),
772
+ // Base01
773
+ accent: rgb(38, 139, 210)
774
+ // Blue
775
+ })
776
+ };
777
+
778
+ // src/ui/theme/themes/tokyo-night-theme.ts
779
+ var TOKYO_NIGHT_THEME = {
780
+ name: "tokyo-night",
781
+ description: "Clean, dark Tokyo-inspired",
782
+ colors: createThemeColors({
783
+ branch: rgb(122, 132, 173),
784
+ // Blue
785
+ changes: rgb(122, 162, 247),
786
+ // Dark blue
787
+ contextLow: rgb(146, 180, 203),
788
+ // Cyan
789
+ contextMedium: rgb(232, 166, 162),
790
+ // Pink-red
791
+ contextHigh: rgb(249, 86, 119),
792
+ // Red
793
+ linesAdded: rgb(146, 180, 203),
794
+ // Cyan
795
+ linesRemoved: rgb(249, 86, 119),
796
+ // Red
797
+ cost: rgb(158, 206, 209),
798
+ // Teal
799
+ model: rgb(169, 177, 214),
800
+ // White-ish
801
+ duration: rgb(113, 119, 161),
802
+ // Dark blue-gray
803
+ accent: rgb(122, 132, 173)
804
+ // Blue
805
+ })
806
+ };
807
+
808
+ // src/ui/theme/themes/vscode-dark-plus-theme.ts
809
+ var VSCODE_DARK_PLUS_THEME = {
810
+ name: "vscode-dark-plus",
811
+ description: "Visual Studio Code's default dark theme (claude-scope default)",
812
+ colors: createThemeColors({
813
+ branch: rgb(0, 122, 204),
814
+ // VSCode blue
815
+ changes: rgb(78, 201, 176),
816
+ // Teal
817
+ contextLow: rgb(78, 201, 176),
818
+ // Teal
819
+ contextMedium: rgb(220, 220, 170),
820
+ // Yellow
821
+ contextHigh: rgb(244, 71, 71),
822
+ // Red
823
+ linesAdded: rgb(78, 201, 176),
824
+ // Teal
825
+ linesRemoved: rgb(244, 71, 71),
826
+ // Red
827
+ cost: rgb(206, 145, 120),
828
+ // Orange
829
+ model: rgb(171, 178, 191),
830
+ // Gray
831
+ duration: rgb(125, 148, 173),
832
+ // Dark gray
833
+ accent: rgb(0, 122, 204)
834
+ // VSCode blue
835
+ })
836
+ };
837
+
838
+ // src/ui/theme/index.ts
839
+ var DEFAULT_THEME = VSCODE_DARK_PLUS_THEME.colors;
840
+
278
841
  // src/ui/utils/style-utils.ts
279
842
  function withLabel(prefix, value) {
280
843
  if (prefix === "") return value;
@@ -292,75 +855,89 @@ function progressBar(percent, width = 10) {
292
855
 
293
856
  // src/widgets/git/styles.ts
294
857
  var gitStyles = {
295
- minimal: (data) => {
296
- return data.branch;
858
+ minimal: (data, colors) => {
859
+ if (!colors) return data.branch;
860
+ return colorize(data.branch, colors.branch);
297
861
  },
298
- balanced: (data) => {
862
+ balanced: (data, colors) => {
299
863
  if (data.changes && data.changes.files > 0) {
300
864
  const parts = [];
301
865
  if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions}`);
302
866
  if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions}`);
303
867
  if (parts.length > 0) {
304
- return `${data.branch} [${parts.join(" ")}]`;
868
+ const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
869
+ const changes = colors ? colorize(`[${parts.join(" ")}]`, colors.changes) : `[${parts.join(" ")}]`;
870
+ return `${branch} ${changes}`;
305
871
  }
306
872
  }
307
- return data.branch;
873
+ return colors ? colorize(data.branch, colors.branch) : data.branch;
308
874
  },
309
- compact: (data) => {
875
+ compact: (data, colors) => {
310
876
  if (data.changes && data.changes.files > 0) {
311
877
  const parts = [];
312
878
  if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions}`);
313
879
  if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions}`);
314
880
  if (parts.length > 0) {
315
- return `${data.branch} ${parts.join("/")}`;
881
+ const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
882
+ const changesStr = parts.join("/");
883
+ return `${branch} ${changesStr}`;
316
884
  }
317
885
  }
318
- return data.branch;
886
+ return colors ? colorize(data.branch, colors.branch) : data.branch;
319
887
  },
320
- playful: (data) => {
888
+ playful: (data, colors) => {
321
889
  if (data.changes && data.changes.files > 0) {
322
890
  const parts = [];
323
891
  if (data.changes.insertions > 0) parts.push(`\u2B06${data.changes.insertions}`);
324
892
  if (data.changes.deletions > 0) parts.push(`\u2B07${data.changes.deletions}`);
325
893
  if (parts.length > 0) {
326
- return `\u{1F500} ${data.branch} ${parts.join(" ")}`;
894
+ const branch2 = colors ? colorize(data.branch, colors.branch) : data.branch;
895
+ return `\u{1F500} ${branch2} ${parts.join(" ")}`;
327
896
  }
328
897
  }
329
- return `\u{1F500} ${data.branch}`;
898
+ const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
899
+ return `\u{1F500} ${branch}`;
330
900
  },
331
- verbose: (data) => {
901
+ verbose: (data, colors) => {
332
902
  if (data.changes && data.changes.files > 0) {
333
903
  const parts = [];
334
904
  if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions} insertions`);
335
905
  if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions} deletions`);
336
906
  if (parts.length > 0) {
337
- return `branch: ${data.branch} [${parts.join(", ")}]`;
907
+ const branch2 = colors ? colorize(data.branch, colors.branch) : data.branch;
908
+ const changes = colors ? colorize(`[${parts.join(", ")}]`, colors.changes) : `[${parts.join(", ")}]`;
909
+ return `branch: ${branch2} ${changes}`;
338
910
  }
339
911
  }
340
- return `branch: ${data.branch} (HEAD)`;
912
+ const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
913
+ return `branch: ${branch} (HEAD)`;
341
914
  },
342
- labeled: (data) => {
915
+ labeled: (data, colors) => {
343
916
  if (data.changes && data.changes.files > 0) {
344
917
  const parts = [];
345
918
  if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions}`);
346
919
  if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions}`);
347
920
  if (parts.length > 0) {
921
+ const branch2 = colors ? colorize(data.branch, colors.branch) : data.branch;
348
922
  const changes = `${data.changes.files} files: ${parts.join("/")}`;
349
- return `Git: ${data.branch} [${changes}]`;
923
+ return `Git: ${branch2} [${changes}]`;
350
924
  }
351
925
  }
352
- return `Git: ${data.branch}`;
926
+ const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
927
+ return `Git: ${branch}`;
353
928
  },
354
- indicator: (data) => {
929
+ indicator: (data, colors) => {
355
930
  if (data.changes && data.changes.files > 0) {
356
931
  const parts = [];
357
932
  if (data.changes.insertions > 0) parts.push(`+${data.changes.insertions}`);
358
933
  if (data.changes.deletions > 0) parts.push(`-${data.changes.deletions}`);
359
934
  if (parts.length > 0) {
360
- return `\u25CF ${data.branch} [${parts.join(" ")}]`;
935
+ const branch = colors ? colorize(data.branch, colors.branch) : data.branch;
936
+ const changes = colors ? colorize(`[${parts.join(" ")}]`, colors.changes) : `[${parts.join(" ")}]`;
937
+ return `\u25CF ${branch} ${changes}`;
361
938
  }
362
939
  }
363
- return withIndicator(data.branch);
940
+ return withIndicator(colors ? colorize(data.branch, colors.branch) : data.branch);
364
941
  }
365
942
  };
366
943
 
@@ -379,14 +956,17 @@ var GitWidget = class {
379
956
  git = null;
380
957
  enabled = true;
381
958
  cwd = null;
959
+ colors;
382
960
  styleFn = gitStyles.balanced;
383
961
  /**
384
962
  * @param gitFactory - Optional factory function for creating IGit instances
385
963
  * If not provided, uses default createGit (production)
386
964
  * Tests can inject MockGit factory here
965
+ * @param colors - Optional theme colors
387
966
  */
388
- constructor(gitFactory) {
967
+ constructor(gitFactory, colors) {
389
968
  this.gitFactory = gitFactory || createGit;
969
+ this.colors = colors ?? DEFAULT_THEME;
390
970
  }
391
971
  setStyle(style = "balanced") {
392
972
  const fn = gitStyles[style];
@@ -424,7 +1004,7 @@ var GitWidget = class {
424
1004
  } catch {
425
1005
  }
426
1006
  const renderData = { branch, changes };
427
- return this.styleFn(renderData);
1007
+ return this.styleFn(renderData, this.colors.git);
428
1008
  } catch {
429
1009
  return null;
430
1010
  }
@@ -444,25 +1024,37 @@ var GitWidget = class {
444
1024
 
445
1025
  // src/widgets/git-tag/styles.ts
446
1026
  var gitTagStyles = {
447
- balanced: (data) => {
448
- return data.tag || "\u2014";
1027
+ balanced: (data, colors) => {
1028
+ const tag = data.tag || "\u2014";
1029
+ if (!colors) return tag;
1030
+ return colorize(tag, colors.branch);
449
1031
  },
450
- compact: (data) => {
1032
+ compact: (data, colors) => {
451
1033
  if (!data.tag) return "\u2014";
452
- return data.tag.replace(/^v/, "");
1034
+ const tag = data.tag.replace(/^v/, "");
1035
+ if (!colors) return tag;
1036
+ return colorize(tag, colors.branch);
453
1037
  },
454
- playful: (data) => {
455
- return `\u{1F3F7}\uFE0F ${data.tag || "\u2014"}`;
1038
+ playful: (data, colors) => {
1039
+ const tag = data.tag || "\u2014";
1040
+ if (!colors) return `\u{1F3F7}\uFE0F ${tag}`;
1041
+ return `\u{1F3F7}\uFE0F ${colorize(tag, colors.branch)}`;
456
1042
  },
457
- verbose: (data) => {
1043
+ verbose: (data, colors) => {
458
1044
  if (!data.tag) return "version: none";
459
- return `version ${data.tag}`;
1045
+ const tag = `version ${data.tag}`;
1046
+ if (!colors) return tag;
1047
+ return `version ${colorize(data.tag, colors.branch)}`;
460
1048
  },
461
- labeled: (data) => {
462
- return withLabel("Tag", data.tag || "none");
1049
+ labeled: (data, colors) => {
1050
+ const tag = data.tag || "none";
1051
+ if (!colors) return withLabel("Tag", tag);
1052
+ return withLabel("Tag", colorize(tag, colors.branch));
463
1053
  },
464
- indicator: (data) => {
465
- return withIndicator(data.tag || "\u2014");
1054
+ indicator: (data, colors) => {
1055
+ const tag = data.tag || "\u2014";
1056
+ if (!colors) return withIndicator(tag);
1057
+ return withIndicator(colorize(tag, colors.branch));
466
1058
  }
467
1059
  };
468
1060
 
@@ -481,14 +1073,17 @@ var GitTagWidget = class {
481
1073
  git = null;
482
1074
  enabled = true;
483
1075
  cwd = null;
1076
+ colors;
484
1077
  styleFn = gitTagStyles.balanced;
485
1078
  /**
486
1079
  * @param gitFactory - Optional factory function for creating IGit instances
487
1080
  * If not provided, uses default createGit (production)
488
1081
  * Tests can inject MockGit factory here
1082
+ * @param colors - Optional theme colors
489
1083
  */
490
- constructor(gitFactory) {
1084
+ constructor(gitFactory, colors) {
491
1085
  this.gitFactory = gitFactory || createGit;
1086
+ this.colors = colors ?? DEFAULT_THEME;
492
1087
  }
493
1088
  setStyle(style = "balanced") {
494
1089
  const fn = gitTagStyles[style];
@@ -506,7 +1101,7 @@ var GitTagWidget = class {
506
1101
  try {
507
1102
  const latestTag = await (this.git.latestTag?.() ?? Promise.resolve(null));
508
1103
  const renderData = { tag: latestTag };
509
- return this.styleFn(renderData);
1104
+ return this.styleFn(renderData, this.colors.git);
510
1105
  } catch {
511
1106
  return null;
512
1107
  }
@@ -524,34 +1119,6 @@ var GitTagWidget = class {
524
1119
  }
525
1120
  };
526
1121
 
527
- // src/widgets/model/styles.ts
528
- function getShortName(displayName) {
529
- return displayName.replace(/^Claude\s+/, "");
530
- }
531
- var modelStyles = {
532
- balanced: (data) => {
533
- return data.displayName;
534
- },
535
- compact: (data) => {
536
- return getShortName(data.displayName);
537
- },
538
- playful: (data) => {
539
- return `\u{1F916} ${getShortName(data.displayName)}`;
540
- },
541
- technical: (data) => {
542
- return data.id;
543
- },
544
- symbolic: (data) => {
545
- return `\u25C6 ${getShortName(data.displayName)}`;
546
- },
547
- labeled: (data) => {
548
- return withLabel("Model", getShortName(data.displayName));
549
- },
550
- indicator: (data) => {
551
- return withIndicator(getShortName(data.displayName));
552
- }
553
- };
554
-
555
1122
  // src/widgets/core/stdin-data-widget.ts
556
1123
  var StdinDataWidget = class {
557
1124
  /**
@@ -610,6 +1177,50 @@ var StdinDataWidget = class {
610
1177
  }
611
1178
  };
612
1179
 
1180
+ // src/widgets/model/styles.ts
1181
+ function getShortName(displayName) {
1182
+ return displayName.replace(/^Claude\s+/, "");
1183
+ }
1184
+ var modelStyles = {
1185
+ balanced: (data, colors) => {
1186
+ if (!colors) return data.displayName;
1187
+ return colorize(data.displayName, colors.name);
1188
+ },
1189
+ compact: (data, colors) => {
1190
+ const shortName = getShortName(data.displayName);
1191
+ if (!colors) return shortName;
1192
+ return colorize(shortName, colors.name);
1193
+ },
1194
+ playful: (data, colors) => {
1195
+ const shortName = getShortName(data.displayName);
1196
+ if (!colors) return `\u{1F916} ${shortName}`;
1197
+ return `\u{1F916} ${colorize(shortName, colors.name)}`;
1198
+ },
1199
+ technical: (data, colors) => {
1200
+ if (!colors) return data.id;
1201
+ const match = data.id.match(/^(.+?)-(\d[\d.]*)$/);
1202
+ if (match) {
1203
+ return colorize(match[1], colors.name) + colorize(`-${match[2]}`, colors.version);
1204
+ }
1205
+ return colorize(data.id, colors.name);
1206
+ },
1207
+ symbolic: (data, colors) => {
1208
+ const shortName = getShortName(data.displayName);
1209
+ if (!colors) return `\u25C6 ${shortName}`;
1210
+ return `\u25C6 ${colorize(shortName, colors.name)}`;
1211
+ },
1212
+ labeled: (data, colors) => {
1213
+ const shortName = getShortName(data.displayName);
1214
+ if (!colors) return withLabel("Model", shortName);
1215
+ return withLabel("Model", colorize(shortName, colors.name));
1216
+ },
1217
+ indicator: (data, colors) => {
1218
+ const shortName = getShortName(data.displayName);
1219
+ if (!colors) return withIndicator(shortName);
1220
+ return withIndicator(colorize(shortName, colors.name));
1221
+ }
1222
+ };
1223
+
613
1224
  // src/widgets/model-widget.ts
614
1225
  var ModelWidget = class extends StdinDataWidget {
615
1226
  id = "model";
@@ -621,7 +1232,12 @@ var ModelWidget = class extends StdinDataWidget {
621
1232
  0
622
1233
  // First line
623
1234
  );
1235
+ colors;
624
1236
  styleFn = modelStyles.balanced;
1237
+ constructor(colors) {
1238
+ super();
1239
+ this.colors = colors ?? DEFAULT_THEME;
1240
+ }
625
1241
  setStyle(style = "balanced") {
626
1242
  const fn = modelStyles[style];
627
1243
  if (fn) {
@@ -633,87 +1249,64 @@ var ModelWidget = class extends StdinDataWidget {
633
1249
  displayName: data.model.display_name,
634
1250
  id: data.model.id
635
1251
  };
636
- return this.styleFn(renderData);
637
- }
638
- };
639
-
640
- // src/ui/utils/colors.ts
641
- var reset = "\x1B[0m";
642
- var red = "\x1B[31m";
643
- var gray = "\x1B[90m";
644
- var lightGray = "\x1B[37m";
645
- var bold = "\x1B[1m";
646
-
647
- // src/ui/theme/default-theme.ts
648
- var DEFAULT_THEME = {
649
- context: {
650
- low: gray,
651
- medium: gray,
652
- high: gray
653
- },
654
- lines: {
655
- added: gray,
656
- removed: gray
1252
+ return this.styleFn(renderData, this.colors.model);
657
1253
  }
658
1254
  };
659
1255
 
660
- // src/ui/utils/formatters.ts
661
- function formatDuration(ms) {
662
- if (ms <= 0) return "0s";
663
- const seconds = Math.floor(ms / TIME.MS_PER_SECOND);
664
- const hours = Math.floor(seconds / TIME.SECONDS_PER_HOUR);
665
- const minutes = Math.floor(seconds % TIME.SECONDS_PER_HOUR / TIME.SECONDS_PER_MINUTE);
666
- const secs = seconds % TIME.SECONDS_PER_MINUTE;
667
- const parts = [];
668
- if (hours > 0) {
669
- parts.push(`${hours}h`);
670
- parts.push(`${minutes}m`);
671
- parts.push(`${secs}s`);
672
- } else if (minutes > 0) {
673
- parts.push(`${minutes}m`);
674
- parts.push(`${secs}s`);
1256
+ // src/widgets/context/styles.ts
1257
+ function getContextColor(percent, colors) {
1258
+ const clampedPercent = Math.max(0, Math.min(100, percent));
1259
+ if (clampedPercent < 50) {
1260
+ return colors.low;
1261
+ } else if (clampedPercent < 80) {
1262
+ return colors.medium;
675
1263
  } else {
676
- parts.push(`${secs}s`);
1264
+ return colors.high;
677
1265
  }
678
- return parts.join(" ");
679
- }
680
- function formatCostUSD(usd) {
681
- return `$${usd.toFixed(2)}`;
682
1266
  }
683
- function colorize(text, color) {
684
- return `${color}${text}${ANSI_COLORS.RESET}`;
685
- }
686
-
687
- // src/widgets/context/styles.ts
688
1267
  var contextStyles = {
689
- balanced: (data) => {
1268
+ balanced: (data, colors) => {
690
1269
  const bar = progressBar(data.percent, 10);
691
- return `[${bar}] ${data.percent}%`;
1270
+ const output = `[${bar}] ${data.percent}%`;
1271
+ if (!colors) return output;
1272
+ return colorize(output, getContextColor(data.percent, colors));
692
1273
  },
693
- compact: (data) => {
694
- return `${data.percent}%`;
1274
+ compact: (data, colors) => {
1275
+ const output = `${data.percent}%`;
1276
+ if (!colors) return output;
1277
+ return colorize(output, getContextColor(data.percent, colors));
695
1278
  },
696
- playful: (data) => {
1279
+ playful: (data, colors) => {
697
1280
  const bar = progressBar(data.percent, 10);
698
- return `\u{1F9E0} [${bar}] ${data.percent}%`;
1281
+ const output = `\u{1F9E0} [${bar}] ${data.percent}%`;
1282
+ if (!colors) return output;
1283
+ return `\u{1F9E0} ` + colorize(`[${bar}] ${data.percent}%`, getContextColor(data.percent, colors));
699
1284
  },
700
- verbose: (data) => {
1285
+ verbose: (data, colors) => {
701
1286
  const usedFormatted = data.used.toLocaleString();
702
1287
  const maxFormatted = data.contextWindowSize.toLocaleString();
703
- return `${usedFormatted} / ${maxFormatted} tokens (${data.percent}%)`;
1288
+ const output = `${usedFormatted} / ${maxFormatted} tokens (${data.percent}%)`;
1289
+ if (!colors) return output;
1290
+ return colorize(output, getContextColor(data.percent, colors));
704
1291
  },
705
- symbolic: (data) => {
1292
+ symbolic: (data, colors) => {
706
1293
  const filled = Math.round(data.percent / 100 * 5);
707
1294
  const empty = 5 - filled;
708
- return `${"\u25AE".repeat(filled)}${"\u25AF".repeat(empty)} ${data.percent}%`;
1295
+ const output = `${"\u25AE".repeat(filled)}${"\u25AF".repeat(empty)} ${data.percent}%`;
1296
+ if (!colors) return output;
1297
+ return colorize(output, getContextColor(data.percent, colors));
709
1298
  },
710
- "compact-verbose": (data) => {
1299
+ "compact-verbose": (data, colors) => {
711
1300
  const usedK = data.used >= 1e3 ? `${Math.floor(data.used / 1e3)}K` : data.used.toString();
712
1301
  const maxK = data.contextWindowSize >= 1e3 ? `${Math.floor(data.contextWindowSize / 1e3)}K` : data.contextWindowSize.toString();
713
- return `${data.percent}% (${usedK}/${maxK})`;
1302
+ const output = `${data.percent}% (${usedK}/${maxK})`;
1303
+ if (!colors) return output;
1304
+ return colorize(output, getContextColor(data.percent, colors));
714
1305
  },
715
- indicator: (data) => {
716
- return `\u25CF ${data.percent}%`;
1306
+ indicator: (data, colors) => {
1307
+ const output = `\u25CF ${data.percent}%`;
1308
+ if (!colors) return output;
1309
+ return colorize(output, getContextColor(data.percent, colors));
717
1310
  }
718
1311
  };
719
1312
 
@@ -732,7 +1325,7 @@ var ContextWidget = class extends StdinDataWidget {
732
1325
  styleFn = contextStyles.balanced;
733
1326
  constructor(colors) {
734
1327
  super();
735
- this.colors = colors ?? DEFAULT_THEME.context;
1328
+ this.colors = colors ?? DEFAULT_THEME;
736
1329
  }
737
1330
  setStyle(style = "balanced") {
738
1331
  const fn = contextStyles[style];
@@ -750,38 +1343,68 @@ var ContextWidget = class extends StdinDataWidget {
750
1343
  contextWindowSize: context_window_size,
751
1344
  percent
752
1345
  };
753
- const output = this.styleFn(renderData);
754
- const color = this.getContextColor(percent);
755
- return colorize(output, color);
756
- }
757
- getContextColor(percent) {
758
- const clampedPercent = Math.max(0, Math.min(100, percent));
759
- if (clampedPercent < 50) {
760
- return this.colors.low;
761
- } else if (clampedPercent < 80) {
762
- return this.colors.medium;
763
- } else {
764
- return this.colors.high;
765
- }
1346
+ return this.styleFn(renderData, this.colors.context);
766
1347
  }
767
1348
  };
768
1349
 
1350
+ // src/ui/utils/formatters.ts
1351
+ function formatDuration(ms) {
1352
+ if (ms <= 0) return "0s";
1353
+ const seconds = Math.floor(ms / TIME.MS_PER_SECOND);
1354
+ const hours = Math.floor(seconds / TIME.SECONDS_PER_HOUR);
1355
+ const minutes = Math.floor(seconds % TIME.SECONDS_PER_HOUR / TIME.SECONDS_PER_MINUTE);
1356
+ const secs = seconds % TIME.SECONDS_PER_MINUTE;
1357
+ const parts = [];
1358
+ if (hours > 0) {
1359
+ parts.push(`${hours}h`);
1360
+ parts.push(`${minutes}m`);
1361
+ parts.push(`${secs}s`);
1362
+ } else if (minutes > 0) {
1363
+ parts.push(`${minutes}m`);
1364
+ parts.push(`${secs}s`);
1365
+ } else {
1366
+ parts.push(`${secs}s`);
1367
+ }
1368
+ return parts.join(" ");
1369
+ }
1370
+ function formatCostUSD(usd) {
1371
+ return `$${usd.toFixed(2)}`;
1372
+ }
1373
+ function colorize2(text, color) {
1374
+ return `${color}${text}${ANSI_COLORS.RESET}`;
1375
+ }
1376
+
769
1377
  // src/widgets/cost/styles.ts
770
1378
  var costStyles = {
771
- balanced: (data) => {
772
- return formatCostUSD(data.costUsd);
1379
+ balanced: (data, colors) => {
1380
+ const formatted = formatCostUSD(data.costUsd);
1381
+ if (!colors) return formatted;
1382
+ const amountStr = data.costUsd.toFixed(2);
1383
+ return colorize("$", colors.currency) + colorize(amountStr, colors.amount);
773
1384
  },
774
- compact: (data) => {
775
- return formatCostUSD(data.costUsd);
1385
+ compact: (data, colors) => {
1386
+ return costStyles.balanced(data, colors);
776
1387
  },
777
- playful: (data) => {
778
- return `\u{1F4B0} ${formatCostUSD(data.costUsd)}`;
1388
+ playful: (data, colors) => {
1389
+ const formatted = formatCostUSD(data.costUsd);
1390
+ if (!colors) return `\u{1F4B0} ${formatted}`;
1391
+ const amountStr = data.costUsd.toFixed(2);
1392
+ const colored = colorize("$", colors.currency) + colorize(amountStr, colors.amount);
1393
+ return `\u{1F4B0} ${colored}`;
779
1394
  },
780
- labeled: (data) => {
781
- return withLabel("Cost", formatCostUSD(data.costUsd));
1395
+ labeled: (data, colors) => {
1396
+ const formatted = formatCostUSD(data.costUsd);
1397
+ if (!colors) return withLabel("Cost", formatted);
1398
+ const amountStr = data.costUsd.toFixed(2);
1399
+ const colored = colorize("$", colors.currency) + colorize(amountStr, colors.amount);
1400
+ return withLabel("Cost", colored);
782
1401
  },
783
- indicator: (data) => {
784
- return withIndicator(formatCostUSD(data.costUsd));
1402
+ indicator: (data, colors) => {
1403
+ const formatted = formatCostUSD(data.costUsd);
1404
+ if (!colors) return withIndicator(formatted);
1405
+ const amountStr = data.costUsd.toFixed(2);
1406
+ const colored = colorize("$", colors.currency) + colorize(amountStr, colors.amount);
1407
+ return withIndicator(colored);
785
1408
  }
786
1409
  };
787
1410
 
@@ -796,7 +1419,12 @@ var CostWidget = class extends StdinDataWidget {
796
1419
  0
797
1420
  // First line
798
1421
  );
1422
+ colors;
799
1423
  styleFn = costStyles.balanced;
1424
+ constructor(colors) {
1425
+ super();
1426
+ this.colors = colors ?? DEFAULT_THEME;
1427
+ }
800
1428
  setStyle(style = "balanced") {
801
1429
  const fn = costStyles[style];
802
1430
  if (fn) {
@@ -808,52 +1436,55 @@ var CostWidget = class extends StdinDataWidget {
808
1436
  const renderData = {
809
1437
  costUsd: data.cost.total_cost_usd
810
1438
  };
811
- return this.styleFn(renderData);
1439
+ return this.styleFn(renderData, this.colors.cost);
812
1440
  }
813
1441
  };
814
1442
 
815
1443
  // src/widgets/lines/styles.ts
816
- function createLinesStyles(colors) {
817
- return {
818
- balanced: (data) => {
819
- const addedStr = colorize(`+${data.added}`, colors.added);
820
- const removedStr = colorize(`-${data.removed}`, colors.removed);
821
- return `${addedStr}/${removedStr}`;
822
- },
823
- compact: (data) => {
824
- const addedStr = colorize(`+${data.added}`, colors.added);
825
- const removedStr = colorize(`-${data.removed}`, colors.removed);
826
- return `${addedStr}${removedStr}`;
827
- },
828
- playful: (data) => {
829
- const addedStr = colorize(`\u2795${data.added}`, colors.added);
830
- const removedStr = colorize(`\u2796${data.removed}`, colors.removed);
831
- return `${addedStr} ${removedStr}`;
832
- },
833
- verbose: (data) => {
834
- const parts = [];
835
- if (data.added > 0) {
836
- parts.push(colorize(`+${data.added} added`, colors.added));
837
- }
838
- if (data.removed > 0) {
839
- parts.push(colorize(`-${data.removed} removed`, colors.removed));
840
- }
841
- return parts.join(", ");
842
- },
843
- labeled: (data) => {
844
- const addedStr = colorize(`+${data.added}`, colors.added);
845
- const removedStr = colorize(`-${data.removed}`, colors.removed);
846
- const lines = `${addedStr}/${removedStr}`;
847
- return withLabel("Lines", lines);
848
- },
849
- indicator: (data) => {
850
- const addedStr = colorize(`+${data.added}`, colors.added);
851
- const removedStr = colorize(`-${data.removed}`, colors.removed);
852
- const lines = `${addedStr}/${removedStr}`;
853
- return withIndicator(lines);
1444
+ var linesStyles = {
1445
+ balanced: (data, colors) => {
1446
+ if (!colors) return `+${data.added}/-${data.removed}`;
1447
+ const addedStr = colorize(`+${data.added}`, colors.added);
1448
+ const removedStr = colorize(`-${data.removed}`, colors.removed);
1449
+ return `${addedStr}/${removedStr}`;
1450
+ },
1451
+ compact: (data, colors) => {
1452
+ if (!colors) return `+${data.added}-${data.removed}`;
1453
+ const addedStr = colorize(`+${data.added}`, colors.added);
1454
+ const removedStr = colorize(`-${data.removed}`, colors.removed);
1455
+ return `${addedStr}${removedStr}`;
1456
+ },
1457
+ playful: (data, colors) => {
1458
+ if (!colors) return `\u2795${data.added} \u2796${data.removed}`;
1459
+ const addedStr = colorize(`\u2795${data.added}`, colors.added);
1460
+ const removedStr = colorize(`\u2796${data.removed}`, colors.removed);
1461
+ return `${addedStr} ${removedStr}`;
1462
+ },
1463
+ verbose: (data, colors) => {
1464
+ const parts = [];
1465
+ if (data.added > 0) {
1466
+ const text = `+${data.added} added`;
1467
+ parts.push(colors ? colorize(text, colors.added) : text);
854
1468
  }
855
- };
856
- }
1469
+ if (data.removed > 0) {
1470
+ const text = `-${data.removed} removed`;
1471
+ parts.push(colors ? colorize(text, colors.removed) : text);
1472
+ }
1473
+ return parts.join(", ");
1474
+ },
1475
+ labeled: (data, colors) => {
1476
+ const addedStr = colors ? colorize(`+${data.added}`, colors.added) : `+${data.added}`;
1477
+ const removedStr = colors ? colorize(`-${data.removed}`, colors.removed) : `-${data.removed}`;
1478
+ const lines = `${addedStr}/${removedStr}`;
1479
+ return withLabel("Lines", lines);
1480
+ },
1481
+ indicator: (data, colors) => {
1482
+ const addedStr = colors ? colorize(`+${data.added}`, colors.added) : `+${data.added}`;
1483
+ const removedStr = colors ? colorize(`-${data.removed}`, colors.removed) : `-${data.removed}`;
1484
+ const lines = `${addedStr}/${removedStr}`;
1485
+ return withIndicator(lines);
1486
+ }
1487
+ };
857
1488
 
858
1489
  // src/widgets/lines-widget.ts
859
1490
  var LinesWidget = class extends StdinDataWidget {
@@ -867,16 +1498,13 @@ var LinesWidget = class extends StdinDataWidget {
867
1498
  // First line
868
1499
  );
869
1500
  colors;
870
- linesStyles;
871
- styleFn;
1501
+ styleFn = linesStyles.balanced;
872
1502
  constructor(colors) {
873
1503
  super();
874
- this.colors = colors ?? DEFAULT_THEME.lines;
875
- this.linesStyles = createLinesStyles(this.colors);
876
- this.styleFn = this.linesStyles.balanced;
1504
+ this.colors = colors ?? DEFAULT_THEME;
877
1505
  }
878
1506
  setStyle(style = "balanced") {
879
- const fn = this.linesStyles[style];
1507
+ const fn = linesStyles[style];
880
1508
  if (fn) {
881
1509
  this.styleFn = fn;
882
1510
  }
@@ -885,43 +1513,89 @@ var LinesWidget = class extends StdinDataWidget {
885
1513
  const added = data.cost?.total_lines_added ?? 0;
886
1514
  const removed = data.cost?.total_lines_removed ?? 0;
887
1515
  const renderData = { added, removed };
888
- return this.styleFn(renderData);
1516
+ return this.styleFn(renderData, this.colors.lines);
889
1517
  }
890
1518
  };
891
1519
 
892
1520
  // src/widgets/duration/styles.ts
893
1521
  var durationStyles = {
894
- balanced: (data) => {
895
- return formatDuration(data.durationMs);
1522
+ balanced: (data, colors) => {
1523
+ const formatted = formatDuration(data.durationMs);
1524
+ if (!colors) return formatted;
1525
+ return formatDurationWithColors(data.durationMs, colors);
896
1526
  },
897
- compact: (data) => {
1527
+ compact: (data, colors) => {
898
1528
  const totalSeconds = Math.floor(data.durationMs / 1e3);
899
1529
  const hours = Math.floor(totalSeconds / 3600);
900
1530
  const minutes = Math.floor(totalSeconds % 3600 / 60);
1531
+ if (!colors) {
1532
+ if (hours > 0) {
1533
+ return `${hours}h${minutes}m`;
1534
+ }
1535
+ return `${minutes}m`;
1536
+ }
901
1537
  if (hours > 0) {
902
- return `${hours}h${minutes}m`;
1538
+ return colorize(`${hours}`, colors.value) + colorize("h", colors.unit) + colorize(`${minutes}`, colors.value) + colorize("m", colors.unit);
903
1539
  }
904
- return `${minutes}m`;
1540
+ return colorize(`${minutes}`, colors.value) + colorize("m", colors.unit);
905
1541
  },
906
- playful: (data) => {
1542
+ playful: (data, colors) => {
907
1543
  const totalSeconds = Math.floor(data.durationMs / 1e3);
908
1544
  const hours = Math.floor(totalSeconds / 3600);
909
1545
  const minutes = Math.floor(totalSeconds % 3600 / 60);
1546
+ if (!colors) {
1547
+ if (hours > 0) {
1548
+ return `\u231B ${hours}h ${minutes}m`;
1549
+ }
1550
+ return `\u231B ${minutes}m`;
1551
+ }
910
1552
  if (hours > 0) {
911
- return `\u231B ${hours}h ${minutes}m`;
1553
+ const colored = colorize(`${hours}`, colors.value) + colorize("h", colors.unit) + colorize(` ${minutes}`, colors.value) + colorize("m", colors.unit);
1554
+ return `\u231B ${colored}`;
912
1555
  }
913
- return `\u231B ${minutes}m`;
1556
+ return `\u231B ` + colorize(`${minutes}`, colors.value) + colorize("m", colors.unit);
914
1557
  },
915
- technical: (data) => {
916
- return `${Math.floor(data.durationMs)}ms`;
1558
+ technical: (data, colors) => {
1559
+ const value = `${Math.floor(data.durationMs)}ms`;
1560
+ if (!colors) return value;
1561
+ return colorize(`${Math.floor(data.durationMs)}`, colors.value) + colorize("ms", colors.unit);
917
1562
  },
918
- labeled: (data) => {
919
- return withLabel("Time", formatDuration(data.durationMs));
1563
+ labeled: (data, colors) => {
1564
+ const formatted = formatDuration(data.durationMs);
1565
+ if (!colors) return withLabel("Time", formatted);
1566
+ const colored = formatDurationWithColors(data.durationMs, colors);
1567
+ return withLabel("Time", colored);
920
1568
  },
921
- indicator: (data) => {
922
- return withIndicator(formatDuration(data.durationMs));
1569
+ indicator: (data, colors) => {
1570
+ const formatted = formatDuration(data.durationMs);
1571
+ if (!colors) return withIndicator(formatted);
1572
+ const colored = formatDurationWithColors(data.durationMs, colors);
1573
+ return withIndicator(colored);
923
1574
  }
924
1575
  };
1576
+ function formatDurationWithColors(ms, colors) {
1577
+ if (ms <= 0) return colorize("0s", colors.value);
1578
+ const totalSeconds = Math.floor(ms / 1e3);
1579
+ const hours = Math.floor(totalSeconds / 3600);
1580
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
1581
+ const seconds = totalSeconds % 60;
1582
+ const parts = [];
1583
+ if (hours > 0) {
1584
+ parts.push(
1585
+ colorize(`${hours}`, colors.value) + colorize("h", colors.unit),
1586
+ colorize(`${minutes}`, colors.value) + colorize("m", colors.unit),
1587
+ colorize(`${seconds}`, colors.value) + colorize("s", colors.unit)
1588
+ );
1589
+ } else if (minutes > 0) {
1590
+ parts.push(
1591
+ colorize(`${minutes}`, colors.value) + colorize("m", colors.unit),
1592
+ colorize(`${seconds}`, colors.value) + colorize("s", colors.unit)
1593
+ );
1594
+ } else {
1595
+ parts.push(colorize(`${seconds}`, colors.value) + colorize("s", colors.unit));
1596
+ }
1597
+ return parts.join(" ");
1598
+ }
925
1599
 
926
1600
  // src/widgets/duration-widget.ts
927
1601
  var DurationWidget = class extends StdinDataWidget {
@@ -934,7 +1608,12 @@ var DurationWidget = class extends StdinDataWidget {
934
1608
  0
935
1609
  // First line
936
1610
  );
1611
+ colors;
937
1612
  styleFn = durationStyles.balanced;
1613
+ constructor(colors) {
1614
+ super();
1615
+ this.colors = colors ?? DEFAULT_THEME;
1616
+ }
938
1617
  setStyle(style = "balanced") {
939
1618
  const fn = durationStyles[style];
940
1619
  if (fn) {
@@ -946,7 +1625,7 @@ var DurationWidget = class extends StdinDataWidget {
946
1625
  const renderData = {
947
1626
  durationMs: data.cost.total_duration_ms
948
1627
  };
949
- return this.styleFn(renderData);
1628
+ return this.styleFn(renderData, this.colors.duration);
950
1629
  }
951
1630
  };
952
1631
 
@@ -1663,13 +2342,13 @@ var HAND_ABBREVIATIONS = {
1663
2342
  "Straight Flush": "SF",
1664
2343
  "Four of a Kind": "4K",
1665
2344
  "Full House": "FH",
1666
- "Flush": "FL",
1667
- "Straight": "ST",
2345
+ Flush: "FL",
2346
+ Straight: "ST",
1668
2347
  "Three of a Kind": "3K",
1669
2348
  "Two Pair": "2P",
1670
2349
  "One Pair": "1P",
1671
2350
  "High Card": "HC",
1672
- "Nothing": "\u2014"
2351
+ Nothing: "\u2014"
1673
2352
  };
1674
2353
  function formatCardByParticipation(cardData, isParticipating) {
1675
2354
  const color = isRedSuit(cardData.card.suit) ? red : gray;
@@ -1709,16 +2388,14 @@ function formatCardEmojiByParticipation(cardData, isParticipating) {
1709
2388
  return `${cardText} `;
1710
2389
  }
1711
2390
  }
1712
- function formatHandResult(handResult) {
2391
+ function formatHandResult(handResult, colors) {
1713
2392
  if (!handResult) {
1714
2393
  return "\u2014";
1715
2394
  }
1716
2395
  const playerParticipates = handResult.participatingIndices.some((idx) => idx < 2);
1717
- if (!playerParticipates) {
1718
- return `Nothing \u{1F0CF}`;
1719
- } else {
1720
- return `${handResult.name}! ${handResult.emoji}`;
1721
- }
2396
+ const resultText = !playerParticipates ? `Nothing \u{1F0CF}` : `${handResult.name}! ${handResult.emoji}`;
2397
+ if (!colors) return resultText;
2398
+ return colorize2(resultText, colors.result);
1722
2399
  }
1723
2400
  function getHandAbbreviation(handResult) {
1724
2401
  if (!handResult) {
@@ -1728,37 +2405,41 @@ function getHandAbbreviation(handResult) {
1728
2405
  return `${abbreviation} (${handResult.name})`;
1729
2406
  }
1730
2407
  var pokerStyles = {
1731
- balanced: (data) => {
2408
+ balanced: (data, colors) => {
1732
2409
  const { holeCards, boardCards, handResult } = data;
1733
2410
  const participatingSet = new Set(handResult?.participatingIndices || []);
1734
2411
  const handStr = holeCards.map((hc, idx) => formatCardByParticipation(hc, participatingSet.has(idx))).join("");
1735
2412
  const boardStr = boardCards.map((bc, idx) => formatCardByParticipation(bc, participatingSet.has(idx + 2))).join("");
1736
- const handLabel = colorize("Hand:", lightGray);
1737
- const boardLabel = colorize("Board:", lightGray);
1738
- return `${handLabel} ${handStr}| ${boardLabel} ${boardStr}\u2192 ${formatHandResult(handResult)}`;
2413
+ const labelColor = colors?.participating ?? lightGray;
2414
+ const handLabel = colorize2("Hand:", labelColor);
2415
+ const boardLabel = colorize2("Board:", labelColor);
2416
+ return `${handLabel} ${handStr}| ${boardLabel} ${boardStr}\u2192 ${formatHandResult(handResult, colors)}`;
1739
2417
  },
1740
- compact: (data) => {
1741
- return pokerStyles.balanced(data);
2418
+ compact: (data, colors) => {
2419
+ return pokerStyles.balanced(data, colors);
1742
2420
  },
1743
- playful: (data) => {
1744
- return pokerStyles.balanced(data);
2421
+ playful: (data, colors) => {
2422
+ return pokerStyles.balanced(data, colors);
1745
2423
  },
1746
- "compact-verbose": (data) => {
2424
+ "compact-verbose": (data, colors) => {
1747
2425
  const { holeCards, boardCards, handResult } = data;
1748
2426
  const participatingSet = new Set(handResult?.participatingIndices || []);
1749
2427
  const handStr = holeCards.map((hc, idx) => formatCardCompact(hc, participatingSet.has(idx))).join("");
1750
2428
  const boardStr = boardCards.map((bc, idx) => formatCardCompact(bc, participatingSet.has(idx + 2))).join("");
1751
2429
  const abbreviation = getHandAbbreviation(handResult);
1752
- return `${handStr}| ${boardStr}\u2192 ${abbreviation}`;
2430
+ const result = `${handStr}| ${boardStr}\u2192 ${abbreviation}`;
2431
+ if (!colors) return result;
2432
+ return colorize2(result, colors.result);
1753
2433
  },
1754
- emoji: (data) => {
2434
+ emoji: (data, colors) => {
1755
2435
  const { holeCards, boardCards, handResult } = data;
1756
2436
  const participatingSet = new Set(handResult?.participatingIndices || []);
1757
2437
  const handStr = holeCards.map((hc, idx) => formatCardEmojiByParticipation(hc, participatingSet.has(idx))).join("");
1758
2438
  const boardStr = boardCards.map((bc, idx) => formatCardEmojiByParticipation(bc, participatingSet.has(idx + 2))).join("");
1759
- const handLabel = colorize("Hand:", lightGray);
1760
- const boardLabel = colorize("Board:", lightGray);
1761
- return `${handLabel} ${handStr}| ${boardLabel} ${boardStr}\u2192 ${formatHandResult(handResult)}`;
2439
+ const labelColor = colors?.participating ?? lightGray;
2440
+ const handLabel = colorize2("Hand:", labelColor);
2441
+ const boardLabel = colorize2("Board:", labelColor);
2442
+ return `${handLabel} ${handStr}| ${boardLabel} ${boardStr}\u2192 ${formatHandResult(handResult, colors)}`;
1762
2443
  }
1763
2444
  };
1764
2445
 
@@ -1779,6 +2460,7 @@ var PokerWidget = class extends StdinDataWidget {
1779
2460
  lastUpdateTimestamp = 0;
1780
2461
  THROTTLE_MS = 5e3;
1781
2462
  // 5 seconds
2463
+ colors;
1782
2464
  styleFn = pokerStyles.balanced;
1783
2465
  setStyle(style = DEFAULT_WIDGET_STYLE) {
1784
2466
  const fn = pokerStyles[style];
@@ -1786,6 +2468,10 @@ var PokerWidget = class extends StdinDataWidget {
1786
2468
  this.styleFn = fn;
1787
2469
  }
1788
2470
  }
2471
+ constructor(colors) {
2472
+ super();
2473
+ this.colors = colors ?? DEFAULT_THEME;
2474
+ }
1789
2475
  /**
1790
2476
  * Generate new poker hand on each update
1791
2477
  */
@@ -1847,14 +2533,14 @@ var PokerWidget = class extends StdinDataWidget {
1847
2533
  boardCards: boardCardsData,
1848
2534
  handResult
1849
2535
  };
1850
- return this.styleFn(renderData);
2536
+ return this.styleFn(renderData, this.colors.poker);
1851
2537
  }
1852
2538
  getHandName(text) {
1853
2539
  const match = text.match(/^([^!]+)/);
1854
2540
  return match ? match[1].trim() : "Nothing";
1855
2541
  }
1856
2542
  getHandEmoji(text) {
1857
- const match = text.match(/([🃏♠️♥️♦️♣️🎉✨🌟])/);
2543
+ const match = text.match(/([🃏♠️♥️♦️♣️🎉✨🌟])/u);
1858
2544
  return match ? match[1] : "\u{1F0CF}";
1859
2545
  }
1860
2546
  };