@underactive/pi-topping 0.6.0 → 0.6.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/menu.ts +24 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@underactive/pi-topping",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "A Pi extension that adds quality of life improvements to Pi's UX: a high-vis user prompt, a shimmering working loader with token activity meter and elapsed timer, and an end-of-turn completion marker",
5
5
  "keywords": ["pi-package", "pi-extension"],
6
6
  "license": "MIT",
package/src/menu.ts CHANGED
@@ -355,6 +355,12 @@ export class MenuComponent implements Component {
355
355
  const flat = this.flat[index]!;
356
356
  if (flat.sectionIndex !== currentSection) {
357
357
  const remaining = maxRows - lines.length;
358
+ // A section continued from above needs room for a blank separator
359
+ // row, its divider, and at least one item row; otherwise end the
360
+ // window here rather than crowd the divider against the previous
361
+ // section or fold the section into it. The window's first section
362
+ // always renders (a degenerate window may drop its divider).
363
+ if (lines.length > 0 && remaining < 3) break;
358
364
  if (lines.length > 0 && remaining >= 3) lines.push(this.renderBlankRow(innerWidth));
359
365
  if (maxRows - lines.length >= 2) lines.push(this.renderSectionDivider(this.sections[flat.sectionIndex]!.title, innerWidth));
360
366
  currentSection = flat.sectionIndex;
@@ -380,18 +386,25 @@ export class MenuComponent implements Component {
380
386
  if (this.cursor < this.scrollStart) this.scrollStart = this.cursor;
381
387
  this.scrollStart = Math.max(0, Math.min(this.scrollStart, this.flat.length - 1));
382
388
 
383
- let window = this.buildToggleWindow(innerWidth, this.scrollStart, contentRows);
384
- while (window.end < this.cursor && this.scrollStart < this.cursor) {
385
- this.scrollStart++;
386
- window = this.buildToggleWindow(innerWidth, this.scrollStart, contentRows);
387
- }
388
- // Backfill from above whenever more context fits without hiding the cursor.
389
- while (this.scrollStart > 0) {
390
- const candidate = this.buildToggleWindow(innerWidth, this.scrollStart - 1, contentRows);
391
- if (candidate.end < this.cursor) break;
392
- this.scrollStart--;
393
- window = candidate;
389
+ // Walk backward from cursor to find the lowest scrollStart that fits in contentRows.
390
+ {
391
+ let rowsUsed = 2; // 1 for cursor item + 1 for first-section divider
392
+ let section = this.flat[this.cursor]!.sectionIndex;
393
+ this.scrollStart = this.cursor;
394
+ for (let i = this.cursor - 1; i >= 0; i--) {
395
+ const sec = this.flat[i]!.sectionIndex;
396
+ if (sec !== section) {
397
+ if (rowsUsed + 3 > contentRows) break;
398
+ rowsUsed += 3;
399
+ section = sec;
400
+ } else {
401
+ if (rowsUsed + 1 > contentRows) break;
402
+ rowsUsed += 1;
403
+ }
404
+ this.scrollStart = i;
405
+ }
394
406
  }
407
+ const window = this.buildToggleWindow(innerWidth, this.scrollStart, contentRows);
395
408
 
396
409
  const rows = [...window.lines];
397
410
  while (rows.length < contentRows) rows.push(this.renderBlankRow(innerWidth));