ccstatusline-usage 2.1.4 → 2.1.6

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 +32 -40
  2. package/dist/ccstatusline.js +1006 -185
  3. package/package.json +1 -1
@@ -51450,7 +51450,7 @@ import { execSync as execSync3 } from "child_process";
51450
51450
  import * as fs5 from "fs";
51451
51451
  import * as path4 from "path";
51452
51452
  var __dirname = "/Users/peter/Documents/Code/ccstatusline-usage/src/utils";
51453
- var PACKAGE_VERSION = "2.1.4";
51453
+ var PACKAGE_VERSION = "2.1.6";
51454
51454
  function getPackageVersion() {
51455
51455
  if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
51456
51456
  return PACKAGE_VERSION;
@@ -52287,6 +52287,18 @@ function getDefaultPowerlineTheme() {
52287
52287
  return "nord-aurora";
52288
52288
  }
52289
52289
 
52290
+ // src/utils/input-guards.ts
52291
+ var CONTROL_CHAR_REGEX = /[\u0000-\u001F\u007F]/u;
52292
+ var shouldInsertInput = (input, key) => {
52293
+ if (!input) {
52294
+ return false;
52295
+ }
52296
+ if (key.ctrl || key.meta || key.tab) {
52297
+ return false;
52298
+ }
52299
+ return !CONTROL_CHAR_REGEX.test(input);
52300
+ };
52301
+
52290
52302
  // src/widgets/Model.ts
52291
52303
  import * as fs6 from "fs";
52292
52304
  import { homedir as homedir4 } from "os";
@@ -52350,6 +52362,9 @@ class ModelWidget {
52350
52362
  getDisplayName() {
52351
52363
  return "Model";
52352
52364
  }
52365
+ getCategory() {
52366
+ return "Core";
52367
+ }
52353
52368
  getEditorDisplay(item) {
52354
52369
  return { displayText: this.getDisplayName() };
52355
52370
  }
@@ -52389,6 +52404,9 @@ class OutputStyleWidget {
52389
52404
  getDisplayName() {
52390
52405
  return "Output Style";
52391
52406
  }
52407
+ getCategory() {
52408
+ return "Core";
52409
+ }
52392
52410
  getEditorDisplay(item) {
52393
52411
  return { displayText: this.getDisplayName() };
52394
52412
  }
@@ -52407,9 +52425,39 @@ class OutputStyleWidget {
52407
52425
  return true;
52408
52426
  }
52409
52427
  }
52410
- // src/widgets/GitBranch.ts
52428
+ // src/utils/git.ts
52411
52429
  import { execSync as execSync4 } from "child_process";
52430
+ function resolveGitCwd(context) {
52431
+ const candidates = [
52432
+ context.data?.cwd,
52433
+ context.data?.workspace?.current_dir,
52434
+ context.data?.workspace?.project_dir
52435
+ ];
52436
+ for (const candidate of candidates) {
52437
+ if (typeof candidate === "string" && candidate.trim().length > 0) {
52438
+ return candidate;
52439
+ }
52440
+ }
52441
+ return;
52442
+ }
52443
+ function runGit(command, context) {
52444
+ try {
52445
+ const cwd2 = resolveGitCwd(context);
52446
+ const output = execSync4(`git ${command}`, {
52447
+ encoding: "utf8",
52448
+ stdio: ["pipe", "pipe", "ignore"],
52449
+ ...cwd2 ? { cwd: cwd2 } : {}
52450
+ }).trim();
52451
+ return output.length > 0 ? output : null;
52452
+ } catch {
52453
+ return null;
52454
+ }
52455
+ }
52456
+ function isInsideGitWorkTree(context) {
52457
+ return runGit("rev-parse --is-inside-work-tree", context) === "true";
52458
+ }
52412
52459
 
52460
+ // src/widgets/GitBranch.ts
52413
52461
  class GitBranchWidget {
52414
52462
  getDefaultColor() {
52415
52463
  return "magenta";
@@ -52420,6 +52468,9 @@ class GitBranchWidget {
52420
52468
  getDisplayName() {
52421
52469
  return "Git Branch";
52422
52470
  }
52471
+ getCategory() {
52472
+ return "Git";
52473
+ }
52423
52474
  getEditorDisplay(item) {
52424
52475
  const hideNoGit = item.metadata?.hideNoGit === "true";
52425
52476
  const modifiers = [];
@@ -52449,21 +52500,16 @@ class GitBranchWidget {
52449
52500
  if (context.isPreview) {
52450
52501
  return item.rawValue ? "main" : "⎇ main";
52451
52502
  }
52452
- const branch = this.getGitBranch();
52503
+ if (!isInsideGitWorkTree(context)) {
52504
+ return hideNoGit ? null : "⎇ no git";
52505
+ }
52506
+ const branch = this.getGitBranch(context);
52453
52507
  if (branch)
52454
52508
  return item.rawValue ? branch : `⎇ ${branch}`;
52455
52509
  return hideNoGit ? null : "⎇ no git";
52456
52510
  }
52457
- getGitBranch() {
52458
- try {
52459
- const branch = execSync4("git branch --show-current", {
52460
- encoding: "utf8",
52461
- stdio: ["pipe", "pipe", "ignore"]
52462
- }).trim();
52463
- return branch || null;
52464
- } catch {
52465
- return null;
52466
- }
52511
+ getGitBranch(context) {
52512
+ return runGit("branch --show-current", context);
52467
52513
  }
52468
52514
  getCustomKeybinds() {
52469
52515
  return [
@@ -52478,8 +52524,6 @@ class GitBranchWidget {
52478
52524
  }
52479
52525
  }
52480
52526
  // src/widgets/GitChanges.ts
52481
- import { execSync as execSync5 } from "child_process";
52482
-
52483
52527
  class GitChangesWidget {
52484
52528
  getDefaultColor() {
52485
52529
  return "yellow";
@@ -52490,6 +52534,9 @@ class GitChangesWidget {
52490
52534
  getDisplayName() {
52491
52535
  return "Git Changes";
52492
52536
  }
52537
+ getCategory() {
52538
+ return "Git";
52539
+ }
52493
52540
  getEditorDisplay(item) {
52494
52541
  const hideNoGit = item.metadata?.hideNoGit === "true";
52495
52542
  const modifiers = [];
@@ -52519,40 +52566,107 @@ class GitChangesWidget {
52519
52566
  if (context.isPreview) {
52520
52567
  return "(+42,-10)";
52521
52568
  }
52522
- const changes = this.getGitChanges();
52569
+ if (!isInsideGitWorkTree(context)) {
52570
+ return hideNoGit ? null : "(no git)";
52571
+ }
52572
+ const changes = this.getGitChanges(context);
52523
52573
  if (changes)
52524
52574
  return `(+${changes.insertions},-${changes.deletions})`;
52525
52575
  else
52526
52576
  return hideNoGit ? null : "(no git)";
52527
52577
  }
52528
- getGitChanges() {
52529
- try {
52530
- let totalInsertions = 0;
52531
- let totalDeletions = 0;
52532
- const unstagedStat = execSync5("git diff --shortstat", {
52533
- encoding: "utf8",
52534
- stdio: ["pipe", "pipe", "ignore"]
52535
- }).trim();
52536
- const stagedStat = execSync5("git diff --cached --shortstat", {
52537
- encoding: "utf8",
52538
- stdio: ["pipe", "pipe", "ignore"]
52539
- }).trim();
52540
- if (unstagedStat) {
52541
- const insertMatch = /(\d+) insertion/.exec(unstagedStat);
52542
- const deleteMatch = /(\d+) deletion/.exec(unstagedStat);
52543
- totalInsertions += insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0;
52544
- totalDeletions += deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0;
52545
- }
52546
- if (stagedStat) {
52547
- const insertMatch = /(\d+) insertion/.exec(stagedStat);
52548
- const deleteMatch = /(\d+) deletion/.exec(stagedStat);
52549
- totalInsertions += insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0;
52550
- totalDeletions += deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0;
52551
- }
52552
- return { insertions: totalInsertions, deletions: totalDeletions };
52553
- } catch {
52554
- return null;
52578
+ getGitChanges(context) {
52579
+ let totalInsertions = 0;
52580
+ let totalDeletions = 0;
52581
+ const unstagedStat = runGit("diff --shortstat", context) ?? "";
52582
+ const stagedStat = runGit("diff --cached --shortstat", context) ?? "";
52583
+ if (unstagedStat) {
52584
+ const insertMatch = /(\d+) insertion/.exec(unstagedStat);
52585
+ const deleteMatch = /(\d+) deletion/.exec(unstagedStat);
52586
+ totalInsertions += insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0;
52587
+ totalDeletions += deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0;
52588
+ }
52589
+ if (stagedStat) {
52590
+ const insertMatch = /(\d+) insertion/.exec(stagedStat);
52591
+ const deleteMatch = /(\d+) deletion/.exec(stagedStat);
52592
+ totalInsertions += insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0;
52593
+ totalDeletions += deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0;
52594
+ }
52595
+ return { insertions: totalInsertions, deletions: totalDeletions };
52596
+ }
52597
+ getCustomKeybinds() {
52598
+ return [
52599
+ { key: "h", label: "(h)ide 'no git' message", action: "toggle-nogit" }
52600
+ ];
52601
+ }
52602
+ supportsRawValue() {
52603
+ return false;
52604
+ }
52605
+ supportsColors(item) {
52606
+ return true;
52607
+ }
52608
+ }
52609
+ // src/widgets/GitRootDir.ts
52610
+ class GitRootDirWidget {
52611
+ getDefaultColor() {
52612
+ return "cyan";
52613
+ }
52614
+ getDescription() {
52615
+ return "Shows the git repository root directory name";
52616
+ }
52617
+ getDisplayName() {
52618
+ return "Git Root Dir";
52619
+ }
52620
+ getCategory() {
52621
+ return "Git";
52622
+ }
52623
+ getEditorDisplay(item) {
52624
+ const hideNoGit = item.metadata?.hideNoGit === "true";
52625
+ const modifiers = [];
52626
+ if (hideNoGit) {
52627
+ modifiers.push("hide 'no git'");
52628
+ }
52629
+ return {
52630
+ displayText: this.getDisplayName(),
52631
+ modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
52632
+ };
52633
+ }
52634
+ handleEditorAction(action, item) {
52635
+ if (action === "toggle-nogit") {
52636
+ const currentState = item.metadata?.hideNoGit === "true";
52637
+ return {
52638
+ ...item,
52639
+ metadata: {
52640
+ ...item.metadata,
52641
+ hideNoGit: (!currentState).toString()
52642
+ }
52643
+ };
52644
+ }
52645
+ return null;
52646
+ }
52647
+ render(item, context, _settings) {
52648
+ const hideNoGit = item.metadata?.hideNoGit === "true";
52649
+ if (context.isPreview) {
52650
+ return "my-repo";
52651
+ }
52652
+ if (!isInsideGitWorkTree(context)) {
52653
+ return hideNoGit ? null : "no git";
52654
+ }
52655
+ const rootDir = this.getGitRootDir(context);
52656
+ if (rootDir) {
52657
+ return this.getRootDirName(rootDir);
52555
52658
  }
52659
+ return hideNoGit ? null : "no git";
52660
+ }
52661
+ getGitRootDir(context) {
52662
+ return runGit("rev-parse --show-toplevel", context);
52663
+ }
52664
+ getRootDirName(rootDir) {
52665
+ const trimmedRootDir = rootDir.replace(/[\\/]+$/, "");
52666
+ const normalizedRootDir = trimmedRootDir.length > 0 ? trimmedRootDir : rootDir;
52667
+ const parts = normalizedRootDir.split(/[\\/]/).filter(Boolean);
52668
+ const lastPart = parts[parts.length - 1];
52669
+ return lastPart && lastPart.length > 0 ? lastPart : normalizedRootDir;
52556
52670
  }
52557
52671
  getCustomKeybinds() {
52558
52672
  return [
@@ -52567,8 +52681,6 @@ class GitChangesWidget {
52567
52681
  }
52568
52682
  }
52569
52683
  // src/widgets/GitWorktree.ts
52570
- import { execSync as execSync6 } from "child_process";
52571
-
52572
52684
  class GitWorktreeWidget {
52573
52685
  getDefaultColor() {
52574
52686
  return "blue";
@@ -52579,6 +52691,9 @@ class GitWorktreeWidget {
52579
52691
  getDisplayName() {
52580
52692
  return "Git Worktree";
52581
52693
  }
52694
+ getCategory() {
52695
+ return "Git";
52696
+ }
52582
52697
  getEditorDisplay(item) {
52583
52698
  const hideNoGit = item.metadata?.hideNoGit === "true";
52584
52699
  const modifiers = [];
@@ -52607,24 +52722,29 @@ class GitWorktreeWidget {
52607
52722
  const hideNoGit = item.metadata?.hideNoGit === "true";
52608
52723
  if (context.isPreview)
52609
52724
  return item.rawValue ? "main" : "\uD81A\uDC30 main";
52610
- const worktree = this.getGitWorktree();
52725
+ if (!isInsideGitWorkTree(context)) {
52726
+ return hideNoGit ? null : "\uD81A\uDC30 no git";
52727
+ }
52728
+ const worktree = this.getGitWorktree(context);
52611
52729
  if (worktree)
52612
52730
  return item.rawValue ? worktree : `\uD81A\uDC30 ${worktree}`;
52613
52731
  return hideNoGit ? null : "\uD81A\uDC30 no git";
52614
52732
  }
52615
- getGitWorktree() {
52616
- try {
52617
- const worktreeDir = execSync6("git rev-parse --git-dir", {
52618
- encoding: "utf8",
52619
- stdio: ["pipe", "pipe", "ignore"]
52620
- }).trim();
52621
- if (worktreeDir.endsWith("/.git") || worktreeDir === ".git")
52622
- return "main";
52623
- const [, worktree] = worktreeDir.split(".git/worktrees/");
52624
- return worktree ?? null;
52625
- } catch {
52733
+ getGitWorktree(context) {
52734
+ const worktreeDir = runGit("rev-parse --git-dir", context);
52735
+ if (!worktreeDir) {
52736
+ return null;
52737
+ }
52738
+ const normalizedGitDir = worktreeDir.replace(/\\/g, "/");
52739
+ if (normalizedGitDir.endsWith("/.git") || normalizedGitDir === ".git")
52740
+ return "main";
52741
+ const marker = ".git/worktrees/";
52742
+ const markerIndex = normalizedGitDir.lastIndexOf(marker);
52743
+ if (markerIndex === -1) {
52626
52744
  return null;
52627
52745
  }
52746
+ const worktree = normalizedGitDir.slice(markerIndex + marker.length);
52747
+ return worktree.length > 0 ? worktree : null;
52628
52748
  }
52629
52749
  getCustomKeybinds() {
52630
52750
  return [
@@ -52646,7 +52766,7 @@ function getContextConfig(modelId) {
52646
52766
  };
52647
52767
  if (!modelId)
52648
52768
  return defaultConfig;
52649
- if (modelId.includes("claude-sonnet-4-5") && modelId.toLowerCase().includes("[1m]")) {
52769
+ if (modelId.toLowerCase().includes("[1m]")) {
52650
52770
  return {
52651
52771
  maxTokens: 1e6,
52652
52772
  usableTokens: 800000
@@ -53342,6 +53462,9 @@ class TokensInputWidget {
53342
53462
  getDisplayName() {
53343
53463
  return "Tokens Input";
53344
53464
  }
53465
+ getCategory() {
53466
+ return "Tokens";
53467
+ }
53345
53468
  getEditorDisplay(item) {
53346
53469
  return { displayText: this.getDisplayName() };
53347
53470
  }
@@ -53371,6 +53494,9 @@ class TokensOutputWidget {
53371
53494
  getDisplayName() {
53372
53495
  return "Tokens Output";
53373
53496
  }
53497
+ getCategory() {
53498
+ return "Tokens";
53499
+ }
53374
53500
  getEditorDisplay(item) {
53375
53501
  return { displayText: this.getDisplayName() };
53376
53502
  }
@@ -53400,6 +53526,9 @@ class TokensCachedWidget {
53400
53526
  getDisplayName() {
53401
53527
  return "Tokens Cached";
53402
53528
  }
53529
+ getCategory() {
53530
+ return "Tokens";
53531
+ }
53403
53532
  getEditorDisplay(item) {
53404
53533
  return { displayText: this.getDisplayName() };
53405
53534
  }
@@ -53429,6 +53558,9 @@ class TokensTotalWidget {
53429
53558
  getDisplayName() {
53430
53559
  return "Tokens Total";
53431
53560
  }
53561
+ getCategory() {
53562
+ return "Tokens";
53563
+ }
53432
53564
  getEditorDisplay(item) {
53433
53565
  return { displayText: this.getDisplayName() };
53434
53566
  }
@@ -53458,6 +53590,9 @@ class ContextLengthWidget {
53458
53590
  getDisplayName() {
53459
53591
  return "Context Length";
53460
53592
  }
53593
+ getCategory() {
53594
+ return "Context";
53595
+ }
53461
53596
  getEditorDisplay(item) {
53462
53597
  return { displayText: this.getDisplayName() };
53463
53598
  }
@@ -53487,6 +53622,9 @@ class ContextPercentageWidget {
53487
53622
  getDisplayName() {
53488
53623
  return "Context %";
53489
53624
  }
53625
+ getCategory() {
53626
+ return "Context";
53627
+ }
53490
53628
  getEditorDisplay(item) {
53491
53629
  const isInverse = item.metadata?.inverse === "true";
53492
53630
  const modifiers = [];
@@ -53549,6 +53687,9 @@ class ContextPercentageUsableWidget {
53549
53687
  getDisplayName() {
53550
53688
  return "Context % (usable)";
53551
53689
  }
53690
+ getCategory() {
53691
+ return "Context";
53692
+ }
53552
53693
  getEditorDisplay(item) {
53553
53694
  const isInverse = item.metadata?.inverse === "true";
53554
53695
  const modifiers = [];
@@ -53611,6 +53752,9 @@ class SessionClockWidget {
53611
53752
  getDisplayName() {
53612
53753
  return "Session Clock";
53613
53754
  }
53755
+ getCategory() {
53756
+ return "Session";
53757
+ }
53614
53758
  getEditorDisplay(item) {
53615
53759
  return { displayText: this.getDisplayName() };
53616
53760
  }
@@ -53639,6 +53783,9 @@ class SessionCostWidget {
53639
53783
  getDisplayName() {
53640
53784
  return "Session Cost";
53641
53785
  }
53786
+ getCategory() {
53787
+ return "Session";
53788
+ }
53642
53789
  getEditorDisplay(item) {
53643
53790
  return { displayText: this.getDisplayName() };
53644
53791
  }
@@ -53671,6 +53818,9 @@ class TerminalWidthWidget {
53671
53818
  getDisplayName() {
53672
53819
  return "Terminal Width";
53673
53820
  }
53821
+ getCategory() {
53822
+ return "Environment";
53823
+ }
53674
53824
  getEditorDisplay(item) {
53675
53825
  return { displayText: this.getDisplayName() };
53676
53826
  }
@@ -53702,6 +53852,9 @@ class VersionWidget {
53702
53852
  getDisplayName() {
53703
53853
  return "Version";
53704
53854
  }
53855
+ getCategory() {
53856
+ return "Core";
53857
+ }
53705
53858
  getEditorDisplay(item) {
53706
53859
  return { displayText: this.getDisplayName() };
53707
53860
  }
@@ -53734,6 +53887,9 @@ class CustomTextWidget {
53734
53887
  getDisplayName() {
53735
53888
  return "Custom Text";
53736
53889
  }
53890
+ getCategory() {
53891
+ return "Custom";
53892
+ }
53737
53893
  getEditorDisplay(item) {
53738
53894
  const text = item.customText ?? "Empty";
53739
53895
  return { displayText: `${this.getDisplayName()} (${text})` };
@@ -53836,7 +53992,7 @@ var CustomTextEditor = ({ widget, onComplete, onCancel }) => {
53836
53992
  setText(text.slice(0, deleteFromIndex) + text.slice(deleteToIndex));
53837
53993
  }
53838
53994
  }
53839
- } else if (input && !key.ctrl && !key.meta) {
53995
+ } else if (shouldInsertInput(input, key)) {
53840
53996
  const newText = text.slice(0, cursorPos) + input + text.slice(cursorPos);
53841
53997
  setText(newText);
53842
53998
  setCursorPos(cursorPos + input.length);
@@ -53872,7 +54028,7 @@ var CustomTextEditor = ({ widget, onComplete, onCancel }) => {
53872
54028
  }, undefined, true, undefined, this);
53873
54029
  };
53874
54030
  // src/widgets/CustomCommand.tsx
53875
- import { execSync as execSync7 } from "child_process";
54031
+ import { execSync as execSync5 } from "child_process";
53876
54032
  var import_react30 = __toESM(require_react(), 1);
53877
54033
  var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
53878
54034
 
@@ -53886,6 +54042,9 @@ class CustomCommandWidget {
53886
54042
  getDisplayName() {
53887
54043
  return "Custom Command";
53888
54044
  }
54045
+ getCategory() {
54046
+ return "Custom";
54047
+ }
53889
54048
  getEditorDisplay(item) {
53890
54049
  const cmd = item.commandPath ?? "No command";
53891
54050
  const truncatedCmd = cmd.length > 20 ? `${cmd.substring(0, 17)}...` : cmd;
@@ -53918,7 +54077,7 @@ class CustomCommandWidget {
53918
54077
  try {
53919
54078
  const timeout = item.timeout ?? 1000;
53920
54079
  const jsonInput = JSON.stringify(context.data);
53921
- let output = execSync7(item.commandPath, {
54080
+ let output = execSync5(item.commandPath, {
53922
54081
  encoding: "utf8",
53923
54082
  input: jsonInput,
53924
54083
  timeout,
@@ -54009,7 +54168,7 @@ var CustomCommandEditor = ({ widget, onComplete, onCancel, action }) => {
54009
54168
  if (commandCursorPos < commandInput.length) {
54010
54169
  setCommandInput(commandInput.slice(0, commandCursorPos) + commandInput.slice(commandCursorPos + 1));
54011
54170
  }
54012
- } else if (input) {
54171
+ } else if (shouldInsertInput(input, key)) {
54013
54172
  setCommandInput(commandInput.slice(0, commandCursorPos) + input + commandInput.slice(commandCursorPos));
54014
54173
  setCommandCursorPos(commandCursorPos + input.length);
54015
54174
  }
@@ -54026,7 +54185,7 @@ var CustomCommandEditor = ({ widget, onComplete, onCancel, action }) => {
54026
54185
  onCancel();
54027
54186
  } else if (key.backspace) {
54028
54187
  setWidthInput(widthInput.slice(0, -1));
54029
- } else if (input && /\d/.test(input)) {
54188
+ } else if (shouldInsertInput(input, key) && /\d/.test(input)) {
54030
54189
  setWidthInput(widthInput + input);
54031
54190
  }
54032
54191
  } else if (mode === "timeout") {
@@ -54042,7 +54201,7 @@ var CustomCommandEditor = ({ widget, onComplete, onCancel, action }) => {
54042
54201
  onCancel();
54043
54202
  } else if (key.backspace) {
54044
54203
  setTimeoutInput(timeoutInput.slice(0, -1));
54045
- } else if (input && /\d/.test(input)) {
54204
+ } else if (shouldInsertInput(input, key) && /\d/.test(input)) {
54046
54205
  setTimeoutInput(timeoutInput + input);
54047
54206
  }
54048
54207
  }
@@ -54136,6 +54295,9 @@ class BlockTimerWidget {
54136
54295
  getDisplayName() {
54137
54296
  return "Block Timer";
54138
54297
  }
54298
+ getCategory() {
54299
+ return "Session";
54300
+ }
54139
54301
  getEditorDisplay(item) {
54140
54302
  const mode = item.metadata?.display ?? "time";
54141
54303
  const modifiers = [];
@@ -54236,8 +54398,8 @@ class BlockTimerWidget {
54236
54398
  }
54237
54399
  // src/widgets/CurrentWorkingDir.tsx
54238
54400
  var import_react31 = __toESM(require_react(), 1);
54239
- var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
54240
54401
  import * as os5 from "node:os";
54402
+ var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
54241
54403
 
54242
54404
  class CurrentWorkingDirWidget {
54243
54405
  getDefaultColor() {
@@ -54249,10 +54411,17 @@ class CurrentWorkingDirWidget {
54249
54411
  getDisplayName() {
54250
54412
  return "Current Working Dir";
54251
54413
  }
54414
+ getCategory() {
54415
+ return "Environment";
54416
+ }
54252
54417
  getEditorDisplay(item) {
54253
54418
  const segments = item.metadata?.segments ? parseInt(item.metadata.segments, 10) : undefined;
54254
54419
  const fishStyle = item.metadata?.fishStyle === "true";
54420
+ const abbreviateHome = item.metadata?.abbreviateHome === "true";
54255
54421
  const modifiers = [];
54422
+ if (abbreviateHome) {
54423
+ modifiers.push("~");
54424
+ }
54256
54425
  if (fishStyle) {
54257
54426
  modifiers.push("fish-style");
54258
54427
  } else if (segments && segments > 0) {
@@ -54264,11 +54433,31 @@ class CurrentWorkingDirWidget {
54264
54433
  };
54265
54434
  }
54266
54435
  handleEditorAction(action, item) {
54436
+ if (action === "toggle-abbreviate-home") {
54437
+ const currentAbbreviateHome = item.metadata?.abbreviateHome === "true";
54438
+ const newAbbreviateHome = !currentAbbreviateHome;
54439
+ if (newAbbreviateHome) {
54440
+ const { fishStyle, ...restMetadata } = item.metadata ?? {};
54441
+ return {
54442
+ ...item,
54443
+ metadata: {
54444
+ ...restMetadata,
54445
+ abbreviateHome: "true"
54446
+ }
54447
+ };
54448
+ } else {
54449
+ const { abbreviateHome, ...restMetadata } = item.metadata ?? {};
54450
+ return {
54451
+ ...item,
54452
+ metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
54453
+ };
54454
+ }
54455
+ }
54267
54456
  if (action === "toggle-fish-style") {
54268
54457
  const currentFishStyle = item.metadata?.fishStyle === "true";
54269
54458
  const newFishStyle = !currentFishStyle;
54270
54459
  if (newFishStyle) {
54271
- const { segments, ...restMetadata } = item.metadata ?? {};
54460
+ const { segments, abbreviateHome, ...restMetadata } = item.metadata ?? {};
54272
54461
  return {
54273
54462
  ...item,
54274
54463
  metadata: {
@@ -54289,10 +54478,19 @@ class CurrentWorkingDirWidget {
54289
54478
  render(item, context, settings) {
54290
54479
  const segments = item.metadata?.segments ? parseInt(item.metadata.segments, 10) : undefined;
54291
54480
  const fishStyle = item.metadata?.fishStyle === "true";
54481
+ const abbreviateHome = item.metadata?.abbreviateHome === "true";
54292
54482
  if (context.isPreview) {
54293
54483
  let previewPath;
54294
54484
  if (fishStyle) {
54295
54485
  previewPath = "~/D/P/my-project";
54486
+ } else if (abbreviateHome && segments && segments > 0) {
54487
+ if (segments === 1) {
54488
+ previewPath = "~/.../my-project";
54489
+ } else {
54490
+ previewPath = "~/.../Projects/my-project";
54491
+ }
54492
+ } else if (abbreviateHome) {
54493
+ previewPath = "~/Documents/Projects/my-project";
54296
54494
  } else if (segments && segments > 0) {
54297
54495
  if (segments === 1) {
54298
54496
  previewPath = ".../project";
@@ -54310,20 +54508,27 @@ class CurrentWorkingDirWidget {
54310
54508
  let displayPath = cwd2;
54311
54509
  if (fishStyle) {
54312
54510
  displayPath = this.abbreviatePath(cwd2);
54313
- } else if (segments && segments > 0) {
54314
- const useBackslash = cwd2.includes("\\") && !cwd2.includes("/");
54315
- const outSep = useBackslash ? "\\" : "/";
54316
- const pathParts = cwd2.split(/[\\/]+/);
54317
- const filteredParts = pathParts.filter((part) => part !== "");
54318
- if (filteredParts.length > segments) {
54319
- const selectedSegments = filteredParts.slice(-segments);
54320
- displayPath = "..." + outSep + selectedSegments.join(outSep);
54511
+ } else {
54512
+ if (abbreviateHome) {
54513
+ displayPath = this.abbreviateHomeDir(displayPath);
54514
+ }
54515
+ if (segments && segments > 0) {
54516
+ const useBackslash = displayPath.includes("\\") && !displayPath.includes("/");
54517
+ const outSep = useBackslash ? "\\" : "/";
54518
+ const pathParts = displayPath.split(/[\\/]+/);
54519
+ const filteredParts = pathParts.filter((part) => part !== "");
54520
+ if (filteredParts.length > segments) {
54521
+ const selectedSegments = filteredParts.slice(-segments);
54522
+ const prefix = displayPath.startsWith("~") ? `~${outSep}` : "";
54523
+ displayPath = prefix + "..." + outSep + selectedSegments.join(outSep);
54524
+ }
54321
54525
  }
54322
54526
  }
54323
54527
  return item.rawValue ? displayPath : `cwd: ${displayPath}`;
54324
54528
  }
54325
54529
  getCustomKeybinds() {
54326
54530
  return [
54531
+ { key: "h", label: "(h)ome ~", action: "toggle-abbreviate-home" },
54327
54532
  { key: "s", label: "(s)egments", action: "edit-segments" },
54328
54533
  { key: "f", label: "(f)ish style", action: "toggle-fish-style" }
54329
54534
  ];
@@ -54339,6 +54544,20 @@ class CurrentWorkingDirWidget {
54339
54544
  supportsColors(item) {
54340
54545
  return true;
54341
54546
  }
54547
+ abbreviateHomeDir(path6) {
54548
+ const homeDir = os5.homedir();
54549
+ if (path6 === homeDir) {
54550
+ return "~";
54551
+ }
54552
+ if (path6.startsWith(homeDir)) {
54553
+ const boundaryChar = path6[homeDir.length];
54554
+ if (boundaryChar !== "/" && boundaryChar !== "\\") {
54555
+ return path6;
54556
+ }
54557
+ return "~" + path6.slice(homeDir.length);
54558
+ }
54559
+ return path6;
54560
+ }
54342
54561
  abbreviatePath(path6) {
54343
54562
  const homeDir = os5.homedir();
54344
54563
  const useBackslash = path6.includes("\\") && !path6.includes("/");
@@ -54391,7 +54610,7 @@ var CurrentWorkingDirEditor = ({ widget, onComplete, onCancel, action }) => {
54391
54610
  onCancel();
54392
54611
  } else if (key.backspace) {
54393
54612
  setSegmentsInput(segmentsInput.slice(0, -1));
54394
- } else if (input && /\d/.test(input) && !key.ctrl) {
54613
+ } else if (shouldInsertInput(input, key) && /\d/.test(input)) {
54395
54614
  setSegmentsInput(segmentsInput + input);
54396
54615
  }
54397
54616
  }
@@ -54437,6 +54656,9 @@ class ClaudeSessionIdWidget {
54437
54656
  getDisplayName() {
54438
54657
  return "Claude Session ID";
54439
54658
  }
54659
+ getCategory() {
54660
+ return "Core";
54661
+ }
54440
54662
  getEditorDisplay(item) {
54441
54663
  return { displayText: this.getDisplayName() };
54442
54664
  }
@@ -54463,7 +54685,7 @@ class ClaudeSessionIdWidget {
54463
54685
  }
54464
54686
  // src/widgets/ApiUsage.tsx
54465
54687
  import {
54466
- execSync as execSync8,
54688
+ execSync as execSync6,
54467
54689
  spawnSync
54468
54690
  } from "child_process";
54469
54691
  import * as fs7 from "fs";
@@ -54488,7 +54710,7 @@ function readTokenFromFile() {
54488
54710
  }
54489
54711
  function readTokenFromKeychain() {
54490
54712
  try {
54491
- const result = execSync8('security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null', { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
54713
+ const result = execSync6('security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null', { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] }).trim();
54492
54714
  const parsed = JSON.parse(result);
54493
54715
  return parsed?.claudeAiOauth?.accessToken ?? null;
54494
54716
  } catch {
@@ -54701,6 +54923,9 @@ class SessionUsageWidget {
54701
54923
  getDisplayName() {
54702
54924
  return "Session Usage";
54703
54925
  }
54926
+ getCategory() {
54927
+ return "API Usage";
54928
+ }
54704
54929
  getEditorDisplay(item) {
54705
54930
  return { displayText: this.getDisplayName() };
54706
54931
  }
@@ -54732,6 +54957,9 @@ class WeeklyUsageWidget {
54732
54957
  getDisplayName() {
54733
54958
  return "Weekly Usage";
54734
54959
  }
54960
+ getCategory() {
54961
+ return "API Usage";
54962
+ }
54735
54963
  getEditorDisplay(item) {
54736
54964
  return { displayText: this.getDisplayName() };
54737
54965
  }
@@ -54763,6 +54991,9 @@ class ResetTimerWidget {
54763
54991
  getDisplayName() {
54764
54992
  return "Reset Timer";
54765
54993
  }
54994
+ getCategory() {
54995
+ return "API Usage";
54996
+ }
54766
54997
  getEditorDisplay(item) {
54767
54998
  return { displayText: this.getDisplayName() };
54768
54999
  }
@@ -54822,6 +55053,9 @@ class ContextBarWidget {
54822
55053
  getDisplayName() {
54823
55054
  return "Context Bar";
54824
55055
  }
55056
+ getCategory() {
55057
+ return "API Usage";
55058
+ }
54825
55059
  getEditorDisplay(item) {
54826
55060
  return { displayText: this.getDisplayName() };
54827
55061
  }
@@ -54857,12 +55091,65 @@ class ContextBarWidget {
54857
55091
  return true;
54858
55092
  }
54859
55093
  }
55094
+ // src/widgets/SessionName.ts
55095
+ import * as fs8 from "fs";
55096
+
55097
+ class SessionNameWidget {
55098
+ getDefaultColor() {
55099
+ return "cyan";
55100
+ }
55101
+ getDescription() {
55102
+ return "Shows the session name set via /rename command in Claude Code";
55103
+ }
55104
+ getDisplayName() {
55105
+ return "Session Name";
55106
+ }
55107
+ getCategory() {
55108
+ return "Session";
55109
+ }
55110
+ getEditorDisplay(item) {
55111
+ return { displayText: this.getDisplayName() };
55112
+ }
55113
+ render(item, context, settings) {
55114
+ if (context.isPreview) {
55115
+ return item.rawValue ? "my-session" : "Session: my-session";
55116
+ }
55117
+ const transcriptPath = context.data?.transcript_path;
55118
+ if (!transcriptPath) {
55119
+ return null;
55120
+ }
55121
+ try {
55122
+ const content = fs8.readFileSync(transcriptPath, "utf-8");
55123
+ const lines = content.split(`
55124
+ `);
55125
+ for (let i = lines.length - 1;i >= 0; i--) {
55126
+ const line = lines[i]?.trim();
55127
+ if (!line)
55128
+ continue;
55129
+ try {
55130
+ const entry = JSON.parse(line);
55131
+ if (entry.type === "custom-title" && entry.customTitle) {
55132
+ return item.rawValue ? entry.customTitle : `Session: ${entry.customTitle}`;
55133
+ }
55134
+ } catch {}
55135
+ }
55136
+ } catch {}
55137
+ return null;
55138
+ }
55139
+ supportsRawValue() {
55140
+ return true;
55141
+ }
55142
+ supportsColors(item) {
55143
+ return true;
55144
+ }
55145
+ }
54860
55146
  // src/utils/widgets.ts
54861
55147
  var widgetRegistry = new Map([
54862
55148
  ["model", new ModelWidget],
54863
55149
  ["output-style", new OutputStyleWidget],
54864
55150
  ["git-branch", new GitBranchWidget],
54865
55151
  ["git-changes", new GitChangesWidget],
55152
+ ["git-root-dir", new GitRootDirWidget],
54866
55153
  ["git-worktree", new GitWorktreeWidget],
54867
55154
  ["current-working-dir", new CurrentWorkingDirWidget],
54868
55155
  ["tokens-input", new TokensInputWidget],
@@ -54883,7 +55170,8 @@ var widgetRegistry = new Map([
54883
55170
  ["session-usage", new SessionUsageWidget],
54884
55171
  ["weekly-usage", new WeeklyUsageWidget],
54885
55172
  ["reset-timer", new ResetTimerWidget],
54886
- ["context-bar", new ContextBarWidget]
55173
+ ["context-bar", new ContextBarWidget],
55174
+ ["session-name", new SessionNameWidget]
54887
55175
  ]);
54888
55176
  function getWidget(type) {
54889
55177
  return widgetRegistry.get(type) ?? null;
@@ -54898,6 +55186,98 @@ function getAllWidgetTypes(settings) {
54898
55186
  }
54899
55187
  return allTypes;
54900
55188
  }
55189
+ var LAYOUT_WIDGETS = {
55190
+ separator: {
55191
+ displayName: "Separator",
55192
+ description: "A separator character between status line widgets",
55193
+ category: "Layout"
55194
+ },
55195
+ "flex-separator": {
55196
+ displayName: "Flex Separator",
55197
+ description: "Expands to fill available terminal width",
55198
+ category: "Layout"
55199
+ }
55200
+ };
55201
+ function getLayoutCatalogEntry(type) {
55202
+ const layout = LAYOUT_WIDGETS[type];
55203
+ if (!layout) {
55204
+ return null;
55205
+ }
55206
+ return {
55207
+ type,
55208
+ displayName: layout.displayName,
55209
+ description: layout.description,
55210
+ category: layout.category,
55211
+ searchText: `${layout.displayName} ${layout.description} ${type}`.toLowerCase()
55212
+ };
55213
+ }
55214
+ function getWidgetCatalog(settings) {
55215
+ return getAllWidgetTypes(settings).map((type) => {
55216
+ const layoutEntry = getLayoutCatalogEntry(type);
55217
+ if (layoutEntry) {
55218
+ return layoutEntry;
55219
+ }
55220
+ const widget = getWidget(type);
55221
+ const displayName = widget?.getDisplayName() ?? type;
55222
+ const description = widget?.getDescription() ?? `Unknown widget: ${type}`;
55223
+ const category = widget?.getCategory() ?? "Other";
55224
+ return {
55225
+ type,
55226
+ displayName,
55227
+ description,
55228
+ category,
55229
+ searchText: `${displayName} ${description} ${type}`.toLowerCase()
55230
+ };
55231
+ });
55232
+ }
55233
+ function getWidgetCatalogCategories(catalog) {
55234
+ const categories = new Set;
55235
+ for (const entry of catalog) {
55236
+ categories.add(entry.category);
55237
+ }
55238
+ return Array.from(categories);
55239
+ }
55240
+ function filterWidgetCatalog(catalog, category, query) {
55241
+ const normalizedQuery = query.trim().toLowerCase();
55242
+ const categoryFiltered = category === "All" ? [...catalog] : catalog.filter((entry) => entry.category === category);
55243
+ const withScore = categoryFiltered.map((entry) => {
55244
+ if (!normalizedQuery) {
55245
+ return {
55246
+ entry,
55247
+ score: 99
55248
+ };
55249
+ }
55250
+ const name = entry.displayName.toLowerCase();
55251
+ const description = entry.description.toLowerCase();
55252
+ const type = entry.type.toLowerCase();
55253
+ if (name.startsWith(normalizedQuery)) {
55254
+ return { entry, score: 0 };
55255
+ }
55256
+ if (name.includes(normalizedQuery)) {
55257
+ return { entry, score: 1 };
55258
+ }
55259
+ if (type.includes(normalizedQuery)) {
55260
+ return { entry, score: 2 };
55261
+ }
55262
+ if (description.includes(normalizedQuery)) {
55263
+ return { entry, score: 3 };
55264
+ }
55265
+ if (entry.searchText.includes(normalizedQuery)) {
55266
+ return { entry, score: 4 };
55267
+ }
55268
+ return null;
55269
+ }).filter((item) => item !== null);
55270
+ return withScore.sort((a, b) => {
55271
+ if (a.score !== b.score) {
55272
+ return a.score - b.score;
55273
+ }
55274
+ const byDisplayName = a.entry.displayName.localeCompare(b.entry.displayName);
55275
+ if (byDisplayName !== 0) {
55276
+ return byDisplayName;
55277
+ }
55278
+ return a.entry.type.localeCompare(b.entry.type);
55279
+ }).map((item) => item.entry);
55280
+ }
54901
55281
 
54902
55282
  // src/tui/components/ConfirmDialog.tsx
54903
55283
  var import_react32 = __toESM(require_react(), 1);
@@ -55016,7 +55396,7 @@ var ColorMenu = ({ widgets, lineIndex, settings, onUpdate, onBack }) => {
55016
55396
  }
55017
55397
  } else if (key.backspace || key.delete) {
55018
55398
  setHexInput(hexInput.slice(0, -1));
55019
- } else if (input && hexInput.length < 6) {
55399
+ } else if (shouldInsertInput(input, key) && hexInput.length < 6) {
55020
55400
  const upperInput = input.toUpperCase();
55021
55401
  if (/^[0-9A-F]$/.test(upperInput)) {
55022
55402
  setHexInput(hexInput + upperInput);
@@ -55054,7 +55434,7 @@ var ColorMenu = ({ widgets, lineIndex, settings, onUpdate, onBack }) => {
55054
55434
  }
55055
55435
  } else if (key.backspace || key.delete) {
55056
55436
  setAnsi256Input(ansi256Input.slice(0, -1));
55057
- } else if (input && ansi256Input.length < 3) {
55437
+ } else if (shouldInsertInput(input, key) && ansi256Input.length < 3) {
55058
55438
  if (/^[0-9]$/.test(input)) {
55059
55439
  const newInput = ansi256Input + input;
55060
55440
  const code = parseInt(newInput, 10);
@@ -55528,7 +55908,7 @@ var GlobalOverridesMenu = ({ settings, onUpdate, onBack }) => {
55528
55908
  setEditingPadding(false);
55529
55909
  } else if (key.backspace) {
55530
55910
  setPaddingInput(paddingInput.slice(0, -1));
55531
- } else if (key.delete) {} else if (input) {
55911
+ } else if (key.delete) {} else if (shouldInsertInput(input, key)) {
55532
55912
  setPaddingInput(paddingInput + input);
55533
55913
  }
55534
55914
  } else if (editingSeparator) {
@@ -55550,7 +55930,7 @@ var GlobalOverridesMenu = ({ settings, onUpdate, onBack }) => {
55550
55930
  setEditingSeparator(false);
55551
55931
  } else if (key.backspace) {
55552
55932
  setSeparatorInput(separatorInput.slice(0, -1));
55553
- } else if (key.delete) {} else if (input) {
55933
+ } else if (key.delete) {} else if (shouldInsertInput(input, key)) {
55554
55934
  setSeparatorInput(separatorInput + input);
55555
55935
  }
55556
55936
  } else if (confirmingSeparator) {
@@ -56017,21 +56397,11 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56017
56397
  const [selectedIndex, setSelectedIndex] = import_react36.useState(0);
56018
56398
  const [moveMode, setMoveMode] = import_react36.useState(false);
56019
56399
  const [customEditorWidget, setCustomEditorWidget] = import_react36.useState(null);
56400
+ const [widgetPicker, setWidgetPicker] = import_react36.useState(null);
56401
+ const [showClearConfirm, setShowClearConfirm] = import_react36.useState(false);
56020
56402
  const separatorChars = ["|", "-", ",", " "];
56021
- const getAllowedTypes = () => {
56022
- let allowedTypes = getAllWidgetTypes(settings);
56023
- if (settings.defaultSeparator) {
56024
- allowedTypes = allowedTypes.filter((t) => t !== "separator");
56025
- }
56026
- if (settings.powerline.enabled) {
56027
- allowedTypes = allowedTypes.filter((t) => t !== "separator" && t !== "flex-separator");
56028
- }
56029
- return allowedTypes;
56030
- };
56031
- const getDefaultItemType = () => {
56032
- const allowedTypes = getAllowedTypes();
56033
- return allowedTypes.includes("model") ? "model" : allowedTypes[0] ?? "model";
56034
- };
56403
+ const widgetCatalog = getWidgetCatalog(settings);
56404
+ const widgetCategories = ["All", ...getWidgetCatalogCategories(widgetCatalog)];
56035
56405
  const getUniqueBackgroundColor = (insertIndex) => {
56036
56406
  if (!settings.powerline.enabled || settings.powerline.theme === "custom") {
56037
56407
  return;
@@ -56057,10 +56427,187 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56057
56427
  const handleEditorCancel = () => {
56058
56428
  setCustomEditorWidget(null);
56059
56429
  };
56430
+ const getFilteredCategories = (query) => {
56431
+ return [...widgetCategories];
56432
+ };
56433
+ const normalizePickerState = (state) => {
56434
+ const filteredCategories = getFilteredCategories(state.categoryQuery);
56435
+ const selectedCategory = state.selectedCategory && filteredCategories.includes(state.selectedCategory) ? state.selectedCategory : filteredCategories[0] ?? null;
56436
+ const hasTopLevelSearch = state.level === "category" && state.categoryQuery.trim().length > 0;
56437
+ const effectiveCategory = hasTopLevelSearch ? "All" : selectedCategory ?? "All";
56438
+ const effectiveQuery = hasTopLevelSearch ? state.categoryQuery : state.widgetQuery;
56439
+ const filteredWidgets = filterWidgetCatalog(widgetCatalog, effectiveCategory, effectiveQuery);
56440
+ const hasSelectedType = state.selectedType ? filteredWidgets.some((entry) => entry.type === state.selectedType) : false;
56441
+ return {
56442
+ ...state,
56443
+ selectedCategory,
56444
+ selectedType: hasSelectedType ? state.selectedType : filteredWidgets[0]?.type ?? null
56445
+ };
56446
+ };
56447
+ const openWidgetPicker = (action) => {
56448
+ if (widgetCatalog.length === 0) {
56449
+ return;
56450
+ }
56451
+ const currentType = widgets[selectedIndex]?.type;
56452
+ const selectedType = action === "change" ? currentType ?? null : null;
56453
+ setWidgetPicker(normalizePickerState({
56454
+ action,
56455
+ level: "category",
56456
+ selectedCategory: "All",
56457
+ categoryQuery: "",
56458
+ widgetQuery: "",
56459
+ selectedType
56460
+ }));
56461
+ };
56462
+ const applyWidgetPickerSelection = (selectedType) => {
56463
+ if (!widgetPicker) {
56464
+ return;
56465
+ }
56466
+ if (widgetPicker.action === "change") {
56467
+ const currentWidget2 = widgets[selectedIndex];
56468
+ if (currentWidget2) {
56469
+ const newWidgets = [...widgets];
56470
+ newWidgets[selectedIndex] = { ...currentWidget2, type: selectedType };
56471
+ onUpdate(newWidgets);
56472
+ }
56473
+ } else {
56474
+ const insertIndex = widgetPicker.action === "add" ? widgets.length > 0 ? selectedIndex + 1 : 0 : selectedIndex;
56475
+ const backgroundColor = getUniqueBackgroundColor(insertIndex);
56476
+ const newWidget = {
56477
+ id: generateGuid(),
56478
+ type: selectedType,
56479
+ ...backgroundColor && { backgroundColor }
56480
+ };
56481
+ const newWidgets = [...widgets];
56482
+ newWidgets.splice(insertIndex, 0, newWidget);
56483
+ onUpdate(newWidgets);
56484
+ setSelectedIndex(insertIndex);
56485
+ }
56486
+ setWidgetPicker(null);
56487
+ };
56060
56488
  use_input_default((input, key) => {
56061
56489
  if (customEditorWidget) {
56062
56490
  return;
56063
56491
  }
56492
+ if (showClearConfirm) {
56493
+ return;
56494
+ }
56495
+ if (widgetPicker) {
56496
+ const filteredCategories = getFilteredCategories(widgetPicker.categoryQuery);
56497
+ const selectedCategory = widgetPicker.selectedCategory && filteredCategories.includes(widgetPicker.selectedCategory) ? widgetPicker.selectedCategory : filteredCategories[0] ?? null;
56498
+ const hasTopLevelSearch = widgetPicker.level === "category" && widgetPicker.categoryQuery.trim().length > 0;
56499
+ const topLevelSearchEntries2 = hasTopLevelSearch ? filterWidgetCatalog(widgetCatalog, "All", widgetPicker.categoryQuery) : [];
56500
+ const topLevelSelectedEntry = topLevelSearchEntries2.find((entry) => entry.type === widgetPicker.selectedType) ?? topLevelSearchEntries2[0];
56501
+ const filteredWidgets = filterWidgetCatalog(widgetCatalog, selectedCategory ?? "All", widgetPicker.widgetQuery);
56502
+ const selectedEntry = filteredWidgets.find((entry) => entry.type === widgetPicker.selectedType) ?? filteredWidgets[0];
56503
+ if (widgetPicker.level === "category") {
56504
+ if (key.escape) {
56505
+ if (widgetPicker.categoryQuery.length > 0) {
56506
+ setWidgetPicker((prev) => prev ? normalizePickerState({
56507
+ ...prev,
56508
+ categoryQuery: ""
56509
+ }) : prev);
56510
+ } else {
56511
+ setWidgetPicker(null);
56512
+ }
56513
+ } else if (key.return) {
56514
+ if (hasTopLevelSearch) {
56515
+ if (topLevelSelectedEntry) {
56516
+ applyWidgetPickerSelection(topLevelSelectedEntry.type);
56517
+ }
56518
+ } else if (selectedCategory) {
56519
+ setWidgetPicker((prev) => prev ? normalizePickerState({
56520
+ ...prev,
56521
+ level: "widget",
56522
+ selectedCategory
56523
+ }) : prev);
56524
+ }
56525
+ } else if (key.upArrow || key.downArrow) {
56526
+ if (hasTopLevelSearch) {
56527
+ if (topLevelSearchEntries2.length === 0) {
56528
+ return;
56529
+ }
56530
+ let currentIndex = topLevelSearchEntries2.findIndex((entry) => entry.type === widgetPicker.selectedType);
56531
+ if (currentIndex === -1) {
56532
+ currentIndex = 0;
56533
+ }
56534
+ const nextIndex = key.downArrow ? Math.min(topLevelSearchEntries2.length - 1, currentIndex + 1) : Math.max(0, currentIndex - 1);
56535
+ const nextType = topLevelSearchEntries2[nextIndex]?.type ?? null;
56536
+ setWidgetPicker((prev) => prev ? normalizePickerState({
56537
+ ...prev,
56538
+ selectedType: nextType
56539
+ }) : prev);
56540
+ } else {
56541
+ if (filteredCategories.length === 0) {
56542
+ return;
56543
+ }
56544
+ let currentIndex = filteredCategories.findIndex((category) => category === selectedCategory);
56545
+ if (currentIndex === -1) {
56546
+ currentIndex = 0;
56547
+ }
56548
+ const nextIndex = key.downArrow ? Math.min(filteredCategories.length - 1, currentIndex + 1) : Math.max(0, currentIndex - 1);
56549
+ const nextCategory = filteredCategories[nextIndex] ?? null;
56550
+ setWidgetPicker((prev) => prev ? normalizePickerState({
56551
+ ...prev,
56552
+ selectedCategory: nextCategory
56553
+ }) : prev);
56554
+ }
56555
+ } else if (key.backspace || key.delete) {
56556
+ setWidgetPicker((prev) => prev ? normalizePickerState({
56557
+ ...prev,
56558
+ categoryQuery: prev.categoryQuery.slice(0, -1)
56559
+ }) : prev);
56560
+ } else if (input && !key.ctrl && !key.meta && !key.tab) {
56561
+ setWidgetPicker((prev) => prev ? normalizePickerState({
56562
+ ...prev,
56563
+ categoryQuery: prev.categoryQuery + input
56564
+ }) : prev);
56565
+ }
56566
+ } else {
56567
+ if (key.escape) {
56568
+ if (widgetPicker.widgetQuery.length > 0) {
56569
+ setWidgetPicker((prev) => prev ? normalizePickerState({
56570
+ ...prev,
56571
+ widgetQuery: ""
56572
+ }) : prev);
56573
+ } else {
56574
+ setWidgetPicker((prev) => prev ? normalizePickerState({
56575
+ ...prev,
56576
+ level: "category"
56577
+ }) : prev);
56578
+ }
56579
+ } else if (key.return) {
56580
+ if (selectedEntry) {
56581
+ applyWidgetPickerSelection(selectedEntry.type);
56582
+ }
56583
+ } else if (key.upArrow || key.downArrow) {
56584
+ if (filteredWidgets.length === 0) {
56585
+ return;
56586
+ }
56587
+ let currentIndex = filteredWidgets.findIndex((entry) => entry.type === widgetPicker.selectedType);
56588
+ if (currentIndex === -1) {
56589
+ currentIndex = 0;
56590
+ }
56591
+ const nextIndex = key.downArrow ? Math.min(filteredWidgets.length - 1, currentIndex + 1) : Math.max(0, currentIndex - 1);
56592
+ const nextType = filteredWidgets[nextIndex]?.type ?? null;
56593
+ setWidgetPicker((prev) => prev ? normalizePickerState({
56594
+ ...prev,
56595
+ selectedType: nextType
56596
+ }) : prev);
56597
+ } else if (key.backspace || key.delete) {
56598
+ setWidgetPicker((prev) => prev ? normalizePickerState({
56599
+ ...prev,
56600
+ widgetQuery: prev.widgetQuery.slice(0, -1)
56601
+ }) : prev);
56602
+ } else if (input && !key.ctrl && !key.meta && !key.tab) {
56603
+ setWidgetPicker((prev) => prev ? normalizePickerState({
56604
+ ...prev,
56605
+ widgetQuery: prev.widgetQuery + input
56606
+ }) : prev);
56607
+ }
56608
+ }
56609
+ return;
56610
+ }
56064
56611
  if (moveMode) {
56065
56612
  if (key.upArrow && selectedIndex > 0) {
56066
56613
  const newWidgets = [...widgets];
@@ -56084,69 +56631,20 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56084
56631
  setMoveMode(false);
56085
56632
  }
56086
56633
  } else {
56087
- if (key.upArrow) {
56634
+ if (key.upArrow && widgets.length > 0) {
56088
56635
  setSelectedIndex(Math.max(0, selectedIndex - 1));
56089
- } else if (key.downArrow) {
56636
+ } else if (key.downArrow && widgets.length > 0) {
56090
56637
  setSelectedIndex(Math.min(widgets.length - 1, selectedIndex + 1));
56091
56638
  } else if (key.leftArrow && widgets.length > 0) {
56092
- const types = getAllowedTypes();
56093
- const currentWidget2 = widgets[selectedIndex];
56094
- if (currentWidget2) {
56095
- const currentType = currentWidget2.type;
56096
- let currentIndex = types.indexOf(currentType);
56097
- if (currentIndex === -1) {
56098
- currentIndex = 0;
56099
- }
56100
- const prevIndex = currentIndex === 0 ? types.length - 1 : currentIndex - 1;
56101
- const newWidgets = [...widgets];
56102
- const prevType = types[prevIndex];
56103
- if (prevType) {
56104
- newWidgets[selectedIndex] = { ...currentWidget2, type: prevType };
56105
- onUpdate(newWidgets);
56106
- }
56107
- }
56639
+ openWidgetPicker("change");
56108
56640
  } else if (key.rightArrow && widgets.length > 0) {
56109
- const types = getAllowedTypes();
56110
- const currentWidget2 = widgets[selectedIndex];
56111
- if (currentWidget2) {
56112
- const currentType = currentWidget2.type;
56113
- let currentIndex = types.indexOf(currentType);
56114
- if (currentIndex === -1) {
56115
- currentIndex = 0;
56116
- }
56117
- const nextIndex = (currentIndex + 1) % types.length;
56118
- const newWidgets = [...widgets];
56119
- const nextType = types[nextIndex];
56120
- if (nextType) {
56121
- newWidgets[selectedIndex] = { ...currentWidget2, type: nextType };
56122
- onUpdate(newWidgets);
56123
- }
56124
- }
56641
+ openWidgetPicker("change");
56125
56642
  } else if (key.return && widgets.length > 0) {
56126
56643
  setMoveMode(true);
56127
56644
  } else if (input === "a") {
56128
- const insertIndex = widgets.length > 0 ? selectedIndex + 1 : 0;
56129
- const backgroundColor = getUniqueBackgroundColor(insertIndex);
56130
- const newWidget = {
56131
- id: generateGuid(),
56132
- type: getDefaultItemType(),
56133
- ...backgroundColor && { backgroundColor }
56134
- };
56135
- const newWidgets = [...widgets];
56136
- newWidgets.splice(insertIndex, 0, newWidget);
56137
- onUpdate(newWidgets);
56138
- setSelectedIndex(insertIndex);
56645
+ openWidgetPicker("add");
56139
56646
  } else if (input === "i") {
56140
- const insertIndex = selectedIndex;
56141
- const backgroundColor = getUniqueBackgroundColor(insertIndex);
56142
- const newWidget = {
56143
- id: generateGuid(),
56144
- type: getDefaultItemType(),
56145
- ...backgroundColor && { backgroundColor }
56146
- };
56147
- const newWidgets = [...widgets];
56148
- newWidgets.splice(insertIndex, 0, newWidget);
56149
- onUpdate(newWidgets);
56647
+ openWidgetPicker("insert");
56150
56648
  } else if (input === "d" && widgets.length > 0) {
56151
56649
  const newWidgets = widgets.filter((_, i) => i !== selectedIndex);
56152
56650
  onUpdate(newWidgets);
@@ -56154,8 +56652,9 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56154
56652
  setSelectedIndex(selectedIndex - 1);
56155
56653
  }
56156
56654
  } else if (input === "c") {
56157
- onUpdate([]);
56158
- setSelectedIndex(0);
56655
+ if (widgets.length > 0) {
56656
+ setShowClearConfirm(true);
56657
+ }
56159
56658
  } else if (input === " " && widgets.length > 0) {
56160
56659
  const currentWidget2 = widgets[selectedIndex];
56161
56660
  if (currentWidget2 && currentWidget2.type === "separator") {
@@ -56168,7 +56667,11 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56168
56667
  }
56169
56668
  } else if (input === "r" && widgets.length > 0) {
56170
56669
  const currentWidget2 = widgets[selectedIndex];
56171
- if (currentWidget2 && currentWidget2.type !== "separator" && currentWidget2.type !== "flex-separator" && currentWidget2.type !== "custom-text") {
56670
+ if (currentWidget2 && currentWidget2.type !== "separator" && currentWidget2.type !== "flex-separator") {
56671
+ const widgetImpl = getWidget(currentWidget2.type);
56672
+ if (!widgetImpl?.supportsRawValue()) {
56673
+ return;
56674
+ }
56172
56675
  const newWidgets = [...widgets];
56173
56676
  newWidgets[selectedIndex] = { ...currentWidget2, rawValue: !currentWidget2.rawValue };
56174
56677
  onUpdate(newWidgets);
@@ -56241,6 +56744,12 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56241
56744
  };
56242
56745
  const hasFlexSeparator = widgets.some((widget) => widget.type === "flex-separator");
56243
56746
  const widthDetectionAvailable = canDetectTerminalWidth();
56747
+ const pickerCategories = widgetPicker ? getFilteredCategories(widgetPicker.categoryQuery) : [];
56748
+ const selectedPickerCategory = widgetPicker ? widgetPicker.selectedCategory && pickerCategories.includes(widgetPicker.selectedCategory) ? widgetPicker.selectedCategory : pickerCategories[0] ?? null : null;
56749
+ const topLevelSearchEntries = widgetPicker && widgetPicker.level === "category" && widgetPicker.categoryQuery.trim().length > 0 ? filterWidgetCatalog(widgetCatalog, "All", widgetPicker.categoryQuery) : [];
56750
+ const selectedTopLevelSearchEntry = widgetPicker ? topLevelSearchEntries.find((entry) => entry.type === widgetPicker.selectedType) ?? topLevelSearchEntries[0] : null;
56751
+ const pickerEntries = widgetPicker ? filterWidgetCatalog(widgetCatalog, selectedPickerCategory ?? "All", widgetPicker.widgetQuery) : [];
56752
+ const selectedPickerEntry = widgetPicker ? pickerEntries.find((entry) => entry.type === widgetPicker.selectedType) ?? pickerEntries[0] : null;
56244
56753
  const currentWidget = widgets[selectedIndex];
56245
56754
  const isSeparator = currentWidget?.type === "separator";
56246
56755
  const isFlexSeparator = currentWidget?.type === "flex-separator";
@@ -56258,11 +56767,14 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56258
56767
  }
56259
56768
  }
56260
56769
  const canMerge = currentWidget && selectedIndex < widgets.length - 1 && !isSeparator && !isFlexSeparator;
56261
- let helpText = "↑↓ select, ←→ change type";
56770
+ const hasWidgets = widgets.length > 0;
56771
+ let helpText = hasWidgets ? "↑↓ select, ←→ open type picker" : "(a)dd via picker, (i)nsert via picker";
56262
56772
  if (isSeparator) {
56263
56773
  helpText += ", Space edit separator";
56264
56774
  }
56265
- helpText += ", Enter to move, (a)dd, (i)nsert, (d)elete, (c)lear line";
56775
+ if (hasWidgets) {
56776
+ helpText += ", Enter to move, (a)dd via picker, (i)nsert via picker, (d)elete, (c)lear line";
56777
+ }
56266
56778
  if (canToggleRaw) {
56267
56779
  helpText += ", (r)aw value";
56268
56780
  }
@@ -56271,6 +56783,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56271
56783
  }
56272
56784
  helpText += ", ESC back";
56273
56785
  const customKeybindsText = customKeybinds.map((kb) => kb.label).join(", ");
56786
+ const pickerActionLabel = widgetPicker?.action === "add" ? "Add Widget" : widgetPicker?.action === "insert" ? "Insert Widget" : "Change Widget Type";
56274
56787
  if (customEditorWidget?.impl.renderEditor) {
56275
56788
  return customEditorWidget.impl.renderEditor({
56276
56789
  widget: customEditorWidget.widget,
@@ -56279,6 +56792,56 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56279
56792
  action: customEditorWidget.action
56280
56793
  });
56281
56794
  }
56795
+ if (showClearConfirm) {
56796
+ return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56797
+ flexDirection: "column",
56798
+ children: [
56799
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56800
+ bold: true,
56801
+ color: "yellow",
56802
+ children: "⚠ Confirm Clear Line"
56803
+ }, undefined, false, undefined, this),
56804
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56805
+ marginTop: 1,
56806
+ flexDirection: "column",
56807
+ children: [
56808
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56809
+ children: [
56810
+ "This will remove all widgets from Line",
56811
+ " ",
56812
+ lineNumber,
56813
+ "."
56814
+ ]
56815
+ }, undefined, true, undefined, this),
56816
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56817
+ color: "red",
56818
+ children: "This action cannot be undone!"
56819
+ }, undefined, false, undefined, this)
56820
+ ]
56821
+ }, undefined, true, undefined, this),
56822
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56823
+ marginTop: 2,
56824
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56825
+ children: "Continue?"
56826
+ }, undefined, false, undefined, this)
56827
+ }, undefined, false, undefined, this),
56828
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56829
+ marginTop: 1,
56830
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(ConfirmDialog, {
56831
+ inline: true,
56832
+ onConfirm: () => {
56833
+ onUpdate([]);
56834
+ setSelectedIndex(0);
56835
+ setShowClearConfirm(false);
56836
+ },
56837
+ onCancel: () => {
56838
+ setShowClearConfirm(false);
56839
+ }
56840
+ }, undefined, false, undefined, this)
56841
+ }, undefined, false, undefined, this)
56842
+ ]
56843
+ }, undefined, true, undefined, this);
56844
+ }
56282
56845
  return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56283
56846
  flexDirection: "column",
56284
56847
  children: [
@@ -56297,6 +56860,10 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56297
56860
  color: "blue",
56298
56861
  children: "[MOVE MODE]"
56299
56862
  }, undefined, false, undefined, this),
56863
+ widgetPicker && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56864
+ color: "cyan",
56865
+ children: `[${pickerActionLabel.toUpperCase()}]`
56866
+ }, undefined, false, undefined, this),
56300
56867
  (settings.powerline.enabled || Boolean(settings.defaultSeparator)) && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56301
56868
  marginLeft: 2,
56302
56869
  children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
@@ -56317,6 +56884,57 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56317
56884
  dimColor: true,
56318
56885
  children: "↑↓ to move widget, ESC or Enter to exit move mode"
56319
56886
  }, undefined, false, undefined, this)
56887
+ }, undefined, false, undefined, this) : widgetPicker ? /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56888
+ flexDirection: "column",
56889
+ children: widgetPicker.level === "category" ? /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(jsx_dev_runtime8.Fragment, {
56890
+ children: [
56891
+ widgetPicker.categoryQuery.trim().length > 0 ? /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56892
+ dimColor: true,
56893
+ children: "↑↓ select widget match, Enter apply, ESC clear/cancel"
56894
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56895
+ dimColor: true,
56896
+ children: "↑↓ select category, type to search all widgets, Enter continue, ESC cancel"
56897
+ }, undefined, false, undefined, this),
56898
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56899
+ children: [
56900
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56901
+ dimColor: true,
56902
+ children: "Search: "
56903
+ }, undefined, false, undefined, this),
56904
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56905
+ color: "cyan",
56906
+ children: widgetPicker.categoryQuery || "(none)"
56907
+ }, undefined, false, undefined, this)
56908
+ ]
56909
+ }, undefined, true, undefined, this)
56910
+ ]
56911
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(jsx_dev_runtime8.Fragment, {
56912
+ children: [
56913
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56914
+ dimColor: true,
56915
+ children: "↑↓ select widget, type to search widgets, Enter apply, ESC back"
56916
+ }, undefined, false, undefined, this),
56917
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56918
+ children: [
56919
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56920
+ dimColor: true,
56921
+ children: [
56922
+ "Category:",
56923
+ " ",
56924
+ selectedPickerCategory ?? "(none)",
56925
+ " ",
56926
+ "| Search:",
56927
+ " "
56928
+ ]
56929
+ }, undefined, true, undefined, this),
56930
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56931
+ color: "cyan",
56932
+ children: widgetPicker.widgetQuery || "(none)"
56933
+ }, undefined, false, undefined, this)
56934
+ ]
56935
+ }, undefined, true, undefined, this)
56936
+ ]
56937
+ }, undefined, true, undefined, this)
56320
56938
  }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56321
56939
  flexDirection: "column",
56322
56940
  children: [
@@ -56343,7 +56961,114 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56343
56961
  }, undefined, false, undefined, this)
56344
56962
  ]
56345
56963
  }, undefined, true, undefined, this),
56346
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56964
+ widgetPicker && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56965
+ marginTop: 1,
56966
+ flexDirection: "column",
56967
+ children: widgetPicker.level === "category" ? widgetPicker.categoryQuery.trim().length > 0 ? topLevelSearchEntries.length === 0 ? /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56968
+ dimColor: true,
56969
+ children: "No widgets match the search."
56970
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(jsx_dev_runtime8.Fragment, {
56971
+ children: [
56972
+ topLevelSearchEntries.map((entry, index) => {
56973
+ const isSelected = entry.type === selectedTopLevelSearchEntry?.type;
56974
+ return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56975
+ flexDirection: "row",
56976
+ flexWrap: "nowrap",
56977
+ children: [
56978
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56979
+ width: 3,
56980
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56981
+ color: isSelected ? "green" : undefined,
56982
+ children: isSelected ? "▶ " : " "
56983
+ }, undefined, false, undefined, this)
56984
+ }, undefined, false, undefined, this),
56985
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56986
+ color: isSelected ? "green" : undefined,
56987
+ children: `${index + 1}. ${entry.displayName}`
56988
+ }, undefined, false, undefined, this)
56989
+ ]
56990
+ }, entry.type, true, undefined, this);
56991
+ }),
56992
+ selectedTopLevelSearchEntry && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56993
+ marginTop: 1,
56994
+ paddingLeft: 2,
56995
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56996
+ dimColor: true,
56997
+ children: selectedTopLevelSearchEntry.description
56998
+ }, undefined, false, undefined, this)
56999
+ }, undefined, false, undefined, this)
57000
+ ]
57001
+ }, undefined, true, undefined, this) : pickerCategories.length === 0 ? /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
57002
+ dimColor: true,
57003
+ children: "No categories available."
57004
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(jsx_dev_runtime8.Fragment, {
57005
+ children: [
57006
+ pickerCategories.map((category, index) => {
57007
+ const isSelected = category === selectedPickerCategory;
57008
+ return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
57009
+ flexDirection: "row",
57010
+ flexWrap: "nowrap",
57011
+ children: [
57012
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
57013
+ width: 3,
57014
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
57015
+ color: isSelected ? "green" : undefined,
57016
+ children: isSelected ? "▶ " : " "
57017
+ }, undefined, false, undefined, this)
57018
+ }, undefined, false, undefined, this),
57019
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
57020
+ color: isSelected ? "green" : undefined,
57021
+ children: `${index + 1}. ${category}`
57022
+ }, undefined, false, undefined, this)
57023
+ ]
57024
+ }, category, true, undefined, this);
57025
+ }),
57026
+ selectedPickerCategory === "All" && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
57027
+ marginTop: 1,
57028
+ paddingLeft: 2,
57029
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
57030
+ dimColor: true,
57031
+ children: "Search across all widget categories."
57032
+ }, undefined, false, undefined, this)
57033
+ }, undefined, false, undefined, this)
57034
+ ]
57035
+ }, undefined, true, undefined, this) : pickerEntries.length === 0 ? /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
57036
+ dimColor: true,
57037
+ children: "No widgets match the current category/search."
57038
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(jsx_dev_runtime8.Fragment, {
57039
+ children: [
57040
+ pickerEntries.map((entry, index) => {
57041
+ const isSelected = entry.type === selectedPickerEntry?.type;
57042
+ return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
57043
+ flexDirection: "row",
57044
+ flexWrap: "nowrap",
57045
+ children: [
57046
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
57047
+ width: 3,
57048
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
57049
+ color: isSelected ? "green" : undefined,
57050
+ children: isSelected ? "▶ " : " "
57051
+ }, undefined, false, undefined, this)
57052
+ }, undefined, false, undefined, this),
57053
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
57054
+ color: isSelected ? "green" : undefined,
57055
+ children: `${index + 1}. ${entry.displayName}`
57056
+ }, undefined, false, undefined, this)
57057
+ ]
57058
+ }, entry.type, true, undefined, this);
57059
+ }),
57060
+ selectedPickerEntry && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
57061
+ marginTop: 1,
57062
+ paddingLeft: 2,
57063
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
57064
+ dimColor: true,
57065
+ children: selectedPickerEntry.description
57066
+ }, undefined, false, undefined, this)
57067
+ }, undefined, false, undefined, this)
57068
+ ]
57069
+ }, undefined, true, undefined, this)
57070
+ }, undefined, false, undefined, this),
57071
+ !widgetPicker && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56347
57072
  marginTop: 1,
56348
57073
  flexDirection: "column",
56349
57074
  children: widgets.length === 0 ? /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
@@ -56355,6 +57080,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56355
57080
  const isSelected = index === selectedIndex;
56356
57081
  const widgetImpl = widget.type !== "separator" && widget.type !== "flex-separator" ? getWidget(widget.type) : null;
56357
57082
  const { displayText, modifierText } = widgetImpl?.getEditorDisplay(widget) ?? { displayText: getWidgetDisplay(widget) };
57083
+ const supportsRawValue = widgetImpl?.supportsRawValue() ?? false;
56358
57084
  return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
56359
57085
  flexDirection: "row",
56360
57086
  flexWrap: "nowrap",
@@ -56377,7 +57103,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
56377
57103
  modifierText
56378
57104
  ]
56379
57105
  }, undefined, true, undefined, this),
56380
- widget.rawValue && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
57106
+ supportsRawValue && widget.rawValue && /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
56381
57107
  dimColor: true,
56382
57108
  children: " (raw value)"
56383
57109
  }, undefined, false, undefined, this),
@@ -56910,7 +57636,7 @@ var PowerlineSeparatorEditor = ({
56910
57636
  } else if (key.backspace && cursorPos > 0) {
56911
57637
  setHexInput(hexInput.slice(0, cursorPos - 1) + hexInput.slice(cursorPos));
56912
57638
  setCursorPos(cursorPos - 1);
56913
- } else if (input && /[0-9a-fA-F]/.test(input) && hexInput.length < 4) {
57639
+ } else if (shouldInsertInput(input, key) && /[0-9a-fA-F]/.test(input) && hexInput.length < 4) {
56914
57640
  setHexInput(hexInput.slice(0, cursorPos) + input.toUpperCase() + hexInput.slice(cursorPos));
56915
57641
  setCursorPos(cursorPos + 1);
56916
57642
  }
@@ -58186,7 +58912,7 @@ var TerminalWidthMenu = ({ settings, onUpdate, onBack }) => {
58186
58912
  } else if (key.backspace) {
58187
58913
  setThresholdInput(thresholdInput.slice(0, -1));
58188
58914
  setValidationError(null);
58189
- } else if (key.delete) {} else if (input && /\d/.test(input)) {
58915
+ } else if (key.delete) {} else if (shouldInsertInput(input, key) && /\d/.test(input)) {
58190
58916
  const newValue = thresholdInput + input;
58191
58917
  if (newValue.length <= 2) {
58192
58918
  setThresholdInput(newValue);
@@ -58732,6 +59458,7 @@ var StatusJSONSchema = exports_external.looseObject({
58732
59458
  total_lines_added: exports_external.number().optional(),
58733
59459
  total_lines_removed: exports_external.number().optional()
58734
59460
  }).optional(),
59461
+ agent: exports_external.object({ name: exports_external.string().optional() }).optional(),
58735
59462
  context_window: exports_external.object({
58736
59463
  context_window_size: exports_external.number().nullable().optional(),
58737
59464
  total_input_tokens: exports_external.number().nullable().optional(),
@@ -58808,7 +59535,9 @@ function renderCompactOutput(preRenderedLines, settings, maxWidth) {
58808
59535
  }
58809
59536
 
58810
59537
  // src/utils/jsonl.ts
58811
- import * as fs8 from "fs";
59538
+ import * as fs9 from "fs";
59539
+ import { createHash } from "node:crypto";
59540
+ import os7 from "node:os";
58812
59541
  import path8 from "node:path";
58813
59542
 
58814
59543
  // node_modules/tinyglobby/dist/index.mjs
@@ -58943,12 +59672,12 @@ function build$3(options) {
58943
59672
  return options.group ? groupFiles : empty;
58944
59673
  }
58945
59674
  var resolveSymlinksAsync = function(path7, state, callback$1) {
58946
- const { queue, fs: fs8, options: { suppressErrors } } = state;
59675
+ const { queue, fs: fs9, options: { suppressErrors } } = state;
58947
59676
  queue.enqueue();
58948
- fs8.realpath(path7, (error43, resolvedPath) => {
59677
+ fs9.realpath(path7, (error43, resolvedPath) => {
58949
59678
  if (error43)
58950
59679
  return queue.dequeue(suppressErrors ? null : error43, state);
58951
- fs8.stat(resolvedPath, (error$1, stat) => {
59680
+ fs9.stat(resolvedPath, (error$1, stat) => {
58952
59681
  if (error$1)
58953
59682
  return queue.dequeue(suppressErrors ? null : error$1, state);
58954
59683
  if (stat.isDirectory() && isRecursive(path7, resolvedPath, state))
@@ -58959,11 +59688,11 @@ var resolveSymlinksAsync = function(path7, state, callback$1) {
58959
59688
  });
58960
59689
  };
58961
59690
  var resolveSymlinks = function(path7, state, callback$1) {
58962
- const { queue, fs: fs8, options: { suppressErrors } } = state;
59691
+ const { queue, fs: fs9, options: { suppressErrors } } = state;
58963
59692
  queue.enqueue();
58964
59693
  try {
58965
- const resolvedPath = fs8.realpathSync(path7);
58966
- const stat = fs8.statSync(resolvedPath);
59694
+ const resolvedPath = fs9.realpathSync(path7);
59695
+ const stat = fs9.statSync(resolvedPath);
58967
59696
  if (stat.isDirectory() && isRecursive(path7, resolvedPath, state))
58968
59697
  return;
58969
59698
  callback$1(stat, resolvedPath);
@@ -59046,23 +59775,23 @@ var walkAsync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
59046
59775
  state.queue.enqueue();
59047
59776
  if (currentDepth < 0)
59048
59777
  return state.queue.dequeue(null, state);
59049
- const { fs: fs8 } = state;
59778
+ const { fs: fs9 } = state;
59050
59779
  state.visited.push(crawlPath);
59051
59780
  state.counts.directories++;
59052
- fs8.readdir(crawlPath || ".", readdirOpts, (error43, entries = []) => {
59781
+ fs9.readdir(crawlPath || ".", readdirOpts, (error43, entries = []) => {
59053
59782
  callback$1(entries, directoryPath, currentDepth);
59054
59783
  state.queue.dequeue(state.options.suppressErrors ? null : error43, state);
59055
59784
  });
59056
59785
  };
59057
59786
  var walkSync = (state, crawlPath, directoryPath, currentDepth, callback$1) => {
59058
- const { fs: fs8 } = state;
59787
+ const { fs: fs9 } = state;
59059
59788
  if (currentDepth < 0)
59060
59789
  return;
59061
59790
  state.visited.push(crawlPath);
59062
59791
  state.counts.directories++;
59063
59792
  let entries = [];
59064
59793
  try {
59065
- entries = fs8.readdirSync(crawlPath || ".", readdirOpts);
59794
+ entries = fs9.readdirSync(crawlPath || ".", readdirOpts);
59066
59795
  } catch (e) {
59067
59796
  if (!state.options.suppressErrors)
59068
59797
  throw e;
@@ -59597,12 +60326,87 @@ function globSync(patternsOrOptions, options) {
59597
60326
 
59598
60327
  // src/utils/jsonl.ts
59599
60328
  import { promisify } from "util";
59600
- var readFile4 = promisify(fs8.readFile);
59601
- var readFileSync6 = fs8.readFileSync;
59602
- var statSync5 = fs8.statSync;
60329
+ var readFile4 = promisify(fs9.readFile);
60330
+ var readFileSync7 = fs9.readFileSync;
60331
+ var statSync5 = fs9.statSync;
60332
+ var writeFileSync3 = fs9.writeFileSync;
60333
+ var mkdirSync4 = fs9.mkdirSync;
60334
+ var existsSync8 = fs9.existsSync;
60335
+ function normalizeConfigDir(configDir) {
60336
+ return path8.resolve(configDir);
60337
+ }
60338
+ function getBlockCachePath(configDir = getClaudeConfigDir()) {
60339
+ const normalizedConfigDir = normalizeConfigDir(configDir);
60340
+ const configHash = createHash("sha256").update(normalizedConfigDir).digest("hex").slice(0, 16);
60341
+ return path8.join(os7.homedir(), ".cache", "ccstatusline", `block-cache-${configHash}.json`);
60342
+ }
60343
+ function readBlockCache(expectedConfigDir) {
60344
+ try {
60345
+ const normalizedExpectedConfigDir = expectedConfigDir !== undefined ? normalizeConfigDir(expectedConfigDir) : undefined;
60346
+ const cachePath = getBlockCachePath(normalizedExpectedConfigDir);
60347
+ if (!existsSync8(cachePath)) {
60348
+ return null;
60349
+ }
60350
+ const content = readFileSync7(cachePath, "utf-8");
60351
+ const cache3 = JSON.parse(content);
60352
+ if (typeof cache3.startTime !== "string") {
60353
+ return null;
60354
+ }
60355
+ if (normalizedExpectedConfigDir !== undefined) {
60356
+ if (typeof cache3.configDir !== "string") {
60357
+ return null;
60358
+ }
60359
+ if (cache3.configDir !== normalizedExpectedConfigDir) {
60360
+ return null;
60361
+ }
60362
+ }
60363
+ const date5 = new Date(cache3.startTime);
60364
+ if (Number.isNaN(date5.getTime())) {
60365
+ return null;
60366
+ }
60367
+ return date5;
60368
+ } catch {
60369
+ return null;
60370
+ }
60371
+ }
60372
+ function writeBlockCache(startTime, configDir = getClaudeConfigDir()) {
60373
+ try {
60374
+ const normalizedConfigDir = normalizeConfigDir(configDir);
60375
+ const cachePath = getBlockCachePath(normalizedConfigDir);
60376
+ const cacheDir = path8.dirname(cachePath);
60377
+ if (!existsSync8(cacheDir)) {
60378
+ mkdirSync4(cacheDir, { recursive: true });
60379
+ }
60380
+ const cache3 = {
60381
+ startTime: startTime.toISOString(),
60382
+ configDir: normalizedConfigDir
60383
+ };
60384
+ writeFileSync3(cachePath, JSON.stringify(cache3), "utf-8");
60385
+ } catch {}
60386
+ }
60387
+ function getCachedBlockMetrics(sessionDurationHours = 5) {
60388
+ const sessionDurationMs = sessionDurationHours * 60 * 60 * 1000;
60389
+ const now = new Date;
60390
+ const activeConfigDir = getClaudeConfigDir();
60391
+ const cachedStartTime = readBlockCache(activeConfigDir);
60392
+ if (cachedStartTime) {
60393
+ const blockEndTime = new Date(cachedStartTime.getTime() + sessionDurationMs);
60394
+ if (now.getTime() <= blockEndTime.getTime()) {
60395
+ return {
60396
+ startTime: cachedStartTime,
60397
+ lastActivity: now
60398
+ };
60399
+ }
60400
+ }
60401
+ const metrics = getBlockMetrics();
60402
+ if (metrics) {
60403
+ writeBlockCache(metrics.startTime, activeConfigDir);
60404
+ }
60405
+ return metrics;
60406
+ }
59603
60407
  async function getSessionDuration(transcriptPath) {
59604
60408
  try {
59605
- if (!fs8.existsSync(transcriptPath)) {
60409
+ if (!fs9.existsSync(transcriptPath)) {
59606
60410
  return null;
59607
60411
  }
59608
60412
  const content = await readFile4(transcriptPath, "utf-8");
@@ -59654,7 +60458,7 @@ async function getSessionDuration(transcriptPath) {
59654
60458
  }
59655
60459
  async function getTokenMetrics(transcriptPath) {
59656
60460
  try {
59657
- if (!fs8.existsSync(transcriptPath)) {
60461
+ if (!fs9.existsSync(transcriptPath)) {
59658
60462
  return { inputTokens: 0, outputTokens: 0, cachedTokens: 0, totalTokens: 0, contextLength: 0 };
59659
60463
  }
59660
60464
  const content = await readFile4(transcriptPath, "utf-8");
@@ -59801,7 +60605,7 @@ function findMostRecentBlockStartTime(rootDir, sessionDurationHours = 5) {
59801
60605
  function getAllTimestampsFromFile(filePath) {
59802
60606
  const timestamps = [];
59803
60607
  try {
59804
- const content = readFileSync6(filePath, "utf-8");
60608
+ const content = readFileSync7(filePath, "utf-8");
59805
60609
  const lines = content.trim().split(`
59806
60610
  `).filter((line) => line.length > 0);
59807
60611
  for (const line of lines) {
@@ -59838,9 +60642,14 @@ function floorToHour(timestamp) {
59838
60642
  }
59839
60643
 
59840
60644
  // src/ccstatusline.ts
59841
- var COMPACT_THRESHOLD = 80;
59842
- function isCompactWidth(width) {
59843
- return width !== null && width > 0 && width < COMPACT_THRESHOLD;
60645
+ var COMPACT_THRESHOLD = 100;
60646
+ var TEAM_LEAD_DEFAULT_WIDTH = 60;
60647
+ function shouldUseCompactMode(width, data) {
60648
+ if (width !== null && width > 0 && width < COMPACT_THRESHOLD)
60649
+ return true;
60650
+ if (data.agent?.name === "team-lead")
60651
+ return true;
60652
+ return false;
59844
60653
  }
59845
60654
  async function readStdin() {
59846
60655
  if (process.stdin.isTTY) {
@@ -59864,6 +60673,15 @@ async function readStdin() {
59864
60673
  return null;
59865
60674
  }
59866
60675
  }
60676
+ async function ensureWindowsUtf8CodePage() {
60677
+ if (process.platform !== "win32") {
60678
+ return;
60679
+ }
60680
+ try {
60681
+ const { execFileSync } = await import("child_process");
60682
+ execFileSync("chcp.com", ["65001"], { stdio: "ignore" });
60683
+ } catch {}
60684
+ }
59867
60685
  async function renderMultipleLines(data) {
59868
60686
  const settings = await loadSettings();
59869
60687
  source_default.level = settings.colorLevel;
@@ -59882,21 +60700,23 @@ async function renderMultipleLines(data) {
59882
60700
  }
59883
60701
  let blockMetrics = null;
59884
60702
  if (hasBlockTimer) {
59885
- blockMetrics = getBlockMetrics();
60703
+ blockMetrics = getCachedBlockMetrics();
59886
60704
  }
59887
60705
  const terminalWidth = getTerminalWidth();
60706
+ const compact = shouldUseCompactMode(terminalWidth, data);
60707
+ const compactWidth = compact ? terminalWidth !== null && terminalWidth > 0 ? terminalWidth >= 80 ? Math.floor(terminalWidth / 2) - 4 : terminalWidth - 6 : TEAM_LEAD_DEFAULT_WIDTH : null;
60708
+ const effectiveWidth = compactWidth ?? terminalWidth;
59888
60709
  const context = {
59889
60710
  data,
59890
60711
  tokenMetrics,
59891
60712
  sessionDuration,
59892
60713
  blockMetrics,
59893
- terminalWidth,
60714
+ terminalWidth: effectiveWidth,
59894
60715
  isPreview: false
59895
60716
  };
59896
60717
  const preRenderedLines = preRenderAllWidgets(lines, settings, context);
59897
- const compact = isCompactWidth(terminalWidth);
59898
- if (compact && terminalWidth) {
59899
- renderCompactOutput(preRenderedLines, settings, terminalWidth - 6);
60718
+ if (compact && compactWidth) {
60719
+ renderCompactOutput(preRenderedLines, settings, compactWidth);
59900
60720
  } else {
59901
60721
  const preCalculatedMaxWidths = calculateMaxWidthsFromPreRendered(preRenderedLines, settings);
59902
60722
  let globalSeparatorIndex = 0;
@@ -59937,6 +60757,7 @@ async function renderMultipleLines(data) {
59937
60757
  }
59938
60758
  async function main() {
59939
60759
  if (!process.stdin.isTTY) {
60760
+ await ensureWindowsUtf8CodePage();
59940
60761
  const input = await readStdin();
59941
60762
  if (input && input.trim() !== "") {
59942
60763
  try {