@kitlangton/knobs 0.4.0-next.6 → 0.4.0-next.7
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 +3 -3
- package/dist/dev/{chunk-ya44t7z5.js → chunk-a9pwf5c0.js} +28 -22
- package/dist/dev/{chunk-nhz9en4k.js → chunk-tttj4xpd.js} +1 -1
- package/dist/dev/index.js +3 -3
- package/dist/panel.js +28 -22
- package/dist/types/ui/compare-css.d.ts +1 -1
- package/dist/types/ui/compare.d.ts +1 -1
- package/dist/types/ui/player-css.d.ts +1 -1
- package/dist/types/ui/player.d.ts +0 -9
- package/dist/types/ui/timeline.d.ts +2 -4
- package/dist/types/ui/walkthrough-blocks.d.ts +14 -2
- package/dist/types/ui/walkthrough-media.d.ts +3 -1
- package/dist/ui-react.js +94 -82
- package/dist/ui-solid.js +94 -82
- package/dist/ui.js +256 -250
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1213,9 +1213,9 @@ compare(viewer, { before, after, timeline: clock })
|
|
|
1213
1213
|
compareStrip(strip, { before, after, timeline: clock })
|
|
1214
1214
|
```
|
|
1215
1215
|
|
|
1216
|
-
**`compare(container, options)`** is a before/after viewer for videos and images (by extension, or `kind`). It offers two modes, side by side (the default `mode`: a split screen down the middle, each side filling its half) and a wipe; `modes: ["side", "wipe", "difference"]` adds a difference (changes above `threshold` in one accent, `--k-compare-diff`), and one mode hides the bar. The modes sit in a segmented control above the stage, the selection pill sliding to the one picked. It draws in one WebGPU pass that copies a frame in only when one arrives, and draws only when something changed; where there's no WebGPU, two `<video>`s with a clip-path wipe stand in. Pinch, `⌘`/ctrl-wheel or double-click zooms into either side and both zoom to the same part (the wheel and a drag pan it, both 1:1); a small glass pill in the corner shows how far, with a reset (`0`, a double-click, `Escape`), which glides back. Side ↔ Wipe is Kit Motion's Comparison fuse: the two sides glide together on one spring (.3 s) and fuse at one side's size in the middle, so the stage never changes size; Before is cut only where they overlap, with a feather that swells mid-transition and a blurred strip over the seam, the wipe's handle fades in with it, and the labels fold to their names and ride either side of the seam (Wipe → Side runs it back, and either way it can be turned around midway). Overlaid, the sides are letterboxed, never cropped. Both videos run from one clock: paused, scrubbed or stepped, each seeks to the frame's midpoint, coalesced while a seek is in flight; playing, After leads, Before's rate leans by up to 25% to stay on it (it seeks past 90 ms), and a bound timeline follows After's time, so only one clock ever moves it (`Space` resumes from the frame showing). Scrubbing answers at once even on raw screen recordings with a keyframe every 8–18 s: frames decoded in the background (WebCodecs where the file is a plain MP4, else a hidden `<video>`) sit in a small cache shared by every viewer and strip of the same source, and the nearest shows while the exact seek lands (mid-drag, far from any cached frame, `fastSeek` answers first; letting go seeks exactly). Encoding with a keyframe every 15 frames makes every seek exact and near instant: `COMPARE_FFMPEG` holds the command (`ffmpeg -i in.mov -vf fps=30 -fps_mode cfr -c:v libx264 -crf 18 -g 15 … out.mp4`). Sources load only near the view and are let go 3 s after leaving it (`lazy: false` keeps them), every viewer shares one GPU device, and in a container with no height of its own it takes the height its sides need, half its width in their shape, so the split has no margins (`aspect` before they load); with a height of its own (a card going full-window, say), the pair fits as a whole and refits as it resizes, keeping the zoom. On a card (`.knobs-surface`, a split's pane) or marked `data-nested`, its stage drops its fill, so one surface shows. Bind an existing `timeline()` (`timeline: clock`), or pass `timeline: true` for one of its own: a player's thin progress line under the stage (`variant: "line"`, the same as `player()`'s), its markers (a walkthrough's chapters) segments with a small gap between; there's no clock or frame readout anywhere, only the chapter and time under the pointer over the line.
|
|
1216
|
+
**`compare(container, options)`** is a before/after viewer for videos and images (by extension, or `kind`). It offers two modes, side by side (the default `mode`: a split screen down the middle, each side filling its half) and a wipe; `modes: ["side", "wipe", "difference"]` adds a difference (changes above `threshold` in one accent, `--k-compare-diff`), and one mode hides the bar. The modes sit in a segmented control above the stage, the selection pill sliding to the one picked. It draws in one WebGPU pass that copies a frame in only when one arrives, and draws only when something changed; where there's no WebGPU, two `<video>`s with a clip-path wipe stand in. Pinch, `⌘`/ctrl-wheel or double-click zooms into either side and both zoom to the same part (the wheel and a drag pan it, both 1:1); a small glass pill in the corner shows how far, with a reset (`0`, a double-click, `Escape`), which glides back. Side ↔ Wipe is Kit Motion's Comparison fuse: the two sides glide together on one spring (.3 s) and fuse at one side's size in the middle, so the stage never changes size; Before is cut only where they overlap, with a feather that swells mid-transition and a blurred strip over the seam, the wipe's handle fades in with it, and the labels fold to their names and ride either side of the seam (Wipe → Side runs it back, and either way it can be turned around midway). Overlaid, the sides are letterboxed, never cropped. Both videos run from one clock: paused, scrubbed or stepped, each seeks to the frame's midpoint, coalesced while a seek is in flight; playing, After leads, Before's rate leans by up to 25% to stay on it (it seeks past 90 ms), and a bound timeline follows After's time, so only one clock ever moves it (`Space` resumes from the frame showing). Scrubbing answers at once even on raw screen recordings with a keyframe every 8–18 s: frames decoded in the background (WebCodecs where the file is a plain MP4, else a hidden `<video>`) sit in a small cache shared by every viewer and strip of the same source, and the nearest shows while the exact seek lands (mid-drag, far from any cached frame, `fastSeek` answers first; letting go seeks exactly). Encoding with a keyframe every 15 frames makes every seek exact and near instant: `COMPARE_FFMPEG` holds the command (`ffmpeg -i in.mov -vf fps=30 -fps_mode cfr -c:v libx264 -crf 18 -g 15 … out.mp4`). Sources load only near the view and are let go 3 s after leaving it (`lazy: false` keeps them), every viewer shares one GPU device, and in a container with no height of its own it takes the height its sides need, half its width in their shape, so the split has no margins (`aspect` before they load); with a height of its own (a card going full-window, say), the pair fits as a whole and refits as it resizes, keeping the zoom. On a card (`.knobs-surface`, a split's pane) or marked `data-nested`, its stage drops its fill, so one surface shows. Bind an existing `timeline()` (`timeline: clock`), or pass `timeline: true` for one of its own: a player's thin progress line under the stage (`variant: "line"`, the same as `player()`'s), its markers (a walkthrough's chapters) segments with a small gap between; there's no clock or frame readout anywhere, only the chapter and time under the pointer over the line. Its row starts with a minimal play/pause button (`Space` too, focused); a click on the stage never plays. `seek(t, { glide: true })` is a chapter's jump: the videos land at once and the playhead catches up. Loop (`L`, the loop icon) sets a loop range around the playhead on the timeline, whose ends drag, and playback stays inside it. The wipe's line carries a raised 16×28 grip in its middle that follows the pointer's height only while dragged and settles back when let go; dragging is 1:1, the cursor hides and the line and grip brighten, and a press elsewhere on the stage brings the line there on a quick catch-up (.15 s). Before and After ride either side of the seam while wiping, each fading as its side runs out of room. The wipe is a slider too (`←`/`→`, `⇧` 10%); a mode change glides. Keys when focused: `Space` plays, `←`/`→` seek half a second (`⇧` two), the playhead gliding there while the videos land at once, `,`/`.` step a frame, `1`–`3` pick the offered modes in order and `S` `W` (`D`, when offered) by name, `Z` held shows the loupe (or `loupe: true`), `L` loops, `=`/`-`/`0` zoom. It reports `onMode`, `onWipe` and `onView({ zoom, loop })`; the handle has `mode`, `modes`, `wipe`, `zoom`, `loop`, `time`, `playing`, `duration`, `renderer`, `timeline`, `strip`, `update`, `seek`, `seekBy`, `play`, `pause`, `toggle`, `step`, `setZoom`, `setLoop`, `focus` and `dispose`. A frame strip is off by default (`strip: true` puts one over the timeline); **`compareStrip(container, { before, after, timeline })`** is the same piece on its own: it draws Before over After along the timeline's view from the same frame cache, decoded only while it's on screen, with a bar for how much each column differs; a press scrubs. `Compare` and `CompareStrip` are in `knobs/ui/react` and `knobs/ui/solid`. The Lab's View switch shows one on its scene timeline.
|
|
1217
1217
|
|
|
1218
|
-
**`player(container, { src, chapters? })`** is a plain video in the same look: the picture in the compare's frame, then one thin progress line
|
|
1218
|
+
**`player(container, { src, chapters? })`** is a plain video in the same look: the picture in the compare's frame, then a row under it: a minimal play/pause button (the filled pair, a 28px target, a quiet fill on hover) and one thin progress line (2px, the tertiary text colour filled in text colour, a segment per chapter `{ label, start }`, thicker under the pointer). The button, or `Space` once it's focused (a click on the picture focuses it), plays and pauses; a click on the picture never plays; click or drag the line to seek, 1:1, and a click away from where it is glides there while the video lands at once. The chapter and time under the pointer float over the line; `←`/`→` seek 5 s (`⇧` 10 s), and a pinch, `⌘`/ctrl-wheel or `=`/`-` zoom the line as a lane's. The picture comes in with its first frame (a 4px blur and a fade). It takes `poster`, `captions` (WebVTT), `loop` (true), `muted` (true), `aspect` and `fps`, reports `onPlay(playing, time)` and `onSeek(time)` (a seek that landed, paused), and the handle has `video`, `timeline`, `time`, `playing`, `duration`, `play`, `pause`, `toggle`, `seek(t, { glide })`, `seekBy`, `focus` and `dispose`. Under it is `timeline(…, { variant: "line" })`, which you can bind to anything else with a clock.
|
|
1219
1219
|
|
|
1220
1220
|
### Activity
|
|
1221
1221
|
|
|
@@ -1393,7 +1393,7 @@ The demo is `examples/walkthrough.html`.
|
|
|
1393
1393
|
"provenance": "inferred", "source": "edge", "step": "4.8" } ] }] }
|
|
1394
1394
|
```
|
|
1395
1395
|
|
|
1396
|
-
**`stack`**: PRs in merge order as a branch graph. `branch` is `"head → base"` (or `head` and `base`); an item whose base is another's head hangs under it, joined by a drawn rail, and the rest sit on the trunk (`base`, else the branch most items merge into), named at the top. An item on a branch that's neither shows it. `delta` is `"+164 / -18"` or `{ add, del }`, drawn green and red; `status`
|
|
1396
|
+
**`stack`**: PRs in merge order as a branch graph. `branch` is `"head → base"` (or `head` and `base`); an item whose base is another's head hangs under it, joined by a drawn rail, and the rest sit on the trunk (`base`, else the branch most items merge into), named at the top. An item on a branch that's neither shows it. `delta` is `"+164 / -18"` or `{ add, del }`, drawn green and red; its PR's state shows the GitHub way, from the doc's `prs` or the first word of `status` (`merged`, `open`, `draft`, `closed`, any case), never from `tone`: the merge or pull-request glyph and word, open and merged quietly tinted, draft and closed faint, and a small check after it where `status` says the checks pass (`green`, `passing`, `CI`). Any other `status` is a chip in its `tone`. `step` (or `stepId`) makes the whole row go to that step, its title underlining under the pointer, with nothing trailing it; the PR number links out (`href`, else the doc's `prs` or `repo`).
|
|
1397
1397
|
|
|
1398
1398
|
```json
|
|
1399
1399
|
{ "kind": "stack", "base": "dev", "items": [
|
|
@@ -11453,13 +11453,14 @@ var compareCss = `
|
|
|
11453
11453
|
picked: the pill's bright copy is. */
|
|
11454
11454
|
.knobs-cmp-modes{position:relative;display:inline-flex;height:var(--_k-control-h);border-radius:var(--_k-radius);background:var(--_k-fill)}
|
|
11455
11455
|
.knobs-cmp-modes[hidden]{display:none}
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
|
|
11456
|
+
/* Hover is a quiet fill under the arrow cursor (no hand, no brightening), there at once. */
|
|
11457
|
+
.knobs-ui .knobs-cmp-mode{display:inline-flex;align-items:center;height:100%;padding:0 8px;border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:default;white-space:nowrap;
|
|
11458
|
+
transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
11459
|
+
.knobs-ui .knobs-cmp-mode:not([aria-checked="true"]):is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
11459
11460
|
/* Toggles: icon buttons, the accent's wash when on. */
|
|
11460
|
-
.knobs-ui .knobs-cmp-toggle{display:inline-flex;align-items:center;justify-content:center;width:var(--_k-control-h);height:var(--_k-control-h);border-radius:var(--_k-radius);color:var(--_k-fg-
|
|
11461
|
-
transition:
|
|
11462
|
-
.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){
|
|
11461
|
+
.knobs-ui .knobs-cmp-toggle{display:inline-flex;align-items:center;justify-content:center;width:var(--_k-control-h);height:var(--_k-control-h);border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:default;
|
|
11462
|
+
transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
11463
|
+
.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
11463
11464
|
.knobs-ui .knobs-cmp-toggle[aria-pressed="true"]{color:var(--_k-accent-fg);background:var(--_k-accent-soft)}
|
|
11464
11465
|
.knobs-cmp-toggle svg{display:block}
|
|
11465
11466
|
.knobs-cmp-fill{flex:1}
|
|
@@ -11473,11 +11474,10 @@ var compareCss = `
|
|
|
11473
11474
|
.knobs-cmp-stage{position:relative;flex:1;min-height:96px;overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_ku-cmp-stage);touch-action:pan-y;outline:none}
|
|
11474
11475
|
.knobs-compare[data-frame="flat"] .knobs-cmp-stage{border-radius:0}
|
|
11475
11476
|
.knobs-compare[data-mode="wipe"] .knobs-cmp-stage{cursor:ew-resize}
|
|
11476
|
-
/* Videos: a click on the stage plays and pauses. */
|
|
11477
|
-
.knobs-compare[data-video]:not([data-mode="wipe"],[data-zoomed]) .knobs-cmp-stage{cursor:pointer}
|
|
11478
11477
|
/* Unzoomed, a finger still scrolls the page up and down; zoomed, the stage takes every gesture. */
|
|
11479
|
-
.
|
|
11480
|
-
.knobs-compare[data-
|
|
11478
|
+
/* Zoomed, it pans: a move cursor, never a hand. */
|
|
11479
|
+
.knobs-compare[data-zoomed] .knobs-cmp-stage{cursor:move;touch-action:none}
|
|
11480
|
+
.knobs-compare[data-panning],.knobs-compare[data-panning] *{cursor:move!important}
|
|
11481
11481
|
/* Wiping, the grip stands in for the cursor. */
|
|
11482
11482
|
.knobs-compare[data-dragging],.knobs-compare[data-dragging] *{cursor:none!important}
|
|
11483
11483
|
.knobs-cmp-sizer{position:absolute;left:0;right:0;top:0;height:0;visibility:hidden;pointer-events:none}
|
|
@@ -11524,8 +11524,8 @@ var compareCss = `
|
|
|
11524
11524
|
opacity:0;scale:.96;pointer-events:none;transition:opacity .16s cubic-bezier(.4,0,1,1),scale .16s cubic-bezier(.4,0,1,1)}
|
|
11525
11525
|
.knobs-cmp-zoom[data-on]{opacity:1;scale:1;pointer-events:auto;transition:opacity .2s cubic-bezier(.2,.8,.2,1),scale .2s cubic-bezier(.2,.8,.2,1)}
|
|
11526
11526
|
:where(.knobs-ui) .knobs-cmp-zoom-reset{all:revert;box-sizing:border-box;font:inherit;letter-spacing:inherit;margin:0;border:0;outline:none;box-shadow:none;
|
|
11527
|
-
display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border-radius:999px;background:transparent;color:var(--_k-fg-2);cursor:
|
|
11528
|
-
:where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){
|
|
11527
|
+
display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border-radius:999px;background:transparent;color:var(--_k-fg-2);cursor:default;transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
11528
|
+
:where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
11529
11529
|
.knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--_k-fg-3);font-size:var(--_k-text-meta);pointer-events:none}
|
|
11530
11530
|
.knobs-cmp-note:empty{display:none}
|
|
11531
11531
|
.knobs-cmp-strip-host{flex:none;height:60px;min-height:0}
|
|
@@ -11543,23 +11543,29 @@ var playerCss = `
|
|
|
11543
11543
|
.knobs-ui.knobs-player{--_kp-stage:var(--_k-compare-stage);display:flex;flex-direction:column;gap:6px;width:100%;outline:none;
|
|
11544
11544
|
font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}
|
|
11545
11545
|
:where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui.knobs-player,.knobs-ui.knobs-player[data-nested]{--_kp-stage:var(--k-compare-stage,transparent)}
|
|
11546
|
-
.knobs-player-frame{position:relative;width:100%;aspect-ratio:var(--kp-aspect,16/9);overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_kp-stage)
|
|
11546
|
+
.knobs-player-frame{position:relative;width:100%;aspect-ratio:var(--kp-aspect,16/9);overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_kp-stage)}
|
|
11547
11547
|
.knobs-player[data-frame="flat"] .knobs-player-frame{border-radius:0}
|
|
11548
11548
|
.knobs-player-media{position:absolute;inset:0;display:block;width:100%;height:100%;margin:0;padding:0;border:0;object-fit:contain;
|
|
11549
11549
|
opacity:0;filter:blur(4px);transition:opacity calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default),filter calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default)}
|
|
11550
11550
|
.knobs-player[data-ready] .knobs-player-media{opacity:1;filter:none}
|
|
11551
|
-
.knobs-player-glyph{position:absolute;left:50%;top:50%;display:grid;place-items:center;width:44px;height:44px;margin:-22px 0 0 -22px;border-radius:50%;color:var(--_k-fg);pointer-events:none;
|
|
11552
|
-
opacity:0;filter:blur(4px);scale:.96;
|
|
11553
|
-
background:color-mix(in srgb,var(--_k-bg) 52%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.6);backdrop-filter:blur(14px) saturate(1.6);
|
|
11554
|
-
box-shadow:inset 0 0 0 .5px var(--_k-border),inset 0 1px 0 var(--_k-rim);
|
|
11555
|
-
transition:opacity calc(var(--_k-motion-snappy-ms) * 1ms) var(--_k-motion-snappy),filter calc(var(--_k-motion-snappy-ms) * 1ms) var(--_k-motion-snappy),scale calc(var(--_k-motion-snappy-ms) * 1ms) var(--_k-motion-snappy)}
|
|
11556
|
-
.knobs-player-glyph svg{width:16px;height:16px}
|
|
11557
|
-
.knobs-player-glyph[data-flash]{opacity:1;filter:none;scale:1}
|
|
11558
11551
|
.knobs-player-line{flex:none;min-height:0}
|
|
11559
|
-
/*
|
|
11560
|
-
|
|
11552
|
+
/* The timeline's own stylesheet is look.ts's; what the player's row and every timeline share
|
|
11553
|
+
about the hand is set here, after it. No hand cursor anywhere (the arrow, or a resize where it
|
|
11554
|
+
resizes); hover is a quiet fill (fill-hover), in at once (hover-in, 0 ms), out easing. */
|
|
11555
|
+
.knobs-ui .knobs-tl-play,.knobs-ui.knobs-timeline :is(.knobs-tl-pin,.knobs-tl-rlabel),
|
|
11556
|
+
.knobs-ui.knobs-timeline[data-dragging] .knobs-tl-marker :is(.knobs-tl-pin,.knobs-tl-mlabel){cursor:default}
|
|
11561
11557
|
.knobs-ui .knobs-tl-play:hover,.knobs-tl-edge:hover::after,.knobs-tl-rlabel:hover,.knobs-tl-track:hover .knobs-tl-hover,
|
|
11562
11558
|
.knobs-timeline[data-variant="line"] .knobs-tl-track:hover .knobs-tl-segs{transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
11559
|
+
/* The line's row: a minimal play/pause (the filled pair, a 28px target, no fill at rest), then
|
|
11560
|
+
the line, centred on it. */
|
|
11561
|
+
.knobs-ui.knobs-timeline[data-variant="line"]{gap:4px;align-items:center}
|
|
11562
|
+
.knobs-timeline[data-variant="line"] .knobs-tl-transport{display:flex}
|
|
11563
|
+
.knobs-ui.knobs-timeline[data-variant="line"] .knobs-tl-play{width:28px;height:28px;min-width:28px;min-height:28px;border-radius:var(--_k-radius);background:transparent;color:var(--_k-fg-2);
|
|
11564
|
+
transition:background calc(var(--_k-hover-out) * 1ms),transform .15s var(--_ku-ease)}
|
|
11565
|
+
.knobs-ui.knobs-timeline[data-variant="line"][data-playing] .knobs-tl-play{background:transparent;color:var(--_k-fg-2)}
|
|
11566
|
+
.knobs-ui.knobs-timeline[data-variant="line"] .knobs-tl-play:hover{background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
11567
|
+
.knobs-ui.knobs-timeline[data-variant="line"] .knobs-tl-track{cursor:default;transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
11568
|
+
.knobs-ui.knobs-timeline[data-variant="line"] .knobs-tl-track:hover{background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
11563
11569
|
`;
|
|
11564
11570
|
|
|
11565
11571
|
// src/ui/overlay-css.ts
|
|
@@ -85,7 +85,7 @@ function attach(controls, element, options = {}) {
|
|
|
85
85
|
return;
|
|
86
86
|
loading = !0;
|
|
87
87
|
try {
|
|
88
|
-
let { createPanel } = await (__preload("
|
|
88
|
+
let { createPanel } = await (__preload("a9pwf5c0"), import("./chunk-a9pwf5c0.js"));
|
|
89
89
|
if (disposed || !controls.enabled || panel)
|
|
90
90
|
return;
|
|
91
91
|
if (panel = createPanel(controls, element, close, { restored, chip }), remember)
|
package/dist/dev/index.js
CHANGED
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
urlFlag2,
|
|
77
77
|
storageKey
|
|
78
78
|
} from "./chunk-3ygqgy1x.js";
|
|
79
|
-
__chunks(import.meta.url,["
|
|
79
|
+
__chunks(import.meta.url,["zgxm4jdw","a9pwf5c0","tttj4xpd","3ygqgy1x","dyq4m24m"],[["./index.js",3],["./chunk-a9pwf5c0.js",3,4],["./chunk-tttj4xpd.js",3,4],["./chunk-3ygqgy1x.js"],["./chunk-dyq4m24m.js",3]],0);
|
|
80
80
|
// src/core/random.ts
|
|
81
81
|
var lattice = (min, max, step, r) => min + Math.floor(r * (Math.floor((max - min) / step + 0.000000001) + 1)) * step, between = (min, max, r) => min + (max - min) * r;
|
|
82
82
|
function pick(field, random) {
|
|
@@ -1378,11 +1378,11 @@ function defineControls(id, input, options = {}) {
|
|
|
1378
1378
|
code: (format, values) => formatCode(values ?? get(), format),
|
|
1379
1379
|
variants,
|
|
1380
1380
|
attach(element, chip) {
|
|
1381
|
-
let load = options.ship ? () => options.ship().then((m) => m.attach) : () => (__preload("
|
|
1381
|
+
let load = options.ship ? () => options.ship().then((m) => m.attach) : () => (__preload("tttj4xpd"), import("./chunk-tttj4xpd.js")).then((m) => m.attach);
|
|
1382
1382
|
return live(load, (attach) => attach(controls, element, chip), (detach) => detach());
|
|
1383
1383
|
},
|
|
1384
1384
|
mount(container, mountOptions) {
|
|
1385
|
-
let load = options.ship ? () => options.ship().then((m) => m.mountPanel) : () => (__preload("
|
|
1385
|
+
let load = options.ship ? () => options.ship().then((m) => m.mountPanel) : () => (__preload("a9pwf5c0"), import("./chunk-a9pwf5c0.js")).then((m) => m.mountPanel);
|
|
1386
1386
|
return live(load, (mountPanel) => {
|
|
1387
1387
|
let panel = mountPanel(controls, container, mountOptions);
|
|
1388
1388
|
return mountOptions?.onReady?.(panel), panel;
|
package/dist/panel.js
CHANGED
|
@@ -21076,13 +21076,14 @@ var compareCss = `
|
|
|
21076
21076
|
picked: the pill's bright copy is. */
|
|
21077
21077
|
.knobs-cmp-modes{position:relative;display:inline-flex;height:var(--_k-control-h);border-radius:var(--_k-radius);background:var(--_k-fill)}
|
|
21078
21078
|
.knobs-cmp-modes[hidden]{display:none}
|
|
21079
|
-
|
|
21080
|
-
|
|
21081
|
-
|
|
21079
|
+
/* Hover is a quiet fill under the arrow cursor (no hand, no brightening), there at once. */
|
|
21080
|
+
.knobs-ui .knobs-cmp-mode{display:inline-flex;align-items:center;height:100%;padding:0 8px;border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:default;white-space:nowrap;
|
|
21081
|
+
transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
21082
|
+
.knobs-ui .knobs-cmp-mode:not([aria-checked="true"]):is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
21082
21083
|
/* Toggles: icon buttons, the accent's wash when on. */
|
|
21083
|
-
.knobs-ui .knobs-cmp-toggle{display:inline-flex;align-items:center;justify-content:center;width:var(--_k-control-h);height:var(--_k-control-h);border-radius:var(--_k-radius);color:var(--_k-fg-
|
|
21084
|
-
transition:
|
|
21085
|
-
.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){
|
|
21084
|
+
.knobs-ui .knobs-cmp-toggle{display:inline-flex;align-items:center;justify-content:center;width:var(--_k-control-h);height:var(--_k-control-h);border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:default;
|
|
21085
|
+
transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
21086
|
+
.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
21086
21087
|
.knobs-ui .knobs-cmp-toggle[aria-pressed="true"]{color:var(--_k-accent-fg);background:var(--_k-accent-soft)}
|
|
21087
21088
|
.knobs-cmp-toggle svg{display:block}
|
|
21088
21089
|
.knobs-cmp-fill{flex:1}
|
|
@@ -21096,11 +21097,10 @@ var compareCss = `
|
|
|
21096
21097
|
.knobs-cmp-stage{position:relative;flex:1;min-height:96px;overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_ku-cmp-stage);touch-action:pan-y;outline:none}
|
|
21097
21098
|
.knobs-compare[data-frame="flat"] .knobs-cmp-stage{border-radius:0}
|
|
21098
21099
|
.knobs-compare[data-mode="wipe"] .knobs-cmp-stage{cursor:ew-resize}
|
|
21099
|
-
/* Videos: a click on the stage plays and pauses. */
|
|
21100
|
-
.knobs-compare[data-video]:not([data-mode="wipe"],[data-zoomed]) .knobs-cmp-stage{cursor:pointer}
|
|
21101
21100
|
/* Unzoomed, a finger still scrolls the page up and down; zoomed, the stage takes every gesture. */
|
|
21102
|
-
.
|
|
21103
|
-
.knobs-compare[data-
|
|
21101
|
+
/* Zoomed, it pans: a move cursor, never a hand. */
|
|
21102
|
+
.knobs-compare[data-zoomed] .knobs-cmp-stage{cursor:move;touch-action:none}
|
|
21103
|
+
.knobs-compare[data-panning],.knobs-compare[data-panning] *{cursor:move!important}
|
|
21104
21104
|
/* Wiping, the grip stands in for the cursor. */
|
|
21105
21105
|
.knobs-compare[data-dragging],.knobs-compare[data-dragging] *{cursor:none!important}
|
|
21106
21106
|
.knobs-cmp-sizer{position:absolute;left:0;right:0;top:0;height:0;visibility:hidden;pointer-events:none}
|
|
@@ -21147,8 +21147,8 @@ var compareCss = `
|
|
|
21147
21147
|
opacity:0;scale:.96;pointer-events:none;transition:opacity .16s cubic-bezier(.4,0,1,1),scale .16s cubic-bezier(.4,0,1,1)}
|
|
21148
21148
|
.knobs-cmp-zoom[data-on]{opacity:1;scale:1;pointer-events:auto;transition:opacity .2s cubic-bezier(.2,.8,.2,1),scale .2s cubic-bezier(.2,.8,.2,1)}
|
|
21149
21149
|
:where(.knobs-ui) .knobs-cmp-zoom-reset{all:revert;box-sizing:border-box;font:inherit;letter-spacing:inherit;margin:0;border:0;outline:none;box-shadow:none;
|
|
21150
|
-
display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border-radius:999px;background:transparent;color:var(--_k-fg-2);cursor:
|
|
21151
|
-
:where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){
|
|
21150
|
+
display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border-radius:999px;background:transparent;color:var(--_k-fg-2);cursor:default;transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
21151
|
+
:where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
21152
21152
|
.knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--_k-fg-3);font-size:var(--_k-text-meta);pointer-events:none}
|
|
21153
21153
|
.knobs-cmp-note:empty{display:none}
|
|
21154
21154
|
.knobs-cmp-strip-host{flex:none;height:60px;min-height:0}
|
|
@@ -21166,23 +21166,29 @@ var playerCss = `
|
|
|
21166
21166
|
.knobs-ui.knobs-player{--_kp-stage:var(--_k-compare-stage);display:flex;flex-direction:column;gap:6px;width:100%;outline:none;
|
|
21167
21167
|
font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}
|
|
21168
21168
|
:where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui.knobs-player,.knobs-ui.knobs-player[data-nested]{--_kp-stage:var(--k-compare-stage,transparent)}
|
|
21169
|
-
.knobs-player-frame{position:relative;width:100%;aspect-ratio:var(--kp-aspect,16/9);overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_kp-stage)
|
|
21169
|
+
.knobs-player-frame{position:relative;width:100%;aspect-ratio:var(--kp-aspect,16/9);overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_kp-stage)}
|
|
21170
21170
|
.knobs-player[data-frame="flat"] .knobs-player-frame{border-radius:0}
|
|
21171
21171
|
.knobs-player-media{position:absolute;inset:0;display:block;width:100%;height:100%;margin:0;padding:0;border:0;object-fit:contain;
|
|
21172
21172
|
opacity:0;filter:blur(4px);transition:opacity calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default),filter calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default)}
|
|
21173
21173
|
.knobs-player[data-ready] .knobs-player-media{opacity:1;filter:none}
|
|
21174
|
-
.knobs-player-glyph{position:absolute;left:50%;top:50%;display:grid;place-items:center;width:44px;height:44px;margin:-22px 0 0 -22px;border-radius:50%;color:var(--_k-fg);pointer-events:none;
|
|
21175
|
-
opacity:0;filter:blur(4px);scale:.96;
|
|
21176
|
-
background:color-mix(in srgb,var(--_k-bg) 52%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.6);backdrop-filter:blur(14px) saturate(1.6);
|
|
21177
|
-
box-shadow:inset 0 0 0 .5px var(--_k-border),inset 0 1px 0 var(--_k-rim);
|
|
21178
|
-
transition:opacity calc(var(--_k-motion-snappy-ms) * 1ms) var(--_k-motion-snappy),filter calc(var(--_k-motion-snappy-ms) * 1ms) var(--_k-motion-snappy),scale calc(var(--_k-motion-snappy-ms) * 1ms) var(--_k-motion-snappy)}
|
|
21179
|
-
.knobs-player-glyph svg{width:16px;height:16px}
|
|
21180
|
-
.knobs-player-glyph[data-flash]{opacity:1;filter:none;scale:1}
|
|
21181
21174
|
.knobs-player-line{flex:none;min-height:0}
|
|
21182
|
-
/*
|
|
21183
|
-
|
|
21175
|
+
/* The timeline's own stylesheet is look.ts's; what the player's row and every timeline share
|
|
21176
|
+
about the hand is set here, after it. No hand cursor anywhere (the arrow, or a resize where it
|
|
21177
|
+
resizes); hover is a quiet fill (fill-hover), in at once (hover-in, 0 ms), out easing. */
|
|
21178
|
+
.knobs-ui .knobs-tl-play,.knobs-ui.knobs-timeline :is(.knobs-tl-pin,.knobs-tl-rlabel),
|
|
21179
|
+
.knobs-ui.knobs-timeline[data-dragging] .knobs-tl-marker :is(.knobs-tl-pin,.knobs-tl-mlabel){cursor:default}
|
|
21184
21180
|
.knobs-ui .knobs-tl-play:hover,.knobs-tl-edge:hover::after,.knobs-tl-rlabel:hover,.knobs-tl-track:hover .knobs-tl-hover,
|
|
21185
21181
|
.knobs-timeline[data-variant="line"] .knobs-tl-track:hover .knobs-tl-segs{transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
21182
|
+
/* The line's row: a minimal play/pause (the filled pair, a 28px target, no fill at rest), then
|
|
21183
|
+
the line, centred on it. */
|
|
21184
|
+
.knobs-ui.knobs-timeline[data-variant="line"]{gap:4px;align-items:center}
|
|
21185
|
+
.knobs-timeline[data-variant="line"] .knobs-tl-transport{display:flex}
|
|
21186
|
+
.knobs-ui.knobs-timeline[data-variant="line"] .knobs-tl-play{width:28px;height:28px;min-width:28px;min-height:28px;border-radius:var(--_k-radius);background:transparent;color:var(--_k-fg-2);
|
|
21187
|
+
transition:background calc(var(--_k-hover-out) * 1ms),transform .15s var(--_ku-ease)}
|
|
21188
|
+
.knobs-ui.knobs-timeline[data-variant="line"][data-playing] .knobs-tl-play{background:transparent;color:var(--_k-fg-2)}
|
|
21189
|
+
.knobs-ui.knobs-timeline[data-variant="line"] .knobs-tl-play:hover{background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
21190
|
+
.knobs-ui.knobs-timeline[data-variant="line"] .knobs-tl-track{cursor:default;transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
21191
|
+
.knobs-ui.knobs-timeline[data-variant="line"] .knobs-tl-track:hover{background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
21186
21192
|
`;
|
|
21187
21193
|
|
|
21188
21194
|
// src/ui/overlay-css.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const compareCss = "\n:where(.knobs-compare,.knobs-compare *,.knobs-cmp-strip,.knobs-cmp-strip *){box-sizing:border-box}\n.knobs-ui.knobs-compare{--_ku-cmp-diff:var(--k-compare-diff,var(--_k-ok));--_ku-cmp-line:var(--_k-compare-divider);\n --_ku-cmp-stage:var(--_k-compare-stage);\n display:flex;flex-direction:column;gap:6px;width:100%;height:100%;min-height:160px;outline:none;user-select:none;-webkit-user-select:none;\n font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}\n:where(.knobs-ui) :is(.knobs-cmp-mode,.knobs-cmp-toggle){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}\n.knobs-cmp-bar{flex:none;display:flex;align-items:center;gap:var(--_k-gap);height:var(--_k-control-h)}\n/* The modes: one fill, the selection pill on the one picked; a mode isn't brighter for being\n picked: the pill's bright copy is. */\n.knobs-cmp-modes{position:relative;display:inline-flex;height:var(--_k-control-h);border-radius:var(--_k-radius);background:var(--_k-fill)}\n.knobs-cmp-modes[hidden]{display:none}\n.knobs-ui .knobs-cmp-mode{display:inline-flex;align-items:center;height:100%;padding:0 8px;border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:pointer;white-space:nowrap;\n transition:color calc(var(--_k-hover-out) * 1ms)}\n.knobs-ui .knobs-cmp-mode:is(:hover,:focus-visible){color:var(--_k-fg);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n/* Toggles: icon buttons, the accent's wash when on. */\n.knobs-ui .knobs-cmp-toggle{display:inline-flex;align-items:center;justify-content:center;width:var(--_k-control-h);height:var(--_k-control-h);border-radius:var(--_k-radius);color:var(--_k-fg-3);cursor:pointer;\n transition:color calc(var(--_k-hover-out) * 1ms),background calc(var(--_k-hover-out) * 1ms)}\n.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){color:var(--_k-fg);background:var(--_ku-wash);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-ui .knobs-cmp-toggle[aria-pressed=\"true\"]{color:var(--_k-accent-fg);background:var(--_k-accent-soft)}\n.knobs-cmp-toggle svg{display:block}\n.knobs-cmp-fill{flex:1}\n.knobs-cmp-toggle[hidden]{display:none}\n/* One surface: on a card (a walkthrough's step, a split's pane, anything .knobs-surface) or marked\n data-nested, the stage drops its fill and the sides sit on that card. */\n:where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui.knobs-compare,.knobs-ui.knobs-compare[data-nested]{--_ku-cmp-stage:var(--k-compare-stage,transparent)}\n/* In a page's flow (a container with no height), it takes the height its sides need. */\n.knobs-ui.knobs-compare[data-auto]{height:auto}\n.knobs-compare[data-auto] .knobs-cmp-stage{flex:none;min-height:0}\n.knobs-cmp-stage{position:relative;flex:1;min-height:96px;overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_ku-cmp-stage);touch-action:pan-y;outline:none}\n.knobs-compare[data-frame=\"flat\"] .knobs-cmp-stage{border-radius:0}\n.knobs-compare[data-mode=\"wipe\"] .knobs-cmp-stage{cursor:ew-resize}\n/* Videos: a click on the stage plays and pauses. */\n.knobs-compare[data-video]:not([data-mode=\"wipe\"],[data-zoomed]) .knobs-cmp-stage{cursor:pointer}\n/* Unzoomed, a finger still scrolls the page up and down; zoomed, the stage takes every gesture. */\n.knobs-compare[data-zoomed] .knobs-cmp-stage{cursor:grab;touch-action:none}\n.knobs-compare[data-panning],.knobs-compare[data-panning] *{cursor:grabbing!important}\n/* Wiping, the grip stands in for the cursor. */\n.knobs-compare[data-dragging],.knobs-compare[data-dragging] *{cursor:none!important}\n.knobs-cmp-sizer{position:absolute;left:0;right:0;top:0;height:0;visibility:hidden;pointer-events:none}\n.knobs-cmp-canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}\n.knobs-cmp-media{position:absolute;left:0;top:0;display:block;max-width:none;margin:0;padding:0;border:0;object-fit:fill;transform-origin:0 0;pointer-events:none;will-change:transform}\n.knobs-compare[data-renderer=\"gpu\"] .knobs-cmp-media{opacity:0}\n/* The media comes in with its first frames: a fade and a 4px blur on the default spring. */\n.knobs-cmp-canvas,.knobs-compare[data-renderer=\"dom\"] .knobs-cmp-media{transition:opacity calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default),filter calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default)}\n.knobs-compare:not([data-ready]) :is(.knobs-cmp-canvas,.knobs-cmp-media){opacity:0;filter:blur(4px)}\n/* Glass: what's behind shows through, blurred, on the knobs tokens. */\n.knobs-cmp-label,.knobs-cmp-zoom{background:color-mix(in srgb,var(--_k-bg) 52%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.6);backdrop-filter:blur(14px) saturate(1.6);\n box-shadow:inset 0 0 0 .5px var(--_k-border),inset 0 1px 0 var(--_k-rim),0 2px 10px rgba(0,0,0,calc(.18 * var(--_k-shadow-k,1)))}\n/* \u2717 Before \u00B7 \u2713 After: Before quieter (fg-3), After in full text. Neutral: no colour of its own. */\n.knobs-cmp-label{position:absolute;left:0;top:0;display:flex;align-items:center;gap:4px;padding:1px 7px 1px 5px;border-radius:999px;font-size:var(--_k-text-meta);line-height:16px;font-weight:var(--_k-weight-label);\n white-space:nowrap;pointer-events:none;will-change:transform}\n.knobs-cmp-label[data-side=\"before\"]{color:var(--_k-fg-3)}\n.knobs-cmp-label[data-side=\"after\"]{color:var(--_k-fg)}\n/* Fusing, the mark folds away and the label is its name. */\n.knobs-cmp-mark{flex:none;display:flex;justify-content:flex-end;overflow:hidden}\n.knobs-cmp-mark svg{display:block;flex:none;width:12px;height:12px}\n/* The fuse's seam: a blurred strip over where the sides meet, soft at both sides. */\n.knobs-cmp-seam{position:absolute;left:0;top:0;width:8px;height:0;opacity:0;pointer-events:none;will-change:transform,opacity;\n -webkit-mask-image:linear-gradient(to right,transparent,#000 35%,#000 65%,transparent);mask-image:linear-gradient(to right,transparent,#000 35%,#000 65%,transparent)}\n/* The wipe: a hairline down the line with a raised grip in its middle (at the pointer's height\n while dragged); a wider strip takes the hand and the keys (a slider). It fades in with the\n fuse; wiping, line and grip brighten. */\n.knobs-cmp-handle{cursor:ew-resize;position:absolute;left:-12px;top:0;width:24px;height:0;opacity:0;pointer-events:none;outline:none;will-change:transform,opacity}\n.knobs-cmp-handle[data-on]{pointer-events:auto}\n.knobs-cmp-handle::before{content:\"\";position:absolute;top:0;bottom:0;left:11.5px;width:1px;background:color-mix(in srgb,var(--_ku-cmp-line) 72%,transparent);box-shadow:0 0 0 .5px rgba(0,0,0,.28),0 0 6px rgba(0,0,0,.25)}\n.knobs-compare[data-dragging] .knobs-cmp-handle::before{background:var(--_ku-cmp-line)}\n.knobs-cmp-grip{position:absolute;top:0;left:4px;width:16px;height:28px;border-radius:min(8px,calc(var(--_k-radius) * 999));background:var(--_k-bg-overlay);\n box-shadow:var(--_k-shadow-overlay),inset 0 0 0 1px var(--_k-border),inset 0 1px 0 var(--_k-rim);will-change:transform;transition:box-shadow calc(var(--_k-hover-out) * 1ms)}\n.knobs-cmp-grip::before,.knobs-cmp-grip::after{content:\"\";position:absolute;top:10px;width:1px;height:8px;background:var(--_k-fg-3);transition:background calc(var(--_k-hover-out) * 1ms)}\n.knobs-cmp-grip::before{left:6px}\n.knobs-cmp-grip::after{left:9px}\n.knobs-compare[data-dragging] .knobs-cmp-grip{box-shadow:var(--_k-shadow-overlay),inset 0 0 0 1px var(--_k-border-strong),inset 0 1px 0 var(--_k-rim)}\n.knobs-compare[data-dragging] .knobs-cmp-grip::before,.knobs-compare[data-dragging] .knobs-cmp-grip::after{background:var(--_k-fg)}\n.knobs-cmp-handle:focus-visible .knobs-cmp-grip,.knobs-compare[data-keyboard] .knobs-cmp-handle:focus .knobs-cmp-grip{box-shadow:var(--_k-shadow-overlay),0 0 0 2px var(--_k-accent)}\n/* The split's hairline, down the middle side by side. */\n.knobs-cmp-split{position:absolute;left:0;top:0;width:1px;height:0;margin-left:-.5px;background:color-mix(in srgb,var(--_k-bg) 72%,transparent);pointer-events:none;will-change:transform,opacity}\n/* Zoomed: how far, and a way back, in the stage's corner; it fades in and out, nothing shifts. */\n.knobs-cmp-zoom{position:absolute;right:8px;bottom:8px;display:flex;align-items:center;gap:4px;height:26px;padding:0 3px 0 10px;border-radius:999px;\n color:var(--_k-fg);font-size:var(--_k-text-meta);font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";white-space:nowrap;\n opacity:0;scale:.96;pointer-events:none;transition:opacity .16s cubic-bezier(.4,0,1,1),scale .16s cubic-bezier(.4,0,1,1)}\n.knobs-cmp-zoom[data-on]{opacity:1;scale:1;pointer-events:auto;transition:opacity .2s cubic-bezier(.2,.8,.2,1),scale .2s cubic-bezier(.2,.8,.2,1)}\n:where(.knobs-ui) .knobs-cmp-zoom-reset{all:revert;box-sizing:border-box;font:inherit;letter-spacing:inherit;margin:0;border:0;outline:none;box-shadow:none;\n display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border-radius:999px;background:transparent;color:var(--_k-fg-2);cursor:pointer;transition:color .15s,background .15s}\n:where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){color:var(--_k-fg);background:color-mix(in srgb,var(--_k-fg) 12%,transparent);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--_k-fg-3);font-size:var(--_k-text-meta);pointer-events:none}\n.knobs-cmp-note:empty{display:none}\n.knobs-cmp-strip-host{flex:none;height:60px;min-height:0}\n.knobs-cmp-timeline-host{flex:none;min-height:0}\n/* The frame strip: Before over After per column, a difference bar under them, a dot where it peaks. */\n.knobs-ui.knobs-cmp-strip{--_ku-cmp-diff:var(--k-compare-diff,var(--_k-ok));position:relative;width:100%;height:100%;min-height:40px;overflow:hidden;cursor:col-resize;touch-action:none;\n font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg)}\n.knobs-cmp-strip>canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}\n@media(prefers-reduced-motion:reduce){:is(.knobs-compare,.knobs-cmp-strip) :where(*,::before,::after){transition-duration:.12s!important}}\n";
|
|
1
|
+
export declare const compareCss = "\n:where(.knobs-compare,.knobs-compare *,.knobs-cmp-strip,.knobs-cmp-strip *){box-sizing:border-box}\n.knobs-ui.knobs-compare{--_ku-cmp-diff:var(--k-compare-diff,var(--_k-ok));--_ku-cmp-line:var(--_k-compare-divider);\n --_ku-cmp-stage:var(--_k-compare-stage);\n display:flex;flex-direction:column;gap:6px;width:100%;height:100%;min-height:160px;outline:none;user-select:none;-webkit-user-select:none;\n font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}\n:where(.knobs-ui) :is(.knobs-cmp-mode,.knobs-cmp-toggle){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}\n.knobs-cmp-bar{flex:none;display:flex;align-items:center;gap:var(--_k-gap);height:var(--_k-control-h)}\n/* The modes: one fill, the selection pill on the one picked; a mode isn't brighter for being\n picked: the pill's bright copy is. */\n.knobs-cmp-modes{position:relative;display:inline-flex;height:var(--_k-control-h);border-radius:var(--_k-radius);background:var(--_k-fill)}\n.knobs-cmp-modes[hidden]{display:none}\n/* Hover is a quiet fill under the arrow cursor (no hand, no brightening), there at once. */\n.knobs-ui .knobs-cmp-mode{display:inline-flex;align-items:center;height:100%;padding:0 8px;border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:default;white-space:nowrap;\n transition:background calc(var(--_k-hover-out) * 1ms)}\n.knobs-ui .knobs-cmp-mode:not([aria-checked=\"true\"]):is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n/* Toggles: icon buttons, the accent's wash when on. */\n.knobs-ui .knobs-cmp-toggle{display:inline-flex;align-items:center;justify-content:center;width:var(--_k-control-h);height:var(--_k-control-h);border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:default;\n transition:background calc(var(--_k-hover-out) * 1ms)}\n.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-ui .knobs-cmp-toggle[aria-pressed=\"true\"]{color:var(--_k-accent-fg);background:var(--_k-accent-soft)}\n.knobs-cmp-toggle svg{display:block}\n.knobs-cmp-fill{flex:1}\n.knobs-cmp-toggle[hidden]{display:none}\n/* One surface: on a card (a walkthrough's step, a split's pane, anything .knobs-surface) or marked\n data-nested, the stage drops its fill and the sides sit on that card. */\n:where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui.knobs-compare,.knobs-ui.knobs-compare[data-nested]{--_ku-cmp-stage:var(--k-compare-stage,transparent)}\n/* In a page's flow (a container with no height), it takes the height its sides need. */\n.knobs-ui.knobs-compare[data-auto]{height:auto}\n.knobs-compare[data-auto] .knobs-cmp-stage{flex:none;min-height:0}\n.knobs-cmp-stage{position:relative;flex:1;min-height:96px;overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_ku-cmp-stage);touch-action:pan-y;outline:none}\n.knobs-compare[data-frame=\"flat\"] .knobs-cmp-stage{border-radius:0}\n.knobs-compare[data-mode=\"wipe\"] .knobs-cmp-stage{cursor:ew-resize}\n/* Unzoomed, a finger still scrolls the page up and down; zoomed, the stage takes every gesture. */\n/* Zoomed, it pans: a move cursor, never a hand. */\n.knobs-compare[data-zoomed] .knobs-cmp-stage{cursor:move;touch-action:none}\n.knobs-compare[data-panning],.knobs-compare[data-panning] *{cursor:move!important}\n/* Wiping, the grip stands in for the cursor. */\n.knobs-compare[data-dragging],.knobs-compare[data-dragging] *{cursor:none!important}\n.knobs-cmp-sizer{position:absolute;left:0;right:0;top:0;height:0;visibility:hidden;pointer-events:none}\n.knobs-cmp-canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}\n.knobs-cmp-media{position:absolute;left:0;top:0;display:block;max-width:none;margin:0;padding:0;border:0;object-fit:fill;transform-origin:0 0;pointer-events:none;will-change:transform}\n.knobs-compare[data-renderer=\"gpu\"] .knobs-cmp-media{opacity:0}\n/* The media comes in with its first frames: a fade and a 4px blur on the default spring. */\n.knobs-cmp-canvas,.knobs-compare[data-renderer=\"dom\"] .knobs-cmp-media{transition:opacity calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default),filter calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default)}\n.knobs-compare:not([data-ready]) :is(.knobs-cmp-canvas,.knobs-cmp-media){opacity:0;filter:blur(4px)}\n/* Glass: what's behind shows through, blurred, on the knobs tokens. */\n.knobs-cmp-label,.knobs-cmp-zoom{background:color-mix(in srgb,var(--_k-bg) 52%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.6);backdrop-filter:blur(14px) saturate(1.6);\n box-shadow:inset 0 0 0 .5px var(--_k-border),inset 0 1px 0 var(--_k-rim),0 2px 10px rgba(0,0,0,calc(.18 * var(--_k-shadow-k,1)))}\n/* \u2717 Before \u00B7 \u2713 After: Before quieter (fg-3), After in full text. Neutral: no colour of its own. */\n.knobs-cmp-label{position:absolute;left:0;top:0;display:flex;align-items:center;gap:4px;padding:1px 7px 1px 5px;border-radius:999px;font-size:var(--_k-text-meta);line-height:16px;font-weight:var(--_k-weight-label);\n white-space:nowrap;pointer-events:none;will-change:transform}\n.knobs-cmp-label[data-side=\"before\"]{color:var(--_k-fg-3)}\n.knobs-cmp-label[data-side=\"after\"]{color:var(--_k-fg)}\n/* Fusing, the mark folds away and the label is its name. */\n.knobs-cmp-mark{flex:none;display:flex;justify-content:flex-end;overflow:hidden}\n.knobs-cmp-mark svg{display:block;flex:none;width:12px;height:12px}\n/* The fuse's seam: a blurred strip over where the sides meet, soft at both sides. */\n.knobs-cmp-seam{position:absolute;left:0;top:0;width:8px;height:0;opacity:0;pointer-events:none;will-change:transform,opacity;\n -webkit-mask-image:linear-gradient(to right,transparent,#000 35%,#000 65%,transparent);mask-image:linear-gradient(to right,transparent,#000 35%,#000 65%,transparent)}\n/* The wipe: a hairline down the line with a raised grip in its middle (at the pointer's height\n while dragged); a wider strip takes the hand and the keys (a slider). It fades in with the\n fuse; wiping, line and grip brighten. */\n.knobs-cmp-handle{cursor:ew-resize;position:absolute;left:-12px;top:0;width:24px;height:0;opacity:0;pointer-events:none;outline:none;will-change:transform,opacity}\n.knobs-cmp-handle[data-on]{pointer-events:auto}\n.knobs-cmp-handle::before{content:\"\";position:absolute;top:0;bottom:0;left:11.5px;width:1px;background:color-mix(in srgb,var(--_ku-cmp-line) 72%,transparent);box-shadow:0 0 0 .5px rgba(0,0,0,.28),0 0 6px rgba(0,0,0,.25)}\n.knobs-compare[data-dragging] .knobs-cmp-handle::before{background:var(--_ku-cmp-line)}\n.knobs-cmp-grip{position:absolute;top:0;left:4px;width:16px;height:28px;border-radius:min(8px,calc(var(--_k-radius) * 999));background:var(--_k-bg-overlay);\n box-shadow:var(--_k-shadow-overlay),inset 0 0 0 1px var(--_k-border),inset 0 1px 0 var(--_k-rim);will-change:transform;transition:box-shadow calc(var(--_k-hover-out) * 1ms)}\n.knobs-cmp-grip::before,.knobs-cmp-grip::after{content:\"\";position:absolute;top:10px;width:1px;height:8px;background:var(--_k-fg-3);transition:background calc(var(--_k-hover-out) * 1ms)}\n.knobs-cmp-grip::before{left:6px}\n.knobs-cmp-grip::after{left:9px}\n.knobs-compare[data-dragging] .knobs-cmp-grip{box-shadow:var(--_k-shadow-overlay),inset 0 0 0 1px var(--_k-border-strong),inset 0 1px 0 var(--_k-rim)}\n.knobs-compare[data-dragging] .knobs-cmp-grip::before,.knobs-compare[data-dragging] .knobs-cmp-grip::after{background:var(--_k-fg)}\n.knobs-cmp-handle:focus-visible .knobs-cmp-grip,.knobs-compare[data-keyboard] .knobs-cmp-handle:focus .knobs-cmp-grip{box-shadow:var(--_k-shadow-overlay),0 0 0 2px var(--_k-accent)}\n/* The split's hairline, down the middle side by side. */\n.knobs-cmp-split{position:absolute;left:0;top:0;width:1px;height:0;margin-left:-.5px;background:color-mix(in srgb,var(--_k-bg) 72%,transparent);pointer-events:none;will-change:transform,opacity}\n/* Zoomed: how far, and a way back, in the stage's corner; it fades in and out, nothing shifts. */\n.knobs-cmp-zoom{position:absolute;right:8px;bottom:8px;display:flex;align-items:center;gap:4px;height:26px;padding:0 3px 0 10px;border-radius:999px;\n color:var(--_k-fg);font-size:var(--_k-text-meta);font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";white-space:nowrap;\n opacity:0;scale:.96;pointer-events:none;transition:opacity .16s cubic-bezier(.4,0,1,1),scale .16s cubic-bezier(.4,0,1,1)}\n.knobs-cmp-zoom[data-on]{opacity:1;scale:1;pointer-events:auto;transition:opacity .2s cubic-bezier(.2,.8,.2,1),scale .2s cubic-bezier(.2,.8,.2,1)}\n:where(.knobs-ui) .knobs-cmp-zoom-reset{all:revert;box-sizing:border-box;font:inherit;letter-spacing:inherit;margin:0;border:0;outline:none;box-shadow:none;\n display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border-radius:999px;background:transparent;color:var(--_k-fg-2);cursor:default;transition:background calc(var(--_k-hover-out) * 1ms)}\n:where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--_k-fg-3);font-size:var(--_k-text-meta);pointer-events:none}\n.knobs-cmp-note:empty{display:none}\n.knobs-cmp-strip-host{flex:none;height:60px;min-height:0}\n.knobs-cmp-timeline-host{flex:none;min-height:0}\n/* The frame strip: Before over After per column, a difference bar under them, a dot where it peaks. */\n.knobs-ui.knobs-cmp-strip{--_ku-cmp-diff:var(--k-compare-diff,var(--_k-ok));position:relative;width:100%;height:100%;min-height:40px;overflow:hidden;cursor:col-resize;touch-action:none;\n font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg)}\n.knobs-cmp-strip>canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}\n@media(prefers-reduced-motion:reduce){:is(.knobs-compare,.knobs-cmp-strip) :where(*,::before,::after){transition-duration:.12s!important}}\n";
|
|
@@ -48,7 +48,7 @@ export interface CompareOptions extends UiLook {
|
|
|
48
48
|
* The clock: an existing `timeline()` (its time drives both sides; while playing it follows
|
|
49
49
|
* After), or `true` for one of its own under the viewer: a player's thin progress line (the
|
|
50
50
|
* `"line"` variant, as `player()` has), its markers chapter segments. Without one, `seek`,
|
|
51
|
-
* `play` and keys still work.
|
|
51
|
+
* `play` and keys still work.
|
|
52
52
|
*/
|
|
53
53
|
readonly timeline?: Timeline | boolean;
|
|
54
54
|
/** The frame strip over the timeline (off; one timeline is made if there's none). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const playerCss = "\n:where(.knobs-player,.knobs-player *){box-sizing:border-box}\n.knobs-ui.knobs-player{--_kp-stage:var(--_k-compare-stage);display:flex;flex-direction:column;gap:6px;width:100%;outline:none;\n font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}\n:where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui.knobs-player,.knobs-ui.knobs-player[data-nested]{--_kp-stage:var(--k-compare-stage,transparent)}\n.knobs-player-frame{position:relative;width:100%;aspect-ratio:var(--kp-aspect,16/9);overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_kp-stage)
|
|
1
|
+
export declare const playerCss = "\n:where(.knobs-player,.knobs-player *){box-sizing:border-box}\n.knobs-ui.knobs-player{--_kp-stage:var(--_k-compare-stage);display:flex;flex-direction:column;gap:6px;width:100%;outline:none;\n font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}\n:where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui.knobs-player,.knobs-ui.knobs-player[data-nested]{--_kp-stage:var(--k-compare-stage,transparent)}\n.knobs-player-frame{position:relative;width:100%;aspect-ratio:var(--kp-aspect,16/9);overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_kp-stage)}\n.knobs-player[data-frame=\"flat\"] .knobs-player-frame{border-radius:0}\n.knobs-player-media{position:absolute;inset:0;display:block;width:100%;height:100%;margin:0;padding:0;border:0;object-fit:contain;\n opacity:0;filter:blur(4px);transition:opacity calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default),filter calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default)}\n.knobs-player[data-ready] .knobs-player-media{opacity:1;filter:none}\n.knobs-player-line{flex:none;min-height:0}\n/* The timeline's own stylesheet is look.ts's; what the player's row and every timeline share\n about the hand is set here, after it. No hand cursor anywhere (the arrow, or a resize where it\n resizes); hover is a quiet fill (fill-hover), in at once (hover-in, 0 ms), out easing. */\n.knobs-ui .knobs-tl-play,.knobs-ui.knobs-timeline :is(.knobs-tl-pin,.knobs-tl-rlabel),\n.knobs-ui.knobs-timeline[data-dragging] .knobs-tl-marker :is(.knobs-tl-pin,.knobs-tl-mlabel){cursor:default}\n.knobs-ui .knobs-tl-play:hover,.knobs-tl-edge:hover::after,.knobs-tl-rlabel:hover,.knobs-tl-track:hover .knobs-tl-hover,\n.knobs-timeline[data-variant=\"line\"] .knobs-tl-track:hover .knobs-tl-segs{transition-duration:calc(var(--_k-hover-in) * 1ms)}\n/* The line's row: a minimal play/pause (the filled pair, a 28px target, no fill at rest), then\n the line, centred on it. */\n.knobs-ui.knobs-timeline[data-variant=\"line\"]{gap:4px;align-items:center}\n.knobs-timeline[data-variant=\"line\"] .knobs-tl-transport{display:flex}\n.knobs-ui.knobs-timeline[data-variant=\"line\"] .knobs-tl-play{width:28px;height:28px;min-width:28px;min-height:28px;border-radius:var(--_k-radius);background:transparent;color:var(--_k-fg-2);\n transition:background calc(var(--_k-hover-out) * 1ms),transform .15s var(--_ku-ease)}\n.knobs-ui.knobs-timeline[data-variant=\"line\"][data-playing] .knobs-tl-play{background:transparent;color:var(--_k-fg-2)}\n.knobs-ui.knobs-timeline[data-variant=\"line\"] .knobs-tl-play:hover{background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-ui.knobs-timeline[data-variant=\"line\"] .knobs-tl-track{cursor:default;transition:background calc(var(--_k-hover-out) * 1ms)}\n.knobs-ui.knobs-timeline[data-variant=\"line\"] .knobs-tl-track:hover{background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n";
|
|
@@ -49,12 +49,3 @@ export interface Player {
|
|
|
49
49
|
dispose(): void;
|
|
50
50
|
}
|
|
51
51
|
export declare function player(container: HTMLElement, options: PlayerOptions): Player;
|
|
52
|
-
/**
|
|
53
|
-
* The glyph a play or a pause flashes in the middle of the media (a player's, a compare's stage):
|
|
54
|
-
* the state it went to, blurring in and out.
|
|
55
|
-
*/
|
|
56
|
-
export declare function playGlyph(doc: Document): {
|
|
57
|
-
element: HTMLSpanElement;
|
|
58
|
-
flash(playing: boolean): void;
|
|
59
|
-
dispose: () => void;
|
|
60
|
-
};
|
|
@@ -51,8 +51,8 @@ export interface TimelineOptions extends UiLook {
|
|
|
51
51
|
* and no labels, markers as faint chapter ticks (the current one in text colour) and nothing to
|
|
52
52
|
* edit. A pinch, ⌘/ctrl-wheel or = and - zoom it around the pointer, a sideways scroll pans it,
|
|
53
53
|
* both following the hand 1:1; a double-click or 0 fits it again. An up-and-down wheel is left
|
|
54
|
-
* to the page. `"line"`: a player's
|
|
55
|
-
*
|
|
54
|
+
* to the page. `"line"`: a player's row under a video or a compare: a minimal play/pause button,
|
|
55
|
+
* then a single thin progress line, one segment per chapter with a small gap between,
|
|
56
56
|
* each filling as the time passes it, thicker under the pointer; click or drag anywhere on it
|
|
57
57
|
* to seek, 1:1, and the chapter and time under the pointer show over it. Zooms as a lane does.
|
|
58
58
|
*/
|
|
@@ -122,5 +122,3 @@ export interface Timeline {
|
|
|
122
122
|
dispose(): void;
|
|
123
123
|
}
|
|
124
124
|
export declare function timeline(container: HTMLElement, options: TimelineOptions): Timeline;
|
|
125
|
-
export declare const PLAY = "<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M5 3.6v8.8c0 .5.5.8.9.5l6.6-4.4c.4-.3.4-.8 0-1L5.9 3.1c-.4-.3-.9 0-.9.5Z\" fill=\"currentColor\"/></svg>";
|
|
126
|
-
export declare const PAUSE = "<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><rect x=\"4\" y=\"3.2\" width=\"2.8\" height=\"9.6\" rx=\"1\" fill=\"currentColor\"/><rect x=\"9.2\" y=\"3.2\" width=\"2.8\" height=\"9.6\" rx=\"1\" fill=\"currentColor\"/></svg>";
|
|
@@ -32,7 +32,7 @@ export declare function mountHistory(host: HTMLElement, m: Extract<WalkMedia, {
|
|
|
32
32
|
}>, steps: StepLinks | undefined): Block;
|
|
33
33
|
export declare function mountStack(host: HTMLElement, m: Extract<WalkMedia, {
|
|
34
34
|
kind: "stack";
|
|
35
|
-
}>, steps: StepLinks | undefined): Block;
|
|
35
|
+
}>, steps: StepLinks | undefined, findPR?: (n: string) => PRInfo | null): Block;
|
|
36
36
|
export declare function mountTable(host: HTMLElement, m: Extract<WalkMedia, {
|
|
37
37
|
kind: "table";
|
|
38
38
|
}>, steps: StepLinks | undefined): Block;
|
|
@@ -67,8 +67,20 @@ declare const PR_STATE: {
|
|
|
67
67
|
readonly draft: "Draft";
|
|
68
68
|
readonly closed: "Closed";
|
|
69
69
|
};
|
|
70
|
+
export type PRState = keyof typeof PR_STATE;
|
|
71
|
+
/**
|
|
72
|
+
* A stack row's pull-request state from its `status` words: the first word when it's merged,
|
|
73
|
+
* draft, open or closed (any case), and whether they say its checks pass ("green", "passing",
|
|
74
|
+
* "CI"). The state comes from the words, never the tone.
|
|
75
|
+
*/
|
|
76
|
+
export declare function prStatus(status: string | undefined): {
|
|
77
|
+
state: PRState | null;
|
|
78
|
+
checks: boolean;
|
|
79
|
+
};
|
|
80
|
+
/** A pull request's state as GitHub shows it: its glyph and word, quietly tinted; a check after. */
|
|
81
|
+
export declare function prStateLabel(doc: Document, state: PRState, checks: boolean, title?: string): HTMLSpanElement;
|
|
70
82
|
export interface PRInfo {
|
|
71
|
-
readonly state?:
|
|
83
|
+
readonly state?: PRState;
|
|
72
84
|
readonly title?: string;
|
|
73
85
|
readonly href?: string;
|
|
74
86
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type UiLook } from "./look.js";
|
|
2
|
-
import { type StepLinks } from "./walkthrough-blocks.js";
|
|
2
|
+
import { type PRInfo, type StepLinks } from "./walkthrough-blocks.js";
|
|
3
3
|
import { type ContextEvent, type MediaContext, type WalkthroughMedia } from "./walkthrough-model.js";
|
|
4
4
|
export interface MediaSlotOptions extends UiLook {
|
|
5
5
|
readonly media: WalkthroughMedia;
|
|
@@ -9,6 +9,8 @@ export interface MediaSlotOptions extends UiLook {
|
|
|
9
9
|
readonly onEvent?: (event: Omit<ContextEvent, "at" | "step">) => void;
|
|
10
10
|
/** The page's steps, for `step` on a history event, a stack item or a table cell. */
|
|
11
11
|
readonly steps?: StepLinks;
|
|
12
|
+
/** What the page knows of a pull request by its number (a stack row's state and link). */
|
|
13
|
+
readonly findPR?: (n: string) => PRInfo | null;
|
|
12
14
|
}
|
|
13
15
|
export type { StepLinks };
|
|
14
16
|
export interface MediaSlot {
|