@navios/commander-tui 1.5.1 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.cjs CHANGED
@@ -4333,7 +4333,7 @@ const ScreenOptionsSchema = object({
4333
4333
  icon: string().optional(),
4334
4334
  badgeCount: number().optional(),
4335
4335
  hidden: boolean().optional().default(false),
4336
- static: boolean().optional().default(false)
4336
+ static: boolean().optional().default(true)
4337
4337
  });
4338
4338
 
4339
4339
  //#endregion
@@ -6296,6 +6296,7 @@ var ScreenInstance = class extends node_events.EventEmitter {
6296
6296
  version = 0;
6297
6297
  promptQueue = [];
6298
6298
  activePrompt = null;
6299
+ promptVersion = 0;
6299
6300
  constructor(id, options) {
6300
6301
  super();
6301
6302
  this.id = id;
@@ -6311,6 +6312,12 @@ var ScreenInstance = class extends node_events.EventEmitter {
6311
6312
  getVersion() {
6312
6313
  return this.version;
6313
6314
  }
6315
+ incrementPromptVersion() {
6316
+ this.promptVersion++;
6317
+ }
6318
+ getPromptVersion() {
6319
+ return this.promptVersion;
6320
+ }
6314
6321
  /**
6315
6322
  * Internal: Set the manager reference
6316
6323
  */ _setManager(manager) {
@@ -6494,9 +6501,16 @@ var ScreenInstance = class extends node_events.EventEmitter {
6494
6501
  resolve(getPromptDefaultValue(prompt));
6495
6502
  }
6496
6503
  /**
6497
- * Get the currently active prompt (for rendering)
6504
+ * Get the currently active prompt (for rendering).
6505
+ * Returns a shallow clone to ensure React detects changes when prompt state mutates.
6498
6506
  */ getActivePrompt() {
6499
- return this.activePrompt?.data ?? null;
6507
+ if (!this.activePrompt?.data) return null;
6508
+ const prompt = this.activePrompt.data;
6509
+ if (prompt.type === "multiChoice") return {
6510
+ ...prompt,
6511
+ selectedIndices: new Set(prompt.selectedIndices)
6512
+ };
6513
+ return { ...prompt };
6500
6514
  }
6501
6515
  /**
6502
6516
  * Check if this screen has an active prompt
@@ -6515,6 +6529,7 @@ var ScreenInstance = class extends node_events.EventEmitter {
6515
6529
  const maxIndex = prompt.choices.length - 1;
6516
6530
  prompt.focusedIndex = Math.max(0, Math.min(index, maxIndex));
6517
6531
  } else if (prompt.type === "confirm") prompt.selectedValue = index === 0;
6532
+ this.incrementPromptVersion();
6518
6533
  this.emit("prompt:updated");
6519
6534
  }
6520
6535
  /**
@@ -6542,6 +6557,7 @@ var ScreenInstance = class extends node_events.EventEmitter {
6542
6557
  const prompt = this.activePrompt.data;
6543
6558
  if (prompt.type === "confirm") {
6544
6559
  prompt.selectedValue = true;
6560
+ this.incrementPromptVersion();
6545
6561
  this.emit("prompt:updated");
6546
6562
  }
6547
6563
  }
@@ -6550,6 +6566,7 @@ var ScreenInstance = class extends node_events.EventEmitter {
6550
6566
  const prompt = this.activePrompt.data;
6551
6567
  if (prompt.type === "confirm") {
6552
6568
  prompt.selectedValue = false;
6569
+ this.incrementPromptVersion();
6553
6570
  this.emit("prompt:updated");
6554
6571
  }
6555
6572
  }
@@ -6562,6 +6579,7 @@ var ScreenInstance = class extends node_events.EventEmitter {
6562
6579
  const p = prompt;
6563
6580
  if (p.selectedIndices.has(p.focusedIndex)) p.selectedIndices.delete(p.focusedIndex);
6564
6581
  else if (p.selectedIndices.size < p.maxSelect) p.selectedIndices.add(p.focusedIndex);
6582
+ this.incrementPromptVersion();
6565
6583
  this.emit("prompt:updated");
6566
6584
  }
6567
6585
  }
@@ -6574,6 +6592,7 @@ var ScreenInstance = class extends node_events.EventEmitter {
6574
6592
  if (prompt.type === "choice") {
6575
6593
  if (prompt.choices[prompt.selectedIndex]?.input) {
6576
6594
  prompt.inputMode = true;
6595
+ this.incrementPromptVersion();
6577
6596
  this.emit("prompt:updated");
6578
6597
  return true;
6579
6598
  }
@@ -6587,6 +6606,7 @@ var ScreenInstance = class extends node_events.EventEmitter {
6587
6606
  const prompt = this.activePrompt.data;
6588
6607
  if (prompt.type === "choice" && prompt.inputMode) {
6589
6608
  prompt.inputMode = false;
6609
+ this.incrementPromptVersion();
6590
6610
  this.emit("prompt:updated");
6591
6611
  }
6592
6612
  }
@@ -6606,9 +6626,11 @@ var ScreenInstance = class extends node_events.EventEmitter {
6606
6626
  const prompt = this.activePrompt.data;
6607
6627
  if (prompt.type === "choice" && prompt.inputMode) {
6608
6628
  prompt.inputValue = value;
6629
+ this.incrementPromptVersion();
6609
6630
  this.emit("prompt:updated");
6610
6631
  } else if (prompt.type === "input") {
6611
6632
  prompt.value = value;
6633
+ this.incrementPromptVersion();
6612
6634
  this.emit("prompt:updated");
6613
6635
  }
6614
6636
  }
@@ -6619,9 +6641,11 @@ var ScreenInstance = class extends node_events.EventEmitter {
6619
6641
  const prompt = this.activePrompt.data;
6620
6642
  if (prompt.type === "choice" && prompt.inputMode) {
6621
6643
  prompt.inputValue += char;
6644
+ this.incrementPromptVersion();
6622
6645
  this.emit("prompt:updated");
6623
6646
  } else if (prompt.type === "input") {
6624
6647
  prompt.value += char;
6648
+ this.incrementPromptVersion();
6625
6649
  this.emit("prompt:updated");
6626
6650
  }
6627
6651
  }
@@ -6632,9 +6656,11 @@ var ScreenInstance = class extends node_events.EventEmitter {
6632
6656
  const prompt = this.activePrompt.data;
6633
6657
  if (prompt.type === "choice" && prompt.inputMode) {
6634
6658
  prompt.inputValue = prompt.inputValue.slice(0, -1);
6659
+ this.incrementPromptVersion();
6635
6660
  this.emit("prompt:updated");
6636
6661
  } else if (prompt.type === "input") {
6637
6662
  prompt.value = prompt.value.slice(0, -1);
6663
+ this.incrementPromptVersion();
6638
6664
  this.emit("prompt:updated");
6639
6665
  }
6640
6666
  }
@@ -6680,6 +6706,7 @@ var ScreenInstance = class extends node_events.EventEmitter {
6680
6706
  this.activePrompt = null;
6681
6707
  this.activateNextPrompt();
6682
6708
  this.incrementVersion();
6709
+ this.incrementPromptVersion();
6683
6710
  this.emit("prompt:resolved");
6684
6711
  }
6685
6712
  /**
@@ -6689,6 +6716,7 @@ var ScreenInstance = class extends node_events.EventEmitter {
6689
6716
  this.activePrompt = this.promptQueue.shift();
6690
6717
  this.manager?.onScreenPromptActivated(this);
6691
6718
  this.incrementVersion();
6719
+ this.incrementPromptVersion();
6692
6720
  this.emit("prompt:activated");
6693
6721
  }
6694
6722
  }
@@ -7022,7 +7050,10 @@ var ScreenManagerInstance = class extends (_EventEmitter = node_events.EventEmit
7022
7050
  screen._setPrintFn(printMessagesToStdout);
7023
7051
  this.screens.set(id, screen);
7024
7052
  this.screenOrder.push(id);
7025
- if (!this.activeScreenId && !screen.isHidden()) this.activeScreenId = id;
7053
+ if (!this.activeScreenId && !screen.isHidden()) {
7054
+ this.activeScreenId = id;
7055
+ this.emit("activeScreen:changed", id);
7056
+ }
7026
7057
  this.checkAutoClose();
7027
7058
  this.emit("screen:added", id);
7028
7059
  return screen;
@@ -7057,6 +7088,7 @@ var ScreenManagerInstance = class extends (_EventEmitter = node_events.EventEmit
7057
7088
  * Non-blocking bind - starts TUI rendering in background
7058
7089
  */ async bind(options) {
7059
7090
  if (this.mode !== RenderMode.UNBOUND) return;
7091
+ if (!process.stdout.isTTY) return;
7060
7092
  this.bindOptions = options ?? {};
7061
7093
  if (options?.theme) this.theme = typeof options.theme === "string" ? getThemePreset(options.theme) : options.theme;
7062
7094
  if (!(options?.useOpenTUI ?? isBunRuntime())) {
@@ -7139,13 +7171,13 @@ var ScreenManagerInstance = class extends (_EventEmitter = node_events.EventEmit
7139
7171
  */ getGlobalLogLevels() {
7140
7172
  return this.globalLogLevels ? Array.from(this.globalLogLevels) : null;
7141
7173
  }
7142
- onServiceDestroy() {
7143
- this.unbind();
7174
+ async onServiceDestroy() {
7175
+ await this.unbind();
7144
7176
  }
7145
7177
  /**
7146
7178
  * Stop TUI rendering and cleanup
7147
7179
  * Flushes screens to stdout/stderr based on mode
7148
- */ unbind() {
7180
+ */ async unbind() {
7149
7181
  if (this.mode === RenderMode.UNBOUND) {
7150
7182
  this.flushRemainingScreens();
7151
7183
  return;
@@ -7156,7 +7188,7 @@ var ScreenManagerInstance = class extends (_EventEmitter = node_events.EventEmit
7156
7188
  this.autoCloseTimer = null;
7157
7189
  }
7158
7190
  if (previousMode === RenderMode.TUI_ACTIVE) {
7159
- if (this.root) this.root.unmount();
7191
+ if (this.root) await this.root.unmount();
7160
7192
  if (this.renderer) {
7161
7193
  if ("disableMouse" in this.renderer) this.renderer.disableMouse();
7162
7194
  this.renderer.destroy();
@@ -7666,10 +7698,7 @@ var ScreenLoggerInstance = class {
7666
7698
  ({c: [_ScreenLoggerInstance, _initClass$1]} = _apply_decs_2203_r$1(this, [], [_dec$1]));
7667
7699
  }
7668
7700
  constructor(options) {
7669
- this.screen = (0, _navios_core.inject)(Screen, typeof options.screen === "string" ? {
7670
- name: options.screen,
7671
- static: true
7672
- } : options.screen);
7701
+ this.screen = (0, _navios_core.inject)(Screen, typeof options.screen === "string" ? { name: options.screen } : options.screen);
7673
7702
  this.context = options.context;
7674
7703
  this.enabledLevels = new Set(options.enabledLevels);
7675
7704
  }
@@ -8293,132 +8322,6 @@ var PromptInstance = class {
8293
8322
  }
8294
8323
  };
8295
8324
 
8296
- //#endregion
8297
- //#region src/keyboard/keyboard_manager.ts
8298
- /**
8299
- * Manages keyboard bindings and dispatches key events to handlers.
8300
- */ var KeyboardManager = class {
8301
- bindings = [];
8302
- disabled = /* @__PURE__ */ new Set();
8303
- constructor(config$1) {
8304
- if (config$1?.bindings) this.bindings = [...config$1.bindings];
8305
- if (config$1?.disabled) this.disabled = new Set(config$1.disabled);
8306
- this.sortBindings();
8307
- }
8308
- /**
8309
- * Add bindings to the manager.
8310
- */ addBindings(bindings) {
8311
- this.bindings.push(...bindings);
8312
- this.sortBindings();
8313
- }
8314
- /**
8315
- * Remove a binding by key name.
8316
- */ removeBinding(key) {
8317
- this.bindings = this.bindings.filter((b) => {
8318
- return !(Array.isArray(b.key) ? b.key : [b.key]).includes(key);
8319
- });
8320
- }
8321
- /**
8322
- * Disable a key (prevents it from being matched).
8323
- */ disableKey(key) {
8324
- this.disabled.add(key);
8325
- }
8326
- /**
8327
- * Enable a previously disabled key.
8328
- */ enableKey(key) {
8329
- this.disabled.delete(key);
8330
- }
8331
- /**
8332
- * Handle a key event, dispatching to the appropriate handler.
8333
- * Returns true if a handler consumed the event.
8334
- */ handleKey(key, context) {
8335
- const binding = this.findMatchingBinding(key, context);
8336
- if (binding) return binding.handler(key, context) !== false;
8337
- return false;
8338
- }
8339
- /**
8340
- * Get all bindings for display in help overlay.
8341
- */ getBindingsForHelp() {
8342
- return this.bindings.filter((b) => b.description);
8343
- }
8344
- /**
8345
- * Get bindings grouped by category.
8346
- */ getBindingsByCategory() {
8347
- const grouped = {
8348
- general: [],
8349
- navigation: [],
8350
- screen: [],
8351
- prompt: [],
8352
- filter: []
8353
- };
8354
- for (const binding of this.bindings) if (binding.description) grouped[binding.category].push(binding);
8355
- return grouped;
8356
- }
8357
- /**
8358
- * Find a matching binding for the given key and context.
8359
- */ findMatchingBinding(key, context) {
8360
- for (const binding of this.bindings) if (this.keyMatches(key, binding) && this.conditionMatches(binding.when, context) && !this.isDisabled(binding)) return binding;
8361
- return null;
8362
- }
8363
- /**
8364
- * Check if a key event matches a binding's key specification.
8365
- */ keyMatches(key, binding) {
8366
- const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
8367
- if (!(keys.includes(key.name) || key.sequence && keys.includes(key.sequence))) return false;
8368
- const ctrlMatches = (binding.ctrl ?? false) === (key.ctrl ?? false);
8369
- const metaMatches = (binding.meta ?? false) === (key.meta ?? false);
8370
- const shiftMatches = (binding.shift ?? false) === (key.shift ?? false);
8371
- return ctrlMatches && metaMatches && shiftMatches;
8372
- }
8373
- /**
8374
- * Check if context matches a binding's condition.
8375
- */ conditionMatches(condition, context) {
8376
- if (!condition) return true;
8377
- if (condition.hasPrompt !== void 0 && condition.hasPrompt !== context.hasPrompt) return false;
8378
- if (condition.inInputMode !== void 0 && condition.inInputMode !== context.inInputMode) return false;
8379
- if (condition.focusArea !== void 0 && condition.focusArea !== context.focusArea) return false;
8380
- if (condition.isFilterActive !== void 0 && condition.isFilterActive !== context.isFilterActive) return false;
8381
- if (condition.isHelpVisible !== void 0 && condition.isHelpVisible !== context.isHelpVisible) return false;
8382
- if (condition.hasSidebar !== void 0 && condition.hasSidebar !== context.hasSidebar) return false;
8383
- return true;
8384
- }
8385
- /**
8386
- * Check if a binding is disabled.
8387
- */ isDisabled(binding) {
8388
- return (Array.isArray(binding.key) ? binding.key : [binding.key]).some((k) => this.disabled.has(k));
8389
- }
8390
- /**
8391
- * Sort bindings by priority (higher first).
8392
- */ sortBindings() {
8393
- this.bindings.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
8394
- }
8395
- };
8396
- /**
8397
- * Format a key binding for display.
8398
- */ function formatKeyBinding(binding) {
8399
- const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
8400
- const parts = [];
8401
- if (binding.ctrl) parts.push("Ctrl");
8402
- if (binding.meta) parts.push("Cmd");
8403
- if (binding.shift) parts.push("Shift");
8404
- const keyDisplay = keys.map((k) => {
8405
- switch (k) {
8406
- case "up": return "↑";
8407
- case "down": return "↓";
8408
- case "left": return "←";
8409
- case "right": return "→";
8410
- case "return": return "Enter";
8411
- case "escape": return "Esc";
8412
- case "space": return "Space";
8413
- case "tab": return "Tab";
8414
- case "\\": return "\\";
8415
- default: return k;
8416
- }
8417
- }).join("/");
8418
- parts.push(keyDisplay);
8419
- return parts.join("+");
8420
- }
8421
-
8422
8325
  //#endregion
8423
8326
  //#region src/keyboard/create_bindings.ts
8424
8327
  /**
@@ -8814,6 +8717,132 @@ var PromptInstance = class {
8814
8717
  return false;
8815
8718
  }
8816
8719
 
8720
+ //#endregion
8721
+ //#region src/keyboard/keyboard_manager.ts
8722
+ /**
8723
+ * Manages keyboard bindings and dispatches key events to handlers.
8724
+ */ var KeyboardManager = class {
8725
+ bindings = [];
8726
+ disabled = /* @__PURE__ */ new Set();
8727
+ constructor(config$1) {
8728
+ if (config$1?.bindings) this.bindings = [...config$1.bindings];
8729
+ if (config$1?.disabled) this.disabled = new Set(config$1.disabled);
8730
+ this.sortBindings();
8731
+ }
8732
+ /**
8733
+ * Add bindings to the manager.
8734
+ */ addBindings(bindings) {
8735
+ this.bindings.push(...bindings);
8736
+ this.sortBindings();
8737
+ }
8738
+ /**
8739
+ * Remove a binding by key name.
8740
+ */ removeBinding(key) {
8741
+ this.bindings = this.bindings.filter((b) => {
8742
+ return !(Array.isArray(b.key) ? b.key : [b.key]).includes(key);
8743
+ });
8744
+ }
8745
+ /**
8746
+ * Disable a key (prevents it from being matched).
8747
+ */ disableKey(key) {
8748
+ this.disabled.add(key);
8749
+ }
8750
+ /**
8751
+ * Enable a previously disabled key.
8752
+ */ enableKey(key) {
8753
+ this.disabled.delete(key);
8754
+ }
8755
+ /**
8756
+ * Handle a key event, dispatching to the appropriate handler.
8757
+ * Returns true if a handler consumed the event.
8758
+ */ handleKey(key, context) {
8759
+ const binding = this.findMatchingBinding(key, context);
8760
+ if (binding) return binding.handler(key, context) !== false;
8761
+ return false;
8762
+ }
8763
+ /**
8764
+ * Get all bindings for display in help overlay.
8765
+ */ getBindingsForHelp() {
8766
+ return this.bindings.filter((b) => b.description);
8767
+ }
8768
+ /**
8769
+ * Get bindings grouped by category.
8770
+ */ getBindingsByCategory() {
8771
+ const grouped = {
8772
+ general: [],
8773
+ navigation: [],
8774
+ screen: [],
8775
+ prompt: [],
8776
+ filter: []
8777
+ };
8778
+ for (const binding of this.bindings) if (binding.description) grouped[binding.category].push(binding);
8779
+ return grouped;
8780
+ }
8781
+ /**
8782
+ * Find a matching binding for the given key and context.
8783
+ */ findMatchingBinding(key, context) {
8784
+ for (const binding of this.bindings) if (this.keyMatches(key, binding) && this.conditionMatches(binding.when, context) && !this.isDisabled(binding)) return binding;
8785
+ return null;
8786
+ }
8787
+ /**
8788
+ * Check if a key event matches a binding's key specification.
8789
+ */ keyMatches(key, binding) {
8790
+ const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
8791
+ if (!(keys.includes(key.name) || key.sequence && keys.includes(key.sequence))) return false;
8792
+ const ctrlMatches = (binding.ctrl ?? false) === (key.ctrl ?? false);
8793
+ const metaMatches = (binding.meta ?? false) === (key.meta ?? false);
8794
+ const shiftMatches = (binding.shift ?? false) === (key.shift ?? false);
8795
+ return ctrlMatches && metaMatches && shiftMatches;
8796
+ }
8797
+ /**
8798
+ * Check if context matches a binding's condition.
8799
+ */ conditionMatches(condition, context) {
8800
+ if (!condition) return true;
8801
+ if (condition.hasPrompt !== void 0 && condition.hasPrompt !== context.hasPrompt) return false;
8802
+ if (condition.inInputMode !== void 0 && condition.inInputMode !== context.inInputMode) return false;
8803
+ if (condition.focusArea !== void 0 && condition.focusArea !== context.focusArea) return false;
8804
+ if (condition.isFilterActive !== void 0 && condition.isFilterActive !== context.isFilterActive) return false;
8805
+ if (condition.isHelpVisible !== void 0 && condition.isHelpVisible !== context.isHelpVisible) return false;
8806
+ if (condition.hasSidebar !== void 0 && condition.hasSidebar !== context.hasSidebar) return false;
8807
+ return true;
8808
+ }
8809
+ /**
8810
+ * Check if a binding is disabled.
8811
+ */ isDisabled(binding) {
8812
+ return (Array.isArray(binding.key) ? binding.key : [binding.key]).some((k) => this.disabled.has(k));
8813
+ }
8814
+ /**
8815
+ * Sort bindings by priority (higher first).
8816
+ */ sortBindings() {
8817
+ this.bindings.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
8818
+ }
8819
+ };
8820
+ /**
8821
+ * Format a key binding for display.
8822
+ */ function formatKeyBinding(binding) {
8823
+ const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
8824
+ const parts = [];
8825
+ if (binding.ctrl) parts.push("Ctrl");
8826
+ if (binding.meta) parts.push("Cmd");
8827
+ if (binding.shift) parts.push("Shift");
8828
+ const keyDisplay = keys.map((k) => {
8829
+ switch (k) {
8830
+ case "up": return "↑";
8831
+ case "down": return "↓";
8832
+ case "left": return "←";
8833
+ case "right": return "→";
8834
+ case "return": return "Enter";
8835
+ case "escape": return "Esc";
8836
+ case "space": return "Space";
8837
+ case "tab": return "Tab";
8838
+ case "\\": return "\\";
8839
+ default: return k;
8840
+ }
8841
+ }).join("/");
8842
+ parts.push(keyDisplay);
8843
+ return parts.join("+");
8844
+ }
8845
+
8817
8846
  //#endregion
8818
8847
  //#region src/filter/filter_engine.ts
8819
8848
  /**