@vincemakes/kiso-tui-cells 0.16.2 → 0.16.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.
- package/dist/approval-panel.d.ts +4 -3
- package/dist/approval-panel.js +136 -39
- package/dist/components.d.ts +21 -8
- package/dist/components.js +144 -48
- package/dist/ground.d.ts +46 -0
- package/dist/ground.js +76 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -1
- package/dist/md.d.ts +1 -1
- package/dist/md.js +73 -31
- package/dist/render.d.ts +47 -11
- package/dist/render.js +175 -20
- package/dist/strings.js +72 -28
- package/package.json +2 -2
package/dist/approval-panel.d.ts
CHANGED
|
@@ -262,7 +262,7 @@ export interface PanelView {
|
|
|
262
262
|
/** The fix hint per speaker (the v8 design §3.5 table). */
|
|
263
263
|
readonly hint?: string;
|
|
264
264
|
/** The options-phase status-left text — the CLI knows the context
|
|
265
|
-
* ("
|
|
265
|
+
* ("⏸ run paused", the trust gate's line). */
|
|
266
266
|
readonly statusText: string;
|
|
267
267
|
/** The ALWAYS-verbose args — the full command/content/diff. */
|
|
268
268
|
readonly args: PanelArgs;
|
|
@@ -385,12 +385,13 @@ export declare function panelBlockLayout(view: PanelView, phase: PanelPhase, cur
|
|
|
385
385
|
*/
|
|
386
386
|
export declare function panelLead(view: PanelView, phase: PanelPhase, cursor: number): string;
|
|
387
387
|
/** The lead's plain text — the editor's reflow width (the line must
|
|
388
|
-
* fit the lead + the
|
|
388
|
+
* fit the lead + the drawn cursor's own cell — R2 retired the box and
|
|
389
|
+
* its walls with it). */
|
|
389
390
|
export declare function panelLeadPlain(view: PanelView, phase: PanelPhase, cursor: number): string;
|
|
390
391
|
export declare function panelLeadWidth(view: PanelView, phase: PanelPhase, cursor: number): number;
|
|
391
392
|
/** The status row's left text while the panel is up — the phase, not
|
|
392
393
|
* the CLI's painting status (the compositor derives it from the panel
|
|
393
|
-
* state; the "
|
|
394
|
+
* state; the "⏸ run paused" etc. ride the options phase). */
|
|
394
395
|
export declare function panelStatus(view: PanelView, phase: PanelPhase, cursor: number): string;
|
|
395
396
|
/**
|
|
396
397
|
* The status row's right-aligned hint — the v4 frame's line, verbatim.
|
package/dist/approval-panel.js
CHANGED
|
@@ -193,7 +193,8 @@ function panelRuleText(view) {
|
|
|
193
193
|
const base = view.amended === true
|
|
194
194
|
? `${head}${p.dim}needs approval · (amended) — asked by${p.reset}${tail}`
|
|
195
195
|
: `${head}${p.dim}needs approval — asked by${p.reset}${tail}`;
|
|
196
|
-
|
|
196
|
+
// DC-3: the fix hint is metadata — it borrowed the inline-code tint.
|
|
197
|
+
return hint ? `${base}${p.dim} · ${escapeTerminal(hint)}${p.reset}` : base;
|
|
197
198
|
}
|
|
198
199
|
/**
|
|
199
200
|
* TUI2-R3v2 ① — ONE ROW PER OPTION, and the cursor's row is a bar.
|
|
@@ -204,21 +205,52 @@ function panelRuleText(view) {
|
|
|
204
205
|
* trade to make: each option owns a row, a narrow window cuts LABELS,
|
|
205
206
|
* and every choice stays reachable at every width the product survives.
|
|
206
207
|
*
|
|
207
|
-
* The unselected row
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
208
|
+
* The unselected row is a two-space indent; the selected row is the
|
|
209
|
+
* shared selectionBar, which spends its own two cells of frame. Both
|
|
210
|
+
* build their span against W−2, so the digit column does not shift as
|
|
211
|
+
* the bar walks — a column that moves per row reads as damage, which is
|
|
212
|
+
* the R2 picker's finding, inherited.
|
|
213
|
+
*
|
|
214
|
+
* R2 — two changes. The unselected row carried the block's │ gutter: a
|
|
215
|
+
* gutter SCOPES a verbatim block (the args keep theirs), and an option
|
|
216
|
+
* list is not verbatim, so it draws a boundary the block already has a
|
|
217
|
+
* rule for. And the cursor now carries `→` as well as the bar (design
|
|
218
|
+
* §7.5) — the bar is the loud signal, the arrow is the one that
|
|
219
|
+
* survives a strip, which is law 1.3's test applied to a selection.
|
|
212
220
|
*/
|
|
213
|
-
function panelOptionRow(option, n, selected, W) {
|
|
221
|
+
function panelOptionRow(option, n, selected, W, note, stop = 0) {
|
|
214
222
|
const p = palette();
|
|
215
223
|
const room = Math.max(1, W - 2);
|
|
216
|
-
const plain =
|
|
217
|
-
const
|
|
224
|
+
const plain = optionLead(option, n, selected);
|
|
225
|
+
const tail = note === undefined || note === ""
|
|
226
|
+
? ""
|
|
227
|
+
: stop > 0
|
|
228
|
+
? `${" ".repeat(Math.max(1, stop - visibleWidth(plain)))}${p.dim}${widthCut(escapeTerminal(note), Math.max(0, room - stop))}${p.reset}`
|
|
229
|
+
: `${p.dim} — ${escapeTerminal(note)}${p.reset}`;
|
|
230
|
+
const text = cutLine(`${selected ? p.bold : ""}${escapeTerminal(plain)}${p.reset}${tail}`, room);
|
|
218
231
|
if (!selected)
|
|
219
|
-
return
|
|
232
|
+
return ` ${text}`;
|
|
220
233
|
return selectionBar(text, visibleWidth(text), W);
|
|
221
234
|
}
|
|
235
|
+
/** The row's left span, PLAIN — written once so the column arithmetic
|
|
236
|
+
* and the row cannot disagree about how wide it is. */
|
|
237
|
+
function optionLead(option, n, selected) {
|
|
238
|
+
return `${selected ? "→" : " "} ${n} ${option.label}`;
|
|
239
|
+
}
|
|
240
|
+
/** R2 — the safer list's `why` column. Same rule as the ask panel's
|
|
241
|
+
* descriptions: computed over the WHOLE list so the column belongs to
|
|
242
|
+
* the list, and 0 (the em-dash fallback) when there is no room for it. */
|
|
243
|
+
function saferStop(options, W) {
|
|
244
|
+
// an empty list has no column to compute — `Math.max()` of nothing is
|
|
245
|
+
// -Infinity, which would sail through both guards below and return a
|
|
246
|
+
// negative stop
|
|
247
|
+
if (options.length === 0)
|
|
248
|
+
return 0;
|
|
249
|
+
const room = Math.max(1, W - 2);
|
|
250
|
+
const widest = Math.max(...options.map((o, i) => visibleWidth(optionLead({ kind: "allow", label: o.command }, i + 1, false))));
|
|
251
|
+
const stop = widest + 2;
|
|
252
|
+
return stop > Math.floor(room / 2) || room - stop < 18 ? 0 : stop;
|
|
253
|
+
}
|
|
222
254
|
/** The block's rows — EXACTLY the preview's frame shape, the gutter at
|
|
223
255
|
* the left edge (the preview's two-space mock indent is its own
|
|
224
256
|
* styling; the real rows sit at column 1, like every tool cell).
|
|
@@ -228,15 +260,27 @@ export function panelBlockRows(view, phase, cursor, W, maxRows, note, safer) {
|
|
|
228
260
|
}
|
|
229
261
|
export function panelBlockLayout(view, phase, cursor, W, maxRows, note, safer) {
|
|
230
262
|
const p = palette();
|
|
231
|
-
|
|
263
|
+
// R2: the block's own PROSE rows (the risk line, the safer-options
|
|
264
|
+
// note, the affordance) take the two-space indent every other row in
|
|
265
|
+
// the block takes. The │ gutter stays where it means something — on
|
|
266
|
+
// the args, which are verbatim, and which is the whole distinction:
|
|
267
|
+
// a gutter SCOPES a quotation, it is not a left edge for a panel.
|
|
268
|
+
const gutter = " ";
|
|
232
269
|
const rows = [];
|
|
233
|
-
|
|
234
|
-
|
|
270
|
+
// R2 — the block opens and closes with the SAME dashed rule the
|
|
271
|
+
// composer uses. It used to open with the │ gutter, divide with a
|
|
272
|
+
// ─ run and close with a └ rule: three edge vocabularies inside one
|
|
273
|
+
// block, and none of them the composer's. A rule SEPARATES, a gutter
|
|
274
|
+
// SCOPES — the args keep their gutter because they are a verbatim
|
|
275
|
+
// block; everything that was drawing a boundary is one rule now.
|
|
276
|
+
rows.push(`${p.dim}${"\u254c".repeat(Math.max(0, W))}${p.reset}`);
|
|
277
|
+
rows.push(` ${cutLine(panelRuleText(view), Math.max(1, W - 2))}`);
|
|
278
|
+
rows.push(` ${cutLine(`${p.bold}${escapeTerminal(view.title)}${p.reset}`, Math.max(1, W - 2))}`);
|
|
235
279
|
// TUI2-R1.5 ⑤ (VD-11): the divider is a LABEL, not a design note. "the
|
|
236
280
|
// full args — never truncated" is a sentence about the implementation,
|
|
237
281
|
// addressed to whoever was building the panel; the human reading it
|
|
238
282
|
// during an approval wants to know what the block below is.
|
|
239
|
-
rows.push(
|
|
283
|
+
rows.push("");
|
|
240
284
|
// the args — the bounded block's body: fold, then cap. The └ cut is
|
|
241
285
|
// ONE row (the W20 discipline): when the args exceed the budget, one
|
|
242
286
|
// notice row carries the count and where the rest is (the event log).
|
|
@@ -251,7 +295,12 @@ export function panelBlockLayout(view, phase, cursor, W, maxRows, note, safer) {
|
|
|
251
295
|
// they can also read in the event log is worth less than the row that
|
|
252
296
|
// carries the choice. The args keep a floor of one row so the block
|
|
253
297
|
// never claims to show what it is asking about and then shows nothing.
|
|
254
|
-
const chrome =
|
|
298
|
+
const chrome =
|
|
299
|
+
// R2: SIX rows of frame, not five — the block opens with a rule now
|
|
300
|
+
// as well as closing with one, and the divider row became a blank.
|
|
301
|
+
// The count is the same shape it always was: every row the block
|
|
302
|
+
// spends on itself before the args and the list share what is left.
|
|
303
|
+
6 +
|
|
255
304
|
(phase === "options" && note !== undefined ? 1 : 0) +
|
|
256
305
|
(view.riskHint !== undefined && view.riskHint !== "" ? 1 : 0) +
|
|
257
306
|
(phase === "asking" ? 1 : 0) +
|
|
@@ -296,9 +345,13 @@ export function panelBlockLayout(view, phase, cursor, W, maxRows, note, safer) {
|
|
|
296
345
|
// out of would be a trap.
|
|
297
346
|
if (phase === "safer" && safer !== undefined) {
|
|
298
347
|
offset = rows.length;
|
|
348
|
+
// R2: the `why` takes a COLUMN rather than running on after an em
|
|
349
|
+
// dash — the commands are what is being chosen between, and they
|
|
350
|
+
// only scan when they all start and end at the same columns.
|
|
351
|
+
const stop = saferStop(safer.options, W);
|
|
299
352
|
for (let i = 0; i < safer.options.length; i += 1) {
|
|
300
353
|
const o = safer.options[i];
|
|
301
|
-
rows.push(panelOptionRow({ kind: "allow", label:
|
|
354
|
+
rows.push(panelOptionRow({ kind: "allow", label: o.command }, i + 1, i === safer.cursor, W, o.why, stop));
|
|
302
355
|
}
|
|
303
356
|
rows.push(panelOptionRow({ kind: "deny", label: SAFER_BACK }, safer.options.length + 1, safer.cursor === safer.options.length, W));
|
|
304
357
|
}
|
|
@@ -335,7 +388,7 @@ export function panelBlockLayout(view, phase, cursor, W, maxRows, note, safer) {
|
|
|
335
388
|
// else in the product, so a CAPPED panel emitted two elbow rows in a
|
|
336
389
|
// row meaning entirely different things. The rule reads as an edge,
|
|
337
390
|
// and the cut notice above it reads as a notice.
|
|
338
|
-
rows.push(`${p.dim}
|
|
391
|
+
rows.push(`${p.dim}${"\u254c".repeat(Math.max(0, W))}${p.reset}`);
|
|
339
392
|
return { rows, ...layout };
|
|
340
393
|
}
|
|
341
394
|
/**
|
|
@@ -353,13 +406,24 @@ export function panelLead(view, phase, cursor) {
|
|
|
353
406
|
const p = palette();
|
|
354
407
|
if (phase === "amend")
|
|
355
408
|
return `${p.dim}amend› ${p.reset}`;
|
|
356
|
-
|
|
409
|
+
// R2: an EMPTY lead emits no bytes at all — `dim + reset` around
|
|
410
|
+
// nothing is eight bytes on the composer row of every frame a panel
|
|
411
|
+
// is up, and the row it wraps has no content to style.
|
|
412
|
+
return PANEL_IDLE_LEAD === "" ? "" : `${p.dim}${PANEL_IDLE_LEAD}${p.reset}`;
|
|
357
413
|
}
|
|
358
|
-
/** The composer's lead while a selection list owns the keys
|
|
359
|
-
*
|
|
360
|
-
|
|
414
|
+
/** The composer's lead while a selection list owns the keys.
|
|
415
|
+
*
|
|
416
|
+
* R2: EMPTY. It was a quiet chevron, on the argument that it is "not a
|
|
417
|
+
* prompt for input that is not being asked for" — but the composer
|
|
418
|
+
* dropped its own chevron this round (the cursor sits at column one),
|
|
419
|
+
* so the panel would have been the one surface reintroducing the glyph
|
|
420
|
+
* the rest of the product just removed. The NAMED leads stay: `amend›`
|
|
421
|
+
* and the pick panel's `1-4>` say where the keystrokes go, which is
|
|
422
|
+
* information rather than decoration. */
|
|
423
|
+
const PANEL_IDLE_LEAD = "";
|
|
361
424
|
/** The lead's plain text — the editor's reflow width (the line must
|
|
362
|
-
* fit the lead + the
|
|
425
|
+
* fit the lead + the drawn cursor's own cell — R2 retired the box and
|
|
426
|
+
* its walls with it). */
|
|
363
427
|
export function panelLeadPlain(view, phase, cursor) {
|
|
364
428
|
return phase === "amend" ? "amend› " : PANEL_IDLE_LEAD;
|
|
365
429
|
}
|
|
@@ -368,20 +432,25 @@ export function panelLeadWidth(view, phase, cursor) {
|
|
|
368
432
|
}
|
|
369
433
|
/** The status row's left text while the panel is up — the phase, not
|
|
370
434
|
* the CLI's painting status (the compositor derives it from the panel
|
|
371
|
-
* state; the "
|
|
435
|
+
* state; the "⏸ run paused" etc. ride the options phase). */
|
|
436
|
+
// R2 (design §4, the ⏸ ruling): a panel that is WAITING ON A HUMAN says
|
|
437
|
+
// so with the one mark that means it. `▸` is the checklist's "the
|
|
438
|
+
// current one" — a mark meaning two things is worse than two marks
|
|
439
|
+
// (law 4.2), and the thing this row has to convey is not "here" but
|
|
440
|
+
// "nothing moves until you answer".
|
|
372
441
|
export function panelStatus(view, phase, cursor) {
|
|
373
442
|
// TUI2-R3v2 ③: the frames' own words — what the panel is doing, and
|
|
374
443
|
// (in the safer list) what it did.
|
|
375
444
|
if (phase === "asking")
|
|
376
|
-
return "\
|
|
445
|
+
return "\u23f8 asked the model for safer options";
|
|
377
446
|
if (phase === "safer")
|
|
378
|
-
return "\
|
|
447
|
+
return "\u23f8 asked the model for safer options";
|
|
379
448
|
// TUI2-R3v2 ①: the typed phase says where the words GO. "the words ride
|
|
380
449
|
// the verdict" described the plumbing to whoever wrote it; the human
|
|
381
450
|
// typing needs to know the model will read this and answer with a new
|
|
382
451
|
// call — which is what the v4 frame says, in those words.
|
|
383
452
|
if (phase === "amend")
|
|
384
|
-
return "
|
|
453
|
+
return "⏸ your note goes to the model — it will propose a new call";
|
|
385
454
|
return view.statusText;
|
|
386
455
|
}
|
|
387
456
|
/**
|
|
@@ -424,32 +493,60 @@ export function panelAffordance(view, phase, cursor, safer) {
|
|
|
424
493
|
export function pickBlockRows(view, state, W, maxRows) {
|
|
425
494
|
const p = palette();
|
|
426
495
|
const spec = view.pick;
|
|
427
|
-
const
|
|
428
|
-
const rows = [];
|
|
496
|
+
const rows = [`${p.dim}${"\u254c".repeat(Math.max(0, W))}${p.reset}`]; // R2: the same rule the composer and the other panels use
|
|
429
497
|
const room = Math.max(1, W - 2);
|
|
430
|
-
rows.push(
|
|
498
|
+
rows.push(` ${cutLine(`${p.bold}${escapeTerminal(spec.header.split(" \u2014 ")[0] ?? spec.header)}${p.reset}${p.dim}${escapeTerminal(spec.header.slice((spec.header.split(" \u2014 ")[0] ?? "").length))}${p.reset}`, room)}`);
|
|
431
499
|
if (spec.options.length === 0) {
|
|
432
500
|
// the honest empty state \u2014 the caller's own copy, verbatim
|
|
433
|
-
rows.push(
|
|
501
|
+
rows.push(` ${cutLine(`${p.dim} ${escapeTerminal(spec.emptyNote ?? "no options")}${p.reset}`, room)}`);
|
|
434
502
|
}
|
|
435
503
|
else {
|
|
436
|
-
// the budget: the header, the t row, the
|
|
437
|
-
|
|
504
|
+
// the budget: the OPENING rule, the header, the t row, the
|
|
505
|
+
// affordance and the CLOSING rule — five, not four. R2 added the
|
|
506
|
+
// opening rule to this block and bumped the ask panel (5→6) and the
|
|
507
|
+
// approval panel (5→6) to pay for it, and missed this one: the
|
|
508
|
+
// block ran two rows over its budget, and two rows of committed
|
|
509
|
+
// content were scrolled irreversibly into the scrollback every time
|
|
510
|
+
// `/model` opened on a tight screen. The `+N more` row is a sixth
|
|
511
|
+
// when it appears, so it is paid for too.
|
|
512
|
+
const chrome = 5 + (spec.options.length > Math.min(Math.max(1, maxRows - 5), PICK_MAX) ? 1 : 0);
|
|
513
|
+
const budget = Math.max(1, maxRows - chrome);
|
|
438
514
|
const shown = spec.options.slice(0, Math.min(budget, PICK_MAX));
|
|
515
|
+
// R2: the note takes a COLUMN, not three spaces after a label of
|
|
516
|
+
// whatever length this row happened to have, and the cursor row
|
|
517
|
+
// wears the bar and the arrow like every other list in the
|
|
518
|
+
// product. This panel was the last one still saying "selected"
|
|
519
|
+
// with bold alone.
|
|
520
|
+
const lead = (o, i, cursor) => `${cursor ? "\u2192" : " "} ${i + 1} ${escapeTerminal(o.label)}`;
|
|
521
|
+
const widest = Math.max(...shown.map((o, i) => visibleWidth(lead(o, i, false))));
|
|
522
|
+
const stop = shown.some((o) => o.note !== undefined) && widest + 2 <= Math.floor(room / 2) && room - widest - 2 >= 18 ? widest + 2 : 0;
|
|
439
523
|
for (let i = 0; i < shown.length; i += 1) {
|
|
440
524
|
const o = shown[i];
|
|
441
525
|
const mark = i === state.cursor && state.phase === "options";
|
|
442
|
-
const
|
|
443
|
-
const
|
|
444
|
-
|
|
526
|
+
const plain = lead(o, i, mark);
|
|
527
|
+
const head = `${mark ? p.bold : ""}${plain}${mark ? p.reset : ""}`;
|
|
528
|
+
const note = o.note === undefined
|
|
529
|
+
? ""
|
|
530
|
+
: stop > 0
|
|
531
|
+
? `${" ".repeat(Math.max(1, stop - visibleWidth(plain)))}${p.dim}${widthCut(escapeTerminal(o.note), Math.max(0, room - stop))}${p.reset}`
|
|
532
|
+
: `${p.dim} ${escapeTerminal(o.note)}${p.reset}`;
|
|
533
|
+
const text = cutLine(`${head}${note}`, room);
|
|
534
|
+
// ONE space, like the approval and ask panels: the bar spends a
|
|
535
|
+
// leading cell of its own, so a two-space unselected prefix
|
|
536
|
+
// moves the digit column by one as the cursor walks — the exact
|
|
537
|
+
// "a column that moves per row reads as damage" this file
|
|
538
|
+
// quotes twice as its standard.
|
|
539
|
+
rows.push(mark ? selectionBar(text, visibleWidth(text), W) : ` ${text}`);
|
|
445
540
|
}
|
|
446
541
|
if (spec.options.length > shown.length) {
|
|
447
|
-
rows.push(
|
|
542
|
+
rows.push(` ${cutLine(`${p.dim} \u2514 +${spec.options.length - shown.length} more \u2014 /model <name> takes any of them${p.reset}`, room)}`);
|
|
448
543
|
}
|
|
449
544
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
rows.push(
|
|
545
|
+
const typing = state.phase === "custom";
|
|
546
|
+
const tText = cutLine(`${typing ? p.bold : ""}${typing ? "\u2192" : " "} t ${p.reset}${p.dim}${escapeTerminal(spec.typeHint)}${p.reset}`, room);
|
|
547
|
+
rows.push(typing ? selectionBar(tText, visibleWidth(tText), W) : ` ${tText}`);
|
|
548
|
+
rows.push(` ${p.dim}${cutLine(pickAffordance(state), room)}${p.reset}`);
|
|
549
|
+
rows.push(`${p.dim}${"\u254c".repeat(Math.max(0, W))}${p.reset}`);
|
|
453
550
|
return rows;
|
|
454
551
|
}
|
|
455
552
|
/** The digits are the keys, so the list the panel offers is bounded by
|
package/dist/components.d.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* (untouched); render.ts supplies the original text (palette, escape,
|
|
18
18
|
* tint, fold wording).
|
|
19
19
|
*/
|
|
20
|
-
import { foldThinking, foldResult, renderToolSummary, type ResumeMeta } from "./render.js";
|
|
20
|
+
import { foldThinking, foldResult, renderToolSummary, type ResumeMeta, type BannerMeta } from "./render.js";
|
|
21
21
|
import { type MdBlock } from "./md.js";
|
|
22
22
|
export { MdStream, renderBlock, renderMarkdown, type MdBlock, type MdKind } from "./md.js";
|
|
23
23
|
/** The spinner glyphs, cycled by the compositor's on-demand tick. */
|
|
@@ -168,6 +168,7 @@ export type BodyCell = {
|
|
|
168
168
|
version: string;
|
|
169
169
|
extensionsText: string;
|
|
170
170
|
resume: ResumeMeta[];
|
|
171
|
+
meta?: BannerMeta | undefined;
|
|
171
172
|
done: true;
|
|
172
173
|
} | {
|
|
173
174
|
kind: "raw";
|
|
@@ -244,7 +245,7 @@ export declare function expandSuffix(lines: number | null, room: number): string
|
|
|
244
245
|
* would put the invariant "exactly one bright token" in as many hands as
|
|
245
246
|
* there are emitters. Here it has exactly one.
|
|
246
247
|
*
|
|
247
|
-
* NO_COLOR: p.
|
|
248
|
+
* NO_COLOR: p.dim is empty, so the row's bytes are untouched.
|
|
248
249
|
*/
|
|
249
250
|
export declare function focusToken(row: string, W: number): string;
|
|
250
251
|
/** W13 — the rollup opt-in table: which tools collapse, and the count
|
|
@@ -374,13 +375,25 @@ export declare function widthCut(text: string, max: number): string;
|
|
|
374
375
|
* keeps the columns from moving as the bar walks the list.
|
|
375
376
|
*/
|
|
376
377
|
export declare function selectionBar(styled: string, visible: number, W: number): string;
|
|
377
|
-
/**
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
378
|
+
/**
|
|
379
|
+
* R2 — the composer's rails, and the ONE edge vocabulary.
|
|
380
|
+
*
|
|
381
|
+
* W6 turned two \u254c dotted rows into a rounded box, reasoning that
|
|
382
|
+
* "the box already says input lives here". That is reversed here, and
|
|
383
|
+
* the reason is not taste: a rule is a DELIMITER and a box is a
|
|
384
|
+
* CONTAINER, and the screen was carrying six edge vocabularies at once
|
|
385
|
+
* (this box, the panel's \u2502 gutter and \u2514\u2500\u2500 tail, the
|
|
386
|
+
* diff gutter, the quote's \u258f, the table's rails, the markdown
|
|
387
|
+
* rule). One dashed rule replaces the ones that SEPARATE; the \u2502
|
|
388
|
+
* gutter survives where it SCOPES.
|
|
389
|
+
*
|
|
390
|
+
* Row-neutral by construction: CHROME_ROWS is still 4, so every gate
|
|
391
|
+
* keyed on H \u2212 4 is untouched, and the input row gains the two
|
|
392
|
+
* columns the walls were taking.
|
|
393
|
+
*/
|
|
382
394
|
export declare function boxTop(W: number): string;
|
|
383
|
-
/**
|
|
395
|
+
/** R2 — the same rule below. Named for its POSITION, not its shape, so
|
|
396
|
+
* the compositor's two call sites did not have to move. */
|
|
384
397
|
export declare function boxBottom(W: number): string;
|
|
385
398
|
/** The terminal label + rhythm gap (the pipe path's v2c bytes — the
|
|
386
399
|
* exact render the passthrough needs). */
|