@leo-alvarenga/pi-zen-frame 0.12.0 → 0.12.1

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.
@@ -32,6 +32,17 @@ export interface HeaderEnv {
32
32
  const RANDOM_TIP =
33
33
  HEADER_TIPS[Math.floor(Math.random() * HEADER_TIPS.length)]?.text ?? "";
34
34
 
35
+ function wrapLines(
36
+ lines: string[],
37
+ maxLen: number,
38
+ style?: (line: string) => string,
39
+ ): string[] {
40
+ const wrapped = lines.map((l) => wrapTextWithAnsi(l, maxLen)).flat();
41
+ if (style) return wrapped.map((l) => (l.length ? style(l) : l));
42
+
43
+ return wrapped;
44
+ }
45
+
35
46
  export function createHeader(
36
47
  _tui: TUI,
37
48
  theme: Theme,
@@ -57,29 +68,6 @@ export function createHeader(
57
68
  color: settings.header?.logoColor ?? DEFAULT_SETTINGS.header?.logoColor,
58
69
  };
59
70
 
60
- const leftLines = [
61
- ...logo.lines.map((l) => theme.fg(logo.color, l)),
62
-
63
- "",
64
- "",
65
-
66
- theme.bold(
67
- theme.fg(
68
- "muted",
69
- settings.header?.heading ?? DEFAULT_SETTINGS.header?.heading,
70
- ),
71
- ),
72
-
73
- "",
74
-
75
- theme.italic(
76
- theme.fg(
77
- "muted",
78
- settings.header?.subheading ?? DEFAULT_SETTINGS.header?.subheading,
79
- ),
80
- ),
81
- ];
82
-
83
71
  const border = (s: string, fg?: ThemeColor) => theme.fg(fg ?? accentColor, s);
84
72
 
85
73
  /** Space-pad `text` so it sits horizontally centered within `inner` cols. */
@@ -106,7 +94,7 @@ export function createHeader(
106
94
  }
107
95
 
108
96
  /** Right column halves: top = model(+provider), bottom = cwd + git. */
109
- function infoRows(env: HeaderEnv): string[] {
97
+ function infoRows(env: HeaderEnv, width: number): string[] {
110
98
  const icons = DEFAULT_ICONS;
111
99
  const parts: string[] = [];
112
100
 
@@ -123,46 +111,74 @@ export function createHeader(
123
111
 
124
112
  return [
125
113
  theme.bold(border("Model Info")),
126
- env.modelName ? theme.fg("muted", `${icons.model} ${env.modelName}`) : "",
114
+
115
+ ...wrapLines(
116
+ [
117
+ env.modelName
118
+ ? theme.fg("muted", `${icons.model} ${env.modelName}`)
119
+ : "",
120
+ ],
121
+ width,
122
+ (str) => theme.fg("muted", str),
123
+ ),
124
+
127
125
  "",
126
+
128
127
  theme.bold(border("Current Directory")),
129
128
  parts.length ? parts.join(" · ") : "",
129
+
130
130
  "",
131
+
131
132
  theme.bold(border("Tip")),
132
- theme.fg("muted", RANDOM_TIP),
133
+ ...wrapLines([RANDOM_TIP], width, (str) => theme.fg("muted", str)),
133
134
  ];
134
135
  }
135
136
 
136
137
  return {
137
138
  render(width: number): string[] {
138
- // Too narrow for a box → fall back to a plain centered logo.
139
- if (width < MIN_BOX_WIDTH) {
140
- return leftLines;
141
- }
142
-
143
139
  const env = getEnv(pi);
144
- const rightRows = infoRows(env);
145
140
 
146
141
  const inner = Math.max(0, width - 2);
147
142
  const leftW = Math.floor(inner * LEFT_COL_RATIO);
148
- const rightW = inner - leftW - 1; // divider column
143
+
144
+ const rightW = inner - leftW - 1;
145
+
146
+ const rightLines = infoRows(env, rightW);
147
+ const leftLines = [
148
+ ...logo.lines.map((l) => theme.fg(logo.color, l)),
149
+
150
+ "",
151
+ "",
152
+
153
+ ...wrapLines(
154
+ [settings.header?.heading ?? DEFAULT_SETTINGS.header?.heading ?? ""],
155
+ leftW,
156
+ ).map((line) => theme.bold(theme.fg("muted", line))),
157
+
158
+ "",
159
+
160
+ ...wrapLines(
161
+ [
162
+ settings.header?.subheading ??
163
+ DEFAULT_SETTINGS.header?.subheading ??
164
+ "",
165
+ ],
166
+ leftW,
167
+ ).map((line) => theme.italic(theme.fg("muted", line))),
168
+ ];
169
+
170
+ // Too narrow for a box → fall back to a plain centered logo.
171
+ if (width < MIN_BOX_WIDTH) {
172
+ return leftLines;
173
+ }
149
174
 
150
175
  // No truncation: overflow wraps onto following lines until it all fits.
151
- const leftWrapped = leftLines
152
- .map((l) => wrapTextWithAnsi(l, leftW))
153
- .flat();
154
- const rightWrapped = rightRows
155
- .map((r) => wrapTextWithAnsi(r, Math.max(1, rightW - 2))) // 2-col indent
156
- .flat();
157
-
158
- const height = Math.max(leftWrapped.length, rightWrapped.length);
159
- const logoTop = Math.max(
160
- 0,
161
- Math.floor((height - leftWrapped.length) / 2),
162
- );
176
+ const height = Math.max(leftLines.length, rightLines.length);
177
+ const logoTop = Math.max(0, Math.floor((height - leftLines.length) / 2));
178
+
163
179
  const rightTop = Math.max(
164
180
  0,
165
- Math.floor((height - rightWrapped.length) / 2),
181
+ Math.floor((height - rightLines.length) / 2),
166
182
  );
167
183
 
168
184
  const lines: string[] = [""];
@@ -172,12 +188,10 @@ export function createHeader(
172
188
 
173
189
  for (let i = 0; i < height; i++) {
174
190
  const l = i - logoTop;
175
- const leftLine =
176
- l >= 0 && l < leftWrapped.length ? leftWrapped[l]! : "";
191
+ const leftLine = l >= 0 && l < leftLines.length ? leftLines[l]! : "";
177
192
 
178
193
  const r = i - rightTop;
179
- const rightLine =
180
- r >= 0 && r < rightWrapped.length ? rightWrapped[r]! : "";
194
+ const rightLine = r >= 0 && r < rightLines.length ? rightLines[r]! : "";
181
195
 
182
196
  lines.push(splitRow(leftW, rightW, leftLine, rightLine));
183
197
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@leo-alvarenga/pi-zen-frame",
3
3
  "description": "A pi-coding-agent extension that gives the TUI editor a simple yet polished look and feel",
4
4
  "author": "Leonardo A. Alvarenga",
5
- "version": "0.12.0",
5
+ "version": "0.12.1",
6
6
  "license": "MIT",
7
7
  "repository": "github.com/leo-alvarenga/pi-mono",
8
8
  "publishConfig": {