@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/.turbo/turbo-build.log +13 -13
- package/.turbo/turbo-lint.log +7 -7
- package/.turbo/turbo-test$colon$ci.log +6 -6
- package/.turbo/turbo-test.log +33 -0
- package/CHANGELOG.md +16 -0
- package/dist/base/src/adapters/interface.d.ts +2 -1
- package/dist/base/src/adapters/interface.d.ts.map +1 -1
- package/dist/base/src/keyboard/index.d.ts +1 -1
- package/dist/base/src/keyboard/index.d.ts.map +1 -1
- package/dist/base/src/services/logger.d.ts.map +1 -1
- package/dist/base/src/services/screen.d.ts +5 -1
- package/dist/base/src/services/screen.d.ts.map +1 -1
- package/dist/base/src/services/screen_manager.d.ts +2 -2
- package/dist/base/src/services/screen_manager.d.ts.map +1 -1
- package/dist/base/tsconfig.tsbuildinfo +1 -1
- package/lib/index.cjs +167 -138
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +74 -69
- package/lib/index.d.cts.map +1 -1
- package/lib/index.d.mts +74 -69
- package/lib/index.d.mts.map +1 -1
- package/lib/index.mjs +167 -138
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/adapters/interface.ts +2 -1
- package/src/keyboard/index.ts +1 -1
- package/src/schemas/screen-options.ts +1 -1
- package/src/services/logger.ts +0 -1
- package/src/services/screen.ts +37 -2
- package/src/services/screen_manager.ts +13 -5
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(
|
|
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
|
-
|
|
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())
|
|
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
|
/**
|