@xynogen/pix-toolbox 0.1.1 → 0.1.3

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/README.md CHANGED
@@ -14,6 +14,8 @@ pi install npm:@xynogen/pix-toolbox
14
14
 
15
15
  ## Full distro
16
16
 
17
+ Source: [github.com/xynogen/pix-mono](https://github.com/xynogen/pix-mono)
18
+
17
19
  To install the complete pix suite (all packages + Pi itself):
18
20
 
19
21
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xynogen/pix-toolbox",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Pi tool — gated tool toggle UI (/toolbox)",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -33,6 +33,9 @@
33
33
  "publishConfig": {
34
34
  "access": "public"
35
35
  },
36
+ "dependencies": {
37
+ "@xynogen/pix-pretty": "*"
38
+ },
36
39
  "peerDependencies": {
37
40
  "@earendil-works/pi-coding-agent": "*",
38
41
  "@earendil-works/pi-tui": "*"
package/src/toolbox.ts CHANGED
@@ -21,9 +21,8 @@ import type {
21
21
  Theme,
22
22
  ToolInfo,
23
23
  } from "@earendil-works/pi-coding-agent";
24
- import { DynamicBorder, getAgentDir } from "@earendil-works/pi-coding-agent";
24
+ import { getAgentDir } from "@earendil-works/pi-coding-agent";
25
25
  import {
26
- Container,
27
26
  decodeKittyPrintable,
28
27
  fuzzyFilter,
29
28
  Input,
@@ -32,10 +31,10 @@ import {
32
31
  matchesKey,
33
32
  type SelectItem,
34
33
  SelectList,
35
- Text,
36
34
  type TUI,
37
35
  visibleWidth,
38
36
  } from "@earendil-works/pi-tui";
37
+ import { frameLines, modalWidth } from "@xynogen/pix-pretty/modal-frame";
39
38
 
40
39
  // ─── Constants ──────────────────────────────────────────────────────────────
41
40
 
@@ -337,7 +336,17 @@ export default function registerToolbox(pi: ExtensionAPI): void {
337
336
 
338
337
  async function showPicker(ctx: {
339
338
  ui: {
340
- custom: <T>(f: unknown) => Promise<T>;
339
+ custom: <T>(
340
+ f: unknown,
341
+ opts?: {
342
+ overlay?: boolean;
343
+ overlayOptions?: {
344
+ anchor?: string;
345
+ maxHeight?: number | string;
346
+ width?: number | string;
347
+ };
348
+ },
349
+ ) => Promise<T>;
341
350
  notify: (m: string, t?: "info" | "warning" | "error") => void;
342
351
  };
343
352
  }): Promise<void> {
@@ -350,7 +359,6 @@ export default function registerToolbox(pi: ExtensionAPI): void {
350
359
  ) => {
351
360
  const accent = "accent";
352
361
  const mute = (s: string) => theme.fg("muted", s);
353
- const container = new Container();
354
362
 
355
363
  type RowState = "active" | "gated";
356
364
  const stateOf = (name: string): RowState =>
@@ -414,7 +422,7 @@ export default function registerToolbox(pi: ExtensionAPI): void {
414
422
  };
415
423
 
416
424
  const search = new Input();
417
- const statusLine = new Text("");
425
+ let statusText = "";
418
426
 
419
427
  const refreshLabels = () => {
420
428
  for (const it of internal.items) {
@@ -424,7 +432,6 @@ export default function registerToolbox(pi: ExtensionAPI): void {
424
432
  it.description = descFor(r);
425
433
  }
426
434
  list.invalidate();
427
- container.invalidate();
428
435
  tui.requestRender?.();
429
436
  };
430
437
 
@@ -432,7 +439,7 @@ export default function registerToolbox(pi: ExtensionAPI): void {
432
439
  const sel = list.getSelectedItem();
433
440
  if (!sel) return;
434
441
  const msg = toggleTool(action, sel.value, rows, ops);
435
- statusLine.setText(theme.fg("muted", msg));
442
+ statusText = theme.fg("muted", msg);
436
443
  refreshLabels();
437
444
  };
438
445
 
@@ -455,41 +462,39 @@ export default function registerToolbox(pi: ExtensionAPI): void {
455
462
  );
456
463
  internal.selectedIndex = 0;
457
464
  list.invalidate();
458
- container.invalidate();
459
465
  };
460
466
 
461
467
  list.onSelect = () => done(null);
462
468
  list.onCancel = () => done(null);
463
469
  search.onEscape = () => done(null);
464
470
 
465
- container.addChild(
466
- new DynamicBorder((s: string) => theme.fg(accent, s)),
467
- );
468
- container.addChild(
469
- new Text(theme.fg(accent, theme.bold("🧰 Toolbox"))),
470
- );
471
- container.addChild(new Text(theme.fg("muted", "Search:")));
472
- container.addChild(search);
473
- container.addChild(list);
474
- container.addChild(statusLine);
475
- container.addChild(
476
- new Text(
477
- theme.fg(
478
- "dim",
479
- "↑↓ navigate · e enable · d disable · space toggle · esc close",
480
- ),
481
- ),
482
- );
483
- container.addChild(
484
- new DynamicBorder((s: string) => theme.fg(accent, s)),
485
- );
486
-
487
471
  return {
488
472
  render(w: number) {
489
- return container.render(w);
473
+ const mw = modalWidth(w);
474
+ const inner = mw - 4; // CHROME = 2 border + 2 padding
475
+ const lines: string[] = [
476
+ theme.fg(accent, theme.bold("🧰 Toolbox")),
477
+ theme.fg("muted", "Search:"),
478
+ ...search.render(inner),
479
+ ...list.render(inner),
480
+ ];
481
+ if (statusText) lines.push(statusText);
482
+ lines.push(
483
+ theme.fg(
484
+ "dim",
485
+ "↑↓ navigate · e enable · d disable · space toggle · esc close",
486
+ ),
487
+ );
488
+ return frameLines({
489
+ width: mw,
490
+ lines,
491
+ color: (s) => theme.fg(accent, s),
492
+ bg: (s) => theme.bg("customMessageBg", s),
493
+ });
490
494
  },
491
495
  invalidate() {
492
- container.invalidate();
496
+ list.invalidate();
497
+ search.invalidate();
493
498
  },
494
499
  handleInput(data: string) {
495
500
  if (matchesKey(data, Key.up) || matchesKey(data, Key.down)) {
@@ -521,11 +526,12 @@ export default function registerToolbox(pi: ExtensionAPI): void {
521
526
  applyFilter(search.getValue?.() ?? "");
522
527
  }
523
528
  }
524
- container.invalidate();
529
+ list.invalidate();
525
530
  tui.requestRender?.();
526
531
  },
527
532
  };
528
533
  },
534
+ { overlay: true, overlayOptions: { anchor: "center", maxHeight: "80%" } },
529
535
  );
530
536
  }
531
537