@kitlangton/knobs 0.4.0-next.1 → 0.4.0-next.3
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/README.md +78 -8
- package/dist/dev/{chunk-ayb292zj.js → chunk-j6zmtens.js} +1 -1
- package/dist/dev/{chunk-1qzffbpa.js → chunk-zwj6yngd.js} +66 -33
- package/dist/dev/index.js +3 -3
- package/dist/panel.js +66 -33
- package/dist/types/ui/compare-css.d.ts +1 -1
- package/dist/types/ui/compare-gpu.d.ts +0 -5
- package/dist/types/ui/compare-model.d.ts +31 -2
- package/dist/types/ui/compare.d.ts +17 -4
- package/dist/types/ui/icons.d.ts +40 -0
- package/dist/types/ui/index.d.ts +6 -4
- package/dist/types/ui/selection-pill-css.d.ts +1 -0
- package/dist/types/ui/selection-pill.d.ts +103 -0
- package/dist/types/ui/timeline-model.d.ts +23 -0
- package/dist/types/ui/timeline.d.ts +11 -1
- package/dist/types/ui/tree.d.ts +3 -2
- package/dist/types/ui/walkthrough-blocks.d.ts +43 -0
- package/dist/types/ui/walkthrough-media.d.ts +4 -0
- package/dist/types/ui/walkthrough-model.d.ts +237 -3
- package/dist/types/ui/walkthrough.d.ts +3 -1
- package/dist/ui-react.js +1544 -360
- package/dist/ui-solid.js +1544 -360
- package/dist/ui.js +1565 -360
- package/package.json +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type ContextEvent, type WalkChapter, type WalkMedia } from "./walkthrough-model.js";
|
|
2
|
+
/** How media reach the page's steps: `step` on a history event, a stack item or a table cell. */
|
|
3
|
+
export interface StepLinks {
|
|
4
|
+
/** The step a ref names (its key, id or number), or null when there's none. */
|
|
5
|
+
find(ref: string): {
|
|
6
|
+
readonly key: string;
|
|
7
|
+
readonly number: string;
|
|
8
|
+
readonly title: string;
|
|
9
|
+
} | null;
|
|
10
|
+
/** Goes to the step, as j / k do. */
|
|
11
|
+
go(key: string): void;
|
|
12
|
+
}
|
|
13
|
+
type OnEvent = ((event: Omit<ContextEvent, "at" | "step">) => void) | undefined;
|
|
14
|
+
export interface Block {
|
|
15
|
+
dispose(): void;
|
|
16
|
+
context?(): {
|
|
17
|
+
kind: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export declare function mountHistory(host: HTMLElement, m: Extract<WalkMedia, {
|
|
21
|
+
kind: "history";
|
|
22
|
+
}>, steps: StepLinks | undefined): Block;
|
|
23
|
+
export declare function mountStack(host: HTMLElement, m: Extract<WalkMedia, {
|
|
24
|
+
kind: "stack";
|
|
25
|
+
}>, steps: StepLinks | undefined): Block;
|
|
26
|
+
export declare function mountTable(host: HTMLElement, m: Extract<WalkMedia, {
|
|
27
|
+
kind: "table";
|
|
28
|
+
}>, steps: StepLinks | undefined): Block;
|
|
29
|
+
export interface ChapterPills {
|
|
30
|
+
/** The chapter the time is in (call as it plays or seeks): the highlight springs to it. */
|
|
31
|
+
sync(): void;
|
|
32
|
+
/** The chapter playing, or null. */
|
|
33
|
+
readonly current: WalkChapter | null;
|
|
34
|
+
dispose(): void;
|
|
35
|
+
}
|
|
36
|
+
export declare function chapterPills(host: HTMLElement, chapters: readonly WalkChapter[], io: {
|
|
37
|
+
/** Seconds. */
|
|
38
|
+
now(): number;
|
|
39
|
+
/** Seeks and plays. */
|
|
40
|
+
seek(time: number): void;
|
|
41
|
+
onEvent: OnEvent;
|
|
42
|
+
}): ChapterPills;
|
|
43
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type UiLook } from "./look.js";
|
|
2
|
+
import { type StepLinks } from "./walkthrough-blocks.js";
|
|
2
3
|
import { type ContextEvent, type MediaContext, type WalkthroughMedia } from "./walkthrough-model.js";
|
|
3
4
|
export interface MediaSlotOptions extends UiLook {
|
|
4
5
|
readonly media: WalkthroughMedia;
|
|
@@ -6,7 +7,10 @@ export interface MediaSlotOptions extends UiLook {
|
|
|
6
7
|
readonly lazy?: boolean;
|
|
7
8
|
/** Kit played, paused or sought a video, or showed another diff file (for a note's log). */
|
|
8
9
|
readonly onEvent?: (event: Omit<ContextEvent, "at" | "step">) => void;
|
|
10
|
+
/** The page's steps, for `step` on a history event, a stack item or a table cell. */
|
|
11
|
+
readonly steps?: StepLinks;
|
|
9
12
|
}
|
|
13
|
+
export type { StepLinks };
|
|
10
14
|
export interface MediaSlot {
|
|
11
15
|
readonly element: HTMLElement;
|
|
12
16
|
/** Whether its content is mounted (heavy kinds wait until they're near the view). */
|
|
@@ -7,6 +7,98 @@ export interface WalkthroughSource {
|
|
|
7
7
|
readonly src: string;
|
|
8
8
|
readonly label?: string;
|
|
9
9
|
}
|
|
10
|
+
/** A status colour: a dot, a chip or a cell's badge. */
|
|
11
|
+
export type WalkthroughTone = "good" | "warn" | "bad" | "info" | "dim";
|
|
12
|
+
/** A small tag that backs a claim: a PR, a commit, a log, as a link or not. */
|
|
13
|
+
export interface WalkthroughEvidence {
|
|
14
|
+
readonly label: string;
|
|
15
|
+
readonly href?: string;
|
|
16
|
+
}
|
|
17
|
+
/** One dated moment in a `history`. */
|
|
18
|
+
export interface WalkthroughHistoryEvent {
|
|
19
|
+
/** As written: "Apr 9, 2026", "2026-04-09", "May 7–8". */
|
|
20
|
+
readonly date: string;
|
|
21
|
+
/** How long ago, or how long it lasted: "116d ago". */
|
|
22
|
+
readonly age?: string;
|
|
23
|
+
readonly title: string;
|
|
24
|
+
readonly detail?: string;
|
|
25
|
+
readonly tone?: WalkthroughTone;
|
|
26
|
+
/** Seen in the record (`"verified"`) or worked out from behaviour (`"inferred"`). */
|
|
27
|
+
readonly provenance?: "verified" | "inferred";
|
|
28
|
+
/** Where it was seen or inferred from: `"git"` shows as "verified · git". */
|
|
29
|
+
readonly source?: string;
|
|
30
|
+
readonly evidence?: readonly WalkthroughEvidence[];
|
|
31
|
+
/** A step it's about: its key, id or number ("1.2"). */
|
|
32
|
+
readonly step?: string;
|
|
33
|
+
/** What happened, which shapes its dot: a release a diamond, an audit a square. */
|
|
34
|
+
readonly type?: "commit" | "release" | "channel" | "audit" | (string & {});
|
|
35
|
+
}
|
|
36
|
+
export interface WalkthroughHistoryGroup {
|
|
37
|
+
readonly heading?: string;
|
|
38
|
+
readonly summary?: string;
|
|
39
|
+
readonly events?: readonly WalkthroughHistoryEvent[];
|
|
40
|
+
/** Another name for `events`. */
|
|
41
|
+
readonly rows?: readonly WalkthroughHistoryEvent[];
|
|
42
|
+
}
|
|
43
|
+
/** One PR in a `stack`. */
|
|
44
|
+
export interface WalkthroughStackItem {
|
|
45
|
+
/** "#57148" (or 57148). */
|
|
46
|
+
readonly pr: string | number;
|
|
47
|
+
readonly href?: string;
|
|
48
|
+
readonly title: string;
|
|
49
|
+
/** Its branch: `"head → base"` (or `->`), or just the head (on `base`, else the trunk). */
|
|
50
|
+
readonly branch?: string;
|
|
51
|
+
/** The branch it merges into, when `branch` names only its head. */
|
|
52
|
+
readonly base?: string;
|
|
53
|
+
/** Lines changed: `"+164 / -18"`, or `{ add, del }`. */
|
|
54
|
+
readonly delta?: string | {
|
|
55
|
+
readonly add: number;
|
|
56
|
+
readonly del: number;
|
|
57
|
+
};
|
|
58
|
+
readonly status?: string;
|
|
59
|
+
readonly tone?: WalkthroughTone;
|
|
60
|
+
readonly summary?: string;
|
|
61
|
+
/** Its head branch, with `base`: another way to write `branch`. */
|
|
62
|
+
readonly head?: string;
|
|
63
|
+
/** The step that shows it: its key, id or number. */
|
|
64
|
+
readonly step?: string;
|
|
65
|
+
/** Another name for `step`. */
|
|
66
|
+
readonly stepId?: string;
|
|
67
|
+
/** Its place as written: "01", "06 · 1/4". */
|
|
68
|
+
readonly order?: string | number;
|
|
69
|
+
}
|
|
70
|
+
/** A table's cell: its text, or that with a link, code, a badge, a colour or a step. */
|
|
71
|
+
export type WalkthroughTableCell = string | number | {
|
|
72
|
+
readonly text: string | number;
|
|
73
|
+
readonly href?: string;
|
|
74
|
+
readonly code?: boolean;
|
|
75
|
+
/** Drawn as a chip in this colour. */
|
|
76
|
+
readonly badge?: WalkthroughTone;
|
|
77
|
+
/** The text in this colour. */
|
|
78
|
+
readonly tone?: WalkthroughTone;
|
|
79
|
+
readonly step?: string;
|
|
80
|
+
};
|
|
81
|
+
export interface WalkthroughTableColumn {
|
|
82
|
+
readonly key: string;
|
|
83
|
+
readonly label: string;
|
|
84
|
+
readonly mono?: boolean;
|
|
85
|
+
/** Numbers go right by default. */
|
|
86
|
+
readonly align?: "left" | "right" | "center";
|
|
87
|
+
}
|
|
88
|
+
/** A row: its cells by column key, bare or under `cells`. */
|
|
89
|
+
export type WalkthroughTableRow = Readonly<Record<string, WalkthroughTableCell>> | {
|
|
90
|
+
readonly cells: Readonly<Record<string, WalkthroughTableCell>>;
|
|
91
|
+
};
|
|
92
|
+
/** A stretch of a video: a pill under it, and a marker on its timeline. */
|
|
93
|
+
export interface WalkthroughChapter {
|
|
94
|
+
readonly id?: string;
|
|
95
|
+
readonly label: string;
|
|
96
|
+
/** Seconds. */
|
|
97
|
+
readonly start: number;
|
|
98
|
+
/** Seconds; else `start + duration`, else the next chapter's start. */
|
|
99
|
+
readonly end?: number;
|
|
100
|
+
readonly duration?: number;
|
|
101
|
+
}
|
|
10
102
|
/**
|
|
11
103
|
* What a step shows. A bare string is a video or image URL (by its extension). `mount` is the one
|
|
12
104
|
* kind that isn't JSON: anything of your own, given its element, returning its cleanup.
|
|
@@ -21,12 +113,37 @@ export type WalkthroughMedia = string | {
|
|
|
21
113
|
readonly aspect?: number | string;
|
|
22
114
|
/** The frame strip over the timeline. */
|
|
23
115
|
readonly strip?: boolean;
|
|
116
|
+
/** Pills under it that seek, and markers on its timeline. */
|
|
117
|
+
readonly chapters?: readonly WalkthroughChapter[];
|
|
24
118
|
} | {
|
|
25
119
|
readonly kind: "video";
|
|
26
120
|
readonly src: string;
|
|
27
121
|
readonly label?: string;
|
|
28
122
|
readonly aspect?: number | string;
|
|
29
123
|
readonly poster?: string;
|
|
124
|
+
/** Pills under it that seek; the one playing lit. */
|
|
125
|
+
readonly chapters?: readonly WalkthroughChapter[];
|
|
126
|
+
/** A WebVTT file's URL, shown by default. */
|
|
127
|
+
readonly captions?: string;
|
|
128
|
+
/** Another name for `captions`. */
|
|
129
|
+
readonly captionsSrc?: string;
|
|
130
|
+
} | {
|
|
131
|
+
readonly kind: "history";
|
|
132
|
+
/** Dated events under quiet headings… */
|
|
133
|
+
readonly groups?: readonly WalkthroughHistoryGroup[];
|
|
134
|
+
/** …or one run of them. */
|
|
135
|
+
readonly events?: readonly WalkthroughHistoryEvent[];
|
|
136
|
+
} | {
|
|
137
|
+
readonly kind: "stack";
|
|
138
|
+
/** The branch the stack lands on ("dev"); else the one most items merge into. */
|
|
139
|
+
readonly base?: string;
|
|
140
|
+
/** In merge order; an item on another's branch hangs under it. */
|
|
141
|
+
readonly items: readonly WalkthroughStackItem[];
|
|
142
|
+
} | {
|
|
143
|
+
readonly kind: "table";
|
|
144
|
+
readonly columns: readonly WalkthroughTableColumn[];
|
|
145
|
+
readonly rows: readonly WalkthroughTableRow[];
|
|
146
|
+
readonly caption?: string;
|
|
30
147
|
} | {
|
|
31
148
|
readonly kind: "image";
|
|
32
149
|
readonly src: string;
|
|
@@ -154,11 +271,78 @@ export interface WalkthroughDoc {
|
|
|
154
271
|
type CompareMedia = Extract<WalkthroughMedia, {
|
|
155
272
|
kind: "compare";
|
|
156
273
|
}>;
|
|
157
|
-
|
|
158
|
-
|
|
274
|
+
type VideoMedia = Extract<WalkthroughMedia, {
|
|
275
|
+
kind: "video";
|
|
276
|
+
}>;
|
|
277
|
+
/** A chapter filled in: an id, and its end where one can be known. */
|
|
278
|
+
export interface WalkChapter {
|
|
279
|
+
readonly id: string;
|
|
280
|
+
readonly label: string;
|
|
281
|
+
readonly start: number;
|
|
282
|
+
readonly end?: number;
|
|
283
|
+
}
|
|
284
|
+
export interface WalkHistoryGroup {
|
|
285
|
+
readonly heading?: string;
|
|
286
|
+
readonly summary?: string;
|
|
287
|
+
readonly events: readonly WalkthroughHistoryEvent[];
|
|
288
|
+
}
|
|
289
|
+
/** A stack's item filled in: its PR as `#123`, its branch split, `step` for `stepId`. */
|
|
290
|
+
export interface WalkStackItem {
|
|
291
|
+
readonly pr: string;
|
|
292
|
+
readonly href?: string;
|
|
293
|
+
readonly title: string;
|
|
294
|
+
readonly head?: string;
|
|
295
|
+
readonly base?: string;
|
|
296
|
+
readonly delta?: string | {
|
|
297
|
+
readonly add: number;
|
|
298
|
+
readonly del: number;
|
|
299
|
+
};
|
|
300
|
+
readonly status?: string;
|
|
301
|
+
readonly tone?: WalkthroughTone;
|
|
302
|
+
readonly summary?: string;
|
|
303
|
+
readonly step?: string;
|
|
304
|
+
readonly order?: string;
|
|
305
|
+
}
|
|
306
|
+
export interface WalkTableCell {
|
|
307
|
+
readonly text: string;
|
|
308
|
+
readonly href?: string;
|
|
309
|
+
readonly code?: boolean;
|
|
310
|
+
readonly badge?: WalkthroughTone;
|
|
311
|
+
readonly tone?: WalkthroughTone;
|
|
312
|
+
readonly step?: string;
|
|
313
|
+
}
|
|
314
|
+
export interface WalkTableColumn {
|
|
315
|
+
readonly key: string;
|
|
316
|
+
readonly label: string;
|
|
317
|
+
readonly mono?: boolean;
|
|
318
|
+
readonly align: "left" | "right" | "center";
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Media filled in: no bare URLs, a compare's sides as sources, chapters with their ends, history in
|
|
322
|
+
* groups, a stack's branches split and a table's cells as objects. Filling it again changes
|
|
323
|
+
* nothing.
|
|
324
|
+
*/
|
|
325
|
+
export type WalkMedia = Exclude<WalkthroughMedia, string | {
|
|
326
|
+
readonly kind: "compare" | "video" | "history" | "stack" | "table";
|
|
327
|
+
}> | (Omit<CompareMedia, "before" | "after" | "chapters"> & {
|
|
159
328
|
readonly before: WalkthroughSource;
|
|
160
329
|
readonly after: WalkthroughSource;
|
|
161
|
-
|
|
330
|
+
readonly chapters?: readonly WalkChapter[];
|
|
331
|
+
}) | (Omit<VideoMedia, "chapters" | "captionsSrc"> & {
|
|
332
|
+
readonly chapters?: readonly WalkChapter[];
|
|
333
|
+
}) | {
|
|
334
|
+
readonly kind: "history";
|
|
335
|
+
readonly groups: readonly WalkHistoryGroup[];
|
|
336
|
+
} | {
|
|
337
|
+
readonly kind: "stack";
|
|
338
|
+
readonly base?: string;
|
|
339
|
+
readonly items: readonly WalkStackItem[];
|
|
340
|
+
} | {
|
|
341
|
+
readonly kind: "table";
|
|
342
|
+
readonly columns: readonly WalkTableColumn[];
|
|
343
|
+
readonly rows: readonly Readonly<Record<string, WalkTableCell>>[];
|
|
344
|
+
readonly caption?: string;
|
|
345
|
+
};
|
|
162
346
|
export interface WalkOption {
|
|
163
347
|
readonly id: string;
|
|
164
348
|
readonly label: string;
|
|
@@ -231,6 +415,54 @@ export declare const mediaOf: (src: string) => WalkMedia;
|
|
|
231
415
|
export declare function parseAspect(aspect: number | string | undefined): number | undefined;
|
|
232
416
|
/** Media filled in: a bare URL as a video or image, sources resolved against `base`. */
|
|
233
417
|
export declare function fillMedia(m: WalkthroughMedia, base?: string): WalkMedia;
|
|
418
|
+
/** `"head → base"` (or `->`, `=>`, `⇒`) as its two branches; one name is the head alone. */
|
|
419
|
+
export declare function parseBranch(branch: string | undefined): {
|
|
420
|
+
head?: string;
|
|
421
|
+
base?: string;
|
|
422
|
+
};
|
|
423
|
+
/** `"+164 / -18"`, `"+164 −18"` or `{ add, del }` as numbers; other text stays as written. */
|
|
424
|
+
export declare function parseDelta(delta: WalkthroughStackItem["delta"]): {
|
|
425
|
+
add: number;
|
|
426
|
+
del: number;
|
|
427
|
+
} | string | undefined;
|
|
428
|
+
/** One row of a stack as drawn: where it hangs, and which rails pass beside it. */
|
|
429
|
+
export interface StackRow {
|
|
430
|
+
readonly item: WalkStackItem;
|
|
431
|
+
/** Its place in `items`. */
|
|
432
|
+
readonly index: number;
|
|
433
|
+
/** 0 on the trunk; one more for each item it's stacked on. */
|
|
434
|
+
readonly depth: number;
|
|
435
|
+
/** The item it's stacked on (its place in `items`); null on the trunk. */
|
|
436
|
+
readonly parent: number | null;
|
|
437
|
+
/** The last of its siblings: its rail ends here (└) rather than going on (├). */
|
|
438
|
+
readonly last: boolean;
|
|
439
|
+
/** For each level above its own (0 the trunk's), whether that level's rail passes beside it. */
|
|
440
|
+
readonly rails: readonly boolean[];
|
|
441
|
+
readonly children: number;
|
|
442
|
+
/** The branch it merges into when that's neither the trunk nor another item's. */
|
|
443
|
+
readonly offBase?: string;
|
|
444
|
+
}
|
|
445
|
+
export interface StackLayout {
|
|
446
|
+
/** The branch it lands on: `base`, else the one most items merge into; null when none says. */
|
|
447
|
+
readonly trunk: string | null;
|
|
448
|
+
/** Depth-first in merge order: each item after the one it's stacked on. */
|
|
449
|
+
readonly rows: readonly StackRow[];
|
|
450
|
+
/** Nothing is stacked on anything, and there's no trunk: a plain list. */
|
|
451
|
+
readonly flat: boolean;
|
|
452
|
+
}
|
|
453
|
+
/** A stack's branch topology: which item each one is stacked on, in rows to draw as a graph. */
|
|
454
|
+
export declare function stackLayout(m: {
|
|
455
|
+
readonly base?: string;
|
|
456
|
+
readonly items: readonly WalkStackItem[];
|
|
457
|
+
}): StackLayout;
|
|
458
|
+
/** Chapters with ids and, where it can be known, an end: given, `start + duration`, or the next. */
|
|
459
|
+
export declare function fillChapters(chapters: readonly WalkthroughChapter[]): WalkChapter[];
|
|
460
|
+
/** The chapter playing at `time` (seconds): the one it's in that started last; -1 for none. */
|
|
461
|
+
export declare function chapterAt(chapters: readonly WalkChapter[], time: number): number;
|
|
462
|
+
/** Seconds as a clock: `1:05`, `1:02:05` past the hour. */
|
|
463
|
+
export declare function clock(seconds: number): string;
|
|
464
|
+
/** A step named by its key, id or number ("1.2"), a leading `#` allowed; undefined if there's none. */
|
|
465
|
+
export declare function findStep(steps: readonly WalkStep[], ref: string | undefined): WalkStep | undefined;
|
|
234
466
|
/** A GitHub PR or issue URL's number as `#123`; else the URL's last part. */
|
|
235
467
|
export declare function linkLabel(href: string): string;
|
|
236
468
|
/**
|
|
@@ -280,6 +512,8 @@ export interface MediaContext {
|
|
|
280
512
|
readonly time?: number;
|
|
281
513
|
readonly duration?: number;
|
|
282
514
|
readonly playing?: boolean;
|
|
515
|
+
/** The chapter the time is in, by its label. */
|
|
516
|
+
readonly chapter?: string;
|
|
283
517
|
/** The loop range, in seconds. */
|
|
284
518
|
readonly loop?: {
|
|
285
519
|
readonly start: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type StoragePort } from "../core/storage.js";
|
|
2
2
|
import { type UiLook } from "./look.js";
|
|
3
|
-
import { type MediaSlot } from "./walkthrough-media.js";
|
|
3
|
+
import { type MediaSlot, type StepLinks } from "./walkthrough-media.js";
|
|
4
4
|
import { type WalkOption, type WalkPage, type WalkthroughDoc, type WalkthroughFeedback, type WalkthroughOption, type WalkthroughState } from "./walkthrough-model.js";
|
|
5
5
|
export interface TasteTestOptions extends UiLook {
|
|
6
6
|
readonly options: readonly (WalkthroughOption | WalkOption)[];
|
|
@@ -9,6 +9,8 @@ export interface TasteTestOptions extends UiLook {
|
|
|
9
9
|
readonly onPick?: (id: string | null) => void;
|
|
10
10
|
/** Mount each option's media when near the view (on by default). */
|
|
11
11
|
readonly lazy?: boolean;
|
|
12
|
+
/** The page's steps, for media that name one. */
|
|
13
|
+
readonly steps?: StepLinks;
|
|
12
14
|
}
|
|
13
15
|
export interface TasteTest {
|
|
14
16
|
readonly element: HTMLElement;
|