@vincemakes/kiso-tui 0.20.3 → 0.21.0

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/dist/ask-panel.js CHANGED
@@ -418,7 +418,7 @@ export function askStatus(view, state) {
418
418
  // that no competitor can copy without building the log first.
419
419
  const total = view.ask.questions.length;
420
420
  const where = total > 1 ? `question ${state.qIndex + 1} of ${total}` : "a question for you";
421
- return `⏸ ${where} · answers are durable facts`;
421
+ return `❯ ${where} · answers are durable facts`;
422
422
  }
423
423
  /** The input row's lead: the digit lead while picking, the typing lead
424
424
  * in the custom phase (the rule-input phase's shape, reused). */
@@ -508,7 +508,7 @@ export function askView(spec) {
508
508
  name: "ask_user",
509
509
  title: first.header ?? first.question,
510
510
  speaker: "kiso",
511
- statusText: " a question for you",
511
+ statusText: " a question for you",
512
512
  args: { kind: "text", lines: askDeclineList(spec) },
513
513
  fallbackQuestion: `⚠ ${escapeTerminal(first.question)} — this terminal cannot show the option panel; the question is declined `,
514
514
  ask: spec,
@@ -221,21 +221,21 @@ export declare class Body {
221
221
  };
222
222
  /** Whether the viewer owns the live region right now. */
223
223
  viewerOpen(): boolean;
224
- /** ctrl+o — open on the newest fold, or close. */
224
+ /** ctrl+r — open on the newest fold, or close. */
225
225
  viewerToggleMode(): void;
226
226
  /** The viewer's keys. Everything the surface can do, a key does —
227
227
  * there is no pointer, so there is nothing a pointer could reach
228
228
  * that a keyboard cannot. */
229
229
  viewerKey(cmd: "up" | "down" | "toggle" | "all" | "pageUp" | "pageDown" | "home" | "end"): void;
230
230
  /**
231
- * DC-35 — ctrl+r does not print the same expansion twice in a row.
231
+ * DC-35 — ctrl+o does not print the same expansion twice in a row.
232
232
  *
233
233
  * The ring walks newest-back and restarts its cycle once every entry
234
234
  * has been opened (R4/C1, which is what makes the walk immune to the
235
235
  * ring growing underneath it). With a ring of ONE the restart is
236
236
  * immediate, so holding the key appended the identical block over
237
237
  * and over — the owner got three copies of the same four rows, each
238
- * closing with `ctrl+r opens the one before it`, a footer naming
238
+ * closing with `ctrl+o opens the one before it`, a footer naming
239
239
  * something that does not exist.
240
240
  *
241
241
  * The bar is the BOTTOM of the transcript, not "ever shown": once
@@ -47,7 +47,7 @@ import { MENU_ITEMS, displayWidth } from "./editor.js";
47
47
  import { leadWidth } from "./width.js"; // W23: the ONE width authority (the editor, #inputRow, and editCol share it)
48
48
  // KC3.5: the panel-slot reads come from the DISPATCHERS — one source
49
49
  // for four reads, so an ask can never render half as an approval.
50
- import { panelAffordanceOf, panelFrameOf, panelLeadOf, panelRowsOf, panelStatusOf } from "./ask-panel.js";
50
+ import { panelFrameOf, panelLeadOf, panelRowsOf, panelStatusOf } from "./ask-panel.js";
51
51
  import { MOUSE_OFF } from "./editor.js";
52
52
  import { atPanelRows, bandHeader } from "./at-picker.js";
53
53
  // TUI2-R2 ②: the session picker's rows — the band's third occupant.
@@ -93,7 +93,7 @@ function rolledTitle(cell) {
93
93
  * one.
94
94
  *
95
95
  * Extracted at R3b so the segment fold's expansion opens a run to the
96
- * SAME rows `ctrl+r` on the run itself would have opened. Two copies of
96
+ * SAME rows `ctrl+o` on the run itself would have opened. Two copies of
97
97
  * this would be two answers to "show me that run". */
98
98
  function rolledDetail(cell, W) {
99
99
  const p = palette();
@@ -331,7 +331,7 @@ export class Body {
331
331
  #mdBase = 0;
332
332
  #toolCells = new Map(); // callId → cell index (parallel tools)
333
333
  // W15: the collapsed (cut) tool cells — committed cells whose last
334
- // rendered row carried the "ctrl+r" affordance; the expand key's
334
+ // rendered row carried the "ctrl+o" affordance; the expand key's
335
335
  // cycling pointer walks this list from the newest back.
336
336
  #collapsed = [];
337
337
  /** R4 (C1) — the ring walk is by IDENTITY, not by a modular pointer.
@@ -1040,7 +1040,7 @@ export class Body {
1040
1040
  lastTool() {
1041
1041
  return this.#lastTool;
1042
1042
  }
1043
- /** W15 — the expand key's target (ctrl+r). A cell still in the LIVE
1043
+ /** W15 — the expand key's target (ctrl+o). A cell still in the LIVE
1044
1044
  * region (the newest live tool) TOGGLES in place — the compositor
1045
1045
  * owns those rows and redraws them (the body flips to the full
1046
1046
  * form, no cap). A committed cell can never toggle — history is
@@ -1050,7 +1050,7 @@ export class Body {
1050
1050
  * the header names the target ("N turns back" — the user cells
1051
1051
  * after it), so every press tells the user what they got. */
1052
1052
  /**
1053
- * TUI2-R2 ⑤ — the cell the next ctrl+r will act on, or -1.
1053
+ * TUI2-R2 ⑤ — the cell the next ctrl+o will act on, or -1.
1054
1054
  *
1055
1055
  * The rule is expandNext's own first loop, extracted verbatim: the
1056
1056
  * LAST live cell that can toggle. It is a separate method rather than
@@ -1158,7 +1158,7 @@ export class Body {
1158
1158
  const saved = head.rolled;
1159
1159
  head.rolled = rolledOf(run);
1160
1160
  // the run OPENS. The fold's key already asked to see the
1161
- // work, so what lands is the same rows `ctrl+r` on the
1161
+ // work, so what lands is the same rows `ctrl+o` on the
1162
1162
  // run itself would have opened — its title, then its
1163
1163
  // detail — never its collapsed row, which would make the
1164
1164
  // reader press a second time for what the first press
@@ -1226,7 +1226,7 @@ export class Body {
1226
1226
  viewerOpen() {
1227
1227
  return this.#viewer !== null;
1228
1228
  }
1229
- /** ctrl+o — open on the newest fold, or close. */
1229
+ /** ctrl+r — open on the newest fold, or close. */
1230
1230
  viewerToggleMode() {
1231
1231
  if (this.#viewer !== null) {
1232
1232
  this.#viewer = null;
@@ -1288,7 +1288,7 @@ export class Body {
1288
1288
  /**
1289
1289
  * The expandable things in the transcript, oldest first.
1290
1290
  *
1291
- * The set is `#collapsed` — the SAME ring `ctrl+r` walks — so the two
1291
+ * The set is `#collapsed` — the SAME ring `ctrl+o` walks — so the two
1292
1292
  * mechanisms can never disagree about what is reachable. The ring is
1293
1293
  * newest-first (it is unshifted on commit); reading order is the
1294
1294
  * other way, so it is reversed here.
@@ -1315,7 +1315,7 @@ export class Body {
1315
1315
  }
1316
1316
  if (cell.kind !== "tool")
1317
1317
  continue;
1318
- // the tool card's FULL body — the same rows its own ctrl+r
1318
+ // the tool card's FULL body — the same rows its own ctrl+o
1319
1319
  // opens. The expanded flag is saved and restored inside this
1320
1320
  // synchronous call, the pattern the rollup path has always
1321
1321
  // used for head.rolled; it never outlives the render, so the
@@ -1355,14 +1355,14 @@ export class Body {
1355
1355
  * transcript does not already END with. */
1356
1356
  #lastAppend = null;
1357
1357
  /**
1358
- * DC-35 — ctrl+r does not print the same expansion twice in a row.
1358
+ * DC-35 — ctrl+o does not print the same expansion twice in a row.
1359
1359
  *
1360
1360
  * The ring walks newest-back and restarts its cycle once every entry
1361
1361
  * has been opened (R4/C1, which is what makes the walk immune to the
1362
1362
  * ring growing underneath it). With a ring of ONE the restart is
1363
1363
  * immediate, so holding the key appended the identical block over
1364
1364
  * and over — the owner got three copies of the same four rows, each
1365
- * closing with `ctrl+r opens the one before it`, a footer naming
1365
+ * closing with `ctrl+o opens the one before it`, a footer naming
1366
1366
  * something that does not exist.
1367
1367
  *
1368
1368
  * The bar is the BOTTOM of the transcript, not "ever shown": once
@@ -1395,7 +1395,7 @@ export class Body {
1395
1395
  }
1396
1396
  // W20: the LIVE task block toggles in place too — the capped
1397
1397
  // form flips to the full list (the "done-collapse expands
1398
- // under ctrl+r" claim). The SETTLED block is already full —
1398
+ // under ctrl+o" claim). The SETTLED block is already full —
1399
1399
  // no toggle, and its rows carry no affordance, so it never
1400
1400
  // joins #collapsed (the committed /last append is moot).
1401
1401
  if (cell.kind === "checklist" && !cell.done) {
@@ -1462,12 +1462,12 @@ export class Body {
1462
1462
  // R3i phase 4 — THE FOOTER TELLS THE TRUTH ABOUT THIS PATH.
1463
1463
  //
1464
1464
  // The rows come from the rollup's own projection, whose last
1465
- // row reads `└ ctrl+r collapses` — true where it was written
1465
+ // row reads `└ ctrl+o collapses` — true where it was written
1466
1466
  // (the LIVE toggle, which really does close again) and false
1467
1467
  // here. A committed row is ink: ADR-0046 forbids rewriting
1468
1468
  // history, so nothing about this block can be taken back. The
1469
1469
  // next press opens the NEXT fold, and the row now says so.
1470
- const closing = rows.length > 0 && /ctrl\+r collapses/.test(rows[rows.length - 1] ?? "");
1470
+ const closing = rows.length > 0 && /ctrl\+o collapses/.test(rows[rows.length - 1] ?? "");
1471
1471
  const body = closing ? rows.slice(0, -1) : rows;
1472
1472
  return {
1473
1473
  kind: "appended",
@@ -1480,7 +1480,7 @@ export class Body {
1480
1480
  ...body,
1481
1481
  // R8a: an in-block note takes the block's indent, not a
1482
1482
  // second corner — the corner opens the body above it.
1483
- `${p.dim} end of expansion · ctrl+r opens the one before it${p.reset}`,
1483
+ `${p.dim} end of expansion · ctrl+o opens the one before it${p.reset}`,
1484
1484
  ],
1485
1485
  };
1486
1486
  }
@@ -1820,8 +1820,25 @@ export class Body {
1820
1820
  * now). */
1821
1821
  #statusSource() {
1822
1822
  const panel = this.#panelState?.() ?? null;
1823
+ // DC-38: the panel's STATUS replaces the CLI's painting status —
1824
+ // that half of W21 stands. The HINT does not come with it, because
1825
+ // the panel block already ends in its own affordance row and has
1826
+ // since TUI2-R1.5 ("the affordance — the phase's key hint, ONE
1827
+ // row"). Both sites read `panelAffordance`, neither knew about the
1828
+ // other, and an approval at W≥100 printed the same 48-cell sentence
1829
+ // twice, six rows apart.
1830
+ //
1831
+ // The block's copy is the one to keep, on two grounds. It sits next
1832
+ // to the options it names. And it never disappears: the status row
1833
+ // drops its hint when the left text plus the hint will not fit, so
1834
+ // the duplicate was width-dependent — one copy on an ask (long left
1835
+ // text), two on an approval (`❯ run paused`, twelve cells) — which
1836
+ // is why every fixed-width gate was blind to it. Each flavour's
1837
+ // block carries its own row (approval-panel.ts pushes it for the
1838
+ // approval and the pick, ask-panel.ts for the ask), so nothing is
1839
+ // lost anywhere.
1823
1840
  if (panel !== null)
1824
- return { status: panelStatusOf(panel), hint: panelAffordanceOf(panel) };
1841
+ return { status: panelStatusOf(panel), hint: undefined };
1825
1842
  // W22: while turns wait in the queue, the right hint shows the
1826
1843
  // count — the chips below carry the lines themselves.
1827
1844
  const queued = this.#queueState?.().length ?? 0;
@@ -2116,7 +2133,7 @@ export class Body {
2116
2133
  * The phases, in the order they are tested:
2117
2134
  * - an EXPANDED live cell outranks the slot (W15 — "the user asked
2118
2135
  * for it"): it renders in full, variable height. This is also
2119
- * DC-28's cure: mid-stretch `ctrl+r` had a target it toggled and
2136
+ * DC-28's cure: mid-stretch `ctrl+o` had a target it toggled and
2120
2137
  * never drew, so the press did nothing visible now and changed a
2121
2138
  * later expansion's shape;
2122
2139
  * - CALLS IN FLIGHT: one head row each within the budget, the tail
@@ -2161,8 +2178,8 @@ export class Body {
2161
2178
  //
2162
2179
  // (The approval half is a regression this round caused and its
2163
2180
  // gate caught: the first draft treated a pending approval as a
2164
- // call in flight, so `⏸ edit x.ts` lost its diff tail and the
2165
- // `ctrl+r to expand` note with it.)
2181
+ // call in flight, so `❯ edit x.ts` lost its diff tail and the
2182
+ // `ctrl+o to expand` note with it.)
2166
2183
  const owned = tools.filter((i) => toolAt(i).expanded || toolAt(i).state === "approval");
2167
2184
  if (owned.length > 0) {
2168
2185
  // In CELL ORDER, so the frame reads the way the work happened:
@@ -2621,7 +2638,7 @@ export class Body {
2621
2638
  panelSpan = frame.options;
2622
2639
  }
2623
2640
  else {
2624
- // TUI2-R2 ⑤ (D, candidate 1): the FOCUS — the cell the next ctrl+r
2641
+ // TUI2-R2 ⑤ (D, candidate 1): the FOCUS — the cell the next ctrl+o
2625
2642
  // will act on brightens its own token. The index is derived from
2626
2643
  // the SAME scan expandNext performs (#focusIndex shares its rule
2627
2644
  // by construction), so the marker can never point at a cell the
@@ -2702,24 +2719,37 @@ export class Body {
2702
2719
  // the steady state for the session's whole life. It repairs a
2703
2720
  // killed predecessor straight into the same state. The visible
2704
2721
  // cursor comes back exactly once, in editor.exit().
2705
- out.push("\x1b[r\x1b[?69l\x1b[?7h\x1b[?25l");
2706
- // REL-0152-D20 the mechanism is understood and the obvious fix
2707
- // is NOT taken here. See the finding.
2722
+ // DC-40 — H line feeds BEFORE the reset, from wherever the shell
2723
+ // left the cursor. The first frame is the full-redraw path and
2724
+ // addresses rows 1..H absolutely; at launch those rows are the
2725
+ // shell's (its prompt, the launch command, the tail of whatever
2726
+ // ran before), and the frame painted over them — gone, not in
2727
+ // the scrollback (REL-0152-D20 established the mechanism; 37/60
2728
+ // shell lines survived on Apple Terminal, every line ON SCREEN
2729
+ // lost). From cursor row r, H feeds move H−r rows and then
2730
+ // scroll exactly r: the shell's rows 1..r enter the scrollback
2731
+ // as CONTENT (at most one blank row — the cursor's own line),
2732
+ // the screen is blank, and the model's assumption "row 0 is the
2733
+ // terminal's row 1" is true by construction. The count does not
2734
+ // depend on r, so nothing is asked of the terminal.
2708
2735
  //
2709
- // The first frame addresses rows 1..H absolutely and draws over
2710
- // whatever the terminal was showing. Scrolling a screenful away
2711
- // first would fix that, and it was built and measured: it pushes
2712
- // up to H BLANK rows into the scrollback, and TUI2-R2pre's
2713
- // blank-share gate went from 14/43 to 29/43 past the "a
2714
- // healthy session's scrollback is mostly content" invariant that
2715
- // gate exists to hold. Trading a symptom with a five-second
2716
- // user-side setting for a broken invariant is a worse deal.
2736
+ // THE ORDER IS THE FIX. `ESC[r` (DECSTBM) HOMES THE CURSOR to
2737
+ // row 1 VT100 semantics, honoured by Apple Terminal, xterm,
2738
+ // xterm.js and tmux alike. Feeds emitted AFTER the reset start
2739
+ // from row 1, move H−1 rows and scroll ONE: measured on Apple
2740
+ // Terminal, 1/20 shell lines survived with an otherwise
2741
+ // byte-identical frame. Feeds BEFORE the reset: 20/20. The house
2742
+ // emulators did not model the homing and passed the wrong order;
2743
+ // VtScrollback does now, and the DC-40 gate is red on it.
2717
2744
  //
2718
- // The correct version scrolls only as far as the terminal's
2719
- // content actually reaches, which needs a cursor-position query
2720
- // at boot its own round, with its own risk (this file already
2721
- // declined a boot-time round-trip once, for racing the editor
2722
- // for stdin).
2745
+ // The reset still precedes the FRAME (REL-0152-D19: a frame
2746
+ // drawn into an inherited sub-region is the defect); only the
2747
+ // feeds run under whatever region the shell left. A region a
2748
+ // killed foreign program left set makes the feeds scroll that
2749
+ // region alone and the frame paint over the rows outside it —
2750
+ // which is what every frame did before this fix, never worse.
2751
+ out.push("\n".repeat(H));
2752
+ out.push("\x1b[r\x1b[?69l\x1b[?7h\x1b[?25l");
2723
2753
  }
2724
2754
  out.push("\x1b[?7l");
2725
2755
  // REL-0161: ?25l is the STEADY state now, not a frame bracket —
@@ -2852,11 +2882,11 @@ export class Body {
2852
2882
  #commitCell(i, W, ctx) {
2853
2883
  const cell = this.#cells[i];
2854
2884
  const lines = this.#foldOrRollup(cell, i, W, ctx);
2855
- // W15: a tool cell whose committed rows carried the "ctrl+r"
2885
+ // W15: a tool cell whose committed rows carried the "ctrl+o"
2856
2886
  // affordance joins the expand history — the detection is the
2857
2887
  // renderer's OWN output, so the read's "/last"-only cut note never
2858
2888
  // lands here. TUI2-R1 (A/B): the affordance is no longer only the
2859
- // renderer cut's "└ … ctrl+r" — the self-naming head suffix and
2889
+ // renderer cut's "└ … ctrl+o" — the self-naming head suffix and
2860
2890
  // the exploration row carry it on the HEAD row, and a promise the
2861
2891
  // key does not answer would be the one thing worse than silence.
2862
2892
  // unshift: the cells commit oldest-first, so the NEWEST cut lands
@@ -2870,13 +2900,13 @@ export class Body {
2870
2900
  // printed bytes.
2871
2901
  //
2872
2902
  // This used to require the rendered rows to contain the literal
2873
- // "ctrl+r", which made the affordance LOAD-BEARING: retiring the
2903
+ // "ctrl+o", which made the affordance LOAD-BEARING: retiring the
2874
2904
  // printed key (the owner's ruling) would have silently emptied the
2875
2905
  // ring and taken the expand key with it — not a missing hint, a
2876
2906
  // missing feature. A fold head is a fold head because the segment
2877
2907
  // says so; a tool cell is expandable when it is hiding rows.
2878
2908
  const isFoldHead = this.#segmentOf(i)?.headCell === i;
2879
- const hidesRows = cell.kind === "tool" && lines.some((l) => l.includes("ctrl+r"));
2909
+ const hidesRows = cell.kind === "tool" && lines.some((l) => l.includes("ctrl+o"));
2880
2910
  if (isFoldHead || hidesRows) {
2881
2911
  this.#collapsed.unshift(i);
2882
2912
  // R4a — a new fold resets the walk, so the FIRST press after any
package/dist/editor.js CHANGED
@@ -83,7 +83,7 @@ export function viewerCommand(text) {
83
83
  return "end";
84
84
  case "\x1b":
85
85
  case "q":
86
- case "\x0f": // ctrl+o — the key that opens it also puts it away
86
+ case "\x12": // ctrl+r — the key that opens it also puts it away
87
87
  return "close";
88
88
  default:
89
89
  return null;
@@ -275,7 +275,7 @@ export class Editor {
275
275
  // the CLI's — here it is only "these two keys, pressed together, hand
276
276
  // the line over by a different door than Enter's".
277
277
  #redirectCbs = [];
278
- // W15: the expand-key list (ctrl+r) — the CLI's dispatch decides the
278
+ // W15: the expand-key list (ctrl+o) — the CLI's dispatch decides the
279
279
  // target (a live cell toggles in place; a committed cell appends the
280
280
  // expanded block). Mirrors the escape list: multiple listeners can
281
281
  // coexist; the editor never interprets the key itself.
@@ -929,7 +929,7 @@ export class Editor {
929
929
  // sheet (which any key dismisses) this surface is INTERACTIVE, so
930
930
  // the chunk is matched against its own bindings and anything
931
931
  // unrecognised is swallowed rather than typed into the composer
932
- // behind it. esc closes; ctrl+o closes too, so the key that opens
932
+ // behind it. esc closes; ctrl+r closes too, so the key that opens
933
933
  // it also puts it away.
934
934
  if (this.#viewerUp?.() === true) {
935
935
  const cmd = viewerCommand(text);
@@ -1407,18 +1407,30 @@ export class Editor {
1407
1407
  }
1408
1408
  i += 1;
1409
1409
  }
1410
- else if (c === "\x12") {
1411
- // W15: the expand key (ctrl+r) — rides the chain like a
1412
- // command, the editor just forwards it.
1410
+ else if (c === "\x0f") {
1411
+ // W15: the expand key — rides the chain like a command, the
1412
+ // editor just forwards it.
1413
+ //
1414
+ // DC-41 (owner ruling 2026-09-02): this is ctrl+o now. R5
1415
+ // gave ctrl+o to the viewer because it was free and because
1416
+ // the reference implementation uses it — betting that the
1417
+ // finger cared about the KEY. It does not: the reference's
1418
+ // ctrl+o expands the tool output in front of you, which is
1419
+ // this action, and the owner reported reaching for it and
1420
+ // getting a reader. The gesture and the job are together
1421
+ // again; §7.1 is why kiso's form of it appends rather than
1422
+ // toggling in place.
1413
1423
  for (const cb of [...this.#expandCbs])
1414
1424
  cb();
1415
1425
  i += 1;
1416
1426
  }
1417
- else if (c === "\x0f" && this.#composerIdle() && this.#chars.length === 0) {
1418
- // R5 — ctrl+o opens the transcript viewer. Free in kiso, and
1419
- // the same key the reference implementation uses, so the
1420
- // muscle memory transfers even though what it opens is not
1421
- // the same surface. Idle composer only, exactly like `?`:
1427
+ else if (c === "\x12" && this.#composerIdle() && this.#chars.length === 0) {
1428
+ // R5 — the transcript viewer, on ctrl+r since DC-41. The
1429
+ // reference binds ctrl+r to renaming a session, which kiso
1430
+ // has no equivalent of, so nothing a reference user means by
1431
+ // it is displaced; every other free control key in this
1432
+ // dispatch collides with something that surface actually
1433
+ // does. Idle composer only, exactly like `?`:
1422
1434
  // mid-text it would be a keystroke stolen from the human.
1423
1435
  this.#viewerSend("open");
1424
1436
  i += 1;
package/dist/render.js CHANGED
@@ -72,7 +72,7 @@ export function renderEvent(ev, prevThinking = false, resolvePath = (p) => p) {
72
72
  case "permission_requested":
73
73
  // round 8: the tool NAME is model text — escaped like everything else.
74
74
  return {
75
- text: `⏸ ${escapeTerminal(ev.name)} needs approval ${p.dim}${approvalDetail(ev.name, ev.input, resolvePath)}${p.reset} `,
75
+ text: `❯ ${escapeTerminal(ev.name)} needs approval ${p.dim}${approvalDetail(ev.name, ev.input, resolvePath)}${p.reset} `,
76
76
  newline: false,
77
77
  prompt: true,
78
78
  };
@@ -38,7 +38,7 @@ import { visibleWidth } from "./components.js";
38
38
  /** The gutter every viewer row carries: the cursor mark and its space. */
39
39
  export const VIEWER_GUTTER = 3;
40
40
  export function viewerInit(entries) {
41
- // the cursor starts on the NEWEST fold — the one ctrl+r would have
41
+ // the cursor starts on the NEWEST fold — the one ctrl+o would have
42
42
  // opened, so the two mechanisms agree on their first answer.
43
43
  return { cursor: Math.max(0, entries.length - 1), top: 0, open: new Set() };
44
44
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-tui",
3
- "version": "0.20.3",
3
+ "version": "0.21.0",
4
4
  "description": "kiso tui — the pure terminal layer (cell renderer, dock, raw editor, diff, palette). Zero runtime dependencies: input is data, output is bytes.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -35,6 +35,6 @@
35
35
  },
36
36
  "homepage": "https://github.com/vincemakes/kiso/tree/main/packages/tui#readme",
37
37
  "dependencies": {
38
- "@vincemakes/kiso-tui-cells": "0.20.3"
38
+ "@vincemakes/kiso-tui-cells": "0.21.0"
39
39
  }
40
40
  }