@xynogen/pix-pretty 1.18.1 → 1.18.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xynogen/pix-pretty",
3
- "version": "1.18.1",
3
+ "version": "1.18.2",
4
4
  "description": "Enhanced tool output rendering with syntax highlighting, file icons, tree views, diff rendering, and FFF search",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -31,6 +31,7 @@ interface Wired {
31
31
  function makeUI(
32
32
  onReady: (comp: Wired, finish: (v: unknown) => void) => void,
33
33
  onOptions?: (options: unknown) => void,
34
+ renderTheme = theme,
34
35
  ): OverlayUI {
35
36
  return {
36
37
  custom: async <T>(
@@ -47,7 +48,7 @@ function makeUI(
47
48
  const done = (v: T) => {
48
49
  resolved = v;
49
50
  };
50
- const comp = cb({ requestRender: () => {} }, theme, undefined, done);
51
+ const comp = cb({ requestRender: () => {} }, renderTheme, undefined, done);
51
52
  comp.render(80); // initialise render path
52
53
  onReady(comp, done as (v: unknown) => void);
53
54
  return resolved;
@@ -136,6 +137,47 @@ describe("showOverlay — confirm mode", () => {
136
137
  expect(joined).toContain("body-line-x");
137
138
  });
138
139
 
140
+ test("uses semantic colors for transfer details", async () => {
141
+ const coloredTheme = {
142
+ fg: (color: string, text: string) => `<${color}>${text}</${color}>`,
143
+ bg: (_color: string, text: string) => text,
144
+ bold: (text: string) => text,
145
+ };
146
+ let captured: string[] = [];
147
+ await showOverlay(
148
+ makeUI(
149
+ (comp) => {
150
+ captured = comp.render(100);
151
+ comp.handleInput(ENTER);
152
+ },
153
+ undefined,
154
+ coloredTheme,
155
+ ),
156
+ {
157
+ mode: "confirm",
158
+ title: "SSH FILE TRANSFER",
159
+ body: [
160
+ "Intent: Copy a release artifact",
161
+ "Host: deploy@example.com",
162
+ "Direction: Download",
163
+ "From: /srv/releases/app.tar.gz",
164
+ "To: /tmp/app.tar.gz",
165
+ "Mode: Single item",
166
+ "Warning: existing destination may be overwritten",
167
+ "Auth: SSH key (no password)",
168
+ ],
169
+ timeoutMs: 0,
170
+ },
171
+ );
172
+ const joined = captured.join("\n");
173
+ expect(joined).toContain("<dim>Host:</dim> <accent>deploy@example.com</accent>");
174
+ expect(joined).toContain("<dim>Direction:</dim> <warning>Download</warning>");
175
+ expect(joined).toContain("<dim>From:</dim> <text>/srv/releases/app.tar.gz</text>");
176
+ expect(joined).toContain("<dim>To:</dim> <accent>/tmp/app.tar.gz</accent>");
177
+ expect(joined).toContain("<warning>Warning: existing destination may be overwritten</warning>");
178
+ expect(joined).toContain("<dim>Auth:</dim> <success>SSH key (no password)</success>");
179
+ });
180
+
139
181
  test("wraps a long body command instead of truncating it", async () => {
140
182
  // A command far wider than any modal width — must survive in full, wrapped.
141
183
  const longCmd = `echo ${"pix-gate-installed-or-linked ".repeat(8)}done`;
@@ -178,7 +178,25 @@ function buildSections(opts: {
178
178
  const body = (config.body ?? []).map((line) => {
179
179
  if (line.startsWith("Intent:")) return theme.fg("text", line.slice(7).trimStart());
180
180
  if (line.startsWith("Command:")) return theme.fg("dim", line.slice(8).trimStart());
181
- return theme.fg("text", line);
181
+ if (line.startsWith("Warning:")) return theme.fg("warning", line);
182
+ if (line.startsWith("(") && line.endsWith(")")) return theme.fg("dim", line);
183
+
184
+ const separator = line.indexOf(":");
185
+ if (separator < 1) return theme.fg("text", line);
186
+ const label = line.slice(0, separator + 1);
187
+ const value = line.slice(separator + 1).trimStart();
188
+ const valueColors: Record<string, string> = {
189
+ "Host:": "accent",
190
+ "Direction:": "warning",
191
+ "From:": "text",
192
+ "To:": "accent",
193
+ "Mode:": "muted",
194
+ "Auth:": "success",
195
+ };
196
+ const valueColor = valueColors[label];
197
+ return valueColor
198
+ ? `${theme.fg("dim", label)} ${theme.fg(valueColor, value)}`
199
+ : theme.fg("text", line);
182
200
  });
183
201
  const footer = [theme.fg("dim", "─".repeat(inner))];
184
202