@danypops/pi-packed 0.12.0 → 0.13.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.
- package/extension/src/tui.ts +39 -16
- package/package.json +1 -1
package/extension/src/tui.ts
CHANGED
|
@@ -12,13 +12,18 @@
|
|
|
12
12
|
* only the footer moves as content height changes. Enter opens a second,
|
|
13
13
|
* smaller overlay action menu on top of it. U's batch update stays on
|
|
14
14
|
* this same package list -- progress renders inline next to the row
|
|
15
|
-
* currently being updated, not as a separate screen.
|
|
16
|
-
*
|
|
15
|
+
* currently being updated, not as a separate screen. Rows render through
|
|
16
|
+
* Malevich's Table (real column-aligned Package/Version/status cells,
|
|
17
|
+
* per-row selection styling baked into each cell since Table's own
|
|
18
|
+
* cellStyle is column-wide, not row-wide) inside this panel's own
|
|
19
|
+
* scroll-window slice -- Table deliberately owns no pagination of its
|
|
20
|
+
* own, so the visible-window-around-selectedIndex math stays here. All
|
|
21
|
+
* data flows through the packed CLI (thin seam).
|
|
17
22
|
*/
|
|
18
23
|
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
19
24
|
import { DynamicBorder, rawKeyHint } from "@earendil-works/pi-coding-agent";
|
|
20
|
-
import { Container, Input, Spacer, truncateToWidth } from "@earendil-works/pi-tui";
|
|
21
|
-
import { Envelope, Menu, ProgressBar, type MenuItem } from "malevich-tui-components";
|
|
25
|
+
import { Container, Input, Spacer, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
26
|
+
import { Envelope, Menu, ProgressBar, Table, type MenuItem, type TableColumn, type TextMeasure } from "malevich-tui-components";
|
|
22
27
|
import { filterRows, mergeRows, nextMode, visibleRows } from "./model.js";
|
|
23
28
|
import type { Row, ViewMode } from "./model.js";
|
|
24
29
|
import type { Natives, PackageResources } from "./packed.js";
|
|
@@ -409,6 +414,19 @@ function renderPanel(ctx: ExtensionCommandContext, natives: Natives, initialRows
|
|
|
409
414
|
},
|
|
410
415
|
};
|
|
411
416
|
|
|
417
|
+
// pi-tui's own visibleWidth/truncateToWidth are ANSI-aware (they strip
|
|
418
|
+
// escape codes for measurement, matching the pair Malevich's TextMeasure
|
|
419
|
+
// port expects) -- rows below bake selection/status styling directly
|
|
420
|
+
// into each cell's text since Table's own cellStyle is column-wide, not
|
|
421
|
+
// per-row.
|
|
422
|
+
const measure: TextMeasure = { visibleWidth, truncateToWidth };
|
|
423
|
+
const columns: TableColumn[] = [
|
|
424
|
+
{ header: "Package", key: "name" },
|
|
425
|
+
{ header: "Version", key: "version" },
|
|
426
|
+
{ header: "", key: "status" },
|
|
427
|
+
];
|
|
428
|
+
const table = new Table({ columns, rows: [], measure, headerStyle: (s) => theme.fg("muted", s) });
|
|
429
|
+
|
|
412
430
|
const list = {
|
|
413
431
|
invalidate() {},
|
|
414
432
|
render(width: number): string[] {
|
|
@@ -419,20 +437,25 @@ function renderPanel(ctx: ExtensionCommandContext, natives: Natives, initialRows
|
|
|
419
437
|
lines.push(theme.fg("muted", " No packages"));
|
|
420
438
|
return lines;
|
|
421
439
|
}
|
|
440
|
+
// No scrolling of its own (Malevich's Table is deliberately
|
|
441
|
+
// unopinionated about pagination) -- the visible window around
|
|
442
|
+
// selectedIndex stays this panel's own job, same as before.
|
|
422
443
|
const start = Math.max(0, Math.min(selectedIndex - Math.floor(maxVisible / 2), filtered.length - maxVisible));
|
|
423
444
|
const end = Math.min(start + maxVisible, filtered.length);
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
445
|
+
table.setRows(
|
|
446
|
+
filtered.slice(start, end).map((row, offset) => {
|
|
447
|
+
const i = start + offset;
|
|
448
|
+
const selected = i === selectedIndex;
|
|
449
|
+
const cursor = selected ? theme.fg("accent", "❯ ") : " ";
|
|
450
|
+
const name = selected ? theme.bold(row.name) : row.name;
|
|
451
|
+
const isUpdating = updatingRowName === row.name;
|
|
452
|
+
const status = isUpdating
|
|
453
|
+
? theme.fg("accent", `${updatingBar.format(10)} updating…`)
|
|
454
|
+
: row.hasUpdate ? theme.fg("warning", `↑${row.latest}`) : "";
|
|
455
|
+
return { name: `${cursor}${name}`, version: theme.fg("dim", row.version), status };
|
|
456
|
+
}),
|
|
457
|
+
);
|
|
458
|
+
lines.push(...table.render(width));
|
|
436
459
|
const hasScroll = start > 0 || end < filtered.length;
|
|
437
460
|
lines.push(theme.fg("dim", ` ${hasScroll ? `${selectedIndex + 1}/${filtered.length} ` : ""}${mode}`));
|
|
438
461
|
return lines;
|