pickem 1.0.2 → 1.0.4

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 (57) hide show
  1. package/core/chrome.d.ts +19 -5
  2. package/core/chrome.d.ts.map +1 -1
  3. package/core/chrome.js +26 -9
  4. package/core/chrome.js.map +1 -1
  5. package/core/cleanup.js +2 -2
  6. package/core/cleanup.js.map +1 -1
  7. package/core/colors.d.ts +1 -0
  8. package/core/colors.d.ts.map +1 -1
  9. package/core/colors.js +4 -0
  10. package/core/colors.js.map +1 -1
  11. package/core/pagination.d.ts +5 -1
  12. package/core/pagination.d.ts.map +1 -1
  13. package/core/pagination.js +12 -16
  14. package/core/pagination.js.map +1 -1
  15. package/core/screen.d.ts +8 -1
  16. package/core/screen.d.ts.map +1 -1
  17. package/core/screen.js +45 -11
  18. package/core/screen.js.map +1 -1
  19. package/core/status-glyph.d.ts.map +1 -1
  20. package/core/status-glyph.js +10 -4
  21. package/core/status-glyph.js.map +1 -1
  22. package/core/symbols.d.ts +1 -0
  23. package/core/symbols.d.ts.map +1 -1
  24. package/core/symbols.js +1 -0
  25. package/core/symbols.js.map +1 -1
  26. package/core/testing.d.ts.map +1 -1
  27. package/core/testing.js +97 -10
  28. package/core/testing.js.map +1 -1
  29. package/core/theme.d.ts.map +1 -1
  30. package/core/theme.js +2 -1
  31. package/core/theme.js.map +1 -1
  32. package/core/width.d.ts.map +1 -1
  33. package/core/width.js +111 -6
  34. package/core/width.js.map +1 -1
  35. package/display/format.js +1 -1
  36. package/display/format.js.map +1 -1
  37. package/package.json +1 -4
  38. package/pickem.d.ts.map +1 -1
  39. package/pickem.js +17 -9
  40. package/pickem.js.map +1 -1
  41. package/prompts/checkbox.js +2 -2
  42. package/prompts/checkbox.js.map +1 -1
  43. package/prompts/input.d.ts.map +1 -1
  44. package/prompts/input.js +1 -2
  45. package/prompts/input.js.map +1 -1
  46. package/prompts/search.d.ts.map +1 -1
  47. package/prompts/search.js +8 -8
  48. package/prompts/search.js.map +1 -1
  49. package/prompts/searchable-checkbox.d.ts.map +1 -1
  50. package/prompts/searchable-checkbox.js +14 -12
  51. package/prompts/searchable-checkbox.js.map +1 -1
  52. package/prompts/select.d.ts.map +1 -1
  53. package/prompts/select.js +3 -4
  54. package/prompts/select.js.map +1 -1
  55. package/wizard.d.ts.map +1 -1
  56. package/wizard.js +13 -16
  57. package/wizard.js.map +1 -1
package/core/chrome.d.ts CHANGED
@@ -3,14 +3,16 @@ import type { Symbols } from './symbols.js';
3
3
  export interface ChromeDeps {
4
4
  colors: Colors;
5
5
  symbols: Symbols;
6
+ /** Terminal column count, snapshotted once per render to avoid per-row reads. */
7
+ columns?: number;
6
8
  }
7
9
  export interface RowArgs {
8
10
  label: string;
9
11
  meta?: string[];
10
12
  active?: boolean;
11
13
  glyph?: string;
12
- state?: string;
13
- maxWidth?: number;
14
+ /** Filter term to highlight inside the label on inactive rows. */
15
+ term?: string;
14
16
  }
15
17
  export interface SearchBoxArgs {
16
18
  value: string;
@@ -26,10 +28,22 @@ export interface FooterArgs {
26
28
  export declare function makeChrome({ colors, symbols }: ChromeDeps): {
27
29
  /** Accent+bold title, then a dim "·"-joined hint line. */
28
30
  header(title: string, hints?: string[]): string;
29
- /** Rounded boxed search input (searchable pickers only). */
31
+ /**
32
+ * Rounded boxed search input (searchable pickers only). When empty, the block
33
+ * cursor sits at the START of the input (where typing begins) with the
34
+ * placeholder dimmed behind it — not parked after the placeholder text.
35
+ */
30
36
  searchBox({ value, placeholder, focused, width }: SearchBoxArgs): string;
31
- /** One columnar list row: pointer [glyph] [state] name · dim-meta. */
32
- row({ label, meta, active, glyph, state, maxWidth }: RowArgs): string;
37
+ /**
38
+ * One columnar list row. Every row begins with the same `❯` chevron cell, so
39
+ * the column is reserved identically on every row and the label NEVER shifts
40
+ * as the cursor moves — the chevron is simply concealed (invisible) on
41
+ * inactive rows and lit in accent on the active row. The active label is also
42
+ * recolored to accent (bold); the caller's own ANSI is stripped first so the
43
+ * accent always wins (an embedded reset can't cancel it), which is why the
44
+ * highlight shows on colored rows too. Inactive rows highlight matched `term`.
45
+ */
46
+ row({ label, meta, active, glyph, term }: RowArgs): string;
33
47
  /** Dim pagination/summary footer. */
34
48
  footer({ moreAbove, moreBelow, summary }: FooterArgs): string;
35
49
  };
@@ -1 +1 @@
1
- {"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../src/core/chrome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAG3C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAOD,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,UAAU;IAKtD,0DAA0D;kBAC5C,MAAM,UAAS,MAAM,EAAE,GAAQ,MAAM;IAMnD,4DAA4D;sDACO,aAAa,GAAG,MAAM;IAYzF,sEAAsE;yDACW,OAAO,GAAG,MAAM;IASjG,qCAAqC;8CACkB,UAAU,GAAG,MAAM;EAQ7E;AAED,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA"}
1
+ {"version":3,"file":"chrome.d.ts","sourceRoot":"","sources":["../../src/core/chrome.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAG3C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAOD,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,UAAU;IAKtD,0DAA0D;kBAC5C,MAAM,UAAS,MAAM,EAAE,GAAQ,MAAM;IAMnD;;;;OAIG;sDACgE,aAAa,GAAG,MAAM;IAYzF;;;;;;;;OAQG;8CAC8D,OAAO,GAAG,MAAM;IAYjF,qCAAqC;8CACkB,UAAU,GAAG,MAAM;EAQ7E;AAED,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA"}
package/core/chrome.js CHANGED
@@ -1,4 +1,4 @@
1
- import { displayWidth, truncateToWidth } from './width.js';
1
+ import { displayWidth, stripAnsi } from './width.js';
2
2
  function padToWidth(str, width) {
3
3
  const w = displayWidth(str);
4
4
  return w >= width ? str : str + ' '.repeat(width - w);
@@ -14,11 +14,15 @@ export function makeChrome({ colors, symbols }) {
14
14
  return head;
15
15
  return `${head}\n${colors.dim(hints.join(' · '))}`;
16
16
  },
17
- /** Rounded boxed search input (searchable pickers only). */
17
+ /**
18
+ * Rounded boxed search input (searchable pickers only). When empty, the block
19
+ * cursor sits at the START of the input (where typing begins) with the
20
+ * placeholder dimmed behind it — not parked after the placeholder text.
21
+ */
18
22
  searchBox({ value, placeholder = '', focused = true, width = 40 }) {
19
23
  const w = Math.max(20, Math.min(width, 60));
20
24
  const cursor = focused ? colors.inverse(' ') : '';
21
- const text = value.length ? value + cursor : colors.dim(placeholder) + cursor;
25
+ const text = value.length ? `${value}${cursor}` : `${cursor}${colors.dim(placeholder)}`;
22
26
  const content = `${colors.dim(symbols.search)} ${text}`;
23
27
  const inner = padToWidth(content, w);
24
28
  const top = colors.dim(symbols.cornerTL + symbols.line.repeat(w + 1) + symbols.cornerTR);
@@ -26,14 +30,27 @@ export function makeChrome({ colors, symbols }) {
26
30
  const bot = colors.dim(symbols.cornerBL + symbols.line.repeat(w + 1) + symbols.cornerBR);
27
31
  return `${top}\n${mid}\n${bot}`;
28
32
  },
29
- /** One columnar list row: pointer [glyph] [state] name · dim-meta. */
30
- row({ label, meta = [], active = false, glyph = '', state = '', maxWidth = 80 }) {
31
- const pointer = active ? accent(symbols.pointer) : ' ';
33
+ /**
34
+ * One columnar list row. Every row begins with the same `❯` chevron cell, so
35
+ * the column is reserved identically on every row and the label NEVER shifts
36
+ * as the cursor moves — the chevron is simply concealed (invisible) on
37
+ * inactive rows and lit in accent on the active row. The active label is also
38
+ * recolored to accent (bold); the caller's own ANSI is stripped first so the
39
+ * accent always wins (an embedded reset can't cancel it), which is why the
40
+ * highlight shows on colored rows too. Inactive rows highlight matched `term`.
41
+ */
42
+ row({ label, meta = [], active = false, glyph = '', term = '' }) {
43
+ const chevron = active ? `${accent(symbols.pointer)} ` : `${colors.conceal(symbols.pointer)} `;
32
44
  const g = glyph ? `${glyph} ` : '';
33
- const s = state ? `${colors.dim(state)} ` : '';
34
- const name = active ? accent(truncateToWidth(label, maxWidth)) : truncateToWidth(label, maxWidth);
35
45
  const m = meta.length ? dot + colors.dim(meta.join(' · ')) : '';
36
- return `${pointer} ${g}${s}${name}${m}`;
46
+ if (active)
47
+ return `${chevron}${g}${colors.bold(accent(stripAnsi(label)))}${m}`;
48
+ if (!term)
49
+ return `${chevron}${g}${label}${m}`;
50
+ const i = label.toLowerCase().indexOf(term.toLowerCase());
51
+ const hl = i < 0 ? label
52
+ : label.slice(0, i) + accent(label.slice(i, i + term.length)) + label.slice(i + term.length);
53
+ return `${chevron}${g}${hl}${m}`;
37
54
  },
38
55
  /** Dim pagination/summary footer. */
39
56
  footer({ moreAbove = 0, moreBelow = 0, summary = '' }) {
@@ -1 +1 @@
1
- {"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../src/core/chrome.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chrome.js","sourceRoot":"","sources":["../../src/core/chrome.ts"],"names":[],"mappings":"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"}
package/core/cleanup.js CHANGED
@@ -14,9 +14,9 @@ function install() {
14
14
  if (installed)
15
15
  return;
16
16
  installed = true;
17
- process.once('exit', fireAll);
17
+ process.on('exit', fireAll);
18
18
  for (const sig of ['SIGINT', 'SIGTERM', 'SIGHUP']) {
19
- process.once(sig, () => {
19
+ process.on(sig, () => {
20
20
  fireAll();
21
21
  process.exit(sig === 'SIGINT' ? 130 : 1);
22
22
  });
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/core/cleanup.ts"],"names":[],"mappings":"AACA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAW,CAAA;AACnC,IAAI,SAAS,GAAG,KAAK,CAAA;AAErB,SAAS,OAAO;IACd,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,CAAC,EAAE,CAAA;QACL,CAAC;QAAC,MAAM,CAAC;YACP,iCAAiC;QACnC,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,OAAO;IACd,IAAI,SAAS;QAAE,OAAM;IACrB,SAAS,GAAG,IAAI,CAAA;IAChB,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAU,EAAE,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE;YACrB,OAAO,EAAE,CAAA;YACT,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,MAAM,CAAC,EAAW;IAChC,OAAO,EAAE,CAAA;IACT,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAChB,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAClC,CAAC"}
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/core/cleanup.ts"],"names":[],"mappings":"AACA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAW,CAAA;AACnC,IAAI,SAAS,GAAG,KAAK,CAAA;AAErB,SAAS,OAAO;IACd,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,CAAC,EAAE,CAAA;QACL,CAAC;QAAC,MAAM,CAAC;YACP,iCAAiC;QACnC,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,OAAO;IACd,IAAI,SAAS;QAAE,OAAM;IACrB,SAAS,GAAG,IAAI,CAAA;IAChB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC3B,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAU,EAAE,CAAC;QAC3D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE;YACnB,OAAO,EAAE,CAAA;YACT,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC1C,CAAC,CAAC,CAAA;IACJ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,MAAM,CAAC,EAAW;IAChC,OAAO,EAAE,CAAA;IACT,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAChB,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AAClC,CAAC"}
package/core/colors.d.ts CHANGED
@@ -11,6 +11,7 @@ export declare function makeColors(opts?: ColorOptions): {
11
11
  italic: (s: string) => string;
12
12
  underline: (s: string) => string;
13
13
  inverse: (s: string) => string;
14
+ conceal: (s: string) => string;
14
15
  cyan: (s: string) => string;
15
16
  green: (s: string) => string;
16
17
  red: (s: string) => string;
@@ -1 +1 @@
1
- {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/core/colors.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAajF;AAQD,wBAAgB,UAAU,CAAC,IAAI,GAAE,YAAiB;;cAEb,MAAM;aAAN,MAAM;gBAAN,MAAM;mBAAN,MAAM;iBAAN,MAAM;cAAN,MAAM;eAAN,MAAM;aAAN,MAAM;gBAAN,MAAM;cAAN,MAAM;gBACY,MAAM;aAA3C,MAAM,KAAK,MAAM,KAAK,MAAM,MAAM,GAAG,MAAM;qBAMnC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM;EA6B9F;AAED,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA"}
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/core/colors.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAajF;AAQD,wBAAgB,UAAU,CAAC,IAAI,GAAE,YAAiB;;cAEb,MAAM;aAAN,MAAM;gBAAN,MAAM;mBAAN,MAAM;iBAAN,MAAM;iBAAN,MAAM;cAAN,MAAM;eAAN,MAAM;aAAN,MAAM;gBAAN,MAAM;cAAN,MAAM;gBACY,MAAM;aAA3C,MAAM,KAAK,MAAM,KAAK,MAAM,MAAM,GAAG,MAAM;qBAMnC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM;EAiC9F;AAED,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAA"}
package/core/colors.js CHANGED
@@ -52,6 +52,10 @@ export function makeColors(opts = {}) {
52
52
  italic: wrap('3'),
53
53
  underline: wrap('4'),
54
54
  inverse: wrap('7'),
55
+ // SGR 8 — occupies its normal cell width but renders invisibly (where the
56
+ // terminal supports it). Used for the always-present active-row chevron so
57
+ // inactive rows reserve the exact same column without showing the glyph.
58
+ conceal: wrap('8'),
55
59
  cyan: wrap('36'),
56
60
  green: wrap('32'),
57
61
  red: wrap('31'),
@@ -1 +1 @@
1
- {"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/core/colors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/core/colors.ts"],"names":[],"mappings":"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"}
@@ -10,5 +10,9 @@ export interface PaginationArgs<T> {
10
10
  loop?: boolean;
11
11
  renderItem: (args: RenderItemArgs<T>) => string;
12
12
  }
13
- export declare function usePagination<T>({ items, active, pageSize, loop, renderItem, }: PaginationArgs<T>): string;
13
+ export interface PaginationResult {
14
+ lines: string;
15
+ windowTop: number;
16
+ }
17
+ export declare function usePagination<T>({ items, active, pageSize, loop, renderItem, }: PaginationArgs<T>): PaginationResult;
14
18
  //# sourceMappingURL=pagination.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/core/pagination.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,IAAI,EAAE,CAAC,CAAA;IACP,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,KAAK,EAAE,SAAS,CAAC,EAAE,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,UAAU,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,MAAM,CAAA;CAChD;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,EAC/B,KAAK,EACL,MAAM,EACN,QAAQ,EACR,IAAW,EACX,UAAU,GACX,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,MAAM,CA8B5B"}
1
+ {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/core/pagination.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,IAAI,EAAE,CAAC,CAAA;IACP,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,KAAK,EAAE,SAAS,CAAC,EAAE,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,UAAU,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,MAAM,CAAA;CAChD;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,EAC/B,KAAK,EACL,MAAM,EACN,QAAQ,EACR,IAAW,EACX,UAAU,GACX,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,gBAAgB,CA2BtC"}
@@ -3,22 +3,18 @@ export function usePagination({ items, active, pageSize, loop = true, renderItem
3
3
  const pointer = useRef(0); // active row position within the visible window
4
4
  const size = Math.min(pageSize, items.length);
5
5
  if (items.length === 0)
6
- return '';
7
- // Keep the active row's window position stable, clamping at list edges (non-loop).
6
+ return { lines: '', windowTop: 0 };
7
+ // Keep the window stable: only scroll when the active item would leave the visible region.
8
+ // Both loop and non-loop modes use the same edge-clamping logic so the window doesn't
9
+ // shift on every keypress — the cursor moves to the edge first, then the list scrolls.
8
10
  if (size < items.length) {
9
- if (loop) {
10
- // Center-ish: move the pointer with the active item, wrapping.
11
- pointer.current = Math.floor(size / 2);
12
- }
13
- else {
14
- const half = Math.floor(size / 2);
15
- if (active < half)
16
- pointer.current = active;
17
- else if (active >= items.length - half)
18
- pointer.current = size - (items.length - active);
19
- else
20
- pointer.current = half;
21
- }
11
+ const half = Math.floor(size / 2);
12
+ if (active < half)
13
+ pointer.current = active;
14
+ else if (active >= items.length - half)
15
+ pointer.current = size - (items.length - active);
16
+ else
17
+ pointer.current = half;
22
18
  }
23
19
  else {
24
20
  pointer.current = active;
@@ -31,6 +27,6 @@ export function usePagination({ items, active, pageSize, loop = true, renderItem
31
27
  const index = loop ? (top + i) % items.length : top + i;
32
28
  lines.push(renderItem({ item: items[index], index, isActive: index === active }));
33
29
  }
34
- return lines.join('\n');
30
+ return { lines: lines.join('\n'), windowTop: top };
35
31
  }
36
32
  //# sourceMappingURL=pagination.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/core/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAgBnC,MAAM,UAAU,aAAa,CAAI,EAC/B,KAAK,EACL,MAAM,EACN,QAAQ,EACR,IAAI,GAAG,IAAI,EACX,UAAU,GACQ;IAClB,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA,CAAC,gDAAgD;IAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC7C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAEjC,mFAAmF;IACnF,IAAI,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACxB,IAAI,IAAI,EAAE,CAAC;YACT,+DAA+D;YAC/D,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAA;QACxC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAA;YACjC,IAAI,MAAM,GAAG,IAAI;gBAAE,OAAO,CAAC,OAAO,GAAG,MAAM,CAAA;iBACtC,IAAI,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI;gBAAE,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAA;;gBACnF,OAAO,CAAC,OAAO,GAAG,IAAI,CAAA;QAC7B,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,OAAO,GAAG,MAAM,CAAA;IAC1B,CAAC;IAED,MAAM,GAAG,GAAG,IAAI;QACd,CAAC,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM;QAC1D,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAA;IAExE,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAA;QACvD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,KAAK,MAAM,EAAE,CAAC,CAAC,CAAA;IACnF,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
1
+ {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/core/pagination.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAqBnC,MAAM,UAAU,aAAa,CAAI,EAC/B,KAAK,EACL,MAAM,EACN,QAAQ,EACR,IAAI,GAAG,IAAI,EACX,UAAU,GACQ;IAClB,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA,CAAC,gDAAgD;IAC1E,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC7C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,CAAA;IAE1D,2FAA2F;IAC3F,sFAAsF;IACtF,uFAAuF;IACvF,IAAI,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAA;QACjC,IAAI,MAAM,GAAG,IAAI;YAAE,OAAO,CAAC,OAAO,GAAG,MAAM,CAAA;aACtC,IAAI,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI;YAAE,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAA;;YACnF,OAAO,CAAC,OAAO,GAAG,IAAI,CAAA;IAC7B,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,OAAO,GAAG,MAAM,CAAA;IAC1B,CAAC;IAED,MAAM,GAAG,GAAG,IAAI;QACd,CAAC,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM;QAC1D,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAA;IAExE,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAA;QACvD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,KAAK,MAAM,EAAE,CAAC,CAAC,CAAA;IACnF,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAA;AACpD,CAAC"}
package/core/screen.d.ts CHANGED
@@ -1,6 +1,13 @@
1
+ /**
2
+ * Line-diffing terminal renderer. Only the lines that actually changed since the
3
+ * previous frame are repainted (per-line `eraseLine`), so unchanged lines never
4
+ * flash — even on terminals that don't support DEC synchronized output (e.g.
5
+ * macOS Terminal.app). Sync-output markers are still emitted as a bonus for
6
+ * terminals that do support them (atomic repaint).
7
+ */
1
8
  export declare class Screen {
2
9
  private readonly out;
3
- private height;
10
+ private prevLines;
4
11
  private offExit;
5
12
  private onResize;
6
13
  private lastRender;
@@ -1 +1 @@
1
- {"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../src/core/screen.ts"],"names":[],"mappings":"AAIA,qBAAa,MAAM;IAML,OAAO,CAAC,QAAQ,CAAC,GAAG;IALhC,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,QAAQ,CAA+E;IAC/F,OAAO,CAAC,UAAU,CAAgC;gBAErB,GAAG,EAAE,MAAM,CAAC,WAAW;IAEpD,OAAO,KAAK,OAAO,GAElB;IAED,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,IAAI;IAMZ,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAK,GAAG,IAAI;IAgBvC,IAAI,IAAI,IAAI;CAOb"}
1
+ {"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../src/core/screen.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,qBAAa,MAAM;IAML,OAAO,CAAC,QAAQ,CAAC,GAAG;IALhC,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,QAAQ,CAA+E;IAC/F,OAAO,CAAC,UAAU,CAAgC;gBAErB,GAAG,EAAE,MAAM,CAAC,WAAW;IAEpD,OAAO,KAAK,OAAO,GAElB;IAED,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,IAAI;IAMZ,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAK,GAAG,IAAI;IA4CvC,IAAI,IAAI,IAAI;CAOb"}
package/core/screen.js CHANGED
@@ -1,9 +1,16 @@
1
1
  import { ansi } from './ansi.js';
2
2
  import { onExit } from './cleanup.js';
3
- import { wrapToWidth } from './width.js';
3
+ import { displayWidth, wrapToWidth } from './width.js';
4
+ /**
5
+ * Line-diffing terminal renderer. Only the lines that actually changed since the
6
+ * previous frame are repainted (per-line `eraseLine`), so unchanged lines never
7
+ * flash — even on terminals that don't support DEC synchronized output (e.g.
8
+ * macOS Terminal.app). Sync-output markers are still emitted as a bonus for
9
+ * terminals that do support them (atomic repaint).
10
+ */
4
11
  export class Screen {
5
12
  out;
6
- height = 0;
13
+ prevLines = [];
7
14
  offExit = null;
8
15
  onResize = () => this.lastRender && this.render(this.lastRender[0], this.lastRender[1]);
9
16
  lastRender = null;
@@ -26,24 +33,51 @@ export class Screen {
26
33
  render(body, bottom = '') {
27
34
  this.lastRender = [body, bottom];
28
35
  const frame = bottom ? `${body}\n${bottom}` : body;
29
- const lines = this.wrap(frame);
36
+ const next = this.wrap(frame);
37
+ const prev = this.prevLines;
30
38
  let buf = ansi.beginSync;
31
- if (this.height > 0) {
32
- buf += ansi.cursorTo(0);
33
- if (this.height > 1)
34
- buf += ansi.cursorUp(this.height - 1);
35
- buf += ansi.eraseDown;
39
+ if (prev.length === 0) {
40
+ // First paint — write the whole frame once.
41
+ buf += next.join('\n');
42
+ }
43
+ else {
44
+ // Move to column 0 of the first line of the previous block.
45
+ buf += '\r';
46
+ if (prev.length > 1)
47
+ buf += ansi.cursorUp(prev.length - 1);
48
+ const max = Math.max(prev.length, next.length);
49
+ for (let i = 0; i < max; i++) {
50
+ if (i > 0)
51
+ buf += '\n\r'; // advance to next line, column 0
52
+ if (i < next.length) {
53
+ // Overwrite in-place rather than erase-then-write: write the new content
54
+ // then pad with spaces to the terminal width. This covers any longer old
55
+ // content in a single write, so the line never flashes blank.
56
+ if (next[i] !== prev[i]) {
57
+ const pad = Math.max(0, this.columns - displayWidth(next[i]));
58
+ buf += next[i] + ' '.repeat(pad);
59
+ }
60
+ }
61
+ else {
62
+ // Line existed before but not now — blank it.
63
+ buf += ansi.eraseLine;
64
+ }
65
+ }
66
+ // If the new frame is shorter, the cursor is parked on an old (now-blank)
67
+ // line; move it back up to the real last content line so height tracking
68
+ // stays correct for the next diff.
69
+ if (next.length < prev.length)
70
+ buf += ansi.cursorUp(prev.length - next.length);
36
71
  }
37
- buf += lines.join('\n');
38
72
  buf += ansi.endSync;
39
73
  this.out.write(buf);
40
- this.height = lines.length;
74
+ this.prevLines = next;
41
75
  }
42
76
  done() {
43
77
  this.out.write(`${ansi.showCursor}\n`);
44
78
  this.out.off?.('resize', this.onResize);
45
79
  this.offExit?.();
46
- this.height = 0;
80
+ this.prevLines = [];
47
81
  this.lastRender = null;
48
82
  }
49
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"screen.js","sourceRoot":"","sources":["../../src/core/screen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAExC,MAAM,OAAO,MAAM;IAMY;IALrB,MAAM,GAAG,CAAC,CAAA;IACV,OAAO,GAAwB,IAAI,CAAA;IACnC,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;IACvF,UAAU,GAA4B,IAAI,CAAA;IAElD,YAA6B,GAAuB;QAAvB,QAAG,GAAH,GAAG,CAAoB;IAAG,CAAC;IAExD,IAAY,OAAO;QACjB,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAA;IAC/B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAC/B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAA;QAC5D,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;IACxC,CAAC;IAEO,IAAI,CAAC,KAAa;QACxB,OAAO,KAAK;aACT,KAAK,CAAC,IAAI,CAAC;aACX,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAC9E,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,MAAM,GAAG,EAAE;QAC9B,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAChC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;QAClD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC9B,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAA;QACxB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;YACvB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;YAC1D,GAAG,IAAI,IAAI,CAAC,SAAS,CAAA;QACvB,CAAC;QACD,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACvB,GAAG,IAAI,IAAI,CAAC,OAAO,CAAA;QACnB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACnB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;IAC5B,CAAC;IAED,IAAI;QACF,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAA;QACtC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QACvC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAA;QAChB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;QACf,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;IACxB,CAAC;CACF"}
1
+ {"version":3,"file":"screen.js","sourceRoot":"","sources":["../../src/core/screen.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"status-glyph.d.ts","sourceRoot":"","sources":["../../src/core/status-glyph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAE3C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,eAAe,GAAG,MAAM,CAYnF"}
1
+ {"version":3,"file":"status-glyph.d.ts","sourceRoot":"","sources":["../../src/core/status-glyph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAE3C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,eAAe,GAAG,MAAM,CAkBnF"}
@@ -1,14 +1,20 @@
1
- import { useState, useEffect } from './hooks.js';
1
+ import { useState, useEffect, useRef } from './hooks.js';
2
2
  export function useStatusGlyph({ status, colors, symbols }) {
3
- const [frame, setFrame] = useState(0);
3
+ const frameRef = useRef(0);
4
+ // _tick is only read by useState to trigger re-renders; frame value lives in frameRef.
5
+ const [_tick, forceRender] = useState(0);
4
6
  useEffect(() => {
5
7
  if (status !== 'loading')
6
8
  return;
7
- const id = setInterval(() => setFrame((frame + 1) % symbols.spinnerFrames.length), 80);
9
+ let tick = 0;
10
+ const id = setInterval(() => {
11
+ frameRef.current = (frameRef.current + 1) % symbols.spinnerFrames.length;
12
+ forceRender(++tick);
13
+ }, 80);
8
14
  return () => clearInterval(id);
9
15
  }, [status]);
10
16
  if (status === 'loading')
11
- return colors.cyan(symbols.spinnerFrames[frame]);
17
+ return colors.cyan(symbols.spinnerFrames[frameRef.current]);
12
18
  if (status === 'done')
13
19
  return colors.green(symbols.stepDone);
14
20
  if (status === 'canceled')
@@ -1 +1 @@
1
- {"version":3,"file":"status-glyph.js","sourceRoot":"","sources":["../../src/core/status-glyph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAWhD,MAAM,UAAU,cAAc,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAmB;IACzE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACrC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,KAAK,SAAS;YAAE,OAAM;QAChC,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAA;QACtF,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;IAChC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAA;IAC1E,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC5D,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IAChE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;AACxC,CAAC"}
1
+ {"version":3,"file":"status-glyph.js","sourceRoot":"","sources":["../../src/core/status-glyph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAWxD,MAAM,UAAU,cAAc,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAmB;IACzE,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;IAC1B,uFAAuF;IACvF,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IACxC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,KAAK,SAAS;YAAE,OAAM;QAChC,IAAI,IAAI,GAAG,CAAC,CAAA;QACZ,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE;YAC1B,QAAQ,CAAC,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAA;YACxE,WAAW,CAAC,EAAE,IAAI,CAAC,CAAA;QACrB,CAAC,EAAE,EAAE,CAAC,CAAA;QACN,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAA;IAChC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAA;IACrF,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC5D,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IAChE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;AACxC,CAAC"}
package/core/symbols.d.ts CHANGED
@@ -12,6 +12,7 @@ export declare function makeSymbols(unicode?: boolean): {
12
12
  checkOn: string;
13
13
  checkOff: string;
14
14
  pointer: string;
15
+ pointerLeft: string;
15
16
  cornerTL: string;
16
17
  cornerTR: string;
17
18
  cornerBL: string;
@@ -1 +1 @@
1
- {"version":3,"file":"symbols.d.ts","sourceRoot":"","sources":["../../src/core/symbols.ts"],"names":[],"mappings":"AAGA,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAUhF;AAED,wBAAgB,WAAW,CAAC,OAAO,UAAuB;;;;;;;;;;;;;;;;;;;;;;;EA2BzD;AAED,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA"}
1
+ {"version":3,"file":"symbols.d.ts","sourceRoot":"","sources":["../../src/core/symbols.ts"],"names":[],"mappings":"AAGA,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAUhF;AAED,wBAAgB,WAAW,CAAC,OAAO,UAAuB;;;;;;;;;;;;;;;;;;;;;;;;EA4BzD;AAED,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA"}
package/core/symbols.js CHANGED
@@ -25,6 +25,7 @@ export function makeSymbols(unicode = isUnicodeSupported()) {
25
25
  checkOn: u('◼', '[x]'),
26
26
  checkOff: u('◻', '[ ]'),
27
27
  pointer: u('❯', '>'),
28
+ pointerLeft: u('❮', '<'),
28
29
  cornerTL: u('╭', '+'),
29
30
  cornerTR: u('╮', '+'),
30
31
  cornerBL: u('╰', '+'),
@@ -1 +1 @@
1
- {"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/core/symbols.ts"],"names":[],"mappings":"AAAA,sBAAsB;AAEtB,4EAA4E;AAC5E,MAAM,UAAU,kBAAkB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACrE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC,IAAI,KAAK,OAAO,CAAA;IAC7D,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,mBAAmB;QAC9C,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAC7B,GAAG,CAAC,UAAU,KAAK,cAAc;QACjC,GAAG,CAAC,YAAY,KAAK,QAAQ;QAC7B,GAAG,CAAC,IAAI,KAAK,gBAAgB;QAC7B,GAAG,CAAC,IAAI,KAAK,WAAW,CACzB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAO,GAAG,kBAAkB,EAAE;IACxD,MAAM,CAAC,GAAG,CAAI,GAAM,EAAE,KAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IAC1D,OAAO;QACL,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACpB,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACpB,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACtB,UAAU,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACvB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,UAAU,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACvB,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACtB,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACpB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC;QACtB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC;QACvB,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACpB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACjB,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACjB,qDAAqD;QACrD,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACnB,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACtB,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACtB,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;KACpG,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/core/symbols.ts"],"names":[],"mappings":"AAAA,sBAAsB;AAEtB,4EAA4E;AAC5E,MAAM,UAAU,kBAAkB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACrE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC,IAAI,KAAK,OAAO,CAAA;IAC7D,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,mBAAmB;QAC9C,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAC7B,GAAG,CAAC,UAAU,KAAK,cAAc;QACjC,GAAG,CAAC,YAAY,KAAK,QAAQ;QAC7B,GAAG,CAAC,IAAI,KAAK,gBAAgB;QAC7B,GAAG,CAAC,IAAI,KAAK,WAAW,CACzB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAO,GAAG,kBAAkB,EAAE;IACxD,MAAM,CAAC,GAAG,CAAI,GAAM,EAAE,KAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IAC1D,OAAO;QACL,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACpB,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACpB,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACtB,UAAU,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACvB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,UAAU,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACvB,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACtB,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACpB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC;QACtB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC;QACvB,OAAO,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACpB,WAAW,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACxB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACrB,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACjB,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACjB,qDAAqD;QACrD,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACnB,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACtB,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QACtB,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;KACpG,CAAA;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/core/testing.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AA+BzC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;IACtD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IAClB,MAAM,EAAE,UAAU,CAAA;IAClB,SAAS,IAAI,MAAM,CAAA;CACpB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,CAAC,EACxC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,GAAG,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE,KAAK,OAAO,CAAC,CAAC,CAAC,EAC3E,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAgBxB"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../src/core/testing.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AA0HzC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;IACtD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IAClB,MAAM,EAAE,UAAU,CAAA;IAClB,SAAS,IAAI,MAAM,CAAA;CACpB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,CAAC,EACxC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,GAAG,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE,KAAK,OAAO,CAAC,CAAC,CAAC,EAC3E,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAgBxB"}
package/core/testing.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { EventEmitter } from 'node:events';
2
- import { stripAnsi } from './width.js';
3
2
  class FakeInput extends EventEmitter {
4
3
  isTTY = false;
5
4
  setRawMode() { }
@@ -11,20 +10,108 @@ class FakeInput extends EventEmitter {
11
10
  this.emit('keypress', key.sequence, key);
12
11
  }
13
12
  }
13
+ /**
14
+ * A minimal virtual terminal. It records every write and, on demand, replays the
15
+ * whole stream into a line buffer — honoring cursor moves, line/whole-screen
16
+ * erases, and carriage returns. This is what makes a *line-diff* renderer (which
17
+ * only re-emits the lines that changed) testable: `getScreen()` reflects the true
18
+ * on-screen state, not just the bytes of the last frame. SGR/colour and private
19
+ * modes (synchronized output, cursor hide/show) are zero-width and ignored.
20
+ */
14
21
  class FakeOutput extends EventEmitter {
15
22
  columns = 80;
16
23
  isTTY = true;
17
- buffer = '';
24
+ writes = '';
18
25
  write(s) {
19
- // Synchronized-output + erase sequences are stripped for assertion simplicity;
20
- // we keep only the latest "frame" by resetting on the begin-sync marker.
21
- this.buffer += s;
26
+ this.writes += s;
22
27
  return true;
23
28
  }
24
- latestFrame() {
25
- // Keep text after the final beginSync marker, strip all ANSI.
26
- const parts = this.buffer.split('\x1b[?2026h');
27
- return stripAnsi(parts[parts.length - 1] ?? '');
29
+ /** Replay the full write stream into a fresh line buffer and return it. */
30
+ screen() {
31
+ const lines = [''];
32
+ let row = 0;
33
+ let col = 0;
34
+ const s = this.writes;
35
+ let i = 0;
36
+ const ensureRow = () => {
37
+ while (lines.length <= row)
38
+ lines.push('');
39
+ };
40
+ const put = (ch) => {
41
+ ensureRow();
42
+ let line = lines[row];
43
+ if (line.length < col)
44
+ line += ' '.repeat(col - line.length);
45
+ lines[row] = line.slice(0, col) + ch + line.slice(col + 1);
46
+ col += 1;
47
+ };
48
+ while (i < s.length) {
49
+ const ch = s[i];
50
+ if (ch === '\x1b' && s[i + 1] === '[') {
51
+ // Parse a CSI sequence: ESC [ [?] params final
52
+ let j = i + 2;
53
+ let question = false;
54
+ if (s[j] === '?') {
55
+ question = true;
56
+ j += 1;
57
+ }
58
+ let params = '';
59
+ while (j < s.length && /[0-9;]/.test(s[j])) {
60
+ params += s[j];
61
+ j += 1;
62
+ }
63
+ const final = s[j] ?? '';
64
+ const n = parseInt(params, 10) || 0;
65
+ if (!question) {
66
+ switch (final) {
67
+ case 'A':
68
+ row = Math.max(0, row - Math.max(1, n));
69
+ break;
70
+ case 'B':
71
+ row += Math.max(1, n);
72
+ ensureRow();
73
+ break;
74
+ case 'C':
75
+ col += Math.max(1, n);
76
+ break;
77
+ case 'D':
78
+ col = Math.max(0, col - Math.max(1, n));
79
+ break;
80
+ case 'G':
81
+ col = Math.max(0, (n || 1) - 1);
82
+ break;
83
+ case 'K': // erase line (0/2 → whole line for our purposes)
84
+ ensureRow();
85
+ lines[row] = '';
86
+ break;
87
+ case 'J': // erase from cursor down
88
+ ensureRow();
89
+ lines[row] = lines[row].slice(0, col);
90
+ lines.length = row + 1;
91
+ break;
92
+ // 'm' (SGR) and anything else: no layout effect
93
+ }
94
+ }
95
+ // private modes (?2026h/l, ?25h/l) and SGR: skip
96
+ i = j + 1;
97
+ continue;
98
+ }
99
+ if (ch === '\n') {
100
+ row += 1;
101
+ col = 0;
102
+ ensureRow();
103
+ i += 1;
104
+ continue;
105
+ }
106
+ if (ch === '\r') {
107
+ col = 0;
108
+ i += 1;
109
+ continue;
110
+ }
111
+ put(ch);
112
+ i += 1;
113
+ }
114
+ return lines.join('\n');
28
115
  }
29
116
  }
30
117
  export async function renderTest(picker, config) {
@@ -42,6 +129,6 @@ export async function renderTest(picker, config) {
42
129
  };
43
130
  // Let the initial render settle.
44
131
  await Promise.resolve();
45
- return { answer, events, getScreen: () => output.latestFrame().trim() };
132
+ return { answer, events, getScreen: () => output.screen().replace(/[ \t]+$/gm, '').replace(/\n+$/, '') };
46
133
  }
47
134
  //# sourceMappingURL=testing.js.map