@kitlangton/knobs 0.4.0-next.1 → 0.4.0-next.10

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 (46) hide show
  1. package/README.md +164 -12
  2. package/dist/dev/{chunk-1qzffbpa.js → chunk-5pb7ymrd.js} +150 -46
  3. package/dist/dev/{chunk-ayb292zj.js → chunk-a7cjgy8x.js} +2 -2
  4. package/dist/dev/{chunk-8mabjeyk.js → chunk-dyq4m24m.js} +162 -1
  5. package/dist/dev/index.js +3 -3
  6. package/dist/panel.js +312 -46
  7. package/dist/review-react.js +18580 -0
  8. package/dist/review-solid.js +18482 -0
  9. package/dist/review.js +18488 -0
  10. package/dist/themes.js +281 -23
  11. package/dist/types/review/font.d.ts +13 -0
  12. package/dist/types/review/foundations.d.ts +175 -0
  13. package/dist/types/review/index.d.ts +13 -0
  14. package/dist/types/review/react.d.ts +1 -0
  15. package/dist/types/review/solid.d.ts +1 -0
  16. package/dist/types/themes/index.d.ts +7 -2
  17. package/dist/types/themes/review.d.ts +8 -0
  18. package/dist/types/tokens/schema.d.ts +180 -0
  19. package/dist/types/ui/compare-css.d.ts +1 -1
  20. package/dist/types/ui/compare-gpu.d.ts +6 -6
  21. package/dist/types/ui/compare-model.d.ts +85 -2
  22. package/dist/types/ui/compare.d.ts +18 -4
  23. package/dist/types/ui/diff.d.ts +4 -5
  24. package/dist/types/ui/history-css.d.ts +1 -0
  25. package/dist/types/ui/history-model.d.ts +249 -0
  26. package/dist/types/ui/history.d.ts +38 -0
  27. package/dist/types/ui/icons.d.ts +40 -0
  28. package/dist/types/ui/index.d.ts +8 -4
  29. package/dist/types/ui/player-css.d.ts +1 -0
  30. package/dist/types/ui/player.d.ts +51 -0
  31. package/dist/types/ui/review-look.d.ts +6 -0
  32. package/dist/types/ui/review-options.d.ts +28 -0
  33. package/dist/types/ui/selection-pill-css.d.ts +1 -0
  34. package/dist/types/ui/selection-pill.d.ts +106 -0
  35. package/dist/types/ui/timeline-model.d.ts +27 -0
  36. package/dist/types/ui/timeline.d.ts +16 -1
  37. package/dist/types/ui/tree.d.ts +3 -2
  38. package/dist/types/ui/walkthrough-annotations.d.ts +42 -0
  39. package/dist/types/ui/walkthrough-blocks.d.ts +87 -0
  40. package/dist/types/ui/walkthrough-media.d.ts +30 -1
  41. package/dist/types/ui/walkthrough-model.d.ts +469 -5
  42. package/dist/types/ui/walkthrough.d.ts +27 -5
  43. package/dist/ui-react.js +5124 -1031
  44. package/dist/ui-solid.js +5136 -1043
  45. package/dist/ui.js +6411 -2269
  46. package/package.json +13 -1
@@ -1,5 +1,6 @@
1
1
  import type { CompareMode } from "./compare-model.js";
2
2
  import type { DiffSource } from "./diff-model.js";
3
+ import type { HistoryData, HistoryEvent } from "./history-model.js";
3
4
  /** Where a PR or topic stands, as the agent sees it: a chip beside its title. */
4
5
  export type WalkthroughStatus = "ready" | "needs-taste" | "draft" | "blocked" | "merged" | (string & {});
5
6
  /** A picture or video, by URL. */
@@ -7,6 +8,114 @@ export interface WalkthroughSource {
7
8
  readonly src: string;
8
9
  readonly label?: string;
9
10
  }
11
+ /** A status colour: a dot, a chip or a cell's badge. */
12
+ export type WalkthroughTone = "good" | "warn" | "bad" | "info" | "dim";
13
+ /** A small tag that backs a claim: a PR, a commit, a log, as a link or not. */
14
+ export interface WalkthroughEvidence {
15
+ readonly label: string;
16
+ readonly href?: string;
17
+ }
18
+ /** One dated moment in a `history`. */
19
+ export interface WalkthroughHistoryEvent {
20
+ /** As written: "Apr 9, 2026", "2026-04-09", "May 7–8". */
21
+ readonly date: string;
22
+ /** How long ago, or how long it lasted: "116d ago". */
23
+ readonly age?: string;
24
+ readonly title: string;
25
+ readonly detail?: string;
26
+ readonly tone?: WalkthroughTone;
27
+ /** Seen in the record (`"verified"`) or worked out from behaviour (`"inferred"`). */
28
+ readonly provenance?: "verified" | "inferred";
29
+ /** Where it was seen or inferred from: `"git"` shows as "verified · git". */
30
+ readonly source?: string;
31
+ readonly evidence?: readonly WalkthroughEvidence[];
32
+ /** A step it's about: its key, id or number ("1.2"). */
33
+ readonly step?: string;
34
+ /** What happened, which shapes its dot: a release a diamond, an audit a square. */
35
+ readonly type?: "commit" | "release" | "channel" | "audit" | (string & {});
36
+ }
37
+ export interface WalkthroughHistoryGroup {
38
+ readonly heading?: string;
39
+ readonly summary?: string;
40
+ readonly events?: readonly WalkthroughHistoryEvent[];
41
+ /** Another name for `events`. */
42
+ readonly rows?: readonly WalkthroughHistoryEvent[];
43
+ }
44
+ /** One PR in a `stack`. */
45
+ export interface WalkthroughStackItem {
46
+ /** "#57148" (or 57148). */
47
+ readonly pr: string | number;
48
+ readonly href?: string;
49
+ readonly title: string;
50
+ /** Its branch: `"head → base"` (or `->`), or just the head (on `base`, else the trunk). */
51
+ readonly branch?: string;
52
+ /** The branch it merges into, when `branch` names only its head. */
53
+ readonly base?: string;
54
+ /** Lines changed: `"+164 / -18"`, or `{ add, del }`. */
55
+ readonly delta?: string | {
56
+ readonly add: number;
57
+ readonly del: number;
58
+ };
59
+ readonly status?: string;
60
+ readonly tone?: WalkthroughTone;
61
+ readonly summary?: string;
62
+ /** Its head branch, with `base`: another way to write `branch`. */
63
+ readonly head?: string;
64
+ /** The step that shows it: its key, id or number. */
65
+ readonly step?: string;
66
+ /** Another name for `step`. */
67
+ readonly stepId?: string;
68
+ /** Its place as written: "01", "06 · 1/4". */
69
+ readonly order?: string | number;
70
+ }
71
+ /** A table's cell: its text, or that with a link, code, a badge, a colour or a step. */
72
+ export type WalkthroughTableCell = string | number | {
73
+ readonly text: string | number;
74
+ readonly href?: string;
75
+ readonly code?: boolean;
76
+ /** Drawn as a chip in this colour. */
77
+ readonly badge?: WalkthroughTone;
78
+ /** The text in this colour. */
79
+ readonly tone?: WalkthroughTone;
80
+ readonly step?: string;
81
+ };
82
+ export interface WalkthroughTableColumn {
83
+ readonly key: string;
84
+ readonly label: string;
85
+ readonly mono?: boolean;
86
+ /** Numbers go right by default. */
87
+ readonly align?: "left" | "right" | "center";
88
+ }
89
+ /** A row: its cells by column key, bare or under `cells`. */
90
+ export type WalkthroughTableRow = Readonly<Record<string, WalkthroughTableCell>> | {
91
+ readonly cells: Readonly<Record<string, WalkthroughTableCell>>;
92
+ };
93
+ /**
94
+ * A mark on a picture drawing the eye to what matters: a ring round a box, a dot or an arrow at a
95
+ * point, with a small label. In 0–1 of the picture (`x`, `y` the box's top-left or the point).
96
+ */
97
+ export interface WalkthroughAnnotation {
98
+ readonly x: number;
99
+ readonly y: number;
100
+ /** A box's size; left out, it's a point. */
101
+ readonly w?: number;
102
+ readonly h?: number;
103
+ readonly label?: string;
104
+ /** Seconds it shows between, on a video or compare; always, left out. */
105
+ readonly at?: readonly [number, number];
106
+ /** `"box"` where it has a size, else `"dot"`. */
107
+ readonly shape?: "box" | "dot" | "arrow";
108
+ }
109
+ /** A stretch of a video: a pill under it, and a marker on its timeline. */
110
+ export interface WalkthroughChapter {
111
+ readonly id?: string;
112
+ readonly label: string;
113
+ /** Seconds. */
114
+ readonly start: number;
115
+ /** Seconds; else `start + duration`, else the next chapter's start. */
116
+ readonly end?: number;
117
+ readonly duration?: number;
118
+ }
10
119
  /**
11
120
  * What a step shows. A bare string is a video or image URL (by its extension). `mount` is the one
12
121
  * kind that isn't JSON: anything of your own, given its element, returning its cleanup.
@@ -21,17 +130,65 @@ export type WalkthroughMedia = string | {
21
130
  readonly aspect?: number | string;
22
131
  /** The frame strip over the timeline. */
23
132
  readonly strip?: boolean;
133
+ /** Pills under it that seek, and markers on its timeline. */
134
+ readonly chapters?: readonly WalkthroughChapter[];
135
+ /** Marks on the pictures, on both sides (and under a zoom). */
136
+ readonly annotations?: readonly WalkthroughAnnotation[];
24
137
  } | {
25
138
  readonly kind: "video";
26
139
  readonly src: string;
27
140
  readonly label?: string;
28
141
  readonly aspect?: number | string;
29
142
  readonly poster?: string;
143
+ /** Pills under it that seek; the one playing lit. */
144
+ readonly chapters?: readonly WalkthroughChapter[];
145
+ /** A WebVTT file's URL, shown by default. */
146
+ readonly captions?: string;
147
+ /** Another name for `captions`. */
148
+ readonly captionsSrc?: string;
149
+ /** Marks on the picture. */
150
+ readonly annotations?: readonly WalkthroughAnnotation[];
151
+ } | {
152
+ readonly kind: "history";
153
+ /** Lanes of dated spans over one axis (`history()`'s shape)… */
154
+ readonly lanes?: HistoryData["lanes"];
155
+ readonly bands?: HistoryData["bands"];
156
+ readonly states?: HistoryData["states"];
157
+ readonly axis?: HistoryData["axis"];
158
+ /** …dated events (on the lanes, or one run of them in the older shape)… */
159
+ readonly events?: readonly (WalkthroughHistoryEvent | HistoryEvent)[];
160
+ /** …or the older groups of events under quiet headings. */
161
+ readonly groups?: readonly WalkthroughHistoryGroup[];
162
+ /** Its accessible name. */
163
+ readonly label?: string;
164
+ /** The event types marked from the start (releases and deletions), or `"all"`. */
165
+ readonly marks?: readonly string[] | "all";
166
+ } | {
167
+ readonly kind: "stack";
168
+ /** The branch the stack lands on ("dev"); else the one most items merge into. */
169
+ readonly base?: string;
170
+ /** In merge order; an item on another's branch hangs under it. */
171
+ readonly items: readonly WalkthroughStackItem[];
172
+ } | {
173
+ readonly kind: "table";
174
+ readonly columns: readonly WalkthroughTableColumn[];
175
+ readonly rows: readonly WalkthroughTableRow[];
176
+ readonly caption?: string;
177
+ /**
178
+ * Where the step is too narrow for its columns, each row becomes a block: its primary cell
179
+ * as a title over the rest as term and value (`"auto"`, the default); always; or never
180
+ * (the table scrolls sideways instead).
181
+ */
182
+ readonly stack?: "auto" | "always" | "never";
183
+ /** The column that titles a stacked row (its key); the first by default. */
184
+ readonly primary?: string;
30
185
  } | {
31
186
  readonly kind: "image";
32
187
  readonly src: string;
33
188
  readonly label?: string;
34
189
  readonly alt?: string;
190
+ /** Marks on the picture. */
191
+ readonly annotations?: readonly WalkthroughAnnotation[];
35
192
  } | {
36
193
  readonly kind: "diff";
37
194
  /** `git diff` / `git show` output. */
@@ -65,6 +222,20 @@ export type WalkthroughMedia = string | {
65
222
  } | {
66
223
  readonly kind: "text";
67
224
  readonly text: string;
225
+ } | {
226
+ readonly kind: "facts";
227
+ /** A small faint label over it. */
228
+ readonly title?: string;
229
+ /** One run of term → value pairs… */
230
+ readonly facts?: WalkthroughFacts;
231
+ /** …or several, each under a heading, hairlines between. */
232
+ readonly groups?: readonly WalkthroughFactGroup[];
233
+ } | {
234
+ readonly kind: "decision";
235
+ /** Side by side where there's room, one under another where there isn't. */
236
+ readonly options: readonly WalkthroughDecisionOption[];
237
+ /** The word before each option's number: "Option" by default. */
238
+ readonly noun?: string;
68
239
  } | {
69
240
  readonly kind: "mount";
70
241
  readonly mount: (element: HTMLElement) => (() => void) | void;
@@ -72,6 +243,35 @@ export type WalkthroughMedia = string | {
72
243
  readonly height?: number;
73
244
  };
74
245
  export type CalloutTone = "info" | "good" | "warn" | "bad";
246
+ /** A term and its value. */
247
+ export interface WalkthroughFact {
248
+ readonly term: string;
249
+ /** Markdown, where `code` reads as a small mono chip; several values sit one under another. */
250
+ readonly value: string | readonly string[];
251
+ /** Each value is code or evidence (a string splits at commas): small mono chips. */
252
+ readonly code?: boolean;
253
+ }
254
+ /** Facts as a list, or as `{ term: value }`. */
255
+ export type WalkthroughFacts = readonly WalkthroughFact[] | Readonly<Record<string, string | readonly string[]>>;
256
+ export interface WalkthroughFactGroup {
257
+ readonly title?: string;
258
+ readonly facts: WalkthroughFacts;
259
+ }
260
+ /** One way to go in a decision. */
261
+ export interface WalkthroughDecisionOption {
262
+ readonly id?: string;
263
+ readonly title: string;
264
+ /** A sentence: what it does. Markdown. */
265
+ readonly summary?: string;
266
+ /** What it looks like: a picture, a compare, code. */
267
+ readonly media?: WalkthroughMedia;
268
+ /** What changes, as facts ("What the user sees", "Size"). */
269
+ readonly facts?: WalkthroughFacts;
270
+ readonly pros?: readonly string[];
271
+ readonly cons?: readonly string[];
272
+ /** The one to take: a quiet "Recommended" beside its number. */
273
+ readonly recommended?: boolean;
274
+ }
75
275
  /** One option in a taste test. */
76
276
  export interface WalkthroughOption {
77
277
  /** "a", "b"… by position when left out. */
@@ -79,8 +279,12 @@ export interface WalkthroughOption {
79
279
  readonly label: string;
80
280
  readonly caption?: string;
81
281
  readonly media?: WalkthroughMedia;
82
- /** The agent's own pick, marked "Suggested". */
282
+ /** What changes, as facts, under its caption. */
283
+ readonly facts?: WalkthroughFacts;
284
+ /** The agent's own pick, marked "Recommended". */
83
285
  readonly suggested?: boolean;
286
+ /** Another name for `suggested`. */
287
+ readonly recommended?: boolean;
84
288
  }
85
289
  export interface WalkthroughStep {
86
290
  /** From the title when left out. */
@@ -88,8 +292,15 @@ export interface WalkthroughStep {
88
292
  readonly title: string;
89
293
  /** A line or two: what it shows and how it was made. `code`, **bold** and [links](…) work. */
90
294
  readonly caption?: string;
91
- /** One slot; two or more sit side by side, stacking where it's narrow. */
295
+ /** One slot, or several one under another (`columns` sets them side by side). */
92
296
  readonly media?: WalkthroughMedia | readonly WalkthroughMedia[];
297
+ /** Media side by side, this many to a row where there's room; one under another by default. */
298
+ readonly columns?: 1 | 2 | 3;
299
+ /**
300
+ * The rest, folded away under the caption behind "More" (Markdown; blank lines start new
301
+ * paragraphs). Keep the title the claim and the caption one sentence; everything else goes here.
302
+ */
303
+ readonly more?: string;
93
304
  /** A taste test: Kit picks one. */
94
305
  readonly options?: readonly WalkthroughOption[];
95
306
  /**
@@ -108,8 +319,16 @@ export interface WalkthroughSection {
108
319
  readonly href: string;
109
320
  readonly label?: string;
110
321
  };
322
+ /**
323
+ * The words that lead its meta line, in text colour: its count by default (`"PR 2 of 5"` where
324
+ * `link` is a pull request, or the doc's `kickers` noun), your own words, or `false` for none.
325
+ */
326
+ readonly kicker?: string | false;
327
+ /** A chip on its meta line ("needs-taste" → Needs taste), with `review: true` only. */
111
328
  readonly status?: WalkthroughStatus;
112
329
  readonly summary?: string;
330
+ /** The rest, folded away under the summary behind "More" (Markdown). */
331
+ readonly more?: string;
113
332
  readonly steps: readonly WalkthroughStep[];
114
333
  }
115
334
  export interface WalkthroughMeta {
@@ -124,6 +343,10 @@ export interface WalkthroughUpdate {
124
343
  readonly text: string;
125
344
  /** The step it's about: its key, id or number ("1.2"). */
126
345
  readonly step?: string;
346
+ /** Its state in a word or two (`"shipped"`, `"changes"`), last on its meta line. */
347
+ readonly status?: string;
348
+ /** Context, folded away under the item: one line each, `"0:04 · Played the compare"`. */
349
+ readonly trail?: readonly string[];
127
350
  }
128
351
  /** A question Kit asked and the agent's answer. */
129
352
  export interface WalkthroughQA {
@@ -132,6 +355,10 @@ export interface WalkthroughQA {
132
355
  readonly q: string;
133
356
  readonly a: string;
134
357
  readonly step?: string;
358
+ /** `"shipped"` or `"changes"` (shown as "Changes queued"), or your own words. */
359
+ readonly status?: string;
360
+ /** What Kit did before asking, folded away under the answer: `"0:04 · Played the compare"`. */
361
+ readonly trail?: readonly string[];
135
362
  }
136
363
  /** The document an agent writes: plain data, JSON but for `mount` media. */
137
364
  export interface WalkthroughDoc {
@@ -139,6 +366,8 @@ export interface WalkthroughDoc {
139
366
  readonly id: string;
140
367
  readonly title: string;
141
368
  readonly summary?: string;
369
+ /** The rest, folded away under the summary behind "More" (Markdown). */
370
+ readonly more?: string;
142
371
  /** Facts beside the title: branch, commit, date… */
143
372
  readonly meta?: Readonly<Record<string, string>> | readonly WalkthroughMeta[];
144
373
  /** Relative media URLs resolve against this. */
@@ -149,16 +378,117 @@ export interface WalkthroughDoc {
149
378
  readonly updates?: readonly WalkthroughUpdate[];
150
379
  /** Kit's questions and the agent's answers. */
151
380
  readonly qa?: readonly WalkthroughQA[];
381
+ /**
382
+ * How sections are counted on their meta line: `"pr"` (the default) gives "PR i of N" to the
383
+ * sections that link a pull request, `{ noun: "Part" }` "Part i of N" to every section, and
384
+ * `false` none. A section's own `kicker` wins over its count, and `false` hides it, without
385
+ * renumbering the rest.
386
+ */
387
+ readonly kickers?: "pr" | {
388
+ readonly noun: string;
389
+ } | false;
390
+ /**
391
+ * The pull requests the page mentions, by number: their state and title. A `#57148` in a title,
392
+ * caption or summary, a link to a pull request, and a section's PR `link` read as a small chip
393
+ * (its state's icon and number; the title on hover).
394
+ */
395
+ readonly prs?: Readonly<Record<string, WalkthroughPR>>;
396
+ /** `owner/name` on GitHub, so a bare `#57148` links to its pull request. */
397
+ readonly repo?: string;
152
398
  readonly sections: readonly WalkthroughSection[];
153
399
  }
400
+ export interface WalkthroughPR {
401
+ readonly state?: "merged" | "open" | "draft" | "closed";
402
+ /** An issue rather than a pull request (`issue:` refs and `/issues/` links are). */
403
+ readonly kind?: "pr" | "issue";
404
+ /** Its checks pass (a stack item's status saying green, passing or CI). */
405
+ readonly checks?: boolean;
406
+ readonly title?: string;
407
+ /** Its URL, when neither `repo` nor a link on the page gives it. */
408
+ readonly href?: string;
409
+ }
154
410
  type CompareMedia = Extract<WalkthroughMedia, {
155
411
  kind: "compare";
156
412
  }>;
157
- /** Media filled in: no bare URLs, and a compare's sides as sources. */
158
- export type WalkMedia = Exclude<WalkthroughMedia, string | CompareMedia> | (Omit<CompareMedia, "before" | "after"> & {
413
+ type VideoMedia = Extract<WalkthroughMedia, {
414
+ kind: "video";
415
+ }>;
416
+ /** A chapter filled in: an id, and its end where one can be known. */
417
+ export interface WalkChapter {
418
+ readonly id: string;
419
+ readonly label: string;
420
+ readonly start: number;
421
+ readonly end?: number;
422
+ }
423
+ /** A stack's item filled in: its PR as `#123`, its branch split, `step` for `stepId`. */
424
+ export interface WalkStackItem {
425
+ readonly pr: string;
426
+ readonly href?: string;
427
+ readonly title: string;
428
+ readonly head?: string;
429
+ readonly base?: string;
430
+ readonly delta?: string | {
431
+ readonly add: number;
432
+ readonly del: number;
433
+ };
434
+ readonly status?: string;
435
+ readonly tone?: WalkthroughTone;
436
+ readonly summary?: string;
437
+ readonly step?: string;
438
+ readonly order?: string;
439
+ }
440
+ export interface WalkTableCell {
441
+ readonly text: string;
442
+ readonly href?: string;
443
+ readonly code?: boolean;
444
+ readonly badge?: WalkthroughTone;
445
+ readonly tone?: WalkthroughTone;
446
+ readonly step?: string;
447
+ }
448
+ export interface WalkTableColumn {
449
+ readonly key: string;
450
+ readonly label: string;
451
+ readonly mono?: boolean;
452
+ readonly align: "left" | "right" | "center";
453
+ }
454
+ /**
455
+ * Media filled in: no bare URLs, a compare's sides as sources, chapters with their ends, history in
456
+ * groups, a stack's branches split and a table's cells as objects. Filling it again changes
457
+ * nothing.
458
+ */
459
+ export type WalkMedia = Exclude<WalkthroughMedia, string | {
460
+ readonly kind: "compare" | "video" | "history" | "stack" | "table" | "facts" | "decision";
461
+ }> | (Omit<CompareMedia, "before" | "after" | "chapters"> & {
159
462
  readonly before: WalkthroughSource;
160
463
  readonly after: WalkthroughSource;
161
- });
464
+ readonly chapters?: readonly WalkChapter[];
465
+ }) | (Omit<VideoMedia, "chapters" | "captionsSrc"> & {
466
+ readonly chapters?: readonly WalkChapter[];
467
+ }) | {
468
+ readonly kind: "history";
469
+ readonly data: HistoryData;
470
+ readonly label?: string;
471
+ readonly marks?: readonly string[] | "all";
472
+ } | {
473
+ readonly kind: "stack";
474
+ readonly base?: string;
475
+ readonly items: readonly WalkStackItem[];
476
+ } | {
477
+ readonly kind: "facts";
478
+ readonly title?: string;
479
+ readonly groups: readonly WalkFactGroup[];
480
+ } | {
481
+ readonly kind: "decision";
482
+ readonly options: readonly WalkDecisionOption[];
483
+ } | {
484
+ readonly kind: "table";
485
+ readonly columns: readonly WalkTableColumn[];
486
+ readonly rows: readonly Readonly<Record<string, WalkTableCell>>[];
487
+ readonly caption?: string;
488
+ readonly stack: "auto" | "always" | "never";
489
+ /** The key of the column that titles a stacked row. */
490
+ readonly primary: string;
491
+ };
162
492
  export interface WalkOption {
163
493
  readonly id: string;
164
494
  readonly label: string;
@@ -166,8 +496,30 @@ export interface WalkOption {
166
496
  readonly letter: string;
167
497
  readonly caption?: string;
168
498
  readonly media?: WalkMedia;
499
+ readonly facts?: readonly WalkFact[];
169
500
  readonly suggested: boolean;
170
501
  }
502
+ /** A fact filled in: its values as a list. */
503
+ export interface WalkFact {
504
+ readonly term: string;
505
+ readonly value: readonly string[];
506
+ readonly code: boolean;
507
+ }
508
+ export interface WalkFactGroup {
509
+ readonly title?: string;
510
+ readonly facts: readonly WalkFact[];
511
+ }
512
+ /** A decision's option filled in: its id, its number's words, pros and cons as facts. */
513
+ export interface WalkDecisionOption {
514
+ readonly id: string;
515
+ /** "Option 1". */
516
+ readonly number: string;
517
+ readonly title: string;
518
+ readonly summary?: string;
519
+ readonly media?: WalkMedia;
520
+ readonly facts: readonly WalkFact[];
521
+ readonly recommended: boolean;
522
+ }
171
523
  export interface WalkStep {
172
524
  /** `section/step`: where its feedback is kept. */
173
525
  readonly key: string;
@@ -179,6 +531,9 @@ export interface WalkStep {
179
531
  readonly caption?: string;
180
532
  readonly question?: string;
181
533
  readonly media: readonly WalkMedia[];
534
+ /** Media to a row: 1 (one under another) unless the step asked for more. */
535
+ readonly columns: number;
536
+ readonly more?: string;
182
537
  readonly options: readonly WalkOption[];
183
538
  readonly ask: "note" | "pick" | "none";
184
539
  }
@@ -189,8 +544,11 @@ export interface WalkSection {
189
544
  readonly href: string;
190
545
  readonly label: string;
191
546
  };
547
+ /** What leads its meta line ("PR 2 of 5"), when anything does. */
548
+ readonly kicker?: string;
192
549
  readonly status?: WalkthroughStatus;
193
550
  readonly summary?: string;
551
+ readonly more?: string;
194
552
  readonly steps: readonly WalkStep[];
195
553
  }
196
554
  export interface WalkVerdict {
@@ -207,11 +565,14 @@ export interface FeedItem {
207
565
  readonly q?: string;
208
566
  /** The step's key, when it names one that's there. */
209
567
  readonly step: string | null;
568
+ readonly status?: string;
569
+ readonly trail: readonly string[];
210
570
  }
211
571
  export interface WalkPage {
212
572
  readonly id: string;
213
573
  readonly title: string;
214
574
  readonly summary?: string;
575
+ readonly more?: string;
215
576
  readonly meta: readonly WalkthroughMeta[];
216
577
  readonly verdicts: readonly WalkVerdict[];
217
578
  readonly sections: readonly WalkSection[];
@@ -219,6 +580,10 @@ export interface WalkPage {
219
580
  readonly steps: readonly WalkStep[];
220
581
  /** Updates and answers, newest first. */
221
582
  readonly feed: readonly FeedItem[];
583
+ /** The pull requests the page knows, by number, each with its URL when one is known. */
584
+ readonly prs: Readonly<Record<string, WalkthroughPR>>;
585
+ /** `owner/name`, when the doc gave one. */
586
+ readonly repo?: string;
222
587
  }
223
588
  export declare const DEFAULT_VERDICTS: readonly ["ship", "change", "unsure"];
224
589
  /** A URL-safe id from a title: "Retired model (HTTP 410)" → "retired-model-http-410". */
@@ -231,6 +596,70 @@ export declare const mediaOf: (src: string) => WalkMedia;
231
596
  export declare function parseAspect(aspect: number | string | undefined): number | undefined;
232
597
  /** Media filled in: a bare URL as a video or image, sources resolved against `base`. */
233
598
  export declare function fillMedia(m: WalkthroughMedia, base?: string): WalkMedia;
599
+ /** Facts as a list of terms and their values (a code value split at its commas). */
600
+ export declare function fillFacts(facts: WalkthroughFacts | readonly WalkFact[]): readonly WalkFact[];
601
+ /**
602
+ * How many options sit side by side: as many as fit at `min` px each with `gap` between, up to 4,
603
+ * and always a count that fills whole rows (4 → 4, 2 or 1; 3 → 3 or 1; 5 → 1), so no row is short.
604
+ */
605
+ export declare function optionColumns(count: number, width: number, min?: number, gap?: number): number;
606
+ /** A decision's options filled in: ids, "Option 1"…, pros and cons as the last facts. */
607
+ export declare function fillDecision(options: readonly (WalkthroughDecisionOption | WalkDecisionOption)[], noun?: string, base?: string): readonly WalkDecisionOption[];
608
+ /**
609
+ * What `history()` draws: the lanes shape as written, or the older groups (`rows` read as
610
+ * `events`, bare `events` as one group first) for it to lay on the code lane.
611
+ */
612
+ export declare function historyData(m: Extract<WalkthroughMedia, {
613
+ kind: "history";
614
+ }>): HistoryData;
615
+ /** `"head → base"` (or `->`, `=>`, `⇒`) as its two branches; one name is the head alone. */
616
+ export declare function parseBranch(branch: string | undefined): {
617
+ head?: string;
618
+ base?: string;
619
+ };
620
+ /** `"+164 / -18"`, `"+164 −18"` or `{ add, del }` as numbers; other text stays as written. */
621
+ export declare function parseDelta(delta: WalkthroughStackItem["delta"]): {
622
+ add: number;
623
+ del: number;
624
+ } | string | undefined;
625
+ /** One row of a stack as drawn: where it hangs, and which rails pass beside it. */
626
+ export interface StackRow {
627
+ readonly item: WalkStackItem;
628
+ /** Its place in `items`. */
629
+ readonly index: number;
630
+ /** 0 on the trunk; one more for each item it's stacked on. */
631
+ readonly depth: number;
632
+ /** The item it's stacked on (its place in `items`); null on the trunk. */
633
+ readonly parent: number | null;
634
+ /** The last of its siblings: its rail ends here (└) rather than going on (├). */
635
+ readonly last: boolean;
636
+ /** For each level above its own (0 the trunk's), whether that level's rail passes beside it. */
637
+ readonly rails: readonly boolean[];
638
+ readonly children: number;
639
+ /** The branch it merges into when that's neither the trunk nor another item's. */
640
+ readonly offBase?: string;
641
+ }
642
+ export interface StackLayout {
643
+ /** The branch it lands on: `base`, else the one most items merge into; null when none says. */
644
+ readonly trunk: string | null;
645
+ /** Depth-first in merge order: each item after the one it's stacked on. */
646
+ readonly rows: readonly StackRow[];
647
+ /** Nothing is stacked on anything, and there's no trunk: a plain list. */
648
+ readonly flat: boolean;
649
+ }
650
+ /** A stack's branch topology: which item each one is stacked on, in rows to draw as a graph. */
651
+ export declare function stackLayout(m: {
652
+ readonly base?: string;
653
+ readonly items: readonly WalkStackItem[];
654
+ }): StackLayout;
655
+ /** Chapters with ids and, where it can be known, an end: given, `start + duration`, or the next. */
656
+ export declare function fillChapters(chapters: readonly WalkthroughChapter[]): WalkChapter[];
657
+ /** The chapter playing at `time` (seconds): the one it's in that started last; -1 for none. */
658
+ export declare function chapterAt(chapters: readonly WalkChapter[], time: number): number;
659
+ /** Seconds as a clock: `1:05`, `1:02:05` past the hour. */
660
+ export declare function clock(seconds: number): string;
661
+ /** A step named by its key, id or number ("1.2"), a leading `#` allowed; undefined if there's none. */
662
+ export declare function findStep(steps: readonly WalkStep[], ref: string | undefined): WalkStep | undefined;
234
663
  /** A GitHub PR or issue URL's number as `#123`; else the URL's last part. */
235
664
  export declare function linkLabel(href: string): string;
236
665
  /**
@@ -238,6 +667,37 @@ export declare function linkLabel(href: string): string;
238
667
  * ask, options lettered, media URLs resolved against `base`, and the verdicts labelled.
239
668
  */
240
669
  export declare function normalizeWalkthrough(doc: WalkthroughDoc): WalkPage;
670
+ /** The number in a pull request's URL (`…/pull/57148`), or null. */
671
+ export declare const prNumber: (href: string) => string | null;
672
+ export type PRState = NonNullable<WalkthroughPR["state"]>;
673
+ /**
674
+ * A pull request's state from some status words: the first word when it's merged, draft, open or
675
+ * closed (any case; shipped and done read as merged), and whether they say its checks pass
676
+ * ("green", "passing", "CI"). The state comes from the words, never a tone.
677
+ */
678
+ export declare function prStatus(status: string | undefined): {
679
+ state: PRState | null;
680
+ checks: boolean;
681
+ };
682
+ /**
683
+ * A pull request (or an issue) by number: what the page knows, or (with a repo) its URL; null
684
+ * when it knows nothing. An issue takes only what `prs` says of it as an issue.
685
+ */
686
+ export declare function findPR(prs: Readonly<Record<string, WalkthroughPR>>, n: string, repo?: string, kind?: "pr" | "issue"): WalkthroughPR | null;
687
+ /** The number in an issue's URL (`…/issues/123`), or null. */
688
+ export declare const issueNumber: (href: string) => string | null;
689
+ /** Whether a link is a pull (or merge) request: GitHub's `/pull/123`, GitLab's merge requests. */
690
+ export declare const isPullRequest: (href: string) => boolean;
691
+ /**
692
+ * Whether a table stacks its rows into blocks: always, never, or (auto) when the room it has is
693
+ * less than its columns' natural width.
694
+ */
695
+ export declare function tableStacks(stack: "auto" | "always" | "never", room: number, natural: number): boolean;
696
+ /**
697
+ * The page's bottom reserve for the docked note bar: its height, the gap it floats above the
698
+ * page's edge, and a gap above it, so the last step and a step gone to never sit under it.
699
+ */
700
+ export declare function noteBarReserve(bar: number, inset: number, gap: number): number;
241
701
  /** An ISO time as epoch ms; null when it isn't one. */
242
702
  export declare function parseAt(at: string | undefined): number | null;
243
703
  /** Newest first; items without a time after those with one, later-written first. */
@@ -280,6 +740,8 @@ export interface MediaContext {
280
740
  readonly time?: number;
281
741
  readonly duration?: number;
282
742
  readonly playing?: boolean;
743
+ /** The chapter the time is in, by its label. */
744
+ readonly chapter?: string;
283
745
  /** The loop range, in seconds. */
284
746
  readonly loop?: {
285
747
  readonly start: number;
@@ -443,5 +905,7 @@ export declare function feedbackMarkdown(fb: WalkthroughFeedback, verdicts?: rea
443
905
  * Inline Markdown as safe HTML: `code`, **bold**, *italic* and [links](https://…), the rest
444
906
  * escaped. Links take http(s), relative and # URLs only; blank lines make paragraphs' breaks.
445
907
  */
908
+ /** Inline Markdown as plain words, for a contents row, a label or a title attribute. */
909
+ export declare function plainMarkdown(text: string): string;
446
910
  export declare function inlineMarkdown(text: string): string;
447
911
  export {};