@gajae-code/tui 0.6.4 → 0.7.0

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.
@@ -35,6 +35,7 @@ export interface Keybindings {
35
35
  "tui.select.pageDown": true;
36
36
  "tui.select.confirm": true;
37
37
  "tui.select.cancel": true;
38
+ "tui.global.debug": true;
38
39
  }
39
40
  export type Keybinding = keyof Keybindings;
40
41
  export type { KeyId };
@@ -169,6 +170,10 @@ export declare const TUI_KEYBINDINGS: {
169
170
  readonly defaultKeys: ["escape", "ctrl+c"];
170
171
  readonly description: "Cancel selection";
171
172
  };
173
+ readonly "tui.global.debug": {
174
+ readonly defaultKeys: "shift+ctrl+d";
175
+ readonly description: "Toggle debug overlay";
176
+ };
172
177
  };
173
178
  export interface KeybindingConflict {
174
179
  key: KeyId;
@@ -185,5 +190,12 @@ export declare class KeybindingsManager {
185
190
  getUserBindings(): KeybindingsConfig;
186
191
  getResolvedBindings(): KeybindingsConfig;
187
192
  }
193
+ /**
194
+ * Detect default-key collisions across the registry: keys whose default
195
+ * binding is claimed by more than one action. Cross-context collisions are
196
+ * often intentional (the dispatch context disambiguates them), so this is a
197
+ * diagnostics aid for auditing the surface, not an error by itself.
198
+ */
199
+ export declare function detectDefaultKeyCollisions(definitions: KeybindingDefinitions): KeybindingConflict[];
188
200
  export declare function setKeybindings(keybindings: KeybindingsManager): void;
189
201
  export declare function getKeybindings(): KeybindingsManager;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@gajae-code/tui",
4
- "version": "0.6.4",
4
+ "version": "0.7.0",
5
5
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
6
  "homepage": "https://gaebal-gajae.dev",
7
7
  "author": "Yeachan-Heo",
@@ -38,8 +38,8 @@
38
38
  "fmt": "biome format --write ."
39
39
  },
40
40
  "dependencies": {
41
- "@gajae-code/natives": "0.6.4",
42
- "@gajae-code/utils": "0.6.4",
41
+ "@gajae-code/natives": "0.7.0",
42
+ "@gajae-code/utils": "0.7.0",
43
43
  "lru-cache": "11.3.6",
44
44
  "marked": "^18.0.3"
45
45
  },
@@ -1250,7 +1250,7 @@ export class Editor implements Component, Focusable {
1250
1250
  data === "\x1b[13;2~" || // Shift+Enter in some terminals (legacy format)
1251
1251
  kb.matches(data, "tui.input.newLine") || // Shift+Enter (Kitty protocol, handles lock bits)
1252
1252
  (data.length > 1 && data.includes("\x1b") && data.includes("\r")) ||
1253
- (data === "\n" && data.length === 1 && process.platform !== "win32") // Shift+Enter from iTerm2 mapping
1253
+ (data === "\n" && data.length === 1) // Shift+Enter from terminal sendInput mapping
1254
1254
  ) {
1255
1255
  if (this.#shouldSubmitOnBackslashEnter(data, kb)) {
1256
1256
  this.#handleBackspace();
@@ -39,6 +39,8 @@ export interface Keybindings {
39
39
  "tui.select.pageDown": true;
40
40
  "tui.select.confirm": true;
41
41
  "tui.select.cancel": true;
42
+ // Global engine actions
43
+ "tui.global.debug": true;
42
44
  }
43
45
 
44
46
  export type Keybinding = keyof Keybindings;
@@ -134,6 +136,10 @@ export const TUI_KEYBINDINGS = {
134
136
  defaultKeys: ["escape", "ctrl+c"],
135
137
  description: "Cancel selection",
136
138
  },
139
+ "tui.global.debug": {
140
+ defaultKeys: "shift+ctrl+d",
141
+ description: "Toggle debug overlay",
142
+ },
137
143
  } as const satisfies KeybindingDefinitions;
138
144
 
139
145
  export interface KeybindingConflict {
@@ -265,6 +271,30 @@ export class KeybindingsManager {
265
271
  }
266
272
  }
267
273
 
274
+ /**
275
+ * Detect default-key collisions across the registry: keys whose default
276
+ * binding is claimed by more than one action. Cross-context collisions are
277
+ * often intentional (the dispatch context disambiguates them), so this is a
278
+ * diagnostics aid for auditing the surface, not an error by itself.
279
+ */
280
+ export function detectDefaultKeyCollisions(definitions: KeybindingDefinitions): KeybindingConflict[] {
281
+ const claims = new Map<KeyId, Set<Keybinding>>();
282
+ for (const [id, definition] of Object.entries(definitions)) {
283
+ for (const key of normalizeKeys(definition.defaultKeys)) {
284
+ const claimants = claims.get(key) ?? new Set<Keybinding>();
285
+ claimants.add(id as Keybinding);
286
+ claims.set(key, claimants);
287
+ }
288
+ }
289
+ const collisions: KeybindingConflict[] = [];
290
+ for (const [key, keybindings] of claims) {
291
+ if (keybindings.size > 1) {
292
+ collisions.push({ key, keybindings: [...keybindings] });
293
+ }
294
+ }
295
+ return collisions;
296
+ }
297
+
268
298
  let globalKeybindings: KeybindingsManager | null = null;
269
299
 
270
300
  export function setKeybindings(keybindings: KeybindingsManager): void {
package/src/tui.ts CHANGED
@@ -5,7 +5,8 @@ import * as fs from "node:fs";
5
5
  import * as path from "node:path";
6
6
  import { performance } from "node:perf_hooks";
7
7
  import { $flag, getDebugLogPath } from "@gajae-code/utils";
8
- import { isKeyRelease, matchesKey } from "./keys";
8
+ import { getKeybindings } from "./keybindings";
9
+ import { isKeyRelease } from "./keys";
9
10
  import { renderMetrics } from "./metrics";
10
11
  import type { Terminal } from "./terminal";
11
12
  import { ImageProtocol, setCellDimensions, setTerminalImageProtocol, TERMINAL } from "./terminal-capabilities";
@@ -842,8 +843,8 @@ export class TUI extends Container {
842
843
  return;
843
844
  }
844
845
 
845
- // Global debug key handler (Shift+Ctrl+D)
846
- if (matchesKey(data, "shift+ctrl+d") && this.onDebug) {
846
+ // Global debug key handler (registry: tui.global.debug, default Shift+Ctrl+D)
847
+ if (getKeybindings().matches(data, "tui.global.debug") && this.onDebug) {
847
848
  this.onDebug();
848
849
  return;
849
850
  }