giggles 0.5.1 → 0.6.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.
|
@@ -48,7 +48,6 @@ function useKeybindingRegistry(focus) {
|
|
|
48
48
|
return trapIndex >= 0 ? new Set(branchPath.slice(0, trapIndex + 1)) : null;
|
|
49
49
|
})();
|
|
50
50
|
const available = all.filter((b) => {
|
|
51
|
-
if (b.when === "mounted") return withinTrapSet ? withinTrapSet.has(b.nodeId) : true;
|
|
52
51
|
return (withinTrapSet ?? branchSet).has(b.nodeId);
|
|
53
52
|
});
|
|
54
53
|
const local = focus ? all.filter((b) => b.nodeId === focus.id) : [];
|
|
@@ -397,14 +396,12 @@ var FocusStore = class {
|
|
|
397
396
|
if (typeof def === "function") {
|
|
398
397
|
return [key, { handler: def }];
|
|
399
398
|
}
|
|
400
|
-
return [key, { handler: def.action, name: def.name
|
|
399
|
+
return [key, { handler: def.action, name: def.name }];
|
|
401
400
|
});
|
|
402
401
|
const registration = {
|
|
403
402
|
bindings: new Map(entries),
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
passthrough: (options == null ? void 0 : options.passthrough) ? new Set(options.passthrough) : void 0,
|
|
407
|
-
layer: options == null ? void 0 : options.layer
|
|
403
|
+
fallback: options == null ? void 0 : options.fallback,
|
|
404
|
+
bubble: (options == null ? void 0 : options.bubble) ? new Set(options.bubble) : void 0
|
|
408
405
|
};
|
|
409
406
|
if (!this.keybindings.has(nodeId)) {
|
|
410
407
|
this.keybindings.set(nodeId, /* @__PURE__ */ new Map());
|
|
@@ -424,33 +421,21 @@ var FocusStore = class {
|
|
|
424
421
|
const nodeRegistrations = this.keybindings.get(nodeId);
|
|
425
422
|
if (!nodeRegistrations || nodeRegistrations.size === 0) return void 0;
|
|
426
423
|
const mergedBindings = /* @__PURE__ */ new Map();
|
|
427
|
-
let
|
|
428
|
-
let
|
|
429
|
-
let finalPassthrough;
|
|
430
|
-
let finalLayer;
|
|
424
|
+
let finalFallback;
|
|
425
|
+
let finalBubble;
|
|
431
426
|
for (const registration of nodeRegistrations.values()) {
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
if (shouldIncludeBindings) {
|
|
435
|
-
for (const [key, entry] of registration.bindings) {
|
|
436
|
-
mergedBindings.set(key, entry);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
if (registration.capture) {
|
|
440
|
-
finalCapture = true;
|
|
441
|
-
finalOnKeypress = registration.onKeypress;
|
|
442
|
-
finalPassthrough = registration.passthrough;
|
|
427
|
+
for (const [key, entry] of registration.bindings) {
|
|
428
|
+
mergedBindings.set(key, entry);
|
|
443
429
|
}
|
|
444
|
-
if (registration.
|
|
445
|
-
|
|
430
|
+
if (registration.fallback) {
|
|
431
|
+
finalFallback = registration.fallback;
|
|
432
|
+
finalBubble = registration.bubble;
|
|
446
433
|
}
|
|
447
434
|
}
|
|
448
435
|
return {
|
|
449
436
|
bindings: mergedBindings,
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
passthrough: finalPassthrough,
|
|
453
|
-
layer: finalLayer
|
|
437
|
+
fallback: finalFallback,
|
|
438
|
+
bubble: finalBubble
|
|
454
439
|
};
|
|
455
440
|
}
|
|
456
441
|
getAllBindings() {
|
|
@@ -462,9 +447,7 @@ var FocusStore = class {
|
|
|
462
447
|
nodeId,
|
|
463
448
|
key,
|
|
464
449
|
handler: entry.handler,
|
|
465
|
-
name: entry.name
|
|
466
|
-
when: entry.when,
|
|
467
|
-
layer: registration.layer
|
|
450
|
+
name: entry.name
|
|
468
451
|
});
|
|
469
452
|
}
|
|
470
453
|
}
|
|
@@ -475,39 +458,42 @@ var FocusStore = class {
|
|
|
475
458
|
// Input dispatch
|
|
476
459
|
// ---------------------------------------------------------------------------
|
|
477
460
|
// Bridge target for InputRouter. Walks the active branch path with passive-scope
|
|
478
|
-
// skipping,
|
|
461
|
+
// skipping, fallback handlers, and trap boundary — the full dispatch algorithm.
|
|
462
|
+
//
|
|
463
|
+
// Priority order (per node, walking focused → root):
|
|
464
|
+
// 1. Named bindings — always checked first
|
|
465
|
+
// 2. Fallback handler — deferred until after the full path walk, so named
|
|
466
|
+
// bindings at any ancestor still fire before the fallback kicks in.
|
|
467
|
+
// Keys in `bubble` skip the fallback and continue to the next ancestor.
|
|
468
|
+
// 3. Trap boundary — stops the walk; fallback inside the trap still fires.
|
|
479
469
|
dispatch(input, key) {
|
|
480
470
|
var _a;
|
|
481
471
|
const keyName = normalizeKey(input, key);
|
|
482
472
|
if (!keyName) return;
|
|
483
473
|
const path = this.getActiveBranchPath();
|
|
484
474
|
const trapNodeId = this.trapNodeId;
|
|
475
|
+
let pendingFallback;
|
|
485
476
|
for (const nodeId of path) {
|
|
486
477
|
if (this.passiveSet.has(nodeId)) continue;
|
|
487
478
|
const nodeBindings = this.getNodeBindings(nodeId);
|
|
488
479
|
if (nodeBindings) {
|
|
489
|
-
if (nodeBindings.capture && nodeBindings.onKeypress) {
|
|
490
|
-
if (!((_a = nodeBindings.passthrough) == null ? void 0 : _a.has(keyName))) {
|
|
491
|
-
nodeBindings.onKeypress(input, key);
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
480
|
const entry = nodeBindings.bindings.get(keyName);
|
|
496
|
-
if (entry
|
|
481
|
+
if (entry) {
|
|
497
482
|
entry.handler(input, key);
|
|
498
483
|
return;
|
|
499
484
|
}
|
|
485
|
+
if (!pendingFallback && nodeBindings.fallback) {
|
|
486
|
+
if ((_a = nodeBindings.bubble) == null ? void 0 : _a.has(keyName)) {
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
pendingFallback = nodeBindings.fallback;
|
|
490
|
+
}
|
|
500
491
|
}
|
|
501
492
|
if (nodeId === trapNodeId) {
|
|
502
|
-
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
for (const binding of this.getAllBindings()) {
|
|
506
|
-
if (binding.key === keyName && binding.when === "mounted") {
|
|
507
|
-
binding.handler(input, key);
|
|
508
|
-
return;
|
|
493
|
+
break;
|
|
509
494
|
}
|
|
510
495
|
}
|
|
496
|
+
pendingFallback == null ? void 0 : pendingFallback(input, key);
|
|
511
497
|
}
|
|
512
498
|
// ---------------------------------------------------------------------------
|
|
513
499
|
// Private helpers
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { BoxProps } from 'ink';
|
|
4
4
|
export { Key } from 'ink';
|
|
5
|
-
import { K as Keybindings, a as KeybindingOptions, R as RegisteredKeybinding } from './types-
|
|
6
|
-
export { b as KeyHandler } from './types-
|
|
5
|
+
import { K as Keybindings, a as KeybindingOptions, R as RegisteredKeybinding } from './types-HR6Vak_5.js';
|
|
6
|
+
export { b as KeyHandler } from './types-HR6Vak_5.js';
|
|
7
7
|
|
|
8
8
|
declare class GigglesError extends Error {
|
|
9
9
|
constructor(message: string);
|
package/dist/index.js
CHANGED
|
@@ -6,22 +6,17 @@ type KeyName = SpecialKey | (string & {});
|
|
|
6
6
|
type KeybindingDefinition = KeyHandler | {
|
|
7
7
|
action: KeyHandler;
|
|
8
8
|
name: string;
|
|
9
|
-
when?: 'focused' | 'mounted';
|
|
10
9
|
};
|
|
11
10
|
type Keybindings = Partial<Record<KeyName, KeybindingDefinition>>;
|
|
12
11
|
type KeybindingOptions = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
passthrough?: string[];
|
|
16
|
-
layer?: string;
|
|
12
|
+
fallback?: (input: string, key: Key) => void;
|
|
13
|
+
bubble?: string[];
|
|
17
14
|
};
|
|
18
15
|
type RegisteredKeybinding = {
|
|
19
16
|
nodeId: string;
|
|
20
17
|
key: string;
|
|
21
18
|
handler: KeyHandler;
|
|
22
19
|
name?: string;
|
|
23
|
-
when?: 'focused' | 'mounted';
|
|
24
|
-
layer?: string;
|
|
25
20
|
};
|
|
26
21
|
|
|
27
22
|
export type { Keybindings as K, RegisteredKeybinding as R, KeybindingOptions as a, KeyHandler as b };
|
package/dist/ui/index.d.ts
CHANGED
package/dist/ui/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
useFocusNode,
|
|
5
5
|
useKeybindingRegistry,
|
|
6
6
|
useKeybindings
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-QV7GQTKO.js";
|
|
8
8
|
import {
|
|
9
9
|
CodeBlock
|
|
10
10
|
} from "../chunk-SKSDNDQF.js";
|
|
@@ -77,9 +77,7 @@ function Inner({ onClose, render }) {
|
|
|
77
77
|
}
|
|
78
78
|
},
|
|
79
79
|
{
|
|
80
|
-
|
|
81
|
-
passthrough: ["escape", "enter", "left", "right", "backspace"],
|
|
82
|
-
onKeypress: (input, key) => {
|
|
80
|
+
fallback: (input, key) => {
|
|
83
81
|
if (input.length === 1 && !key.ctrl) {
|
|
84
82
|
setQuery((q) => q + input);
|
|
85
83
|
setSelectedIndex(0);
|
|
@@ -179,15 +177,14 @@ function TextInput({ label, value, onChange, onSubmit, placeholder, render }) {
|
|
|
179
177
|
...onSubmit && { enter: () => onSubmit(value) }
|
|
180
178
|
},
|
|
181
179
|
{
|
|
182
|
-
|
|
183
|
-
passthrough: ["tab", "shift+tab", "enter", "escape", "backspace", "delete", "left", "right", "home", "end"],
|
|
184
|
-
onKeypress: (input, key) => {
|
|
180
|
+
fallback: (input, key) => {
|
|
185
181
|
if (input.length === 1 && !key.ctrl && !key.return && !key.escape && !key.tab) {
|
|
186
182
|
const c = cursorRef.current;
|
|
187
183
|
cursorRef.current = c + 1;
|
|
188
184
|
onChange(value.slice(0, c) + input + value.slice(c));
|
|
189
185
|
}
|
|
190
|
-
}
|
|
186
|
+
},
|
|
187
|
+
bubble: ["tab", "shift+tab", "enter", "escape", "backspace", "delete", "left", "right", "home", "end"]
|
|
191
188
|
}
|
|
192
189
|
);
|
|
193
190
|
const before = value.slice(0, cursor);
|
|
@@ -643,28 +640,14 @@ function Autocomplete({
|
|
|
643
640
|
}
|
|
644
641
|
},
|
|
645
642
|
{
|
|
646
|
-
|
|
647
|
-
passthrough: [
|
|
648
|
-
"tab",
|
|
649
|
-
"shift+tab",
|
|
650
|
-
"escape",
|
|
651
|
-
"backspace",
|
|
652
|
-
"delete",
|
|
653
|
-
"left",
|
|
654
|
-
"right",
|
|
655
|
-
"home",
|
|
656
|
-
"end",
|
|
657
|
-
"up",
|
|
658
|
-
"down",
|
|
659
|
-
"enter"
|
|
660
|
-
],
|
|
661
|
-
onKeypress: (input, key) => {
|
|
643
|
+
fallback: (input, key) => {
|
|
662
644
|
if (input.length === 1 && !key.ctrl && !key.return && !key.escape && !key.tab) {
|
|
663
645
|
const c = cursorRef.current;
|
|
664
646
|
cursorRef.current = c + 1;
|
|
665
647
|
updateQuery(query.slice(0, c) + input + query.slice(c));
|
|
666
648
|
}
|
|
667
|
-
}
|
|
649
|
+
},
|
|
650
|
+
bubble: ["tab", "shift+tab", "escape"]
|
|
668
651
|
}
|
|
669
652
|
);
|
|
670
653
|
const before = query.slice(0, cursor);
|