@kitlangton/knobs 0.4.0-next.1 → 0.4.0-next.11
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 +191 -13
- package/dist/dev/{chunk-ayb292zj.js → chunk-75gbzbyd.js} +3 -3
- package/dist/dev/{chunk-1qzffbpa.js → chunk-bnhzf1tj.js} +240 -87
- package/dist/dev/{chunk-8mabjeyk.js → chunk-j57rhjtm.js} +166 -2
- package/dist/dev/{chunk-3ygqgy1x.js → chunk-mjdgzad5.js} +15 -2
- package/dist/dev/index.js +37 -14
- package/dist/index.js +46 -11
- package/dist/panel.js +408 -73
- package/dist/review-react.js +18580 -0
- package/dist/review-solid.js +18482 -0
- package/dist/review.js +18488 -0
- package/dist/themes.js +281 -23
- package/dist/types/core/remote.d.ts +2 -0
- package/dist/types/core/schema.d.ts +13 -1
- package/dist/types/core/store.d.ts +8 -0
- package/dist/types/panel/gpu/renderer.d.ts +2 -0
- package/dist/types/panel/presets.d.ts +7 -1
- 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/tokens/schema.d.ts +180 -0
- package/dist/types/ui/compare-css.d.ts +1 -1
- package/dist/types/ui/compare-gpu.d.ts +6 -6
- package/dist/types/ui/compare-model.d.ts +85 -2
- package/dist/types/ui/compare.d.ts +18 -4
- package/dist/types/ui/diff.d.ts +4 -5
- package/dist/types/ui/history-css.d.ts +1 -0
- package/dist/types/ui/history-model.d.ts +249 -0
- package/dist/types/ui/history.d.ts +38 -0
- package/dist/types/ui/icons.d.ts +40 -0
- package/dist/types/ui/index.d.ts +8 -4
- package/dist/types/ui/player-css.d.ts +1 -0
- package/dist/types/ui/player.d.ts +51 -0
- 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-css.d.ts +1 -0
- package/dist/types/ui/selection-pill.d.ts +106 -0
- package/dist/types/ui/timeline-model.d.ts +27 -0
- package/dist/types/ui/timeline.d.ts +16 -1
- package/dist/types/ui/tree.d.ts +3 -2
- package/dist/types/ui/walkthrough-annotations.d.ts +42 -0
- package/dist/types/ui/walkthrough-blocks.d.ts +87 -0
- package/dist/types/ui/walkthrough-media.d.ts +30 -1
- package/dist/types/ui/walkthrough-model.d.ts +469 -5
- package/dist/types/ui/walkthrough.d.ts +27 -5
- package/dist/ui-react.js +5124 -1031
- package/dist/ui-solid.js +5136 -1043
- package/dist/ui.js +6411 -2269
- package/package.json +13 -1
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { knobs } from "./knobs.js";
|
|
2
|
+
import { reviewTheme } from "./review.js";
|
|
2
3
|
import { voidTheme } from "./void.js";
|
|
3
4
|
export { APCA_BUDGET, type Appearance as ThemeAppearance, type Density, defineTheme, type GpuColors, type Material, type ResolvedTokens, type Theme, type ThemeInputs, type ThemeSpec, type TokenOverrides, } from "./define.js";
|
|
4
|
-
export { knobs, voidTheme };
|
|
5
|
+
export { knobs, reviewTheme, voidTheme };
|
|
5
6
|
export type { Appearance } from "../core/appearance.js";
|
|
6
7
|
export type { PublicTokenName, TokenName, TokenProperty } from "../tokens/schema.js";
|
|
7
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* The shipped themes: Knobs (the default), Void (true black, flat, for OLED and video) and Review
|
|
10
|
+
* (the review pieces' own default: Void with hairlines you can see).
|
|
11
|
+
*/
|
|
8
12
|
export declare const themes: {
|
|
9
13
|
readonly knobs: import("./define.js").Theme;
|
|
10
14
|
readonly void: import("./define.js").Theme;
|
|
15
|
+
readonly review: import("./define.js").Theme;
|
|
11
16
|
};
|
|
12
17
|
export { labPreset, presetCss, problemsPreset, type TokenPreset } from "../core/theme.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The review pieces' own look (walkthrough, compare, player, diff, facts, decision): Void's true
|
|
3
|
+
* black, flat and neutral, with hairlines you can see. Borders are alpha of the text colour, set
|
|
4
|
+
* by APCA on the page: subtle ≈ Lc 9, default ≈ Lc 12, strong ≈ Lc 17, in both appearances
|
|
5
|
+
* (Void's composited 6% and 10% read Lc 0 on black). Fills step 6 / 10 / 14% so a hover's
|
|
6
|
+
* background is plain to see. Light is white, page and surface alike. The platform's own face.
|
|
7
|
+
*/
|
|
8
|
+
export declare const reviewTheme: import("./define.js").Theme;
|
|
@@ -409,6 +409,24 @@ export declare const TOKENS: readonly [{
|
|
|
409
409
|
readonly css: "var(--k-warn)";
|
|
410
410
|
};
|
|
411
411
|
readonly doc: "Modified lines.";
|
|
412
|
+
}, {
|
|
413
|
+
readonly name: "before";
|
|
414
|
+
readonly tier: "semantic";
|
|
415
|
+
readonly type: "color";
|
|
416
|
+
readonly group: "Data";
|
|
417
|
+
readonly source: {
|
|
418
|
+
readonly css: "var(--k-fg-3)";
|
|
419
|
+
};
|
|
420
|
+
readonly doc: "Before in a comparison, and only Before: its label and side of the seam. Neutral unless a theme gives it a colour.";
|
|
421
|
+
}, {
|
|
422
|
+
readonly name: "after";
|
|
423
|
+
readonly tier: "semantic";
|
|
424
|
+
readonly type: "color";
|
|
425
|
+
readonly group: "Data";
|
|
426
|
+
readonly source: {
|
|
427
|
+
readonly css: "var(--k-fg)";
|
|
428
|
+
};
|
|
429
|
+
readonly doc: "After in a comparison, and only After.";
|
|
412
430
|
}, {
|
|
413
431
|
readonly name: "series-1";
|
|
414
432
|
readonly tier: "semantic";
|
|
@@ -510,6 +528,168 @@ export declare const TOKENS: readonly [{
|
|
|
510
528
|
readonly value: "288px";
|
|
511
529
|
};
|
|
512
530
|
readonly doc: "Panel width.";
|
|
531
|
+
}, {
|
|
532
|
+
readonly name: "space-inside";
|
|
533
|
+
readonly tier: "semantic";
|
|
534
|
+
readonly type: "length";
|
|
535
|
+
readonly group: "Space";
|
|
536
|
+
readonly source: {
|
|
537
|
+
readonly css: "var(--k-unit)";
|
|
538
|
+
};
|
|
539
|
+
readonly doc: "Parts of one thing: an icon and its label, a meta line and its title.";
|
|
540
|
+
}, {
|
|
541
|
+
readonly name: "space-sibling";
|
|
542
|
+
readonly tier: "semantic";
|
|
543
|
+
readonly type: "length";
|
|
544
|
+
readonly group: "Space";
|
|
545
|
+
readonly source: {
|
|
546
|
+
readonly css: "calc(var(--k-unit) * 2)";
|
|
547
|
+
};
|
|
548
|
+
readonly doc: "Siblings in a group: buttons in a row, a list item's lines.";
|
|
549
|
+
}, {
|
|
550
|
+
readonly name: "space-title";
|
|
551
|
+
readonly tier: "semantic";
|
|
552
|
+
readonly type: "length";
|
|
553
|
+
readonly group: "Space";
|
|
554
|
+
readonly source: {
|
|
555
|
+
readonly css: "calc(var(--k-unit) * 3)";
|
|
556
|
+
};
|
|
557
|
+
readonly doc: "A heading and what it heads.";
|
|
558
|
+
}, {
|
|
559
|
+
readonly name: "space-group";
|
|
560
|
+
readonly tier: "semantic";
|
|
561
|
+
readonly type: "length";
|
|
562
|
+
readonly group: "Space";
|
|
563
|
+
readonly source: {
|
|
564
|
+
readonly css: "calc(var(--k-unit) * 12)";
|
|
565
|
+
};
|
|
566
|
+
readonly doc: "Groups inside a section (prose, video, diff), stacked media, feed items (a hairline in the middle).";
|
|
567
|
+
}, {
|
|
568
|
+
readonly name: "space-section";
|
|
569
|
+
readonly tier: "semantic";
|
|
570
|
+
readonly type: "length";
|
|
571
|
+
readonly group: "Space";
|
|
572
|
+
readonly source: {
|
|
573
|
+
readonly css: "calc(var(--k-unit) * 24)";
|
|
574
|
+
};
|
|
575
|
+
readonly doc: "Sections of a page (the intro, the updates, each PR), a hairline in the middle.";
|
|
576
|
+
}, {
|
|
577
|
+
readonly name: "space-column";
|
|
578
|
+
readonly tier: "semantic";
|
|
579
|
+
readonly type: "length";
|
|
580
|
+
readonly group: "Space";
|
|
581
|
+
readonly source: {
|
|
582
|
+
readonly css: "calc(var(--k-unit) * 6)";
|
|
583
|
+
};
|
|
584
|
+
readonly doc: "Columns: a contents rail and the page, media side by side.";
|
|
585
|
+
}, {
|
|
586
|
+
readonly name: "pad-page";
|
|
587
|
+
readonly tier: "semantic";
|
|
588
|
+
readonly type: "length";
|
|
589
|
+
readonly group: "Space";
|
|
590
|
+
readonly source: {
|
|
591
|
+
readonly css: "calc(var(--k-unit) * 6)";
|
|
592
|
+
};
|
|
593
|
+
readonly doc: "A page's edge; 16px under 640px wide.";
|
|
594
|
+
}, {
|
|
595
|
+
readonly name: "pad-card";
|
|
596
|
+
readonly tier: "semantic";
|
|
597
|
+
readonly type: "length";
|
|
598
|
+
readonly group: "Space";
|
|
599
|
+
readonly source: {
|
|
600
|
+
readonly css: "calc(var(--k-unit) * 3)";
|
|
601
|
+
};
|
|
602
|
+
readonly doc: "Inside a card or popover.";
|
|
603
|
+
}, {
|
|
604
|
+
readonly name: "type-heading";
|
|
605
|
+
readonly tier: "semantic";
|
|
606
|
+
readonly type: "length";
|
|
607
|
+
readonly group: "Type";
|
|
608
|
+
readonly source: {
|
|
609
|
+
readonly value: "20px";
|
|
610
|
+
};
|
|
611
|
+
readonly doc: "A page's title, weight 500.";
|
|
612
|
+
}, {
|
|
613
|
+
readonly name: "leading-heading";
|
|
614
|
+
readonly tier: "semantic";
|
|
615
|
+
readonly type: "length";
|
|
616
|
+
readonly group: "Type";
|
|
617
|
+
readonly source: {
|
|
618
|
+
readonly value: "28px";
|
|
619
|
+
};
|
|
620
|
+
readonly doc: "Line height for type-heading.";
|
|
621
|
+
}, {
|
|
622
|
+
readonly name: "type-title";
|
|
623
|
+
readonly tier: "semantic";
|
|
624
|
+
readonly type: "length";
|
|
625
|
+
readonly group: "Type";
|
|
626
|
+
readonly source: {
|
|
627
|
+
readonly value: "16px";
|
|
628
|
+
};
|
|
629
|
+
readonly doc: "Section titles (under their kicker), weight 500.";
|
|
630
|
+
}, {
|
|
631
|
+
readonly name: "leading-title";
|
|
632
|
+
readonly tier: "semantic";
|
|
633
|
+
readonly type: "length";
|
|
634
|
+
readonly group: "Type";
|
|
635
|
+
readonly source: {
|
|
636
|
+
readonly value: "24px";
|
|
637
|
+
};
|
|
638
|
+
readonly doc: "Line height for type-title.";
|
|
639
|
+
}, {
|
|
640
|
+
readonly name: "type-body";
|
|
641
|
+
readonly tier: "semantic";
|
|
642
|
+
readonly type: "length";
|
|
643
|
+
readonly group: "Type";
|
|
644
|
+
readonly source: {
|
|
645
|
+
readonly value: "13px";
|
|
646
|
+
};
|
|
647
|
+
readonly doc: "Prose, questions, list rows, step titles; 400, or 500 for emphasis.";
|
|
648
|
+
}, {
|
|
649
|
+
readonly name: "leading-body";
|
|
650
|
+
readonly tier: "semantic";
|
|
651
|
+
readonly type: "length";
|
|
652
|
+
readonly group: "Type";
|
|
653
|
+
readonly source: {
|
|
654
|
+
readonly value: "20px";
|
|
655
|
+
};
|
|
656
|
+
readonly doc: "Line height for type-body.";
|
|
657
|
+
}, {
|
|
658
|
+
readonly name: "type-label";
|
|
659
|
+
readonly tier: "semantic";
|
|
660
|
+
readonly type: "length";
|
|
661
|
+
readonly group: "Type";
|
|
662
|
+
readonly source: {
|
|
663
|
+
readonly value: "12px";
|
|
664
|
+
};
|
|
665
|
+
readonly doc: "Mono inside body text: code and paths.";
|
|
666
|
+
}, {
|
|
667
|
+
readonly name: "leading-label";
|
|
668
|
+
readonly tier: "semantic";
|
|
669
|
+
readonly type: "length";
|
|
670
|
+
readonly group: "Type";
|
|
671
|
+
readonly source: {
|
|
672
|
+
readonly value: "16px";
|
|
673
|
+
};
|
|
674
|
+
readonly doc: "Line height for type-label.";
|
|
675
|
+
}, {
|
|
676
|
+
readonly name: "type-small";
|
|
677
|
+
readonly tier: "semantic";
|
|
678
|
+
readonly type: "length";
|
|
679
|
+
readonly group: "Type";
|
|
680
|
+
readonly source: {
|
|
681
|
+
readonly value: "11px";
|
|
682
|
+
};
|
|
683
|
+
readonly doc: "Meta, controls, keys, timestamps; mono inside labels.";
|
|
684
|
+
}, {
|
|
685
|
+
readonly name: "leading-small";
|
|
686
|
+
readonly tier: "semantic";
|
|
687
|
+
readonly type: "length";
|
|
688
|
+
readonly group: "Type";
|
|
689
|
+
readonly source: {
|
|
690
|
+
readonly value: "16px";
|
|
691
|
+
};
|
|
692
|
+
readonly doc: "Line height for type-small.";
|
|
513
693
|
}, {
|
|
514
694
|
readonly name: "font-size";
|
|
515
695
|
readonly tier: "semantic";
|
|
@@ -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-
|
|
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-type-small)/var(--_k-leading-small) var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left}\n:where(.knobs-ui) :is(.knobs-cmp-mode,.knobs-cmp-toggle){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}\n.knobs-cmp-bar{flex:none;display:flex;align-items:center;gap:var(--_k-gap);height:var(--_k-control-h)}\n/* The modes: one fill, the selection pill on the one picked; a mode isn't brighter for being\n picked: the pill's bright copy is. */\n.knobs-cmp-modes{position:relative;display:inline-flex;height:var(--_k-control-h);border-radius:var(--_k-radius);background:var(--_k-fill)}\n.knobs-cmp-modes[hidden]{display:none}\n/* Hover is a quiet fill under the arrow cursor (no hand, no brightening), there at once. */\n.knobs-ui .knobs-cmp-mode{display:inline-flex;align-items:center;height:100%;padding:0 8px;border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:default;white-space:nowrap;\n transition:background calc(var(--_k-hover-out) * 1ms)}\n.knobs-ui .knobs-cmp-mode:not([aria-checked=\"true\"]):is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n/* Toggles: icon buttons, the accent's wash when on. */\n.knobs-ui .knobs-cmp-toggle{display:inline-flex;align-items:center;justify-content:center;width:var(--_k-control-h);height:var(--_k-control-h);border-radius:var(--_k-radius);color:var(--_k-fg-2);cursor:default;\n transition:background calc(var(--_k-hover-out) * 1ms)}\n.knobs-ui .knobs-cmp-toggle:is(:hover,:focus-visible){background:var(--_k-fill-hover);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-ui .knobs-cmp-toggle[aria-pressed=\"true\"]{color:var(--_k-accent-fg);background:var(--_k-accent-soft)}\n.knobs-cmp-toggle svg{display:block}\n.knobs-cmp-fill{flex:1}\n.knobs-cmp-toggle[hidden]{display:none}\n/* One surface: on a card (a walkthrough's step, a split's pane, anything .knobs-surface) or marked\n data-nested, the stage drops its fill and the sides sit on that card. */\n:where(.knobs-surface,.knobs-pane:not([data-nested])>.knobs-pane-clip) .knobs-ui.knobs-compare,.knobs-ui.knobs-compare[data-nested]{--_ku-cmp-stage:var(--k-compare-stage,transparent)}\n/* In a page's flow (a container with no height), it takes the height its sides need. */\n.knobs-ui.knobs-compare[data-auto]{height:auto}\n.knobs-compare[data-auto] .knobs-cmp-stage{flex:none;min-height:0}\n.knobs-cmp-stage{position:relative;flex:1;min-height:96px;overflow:hidden;border-radius:var(--_k-radius-panel);background:var(--_ku-cmp-stage);touch-action:pan-y;outline:none}\n.knobs-compare[data-frame=\"flat\"] .knobs-cmp-stage{border-radius:0}\n.knobs-compare[data-mode=\"wipe\"] .knobs-cmp-stage{cursor:ew-resize}\n/* Unzoomed, a finger still scrolls the page up and down; zoomed, the stage takes every gesture. */\n/* Zoomed, it pans: a move cursor, never a hand. */\n.knobs-compare[data-zoomed] .knobs-cmp-stage{cursor:move;touch-action:none}\n.knobs-compare[data-panning],.knobs-compare[data-panning] *{cursor:move!important}\n/* Wiping, the grip stands in for the cursor. */\n.knobs-compare[data-dragging],.knobs-compare[data-dragging] *{cursor:none!important}\n.knobs-cmp-sizer{position:absolute;left:0;right:0;top:0;height:0;visibility:hidden;pointer-events:none}\n.knobs-cmp-canvas{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none}\n.knobs-cmp-media{position:absolute;left:0;top:0;display:block;max-width:none;margin:0;padding:0;border:0;object-fit:fill;transform-origin:0 0;pointer-events:none;will-change:transform}\n.knobs-compare[data-renderer=\"gpu\"] .knobs-cmp-media{opacity:0}\n/* The media comes in with its first frames: a fade and a 4px blur on the default spring. */\n.knobs-cmp-canvas,.knobs-compare[data-renderer=\"dom\"] .knobs-cmp-media{transition:opacity calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default),filter calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default)}\n.knobs-compare:not([data-ready]) :is(.knobs-cmp-canvas,.knobs-cmp-media){opacity:0;filter:blur(4px)}\n/* Over the pictures: a quiet scrim, dark in either appearance, blurred, with no ring. */\n.knobs-cmp-label,.knobs-cmp-zoom,.knobs-cmp-grip{background:var(--_ku-media-scrim);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}\n/* \u2717 Before \u00B7 \u2713 After: Before quieter, After in full. Neutral: no colour of its own. */\n.knobs-cmp-label{position:absolute;left:0;top:0;display:flex;align-items:center;gap:4px;padding:1px 7px 1px 5px;border-radius:999px;font-weight:var(--_k-weight-label);\n white-space:nowrap;pointer-events:none;will-change:transform}\n.knobs-cmp-label[data-side=\"before\"]{color:var(--_ku-on-media-2)}\n.knobs-cmp-label[data-side=\"after\"]{color:var(--_ku-on-media)}\n/* Fusing, the mark folds away and the label is its name. */\n.knobs-cmp-mark{flex:none;display:flex;justify-content:flex-end;overflow:hidden}\n.knobs-cmp-mark svg{display:block;flex:none;width:12px;height:12px}\n/* The fuse's seam: a blurred strip over where the sides meet, soft at both sides. */\n.knobs-cmp-seam{position:absolute;left:0;top:0;width:8px;height:0;opacity:0;pointer-events:none;will-change:transform,opacity;\n -webkit-mask-image:linear-gradient(to right,transparent,#000 35%,#000 65%,transparent);mask-image:linear-gradient(to right,transparent,#000 35%,#000 65%,transparent)}\n/* The wipe: a hairline down the line with a raised grip in its middle (at the pointer's height\n while dragged); a wider strip takes the hand and the keys (a slider). It fades in with the\n fuse; wiping, line and grip brighten. */\n.knobs-cmp-handle{cursor:ew-resize;position:absolute;left:-12px;top:0;width:24px;height:0;opacity:0;pointer-events:none;outline:none;will-change:transform,opacity}\n.knobs-cmp-handle[data-on]{pointer-events:auto}\n.knobs-cmp-handle::before{content:\"\";position:absolute;top:0;bottom:0;left:11.5px;width:1px;background:color-mix(in srgb,var(--_ku-cmp-line) 72%,transparent);box-shadow:0 0 6px var(--_ku-media-scrim)}\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));will-change:transform}\n.knobs-cmp-grip::before,.knobs-cmp-grip::after{content:\"\";position:absolute;top:10px;width:1px;height:8px;background:var(--_ku-on-media-2);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::before,.knobs-compare[data-dragging] .knobs-cmp-grip::after{background:var(--_ku-on-media)}\n.knobs-cmp-handle:focus-visible .knobs-cmp-grip,.knobs-compare[data-keyboard] .knobs-cmp-handle:focus .knobs-cmp-grip{box-shadow: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(--_ku-on-media);font-variant-numeric:tabular-nums;font-feature-settings:var(--_kr-data,\"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(--_ku-on-media-2);cursor:default;transition:background calc(var(--_k-hover-out) * 1ms),color calc(var(--_k-hover-out) * 1ms)}\n:where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){background:color-mix(in srgb,var(--_ku-on-media) 16%,transparent);color:var(--_ku-on-media);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--_k-fg-3);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-type-small)/var(--_k-leading-small) 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). */
|
|
@@ -12,20 +11,21 @@ export interface CompareDraw {
|
|
|
12
11
|
/** Device px: the part of the stage each side may draw in. */
|
|
13
12
|
readonly beforeClip: Rect;
|
|
14
13
|
readonly afterClip: Rect;
|
|
14
|
+
/** Device px: the clips' corner radii, Before's left and right, then After's. */
|
|
15
|
+
readonly radii: readonly [number, number, number, number];
|
|
15
16
|
readonly width: number;
|
|
16
17
|
readonly height: number;
|
|
17
18
|
readonly dpr: number;
|
|
18
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Where Before is cut (device px: the split side by side, the wipe's line fused) and its soft
|
|
21
|
+
* edge either side (device px). Side and Wipe composite the same way; only the cut moves.
|
|
22
|
+
*/
|
|
19
23
|
readonly wipeX: number;
|
|
20
24
|
readonly soft: number;
|
|
21
25
|
readonly from: number;
|
|
22
26
|
readonly to: number;
|
|
23
27
|
/** 0 shows `from`, 1 shows `to`. */
|
|
24
28
|
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
29
|
readonly threshold: number;
|
|
30
30
|
readonly gain: number;
|
|
31
31
|
readonly accent: readonly [number, number, number];
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import type { TimeView } from "./timeline-model.js";
|
|
2
|
-
|
|
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,10 @@ export interface CompareLayout {
|
|
|
76
89
|
readonly after: Rect;
|
|
77
90
|
readonly split: number;
|
|
78
91
|
};
|
|
79
|
-
/**
|
|
92
|
+
/**
|
|
93
|
+
* Overlaid (wipe, difference): both in the same place, one side's size, centred on the split,
|
|
94
|
+
* so fusing never resizes anything.
|
|
95
|
+
*/
|
|
80
96
|
readonly overlay: {
|
|
81
97
|
readonly before: Rect;
|
|
82
98
|
readonly after: Rect;
|
|
@@ -84,6 +100,57 @@ export interface CompareLayout {
|
|
|
84
100
|
}
|
|
85
101
|
/** Where the two sides sit inside `box`, side by side and overlaid. */
|
|
86
102
|
export declare function compareLayout(box: Rect, before: Size, after: Size): CompareLayout;
|
|
103
|
+
/**
|
|
104
|
+
* Kit Motion's blend blur, in px: the feather Before's cut swells to mid-fuse, the blur of the
|
|
105
|
+
* strip over the seam at its peak (mid-fuse too), and the overlap the seam fades in over.
|
|
106
|
+
*/
|
|
107
|
+
export declare const FUSE: {
|
|
108
|
+
readonly feather: 32;
|
|
109
|
+
readonly blur: 8;
|
|
110
|
+
readonly seamFade: 48;
|
|
111
|
+
};
|
|
112
|
+
export interface FuseFrame {
|
|
113
|
+
/** Where Before is cut: the split side by side, the wipe's line fused. */
|
|
114
|
+
readonly cut: number;
|
|
115
|
+
/** The cut's soft edge, px either side of it. */
|
|
116
|
+
readonly feather: number;
|
|
117
|
+
/** The seam's (and the wipe handle's) opacity, 0–1. */
|
|
118
|
+
readonly seam: number;
|
|
119
|
+
/** The seam's blur (px): none apart or fused, `FUSE.blur` mid-fuse. */
|
|
120
|
+
readonly blur: number;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Kit Motion's Comparison fuse, one frame of it: side by side (`k` 0) the panes glide together
|
|
124
|
+
* into one (`k` 1). Before is cut only where the inner edges overlap, with a feather that swells
|
|
125
|
+
* mid-transition, and a blurred strip over the seam blends the two, strongest mid-transition
|
|
126
|
+
* (the blend blur); it fades in as they overlap. `before` and `after` are where the sides are
|
|
127
|
+
* drawn this frame.
|
|
128
|
+
*/
|
|
129
|
+
export declare function fuseFrame(L: CompareLayout, before: Rect, after: Rect, k: number, wipe: number): FuseFrame;
|
|
130
|
+
/**
|
|
131
|
+
* A label folded `fold` (0 open, 1 folded to its name): its mark's width, opacity and blur (px,
|
|
132
|
+
* up to `blur` as it goes, kit-motion's in-place exit).
|
|
133
|
+
*/
|
|
134
|
+
/**
|
|
135
|
+
* Each side's corner radii, `left` and `right` (px), so the frame is rounded at every frame of the
|
|
136
|
+
* fuse: a side's outer corners always take the frame's radius `r`; its inner ones (at the split)
|
|
137
|
+
* are square apart and grow to `r` as the sides fuse into one picture.
|
|
138
|
+
*/
|
|
139
|
+
export declare const fuseCorners: (r: number, k: number) => {
|
|
140
|
+
before: {
|
|
141
|
+
left: number;
|
|
142
|
+
right: number;
|
|
143
|
+
};
|
|
144
|
+
after: {
|
|
145
|
+
left: number;
|
|
146
|
+
right: number;
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
export declare const labelFold: (fold: number, mark: number, blur?: number) => {
|
|
150
|
+
width: number;
|
|
151
|
+
opacity: number;
|
|
152
|
+
blur: number;
|
|
153
|
+
};
|
|
87
154
|
/** The height a split screen of `w` needs so neither side has margins: half its width, in shape. */
|
|
88
155
|
export declare const splitHeight: (w: number, media: Size) => number;
|
|
89
156
|
/**
|
|
@@ -134,6 +201,22 @@ export declare function wipeGrab(x: number, rect: Rect, wipe: number, slop?: num
|
|
|
134
201
|
onLine: boolean;
|
|
135
202
|
offset: number;
|
|
136
203
|
};
|
|
204
|
+
/**
|
|
205
|
+
* Wiping, Before and After ride either side of the seam at `x`, `gap` from it, each fading out as
|
|
206
|
+
* its side runs out of room (`left`/`right`: the wipe's edges; `wb`/`wa`: the labels' widths).
|
|
207
|
+
*/
|
|
208
|
+
export declare function seamLabels(x: number, left: number, right: number, wb: number, wa: number, gap?: number): {
|
|
209
|
+
before: {
|
|
210
|
+
x: number;
|
|
211
|
+
opacity: number;
|
|
212
|
+
};
|
|
213
|
+
after: {
|
|
214
|
+
x: number;
|
|
215
|
+
opacity: number;
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
/** Where the wipe's grip sits for a pointer at `y`: its top, kept `margin` inside the line. */
|
|
219
|
+
export declare function gripTop(y: number, rect: Rect, grip: number, margin?: number): number;
|
|
137
220
|
/** The wipe moved by a key: 1% a press, 10% with Shift. */
|
|
138
221
|
export declare const wipeKey: (wipe: number, dir: -1 | 1, big?: boolean) => number;
|
|
139
222
|
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"
|
|
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,9 @@ 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
|
|
45
|
-
*
|
|
49
|
+
* After), or `true` for one of its own under the viewer: a player's thin progress line (the
|
|
50
|
+
* `"line"` variant, as `player()` has), its markers chapter segments. Without one, `seek`,
|
|
51
|
+
* `play` and keys still work.
|
|
46
52
|
*/
|
|
47
53
|
readonly timeline?: Timeline | boolean;
|
|
48
54
|
/** The frame strip over the timeline (off; one timeline is made if there's none). */
|
|
@@ -68,6 +74,8 @@ export interface CompareOptions extends UiLook {
|
|
|
68
74
|
export interface Compare {
|
|
69
75
|
readonly element: HTMLElement;
|
|
70
76
|
readonly mode: CompareMode;
|
|
77
|
+
/** The modes it offers. */
|
|
78
|
+
readonly modes: readonly CompareMode[];
|
|
71
79
|
readonly wipe: number;
|
|
72
80
|
readonly loupe: boolean;
|
|
73
81
|
/** Seconds. */
|
|
@@ -85,7 +93,13 @@ export interface Compare {
|
|
|
85
93
|
readonly loop: CompareLoop | null;
|
|
86
94
|
/** New sources, mode, wipe, loupe, threshold or fps. A new mode glides in. */
|
|
87
95
|
update(next: Partial<Pick<CompareOptions, "before" | "after" | "mode" | "wipe" | "loupe" | "threshold" | "fps">>): void;
|
|
88
|
-
|
|
96
|
+
/**
|
|
97
|
+
* `glide`: a jump the hand didn't make (a chapter's click): the timeline's playhead catches up
|
|
98
|
+
* from where it is while the videos land at once.
|
|
99
|
+
*/
|
|
100
|
+
seek(time: number, options?: {
|
|
101
|
+
readonly glide?: boolean;
|
|
102
|
+
}): void;
|
|
89
103
|
/** Moves by `seconds`, the timeline's playhead gliding there (playing carries on). */
|
|
90
104
|
seekBy(seconds: number): void;
|
|
91
105
|
play(): void;
|
package/dist/types/ui/diff.d.ts
CHANGED
|
@@ -105,12 +105,11 @@ export declare function diffCounts(file: DiffFile, doc?: Document, options?: {
|
|
|
105
105
|
/** A file's change as a letter (M, A, D, R), for a tree's `icon`. */
|
|
106
106
|
export declare function diffStatus(file: DiffFile, doc?: Document): HTMLElement;
|
|
107
107
|
/**
|
|
108
|
-
* A code diff
|
|
109
|
-
* over the diff, drawn by `@pierre/diffs` (Shiki highlighting, word-level changes, hunks that
|
|
108
|
+
* A code diff on the void (no card, fill or ring: a hairline under its header and one under the
|
|
109
|
+
* code): a quiet header with the file's path, its counts and Split | Unified over the diff, drawn by `@pierre/diffs` (Shiki highlighting, word-level changes, hunks that
|
|
110
110
|
* expand when the whole files are known). Takes a unified patch or before and after pairs.
|
|
111
111
|
* Changing the file or the layout fades the new view in over the old, in place; each file
|
|
112
|
-
* keeps its scroll.
|
|
113
|
-
* no card of its own. Needs `@pierre/diffs` installed; it loads on first use.
|
|
112
|
+
* keeps its scroll. Needs `@pierre/diffs` installed; it loads on first use.
|
|
114
113
|
*/
|
|
115
114
|
export declare function codeDiff(container: HTMLElement, options: CodeDiffOptions): CodeDiff;
|
|
116
115
|
export interface DiffReviewOptions extends CodeDiffOptions {
|
|
@@ -147,7 +146,7 @@ export interface DiffReview {
|
|
|
147
146
|
dispose(): void;
|
|
148
147
|
}
|
|
149
148
|
/**
|
|
150
|
-
* A diff beside its file list, as a review,
|
|
149
|
+
* A diff beside its file list, as a review, on the void as the diff is: the list is a drawer at its left that
|
|
151
150
|
* springs open and shut (0 to 256px, .4 s, no bounce; the diff reflows as it moves) from a
|
|
152
151
|
* button at the start of the diff's header, or ⌘B / Ctrl+B. In it, a field that narrows the list
|
|
153
152
|
* by path, then the changed files as a compact tree (folders folded into paths), each with its
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const historyCss = "\n:where(.knobs-history,.knobs-history *){box-sizing:border-box}\n.knobs-ui.knobs-history{--hy-gutter:128px;--hy-lane:24px;--hy-bar:16px;--hy-axis:20px;--hy-bandrow:0px;--hy-c:var(--_k-fg-3);\n --hy-fade:linear-gradient(to right,#000 calc(100% - 1.5em),transparent);\n position:relative;display:flex;flex-direction:column;width:100%;min-width:0;outline:none;color:var(--_k-fg);\n font:var(--_k-weight) var(--_k-type-body)/var(--_k-leading-body) var(--_k-font);font-variant-numeric:tabular-nums;font-feature-settings:var(--_kr-data,\"tnum\");\n text-align:left;letter-spacing:normal;-webkit-font-smoothing:antialiased;user-select:none;-webkit-user-select:none}\n.knobs-history[data-bands]{--hy-bandrow:var(--_k-leading-small)}\n.knobs-history[data-narrow]{--hy-gutter:0px}\n.knobs-history [hidden]{display:none!important}\n:where(.knobs-ui) :is(.knobs-hy-ev,.knobs-hy-span,.knobs-hy-jump,.knobs-hy-more){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;\n background:transparent;border:0;border-radius:0;margin:0;padding:0;min-width:0;box-shadow:none;outline:none}\n.knobs-history [data-tone=\"good\"]{--hy-c:var(--_k-ok)}\n.knobs-history [data-tone=\"warn\"]{--hy-c:var(--_k-warn)}\n.knobs-history [data-tone=\"bad\"]{--hy-c:var(--_k-danger)}\n.knobs-history [data-tone=\"info\"]{--hy-c:var(--_k-info)}\n.knobs-history [data-tone=\"dim\"]{--hy-c:var(--_k-fg-3)}\n\n/* \u2014\u2014\u2014 the chart: lane labels beside the plot (above each lane where it's narrow) \u2014\u2014\u2014 */\n.knobs-hy-chart{position:relative;display:grid;grid-template-columns:var(--hy-gutter) minmax(0,1fr)}\n.knobs-hy-axis{position:relative;grid-column:2;grid-row:1;height:calc(var(--hy-bandrow) + var(--hy-axis))}\n:is(.knobs-hy-tick,.knobs-hy-now,.knobs-hy-blabel){position:absolute;white-space:nowrap;font-size:var(--_k-type-small);line-height:var(--_k-leading-small);color:var(--_k-fg-3)}\n.knobs-hy-tick{bottom:2px;padding-left:4px}\n.knobs-hy-now{bottom:2px;color:var(--_k-accent-fg);font-weight:var(--_k-weight-label)}\n.knobs-hy-blabel{top:0;padding-left:4px;overflow:hidden;color:var(--_k-fg-2)}\n.knobs-hy-label{grid-column:1;align-self:center;min-width:0;margin-right:var(--_k-space-title);overflow:hidden;white-space:nowrap;\n font-size:var(--_k-type-small);line-height:var(--_k-leading-small);color:var(--_k-fg-3)}\n.knobs-history[data-narrow] .knobs-hy-label{grid-column:2;align-self:end;margin:0}\n:is(.knobs-hy-label,.knobs-hy-blabel)[data-overflow]{-webkit-mask-image:var(--hy-fade);mask-image:var(--hy-fade)}\n.knobs-hy-track{position:relative;grid-column:2;height:var(--hy-lane)}\n.knobs-hy-layer{position:absolute;inset:0;grid-column:2;grid-row:1/-1;pointer-events:none}\n\n/* Bands and month lines behind the lanes; today, the selection and the pointer's line over them. */\n.knobs-hy-band{position:absolute;top:0;bottom:0;background:var(--_k-fill);box-shadow:inset 1px 0 0 var(--_k-border-subtle)}\n: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}\n.knobs-hy-grid{background:var(--_k-border-subtle)}\n.knobs-hy-today{top:calc(var(--hy-bandrow) + var(--hy-axis) - 4px);background:var(--_k-accent)}\n.knobs-hy-hover{background:color-mix(in oklch,var(--_k-fg) 32%,transparent);opacity:0;transition:opacity calc(var(--_k-hover-out) * 1ms)}\n.knobs-hy-hover[data-on]{opacity:1;transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-hy-sel{background:var(--_k-fg-2);opacity:0}\n.knobs-hy-sel[data-on]{opacity:.6}\n\n/* Spans: a soft bar in their state's tone, inferred ones hatched; the tag at the end. */\n.knobs-hy-span{position:absolute;top:calc((var(--hy-lane) - var(--hy-bar)) / 2);height:var(--hy-bar);border-radius:var(--_k-radius-sm);cursor:default;\n background:color-mix(in oklch,var(--hy-c) 24%,transparent);transition:background calc(var(--_k-hover-out) * 1ms),box-shadow calc(var(--_k-hover-out) * 1ms)}\n.knobs-hy-span[data-inferred]{background:repeating-linear-gradient(135deg,color-mix(in oklch,var(--hy-c) 34%,transparent) 0 2px,color-mix(in oklch,var(--hy-c) 9%,transparent) 2px 6px)}\n.knobs-hy-span[data-hover]{background-color:color-mix(in oklch,var(--hy-c) 34%,transparent);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-hy-span[data-selected]{box-shadow:inset 0 0 0 1px var(--hy-c)}\n.knobs-hy-span[data-clip-start]{border-top-left-radius:0;border-bottom-left-radius:0;-webkit-mask-image:linear-gradient(to right,transparent,#000 16px);mask-image:linear-gradient(to right,transparent,#000 16px)}\n.knobs-hy-span[data-clip-end]{border-top-right-radius:0;border-bottom-right-radius:0;-webkit-mask-image:linear-gradient(to left,transparent,#000 16px);mask-image:linear-gradient(to left,transparent,#000 16px)}\n.knobs-hy-tag{position:absolute;top:0;right:6px;font-size:var(--_k-type-small);line-height:var(--hy-bar);white-space:nowrap;pointer-events:none;\n color:color-mix(in oklch,var(--hy-c) 55%,var(--_k-fg))}\n.knobs-hy-tag[data-place=\"after\"]{right:auto;left:calc(100% + 6px)}\n.knobs-hy-tag[data-place=\"none\"]{visibility:hidden}\n\n/* Event marks (their kind named in the tooltip): a dot for a commit, a diamond for a release, a cross for a deletion, a square for a\n channel's switch, a triangle for a finding; inferred ones hollow. */\n.knobs-hy-ev{position:absolute;top:0;width:16px;height:var(--hy-lane);margin-left:-8px;cursor:default;--hy-c:var(--_k-fg-2);--hy-s:9px}\n.knobs-hy-ev::before{content:\"\";position:absolute;left:50%;top:50%;width:var(--hy-s);height:var(--hy-s);margin:calc(var(--hy-s) / -2) 0 0 calc(var(--hy-s) / -2);\n border-radius:50%;background:var(--hy-c);transition:scale calc(var(--_k-motion-snappy-ms) * 1ms) var(--_k-motion-snappy)}\n.knobs-hy-ev[data-range]{width:calc(var(--hy-w) + 16px)}\n.knobs-hy-ev[data-range]::before{left:calc(8px - var(--hy-s) / 2);right:calc(8px - var(--hy-s) / 2);width:auto;margin-left:0;border-radius:var(--_k-round)}\n.knobs-hy-ev[data-type=\"release\"]{--hy-s:8px}\n.knobs-hy-ev[data-type=\"release\"]::before{border-radius:1.5px;rotate:45deg}\n.knobs-hy-ev[data-type=\"channel\"]{--hy-s:8px}\n.knobs-hy-ev[data-type=\"channel\"]::before{border-radius:2px}\n.knobs-hy-ev[data-type=\"audit\"]{--hy-s:10px}\n.knobs-hy-ev[data-type=\"audit\"]::before{border-radius:0;clip-path:polygon(50% 4%,100% 92%,0 92%)}\n.knobs-hy-ev[data-type=\"deletion\"]::before{border-radius:0;rotate:45deg;\n background:linear-gradient(var(--hy-c),var(--hy-c)) center/100% 1.75px no-repeat,linear-gradient(var(--hy-c),var(--hy-c)) center/1.75px 100% no-repeat}\n.knobs-hy-ev[data-inferred]:not([data-type=\"audit\"],[data-type=\"deletion\"])::before{background:transparent;box-shadow:inset 0 0 0 1.5px var(--hy-c)}\n.knobs-hy-ev[data-inferred]:is([data-type=\"audit\"],[data-type=\"deletion\"])::before{opacity:.5}\n/* Held-back marks (commits, by default) come up while the pointer is on their lane, and stay with\n \"Show commits\" or while selected. */\n.knobs-hy-ev[data-quiet]{opacity:0;transition:opacity calc(var(--_k-hover-out) * 1ms)}\n.knobs-hy-track:hover .knobs-hy-ev[data-quiet]{opacity:.6;transition-duration:calc(var(--_k-hover-in) * 1ms)}\n:is(.knobs-history[data-all] .knobs-hy-ev[data-quiet],.knobs-hy-ev[data-quiet]:is([data-selected],[data-hover])){opacity:1}\n.knobs-hy-ev[data-hover]::before{scale:1.25}\n.knobs-hy-ev[data-selected]::before{scale:1.3}\n.knobs-hy-ev[data-selected]::after{content:\"\";position:absolute;left:50%;top:50%;width:calc(var(--hy-s) + 9px);height:calc(var(--hy-s) + 9px);\n margin:calc((var(--hy-s) + 9px) / -2) 0 0 calc((var(--hy-s) + 9px) / -2);border-radius:50%;box-shadow:0 0 0 1.5px var(--hy-c)}\n.knobs-hy-ev[data-range][data-selected]::after{left:3px;right:3px;width:auto;margin-left:0;border-radius:var(--_k-round)}\n.knobs-history:focus-visible .knobs-hy-ev[data-selected]::after{box-shadow:0 0 0 2px var(--_k-focus)}\n.knobs-history:focus-visible .knobs-hy-span[data-selected]{box-shadow:inset 0 0 0 2px var(--_k-focus)}\n\n/* \u2014\u2014\u2014 under the chart: \"Show commits\", and a legend only when inferred and verified both appear \u2014\u2014\u2014 */\n.knobs-hy-foot{display:flex;flex-wrap:wrap;align-items:center;gap:var(--_k-space-inside) var(--_k-space-title);margin-top:var(--_k-space-sibling);padding-left:var(--hy-gutter);\n font-size:var(--_k-type-small);line-height:var(--_k-leading-small);color:var(--_k-fg-3)}\n.knobs-hy-legend{display:flex;flex-wrap:wrap;gap:var(--_k-space-inside) var(--_k-space-title)}\n.knobs-ui .knobs-hy-more{height:20px;margin-left:-6px;padding:0 6px;border-radius:var(--_k-radius-sm);color:var(--_k-fg-3);cursor:default;\n transition:background calc(var(--_k-hover-out) * 1ms),color calc(var(--_k-hover-out) * 1ms)}\n.knobs-ui .knobs-hy-more:is(:hover,:focus-visible){background:var(--_k-fill-hover);color:var(--_k-fg);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-hy-key{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}\n.knobs-hy-swatch{flex:none;width:14px;height:8px;border-radius:2px;background:color-mix(in oklch,var(--hy-c) 34%,transparent)}\n.knobs-hy-swatch[data-inferred]{background:repeating-linear-gradient(135deg,color-mix(in oklch,var(--hy-c) 60%,transparent) 0 1.5px,transparent 1.5px 4px)}\n\n/* \u2014\u2014\u2014 the detail: one area under the chart, its height on a spring \u2014\u2014\u2014 */\n.knobs-hy-detail{position:relative;overflow:hidden;user-select:text;-webkit-user-select:text}\n.knobs-hy-detail[data-moving]{-webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 16px),transparent);mask-image:linear-gradient(to bottom,#000 calc(100% - 16px),transparent)}\n.knobs-hy-dc{padding:var(--_k-space-title) 0 0 var(--hy-gutter);transition:opacity calc(var(--_k-motion-snappy-ms) * 1ms) var(--_k-motion-snappy)}\n.knobs-hy-dc:is([data-enter],[data-leave]){opacity:0}\n.knobs-hy-dc[data-leave]{position:absolute;left:0;right:0;top:0;transition-duration:calc(var(--_k-motion-snappy-ms) * .8ms)}\n.knobs-hy-dmeta{display:flex;flex-wrap:wrap;gap:0 var(--_k-space-sibling);font-size:var(--_k-type-small);line-height:var(--_k-leading-small);color:var(--_k-fg-3)}\n.knobs-hy-dmeta>[data-tone]{color:var(--hy-c)}\n.knobs-hy-dtitle{margin-top:var(--_k-space-inside);font-size:var(--_k-type-body);line-height:var(--_k-leading-body);font-weight:var(--_k-weight-label);color:var(--_k-fg);text-wrap:balance}\n.knobs-hy-dtext{margin:var(--_k-space-inside) 0 0;max-width:68ch;font-size:var(--_k-type-body);line-height:var(--_k-leading-body);color:var(--_k-fg-2);text-wrap:pretty}\n.knobs-hy-dtext code{font:var(--_k-type-label) var(--_k-mono);letter-spacing:0;padding:1px 5px;border-radius:calc(var(--_k-radius) / 2);background:var(--_k-fill)}\n.knobs-hy-dfoot{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:var(--_k-space-sibling)}\n.knobs-hy-dfoot:empty{display:none}\n.knobs-hy-evidence{display:inline-flex;align-items:center;height:20px;padding:0 6px;border-radius:var(--_k-radius-sm);background:var(--_k-fill);color:var(--_k-fg-2);\n font:var(--_k-type-small)/1 var(--_k-mono);text-decoration:none;transition:background calc(var(--_k-hover-out) * 1ms),color calc(var(--_k-hover-out) * 1ms)}\na.knobs-hy-evidence:hover{background:var(--_k-fill-hover);color:var(--_k-fg);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-ui .knobs-hy-jump{display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 5px 0 6px;border-radius:var(--_k-radius-sm);color:var(--_k-fg-2);cursor:default;\n font-size:var(--_k-type-small);transition:background calc(var(--_k-hover-out) * 1ms),color calc(var(--_k-hover-out) * 1ms)}\n.knobs-ui .knobs-hy-jump:is(:hover,:focus-visible){background:var(--_k-fill-hover);color:var(--_k-fg);transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-hy-jump svg{width:12px;height:12px}\n\n/* \u2014\u2014\u2014 the pointer's tooltip: title, date, one line \u2014\u2014\u2014 */\n.knobs-hy-tip{position:absolute;left:0;top:0;max-width:280px;padding:6px 8px;border-radius:var(--_k-radius-md);background:var(--_k-bg-overlay);\n box-shadow:var(--_k-shadow-overlay),0 0 0 1px var(--_k-border);pointer-events:none;opacity:0;transition:opacity calc(var(--_k-hover-out) * 1ms)}\n.knobs-hy-tip[data-on]{opacity:1;transition-duration:calc(var(--_k-hover-in) * 1ms)}\n.knobs-hy-tt{font-size:var(--_k-type-small);line-height:var(--_k-leading-small);font-weight:var(--_k-weight-label);color:var(--_k-fg);text-wrap:balance}\n:is(.knobs-hy-td,.knobs-hy-tl){font-size:var(--_k-type-small);line-height:var(--_k-leading-small);color:var(--_k-fg-3)}\n.knobs-hy-tl{margin-top:2px;color:var(--_k-fg-2);text-wrap:pretty}\n.knobs-hy-tl:empty{display:none}\n\n@media(prefers-reduced-motion:reduce){\n .knobs-history :where(*,::before,::after){transition-property:opacity,background,color,box-shadow!important}\n .knobs-hy-dc{transition-duration:calc(var(--_k-hover-out) * 1ms)!important}\n}\n";
|