@xynogen/pix-toolbox 0.1.8 → 0.1.10
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/package.json +1 -1
- package/src/toolbox.ts +52 -14
package/package.json
CHANGED
package/src/toolbox.ts
CHANGED
|
@@ -34,7 +34,13 @@ import {
|
|
|
34
34
|
type TUI,
|
|
35
35
|
visibleWidth,
|
|
36
36
|
} from "@earendil-works/pi-tui";
|
|
37
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
frameModal,
|
|
39
|
+
MIN_MODAL_HEIGHT,
|
|
40
|
+
ModalPager,
|
|
41
|
+
modalWidth,
|
|
42
|
+
terminalModalHeight,
|
|
43
|
+
} from "@xynogen/pix-pretty/modal-frame";
|
|
38
44
|
|
|
39
45
|
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
40
46
|
|
|
@@ -334,9 +340,12 @@ export default function registerToolbox(pi: ExtensionAPI): void {
|
|
|
334
340
|
};
|
|
335
341
|
}): Promise<void> {
|
|
336
342
|
await ctx.ui.custom<null>(
|
|
337
|
-
(tui: TUI, theme: Theme,
|
|
343
|
+
(tui: TUI, theme: Theme, keybindings: KeybindingsManager, done: (r: null) => void) => {
|
|
338
344
|
const accent = "accent";
|
|
339
345
|
const mute = (s: string) => theme.fg("muted", s);
|
|
346
|
+
const guide = (key: string, action: string) =>
|
|
347
|
+
theme.fg("text", key) + theme.fg("dim", ` ${action}`);
|
|
348
|
+
const guideSep = theme.fg("dim", " · ");
|
|
340
349
|
|
|
341
350
|
type RowState = "active" | "gated";
|
|
342
351
|
const stateOf = (name: string): RowState => (ops.isActive(name) ? "active" : "gated");
|
|
@@ -371,7 +380,7 @@ export default function registerToolbox(pi: ExtensionAPI): void {
|
|
|
371
380
|
|
|
372
381
|
const list = new SelectList(
|
|
373
382
|
allItems,
|
|
374
|
-
Math.
|
|
383
|
+
Math.max(1, allItems.length),
|
|
375
384
|
{
|
|
376
385
|
selectedPrefix: (t: string) => theme.fg(accent, t),
|
|
377
386
|
selectedText: (t: string) => theme.fg(accent, t),
|
|
@@ -393,6 +402,7 @@ export default function registerToolbox(pi: ExtensionAPI): void {
|
|
|
393
402
|
|
|
394
403
|
const search = new Input();
|
|
395
404
|
let statusText = "";
|
|
405
|
+
const pager = new ModalPager();
|
|
396
406
|
|
|
397
407
|
const refreshLabels = () => {
|
|
398
408
|
for (const it of internal.items) {
|
|
@@ -442,30 +452,56 @@ export default function registerToolbox(pi: ExtensionAPI): void {
|
|
|
442
452
|
render(w: number) {
|
|
443
453
|
const mw = modalWidth(w);
|
|
444
454
|
const inner = mw - 4; // CHROME = 2 border + 2 padding
|
|
445
|
-
const
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
455
|
+
const footer = statusText ? ["", statusText] : [""];
|
|
456
|
+
footer.push(
|
|
457
|
+
guide("↑↓", "navigate") +
|
|
458
|
+
guideSep +
|
|
459
|
+
guide("←→/PgUp/PgDn", "inspect") +
|
|
460
|
+
guideSep +
|
|
461
|
+
guide("e", "enable") +
|
|
462
|
+
guideSep +
|
|
463
|
+
guide("d", "disable") +
|
|
464
|
+
guideSep +
|
|
465
|
+
guide("space", "toggle") +
|
|
466
|
+
guideSep +
|
|
467
|
+
guide("esc", "close"),
|
|
454
468
|
);
|
|
455
|
-
|
|
469
|
+
const result = frameModal({
|
|
456
470
|
width: mw,
|
|
457
|
-
|
|
471
|
+
maxHeight: terminalModalHeight(tui.terminal.rows),
|
|
472
|
+
minHeight: MIN_MODAL_HEIGHT,
|
|
473
|
+
header: [
|
|
474
|
+
theme.fg(accent, theme.bold("🧰 Toolbox")),
|
|
475
|
+
theme.fg("muted", "Search:"),
|
|
476
|
+
...search.render(inner),
|
|
477
|
+
"",
|
|
478
|
+
],
|
|
479
|
+
body: list.render(inner),
|
|
480
|
+
selectedBodyRange: pager.selectedRange({
|
|
481
|
+
start: internal.selectedIndex,
|
|
482
|
+
end: internal.selectedIndex + 1,
|
|
483
|
+
}),
|
|
484
|
+
footer,
|
|
485
|
+
bodyOffset: pager.bodyOffset,
|
|
458
486
|
color: (s) => theme.fg(accent, s),
|
|
459
487
|
bg: (s) => theme.bg("customMessageBg", s),
|
|
488
|
+
fg: (s) => theme.fg("text", s),
|
|
460
489
|
});
|
|
490
|
+
pager.sync(result);
|
|
491
|
+
return result.lines;
|
|
461
492
|
},
|
|
462
493
|
invalidate() {
|
|
463
494
|
list.invalidate();
|
|
464
495
|
search.invalidate();
|
|
465
496
|
},
|
|
466
497
|
handleInput(data: string) {
|
|
498
|
+
if (pager.handleInput(data, keybindings, true)) {
|
|
499
|
+
tui.requestRender?.();
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
467
502
|
if (matchesKey(data, Key.up) || matchesKey(data, Key.down)) {
|
|
468
503
|
list.handleInput?.(data);
|
|
504
|
+
pager.followSelection();
|
|
469
505
|
} else if (matchesKey(data, Key.enter) || matchesKey(data, Key.escape)) {
|
|
470
506
|
done(null);
|
|
471
507
|
return;
|
|
@@ -481,10 +517,12 @@ export default function registerToolbox(pi: ExtensionAPI): void {
|
|
|
481
517
|
} else {
|
|
482
518
|
search.handleInput?.(data);
|
|
483
519
|
applyFilter(search.getValue?.() ?? "");
|
|
520
|
+
pager.followSelection();
|
|
484
521
|
}
|
|
485
522
|
} else {
|
|
486
523
|
search.handleInput?.(data);
|
|
487
524
|
applyFilter(search.getValue?.() ?? "");
|
|
525
|
+
pager.followSelection();
|
|
488
526
|
}
|
|
489
527
|
}
|
|
490
528
|
list.invalidate();
|