@kitlangton/knobs 0.4.0-next.0 → 0.4.0-next.2

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.
Files changed (47) hide show
  1. package/README.md +351 -43
  2. package/dist/dev/{chunk-stbcgz1y.js → chunk-1qzffbpa.js} +443 -451
  3. package/dist/dev/{chunk-7xgkerd2.js → chunk-3ygqgy1x.js} +23 -1
  4. package/dist/dev/{chunk-pmkvb9ep.js → chunk-8mabjeyk.js} +1920 -507
  5. package/dist/dev/{chunk-t68smqkc.js → chunk-ayb292zj.js} +13 -11
  6. package/dist/dev/index.js +10 -5
  7. package/dist/index.js +25 -1
  8. package/dist/panel.js +2900 -1320
  9. package/dist/react.js +294 -6
  10. package/dist/solid.js +292 -4
  11. package/dist/themes.js +1509 -7
  12. package/dist/types/core/adapter.d.ts +6 -2
  13. package/dist/types/core/appearance.d.ts +44 -0
  14. package/dist/types/core/glide.d.ts +7 -0
  15. package/dist/types/core/motion.d.ts +66 -0
  16. package/dist/types/core/root.d.ts +13 -0
  17. package/dist/types/core/store.d.ts +18 -5
  18. package/dist/types/core/theme.d.ts +10 -3
  19. package/dist/types/index.d.ts +2 -1
  20. package/dist/types/panel/gpu/color.d.ts +6 -0
  21. package/dist/types/panel/motion.d.ts +1 -1
  22. package/dist/types/panel/styles.d.ts +2 -3
  23. package/dist/types/themes/define.d.ts +104 -0
  24. package/dist/types/themes/index.d.ts +11 -0
  25. package/dist/types/themes/knobs.d.ts +5 -0
  26. package/dist/types/themes/void.d.ts +8 -0
  27. package/dist/types/tokens/color.d.ts +42 -0
  28. package/dist/types/tokens/css.d.ts +13 -0
  29. package/dist/types/tokens/evaluate.d.ts +8 -0
  30. package/dist/types/tokens/index.d.ts +4 -0
  31. package/dist/types/tokens/schema.d.ts +1100 -0
  32. package/dist/types/ui/bento-css.d.ts +1 -1
  33. package/dist/types/ui/compare-css.d.ts +1 -1
  34. package/dist/types/ui/index.d.ts +3 -3
  35. package/dist/types/ui/look.d.ts +18 -13
  36. package/dist/types/ui/overlay-css.d.ts +1 -1
  37. package/dist/types/ui/readout-css.d.ts +1 -1
  38. package/dist/types/ui/readout-model.d.ts +5 -1
  39. package/dist/types/ui/rgba.d.ts +11 -0
  40. package/dist/types/ui/walkthrough-blocks.d.ts +43 -0
  41. package/dist/types/ui/walkthrough-media.d.ts +4 -0
  42. package/dist/types/ui/walkthrough-model.d.ts +237 -3
  43. package/dist/types/ui/walkthrough.d.ts +3 -1
  44. package/dist/ui-react.js +3193 -791
  45. package/dist/ui-solid.js +3193 -791
  46. package/dist/ui.js +3340 -935
  47. package/package.json +1 -1
@@ -1 +1 @@
1
- export declare const bentoCss = "\n.knobs-ui.knobs-bento{--ku-bento-radius:var(--k-ui-bento-radius,max(0px,calc(var(--ku-radius) - 5px)));\n position:relative;width:100%;height:100%;overflow:hidden auto;outline:none;background:var(--k-ui-bento-bg,var(--ku-page));\n scrollbar-width:thin;scrollbar-gutter:stable;overscroll-behavior:contain;touch-action:pan-y;user-select:none;-webkit-user-select:none;\n font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text);letter-spacing:normal;text-align:left}\n.knobs-bento[data-frame=\"flat\"]{--ku-bento-radius:var(--k-ui-bento-radius,0px)}\n.knobs-bento[data-pending] .knobs-bento-space{visibility:hidden}\n:where(.knobs-bento-space,.knobs-bento-space *){box-sizing:border-box}\n.knobs-bento-space{position:relative;width:100%}\n.knobs-bento-tile{position:absolute;left:0;top:0;transform-origin:0 0;overflow:hidden;border-radius:var(--ku-bento-radius);\n background:var(--ku-surface);contain:strict;cursor:zoom-in}\n.knobs-bento-tile[data-focus]{z-index:2;cursor:zoom-out}\n.knobs-bento-tile[data-focus][data-live]{cursor:auto}\n.knobs-bento-img{display:block;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .18s cubic-bezier(.2,.8,.2,1);-webkit-user-drag:none}\n.knobs-bento-tile[data-ready] .knobs-bento-img{opacity:1}\n.knobs-bento-tile[data-instant] .knobs-bento-img{transition:none}\n.knobs-bento-body{position:absolute;inset:0;pointer-events:none}\n.knobs-bento-tile[data-focus] .knobs-bento-body{pointer-events:auto}\n.knobs-bento-label{position:absolute;left:9px;right:9px;bottom:7px;color:#fff;font-size:var(--ku-text-meta);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;\n text-shadow:0 0 6px rgba(0,0,0,.55),0 0 1px rgba(0,0,0,.5);opacity:0;pointer-events:none;transition:opacity calc(var(--ku-hover-out) * 1ms)}\n.knobs-bento:not([data-keyboard]) .knobs-bento-tile:hover .knobs-bento-label,\n.knobs-bento[data-keyboard]:focus .knobs-bento-tile[data-active] .knobs-bento-label,\n.knobs-bento-tile[data-focus] .knobs-bento-label{opacity:1;transition-duration:calc(var(--ku-hover-in) * 1ms)}\n/* A pick: a small dot in the accent, ringed in the page so it reads on any picture. */\n.knobs-bento-tile::after{content:\"\";position:absolute;top:8px;right:8px;width:8px;height:8px;border-radius:50%;background:var(--ku-accent);\n box-shadow:0 0 0 1.5px color-mix(in srgb,var(--ku-page) 70%,transparent);opacity:0;scale:.4;pointer-events:none;\n transition:opacity .11s cubic-bezier(.4,0,1,1),scale var(--ku-ease-ms) var(--ku-ease)}\n.knobs-bento-tile[aria-selected=\"true\"]::after{opacity:1;scale:1;transition:opacity .15s cubic-bezier(.2,.8,.2,1),scale var(--ku-ease-ms) var(--ku-ease)}\n.knobs-bento-wash{position:absolute;left:0;top:0;width:100px;height:100px;transform-origin:0 0;z-index:3;pointer-events:none;border-radius:var(--ku-bento-radius);\n background:color-mix(in srgb,var(--ku-accent) 12%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ku-accent) 45%,transparent);\n opacity:0;transition:opacity .15s}\n.knobs-bento[data-keyboard]:focus:not([data-zoomed]) .knobs-bento-wash[data-on]{opacity:1}\n.knobs-bento-scrim{position:absolute;left:0;top:0;width:100%;z-index:1;background:var(--k-ui-scrim,var(--k-ui-bento-bg,var(--ku-page)));opacity:0;pointer-events:none;cursor:zoom-out}\n.knobs-bento[data-zoomed] .knobs-bento-scrim{pointer-events:auto}\n.knobs-bento-head{position:absolute;left:0;top:0;display:flex;align-items:flex-end;padding:0 0 6px 2px;color:var(--ku-label);font-weight:var(--ku-label-weight);\n font-size:var(--ku-text-meta);white-space:nowrap;pointer-events:none}\n";
1
+ export declare const bentoCss = "\n.knobs-ui.knobs-bento{--_ku-bento-radius:var(--k-ui-bento-radius,max(0px,calc(var(--_k-radius) - 5px)));\n position:relative;width:100%;height:100%;overflow:hidden auto;outline:none;background:var(--k-ui-bento-bg,var(--_k-bg-page));\n scrollbar-width:thin;scrollbar-gutter:stable;overscroll-behavior:contain;touch-action:pan-y;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.knobs-bento[data-frame=\"flat\"]{--_ku-bento-radius:var(--k-ui-bento-radius,0px)}\n.knobs-bento[data-pending] .knobs-bento-space{visibility:hidden}\n:where(.knobs-bento-space,.knobs-bento-space *){box-sizing:border-box}\n.knobs-bento-space{position:relative;width:100%}\n.knobs-bento-tile{position:absolute;left:0;top:0;transform-origin:0 0;overflow:hidden;border-radius:var(--_ku-bento-radius);\n background:var(--_k-fill);contain:strict;cursor:zoom-in}\n.knobs-bento-tile[data-focus]{z-index:2;cursor:zoom-out}\n.knobs-bento-tile[data-focus][data-live]{cursor:auto}\n.knobs-bento-img{display:block;width:100%;height:100%;object-fit:cover;opacity:0;transition:opacity .18s cubic-bezier(.2,.8,.2,1);-webkit-user-drag:none}\n.knobs-bento-tile[data-ready] .knobs-bento-img{opacity:1}\n.knobs-bento-tile[data-instant] .knobs-bento-img{transition:none}\n.knobs-bento-body{position:absolute;inset:0;pointer-events:none}\n.knobs-bento-tile[data-focus] .knobs-bento-body{pointer-events:auto}\n.knobs-bento-label{position:absolute;left:9px;right:9px;bottom:7px;color:#fff;font-size:var(--_k-text-meta);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;\n text-shadow:0 0 6px rgba(0,0,0,.55),0 0 1px rgba(0,0,0,.5);opacity:0;pointer-events:none;transition:opacity calc(var(--_k-hover-out) * 1ms)}\n.knobs-bento:not([data-keyboard]) .knobs-bento-tile:hover .knobs-bento-label,\n.knobs-bento[data-keyboard]:focus .knobs-bento-tile[data-active] .knobs-bento-label,\n.knobs-bento-tile[data-focus] .knobs-bento-label{opacity:1;transition-duration:calc(var(--_k-hover-in) * 1ms)}\n/* A pick: a small dot in the accent, ringed in the page so it reads on any picture. */\n.knobs-bento-tile::after{content:\"\";position:absolute;top:8px;right:8px;width:8px;height:8px;border-radius:50%;background:var(--_k-accent);\n box-shadow:0 0 0 1.5px color-mix(in srgb,var(--_k-bg-page) 70%,transparent);opacity:0;scale:.4;pointer-events:none;\n transition:opacity .11s cubic-bezier(.4,0,1,1),scale var(--_ku-ease-ms) var(--_ku-ease)}\n.knobs-bento-tile[aria-selected=\"true\"]::after{opacity:1;scale:1;transition:opacity .15s cubic-bezier(.2,.8,.2,1),scale var(--_ku-ease-ms) var(--_ku-ease)}\n.knobs-bento-wash{position:absolute;left:0;top:0;width:100px;height:100px;transform-origin:0 0;z-index:3;pointer-events:none;border-radius:var(--_ku-bento-radius);\n background:color-mix(in srgb,var(--_k-accent) 12%,transparent);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--_k-accent) 45%,transparent);\n opacity:0;transition:opacity .15s}\n.knobs-bento[data-keyboard]:focus:not([data-zoomed]) .knobs-bento-wash[data-on]{opacity:1}\n.knobs-bento-scrim{position:absolute;left:0;top:0;width:100%;z-index:1;background:var(--k-ui-scrim,var(--k-ui-bento-bg,var(--_k-bg-page)));opacity:0;pointer-events:none;cursor:zoom-out}\n.knobs-bento[data-zoomed] .knobs-bento-scrim{pointer-events:auto}\n.knobs-bento-head{position:absolute;left:0;top:0;display:flex;align-items:flex-end;padding:0 0 6px 2px;color:var(--_k-fg-2);font-weight:var(--_k-weight-label);\n font-size:var(--_k-text-meta);white-space:nowrap;pointer-events:none}\n";
@@ -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,#7dcf9c);--ku-cmp-line:var(--k-compare-line,#fff);\n --ku-cmp-stage:var(--k-compare-stage,var(--ku-surface));\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(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text);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(--ku-radius) - 2px));color:var(--ku-dim);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(--ku-text);background:var(--ku-wash)}\n.knobs-ui .knobs-cmp-mode[aria-checked=\"true\"],.knobs-ui .knobs-cmp-toggle[aria-pressed=\"true\"]{color:var(--ku-text);font-weight:var(--ku-label-weight)}\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(--ku-panel-radius);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(--ku-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(--ku-line),inset 0 1px 0 var(--ku-rim),0 2px 10px rgba(0,0,0,.18)}\n.knobs-cmp-label{position:absolute;left:0;top:0;padding:1px 7px;border-radius:999px;font-size:var(--ku-text-meta);line-height:16px;color:var(--ku-label);white-space:nowrap;pointer-events:none;will-change:transform;transition:color .15s}\n.knobs-cmp-label[data-lit]{color:var(--ku-text)}\n.knobs-cmp-label[data-dim]{color:var(--ku-dim)}\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(--ku-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(--ku-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-text);font-size:var(--ku-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(--ku-label);cursor:pointer;transition:color .15s,background .15s}\n:where(.knobs-ui) .knobs-cmp-zoom-reset:is(:hover,:focus-visible){color:var(--ku-text);background:color-mix(in srgb,var(--ku-text) 12%,transparent)}\n.knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--ku-dim);font-size:var(--ku-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,#7dcf9c);position:relative;width:100%;height:100%;min-height:40px;overflow:hidden;cursor:col-resize;touch-action:none;\n font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text)}\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: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,4 +1,4 @@
1
- export { injectUiStyles, restyle, type RestyleLook, type UiLook, type UiTheme } from "./look.js";
1
+ export { type Appearance, injectUiStyles, restyle, type RestyleLook, type UiLook, type UiTheme, } from "./look.js";
2
2
  export { commandsFrom, type CommandsFromOptions } from "./commands.js";
3
3
  export { confirm, type ConfirmOptions } from "./confirm.js";
4
4
  export { overlayLook, type Anchor } from "./layer.js";
@@ -28,5 +28,5 @@ export { diffActivity, flattenActivity, formatDuration, indexActivity, keepSelec
28
28
  export { optionPicker, type OptionPicker, type OptionPickerOptions, type PickerOption, } from "./picker.js";
29
29
  export { claimsDigit, digitPick, keepPick, stepPick } from "./picker-model.js";
30
30
  export { tasteTest, walkthrough, type TasteTest, type TasteTestOptions, type Walkthrough, type WalkthroughOptions, } from "./walkthrough.js";
31
- export { mediaSlot, type MediaSlot, type MediaSlotOptions } from "./walkthrough-media.js";
32
- export { collectFeedback, feedbackMarkdown, inlineMarkdown, normalizeWalkthrough, readState as readWalkthroughState, walkthroughProgress, type ContextEvent, type FeedbackItem, type FeedbackNote, type FeedItem, type MediaContext, type NoteContext, type WalkInk, type WalkNote, type WalkVoice, type WalkthroughQA, type WalkthroughUpdate, type WalkPage, type WalkStep, type WalkthroughDoc, type WalkthroughFeedback, type WalkthroughMedia, type WalkthroughMeta, type WalkthroughOption, type WalkthroughSection, type WalkthroughSource, type WalkthroughState, type WalkthroughStatus, type WalkthroughStep, } from "./walkthrough-model.js";
31
+ export { mediaSlot, type MediaSlot, type MediaSlotOptions, type StepLinks, } from "./walkthrough-media.js";
32
+ 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";
@@ -1,14 +1,18 @@
1
- import { type TokenPreset } from "../core/theme.js";
2
- export type UiTheme = "dark" | "light" | "auto";
3
- /** What every piece takes to match the panels beside it. */
4
- export interface UiLook {
5
- /** A token preset (`labPreset`): the same tokens a panel takes. */
6
- readonly preset?: TokenPreset;
7
- readonly theme?: UiTheme;
8
- }
1
+ import { type Appearance, type LookOptions, type ThemeMode } from "../core/appearance.js";
2
+ /** @deprecated The old appearance option: use `appearance` (`auto` is `system`). */
3
+ export type UiTheme = ThemeMode;
4
+ export type { Appearance };
5
+ /**
6
+ * What every piece takes to match the panels beside it: a theme (`themes.void`, or your own from
7
+ * `defineTheme`) and an appearance (dark | light | system | inherit, the default). The old
8
+ * `theme: "dark" | "light" | "auto"` and `preset` still work.
9
+ */
10
+ export type UiLook = LookOptions;
11
+ /** The pieces' stylesheet, as `injectUiStyles` writes it (after the token sheet). */
12
+ export declare const uiCss: () => string;
9
13
  /** Adds the pieces' stylesheet once per document. */
10
14
  export declare function injectUiStyles(doc: Document): void;
11
- /** Styles, preset and theme for a piece's root. */
15
+ /** Styles, theme, appearance and preset for a piece's root. */
12
16
  export declare function applyLook(root: HTMLElement, look: UiLook): void;
13
17
  /**
14
18
  * `--k-frame: flat` (a preset's, or a host's on any ancestor) marks the piece `data-frame`. Read
@@ -21,16 +25,17 @@ export interface RestyleLook extends UiLook {
21
25
  }
22
26
  /**
23
27
  * Changes the look of what's already on screen: every knobs/ui piece and panel inside `target`
24
- * (the whole document by default) takes `look`'s preset (none for knobs' own), theme and, for
25
- * panels, density. Panels' tokens glide to the new values; splits and trees measure again. On a
26
- * document, overlays opened afterwards take it too (`overlayLook`).
28
+ * (the whole document by default) takes `look`'s theme and preset (knobs' own where it gives
29
+ * none) and, where it gives them, its appearance and a panel's density. Tokens glide to the new
30
+ * values; splits and trees measure again. On a document, overlays opened afterwards take it too
31
+ * (`overlayLook`).
27
32
  */
28
33
  export declare function restyle(target: Document | Element, look: RestyleLook): void;
29
34
  /** The look overlays take unless given their own (`overlayLook`, `restyle(document)`). */
30
35
  export declare const lookDefaults: {
31
36
  current: UiLook;
32
37
  };
33
- export declare const reducedMotion: (win: Window | null) => boolean;
38
+ export { reducedMotion } from "../core/motion.js";
34
39
  export declare const tune: <T extends {
35
40
  omega: number;
36
41
  zeta: number;
@@ -1 +1 @@
1
- export declare const overlayCss = "\n.knobs-layers{position:fixed;inset:0;z-index:2147480005;pointer-events:none}\n.knobs-layers>.knobs-layer,.knobs-ui.knobs-toast{position:fixed;left:0;top:0;box-sizing:border-box;pointer-events:auto;outline:none;\n font:var(--ku-font-weight) var(--ku-font-size)/1.4 var(--ku-font);color:var(--ku-text);letter-spacing:normal;text-align:left;text-transform:none;\n -webkit-font-smoothing:antialiased;will-change:transform,opacity,filter}\n/* The overlays' own elements stop a host's element rules; what you put in a popover is yours. */\n:where(.knobs-layers,.knobs-toast) :is(.knobs-kbd,.knobs-mitem,.knobs-menu-sep,.knobs-palette-input,.knobs-palette-label>mark,.knobs-confirm-title,.knobs-confirm-body,.knobs-confirm-btn,.knobs-toast-action){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;\n background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}\n.knobs-layers .knobs-layer *{box-sizing:border-box}\n/* A floating surface: frosted, a hairline rim, a soft shadow. */\n.knobs-layers>:is(.knobs-popover-layer,.knobs-palette,.knobs-confirm,.knobs-menu-layer){background:color-mix(in srgb,var(--ku-bg) 88%,transparent);\n -webkit-backdrop-filter:blur(28px) saturate(1.7);backdrop-filter:blur(28px) saturate(1.7);border-radius:var(--ku-panel-radius);\n box-shadow:0 0 0 .5px var(--ku-line-hi),inset 0 1px 0 var(--ku-rim),0 12px 40px rgba(0,0,0,.36),0 2px 8px rgba(0,0,0,.18)}\n.knobs-layers>.knobs-popover-layer{min-width:120px;max-width:min(420px,calc(100vw - 16px));padding:6px}\n.knobs-popover-layer .knobs-popover-text{padding:4px 6px;color:var(--ku-label)}\n\n/* Menus: rows of the panel's control height, a soft wash on the active one (never an outline),\n concentric corners inside the surface. */\n.knobs-layers>.knobs-menu-layer{display:flex;flex-direction:column;min-width:184px;max-width:min(340px,calc(100vw - 16px));max-height:calc(100vh - 16px);overflow:auto;padding:5px;\n scrollbar-width:thin;overscroll-behavior:contain;user-select:none;-webkit-user-select:none}\n.knobs-menu-layer .knobs-mitem{position:relative;display:flex;align-items:center;gap:8px;flex:none;height:max(22px,calc(var(--ku-row) - 6px));padding:0 8px;\n border-radius:max(0px,calc(var(--ku-panel-radius) - 5px));color:var(--ku-text);cursor:default;white-space:nowrap}\n.knobs-menu-layer .knobs-mitem[data-active],.knobs-menu-layer .knobs-mitem[data-open]{background:var(--ku-wash-hi)}\n.knobs-menu-layer .knobs-mitem[data-destructive]{color:var(--ku-critical)}\n.knobs-menu-layer .knobs-mitem[data-destructive][data-active]{background:color-mix(in srgb,var(--ku-critical) 16%,transparent)}\n.knobs-menu-layer .knobs-mitem[aria-disabled=\"true\"]{opacity:.38}\n.knobs-menu-layer .knobs-menu-lead{flex:none;display:flex;align-items:center;justify-content:center;width:14px;margin-left:-2px;color:var(--ku-label);font-size:calc(var(--ku-font-size) - 1px)}\n.knobs-menu-layer .knobs-mitem[data-destructive] .knobs-menu-lead,.knobs-menu-layer .knobs-mitem[aria-checked=\"true\"] .knobs-menu-lead{color:inherit}\n.knobs-menu-layer .knobs-menu-lead svg{width:13px;height:13px}\n.knobs-menu-layer .knobs-menu-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}\n.knobs-menu-layer .knobs-menu-hint{flex:none;color:var(--ku-dim)}\n.knobs-menu-layer .knobs-menu-keys{display:inline-flex;gap:2px;flex:none;margin-left:12px}\n.knobs-menu-layer .knobs-mitem[data-active] .knobs-kbd{background:color-mix(in srgb,var(--ku-text) 14%,transparent);color:var(--ku-text)}\n.knobs-menu-layer .knobs-menu-caret{flex:none;display:flex;margin-left:8px;margin-right:-3px;color:var(--ku-dim)}\n.knobs-menu-layer .knobs-menu-caret svg{width:10px;height:10px}\n.knobs-menu-layer .knobs-menu-sep{flex:none;height:1px;margin:4px 8px;background:var(--ku-line)}\n\n.knobs-layers>.knobs-tooltip{display:inline-flex;align-items:center;gap:7px;max-width:300px;padding:4px 8px;pointer-events:none;white-space:nowrap;\n font-size:calc(var(--ku-font-size) - .5px);background:var(--ku-bg);color:var(--ku-text);border-radius:min(var(--ku-radius),6px);\n box-shadow:0 0 0 .5px var(--ku-line-hi),0 4px 14px rgba(0,0,0,.3)}\n.knobs-tooltip .knobs-tooltip-text{overflow:hidden;text-overflow:ellipsis}\n.knobs-layer :is(.knobs-tooltip-keys,.knobs-palette-keys){display:inline-flex;gap:2px;flex:none}\n.knobs-layer .knobs-tooltip-keys[hidden]{display:none}\n.knobs-layer .knobs-kbd{display:inline-flex;align-items:center;justify-content:center;min-width:17px;height:17px;padding:0 4px;\n border-radius:min(var(--ku-radius),4px);background:var(--ku-surface-hi);color:var(--ku-label);font:500 calc(var(--ku-font-size) - 1.5px)/1 var(--ku-font)}\n\n.knobs-layers>.knobs-palette{left:50%;top:max(48px,15vh);translate:-50% 0;transform-origin:50% 0;display:flex;flex-direction:column;\n width:min(580px,calc(100vw - 32px));max-height:min(460px,72vh);overflow:hidden}\n.knobs-palette .knobs-palette-field{display:flex;align-items:center;gap:10px;flex:none;height:46px;padding:0 16px;border-bottom:1px solid var(--ku-line);color:var(--ku-dim)}\n.knobs-palette .knobs-palette-field svg{width:15px;height:15px;flex:none}\n.knobs-palette .knobs-palette-input{flex:1;min-width:0;height:100%;font-size:calc(var(--ku-font-size) + 3px);color:var(--ku-text);caret-color:var(--ku-accent)}\n.knobs-palette .knobs-palette-input::placeholder{color:var(--ku-dim)}\n.knobs-palette .knobs-palette-list{position:relative;flex:1;min-height:0;overflow:auto;padding:6px;scrollbar-width:thin;overscroll-behavior:contain}\n.knobs-palette .knobs-palette-hl{position:absolute;left:6px;right:6px;top:0;border-radius:max(0px,calc(var(--ku-panel-radius) - 6px));background:var(--ku-wash-hi);opacity:0;pointer-events:none;\n transition:transform var(--ku-ease-ms) var(--ku-ease),height var(--ku-ease-ms) var(--ku-ease),opacity .12s}\n.knobs-palette .knobs-palette-section{padding:10px 10px 4px;color:var(--ku-dim);font-size:calc(var(--ku-font-size) - 1px);font-weight:var(--ku-label-weight);user-select:none}\n.knobs-palette .knobs-palette-section:first-of-type{padding-top:4px}\n.knobs-palette .knobs-palette-item{position:relative;display:flex;align-items:center;gap:8px;height:max(32px,var(--ku-row));padding:0 10px;\n color:var(--ku-label);cursor:default;user-select:none}\n.knobs-palette .knobs-palette-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ku-text)}\n/* Searching, the label dims and its matched letters light up. */\n.knobs-palette[data-query] .knobs-palette-label{color:var(--ku-label)}\n.knobs-palette .knobs-palette-label mark{color:var(--ku-accent);font-weight:var(--ku-title-weight)}\n.knobs-palette[data-query] .knobs-palette-item[data-active] .knobs-palette-label{color:var(--ku-text)}\n.knobs-palette .knobs-palette-hint{flex:none;color:var(--ku-dim)}\n.knobs-palette .knobs-palette-fill{flex:1}\n.knobs-palette .knobs-palette-tag{flex:none;color:var(--ku-dim);font-size:calc(var(--ku-font-size) - 1px);white-space:nowrap}\n.knobs-palette .knobs-palette-item[aria-disabled=\"true\"]{opacity:.4}\n.knobs-palette .knobs-palette-empty{padding:18px 10px;color:var(--ku-dim);text-align:center}\n\n.knobs-layers>.knobs-scrim{inset:0;width:100%;height:100%;background:rgba(0,0,0,.3)}\n.knobs-layers>.knobs-confirm{left:50%;top:42%;translate:-50% -50%;width:min(340px,calc(100vw - 32px));padding:18px 18px 14px}\n.knobs-confirm .knobs-confirm-title{margin:0 0 6px;font-size:calc(var(--ku-font-size) + 1.5px);font-weight:var(--ku-title-weight);color:var(--ku-text);line-height:1.3}\n.knobs-confirm .knobs-confirm-body{margin:0;color:var(--ku-label);line-height:1.45}\n.knobs-confirm .knobs-confirm-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:18px}\n.knobs-confirm .knobs-confirm-btn{height:28px;padding:0 14px;border-radius:min(var(--ku-radius),7px);background:var(--ku-surface-hi);color:var(--ku-text);\n font-weight:var(--ku-label-weight);cursor:pointer;transition:background .15s,filter .15s}\n.knobs-confirm .knobs-confirm-cancel:is(:hover,:focus-visible){background:color-mix(in srgb,var(--ku-text) 18%,transparent)}\n.knobs-confirm .knobs-confirm-ok{background:var(--ku-accent);color:var(--ku-bg)}\n.knobs-confirm .knobs-confirm-ok[data-destructive]{background:var(--ku-critical);color:#fff}\n.knobs-confirm .knobs-confirm-ok:is(:hover,:focus-visible){filter:brightness(1.14)}\n\n.knobs-ui.knobs-toast{left:50%;top:auto;bottom:24px;z-index:2147480005;translate:-50% 0;display:inline-flex;align-items:center;gap:10px;\n max-width:min(480px,80vw);padding:8px 16px;background:var(--ku-bg);color:var(--ku-text);border-radius:calc(var(--ku-radius) * 999);\n box-shadow:0 0 0 .5px var(--ku-line-hi),0 8px 28px rgba(0,0,0,.32)}\n.knobs-toast .knobs-toast-text{overflow-wrap:anywhere}\n.knobs-toast[data-tone=\"warn\"]::before,.knobs-toast[data-tone=\"error\"]::before{content:\"\";flex:none;width:7px;height:7px;border-radius:50%;background:var(--ku-warn)}\n.knobs-toast[data-tone=\"error\"]::before{background:var(--ku-critical)}\n.knobs-toast .knobs-toast-action{flex:none;color:var(--ku-accent);font-weight:var(--ku-title-weight);cursor:pointer}\n.knobs-toast .knobs-toast-action[hidden]{display:none}\n";
1
+ export declare const overlayCss = "\n.knobs-layers{position:fixed;inset:0;z-index:2147480005;pointer-events:none}\n.knobs-layers>.knobs-layer,.knobs-ui.knobs-toast{position:fixed;left:0;top:0;box-sizing:border-box;pointer-events:auto;outline:none;\n font:var(--_k-weight) var(--_k-font-size)/1.4 var(--_k-font);color:var(--_k-fg);letter-spacing:normal;text-align:left;text-transform:none;\n -webkit-font-smoothing:antialiased;will-change:transform,opacity,filter}\n/* The overlays' own elements stop a host's element rules; what you put in a popover is yours. */\n:where(.knobs-layers,.knobs-toast) :is(.knobs-kbd,.knobs-mitem,.knobs-menu-sep,.knobs-palette-input,.knobs-palette-label>mark,.knobs-confirm-title,.knobs-confirm-body,.knobs-confirm-btn,.knobs-toast-action){all:revert;box-sizing:border-box;font:inherit;color:inherit;letter-spacing:inherit;\n background:transparent;border:0;margin:0;padding:0;outline:none;box-shadow:none}\n.knobs-layers .knobs-layer *{box-sizing:border-box}\n/* A floating surface: frosted, a hairline rim, a soft shadow. */\n.knobs-layers>:is(.knobs-popover-layer,.knobs-palette,.knobs-confirm,.knobs-menu-layer){background:color-mix(in srgb,var(--_k-bg) 88%,transparent);\n -webkit-backdrop-filter:blur(28px) saturate(1.7);backdrop-filter:blur(28px) saturate(1.7);border-radius:var(--_k-radius-panel);\n box-shadow:0 0 0 .5px var(--_k-border-strong),inset 0 1px 0 var(--_k-rim),0 12px 40px rgba(0,0,0,calc(.36 * var(--_k-shadow-k,1))),0 2px 8px rgba(0,0,0,calc(.18 * var(--_k-shadow-k,1)))}\n.knobs-layers>.knobs-popover-layer{min-width:120px;max-width:min(420px,calc(100vw - 16px));padding:6px}\n.knobs-popover-layer .knobs-popover-text{padding:4px 6px;color:var(--_k-fg-2)}\n\n/* Menus: rows of the panel's control height, a soft wash on the active one (never an outline),\n concentric corners inside the surface. */\n.knobs-layers>.knobs-menu-layer{display:flex;flex-direction:column;min-width:184px;max-width:min(340px,calc(100vw - 16px));max-height:calc(100vh - 16px);overflow:auto;padding:5px;\n scrollbar-width:thin;overscroll-behavior:contain;user-select:none;-webkit-user-select:none}\n.knobs-menu-layer .knobs-mitem{position:relative;display:flex;align-items:center;gap:8px;flex:none;height:max(22px,calc(var(--_k-row) - 6px));padding:0 8px;\n border-radius:max(0px,calc(var(--_k-radius-panel) - 5px));color:var(--_k-fg);cursor:default;white-space:nowrap}\n.knobs-menu-layer .knobs-mitem[data-active],.knobs-menu-layer .knobs-mitem[data-open]{background:var(--_ku-wash-hi)}\n.knobs-menu-layer .knobs-mitem[data-destructive]{color:var(--_k-danger)}\n.knobs-menu-layer .knobs-mitem[data-destructive][data-active]{background:color-mix(in srgb,var(--_k-danger) 16%,transparent)}\n.knobs-menu-layer .knobs-mitem[aria-disabled=\"true\"]{opacity:.38}\n.knobs-menu-layer .knobs-menu-lead{flex:none;display:flex;align-items:center;justify-content:center;width:14px;margin-left:-2px;color:var(--_k-fg-2);font-size:calc(var(--_k-font-size) - 1px)}\n.knobs-menu-layer .knobs-mitem[data-destructive] .knobs-menu-lead,.knobs-menu-layer .knobs-mitem[aria-checked=\"true\"] .knobs-menu-lead{color:inherit}\n.knobs-menu-layer .knobs-menu-lead svg{width:13px;height:13px}\n.knobs-menu-layer .knobs-menu-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}\n.knobs-menu-layer .knobs-menu-hint{flex:none;color:var(--_k-fg-3)}\n.knobs-menu-layer .knobs-menu-keys{display:inline-flex;gap:2px;flex:none;margin-left:12px}\n.knobs-menu-layer .knobs-mitem[data-active] .knobs-kbd{background:color-mix(in srgb,var(--_k-fg) 14%,transparent);color:var(--_k-fg)}\n.knobs-menu-layer .knobs-menu-caret{flex:none;display:flex;margin-left:8px;margin-right:-3px;color:var(--_k-fg-3)}\n.knobs-menu-layer .knobs-menu-caret svg{width:10px;height:10px}\n.knobs-menu-layer .knobs-menu-sep{flex:none;height:1px;margin:4px 8px;background:var(--_k-border)}\n\n.knobs-layers>.knobs-tooltip{display:inline-flex;align-items:center;gap:7px;max-width:300px;padding:4px 8px;pointer-events:none;white-space:nowrap;\n font-size:calc(var(--_k-font-size) - .5px);background:var(--_k-bg);color:var(--_k-fg);border-radius:min(var(--_k-radius),6px);\n box-shadow:0 0 0 .5px var(--_k-border-strong),0 4px 14px rgba(0,0,0,calc(.3 * var(--_k-shadow-k,1)))}\n.knobs-tooltip .knobs-tooltip-text{overflow:hidden;text-overflow:ellipsis}\n.knobs-layer :is(.knobs-tooltip-keys,.knobs-palette-keys){display:inline-flex;gap:2px;flex:none}\n.knobs-layer .knobs-tooltip-keys[hidden]{display:none}\n.knobs-layer .knobs-kbd{display:inline-flex;align-items:center;justify-content:center;min-width:17px;height:17px;padding:0 4px;\n border-radius:min(var(--_k-radius),4px);background:var(--_k-fill-selected);color:var(--_k-fg-2);font:500 calc(var(--_k-font-size) - 1.5px)/1 var(--_k-font)}\n\n.knobs-layers>.knobs-palette{left:50%;top:max(48px,15vh);translate:-50% 0;transform-origin:50% 0;display:flex;flex-direction:column;\n width:min(580px,calc(100vw - 32px));max-height:min(460px,72vh);overflow:hidden}\n.knobs-palette .knobs-palette-field{display:flex;align-items:center;gap:10px;flex:none;height:46px;padding:0 16px;border-bottom:1px solid var(--_k-border);color:var(--_k-fg-3)}\n.knobs-palette .knobs-palette-field svg{width:15px;height:15px;flex:none}\n.knobs-palette .knobs-palette-input{flex:1;min-width:0;height:100%;font-size:calc(var(--_k-font-size) + 3px);color:var(--_k-fg);caret-color:var(--_k-accent)}\n.knobs-palette .knobs-palette-input::placeholder{color:var(--_k-fg-3)}\n.knobs-palette .knobs-palette-list{position:relative;flex:1;min-height:0;overflow:auto;padding:6px;scrollbar-width:thin;overscroll-behavior:contain}\n.knobs-palette .knobs-palette-hl{position:absolute;left:6px;right:6px;top:0;border-radius:max(0px,calc(var(--_k-radius-panel) - 6px));background:var(--_ku-wash-hi);opacity:0;pointer-events:none;\n transition:transform var(--_ku-ease-ms) var(--_ku-ease),height var(--_ku-ease-ms) var(--_ku-ease),opacity .12s}\n.knobs-palette .knobs-palette-section{padding:10px 10px 4px;color:var(--_k-fg-3);font-size:calc(var(--_k-font-size) - 1px);font-weight:var(--_k-weight-label);user-select:none}\n.knobs-palette .knobs-palette-section:first-of-type{padding-top:4px}\n.knobs-palette .knobs-palette-item{position:relative;display:flex;align-items:center;gap:8px;height:max(32px,var(--_k-row));padding:0 10px;\n color:var(--_k-fg-2);cursor:default;user-select:none}\n.knobs-palette .knobs-palette-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--_k-fg)}\n/* Searching, the label dims and its matched letters light up. */\n.knobs-palette[data-query] .knobs-palette-label{color:var(--_k-fg-2)}\n.knobs-palette .knobs-palette-label mark{color:var(--_k-accent);font-weight:var(--_k-weight-title)}\n.knobs-palette[data-query] .knobs-palette-item[data-active] .knobs-palette-label{color:var(--_k-fg)}\n.knobs-palette .knobs-palette-hint{flex:none;color:var(--_k-fg-3)}\n.knobs-palette .knobs-palette-fill{flex:1}\n.knobs-palette .knobs-palette-tag{flex:none;color:var(--_k-fg-3);font-size:calc(var(--_k-font-size) - 1px);white-space:nowrap}\n.knobs-palette .knobs-palette-item[aria-disabled=\"true\"]{opacity:.4}\n.knobs-palette .knobs-palette-empty{padding:18px 10px;color:var(--_k-fg-3);text-align:center}\n\n.knobs-layers>.knobs-scrim{inset:0;width:100%;height:100%;background:var(--_k-scrim)}\n.knobs-layers>.knobs-confirm{left:50%;top:42%;translate:-50% -50%;width:min(340px,calc(100vw - 32px));padding:18px 18px 14px}\n.knobs-confirm .knobs-confirm-title{margin:0 0 6px;font-size:calc(var(--_k-font-size) + 1.5px);font-weight:var(--_k-weight-title);color:var(--_k-fg);line-height:1.3}\n.knobs-confirm .knobs-confirm-body{margin:0;color:var(--_k-fg-2);line-height:1.45}\n.knobs-confirm .knobs-confirm-buttons{display:flex;justify-content:flex-end;gap:8px;margin-top:18px}\n.knobs-confirm .knobs-confirm-btn{height:28px;padding:0 14px;border-radius:min(var(--_k-radius),7px);background:var(--_k-fill-selected);color:var(--_k-fg);\n font-weight:var(--_k-weight-label);cursor:pointer;transition:background .15s,filter .15s}\n.knobs-confirm .knobs-confirm-cancel:is(:hover,:focus-visible){background:color-mix(in srgb,var(--_k-fg) 18%,transparent)}\n.knobs-confirm .knobs-confirm-ok{background:var(--_k-accent);color:var(--_k-bg)}\n.knobs-confirm .knobs-confirm-ok[data-destructive]{background:var(--_k-danger);color:#fff}\n.knobs-confirm .knobs-confirm-ok:is(:hover,:focus-visible){filter:brightness(1.14)}\n\n.knobs-ui.knobs-toast{left:50%;top:auto;bottom:24px;z-index:2147480005;translate:-50% 0;display:inline-flex;align-items:center;gap:10px;\n max-width:min(480px,80vw);padding:8px 16px;background:var(--_k-bg);color:var(--_k-fg);border-radius:calc(var(--_k-radius) * 999);\n box-shadow:0 0 0 .5px var(--_k-border-strong),0 8px 28px rgba(0,0,0,calc(.32 * var(--_k-shadow-k,1)))}\n.knobs-toast .knobs-toast-text{overflow-wrap:anywhere}\n.knobs-toast[data-tone=\"warn\"]::before,.knobs-toast[data-tone=\"error\"]::before{content:\"\";flex:none;width:7px;height:7px;border-radius:50%;background:var(--_k-warn)}\n.knobs-toast[data-tone=\"error\"]::before{background:var(--_k-danger)}\n.knobs-toast .knobs-toast-action{flex:none;color:var(--_k-accent);font-weight:var(--_k-weight-title);cursor:pointer}\n.knobs-toast .knobs-toast-action[hidden]{display:none}\n";
@@ -1 +1 @@
1
- export declare const readoutCss = "\n/* Readouts: live values, sparklines, graphs, meters, tables and logs. */\n:where(.knobs-ui) :is(.knobs-rd-chip,.knobs-rd-copy,.knobs-rd-jump,.knobs-rd-find,.knobs-rd-match){all:revert;box-sizing:border-box;\n font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;border-radius:0;margin:0;padding:0;min-width:0;box-shadow:none;outline:none}\n.knobs-ui.knobs-rd,.knobs-rd *{box-sizing:border-box}\n.knobs-ui.knobs-rd{display:flex;align-items:center;gap:8px;min-width:0;color:var(--ku-text);letter-spacing:normal}\n.knobs-rd .knobs-rd-v{font:var(--ku-font-weight) var(--ku-value-size)/1.25 var(--ku-value-font);font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";white-space:nowrap}\n.knobs-rd .knobs-rd-mono{font:400 var(--ku-text-meta)/1.25 var(--ku-mono);font-variant-numeric:tabular-nums;white-space:pre}\n.knobs-rd .knobs-rd-meta{font:var(--ku-font-weight) var(--ku-text-meta)/1.25 var(--ku-font);white-space:nowrap}\n.knobs-rd .knobs-rd-value{display:inline-flex;justify-content:flex-end;align-items:baseline;flex:none;margin-left:auto;contain:layout paint style}\n.knobs-rd .knobs-rd-num{color:var(--ku-text);text-align:right;transition:color .15s}\n.knobs-rd .knobs-rd-unit{margin-left:var(--k-unit-gap,.28em);color:var(--ku-dim)}\n.knobs-rd .knobs-rd-unit[hidden]{display:none}\n.knobs-rd.knobs-rd-watch{flex:1 1 auto;justify-content:flex-end}\n.knobs-rd.knobs-rd-spark,.knobs-rd.knobs-rd-meter{flex:0 1 64%;margin-left:auto}\n.knobs-rd .knobs-rd-plot{display:block;flex:1 1 0;min-width:24px;height:max(12px,calc(var(--ku-control-h) - 2px))}\n.knobs-rd.knobs-rd-meter>.knobs-rd-plot{height:8px}\n.knobs-rd.knobs-rd-spark[data-hover] .knobs-rd-num{color:var(--ku-label)}\n.knobs-rd .knobs-rd-cap,.knobs-rd .knobs-rd-head>span:first-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ku-label);font-weight:var(--ku-label-weight)}\n\n/* Blocks: a head line (the label and what goes with it) over a body. In a panel the row grows to fit. */\n.knobs-panel .knobs-row.knobs-rd-rowblock{display:block;height:auto}\n.knobs-rd.knobs-rd-block{display:flex;flex-direction:column;align-items:stretch;gap:2px;width:100%}\n.knobs-rd .knobs-rd-head{display:flex;align-items:center;gap:0 10px;min-height:var(--ku-row);min-width:0}\n/* The title keeps its words; the legend or tools beside it give way (see fitHead). */\n.knobs-rd .knobs-rd-head>span:first-child{flex:0 0 auto;max-width:100%}\n.knobs-rd .knobs-rd-legend{display:flex;align-items:center;gap:12px;margin-left:auto;min-width:0;overflow:hidden}\n.knobs-rd .knobs-rd-tools{display:flex;align-items:center;gap:10px;margin-left:auto;min-width:0}\n.knobs-rd .knobs-rd-tools>.knobs-rd-find{flex:1 1 56px;min-width:56px;max-width:84px}\n.knobs-rd .knobs-rd-head[data-short] .knobs-rd-legend .knobs-rd-unit{display:none}\n.knobs-rd .knobs-rd-head[data-wrap]{flex-wrap:wrap;padding-bottom:4px}\n.knobs-rd .knobs-rd-head[data-wrap]>span:first-child{display:flex;align-items:center;min-height:var(--ku-row)}\n.knobs-rd .knobs-rd-head[data-wrap]>:is(.knobs-rd-legend,.knobs-rd-tools){flex:1 0 100%;margin-left:0}\n.knobs-rd .knobs-rd-head[data-wrap]>.knobs-rd-tools{flex-wrap:wrap;row-gap:4px}\n.knobs-rd .knobs-rd-key{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}\n.knobs-rd .knobs-rd-swatch{flex:none;width:8px;height:2px;border-radius:1px}\n.knobs-rd .knobs-rd-name{color:var(--ku-label)}\n.knobs-rd .knobs-rd-key>.knobs-rd-value{margin-left:2px}\n.knobs-rd .knobs-rd-plotbox{position:relative;outline:none;margin-bottom:6px}\n.knobs-rd .knobs-rd-plotbox>.knobs-rd-plot{position:absolute;inset:0;width:100%;height:100%;min-width:0}\n.knobs-rd .knobs-rd-tick,.knobs-rd .knobs-rd-mark{position:absolute;color:var(--ku-dim);pointer-events:none;line-height:14px;height:14px}\n.knobs-rd .knobs-rd-tick{left:0}\n.knobs-rd .knobs-rd-tick[data-at=\"top\"]{top:-2px}\n.knobs-rd .knobs-rd-tick[data-at=\"bottom\"]{bottom:0}\n.knobs-rd .knobs-rd-mark{right:0;top:0}\n.knobs-rd .knobs-rd-mark[hidden]{display:none}\n\n.knobs-rd .knobs-rd-grid{display:grid;column-gap:14px;align-items:center;outline:none;margin-bottom:4px}\n.knobs-rd .knobs-rd-tr{display:contents}\n.knobs-rd .knobs-rd-tr>*{height:calc(var(--ku-row) * .72);line-height:calc(var(--ku-row) * .72);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.knobs-rd .knobs-rd-thead>*{height:var(--ku-row);line-height:var(--ku-row)}\n.knobs-rd .knobs-rd-th{color:var(--ku-dim);text-align:right}\n.knobs-rd .knobs-rd-td{color:var(--ku-text)}\n.knobs-rd .knobs-rd-td:first-child{color:var(--ku-label)}\n.knobs-rd .knobs-rd-td[data-num]{text-align:right}\n\n.knobs-rd.knobs-rd-log{--rd-lh:18px}\n.knobs-rd .knobs-rd-chips{display:inline-flex;align-items:center;gap:2px;margin-right:auto}\n.knobs-ui .knobs-rd-chip,.knobs-ui .knobs-rd-copy{height:calc(var(--ku-control-h) - 2px);padding:0 7px;border-radius:min(var(--ku-radius),5px);color:var(--ku-label);cursor:pointer;transition:background .15s,color .15s}\n.knobs-ui .knobs-rd-chip:hover,.knobs-ui .knobs-rd-copy:hover{background:var(--ku-wash);color:var(--ku-text)}\n.knobs-ui .knobs-rd-chip[aria-checked=\"true\"]{background:var(--ku-wash-hi);color:var(--ku-text)}\n.knobs-ui .knobs-rd-find{width:84px;height:calc(var(--ku-control-h) - 2px);padding:0 7px;border-radius:min(var(--ku-radius),5px);\n background:color-mix(in srgb,var(--ku-surface-hi) 60%,transparent);color:var(--ku-text);caret-color:var(--ku-accent)}\n.knobs-rd .knobs-rd-find::placeholder{color:var(--ku-dim)}\n.knobs-rd .knobs-rd-find::-webkit-search-cancel-button{display:none}\n.knobs-rd .knobs-rd-logbody{position:relative;margin-bottom:6px}\n.knobs-rd .knobs-rd-scroll{position:relative;overflow-x:hidden;overflow-y:auto;height:calc(var(--knobs-rd-lines,8) * var(--rd-lh));outline:none;\n background:color-mix(in srgb,var(--ku-surface-hi) 45%,transparent);border-radius:min(var(--ku-radius),6px);scrollbar-width:thin;overscroll-behavior:contain}\n.knobs-rd .knobs-rd-space{position:relative;width:100%}\n.knobs-rd .knobs-rd-line{position:absolute;left:0;right:0;top:0;display:flex;gap:10px;height:var(--rd-lh);line-height:var(--rd-lh);padding:0 8px;contain:layout style;will-change:transform}\n.knobs-rd .knobs-rd-line[hidden]{display:none}\n.knobs-rd .knobs-rd-time{flex:none;color:var(--ku-dim)}\n.knobs-rd .knobs-rd-text{min-width:0;overflow:hidden;text-overflow:ellipsis;color:var(--ku-text)}\n.knobs-rd .knobs-rd-line[data-level=\"warn\"]>.knobs-rd-text{color:var(--ku-warn)}\n.knobs-rd .knobs-rd-line[data-level=\"error\"]>.knobs-rd-text{color:var(--ku-critical)}\n.knobs-rd .knobs-rd-line[data-level=\"debug\"]>.knobs-rd-text{color:var(--ku-dim)}\n.knobs-ui .knobs-rd-match{color:var(--ku-accent)}\n.knobs-ui .knobs-rd-jump{position:absolute;left:50%;bottom:6px;height:20px;padding:0 10px;border-radius:calc(var(--ku-radius) * 999);\n background:var(--ku-accent);color:var(--ku-bg);opacity:0;transform:translate(-50%,6px);cursor:pointer;white-space:nowrap}\n\n/* Under the GPU overlay the readouts' DOM stays for focus, hit-testing and screen readers; the\n overlay draws them. Their filter field sits above it. */\n.knobs-panel[data-gpu-active=\"true\"] .knobs-rd :where(*:not(.knobs-rd-find)),.knobs-panel[data-gpu-active=\"true\"] .knobs-rd{color:transparent!important;background:transparent!important;border-color:transparent!important;box-shadow:none!important}\n.knobs-panel[data-gpu-active=\"true\"] .knobs-rd-plot{visibility:hidden}\n.knobs-panel[data-gpu-active=\"true\"] .knobs-rd-find{position:relative;z-index:2147480003}\n@media(prefers-reduced-motion:reduce){.knobs-rd :where(*){transition:none!important}}\n";
1
+ export declare const readoutCss = "\n/* Readouts: live values, sparklines, graphs, meters, tables and logs. */\n:where(.knobs-ui) :is(.knobs-rd-chip,.knobs-rd-copy,.knobs-rd-jump,.knobs-rd-find,.knobs-rd-match){all:revert;box-sizing:border-box;\n font:inherit;color:inherit;letter-spacing:inherit;background:transparent;border:0;border-radius:0;margin:0;padding:0;min-width:0;box-shadow:none;outline:none}\n.knobs-ui.knobs-rd,.knobs-rd *{box-sizing:border-box}\n.knobs-ui.knobs-rd{display:flex;align-items:center;gap:8px;min-width:0;color:var(--_k-fg);letter-spacing:normal}\n.knobs-rd .knobs-rd-v{font:var(--_k-weight) var(--_k-value-size)/1.25 var(--_k-value-font);font-variant-numeric:tabular-nums;font-feature-settings:\"tnum\";white-space:nowrap}\n.knobs-rd .knobs-rd-mono{font:400 var(--_k-text-meta)/1.25 var(--_k-mono);font-variant-numeric:tabular-nums;white-space:pre}\n.knobs-rd .knobs-rd-meta{font:var(--_k-weight) var(--_k-text-meta)/1.25 var(--_k-font);white-space:nowrap}\n.knobs-rd .knobs-rd-value{display:inline-flex;justify-content:flex-end;align-items:baseline;flex:none;margin-left:auto;contain:layout paint style}\n.knobs-rd .knobs-rd-num{color:var(--_k-fg);text-align:right;transition:color .15s}\n.knobs-rd .knobs-rd-unit{margin-left:var(--k-unit-gap,.28em);color:var(--_k-fg-3)}\n.knobs-rd .knobs-rd-unit[hidden]{display:none}\n.knobs-rd.knobs-rd-watch{flex:1 1 auto;justify-content:flex-end}\n.knobs-rd.knobs-rd-spark,.knobs-rd.knobs-rd-meter{flex:0 1 64%;margin-left:auto}\n.knobs-rd .knobs-rd-plot{display:block;flex:1 1 0;min-width:24px;height:max(12px,calc(var(--_k-control-h) - 2px))}\n.knobs-rd.knobs-rd-meter>.knobs-rd-plot{height:8px}\n.knobs-rd.knobs-rd-spark[data-hover] .knobs-rd-num{color:var(--_k-fg-2)}\n.knobs-rd .knobs-rd-cap,.knobs-rd .knobs-rd-head>span:first-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--_k-fg-2);font-weight:var(--_k-weight-label)}\n\n/* Blocks: a head line (the label and what goes with it) over a body. In a panel the row grows to fit. */\n.knobs-panel .knobs-row.knobs-rd-rowblock{display:block;height:auto}\n.knobs-rd.knobs-rd-block{display:flex;flex-direction:column;align-items:stretch;gap:2px;width:100%}\n.knobs-rd .knobs-rd-head{display:flex;align-items:center;gap:0 10px;min-height:var(--_k-row);min-width:0}\n/* The title keeps its words; the legend or tools beside it give way (see fitHead). */\n.knobs-rd .knobs-rd-head>span:first-child{flex:0 0 auto;max-width:100%}\n.knobs-rd .knobs-rd-legend{display:flex;align-items:center;gap:12px;margin-left:auto;min-width:0;overflow:hidden}\n.knobs-rd .knobs-rd-tools{display:flex;align-items:center;gap:10px;margin-left:auto;min-width:0}\n.knobs-rd .knobs-rd-tools>.knobs-rd-find{flex:1 1 56px;min-width:56px;max-width:84px}\n.knobs-rd .knobs-rd-head[data-short] .knobs-rd-legend .knobs-rd-unit{display:none}\n.knobs-rd .knobs-rd-head[data-wrap]{flex-wrap:wrap;padding-bottom:4px}\n.knobs-rd .knobs-rd-head[data-wrap]>span:first-child{display:flex;align-items:center;min-height:var(--_k-row)}\n.knobs-rd .knobs-rd-head[data-wrap]>:is(.knobs-rd-legend,.knobs-rd-tools){flex:1 0 100%;margin-left:0}\n.knobs-rd .knobs-rd-head[data-wrap]>.knobs-rd-tools{flex-wrap:wrap;row-gap:4px}\n.knobs-rd .knobs-rd-key{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}\n.knobs-rd .knobs-rd-swatch{flex:none;width:8px;height:2px;border-radius:1px}\n.knobs-rd .knobs-rd-name{color:var(--_k-fg-2)}\n.knobs-rd .knobs-rd-key>.knobs-rd-value{margin-left:2px}\n.knobs-rd .knobs-rd-plotbox{position:relative;outline:none;margin-bottom:6px}\n.knobs-rd .knobs-rd-plotbox>.knobs-rd-plot{position:absolute;inset:0;width:100%;height:100%;min-width:0}\n.knobs-rd .knobs-rd-tick,.knobs-rd .knobs-rd-mark{position:absolute;color:var(--_k-fg-3);pointer-events:none;line-height:14px;height:14px}\n.knobs-rd .knobs-rd-tick{left:0}\n.knobs-rd .knobs-rd-tick[data-at=\"top\"]{top:-2px}\n.knobs-rd .knobs-rd-tick[data-at=\"bottom\"]{bottom:0}\n.knobs-rd .knobs-rd-mark{right:0;top:0}\n.knobs-rd .knobs-rd-mark[hidden]{display:none}\n\n.knobs-rd .knobs-rd-grid{display:grid;column-gap:14px;align-items:center;outline:none;margin-bottom:4px}\n.knobs-rd .knobs-rd-tr{display:contents}\n.knobs-rd .knobs-rd-tr>*{height:calc(var(--_k-row) * .72);line-height:calc(var(--_k-row) * .72);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.knobs-rd .knobs-rd-thead>*{height:var(--_k-row);line-height:var(--_k-row)}\n.knobs-rd .knobs-rd-th{color:var(--_k-fg-3);text-align:right}\n.knobs-rd .knobs-rd-td{color:var(--_k-fg)}\n.knobs-rd .knobs-rd-td:first-child{color:var(--_k-fg-2)}\n.knobs-rd .knobs-rd-td[data-num]{text-align:right}\n\n.knobs-rd.knobs-rd-log{--rd-lh:18px}\n.knobs-rd .knobs-rd-chips{display:inline-flex;align-items:center;gap:2px;margin-right:auto}\n.knobs-ui .knobs-rd-chip,.knobs-ui .knobs-rd-copy{height:calc(var(--_k-control-h) - 2px);padding:0 7px;border-radius:min(var(--_k-radius),5px);color:var(--_k-fg-2);cursor:pointer;transition:background .15s,color .15s}\n.knobs-ui .knobs-rd-chip:hover,.knobs-ui .knobs-rd-copy:hover{background:var(--_ku-wash);color:var(--_k-fg)}\n.knobs-ui .knobs-rd-chip[aria-checked=\"true\"]{background:var(--_ku-wash-hi);color:var(--_k-fg)}\n.knobs-ui .knobs-rd-find{width:84px;height:calc(var(--_k-control-h) - 2px);padding:0 7px;border-radius:min(var(--_k-radius),5px);\n background:color-mix(in srgb,var(--_k-fill-selected) 60%,transparent);color:var(--_k-fg);caret-color:var(--_k-accent)}\n.knobs-rd .knobs-rd-find::placeholder{color:var(--_k-fg-3)}\n.knobs-rd .knobs-rd-find::-webkit-search-cancel-button{display:none}\n.knobs-rd .knobs-rd-logbody{position:relative;margin-bottom:6px}\n.knobs-rd .knobs-rd-scroll{position:relative;overflow-x:hidden;overflow-y:auto;height:calc(var(--knobs-rd-lines,8) * var(--rd-lh));outline:none;\n background:color-mix(in srgb,var(--_k-fill-selected) 45%,transparent);border-radius:min(var(--_k-radius),6px);scrollbar-width:thin;overscroll-behavior:contain}\n.knobs-rd .knobs-rd-space{position:relative;width:100%}\n.knobs-rd .knobs-rd-line{position:absolute;left:0;right:0;top:0;display:flex;gap:10px;height:var(--rd-lh);line-height:var(--rd-lh);padding:0 8px;contain:layout style;will-change:transform}\n.knobs-rd .knobs-rd-line[hidden]{display:none}\n.knobs-rd .knobs-rd-time{flex:none;color:var(--_k-fg-3)}\n.knobs-rd .knobs-rd-text{min-width:0;overflow:hidden;text-overflow:ellipsis;color:var(--_k-fg)}\n.knobs-rd .knobs-rd-line[data-level=\"warn\"]>.knobs-rd-text{color:var(--_k-warn)}\n.knobs-rd .knobs-rd-line[data-level=\"error\"]>.knobs-rd-text{color:var(--_k-danger)}\n.knobs-rd .knobs-rd-line[data-level=\"debug\"]>.knobs-rd-text{color:var(--_k-fg-3)}\n.knobs-ui .knobs-rd-match{color:var(--_k-accent)}\n.knobs-ui .knobs-rd-jump{position:absolute;left:50%;bottom:6px;height:20px;padding:0 10px;border-radius:calc(var(--_k-radius) * 999);\n background:var(--_k-accent);color:var(--_k-bg);opacity:0;transform:translate(-50%,6px);cursor:pointer;white-space:nowrap}\n\n/* Under the GPU overlay the readouts' DOM stays for focus, hit-testing and screen readers; the\n overlay draws them. Their filter field sits above it. */\n.knobs-panel[data-gpu-active=\"true\"] .knobs-rd :where(*:not(.knobs-rd-find)),.knobs-panel[data-gpu-active=\"true\"] .knobs-rd{color:transparent!important;background:transparent!important;border-color:transparent!important;box-shadow:none!important}\n.knobs-panel[data-gpu-active=\"true\"] .knobs-rd-plot{visibility:hidden}\n.knobs-panel[data-gpu-active=\"true\"] .knobs-rd-find{position:relative;z-index:2147480003}\n@media(prefers-reduced-motion:reduce){.knobs-rd :where(*){transition:none!important}}\n";
@@ -38,10 +38,14 @@ export interface Palette {
38
38
  readonly surfaceHi: Rgba;
39
39
  readonly warn: Rgba;
40
40
  readonly critical: Rgba;
41
+ /** Series colours after the first (the accent): the theme's `--k-series-*`. */
42
+ readonly series: readonly Rgba[];
41
43
  /** Corner radius (px); 0 squares the bars. */
42
44
  readonly radius: number;
43
45
  }
44
- /** Series colours after the first (the accent). */
46
+ /** The theme's chart series, read for the series after the first (the accent). */
47
+ export declare const SERIES_TOKENS: readonly ["--_k-series-1", "--_k-series-2", "--_k-series-3", "--_k-series-4", "--_k-series-5", "--_k-series-6"];
48
+ /** Series colours where no token sheet has loaded. */
45
49
  export declare const SERIES: string[];
46
50
  /** A number as text: `decimals` places, else fewer as it grows (2 under 10, 1 under 100, 0 past). */
47
51
  export declare function formatNumber(v: number, decimals?: number): string;
@@ -4,3 +4,14 @@ export declare function parseCssColor(raw: string, fallback?: Rgba): Rgba;
4
4
  export declare const withAlpha: (c: Rgba, k: number) => Rgba;
5
5
  export declare const mixRgba: (a: Rgba, b: Rgba, t: number) => Rgba;
6
6
  export declare const rgbaCss: (c: Rgba) => string;
7
+ /**
8
+ * A token's computed value with each `light-dark(a, b)` in it (as theme colours arrive in custom
9
+ * properties) replaced by the side `light` picks, so a canvas can parse it.
10
+ */
11
+ export declare function pickScheme(raw: string, light: boolean): string;
12
+ /** Whether a knobs root (or anything in one) shows its light appearance. */
13
+ export declare const isLightStyle: (style: CSSStyleDeclaration) => boolean;
14
+ /** A colour token (`--kv-fg`, `--_k-warn`) as `style`'s element shows it. */
15
+ export declare function tokenColor(style: CSSStyleDeclaration, name: string, fallback: Rgba): Rgba;
16
+ /** A colour token as CSS a canvas takes, or `fallback`. */
17
+ export declare function tokenCss(style: CSSStyleDeclaration, name: string, fallback: string): string;
@@ -0,0 +1,43 @@
1
+ import { type ContextEvent, type WalkChapter, type WalkMedia } from "./walkthrough-model.js";
2
+ /** How media reach the page's steps: `step` on a history event, a stack item or a table cell. */
3
+ export interface StepLinks {
4
+ /** The step a ref names (its key, id or number), or null when there's none. */
5
+ find(ref: string): {
6
+ readonly key: string;
7
+ readonly number: string;
8
+ readonly title: string;
9
+ } | null;
10
+ /** Goes to the step, as j / k do. */
11
+ go(key: string): void;
12
+ }
13
+ type OnEvent = ((event: Omit<ContextEvent, "at" | "step">) => void) | undefined;
14
+ export interface Block {
15
+ dispose(): void;
16
+ context?(): {
17
+ kind: string;
18
+ };
19
+ }
20
+ export declare function mountHistory(host: HTMLElement, m: Extract<WalkMedia, {
21
+ kind: "history";
22
+ }>, steps: StepLinks | undefined): Block;
23
+ export declare function mountStack(host: HTMLElement, m: Extract<WalkMedia, {
24
+ kind: "stack";
25
+ }>, steps: StepLinks | undefined): Block;
26
+ export declare function mountTable(host: HTMLElement, m: Extract<WalkMedia, {
27
+ kind: "table";
28
+ }>, steps: StepLinks | undefined): Block;
29
+ export interface ChapterPills {
30
+ /** The chapter the time is in (call as it plays or seeks): the highlight springs to it. */
31
+ sync(): void;
32
+ /** The chapter playing, or null. */
33
+ readonly current: WalkChapter | null;
34
+ dispose(): void;
35
+ }
36
+ export declare function chapterPills(host: HTMLElement, chapters: readonly WalkChapter[], io: {
37
+ /** Seconds. */
38
+ now(): number;
39
+ /** Seeks and plays. */
40
+ seek(time: number): void;
41
+ onEvent: OnEvent;
42
+ }): ChapterPills;
43
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { type UiLook } from "./look.js";
2
+ import { type StepLinks } from "./walkthrough-blocks.js";
2
3
  import { type ContextEvent, type MediaContext, type WalkthroughMedia } from "./walkthrough-model.js";
3
4
  export interface MediaSlotOptions extends UiLook {
4
5
  readonly media: WalkthroughMedia;
@@ -6,7 +7,10 @@ export interface MediaSlotOptions extends UiLook {
6
7
  readonly lazy?: boolean;
7
8
  /** Kit played, paused or sought a video, or showed another diff file (for a note's log). */
8
9
  readonly onEvent?: (event: Omit<ContextEvent, "at" | "step">) => void;
10
+ /** The page's steps, for `step` on a history event, a stack item or a table cell. */
11
+ readonly steps?: StepLinks;
9
12
  }
13
+ export type { StepLinks };
10
14
  export interface MediaSlot {
11
15
  readonly element: HTMLElement;
12
16
  /** Whether its content is mounted (heavy kinds wait until they're near the view). */
@@ -7,6 +7,98 @@ export interface WalkthroughSource {
7
7
  readonly src: string;
8
8
  readonly label?: string;
9
9
  }
10
+ /** A status colour: a dot, a chip or a cell's badge. */
11
+ export type WalkthroughTone = "good" | "warn" | "bad" | "info" | "dim";
12
+ /** A small tag that backs a claim: a PR, a commit, a log, as a link or not. */
13
+ export interface WalkthroughEvidence {
14
+ readonly label: string;
15
+ readonly href?: string;
16
+ }
17
+ /** One dated moment in a `history`. */
18
+ export interface WalkthroughHistoryEvent {
19
+ /** As written: "Apr 9, 2026", "2026-04-09", "May 7–8". */
20
+ readonly date: string;
21
+ /** How long ago, or how long it lasted: "116d ago". */
22
+ readonly age?: string;
23
+ readonly title: string;
24
+ readonly detail?: string;
25
+ readonly tone?: WalkthroughTone;
26
+ /** Seen in the record (`"verified"`) or worked out from behaviour (`"inferred"`). */
27
+ readonly provenance?: "verified" | "inferred";
28
+ /** Where it was seen or inferred from: `"git"` shows as "verified · git". */
29
+ readonly source?: string;
30
+ readonly evidence?: readonly WalkthroughEvidence[];
31
+ /** A step it's about: its key, id or number ("1.2"). */
32
+ readonly step?: string;
33
+ /** What happened, which shapes its dot: a release a diamond, an audit a square. */
34
+ readonly type?: "commit" | "release" | "channel" | "audit" | (string & {});
35
+ }
36
+ export interface WalkthroughHistoryGroup {
37
+ readonly heading?: string;
38
+ readonly summary?: string;
39
+ readonly events?: readonly WalkthroughHistoryEvent[];
40
+ /** Another name for `events`. */
41
+ readonly rows?: readonly WalkthroughHistoryEvent[];
42
+ }
43
+ /** One PR in a `stack`. */
44
+ export interface WalkthroughStackItem {
45
+ /** "#57148" (or 57148). */
46
+ readonly pr: string | number;
47
+ readonly href?: string;
48
+ readonly title: string;
49
+ /** Its branch: `"head → base"` (or `->`), or just the head (on `base`, else the trunk). */
50
+ readonly branch?: string;
51
+ /** The branch it merges into, when `branch` names only its head. */
52
+ readonly base?: string;
53
+ /** Lines changed: `"+164 / -18"`, or `{ add, del }`. */
54
+ readonly delta?: string | {
55
+ readonly add: number;
56
+ readonly del: number;
57
+ };
58
+ readonly status?: string;
59
+ readonly tone?: WalkthroughTone;
60
+ readonly summary?: string;
61
+ /** Its head branch, with `base`: another way to write `branch`. */
62
+ readonly head?: string;
63
+ /** The step that shows it: its key, id or number. */
64
+ readonly step?: string;
65
+ /** Another name for `step`. */
66
+ readonly stepId?: string;
67
+ /** Its place as written: "01", "06 · 1/4". */
68
+ readonly order?: string | number;
69
+ }
70
+ /** A table's cell: its text, or that with a link, code, a badge, a colour or a step. */
71
+ export type WalkthroughTableCell = string | number | {
72
+ readonly text: string | number;
73
+ readonly href?: string;
74
+ readonly code?: boolean;
75
+ /** Drawn as a chip in this colour. */
76
+ readonly badge?: WalkthroughTone;
77
+ /** The text in this colour. */
78
+ readonly tone?: WalkthroughTone;
79
+ readonly step?: string;
80
+ };
81
+ export interface WalkthroughTableColumn {
82
+ readonly key: string;
83
+ readonly label: string;
84
+ readonly mono?: boolean;
85
+ /** Numbers go right by default. */
86
+ readonly align?: "left" | "right" | "center";
87
+ }
88
+ /** A row: its cells by column key, bare or under `cells`. */
89
+ export type WalkthroughTableRow = Readonly<Record<string, WalkthroughTableCell>> | {
90
+ readonly cells: Readonly<Record<string, WalkthroughTableCell>>;
91
+ };
92
+ /** A stretch of a video: a pill under it, and a marker on its timeline. */
93
+ export interface WalkthroughChapter {
94
+ readonly id?: string;
95
+ readonly label: string;
96
+ /** Seconds. */
97
+ readonly start: number;
98
+ /** Seconds; else `start + duration`, else the next chapter's start. */
99
+ readonly end?: number;
100
+ readonly duration?: number;
101
+ }
10
102
  /**
11
103
  * What a step shows. A bare string is a video or image URL (by its extension). `mount` is the one
12
104
  * kind that isn't JSON: anything of your own, given its element, returning its cleanup.
@@ -21,12 +113,37 @@ export type WalkthroughMedia = string | {
21
113
  readonly aspect?: number | string;
22
114
  /** The frame strip over the timeline. */
23
115
  readonly strip?: boolean;
116
+ /** Pills under it that seek, and markers on its timeline. */
117
+ readonly chapters?: readonly WalkthroughChapter[];
24
118
  } | {
25
119
  readonly kind: "video";
26
120
  readonly src: string;
27
121
  readonly label?: string;
28
122
  readonly aspect?: number | string;
29
123
  readonly poster?: string;
124
+ /** Pills under it that seek; the one playing lit. */
125
+ readonly chapters?: readonly WalkthroughChapter[];
126
+ /** A WebVTT file's URL, shown by default. */
127
+ readonly captions?: string;
128
+ /** Another name for `captions`. */
129
+ readonly captionsSrc?: string;
130
+ } | {
131
+ readonly kind: "history";
132
+ /** Dated events under quiet headings… */
133
+ readonly groups?: readonly WalkthroughHistoryGroup[];
134
+ /** …or one run of them. */
135
+ readonly events?: readonly WalkthroughHistoryEvent[];
136
+ } | {
137
+ readonly kind: "stack";
138
+ /** The branch the stack lands on ("dev"); else the one most items merge into. */
139
+ readonly base?: string;
140
+ /** In merge order; an item on another's branch hangs under it. */
141
+ readonly items: readonly WalkthroughStackItem[];
142
+ } | {
143
+ readonly kind: "table";
144
+ readonly columns: readonly WalkthroughTableColumn[];
145
+ readonly rows: readonly WalkthroughTableRow[];
146
+ readonly caption?: string;
30
147
  } | {
31
148
  readonly kind: "image";
32
149
  readonly src: string;
@@ -154,11 +271,78 @@ export interface WalkthroughDoc {
154
271
  type CompareMedia = Extract<WalkthroughMedia, {
155
272
  kind: "compare";
156
273
  }>;
157
- /** Media filled in: no bare URLs, and a compare's sides as sources. */
158
- export type WalkMedia = Exclude<WalkthroughMedia, string | CompareMedia> | (Omit<CompareMedia, "before" | "after"> & {
274
+ type VideoMedia = Extract<WalkthroughMedia, {
275
+ kind: "video";
276
+ }>;
277
+ /** A chapter filled in: an id, and its end where one can be known. */
278
+ export interface WalkChapter {
279
+ readonly id: string;
280
+ readonly label: string;
281
+ readonly start: number;
282
+ readonly end?: number;
283
+ }
284
+ export interface WalkHistoryGroup {
285
+ readonly heading?: string;
286
+ readonly summary?: string;
287
+ readonly events: readonly WalkthroughHistoryEvent[];
288
+ }
289
+ /** A stack's item filled in: its PR as `#123`, its branch split, `step` for `stepId`. */
290
+ export interface WalkStackItem {
291
+ readonly pr: string;
292
+ readonly href?: string;
293
+ readonly title: string;
294
+ readonly head?: string;
295
+ readonly base?: string;
296
+ readonly delta?: string | {
297
+ readonly add: number;
298
+ readonly del: number;
299
+ };
300
+ readonly status?: string;
301
+ readonly tone?: WalkthroughTone;
302
+ readonly summary?: string;
303
+ readonly step?: string;
304
+ readonly order?: string;
305
+ }
306
+ export interface WalkTableCell {
307
+ readonly text: string;
308
+ readonly href?: string;
309
+ readonly code?: boolean;
310
+ readonly badge?: WalkthroughTone;
311
+ readonly tone?: WalkthroughTone;
312
+ readonly step?: string;
313
+ }
314
+ export interface WalkTableColumn {
315
+ readonly key: string;
316
+ readonly label: string;
317
+ readonly mono?: boolean;
318
+ readonly align: "left" | "right" | "center";
319
+ }
320
+ /**
321
+ * Media filled in: no bare URLs, a compare's sides as sources, chapters with their ends, history in
322
+ * groups, a stack's branches split and a table's cells as objects. Filling it again changes
323
+ * nothing.
324
+ */
325
+ export type WalkMedia = Exclude<WalkthroughMedia, string | {
326
+ readonly kind: "compare" | "video" | "history" | "stack" | "table";
327
+ }> | (Omit<CompareMedia, "before" | "after" | "chapters"> & {
159
328
  readonly before: WalkthroughSource;
160
329
  readonly after: WalkthroughSource;
161
- });
330
+ readonly chapters?: readonly WalkChapter[];
331
+ }) | (Omit<VideoMedia, "chapters" | "captionsSrc"> & {
332
+ readonly chapters?: readonly WalkChapter[];
333
+ }) | {
334
+ readonly kind: "history";
335
+ readonly groups: readonly WalkHistoryGroup[];
336
+ } | {
337
+ readonly kind: "stack";
338
+ readonly base?: string;
339
+ readonly items: readonly WalkStackItem[];
340
+ } | {
341
+ readonly kind: "table";
342
+ readonly columns: readonly WalkTableColumn[];
343
+ readonly rows: readonly Readonly<Record<string, WalkTableCell>>[];
344
+ readonly caption?: string;
345
+ };
162
346
  export interface WalkOption {
163
347
  readonly id: string;
164
348
  readonly label: string;
@@ -231,6 +415,54 @@ export declare const mediaOf: (src: string) => WalkMedia;
231
415
  export declare function parseAspect(aspect: number | string | undefined): number | undefined;
232
416
  /** Media filled in: a bare URL as a video or image, sources resolved against `base`. */
233
417
  export declare function fillMedia(m: WalkthroughMedia, base?: string): WalkMedia;
418
+ /** `"head → base"` (or `->`, `=>`, `⇒`) as its two branches; one name is the head alone. */
419
+ export declare function parseBranch(branch: string | undefined): {
420
+ head?: string;
421
+ base?: string;
422
+ };
423
+ /** `"+164 / -18"`, `"+164 −18"` or `{ add, del }` as numbers; other text stays as written. */
424
+ export declare function parseDelta(delta: WalkthroughStackItem["delta"]): {
425
+ add: number;
426
+ del: number;
427
+ } | string | undefined;
428
+ /** One row of a stack as drawn: where it hangs, and which rails pass beside it. */
429
+ export interface StackRow {
430
+ readonly item: WalkStackItem;
431
+ /** Its place in `items`. */
432
+ readonly index: number;
433
+ /** 0 on the trunk; one more for each item it's stacked on. */
434
+ readonly depth: number;
435
+ /** The item it's stacked on (its place in `items`); null on the trunk. */
436
+ readonly parent: number | null;
437
+ /** The last of its siblings: its rail ends here (└) rather than going on (├). */
438
+ readonly last: boolean;
439
+ /** For each level above its own (0 the trunk's), whether that level's rail passes beside it. */
440
+ readonly rails: readonly boolean[];
441
+ readonly children: number;
442
+ /** The branch it merges into when that's neither the trunk nor another item's. */
443
+ readonly offBase?: string;
444
+ }
445
+ export interface StackLayout {
446
+ /** The branch it lands on: `base`, else the one most items merge into; null when none says. */
447
+ readonly trunk: string | null;
448
+ /** Depth-first in merge order: each item after the one it's stacked on. */
449
+ readonly rows: readonly StackRow[];
450
+ /** Nothing is stacked on anything, and there's no trunk: a plain list. */
451
+ readonly flat: boolean;
452
+ }
453
+ /** A stack's branch topology: which item each one is stacked on, in rows to draw as a graph. */
454
+ export declare function stackLayout(m: {
455
+ readonly base?: string;
456
+ readonly items: readonly WalkStackItem[];
457
+ }): StackLayout;
458
+ /** Chapters with ids and, where it can be known, an end: given, `start + duration`, or the next. */
459
+ export declare function fillChapters(chapters: readonly WalkthroughChapter[]): WalkChapter[];
460
+ /** The chapter playing at `time` (seconds): the one it's in that started last; -1 for none. */
461
+ export declare function chapterAt(chapters: readonly WalkChapter[], time: number): number;
462
+ /** Seconds as a clock: `1:05`, `1:02:05` past the hour. */
463
+ export declare function clock(seconds: number): string;
464
+ /** A step named by its key, id or number ("1.2"), a leading `#` allowed; undefined if there's none. */
465
+ export declare function findStep(steps: readonly WalkStep[], ref: string | undefined): WalkStep | undefined;
234
466
  /** A GitHub PR or issue URL's number as `#123`; else the URL's last part. */
235
467
  export declare function linkLabel(href: string): string;
236
468
  /**
@@ -280,6 +512,8 @@ export interface MediaContext {
280
512
  readonly time?: number;
281
513
  readonly duration?: number;
282
514
  readonly playing?: boolean;
515
+ /** The chapter the time is in, by its label. */
516
+ readonly chapter?: string;
283
517
  /** The loop range, in seconds. */
284
518
  readonly loop?: {
285
519
  readonly start: number;
@@ -1,6 +1,6 @@
1
1
  import { type StoragePort } from "../core/storage.js";
2
2
  import { type UiLook } from "./look.js";
3
- import { type MediaSlot } from "./walkthrough-media.js";
3
+ import { type MediaSlot, type StepLinks } from "./walkthrough-media.js";
4
4
  import { type WalkOption, type WalkPage, type WalkthroughDoc, type WalkthroughFeedback, type WalkthroughOption, type WalkthroughState } from "./walkthrough-model.js";
5
5
  export interface TasteTestOptions extends UiLook {
6
6
  readonly options: readonly (WalkthroughOption | WalkOption)[];
@@ -9,6 +9,8 @@ export interface TasteTestOptions extends UiLook {
9
9
  readonly onPick?: (id: string | null) => void;
10
10
  /** Mount each option's media when near the view (on by default). */
11
11
  readonly lazy?: boolean;
12
+ /** The page's steps, for media that name one. */
13
+ readonly steps?: StepLinks;
12
14
  }
13
15
  export interface TasteTest {
14
16
  readonly element: HTMLElement;