@trendr/core 0.2.10 → 0.2.11

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": "@trendr/core",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "direct-mode TUI renderer with JSX, signals, and per-cell diffing",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/ansi.js CHANGED
@@ -11,6 +11,7 @@ export const showCursor = `${ESC}?25h`
11
11
  export const clearScreen = `${ESC}2J`
12
12
  export const clearLine = `${ESC}2K`
13
13
  export const clearDown = `${ESC}0J`
14
+ export const clearScrollback = `${ESC}3J`
14
15
  export const altScreen = `${ESC}?1049h`
15
16
  export const exitAltScreen = `${ESC}?1049l`
16
17
  export const sgrReset = `${ESC}0m`
package/src/renderer.js CHANGED
@@ -660,10 +660,12 @@ export function mount(rootComponent, { stream, stdin, title, theme, onExit: onEx
660
660
  let forceFullPaint = false
661
661
  let prevHadOverlays = false
662
662
 
663
- // inline mode state: how many scrollback items have been committed, how many
664
- // lines the live region occupied last emit, and that emit's text for skipping
663
+ // inline mode state: how many scrollback items have been committed, the
664
+ // visible width of each line the live region last emitted (so a later resize
665
+ // can compute how many physical rows they reflowed into), and that emit's
666
+ // text for skipping unchanged frames
665
667
  let flushedCount = 0
666
- let prevLiveLines = 0
668
+ let prevLineLens = []
667
669
  let prevLiveText = null
668
670
 
669
671
  // mirror per-instance layout (incl. scroll contentHeight/childHeights) back
@@ -743,16 +745,25 @@ export function mount(rootComponent, { stream, stdin, title, theme, onExit: onEx
743
745
  const liveText = liveLines.join('\r\n')
744
746
  if (!committed && liveText === prevLiveText) return
745
747
 
748
+ // the cursor rests at the end of the last live line between frames. erase
749
+ // the previous live region before repainting: since it was drawn, a resize
750
+ // may have reflowed each of its lines into ceil(visibleWidth / width) rows,
751
+ // so step back over that real physical height rather than the logical line
752
+ // count - otherwise a shrink leaves the extra wrapped rows stranded as
753
+ // ghost bars. history above is left to the terminal's own reflow
754
+ let phys = 0
755
+ for (const len of prevLineLens) phys += Math.max(1, Math.ceil(len / width))
756
+
746
757
  let out_ = ''
747
- if (prevLiveLines > 0) {
758
+ if (phys > 0) {
748
759
  out_ += '\r'
749
- if (prevLiveLines > 1) out_ += ansi.moveUp(prevLiveLines - 1)
760
+ if (phys > 1) out_ += ansi.moveUp(phys - 1)
750
761
  out_ += ansi.clearDown
751
762
  }
752
763
  out_ += committed + liveText
753
764
 
754
765
  out.write(ansi.hideCursor + out_)
755
- prevLiveLines = liveLines.length
766
+ prevLineLens = liveLines.map(l => measureText(l))
756
767
  prevLiveText = liveText
757
768
  }
758
769
 
@@ -896,11 +907,16 @@ export function mount(rootComponent, { stream, stdin, title, theme, onExit: onEx
896
907
  width = out.columns ?? 80
897
908
  height = out.rows ?? 24
898
909
  if (inline) {
899
- // the terminal reflows committed history on its own; drop our live-region
900
- // geometry and repaint it fresh below wherever the cursor landed
901
- prevLiveLines = 0
910
+ // a resize reflows committed scrollback unpredictably, and a relative
911
+ // erase of the live region cannot reliably track it across terminals.
912
+ // rebuild instead: wipe the screen and scrollback, reset the commit
913
+ // cursor, and re-commit the whole transcript cleanly at the new width
914
+ width = out.columns ?? 80
915
+ height = out.rows ?? 24
916
+ out.write(ansi.clearScrollback + ansi.clearScreen + ansi.moveTo(1, 1))
917
+ flushedCount = 0
918
+ prevLineLens = []
902
919
  prevLiveText = null
903
- out.write('\r\n')
904
920
  scheduler.forceFrame()
905
921
  return
906
922
  }