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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/panel.js CHANGED
@@ -20909,12 +20909,20 @@ var compareCss = `
20909
20909
  display:flex;flex-direction:column;gap:6px;width:100%;height:100%;min-height:160px;outline:none;user-select:none;-webkit-user-select:none;
20910
20910
  font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}
20911
20911
  :where(.knobs-ui) :is(.knobs-cmp-mode,.knobs-cmp-toggle){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}
20912
- .knobs-cmp-bar{flex:none;display:flex;align-items:center;gap:2px;height:24px;padding:0 2px}
20913
- .knobs-cmp-modes{display:flex;align-items:center;gap:2px}
20914
- .knobs-ui .knobs-cmp-mode,.knobs-ui .knobs-cmp-toggle{height:22px;padding:0 7px;border-radius:max(0px,calc(var(--_k-radius) - 2px));color:var(--_k-fg-3);cursor:pointer;white-space:nowrap;
20915
- transition:color .15s,background .15s}
20916
- .knobs-ui .knobs-cmp-mode:is(:hover,:focus-visible),.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){color:var(--_k-fg);background:var(--_ku-wash)}
20917
- .knobs-ui .knobs-cmp-mode[aria-checked="true"],.knobs-ui .knobs-cmp-toggle[aria-pressed="true"]{color:var(--_k-fg);font-weight:var(--_k-weight-label)}
20912
+ .knobs-cmp-bar{flex:none;display:flex;align-items:center;gap:var(--_k-gap);height:var(--_k-control-h)}
20913
+ /* The modes: one fill, the selection pill on the one picked; a mode isn't brighter for being
20914
+ picked: the pill's bright copy is. */
20915
+ .knobs-cmp-modes{position:relative;display:inline-flex;height:var(--_k-control-h);border-radius:var(--_k-radius);background:var(--_k-fill)}
20916
+ .knobs-cmp-modes[hidden]{display:none}
20917
+ .knobs-ui .knobs-cmp-mode{display:inline-flex;align-items:center;height:100%;padding:0 8px;border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:pointer;white-space:nowrap;
20918
+ transition:color calc(var(--_k-hover-out) * 1ms)}
20919
+ .knobs-ui .knobs-cmp-mode:is(:hover,:focus-visible){color:var(--_k-fg)}
20920
+ /* Toggles: icon buttons, the accent's wash when on. */
20921
+ .knobs-ui .knobs-cmp-toggle{display:inline-flex;align-items:center;justify-content:center;width:var(--_k-control-h);height:var(--_k-control-h);border-radius:var(--_k-radius);color:var(--_k-fg-3);cursor:pointer;
20922
+ transition:color calc(var(--_k-hover-out) * 1ms),background calc(var(--_k-hover-out) * 1ms)}
20923
+ .knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){color:var(--_k-fg);background:var(--_ku-wash)}
20924
+ .knobs-ui .knobs-cmp-toggle[aria-pressed="true"]{color:var(--_k-accent-fg);background:var(--_k-accent-soft)}
20925
+ .knobs-cmp-toggle svg{display:block}
20918
20926
  .knobs-cmp-fill{flex:1}
20919
20927
  .knobs-cmp-toggle[hidden]{display:none}
20920
20928
  /* One surface: on a card (a walkthrough's step, a split's pane, anything .knobs-surface) or marked
@@ -20929,7 +20937,8 @@ var compareCss = `
20929
20937
  /* Unzoomed, a finger still scrolls the page up and down; zoomed, the stage takes every gesture. */
20930
20938
  .knobs-compare[data-zoomed] .knobs-cmp-stage{cursor:grab;touch-action:none}
20931
20939
  .knobs-compare[data-panning],.knobs-compare[data-panning] *{cursor:grabbing!important}
20932
- .knobs-compare[data-dragging],.knobs-compare[data-dragging] *{cursor:ew-resize!important}
20940
+ /* Wiping, the grip stands in for the cursor. */
20941
+ .knobs-compare[data-dragging],.knobs-compare[data-dragging] *{cursor:none!important}
20933
20942
  .knobs-cmp-sizer{position:absolute;left:0;right:0;top:0;height:0;visibility:hidden;pointer-events:none}
20934
20943
  .knobs-cmp-canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}
20935
20944
  .knobs-cmp-media{position:absolute;left:0;top:0;display:block;max-width:none;margin:0;padding:0;border:0;object-fit:fill;transform-origin:0 0;pointer-events:none;will-change:transform}
@@ -20937,18 +20946,21 @@ var compareCss = `
20937
20946
  /* Glass: what's behind shows through, blurred, on the knobs tokens. */
20938
20947
  .knobs-cmp-label,.knobs-cmp-zoom{background:color-mix(in srgb,var(--_k-bg) 52%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.6);backdrop-filter:blur(14px) saturate(1.6);
20939
20948
  box-shadow:inset 0 0 0 .5px var(--_k-border),inset 0 1px 0 var(--_k-rim),0 2px 10px rgba(0,0,0,calc(.18 * var(--_k-shadow-k,1)))}
20940
- .knobs-cmp-label{position:absolute;left:0;top:0;padding:1px 7px;border-radius:999px;font-size:var(--_k-text-meta);line-height:16px;color:var(--_k-fg-2);white-space:nowrap;pointer-events:none;will-change:transform;transition:color .15s}
20941
- .knobs-cmp-label[data-lit]{color:var(--_k-fg)}
20942
- .knobs-cmp-label[data-dim]{color:var(--_k-fg-3)}
20943
- /* The wipe: a hairline down the line with a grip at its middle; a wider strip takes the hand and
20944
- the keys (a slider). It fades with the mode. */
20949
+ .knobs-cmp-label{position:absolute;left:0;top:0;padding:1px 7px;border-radius:999px;font-size:var(--_k-text-meta);line-height:16px;color:var(--_k-fg-2);white-space:nowrap;pointer-events:none;will-change:transform;transition:color calc(var(--_k-hover-out) * 1ms)}
20950
+ /* The wipe: a hairline down the line with a raised grip at the pointer's height; a wider strip
20951
+ takes the hand and the keys (a slider). It fades with the mode; wiping, line and grip brighten. */
20945
20952
  .knobs-cmp-handle{cursor:ew-resize;position:absolute;left:-12px;top:0;width:24px;height:0;opacity:0;pointer-events:none;outline:none;will-change:transform;transition:opacity .18s cubic-bezier(.4,0,1,1)}
20946
20953
  .knobs-cmp-handle[data-on]{opacity:1;pointer-events:auto;transition:opacity .22s cubic-bezier(.2,.8,.2,1)}
20947
- .knobs-cmp-handle::before{content:"";position:absolute;top:0;bottom:0;left:11.5px;width:1px;background:var(--_ku-cmp-line);box-shadow:0 0 0 .5px rgba(0,0,0,.28),0 0 6px rgba(0,0,0,.25)}
20948
- .knobs-cmp-handle::after{content:"";position:absolute;top:50%;left:9px;width:6px;height:28px;margin-top:-14px;border-radius:3px;background:var(--_ku-cmp-line);
20949
- box-shadow:0 1px 3px rgba(0,0,0,.35),0 0 0 .5px rgba(0,0,0,.2);transition:scale .18s var(--_ku-ease),box-shadow .15s}
20950
- .knobs-compare[data-dragging] .knobs-cmp-handle::after{scale:1.12}
20951
- .knobs-cmp-handle:focus-visible::after,.knobs-compare[data-keyboard] .knobs-cmp-handle:focus::after{box-shadow:0 1px 3px rgba(0,0,0,.35),0 0 0 3px color-mix(in srgb,var(--_k-accent) 40%,transparent)}
20954
+ .knobs-cmp-handle::before{content:"";position:absolute;top:0;bottom:0;left:11.5px;width:1px;background:color-mix(in srgb,var(--_ku-cmp-line) 72%,transparent);box-shadow:0 0 0 .5px rgba(0,0,0,.28),0 0 6px rgba(0,0,0,.25)}
20955
+ .knobs-compare[data-dragging] .knobs-cmp-handle::before{background:var(--_ku-cmp-line)}
20956
+ .knobs-cmp-grip{position:absolute;top:0;left:4px;width:16px;height:28px;border-radius:min(8px,calc(var(--_k-radius) * 999));background:var(--_k-bg-overlay);
20957
+ box-shadow:var(--_k-shadow-overlay),inset 0 0 0 1px var(--_k-border),inset 0 1px 0 var(--_k-rim);will-change:transform;transition:box-shadow calc(var(--_k-hover-out) * 1ms)}
20958
+ .knobs-cmp-grip::before,.knobs-cmp-grip::after{content:"";position:absolute;top:10px;width:1px;height:8px;background:var(--_k-fg-3);transition:background calc(var(--_k-hover-out) * 1ms)}
20959
+ .knobs-cmp-grip::before{left:6px}
20960
+ .knobs-cmp-grip::after{left:9px}
20961
+ .knobs-compare[data-dragging] .knobs-cmp-grip{box-shadow:var(--_k-shadow-overlay),inset 0 0 0 1px var(--_k-border-strong),inset 0 1px 0 var(--_k-rim)}
20962
+ .knobs-compare[data-dragging] .knobs-cmp-grip::before,.knobs-compare[data-dragging] .knobs-cmp-grip::after{background:var(--_k-fg)}
20963
+ .knobs-cmp-handle:focus-visible .knobs-cmp-grip,.knobs-compare[data-keyboard] .knobs-cmp-handle:focus .knobs-cmp-grip{box-shadow:var(--_k-shadow-overlay),0 0 0 2px var(--_k-accent)}
20952
20964
  /* The split's hairline, down the middle side by side. */
20953
20965
  .knobs-cmp-split{position:absolute;left:0;top:0;width:1px;height:0;margin-left:-.5px;background:color-mix(in srgb,var(--_k-bg) 72%,transparent);pointer-events:none;will-change:transform,opacity}
20954
20966
  /* Zoomed: how far, and a way back, in the stage's corner; it fades in and out, nothing shifts. */
@@ -20957,12 +20969,12 @@ var compareCss = `
20957
20969
  opacity:0;scale:.96;pointer-events:none;transition:opacity .16s cubic-bezier(.4,0,1,1),scale .16s cubic-bezier(.4,0,1,1)}
20958
20970
  .knobs-cmp-zoom[data-on]{opacity:1;scale:1;pointer-events:auto;transition:opacity .2s cubic-bezier(.2,.8,.2,1),scale .2s cubic-bezier(.2,.8,.2,1)}
20959
20971
  :where(.knobs-ui) .knobs-cmp-zoom-reset{all:revert;box-sizing:border-box;font:inherit;letter-spacing:inherit;margin:0;border:0;outline:none;box-shadow:none;
20960
- height:20px;padding:0 8px;border-radius:999px;background:transparent;color:var(--_k-fg-2);cursor:pointer;transition:color .15s,background .15s}
20972
+ display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border-radius:999px;background:transparent;color:var(--_k-fg-2);cursor:pointer;transition:color .15s,background .15s}
20961
20973
  :where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){color:var(--_k-fg);background:color-mix(in srgb,var(--_k-fg) 12%,transparent)}
20962
20974
  .knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--_k-fg-3);font-size:var(--_k-text-meta);pointer-events:none}
20963
20975
  .knobs-cmp-note:empty{display:none}
20964
20976
  .knobs-cmp-strip-host{flex:none;height:60px;min-height:0}
20965
- .knobs-cmp-timeline-host{flex:none;height:56px;min-height:0}
20977
+ .knobs-cmp-timeline-host{flex:none;min-height:0}
20966
20978
  /* The frame strip: Before over After per column, a difference bar under them, a dot where it peaks. */
20967
20979
  .knobs-ui.knobs-cmp-strip{--_ku-cmp-diff:var(--k-compare-diff,var(--_k-ok));position:relative;width:100%;height:100%;min-height:40px;overflow:hidden;cursor:col-resize;touch-action:none;
20968
20980
  font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg)}
@@ -21105,7 +21117,7 @@ var init_picker_css = __esm(() => {
21105
21117
  .knobs-picker-suggested{flex:none;color:var(--_k-fg-3);font-size:var(--_k-text-meta)}
21106
21118
  .knobs-picker-check{flex:none;display:flex;width:14px;height:14px;color:var(--_k-accent);opacity:0;scale:.6;filter:blur(2px);
21107
21119
  transition:opacity .11s ease-in,scale .11s ease-in,filter .11s ease-in}
21108
- .knobs-picker-check svg{display:block;width:14px;height:14px}
21120
+ .knobs-picker-check svg{display:block;width:12px;height:12px}
21109
21121
  .knobs-picker-option[data-chosen] .knobs-picker-check{opacity:1;scale:1;filter:none;transition:opacity .15s ease-out,scale var(--kp-snappy-ms) var(--kp-snappy),filter .15s ease-out}
21110
21122
  .knobs-picker-body{position:relative;overflow:visible}
21111
21123
  .knobs-picker-body[data-moving]{overflow:hidden}
@@ -21209,6 +21221,15 @@ var readoutCss = `
21209
21221
  @media(prefers-reduced-motion:reduce){.knobs-rd :where(*){transition:none!important}}
21210
21222
  `;
21211
21223
 
21224
+ // src/ui/selection-pill-css.ts
21225
+ var selectionPillCss = `
21226
+ .knobs-pick-pill,.knobs-pick-copy{position:absolute;left:0;top:0;width:0;height:0;pointer-events:none;transition:opacity .1s linear}
21227
+ .knobs-pick-pill{background:var(--_k-fill-selected);will-change:transform}
21228
+ .knobs-pick-copy{overflow:hidden;will-change:transform}
21229
+ .knobs-pick-copy-rows{position:absolute;left:0;top:0;width:0;height:0}
21230
+ :is(.knobs-pick-pill,.knobs-pick-copy)[data-off]{opacity:0}
21231
+ `;
21232
+
21212
21233
  // src/ui/look.ts
21213
21234
  function injectUiStyles(doc) {
21214
21235
  injectTokens(doc);
@@ -21429,11 +21450,9 @@ var css3 = `
21429
21450
  .knobs-tree:focus .knobs-tree-row[data-active][aria-selected="true"]::before{background:var(--_ku-select-focus)}
21430
21451
  .knobs-tree-row[data-drop="into"]::before{opacity:1;background:color-mix(in srgb,var(--_k-accent) 30%,transparent)}
21431
21452
  .knobs-tree-row[data-dragged]{opacity:.38}
21432
- /* glide: one highlight under the selected row that glides between rows (the row's own stays off). */
21433
- .knobs-tree-cursor{position:absolute;left:var(--_ku-row-x);right:var(--_ku-row-x);top:0;height:var(--_k-row);border-radius:var(--_ku-row-radius);background:var(--_ku-select);
21434
- opacity:0;pointer-events:none;will-change:transform;transition:opacity .15s ease-out,background .12s}
21435
- .knobs-tree-cursor[data-on]{opacity:1}
21436
- .knobs-tree:focus .knobs-tree-cursor{background:var(--_ku-select-focus)}
21453
+ /* glide: the selection pill on the selected row, in the selection's colour (the row's own stays off). */
21454
+ .knobs-tree>.knobs-pick-pill{background:var(--_ku-select)}
21455
+ .knobs-tree:focus>.knobs-pick-pill{background:var(--_ku-select-focus)}
21437
21456
  .knobs-tree[data-glide] .knobs-tree-row[aria-selected="true"]::before{opacity:0!important}
21438
21457
  .knobs-tree-row>*{position:relative}
21439
21458
  .knobs-tree-caret{flex:none;display:flex;align-items:center;justify-content:center;width:16px;height:100%;color:var(--_k-fg-3);transition:transform var(--_ku-ease-ms) var(--_ku-ease)}
@@ -21465,22 +21484,20 @@ var css3 = `
21465
21484
  box-shadow:0 0 0 1px var(--_k-border-strong),0 6px 18px rgba(0,0,0,calc(.35 * var(--_k-shadow-k,1)));pointer-events:none;white-space:nowrap;font:var(--_k-weight) var(--_k-font-size)/1.6 var(--_k-font)}
21466
21485
  .knobs-tree-empty{padding:10px var(--_k-inset);color:var(--_k-fg-3)}
21467
21486
 
21468
- /* Timeline: a transport (play, the time) beside a track: the ruler's canvas over a lane of
21469
- markers, ranges as soft bands, and the playhead, a hairline in the accent with a cap. */
21487
+ /* Timeline: play beside a track: the ruler's canvas over a lane of markers, ranges as soft bands,
21488
+ and the playhead, a hairline in the accent with a cap. No clock: the time shows under the
21489
+ pointer on the track (the tag), in seconds, while hovering or scrubbing. */
21470
21490
  :where(.knobs-timeline,.knobs-timeline *){box-sizing:border-box}
21471
21491
  .knobs-ui.knobs-timeline{display:flex;align-items:stretch;gap:10px;width:100%;height:100%;min-height:52px;padding:6px var(--_k-inset) 8px 8px;outline:none;user-select:none;-webkit-user-select:none;
21472
21492
  font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}
21473
21493
  :where(.knobs-ui) :is(.knobs-tl-play,.knobs-tl-edit){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}
21474
- .knobs-tl-transport{flex:none;display:flex;align-items:center;gap:8px;min-width:96px}
21494
+ .knobs-tl-transport{flex:none;display:flex;align-items:center}
21475
21495
  .knobs-ui .knobs-tl-play{flex:none;display:inline-flex;align-items:center;justify-content:center;width:var(--_k-control-h);height:var(--_k-control-h);min-width:22px;min-height:22px;border-radius:calc(var(--_k-radius) * 999);
21476
21496
  background:var(--_k-fill-selected);color:var(--_k-fg);cursor:pointer;transition:background .15s,transform .15s var(--_ku-ease)}
21477
21497
  .knobs-ui .knobs-tl-play:hover{background:color-mix(in srgb,var(--_k-fg) 16%,transparent)}
21478
21498
  .knobs-ui .knobs-tl-play:active{transform:scale(.94)}
21479
21499
  .knobs-tl-play svg{width:12px;height:12px}
21480
21500
  .knobs-timeline[data-playing] .knobs-tl-play{background:var(--_k-accent);color:var(--_k-bg)}
21481
- .knobs-tl-time{display:flex;flex-direction:column;line-height:1.2;font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
21482
- .knobs-tl-now{font:var(--_k-weight) var(--_k-value-size)/1.2 var(--_k-value-font);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";color:var(--_k-fg);white-space:nowrap}
21483
- .knobs-tl-sub{font-size:var(--_k-text-meta);color:var(--_k-fg-3);white-space:nowrap}
21484
21501
  .knobs-tl-track{position:relative;flex:1;min-width:0;overflow:hidden;border-radius:var(--_k-radius);background:var(--_k-fill);cursor:col-resize;touch-action:none;
21485
21502
  transition:background calc(var(--_k-hover-out) * 1ms)}
21486
21503
  .knobs-timeline:focus-visible .knobs-tl-track,.knobs-timeline[data-keyboard]:focus .knobs-tl-track{background:color-mix(in srgb,var(--_k-fill-selected) 80%,transparent)}
@@ -21504,7 +21521,8 @@ var css3 = `
21504
21521
  .knobs-tl-pin{position:absolute;top:13px;left:-5px;width:10px;height:10px;pointer-events:auto;cursor:grab}
21505
21522
  .knobs-tl-pin::after{content:"";position:absolute;inset:1.5px;border-radius:min(2px,var(--_k-radius));background:var(--knobs-tl-c);rotate:45deg;transition:background .15s,scale .2s var(--_ku-ease)}
21506
21523
  .knobs-tl-mlabel{position:absolute;top:26px;left:3px;max-width:140px;padding:0 6px;border-radius:max(0px,calc(var(--_k-radius) - 3px));background:var(--_k-fill-selected);color:var(--_k-fg);
21507
- font-size:var(--_k-text-meta);line-height:17px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:auto;cursor:grab;transition:background .15s,color .15s}
21524
+ font-size:var(--_k-text-meta);line-height:17px;white-space:nowrap;pointer-events:auto;cursor:grab;transition:background .15s,color .15s}
21525
+ .knobs-tl-mtext{display:block;overflow:hidden;white-space:nowrap}
21508
21526
  .knobs-tl-marker[data-selected]{--knobs-tl-c:var(--_k-accent)}
21509
21527
  .knobs-tl-marker[data-selected] .knobs-tl-mlabel{background:color-mix(in srgb,var(--_k-accent) 24%,var(--_k-fill-selected))}
21510
21528
  .knobs-tl-marker[data-selected] .knobs-tl-pin::after{scale:1.2}
@@ -21525,7 +21543,22 @@ var css3 = `
21525
21543
  .knobs-timeline[data-scrubbing] .knobs-tl-hover{opacity:0}
21526
21544
  @media(prefers-reduced-motion:reduce){.knobs-timeline :where(*,::before,::after){transition:none!important}}
21527
21545
  @media(prefers-reduced-motion:reduce){:is(.knobs-tree,.knobs-split>.knobs-divider,.knobs-pane-head,.knobs-pane-rail) :where(*,::before,::after){transition:none!important}}
21528
- `, uiCss = () => aliased(css3 + readoutCss + overlayCss + bentoCss + activityCss + pickerCss + compareCss) + rolling_css_default, lookDefaults, svg = (body, box = 16) => `<svg viewBox="0 0 ${box} ${box}" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">${body}</svg>`, ICONS2;
21546
+ .knobs-tl-tag{position:absolute;left:0;bottom:2px;font-size:var(--_k-text-meta);line-height:16px;color:var(--_k-fg);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";white-space:nowrap;pointer-events:none;opacity:0}
21547
+ .knobs-tl-tag[data-on]{opacity:1}
21548
+ /* The lane (variant: "lane"): one slim track of ticks under a compare or a video; markers are
21549
+ faint chapter ticks, the current one in text colour; nothing to edit. */
21550
+ .knobs-ui.knobs-timeline[data-variant="lane"]{height:auto;min-height:0;padding:0;gap:var(--_k-gap)}
21551
+ .knobs-timeline[data-variant="lane"] .knobs-tl-track{height:var(--_k-control-h)}
21552
+ .knobs-timeline[data-variant="lane"] .knobs-tl-ruler{height:100%}
21553
+ .knobs-timeline[data-variant="lane"] .knobs-tl-lane{top:0}
21554
+ .knobs-timeline[data-variant="lane"] .knobs-tl-marker{top:0}
21555
+ .knobs-timeline[data-variant="lane"] .knobs-tl-marker::before{top:0;bottom:50%;left:-.75px;width:1.5px;background:var(--_k-fg-3)}
21556
+ .knobs-timeline[data-variant="lane"] .knobs-tl-marker[data-current]::before{background:var(--_k-fg)}
21557
+ .knobs-timeline[data-variant="lane"] :is(.knobs-tl-pin,.knobs-tl-mlabel,.knobs-tl-rlabel){display:none}
21558
+ .knobs-timeline[data-variant="lane"] .knobs-tl-head::before{top:0}
21559
+ .knobs-timeline[data-variant="lane"] .knobs-tl-head::after{content:none}
21560
+ .knobs-timeline[data-variant="lane"] .knobs-tl-tag{top:2px;bottom:auto}
21561
+ `, uiCss = () => aliased(css3 + readoutCss + overlayCss + bentoCss + activityCss + pickerCss + compareCss + selectionPillCss) + rolling_css_default, lookDefaults, svg = (body, box = 16) => `<svg viewBox="0 0 ${box} ${box}" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">${body}</svg>`, ICONS2;
21529
21562
  var init_look = __esm(() => {
21530
21563
  init_appearance();
21531
21564
  init_activity_css();
@@ -1 +1 @@
1
- export declare const compareCss = "\n:where(.knobs-compare,.knobs-compare *,.knobs-cmp-strip,.knobs-cmp-strip *){box-sizing:border-box}\n.knobs-ui.knobs-compare{--_ku-cmp-diff:var(--k-compare-diff,var(--_k-ok));--_ku-cmp-line:var(--_k-compare-divider);\n --_ku-cmp-stage:var(--_k-compare-stage);\n display:flex;flex-direction:column;gap:6px;width:100%;height:100%;min-height:160px;outline:none;user-select:none;-webkit-user-select:none;\n font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}\n:where(.knobs-ui) :is(.knobs-cmp-mode,.knobs-cmp-toggle){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}\n.knobs-cmp-bar{flex:none;display:flex;align-items:center;gap:2px;height:24px;padding:0 2px}\n.knobs-cmp-modes{display:flex;align-items:center;gap:2px}\n.knobs-ui .knobs-cmp-mode,.knobs-ui .knobs-cmp-toggle{height:22px;padding:0 7px;border-radius:max(0px,calc(var(--_k-radius) - 2px));color:var(--_k-fg-3);cursor:pointer;white-space:nowrap;\n transition:color .15s,background .15s}\n.knobs-ui .knobs-cmp-mode:is(:hover,:focus-visible),.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){color:var(--_k-fg);background:var(--_ku-wash)}\n.knobs-ui .knobs-cmp-mode[aria-checked=\"true\"],.knobs-ui .knobs-cmp-toggle[aria-pressed=\"true\"]{color:var(--_k-fg);font-weight:var(--_k-weight-label)}\n.knobs-cmp-fill{flex:1}\n.knobs-cmp-toggle[hidden]{display:none}\n/* One surface: on a card (a walkthrough's step, a split's pane, anything .knobs-surface) or marked\n data-nested, the stage drops its fill and the sides sit on that card. */\n:where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui.knobs-compare,.knobs-ui.knobs-compare[data-nested]{--_ku-cmp-stage:var(--k-compare-stage,transparent)}\n/* In a page's flow (a container with no height), it takes the height its sides need. */\n.knobs-ui.knobs-compare[data-auto]{height:auto}\n.knobs-compare[data-auto] .knobs-cmp-stage{flex:none;min-height:0}\n.knobs-cmp-stage{position:relative;flex:1;min-height:96px;overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_ku-cmp-stage);touch-action:pan-y;outline:none}\n.knobs-compare[data-frame=\"flat\"] .knobs-cmp-stage{border-radius:0}\n.knobs-compare[data-mode=\"wipe\"] .knobs-cmp-stage{cursor:ew-resize}\n/* Unzoomed, a finger still scrolls the page up and down; zoomed, the stage takes every gesture. */\n.knobs-compare[data-zoomed] .knobs-cmp-stage{cursor:grab;touch-action:none}\n.knobs-compare[data-panning],.knobs-compare[data-panning] *{cursor:grabbing!important}\n.knobs-compare[data-dragging],.knobs-compare[data-dragging] *{cursor:ew-resize!important}\n.knobs-cmp-sizer{position:absolute;left:0;right:0;top:0;height:0;visibility:hidden;pointer-events:none}\n.knobs-cmp-canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}\n.knobs-cmp-media{position:absolute;left:0;top:0;display:block;max-width:none;margin:0;padding:0;border:0;object-fit:fill;transform-origin:0 0;pointer-events:none;will-change:transform}\n.knobs-compare[data-renderer=\"gpu\"] .knobs-cmp-media{opacity:0}\n/* Glass: what's behind shows through, blurred, on the knobs tokens. */\n.knobs-cmp-label,.knobs-cmp-zoom{background:color-mix(in srgb,var(--_k-bg) 52%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.6);backdrop-filter:blur(14px) saturate(1.6);\n box-shadow:inset 0 0 0 .5px var(--_k-border),inset 0 1px 0 var(--_k-rim),0 2px 10px rgba(0,0,0,calc(.18 * var(--_k-shadow-k,1)))}\n.knobs-cmp-label{position:absolute;left:0;top:0;padding:1px 7px;border-radius:999px;font-size:var(--_k-text-meta);line-height:16px;color:var(--_k-fg-2);white-space:nowrap;pointer-events:none;will-change:transform;transition:color .15s}\n.knobs-cmp-label[data-lit]{color:var(--_k-fg)}\n.knobs-cmp-label[data-dim]{color:var(--_k-fg-3)}\n/* The wipe: a hairline down the line with a grip at its middle; a wider strip takes the hand and\n the keys (a slider). It fades with the mode. */\n.knobs-cmp-handle{cursor:ew-resize;position:absolute;left:-12px;top:0;width:24px;height:0;opacity:0;pointer-events:none;outline:none;will-change:transform;transition:opacity .18s cubic-bezier(.4,0,1,1)}\n.knobs-cmp-handle[data-on]{opacity:1;pointer-events:auto;transition:opacity .22s cubic-bezier(.2,.8,.2,1)}\n.knobs-cmp-handle::before{content:\"\";position:absolute;top:0;bottom:0;left:11.5px;width:1px;background:var(--_ku-cmp-line);box-shadow:0 0 0 .5px rgba(0,0,0,.28),0 0 6px rgba(0,0,0,.25)}\n.knobs-cmp-handle::after{content:\"\";position:absolute;top:50%;left:9px;width:6px;height:28px;margin-top:-14px;border-radius:3px;background:var(--_ku-cmp-line);\n box-shadow:0 1px 3px rgba(0,0,0,.35),0 0 0 .5px rgba(0,0,0,.2);transition:scale .18s var(--_ku-ease),box-shadow .15s}\n.knobs-compare[data-dragging] .knobs-cmp-handle::after{scale:1.12}\n.knobs-cmp-handle:focus-visible::after,.knobs-compare[data-keyboard] .knobs-cmp-handle:focus::after{box-shadow:0 1px 3px rgba(0,0,0,.35),0 0 0 3px color-mix(in srgb,var(--_k-accent) 40%,transparent)}\n/* The split's hairline, down the middle side by side. */\n.knobs-cmp-split{position:absolute;left:0;top:0;width:1px;height:0;margin-left:-.5px;background:color-mix(in srgb,var(--_k-bg) 72%,transparent);pointer-events:none;will-change:transform,opacity}\n/* Zoomed: how far, and a way back, in the stage's corner; it fades in and out, nothing shifts. */\n.knobs-cmp-zoom{position:absolute;right:8px;bottom:8px;display:flex;align-items:center;gap:4px;height:26px;padding:0 3px 0 10px;border-radius:999px;\n color:var(--_k-fg);font-size:var(--_k-text-meta);font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";white-space:nowrap;\n opacity:0;scale:.96;pointer-events:none;transition:opacity .16s cubic-bezier(.4,0,1,1),scale .16s cubic-bezier(.4,0,1,1)}\n.knobs-cmp-zoom[data-on]{opacity:1;scale:1;pointer-events:auto;transition:opacity .2s cubic-bezier(.2,.8,.2,1),scale .2s cubic-bezier(.2,.8,.2,1)}\n:where(.knobs-ui) .knobs-cmp-zoom-reset{all:revert;box-sizing:border-box;font:inherit;letter-spacing:inherit;margin:0;border:0;outline:none;box-shadow:none;\n height:20px;padding:0 8px;border-radius:999px;background:transparent;color:var(--_k-fg-2);cursor:pointer;transition:color .15s,background .15s}\n:where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){color:var(--_k-fg);background:color-mix(in srgb,var(--_k-fg) 12%,transparent)}\n.knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--_k-fg-3);font-size:var(--_k-text-meta);pointer-events:none}\n.knobs-cmp-note:empty{display:none}\n.knobs-cmp-strip-host{flex:none;height:60px;min-height:0}\n.knobs-cmp-timeline-host{flex:none;height:56px;min-height:0}\n/* The frame strip: Before over After per column, a difference bar under them, a dot where it peaks. */\n.knobs-ui.knobs-cmp-strip{--_ku-cmp-diff:var(--k-compare-diff,var(--_k-ok));position:relative;width:100%;height:100%;min-height:40px;overflow:hidden;cursor:col-resize;touch-action:none;\n font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg)}\n.knobs-cmp-strip>canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}\n@media(prefers-reduced-motion:reduce){:is(.knobs-compare,.knobs-cmp-strip) :where(*,::before,::after){transition-duration:.12s!important}}\n";
1
+ export declare const compareCss = "\n:where(.knobs-compare,.knobs-compare *,.knobs-cmp-strip,.knobs-cmp-strip *){box-sizing:border-box}\n.knobs-ui.knobs-compare{--_ku-cmp-diff:var(--k-compare-diff,var(--_k-ok));--_ku-cmp-line:var(--_k-compare-divider);\n --_ku-cmp-stage:var(--_k-compare-stage);\n display:flex;flex-direction:column;gap:6px;width:100%;height:100%;min-height:160px;outline:none;user-select:none;-webkit-user-select:none;\n font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}\n:where(.knobs-ui) :is(.knobs-cmp-mode,.knobs-cmp-toggle){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}\n.knobs-cmp-bar{flex:none;display:flex;align-items:center;gap:var(--_k-gap);height:var(--_k-control-h)}\n/* The modes: one fill, the selection pill on the one picked; a mode isn't brighter for being\n picked: the pill's bright copy is. */\n.knobs-cmp-modes{position:relative;display:inline-flex;height:var(--_k-control-h);border-radius:var(--_k-radius);background:var(--_k-fill)}\n.knobs-cmp-modes[hidden]{display:none}\n.knobs-ui .knobs-cmp-mode{display:inline-flex;align-items:center;height:100%;padding:0 8px;border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:pointer;white-space:nowrap;\n transition:color calc(var(--_k-hover-out) * 1ms)}\n.knobs-ui .knobs-cmp-mode:is(:hover,:focus-visible){color:var(--_k-fg)}\n/* Toggles: icon buttons, the accent's wash when on. */\n.knobs-ui .knobs-cmp-toggle{display:inline-flex;align-items:center;justify-content:center;width:var(--_k-control-h);height:var(--_k-control-h);border-radius:var(--_k-radius);color:var(--_k-fg-3);cursor:pointer;\n transition:color calc(var(--_k-hover-out) * 1ms),background calc(var(--_k-hover-out) * 1ms)}\n.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){color:var(--_k-fg);background:var(--_ku-wash)}\n.knobs-ui .knobs-cmp-toggle[aria-pressed=\"true\"]{color:var(--_k-accent-fg);background:var(--_k-accent-soft)}\n.knobs-cmp-toggle svg{display:block}\n.knobs-cmp-fill{flex:1}\n.knobs-cmp-toggle[hidden]{display:none}\n/* One surface: on a card (a walkthrough's step, a split's pane, anything .knobs-surface) or marked\n data-nested, the stage drops its fill and the sides sit on that card. */\n:where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui.knobs-compare,.knobs-ui.knobs-compare[data-nested]{--_ku-cmp-stage:var(--k-compare-stage,transparent)}\n/* In a page's flow (a container with no height), it takes the height its sides need. */\n.knobs-ui.knobs-compare[data-auto]{height:auto}\n.knobs-compare[data-auto] .knobs-cmp-stage{flex:none;min-height:0}\n.knobs-cmp-stage{position:relative;flex:1;min-height:96px;overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_ku-cmp-stage);touch-action:pan-y;outline:none}\n.knobs-compare[data-frame=\"flat\"] .knobs-cmp-stage{border-radius:0}\n.knobs-compare[data-mode=\"wipe\"] .knobs-cmp-stage{cursor:ew-resize}\n/* Unzoomed, a finger still scrolls the page up and down; zoomed, the stage takes every gesture. */\n.knobs-compare[data-zoomed] .knobs-cmp-stage{cursor:grab;touch-action:none}\n.knobs-compare[data-panning],.knobs-compare[data-panning] *{cursor:grabbing!important}\n/* Wiping, the grip stands in for the cursor. */\n.knobs-compare[data-dragging],.knobs-compare[data-dragging] *{cursor:none!important}\n.knobs-cmp-sizer{position:absolute;left:0;right:0;top:0;height:0;visibility:hidden;pointer-events:none}\n.knobs-cmp-canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}\n.knobs-cmp-media{position:absolute;left:0;top:0;display:block;max-width:none;margin:0;padding:0;border:0;object-fit:fill;transform-origin:0 0;pointer-events:none;will-change:transform}\n.knobs-compare[data-renderer=\"gpu\"] .knobs-cmp-media{opacity:0}\n/* Glass: what's behind shows through, blurred, on the knobs tokens. */\n.knobs-cmp-label,.knobs-cmp-zoom{background:color-mix(in srgb,var(--_k-bg) 52%,transparent);-webkit-backdrop-filter:blur(14px) saturate(1.6);backdrop-filter:blur(14px) saturate(1.6);\n box-shadow:inset 0 0 0 .5px var(--_k-border),inset 0 1px 0 var(--_k-rim),0 2px 10px rgba(0,0,0,calc(.18 * var(--_k-shadow-k,1)))}\n.knobs-cmp-label{position:absolute;left:0;top:0;padding:1px 7px;border-radius:999px;font-size:var(--_k-text-meta);line-height:16px;color:var(--_k-fg-2);white-space:nowrap;pointer-events:none;will-change:transform;transition:color calc(var(--_k-hover-out) * 1ms)}\n/* The wipe: a hairline down the line with a raised grip at the pointer's height; a wider strip\n takes the hand and the keys (a slider). It fades with the mode; wiping, line and grip brighten. */\n.knobs-cmp-handle{cursor:ew-resize;position:absolute;left:-12px;top:0;width:24px;height:0;opacity:0;pointer-events:none;outline:none;will-change:transform;transition:opacity .18s cubic-bezier(.4,0,1,1)}\n.knobs-cmp-handle[data-on]{opacity:1;pointer-events:auto;transition:opacity .22s cubic-bezier(.2,.8,.2,1)}\n.knobs-cmp-handle::before{content:\"\";position:absolute;top:0;bottom:0;left:11.5px;width:1px;background:color-mix(in srgb,var(--_ku-cmp-line) 72%,transparent);box-shadow:0 0 0 .5px rgba(0,0,0,.28),0 0 6px rgba(0,0,0,.25)}\n.knobs-compare[data-dragging] .knobs-cmp-handle::before{background:var(--_ku-cmp-line)}\n.knobs-cmp-grip{position:absolute;top:0;left:4px;width:16px;height:28px;border-radius:min(8px,calc(var(--_k-radius) * 999));background:var(--_k-bg-overlay);\n box-shadow:var(--_k-shadow-overlay),inset 0 0 0 1px var(--_k-border),inset 0 1px 0 var(--_k-rim);will-change:transform;transition:box-shadow calc(var(--_k-hover-out) * 1ms)}\n.knobs-cmp-grip::before,.knobs-cmp-grip::after{content:\"\";position:absolute;top:10px;width:1px;height:8px;background:var(--_k-fg-3);transition:background calc(var(--_k-hover-out) * 1ms)}\n.knobs-cmp-grip::before{left:6px}\n.knobs-cmp-grip::after{left:9px}\n.knobs-compare[data-dragging] .knobs-cmp-grip{box-shadow:var(--_k-shadow-overlay),inset 0 0 0 1px var(--_k-border-strong),inset 0 1px 0 var(--_k-rim)}\n.knobs-compare[data-dragging] .knobs-cmp-grip::before,.knobs-compare[data-dragging] .knobs-cmp-grip::after{background:var(--_k-fg)}\n.knobs-cmp-handle:focus-visible .knobs-cmp-grip,.knobs-compare[data-keyboard] .knobs-cmp-handle:focus .knobs-cmp-grip{box-shadow:var(--_k-shadow-overlay),0 0 0 2px var(--_k-accent)}\n/* The split's hairline, down the middle side by side. */\n.knobs-cmp-split{position:absolute;left:0;top:0;width:1px;height:0;margin-left:-.5px;background:color-mix(in srgb,var(--_k-bg) 72%,transparent);pointer-events:none;will-change:transform,opacity}\n/* Zoomed: how far, and a way back, in the stage's corner; it fades in and out, nothing shifts. */\n.knobs-cmp-zoom{position:absolute;right:8px;bottom:8px;display:flex;align-items:center;gap:4px;height:26px;padding:0 3px 0 10px;border-radius:999px;\n color:var(--_k-fg);font-size:var(--_k-text-meta);font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";white-space:nowrap;\n opacity:0;scale:.96;pointer-events:none;transition:opacity .16s cubic-bezier(.4,0,1,1),scale .16s cubic-bezier(.4,0,1,1)}\n.knobs-cmp-zoom[data-on]{opacity:1;scale:1;pointer-events:auto;transition:opacity .2s cubic-bezier(.2,.8,.2,1),scale .2s cubic-bezier(.2,.8,.2,1)}\n:where(.knobs-ui) .knobs-cmp-zoom-reset{all:revert;box-sizing:border-box;font:inherit;letter-spacing:inherit;margin:0;border:0;outline:none;box-shadow:none;\n display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border-radius:999px;background:transparent;color:var(--_k-fg-2);cursor:pointer;transition:color .15s,background .15s}\n:where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){color:var(--_k-fg);background:color-mix(in srgb,var(--_k-fg) 12%,transparent)}\n.knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--_k-fg-3);font-size:var(--_k-text-meta);pointer-events:none}\n.knobs-cmp-note:empty{display:none}\n.knobs-cmp-strip-host{flex:none;height:60px;min-height:0}\n.knobs-cmp-timeline-host{flex:none;min-height:0}\n/* The frame strip: Before over After per column, a difference bar under them, a dot where it peaks. */\n.knobs-ui.knobs-cmp-strip{--_ku-cmp-diff:var(--k-compare-diff,var(--_k-ok));position:relative;width:100%;height:100%;min-height:40px;overflow:hidden;cursor:col-resize;touch-action:none;\n font:var(--_k-weight) var(--_k-font-size)/1.35 var(--_k-font);color:var(--_k-fg)}\n.knobs-cmp-strip>canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}\n@media(prefers-reduced-motion:reduce){:is(.knobs-compare,.knobs-cmp-strip) :where(*,::before,::after){transition-duration:.12s!important}}\n";
@@ -3,7 +3,6 @@ export declare const MODE_INDEX: {
3
3
  readonly side: 0;
4
4
  readonly wipe: 1;
5
5
  readonly difference: 2;
6
- readonly flicker: 3;
7
6
  };
8
7
  export interface CompareDraw {
9
8
  /** Device px: where each side's picture lands (zoomed, it's larger than its clip). */
@@ -22,10 +21,6 @@ export interface CompareDraw {
22
21
  readonly to: number;
23
22
  /** 0 shows `from`, 1 shows `to`. */
24
23
  readonly mix: number;
25
- /** Before in After's place (X held). */
26
- readonly flick: boolean;
27
- /** Flicker mode's phase: Before showing. */
28
- readonly phase: boolean;
29
24
  readonly threshold: number;
30
25
  readonly gain: number;
31
26
  readonly accent: readonly [number, number, number];
@@ -1,5 +1,18 @@
1
1
  import type { TimeView } from "./timeline-model.js";
2
- export type CompareMode = "side" | "wipe" | "difference" | "flicker";
2
+ /** Side by side, a wipe, or (opt in) a difference. */
3
+ export type CompareMode = "side" | "wipe" | "difference";
4
+ /**
5
+ * The modes a viewer offers (`["side", "wipe"]` unless given; `difference` only when asked for),
6
+ * in their order, and the mode it starts in (the first offered when the asked one isn't).
7
+ */
8
+ export declare function compareModes(modes?: readonly CompareMode[], mode?: CompareMode): {
9
+ readonly modes: readonly CompareMode[];
10
+ readonly mode: CompareMode;
11
+ };
12
+ /** The mode a key picks among those offered: a digit by position, or S, W, D. */
13
+ export declare function modeForKey(key: string, modes: readonly CompareMode[]): CompareMode | null;
14
+ /** A mode's letter key (S, W, D). */
15
+ export declare const modeKey: (mode: CompareMode) => string;
3
16
  export type MediaKind = "video" | "image";
4
17
  /** A source's kind: as given, else by its extension (a video's, or an image). */
5
18
  export declare function mediaKind(src: string, kind?: MediaKind): MediaKind;
@@ -76,7 +89,7 @@ export interface CompareLayout {
76
89
  readonly after: Rect;
77
90
  readonly split: number;
78
91
  };
79
- /** Overlaid (wipe, difference, flicker): both in the same place. */
92
+ /** Overlaid (wipe, difference): both in the same place. */
80
93
  readonly overlay: {
81
94
  readonly before: Rect;
82
95
  readonly after: Rect;
@@ -134,6 +147,22 @@ export declare function wipeGrab(x: number, rect: Rect, wipe: number, slop?: num
134
147
  onLine: boolean;
135
148
  offset: number;
136
149
  };
150
+ /**
151
+ * Wiping, Before and After ride either side of the seam at `x`, `gap` from it, each fading out as
152
+ * its side runs out of room (`left`/`right`: the wipe's edges; `wb`/`wa`: the labels' widths).
153
+ */
154
+ export declare function seamLabels(x: number, left: number, right: number, wb: number, wa: number, gap?: number): {
155
+ before: {
156
+ x: number;
157
+ opacity: number;
158
+ };
159
+ after: {
160
+ x: number;
161
+ opacity: number;
162
+ };
163
+ };
164
+ /** Where the wipe's grip sits for a pointer at `y`: its top, kept `margin` inside the line. */
165
+ export declare function gripTop(y: number, rect: Rect, grip: number, margin?: number): number;
137
166
  /** The wipe moved by a key: 1% a press, 10% with Shift. */
138
167
  export declare const wipeKey: (wipe: number, dir: -1 | 1, big?: boolean) => number;
139
168
  export interface StripColumn {
@@ -29,8 +29,13 @@ export interface CompareSource {
29
29
  export interface CompareOptions extends UiLook {
30
30
  readonly before: CompareSource;
31
31
  readonly after: CompareSource;
32
- /** `"side"` (side by side) by default. */
32
+ /** The first of `modes` (`"side"`, side by side) by default. */
33
33
  readonly mode?: CompareMode;
34
+ /**
35
+ * The modes it offers, in the mode bar's order and on `1`–`3`: `["side", "wipe"]` by default.
36
+ * Add `"difference"` to offer a difference. One mode hides the bar.
37
+ */
38
+ readonly modes?: readonly CompareMode[];
34
39
  /** Where the wipe's line sits, 0 (all After) to 1 (all Before); 0.5. */
35
40
  readonly wipe?: number;
36
41
  /** Frames per second (the bound timeline's, else 30): steps, and where paused videos land. */
@@ -41,8 +46,8 @@ export interface CompareOptions extends UiLook {
41
46
  readonly threshold?: number;
42
47
  /**
43
48
  * The clock: an existing `timeline()` (its time drives both sides; while playing it follows
44
- * After), or `true` for one of its own under the viewer. Without one, `seek`, `play` and keys
45
- * still work.
49
+ * After), or `true` for a slim one of its own under the viewer (the `"lane"` variant: its
50
+ * markers are chapter ticks). Without one, `seek`, `play` and keys still work.
46
51
  */
47
52
  readonly timeline?: Timeline | boolean;
48
53
  /** The frame strip over the timeline (off; one timeline is made if there's none). */
@@ -68,6 +73,8 @@ export interface CompareOptions extends UiLook {
68
73
  export interface Compare {
69
74
  readonly element: HTMLElement;
70
75
  readonly mode: CompareMode;
76
+ /** The modes it offers. */
77
+ readonly modes: readonly CompareMode[];
71
78
  readonly wipe: number;
72
79
  readonly loupe: boolean;
73
80
  /** Seconds. */
@@ -85,7 +92,13 @@ export interface Compare {
85
92
  readonly loop: CompareLoop | null;
86
93
  /** New sources, mode, wipe, loupe, threshold or fps. A new mode glides in. */
87
94
  update(next: Partial<Pick<CompareOptions, "before" | "after" | "mode" | "wipe" | "loupe" | "threshold" | "fps">>): void;
88
- seek(time: number): void;
95
+ /**
96
+ * `glide`: a jump the hand didn't make (a chapter's click): the timeline's playhead catches up
97
+ * from where it is while the videos land at once.
98
+ */
99
+ seek(time: number, options?: {
100
+ readonly glide?: boolean;
101
+ }): void;
89
102
  /** Moves by `seconds`, the timeline's playhead gliding there (playing carries on). */
90
103
  seekBy(seconds: number): void;
91
104
  play(): void;
@@ -0,0 +1,40 @@
1
+ declare const PATHS: {
2
+ readonly arrowLeft: "M224,128a8,8,0,0,1-8,8H59.31l58.35,58.34a8,8,0,0,1-11.32,11.32l-72-72a8,8,0,0,1,0-11.32l72-72a8,8,0,0,1,11.32,11.32L59.31,120H216A8,8,0,0,1,224,128Z";
3
+ readonly arrowUpRight: "M200,64V168a8,8,0,0,1-16,0V83.31L69.66,197.66a8,8,0,0,1-11.32-11.32L172.69,72H88a8,8,0,0,1,0-16H192A8,8,0,0,1,200,64Z";
4
+ readonly arrowSquareOut: "M224,104a8,8,0,0,1-16,0V59.32l-66.33,66.34a8,8,0,0,1-11.32-11.32L196.68,48H152a8,8,0,0,1,0-16h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z";
5
+ readonly arrowCounterClockwise: "M224,128a96,96,0,0,1-94.71,96H128A95.38,95.38,0,0,1,62.1,197.8a8,8,0,0,1,11-11.63A80,80,0,1,0,71.43,71.39a3.07,3.07,0,0,1-.26.25L44.59,96H72a8,8,0,0,1,0,16H24a8,8,0,0,1-8-8V56a8,8,0,0,1,16,0V85.8L60.25,60A96,96,0,0,1,224,128Z";
6
+ readonly arrowUDownLeft: "M232,112a64.07,64.07,0,0,1-64,64H51.31l34.35,34.34a8,8,0,0,1-11.32,11.32l-48-48a8,8,0,0,1,0-11.32l48-48a8,8,0,0,1,11.32,11.32L51.31,160H168a48,48,0,0,0,0-96H80a8,8,0,0,1,0-16h88A64.07,64.07,0,0,1,232,112Z";
7
+ readonly arrowsHorizontal: "M136,40V216a8,8,0,0,1-16,0V40a8,8,0,0,1,16,0ZM96,120H35.31l18.35-18.34A8,8,0,0,0,42.34,90.34l-32,32a8,8,0,0,0,0,11.32l32,32a8,8,0,0,0,11.32-11.32L35.31,136H96a8,8,0,0,0,0-16Zm149.66,2.34-32-32a8,8,0,0,0-11.32,11.32L220.69,120H160a8,8,0,0,0,0,16h60.69l-18.35,18.34a8,8,0,0,0,11.32,11.32l32-32A8,8,0,0,0,245.66,122.34Z";
8
+ readonly caretDown: "M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z";
9
+ readonly caretLeft: "M165.66,202.34a8,8,0,0,1-11.32,11.32l-80-80a8,8,0,0,1,0-11.32l80-80a8,8,0,0,1,11.32,11.32L91.31,128Z";
10
+ readonly caretRight: "M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z";
11
+ readonly caretUp: "M213.66,165.66a8,8,0,0,1-11.32,0L128,91.31,53.66,165.66a8,8,0,0,1-11.32-11.32l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,213.66,165.66Z";
12
+ readonly check: "M229.66,77.66l-128,128a8,8,0,0,1-11.32,0l-56-56a8,8,0,0,1,11.32-11.32L96,188.69,218.34,66.34a8,8,0,0,1,11.32,11.32Z";
13
+ readonly checkCircle: "M173.66,98.34a8,8,0,0,1,0,11.32l-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35A8,8,0,0,1,173.66,98.34ZM232,128A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z";
14
+ readonly circle: "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,216Z";
15
+ readonly copy: "M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z";
16
+ readonly cornersIn: "M152,96V48a8,8,0,0,1,16,0V88h40a8,8,0,0,1,0,16H160A8,8,0,0,1,152,96ZM96,152H48a8,8,0,0,0,0,16H88v40a8,8,0,0,0,16,0V160A8,8,0,0,0,96,152Zm112,0H160a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V168h40a8,8,0,0,0,0-16ZM96,40a8,8,0,0,0-8,8V88H48a8,8,0,0,0,0,16H96a8,8,0,0,0,8-8V48A8,8,0,0,0,96,40Z";
17
+ readonly cornersOut: "M216,48V88a8,8,0,0,1-16,0V56H168a8,8,0,0,1,0-16h40A8,8,0,0,1,216,48ZM88,200H56V168a8,8,0,0,0-16,0v40a8,8,0,0,0,8,8H88a8,8,0,0,0,0-16Zm120-40a8,8,0,0,0-8,8v32H168a8,8,0,0,0,0,16h40a8,8,0,0,0,8-8V168A8,8,0,0,0,208,160ZM88,40H48a8,8,0,0,0-8,8V88a8,8,0,0,0,16,0V56H88a8,8,0,0,0,0-16Z";
18
+ readonly folder: "M216,72H130.67L102.93,51.2a16.12,16.12,0,0,0-9.6-3.2H40A16,16,0,0,0,24,64V200a16,16,0,0,0,16,16H216.89A15.13,15.13,0,0,0,232,200.89V88A16,16,0,0,0,216,72Zm0,128H40V64H93.33L123.2,86.4A8,8,0,0,0,128,88h88Z";
19
+ readonly keyboard: "M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192Zm-16-64a8,8,0,0,1-8,8H56a8,8,0,0,1,0-16H200A8,8,0,0,1,208,128Zm0-32a8,8,0,0,1-8,8H56a8,8,0,0,1,0-16H200A8,8,0,0,1,208,96ZM72,160a8,8,0,0,1-8,8H56a8,8,0,0,1,0-16h8A8,8,0,0,1,72,160Zm96,0a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,160Zm40,0a8,8,0,0,1-8,8h-8a8,8,0,0,1,0-16h8A8,8,0,0,1,208,160Z";
20
+ readonly magnifyingGlass: "M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z";
21
+ readonly magnifyingGlassMinus: "M152,112a8,8,0,0,1-8,8H80a8,8,0,0,1,0-16h64A8,8,0,0,1,152,112Zm77.66,117.66a8,8,0,0,1-11.32,0l-50.06-50.07a88.11,88.11,0,1,1,11.31-11.31l50.07,50.06A8,8,0,0,1,229.66,229.66ZM112,184a72,72,0,1,0-72-72A72.08,72.08,0,0,0,112,184Z";
22
+ readonly magnifyingGlassPlus: "M152,112a8,8,0,0,1-8,8H120v24a8,8,0,0,1-16,0V120H80a8,8,0,0,1,0-16h24V80a8,8,0,0,1,16,0v24h24A8,8,0,0,1,152,112Zm77.66,117.66a8,8,0,0,1-11.32,0l-50.06-50.07a88.11,88.11,0,1,1,11.31-11.31l50.07,50.06A8,8,0,0,1,229.66,229.66ZM112,184a72,72,0,1,0-72-72A72.08,72.08,0,0,0,112,184Z";
23
+ readonly microphone: "M128,176a48.05,48.05,0,0,0,48-48V64a48,48,0,0,0-96,0v64A48.05,48.05,0,0,0,128,176ZM96,64a32,32,0,0,1,64,0v64a32,32,0,0,1-64,0Zm40,143.6V240a8,8,0,0,1-16,0V207.6A80.11,80.11,0,0,1,48,128a8,8,0,0,1,16,0,64,64,0,0,0,128,0,8,8,0,0,1,16,0A80.11,80.11,0,0,1,136,207.6Z";
24
+ readonly paperPlaneRight: "M231.87,114l-168-95.89A16,16,0,0,0,40.92,37.34L71.55,128,40.92,218.67A16,16,0,0,0,56,240a16.15,16.15,0,0,0,7.93-2.1l167.92-96.05a16,16,0,0,0,.05-27.89ZM56,224a.56.56,0,0,0,0-.12L85.74,136H144a8,8,0,0,0,0-16H85.74L56.06,32.16A.46.46,0,0,0,56,32l168,95.83Z";
25
+ readonly pencilSimple: "M227.31,73.37,182.63,28.68a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H92.69A15.86,15.86,0,0,0,104,219.31L227.31,96a16,16,0,0,0,0-22.63ZM92.69,208H48V163.31l88-88L180.69,120ZM192,108.68,147.31,64l24-24L216,84.68Z";
26
+ readonly repeat: "M24,128A72.08,72.08,0,0,1,96,56H204.69L194.34,45.66a8,8,0,0,1,11.32-11.32l24,24a8,8,0,0,1,0,11.32l-24,24a8,8,0,0,1-11.32-11.32L204.69,72H96a56.06,56.06,0,0,0-56,56,8,8,0,0,1-16,0Zm200-8a8,8,0,0,0-8,8,56.06,56.06,0,0,1-56,56H51.31l10.35-10.34a8,8,0,0,0-11.32-11.32l-24,24a8,8,0,0,0,0,11.32l24,24a8,8,0,0,0,11.32-11.32L51.31,200H160a72.08,72.08,0,0,0,72-72A8,8,0,0,0,224,120Z";
27
+ readonly sidebar: "M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM40,56H80V200H40ZM216,200H96V56H216V200Z";
28
+ readonly x: "M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z";
29
+ };
30
+ export type IconName = keyof typeof PATHS;
31
+ /** Every glyph's name. */
32
+ export declare const ICON_NAMES: readonly IconName[];
33
+ /**
34
+ * A Phosphor regular glyph as SVG markup, in `currentColor`: 16 px for controls, 12 px (`small`)
35
+ * inline. Decorative (`aria-hidden`); label the control it sits in.
36
+ */
37
+ export declare function icon(name: IconName, options?: {
38
+ readonly small?: boolean;
39
+ }): string;
40
+ export {};
@@ -8,15 +8,17 @@ export { commandPalette, type Command, type CommandPalette, type CommandPaletteO
8
8
  export { contextMenu, menu, type ContextMenu, type ContextMenuOptions, type Menu, type MenuCloseReason, type MenuEntry, type MenuItem, type MenuOptions, } from "./menu.js";
9
9
  export { popover, type Popover, type PopoverCloseReason, type PopoverOptions } from "./popover.js";
10
10
  export { readout, type Readout } from "./readouts.js";
11
+ export { icon, ICON_NAMES, type IconName } from "./icons.js";
12
+ export { planPill, pillBoxOf, pillProgress, pillRadius, pillSpring, selectionPill, type PillBox, type PillPlan, type SelectionPill, type SelectionPillOptions, } from "./selection-pill.js";
11
13
  export { toast, type Toast, type ToastOptions } from "./toast.js";
12
14
  export { tooltip, tooltips, type TooltipContent, type TooltipOptions } from "./tooltip.js";
13
15
  export { split, type PaneAction, type PaneOptions, type Split, type SplitFold, type SplitOptions, type SplitPane, } from "./split.js";
14
16
  export { COLLAPSE_PAST, drag as dragDivider, parseLayout, softClamp, solve as solveSplit, type PaneSpec, type SplitDirection, type SplitLayout, } from "./split-model.js";
15
17
  export { timeline, type SeekSource, type Timeline, type TimelineMarker, type TimelineListener, type TimelineOptions, type TimelineRange, } from "./timeline.js";
16
- export { adjacentMarker, advance, clampView, followView, frameTime, magnet, rulerTicks, scrubTime, timeLabel, toFrame, zoomView, type Tick, type Ticks, type TimeUnits, type TimeView, } from "./timeline-model.js";
18
+ export { adjacentMarker, advance, CATCH_UP, clampView, currentMarker, followView, frameTime, magnet, moveHead, rulerTicks, scrubTime, timeLabel, toFrame, zoomView, type HeadPosition, type Tick, type Ticks, type TimeUnits, type TimeView, } from "./timeline-model.js";
17
19
  export { compare, COMPARE_FFMPEG, type Compare, type CompareLoop, type CompareMode, type CompareOptions, type CompareSource, type CompareView, type MediaKind, type ZoomRegion, } from "./compare.js";
18
20
  export { compareStrip, type CompareStrip, type CompareStripOptions } from "./compare-strip.js";
19
- export { compareLayout, frameMidpoint, frameOf, letterbox, mediaKind, meanAbsDiff, requestSeek, seeked, seekTime, stripColumns, stripPeaks, syncAction, wipeAt, wipeGrab, wipeKey, wipeX, zoomAbout, type CompareLayout, type SeekState, type StripColumn, type SyncAction, } from "./compare-model.js";
21
+ export { compareLayout, compareModes, frameMidpoint, frameOf, gripTop, letterbox, mediaKind, meanAbsDiff, modeForKey, requestSeek, seamLabels, seeked, seekTime, stripColumns, stripPeaks, syncAction, wipeAt, wipeGrab, wipeKey, wipeX, zoomAbout, type CompareLayout, type SeekState, type StripColumn, type SyncAction, } from "./compare-model.js";
20
22
  export { tree, type Tree, type TreeOptions, type TreeRowContext, type TreeToggle } from "./tree.js";
21
23
  export { applyMove, plainAccess, dropTarget, flatten, indexTree, matchLabel, navigate, select, stepMove, topmost, typeahead, validMove, virtualWindow, type DropTarget, type FlatRow, type Selection, type TreeAccess, type TreeFilter, type TreeMove, } from "./tree-model.js";
22
24
  export { codeDiff, diffCounts, diffReview, diffStatus, type CodeDiff, type CodeDiffOptions, type CodeDiffUpdate, type DiffLayout, type DiffLines, type DiffReview, type DiffReviewOptions, } from "./diff.js";
@@ -28,5 +30,5 @@ export { diffActivity, flattenActivity, formatDuration, indexActivity, keepSelec
28
30
  export { optionPicker, type OptionPicker, type OptionPickerOptions, type PickerOption, } from "./picker.js";
29
31
  export { claimsDigit, digitPick, keepPick, stepPick } from "./picker-model.js";
30
32
  export { tasteTest, walkthrough, type TasteTest, type TasteTestOptions, type Walkthrough, type WalkthroughOptions, } from "./walkthrough.js";
31
- export { mediaSlot, type MediaSlot, type MediaSlotOptions } from "./walkthrough-media.js";
32
- export { collectFeedback, feedbackMarkdown, inlineMarkdown, normalizeWalkthrough, readState as readWalkthroughState, walkthroughProgress, type ContextEvent, type FeedbackItem, type FeedbackNote, type FeedItem, type MediaContext, type NoteContext, type WalkInk, type WalkNote, type WalkVoice, type WalkthroughQA, type WalkthroughUpdate, type WalkPage, type WalkStep, type WalkthroughDoc, type WalkthroughFeedback, type WalkthroughMedia, type WalkthroughMeta, type WalkthroughOption, type WalkthroughSection, type WalkthroughSource, type WalkthroughState, type WalkthroughStatus, type WalkthroughStep, } from "./walkthrough-model.js";
33
+ export { mediaSlot, type MediaSlot, type MediaSlotOptions, type StepLinks, } from "./walkthrough-media.js";
34
+ export { collectFeedback, feedbackMarkdown, inlineMarkdown, normalizeWalkthrough, readState as readWalkthroughState, stackLayout, walkthroughProgress, type ContextEvent, type FeedbackItem, type FeedbackNote, type FeedItem, type MediaContext, type NoteContext, type StackLayout, type StackRow, type WalkInk, type WalkNote, type WalkVoice, type WalkthroughQA, type WalkthroughUpdate, type WalkPage, type WalkStep, type WalkthroughChapter, type WalkthroughDoc, type WalkthroughEvidence, type WalkthroughFeedback, type WalkthroughHistoryEvent, type WalkthroughHistoryGroup, type WalkthroughMedia, type WalkthroughMeta, type WalkthroughOption, type WalkthroughSection, type WalkthroughSource, type WalkthroughStackItem, type WalkthroughState, type WalkthroughStatus, type WalkthroughStep, type WalkthroughTableCell, type WalkthroughTableColumn, type WalkthroughTableRow, type WalkthroughTone, } from "./walkthrough-model.js";
@@ -0,0 +1 @@
1
+ export declare const selectionPillCss = "\n.knobs-pick-pill,.knobs-pick-copy{position:absolute;left:0;top:0;width:0;height:0;pointer-events:none;transition:opacity .1s linear}\n.knobs-pick-pill{background:var(--_k-fill-selected);will-change:transform}\n.knobs-pick-copy{overflow:hidden;will-change:transform}\n.knobs-pick-copy-rows{position:absolute;left:0;top:0;width:0;height:0}\n:is(.knobs-pick-pill,.knobs-pick-copy)[data-off]{opacity:0}\n";
@@ -0,0 +1,103 @@
1
+ import { type SpringValue } from "../core/spring.js";
2
+ /** A box in the container's coordinates (its padding box, scrolled content included). */
3
+ export interface PillBox {
4
+ readonly x: number;
5
+ readonly y: number;
6
+ readonly w: number;
7
+ readonly h: number;
8
+ }
9
+ export interface SelectionPillOptions {
10
+ /** The selected row, or null for none. Read on `update()`. */
11
+ selected(): HTMLElement | null;
12
+ /**
13
+ * The rows the pill moves between, for the bright copy. The container's own children by
14
+ * default (the pill's parts left out).
15
+ */
16
+ rows?(): Iterable<HTMLElement>;
17
+ /** A row's corner radius (px); its computed `border-top-left-radius` by default. */
18
+ radius?(row: HTMLElement): number;
19
+ /** The bright copy of the rows clipped to the pill (true). */
20
+ copy?: boolean;
21
+ /**
22
+ * The copy's text colour (`var(--_k-fg)`), set on each copied row; a row's parts with colours
23
+ * of their own keep them unless you restyle them under `.knobs-pick-copy`.
24
+ */
25
+ color?: string;
26
+ }
27
+ export interface SelectionPill {
28
+ /** The fill. */
29
+ readonly element: HTMLElement;
30
+ /**
31
+ * Reads the selection and the rows again (after a click, a key, new content). The pill travels
32
+ * to a new row; `snap` lands it there instead (content swapped wholesale, a row that moved with
33
+ * its list).
34
+ */
35
+ update(options?: {
36
+ readonly snap?: boolean;
37
+ }): void;
38
+ dispose(): void;
39
+ }
40
+ /** The state spring for a trip of `distance` px, 1.4× as long past 400 px. */
41
+ export declare function pillSpring(distance: number, base?: SpringValue): SpringValue;
42
+ /** Where `row` sits in `container`'s coordinates, from their client rects and its scroll. */
43
+ export declare function pillBoxOf(row: {
44
+ left: number;
45
+ top: number;
46
+ width: number;
47
+ height: number;
48
+ }, container: {
49
+ left: number;
50
+ top: number;
51
+ scrollLeft: number;
52
+ scrollTop: number;
53
+ clientLeft: number;
54
+ clientTop: number;
55
+ }): PillBox;
56
+ /**
57
+ * The radius on the way from one row to the next: it follows the height when the rows differ in
58
+ * height (so the pill keeps each row's proportion), else the trip's progress `k`.
59
+ */
60
+ export declare function pillRadius(from: {
61
+ readonly h: number;
62
+ readonly r: number;
63
+ }, to: {
64
+ readonly h: number;
65
+ readonly r: number;
66
+ }, h: number, k: number): number;
67
+ /** How far along a trip from `from` to `to` the box `at` is (1 when there's no trip). */
68
+ export declare function pillProgress(from: PillBox, to: PillBox, at: PillBox): number;
69
+ export type PillPlan = {
70
+ readonly kind: "hide";
71
+ } | {
72
+ readonly kind: "stay";
73
+ } | {
74
+ readonly kind: "land";
75
+ readonly box: PillBox;
76
+ } | {
77
+ readonly kind: "travel";
78
+ readonly box: PillBox;
79
+ readonly spring: SpringValue;
80
+ };
81
+ /**
82
+ * What the pill does next. Nothing selected: it fades out in place. Shown for the first time, after
83
+ * a fade-out, on first paint, with reduced motion or asked to snap: it lands on the row. Otherwise
84
+ * it travels there from wherever it is (mid-trip included), on a spring for the distance.
85
+ */
86
+ export declare function planPill(state: {
87
+ readonly shown: boolean;
88
+ readonly at: PillBox | null;
89
+ readonly target: PillBox | null;
90
+ }, next: PillBox | null, flags?: {
91
+ readonly first?: boolean;
92
+ readonly reduced?: boolean;
93
+ readonly snap?: boolean;
94
+ }): PillPlan;
95
+ /** Whether two boxes overlap. */
96
+ export declare const boxesMeet: (a: PillBox, b: PillBox) => boolean;
97
+ /** The box around both. */
98
+ export declare const boxUnion: (a: PillBox, b: PillBox) => PillBox;
99
+ /**
100
+ * The selection pill over `container`'s rows. The container is positioned if it isn't; its rows
101
+ * may be anywhere in it (flex children, absolutely placed, scrolled), as the pill measures them.
102
+ */
103
+ export declare function selectionPill(container: HTMLElement, options: SelectionPillOptions): SelectionPill;
@@ -81,3 +81,26 @@ export declare function advance(t: number, dt: number, o: {
81
81
  ended: boolean;
82
82
  wrapped: boolean;
83
83
  };
84
+ /** A jump the hand didn't make catches up on this: quick, no bounce. */
85
+ export declare const CATCH_UP: {
86
+ readonly duration: 0.15;
87
+ readonly bounce: 0;
88
+ };
89
+ /** Where the playhead is drawn (`x`) and where it's going (`target`), in seconds. */
90
+ export interface HeadPosition {
91
+ readonly x: number;
92
+ readonly target: number;
93
+ }
94
+ /**
95
+ * The playhead's next move. A `jump` (a chapter or marker click, a loop's wrap, a press on the
96
+ * lane away from it, play from elsewhere, a glide from code) catches up from where it's drawn when
97
+ * it's more than `minGap` seconds away. A `follow` (a drag, the clock, a step) lands 1:1; during a
98
+ * catch-up it shifts both ends, so it follows the hand and the remaining offset settles on its own.
99
+ */
100
+ export declare function moveHead(head: HeadPosition, t: number, motion: "jump" | "follow", catching: boolean, minGap?: number): HeadPosition & {
101
+ readonly catching: boolean;
102
+ };
103
+ /** The last marker at or before `t` (half a frame's leeway): the current chapter. */
104
+ export declare function currentMarker<M extends {
105
+ readonly time: number;
106
+ }>(markers: readonly M[], t: number, fps: number): M | null;
@@ -45,6 +45,13 @@ export interface TimelineOptions extends UiLook {
45
45
  readonly step: number;
46
46
  readonly shift: number;
47
47
  };
48
+ /**
49
+ * `"editor"` (the default): a ruler with labels over a lane of markers to add, drag and name,
50
+ * zoomed and panned by the wheel. `"lane"`: one slim lane under a compare or a video, with ticks
51
+ * and no labels, markers as faint chapter ticks (the current one in text colour), nothing to
52
+ * edit, and the wheel left to the page.
53
+ */
54
+ readonly variant?: "editor" | "lane";
48
55
  readonly label?: string;
49
56
  /** The time moved: scrubbed, stepped, jumped, played (every frame) or set from code. */
50
57
  onSeek?(time: number, source: SeekSource): void;
@@ -82,7 +89,10 @@ export interface Timeline {
82
89
  readonly markers: readonly TimelineMarker[];
83
90
  readonly ranges: readonly TimelineRange[];
84
91
  readonly view: TimeView;
85
- /** `glide`: the playhead springs there (the time, and what it drives, land at once). */
92
+ /**
93
+ * `glide`: a jump the hand didn't make (a chapter's click, say): the playhead catches up from
94
+ * where it is on a quick spring; the time, and what it drives, land at once.
95
+ */
86
96
  seek(time: number, options?: {
87
97
  readonly glide?: boolean;
88
98
  }): void;
@@ -64,8 +64,9 @@ export interface TreeOptions<T> extends UiLook {
64
64
  */
65
65
  readonly hints?: boolean;
66
66
  /**
67
- * The selected row (one) shows as one highlight that glides to the next row selected, on the
68
- * rows' own spring, instead of each row lighting in place. Several selected rows light in place.
67
+ * The selected row (one) shows as the selection pill (`selectionPill`): one highlight that slides
68
+ * to the next row selected on the state spring, the row's text sharp and bright under it, instead
69
+ * of each row lighting in place. Several selected rows light in place.
69
70
  */
70
71
  readonly glide?: boolean;
71
72
  }