@danypops/pi-packed 0.8.0 → 0.9.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.
@@ -5,13 +5,15 @@
5
5
  * itself never mutates; only Install/Cancel (behind the standard
6
6
  * approval) does.
7
7
  */
8
- import type { ExtensionCommandContext, Theme } from "@earendil-works/pi-coding-agent";
8
+ import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
9
9
  import { DynamicBorder, rawKeyHint } from "@earendil-works/pi-coding-agent";
10
- import { Container, Input, SelectList, type SelectItem, type SelectListTheme, Spacer, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
10
+ import { Container, Input, Spacer, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
11
+ import { Menu, type MenuItem } from "malevich-tui-components";
11
12
  import { shouldSearch } from "./discover-model.js";
12
13
  import type { Natives, PackageSummary } from "./packed.js";
13
14
  import { InstallServiceError } from "./packed.js";
14
15
  import { approvePackageOperation } from "./tools.js";
16
+ import { menuTheme } from "./menu-theme.js";
15
17
 
16
18
  const SEARCH_LIMIT = 20;
17
19
 
@@ -51,28 +53,17 @@ export async function applyInstall(result: PackageSummary, natives: Natives, ctx
51
53
  }
52
54
  }
53
55
 
54
- function selectListTheme(theme: Theme): SelectListTheme {
55
- return {
56
- selectedPrefix: (text) => theme.fg("accent", text),
57
- selectedText: (text) => theme.fg("accent", text),
58
- description: (text) => theme.fg("muted", text),
59
- scrollInfo: (text) => theme.fg("muted", text),
60
- noMatch: (text) => theme.fg("muted", text),
61
- };
62
- }
63
-
64
56
  async function showInstallMenu(ctx: ExtensionCommandContext, result: PackageSummary): Promise<boolean> {
65
- const items: SelectItem[] = [{ value: "install", label: `Install ${result.name}@${result.version}` }, { value: "cancel", label: "Cancel" }];
66
- const choice = await ctx.ui.custom<"install" | "cancel" | undefined>(
57
+ return ctx.ui.custom<boolean>(
67
58
  (_tui, theme, _kb, done) => {
68
- const list = new SelectList(items, items.length, selectListTheme(theme));
69
- list.onSelect = (item) => done(item.value as "install" | "cancel");
70
- list.onCancel = () => done(undefined);
71
- return list;
59
+ const items: MenuItem[] = [
60
+ { label: `Install ${result.name}@${result.version}`, action: () => done(true) },
61
+ { label: "Cancel", action: () => done(false) },
62
+ ];
63
+ return new Menu({ items, theme: menuTheme(theme), onClose: () => done(false) });
72
64
  },
73
65
  { overlay: true, overlayOptions: { width: 40, anchor: "center" } },
74
66
  );
75
- return choice === "install";
76
67
  }
77
68
 
78
69
  export async function showDiscoverPanel(ctx: ExtensionCommandContext, natives: Natives): Promise<void> {
@@ -0,0 +1,14 @@
1
+ import type { Theme } from "@earendil-works/pi-coding-agent";
2
+ import type { MenuTheme } from "malevich-tui-components";
3
+
4
+ /** Maps Pi's own Theme onto Malevich's Menu -- the one place this mapping
5
+ * exists, shared by every ctx.ui.custom overlay menu in this extension. */
6
+ export function menuTheme(theme: Theme): MenuTheme {
7
+ return {
8
+ border: (s) => theme.fg("border", s),
9
+ selected: (s) => theme.fg("accent", s),
10
+ normal: (s) => s,
11
+ dim: (s) => theme.fg("muted", s),
12
+ title: (s) => theme.fg("accent", s),
13
+ };
14
+ }
@@ -11,9 +11,10 @@
11
11
  * underneath never disappears. All data flows through the packed CLI
12
12
  * (thin seam).
13
13
  */
14
- import type { ExtensionCommandContext, Theme } from "@earendil-works/pi-coding-agent";
14
+ import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
15
15
  import { DynamicBorder, rawKeyHint } from "@earendil-works/pi-coding-agent";
16
- import { Container, Input, SelectList, type SelectItem, type SelectListTheme, Spacer, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
16
+ import { Container, Input, Spacer, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
17
+ import { Menu, type MenuItem } from "malevich-tui-components";
17
18
  import { filterRows, mergeRows, nextMode, visibleRows } from "./model.js";
18
19
  import type { Row, ViewMode } from "./model.js";
19
20
  import type { Natives, PackageResources } from "./packed.js";
@@ -21,6 +22,7 @@ import { approvePackageOperation } from "./tools.js";
21
22
  import { showPackedSettings } from "./security-tui.js";
22
23
  import { showResourceConfig, applyResourceToggle } from "./resource-config.js";
23
24
  import { showDiscoverPanel } from "./discover.js";
25
+ import { menuTheme } from "./menu-theme.js";
24
26
 
25
27
  interface PanelAction {
26
28
  type: "update" | "updateAll" | "remove" | "disable" | "config" | "find" | "refresh" | "settings";
@@ -173,32 +175,20 @@ async function loadRows(natives: Natives): Promise<{ rows: Row[]; error?: string
173
175
  }
174
176
  }
175
177
 
176
- function selectListTheme(theme: Theme): SelectListTheme {
177
- return {
178
- selectedPrefix: (text) => theme.fg("accent", text),
179
- selectedText: (text) => theme.fg("accent", text),
180
- description: (text) => theme.fg("muted", text),
181
- scrollInfo: (text) => theme.fg("muted", text),
182
- noMatch: (text) => theme.fg("muted", text),
183
- };
184
- }
185
-
186
178
  /** Enter's action menu, floated on top of the still-open packages panel
187
179
  * via ctx.ui.custom's own overlay:true -- no full-screen teardown, unlike
188
180
  * the ctx.ui.select this replaced. */
189
181
  async function showActionMenu(ctx: ExtensionCommandContext, row: Row): Promise<"update" | "remove" | "disable" | "config" | undefined> {
190
- const items: SelectItem[] = [
191
- ...(row.hasUpdate ? [{ value: "update", label: `Update to ${row.latest}` }] : []),
192
- { value: "disable", label: "Disable/enable extensions" },
193
- { value: "config", label: "Configure resources" },
194
- { value: "remove", label: "Remove" },
195
- ];
196
- return ctx.ui.custom<"update" | "remove" | "disable" | "config" | undefined>(
182
+ type Choice = "update" | "remove" | "disable" | "config";
183
+ return ctx.ui.custom<Choice | undefined>(
197
184
  (_tui, theme, _kb, done) => {
198
- const list = new SelectList(items, items.length, selectListTheme(theme));
199
- list.onSelect = (item) => done(item.value as "update" | "remove" | "disable" | "config");
200
- list.onCancel = () => done(undefined);
201
- return list;
185
+ const items: MenuItem[] = [
186
+ ...(row.hasUpdate ? [{ label: `Update to ${row.latest}`, action: () => done("update" as Choice) }] : []),
187
+ { label: "Disable/enable extensions", action: () => done("disable") },
188
+ { label: "Configure resources", action: () => done("config") },
189
+ { label: "Remove", action: () => done("remove") },
190
+ ];
191
+ return new Menu({ items, theme: menuTheme(theme), onClose: () => done(undefined) });
202
192
  },
203
193
  { overlay: true, overlayOptions: { width: 40, anchor: "center" } },
204
194
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/pi-packed",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Pi package tools, commands, profiles, and TUI for the Packed daemon",
5
5
  "type": "module",
6
6
  "keywords": ["pi-package"],
@@ -14,7 +14,8 @@
14
14
  "dependencies": {
15
15
  "@danypops/packed": "^0.2.0",
16
16
  "@danypops/vehicle-client": "^0.1.1",
17
- "@danypops/vehicle-client-pi": "^0.1.5"
17
+ "@danypops/vehicle-client-pi": "^0.1.5",
18
+ "malevich-tui-components": "^0.7.0"
18
19
  },
19
20
  "peerDependencies": {
20
21
  "@earendil-works/pi-coding-agent": "*",