@kitlangton/knobs 0.4.0-next.7 → 0.4.0-next.9
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 +11 -5
- package/dist/review-react.js +18579 -0
- package/dist/review-solid.js +18481 -0
- package/dist/review.js +18487 -0
- package/dist/themes.js +121 -23
- package/dist/types/review/font.d.ts +13 -0
- package/dist/types/review/foundations.d.ts +175 -0
- package/dist/types/review/index.d.ts +13 -0
- package/dist/types/review/react.d.ts +1 -0
- package/dist/types/review/solid.d.ts +1 -0
- package/dist/types/themes/index.d.ts +7 -2
- package/dist/types/themes/review.d.ts +8 -0
- package/dist/types/ui/history-css.d.ts +1 -1
- package/dist/types/ui/index.d.ts +2 -2
- package/dist/types/ui/review-look.d.ts +6 -0
- package/dist/types/ui/review-options.d.ts +28 -0
- package/dist/types/ui/selection-pill.d.ts +3 -0
- package/dist/types/ui/walkthrough-blocks.d.ts +15 -22
- package/dist/types/ui/walkthrough-media.d.ts +24 -1
- package/dist/types/ui/walkthrough-model.d.ts +108 -4
- package/dist/types/ui/walkthrough.d.ts +2 -2
- package/dist/ui-react.js +2262 -1673
- package/dist/ui-solid.js +2262 -1673
- package/dist/ui.js +951 -500
- package/package.json +13 -1
package/dist/ui.js
CHANGED
|
@@ -4995,7 +4995,7 @@ function planPill(state, next, flags = {}) {
|
|
|
4995
4995
|
if (t && t.x === next.x && t.y === next.y && t.w === next.w && t.h === next.h)
|
|
4996
4996
|
return { kind: "stay" };
|
|
4997
4997
|
const d = Math.hypot(next.x - state.at.x, next.y - state.at.y);
|
|
4998
|
-
return { kind: "travel", box: next, spring: pillSpring(d) };
|
|
4998
|
+
return { kind: "travel", box: next, spring: pillSpring(d, flags.spring) };
|
|
4999
4999
|
}
|
|
5000
5000
|
function selectionPill(container, options) {
|
|
5001
5001
|
const doc = container.ownerDocument;
|
|
@@ -5019,7 +5019,7 @@ function selectionPill(container, options) {
|
|
|
5019
5019
|
container.prepend(pill);
|
|
5020
5020
|
if (copyOn)
|
|
5021
5021
|
container.append(copy);
|
|
5022
|
-
const { omega, zeta } = springMotion(SPRINGS.default);
|
|
5022
|
+
const { omega, zeta } = springMotion(options.spring ?? SPRINGS.default);
|
|
5023
5023
|
const springs = [0, 0, 0, 0].map(() => new Spring(0, omega, zeta, 0.01));
|
|
5024
5024
|
const [sx, sy, sw, sh] = springs;
|
|
5025
5025
|
let shown = false;
|
|
@@ -5120,7 +5120,8 @@ function selectionPill(container, options) {
|
|
|
5120
5120
|
const plan = planPill({ shown, at: shown ? at() : null, target }, next, {
|
|
5121
5121
|
first,
|
|
5122
5122
|
reduced: reducedMotion(win),
|
|
5123
|
-
...o?.snap ? { snap: true } : {}
|
|
5123
|
+
...o?.snap ? { snap: true } : {},
|
|
5124
|
+
...options.spring ? { spring: options.spring } : {}
|
|
5124
5125
|
});
|
|
5125
5126
|
first = false;
|
|
5126
5127
|
for (const n of clones.values())
|
|
@@ -8341,6 +8342,7 @@ function compare(container, options) {
|
|
|
8341
8342
|
let loupeHeld = false;
|
|
8342
8343
|
let pointer = null;
|
|
8343
8344
|
let drag = null;
|
|
8345
|
+
let tap = null;
|
|
8344
8346
|
const touches = new Map;
|
|
8345
8347
|
let pinch = null;
|
|
8346
8348
|
const zu = new Spring(0, ZOOM.omega, ZOOM.zeta, 0.00001);
|
|
@@ -9172,15 +9174,18 @@ function compare(container, options) {
|
|
|
9172
9174
|
touches.set(e.pointerId, p);
|
|
9173
9175
|
stage.setPointerCapture(e.pointerId);
|
|
9174
9176
|
if (touches.size >= 2) {
|
|
9177
|
+
tap = null;
|
|
9175
9178
|
e.preventDefault();
|
|
9176
9179
|
return startPinch();
|
|
9177
9180
|
}
|
|
9181
|
+
tap = e.target === handle ? null : { id: e.pointerId, x: p.x, y: p.y };
|
|
9178
9182
|
if (mode === "wipe") {
|
|
9179
9183
|
const wr = wipeRect(layoutNow().L.overlay);
|
|
9180
9184
|
const inside = p.x >= wr.x - SLOP && p.x <= wr.x + wr.w + SLOP && p.y >= wr.y && p.y <= wr.y + wr.h;
|
|
9181
9185
|
const grab = wipeGrab(p.x, wr, wipeLine.x, SLOP);
|
|
9182
9186
|
if (inside && (grab.onLine || !zoomed())) {
|
|
9183
9187
|
drag = { kind: "wipe", offset: grab.offset };
|
|
9188
|
+
tap = null;
|
|
9184
9189
|
root.dataset.dragging = "";
|
|
9185
9190
|
gripAt.snap(wr.h > 0 ? (p.y - wr.y) / wr.h : 0.5);
|
|
9186
9191
|
e.preventDefault();
|
|
@@ -9200,6 +9205,8 @@ function compare(container, options) {
|
|
|
9200
9205
|
const onMove = (e) => {
|
|
9201
9206
|
const p = local(e);
|
|
9202
9207
|
pointer = p;
|
|
9208
|
+
if (tap && Math.hypot(p.x - tap.x, p.y - tap.y) > TAP_SLOP)
|
|
9209
|
+
tap = null;
|
|
9203
9210
|
if (touches.has(e.pointerId))
|
|
9204
9211
|
touches.set(e.pointerId, p);
|
|
9205
9212
|
if (pinch && touches.size >= 2) {
|
|
@@ -9232,6 +9239,11 @@ function compare(container, options) {
|
|
|
9232
9239
|
touches.delete(e.pointerId);
|
|
9233
9240
|
if (touches.size < 2)
|
|
9234
9241
|
pinch = null;
|
|
9242
|
+
if (tap?.id === e.pointerId) {
|
|
9243
|
+
tap = null;
|
|
9244
|
+
if (e.type === "pointerup" && sides.some((s) => s.kind === "video"))
|
|
9245
|
+
api.toggle();
|
|
9246
|
+
}
|
|
9235
9247
|
if (!drag)
|
|
9236
9248
|
return;
|
|
9237
9249
|
if (drag.kind === "wipe") {
|
|
@@ -9633,7 +9645,7 @@ function compare(container, options) {
|
|
|
9633
9645
|
wake();
|
|
9634
9646
|
return api;
|
|
9635
9647
|
}
|
|
9636
|
-
var COMPARE_FFMPEG = "ffmpeg -i in.mov -vf fps=30 -fps_mode cfr -c:v libx264 -preset slow -crf 18 -g 15 -keyint_min 15 -pix_fmt yuv420p -movflags +faststart -an out.mp4", LAYOUT, FADE2, FADE_REDUCED, ZOOM, WIPE_CATCH, SLOP = 12, INSET = 8, GRIP, MARK, LOUPE, FAST_SEEK_FRAMES = 15, RELEASE_MS = 3000, MODE_LABEL;
|
|
9648
|
+
var COMPARE_FFMPEG = "ffmpeg -i in.mov -vf fps=30 -fps_mode cfr -c:v libx264 -preset slow -crf 18 -g 15 -keyint_min 15 -pix_fmt yuv420p -movflags +faststart -an out.mp4", LAYOUT, FADE2, FADE_REDUCED, ZOOM, WIPE_CATCH, SLOP = 12, TAP_SLOP = 4, INSET = 8, GRIP, MARK, LOUPE, FAST_SEEK_FRAMES = 15, RELEASE_MS = 3000, MODE_LABEL;
|
|
9637
9649
|
var init_compare = __esm(() => {
|
|
9638
9650
|
init_motion();
|
|
9639
9651
|
init_page_hints();
|
|
@@ -9662,6 +9674,174 @@ var init_compare = __esm(() => {
|
|
|
9662
9674
|
};
|
|
9663
9675
|
});
|
|
9664
9676
|
|
|
9677
|
+
// src/ui/player.ts
|
|
9678
|
+
function player(container, options) {
|
|
9679
|
+
const doc = container.ownerDocument;
|
|
9680
|
+
const el = (tag, cls) => {
|
|
9681
|
+
const n = doc.createElement(tag);
|
|
9682
|
+
n.className = cls;
|
|
9683
|
+
return n;
|
|
9684
|
+
};
|
|
9685
|
+
const look = {
|
|
9686
|
+
...options.preset ? { preset: options.preset } : {},
|
|
9687
|
+
...options.theme ? { theme: options.theme } : {},
|
|
9688
|
+
...options.appearance ? { appearance: options.appearance } : {}
|
|
9689
|
+
};
|
|
9690
|
+
const root = el("div", "knobs-player");
|
|
9691
|
+
root.setAttribute("role", "group");
|
|
9692
|
+
root.setAttribute("aria-label", options.label ?? "Video");
|
|
9693
|
+
applyLook2(root, options);
|
|
9694
|
+
const frame = el("div", "knobs-player-frame");
|
|
9695
|
+
frame.style.setProperty("--kp-aspect", String(options.aspect ?? 16 / 9));
|
|
9696
|
+
const v = el("video", "knobs-player-media");
|
|
9697
|
+
v.muted = options.muted ?? true;
|
|
9698
|
+
v.defaultMuted = v.muted;
|
|
9699
|
+
v.playsInline = true;
|
|
9700
|
+
v.preload = "metadata";
|
|
9701
|
+
v.setAttribute("playsinline", "");
|
|
9702
|
+
if (options.poster)
|
|
9703
|
+
v.poster = options.poster;
|
|
9704
|
+
if (options.captions) {
|
|
9705
|
+
const track = doc.createElement("track");
|
|
9706
|
+
track.kind = "captions";
|
|
9707
|
+
track.label = "Captions";
|
|
9708
|
+
track.srclang = doc.documentElement.lang || "en";
|
|
9709
|
+
track.default = true;
|
|
9710
|
+
track.src = options.captions;
|
|
9711
|
+
v.append(track);
|
|
9712
|
+
}
|
|
9713
|
+
frame.append(v);
|
|
9714
|
+
const host = el("div", "knobs-player-line");
|
|
9715
|
+
root.append(frame, host);
|
|
9716
|
+
container.append(root);
|
|
9717
|
+
const markers = (options.chapters ?? []).map((c, i) => ({
|
|
9718
|
+
id: c.id ?? `c${i}`,
|
|
9719
|
+
time: c.start,
|
|
9720
|
+
label: c.label
|
|
9721
|
+
}));
|
|
9722
|
+
const tl = timeline(host, {
|
|
9723
|
+
...look,
|
|
9724
|
+
variant: "line",
|
|
9725
|
+
duration: 1,
|
|
9726
|
+
fps: options.fps ?? 30,
|
|
9727
|
+
markers,
|
|
9728
|
+
repeat: options.loop ?? true,
|
|
9729
|
+
arrows: { step: 5, shift: 10 },
|
|
9730
|
+
label: options.label ? `${options.label} time` : "Video time",
|
|
9731
|
+
...options.hints === false ? { hints: false } : {}
|
|
9732
|
+
});
|
|
9733
|
+
const onFrame = () => root.setAttribute("data-ready", "");
|
|
9734
|
+
let pending = null;
|
|
9735
|
+
const seekVideo = (t) => {
|
|
9736
|
+
if (v.readyState < 1)
|
|
9737
|
+
return;
|
|
9738
|
+
if (v.seeking)
|
|
9739
|
+
pending = t;
|
|
9740
|
+
else
|
|
9741
|
+
v.currentTime = t;
|
|
9742
|
+
};
|
|
9743
|
+
let reported = 0;
|
|
9744
|
+
const onSeeked = () => {
|
|
9745
|
+
if (pending !== null) {
|
|
9746
|
+
const t = pending;
|
|
9747
|
+
pending = null;
|
|
9748
|
+
v.currentTime = t;
|
|
9749
|
+
return;
|
|
9750
|
+
}
|
|
9751
|
+
if (!v.paused || tl.playing || Math.abs(v.currentTime - reported) < 0.1)
|
|
9752
|
+
return;
|
|
9753
|
+
reported = v.currentTime;
|
|
9754
|
+
options.onSeek?.(reported);
|
|
9755
|
+
};
|
|
9756
|
+
const onMeta = () => {
|
|
9757
|
+
onFrame();
|
|
9758
|
+
if (v.videoWidth)
|
|
9759
|
+
frame.style.setProperty("--kp-aspect", String(v.videoWidth / v.videoHeight));
|
|
9760
|
+
if (Number.isFinite(v.duration))
|
|
9761
|
+
tl.update({ duration: v.duration });
|
|
9762
|
+
};
|
|
9763
|
+
v.addEventListener("loadedmetadata", onMeta);
|
|
9764
|
+
v.addEventListener("loadeddata", onFrame);
|
|
9765
|
+
v.addEventListener("seeked", onSeeked);
|
|
9766
|
+
const unlisten = tl.listen({
|
|
9767
|
+
onSeek(t, source) {
|
|
9768
|
+
if (source === "play") {
|
|
9769
|
+
if (Math.abs(v.currentTime - t) > 0.25)
|
|
9770
|
+
v.currentTime = t;
|
|
9771
|
+
return;
|
|
9772
|
+
}
|
|
9773
|
+
if (Math.abs(v.currentTime - t) < 1 / (options.fps ?? 30))
|
|
9774
|
+
return;
|
|
9775
|
+
seekVideo(t);
|
|
9776
|
+
},
|
|
9777
|
+
onPlay(on) {
|
|
9778
|
+
if (on)
|
|
9779
|
+
v.play().catch(() => tl.pause());
|
|
9780
|
+
else {
|
|
9781
|
+
v.pause();
|
|
9782
|
+
reported = tl.time;
|
|
9783
|
+
}
|
|
9784
|
+
root.toggleAttribute("data-playing", on);
|
|
9785
|
+
options.onPlay?.(on, tl.time);
|
|
9786
|
+
},
|
|
9787
|
+
onScrub(on) {
|
|
9788
|
+
if (on)
|
|
9789
|
+
v.pause();
|
|
9790
|
+
}
|
|
9791
|
+
});
|
|
9792
|
+
tl.drive(() => {
|
|
9793
|
+
if (v.readyState < 1)
|
|
9794
|
+
return Number.NaN;
|
|
9795
|
+
if (v.seeking)
|
|
9796
|
+
return tl.time;
|
|
9797
|
+
return v.ended ? Number.POSITIVE_INFINITY : v.currentTime;
|
|
9798
|
+
});
|
|
9799
|
+
const onClick = () => {
|
|
9800
|
+
tl.focus();
|
|
9801
|
+
tl.toggle();
|
|
9802
|
+
};
|
|
9803
|
+
frame.addEventListener("click", onClick);
|
|
9804
|
+
v.src = options.src;
|
|
9805
|
+
const api = {
|
|
9806
|
+
element: root,
|
|
9807
|
+
video: v,
|
|
9808
|
+
timeline: tl,
|
|
9809
|
+
get time() {
|
|
9810
|
+
return tl.time;
|
|
9811
|
+
},
|
|
9812
|
+
get playing() {
|
|
9813
|
+
return tl.playing;
|
|
9814
|
+
},
|
|
9815
|
+
get duration() {
|
|
9816
|
+
return Number.isFinite(v.duration) ? v.duration : 0;
|
|
9817
|
+
},
|
|
9818
|
+
play: () => tl.play(),
|
|
9819
|
+
pause: () => tl.pause(),
|
|
9820
|
+
toggle: () => tl.toggle(),
|
|
9821
|
+
seek: (t, o) => tl.seek(t, o?.glide ? { glide: true } : undefined),
|
|
9822
|
+
seekBy: (d) => tl.seek(Math.min(tl.duration, Math.max(0, tl.time + d)), { glide: true }),
|
|
9823
|
+
focus: () => tl.focus(),
|
|
9824
|
+
dispose() {
|
|
9825
|
+
unlisten();
|
|
9826
|
+
tl.drive(null);
|
|
9827
|
+
tl.dispose();
|
|
9828
|
+
v.pause();
|
|
9829
|
+
frame.removeEventListener("click", onClick);
|
|
9830
|
+
v.removeEventListener("loadedmetadata", onMeta);
|
|
9831
|
+
v.removeEventListener("loadeddata", onFrame);
|
|
9832
|
+
v.removeEventListener("seeked", onSeeked);
|
|
9833
|
+
v.removeAttribute("src");
|
|
9834
|
+
v.load();
|
|
9835
|
+
root.remove();
|
|
9836
|
+
}
|
|
9837
|
+
};
|
|
9838
|
+
return api;
|
|
9839
|
+
}
|
|
9840
|
+
var init_player = __esm(() => {
|
|
9841
|
+
init_look();
|
|
9842
|
+
init_timeline();
|
|
9843
|
+
});
|
|
9844
|
+
|
|
9665
9845
|
// src/ui/scrollbar.ts
|
|
9666
9846
|
function overlayScrollbar(scroller, content) {
|
|
9667
9847
|
const doc = scroller.ownerDocument;
|
|
@@ -16379,169 +16559,8 @@ init_timeline();
|
|
|
16379
16559
|
init_timeline_model();
|
|
16380
16560
|
init_compare();
|
|
16381
16561
|
init_compare_strip();
|
|
16562
|
+
init_player();
|
|
16382
16563
|
|
|
16383
|
-
// src/ui/player.ts
|
|
16384
|
-
init_look();
|
|
16385
|
-
init_timeline();
|
|
16386
|
-
function player(container, options) {
|
|
16387
|
-
const doc = container.ownerDocument;
|
|
16388
|
-
const el = (tag, cls) => {
|
|
16389
|
-
const n = doc.createElement(tag);
|
|
16390
|
-
n.className = cls;
|
|
16391
|
-
return n;
|
|
16392
|
-
};
|
|
16393
|
-
const look = {
|
|
16394
|
-
...options.preset ? { preset: options.preset } : {},
|
|
16395
|
-
...options.theme ? { theme: options.theme } : {},
|
|
16396
|
-
...options.appearance ? { appearance: options.appearance } : {}
|
|
16397
|
-
};
|
|
16398
|
-
const root = el("div", "knobs-player");
|
|
16399
|
-
root.setAttribute("role", "group");
|
|
16400
|
-
root.setAttribute("aria-label", options.label ?? "Video");
|
|
16401
|
-
applyLook2(root, options);
|
|
16402
|
-
const frame = el("div", "knobs-player-frame");
|
|
16403
|
-
frame.style.setProperty("--kp-aspect", String(options.aspect ?? 16 / 9));
|
|
16404
|
-
const v = el("video", "knobs-player-media");
|
|
16405
|
-
v.muted = options.muted ?? true;
|
|
16406
|
-
v.defaultMuted = v.muted;
|
|
16407
|
-
v.playsInline = true;
|
|
16408
|
-
v.preload = "metadata";
|
|
16409
|
-
v.setAttribute("playsinline", "");
|
|
16410
|
-
if (options.poster)
|
|
16411
|
-
v.poster = options.poster;
|
|
16412
|
-
if (options.captions) {
|
|
16413
|
-
const track = doc.createElement("track");
|
|
16414
|
-
track.kind = "captions";
|
|
16415
|
-
track.label = "Captions";
|
|
16416
|
-
track.srclang = doc.documentElement.lang || "en";
|
|
16417
|
-
track.default = true;
|
|
16418
|
-
track.src = options.captions;
|
|
16419
|
-
v.append(track);
|
|
16420
|
-
}
|
|
16421
|
-
frame.append(v);
|
|
16422
|
-
const host = el("div", "knobs-player-line");
|
|
16423
|
-
root.append(frame, host);
|
|
16424
|
-
container.append(root);
|
|
16425
|
-
const markers = (options.chapters ?? []).map((c, i) => ({
|
|
16426
|
-
id: c.id ?? `c${i}`,
|
|
16427
|
-
time: c.start,
|
|
16428
|
-
label: c.label
|
|
16429
|
-
}));
|
|
16430
|
-
const tl = timeline(host, {
|
|
16431
|
-
...look,
|
|
16432
|
-
variant: "line",
|
|
16433
|
-
duration: 1,
|
|
16434
|
-
fps: options.fps ?? 30,
|
|
16435
|
-
markers,
|
|
16436
|
-
repeat: options.loop ?? true,
|
|
16437
|
-
arrows: { step: 5, shift: 10 },
|
|
16438
|
-
label: options.label ? `${options.label} time` : "Video time",
|
|
16439
|
-
...options.hints === false ? { hints: false } : {}
|
|
16440
|
-
});
|
|
16441
|
-
const onFrame = () => root.setAttribute("data-ready", "");
|
|
16442
|
-
let pending = null;
|
|
16443
|
-
const seekVideo = (t) => {
|
|
16444
|
-
if (v.readyState < 1)
|
|
16445
|
-
return;
|
|
16446
|
-
if (v.seeking)
|
|
16447
|
-
pending = t;
|
|
16448
|
-
else
|
|
16449
|
-
v.currentTime = t;
|
|
16450
|
-
};
|
|
16451
|
-
let reported = 0;
|
|
16452
|
-
const onSeeked = () => {
|
|
16453
|
-
if (pending !== null) {
|
|
16454
|
-
const t = pending;
|
|
16455
|
-
pending = null;
|
|
16456
|
-
v.currentTime = t;
|
|
16457
|
-
return;
|
|
16458
|
-
}
|
|
16459
|
-
if (!v.paused || tl.playing || Math.abs(v.currentTime - reported) < 0.1)
|
|
16460
|
-
return;
|
|
16461
|
-
reported = v.currentTime;
|
|
16462
|
-
options.onSeek?.(reported);
|
|
16463
|
-
};
|
|
16464
|
-
const onMeta = () => {
|
|
16465
|
-
onFrame();
|
|
16466
|
-
if (v.videoWidth)
|
|
16467
|
-
frame.style.setProperty("--kp-aspect", String(v.videoWidth / v.videoHeight));
|
|
16468
|
-
if (Number.isFinite(v.duration))
|
|
16469
|
-
tl.update({ duration: v.duration });
|
|
16470
|
-
};
|
|
16471
|
-
v.addEventListener("loadedmetadata", onMeta);
|
|
16472
|
-
v.addEventListener("loadeddata", onFrame);
|
|
16473
|
-
v.addEventListener("seeked", onSeeked);
|
|
16474
|
-
const unlisten = tl.listen({
|
|
16475
|
-
onSeek(t, source) {
|
|
16476
|
-
if (source === "play") {
|
|
16477
|
-
if (Math.abs(v.currentTime - t) > 0.25)
|
|
16478
|
-
v.currentTime = t;
|
|
16479
|
-
return;
|
|
16480
|
-
}
|
|
16481
|
-
if (Math.abs(v.currentTime - t) < 1 / (options.fps ?? 30))
|
|
16482
|
-
return;
|
|
16483
|
-
seekVideo(t);
|
|
16484
|
-
},
|
|
16485
|
-
onPlay(on) {
|
|
16486
|
-
if (on)
|
|
16487
|
-
v.play().catch(() => tl.pause());
|
|
16488
|
-
else {
|
|
16489
|
-
v.pause();
|
|
16490
|
-
reported = tl.time;
|
|
16491
|
-
}
|
|
16492
|
-
root.toggleAttribute("data-playing", on);
|
|
16493
|
-
options.onPlay?.(on, tl.time);
|
|
16494
|
-
},
|
|
16495
|
-
onScrub(on) {
|
|
16496
|
-
if (on)
|
|
16497
|
-
v.pause();
|
|
16498
|
-
}
|
|
16499
|
-
});
|
|
16500
|
-
tl.drive(() => {
|
|
16501
|
-
if (v.readyState < 1)
|
|
16502
|
-
return Number.NaN;
|
|
16503
|
-
if (v.seeking)
|
|
16504
|
-
return tl.time;
|
|
16505
|
-
return v.ended ? Number.POSITIVE_INFINITY : v.currentTime;
|
|
16506
|
-
});
|
|
16507
|
-
const onClick = () => tl.focus();
|
|
16508
|
-
frame.addEventListener("click", onClick);
|
|
16509
|
-
v.src = options.src;
|
|
16510
|
-
const api = {
|
|
16511
|
-
element: root,
|
|
16512
|
-
video: v,
|
|
16513
|
-
timeline: tl,
|
|
16514
|
-
get time() {
|
|
16515
|
-
return tl.time;
|
|
16516
|
-
},
|
|
16517
|
-
get playing() {
|
|
16518
|
-
return tl.playing;
|
|
16519
|
-
},
|
|
16520
|
-
get duration() {
|
|
16521
|
-
return Number.isFinite(v.duration) ? v.duration : 0;
|
|
16522
|
-
},
|
|
16523
|
-
play: () => tl.play(),
|
|
16524
|
-
pause: () => tl.pause(),
|
|
16525
|
-
toggle: () => tl.toggle(),
|
|
16526
|
-
seek: (t, o) => tl.seek(t, o?.glide ? { glide: true } : undefined),
|
|
16527
|
-
seekBy: (d) => tl.seek(Math.min(tl.duration, Math.max(0, tl.time + d)), { glide: true }),
|
|
16528
|
-
focus: () => tl.focus(),
|
|
16529
|
-
dispose() {
|
|
16530
|
-
unlisten();
|
|
16531
|
-
tl.drive(null);
|
|
16532
|
-
tl.dispose();
|
|
16533
|
-
v.pause();
|
|
16534
|
-
frame.removeEventListener("click", onClick);
|
|
16535
|
-
v.removeEventListener("loadedmetadata", onMeta);
|
|
16536
|
-
v.removeEventListener("loadeddata", onFrame);
|
|
16537
|
-
v.removeEventListener("seeked", onSeeked);
|
|
16538
|
-
v.removeAttribute("src");
|
|
16539
|
-
v.load();
|
|
16540
|
-
root.remove();
|
|
16541
|
-
}
|
|
16542
|
-
};
|
|
16543
|
-
return api;
|
|
16544
|
-
}
|
|
16545
16564
|
// src/ui/history.ts
|
|
16546
16565
|
init_motion();
|
|
16547
16566
|
init_glide();
|
|
@@ -16580,7 +16599,7 @@ var historyCss = `
|
|
|
16580
16599
|
.knobs-hy-layer{position:absolute;inset:0;grid-column:2;grid-row:1/-1;pointer-events:none}
|
|
16581
16600
|
|
|
16582
16601
|
/* Bands and month lines behind the lanes; today, the selection and the pointer's line over them. */
|
|
16583
|
-
.knobs-hy-band{position:absolute;top:0;bottom:0;background:
|
|
16602
|
+
.knobs-hy-band{position:absolute;top:0;bottom:0;background:var(--_k-fill);box-shadow:inset 1px 0 0 var(--_k-border-subtle)}
|
|
16584
16603
|
:is(.knobs-hy-grid,.knobs-hy-today,.knobs-hy-hover,.knobs-hy-sel){position:absolute;left:0;top:calc(var(--hy-bandrow) + var(--hy-axis));bottom:0;width:1px;margin-left:-.5px}
|
|
16585
16604
|
.knobs-hy-grid{background:var(--_k-border-subtle)}
|
|
16586
16605
|
.knobs-hy-today{top:calc(var(--hy-bandrow) + var(--hy-axis) - 4px);background:var(--_k-accent)}
|
|
@@ -17133,10 +17152,59 @@ function fillMedia(m, base) {
|
|
|
17133
17152
|
};
|
|
17134
17153
|
case "table":
|
|
17135
17154
|
return fillTable(m);
|
|
17155
|
+
case "facts":
|
|
17156
|
+
return {
|
|
17157
|
+
kind: "facts",
|
|
17158
|
+
...m.title ? { title: m.title } : {},
|
|
17159
|
+
groups: [
|
|
17160
|
+
...m.facts ? [{ facts: fillFacts(m.facts) }] : [],
|
|
17161
|
+
...(m.groups ?? []).map((g) => ({
|
|
17162
|
+
...g.title ? { title: g.title } : {},
|
|
17163
|
+
facts: fillFacts(g.facts)
|
|
17164
|
+
}))
|
|
17165
|
+
]
|
|
17166
|
+
};
|
|
17167
|
+
case "decision":
|
|
17168
|
+
return { kind: "decision", options: fillDecision(m.options, m.noun, base) };
|
|
17136
17169
|
default:
|
|
17137
17170
|
return m;
|
|
17138
17171
|
}
|
|
17139
17172
|
}
|
|
17173
|
+
function fillFacts(facts) {
|
|
17174
|
+
const list = Array.isArray(facts) ? facts : Object.entries(facts).map(([term, value]) => ({ term, value }));
|
|
17175
|
+
return list.map((f) => {
|
|
17176
|
+
const code = f.code === true;
|
|
17177
|
+
const raw = typeof f.value === "string" ? [f.value] : [...f.value];
|
|
17178
|
+
const value = (code ? raw.flatMap((v) => v.split(/\s*,\s*/)) : raw).map((v) => v.trim()).filter(Boolean);
|
|
17179
|
+
return { term: f.term, value, code };
|
|
17180
|
+
});
|
|
17181
|
+
}
|
|
17182
|
+
function optionColumns(count, width, min = 280, gap = 48) {
|
|
17183
|
+
for (let c = Math.min(count, 4);c > 1; c--)
|
|
17184
|
+
if (count % c === 0 && (width - gap * (c - 1)) / c >= min)
|
|
17185
|
+
return c;
|
|
17186
|
+
return 1;
|
|
17187
|
+
}
|
|
17188
|
+
function fillDecision(options, noun = "Option", base) {
|
|
17189
|
+
const unique = uniqueIds();
|
|
17190
|
+
return options.map((o, i) => {
|
|
17191
|
+
if ("number" in o)
|
|
17192
|
+
return o;
|
|
17193
|
+
const extra = [
|
|
17194
|
+
...o.pros?.length ? [{ term: "For", value: o.pros }] : [],
|
|
17195
|
+
...o.cons?.length ? [{ term: "Against", value: o.cons }] : []
|
|
17196
|
+
];
|
|
17197
|
+
return {
|
|
17198
|
+
id: unique(o.id ?? slug(o.title)),
|
|
17199
|
+
number: `${noun} ${i + 1}`,
|
|
17200
|
+
title: o.title,
|
|
17201
|
+
...o.summary ? { summary: o.summary } : {},
|
|
17202
|
+
...o.media !== undefined ? { media: fillMedia(o.media, base) } : {},
|
|
17203
|
+
facts: [...o.facts ? fillFacts(o.facts) : [], ...fillFacts(extra)],
|
|
17204
|
+
recommended: o.recommended === true
|
|
17205
|
+
};
|
|
17206
|
+
});
|
|
17207
|
+
}
|
|
17140
17208
|
function historyData(m) {
|
|
17141
17209
|
const events = m.events ?? [];
|
|
17142
17210
|
if (m.lanes || m.bands || m.states || m.axis)
|
|
@@ -17341,7 +17409,8 @@ function normalizeWalkthrough(doc) {
|
|
|
17341
17409
|
letter: String.fromCharCode(65 + oi % 26),
|
|
17342
17410
|
...o.caption ? { caption: o.caption } : {},
|
|
17343
17411
|
...o.media !== undefined ? { media: fillMedia(o.media, doc.base) } : {},
|
|
17344
|
-
|
|
17412
|
+
...o.facts ? { facts: fillFacts(o.facts) } : {},
|
|
17413
|
+
suggested: o.suggested === true || o.recommended === true
|
|
17345
17414
|
}));
|
|
17346
17415
|
const list = step.media === undefined ? [] : Array.isArray(step.media) ? step.media : [step.media];
|
|
17347
17416
|
const asked = step.ask === "verdict" ? "note" : step.ask;
|
|
@@ -17414,25 +17483,63 @@ function normalizeWalkthrough(doc) {
|
|
|
17414
17483
|
})),
|
|
17415
17484
|
sections: withKickers(sections, doc.sections, doc.kickers),
|
|
17416
17485
|
steps,
|
|
17417
|
-
prs: knownPRs(doc, sections),
|
|
17486
|
+
prs: knownPRs(doc, sections, steps),
|
|
17418
17487
|
...repoOf(doc) ? { repo: repoOf(doc) } : {}
|
|
17419
17488
|
};
|
|
17420
17489
|
}
|
|
17421
17490
|
var prNumber = (href) => /\/(?:pull|merge_requests)\/(\d+)(?:[/?#]|$)/.exec(href)?.[1] ?? null;
|
|
17422
17491
|
var repoOf = (doc) => doc.repo?.trim().replace(/^https?:\/\/github\.com\//, "").replace(/\/+$/, "") || undefined;
|
|
17423
|
-
|
|
17492
|
+
var PR_STATES = ["merged", "open", "draft", "closed"];
|
|
17493
|
+
function prStatus(status) {
|
|
17494
|
+
const words = (status ?? "").trim().toLowerCase();
|
|
17495
|
+
const first = /^[a-z]+/.exec(words)?.[0] ?? "";
|
|
17496
|
+
const state = PR_STATES.includes(first) ? first : first === "shipped" || first === "done" ? "merged" : null;
|
|
17497
|
+
return { state, checks: /\b(green|passing|passed|ci|checks? pass)/.test(words) };
|
|
17498
|
+
}
|
|
17499
|
+
function knownPRs(doc, sections, steps = []) {
|
|
17424
17500
|
const out = {};
|
|
17425
17501
|
const repo = repoOf(doc);
|
|
17426
|
-
|
|
17427
|
-
const
|
|
17428
|
-
|
|
17429
|
-
|
|
17430
|
-
|
|
17502
|
+
const add = (n, pr) => {
|
|
17503
|
+
const known = out[n] ?? {};
|
|
17504
|
+
const next = { ...known };
|
|
17505
|
+
for (const [k, v] of Object.entries(pr))
|
|
17506
|
+
if (v !== undefined && next[k] === undefined)
|
|
17507
|
+
next[k] = v;
|
|
17508
|
+
out[n] = next;
|
|
17509
|
+
};
|
|
17431
17510
|
for (const [k, pr] of Object.entries(doc.prs ?? {})) {
|
|
17432
17511
|
const n = k.replace(/^#/, "");
|
|
17433
17512
|
if (!/^\d+$/.test(n))
|
|
17434
17513
|
continue;
|
|
17435
|
-
|
|
17514
|
+
add(n, pr);
|
|
17515
|
+
}
|
|
17516
|
+
for (const step of steps)
|
|
17517
|
+
for (const m of step.media) {
|
|
17518
|
+
if (m.kind !== "stack")
|
|
17519
|
+
continue;
|
|
17520
|
+
for (const it of m.items) {
|
|
17521
|
+
const n = it.pr.replace(/^#/, "");
|
|
17522
|
+
if (!/^\d+$/.test(n))
|
|
17523
|
+
continue;
|
|
17524
|
+
const said = prStatus(it.status);
|
|
17525
|
+
add(n, {
|
|
17526
|
+
...said.state ? { state: said.state } : {},
|
|
17527
|
+
...said.state && said.checks ? { checks: true } : {},
|
|
17528
|
+
...it.title ? { title: plainMarkdown(it.title) } : {},
|
|
17529
|
+
...it.href ? { href: it.href } : {}
|
|
17530
|
+
});
|
|
17531
|
+
}
|
|
17532
|
+
}
|
|
17533
|
+
for (const s of sections) {
|
|
17534
|
+
const n = s.link && prNumber(s.link.href);
|
|
17535
|
+
if (!n)
|
|
17536
|
+
continue;
|
|
17537
|
+
const said = prStatus(s.status);
|
|
17538
|
+
add(n, {
|
|
17539
|
+
href: s.link.href.replace(/(\/pull\/\d+).*$/, "$1"),
|
|
17540
|
+
...said.state ? { state: said.state } : {},
|
|
17541
|
+
title: plainMarkdown(s.title)
|
|
17542
|
+
});
|
|
17436
17543
|
}
|
|
17437
17544
|
if (repo) {
|
|
17438
17545
|
for (const n of Object.keys(out))
|
|
@@ -17441,13 +17548,17 @@ function knownPRs(doc, sections) {
|
|
|
17441
17548
|
}
|
|
17442
17549
|
return out;
|
|
17443
17550
|
}
|
|
17444
|
-
function findPR(prs, n, repo) {
|
|
17445
|
-
const
|
|
17446
|
-
const
|
|
17551
|
+
function findPR(prs, n, repo, kind = "pr") {
|
|
17552
|
+
const entry = prs[n];
|
|
17553
|
+
const known = entry && (entry.kind ?? "pr") === kind ? entry : undefined;
|
|
17554
|
+
const path = kind === "issue" ? "issues" : "pull";
|
|
17555
|
+
const href = repo ? `https://github.com/${repo}/${path}/${n}` : undefined;
|
|
17556
|
+
const base = kind === "issue" ? { kind } : {};
|
|
17447
17557
|
if (known)
|
|
17448
|
-
return known.href || !href ? known : { ...known, href };
|
|
17449
|
-
return href ? { href } : null;
|
|
17558
|
+
return known.href || !href ? { ...base, ...known } : { ...base, ...known, href };
|
|
17559
|
+
return href ? { ...base, href } : kind === "issue" ? { kind } : null;
|
|
17450
17560
|
}
|
|
17561
|
+
var issueNumber = (href) => /^https?:\/\/[^/]+\/.+\/issues\/(\d+)\/?(?:[?#].*)?$/.exec(href)?.[1] ?? null;
|
|
17451
17562
|
var isPullRequest = (href) => /\/(?:pull|merge_requests)\/\d+(?:[/?#]|$)/.test(href);
|
|
17452
17563
|
function withKickers(sections, source, kickers = "pr") {
|
|
17453
17564
|
if (kickers === false)
|
|
@@ -21758,6 +21869,230 @@ init_motion();
|
|
|
21758
21869
|
init_page_hints();
|
|
21759
21870
|
init_icons();
|
|
21760
21871
|
init_look();
|
|
21872
|
+
|
|
21873
|
+
// src/review/foundations.ts
|
|
21874
|
+
init_motion();
|
|
21875
|
+
var TRACKING = 0.03;
|
|
21876
|
+
var MEASURE = "66ch";
|
|
21877
|
+
var FONT = {
|
|
21878
|
+
sans: 'system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI Variable Text","Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif',
|
|
21879
|
+
mono: 'ui-monospace,"SF Mono",SFMono-Regular,"Cascadia Mono","JetBrains Mono",Menlo,Consolas,monospace'
|
|
21880
|
+
};
|
|
21881
|
+
var FEATURES = {
|
|
21882
|
+
figures: "tabular-nums",
|
|
21883
|
+
data: '"tnum" 1,"ss01" 1',
|
|
21884
|
+
code: "none"
|
|
21885
|
+
};
|
|
21886
|
+
var MOTION2 = [
|
|
21887
|
+
{
|
|
21888
|
+
name: "hover",
|
|
21889
|
+
spring: null,
|
|
21890
|
+
ms: "0 in, 120 out",
|
|
21891
|
+
use: "A hover's fill: on at once, off softly"
|
|
21892
|
+
},
|
|
21893
|
+
{
|
|
21894
|
+
name: "quick",
|
|
21895
|
+
spring: FADE,
|
|
21896
|
+
use: "Replacing a whole thing in place: fade, scale .98, blur 3 px"
|
|
21897
|
+
},
|
|
21898
|
+
{ name: "close", spring: CLOSE, use: "A popover closing" },
|
|
21899
|
+
{ name: "snappy", spring: SPRINGS.snappy, use: "Controls: a toggle, a pick, a chapter row" },
|
|
21900
|
+
{ name: "state", spring: SPRINGS.default, use: "The selection pill, a disclosure opening" },
|
|
21901
|
+
{
|
|
21902
|
+
name: "calm",
|
|
21903
|
+
spring: SPRINGS.calm,
|
|
21904
|
+
use: "Layout: a compare's height, the page scrolling to a step"
|
|
21905
|
+
},
|
|
21906
|
+
{ name: "smooth", spring: SPRINGS.smooth, use: "A step opening to the full window" }
|
|
21907
|
+
];
|
|
21908
|
+
var foundationCss = `
|
|
21909
|
+
:where(.knobs-walkthrough,.knobs-wt-slot,.knobs-review){
|
|
21910
|
+
--_kr-track:calc((var(--_k-type-body) - 1em) * ${TRACKING});
|
|
21911
|
+
--_kr-measure:var(--k-walkthrough-measure,${MEASURE});
|
|
21912
|
+
--_kr-block:calc(var(--_k-space-title) * 2);
|
|
21913
|
+
--_kr-data:${FEATURES.data};
|
|
21914
|
+
letter-spacing:var(--_kr-track);font-variant-numeric:${FEATURES.figures};font-optical-sizing:auto;font-kerning:normal}
|
|
21915
|
+
:where(.knobs-walkthrough,.knobs-wt-slot,.knobs-review) :where(*){letter-spacing:var(--_kr-track)}
|
|
21916
|
+
:where(.knobs-walkthrough,.knobs-wt-slot,.knobs-review) :where(code,pre,kbd,samp,.knobs-wt-mono){letter-spacing:0;font-variant-ligatures:${FEATURES.code}}
|
|
21917
|
+
`;
|
|
21918
|
+
|
|
21919
|
+
// src/themes/review.ts
|
|
21920
|
+
init_define();
|
|
21921
|
+
|
|
21922
|
+
// src/themes/void.ts
|
|
21923
|
+
init_define();
|
|
21924
|
+
init_knobs();
|
|
21925
|
+
var voidTheme = defineTheme({
|
|
21926
|
+
name: "void",
|
|
21927
|
+
extends: knobs,
|
|
21928
|
+
gray: { hue: 0, chroma: 0 },
|
|
21929
|
+
accent: { dark: "#ffffff", light: "#1c1c1c" },
|
|
21930
|
+
material: "flat",
|
|
21931
|
+
tokens: {
|
|
21932
|
+
dark: {
|
|
21933
|
+
"bg-page": "#000000",
|
|
21934
|
+
"bg-inset": "#0a0a0a",
|
|
21935
|
+
bg: "#000000",
|
|
21936
|
+
"bg-raised": "#1c1c1e",
|
|
21937
|
+
"bg-overlay": "#2c2c2e",
|
|
21938
|
+
fg: "#ededed",
|
|
21939
|
+
"fg-2": "#cecece",
|
|
21940
|
+
"fg-3": "#989898",
|
|
21941
|
+
"fg-4": "#7a7a7a",
|
|
21942
|
+
"compare-stage": "#000000"
|
|
21943
|
+
}
|
|
21944
|
+
}
|
|
21945
|
+
});
|
|
21946
|
+
|
|
21947
|
+
// src/themes/review.ts
|
|
21948
|
+
var reviewTheme = defineTheme({
|
|
21949
|
+
name: "review",
|
|
21950
|
+
extends: voidTheme,
|
|
21951
|
+
font: FONT,
|
|
21952
|
+
tokens: {
|
|
21953
|
+
dark: {
|
|
21954
|
+
fill: "#ededed0f",
|
|
21955
|
+
"fill-hover": "#ededed1a",
|
|
21956
|
+
"fill-selected": "#ededed24",
|
|
21957
|
+
"border-subtle": "#ededed47",
|
|
21958
|
+
border: "#ededed4f",
|
|
21959
|
+
"border-strong": "#585858"
|
|
21960
|
+
},
|
|
21961
|
+
light: {
|
|
21962
|
+
"bg-page": "#ffffff",
|
|
21963
|
+
"bg-inset": "#f7f7f7",
|
|
21964
|
+
bg: "#ffffff",
|
|
21965
|
+
"bg-raised": "#ffffff",
|
|
21966
|
+
"bg-overlay": "#ffffff",
|
|
21967
|
+
fill: "#1919190a",
|
|
21968
|
+
"fill-hover": "#19191912",
|
|
21969
|
+
"fill-selected": "#1919191c",
|
|
21970
|
+
"border-subtle": "#19191917",
|
|
21971
|
+
border: "#1919191d",
|
|
21972
|
+
"border-strong": "#dcdcdc"
|
|
21973
|
+
}
|
|
21974
|
+
}
|
|
21975
|
+
});
|
|
21976
|
+
|
|
21977
|
+
// src/ui/review-look.ts
|
|
21978
|
+
var MODES2 = { dark: "dark", light: "light", auto: "system" };
|
|
21979
|
+
var THEMED = '[data-knobs-theme]:not([data-knobs-theme="dark"],[data-knobs-theme="light"])';
|
|
21980
|
+
function reviewLook(options, container) {
|
|
21981
|
+
const t = options.theme;
|
|
21982
|
+
if (typeof t === "object")
|
|
21983
|
+
return options;
|
|
21984
|
+
if (!t && container?.closest(THEMED))
|
|
21985
|
+
return options;
|
|
21986
|
+
const appearance = options.appearance ?? (t ? MODES2[t] : undefined);
|
|
21987
|
+
return { ...options, theme: reviewTheme, ...appearance ? { appearance } : {} };
|
|
21988
|
+
}
|
|
21989
|
+
|
|
21990
|
+
// src/ui/review-options.ts
|
|
21991
|
+
var el2 = (doc, tag, cls) => {
|
|
21992
|
+
const n = doc.createElement(tag);
|
|
21993
|
+
if (cls)
|
|
21994
|
+
n.className = cls;
|
|
21995
|
+
return n;
|
|
21996
|
+
};
|
|
21997
|
+
function renderFacts(doc, groups) {
|
|
21998
|
+
const box = el2(doc, "div", "knobs-wt-facts");
|
|
21999
|
+
for (const g of groups) {
|
|
22000
|
+
if (!g.facts.length && !g.title)
|
|
22001
|
+
continue;
|
|
22002
|
+
const group = el2(doc, "section", "knobs-wt-fgroup");
|
|
22003
|
+
if (g.title) {
|
|
22004
|
+
const head = el2(doc, "h3", "knobs-wt-fhead");
|
|
22005
|
+
head.innerHTML = inlineMarkdown(g.title);
|
|
22006
|
+
group.append(head);
|
|
22007
|
+
}
|
|
22008
|
+
if (g.facts.length)
|
|
22009
|
+
group.append(factList(doc, g.facts));
|
|
22010
|
+
box.append(group);
|
|
22011
|
+
}
|
|
22012
|
+
return box;
|
|
22013
|
+
}
|
|
22014
|
+
function factList(doc, facts) {
|
|
22015
|
+
const dl = el2(doc, "dl", "knobs-wt-fterms");
|
|
22016
|
+
for (const f of facts) {
|
|
22017
|
+
const row = el2(doc, "div", "knobs-wt-fact");
|
|
22018
|
+
const dt = el2(doc, "dt");
|
|
22019
|
+
dt.innerHTML = inlineMarkdown(f.term);
|
|
22020
|
+
const dd = el2(doc, "dd");
|
|
22021
|
+
if (f.code) {
|
|
22022
|
+
dd.dataset.code = "";
|
|
22023
|
+
for (const v of f.value) {
|
|
22024
|
+
const chip = el2(doc, "code");
|
|
22025
|
+
chip.textContent = v;
|
|
22026
|
+
dd.append(chip);
|
|
22027
|
+
}
|
|
22028
|
+
} else
|
|
22029
|
+
for (const v of f.value) {
|
|
22030
|
+
const line = el2(doc, "div");
|
|
22031
|
+
line.innerHTML = inlineMarkdown(v);
|
|
22032
|
+
dd.append(line);
|
|
22033
|
+
}
|
|
22034
|
+
row.append(dt, dd);
|
|
22035
|
+
dl.append(row);
|
|
22036
|
+
}
|
|
22037
|
+
return dl;
|
|
22038
|
+
}
|
|
22039
|
+
function optionTile(doc, o, options = {}) {
|
|
22040
|
+
const tile = el2(doc, "div", "knobs-wt-option");
|
|
22041
|
+
const head = options.head ?? el2(doc, "div");
|
|
22042
|
+
head.classList.add("knobs-wt-ohead");
|
|
22043
|
+
const kicker = el2(doc, "span", "knobs-wt-okicker");
|
|
22044
|
+
const n = el2(doc, "span");
|
|
22045
|
+
n.textContent = o.number;
|
|
22046
|
+
kicker.append(n);
|
|
22047
|
+
if (o.recommended) {
|
|
22048
|
+
const rec = el2(doc, "span", "knobs-wt-orec");
|
|
22049
|
+
rec.textContent = "Recommended";
|
|
22050
|
+
kicker.append(rec);
|
|
22051
|
+
}
|
|
22052
|
+
const title = el2(doc, "span", "knobs-wt-otitle");
|
|
22053
|
+
title.innerHTML = inlineMarkdown(o.title);
|
|
22054
|
+
head.append(kicker, title);
|
|
22055
|
+
tile.append(head);
|
|
22056
|
+
if (o.summary) {
|
|
22057
|
+
const p = el2(doc, "p", "knobs-wt-osum");
|
|
22058
|
+
p.innerHTML = inlineMarkdown(o.summary);
|
|
22059
|
+
tile.append(p);
|
|
22060
|
+
}
|
|
22061
|
+
options.media?.(tile);
|
|
22062
|
+
if (o.facts?.length)
|
|
22063
|
+
tile.append(renderFacts(doc, [{ facts: o.facts }]));
|
|
22064
|
+
return { tile, head, kicker };
|
|
22065
|
+
}
|
|
22066
|
+
function layoutOptions(root, tiles) {
|
|
22067
|
+
let cols = 0;
|
|
22068
|
+
const layout = () => {
|
|
22069
|
+
const width = root.clientWidth;
|
|
22070
|
+
if (!width)
|
|
22071
|
+
return;
|
|
22072
|
+
const next = optionColumns(tiles.length, width);
|
|
22073
|
+
if (next === cols)
|
|
22074
|
+
return;
|
|
22075
|
+
cols = next;
|
|
22076
|
+
root.style.setProperty("--kw-cols", String(cols));
|
|
22077
|
+
const rows = Math.ceil(tiles.length / cols);
|
|
22078
|
+
tiles.forEach((t, i) => {
|
|
22079
|
+
const row = Math.floor(i / cols);
|
|
22080
|
+
t.dataset.col = String(i % cols);
|
|
22081
|
+
t.dataset.row = String(row);
|
|
22082
|
+
t.toggleAttribute("data-end", i % cols === cols - 1);
|
|
22083
|
+
t.toggleAttribute("data-last-row", row === rows - 1);
|
|
22084
|
+
});
|
|
22085
|
+
};
|
|
22086
|
+
layout();
|
|
22087
|
+
const win = root.ownerDocument.defaultView;
|
|
22088
|
+
if (!win || typeof win.ResizeObserver !== "function")
|
|
22089
|
+
return () => {};
|
|
22090
|
+
const ro = new win.ResizeObserver(layout);
|
|
22091
|
+
ro.observe(root);
|
|
22092
|
+
return () => ro.disconnect();
|
|
22093
|
+
}
|
|
22094
|
+
|
|
22095
|
+
// src/ui/walkthrough.ts
|
|
21761
22096
|
init_selection_pill();
|
|
21762
22097
|
|
|
21763
22098
|
// src/ui/walkthrough-annotations.ts
|
|
@@ -21878,19 +22213,19 @@ init_selection_pill();
|
|
|
21878
22213
|
var GLYPH = {
|
|
21879
22214
|
caret: icon("caretRight", { small: true })
|
|
21880
22215
|
};
|
|
21881
|
-
var
|
|
22216
|
+
var el3 = (doc, tag, cls) => {
|
|
21882
22217
|
const n = doc.createElement(tag);
|
|
21883
22218
|
if (cls)
|
|
21884
22219
|
n.className = cls;
|
|
21885
22220
|
return n;
|
|
21886
22221
|
};
|
|
21887
22222
|
var text2 = (doc, tag, cls, value) => {
|
|
21888
|
-
const n =
|
|
22223
|
+
const n = el3(doc, tag, cls);
|
|
21889
22224
|
n.textContent = value;
|
|
21890
22225
|
return n;
|
|
21891
22226
|
};
|
|
21892
22227
|
var prose = (doc, tag, cls, value) => {
|
|
21893
|
-
const n =
|
|
22228
|
+
const n = el3(doc, tag, cls);
|
|
21894
22229
|
n.innerHTML = inlineMarkdown(value);
|
|
21895
22230
|
return n;
|
|
21896
22231
|
};
|
|
@@ -21946,10 +22281,10 @@ function mountHistory(host, m, steps) {
|
|
|
21946
22281
|
function mountStack(host, m, steps, findPR) {
|
|
21947
22282
|
const doc = host.ownerDocument;
|
|
21948
22283
|
const layout = stackLayout(m);
|
|
21949
|
-
const root =
|
|
22284
|
+
const root = el3(doc, "div", "knobs-wt-stack");
|
|
21950
22285
|
root.toggleAttribute("data-flat", layout.flat);
|
|
21951
22286
|
const lane = (kind) => {
|
|
21952
|
-
const s =
|
|
22287
|
+
const s = el3(doc, "span", "knobs-wt-lane");
|
|
21953
22288
|
s.dataset.rail = kind;
|
|
21954
22289
|
return s;
|
|
21955
22290
|
};
|
|
@@ -21960,9 +22295,9 @@ function mountStack(host, m, steps, findPR) {
|
|
|
21960
22295
|
};
|
|
21961
22296
|
const from = layout.trunk ? 0 : 1;
|
|
21962
22297
|
if (layout.trunk && layout.rows.length) {
|
|
21963
|
-
const row =
|
|
22298
|
+
const row = el3(doc, "div", "knobs-wt-srow");
|
|
21964
22299
|
row.dataset.trunk = "";
|
|
21965
|
-
const lanes =
|
|
22300
|
+
const lanes = el3(doc, "span", "knobs-wt-lanes");
|
|
21966
22301
|
lanes.setAttribute("aria-hidden", "true");
|
|
21967
22302
|
lanes.append(node(true));
|
|
21968
22303
|
row.append(lanes, text2(doc, "span", "knobs-wt-trunk", layout.trunk));
|
|
@@ -21970,9 +22305,9 @@ function mountStack(host, m, steps, findPR) {
|
|
|
21970
22305
|
}
|
|
21971
22306
|
for (const r of layout.rows) {
|
|
21972
22307
|
const it = r.item;
|
|
21973
|
-
const row =
|
|
22308
|
+
const row = el3(doc, "div", "knobs-wt-srow");
|
|
21974
22309
|
if (!layout.flat) {
|
|
21975
|
-
const lanes =
|
|
22310
|
+
const lanes = el3(doc, "span", "knobs-wt-lanes");
|
|
21976
22311
|
lanes.setAttribute("aria-hidden", "true");
|
|
21977
22312
|
for (let k = from;k < r.depth; k++)
|
|
21978
22313
|
lanes.append(lane(r.rails[k] ? "pass" : "none"));
|
|
@@ -21981,8 +22316,8 @@ function mountStack(host, m, steps, findPR) {
|
|
|
21981
22316
|
lanes.append(node(r.children > 0));
|
|
21982
22317
|
row.append(lanes);
|
|
21983
22318
|
}
|
|
21984
|
-
const main =
|
|
21985
|
-
const line =
|
|
22319
|
+
const main = el3(doc, "div", "knobs-wt-smain");
|
|
22320
|
+
const line = el3(doc, "div", "knobs-wt-sline");
|
|
21986
22321
|
if (it.order)
|
|
21987
22322
|
line.append(text2(doc, "span", "knobs-wt-sord", it.order));
|
|
21988
22323
|
const known = findPR?.(it.pr.replace(/^#/, "")) ?? null;
|
|
@@ -22013,7 +22348,7 @@ function mountStack(host, m, steps, findPR) {
|
|
|
22013
22348
|
main.append(line);
|
|
22014
22349
|
if (it.summary)
|
|
22015
22350
|
main.append(prose(doc, "p", "knobs-wt-ssummary", it.summary));
|
|
22016
|
-
const meta =
|
|
22351
|
+
const meta = el3(doc, "div", "knobs-wt-smeta");
|
|
22017
22352
|
if (it.head) {
|
|
22018
22353
|
const branch = r.offBase ? `${it.head} → ${r.offBase}` : it.head;
|
|
22019
22354
|
meta.append(text2(doc, "span", "knobs-wt-sbranch", branch));
|
|
@@ -22038,7 +22373,7 @@ function mountStack(host, m, steps, findPR) {
|
|
|
22038
22373
|
return { dispose: () => root.remove(), context: () => ({ kind: "stack" }) };
|
|
22039
22374
|
}
|
|
22040
22375
|
function delta(doc, d) {
|
|
22041
|
-
const s =
|
|
22376
|
+
const s = el3(doc, "span", "knobs-wt-delta");
|
|
22042
22377
|
if (typeof d === "string") {
|
|
22043
22378
|
s.textContent = d;
|
|
22044
22379
|
return s;
|
|
@@ -22078,13 +22413,13 @@ var cellAttrs = (td, c) => {
|
|
|
22078
22413
|
function mountTable(host, m, steps) {
|
|
22079
22414
|
const doc = host.ownerDocument;
|
|
22080
22415
|
const win = doc.defaultView;
|
|
22081
|
-
const box =
|
|
22082
|
-
const scroller =
|
|
22083
|
-
const table =
|
|
22416
|
+
const box = el3(doc, "div", "knobs-wt-tablebox");
|
|
22417
|
+
const scroller = el3(doc, "div", "knobs-wt-table");
|
|
22418
|
+
const table = el3(doc, "table");
|
|
22084
22419
|
if (m.caption)
|
|
22085
22420
|
table.append(text2(doc, "caption", "", m.caption));
|
|
22086
|
-
const head =
|
|
22087
|
-
const hr =
|
|
22421
|
+
const head = el3(doc, "thead");
|
|
22422
|
+
const hr = el3(doc, "tr");
|
|
22088
22423
|
for (const c of m.columns) {
|
|
22089
22424
|
const th = text2(doc, "th", "", c.label);
|
|
22090
22425
|
th.scope = "col";
|
|
@@ -22092,11 +22427,11 @@ function mountTable(host, m, steps) {
|
|
|
22092
22427
|
hr.append(th);
|
|
22093
22428
|
}
|
|
22094
22429
|
head.append(hr);
|
|
22095
|
-
const body =
|
|
22430
|
+
const body = el3(doc, "tbody");
|
|
22096
22431
|
for (const r of m.rows) {
|
|
22097
|
-
const tr =
|
|
22432
|
+
const tr = el3(doc, "tr");
|
|
22098
22433
|
for (const c of m.columns) {
|
|
22099
|
-
const td =
|
|
22434
|
+
const td = el3(doc, "td");
|
|
22100
22435
|
cellAttrs(td, c);
|
|
22101
22436
|
const cell = r[c.key];
|
|
22102
22437
|
if (cell) {
|
|
@@ -22111,24 +22446,24 @@ function mountTable(host, m, steps) {
|
|
|
22111
22446
|
}
|
|
22112
22447
|
table.append(head, body);
|
|
22113
22448
|
scroller.append(table);
|
|
22114
|
-
const stack =
|
|
22449
|
+
const stack = el3(doc, "div", "knobs-wt-tstack");
|
|
22115
22450
|
stack.setAttribute("role", "list");
|
|
22116
22451
|
if (m.caption)
|
|
22117
22452
|
stack.setAttribute("aria-label", m.caption);
|
|
22118
22453
|
const primary = m.columns.find((c) => c.key === m.primary) ?? m.columns[0];
|
|
22119
22454
|
for (const r of m.rows) {
|
|
22120
|
-
const item =
|
|
22455
|
+
const item = el3(doc, "div", "knobs-wt-trow");
|
|
22121
22456
|
item.setAttribute("role", "listitem");
|
|
22122
|
-
const title =
|
|
22457
|
+
const title = el3(doc, "div", "knobs-wt-ttitle");
|
|
22123
22458
|
if (primary) {
|
|
22124
22459
|
cellAttrs(title, primary);
|
|
22125
22460
|
const cell = r[primary.key];
|
|
22126
22461
|
if (cell)
|
|
22127
22462
|
cellContent(doc, title, cell);
|
|
22128
22463
|
}
|
|
22129
|
-
const line =
|
|
22464
|
+
const line = el3(doc, "div", "knobs-wt-tline");
|
|
22130
22465
|
line.append(title);
|
|
22131
|
-
const badges =
|
|
22466
|
+
const badges = el3(doc, "div", "knobs-wt-tbadges");
|
|
22132
22467
|
for (const c of m.columns) {
|
|
22133
22468
|
const cell = r[c.key];
|
|
22134
22469
|
if (c !== primary && cell?.badge)
|
|
@@ -22137,14 +22472,14 @@ function mountTable(host, m, steps) {
|
|
|
22137
22472
|
if (badges.childNodes.length)
|
|
22138
22473
|
line.append(badges);
|
|
22139
22474
|
item.append(line);
|
|
22140
|
-
const terms =
|
|
22475
|
+
const terms = el3(doc, "dl", "knobs-wt-tterms");
|
|
22141
22476
|
for (const c of m.columns) {
|
|
22142
22477
|
if (c === primary)
|
|
22143
22478
|
continue;
|
|
22144
22479
|
const cell = r[c.key];
|
|
22145
22480
|
if (!cell || cell.text === "" || cell.badge)
|
|
22146
22481
|
continue;
|
|
22147
|
-
const dd =
|
|
22482
|
+
const dd = el3(doc, "dd");
|
|
22148
22483
|
cellAttrs(dd, c);
|
|
22149
22484
|
dd.removeAttribute("data-align");
|
|
22150
22485
|
cellContent(doc, dd, cell);
|
|
@@ -22210,12 +22545,12 @@ function mountTable(host, m, steps) {
|
|
|
22210
22545
|
}
|
|
22211
22546
|
function chapterPills(host, chapters, io) {
|
|
22212
22547
|
const doc = host.ownerDocument;
|
|
22213
|
-
const list =
|
|
22548
|
+
const list = el3(doc, "div", "knobs-wt-chapters");
|
|
22214
22549
|
list.setAttribute("role", "group");
|
|
22215
22550
|
list.setAttribute("aria-label", "Chapters");
|
|
22216
22551
|
let at = -2;
|
|
22217
22552
|
const rows = chapters.map((c, i) => {
|
|
22218
|
-
const b =
|
|
22553
|
+
const b = el3(doc, "button", "knobs-wt-chapter");
|
|
22219
22554
|
b.type = "button";
|
|
22220
22555
|
b.append(text2(doc, "span", "knobs-wt-chapter-n", String(i + 1)));
|
|
22221
22556
|
b.append(text2(doc, "span", "knobs-wt-chapter-label", c.label));
|
|
@@ -22231,7 +22566,8 @@ function chapterPills(host, chapters, io) {
|
|
|
22231
22566
|
host.append(list);
|
|
22232
22567
|
const pill = selectionPill(list, {
|
|
22233
22568
|
selected: () => rows[at] ?? null,
|
|
22234
|
-
rows: () => rows
|
|
22569
|
+
rows: () => rows,
|
|
22570
|
+
spring: SPRINGS.snappy
|
|
22235
22571
|
});
|
|
22236
22572
|
const select = (i) => {
|
|
22237
22573
|
if (i === at)
|
|
@@ -22257,13 +22593,13 @@ function disclosure(host, options) {
|
|
|
22257
22593
|
const doc = host.ownerDocument;
|
|
22258
22594
|
const win = doc.defaultView;
|
|
22259
22595
|
let open = options.open === true;
|
|
22260
|
-
const root =
|
|
22261
|
-
const toggle =
|
|
22596
|
+
const root = el3(doc, "div", "knobs-wt-disc");
|
|
22597
|
+
const toggle = el3(doc, "button", "knobs-wt-disc-toggle");
|
|
22262
22598
|
toggle.type = "button";
|
|
22263
22599
|
toggle.innerHTML = GLYPH.caret;
|
|
22264
22600
|
toggle.append(text2(doc, "span", "", options.label));
|
|
22265
|
-
const viewport =
|
|
22266
|
-
const content =
|
|
22601
|
+
const viewport = el3(doc, "div", "knobs-wt-disc-body");
|
|
22602
|
+
const content = el3(doc, "div", "knobs-wt-disc-content");
|
|
22267
22603
|
content.append(options.content);
|
|
22268
22604
|
viewport.append(content);
|
|
22269
22605
|
root.append(toggle, viewport);
|
|
@@ -22340,19 +22676,14 @@ var CHECK3 = "M229.66,77.66l-128,128a8,8,0,0,1-11.32,0l-56-56a8,8,0,0,1,11.32-11
|
|
|
22340
22676
|
var svg12 = (d, evenodd = false) => `<svg class="knobs-icon" viewBox="0 0 256 256" width="12" height="12" fill="currentColor"${evenodd ? ' fill-rule="evenodd"' : ""} aria-hidden="true" focusable="false"><path d="${d}"/></svg>`;
|
|
22341
22677
|
var prGlyph = (state) => state === "merged" ? svg12(PR_PATHS.merge) : state === "draft" ? svg12(DRAFT, true) : state === "closed" ? svg12(X) : svg12(PR_PATHS.pull);
|
|
22342
22678
|
var PR_STATE = { merged: "Merged", open: "Open", draft: "Draft", closed: "Closed" };
|
|
22343
|
-
|
|
22344
|
-
const words = (status ?? "").trim().toLowerCase();
|
|
22345
|
-
const first = /^[a-z]+/.exec(words)?.[0] ?? "";
|
|
22346
|
-
const state = first in PR_STATE ? first : null;
|
|
22347
|
-
return { state, checks: /\b(green|passing|passed|ci|checks? pass)/.test(words) };
|
|
22348
|
-
}
|
|
22679
|
+
var ISSUE = "M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-88a16,16,0,1,1-16-16A16,16,0,0,1,144,128Z";
|
|
22349
22680
|
function prStateLabel(doc, state, checks, title) {
|
|
22350
|
-
const s =
|
|
22681
|
+
const s = el3(doc, "span", "knobs-wt-prstate");
|
|
22351
22682
|
s.dataset.state = state;
|
|
22352
22683
|
s.innerHTML = prGlyph(state);
|
|
22353
22684
|
s.append(text2(doc, "span", "", PR_STATE[state]));
|
|
22354
22685
|
if (checks) {
|
|
22355
|
-
const c =
|
|
22686
|
+
const c = el3(doc, "span", "knobs-wt-prchecks");
|
|
22356
22687
|
c.innerHTML = svg12(CHECK3);
|
|
22357
22688
|
c.title = "Checks pass";
|
|
22358
22689
|
c.setAttribute("aria-label", "checks pass");
|
|
@@ -22363,33 +22694,61 @@ function prStateLabel(doc, state, checks, title) {
|
|
|
22363
22694
|
return s;
|
|
22364
22695
|
}
|
|
22365
22696
|
function prChip(doc, n, pr) {
|
|
22366
|
-
const chip =
|
|
22697
|
+
const chip = el3(doc, pr.href ? "a" : "span", "knobs-wt-pr");
|
|
22367
22698
|
if (pr.href) {
|
|
22368
22699
|
chip.setAttribute("href", pr.href);
|
|
22369
22700
|
chip.setAttribute("target", "_blank");
|
|
22370
22701
|
chip.setAttribute("rel", "noreferrer");
|
|
22371
22702
|
}
|
|
22703
|
+
const issue = pr.kind === "issue";
|
|
22704
|
+
if (issue)
|
|
22705
|
+
chip.dataset.kind = "issue";
|
|
22372
22706
|
if (pr.state)
|
|
22373
22707
|
chip.dataset.state = pr.state;
|
|
22374
|
-
chip.innerHTML = prGlyph(pr.state);
|
|
22708
|
+
chip.innerHTML = issue ? svg12(ISSUE) : prGlyph(pr.state);
|
|
22375
22709
|
chip.append(text2(doc, "span", "", `#${n}`));
|
|
22376
|
-
|
|
22377
|
-
|
|
22378
|
-
|
|
22710
|
+
if (pr.checks) {
|
|
22711
|
+
const c = el3(doc, "span", "knobs-wt-prchecks");
|
|
22712
|
+
c.innerHTML = svg12(CHECK3);
|
|
22713
|
+
chip.append(c);
|
|
22714
|
+
}
|
|
22715
|
+
const words = [
|
|
22716
|
+
`${issue ? "Issue" : "Pull request"} #${n}`,
|
|
22717
|
+
pr.title,
|
|
22718
|
+
pr.state ? PR_STATE[pr.state] : "",
|
|
22719
|
+
pr.checks ? "checks pass" : ""
|
|
22720
|
+
].filter(Boolean);
|
|
22721
|
+
chip.title = words.slice(1).length ? `#${n} · ${words.slice(1).join(" · ")}` : `#${n}`;
|
|
22722
|
+
chip.setAttribute("aria-label", words.join(" · "));
|
|
22379
22723
|
return chip;
|
|
22380
22724
|
}
|
|
22381
22725
|
var PR_URL = /^https?:\/\/[^/]+\/.+\/(?:pull|merge_requests)\/(\d+)\/?(?:[?#].*)?$/;
|
|
22382
|
-
var
|
|
22726
|
+
var ISSUE_URL = /^https?:\/\/[^/]+\/.+\/issues\/(\d+)\/?(?:[?#].*)?$/;
|
|
22727
|
+
var REF = /(^|[^\w&/#:])(issue:)?#(\d{3,7})\b/gi;
|
|
22728
|
+
var WHOLE_REF = /^(issue:)?#(\d{1,7})$/i;
|
|
22729
|
+
var KEEP = 'a,pre,button,.knobs-wt-pr,.knobs-wt-slot:not([data-kind="table"]),.knobs-wt-stack';
|
|
22383
22730
|
function linkPRs(root, find) {
|
|
22384
22731
|
const doc = root.ownerDocument;
|
|
22732
|
+
const chip = (n, kind, href) => prChip(doc, n, { ...kind === "issue" ? { kind } : {}, ...find(n, kind), ...href ? { href } : {} });
|
|
22385
22733
|
for (const a of Array.from(root.querySelectorAll("a[href]"))) {
|
|
22386
|
-
if (a.classList.contains("knobs-wt-pr") || a.closest(
|
|
22734
|
+
if (a.classList.contains("knobs-wt-pr") || a.parentElement?.closest(KEEP))
|
|
22735
|
+
continue;
|
|
22736
|
+
const url = a.getAttribute("href") ?? "";
|
|
22737
|
+
const pr = PR_URL.exec(url)?.[1];
|
|
22738
|
+
const n = pr ?? ISSUE_URL.exec(url)?.[1];
|
|
22739
|
+
if (!n)
|
|
22387
22740
|
continue;
|
|
22388
|
-
const
|
|
22389
|
-
|
|
22390
|
-
|
|
22741
|
+
const words = (a.textContent ?? "").trim().replace(/^issue:/i, "");
|
|
22742
|
+
if (!(words === `#${n}` || words === n || words === url))
|
|
22743
|
+
continue;
|
|
22744
|
+
a.replaceWith(chip(n, pr ? "pr" : "issue", a.href));
|
|
22745
|
+
}
|
|
22746
|
+
for (const c of Array.from(root.querySelectorAll("code"))) {
|
|
22747
|
+
if (c.closest("pre") || c.parentElement?.closest(KEEP))
|
|
22391
22748
|
continue;
|
|
22392
|
-
|
|
22749
|
+
const m = WHOLE_REF.exec((c.textContent ?? "").trim());
|
|
22750
|
+
if (m)
|
|
22751
|
+
c.replaceWith(chip(m[2], m[1] ? "issue" : "pr"));
|
|
22393
22752
|
}
|
|
22394
22753
|
const walker = doc.createTreeWalker(root, 5);
|
|
22395
22754
|
const hits = [];
|
|
@@ -22397,29 +22756,22 @@ function linkPRs(root, find) {
|
|
|
22397
22756
|
if (t.nodeType !== 3)
|
|
22398
22757
|
continue;
|
|
22399
22758
|
const p = t.parentElement;
|
|
22400
|
-
if (!p || p.closest(
|
|
22759
|
+
if (!p || p.closest(`${KEEP},code`))
|
|
22401
22760
|
continue;
|
|
22402
|
-
|
|
22403
|
-
if (
|
|
22761
|
+
REF.lastIndex = 0;
|
|
22762
|
+
if (REF.test(t.nodeValue ?? ""))
|
|
22404
22763
|
hits.push(t);
|
|
22405
22764
|
}
|
|
22406
22765
|
for (const t of hits) {
|
|
22407
22766
|
const value = t.nodeValue ?? "";
|
|
22408
22767
|
const frag = doc.createDocumentFragment();
|
|
22409
22768
|
let last = 0;
|
|
22410
|
-
|
|
22411
|
-
|
|
22412
|
-
for (let m = PR_REF.exec(value);m; m = PR_REF.exec(value)) {
|
|
22413
|
-
const pr = find(m[2]);
|
|
22414
|
-
if (!pr)
|
|
22415
|
-
continue;
|
|
22769
|
+
REF.lastIndex = 0;
|
|
22770
|
+
for (let m = REF.exec(value);m; m = REF.exec(value)) {
|
|
22416
22771
|
const at = m.index + m[1].length;
|
|
22417
|
-
frag.append(value.slice(last, at),
|
|
22418
|
-
last =
|
|
22419
|
-
changed = true;
|
|
22772
|
+
frag.append(value.slice(last, at), chip(m[3], m[2] ? "issue" : "pr"));
|
|
22773
|
+
last = m.index + m[0].length;
|
|
22420
22774
|
}
|
|
22421
|
-
if (!changed)
|
|
22422
|
-
continue;
|
|
22423
22775
|
frag.append(value.slice(last));
|
|
22424
22776
|
t.replaceWith(frag);
|
|
22425
22777
|
}
|
|
@@ -22438,22 +22790,26 @@ var snappy3 = springCss(SPRINGS.snappy);
|
|
|
22438
22790
|
var calm = springCss(SPRINGS.calm);
|
|
22439
22791
|
var state = springCss(SPRINGS.default);
|
|
22440
22792
|
var quick = springCss(FADE);
|
|
22441
|
-
var fade2 = "-webkit-mask-image:linear-gradient(to right,#000 calc(100% -
|
|
22442
|
-
var walkthroughCss =
|
|
22793
|
+
var fade2 = "-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 16px),transparent);mask-image:linear-gradient(to right,#000 calc(100% - 16px),transparent)";
|
|
22794
|
+
var walkthroughCss = `${foundationCss}
|
|
22443
22795
|
:where(.knobs-walkthrough,.knobs-walkthrough *,.knobs-wt-slot,.knobs-wt-slot *){box-sizing:border-box}
|
|
22444
22796
|
.knobs-ui:is(.knobs-walkthrough,.knobs-wt-slot){--k-glass:0;--k-glow:0;--kw-quick:${quick.easing};--kw-quick-ms:${quick.duration}ms}
|
|
22445
22797
|
.knobs-ui.knobs-walkthrough{--kw-snappy:${snappy3.easing};--kw-snappy-ms:${snappy3.duration}ms;--kw-calm:${calm.easing};--kw-calm-ms:${calm.duration}ms;--kw-state:${state.easing};--kw-state-ms:${state.duration}ms;--kw-quick:${quick.easing};--kw-quick-ms:${quick.duration}ms;
|
|
22446
|
-
--kw-measure:var(--
|
|
22798
|
+
--kw-measure:var(--_kr-measure);--kw-width:var(--k-walkthrough-width,960px);--kw-rail-w:220px;--kw-rail-gap:calc(var(--_k-space-group) + var(--_k-space-column) / 1.5);--kw-good:var(--k-walkthrough-good,var(--_k-ok));--kw-info:var(--k-walkthrough-info,var(--_k-info));
|
|
22447
22799
|
--kw-card:var(--_ku-pane-bg);--kw-card-ring:var(--_ku-pane-ring);--kw-under:var(--_k-bg-page);--kw-ink:var(--k-walkthrough-ink,#ff375f);--kw-strong:var(--_k-weight-label);
|
|
22448
22800
|
container:knobs-wt / inline-size;display:block;width:100%;color:var(--_k-fg);font:var(--_k-weight) var(--_k-type-body)/var(--_k-leading-body) var(--_k-font);font-variant-numeric:tabular-nums;text-align:left;
|
|
22449
|
-
letter-spacing:
|
|
22801
|
+
letter-spacing:var(--_kr-track);-webkit-font-smoothing:antialiased}
|
|
22450
22802
|
.knobs-walkthrough [hidden]{display:none!important}
|
|
22803
|
+
/* Prose: wrapped to look set by hand, quotes hung in the margin (Safari). Data: figures that line
|
|
22804
|
+
up and can't be misread. */
|
|
22805
|
+
:where(.knobs-wt-summary,.knobs-wt-ssum,.knobs-wt-caption,.knobs-wt-more-text,.knobs-wt-fi-text,.knobs-wt-fi-answer,.knobs-wt-ocap,.knobs-wt-text,.knobs-wt-callout,.knobs-wt-ssummary,.knobs-wt-osum){text-wrap:pretty;hanging-punctuation:first allow-end last}
|
|
22806
|
+
:where(.knobs-wt-table table,.knobs-wt-tterms,.knobs-wt-facts,.knobs-wt-smeta,.knobs-wt-metaline,.knobs-wt-meta,.knobs-wt-pr,.knobs-wt-prstate,.knobs-wt-sord){font-feature-settings:var(--_kr-data)}
|
|
22451
22807
|
/* (0,0,1): a host's element rules stop here, and every class rule below wins over it. */
|
|
22452
|
-
:where(.knobs-walkthrough) :is(h1,h2,h3,p,ol,ul,dl,dd){margin:0;font:inherit;letter-spacing:
|
|
22453
|
-
.knobs-walkthrough a{color:inherit;text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 35%,transparent);text-underline-offset:2px;transition:text-decoration-color
|
|
22808
|
+
:where(.knobs-walkthrough) :is(h1,h2,h3,p,ol,ul,dl,dd){margin:0;font:inherit;letter-spacing:var(--_kr-track)}
|
|
22809
|
+
.knobs-walkthrough a{cursor:default;color:inherit;text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 35%,transparent);text-underline-offset:2px;transition:text-decoration-color calc(var(--_k-hover-out) * 1ms)}
|
|
22454
22810
|
.knobs-walkthrough a:hover{text-decoration-color:currentColor}
|
|
22455
22811
|
.knobs-walkthrough code,.knobs-wt-slot code{font:var(--_k-type-label) var(--_k-mono);padding:1px 5px;border-radius:calc(var(--_k-radius) / 2);background:var(--_k-fill)}
|
|
22456
|
-
:where(.knobs-ui) :is(.knobs-wt-btn,.knobs-wt-pick,.knobs-wt-toc-row,button.knobs-wt-stitle,.knobs-wt-chapter,.knobs-wt-disc-toggle){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:
|
|
22812
|
+
:where(.knobs-ui) :is(.knobs-wt-btn,.knobs-wt-pick,.knobs-wt-toc-row,button.knobs-wt-stitle,.knobs-wt-chapter,.knobs-wt-disc-toggle){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:var(--_kr-track);
|
|
22457
22813
|
background:transparent;border:0;border-radius:0;margin:0;padding:0;min-width:0;box-shadow:none;outline:none}
|
|
22458
22814
|
|
|
22459
22815
|
/* ——— layout: the contents rail sticky at the left edge (right if asked), and the column centred
|
|
@@ -22478,14 +22834,17 @@ var walkthroughCss = `
|
|
|
22478
22834
|
.knobs-walkthrough .knobs-wt-metaline a:not(.knobs-wt-pr){display:inline-flex;align-items:baseline;color:inherit;text-decoration:none;transition:color calc(var(--_k-hover-out) * 1ms)}
|
|
22479
22835
|
.knobs-walkthrough .knobs-wt-metaline a:not(.knobs-wt-pr):hover{color:var(--_k-fg);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
22480
22836
|
.knobs-wt-metaline svg{align-self:center;width:12px;height:12px;margin-left:2px}
|
|
22481
|
-
/* A pull request: a
|
|
22482
|
-
the success hue, merged the violet series, draft and closed
|
|
22483
|
-
|
|
22837
|
+
/* A pull request or issue: a capsule, its state's icon and number in a quiet tint of the state
|
|
22838
|
+
(open the success hue, merged the violet series, draft and closed faint, unknown neutral; a
|
|
22839
|
+
closed issue is done, so violet), a faint check where its checks pass, its title on hover. */
|
|
22840
|
+
.knobs-ui .knobs-wt-pr{--kw-pr:var(--_k-fg-2);display:inline-flex;align-items:center;gap:3px;height:18px;padding:0 6px 0 5px;margin:0 1px;border-radius:9px;vertical-align:1px;
|
|
22484
22841
|
background:color-mix(in oklch,var(--kw-pr) 12%,transparent);color:var(--kw-pr);font:var(--_k-weight-label) var(--_k-type-small)/1 var(--_k-font);font-variant-numeric:tabular-nums;white-space:nowrap;text-decoration:none;
|
|
22485
22842
|
transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
22486
22843
|
.knobs-ui .knobs-wt-pr[data-state="open"]{--kw-pr:color-mix(in oklch,var(--_k-ok) 60%,var(--_k-fg-2))}
|
|
22487
22844
|
.knobs-ui .knobs-wt-pr[data-state="merged"]{--kw-pr:color-mix(in oklch,var(--_k-series-5) 60%,var(--_k-fg-2))}
|
|
22488
22845
|
.knobs-ui .knobs-wt-pr:is([data-state="draft"],[data-state="closed"]){--kw-pr:var(--_k-fg-3)}
|
|
22846
|
+
.knobs-ui .knobs-wt-pr[data-kind="issue"][data-state="closed"]{--kw-pr:color-mix(in oklch,var(--_k-series-5) 60%,var(--_k-fg-2))}
|
|
22847
|
+
.knobs-ui .knobs-wt-pr .knobs-wt-prchecks{margin-left:0}
|
|
22489
22848
|
.knobs-ui a.knobs-wt-pr:is(:hover,:focus-visible){background:color-mix(in oklch,var(--kw-pr) 22%,transparent);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
22490
22849
|
.knobs-wt-pr svg{flex:none}
|
|
22491
22850
|
.knobs-wt-metaline .knobs-wt-pr{align-self:center;margin:0}
|
|
@@ -22544,14 +22903,14 @@ var walkthroughCss = `
|
|
|
22544
22903
|
.knobs-wt-fi-ask{max-width:var(--kw-measure);color:var(--_k-fg);font-weight:var(--kw-strong);text-wrap:pretty}
|
|
22545
22904
|
.knobs-wt-fi-text{max-width:var(--kw-measure);color:var(--_k-fg);text-wrap:pretty}
|
|
22546
22905
|
.knobs-wt-fi-answer{max-width:var(--kw-measure);color:var(--_k-fg-2);text-wrap:pretty}
|
|
22547
|
-
:where(.knobs-ui) .knobs-wt-fi-step{all:revert;box-sizing:border-box;font:inherit;color:inherit;background:transparent;border:0;margin:0;padding:0;cursor:
|
|
22906
|
+
:where(.knobs-ui) .knobs-wt-fi-step{all:revert;box-sizing:border-box;font:inherit;color:inherit;background:transparent;border:0;margin:0;padding:0;cursor:default;outline:none;
|
|
22548
22907
|
transition:color calc(var(--_k-hover-out) * 1ms)}
|
|
22549
22908
|
.knobs-ui .knobs-wt-fi-step:is(:hover,:focus-visible){color:var(--_k-fg);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
22550
22909
|
|
|
22551
22910
|
/* ——— a disclosure: a small faint toggle with a caret, no fill. The body's height springs (in
|
|
22552
22911
|
script) and its content fades in place, top-anchored, under a soft bottom mask ——— */
|
|
22553
22912
|
.knobs-wt-disc{display:flex;flex-direction:column;min-width:0}
|
|
22554
|
-
.knobs-ui .knobs-wt-disc-toggle{display:inline-flex;align-items:center;gap:var(--_k-space-inside);width:max-content;height:20px;color:var(--_k-fg-3);font-size:var(--_k-type-small);line-height:var(--_k-leading-small);cursor:
|
|
22913
|
+
.knobs-ui .knobs-wt-disc-toggle{display:inline-flex;align-items:center;gap:var(--_k-space-inside);width:max-content;height:20px;color:var(--_k-fg-3);font-size:var(--_k-type-small);line-height:var(--_k-leading-small);cursor:default;
|
|
22555
22914
|
border-radius:calc(var(--_k-radius) / 2);transition:color calc(var(--_k-hover-out) * 1ms)}
|
|
22556
22915
|
.knobs-ui .knobs-wt-disc-toggle:is(:hover,:focus-visible),.knobs-wt-disc[data-open]>.knobs-wt-disc-toggle{color:var(--_k-fg-2);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
22557
22916
|
.knobs-ui .knobs-wt-disc-toggle:focus-visible{box-shadow:0 0 0 2px var(--_k-focus)}
|
|
@@ -22578,7 +22937,7 @@ var walkthroughCss = `
|
|
|
22578
22937
|
.knobs-wt-n[data-leaving]{opacity:0;filter:blur(3px);padding-block:0}
|
|
22579
22938
|
.knobs-wt-n+.knobs-wt-n{box-shadow:inset 0 1px 0 var(--_k-border-subtle)}
|
|
22580
22939
|
.knobs-wt-n-meta{flex:none;min-width:44px;color:var(--_k-fg-3);font:var(--_k-weight) var(--_k-type-small)/var(--_k-leading-body) var(--_k-mono)}
|
|
22581
|
-
.knobs-wt-n-meta[data-seek]{cursor:
|
|
22940
|
+
.knobs-wt-n-meta[data-seek]{cursor:default}
|
|
22582
22941
|
.knobs-wt-n-meta[data-seek]:hover{color:var(--_k-fg)}
|
|
22583
22942
|
.knobs-wt-n-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--_k-space-sibling)}
|
|
22584
22943
|
.knobs-wt-n-voice{height:30px;max-width:320px}
|
|
@@ -22595,7 +22954,7 @@ var walkthroughCss = `
|
|
|
22595
22954
|
/* Collapsed: the launcher and the bar swap in place, a quick fade with a little scale and blur
|
|
22596
22955
|
from the launcher's corner; the exit is the shorter. */
|
|
22597
22956
|
:where(.knobs-ui) .knobs-wt-launch{all:revert;box-sizing:border-box;justify-self:end;align-self:end;display:inline-flex;align-items:center;gap:6px;height:32px;margin:0;padding:0 10px 0 9px;border:0;border-radius:var(--_k-round);
|
|
22598
|
-
background:var(--_k-bg);color:var(--_k-fg-2);box-shadow:var(--_ku-pane-ring),var(--_k-shadow-overlay);font:var(--kw-strong) var(--_k-type-small)/1 var(--_k-font);cursor:
|
|
22957
|
+
background:var(--_k-bg);color:var(--_k-fg-2);box-shadow:var(--_ku-pane-ring),var(--_k-shadow-overlay);font:var(--kw-strong) var(--_k-type-small)/1 var(--_k-font);cursor:default;outline:none;transform-origin:100% 100%;
|
|
22599
22958
|
transition:color calc(var(--_k-hover-out) * 1ms),opacity var(--kw-quick-ms) var(--kw-quick),scale var(--kw-quick-ms) var(--kw-quick),filter var(--kw-quick-ms) var(--kw-quick)}
|
|
22600
22959
|
.knobs-ui .knobs-wt-launch:is(:hover,:focus-visible){color:var(--_k-fg)}
|
|
22601
22960
|
.knobs-ui .knobs-wt-launch:focus-visible{box-shadow:var(--_k-focus-ring)}
|
|
@@ -22608,18 +22967,18 @@ var walkthroughCss = `
|
|
|
22608
22967
|
box-shadow:var(--_ku-pane-ring),var(--_k-shadow-overlay)}
|
|
22609
22968
|
.knobs-wt-on{padding-top:3px;color:var(--_k-fg-3);font-size:var(--_k-type-small);line-height:var(--_k-leading-small);white-space:nowrap;overflow:hidden;${fade2}}
|
|
22610
22969
|
.knobs-wt-row{display:flex;align-items:flex-end;gap:4px}
|
|
22611
|
-
:where(.knobs-ui) :is(.knobs-wt-input,.knobs-wt-tool,.knobs-wt-x,.knobs-wt-back){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:
|
|
22970
|
+
:where(.knobs-ui) :is(.knobs-wt-input,.knobs-wt-tool,.knobs-wt-x,.knobs-wt-back){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:var(--_kr-track);background:transparent;border:0;
|
|
22612
22971
|
border-radius:0;margin:0;padding:0;min-width:0;box-shadow:none;outline:none}
|
|
22613
22972
|
.knobs-ui .knobs-wt-input{flex:1;min-width:0;height:32px;max-height:140px;padding:6px 0;resize:none;color:var(--_k-fg);caret-color:var(--_k-accent);line-height:var(--_k-leading-body);font-size:var(--_k-type-body)}
|
|
22614
22973
|
.knobs-ui .knobs-wt-input::placeholder{color:var(--_k-fg-3)}
|
|
22615
22974
|
.knobs-wt-attach{display:flex;gap:4px;align-items:center;align-self:center}
|
|
22616
22975
|
.knobs-wt-attach:empty{display:none}
|
|
22617
22976
|
.knobs-wt-chip-a{display:inline-flex;align-items:center;gap:2px;height:24px;padding:0 2px 0 9px;border-radius:var(--_k-round);background:var(--_k-fill-selected);font-size:var(--_k-type-small);white-space:nowrap}
|
|
22618
|
-
.knobs-ui .knobs-wt-x{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;color:var(--_k-fg-3);cursor:
|
|
22977
|
+
.knobs-ui .knobs-wt-x{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;color:var(--_k-fg-3);cursor:default;transition:background .15s,color .15s}
|
|
22619
22978
|
.knobs-ui .knobs-wt-x:is(:hover,:focus-visible){background:var(--_ku-wash-hi);color:var(--_k-fg)}
|
|
22620
22979
|
.knobs-wt-x svg{width:12px;height:12px}
|
|
22621
22980
|
.knobs-ui .knobs-wt-tool{flex:none;display:inline-flex;align-items:center;justify-content:center;gap:5px;min-width:32px;height:32px;padding:0 8px;border-radius:calc(var(--_k-radius) + 2px);
|
|
22622
|
-
color:var(--_k-fg-2);cursor:
|
|
22981
|
+
color:var(--_k-fg-2);cursor:default;transition:background .15s,color .15s}
|
|
22623
22982
|
.knobs-ui .knobs-wt-tool:is(:hover,:focus-visible){background:var(--_ku-wash-hi);color:var(--_k-fg)}
|
|
22624
22983
|
.knobs-ui .knobs-wt-tool[aria-pressed="true"]{background:var(--_k-fill-selected);color:var(--_k-fg)}
|
|
22625
22984
|
.knobs-wt-tool svg{width:16px;height:16px}
|
|
@@ -22629,7 +22988,7 @@ var walkthroughCss = `
|
|
|
22629
22988
|
.knobs-ui .knobs-wt-tool[data-send][data-ready]{background:var(--_k-accent);color:var(--_k-bg)}
|
|
22630
22989
|
/* Back: in place over the bar for a few seconds after a note moves the page on. */
|
|
22631
22990
|
.knobs-ui .knobs-wt-back{position:absolute;left:8px;bottom:calc(100% + 8px);display:inline-flex;align-items:center;gap:var(--_k-space-inside);max-width:min(360px,calc(100% - 16px));height:28px;padding:0 12px 0 9px;
|
|
22632
|
-
border-radius:var(--_k-round);background:var(--_k-bg);color:var(--_k-fg);box-shadow:var(--_ku-pane-ring),var(--_k-shadow-overlay);font-size:var(--_k-type-small);font-weight:var(--kw-strong);cursor:
|
|
22991
|
+
border-radius:var(--_k-round);background:var(--_k-bg);color:var(--_k-fg);box-shadow:var(--_ku-pane-ring),var(--_k-shadow-overlay);font-size:var(--_k-type-small);font-weight:var(--kw-strong);cursor:default;
|
|
22633
22992
|
opacity:0;scale:.96;filter:blur(3px);pointer-events:none;transition:opacity .11s cubic-bezier(.4,0,1,1),scale .11s cubic-bezier(.4,0,1,1),filter .11s cubic-bezier(.4,0,1,1)}
|
|
22634
22993
|
.knobs-ui .knobs-wt-back[data-on]{opacity:1;scale:1;filter:none;pointer-events:auto;transition:opacity .15s cubic-bezier(.2,.8,.2,1),scale .15s cubic-bezier(.2,.8,.2,1),filter .15s cubic-bezier(.2,.8,.2,1)}
|
|
22635
22994
|
.knobs-ui .knobs-wt-back:hover{background:var(--_k-fill-selected)}
|
|
@@ -22656,28 +23015,57 @@ var walkthroughCss = `
|
|
|
22656
23015
|
.knobs-wt-step[data-full] .knobs-wt-body{flex:1;min-height:0}
|
|
22657
23016
|
.knobs-wt-step[data-full] .knobs-wt-fit{height:100%;transition:none}
|
|
22658
23017
|
.knobs-wt-step[data-full] .knobs-wt-frame{height:100%;aspect-ratio:auto}
|
|
23018
|
+
.knobs-wt-step[data-full] .knobs-wt-slot[data-kind="video"]>.knobs-wt-body{display:flex;flex-direction:column}
|
|
23019
|
+
.knobs-wt-step[data-full] .knobs-wt-slot[data-kind="video"] .knobs-player{flex:1;min-height:0}
|
|
23020
|
+
.knobs-wt-step[data-full] .knobs-wt-slot[data-kind="video"] .knobs-player-frame{flex:1;min-height:0;aspect-ratio:auto}
|
|
22659
23021
|
|
|
22660
|
-
/* ——— a taste test
|
|
22661
|
-
|
|
22662
|
-
|
|
22663
|
-
|
|
22664
|
-
.knobs-wt-
|
|
22665
|
-
.knobs-wt-option
|
|
22666
|
-
.knobs-wt-
|
|
22667
|
-
.knobs-
|
|
22668
|
-
|
|
22669
|
-
.knobs-
|
|
22670
|
-
.knobs-wt-
|
|
22671
|
-
.knobs-wt-
|
|
22672
|
-
.knobs-wt-
|
|
22673
|
-
.knobs-wt-
|
|
22674
|
-
|
|
23022
|
+
/* ——— options: a decision, or a taste test when Kit picks. Columns that fill whole rows (4 → 4, 2
|
|
23023
|
+
or 1 across; 3 → 3 or 1), a hairline between neighbours and between rows, no card of their own.
|
|
23024
|
+
Each: a kicker ("Option 1 · Recommended", the mark a quiet word in text colour), its title, a
|
|
23025
|
+
sentence, its media and what changes as facts. A pick dims the rest ——— */
|
|
23026
|
+
.knobs-wt-options{--kw-ogap:var(--_k-space-group);display:grid;grid-template-columns:repeat(var(--kw-cols,1),minmax(0,1fr));gap:var(--kw-ogap);min-width:0}
|
|
23027
|
+
.knobs-wt-option{position:relative;display:flex;flex-direction:column;gap:var(--_k-space-title);min-width:0}
|
|
23028
|
+
.knobs-wt-option[data-col]:not([data-col="0"])::before{content:"";position:absolute;top:0;bottom:0;left:calc(var(--kw-ogap) / -2);width:1px;background:var(--_k-border-subtle);pointer-events:none}
|
|
23029
|
+
.knobs-wt-option[data-col]:not([data-row="0"])::before{top:calc(var(--kw-ogap) / -2)}
|
|
23030
|
+
.knobs-wt-option[data-col]:not([data-last-row])::before{bottom:calc(var(--kw-ogap) / -2)}
|
|
23031
|
+
.knobs-wt-option[data-col]:not([data-row="0"])::after{content:"";position:absolute;top:calc(var(--kw-ogap) / -2);left:calc(var(--kw-ogap) / -2);right:calc(var(--kw-ogap) / -2);height:1px;background:var(--_k-border-subtle);pointer-events:none}
|
|
23032
|
+
.knobs-wt-option[data-col="0"]::after{left:0}
|
|
23033
|
+
.knobs-wt-option[data-end]::after{right:0}
|
|
23034
|
+
.knobs-wt-option>:not(.knobs-wt-ohead){transition:opacity var(--kw-snappy-ms) var(--kw-snappy)}
|
|
23035
|
+
.knobs-wt-options[data-has-pick] .knobs-wt-option:not([data-picked])>:not(.knobs-wt-ohead){opacity:.55}
|
|
23036
|
+
.knobs-wt-ohead{display:flex;flex-direction:column;gap:var(--_k-space-inside);min-width:0;text-align:left}
|
|
23037
|
+
.knobs-wt-okicker{display:flex;align-items:center;gap:var(--_k-space-inside);min-width:0;height:var(--_k-leading-small);color:var(--_k-fg-3);font-size:var(--_k-type-small);line-height:var(--_k-leading-small);white-space:nowrap}
|
|
23038
|
+
.knobs-wt-orec{color:var(--_k-fg);font-weight:var(--kw-strong)}
|
|
23039
|
+
.knobs-wt-orec::before{content:"·";margin-right:var(--_k-space-inside);color:var(--_k-fg-3);font-weight:var(--_k-weight)}
|
|
23040
|
+
.knobs-wt-otitle{color:var(--_k-fg);font-weight:var(--kw-strong);text-wrap:balance}
|
|
23041
|
+
.knobs-wt-osum{max-width:var(--kw-measure);color:var(--_k-fg-2)}
|
|
23042
|
+
/* Picking: the head is the radio, bled out so its words keep the column's edge; a fill under the
|
|
23043
|
+
pointer at once; a check at the kicker's end that fills when picked. */
|
|
23044
|
+
.knobs-ui .knobs-wt-pick{margin:-6px -8px;padding:6px 8px;border-radius:var(--_k-radius);cursor:default;transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
23045
|
+
.knobs-ui .knobs-wt-pick:is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
23046
|
+
.knobs-ui .knobs-wt-pick:focus-visible{box-shadow:inset 0 0 0 1px var(--_k-focus)}
|
|
23047
|
+
.knobs-wt-check{flex:none;display:flex;width:16px;height:16px;margin-left:auto;align-items:center;justify-content:center;border-radius:50%;box-shadow:inset 0 0 0 1px var(--_k-border-strong);color:transparent;
|
|
23048
|
+
transition:background var(--kw-snappy-ms) var(--kw-snappy),color var(--kw-snappy-ms) var(--kw-snappy),box-shadow var(--kw-snappy-ms) var(--kw-snappy)}
|
|
22675
23049
|
.knobs-wt-check svg{width:12px;height:12px}
|
|
22676
|
-
.knobs-wt-option[data-picked] .knobs-wt-check{background:var(--_k-accent);color:var(--_k-
|
|
22677
|
-
|
|
22678
|
-
|
|
22679
|
-
.
|
|
22680
|
-
|
|
23050
|
+
.knobs-wt-option[data-picked] .knobs-wt-check{background:var(--_k-accent);box-shadow:none;color:var(--_k-on-accent)}
|
|
23051
|
+
|
|
23052
|
+
/* ——— facts: terms in a fixed gutter beside their values, sharing a baseline; groups under a
|
|
23053
|
+
heading, a hairline between them. Code and evidence are small mono chips. Too narrow for the
|
|
23054
|
+
gutter, each term sits over its value ——— */
|
|
23055
|
+
.knobs-wt-facts{--kw-term:144px;display:flex;flex-direction:column;gap:var(--_kr-block);min-width:0}
|
|
23056
|
+
.knobs-wt-fgroup{position:relative;display:flex;flex-direction:column;gap:var(--_k-space-title);min-width:0}
|
|
23057
|
+
.knobs-wt-fgroup+.knobs-wt-fgroup::before{content:"";position:absolute;left:0;right:0;top:calc(var(--_kr-block) / -2);height:1px;background:var(--_k-border-subtle);pointer-events:none}
|
|
23058
|
+
.knobs-wt-fhead{margin:0;color:var(--_k-fg);font-weight:var(--kw-strong);text-wrap:balance}
|
|
23059
|
+
.knobs-wt-fterms{display:grid;grid-template-columns:var(--kw-term) minmax(0,1fr);gap:var(--_k-space-sibling) var(--_kr-block);align-items:baseline;margin:0;min-width:0}
|
|
23060
|
+
.knobs-wt-fact{display:contents}
|
|
23061
|
+
.knobs-wt-fterms dt{margin:0;color:var(--_k-fg-3);font-size:var(--_k-type-small);line-height:var(--_k-leading-small);text-wrap:balance}
|
|
23062
|
+
.knobs-wt-fterms dd{display:flex;flex-direction:column;gap:var(--_k-space-inside);min-width:0;margin:0;color:var(--_k-fg-2);overflow-wrap:anywhere;text-wrap:pretty}
|
|
23063
|
+
.knobs-wt-fterms dd[data-code]{flex-flow:row wrap}
|
|
23064
|
+
.knobs-wt-fterms dd[data-code]>code{padding:2px 6px;line-height:var(--_k-leading-label);color:var(--_k-fg)}
|
|
23065
|
+
@container knobs-wt-slot (max-width:400px){
|
|
23066
|
+
.knobs-wt-fterms{display:flex;flex-direction:column;gap:var(--_k-space-sibling)}
|
|
23067
|
+
.knobs-wt-fact{display:flex;flex-direction:column;gap:var(--_k-space-inside)}
|
|
23068
|
+
}
|
|
22681
23069
|
|
|
22682
23070
|
/* ——— the rail: progress, contents, export ——— */
|
|
22683
23071
|
.knobs-wt-rail{position:sticky;top:var(--_k-pad-page);display:flex;flex-direction:column;gap:var(--_k-space-title);max-height:calc(100vh - var(--_k-pad-page) * 2);min-height:0;font-size:var(--_k-type-small);line-height:var(--_k-leading-small)}
|
|
@@ -22687,17 +23075,18 @@ var walkthroughCss = `
|
|
|
22687
23075
|
.knobs-wt-bar{position:relative;height:4px;border-radius:2px;overflow:hidden;background:var(--_k-fill)}
|
|
22688
23076
|
.knobs-wt-fill{position:absolute;inset:0;border-radius:inherit;background:var(--_k-accent);transform-origin:0 50%;transform:scaleX(var(--kw-done,0))}
|
|
22689
23077
|
.knobs-walkthrough[data-settled] .knobs-wt-fill{transition:transform var(--kw-calm-ms) var(--kw-calm)}
|
|
22690
|
-
/* The contents: every row on one text edge and in one colour, title rows (
|
|
22691
|
-
radius) and the steps under them (20 high, half of it), bled out so their text sits on the
|
|
22692
|
-
rail's edge
|
|
22693
|
-
|
|
23078
|
+
/* The contents: every row on one text edge and in one colour, title rows (28 high, the control
|
|
23079
|
+
radius) and the steps under them (20 high, half of it), bled 6 px out so their text sits on the
|
|
23080
|
+
rail's edge and the first title's words on the column's top line; a narrow fade where a title
|
|
23081
|
+
runs out of room; the selection pill slides to the current step, and base rows never brighten. */
|
|
23082
|
+
.knobs-wt-toc{position:relative;flex:1 1 auto;min-height:0;overflow:auto;scrollbar-width:none;display:flex;flex-direction:column;gap:var(--_k-space-sibling);margin:-4px -6px 0;padding:0 0 8px}
|
|
22694
23083
|
.knobs-wt-toc::-webkit-scrollbar{display:none}
|
|
22695
23084
|
.knobs-wt-toc-group{display:flex;flex-direction:column;min-width:0}
|
|
22696
|
-
.knobs-ui .knobs-wt-toc-row{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:var(--_k-space-sibling);align-items:center;flex:none;width:100%;height:
|
|
22697
|
-
padding:0
|
|
22698
|
-
transition:color calc(var(--_k-hover-out) * 1ms)}
|
|
23085
|
+
.knobs-ui .knobs-wt-toc-row{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:var(--_k-space-sibling);align-items:center;flex:none;width:100%;height:28px;
|
|
23086
|
+
padding:0 6px;border-radius:var(--_k-radius);color:var(--_k-fg-2);font-size:var(--_k-type-body);line-height:var(--_k-leading-body);font-weight:var(--_k-weight);text-align:left;white-space:nowrap;cursor:default;
|
|
23087
|
+
transition:color calc(var(--_k-hover-out) * 1ms),background calc(var(--_k-hover-out) * 1ms)}
|
|
22699
23088
|
.knobs-ui .knobs-wt-toc-sub{height:20px;border-radius:calc(var(--_k-radius) / 2);font-size:var(--_k-type-small);line-height:var(--_k-leading-small);font-weight:var(--_k-weight)}
|
|
22700
|
-
.knobs-ui .knobs-wt-toc-row:is(:hover,:focus-visible){color:var(--_k-fg);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
23089
|
+
.knobs-ui .knobs-wt-toc-row:is(:hover,:focus-visible){color:var(--_k-fg);background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
22701
23090
|
.knobs-ui .knobs-wt-toc-row:focus-visible{box-shadow:inset 0 0 0 1px var(--_k-focus)}
|
|
22702
23091
|
.knobs-wt-toc-end{display:flex;align-items:center;font-size:var(--_k-type-small);line-height:var(--_k-leading-small);font-weight:var(--_k-weight);color:var(--_k-fg-3)}
|
|
22703
23092
|
.knobs-wt-toc-label{min-width:0;overflow:hidden;${fade2}}
|
|
@@ -22709,7 +23098,7 @@ var walkthroughCss = `
|
|
|
22709
23098
|
.knobs-wt-toc-glyph[data-done]{background:var(--kw-tone)}
|
|
22710
23099
|
.knobs-wt-toc-glyph[data-tone="none"]{box-shadow:inset 0 0 0 1px var(--_k-border)}
|
|
22711
23100
|
.knobs-wt-actions{display:flex;flex-wrap:wrap;gap:4px}
|
|
22712
|
-
.knobs-ui .knobs-wt-btn{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 9px;border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:
|
|
23101
|
+
.knobs-ui .knobs-wt-btn{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 9px;border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:default;white-space:nowrap;
|
|
22713
23102
|
transition:background .15s,color .15s}
|
|
22714
23103
|
.knobs-ui .knobs-wt-btn:is(:hover,:focus-visible){background:var(--_ku-wash-hi);color:var(--_k-fg)}
|
|
22715
23104
|
.knobs-ui .knobs-wt-btn[data-primary]{background:var(--_k-fill-selected);color:var(--_k-fg)}
|
|
@@ -22730,11 +23119,11 @@ var walkthroughCss = `
|
|
|
22730
23119
|
set apart by space, hairlines and their own colours. On a card (.knobs-surface) code drops its
|
|
22731
23120
|
well for hairlines, so nothing draws a fill and a ring of its own there ——— */
|
|
22732
23121
|
.knobs-ui.knobs-wt-slot{position:relative;display:flex;flex-direction:column;gap:var(--_k-space-sibling);min-width:0;container:knobs-wt-slot / inline-size;color:var(--_k-fg);
|
|
22733
|
-
font:var(--_k-weight) var(--_k-type-body)/var(--_k-leading-body) var(--_k-font);font-variant-numeric:tabular-nums;--kw-measure:var(--
|
|
23122
|
+
font:var(--_k-weight) var(--_k-type-body)/var(--_k-leading-body) var(--_k-font);font-variant-numeric:tabular-nums;--kw-measure:var(--_kr-measure);
|
|
22734
23123
|
--kw-good:var(--k-walkthrough-good,var(--_k-ok));--kw-info:var(--k-walkthrough-info,var(--_k-info));--kw-frame-r:var(--_k-radius-panel)}
|
|
22735
23124
|
.knobs-surface .knobs-wt-slot{--kw-frame-r:calc(var(--_k-radius-panel) - 4px)}
|
|
22736
23125
|
/* A slot's label: sentence case as written, small and faint, never a heading. */
|
|
22737
|
-
.knobs-wt-slot-label{display:block;min-width:0;overflow:hidden;white-space:nowrap;font:var(--_k-weight) var(--_k-type-small)/var(--_k-leading-small) var(--_k-font);
|
|
23126
|
+
.knobs-wt-slot-label{display:block;min-width:0;overflow:hidden;white-space:nowrap;font:var(--_k-weight) var(--_k-type-small)/var(--_k-leading-small) var(--_k-font);text-transform:none;color:var(--_k-fg-3);${fade2}}
|
|
22738
23127
|
.knobs-wt-body{min-width:0}
|
|
22739
23128
|
/* Media mounting after the first paint, and a picture still decoding, come into focus: a fade with
|
|
22740
23129
|
a small blur on the quick spring, from the top; at rest, nothing. */
|
|
@@ -22743,21 +23132,25 @@ var walkthroughCss = `
|
|
|
22743
23132
|
/* One frame for every slot that has one (a picture, a video, a code block, a compare's stage, a
|
|
22744
23133
|
slot still loading): the panel radius and a quiet fill, no ring; concentric on a card. */
|
|
22745
23134
|
.knobs-wt-slot .knobs-cmp-stage{border-radius:var(--kw-frame-r)}
|
|
22746
|
-
/* A compare is
|
|
22747
|
-
|
|
23135
|
+
/* A compare is as tall as its two pictures side by side at this width, in every mode (Wipe fuses
|
|
23136
|
+
them at one side's size, so nothing grows or re-measures), plus its mode bar, the line and gaps
|
|
22748
23137
|
(92 px), and the frame strip with its gap (158 px). */
|
|
22749
23138
|
.knobs-wt-fit{width:100%;height:calc(100cqw / 2 / var(--kw-aspect,1.7778) + var(--kw-chrome,92px))}
|
|
22750
|
-
.knobs-wt-fit[data-overlay]{height:calc(100cqw / var(--kw-aspect,1.7778) + var(--kw-chrome,92px))}
|
|
22751
23139
|
.knobs-wt-fit[data-strip]{--kw-chrome:158px}
|
|
22752
23140
|
.knobs-wt-fit[data-settled]{transition:height var(--k-wt-calm-ms,${calm.duration}ms) ${calm.easing}}
|
|
22753
23141
|
.knobs-wt-frame{position:relative;width:100%;overflow:hidden;border-radius:var(--kw-frame-r);background:var(--_k-fill);aspect-ratio:var(--kw-aspect,16/9)}
|
|
22754
23142
|
.knobs-wt-frame>:is(video,img){position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:contain;margin:0;border:0}
|
|
22755
23143
|
.knobs-wt-frame[data-natural]{aspect-ratio:auto;background:transparent}
|
|
22756
23144
|
.knobs-wt-frame[data-natural]>img{position:static;height:auto}
|
|
22757
|
-
/* Diff, code and terminal: one plain
|
|
22758
|
-
|
|
22759
|
-
|
|
22760
|
-
.knobs-wt-
|
|
23145
|
+
/* Diff, code and terminal: one plain well, drawn by its hairline alone (a fill and a ring would be
|
|
23146
|
+
two edges for one box), the panel radius and room inside, so a diff's buttons and the code under
|
|
23147
|
+
them can breathe. */
|
|
23148
|
+
.knobs-wt-slot[data-kind="diff"]>.knobs-wt-body{padding:var(--_k-pad-card);border-radius:var(--_k-radius-panel);box-shadow:inset 0 0 0 1px var(--_k-border-subtle)}
|
|
23149
|
+
/* The diff inside it: its header row 28 high on the container's padding, a hairline under it, and
|
|
23150
|
+
no line of its own under the code (the container's ring closes it). */
|
|
23151
|
+
.knobs-wt-slot[data-kind="diff"] .knobs-ui.knobs-diff:not([data-on="pane"]){--kd-head:28px;--kd-x:0px}
|
|
23152
|
+
.knobs-wt-slot[data-kind="diff"] .knobs-ui.knobs-diff:not([data-on="pane"])::after{display:none}
|
|
23153
|
+
.knobs-wt-code{margin:0;padding:var(--_k-pad-card);max-height:420px;overflow:auto;border-radius:var(--_k-radius-panel);box-shadow:inset 0 0 0 1px var(--_k-border-subtle);color:var(--_k-fg);
|
|
22761
23154
|
font:var(--_k-type-label)/var(--_k-leading-body) var(--_k-mono);white-space:pre;tab-size:2;scrollbar-width:thin}
|
|
22762
23155
|
.knobs-surface :is(.knobs-wt-code,.knobs-wt-slot[data-kind="diff"]>.knobs-wt-body){padding-inline:0;border-radius:0;background:transparent;box-shadow:inset 0 1px 0 var(--_k-border-subtle),inset 0 -1px 0 var(--_k-border-subtle)}
|
|
22763
23156
|
.knobs-wt-code[data-terminal]{white-space:pre-wrap;overflow-wrap:anywhere}
|
|
@@ -22766,17 +23159,17 @@ var walkthroughCss = `
|
|
|
22766
23159
|
.knobs-wt-out{color:var(--_k-fg-2)}
|
|
22767
23160
|
.knobs-wt-metric{display:flex;flex-direction:column;gap:var(--_k-space-sibling)}
|
|
22768
23161
|
.knobs-wt-mlabel{color:var(--_k-fg-2)}
|
|
22769
|
-
.knobs-wt-mvalue{display:flex;align-items:baseline;flex-wrap:wrap;gap:var(--_k-space-sibling);font-
|
|
23162
|
+
.knobs-wt-mvalue{display:flex;align-items:baseline;flex-wrap:wrap;gap:var(--_k-space-sibling);font-feature-settings:var(--_kr-data)}
|
|
22770
23163
|
.knobs-wt-mfrom{color:var(--_k-fg-3)}
|
|
22771
23164
|
.knobs-wt-mto{font-size:var(--_k-type-title);line-height:var(--_k-leading-title);font-weight:var(--_k-weight-label)}
|
|
22772
23165
|
.knobs-wt-mof{color:var(--_k-fg-3)}
|
|
22773
23166
|
.knobs-wt-mdelta{--kw-tone:var(--_k-fg-2);font-size:var(--_k-type-small);font-weight:var(--_k-weight-label);color:var(--kw-tone)}
|
|
22774
23167
|
.knobs-wt-mdelta[data-tone="good"]{--kw-tone:var(--kw-good)}
|
|
22775
23168
|
.knobs-wt-mdelta[data-tone="bad"]{--kw-tone:var(--_k-danger)}
|
|
22776
|
-
.knobs-wt-mtrack{position:relative;height:4px;border-radius:2px;background:
|
|
23169
|
+
.knobs-wt-mtrack{position:relative;height:4px;border-radius:2px;background:var(--_k-fill-selected)}
|
|
22777
23170
|
.knobs-wt-mtrack>span{position:absolute;top:0;bottom:0;left:0;border-radius:inherit}
|
|
22778
23171
|
.knobs-wt-mtrack>.knobs-wt-mafter{background:var(--_k-accent)}
|
|
22779
|
-
.knobs-wt-mtrack>.knobs-wt-mbefore{background:
|
|
23172
|
+
.knobs-wt-mtrack>.knobs-wt-mbefore{background:var(--_k-fg-4)}
|
|
22780
23173
|
.knobs-wt-callout{--kw-tone:var(--kw-info);display:flex;gap:var(--_k-space-sibling);max-width:var(--kw-measure);color:var(--_k-fg)}
|
|
22781
23174
|
.knobs-wt-callout::before{content:"";flex:none;width:6px;height:6px;margin-top:7px;border-radius:50%;background:var(--kw-tone)}
|
|
22782
23175
|
.knobs-wt-callout[data-tone="good"]{--kw-tone:var(--kw-good)}
|
|
@@ -22803,7 +23196,7 @@ var walkthroughCss = `
|
|
|
22803
23196
|
.knobs-wt-mark:is([data-shape="dot"],[data-shape="arrow"]) .knobs-wt-mark-label{left:12px;bottom:auto;top:10px}
|
|
22804
23197
|
.knobs-wt-mark[data-shape="arrow"] .knobs-wt-mark-label{left:auto;right:30px;top:auto;bottom:30px}
|
|
22805
23198
|
.knobs-ui .knobs-wt-anno-toggle{all:revert;box-sizing:border-box;position:absolute;top:8px;right:8px;display:grid;place-items:center;width:28px;height:28px;padding:0;border:0;margin:0;
|
|
22806
|
-
border-radius:var(--_k-radius);background:color-mix(in srgb,var(--_k-bg) 72%,transparent);color:var(--_k-fg-2);cursor:
|
|
23199
|
+
border-radius:var(--_k-radius);background:color-mix(in srgb,var(--_k-bg) 72%,transparent);color:var(--_k-fg-2);cursor:default;opacity:.6;outline:none;
|
|
22807
23200
|
transition:opacity calc(var(--_k-hover-out) * 1ms),color calc(var(--_k-hover-out) * 1ms)}
|
|
22808
23201
|
.knobs-ui .knobs-wt-anno-toggle:is(:hover,:focus-visible){opacity:1;color:var(--_k-fg);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
22809
23202
|
.knobs-ui .knobs-wt-anno-toggle:focus-visible{box-shadow:inset 0 0 0 1px var(--_k-focus)}
|
|
@@ -22824,7 +23217,7 @@ var walkthroughCss = `
|
|
|
22824
23217
|
.knobs-wt-srow{display:grid;grid-template-columns:auto minmax(0,1fr) auto;column-gap:10px;align-items:start;margin:0 -8px;padding:var(--kw-spt) 8px var(--kw-spb);
|
|
22825
23218
|
border-radius:max(0px,calc(var(--_k-radius-panel) - 8px));transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
22826
23219
|
.knobs-wt-srow[data-trunk]{--kw-spb:0px;grid-template-columns:auto minmax(0,1fr)}
|
|
22827
|
-
.knobs-wt-srow[data-go]{cursor:
|
|
23220
|
+
.knobs-wt-srow[data-go]{cursor:default}
|
|
22828
23221
|
.knobs-wt-srow[data-go]:hover{background:var(--_ku-wash);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
22829
23222
|
.knobs-wt-lanes{display:flex;align-self:stretch;margin-block:calc(var(--kw-spt) * -1) calc(var(--kw-spb) * -1)}
|
|
22830
23223
|
.knobs-wt-lane{position:relative;flex:none;width:16px}
|
|
@@ -22840,9 +23233,9 @@ var walkthroughCss = `
|
|
|
22840
23233
|
.knobs-ui .knobs-wt-spr{font:var(--_k-weight-label) var(--_k-type-label)/var(--kw-line) var(--_k-mono);color:var(--_k-fg-2);text-decoration:none;white-space:nowrap}
|
|
22841
23234
|
.knobs-ui a.knobs-wt-spr:is(:hover,:focus-visible){color:var(--_k-fg);text-decoration:underline}
|
|
22842
23235
|
.knobs-ui .knobs-wt-stitle{font-weight:var(--_k-weight-label);line-height:var(--kw-line);color:var(--_k-fg);text-align:left}
|
|
22843
|
-
.knobs-ui button.knobs-wt-stitle{cursor:
|
|
23236
|
+
.knobs-ui button.knobs-wt-stitle{cursor:default;text-decoration:underline;text-decoration-color:transparent;text-underline-offset:3px;transition:text-decoration-color calc(var(--_k-hover-out) * 1ms)}
|
|
22844
23237
|
.knobs-ui :is(.knobs-wt-srow[data-go]:hover button.knobs-wt-stitle,button.knobs-wt-stitle:focus-visible){text-decoration-color:color-mix(in oklch,currentColor 45%,transparent);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
22845
|
-
.knobs-ui .knobs-wt-ssummary{margin:0;max-width:var(--
|
|
23238
|
+
.knobs-ui .knobs-wt-ssummary{margin:0;max-width:var(--kw-measure);color:var(--_k-fg-2)}
|
|
22846
23239
|
.knobs-wt-smeta{display:flex;flex-wrap:wrap;align-items:baseline;gap:0 12px;font:var(--_k-weight) var(--_k-type-small)/var(--kw-line) var(--_k-mono);font-variant-numeric:tabular-nums;color:var(--_k-fg-3)}
|
|
22847
23240
|
.knobs-wt-delta{display:inline-flex;gap:6px}
|
|
22848
23241
|
.knobs-wt-add{color:var(--_k-diff-add)}
|
|
@@ -22872,7 +23265,7 @@ var walkthroughCss = `
|
|
|
22872
23265
|
.knobs-wt-tablebox{min-width:0}
|
|
22873
23266
|
/* A row with a step goes there: the whole row, a wash under the pointer, no arrow, so rows with and
|
|
22874
23267
|
without one line up. */
|
|
22875
|
-
.knobs-wt-tablebox [data-go]{cursor:
|
|
23268
|
+
.knobs-wt-tablebox [data-go]{cursor:default;outline:none}
|
|
22876
23269
|
.knobs-wt-tablebox tr[data-go]>td,.knobs-wt-trow[data-go]{transition:background calc(var(--_k-hover-out) * 1ms)}
|
|
22877
23270
|
.knobs-wt-tablebox tr[data-go]:is(:hover,:focus-visible)>td,.knobs-wt-trow[data-go]:is(:hover,:focus-visible){background:var(--_ku-wash);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
22878
23271
|
.knobs-wt-tablebox [data-go]:focus-visible{box-shadow:inset 0 0 0 1px var(--_k-focus)}
|
|
@@ -22928,13 +23321,18 @@ var walkthroughCss = `
|
|
|
22928
23321
|
.knobs-wt-body:has(>.knobs-wt-chapters){display:flex;flex-direction:column;gap:var(--_k-space-title)}
|
|
22929
23322
|
.knobs-wt-chapters{position:relative;display:flex;flex-direction:column;margin:0 calc(var(--_k-space-sibling) * -1)}
|
|
22930
23323
|
.knobs-ui .knobs-wt-chapter{position:relative;display:grid;grid-template-columns:2ch minmax(0,1fr) auto;column-gap:var(--_k-space-sibling);align-items:center;height:32px;padding:0 var(--_k-space-sibling);
|
|
22931
|
-
border-radius:var(--_k-radius);color:var(--_k-fg-2);text-align:left;white-space:nowrap;cursor:
|
|
22932
|
-
.knobs-ui .knobs-wt-chapter:is(:hover,:focus-visible){color:var(--_k-fg);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
23324
|
+
border-radius:var(--_k-radius);color:var(--_k-fg-2);text-align:left;white-space:nowrap;cursor:default;transition:color calc(var(--_k-hover-out) * 1ms),background calc(var(--_k-hover-out) * 1ms)}
|
|
23325
|
+
.knobs-ui .knobs-wt-chapter:is(:hover,:focus-visible){color:var(--_k-fg);background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
22933
23326
|
.knobs-ui .knobs-wt-chapter:focus-visible{box-shadow:inset 0 0 0 1px var(--_k-focus)}
|
|
22934
23327
|
.knobs-wt-chapter-n{font-size:var(--_k-type-small);color:var(--_k-fg-3)}
|
|
22935
23328
|
.knobs-wt-chapter-label{min-width:0;overflow:hidden;${fade2}}
|
|
22936
23329
|
.knobs-wt-chapter-time{font:var(--_k-weight) var(--_k-type-small)/1 var(--_k-mono);color:var(--_k-fg-3)}
|
|
22937
23330
|
.knobs-pick-copy :is(.knobs-wt-chapter-n,.knobs-wt-chapter-time){color:var(--_k-fg-2)}
|
|
23331
|
+
/* Every hover in the walkthrough lands at once (hover-in, 0 ms) and eases out (hover-out): links,
|
|
23332
|
+
buttons, chips, rail, chapter, table and stack rows (its own; the pieces inside keep theirs). */
|
|
23333
|
+
:is(.knobs-walkthrough,.knobs-wt-slot) :is(a,button,[data-go])[class*="knobs-wt-"]:is(:hover,:focus-visible),
|
|
23334
|
+
.knobs-walkthrough a:not([class]):hover,
|
|
23335
|
+
:is(.knobs-walkthrough,.knobs-wt-slot) :is(.knobs-wt-srow,tr)[data-go]:is(:hover,:focus-visible) :is(td,.knobs-wt-stitle){transition-duration:calc(var(--_k-hover-in) * 1ms)}
|
|
22938
23336
|
@media(prefers-reduced-motion:reduce){:is(.knobs-walkthrough,.knobs-wt-slot) :where(*,::before,::after){transition-duration:.15s!important;transition-property:opacity,background,color!important}}
|
|
22939
23337
|
@media(prefers-reduced-motion:reduce){.knobs-wt-disc-content{transition:opacity .15s}}
|
|
22940
23338
|
`;
|
|
@@ -23035,7 +23433,6 @@ async function mountCompare(host, m, look, alive, onEvent) {
|
|
|
23035
23433
|
fit.style.setProperty("--kw-aspect", String(known ?? DEFAULT_ASPECT));
|
|
23036
23434
|
const width = host.getBoundingClientRect().width;
|
|
23037
23435
|
const mode = m.mode ?? (width && width < 560 ? "wipe" : "side");
|
|
23038
|
-
fit.toggleAttribute("data-overlay", mode !== "side");
|
|
23039
23436
|
host.append(fit);
|
|
23040
23437
|
const [aspect, lib] = await Promise.all([
|
|
23041
23438
|
known ? Promise.resolve(known) : probeAspect(doc, after.src),
|
|
@@ -23054,12 +23451,11 @@ async function mountCompare(host, m, look, alive, onEvent) {
|
|
|
23054
23451
|
before: side(before, "Before"),
|
|
23055
23452
|
after: side(after, "After"),
|
|
23056
23453
|
mode,
|
|
23057
|
-
timeline:
|
|
23454
|
+
timeline: mediaKind(before.src) === "video" || mediaKind(after.src) === "video",
|
|
23058
23455
|
lazy: false,
|
|
23059
23456
|
...aspect ? { aspect } : {},
|
|
23060
23457
|
...m.strip ? { strip: true } : {},
|
|
23061
23458
|
onMode: (next) => {
|
|
23062
|
-
fit.toggleAttribute("data-overlay", next !== "side");
|
|
23063
23459
|
onEvent?.({ what: "mode", detail: next });
|
|
23064
23460
|
const layer = marks?.element;
|
|
23065
23461
|
if (layer) {
|
|
@@ -23083,6 +23479,12 @@ async function mountCompare(host, m, look, alive, onEvent) {
|
|
|
23083
23479
|
}
|
|
23084
23480
|
});
|
|
23085
23481
|
const stage = fit.querySelector(".knobs-cmp-stage");
|
|
23482
|
+
if (stage)
|
|
23483
|
+
doc.defaultView?.requestAnimationFrame(() => {
|
|
23484
|
+
const chrome = fit.clientHeight - stage.clientHeight;
|
|
23485
|
+
if (alive() && stage.clientHeight > 0 && chrome > 0)
|
|
23486
|
+
fit.style.setProperty("--kw-chrome", `${Math.round(chrome)}px`);
|
|
23487
|
+
});
|
|
23086
23488
|
if (m.annotations?.length && stage) {
|
|
23087
23489
|
const shape = { w: aspect ?? DEFAULT_ASPECT, h: 1 };
|
|
23088
23490
|
marks = annotationLayer(stage, m.annotations, () => {
|
|
@@ -23158,45 +23560,44 @@ async function mountCompare(host, m, look, alive, onEvent) {
|
|
|
23158
23560
|
var round2 = (v) => Math.round(v * 100) / 100;
|
|
23159
23561
|
var MARK_GLIDE = 450;
|
|
23160
23562
|
var zoomedIn = (z) => z.w < 0.999 || z.h < 0.999;
|
|
23161
|
-
function mountVideo(host, m, onEvent) {
|
|
23563
|
+
async function mountVideo(host, m, look, alive, onEvent) {
|
|
23162
23564
|
const doc = host.ownerDocument;
|
|
23163
|
-
|
|
23565
|
+
await Promise.resolve().then(() => init_player());
|
|
23566
|
+
if (!alive())
|
|
23567
|
+
return { dispose() {} };
|
|
23164
23568
|
const aspect = parseAspect(m.aspect);
|
|
23165
|
-
|
|
23166
|
-
|
|
23167
|
-
const
|
|
23168
|
-
|
|
23169
|
-
|
|
23170
|
-
|
|
23171
|
-
|
|
23172
|
-
|
|
23173
|
-
|
|
23174
|
-
|
|
23175
|
-
|
|
23176
|
-
|
|
23177
|
-
|
|
23178
|
-
|
|
23179
|
-
|
|
23180
|
-
|
|
23181
|
-
|
|
23182
|
-
|
|
23183
|
-
|
|
23184
|
-
|
|
23185
|
-
|
|
23186
|
-
|
|
23187
|
-
|
|
23188
|
-
|
|
23189
|
-
|
|
23190
|
-
if (v.paused)
|
|
23191
|
-
onEvent?.({ what: "seek", time: round2(v.currentTime) });
|
|
23569
|
+
let pills = null;
|
|
23570
|
+
let marking = null;
|
|
23571
|
+
const p = player(host, {
|
|
23572
|
+
...look,
|
|
23573
|
+
src: m.src,
|
|
23574
|
+
...m.poster ? { poster: m.poster } : {},
|
|
23575
|
+
...m.captions ? { captions: m.captions } : {},
|
|
23576
|
+
...aspect ? { aspect } : {},
|
|
23577
|
+
...m.label ? { label: m.label } : {},
|
|
23578
|
+
...m.chapters?.length ? {
|
|
23579
|
+
chapters: m.chapters.map((c) => ({
|
|
23580
|
+
label: c.label,
|
|
23581
|
+
start: c.start,
|
|
23582
|
+
...c.id ? { id: c.id } : {}
|
|
23583
|
+
}))
|
|
23584
|
+
} : {},
|
|
23585
|
+
onPlay: (on, time) => {
|
|
23586
|
+
marking?.kick();
|
|
23587
|
+
onEvent?.({ what: on ? "play" : "pause", time: round2(time) });
|
|
23588
|
+
},
|
|
23589
|
+
onSeek: (time) => {
|
|
23590
|
+
pills?.sync();
|
|
23591
|
+
marking?.kick();
|
|
23592
|
+
onEvent?.({ what: "seek", time: round2(time) });
|
|
23593
|
+
}
|
|
23192
23594
|
});
|
|
23193
|
-
|
|
23194
|
-
host.
|
|
23195
|
-
|
|
23196
|
-
now: () => v.currentTime,
|
|
23595
|
+
const v = p.video;
|
|
23596
|
+
pills = m.chapters?.length ? chapterPills(host, m.chapters, {
|
|
23597
|
+
now: () => p.time,
|
|
23197
23598
|
seek: (t) => {
|
|
23198
|
-
|
|
23199
|
-
|
|
23599
|
+
p.seek(t, { glide: true });
|
|
23600
|
+
p.play();
|
|
23200
23601
|
},
|
|
23201
23602
|
onEvent
|
|
23202
23603
|
}) : null;
|
|
@@ -23204,36 +23605,33 @@ function mountVideo(host, m, onEvent) {
|
|
|
23204
23605
|
if (pills)
|
|
23205
23606
|
for (const type of ["timeupdate", "seeking", "seeked"])
|
|
23206
23607
|
v.addEventListener(type, sync);
|
|
23608
|
+
const frame = p.element.querySelector(".knobs-player-frame") ?? p.element;
|
|
23207
23609
|
const marks = m.annotations?.length ? annotationLayer(frame, m.annotations, () => ({
|
|
23208
23610
|
rects: [
|
|
23209
23611
|
contain({ w: frame.clientWidth, h: frame.clientHeight }, { w: v.videoWidth, h: v.videoHeight })
|
|
23210
23612
|
],
|
|
23211
|
-
time:
|
|
23613
|
+
time: p.time
|
|
23212
23614
|
})) : null;
|
|
23213
|
-
|
|
23214
|
-
|
|
23215
|
-
for (const type of ["
|
|
23216
|
-
v.addEventListener(type, () => marking
|
|
23615
|
+
if (marks) {
|
|
23616
|
+
marking = follow(doc.defaultView, () => p.playing, () => marks.update());
|
|
23617
|
+
for (const type of ["seeked", "loadedmetadata", "timeupdate"])
|
|
23618
|
+
v.addEventListener(type, () => marking?.kick());
|
|
23619
|
+
}
|
|
23217
23620
|
return {
|
|
23218
|
-
pause: () =>
|
|
23219
|
-
seekBy: (d) =>
|
|
23220
|
-
v.currentTime = Math.max(0, Math.min(v.duration || Infinity, v.currentTime + d));
|
|
23221
|
-
},
|
|
23621
|
+
pause: () => p.pause(),
|
|
23622
|
+
seekBy: (d) => p.seekBy(d),
|
|
23222
23623
|
context: () => ({
|
|
23223
23624
|
kind: "video",
|
|
23224
|
-
time: round2(
|
|
23225
|
-
...
|
|
23226
|
-
playing:
|
|
23625
|
+
time: round2(p.time),
|
|
23626
|
+
...p.duration ? { duration: round2(p.duration) } : {},
|
|
23627
|
+
playing: p.playing,
|
|
23227
23628
|
...pills?.current ? { chapter: pills.current.label } : {}
|
|
23228
23629
|
}),
|
|
23229
23630
|
dispose: () => {
|
|
23230
23631
|
marking?.stop();
|
|
23231
23632
|
marks?.dispose();
|
|
23232
23633
|
pills?.dispose();
|
|
23233
|
-
|
|
23234
|
-
v.removeAttribute("src");
|
|
23235
|
-
v.load();
|
|
23236
|
-
frame.remove();
|
|
23634
|
+
p.dispose();
|
|
23237
23635
|
}
|
|
23238
23636
|
};
|
|
23239
23637
|
}
|
|
@@ -23416,12 +23814,39 @@ function mountProse(host, m) {
|
|
|
23416
23814
|
host.append(el);
|
|
23417
23815
|
return { dispose: () => el.remove() };
|
|
23418
23816
|
}
|
|
23817
|
+
function mountFacts(host, m) {
|
|
23818
|
+
const box = renderFacts(host.ownerDocument, m.groups);
|
|
23819
|
+
host.append(box);
|
|
23820
|
+
return { dispose: () => box.remove() };
|
|
23821
|
+
}
|
|
23822
|
+
function mountDecision(host, m, slot) {
|
|
23823
|
+
const root = div(host.ownerDocument, "knobs-wt-options");
|
|
23824
|
+
const slots = [];
|
|
23825
|
+
const tiles = m.options.map((o) => optionTile(host.ownerDocument, o, {
|
|
23826
|
+
media: (tile) => {
|
|
23827
|
+
if (o.media)
|
|
23828
|
+
slots.push(slot(tile, o.media));
|
|
23829
|
+
}
|
|
23830
|
+
}).tile);
|
|
23831
|
+
root.append(...tiles);
|
|
23832
|
+
host.append(root);
|
|
23833
|
+
const unlayout = layoutOptions(root, tiles);
|
|
23834
|
+
return {
|
|
23835
|
+
pause: () => slots.forEach((s) => s.pause()),
|
|
23836
|
+
dispose: () => {
|
|
23837
|
+
unlayout();
|
|
23838
|
+
slots.forEach((s) => s.dispose());
|
|
23839
|
+
root.remove();
|
|
23840
|
+
}
|
|
23841
|
+
};
|
|
23842
|
+
}
|
|
23419
23843
|
var HEAVY = new Set(["compare", "video", "diff", "mount"]);
|
|
23420
23844
|
var RELEASES = new Set(["compare", "video"]);
|
|
23421
|
-
var labelOf3 = (m) => ("label" in m) && m.kind !== "metric" ? m.label : undefined;
|
|
23422
|
-
function mediaSlot(container,
|
|
23845
|
+
var labelOf3 = (m) => m.kind === "facts" ? m.title : ("label" in m) && m.kind !== "metric" ? m.label : undefined;
|
|
23846
|
+
function mediaSlot(container, given) {
|
|
23423
23847
|
const doc = container.ownerDocument;
|
|
23424
23848
|
injectWalkthroughStyles(doc);
|
|
23849
|
+
const options = reviewLook(given, container);
|
|
23425
23850
|
const look = {
|
|
23426
23851
|
...options.preset ? { preset: options.preset } : {},
|
|
23427
23852
|
...options.theme ? { theme: options.theme } : {}
|
|
@@ -23431,7 +23856,7 @@ function mediaSlot(container, options) {
|
|
|
23431
23856
|
root.dataset.kind = m.kind;
|
|
23432
23857
|
applyLook2(root, options);
|
|
23433
23858
|
const label = labelOf3(m);
|
|
23434
|
-
if (label && (m.kind === "video" || m.kind === "image" || m.kind === "code" || m.kind === "terminal")) {
|
|
23859
|
+
if (label && (m.kind === "video" || m.kind === "image" || m.kind === "code" || m.kind === "terminal" || m.kind === "facts")) {
|
|
23435
23860
|
const l = doc.createElement("span");
|
|
23436
23861
|
l.className = "knobs-wt-slot-label";
|
|
23437
23862
|
l.textContent = label;
|
|
@@ -23494,7 +23919,7 @@ function mediaSlot(container, options) {
|
|
|
23494
23919
|
case "diff":
|
|
23495
23920
|
return void mountDiff(host, m, look, alive, options.onEvent).then(done, fail("diff"));
|
|
23496
23921
|
case "video":
|
|
23497
|
-
return
|
|
23922
|
+
return void mountVideo(host, m, look, alive, options.onEvent).then(done, fail("video"));
|
|
23498
23923
|
case "image":
|
|
23499
23924
|
return done(mountImage(host, m));
|
|
23500
23925
|
case "code":
|
|
@@ -23511,6 +23936,16 @@ function mediaSlot(container, options) {
|
|
|
23511
23936
|
return done(mountStack(host, m, options.steps, options.findPR));
|
|
23512
23937
|
case "table":
|
|
23513
23938
|
return done(mountTable(host, m, options.steps));
|
|
23939
|
+
case "facts":
|
|
23940
|
+
return done(mountFacts(host, m));
|
|
23941
|
+
case "decision":
|
|
23942
|
+
return done(mountDecision(host, m, (tile, media) => mediaSlot(tile, {
|
|
23943
|
+
...look,
|
|
23944
|
+
media,
|
|
23945
|
+
...options.lazy === false ? { lazy: false } : {},
|
|
23946
|
+
...options.steps ? { steps: options.steps } : {},
|
|
23947
|
+
...options.onEvent ? { onEvent: options.onEvent } : {}
|
|
23948
|
+
})));
|
|
23514
23949
|
case "mount": {
|
|
23515
23950
|
const cleanup = m.mount(host);
|
|
23516
23951
|
return done({ dispose: () => cleanup ? cleanup() : host.textContent = "" });
|
|
@@ -23563,16 +23998,35 @@ function mediaSlot(container, options) {
|
|
|
23563
23998
|
};
|
|
23564
23999
|
}
|
|
23565
24000
|
var CHECK4 = icon("check", { small: true });
|
|
24001
|
+
function facts(container, options) {
|
|
24002
|
+
const { title, facts: list, groups, ...look } = options;
|
|
24003
|
+
return mediaSlot(container, {
|
|
24004
|
+
...look,
|
|
24005
|
+
media: {
|
|
24006
|
+
kind: "facts",
|
|
24007
|
+
...title ? { title } : {},
|
|
24008
|
+
...list ? { facts: list } : {},
|
|
24009
|
+
...groups ? { groups } : {}
|
|
24010
|
+
}
|
|
24011
|
+
});
|
|
24012
|
+
}
|
|
24013
|
+
function decision(container, options) {
|
|
24014
|
+
const { options: list, noun, ...rest } = options;
|
|
24015
|
+
return mediaSlot(container, {
|
|
24016
|
+
...rest,
|
|
24017
|
+
media: { kind: "decision", options: list, ...noun ? { noun } : {} }
|
|
24018
|
+
});
|
|
24019
|
+
}
|
|
23566
24020
|
|
|
23567
24021
|
// src/ui/walkthrough.ts
|
|
23568
|
-
var
|
|
24022
|
+
var el4 = (doc, tag, cls) => {
|
|
23569
24023
|
const n = doc.createElement(tag);
|
|
23570
24024
|
if (cls)
|
|
23571
24025
|
n.className = cls;
|
|
23572
24026
|
return n;
|
|
23573
24027
|
};
|
|
23574
24028
|
var prose2 = (doc, tag, cls, text) => {
|
|
23575
|
-
const n =
|
|
24029
|
+
const n = el4(doc, tag, cls);
|
|
23576
24030
|
n.innerHTML = inlineMarkdown(text);
|
|
23577
24031
|
return n;
|
|
23578
24032
|
};
|
|
@@ -23597,9 +24051,10 @@ var DOCK_GAP = 12;
|
|
|
23597
24051
|
var CALM2 = springMotion(SPRINGS.calm);
|
|
23598
24052
|
var SMOOTH = springMotion(SPRINGS.smooth);
|
|
23599
24053
|
var BACK_MS = 4500;
|
|
23600
|
-
function tasteTest(container,
|
|
24054
|
+
function tasteTest(container, given) {
|
|
23601
24055
|
const doc = container.ownerDocument;
|
|
23602
24056
|
injectWalkthroughStyles(doc);
|
|
24057
|
+
const options = reviewLook(given, container);
|
|
23603
24058
|
const look = lookOf2(options);
|
|
23604
24059
|
const list = options.options.map((o, i) => ("letter" in o) ? o : {
|
|
23605
24060
|
id: o.id ?? String.fromCharCode(97 + i),
|
|
@@ -23607,66 +24062,55 @@ function tasteTest(container, options) {
|
|
|
23607
24062
|
letter: String.fromCharCode(65 + i),
|
|
23608
24063
|
...o.caption ? { caption: o.caption } : {},
|
|
23609
24064
|
...o.media !== undefined ? { media: fillMedia(o.media) } : {},
|
|
23610
|
-
|
|
24065
|
+
...o.facts ? { facts: fillFacts(o.facts) } : {},
|
|
24066
|
+
suggested: o.suggested === true || o.recommended === true
|
|
23611
24067
|
});
|
|
23612
24068
|
const pickable = options.pickable !== false;
|
|
23613
24069
|
let picked = pickable ? options.picked ?? null : null;
|
|
23614
|
-
const root =
|
|
24070
|
+
const root = el4(doc, "div", "knobs-wt-options");
|
|
23615
24071
|
if (pickable) {
|
|
23616
24072
|
root.setAttribute("role", "radiogroup");
|
|
23617
24073
|
root.setAttribute("aria-label", "Options");
|
|
23618
24074
|
} else
|
|
23619
24075
|
root.dataset.static = "";
|
|
23620
|
-
root.style.setProperty("--kw-n", String(Math.min(list.length, 3)));
|
|
23621
24076
|
if (!container.closest(".knobs-ui"))
|
|
23622
24077
|
applyLook2(root, options);
|
|
23623
24078
|
const slots = [];
|
|
23624
24079
|
const tiles = list.map((o, i) => {
|
|
23625
|
-
const
|
|
23626
|
-
|
|
23627
|
-
|
|
23628
|
-
|
|
23629
|
-
|
|
23630
|
-
|
|
23631
|
-
|
|
23632
|
-
|
|
23633
|
-
|
|
23634
|
-
|
|
23635
|
-
|
|
23636
|
-
|
|
23637
|
-
|
|
23638
|
-
|
|
23639
|
-
|
|
23640
|
-
|
|
23641
|
-
|
|
23642
|
-
|
|
23643
|
-
s.textContent = "Suggested";
|
|
23644
|
-
pick.append(s);
|
|
23645
|
-
}
|
|
23646
|
-
if (i < 9) {
|
|
23647
|
-
const key = el3(doc, "span", "knobs-wt-key");
|
|
23648
|
-
key.textContent = String(i + 1);
|
|
23649
|
-
pick.append(key);
|
|
23650
|
-
}
|
|
23651
|
-
const check = el3(doc, "span", "knobs-wt-check");
|
|
23652
|
-
check.innerHTML = CHECK4;
|
|
23653
|
-
pick.append(check);
|
|
23654
|
-
pick.addEventListener("click", () => {
|
|
23655
|
-
const next = picked === o.id ? null : o.id;
|
|
23656
|
-
api.pick(next);
|
|
23657
|
-
options.onPick?.(next);
|
|
24080
|
+
const button = pickable ? el4(doc, "button", "knobs-wt-pick") : undefined;
|
|
24081
|
+
const { tile, kicker } = optionTile(doc, {
|
|
24082
|
+
number: `Option ${i + 1}`,
|
|
24083
|
+
title: o.label,
|
|
24084
|
+
...o.caption ? { summary: o.caption } : {},
|
|
24085
|
+
recommended: o.suggested,
|
|
24086
|
+
...o.facts ? { facts: o.facts } : {}
|
|
24087
|
+
}, {
|
|
24088
|
+
...button ? { head: button } : {},
|
|
24089
|
+
media: (t) => {
|
|
24090
|
+
if (o.media)
|
|
24091
|
+
slots.push(mediaSlot(t, {
|
|
24092
|
+
...look,
|
|
24093
|
+
media: o.media,
|
|
24094
|
+
...options.lazy === false ? { lazy: false } : {},
|
|
24095
|
+
...options.steps ? { steps: options.steps } : {}
|
|
24096
|
+
}));
|
|
24097
|
+
}
|
|
23658
24098
|
});
|
|
23659
|
-
|
|
23660
|
-
|
|
23661
|
-
|
|
23662
|
-
|
|
23663
|
-
|
|
23664
|
-
|
|
23665
|
-
|
|
23666
|
-
|
|
23667
|
-
|
|
23668
|
-
|
|
23669
|
-
|
|
24099
|
+
const pick = button ?? el4(doc, "button");
|
|
24100
|
+
if (button) {
|
|
24101
|
+
button.type = "button";
|
|
24102
|
+
button.setAttribute("role", "radio");
|
|
24103
|
+
if (i < 9)
|
|
24104
|
+
button.setAttribute("aria-keyshortcuts", String(i + 1));
|
|
24105
|
+
const check = el4(doc, "span", "knobs-wt-check");
|
|
24106
|
+
check.innerHTML = CHECK4;
|
|
24107
|
+
kicker.append(check);
|
|
24108
|
+
button.addEventListener("click", () => {
|
|
24109
|
+
const next = picked === o.id ? null : o.id;
|
|
24110
|
+
api.pick(next);
|
|
24111
|
+
options.onPick?.(next);
|
|
24112
|
+
});
|
|
24113
|
+
}
|
|
23670
24114
|
root.append(tile);
|
|
23671
24115
|
return { tile, pick };
|
|
23672
24116
|
});
|
|
@@ -23680,6 +24124,7 @@ function tasteTest(container, options) {
|
|
|
23680
24124
|
};
|
|
23681
24125
|
sync();
|
|
23682
24126
|
container.append(root);
|
|
24127
|
+
const unlayout = layoutOptions(root, tiles.map((t) => t.tile));
|
|
23683
24128
|
const api = {
|
|
23684
24129
|
element: root,
|
|
23685
24130
|
get picked() {
|
|
@@ -23692,6 +24137,7 @@ function tasteTest(container, options) {
|
|
|
23692
24137
|
},
|
|
23693
24138
|
pause: () => slots.forEach((s) => s.pause()),
|
|
23694
24139
|
dispose() {
|
|
24140
|
+
unlayout();
|
|
23695
24141
|
slots.forEach((s) => s.dispose());
|
|
23696
24142
|
root.remove();
|
|
23697
24143
|
}
|
|
@@ -23708,13 +24154,14 @@ function scrollerOf(el) {
|
|
|
23708
24154
|
}
|
|
23709
24155
|
return doc.scrollingElement ?? doc.documentElement;
|
|
23710
24156
|
}
|
|
23711
|
-
function walkthrough(container,
|
|
24157
|
+
function walkthrough(container, given) {
|
|
23712
24158
|
const doc = container.ownerDocument;
|
|
23713
24159
|
const win = doc.defaultView;
|
|
23714
24160
|
injectWalkthroughStyles(doc);
|
|
24161
|
+
const options = reviewLook(given, container);
|
|
23715
24162
|
const look = lookOf2(options);
|
|
23716
24163
|
const storage = options.storage === undefined ? browserStorage() : options.storage;
|
|
23717
|
-
const root =
|
|
24164
|
+
const root = el4(doc, "div", "knobs-walkthrough");
|
|
23718
24165
|
applyLook2(root, options);
|
|
23719
24166
|
container.append(root);
|
|
23720
24167
|
let page = normalizeWalkthrough(options.doc);
|
|
@@ -23927,7 +24374,7 @@ function walkthrough(container, options) {
|
|
|
23927
24374
|
return true;
|
|
23928
24375
|
return false;
|
|
23929
24376
|
};
|
|
23930
|
-
const scrim =
|
|
24377
|
+
const scrim = el4(doc, "div", "knobs-wt-scrim");
|
|
23931
24378
|
scrim.addEventListener("click", () => setFull(false));
|
|
23932
24379
|
const fullRect = () => ({
|
|
23933
24380
|
x: DOCK_INSET,
|
|
@@ -23977,7 +24424,7 @@ function walkthrough(container, options) {
|
|
|
23977
24424
|
}
|
|
23978
24425
|
if (!full) {
|
|
23979
24426
|
const r = v.card.getBoundingClientRect();
|
|
23980
|
-
const hold =
|
|
24427
|
+
const hold = el4(doc, "div", "knobs-wt-hold-card");
|
|
23981
24428
|
hold.style.height = `${r.height}px`;
|
|
23982
24429
|
v.card.before(hold);
|
|
23983
24430
|
v.card.dataset.full = "";
|
|
@@ -24127,7 +24574,7 @@ function walkthrough(container, options) {
|
|
|
24127
24574
|
toast("Couldn't reach the microphone", { tone: "warn", look, doc });
|
|
24128
24575
|
}
|
|
24129
24576
|
};
|
|
24130
|
-
const backPill =
|
|
24577
|
+
const backPill = el4(doc, "button", "knobs-wt-back");
|
|
24131
24578
|
backPill.type = "button";
|
|
24132
24579
|
let backTo = null;
|
|
24133
24580
|
let backTimer = 0;
|
|
@@ -24147,7 +24594,7 @@ function walkthrough(container, options) {
|
|
|
24147
24594
|
return;
|
|
24148
24595
|
backTo = key;
|
|
24149
24596
|
backPill.innerHTML = ICON.back;
|
|
24150
|
-
const words =
|
|
24597
|
+
const words = el4(doc, "span", "knobs-wt-back-label");
|
|
24151
24598
|
words.textContent = `Back to ${plainMarkdown(v.step.title)}`;
|
|
24152
24599
|
backPill.append(words);
|
|
24153
24600
|
backPill.dataset.on = "";
|
|
@@ -24155,16 +24602,16 @@ function walkthrough(container, options) {
|
|
|
24155
24602
|
backTimer = win.setTimeout(hideBack, BACK_MS);
|
|
24156
24603
|
};
|
|
24157
24604
|
const bar = (() => {
|
|
24158
|
-
const dock =
|
|
24159
|
-
const box =
|
|
24160
|
-
const on =
|
|
24161
|
-
const row =
|
|
24162
|
-
const input =
|
|
24605
|
+
const dock = el4(doc, "div", "knobs-wt-dock");
|
|
24606
|
+
const box = el4(doc, "div", "knobs-wt-notebar");
|
|
24607
|
+
const on = el4(doc, "div", "knobs-wt-on");
|
|
24608
|
+
const row = el4(doc, "div", "knobs-wt-row");
|
|
24609
|
+
const input = el4(doc, "textarea", "knobs-wt-input");
|
|
24163
24610
|
input.rows = 1;
|
|
24164
24611
|
input.setAttribute("aria-label", "Note");
|
|
24165
|
-
const attach =
|
|
24612
|
+
const attach = el4(doc, "div", "knobs-wt-attach");
|
|
24166
24613
|
const btn = (icon, label, run) => {
|
|
24167
|
-
const b =
|
|
24614
|
+
const b = el4(doc, "button", "knobs-wt-tool");
|
|
24168
24615
|
b.type = "button";
|
|
24169
24616
|
b.innerHTML = icon;
|
|
24170
24617
|
b.setAttribute("aria-label", label);
|
|
@@ -24175,17 +24622,17 @@ function walkthrough(container, options) {
|
|
|
24175
24622
|
const fullBtn = btn(ICON.full, "Full window · f", () => setFull(!full));
|
|
24176
24623
|
const penBtn = btn(ICON.pen, "Draw on the media", () => setInk(!ink.on));
|
|
24177
24624
|
const micBtn = btn(ICON.mic, "Record a voice note", () => void toggleVoice());
|
|
24178
|
-
const micTime =
|
|
24625
|
+
const micTime = el4(doc, "span", "knobs-wt-rec");
|
|
24179
24626
|
micBtn.append(micTime);
|
|
24180
24627
|
const sendBtn = btn(ICON.send, "Send · Enter", () => send());
|
|
24181
24628
|
sendBtn.dataset.send = "";
|
|
24182
24629
|
row.append(input, attach, fullBtn, penBtn, micBtn, sendBtn);
|
|
24183
24630
|
box.append(on, row);
|
|
24184
|
-
const launch =
|
|
24631
|
+
const launch = el4(doc, "button", "knobs-wt-launch");
|
|
24185
24632
|
launch.type = "button";
|
|
24186
24633
|
launch.innerHTML = ICON.pen;
|
|
24187
24634
|
launch.append("Note");
|
|
24188
|
-
const kbd =
|
|
24635
|
+
const kbd = el4(doc, "kbd");
|
|
24189
24636
|
kbd.textContent = "n";
|
|
24190
24637
|
launch.append(kbd);
|
|
24191
24638
|
launch.setAttribute("aria-label", "Write a note (n)");
|
|
@@ -24237,9 +24684,9 @@ function walkthrough(container, options) {
|
|
|
24237
24684
|
}
|
|
24238
24685
|
});
|
|
24239
24686
|
const chip = (text, clear) => {
|
|
24240
|
-
const c =
|
|
24687
|
+
const c = el4(doc, "span", "knobs-wt-chip-a");
|
|
24241
24688
|
c.append(text);
|
|
24242
|
-
const x =
|
|
24689
|
+
const x = el4(doc, "button", "knobs-wt-x");
|
|
24243
24690
|
x.type = "button";
|
|
24244
24691
|
x.innerHTML = ICON.close;
|
|
24245
24692
|
x.setAttribute("aria-label", `Remove ${text}`);
|
|
@@ -24388,9 +24835,9 @@ function walkthrough(container, options) {
|
|
|
24388
24835
|
}
|
|
24389
24836
|
};
|
|
24390
24837
|
const renderNote = (v, n, entering = false) => {
|
|
24391
|
-
const row =
|
|
24838
|
+
const row = el4(doc, "div", "knobs-wt-n");
|
|
24392
24839
|
row.dataset.id = n.id;
|
|
24393
|
-
const meta =
|
|
24840
|
+
const meta = el4(doc, "span", "knobs-wt-n-meta");
|
|
24394
24841
|
const m = n.context.media;
|
|
24395
24842
|
meta.textContent = m?.time !== undefined ? formatTime(m.time) : m?.file ? m.file.split("/").pop() : "·";
|
|
24396
24843
|
if (m?.time !== undefined) {
|
|
@@ -24406,11 +24853,11 @@ function walkthrough(container, options) {
|
|
|
24406
24853
|
});
|
|
24407
24854
|
}
|
|
24408
24855
|
row.append(meta);
|
|
24409
|
-
const body =
|
|
24856
|
+
const body = el4(doc, "div", "knobs-wt-n-body");
|
|
24410
24857
|
if (n.text)
|
|
24411
24858
|
body.append(prose2(doc, "p", "knobs-wt-n-text", n.text));
|
|
24412
24859
|
if (n.voice) {
|
|
24413
|
-
const a =
|
|
24860
|
+
const a = el4(doc, "audio", "knobs-wt-n-voice");
|
|
24414
24861
|
a.controls = true;
|
|
24415
24862
|
a.preload = "none";
|
|
24416
24863
|
a.src = n.voice.url;
|
|
@@ -24430,7 +24877,7 @@ function walkthrough(container, options) {
|
|
|
24430
24877
|
body.append(thumb);
|
|
24431
24878
|
}
|
|
24432
24879
|
row.append(body);
|
|
24433
|
-
const x =
|
|
24880
|
+
const x = el4(doc, "button", "knobs-wt-x");
|
|
24434
24881
|
x.type = "button";
|
|
24435
24882
|
x.innerHTML = ICON.close;
|
|
24436
24883
|
x.setAttribute("aria-label", "Delete this note");
|
|
@@ -24470,22 +24917,23 @@ function walkthrough(container, options) {
|
|
|
24470
24917
|
row.addEventListener("transitionend", done, { once: true });
|
|
24471
24918
|
win.setTimeout(done, 600);
|
|
24472
24919
|
};
|
|
24473
|
-
const metaLine = (cls) =>
|
|
24920
|
+
const metaLine = (cls) => el4(doc, "div", `knobs-wt-metaline ${cls}`);
|
|
24474
24921
|
const metaText = (line, text, cls) => {
|
|
24475
|
-
const s =
|
|
24922
|
+
const s = el4(doc, "span", cls);
|
|
24476
24923
|
s.textContent = text;
|
|
24477
24924
|
line.append(s);
|
|
24478
24925
|
return s;
|
|
24479
24926
|
};
|
|
24480
|
-
const findPRIn = (n) => findPR(page.prs, n, page.repo);
|
|
24927
|
+
const findPRIn = (n, kind = "pr") => findPR(page.prs, n, page.repo, kind);
|
|
24481
24928
|
const metaLink = (line, text, href) => {
|
|
24482
24929
|
const n = prNumber(href);
|
|
24483
|
-
|
|
24484
|
-
|
|
24930
|
+
const issue = n ? null : issueNumber(href);
|
|
24931
|
+
if (n || issue) {
|
|
24932
|
+
const chip = n ? prChip(doc, n, { ...findPRIn(n), href }) : prChip(doc, issue, { ...findPRIn(issue, "issue"), href });
|
|
24485
24933
|
line.append(chip);
|
|
24486
24934
|
return chip;
|
|
24487
24935
|
}
|
|
24488
|
-
const a =
|
|
24936
|
+
const a = el4(doc, "a");
|
|
24489
24937
|
a.href = href;
|
|
24490
24938
|
a.target = "_blank";
|
|
24491
24939
|
a.rel = "noreferrer";
|
|
@@ -24495,9 +24943,9 @@ function walkthrough(container, options) {
|
|
|
24495
24943
|
return a;
|
|
24496
24944
|
};
|
|
24497
24945
|
const feedItem = (f, now) => {
|
|
24498
|
-
const li =
|
|
24946
|
+
const li = el4(doc, "li", "knobs-wt-fi");
|
|
24499
24947
|
li.dataset.kind = f.kind;
|
|
24500
|
-
const q =
|
|
24948
|
+
const q = el4(doc, "div", "knobs-wt-fi-q");
|
|
24501
24949
|
const meta = metaLine("knobs-wt-fi-meta");
|
|
24502
24950
|
if (f.at !== null) {
|
|
24503
24951
|
const when = metaText(meta, ago(f.at, now));
|
|
@@ -24506,7 +24954,7 @@ function walkthrough(container, options) {
|
|
|
24506
24954
|
const step = f.step ? page.steps.find((s) => s.key === f.step) : undefined;
|
|
24507
24955
|
if (step) {
|
|
24508
24956
|
const section = page.sections.find((s) => s.id === step.section);
|
|
24509
|
-
const b =
|
|
24957
|
+
const b = el4(doc, "button", "knobs-wt-fi-step");
|
|
24510
24958
|
b.type = "button";
|
|
24511
24959
|
b.textContent = section?.link?.label ?? plainMarkdown(step.title);
|
|
24512
24960
|
b.title = `Go to “${plainMarkdown(step.title)}”`;
|
|
@@ -24528,19 +24976,19 @@ function walkthrough(container, options) {
|
|
|
24528
24976
|
q.append(prose2(doc, "p", "knobs-wt-fi-text", f.text));
|
|
24529
24977
|
li.append(q);
|
|
24530
24978
|
if (f.q || f.trail.length) {
|
|
24531
|
-
const a =
|
|
24979
|
+
const a = el4(doc, "div", "knobs-wt-fi-a");
|
|
24532
24980
|
if (f.q)
|
|
24533
24981
|
a.append(prose2(doc, "div", "knobs-wt-fi-answer", f.text));
|
|
24534
24982
|
if (f.trail.length) {
|
|
24535
|
-
const list =
|
|
24983
|
+
const list = el4(doc, "ol", "knobs-wt-trail");
|
|
24536
24984
|
for (const line of f.trail) {
|
|
24537
24985
|
const i = line.indexOf(" · ");
|
|
24538
|
-
const row =
|
|
24539
|
-
const words =
|
|
24986
|
+
const row = el4(doc, "li");
|
|
24987
|
+
const words = el4(doc, "span", "knobs-wt-trail-text");
|
|
24540
24988
|
words.textContent = i < 0 ? line : line.slice(i + 3);
|
|
24541
24989
|
row.append(words);
|
|
24542
24990
|
if (i >= 0) {
|
|
24543
|
-
const at =
|
|
24991
|
+
const at = el4(doc, "span", "knobs-wt-trail-at");
|
|
24544
24992
|
at.textContent = line.slice(0, i);
|
|
24545
24993
|
row.append(at);
|
|
24546
24994
|
}
|
|
@@ -24574,11 +25022,11 @@ function walkthrough(container, options) {
|
|
|
24574
25022
|
root.dataset.rail = options.rail === false ? "none" : options.rail === "right" ? "right" : "left";
|
|
24575
25023
|
root.toggleAttribute("data-cards", options.cards === true);
|
|
24576
25024
|
root.toggleAttribute("data-review", review);
|
|
24577
|
-
const layout =
|
|
24578
|
-
const main =
|
|
24579
|
-
const flow =
|
|
24580
|
-
const head =
|
|
24581
|
-
const h1 =
|
|
25025
|
+
const layout = el4(doc, "div", "knobs-wt-layout");
|
|
25026
|
+
const main = el4(doc, "div", "knobs-wt-main");
|
|
25027
|
+
const flow = el4(doc, "div", "knobs-wt-flow");
|
|
25028
|
+
const head = el4(doc, "header", "knobs-wt-head");
|
|
25029
|
+
const h1 = el4(doc, "h1", "knobs-wt-title");
|
|
24582
25030
|
h1.textContent = page.title;
|
|
24583
25031
|
head.append(h1);
|
|
24584
25032
|
if (page.summary)
|
|
@@ -24586,13 +25034,13 @@ function walkthrough(container, options) {
|
|
|
24586
25034
|
if (page.more)
|
|
24587
25035
|
head.append(more(page.more));
|
|
24588
25036
|
if (page.meta.length) {
|
|
24589
|
-
const meta =
|
|
25037
|
+
const meta = el4(doc, "div", "knobs-wt-meta");
|
|
24590
25038
|
for (const m of page.meta) {
|
|
24591
|
-
const s =
|
|
25039
|
+
const s = el4(doc, "span");
|
|
24592
25040
|
s.append(m.label);
|
|
24593
|
-
const b =
|
|
25041
|
+
const b = el4(doc, "b");
|
|
24594
25042
|
if (m.href) {
|
|
24595
|
-
const a =
|
|
25043
|
+
const a = el4(doc, "a");
|
|
24596
25044
|
a.href = m.href;
|
|
24597
25045
|
a.target = "_blank";
|
|
24598
25046
|
a.rel = "noreferrer";
|
|
@@ -24608,14 +25056,14 @@ function walkthrough(container, options) {
|
|
|
24608
25056
|
flow.append(head);
|
|
24609
25057
|
let feedEl = null;
|
|
24610
25058
|
if (page.feed.length) {
|
|
24611
|
-
feedEl =
|
|
25059
|
+
feedEl = el4(doc, "section", "knobs-wt-feed");
|
|
24612
25060
|
feedEl.id = "wt-latest";
|
|
24613
25061
|
feedEl.setAttribute("aria-label", "Updates and answers");
|
|
24614
|
-
const fh =
|
|
24615
|
-
const h =
|
|
25062
|
+
const fh = el4(doc, "header", "knobs-wt-feed-head");
|
|
25063
|
+
const h = el4(doc, "h2", "knobs-wt-feed-title");
|
|
24616
25064
|
h.textContent = page.feed.some((f) => f.kind === "qa") ? "Updates & Q&A" : "Updates";
|
|
24617
25065
|
fh.append(h);
|
|
24618
|
-
const list =
|
|
25066
|
+
const list = el4(doc, "ol", "knobs-wt-feed-list");
|
|
24619
25067
|
const now = Date.now();
|
|
24620
25068
|
for (const f of page.feed)
|
|
24621
25069
|
list.append(feedItem(f, now));
|
|
@@ -24625,21 +25073,21 @@ function walkthrough(container, options) {
|
|
|
24625
25073
|
let rail = null;
|
|
24626
25074
|
count = fill = tocEl = null;
|
|
24627
25075
|
if (options.rail !== false) {
|
|
24628
|
-
rail =
|
|
25076
|
+
rail = el4(doc, "aside", "knobs-wt-rail");
|
|
24629
25077
|
rail.setAttribute("aria-label", "Contents");
|
|
24630
|
-
tocEl =
|
|
25078
|
+
tocEl = el4(doc, "nav", "knobs-wt-toc");
|
|
24631
25079
|
tocEl.setAttribute("aria-label", "Contents");
|
|
24632
25080
|
if (feedEl) {
|
|
24633
|
-
const group =
|
|
25081
|
+
const group = el4(doc, "div", "knobs-wt-toc-group");
|
|
24634
25082
|
const target = feedEl;
|
|
24635
25083
|
group.append(tocRow("Latest", false, () => target.scrollIntoView({ block: "start", behavior: reduced() ? "auto" : "smooth" })));
|
|
24636
25084
|
tocEl.append(group);
|
|
24637
25085
|
}
|
|
24638
25086
|
if (review) {
|
|
24639
|
-
const progress =
|
|
24640
|
-
count =
|
|
24641
|
-
const meter =
|
|
24642
|
-
fill =
|
|
25087
|
+
const progress = el4(doc, "div", "knobs-wt-progress");
|
|
25088
|
+
count = el4(doc, "div", "knobs-wt-count");
|
|
25089
|
+
const meter = el4(doc, "div", "knobs-wt-bar");
|
|
25090
|
+
fill = el4(doc, "div", "knobs-wt-fill");
|
|
24643
25091
|
meter.append(fill);
|
|
24644
25092
|
progress.append(count, meter);
|
|
24645
25093
|
rail.append(progress);
|
|
@@ -24648,15 +25096,15 @@ function walkthrough(container, options) {
|
|
|
24648
25096
|
if (review)
|
|
24649
25097
|
rail.append(actions(true));
|
|
24650
25098
|
if (review && options.keys !== false) {
|
|
24651
|
-
const keys =
|
|
25099
|
+
const keys = el4(doc, "div", "knobs-wt-keys");
|
|
24652
25100
|
keys.innerHTML = "<kbd>j</kbd> <kbd>k</kbd> steps · <kbd>←</kbd> <kbd>→</kbd> seek · <kbd>f</kbd> full · <kbd>n</kbd> note" + (page.steps.some((s) => s.ask === "pick") ? " · <kbd>1</kbd>–<kbd>9</kbd> pick" : "");
|
|
24653
25101
|
rail.append(keys);
|
|
24654
25102
|
}
|
|
24655
25103
|
}
|
|
24656
25104
|
for (const section of page.sections) {
|
|
24657
|
-
const sec =
|
|
25105
|
+
const sec = el4(doc, "section", "knobs-wt-section");
|
|
24658
25106
|
sec.id = `wt-${section.id}`;
|
|
24659
|
-
const sh =
|
|
25107
|
+
const sh = el4(doc, "header", "knobs-wt-shead");
|
|
24660
25108
|
const status = review ? section.status : undefined;
|
|
24661
25109
|
if (section.kicker || section.link || status) {
|
|
24662
25110
|
const meta = metaLine("knobs-wt-kicker");
|
|
@@ -24670,10 +25118,10 @@ function walkthrough(container, options) {
|
|
|
24670
25118
|
}
|
|
24671
25119
|
sh.append(meta);
|
|
24672
25120
|
}
|
|
24673
|
-
const h2 =
|
|
25121
|
+
const h2 = el4(doc, "h2", "knobs-wt-heading");
|
|
24674
25122
|
h2.innerHTML = inlineMarkdown(section.title);
|
|
24675
25123
|
sh.append(h2);
|
|
24676
|
-
const intro =
|
|
25124
|
+
const intro = el4(doc, "div", "knobs-wt-sintro");
|
|
24677
25125
|
intro.append(sh);
|
|
24678
25126
|
if (section.summary)
|
|
24679
25127
|
intro.append(prose2(doc, "p", "knobs-wt-ssum", section.summary));
|
|
@@ -24682,7 +25130,7 @@ function walkthrough(container, options) {
|
|
|
24682
25130
|
sec.append(intro);
|
|
24683
25131
|
let group = null;
|
|
24684
25132
|
if (tocEl) {
|
|
24685
|
-
group =
|
|
25133
|
+
group = el4(doc, "div", "knobs-wt-toc-group");
|
|
24686
25134
|
const first = section.steps[0]?.key;
|
|
24687
25135
|
group.append(tocRow(plainMarkdown(section.title), false, () => first ? go(first) : undefined, section.id));
|
|
24688
25136
|
tocEl.append(group);
|
|
@@ -24710,7 +25158,8 @@ function walkthrough(container, options) {
|
|
|
24710
25158
|
if (tocEl)
|
|
24711
25159
|
pill = selectionPill(tocEl, {
|
|
24712
25160
|
selected: () => viewOf(current)?.toc ?? null,
|
|
24713
|
-
rows: () => tocRows
|
|
25161
|
+
rows: () => tocRows,
|
|
25162
|
+
spring: SPRINGS.snappy
|
|
24714
25163
|
});
|
|
24715
25164
|
syncProgress();
|
|
24716
25165
|
current = null;
|
|
@@ -24724,8 +25173,8 @@ function walkthrough(container, options) {
|
|
|
24724
25173
|
}));
|
|
24725
25174
|
};
|
|
24726
25175
|
const more = (text) => {
|
|
24727
|
-
const box =
|
|
24728
|
-
const body =
|
|
25176
|
+
const box = el4(doc, "div", "knobs-wt-more");
|
|
25177
|
+
const body = el4(doc, "div", "knobs-wt-more-text");
|
|
24729
25178
|
for (const para of text.split(/\n\s*\n/))
|
|
24730
25179
|
if (para.trim())
|
|
24731
25180
|
body.append(prose2(doc, "p", "", para.trim()));
|
|
@@ -24733,25 +25182,25 @@ function walkthrough(container, options) {
|
|
|
24733
25182
|
return box;
|
|
24734
25183
|
};
|
|
24735
25184
|
const tocRow = (label, sub, run, section) => {
|
|
24736
|
-
const b =
|
|
25185
|
+
const b = el4(doc, "button", sub ? "knobs-wt-toc-row knobs-wt-toc-sub" : "knobs-wt-toc-row");
|
|
24737
25186
|
b.type = "button";
|
|
24738
25187
|
if (section)
|
|
24739
25188
|
b.dataset.section = section;
|
|
24740
|
-
const t =
|
|
25189
|
+
const t = el4(doc, "span", "knobs-wt-toc-label");
|
|
24741
25190
|
t.textContent = label;
|
|
24742
25191
|
b.title = label;
|
|
24743
25192
|
b.append(t);
|
|
24744
25193
|
if (review)
|
|
24745
|
-
b.append(
|
|
25194
|
+
b.append(el4(doc, "span", "knobs-wt-toc-end"));
|
|
24746
25195
|
b.addEventListener("mousedown", (ev) => ev.preventDefault());
|
|
24747
25196
|
b.addEventListener("click", run);
|
|
24748
25197
|
tocRows.push(b);
|
|
24749
25198
|
return b;
|
|
24750
25199
|
};
|
|
24751
25200
|
const actions = (rail) => {
|
|
24752
|
-
const row =
|
|
25201
|
+
const row = el4(doc, "div", "knobs-wt-actions");
|
|
24753
25202
|
const btn = (text, run, primary = false) => {
|
|
24754
|
-
const b =
|
|
25203
|
+
const b = el4(doc, "button", "knobs-wt-btn");
|
|
24755
25204
|
b.type = "button";
|
|
24756
25205
|
b.textContent = text;
|
|
24757
25206
|
if (primary)
|
|
@@ -24789,13 +25238,13 @@ function walkthrough(container, options) {
|
|
|
24789
25238
|
}
|
|
24790
25239
|
};
|
|
24791
25240
|
const stepView = (step, group) => {
|
|
24792
|
-
const card =
|
|
25241
|
+
const card = el4(doc, "article", options.cards ? "knobs-wt-step knobs-surface" : "knobs-wt-step");
|
|
24793
25242
|
card.id = `wt-${step.key.replace("/", "--")}`;
|
|
24794
25243
|
card.tabIndex = -1;
|
|
24795
25244
|
card.dataset.key = step.key;
|
|
24796
25245
|
card.setAttribute("aria-label", plainMarkdown(step.title));
|
|
24797
|
-
const head =
|
|
24798
|
-
const h3 =
|
|
25246
|
+
const head = el4(doc, "header", "knobs-wt-step-head");
|
|
25247
|
+
const h3 = el4(doc, "h3", "knobs-wt-stepTitle");
|
|
24799
25248
|
h3.innerHTML = inlineMarkdown(step.title);
|
|
24800
25249
|
head.append(h3);
|
|
24801
25250
|
if (step.caption)
|
|
@@ -24807,7 +25256,7 @@ function walkthrough(container, options) {
|
|
|
24807
25256
|
const onEvent = (e) => record({ ...e, step: step.key });
|
|
24808
25257
|
let media = null;
|
|
24809
25258
|
if (step.media.length) {
|
|
24810
|
-
media =
|
|
25259
|
+
media = el4(doc, "div", "knobs-wt-media");
|
|
24811
25260
|
media.style.setProperty("--kw-n", String(Math.min(step.media.length, step.columns)));
|
|
24812
25261
|
for (const m of step.media)
|
|
24813
25262
|
slots.push(mediaSlot(media, { ...look, media: m, onEvent, steps: stepLinks, findPR: findPRIn }));
|
|
@@ -24827,7 +25276,7 @@ function walkthrough(container, options) {
|
|
|
24827
25276
|
});
|
|
24828
25277
|
media ??= taste.element;
|
|
24829
25278
|
}
|
|
24830
|
-
const notes =
|
|
25279
|
+
const notes = el4(doc, "div", "knobs-wt-notes");
|
|
24831
25280
|
if (review)
|
|
24832
25281
|
card.append(notes);
|
|
24833
25282
|
card.addEventListener("focusin", () => {
|
|
@@ -24841,7 +25290,7 @@ function walkthrough(container, options) {
|
|
|
24841
25290
|
if (group) {
|
|
24842
25291
|
toc = tocRow(plainMarkdown(step.title), true, () => go(step.key));
|
|
24843
25292
|
if (review) {
|
|
24844
|
-
glyph =
|
|
25293
|
+
glyph = el4(doc, "span", "knobs-wt-toc-glyph");
|
|
24845
25294
|
toc.querySelector(".knobs-wt-toc-end").append(glyph);
|
|
24846
25295
|
}
|
|
24847
25296
|
group.append(toc);
|
|
@@ -25045,6 +25494,7 @@ export {
|
|
|
25045
25494
|
contextMenu,
|
|
25046
25495
|
countChanges,
|
|
25047
25496
|
currentMarker,
|
|
25497
|
+
decision,
|
|
25048
25498
|
diffActivity,
|
|
25049
25499
|
diffBar,
|
|
25050
25500
|
diffCounts,
|
|
@@ -25057,6 +25507,7 @@ export {
|
|
|
25057
25507
|
digitPick,
|
|
25058
25508
|
drag as dragDivider,
|
|
25059
25509
|
dropTarget,
|
|
25510
|
+
facts,
|
|
25060
25511
|
feedbackMarkdown,
|
|
25061
25512
|
fileKey,
|
|
25062
25513
|
filesUnder,
|