@vincemakes/kiso-tui-cells 0.46.2 → 0.47.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.
@@ -24,6 +24,7 @@
24
24
  * count, the W20 discipline — the #checked throw demands it); the args
25
25
  * FOLD (a bounded block's body — content folds, metadata cuts).
26
26
  */
27
+ import { foldAtSpaces } from "./components.js";
27
28
  export type PanelFlavor = "approval" | "simple";
28
29
  /**
29
30
  * TUI2-R3v2 ① — two phases, not three.
@@ -225,6 +226,30 @@ export interface PickOption {
225
226
  * previous selection asked ("effort xhigh \u2192 high: the nearest this
226
227
  * model supports"). The caller's sentence, reproduced verbatim. */
227
228
  readonly levelNote?: string;
229
+ /** Graphite R3e: what the second axis IS, named on its key hint
230
+ * (`←→ mode`); absent, it is the model's `effort`. P3: a named axis is
231
+ * the row's own value, so its strip carries no label of its own. */
232
+ readonly axisLabel?: string;
233
+ /** Graphite P3: the columns after the label (a profile's host and state,
234
+ * a setting's value and source), measured over EVERY option so nothing
235
+ * moves as the cursor or the filter does. Absent, the `note` is the one
236
+ * column. */
237
+ readonly cols?: readonly string[];
238
+ /** Graphite P3: what the selected row OPENS into, on the same wash (the
239
+ * /resume shape) — what the columns cannot hold: why a profile cannot
240
+ * run, how a config setting changes. After the level strip when there
241
+ * is one, and it gives way first. */
242
+ readonly opened?: string;
243
+ /** Graphite P3: the option cannot run as it stands (a profile with no
244
+ * credential): its row is dim. It can still be picked; the caller says
245
+ * why, as it always has. */
246
+ readonly off?: boolean;
247
+ /** Graphite P3: further texts the filter reaches (a profile's name),
248
+ * after the label and the first column. Never drawn. */
249
+ readonly match?: readonly string[];
250
+ /** Graphite P3: what ⏎ does on THIS row, for the key row
251
+ * (`⏎ opens /model`); absent, the spec's word. */
252
+ readonly enter?: string;
228
253
  }
229
254
  /** The level cursor, CORRECTED at read time: never off the end, never on
230
255
  * a forbidden index, and never invented where the caller supplied none.
@@ -242,18 +267,38 @@ export declare function startLevel(o: PickOption | undefined): number | null;
242
267
  /** The next enabled index in `dir`, or the current one at the end of the
243
268
  * ladder. Forbidden indexes are stepped OVER, never landed on. */
244
269
  export declare function stepLevel(o: PickOption, from: number | null, dir: -1 | 1): number | null;
245
- /** The whole pick: the header sentence, the options, the free-text
246
- * escape hatch, and the honest empty state. */
270
+ /** The whole pick: the band's name, the options, how the keys reach
271
+ * them, and the honest empty state. */
247
272
  export interface PickSpec {
273
+ /** the band's NAME (`model`). A legacy `name — words` header still
274
+ * splits: the words join the facts. */
248
275
  readonly header: string;
249
276
  readonly options: readonly PickOption[];
250
- /** the `t` row — typing directly. OPTIONAL, and its absence means the
251
- * option list is the WHOLE world: `/model`'s profiles never are (a
252
- * model that exists but is not configured has to be typeable), and
253
- * `/mode`'s five tiers always are. Offering a `t` row over a closed
254
- * set is a row that carries no fact — §1.3 — and it is what made
255
- * the owner read the mode panel as "type the answer". */
256
- readonly typeHint?: string;
277
+ /** Graphite P3: what the band's name says after the count
278
+ * (`current: default · don't ask`, `run paused`). */
279
+ readonly facts?: string;
280
+ /** Graphite P3: the band counts its options with this noun
281
+ * (`profiles` → `9 profiles`, `""` → `11`), and says `2 of 9 match`
282
+ * under a filter. Absent, no count. */
283
+ readonly noun?: string;
284
+ /** Graphite P3: how keys reach the rows. `digits` (the default): a digit
285
+ * moves to that row on screen. `filter`: the input row filters, as in
286
+ * /resume — a digit is a letter there. `arrows`: ↑↓ alone. */
287
+ readonly input?: "digits" | "filter" | "arrows";
288
+ /** filter only: the input row's words while it is empty */
289
+ readonly filterHint?: string;
290
+ /** filter only: a typed `provider/model` that nothing on the list
291
+ * matches becomes a row of its own, and ⏎ on it hands the text back. It
292
+ * replaced the `t` row (P3, owner, 2026-10-04). Only when NOTHING
293
+ * matches: a slash typed into a profile's name (`op/`) is filtering. */
294
+ readonly direct?: boolean;
295
+ /** how the columns are styled, by index: `dim` unless `plain` */
296
+ readonly columns?: readonly ("plain" | "dim")[];
297
+ /** the column that shows the walked level on the selected row (a
298
+ * setting's value follows ←→) */
299
+ readonly levelColumn?: number;
300
+ /** what ⏎ does, for the key row (`⏎ switches`); a row may say its own */
301
+ readonly enter?: string;
257
302
  /** shown INSTEAD of the options when there are none. The copy is the
258
303
  * caller's and is reproduced verbatim. */
259
304
  readonly emptyNote?: string;
@@ -263,15 +308,42 @@ export interface PickSpec {
263
308
  * pays without anyone choosing to. */
264
309
  readonly initial?: number;
265
310
  }
266
- /** The pick panel's runtime state \u2014 the editor owns it, the compositor
267
- * reads it (the AskRuntime precedent, two fields instead of five). */
311
+ /** The pick panel's runtime state — the editor owns it, the compositor
312
+ * reads it (the AskRuntime precedent). */
268
313
  export interface PickRuntime {
314
+ /** an OPTION index (never a position on screen); `options.length` is
315
+ * the direct row. Corrected at read time by `pickList`. */
269
316
  readonly cursor: number;
270
- readonly phase: "options" | "custom";
271
317
  /** OR-7: the level cursor within the highlighted option. null = the
272
318
  * option has no levels, or has no default to mark. */
273
319
  readonly level: number | null;
320
+ /** filter: the input's text, read from the composer on every frame —
321
+ * the panel never stores a copy that could disagree with it */
322
+ readonly query?: string;
323
+ }
324
+ /** Graphite P3 — what the pick shows right now, derived from the spec and
325
+ * the runtime: the ONE derivation the renderer, the keys and the digit
326
+ * window all read, so the row the eye is on is the row a key acts on. */
327
+ export interface PickList {
328
+ /** the option indexes on the list, in the caller's order; the direct
329
+ * row (`options.length`) last when it is offered */
330
+ readonly shown: readonly number[];
331
+ /** the cursor, corrected: an entry of `shown`, or -1 when nothing shows */
332
+ readonly cursor: number;
333
+ /** the level in force for the cursor's option */
334
+ readonly level: number | null;
335
+ /** the typed letters, per option: which text they landed in (0 the
336
+ * label, 1 the first column) and where */
337
+ readonly hits: ReadonlyMap<number, {
338
+ readonly col: number;
339
+ readonly at: readonly number[];
340
+ }>;
341
+ /** what the direct row would hand back, when it is offered */
342
+ readonly direct: string | null;
343
+ /** the query the list was filtered by ("" when none) */
344
+ readonly query: string;
274
345
  }
346
+ export declare function pickList(spec: PickSpec, state: PickRuntime): PickList;
275
347
  /** What was picked: a listed option by INDEX (never a label the caller
276
348
  * would have to re-match against its own list), or typed text. */
277
349
  export type PickResult = {
@@ -340,6 +412,17 @@ export interface PanelView {
340
412
  /** TUI2-R2 \u2463: the options, when this view is a PICK. Same contract
341
413
  * as `ask`, one payload over. */
342
414
  readonly pick?: PickSpec;
415
+ /** Graphite P1b (owner, 2026-09-30) — kiso's OWN question (a cold
416
+ * cache, a call that may have run, an unanswered question, the trust
417
+ * gate). Present = the panel opens on the question as its band name
418
+ * with the facts dim after it, then at most two sentences at the
419
+ * content edge; the gutter keeps only what is quoted verbatim (`args`).
420
+ * Absent = the approval layout, unchanged. */
421
+ readonly asked?: {
422
+ readonly question: string;
423
+ readonly facts: readonly string[];
424
+ readonly prose: string;
425
+ };
343
426
  }
344
427
  export type PanelVerdict = {
345
428
  readonly action: "allow";
@@ -418,6 +501,14 @@ export interface PanelBlockLayout {
418
501
  * maxRows caps the TOTAL (the args fold; the single-row lines cut). */
419
502
  export declare function panelBlockRows(view: PanelView, phase: PanelPhase, cursor: number, W: number, maxRows: number, note?: string, safer?: SaferRuntime): string[];
420
503
  export declare function panelBlockLayout(view: PanelView, phase: PanelPhase, cursor: number, W: number, maxRows: number, note?: string, safer?: SaferRuntime): PanelBlockLayout;
504
+ /** Graphite P4's fold for a one-line command; it lives with the card's
505
+ * head now, which folds a command the same way (the card round). */
506
+ export { foldAtSpaces };
507
+ /** The key row: the keys, cut by cells, and the counter at the right margin. */
508
+ export declare function panelKeyRow(keys: string, list: {
509
+ readonly at: number;
510
+ readonly of: number;
511
+ } | null, W: number): string;
421
512
  /**
422
513
  * The input row's lead. In the options phase there is NOTHING to type,
423
514
  * so the lead stops pretending there is.
@@ -429,11 +520,11 @@ export declare function panelBlockLayout(view: PanelView, phase: PanelPhase, cur
429
520
  * a human really is writing — leads with the word for what they are
430
521
  * writing.
431
522
  */
432
- export declare function panelLead(view: PanelView, phase: PanelPhase, cursor: number): string;
523
+ export declare function panelLead(_view: PanelView, _phase: PanelPhase, _cursor: number): string;
433
524
  /** The lead's plain text — the editor's reflow width (the line must
434
525
  * fit the lead + the drawn cursor's own cell — R2 retired the box and
435
526
  * its walls with it). */
436
- export declare function panelLeadPlain(view: PanelView, phase: PanelPhase, cursor: number): string;
527
+ export declare function panelLeadPlain(_view: PanelView, _phase: PanelPhase, _cursor: number): string;
437
528
  export declare function panelLeadWidth(view: PanelView, phase: PanelPhase, cursor: number): number;
438
529
  /** The status row's left text while the panel is up — the phase, not
439
530
  * the CLI's painting status (the compositor derives it from the panel
@@ -449,64 +540,57 @@ export declare function panelStatus(view: PanelView, phase: PanelPhase, cursor:
449
540
  */
450
541
  export declare function panelAffordance(view: PanelView, phase: PanelPhase, cursor: number, safer?: SaferRuntime): string;
451
542
  /**
452
- * The pick block's rows — the prototype's C frame.
453
- *
454
- * The header says what is in effect right now, because the first
455
- * question anyone opening this panel has is "what am I on?". The
456
- * options are numbered from 1 and the number IS the key. The `t` row is
457
- * last and always present: a profile list is a convenience, never the
458
- * set of models that exist, and a picker that can only offer what
459
- * someone remembered to configure is a smaller product than the one it
460
- * replaced.
543
+ * Graphite P3 (owner, 2026-10-04) — the pick block takes the shape of every
544
+ * list band (§8.2, §8.13). The band names itself with its count or its
545
+ * current value; a window of eight rows from a 30-row terminal, five below,
546
+ * with dim more-marks in column 0; the rows a TABLE, each column measured
547
+ * over the whole list; the selected row the card head every list shares,
548
+ * OPENED into a second row on the same wash (the /resume shape) for the
549
+ * level strip and what the columns cannot hold; one key row with the
550
+ * counter. No closing rule: the composer's rail closes the band, as it does
551
+ * the command list.
461
552
  *
462
- * Single-row discipline: every row CUTS, never folds — the block's
463
- * height is its row count (the W20 rule the #checked throw demands).
464
- */
465
- export declare function pickBlockRows(view: PanelView, state: PickRuntime, W: number, maxRows: number): string[];
466
- /** The digits are the keys, so what one SCREEN offers is still bounded by
467
- * the digits there are — but the list itself is no longer bounded by it.
553
+ * DECLARED REVERSALS (P3, owner, 2026-10-04): the `current:` row (its words
554
+ * ride the band's name), the bracketed level (the level in force is gold),
555
+ * the `↕ 1-9 / 11` row (the more-marks say it), PICK_MAX's nine-row window
556
+ * (§8.2's eight and five), and the `t` row with its typing phase (a typed
557
+ * `provider/model` is a row of the filter — PickSpec.direct).
468
558
  *
469
- * Finding DC-58 (the owner, 2026-09-21): this constant used to cap what the
470
- * KEYBOARD could reach (`/model` on a 60-profile config offered nine and
471
- * said `/model <name>` for the rest). The window now follows the cursor —
472
- * `pickWindow` — so PICK_MAX is only how many rows one screen shows, and
473
- * ↑↓ walks every option.
559
+ * Single-row discipline: every row CUTS, never folds — the block's height
560
+ * is its row count (the W20 rule the #checked throw demands).
474
561
  */
562
+ export declare function pickBlockRows(view: PanelView, state: PickRuntime, W: number, maxRows: number, height?: number): string[];
563
+ /** The digits are the keys, so what one SCREEN offers is bounded by the
564
+ * digits there are. Finding DC-58 (the owner, 2026-09-21) made the window
565
+ * follow the cursor, so this is how many rows a digit can name, not how
566
+ * many rows the keyboard reaches. */
475
567
  export declare const PICK_MAX = 9;
476
- /** The option window the pick panel draws and the digits name: `size` rows
477
- * starting at `first`, with `first` derived from the cursor so it cannot
478
- * drift from it. Edge-following (the window starts moving only when the
479
- * cursor leaves it) and clamped at both ends, so the last page is full
480
- * rather than short.
481
- *
482
- * Pure, and the ONE copy: the renderer, the digit keys and the click
483
- * hit-test all ask this function rather than each deriving an offset.
484
- */
485
- /** The pick panel's window for THIS frame's budget — the one derivation the
486
- * renderer and the input layer share (review of this round).
568
+ /**
569
+ * The pick's window for THIS frame — the one derivation the renderer and
570
+ * the digit keys share (DC-58's review: a size derived twice is a size that
571
+ * can disagree). Positions are into `pickList(...).shown`.
487
572
  *
488
- * The renderer draws it; `Dock.visiblePickWindow` hands the SAME value to the
489
- * digit keys, because a size derived twice is a size that can disagree — and
490
- * on a short terminal it did (two rows drawn, nine assumed, so `1` could mean
491
- * a row nobody could see). `phase` is compared as a string so this module
492
- * keeps its zero-dependency contract.
573
+ * Graphite P3: §8.2's window (eight rows from a 30-row terminal, five
574
+ * below, the cursor kept a row inside an edge while more lies past it),
575
+ * within the frame's budget: the band's name, the key row, the opened row
576
+ * and a `nothing matches` row are the chrome.
493
577
  */
494
- export declare function pickWindowOf(view: PanelView, cursor: number, phase: string, maxRows: number): {
495
- first: number;
496
- size: number;
497
- };
498
- export declare function pickWindow(cursor: number, count: number, size: number): {
578
+ export declare function pickWindowOf(view: PanelView, state: PickRuntime, maxRows: number, height?: number): {
499
579
  first: number;
500
580
  size: number;
501
581
  };
502
- /** The input row's lead: the digit range while picking, the named
503
- * prompt while typing one out. */
504
- export declare function pickLeadPlain(view: PanelView, state: PickRuntime): string;
505
- export declare function pickLead(view: PanelView, state: PickRuntime): string;
506
- /** The status row's left text \u2014 the CALLER's, because only the caller
507
- * knows whether a run is paused behind this panel. */
582
+ /** The input row's lead. Graphite P3: a pick leaves the input row to the
583
+ * composer — the filter is typed there, and a digit list needs no lead
584
+ * to say so (its key row does). */
585
+ export declare function pickLeadPlain(_view: PanelView, _state: PickRuntime): string;
586
+ export declare function pickLead(_view: PanelView, _state: PickRuntime): string;
587
+ /** The status row's left text — the CALLER's, because only the caller
588
+ * knows whether a run is paused behind this panel. (Graphite P3: on a
589
+ * dock the bar stays under a pick; this is the dock-less text.) */
508
590
  export declare function pickStatus(view: PanelView): string;
509
- export declare function pickAffordance(state: PickRuntime, axis?: boolean): string;
591
+ /** The key words, for a caller that draws them outside the block. The
592
+ * block's own key row is the one on screen (P3). */
593
+ export declare function pickAffordance(_state: PickRuntime, axis?: boolean | string): string;
510
594
  /** Compose a pick view. The flavor/name/title/args fields exist for the
511
595
  * approval path and are given inert values here \u2014 the pick block
512
596
  * reads none of them. */
@@ -518,6 +602,9 @@ export declare function pickAffordance(state: PickRuntime, axis?: boolean): stri
518
602
  * `pick` and `statusText`, so a second flavour is a name and a
519
603
  * fallback question, not a second mechanism. */
520
604
  export declare function modePickView(spec: PickSpec, statusText: string): PanelView;
605
+ /** Graphite R3e — `/settings` as a pick panel: a row per setting, the
606
+ * session's own ones with a second axis to walk. */
607
+ export declare function settingsPickView(spec: PickSpec, statusText: string): PanelView;
521
608
  /** ADR-0058 (3e): the `/tasks` list, a task's actions, and the exit
522
609
  * question — the same pick panel as /mode and /model, under its name. */
523
610
  export declare function namedPickView(name: string, spec: PickSpec, statusText: string, fallbackQuestion: string): PanelView;