@kitlangton/knobs 0.4.0-next.15 → 0.4.0-next.17
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 +46 -14
- package/dist/dev/{chunk-v2g91mrm.js → chunk-2g0znytq.js} +1 -0
- package/dist/dev/{chunk-bejz4qcg.js → chunk-3vag4n3q.js} +47 -10
- package/dist/dev/{chunk-49hkdggk.js → chunk-5cv3g7ca.js} +395 -104
- package/dist/dev/{chunk-902v1jgd.js → chunk-xzm0zawh.js} +6 -6
- package/dist/dev/index.js +9 -8
- package/dist/index.js +7 -5
- package/dist/panel.js +549 -121
- package/dist/review-react.js +1341 -880
- package/dist/review-solid.js +1341 -880
- package/dist/review.js +1711 -1248
- package/dist/themes.js +8 -0
- package/dist/types/core/schema.d.ts +11 -2
- package/dist/types/core/store.d.ts +29 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/panel/active.d.ts +53 -0
- package/dist/types/panel/description-ids.d.ts +6 -0
- package/dist/types/panel/folds.d.ts +7 -4
- package/dist/types/panel/gpu/color.d.ts +2 -0
- package/dist/types/panel/gpu/renderer.d.ts +8 -2
- package/dist/types/panel/index.d.ts +1 -0
- package/dist/types/panel/page-hints.d.ts +3 -2
- package/dist/types/panel/page.d.ts +2 -15
- package/dist/types/panel/position.d.ts +23 -0
- package/dist/types/panel/summary.d.ts +22 -0
- package/dist/types/tokens/schema.d.ts +9 -0
- package/dist/types/ui/compare-css.d.ts +1 -1
- package/dist/types/ui/compare-frames.d.ts +64 -2
- package/dist/types/ui/compare-model.d.ts +23 -0
- package/dist/types/ui/compare.d.ts +6 -4
- package/dist/types/ui/player-css.d.ts +1 -1
- package/dist/types/ui/player.d.ts +6 -0
- package/dist/types/ui/react.d.ts +1 -1
- package/dist/types/ui/solid.d.ts +1 -1
- package/dist/types/ui/tooltip-model.d.ts +35 -0
- package/dist/types/ui/tooltip.d.ts +1 -1
- package/dist/types/ui/walkthrough-model.d.ts +4 -2
- package/dist/ui-react.js +2015 -1507
- package/dist/ui-solid.js +2014 -1506
- package/dist/ui.js +2013 -1505
- package/package.json +1 -1
package/dist/panel.js
CHANGED
|
@@ -1825,6 +1825,14 @@ var init_schema = __esm(() => {
|
|
|
1825
1825
|
doc: "Panel and card radius, concentric with controls.",
|
|
1826
1826
|
deprecated: ["--k-panel-radius", "--ku-panel-radius"]
|
|
1827
1827
|
},
|
|
1828
|
+
{
|
|
1829
|
+
name: "radius-frame",
|
|
1830
|
+
tier: "semantic",
|
|
1831
|
+
type: "length",
|
|
1832
|
+
group: "Shape",
|
|
1833
|
+
source: css("calc(var(--k-radius) + min(var(--k-radius) * 999, var(--_k-pad) + 1px))"),
|
|
1834
|
+
doc: "A tuning panel's outer corners: its cards' radius plus its padding and border, so the cards, the preset strip and the focus lens inside run concentric. Squares when --k-radius is 0."
|
|
1835
|
+
},
|
|
1828
1836
|
{
|
|
1829
1837
|
name: "round",
|
|
1830
1838
|
tier: "semantic",
|
|
@@ -2943,7 +2951,16 @@ var init_glide = __esm(() => {
|
|
|
2943
2951
|
"border-subtle",
|
|
2944
2952
|
"bg-page"
|
|
2945
2953
|
];
|
|
2946
|
-
LENGTH_TOKENS = [
|
|
2954
|
+
LENGTH_TOKENS = [
|
|
2955
|
+
"pad",
|
|
2956
|
+
"inset",
|
|
2957
|
+
"row",
|
|
2958
|
+
"gap",
|
|
2959
|
+
"radius",
|
|
2960
|
+
"radius-panel",
|
|
2961
|
+
"radius-frame",
|
|
2962
|
+
"font-size"
|
|
2963
|
+
];
|
|
2947
2964
|
NUMBER_TOKENS = ["weight-label", "blur", "glow", "glass", "glass-tone"];
|
|
2948
2965
|
ANIMATED = [...COLOR_TOKENS, ...LENGTH_TOKENS, ...NUMBER_TOKENS, "width"];
|
|
2949
2966
|
TOKEN_TRANSITIONS = ANIMATED.map((t) => `--kt-${t} var(--k-token-t)`).join(",");
|
|
@@ -3129,13 +3146,15 @@ ${GRAD_PROPS}
|
|
|
3129
3146
|
catches its top. The light rides on the edge (a shadow raised by its width, so only its top
|
|
3130
3147
|
shows), not inside the card's 1px border, where it read as a second edge. */
|
|
3131
3148
|
.knobs-panel{-webkit-user-select:none;user-select:none;transition:${TOKEN_TRANSITIONS},--k-armed ${ARMED_T};position:fixed;z-index:2147480001;width:var(--_k-width);max-width:calc(100vw - 16px);max-height:calc(100dvh - 16px);overflow:auto;padding:var(--_k-pad);
|
|
3132
|
-
background:color-mix(in srgb,var(--_k-bg) calc(100% - var(--_k-glass) * 20%),transparent);border:1px solid transparent;border-radius:var(--_k-radius-
|
|
3149
|
+
background:color-mix(in srgb,var(--_k-bg) calc(100% - var(--_k-glass) * 20%),transparent);border:1px solid transparent;border-radius:var(--_k-radius-frame);box-shadow:var(--_k-shadow-overlay),0 calc(var(--k-rim-width) * -1) 0 var(--_k-rim),0 0 0 var(--k-rim-width) var(--ka-edge),var(--ka-glow);scrollbar-width:thin;
|
|
3133
3150
|
/* Armed (focus inside: keys come here), the edge takes the accent and a faint glow lifts it. */
|
|
3134
3151
|
--ka-edge:color-mix(in srgb,var(--_k-accent) calc(var(--k-armed) * var(--k-armed-edge) * 100%),var(--_k-border-subtle));
|
|
3135
3152
|
--ka-glow:0 0 calc(var(--k-armed-glow) * 1px) color-mix(in srgb,var(--_k-accent) calc(var(--k-armed) * var(--k-armed-glow-a) * var(--k-chrome,1) * 100%),transparent);
|
|
3136
3153
|
--k-backdrop:blur(calc(var(--_k-glass) * 24px)) saturate(calc(1 + var(--_k-glass) * .8)) brightness(calc(1 + (var(--_k-glass-tone) - 1) * var(--_k-glass)));
|
|
3137
3154
|
-webkit-backdrop-filter:var(--k-backdrop);backdrop-filter:var(--k-backdrop);
|
|
3138
3155
|
animation:knobs-in .16s var(--k-ease);}
|
|
3156
|
+
/* On a phone a floating panel takes the width, less a gutter, and scrolls inside the height. */
|
|
3157
|
+
@media(max-width:420px){.knobs-panel:not(.knobs-inline){width:calc(100vw - 16px)}}
|
|
3139
3158
|
.knobs-panel[data-restored]{animation:none}
|
|
3140
3159
|
/* Opening from its chip, the panel's chrome rides a separate shape (see morph.ts) while the
|
|
3141
3160
|
content, laid out at full size, is clipped to it and revealed top first. */
|
|
@@ -3169,8 +3188,9 @@ ${GRAD_PROPS}
|
|
|
3169
3188
|
:is(.knobs-panel,.knobs-menu) :is(:focus,:focus-visible):where(:not(.knobs-accessory *)){outline:none}
|
|
3170
3189
|
|
|
3171
3190
|
/* Header */
|
|
3172
|
-
|
|
3173
|
-
.knobs-panel
|
|
3191
|
+
/* A floating panel's header carries it; the hand shows only while it's carrying (data-dragging). */
|
|
3192
|
+
.knobs-panel header{position:relative;display:flex;align-items:center;justify-content:space-between;gap:6px;touch-action:none;padding:0 var(--_k-inset) var(--k-section-gap);min-height:var(--k-icon-btn)}
|
|
3193
|
+
.knobs-panel[data-dragging]>header,.knobs-panel[data-dragging]>header *{cursor:grabbing}
|
|
3174
3194
|
/* The title row stays pinned while the rows scroll under it, in the panel (it scrolls once it's
|
|
3175
3195
|
bounded) or, with .knobs-pin-ancestor (which also makes the panel overflow:visible), in the
|
|
3176
3196
|
nearest scroller around it. Once rows are under it, and only then, it frosts (backdrop blur over
|
|
@@ -3185,7 +3205,7 @@ ${GRAD_PROPS}
|
|
|
3185
3205
|
@supports (animation-timeline:scroll()){
|
|
3186
3206
|
.knobs-panel:not(.knobs-page){scroll-timeline:--knobs-self block}
|
|
3187
3207
|
.knobs-panel.knobs-pin-ancestor:not(.knobs-page){overflow:visible;view-timeline:--knobs-view block}
|
|
3188
|
-
.knobs-panel:not(.knobs-page)>header{position:sticky;top:0;z-index:4;border-radius:max(0px,calc(var(--_k-radius-
|
|
3208
|
+
.knobs-panel:not(.knobs-page)>header{position:sticky;top:0;z-index:4;border-radius:max(0px,calc(var(--_k-radius-frame) - 1px)) max(0px,calc(var(--_k-radius-frame) - 1px)) 0 0;
|
|
3189
3209
|
--k-head-on:max(var(--k-head-s),var(--k-head-v));--k-head-bg:color-mix(in srgb,var(--_k-bg) 88%,transparent);
|
|
3190
3210
|
background:color-mix(in srgb,var(--k-head-bg) calc(var(--k-head-on) * 100%),transparent);
|
|
3191
3211
|
animation:knobs-head-s linear both;animation-timeline:--knobs-self;animation-range:0px 24px}
|
|
@@ -3195,7 +3215,6 @@ ${GRAD_PROPS}
|
|
|
3195
3215
|
.knobs-panel[data-gpu-active="true"]:not(.knobs-page)>header{background:transparent!important;-webkit-backdrop-filter:none!important;backdrop-filter:none!important}
|
|
3196
3216
|
.knobs-panel[data-gpu-active="true"]:not(.knobs-page)>header::after{display:none}
|
|
3197
3217
|
}
|
|
3198
|
-
.knobs-panel header:active{cursor:grabbing}
|
|
3199
3218
|
.knobs-panel header strong{flex:1;min-width:0;font-weight:var(--_k-weight-title);font-size:var(--_k-text-title);letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:opacity .2s var(--k-ease),color ${ARMED_T};
|
|
3200
3219
|
color:color-mix(in srgb,var(--_k-fg) calc(var(--k-title-rest) * 100%),var(--_k-fg-2))}
|
|
3201
3220
|
/* At rest a panel's title is a little quiet; armed (keys come here) it's at full strength. */
|
|
@@ -3335,6 +3354,13 @@ ${GRAD_PROPS}
|
|
|
3335
3354
|
.knobs-group-head .knobs-group-die{width:20px;padding:0;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--_k-round);color:var(--_k-fg-3)}
|
|
3336
3355
|
.knobs-group-head .knobs-group-die[disabled]{opacity:var(--k-disabled-opacity);cursor:default}
|
|
3337
3356
|
.knobs-panel .knobs-group-head button:where(:not(.knobs-group-reset)){transition:background var(--k-hover-t),color var(--k-hover-t),opacity .2s,transform .12s}
|
|
3357
|
+
/* A panel card's header: its title, a folded card's summary and its buttons on one line, and its
|
|
3358
|
+
description on the next. The title takes its room first; the summary gets what's left. */
|
|
3359
|
+
.knobs-panel:not(.knobs-page) .knobs-group-head{flex-wrap:wrap;row-gap:0}
|
|
3360
|
+
.knobs-panel:not(.knobs-page) .knobs-group-head>.knobs-group-label{flex:1000 1 0;max-width:max-content;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
3361
|
+
.knobs-group-head>.knobs-group-desc{order:1;flex:0 0 100%;padding:0;line-height:16px;white-space:normal;overflow:visible;text-wrap:pretty}
|
|
3362
|
+
.knobs-group-head>.knobs-group-summary{flex:1 1 0;max-width:max-content;margin-left:auto;font-size:var(--_k-text-meta);text-transform:none}
|
|
3363
|
+
.knobs-group-head[data-folded]>.knobs-group-summary:not(:empty){display:block}
|
|
3338
3364
|
|
|
3339
3365
|
/* Grouped cards: rows share one surface, split by hairlines that stay put whatever a row is doing */
|
|
3340
3366
|
.knobs-card{position:relative;margin-bottom:var(--k-section-gap);border-radius:var(--_k-radius);background:var(--_k-fill);overflow:hidden}
|
|
@@ -4041,7 +4067,7 @@ ${POINTER_ROW} .knobs-slider.knobs-modified:not(:hover,.knobs-active) .knobs-val
|
|
|
4041
4067
|
.knobs-group-summary{display:none;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--_k-fg-3);font-size:var(--_k-text-control);font-weight:500;letter-spacing:0;font-variant-numeric:tabular-nums}
|
|
4042
4068
|
.knobs-tile[data-folded]>.knobs-group-head .knobs-group-summary:not(:empty){display:block}
|
|
4043
4069
|
.knobs-tile[data-folded]>.knobs-group-head .knobs-group-ctl{display:none}
|
|
4044
|
-
.knobs-tile[data-fold-motion]>.knobs-group-head :is(.knobs-group-summary,.knobs-group-ctl){animation:knobs-fade .2s var(--k-ease) both}
|
|
4070
|
+
.knobs-tile[data-fold-motion]>.knobs-group-head :is(.knobs-group-summary,.knobs-group-ctl),.knobs-group-head[data-fold-motion]>.knobs-group-summary{animation:knobs-fade .2s var(--k-ease) both}
|
|
4045
4071
|
/* A highlight (page.highlight): the rest dims under a veil of the page's colour (--k-page-dim at
|
|
4046
4072
|
full), and what's highlighted on its own gets a dot in the gutter by its title. The veil and
|
|
4047
4073
|
dot are written each frame on the panel spring (see page.ts). */
|
|
@@ -5139,12 +5165,24 @@ function createRegistry(doc) {
|
|
|
5139
5165
|
return;
|
|
5140
5166
|
if (e.metaKey || e.ctrlKey || e.altKey || e.key !== PAGE_HINT_KEY)
|
|
5141
5167
|
return;
|
|
5142
|
-
if (isTyping(e.target) || !wide())
|
|
5168
|
+
if (isTyping(e.target) || !wide(e.target))
|
|
5143
5169
|
return;
|
|
5144
5170
|
if (registry.start())
|
|
5145
5171
|
e.preventDefault();
|
|
5146
5172
|
};
|
|
5147
|
-
const
|
|
5173
|
+
const hostHints = () => [...doc.querySelectorAll("[data-hint]")].some((el) => !el.closest(".knobs-panel"));
|
|
5174
|
+
const wide = (target) => {
|
|
5175
|
+
if (!listening)
|
|
5176
|
+
return false;
|
|
5177
|
+
if (sources.some((s) => s.listen && s.rank >= 2) || hostHints())
|
|
5178
|
+
return true;
|
|
5179
|
+
if (sources.length < 2)
|
|
5180
|
+
return false;
|
|
5181
|
+
if (target === undefined)
|
|
5182
|
+
return true;
|
|
5183
|
+
const piece = target?.closest?.(".knobs-ui,.knobs-pane-body");
|
|
5184
|
+
return Boolean(piece?.classList.contains("knobs-ui"));
|
|
5185
|
+
};
|
|
5148
5186
|
const relisten = () => {
|
|
5149
5187
|
const next = sources.some((s) => s.listen);
|
|
5150
5188
|
if (next === listening)
|
|
@@ -9128,6 +9166,7 @@ function readPanelTokens(panel, version = -1) {
|
|
|
9128
9166
|
const trayPad = numProp(style, "tray-pad", unit * 0.5);
|
|
9129
9167
|
const radius = numProp(style, "radius", 8);
|
|
9130
9168
|
const panelRadius = numProp(style, "radius-panel", radius + unit);
|
|
9169
|
+
const frameRadius = numProp(style, "radius-frame", radius > 0 ? radius + pad + 1 : 0);
|
|
9131
9170
|
const radiusMd = Math.max(0, radius - trayPad);
|
|
9132
9171
|
const radiusSm = Math.max(0, radius - trayPad * 2);
|
|
9133
9172
|
const fontSize = parseFloat(style.fontSize) || numProp(style, "font-size", 12);
|
|
@@ -9184,6 +9223,7 @@ function readPanelTokens(panel, version = -1) {
|
|
|
9184
9223
|
trayPad,
|
|
9185
9224
|
radius,
|
|
9186
9225
|
panelRadius,
|
|
9226
|
+
frameRadius,
|
|
9187
9227
|
radiusMd,
|
|
9188
9228
|
radiusSm,
|
|
9189
9229
|
fontSize,
|
|
@@ -11521,6 +11561,44 @@ class GpuOverlayManager {
|
|
|
11521
11561
|
this.clipCache.set(el, { key, text, width, clipped });
|
|
11522
11562
|
return clipped;
|
|
11523
11563
|
}
|
|
11564
|
+
lineCache = new WeakMap;
|
|
11565
|
+
linesOf(el, width) {
|
|
11566
|
+
const text = el.textContent ?? "";
|
|
11567
|
+
const hit = this.lineCache.get(el);
|
|
11568
|
+
if (hit && hit.text === text && hit.width === width)
|
|
11569
|
+
return hit.lines;
|
|
11570
|
+
const lines = [];
|
|
11571
|
+
const node = el.firstChild;
|
|
11572
|
+
if (node?.nodeType === Node.TEXT_NODE) {
|
|
11573
|
+
const top = el.getBoundingClientRect().top;
|
|
11574
|
+
const range = el.ownerDocument.createRange();
|
|
11575
|
+
let line;
|
|
11576
|
+
const flush = () => {
|
|
11577
|
+
if (line)
|
|
11578
|
+
lines.push({
|
|
11579
|
+
text: text.slice(line.from, line.to),
|
|
11580
|
+
y: (line.top + line.bottom) / 2 - top
|
|
11581
|
+
});
|
|
11582
|
+
};
|
|
11583
|
+
for (const word of text.matchAll(/\S+/g)) {
|
|
11584
|
+
const from = word.index;
|
|
11585
|
+
const to = from + word[0].length;
|
|
11586
|
+
range.setStart(node, from);
|
|
11587
|
+
range.setEnd(node, to);
|
|
11588
|
+
const r = range.getBoundingClientRect();
|
|
11589
|
+
if (line && Math.abs(r.top - line.top) < 1) {
|
|
11590
|
+
line.to = to;
|
|
11591
|
+
line.bottom = Math.max(line.bottom, r.bottom);
|
|
11592
|
+
} else {
|
|
11593
|
+
flush();
|
|
11594
|
+
line = { from, to, top: r.top, bottom: r.bottom };
|
|
11595
|
+
}
|
|
11596
|
+
}
|
|
11597
|
+
flush();
|
|
11598
|
+
}
|
|
11599
|
+
this.lineCache.set(el, { text, width, lines });
|
|
11600
|
+
return lines;
|
|
11601
|
+
}
|
|
11524
11602
|
curReduced = false;
|
|
11525
11603
|
curLocks;
|
|
11526
11604
|
curSelected = 0;
|
|
@@ -12994,7 +13072,7 @@ class GpuOverlayManager {
|
|
|
12994
13072
|
const morph = panel.morph?.(this.frameNow);
|
|
12995
13073
|
const shown = morph ? clamp2(morph.progress, 0, 1) : 1;
|
|
12996
13074
|
const card = morph ? new DOMRect(morph.x, morph.y, morph.w, morph.h) : pRect;
|
|
12997
|
-
const cardRadius = morph ? morph.radius : tokens.
|
|
13075
|
+
const cardRadius = morph ? morph.radius : tokens.frameRadius;
|
|
12998
13076
|
if (morph)
|
|
12999
13077
|
anyMoving = true;
|
|
13000
13078
|
const masked = morph !== undefined && this.maskCount < MAX_MASKS;
|
|
@@ -13320,12 +13398,11 @@ class GpuOverlayManager {
|
|
|
13320
13398
|
this.drawText(this.fit(g.labelEl.textContent ?? "", lr.width, px, tokens.titleWeight), lr.left, cy, withAlpha2(tokens.text, 1 - peek), { px, weight: tokens.titleWeight, track: -0.01 });
|
|
13321
13399
|
if (g.peek && peek > 0.005)
|
|
13322
13400
|
this.drawText(this.fit(g.peek.textContent ?? "", lr.width, px, tokens.titleWeight), lr.left, cy, withAlpha2(tokens.text, peek), { px, weight: tokens.titleWeight, track: -0.01 });
|
|
13323
|
-
} else
|
|
13324
|
-
|
|
13325
|
-
|
|
13326
|
-
|
|
13327
|
-
|
|
13328
|
-
});
|
|
13401
|
+
} else {
|
|
13402
|
+
const label = tokens.groupUpper ? (g.labelEl.textContent ?? "").toUpperCase() : g.labelEl.textContent ?? "";
|
|
13403
|
+
const px = Math.max(9, tokens.groupSize);
|
|
13404
|
+
this.drawText(this.domClipped(g.labelEl, label, lr.width) ? this.fit(label, lr.width, px, tokens.titleWeight, undefined, tokens.groupTracking, true) : label, lr.left, lr.top + lr.height * 0.5, tokens.groupColor, { px, weight: tokens.titleWeight, track: tokens.groupTracking });
|
|
13405
|
+
}
|
|
13329
13406
|
if (!g.title && tokens.groupDivider[3] > 0 && g.element.previousElementSibling)
|
|
13330
13407
|
this.pushPrim({
|
|
13331
13408
|
x: gr.left,
|
|
@@ -13340,13 +13417,16 @@ class GpuOverlayManager {
|
|
|
13340
13417
|
const cs = getComputedStyle(g.desc);
|
|
13341
13418
|
const left = r.left + (parseFloat(cs.paddingLeft) || 0);
|
|
13342
13419
|
const w = r.width - (parseFloat(cs.paddingLeft) || 0) - (parseFloat(cs.paddingRight) || 0);
|
|
13343
|
-
|
|
13420
|
+
const lines = cs.whiteSpace.includes("nowrap") ? [{ text: g.desc.textContent ?? "", y: r.height * 0.5 }] : this.linesOf(g.desc, r.width);
|
|
13421
|
+
for (const line of lines)
|
|
13422
|
+
this.drawText(this.fit(line.text, w + 0.5, tokens.textMeta, tokens.labelWeight), left, r.top + line.y, tokens.dim, { px: tokens.textMeta, weight: tokens.labelWeight });
|
|
13344
13423
|
}
|
|
13345
13424
|
const fadeIn = (node) => node.parentElement?.closest("[data-fold-motion]") ? Number(getComputedStyle(node).opacity) || 0 : 1;
|
|
13346
13425
|
if (g.summary && g.summary.getClientRects().length) {
|
|
13347
13426
|
const r = this.rectOf(g.summary);
|
|
13348
13427
|
const a = fadeIn(g.summary);
|
|
13349
|
-
|
|
13428
|
+
const px = g.title ? tokens.textControl : tokens.textMeta;
|
|
13429
|
+
this.drawText(this.fit(g.summary.textContent ?? "", r.width + 0.5, px, 500), r.left, r.top + r.height * 0.5, withAlpha2(tokens.dim, a), { px, weight: 500 });
|
|
13350
13430
|
}
|
|
13351
13431
|
const ctlShown = !g.controls || g.controls.getClientRects().length > 0;
|
|
13352
13432
|
const headAlpha = this.curAlpha;
|
|
@@ -19833,7 +19913,6 @@ var compareCss = `
|
|
|
19833
19913
|
: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)}
|
|
19834
19914
|
.knobs-cmp-note{position:absolute;left:50%;top:50%;translate:-50% -50%;color:var(--_k-fg-3);pointer-events:none}
|
|
19835
19915
|
.knobs-cmp-note:empty{display:none}
|
|
19836
|
-
.knobs-cmp-strip-host{flex:none;height:60px;min-height:0}
|
|
19837
19916
|
.knobs-cmp-timeline-host{flex:none;min-height:0}
|
|
19838
19917
|
/* The frame strip: Before over After per column, a difference bar under them, a dot where it peaks. */
|
|
19839
19918
|
.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;
|
|
@@ -19853,6 +19932,9 @@ var playerCss = `
|
|
|
19853
19932
|
.knobs-player-media{position:absolute;inset:0;display:block;width:100%;height:100%;margin:0;padding:0;border:0;object-fit:contain;
|
|
19854
19933
|
opacity:0;filter:blur(4px);transition:opacity calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default),filter calc(var(--_k-motion-default-ms) * 1ms) var(--_k-motion-default)}
|
|
19855
19934
|
.knobs-player[data-ready] .knobs-player-media{opacity:1;filter:none}
|
|
19935
|
+
/* Mid-scrub, the cached frame under the hand, over the video until it lands. */
|
|
19936
|
+
.knobs-player-preview{position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:contain;pointer-events:none}
|
|
19937
|
+
.knobs-player-preview[hidden]{display:none}
|
|
19856
19938
|
.knobs-player-line{flex:none;min-height:0}
|
|
19857
19939
|
/* The timeline's own stylesheet is look.ts's; what the player's row and every timeline share
|
|
19858
19940
|
about the hand is set here, after it. No hand cursor anywhere (the arrow, or a resize where it
|
|
@@ -20659,6 +20741,62 @@ var init_overlay_model = __esm(() => {
|
|
|
20659
20741
|
opposite = { top: "bottom", bottom: "top", left: "right", right: "left" };
|
|
20660
20742
|
});
|
|
20661
20743
|
|
|
20744
|
+
// src/ui/tooltip-model.ts
|
|
20745
|
+
function tipSchedule(clock, view) {
|
|
20746
|
+
let shown = null;
|
|
20747
|
+
let pending = null;
|
|
20748
|
+
let timer;
|
|
20749
|
+
let hiddenAt = -Infinity;
|
|
20750
|
+
const cancel = () => {
|
|
20751
|
+
if (pending)
|
|
20752
|
+
clock.clear(timer);
|
|
20753
|
+
pending = null;
|
|
20754
|
+
};
|
|
20755
|
+
const hide = (now = false) => {
|
|
20756
|
+
cancel();
|
|
20757
|
+
if (!shown)
|
|
20758
|
+
return;
|
|
20759
|
+
shown = null;
|
|
20760
|
+
hiddenAt = clock.now();
|
|
20761
|
+
view.hide(now);
|
|
20762
|
+
};
|
|
20763
|
+
return {
|
|
20764
|
+
get shown() {
|
|
20765
|
+
return shown;
|
|
20766
|
+
},
|
|
20767
|
+
get pending() {
|
|
20768
|
+
return pending;
|
|
20769
|
+
},
|
|
20770
|
+
want(tip, options = {}) {
|
|
20771
|
+
if (tip.el === shown?.el || tip.el === pending?.el)
|
|
20772
|
+
return;
|
|
20773
|
+
cancel();
|
|
20774
|
+
const handoff = shown !== null || clock.now() - hiddenAt < HANDOFF_MS;
|
|
20775
|
+
if (handoff || options.now) {
|
|
20776
|
+
shown = tip;
|
|
20777
|
+
view.show(tip, handoff);
|
|
20778
|
+
return;
|
|
20779
|
+
}
|
|
20780
|
+
pending = tip;
|
|
20781
|
+
timer = clock.set(() => {
|
|
20782
|
+
pending = null;
|
|
20783
|
+
if (!view.connected(tip))
|
|
20784
|
+
return;
|
|
20785
|
+
shown = tip;
|
|
20786
|
+
view.show(tip, false);
|
|
20787
|
+
}, options.delay ?? TIP_DELAY_MS);
|
|
20788
|
+
},
|
|
20789
|
+
hide,
|
|
20790
|
+
leave(within) {
|
|
20791
|
+
if (pending && within(pending))
|
|
20792
|
+
cancel();
|
|
20793
|
+
if (shown && within(shown))
|
|
20794
|
+
hide();
|
|
20795
|
+
}
|
|
20796
|
+
};
|
|
20797
|
+
}
|
|
20798
|
+
var HANDOFF_MS = 400, TIP_DELAY_MS = 500;
|
|
20799
|
+
|
|
20662
20800
|
// src/ui/tooltip.ts
|
|
20663
20801
|
function tipOf(start) {
|
|
20664
20802
|
let node = start instanceof Element ? start : null;
|
|
@@ -20692,9 +20830,6 @@ function controllerOf(doc) {
|
|
|
20692
20830
|
let text;
|
|
20693
20831
|
let keys;
|
|
20694
20832
|
let target = null;
|
|
20695
|
-
let pending = null;
|
|
20696
|
-
let timer = 0;
|
|
20697
|
-
let hiddenAt = -Infinity;
|
|
20698
20833
|
let quiet = null;
|
|
20699
20834
|
let keyboard = false;
|
|
20700
20835
|
const build = (look) => {
|
|
@@ -20739,41 +20874,32 @@ function controllerOf(doc) {
|
|
|
20739
20874
|
else
|
|
20740
20875
|
motion.show();
|
|
20741
20876
|
};
|
|
20742
|
-
const
|
|
20743
|
-
win.
|
|
20744
|
-
|
|
20745
|
-
|
|
20746
|
-
|
|
20747
|
-
|
|
20748
|
-
|
|
20749
|
-
|
|
20750
|
-
|
|
20751
|
-
|
|
20752
|
-
|
|
20753
|
-
|
|
20754
|
-
|
|
20755
|
-
|
|
20877
|
+
const schedule = tipSchedule({
|
|
20878
|
+
set: (run, ms) => win.setTimeout(run, ms),
|
|
20879
|
+
clear: (handle) => win.clearTimeout(handle),
|
|
20880
|
+
now: () => performance.now()
|
|
20881
|
+
}, {
|
|
20882
|
+
show: ({ el, tip }, snap) => show(el, tip, snap),
|
|
20883
|
+
hide: (now) => {
|
|
20884
|
+
target?.removeAttribute("aria-describedby");
|
|
20885
|
+
target = null;
|
|
20886
|
+
if (now)
|
|
20887
|
+
motion?.snap(0);
|
|
20888
|
+
else
|
|
20889
|
+
motion?.hide();
|
|
20890
|
+
},
|
|
20891
|
+
connected: ({ el }) => el.isConnected
|
|
20892
|
+
});
|
|
20893
|
+
const hide = (now = false) => schedule.hide(now);
|
|
20894
|
+
const want = (found, now = false) => {
|
|
20756
20895
|
if (!found)
|
|
20757
20896
|
return hide();
|
|
20758
|
-
if (found.el === target || found.el === pending?.el)
|
|
20759
|
-
return;
|
|
20760
20897
|
if (found.el === quiet)
|
|
20761
20898
|
return;
|
|
20762
|
-
|
|
20763
|
-
|
|
20764
|
-
|
|
20765
|
-
|
|
20766
|
-
show(found.el, found.tip, true);
|
|
20767
|
-
return;
|
|
20768
|
-
}
|
|
20769
|
-
if (target)
|
|
20770
|
-
hide();
|
|
20771
|
-
pending = found;
|
|
20772
|
-
timer = win.setTimeout(() => {
|
|
20773
|
-
pending = null;
|
|
20774
|
-
if (found.el.isConnected)
|
|
20775
|
-
show(found.el, found.tip, false);
|
|
20776
|
-
}, found.tip.opts.delay ?? 500);
|
|
20899
|
+
schedule.want(found, {
|
|
20900
|
+
now,
|
|
20901
|
+
...found.tip.opts.delay !== undefined ? { delay: found.tip.opts.delay } : {}
|
|
20902
|
+
});
|
|
20777
20903
|
};
|
|
20778
20904
|
doc.addEventListener("pointerover", (e) => {
|
|
20779
20905
|
if (e.pointerType === "touch")
|
|
@@ -20807,11 +20933,10 @@ function controllerOf(doc) {
|
|
|
20807
20933
|
doc.addEventListener("focusin", (e) => {
|
|
20808
20934
|
const found = tipOf(e.target);
|
|
20809
20935
|
if (found && keyboard && e.target.matches(":focus-visible"))
|
|
20810
|
-
want(found);
|
|
20936
|
+
want(found, true);
|
|
20811
20937
|
});
|
|
20812
20938
|
doc.addEventListener("focusout", (e) => {
|
|
20813
|
-
|
|
20814
|
-
hide();
|
|
20939
|
+
schedule.leave(({ el }) => el.contains(e.target));
|
|
20815
20940
|
});
|
|
20816
20941
|
doc.addEventListener("scroll", () => target && hide(true), true);
|
|
20817
20942
|
const c = { hide };
|
|
@@ -20830,7 +20955,7 @@ function tooltip(el, content, options = {}) {
|
|
|
20830
20955
|
c.hide(true);
|
|
20831
20956
|
};
|
|
20832
20957
|
}
|
|
20833
|
-
var tips,
|
|
20958
|
+
var tips, controllers;
|
|
20834
20959
|
var init_tooltip = __esm(() => {
|
|
20835
20960
|
init_keys();
|
|
20836
20961
|
init_layer();
|
|
@@ -22246,6 +22371,14 @@ var init_inspector = __esm(() => {
|
|
|
22246
22371
|
CAP_MORPH = springLinear(SPRINGS.snappy);
|
|
22247
22372
|
});
|
|
22248
22373
|
|
|
22374
|
+
// src/panel/description-ids.ts
|
|
22375
|
+
function descriptionIds(storeId) {
|
|
22376
|
+
const prefix = `knobs-desc-${++panels2}-${storeId.replace(/[^\w-]/g, "-")}`;
|
|
22377
|
+
let n = 0;
|
|
22378
|
+
return () => `${prefix}-${++n}`;
|
|
22379
|
+
}
|
|
22380
|
+
var panels2 = 0;
|
|
22381
|
+
|
|
22249
22382
|
// src/panel/search.ts
|
|
22250
22383
|
function createSearch(doc, options) {
|
|
22251
22384
|
const element = doc.createElement("div");
|
|
@@ -25131,6 +25264,114 @@ var init_lens = __esm(() => {
|
|
|
25131
25264
|
};
|
|
25132
25265
|
});
|
|
25133
25266
|
|
|
25267
|
+
// src/panel/active.ts
|
|
25268
|
+
function activeReporter(resolve, report, schedule) {
|
|
25269
|
+
let hover = null;
|
|
25270
|
+
let focus = null;
|
|
25271
|
+
let lead = "pointer";
|
|
25272
|
+
let last = null;
|
|
25273
|
+
let cancel;
|
|
25274
|
+
const flush = () => {
|
|
25275
|
+
cancel = undefined;
|
|
25276
|
+
const [first, second] = lead === "pointer" ? [hover, focus] : [focus, hover];
|
|
25277
|
+
const at = resolve(first) ?? resolve(second);
|
|
25278
|
+
if (same3(at, last))
|
|
25279
|
+
return;
|
|
25280
|
+
last = at;
|
|
25281
|
+
report(at);
|
|
25282
|
+
};
|
|
25283
|
+
const touch = () => {
|
|
25284
|
+
cancel ??= schedule(flush);
|
|
25285
|
+
};
|
|
25286
|
+
return {
|
|
25287
|
+
pointer(target) {
|
|
25288
|
+
hover = target;
|
|
25289
|
+
if (target !== null)
|
|
25290
|
+
lead = "pointer";
|
|
25291
|
+
touch();
|
|
25292
|
+
},
|
|
25293
|
+
focus(target) {
|
|
25294
|
+
focus = target;
|
|
25295
|
+
if (target !== null)
|
|
25296
|
+
lead = "focus";
|
|
25297
|
+
touch();
|
|
25298
|
+
},
|
|
25299
|
+
dispose() {
|
|
25300
|
+
cancel?.();
|
|
25301
|
+
cancel = undefined;
|
|
25302
|
+
hover = focus = null;
|
|
25303
|
+
if (last !== null)
|
|
25304
|
+
report(last = null);
|
|
25305
|
+
}
|
|
25306
|
+
};
|
|
25307
|
+
}
|
|
25308
|
+
function activeEvents(reporter, where) {
|
|
25309
|
+
let inMenu = false;
|
|
25310
|
+
return {
|
|
25311
|
+
over(e) {
|
|
25312
|
+
reporter.pointer(e.target);
|
|
25313
|
+
},
|
|
25314
|
+
move(e) {
|
|
25315
|
+
if (e.movementX || e.movementY)
|
|
25316
|
+
reporter.pointer(e.target);
|
|
25317
|
+
},
|
|
25318
|
+
out(e) {
|
|
25319
|
+
if (where(e.relatedTarget) !== "inside")
|
|
25320
|
+
reporter.pointer(null);
|
|
25321
|
+
},
|
|
25322
|
+
focusIn(e) {
|
|
25323
|
+
const at = where(e.target);
|
|
25324
|
+
inMenu = at === "menu";
|
|
25325
|
+
if (at === "inside")
|
|
25326
|
+
reporter.focus(e.target);
|
|
25327
|
+
else if (at === "outside")
|
|
25328
|
+
reporter.focus(null);
|
|
25329
|
+
},
|
|
25330
|
+
focusOut(e) {
|
|
25331
|
+
if (e.relatedTarget !== null)
|
|
25332
|
+
return;
|
|
25333
|
+
const at = where(e.target);
|
|
25334
|
+
if (at === "inside" || at === "menu" && inMenu) {
|
|
25335
|
+
inMenu = false;
|
|
25336
|
+
reporter.focus(null);
|
|
25337
|
+
}
|
|
25338
|
+
}
|
|
25339
|
+
};
|
|
25340
|
+
}
|
|
25341
|
+
function watchActive(root, resolve, report) {
|
|
25342
|
+
const doc = root.ownerDocument;
|
|
25343
|
+
const win = doc.defaultView;
|
|
25344
|
+
const reporter = activeReporter(resolve, report, (flush) => {
|
|
25345
|
+
const id = win.requestAnimationFrame(flush);
|
|
25346
|
+
return () => win.cancelAnimationFrame(id);
|
|
25347
|
+
});
|
|
25348
|
+
const events = activeEvents(reporter, (node) => node instanceof Node && root.contains(node) ? "inside" : node instanceof Element && node.closest(".knobs-menu") ? "menu" : "outside");
|
|
25349
|
+
const el = (node) => node;
|
|
25350
|
+
const over = (e) => events.over({ target: el(e.target) });
|
|
25351
|
+
const move = (e) => events.move({ target: el(e.target), movementX: e.movementX, movementY: e.movementY });
|
|
25352
|
+
const out = (e) => events.out({ relatedTarget: el(e.relatedTarget) });
|
|
25353
|
+
const focusIn = (e) => events.focusIn({ target: el(e.target) });
|
|
25354
|
+
const focusOut = (e) => events.focusOut({ target: el(e.target), relatedTarget: el(e.relatedTarget) });
|
|
25355
|
+
root.addEventListener("pointerover", over);
|
|
25356
|
+
root.addEventListener("pointermove", move);
|
|
25357
|
+
root.addEventListener("pointerout", out);
|
|
25358
|
+
doc.addEventListener("focusin", focusIn);
|
|
25359
|
+
doc.addEventListener("focusout", focusOut);
|
|
25360
|
+
if (doc.activeElement && root.contains(doc.activeElement))
|
|
25361
|
+
reporter.focus(doc.activeElement);
|
|
25362
|
+
return {
|
|
25363
|
+
dispose() {
|
|
25364
|
+
root.removeEventListener("pointerover", over);
|
|
25365
|
+
root.removeEventListener("pointermove", move);
|
|
25366
|
+
root.removeEventListener("pointerout", out);
|
|
25367
|
+
doc.removeEventListener("focusin", focusIn);
|
|
25368
|
+
doc.removeEventListener("focusout", focusOut);
|
|
25369
|
+
reporter.dispose();
|
|
25370
|
+
}
|
|
25371
|
+
};
|
|
25372
|
+
}
|
|
25373
|
+
var same3 = (a, b) => a === b || a !== null && b !== null && a.group === b.group && a.key === b.key;
|
|
25374
|
+
|
|
25134
25375
|
// src/panel/has.ts
|
|
25135
25376
|
function trackHas(root) {
|
|
25136
25377
|
const doc = root.ownerDocument;
|
|
@@ -25376,7 +25617,7 @@ function morphFromChip(chip, root, wake, restored) {
|
|
|
25376
25617
|
if (shape)
|
|
25377
25618
|
return shape;
|
|
25378
25619
|
const cs = getComputedStyle(root);
|
|
25379
|
-
const r = parseFloat(cs.getPropertyValue("--kv-radius-
|
|
25620
|
+
const r = parseFloat(cs.getPropertyValue("--kv-radius-frame"));
|
|
25380
25621
|
if (Number.isFinite(r))
|
|
25381
25622
|
panelRadius = r;
|
|
25382
25623
|
shape = doc.createElement("div");
|
|
@@ -25592,6 +25833,7 @@ function foldMemory(id, storage) {
|
|
|
25592
25833
|
const next = {
|
|
25593
25834
|
sections: { ...data.sections },
|
|
25594
25835
|
groups: { ...data.groups },
|
|
25836
|
+
...data.subsections ? { subsections: { ...data.subsections } } : {},
|
|
25595
25837
|
[kind]: { ...data[kind], [at]: folded }
|
|
25596
25838
|
};
|
|
25597
25839
|
try {
|
|
@@ -25603,6 +25845,18 @@ function foldMemory(id, storage) {
|
|
|
25603
25845
|
var init_folds = () => {};
|
|
25604
25846
|
|
|
25605
25847
|
// src/panel/position.ts
|
|
25848
|
+
function savedPosition(left, top, width, view) {
|
|
25849
|
+
const right = left + width / 2 > view / 2;
|
|
25850
|
+
return right ? { x: view - left - width, y: top, right } : { x: left, y: top };
|
|
25851
|
+
}
|
|
25852
|
+
function readPosition(raw) {
|
|
25853
|
+
try {
|
|
25854
|
+
const saved = JSON.parse(raw ?? "null");
|
|
25855
|
+
if (saved && Number.isFinite(saved.x) && Number.isFinite(saved.y))
|
|
25856
|
+
return { x: saved.x, y: saved.y, ...saved.right === true ? { right: true } : {} };
|
|
25857
|
+
} catch {}
|
|
25858
|
+
return;
|
|
25859
|
+
}
|
|
25606
25860
|
function positionPanel(panel, header, anchor, id, storage) {
|
|
25607
25861
|
const doc = panel.ownerDocument;
|
|
25608
25862
|
const win = doc.defaultView;
|
|
@@ -25612,16 +25866,14 @@ function positionPanel(panel, header, anchor, id, storage) {
|
|
|
25612
25866
|
let x = bounds.right + w <= win.innerWidth - 8 ? bounds.right + 8 : clampX(bounds.left - w - 8);
|
|
25613
25867
|
let y = Math.max(8, bounds.top);
|
|
25614
25868
|
const key = storageKey(id, "position");
|
|
25615
|
-
let
|
|
25869
|
+
let saved;
|
|
25616
25870
|
try {
|
|
25617
|
-
|
|
25618
|
-
if (saved && Number.isFinite(saved.x) && Number.isFinite(saved.y)) {
|
|
25619
|
-
x = saved.x;
|
|
25620
|
-
y = saved.y;
|
|
25621
|
-
hasSaved = true;
|
|
25622
|
-
}
|
|
25871
|
+
saved = readPosition(storage()?.getItem(key));
|
|
25623
25872
|
} catch {}
|
|
25624
|
-
if (
|
|
25873
|
+
if (saved) {
|
|
25874
|
+
x = leftOf(saved, w, win.innerWidth);
|
|
25875
|
+
y = saved.y;
|
|
25876
|
+
} else {
|
|
25625
25877
|
const others = [...doc.querySelectorAll(".knobs-panel:not(.knobs-inline)")].filter((el) => el !== panel).map((el) => el.getBoundingClientRect());
|
|
25626
25878
|
if (others.length > 0) {
|
|
25627
25879
|
const overlaps = (cx, cy) => others.some((r) => Math.abs(cx - r.left) < w - 24 && Math.abs(cy - r.top) < 120);
|
|
@@ -25645,6 +25897,8 @@ function positionPanel(panel, header, anchor, id, storage) {
|
|
|
25645
25897
|
}
|
|
25646
25898
|
let shown = { x, y };
|
|
25647
25899
|
const constrain = () => {
|
|
25900
|
+
if (saved && !drag)
|
|
25901
|
+
x = leftOf(saved, panel.offsetWidth, win.innerWidth);
|
|
25648
25902
|
shown = {
|
|
25649
25903
|
x: Math.max(8, Math.min(x, win.innerWidth - panel.offsetWidth - 8)),
|
|
25650
25904
|
y: Math.max(8, Math.min(y, win.innerHeight - panel.offsetHeight - 8))
|
|
@@ -25658,22 +25912,35 @@ function positionPanel(panel, header, anchor, id, storage) {
|
|
|
25658
25912
|
return;
|
|
25659
25913
|
event.preventDefault();
|
|
25660
25914
|
drag = { id: event.pointerId, x: event.clientX, y: event.clientY, left: shown.x, top: shown.y };
|
|
25661
|
-
header.setPointerCapture(event.pointerId);
|
|
25662
25915
|
};
|
|
25663
25916
|
header.onpointermove = (event) => {
|
|
25664
25917
|
if (!drag || event.pointerId !== drag.id)
|
|
25665
25918
|
return;
|
|
25919
|
+
if (!("dragging" in panel.dataset)) {
|
|
25920
|
+
if (!(event.buttons & 1))
|
|
25921
|
+
return void (drag = undefined);
|
|
25922
|
+
if (Math.hypot(event.clientX - drag.x, event.clientY - drag.y) <= 2)
|
|
25923
|
+
return;
|
|
25924
|
+
panel.dataset.dragging = "";
|
|
25925
|
+
header.setPointerCapture(event.pointerId);
|
|
25926
|
+
}
|
|
25666
25927
|
x = drag.left + event.clientX - drag.x;
|
|
25667
25928
|
y = drag.top + event.clientY - drag.y;
|
|
25668
25929
|
constrain();
|
|
25669
25930
|
};
|
|
25931
|
+
header.onpointerup = header.onpointercancel = () => {
|
|
25932
|
+
if (drag && !("dragging" in panel.dataset))
|
|
25933
|
+
drag = undefined;
|
|
25934
|
+
};
|
|
25670
25935
|
header.onlostpointercapture = () => {
|
|
25671
25936
|
if (!drag)
|
|
25672
25937
|
return;
|
|
25673
25938
|
drag = undefined;
|
|
25939
|
+
delete panel.dataset.dragging;
|
|
25674
25940
|
({ x, y } = shown);
|
|
25941
|
+
saved = savedPosition(x, y, panel.offsetWidth, win.innerWidth);
|
|
25675
25942
|
try {
|
|
25676
|
-
storage()?.setItem(key, JSON.stringify(
|
|
25943
|
+
storage()?.setItem(key, JSON.stringify(saved));
|
|
25677
25944
|
} catch {}
|
|
25678
25945
|
};
|
|
25679
25946
|
const observer = new ResizeObserver(constrain);
|
|
@@ -25688,6 +25955,7 @@ function positionPanel(panel, header, anchor, id, storage) {
|
|
|
25688
25955
|
}
|
|
25689
25956
|
};
|
|
25690
25957
|
}
|
|
25958
|
+
var leftOf = (saved, width, view) => saved.right ? view - width - saved.x : saved.x;
|
|
25691
25959
|
var init_position = () => {};
|
|
25692
25960
|
|
|
25693
25961
|
// src/panel/dock.ts
|
|
@@ -25831,7 +26099,7 @@ function createPresence(root, options) {
|
|
|
25831
26099
|
return;
|
|
25832
26100
|
const look = presenceLook(spring.x, inline, reduced);
|
|
25833
26101
|
const r = root.getBoundingClientRect();
|
|
25834
|
-
radius ??= parseFloat(win.getComputedStyle(root).getPropertyValue("--kv-radius-
|
|
26102
|
+
radius ??= parseFloat(win.getComputedStyle(root).getPropertyValue("--kv-radius-frame")) || 12;
|
|
25835
26103
|
const s = look.scale;
|
|
25836
26104
|
const ox = r.left + r.width / 2;
|
|
25837
26105
|
const oy = inline ? r.top : r.top + r.height / 2;
|
|
@@ -25879,6 +26147,20 @@ var init_presence = __esm(() => {
|
|
|
25879
26147
|
LOOK = ["opacity", "filter", "scale", "transform-origin"];
|
|
25880
26148
|
});
|
|
25881
26149
|
|
|
26150
|
+
// src/panel/summary.ts
|
|
26151
|
+
function panelFoldSummary(rows, preset) {
|
|
26152
|
+
if (rows.length === 1 && rows[0].value)
|
|
26153
|
+
return rows[0].value;
|
|
26154
|
+
const lead = preset ?? rows.find((r) => r.changed && r.value)?.value ?? rows.find((r) => r.choice && r.value)?.value;
|
|
26155
|
+
const changed = rows.filter((r) => r.changed).length;
|
|
26156
|
+
return [lead, changed ? `${changed} changed` : ""].filter(Boolean).join(" · ");
|
|
26157
|
+
}
|
|
26158
|
+
var baseSignature = (controls) => JSON.stringify([
|
|
26159
|
+
controls.activePreset(),
|
|
26160
|
+
Object.keys(controls.scopes).map((s) => controls.activePreset(s)),
|
|
26161
|
+
Object.keys(controls.groupPresets).map((g) => controls.activeGroupPreset(g))
|
|
26162
|
+
]);
|
|
26163
|
+
|
|
25882
26164
|
// src/panel/panel.ts
|
|
25883
26165
|
function readableTitle(id) {
|
|
25884
26166
|
if (/\s/.test(id))
|
|
@@ -26526,19 +26808,24 @@ function buildPanel(controls, host, options) {
|
|
|
26526
26808
|
foldTile(card, next && !filterEl.value.trim(), animate);
|
|
26527
26809
|
else
|
|
26528
26810
|
applyVisibility(animate ? "reveal" : "instant");
|
|
26529
|
-
|
|
26530
|
-
|
|
26531
|
-
|
|
26811
|
+
const marked = page ? card.parentElement : head;
|
|
26812
|
+
if (marked) {
|
|
26813
|
+
marked.toggleAttribute("data-folded", next);
|
|
26532
26814
|
if (animate) {
|
|
26533
|
-
|
|
26534
|
-
clearTimeout(foldMotions.get(
|
|
26535
|
-
foldMotions.set(
|
|
26815
|
+
marked.setAttribute("data-fold-motion", "");
|
|
26816
|
+
clearTimeout(foldMotions.get(marked));
|
|
26817
|
+
foldMotions.set(marked, setTimeout(() => marked.removeAttribute("data-fold-motion"), 400));
|
|
26536
26818
|
}
|
|
26819
|
+
}
|
|
26820
|
+
if (page) {
|
|
26537
26821
|
if (remember)
|
|
26538
26822
|
foldsKept?.set("groups", group, next);
|
|
26539
|
-
|
|
26540
|
-
} else if (sessionKept)
|
|
26823
|
+
} else if (sessionKept) {
|
|
26541
26824
|
writeSession(controls.id, { groups: { ...readSession(controls.id).groups, [group]: next } });
|
|
26825
|
+
if (remember)
|
|
26826
|
+
panelFolds?.set("groups", group, next);
|
|
26827
|
+
}
|
|
26828
|
+
refreshFolds();
|
|
26542
26829
|
positioned?.constrain();
|
|
26543
26830
|
wakeGpu();
|
|
26544
26831
|
}
|
|
@@ -26586,8 +26873,7 @@ function buildPanel(controls, host, options) {
|
|
|
26586
26873
|
gRandom.dataset.hint = `${title} random`;
|
|
26587
26874
|
gRandom.querySelector(".knobs-icon")?.replaceWith(gDie.node);
|
|
26588
26875
|
gRandom.onclick = (event) => run(() => rerollGroup(groupName, event.altKey));
|
|
26589
|
-
|
|
26590
|
-
if (!bound("random") && !bound("mutate") || !rollable)
|
|
26876
|
+
if (!bound("random") && !bound("mutate"))
|
|
26591
26877
|
gRandom.hidden = true;
|
|
26592
26878
|
groupDice.set(groupName, { button: gRandom, die: gDie });
|
|
26593
26879
|
const presets = page ? (controls.groupPresets[groupName] ?? []).slice(0, 9) : [];
|
|
@@ -26695,21 +26981,22 @@ function buildPanel(controls, host, options) {
|
|
|
26695
26981
|
describeGroup(groupName);
|
|
26696
26982
|
}
|
|
26697
26983
|
if (foldAt !== undefined) {
|
|
26698
|
-
|
|
26699
|
-
|
|
26700
|
-
|
|
26984
|
+
summary = el("span");
|
|
26985
|
+
summary.className = "knobs-group-summary";
|
|
26986
|
+
if (page)
|
|
26701
26987
|
gRight.append(summary);
|
|
26702
|
-
|
|
26703
|
-
}
|
|
26988
|
+
groupSummaries.set(groupName, summary);
|
|
26704
26989
|
caret = caretSvg();
|
|
26705
26990
|
gRight.append(caret);
|
|
26706
26991
|
gHead.dataset.foldable = "";
|
|
26707
26992
|
gHead.tabIndex = -1;
|
|
26708
26993
|
gHead.setAttribute("role", "button");
|
|
26709
26994
|
gHead.setAttribute("aria-label", title);
|
|
26710
|
-
const folded = (page ? foldsKept?.get("groups", groupName) : session.groups?.[groupName]) ?? foldAt;
|
|
26995
|
+
const folded = (page ? foldsKept?.get("groups", groupName) : session.groups?.[groupName] ?? panelFolds?.get("groups", groupName)) ?? foldAt;
|
|
26711
26996
|
folds.set(groupName, folded);
|
|
26712
26997
|
gHead.setAttribute("aria-expanded", String(!folded));
|
|
26998
|
+
if (!page)
|
|
26999
|
+
gHead.toggleAttribute("data-folded", folded);
|
|
26713
27000
|
gHead.addEventListener("click", (event) => {
|
|
26714
27001
|
if (event.detail > 1 || event.target.closest("button"))
|
|
26715
27002
|
return;
|
|
@@ -26721,8 +27008,13 @@ function buildPanel(controls, host, options) {
|
|
|
26721
27008
|
gTitle.className = "knobs-group-title";
|
|
26722
27009
|
gTitle.append(gLabel, gPeek);
|
|
26723
27010
|
gHead.append(gTitle, gRight);
|
|
26724
|
-
} else
|
|
26725
|
-
|
|
27011
|
+
} else {
|
|
27012
|
+
const desc = el("span");
|
|
27013
|
+
desc.className = "knobs-group-desc";
|
|
27014
|
+
groupDescs.set(groupName, desc);
|
|
27015
|
+
describeGroup(groupName);
|
|
27016
|
+
gHead.append(gLabel, desc, ...summary ? [summary] : [], gRight);
|
|
27017
|
+
}
|
|
26726
27018
|
gpuGroups.push({
|
|
26727
27019
|
element: gHead,
|
|
26728
27020
|
labelEl: gLabel,
|
|
@@ -26776,6 +27068,7 @@ function buildPanel(controls, host, options) {
|
|
|
26776
27068
|
const session = remember ? readSession(controls.id) : {};
|
|
26777
27069
|
const foldPort = page?.foldStorage !== undefined ? page.foldStorage : controls.persist === "none" ? null : controls.storage;
|
|
26778
27070
|
const foldsKept = page && foldPort ? foldMemory(controls.id, () => foldPort) : null;
|
|
27071
|
+
const panelFolds = !page && remember && foldPort ? foldMemory(controls.id, () => foldPort) : null;
|
|
26779
27072
|
const tracks = new Map;
|
|
26780
27073
|
const toolbars = new Map;
|
|
26781
27074
|
const keyedActions = new Map;
|
|
@@ -26816,7 +27109,8 @@ function buildPanel(controls, host, options) {
|
|
|
26816
27109
|
label,
|
|
26817
27110
|
...duration.group !== undefined ? { group: duration.group } : {},
|
|
26818
27111
|
...duration.section !== undefined ? { section: duration.section } : {},
|
|
26819
|
-
...duration.shortcut !== undefined ? { shortcut: duration.shortcut } : {}
|
|
27112
|
+
...duration.shortcut !== undefined ? { shortcut: duration.shortcut } : {},
|
|
27113
|
+
...duration.description !== undefined ? { description: duration.description } : {}
|
|
26820
27114
|
},
|
|
26821
27115
|
parts: { duration, bounce },
|
|
26822
27116
|
group: duration.group,
|
|
@@ -27326,6 +27620,41 @@ function buildPanel(controls, host, options) {
|
|
|
27326
27620
|
return;
|
|
27327
27621
|
slot.replaceChildren(...node ? [node] : []);
|
|
27328
27622
|
}
|
|
27623
|
+
const descriptions = el("div");
|
|
27624
|
+
descriptions.hidden = true;
|
|
27625
|
+
root.append(descriptions);
|
|
27626
|
+
const described = new Map;
|
|
27627
|
+
const descriptionId = descriptionIds(controls.id);
|
|
27628
|
+
function describe(row) {
|
|
27629
|
+
const text = row.field.description?.trim() ?? "";
|
|
27630
|
+
const had = described.get(row);
|
|
27631
|
+
if ((had?.text ?? "") === text)
|
|
27632
|
+
return;
|
|
27633
|
+
const inputs = row.choice ? [row.choice.seg, row.choice.menu] : [row.input];
|
|
27634
|
+
if (had) {
|
|
27635
|
+
had.untip();
|
|
27636
|
+
had.node.remove();
|
|
27637
|
+
described.delete(row);
|
|
27638
|
+
for (const input of inputs)
|
|
27639
|
+
input.removeAttribute("aria-describedby");
|
|
27640
|
+
}
|
|
27641
|
+
if (!text)
|
|
27642
|
+
return;
|
|
27643
|
+
const node = el("span", text);
|
|
27644
|
+
node.id = descriptionId();
|
|
27645
|
+
descriptions.append(node);
|
|
27646
|
+
for (const input of inputs)
|
|
27647
|
+
input.setAttribute("aria-describedby", node.id);
|
|
27648
|
+
described.set(row, { text, node, untip: tooltip(row.row, text) });
|
|
27649
|
+
}
|
|
27650
|
+
const undescribe = (row) => {
|
|
27651
|
+
const had = described.get(row);
|
|
27652
|
+
if (!had)
|
|
27653
|
+
return;
|
|
27654
|
+
had.untip();
|
|
27655
|
+
had.node.remove();
|
|
27656
|
+
described.delete(row);
|
|
27657
|
+
};
|
|
27329
27658
|
const fieldFlag = (field, name) => {
|
|
27330
27659
|
const v = field[name];
|
|
27331
27660
|
return typeof v === "function" ? Boolean(v(controls.get())) : Boolean(v);
|
|
@@ -27371,6 +27700,7 @@ function buildPanel(controls, host, options) {
|
|
|
27371
27700
|
wakeGpu();
|
|
27372
27701
|
};
|
|
27373
27702
|
const dropGpu = (row) => {
|
|
27703
|
+
undescribe(row);
|
|
27374
27704
|
row.dispose?.();
|
|
27375
27705
|
row.slider?.dispose();
|
|
27376
27706
|
row.editor?.dispose();
|
|
@@ -27429,11 +27759,13 @@ function buildPanel(controls, host, options) {
|
|
|
27429
27759
|
if (existing && existing.shape === shapeOf(spec)) {
|
|
27430
27760
|
kept.delete(spec.id);
|
|
27431
27761
|
existing.retune(spec);
|
|
27762
|
+
describe(existing);
|
|
27432
27763
|
next.push(existing);
|
|
27433
27764
|
continue;
|
|
27434
27765
|
}
|
|
27435
27766
|
const row = buildRow(spec);
|
|
27436
27767
|
decorate(row);
|
|
27768
|
+
describe(row);
|
|
27437
27769
|
gpuRows.push(...row.gpu);
|
|
27438
27770
|
entering.add(row);
|
|
27439
27771
|
next.push(row);
|
|
@@ -27540,6 +27872,8 @@ function buildPanel(controls, host, options) {
|
|
|
27540
27872
|
motion.push({ node: r.row, show: true });
|
|
27541
27873
|
}
|
|
27542
27874
|
}
|
|
27875
|
+
for (const group of groupDescs.keys())
|
|
27876
|
+
describeGroup(group);
|
|
27543
27877
|
for (const [id, sh] of subheads)
|
|
27544
27878
|
if (!usedSubheads.has(id)) {
|
|
27545
27879
|
sh.el.remove();
|
|
@@ -27598,8 +27932,7 @@ function buildPanel(controls, host, options) {
|
|
|
27598
27932
|
motion.forEach((m, i) => present(m.node, m.show, i * stagger, m.after));
|
|
27599
27933
|
}
|
|
27600
27934
|
applyVisibility(animate ? "reveal" : "instant");
|
|
27601
|
-
|
|
27602
|
-
refreshFolds();
|
|
27935
|
+
refreshFolds();
|
|
27603
27936
|
if (focused && root.contains(focused) && doc.activeElement !== focused && focused.isConnected)
|
|
27604
27937
|
focused.focus({ preventScroll: true });
|
|
27605
27938
|
const gone = focused ? leaving.find((r) => r.row.contains(focused)) : undefined;
|
|
@@ -27636,7 +27969,7 @@ function buildPanel(controls, host, options) {
|
|
|
27636
27969
|
const caret = caretSvg();
|
|
27637
27970
|
node.append(label, caret);
|
|
27638
27971
|
if (!subFolds.has(id))
|
|
27639
|
-
subFolds.set(id, session.subsections?.[id] ?? options.subsectionFolded?.[name] ?? false);
|
|
27972
|
+
subFolds.set(id, session.subsections?.[id] ?? panelFolds?.get("subsections", id) ?? options.subsectionFolded?.[name] ?? false);
|
|
27640
27973
|
node.setAttribute("aria-expanded", String(!subFolds.get(id)));
|
|
27641
27974
|
node.addEventListener("click", (event) => {
|
|
27642
27975
|
if (event.detail < 2)
|
|
@@ -27670,10 +28003,12 @@ function buildPanel(controls, host, options) {
|
|
|
27670
28003
|
if (next && rows.some((r) => r.subhead === id && r.row.contains(doc.activeElement)))
|
|
27671
28004
|
sh.el.focus({ preventScroll: true, focusVisible: false });
|
|
27672
28005
|
applyVisibility("reveal");
|
|
27673
|
-
if (remember)
|
|
28006
|
+
if (remember) {
|
|
27674
28007
|
writeSession(controls.id, {
|
|
27675
28008
|
subsections: { ...readSession(controls.id).subsections, [id]: next }
|
|
27676
28009
|
});
|
|
28010
|
+
panelFolds?.set("subsections", id, next);
|
|
28011
|
+
}
|
|
27677
28012
|
}
|
|
27678
28013
|
const groupTab = (group) => {
|
|
27679
28014
|
for (const f of Object.values(controls.schema))
|
|
@@ -27759,7 +28094,7 @@ function buildPanel(controls, host, options) {
|
|
|
27759
28094
|
const searching = () => search?.filtering() ?? false;
|
|
27760
28095
|
const rowMatches = (r) => {
|
|
27761
28096
|
const query = search.query();
|
|
27762
|
-
if (query && !matchesFilter(query, r.display, r.key, r.group, r.group && groupTitle(r.group), r.field.subsection))
|
|
28097
|
+
if (query && !matchesFilter(query, r.display, r.key, r.group, r.group && groupTitle(r.group), r.group && groupDescription(r.group), r.field.subsection, r.field.description))
|
|
27763
28098
|
return false;
|
|
27764
28099
|
for (const chip of search.active())
|
|
27765
28100
|
if (!r.keys.some((k) => chipTests.get(chip)?.(k)))
|
|
@@ -27881,6 +28216,10 @@ function buildPanel(controls, host, options) {
|
|
|
27881
28216
|
};
|
|
27882
28217
|
const keysOf = (indices) => indices.flatMap((i) => rows[i]?.keys ?? []);
|
|
27883
28218
|
const groupKeys = (group) => rows.filter((r) => r.group === group).flatMap((r) => r.keys);
|
|
28219
|
+
const mayRoll = (key) => {
|
|
28220
|
+
const field = controls.schema[key];
|
|
28221
|
+
return Boolean(field && hasValue(field) && field.random !== false);
|
|
28222
|
+
};
|
|
27884
28223
|
const rerollGroup = (group, nudge) => {
|
|
27885
28224
|
const roller = groupDice.get(group)?.die;
|
|
27886
28225
|
if (!roller)
|
|
@@ -28027,22 +28366,29 @@ function buildPanel(controls, host, options) {
|
|
|
28027
28366
|
apply.setAttribute("aria-label", "Import JSON");
|
|
28028
28367
|
apply.hidden = true;
|
|
28029
28368
|
const copy = async (value, inPlace = true) => {
|
|
28030
|
-
|
|
28031
|
-
await doc.defaultView.navigator.clipboard.writeText(value);
|
|
28369
|
+
const done = () => {
|
|
28032
28370
|
if (inPlace && !copyButton.hidden && headerShown())
|
|
28033
28371
|
copied();
|
|
28034
28372
|
else
|
|
28035
28373
|
say("Copied.");
|
|
28374
|
+
};
|
|
28375
|
+
try {
|
|
28376
|
+
await doc.defaultView.navigator.clipboard.writeText(value);
|
|
28377
|
+
done();
|
|
28036
28378
|
} catch {
|
|
28037
|
-
|
|
28038
|
-
|
|
28039
|
-
|
|
28040
|
-
|
|
28041
|
-
|
|
28042
|
-
|
|
28043
|
-
|
|
28044
|
-
|
|
28045
|
-
|
|
28379
|
+
if (copyByCommand(doc, value))
|
|
28380
|
+
done();
|
|
28381
|
+
else {
|
|
28382
|
+
text.value = value;
|
|
28383
|
+
if (page)
|
|
28384
|
+
togglePopover(true);
|
|
28385
|
+
reveal(text, true);
|
|
28386
|
+
apply.hidden = true;
|
|
28387
|
+
positioned?.constrain();
|
|
28388
|
+
text.focus();
|
|
28389
|
+
text.select();
|
|
28390
|
+
say("Clipboard unavailable. Copy the selected text.", 6000);
|
|
28391
|
+
}
|
|
28046
28392
|
}
|
|
28047
28393
|
wakeGpu();
|
|
28048
28394
|
};
|
|
@@ -28157,11 +28503,6 @@ function buildPanel(controls, host, options) {
|
|
|
28157
28503
|
wakeGpu();
|
|
28158
28504
|
}
|
|
28159
28505
|
let shownBase = "";
|
|
28160
|
-
const baseSignature = () => JSON.stringify([
|
|
28161
|
-
controls.activePreset(),
|
|
28162
|
-
Object.keys(controls.scopes).map((s) => controls.activePreset(s)),
|
|
28163
|
-
Object.keys(controls.groupPresets).map((g) => controls.activeGroupPreset(g))
|
|
28164
|
-
]);
|
|
28165
28506
|
function update() {
|
|
28166
28507
|
if (!controls.enabled) {
|
|
28167
28508
|
close?.();
|
|
@@ -28188,6 +28529,7 @@ function buildPanel(controls, host, options) {
|
|
|
28188
28529
|
}
|
|
28189
28530
|
const stagger = initialized ? cascade(changedCount) : 0;
|
|
28190
28531
|
const moving = initialized ? rows.filter(changed) : rows;
|
|
28532
|
+
const rebasing = baseSignature(controls) !== shownBase;
|
|
28191
28533
|
updateStrips();
|
|
28192
28534
|
batchMeasures(() => {
|
|
28193
28535
|
for (const row of moving) {
|
|
@@ -28200,7 +28542,7 @@ function buildPanel(controls, host, options) {
|
|
|
28200
28542
|
primeSegPill(chips.seg, chips.buttons);
|
|
28201
28543
|
showValues(values, moving, stagger, landing);
|
|
28202
28544
|
});
|
|
28203
|
-
if (moving.length || !initialized)
|
|
28545
|
+
if (moving.length || !initialized || rebasing)
|
|
28204
28546
|
refreshFolds();
|
|
28205
28547
|
shown = values;
|
|
28206
28548
|
initialized = true;
|
|
@@ -28226,7 +28568,7 @@ function buildPanel(controls, host, options) {
|
|
|
28226
28568
|
const fresh = (r) => r.row.dataset.shown === undefined;
|
|
28227
28569
|
const now = performance.now();
|
|
28228
28570
|
let turn = 0;
|
|
28229
|
-
const based = baseSignature();
|
|
28571
|
+
const based = baseSignature(controls);
|
|
28230
28572
|
const rebased = based !== shownBase;
|
|
28231
28573
|
shownBase = based;
|
|
28232
28574
|
for (const row of moving) {
|
|
@@ -28294,10 +28636,17 @@ function buildPanel(controls, host, options) {
|
|
|
28294
28636
|
}
|
|
28295
28637
|
if (randomButton.disabled !== (unlocked === 0))
|
|
28296
28638
|
randomButton.disabled = unlocked === 0;
|
|
28639
|
+
const rolls = (bound("random") || bound("mutate")) && shows("random");
|
|
28640
|
+
const headerHidden = !rolls || !rows.some((r) => r.keys.some(mayRoll));
|
|
28641
|
+
if (randomButton.hidden !== headerHidden)
|
|
28642
|
+
randomButton.hidden = headerHidden;
|
|
28297
28643
|
for (const [group, { button }] of groupDice) {
|
|
28298
28644
|
const off = !options.groupRandom && !groupKeys(group).some((k) => controls.canRoll(k));
|
|
28299
28645
|
if (button.disabled !== off)
|
|
28300
28646
|
button.disabled = off;
|
|
28647
|
+
const hidden = !bound("random") && !bound("mutate") || !options.groupRandom && !groupKeys(group).some(mayRoll);
|
|
28648
|
+
if (button.hidden !== hidden)
|
|
28649
|
+
button.hidden = hidden;
|
|
28301
28650
|
}
|
|
28302
28651
|
if (root.hasAttribute("data-comparing") !== controls.comparing)
|
|
28303
28652
|
root.toggleAttribute("data-comparing", controls.comparing);
|
|
@@ -28482,7 +28831,7 @@ function buildPanel(controls, host, options) {
|
|
|
28482
28831
|
layout.change(() => {
|
|
28483
28832
|
layout.openFolds(Boolean(query));
|
|
28484
28833
|
for (const r of rows) {
|
|
28485
|
-
const show = !query || matchesFilter(query, r.display, r.key, r.group, r.group && groupTitle(r.group, r.section), r.group && groupDescription(r.group), r.section, r.section && sectionTitle(r.section), r.section && sectionDescription(r.section));
|
|
28834
|
+
const show = !query || matchesFilter(query, r.display, r.key, r.group, r.group && groupTitle(r.group, r.section), r.group && groupDescription(r.group), r.section, r.section && sectionTitle(r.section), r.section && sectionDescription(r.section), r.field.description);
|
|
28486
28835
|
if (r.row.hidden === show)
|
|
28487
28836
|
r.row.hidden = !show;
|
|
28488
28837
|
}
|
|
@@ -28531,15 +28880,49 @@ function buildPanel(controls, host, options) {
|
|
|
28531
28880
|
keys: rows.filter((r) => r.section === section).flatMap((r) => r.keys)
|
|
28532
28881
|
});
|
|
28533
28882
|
const changedText = (n) => n && marks ? `${n} changed` : "";
|
|
28883
|
+
const valueText = (r, values) => {
|
|
28884
|
+
const f = r.field;
|
|
28885
|
+
const v = r.value(values);
|
|
28886
|
+
const num = (n) => String(Number(n.toFixed(2)));
|
|
28887
|
+
switch (f.kind) {
|
|
28888
|
+
case "choice":
|
|
28889
|
+
return f.labels?.[v] ?? String(v);
|
|
28890
|
+
case "toggle":
|
|
28891
|
+
return v ? "On" : "Off";
|
|
28892
|
+
case "knob":
|
|
28893
|
+
return `${v.toFixed(f.decimals ?? decimals(f.step))}${f.unit ? ` ${f.unit}` : ""}`;
|
|
28894
|
+
case "spring": {
|
|
28895
|
+
const { duration, bounce } = v;
|
|
28896
|
+
return `${num(duration)} s${bounce ? `, bounce ${num(bounce)}` : ""}`;
|
|
28897
|
+
}
|
|
28898
|
+
case "color":
|
|
28899
|
+
return colorHex(v);
|
|
28900
|
+
case "text":
|
|
28901
|
+
return String(v);
|
|
28902
|
+
default:
|
|
28903
|
+
return "";
|
|
28904
|
+
}
|
|
28905
|
+
};
|
|
28906
|
+
const groupSummary = (group) => {
|
|
28907
|
+
const info = groupInfo(group);
|
|
28908
|
+
if (options.groupSummary)
|
|
28909
|
+
return options.groupSummary(group, info);
|
|
28910
|
+
if (page)
|
|
28911
|
+
return [info.preset, changedText(info.changed)].filter(Boolean).join(" · ") || null;
|
|
28912
|
+
const values = controls.get();
|
|
28913
|
+
const own = rows.filter((r) => r.group === group && !r.leaving && r.keys.length);
|
|
28914
|
+
return panelFoldSummary(own.map((r) => ({
|
|
28915
|
+
value: valueText(r, values),
|
|
28916
|
+
changed: marks && r.keys.some((k) => controls.isModified(k)),
|
|
28917
|
+
choice: r.field.kind === "choice"
|
|
28918
|
+
})), info.preset) || null;
|
|
28919
|
+
};
|
|
28534
28920
|
function refreshFolds() {
|
|
28921
|
+
for (const [group, node] of groupSummaries)
|
|
28922
|
+
if (folds.get(group))
|
|
28923
|
+
putSummary(node, groupSummary(group));
|
|
28535
28924
|
if (!layout || !page)
|
|
28536
28925
|
return;
|
|
28537
|
-
for (const [group, node] of groupSummaries) {
|
|
28538
|
-
if (!folds.get(group))
|
|
28539
|
-
continue;
|
|
28540
|
-
const info = groupInfo(group);
|
|
28541
|
-
putSummary(node, page.groupSummary ? page.groupSummary(group, info) : [info.preset, changedText(info.changed)].filter(Boolean).join(" · ") || null);
|
|
28542
|
-
}
|
|
28543
28926
|
for (const s of layout.sectionList()) {
|
|
28544
28927
|
const node = s.label?.querySelector(":scope > .knobs-section-summary");
|
|
28545
28928
|
if (!node || !s.folded)
|
|
@@ -29052,7 +29435,20 @@ function buildPanel(controls, host, options) {
|
|
|
29052
29435
|
queueScope();
|
|
29053
29436
|
});
|
|
29054
29437
|
};
|
|
29438
|
+
const onPressOutside = (event) => {
|
|
29439
|
+
const target = event.target;
|
|
29440
|
+
if (page || !target || root.contains(target))
|
|
29441
|
+
return;
|
|
29442
|
+
if (target.closest?.(".knobs-root,.knobs-layers"))
|
|
29443
|
+
return;
|
|
29444
|
+
setTimeout(() => {
|
|
29445
|
+
const active = doc.activeElement;
|
|
29446
|
+
if (active && root.contains(active))
|
|
29447
|
+
active.blur();
|
|
29448
|
+
});
|
|
29449
|
+
};
|
|
29055
29450
|
doc.addEventListener("pointerdown", onPress, true);
|
|
29451
|
+
doc.addEventListener("pointerdown", onPressOutside, true);
|
|
29056
29452
|
doc.addEventListener("pointerup", onRelease, true);
|
|
29057
29453
|
doc.addEventListener("pointercancel", onRelease, true);
|
|
29058
29454
|
root.addEventListener("keydown", () => {
|
|
@@ -30057,6 +30453,16 @@ function buildPanel(controls, host, options) {
|
|
|
30057
30453
|
attributes: true,
|
|
30058
30454
|
attributeFilter: ["data-knobs-renderer", "data-theme", "data-appearance", "class", "style"]
|
|
30059
30455
|
});
|
|
30456
|
+
const onActive = options.onActive;
|
|
30457
|
+
const active = onActive ? watchActive(root, (node) => {
|
|
30458
|
+
if (!node || !root.contains(node))
|
|
30459
|
+
return null;
|
|
30460
|
+
const r = rows.find((r) => !r.leaving && r.row.contains(node));
|
|
30461
|
+
if (r)
|
|
30462
|
+
return r.group === undefined ? null : { group: r.group, key: r.key };
|
|
30463
|
+
const card = node.closest("[data-group]");
|
|
30464
|
+
return card && root.contains(card) ? { group: card.dataset.group } : null;
|
|
30465
|
+
}, onActive) : undefined;
|
|
30060
30466
|
const panel = {
|
|
30061
30467
|
element: root,
|
|
30062
30468
|
presetStrip,
|
|
@@ -30144,9 +30550,11 @@ function buildPanel(controls, host, options) {
|
|
|
30144
30550
|
lens.dispose();
|
|
30145
30551
|
win?.cancelAnimationFrame(lensFrame);
|
|
30146
30552
|
doc.removeEventListener("pointerdown", onPress, true);
|
|
30553
|
+
doc.removeEventListener("pointerdown", onPressOutside, true);
|
|
30147
30554
|
doc.removeEventListener("pointerup", onRelease, true);
|
|
30148
30555
|
doc.removeEventListener("pointercancel", onRelease, true);
|
|
30149
30556
|
crumbs?.dispose();
|
|
30557
|
+
active?.dispose();
|
|
30150
30558
|
clearTimeout(escTimer);
|
|
30151
30559
|
win?.removeEventListener("blur", queueScope);
|
|
30152
30560
|
win?.removeEventListener("focus", queueScope);
|
|
@@ -30350,6 +30758,24 @@ function buildPanel(controls, host, options) {
|
|
|
30350
30758
|
}
|
|
30351
30759
|
return pageApi;
|
|
30352
30760
|
}
|
|
30761
|
+
function copyByCommand(doc, value) {
|
|
30762
|
+
const was = doc.activeElement;
|
|
30763
|
+
const area = doc.createElement("textarea");
|
|
30764
|
+
area.value = value;
|
|
30765
|
+
area.setAttribute("readonly", "");
|
|
30766
|
+
area.style.cssText = "position:fixed;top:0;left:0;opacity:0;pointer-events:none";
|
|
30767
|
+
doc.body.append(area);
|
|
30768
|
+
area.select();
|
|
30769
|
+
let ok = false;
|
|
30770
|
+
try {
|
|
30771
|
+
ok = doc.execCommand("copy");
|
|
30772
|
+
} catch {
|
|
30773
|
+
ok = false;
|
|
30774
|
+
}
|
|
30775
|
+
area.remove();
|
|
30776
|
+
was?.focus({ preventScroll: true });
|
|
30777
|
+
return ok;
|
|
30778
|
+
}
|
|
30353
30779
|
function createPanel(controls, anchor, close, options) {
|
|
30354
30780
|
return buildPanel(controls, anchor.ownerDocument.body, {
|
|
30355
30781
|
...options,
|
|
@@ -30382,6 +30808,7 @@ var init_panel = __esm(() => {
|
|
|
30382
30808
|
init_readout();
|
|
30383
30809
|
init_readout_row();
|
|
30384
30810
|
init_toast();
|
|
30811
|
+
init_tooltip();
|
|
30385
30812
|
init_tabs();
|
|
30386
30813
|
init_tab_transition();
|
|
30387
30814
|
init_choice();
|
|
@@ -30528,7 +30955,7 @@ function attach(controls, element, options = {}) {
|
|
|
30528
30955
|
const open = async (restored = false) => {
|
|
30529
30956
|
if (panel) {
|
|
30530
30957
|
unpress();
|
|
30531
|
-
panel
|
|
30958
|
+
focusPanel(panel);
|
|
30532
30959
|
return;
|
|
30533
30960
|
}
|
|
30534
30961
|
if (leaving?.reopen()) {
|
|
@@ -30539,7 +30966,7 @@ function attach(controls, element, options = {}) {
|
|
|
30539
30966
|
writeSession(controls.id, { open: true });
|
|
30540
30967
|
chip.setAttribute("aria-expanded", "true");
|
|
30541
30968
|
update();
|
|
30542
|
-
panel
|
|
30969
|
+
focusPanel(panel);
|
|
30543
30970
|
return;
|
|
30544
30971
|
}
|
|
30545
30972
|
leaving = undefined;
|
|
@@ -30556,7 +30983,7 @@ function attach(controls, element, options = {}) {
|
|
|
30556
30983
|
chip.setAttribute("aria-expanded", "true");
|
|
30557
30984
|
update();
|
|
30558
30985
|
if (!restored)
|
|
30559
|
-
panel
|
|
30986
|
+
focusPanel(panel);
|
|
30560
30987
|
} catch (cause) {
|
|
30561
30988
|
chip.title = String(cause);
|
|
30562
30989
|
renderFace("Retry knobs");
|
|
@@ -30614,6 +31041,7 @@ function attach(controls, element, options = {}) {
|
|
|
30614
31041
|
element.removeAttribute("tabindex");
|
|
30615
31042
|
};
|
|
30616
31043
|
}
|
|
31044
|
+
var focusPanel = (panel) => panel.element.focus({ preventScroll: true });
|
|
30617
31045
|
var MODE_KEY = "knobs:mode";
|
|
30618
31046
|
var MODE_EVENT = "knobs-mode";
|
|
30619
31047
|
function knobsMode(win) {
|