@kitlangton/knobs 0.3.0 → 0.4.0-next.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.
@@ -12,13 +12,21 @@ export { toast, type Toast, type ToastOptions } from "./toast.js";
12
12
  export { tooltip, tooltips, type TooltipContent, type TooltipOptions } from "./tooltip.js";
13
13
  export { split, type PaneAction, type PaneOptions, type Split, type SplitFold, type SplitOptions, type SplitPane, } from "./split.js";
14
14
  export { COLLAPSE_PAST, drag as dragDivider, parseLayout, softClamp, solve as solveSplit, type PaneSpec, type SplitDirection, type SplitLayout, } from "./split-model.js";
15
- export { timeline, type SeekSource, type Timeline, type TimelineMarker, type TimelineOptions, type TimelineRange, } from "./timeline.js";
15
+ export { timeline, type SeekSource, type Timeline, type TimelineMarker, type TimelineListener, type TimelineOptions, type TimelineRange, } from "./timeline.js";
16
16
  export { adjacentMarker, advance, clampView, followView, frameTime, magnet, rulerTicks, scrubTime, timeLabel, toFrame, zoomView, type Tick, type Ticks, type TimeUnits, type TimeView, } from "./timeline-model.js";
17
+ export { compare, COMPARE_FFMPEG, type Compare, type CompareLoop, type CompareMode, type CompareOptions, type CompareSource, type CompareView, type MediaKind, type ZoomRegion, } from "./compare.js";
18
+ export { compareStrip, type CompareStrip, type CompareStripOptions } from "./compare-strip.js";
19
+ export { compareLayout, frameMidpoint, frameOf, letterbox, mediaKind, meanAbsDiff, requestSeek, seeked, seekTime, stripColumns, stripPeaks, syncAction, wipeAt, wipeGrab, wipeKey, wipeX, zoomAbout, type CompareLayout, type SeekState, type StripColumn, type SyncAction, } from "./compare-model.js";
17
20
  export { tree, type Tree, type TreeOptions, type TreeRowContext, type TreeToggle } from "./tree.js";
18
21
  export { applyMove, plainAccess, dropTarget, flatten, indexTree, matchLabel, navigate, select, stepMove, topmost, typeahead, validMove, virtualWindow, type DropTarget, type FlatRow, type Selection, type TreeAccess, type TreeFilter, type TreeMove, } from "./tree-model.js";
22
+ export { codeDiff, diffCounts, diffReview, diffStatus, type CodeDiff, type CodeDiffOptions, type CodeDiffUpdate, type DiffLayout, type DiffLines, type DiffReview, type DiffReviewOptions, } from "./diff.js";
23
+ export { compareText, comparePaths, countChanges, diffBar, diffFiles, diffFolders, diffStats, diffTree, fileKey, filesUnder, keepFile, matchPath, parsePatch, splitPath, stepFile, type DiffChange, type DiffFile, type DiffInput, type DiffRows, type DiffSource, type DiffTreeItem, } from "./diff-model.js";
19
24
  export { bento, type Bento, type BentoItem, type BentoOptions } from "./bento.js";
20
25
  export { fitRect, FIT_MAX, motionBlur, neighbour as bentoNeighbour, planBento, rowTarget, windowOf as bentoWindow, type BentoDirection, type BentoLayout, type BentoMode, type BentoPlan, type BentoRect, } from "./bento-model.js";
21
26
  export { activity, type Activity, type ActivityOptions, } from "./activity.js";
22
27
  export { diffActivity, flattenActivity, formatDuration, indexActivity, keepSelection as keepActivitySelection, navigateActivity, railSegments, showsSelection, stackRows, type ActivityEvent, type ActivityInput, type ActivityKey, type ActivityKind, type ActivityRow, type RailNode, } from "./activity-model.js";
23
28
  export { optionPicker, type OptionPicker, type OptionPickerOptions, type PickerOption, } from "./picker.js";
24
29
  export { claimsDigit, digitPick, keepPick, stepPick } from "./picker-model.js";
30
+ export { tasteTest, walkthrough, type TasteTest, type TasteTestOptions, type Walkthrough, type WalkthroughOptions, } from "./walkthrough.js";
31
+ export { mediaSlot, type MediaSlot, type MediaSlotOptions } from "./walkthrough-media.js";
32
+ export { collectFeedback, feedbackMarkdown, inlineMarkdown, normalizeWalkthrough, readState as readWalkthroughState, walkthroughProgress, type ContextEvent, type FeedbackItem, type FeedbackNote, type FeedItem, type MediaContext, type NoteContext, type WalkInk, type WalkNote, type WalkVoice, type WalkthroughQA, type WalkthroughUpdate, type WalkPage, type WalkStep, type WalkthroughDoc, type WalkthroughFeedback, type WalkthroughMedia, type WalkthroughMeta, type WalkthroughOption, type WalkthroughSection, type WalkthroughSource, type WalkthroughState, type WalkthroughStatus, type WalkthroughStep, } from "./walkthrough-model.js";
@@ -1,10 +1,15 @@
1
1
  import { type CSSProperties, type ReactNode } from "react";
2
2
  import { type Activity as ActivityHandle, type ActivityOptions } from "./activity.js";
3
3
  import { type Bento as BentoHandle, type BentoOptions } from "./bento.js";
4
+ import { type CodeDiff as CodeDiffHandle, type CodeDiffOptions, type DiffReview as DiffReviewHandle, type DiffReviewOptions } from "./diff.js";
4
5
  import { type OptionPicker as OptionPickerHandle, type OptionPickerOptions, type PickerOption } from "./picker.js";
5
6
  import { type Split as SplitHandle, type SplitOptions } from "./split.js";
6
7
  import { type Timeline as TimelineHandle, type TimelineOptions } from "./timeline.js";
8
+ import { type Compare as CompareHandle, type CompareOptions } from "./compare.js";
9
+ import { type CompareStrip as CompareStripHandle, type CompareStripOptions } from "./compare-strip.js";
7
10
  import { type Tree as TreeHandle, type TreeOptions } from "./tree.js";
11
+ import { type TasteTest as TasteTestHandle, type TasteTestOptions, type Walkthrough as WalkthroughHandle, type WalkthroughOptions } from "./walkthrough.js";
12
+ import { type MediaSlot as MediaSlotHandle, type MediaSlotOptions } from "./walkthrough-media.js";
8
13
  export type SplitProps = SplitOptions & {
9
14
  /** One child per pane, in the panes' order; each renders into its pane's body. */
10
15
  children?: ReactNode;
@@ -24,6 +29,24 @@ export type TreeProps<T> = TreeOptions<T> & {
24
29
  * `filter` follow their props; callbacks always call the latest props.
25
30
  */
26
31
  export declare function Tree<T>(props: TreeProps<T>): import("react").JSX.Element;
32
+ export type CodeDiffProps = CodeDiffOptions & {
33
+ className?: string;
34
+ style?: CSSProperties;
35
+ onReady?: (diff: CodeDiffHandle) => void;
36
+ };
37
+ /**
38
+ * `codeDiff()` as a component. `patch`, `files`, `file`, `layout`, `wrap`, `viewed`, `height` and
39
+ * `maxHeight` follow their
40
+ * props; callbacks always call the latest props.
41
+ */
42
+ export declare function CodeDiff(props: CodeDiffProps): import("react").JSX.Element;
43
+ export type DiffReviewProps = DiffReviewOptions & {
44
+ className?: string;
45
+ style?: CSSProperties;
46
+ onReady?: (review: DiffReviewHandle) => void;
47
+ };
48
+ /** `diffReview()` as a component: the file tree beside the diff; follows as `CodeDiff` does. */
49
+ export declare function DiffReview(props: DiffReviewProps): import("react").JSX.Element;
27
50
  export type TimelineProps = TimelineOptions & {
28
51
  className?: string;
29
52
  style?: CSSProperties;
@@ -35,6 +58,24 @@ export type TimelineProps = TimelineOptions & {
35
58
  * always call the latest props.
36
59
  */
37
60
  export declare function Timeline(props: TimelineProps): import("react").JSX.Element;
61
+ export type CompareProps = CompareOptions & {
62
+ className?: string;
63
+ style?: CSSProperties;
64
+ onReady?: (compare: CompareHandle) => void;
65
+ };
66
+ /**
67
+ * `compare()` as a component. `before`, `after` (by `src`), `mode`, `wipe`, `loupe`, `threshold`
68
+ * and `fps` follow their props; a new `timeline` handle, `strip` or `renderer` makes it afresh;
69
+ * callbacks always call the latest props.
70
+ */
71
+ export declare function Compare(props: CompareProps): import("react").JSX.Element;
72
+ export type CompareStripProps = CompareStripOptions & {
73
+ className?: string;
74
+ style?: CSSProperties;
75
+ onReady?: (strip: CompareStripHandle) => void;
76
+ };
77
+ /** `compareStrip()` as a component, on a timeline handle; new sources (by `src`) follow. */
78
+ export declare function CompareStrip(props: CompareStripProps): import("react").JSX.Element;
38
79
  export type BentoProps = BentoOptions & {
39
80
  className?: string;
40
81
  style?: CSSProperties;
@@ -70,3 +111,28 @@ export type OptionPickerProps = Omit<OptionPickerOptions, "body"> & {
70
111
  export declare function OptionPicker(props: OptionPickerProps): import("react").JSX.Element;
71
112
  export type { ActivityEvent } from "./activity-model.js";
72
113
  export type { PickerOption } from "./picker.js";
114
+ export type WalkthroughProps = WalkthroughOptions & {
115
+ className?: string;
116
+ style?: CSSProperties;
117
+ onReady?: (walkthrough: WalkthroughHandle) => void;
118
+ };
119
+ /**
120
+ * `walkthrough()` as a component: a new `doc` is a new draft (answers carry over by step key);
121
+ * `onFeedback` always calls the latest prop.
122
+ */
123
+ export declare function Walkthrough(props: WalkthroughProps): import("react").JSX.Element;
124
+ export type TasteTestProps = TasteTestOptions & {
125
+ className?: string;
126
+ style?: CSSProperties;
127
+ onReady?: (test: TasteTestHandle) => void;
128
+ };
129
+ /** `tasteTest()` as a component: `picked` follows its prop; new `options` make it afresh. */
130
+ export declare function TasteTest(props: TasteTestProps): import("react").JSX.Element;
131
+ export type MediaSlotProps = MediaSlotOptions & {
132
+ className?: string;
133
+ style?: CSSProperties;
134
+ onReady?: (slot: MediaSlotHandle) => void;
135
+ };
136
+ /** `mediaSlot()` as a component: one walkthrough media slot; new `media` mounts afresh. */
137
+ export declare function MediaSlot(props: MediaSlotProps): import("react").JSX.Element;
138
+ export type { WalkthroughDoc, WalkthroughFeedback } from "./walkthrough-model.js";
@@ -2,8 +2,8 @@
2
2
  * A thin scrollbar drawn over a scroller's content, in place of the native one beside it. A native
3
3
  * scrollbar that's always shown (as a system may be set) takes its width from the rows the moment
4
4
  * the content overflows, so every row jumps sideways, and gives it back when it stops; this one
5
- * takes no room. It shows while the content scrolls and while the pointer is over the scroller,
6
- * and drags. `content` is the element whose height makes the scroll: it's watched for changes.
5
+ * takes no room. It shows while the pointer is over the scroller, while you scroll it and while
6
+ * you drag it; a scroll from code (a reveal, a restored position) doesn't flash it. `content` is the element whose height makes the scroll: it's watched for changes.
7
7
  * The scroller hides its own (`scrollbar-width: none`) and is positioned.
8
8
  */
9
9
  export declare function overlayScrollbar(scroller: HTMLElement, content: Element): {
@@ -1,10 +1,15 @@
1
1
  import { type JSX } from "solid-js";
2
2
  import { type Activity as ActivityHandle, type ActivityOptions } from "./activity.js";
3
3
  import { type Bento as BentoHandle, type BentoOptions } from "./bento.js";
4
+ import { type CodeDiff as CodeDiffHandle, type CodeDiffOptions, type DiffReview as DiffReviewHandle, type DiffReviewOptions } from "./diff.js";
4
5
  import { type OptionPicker as OptionPickerHandle, type OptionPickerOptions, type PickerOption } from "./picker.js";
5
6
  import { type Split as SplitHandle, type SplitOptions } from "./split.js";
6
7
  import { type Timeline as TimelineHandle, type TimelineOptions } from "./timeline.js";
8
+ import { type Compare as CompareHandle, type CompareOptions } from "./compare.js";
9
+ import { type CompareStrip as CompareStripHandle, type CompareStripOptions } from "./compare-strip.js";
7
10
  import { type Tree as TreeHandle, type TreeOptions } from "./tree.js";
11
+ import { type TasteTest as TasteTestHandle, type TasteTestOptions, type Walkthrough as WalkthroughHandle, type WalkthroughOptions } from "./walkthrough.js";
12
+ import { type MediaSlot as MediaSlotHandle, type MediaSlotOptions } from "./walkthrough-media.js";
8
13
  export type SplitProps = SplitOptions & {
9
14
  /** One element per pane, in the panes' order; each goes into its pane's body. */
10
15
  children?: JSX.Element;
@@ -23,6 +28,20 @@ export type TreeProps<T> = TreeOptions<T> & {
23
28
  * `filter` follow their props; callbacks always call the latest props.
24
29
  */
25
30
  export declare function Tree<T>(props: TreeProps<T>): JSX.Element;
31
+ export type CodeDiffProps = CodeDiffOptions & {
32
+ onReady?: (diff: CodeDiffHandle) => void;
33
+ };
34
+ /**
35
+ * `codeDiff()` as a component. `patch`, `files`, `file`, `layout`, `wrap`, `viewed`, `height` and
36
+ * `maxHeight` follow their
37
+ * props; callbacks always call the latest props.
38
+ */
39
+ export declare function CodeDiff(props: CodeDiffProps): JSX.Element;
40
+ export type DiffReviewProps = DiffReviewOptions & {
41
+ onReady?: (review: DiffReviewHandle) => void;
42
+ };
43
+ /** `diffReview()` as a component: the file tree beside the diff; follows as `CodeDiff` does. */
44
+ export declare function DiffReview(props: DiffReviewProps): JSX.Element;
26
45
  export type TimelineProps = TimelineOptions & {
27
46
  onReady?: (timeline: TimelineHandle) => void;
28
47
  };
@@ -32,6 +51,20 @@ export type TimelineProps = TimelineOptions & {
32
51
  * always call the latest props.
33
52
  */
34
53
  export declare function Timeline(props: TimelineProps): JSX.Element;
54
+ export type CompareProps = CompareOptions & {
55
+ onReady?: (compare: CompareHandle) => void;
56
+ };
57
+ /**
58
+ * `compare()` as a component, made once (with the `timeline`, `strip` and `renderer` it starts
59
+ * with). `before`, `after` (by `src`), `mode`, `wipe`, `loupe`, `threshold` and `fps` follow
60
+ * their props; callbacks always call the latest props.
61
+ */
62
+ export declare function Compare(props: CompareProps): JSX.Element;
63
+ export type CompareStripProps = CompareStripOptions & {
64
+ onReady?: (strip: CompareStripHandle) => void;
65
+ };
66
+ /** `compareStrip()` as a component, on a timeline handle; new sources (by `src`) follow. */
67
+ export declare function CompareStrip(props: CompareStripProps): JSX.Element;
35
68
  export type BentoProps = BentoOptions & {
36
69
  onReady?: (bento: BentoHandle) => void;
37
70
  };
@@ -61,3 +94,22 @@ export type OptionPickerProps = Omit<OptionPickerOptions, "body"> & {
61
94
  export declare function OptionPicker(props: OptionPickerProps): JSX.Element;
62
95
  export type { ActivityEvent } from "./activity-model.js";
63
96
  export type { PickerOption } from "./picker.js";
97
+ export type WalkthroughProps = WalkthroughOptions & {
98
+ onReady?: (walkthrough: WalkthroughHandle) => void;
99
+ };
100
+ /**
101
+ * `walkthrough()` as a component: a new `doc` is a new draft (answers carry over by step key);
102
+ * `onFeedback` always calls the latest prop.
103
+ */
104
+ export declare function Walkthrough(props: WalkthroughProps): JSX.Element;
105
+ export type TasteTestProps = TasteTestOptions & {
106
+ onReady?: (test: TasteTestHandle) => void;
107
+ };
108
+ /** `tasteTest()` as a component: `picked` follows its prop. */
109
+ export declare function TasteTest(props: TasteTestProps): JSX.Element;
110
+ export type MediaSlotProps = MediaSlotOptions & {
111
+ onReady?: (slot: MediaSlotHandle) => void;
112
+ };
113
+ /** `mediaSlot()` as a component: one walkthrough media slot. */
114
+ export declare function MediaSlot(props: MediaSlotProps): JSX.Element;
115
+ export type { WalkthroughDoc, WalkthroughFeedback } from "./walkthrough-model.js";
@@ -37,6 +37,14 @@ export interface TimelineOptions extends UiLook {
37
37
  readonly speed?: number;
38
38
  /** Playback starts over at the end when there's no loop range (`false`: it stops). */
39
39
  readonly repeat?: boolean;
40
+ /**
41
+ * What ←/→ move: frames (one, ten with ⇧) by default, or seconds (`{ step: 0.5, shift: 2 }`),
42
+ * the playhead gliding there; `,` and `.` step a frame either way.
43
+ */
44
+ readonly arrows?: "frames" | {
45
+ readonly step: number;
46
+ readonly shift: number;
47
+ };
40
48
  readonly label?: string;
41
49
  /** The time moved: scrubbed, stepped, jumped, played (every frame) or set from code. */
42
50
  onSeek?(time: number, source: SeekSource): void;
@@ -47,29 +55,54 @@ export interface TimelineOptions extends UiLook {
47
55
  onRanges?(ranges: readonly TimelineRange[]): void;
48
56
  /** Playback passed a marker. */
49
57
  onCross?(marker: TimelineMarker): void;
58
+ /** The visible window moved: a zoom, a pan, a fit or a follow. */
59
+ onView?(view: TimeView): void;
50
60
  /**
51
61
  * Play, each marker and the playhead take codes in the page's hint mode (`s`), on by default:
52
62
  * a marker's code jumps to it, the playhead's focuses the timeline.
53
63
  */
54
64
  readonly hints?: boolean;
55
65
  }
66
+ /** What `listen` reports: the same as the options' callbacks, for pieces bound to a timeline. */
67
+ export interface TimelineListener {
68
+ onSeek?(time: number, source: SeekSource): void;
69
+ onPlay?(playing: boolean): void;
70
+ onView?(view: TimeView): void;
71
+ /** A scrub of the playhead started (`true`) or let go (`false`). */
72
+ onScrub?(active: boolean): void;
73
+ /** Ranges were set, moved or cleared (the whole list). */
74
+ onRanges?(ranges: readonly TimelineRange[]): void;
75
+ }
56
76
  export interface Timeline {
57
77
  readonly element: HTMLElement;
58
78
  readonly time: number;
59
79
  readonly playing: boolean;
80
+ readonly duration: number;
81
+ readonly fps: number;
60
82
  readonly markers: readonly TimelineMarker[];
61
83
  readonly ranges: readonly TimelineRange[];
62
84
  readonly view: TimeView;
63
- seek(time: number): void;
85
+ /** `glide`: the playhead springs there (the time, and what it drives, land at once). */
86
+ seek(time: number, options?: {
87
+ readonly glide?: boolean;
88
+ }): void;
64
89
  play(): void;
65
90
  pause(): void;
66
91
  toggle(): void;
67
92
  /** New duration, markers, ranges, fps, units or speed; the time and view stay. */
68
- update(next: Partial<Omit<TimelineOptions, "onSeek" | "onPlay" | "onMarkers" | "onRanges" | "onCross">>): void;
93
+ update(next: Partial<Omit<TimelineOptions, "onSeek" | "onPlay" | "onMarkers" | "onRanges" | "onCross" | "onView">>): void;
69
94
  /** Shows the whole duration (animated). */
70
95
  fit(): void;
71
96
  /** Zooms by `factor` (above 1 zooms in) around a time (the playhead's by default). */
72
97
  zoom(factor: number, at?: number): void;
98
+ /** Hears seeks, play and pause, and view moves alongside the options' callbacks; returns a stop. */
99
+ listen(listener: TimelineListener): () => void;
100
+ /**
101
+ * While playing, time follows `clock` (seconds, `Infinity` once it has run out: a video's
102
+ * `currentTime`, say) instead of the timeline's own frame clock, so the two never drift; loops
103
+ * and the end still apply. `null` hands time back.
104
+ */
105
+ drive(clock: (() => number) | null): void;
73
106
  focus(): void;
74
107
  dispose(): void;
75
108
  }
@@ -29,8 +29,8 @@ export interface TreeOptions<T> extends UiLook {
29
29
  readonly getLabel?: (item: T) => string;
30
30
  /** A glyph, SVG markup or node before the label. */
31
31
  readonly icon?: (item: T) => string | Node | undefined;
32
- /** Dimmed text after the label (a count, a kind). */
33
- readonly detail?: (item: T) => string | undefined;
32
+ /** Dimmed text (or a node of your own) after the label: a count, a kind. */
33
+ readonly detail?: (item: T) => string | Node | undefined;
34
34
  /** Your own content in place of the label. */
35
35
  readonly render?: (item: T, row: TreeRowContext) => Node | string | undefined | void;
36
36
  readonly selection?: Iterable<string>;
@@ -63,6 +63,11 @@ export interface TreeOptions<T> extends UiLook {
63
63
  * row as a click does. While the page has hint mode, `s` goes to it rather than type-ahead.
64
64
  */
65
65
  readonly hints?: boolean;
66
+ /**
67
+ * The selected row (one) shows as one highlight that glides to the next row selected, on the
68
+ * rows' own spring, instead of each row lighting in place. Several selected rows light in place.
69
+ */
70
+ readonly glide?: boolean;
66
71
  }
67
72
  export interface Tree<T> {
68
73
  readonly element: HTMLElement;
@@ -0,0 +1 @@
1
+ export declare const walkthroughCss: string;
@@ -0,0 +1,29 @@
1
+ import { type UiLook } from "./look.js";
2
+ import { type ContextEvent, type MediaContext, type WalkthroughMedia } from "./walkthrough-model.js";
3
+ export interface MediaSlotOptions extends UiLook {
4
+ readonly media: WalkthroughMedia;
5
+ /** Mount heavy kinds near the view and let them go far from it (on by default). */
6
+ readonly lazy?: boolean;
7
+ /** Kit played, paused or sought a video, or showed another diff file (for a note's log). */
8
+ readonly onEvent?: (event: Omit<ContextEvent, "at" | "step">) => void;
9
+ }
10
+ export interface MediaSlot {
11
+ readonly element: HTMLElement;
12
+ /** Whether its content is mounted (heavy kinds wait until they're near the view). */
13
+ readonly mounted: boolean;
14
+ /** Pauses any video in it. */
15
+ pause(): void;
16
+ /** Moves its video (or compare) by `seconds`; false when there's none mounted. */
17
+ seekBy(seconds: number): boolean;
18
+ /** What it's showing now: a video's time, a compare's loop, zoom and mode, a diff's file. */
19
+ context(): MediaContext | null;
20
+ /** A zoomed compare back to the whole picture; false when nothing was zoomed. */
21
+ unzoom(): boolean;
22
+ /** Fills the slot's height (its step full window) or goes back: a diff switches its height. */
23
+ fill(on: boolean): void;
24
+ dispose(): void;
25
+ }
26
+ /** Adds the walkthrough's stylesheet once per document. */
27
+ export declare function injectWalkthroughStyles(doc: Document): void;
28
+ export declare function mediaSlot(container: HTMLElement, options: MediaSlotOptions): MediaSlot;
29
+ export declare const CHECK: string;