@kitlangton/knobs 0.4.0-next.11 → 0.4.0-next.12
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 +88 -12
- package/dist/dev/{chunk-mjdgzad5.js → chunk-7kns3qe6.js} +29 -25
- package/dist/dev/{chunk-bnhzf1tj.js → chunk-9qtvxa6k.js} +1378 -1066
- package/dist/dev/{chunk-75gbzbyd.js → chunk-ab7vfghg.js} +2 -5
- package/dist/dev/{chunk-j57rhjtm.js → chunk-nwfm1bfj.js} +89 -37
- package/dist/dev/index.js +41 -18
- package/dist/index.js +64 -15
- package/dist/panel.js +2788 -2294
- package/dist/review-react.js +8 -4
- package/dist/review-solid.js +10 -5
- package/dist/review.js +8 -4
- package/dist/types/core/remote.d.ts +8 -2
- package/dist/types/core/schema.d.ts +52 -4
- package/dist/types/core/store.d.ts +7 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/panel/dock.d.ts +9 -0
- package/dist/types/panel/gpu/renderer.d.ts +11 -1
- package/dist/types/panel/inspector.d.ts +11 -3
- package/dist/types/panel/presets.d.ts +14 -0
- package/dist/types/panel/scope.d.ts +15 -4
- package/dist/types/ui/canvas-css.d.ts +1 -0
- package/dist/types/ui/canvas-model.d.ts +116 -0
- package/dist/types/ui/canvas.d.ts +66 -0
- package/dist/types/ui/index.d.ts +2 -0
- package/dist/types/ui/react.d.ts +12 -0
- package/dist/types/ui/solid.d.ts +9 -0
- package/dist/ui-react.js +1020 -17
- package/dist/ui-solid.js +1032 -25
- package/dist/ui.js +986 -4
- package/package.json +1 -1
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
comboFromEvent2,
|
|
14
14
|
heldMods,
|
|
15
15
|
matchesCombo2,
|
|
16
|
+
comboParts2,
|
|
16
17
|
comboLabel2,
|
|
17
18
|
isTypingTarget,
|
|
18
19
|
GRADIENT_SAMPLES,
|
|
@@ -25,6 +26,7 @@ import {
|
|
|
25
26
|
sameRamp,
|
|
26
27
|
isReadout2,
|
|
27
28
|
hasValue2,
|
|
29
|
+
variantsOf,
|
|
28
30
|
SPRING2,
|
|
29
31
|
toolbarShortcut2,
|
|
30
32
|
actionShortcut2,
|
|
@@ -44,7 +46,7 @@ import {
|
|
|
44
46
|
pushReadout,
|
|
45
47
|
READOUT,
|
|
46
48
|
storageKey
|
|
47
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-7kns3qe6.js";
|
|
48
50
|
import {
|
|
49
51
|
resolveLook,
|
|
50
52
|
themeOf,
|
|
@@ -99,6 +101,7 @@ import {
|
|
|
99
101
|
crumbTrail,
|
|
100
102
|
escTarget,
|
|
101
103
|
digitOption,
|
|
104
|
+
digitRoute,
|
|
102
105
|
digitHints,
|
|
103
106
|
createCrumbs,
|
|
104
107
|
TOKENS,
|
|
@@ -116,7 +119,7 @@ import {
|
|
|
116
119
|
createHintController,
|
|
117
120
|
pageHints,
|
|
118
121
|
toggleLayer
|
|
119
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-nwfm1bfj.js";
|
|
120
123
|
|
|
121
124
|
// src/panel/die.ts
|
|
122
125
|
var ROUND = 16 * Math.sqrt(5), DIE = { half: 64 + ROUND, round: ROUND, pip: 12 }, PIPS = {
|
|
@@ -994,6 +997,11 @@ function resolveActivePresetEntry(entries, currentValues, lastAppliedId, baseId
|
|
|
994
997
|
isCustom: !0
|
|
995
998
|
};
|
|
996
999
|
}
|
|
1000
|
+
function presetLines(count, min, avail, gap) {
|
|
1001
|
+
if (count <= 0 || min <= 0 || avail <= 0)
|
|
1002
|
+
return 1;
|
|
1003
|
+
return Math.ceil(count / Math.max(1, Math.floor((avail + gap) / (min + gap))));
|
|
1004
|
+
}
|
|
997
1005
|
function presetsTouch(entries, keys, defaults) {
|
|
998
1006
|
return entries.some((e) => !(e.kind === "preset" && e.rawId === "default") && keys.some((k) => !same(e.values[k], defaults[k])));
|
|
999
1007
|
}
|
|
@@ -1021,7 +1029,7 @@ function createPresetStrip(doc, controls, showVariants, run, onAfterChange, pres
|
|
|
1021
1029
|
saveButton.type = "button", saveButton.tabIndex = -1, saveButton.setAttribute("aria-label", "Save as variant"), saveButton.setAttribute("aria-keyshortcuts", "Shift+S"), saveButton.dataset.hint = "Save", saveButton.onclick = () => run(save);
|
|
1022
1030
|
if (track.append(pill), root.append(track), saveButton)
|
|
1023
1031
|
root.append(saveButton);
|
|
1024
|
-
let pillEdges = new Edges, pillY = new Spring(0, 28, 0.86), pillAlpha = new Spring(1, 26, 0.9), entries = [], buttons = [], signature = "", lastVariantsRef = null, lastAppliedId = null, activeState = { activeId: "p:default", activeIndex: 0, isCustom: !1 }, prevActiveId = "", prevActiveIndex = -2, prevIsCustom = !1, prevDrifted = !1, initializedPill = !1, slideUntil = 0, unpinned = (values) => {
|
|
1032
|
+
let pillEdges = new Edges, pillY = new Spring(0, 28, 0.86), pillAlpha = new Spring(1, 26, 0.9), entries = [], buttons = [], signature = "", lastVariantsRef = null, lastAppliedId = null, activeState = { activeId: "p:default", activeIndex: 0, isCustom: !1 }, prevActiveId = "", prevActiveIndex = -2, prevIsCustom = !1, prevDrifted = !1, initializedPill = !1, slideUntil = 0, display = "auto", chipMin = 0, unpinned = (values) => {
|
|
1025
1033
|
let out;
|
|
1026
1034
|
for (let k of Object.keys(values))
|
|
1027
1035
|
if (controls.isPinned(k) && !same(values[k], controls.locked[k]))
|
|
@@ -1152,7 +1160,18 @@ function createPresetStrip(doc, controls, showVariants, run, onAfterChange, pres
|
|
|
1152
1160
|
range.selectNodeContents(b), widest = Math.max(widest, range.getBoundingClientRect().width);
|
|
1153
1161
|
}
|
|
1154
1162
|
if (widest > 0)
|
|
1155
|
-
track.style.setProperty("--k-preset-min", `${
|
|
1163
|
+
chipMin = Math.ceil(widest * 1.06 + 14), track.style.setProperty("--k-preset-min", `${chipMin}px`);
|
|
1164
|
+
placeDisplay();
|
|
1165
|
+
}
|
|
1166
|
+
function chipLines() {
|
|
1167
|
+
let pad = parseFloat(getComputedStyle(root).getPropertyValue("--_k-tray-pad")) || 0, save = saveButton ? saveButton.offsetWidth + pad : 0;
|
|
1168
|
+
return presetLines(buttons.length, chipMin, root.clientWidth - pad * 2 - save, pad);
|
|
1169
|
+
}
|
|
1170
|
+
function placeDisplay() {
|
|
1171
|
+
let want = display === "list" || display === "auto" && chipLines() > 2 ? "list" : "chips";
|
|
1172
|
+
if (root.dataset.display === want)
|
|
1173
|
+
return !1;
|
|
1174
|
+
return root.dataset.display = want, !0;
|
|
1156
1175
|
}
|
|
1157
1176
|
function save() {
|
|
1158
1177
|
finishName(!0);
|
|
@@ -1288,8 +1307,8 @@ function createPresetStrip(doc, controls, showVariants, run, onAfterChange, pres
|
|
|
1288
1307
|
minWidth: 20,
|
|
1289
1308
|
rows: !0
|
|
1290
1309
|
}), doc.fonts?.ready.then(fitColumns);
|
|
1291
|
-
let ro = new ResizeObserver(() => measurePill(performance.now() >= slideUntil));
|
|
1292
|
-
return ro.observe(track), {
|
|
1310
|
+
let ro = new ResizeObserver(() => measurePill(placeDisplay() || performance.now() >= slideUntil));
|
|
1311
|
+
return ro.observe(track), ro.observe(root), {
|
|
1293
1312
|
element: root,
|
|
1294
1313
|
track,
|
|
1295
1314
|
pill,
|
|
@@ -1302,7 +1321,15 @@ function createPresetStrip(doc, controls, showVariants, run, onAfterChange, pres
|
|
|
1302
1321
|
getActiveState: () => activeState,
|
|
1303
1322
|
shows: () => wanted(entries),
|
|
1304
1323
|
cycle,
|
|
1324
|
+
select: (index) => {
|
|
1325
|
+
if (index !== activeState.activeIndex || activeState.drifted)
|
|
1326
|
+
selectAt(index);
|
|
1327
|
+
},
|
|
1305
1328
|
selectById,
|
|
1329
|
+
display(mode) {
|
|
1330
|
+
if (display = mode, placeDisplay())
|
|
1331
|
+
measurePill(!0);
|
|
1332
|
+
},
|
|
1306
1333
|
save: () => {
|
|
1307
1334
|
let message = "";
|
|
1308
1335
|
return run(() => message = save()), message;
|
|
@@ -5642,7 +5669,9 @@ class GpuOverlayManager {
|
|
|
5642
5669
|
this.drawIcon(item.icon, t.iconSm, at, ink, cardClip, k);
|
|
5643
5670
|
}
|
|
5644
5671
|
let lr = this.rectOf(item.label), px = t.buttonFontSize ?? t.textControl, words = this.fit(item.label.textContent ?? "", lr.width + 1, px, t.labelWeight);
|
|
5645
|
-
if (
|
|
5672
|
+
if (lr.width > 0)
|
|
5673
|
+
this.drawText(words, lr.left, cy, ink, { px, weight: t.labelWeight, ...zoom });
|
|
5674
|
+
if (item.chip && item.chip.getClientRects().length) {
|
|
5646
5675
|
let kr = this.rectOf(item.chip);
|
|
5647
5676
|
this.drawText(item.chip.textContent ?? "", kr.left, cy, withAlpha(t.dim, alpha), {
|
|
5648
5677
|
px: t.textCap,
|
|
@@ -6447,7 +6476,10 @@ class GpuOverlayManager {
|
|
|
6447
6476
|
this.drawRoundWash(dr, rowAlpha, this.wash(button, on)), this.drawDie(die, dr, withAlpha(this.hot(button, on, tokens.dim), rowAlpha)), this.drawRowOverlay(row.row, rRect, cardClip);
|
|
6448
6477
|
} else if (row.kind === "keybind")
|
|
6449
6478
|
this.drawKeybind(row, rRect, cardClip, rowAlpha, hovered);
|
|
6450
|
-
else if (row.kind === "
|
|
6479
|
+
else if (row.kind === "text") {
|
|
6480
|
+
let labelY = row.row.hasAttribute("data-multiline") ? this.rectOf(row.labelEl).top + this.rectOf(row.labelEl).height / 2 : rowCenterY;
|
|
6481
|
+
this.drawRowHover(row.row, rRect, hovered || row.row.classList.contains("knobs-active")), this.drawRowLabel(row.labelEl, row.display, row.isModified(), labelY, rowAlpha), this.drawRowOverlay(row.row, rRect, cardClip);
|
|
6482
|
+
} else if (row.kind === "toolbar")
|
|
6451
6483
|
this.drawToolbar(row, rRect, cardClip, rowAlpha, hinting);
|
|
6452
6484
|
else if (row.kind === "readout")
|
|
6453
6485
|
this.drawReadout(row, rRect, cardClip, rowAlpha, hovered);
|
|
@@ -10392,954 +10424,6 @@ function toolbarColumns(count, widest, avail, gap) {
|
|
|
10392
10424
|
return Math.ceil(count / Math.ceil(count / cols));
|
|
10393
10425
|
}
|
|
10394
10426
|
|
|
10395
|
-
// src/panel/inspector.ts
|
|
10396
|
-
function make(doc) {
|
|
10397
|
-
return (tag, cls, text) => {
|
|
10398
|
-
let node = doc.createElement(tag);
|
|
10399
|
-
if (cls)
|
|
10400
|
-
node.className = cls;
|
|
10401
|
-
if (text !== void 0)
|
|
10402
|
-
node.textContent = text;
|
|
10403
|
-
return node;
|
|
10404
|
-
};
|
|
10405
|
-
}
|
|
10406
|
-
function shell(c, kind) {
|
|
10407
|
-
let el = make(c.doc), row = el("div", "knobs-row knobs-insp");
|
|
10408
|
-
row.dataset.field = c.key, row.dataset.kind = kind;
|
|
10409
|
-
let label = el("span", void 0, c.display);
|
|
10410
|
-
return row.append(label), { row, label, el };
|
|
10411
|
-
}
|
|
10412
|
-
var fmt = (v, places) => (Object.is(v, -0) ? 0 : v).toFixed(places);
|
|
10413
|
-
function inlineEdit(doc, host, label, commit, back) {
|
|
10414
|
-
let input = doc.createElement("input");
|
|
10415
|
-
input.className = "knobs-cell-edit", input.type = "text", input.inputMode = "decimal", input.spellcheck = !1, input.hidden = !0, input.setAttribute("aria-label", label), host.append(input);
|
|
10416
|
-
let open = !1, done = (keep) => {
|
|
10417
|
-
if (!open)
|
|
10418
|
-
return;
|
|
10419
|
-
open = !1;
|
|
10420
|
-
let next = Number(input.value.trim().replace(/[^\d.eE+-]/g, ""));
|
|
10421
|
-
if (input.hidden = !0, host.classList.remove("knobs-editing"), keep && input.value.trim() !== "" && Number.isFinite(next))
|
|
10422
|
-
commit(next);
|
|
10423
|
-
let target = back();
|
|
10424
|
-
if (doc.activeElement === input || doc.activeElement === doc.body)
|
|
10425
|
-
target.focus({ preventScroll: !0 });
|
|
10426
|
-
};
|
|
10427
|
-
return input.addEventListener("keydown", (event) => {
|
|
10428
|
-
if (event.key === "Enter" || event.key === "Escape")
|
|
10429
|
-
event.preventDefault(), event.stopPropagation(), done(event.key === "Enter");
|
|
10430
|
-
else
|
|
10431
|
-
event.stopPropagation();
|
|
10432
|
-
}), input.addEventListener("blur", () => done(!0)), {
|
|
10433
|
-
input,
|
|
10434
|
-
get open() {
|
|
10435
|
-
return open;
|
|
10436
|
-
},
|
|
10437
|
-
start(text, select = !0) {
|
|
10438
|
-
if (open = !0, input.value = text, input.hidden = !1, host.classList.add("knobs-editing"), input.focus({ preventScroll: !0 }), select)
|
|
10439
|
-
input.select();
|
|
10440
|
-
else
|
|
10441
|
-
input.setSelectionRange(text.length, text.length);
|
|
10442
|
-
},
|
|
10443
|
-
done
|
|
10444
|
-
};
|
|
10445
|
-
}
|
|
10446
|
-
var typed = (event) => plainKey(event) && !event.altKey && /^[0-9.\-]$/.test(event.key) ? event.key : void 0;
|
|
10447
|
-
function scrub(target, row, o) {
|
|
10448
|
-
let at, moved = !1, last = 0, carried = 0, rect;
|
|
10449
|
-
target.addEventListener("pointerdown", (event) => {
|
|
10450
|
-
if (event.button !== 0 || event.shiftKey || event.metaKey)
|
|
10451
|
-
return;
|
|
10452
|
-
event.preventDefault(), target.setPointerCapture(event.pointerId), target.focus({ preventScroll: !0, focusVisible: !1 }), at = last = event.clientX, carried = 0, moved = !1;
|
|
10453
|
-
}), target.addEventListener("pointermove", (event) => {
|
|
10454
|
-
if (at === void 0)
|
|
10455
|
-
return;
|
|
10456
|
-
if (!moved && Math.abs(event.clientX - at) < 3)
|
|
10457
|
-
return;
|
|
10458
|
-
if (!moved)
|
|
10459
|
-
moved = !0, last = event.clientX, rect = row.getBoundingClientRect(), row.classList.add("knobs-active"), o.start();
|
|
10460
|
-
let r = rect, rate = precisionRate(offRow(event.clientY, r.top, r.bottom)) * (event.altKey ? 0.1 : 1);
|
|
10461
|
-
carried += (event.clientX - last) * rate, last = event.clientX, o.move(carried, event.altKey, event.shiftKey);
|
|
10462
|
-
});
|
|
10463
|
-
let release = (event) => {
|
|
10464
|
-
if (at === void 0)
|
|
10465
|
-
return;
|
|
10466
|
-
at = void 0, rect = void 0, row.classList.remove("knobs-active"), o.end(moved, event);
|
|
10467
|
-
};
|
|
10468
|
-
return target.addEventListener("pointerup", release), target.addEventListener("pointercancel", release), { scrubbing: () => at !== void 0 && moved };
|
|
10469
|
-
}
|
|
10470
|
-
var rate = (min, max, step) => Math.max(step, (max - min) / 200), onGrid = (v, min, step) => Number((min + Math.round((v - min) / step) * step).toPrecision(12)), AXES = ["x", "y", "z"];
|
|
10471
|
-
function vecRow(c) {
|
|
10472
|
-
let { row, label, el } = shell(c, "vec"), f = () => c.field, places = () => f().decimals ?? decimals(f().step), axes = AXES.slice(0, c.field.axes), cells = el("span", "knobs-cells");
|
|
10473
|
-
if (axes.length > 2)
|
|
10474
|
-
cells.dataset.wide = "";
|
|
10475
|
-
let linked = Boolean(c.field.linked), link;
|
|
10476
|
-
if (c.field.link) {
|
|
10477
|
-
link = el("button", "knobs-link"), link.type = "button", link.tabIndex = -1;
|
|
10478
|
-
let paint = () => {
|
|
10479
|
-
link.replaceChildren(iconSvg(c.doc, linked ? "link" : "unlink")), link.setAttribute("aria-pressed", String(linked)), link.setAttribute("aria-label", linked ? "Unlink axes" : "Link axes");
|
|
10480
|
-
};
|
|
10481
|
-
paint(), link.onclick = () => {
|
|
10482
|
-
linked = !linked, paint(), c.wake();
|
|
10483
|
-
}, row.append(link);
|
|
10484
|
-
}
|
|
10485
|
-
row.append(cells);
|
|
10486
|
-
let shown = c.get(), mixed = !1, g = gesture(c), base = shown, withAxis = (from, axis, v) => {
|
|
10487
|
-
let { min, max, step } = f(), next = clamp(onGrid(v, min, step), min, max);
|
|
10488
|
-
if (!linked)
|
|
10489
|
-
return { ...from, [axis]: next };
|
|
10490
|
-
let was = from[axis] ?? 0, k = Math.abs(was) > 0.000000001 ? next / was : void 0, out = {};
|
|
10491
|
-
for (let a of axes) {
|
|
10492
|
-
let own = from[a] ?? 0;
|
|
10493
|
-
out[a] = a === axis ? next : clamp(Number((k !== void 0 ? own * k : own + (next - was)).toPrecision(12)), min, max);
|
|
10494
|
-
}
|
|
10495
|
-
return out;
|
|
10496
|
-
}, gpuCells = [], reads = [], rolls = [], stops = [];
|
|
10497
|
-
for (let axis of axes) {
|
|
10498
|
-
let cell = el("span", "knobs-cell");
|
|
10499
|
-
cell.tabIndex = 0, cell.dataset.axis = axis, cell.setAttribute("role", "spinbutton");
|
|
10500
|
-
let name = c.field.axisLabels?.[axes.indexOf(axis)] ?? axis;
|
|
10501
|
-
cell.setAttribute("aria-label", `${c.display} ${name}`);
|
|
10502
|
-
let letter = el("i", "knobs-cell-axis", name.toUpperCase());
|
|
10503
|
-
letter.setAttribute("aria-hidden", "true");
|
|
10504
|
-
let read = el("span", "knobs-cell-read");
|
|
10505
|
-
cell.append(letter, read), cells.append(cell), reads.push(read), rolls.push(rollingReadout(read)), stops.push(cell);
|
|
10506
|
-
let editor = inlineEdit(c.doc, cell, `${c.display} ${name} value`, (v) => {
|
|
10507
|
-
g.start(), g.set(withAxis(c.get(), axis, v));
|
|
10508
|
-
}, () => cell), drag = scrub(cell, row, {
|
|
10509
|
-
perPx: () => rate(f().min, f().max, f().step),
|
|
10510
|
-
start() {
|
|
10511
|
-
g.start(), base = c.get();
|
|
10512
|
-
},
|
|
10513
|
-
move(dx, _fine, coarse) {
|
|
10514
|
-
let by = dx * rate(f().min, f().max, f().step) * (coarse ? 10 : 1);
|
|
10515
|
-
g.set(withAxis(base, axis, (base[axis] ?? 0) + by));
|
|
10516
|
-
},
|
|
10517
|
-
end(moved) {
|
|
10518
|
-
if (!moved)
|
|
10519
|
-
editor.start(mixed ? "" : fmt(shown[axis] ?? 0, places()));
|
|
10520
|
-
c.wake();
|
|
10521
|
-
}
|
|
10522
|
-
}), panAt, give = textGive(read, () => c.wake());
|
|
10523
|
-
onPan(cell, {
|
|
10524
|
-
accept: () => !drag.scrubbing() && !editor.open,
|
|
10525
|
-
move(dx) {
|
|
10526
|
-
let perPx = rate(f().min, f().max, f().step);
|
|
10527
|
-
if (panAt === void 0)
|
|
10528
|
-
g.start(), base = c.get(), panAt = { at: 0, give: 0 }, row.classList.add("knobs-active"), cell.setAttribute("data-panned", "");
|
|
10529
|
-
let from = base[axis] ?? 0;
|
|
10530
|
-
if (panAt = band(panAt, dx, (f().min - from) / perPx, (f().max - from) / perPx), g.set(withAxis(base, axis, from + panAt.at * perPx)), panAt.give !== give.give)
|
|
10531
|
-
give.hold(panAt.give);
|
|
10532
|
-
},
|
|
10533
|
-
lift: () => give.release(),
|
|
10534
|
-
end() {
|
|
10535
|
-
panAt = void 0, give.release(), row.classList.remove("knobs-active"), cell.removeAttribute("data-panned"), c.wake();
|
|
10536
|
-
},
|
|
10537
|
-
step(direction) {
|
|
10538
|
-
g.start(), g.set(withAxis(c.get(), axis, (shown[axis] ?? 0) + direction * f().step));
|
|
10539
|
-
}
|
|
10540
|
-
}), cell.addEventListener("keydown", (event) => {
|
|
10541
|
-
if (event.target !== cell || !plainKey(event))
|
|
10542
|
-
return;
|
|
10543
|
-
let dir = arrowOf(event), char = typed(event);
|
|
10544
|
-
if (dir) {
|
|
10545
|
-
event.preventDefault(), event.stopPropagation();
|
|
10546
|
-
let by = f().step * (event.shiftKey ? bigOf(event) : event.altKey ? 0.1 : 1);
|
|
10547
|
-
g.start(), g.set(withAxis(c.get(), axis, (shown[axis] ?? 0) + dir * by));
|
|
10548
|
-
} else if (event.key === "Home" || event.key === "End")
|
|
10549
|
-
event.preventDefault(), g.start(), g.set(withAxis(c.get(), axis, event.key === "Home" ? f().min : f().max));
|
|
10550
|
-
else if (event.key === "Enter" && keyPrefs(cell).edit)
|
|
10551
|
-
event.preventDefault(), event.stopPropagation(), editor.start(mixed ? "" : fmt(shown[axis] ?? 0, places()));
|
|
10552
|
-
else if (char && keyPrefs(cell).edit)
|
|
10553
|
-
event.preventDefault(), event.stopPropagation(), editor.start(char, !1);
|
|
10554
|
-
}), gpuCells.push({
|
|
10555
|
-
el: cell,
|
|
10556
|
-
axis: letter,
|
|
10557
|
-
read,
|
|
10558
|
-
editing: () => editor.open,
|
|
10559
|
-
active: () => drag.scrubbing() || panAt !== void 0
|
|
10560
|
-
});
|
|
10561
|
-
}
|
|
10562
|
-
let paint = (ms = 0, delay = 0) => {
|
|
10563
|
-
axes.forEach((axis, i) => {
|
|
10564
|
-
let text = mixed ? "—" : fmt(shown[axis] ?? 0, places()), unit = f().unit && !mixed ? ` ${f().unit}` : "";
|
|
10565
|
-
rolls[i].show(mixed ? ["—"] : [{ value: shown[axis] ?? 0, decimals: places() }], ms, delay), stops[i].setAttribute("aria-valuetext", `${text}${unit}`);
|
|
10566
|
-
});
|
|
10567
|
-
};
|
|
10568
|
-
paint();
|
|
10569
|
-
let placed = !1, gpu = {
|
|
10570
|
-
kind: "vec",
|
|
10571
|
-
key: c.key,
|
|
10572
|
-
display: c.display,
|
|
10573
|
-
row,
|
|
10574
|
-
labelEl: label,
|
|
10575
|
-
cells: gpuCells,
|
|
10576
|
-
...link ? { link } : {},
|
|
10577
|
-
linked: () => linked,
|
|
10578
|
-
wave: c.wave,
|
|
10579
|
-
isModified: c.isModified
|
|
10580
|
-
};
|
|
10581
|
-
return {
|
|
10582
|
-
row,
|
|
10583
|
-
labelEl: label,
|
|
10584
|
-
input: stops[0],
|
|
10585
|
-
stops: () => stops,
|
|
10586
|
-
update(value, delay, instant, isMixed = !1) {
|
|
10587
|
-
shown = value, mixed = isMixed;
|
|
10588
|
-
let hand = row.classList.contains("knobs-active");
|
|
10589
|
-
paint(!placed || instant || hand ? 0 : rollMs(row), delay), placed = !0;
|
|
10590
|
-
},
|
|
10591
|
-
dispose() {
|
|
10592
|
-
for (let r of rolls)
|
|
10593
|
-
r.dispose();
|
|
10594
|
-
},
|
|
10595
|
-
tracks: [],
|
|
10596
|
-
gpu: [gpu]
|
|
10597
|
-
};
|
|
10598
|
-
}
|
|
10599
|
-
function rangeRow(c) {
|
|
10600
|
-
let el = make(c.doc), f = () => c.field, places = () => f().decimals ?? decimals(f().step), row = el("div", "knobs-row knobs-range");
|
|
10601
|
-
row.dataset.field = c.key;
|
|
10602
|
-
let track = el("div", "knobs-range-track"), fill = el("i", "knobs-range-fill"), label = el("span", "knobs-label", c.display), read = el("span", "knobs-range-read"), thumbs = ["lo", "hi"].map((end) => {
|
|
10603
|
-
let t = el("span", "knobs-range-thumb");
|
|
10604
|
-
return t.dataset.end = end, t.tabIndex = 0, t.setAttribute("role", "slider"), t.setAttribute("aria-label", `${c.display} ${end === "lo" ? "low" : "high"}`), t;
|
|
10605
|
-
}), words = el("span", "knobs-range-text");
|
|
10606
|
-
words.append(label, read);
|
|
10607
|
-
let band2 = el("i", "knobs-range-smear");
|
|
10608
|
-
track.append(fill, band2, ...thumbs, words), row.append(track);
|
|
10609
|
-
let shown = c.get(), mixed = !1, dragging = !1, smearFrame = 0, smearAt = 0, smearStrength = 0, lastEnds = [0, 0], smears = [0, 0], ends = () => {
|
|
10610
|
-
let cs = getComputedStyle(track);
|
|
10611
|
-
return [
|
|
10612
|
-
parseFloat(cs.getPropertyValue("--kr-lo")) || 0,
|
|
10613
|
-
parseFloat(cs.getPropertyValue("--kr-hi")) || 0
|
|
10614
|
-
];
|
|
10615
|
-
}, setSmears = (lo, hi) => {
|
|
10616
|
-
smears[0] = lo === 0 ? 0 : (smears[0] + lo) / 2, smears[1] = hi === 0 ? 0 : (smears[1] + hi) / 2, track.classList.toggle("knobs-range-smearing", smears[0] > 0 || smears[1] > 0), track.style.setProperty("--kr-smear-lo", smears[0].toFixed(2)), track.style.setProperty("--kr-smear-hi", smears[1].toFixed(2));
|
|
10617
|
-
}, runSmear = (now) => {
|
|
10618
|
-
let at = ends(), dt = (now - smearAt) / 1000, w = track.clientWidth, speeds = [0, 1].map((i) => dt > 0 ? Math.abs(at[i] - lastEnds[i]) * w / dt : 0);
|
|
10619
|
-
lastEnds = at, smearAt = now;
|
|
10620
|
-
let gliding = !dragging && track.getAnimations().length > 0;
|
|
10621
|
-
setSmears(gliding ? rangeSmear(speeds[0], smearStrength) : 0, gliding ? rangeSmear(speeds[1], smearStrength) : 0), smearFrame = gliding ? requestAnimationFrame(runSmear) : 0;
|
|
10622
|
-
};
|
|
10623
|
-
track.addEventListener("transitionrun", (event) => {
|
|
10624
|
-
if (event.target !== track || smearFrame || dragging)
|
|
10625
|
-
return;
|
|
10626
|
-
if (track.closest('[data-gpu-active="true"]'))
|
|
10627
|
-
return;
|
|
10628
|
-
smearStrength = clamp(parseFloat(getComputedStyle(track).getPropertyValue("--k-range-blur")) || 0, 0, 1);
|
|
10629
|
-
let reduced = c.doc.defaultView?.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
10630
|
-
if (smearStrength <= 0 || reduced)
|
|
10631
|
-
return;
|
|
10632
|
-
lastEnds = ends(), smearAt = performance.now(), smearFrame = requestAnimationFrame(runSmear);
|
|
10633
|
-
});
|
|
10634
|
-
let lastEnd = 0, g = gesture(c), span = () => f().max - f().min || 1, ratio = (v) => clamp((v - f().min) / span(), 0, 1), quant = (v, fine) => clamp(onGrid(v, f().min, fine ? f().step / 10 : f().step), f().min, f().max), withEnd = (from, end, v, fine = !1) => {
|
|
10635
|
-
let q = quant(v, fine);
|
|
10636
|
-
return end === 0 ? [Math.min(q, from[1]), from[1]] : [from[0], Math.max(q, from[0])];
|
|
10637
|
-
}, rolling = rollingReadout(read), showText = (ms, delay) => rolling.show(mixed ? ["—"] : [
|
|
10638
|
-
{ value: shown[0], decimals: places() },
|
|
10639
|
-
"–",
|
|
10640
|
-
{ value: shown[1], decimals: places() },
|
|
10641
|
-
f().unit ? ` ${f().unit}` : ""
|
|
10642
|
-
], ms, delay), place = (instant) => {
|
|
10643
|
-
let [a, b] = [ratio(shown[0]), ratio(shown[1])], nodes = [fill, track];
|
|
10644
|
-
if (instant)
|
|
10645
|
-
for (let n of nodes)
|
|
10646
|
-
n.style.transition = "none";
|
|
10647
|
-
if (fill.style.transform = `translateX(${(a * 100).toFixed(4)}%) scaleX(${Math.max(0, b - a).toFixed(5)})`, track.style.setProperty("--kr-lo", a.toFixed(6)), track.style.setProperty("--kr-hi", b.toFixed(6)), instant) {
|
|
10648
|
-
fill.offsetWidth;
|
|
10649
|
-
for (let n of nodes)
|
|
10650
|
-
n.style.transition = "";
|
|
10651
|
-
}
|
|
10652
|
-
}, paint = (instant, delay = 0) => {
|
|
10653
|
-
showText(instant ? 0 : rollMs(row), delay), thumbs.forEach((th, i) => {
|
|
10654
|
-
th.setAttribute("aria-valuenow", String(shown[i])), th.setAttribute("aria-valuemin", String(i === 0 ? f().min : shown[0])), th.setAttribute("aria-valuemax", String(i === 0 ? shown[1] : f().max));
|
|
10655
|
-
}), place(instant);
|
|
10656
|
-
}, grab = 0, startValue = shown, rect, lastX = 0, hand = { at: 0, give: 0 }, moved = 0, card = () => row.parentElement?.classList.contains("knobs-card") ? row.parentElement : null, give = textGive(row, () => c.wake(), {
|
|
10657
|
-
home: STRETCH_HOME_S,
|
|
10658
|
-
draw: (px) => drawStretch(row, px, 0, { w: track.clientWidth, h: 0 }, { thin: !0, unclip: card() })
|
|
10659
|
-
}), most = GIVE, fit = () => {
|
|
10660
|
-
let room = roomOf(row, card());
|
|
10661
|
-
most = giveRoom(Math.min(room.left, room.right) - 1, GIVE);
|
|
10662
|
-
}, valueAt = (x) => f().min + clamp((x - rect.left) / rect.width, 0, 1) * span();
|
|
10663
|
-
track.addEventListener("pointerdown", (event) => {
|
|
10664
|
-
if (event.button !== 0 || event.shiftKey || event.metaKey)
|
|
10665
|
-
return;
|
|
10666
|
-
if (event.target.closest(".knobs-cell-edit,.knobs-accessory"))
|
|
10667
|
-
return;
|
|
10668
|
-
event.preventDefault(), track.setPointerCapture(event.pointerId), rect = track.getBoundingClientRect();
|
|
10669
|
-
let x = event.clientX - rect.left, [ax, bx] = [ratio(shown[0]) * rect.width, ratio(shown[1]) * rect.width];
|
|
10670
|
-
if (grab = x > ax + 8 && x < bx - 8 && bx - ax > 24 ? 2 : Math.abs(x - ax) <= Math.abs(x - bx) && !(x > bx) ? 0 : 1, ax === bx)
|
|
10671
|
-
grab = x < ax ? 0 : 1;
|
|
10672
|
-
if (grab !== 2)
|
|
10673
|
-
lastEnd = grab;
|
|
10674
|
-
if (thumbs[grab === 2 ? lastEnd : grab].focus({
|
|
10675
|
-
preventScroll: !0,
|
|
10676
|
-
focusVisible: !1
|
|
10677
|
-
}), lastX = event.clientX, startValue = shown, moved = 0, fit(), hand = {
|
|
10678
|
-
at: grab === 2 || event.altKey ? ratio(shown[grab === 2 ? 0 : grab]) * rect.width : clamp(x, 0, rect.width),
|
|
10679
|
-
give: 0
|
|
10680
|
-
}, dragging = !0, row.classList.add("knobs-active"), g.start(), grab !== 2 && !event.altKey)
|
|
10681
|
-
g.set(withEnd(shown, grab, valueAt(event.clientX)));
|
|
10682
|
-
c.wake();
|
|
10683
|
-
}), track.addEventListener("pointermove", (event) => {
|
|
10684
|
-
if (!dragging || !rect)
|
|
10685
|
-
return;
|
|
10686
|
-
let rate = precisionRate(offRow(event.clientY, rect.top, rect.bottom)) * (event.altKey ? 0.1 : 1), dx = (event.clientX - lastX) * rate;
|
|
10687
|
-
if (lastX = event.clientX, grab === 2) {
|
|
10688
|
-
moved += dx;
|
|
10689
|
-
let width = startValue[1] - startValue[0], by = moved / rect.width * span(), lo = clamp(quant(startValue[0] + by, event.altKey), f().min, f().max - width);
|
|
10690
|
-
g.set([lo, Number((lo + width).toPrecision(12))]);
|
|
10691
|
-
return;
|
|
10692
|
-
}
|
|
10693
|
-
if (hand = band(hand, dx, 0, rect.width, most), g.set(withEnd(c.get(), grab, f().min + hand.at / rect.width * span(), event.altKey)), hand.give !== give.give)
|
|
10694
|
-
give.hold(hand.give);
|
|
10695
|
-
});
|
|
10696
|
-
let release = () => {
|
|
10697
|
-
if (!dragging)
|
|
10698
|
-
return;
|
|
10699
|
-
dragging = !1, rect = void 0, give.release(), row.classList.remove("knobs-active"), c.wake();
|
|
10700
|
-
};
|
|
10701
|
-
track.addEventListener("pointerup", release), track.addEventListener("pointercancel", release);
|
|
10702
|
-
let panAt;
|
|
10703
|
-
onPan(track, {
|
|
10704
|
-
accept: () => !dragging,
|
|
10705
|
-
move(dx) {
|
|
10706
|
-
let w = track.clientWidth;
|
|
10707
|
-
if (!w)
|
|
10708
|
-
return;
|
|
10709
|
-
if (panAt === void 0)
|
|
10710
|
-
g.start(), panAt = { at: (shown[lastEnd] - f().min) / span() * w, give: 0 }, fit(), dragging = !0, row.classList.add("knobs-active");
|
|
10711
|
-
if (panAt = band(panAt, dx, 0, w, most), g.set(withEnd(c.get(), lastEnd, f().min + panAt.at / w * span())), panAt.give !== give.give)
|
|
10712
|
-
give.hold(panAt.give);
|
|
10713
|
-
},
|
|
10714
|
-
lift: () => give.release(),
|
|
10715
|
-
end() {
|
|
10716
|
-
panAt = void 0, give.release(), dragging = !1, row.classList.remove("knobs-active"), c.wake();
|
|
10717
|
-
},
|
|
10718
|
-
step(direction) {
|
|
10719
|
-
g.start(), g.set(withEnd(shown, lastEnd, shown[lastEnd] + direction * f().step));
|
|
10720
|
-
}
|
|
10721
|
-
});
|
|
10722
|
-
let editors = thumbs.map((th, i) => inlineEdit(c.doc, row, `${c.display} ${i === 0 ? "low" : "high"} value`, (v) => {
|
|
10723
|
-
g.start(), g.set(withEnd(c.get(), i, v));
|
|
10724
|
-
}, () => th));
|
|
10725
|
-
thumbs.forEach((th, i) => {
|
|
10726
|
-
let end = i;
|
|
10727
|
-
th.addEventListener("focus", () => {
|
|
10728
|
-
lastEnd = end, row.dataset.endFocus = th.dataset.end, c.wake();
|
|
10729
|
-
}), th.addEventListener("blur", () => {
|
|
10730
|
-
if (row.dataset.endFocus === th.dataset.end)
|
|
10731
|
-
delete row.dataset.endFocus;
|
|
10732
|
-
}), th.addEventListener("keydown", (event) => {
|
|
10733
|
-
if (!plainKey(event))
|
|
10734
|
-
return;
|
|
10735
|
-
let dir = arrowOf(event), char = typed(event);
|
|
10736
|
-
if (dir) {
|
|
10737
|
-
event.preventDefault(), event.stopPropagation();
|
|
10738
|
-
let by = f().step * (event.shiftKey ? bigOf(event) : event.altKey ? 0.1 : 1);
|
|
10739
|
-
g.start(), g.set(withEnd(shown, end, shown[end] + dir * by, event.altKey));
|
|
10740
|
-
} else if (event.key === "Home" || event.key === "End")
|
|
10741
|
-
event.preventDefault(), g.start(), g.set(withEnd(shown, end, event.key === "Home" ? f().min : f().max));
|
|
10742
|
-
else if (event.key === "Enter" && keyPrefs(th).edit)
|
|
10743
|
-
event.preventDefault(), event.stopPropagation(), editors[end].start(mixed ? "" : fmt(shown[end], places()));
|
|
10744
|
-
else if (char && keyPrefs(th).edit)
|
|
10745
|
-
event.preventDefault(), event.stopPropagation(), editors[end].start(char, !1);
|
|
10746
|
-
});
|
|
10747
|
-
});
|
|
10748
|
-
let first = !0, gpu = {
|
|
10749
|
-
kind: "range",
|
|
10750
|
-
key: c.key,
|
|
10751
|
-
display: c.display,
|
|
10752
|
-
row,
|
|
10753
|
-
labelEl: label,
|
|
10754
|
-
track,
|
|
10755
|
-
read,
|
|
10756
|
-
thumbs,
|
|
10757
|
-
ratios: () => [ratio(shown[0]), ratio(shown[1])],
|
|
10758
|
-
dragging: () => dragging,
|
|
10759
|
-
editing: () => editors.some((e) => e.open),
|
|
10760
|
-
wave: c.wave,
|
|
10761
|
-
isModified: c.isModified
|
|
10762
|
-
};
|
|
10763
|
-
return {
|
|
10764
|
-
row,
|
|
10765
|
-
labelEl: label,
|
|
10766
|
-
input: thumbs[0],
|
|
10767
|
-
stops: () => thumbs,
|
|
10768
|
-
update(value, delay, instant, isMixed = !1) {
|
|
10769
|
-
shown = value, mixed = isMixed, paint(first || Boolean(instant) || dragging, delay), first = !1;
|
|
10770
|
-
},
|
|
10771
|
-
dispose() {
|
|
10772
|
-
cancelAnimationFrame(smearFrame), rolling.dispose();
|
|
10773
|
-
},
|
|
10774
|
-
tracks: [],
|
|
10775
|
-
gpu: [gpu]
|
|
10776
|
-
};
|
|
10777
|
-
}
|
|
10778
|
-
function angleRow(c) {
|
|
10779
|
-
let { row, label, el } = shell(c, "angle"), f = () => c.field, control = el("span", "knobs-angle");
|
|
10780
|
-
control.tabIndex = 0, control.setAttribute("role", "slider"), control.setAttribute("aria-label", c.display);
|
|
10781
|
-
let read = el("span", "knobs-angle-read"), dial = el("span", "knobs-dial"), hand = el("i", "knobs-dial-hand");
|
|
10782
|
-
dial.append(hand), control.append(read, dial), row.append(control);
|
|
10783
|
-
let value = c.get(), turn = value, mixed = !1, dragging = !1, g = gesture(c), places = () => decimals(f().step), snapTo = (v, coarse) => {
|
|
10784
|
-
let step = coarse ? Math.max(15, f().step) : f().step, q = Number((Math.round(v / step) * step).toPrecision(12));
|
|
10785
|
-
return f().wrap ? wrapAngle2(q, f().min, f().max) : clamp(q, f().min, f().max);
|
|
10786
|
-
}, rolling = rollingReadout(read), paint = (instant, delay = 0) => {
|
|
10787
|
-
let t = mixed ? "—" : `${fmt(value, places())}°`;
|
|
10788
|
-
if (rolling.show(mixed ? ["—"] : [{ value, decimals: places() }, "°"], instant || row.classList.contains("knobs-active") ? 0 : rollMs(row), delay), control.setAttribute("aria-valuenow", String(value)), control.setAttribute("aria-valuetext", t), instant || reducedMotion4(c.doc))
|
|
10789
|
-
hand.style.transition = "none";
|
|
10790
|
-
if (hand.style.rotate = `${turn.toFixed(3)}deg`, instant)
|
|
10791
|
-
hand.offsetWidth, hand.style.transition = "";
|
|
10792
|
-
}, follow = (next) => {
|
|
10793
|
-
let d = next - value;
|
|
10794
|
-
if (f().wrap) {
|
|
10795
|
-
let s = f().max - f().min;
|
|
10796
|
-
d = ((d + s / 2) % s + s) % s - s / 2;
|
|
10797
|
-
}
|
|
10798
|
-
turn += d, value = next;
|
|
10799
|
-
}, mode = "scrub", startX = 0, startValue = 0, carried = 0, rowRect, centre = [0, 0], moved = !1, angleAt = (x, y) => Math.atan2(x - centre[0], -(y - centre[1])) * 180 / Math.PI;
|
|
10800
|
-
control.addEventListener("pointerdown", (event) => {
|
|
10801
|
-
if (event.button !== 0 || event.shiftKey || event.metaKey)
|
|
10802
|
-
return;
|
|
10803
|
-
if (event.target.closest(".knobs-cell-edit"))
|
|
10804
|
-
return;
|
|
10805
|
-
event.preventDefault(), control.setPointerCapture(event.pointerId), control.focus({ preventScroll: !0, focusVisible: !1 });
|
|
10806
|
-
let r = dial.getBoundingClientRect();
|
|
10807
|
-
if (centre = [r.left + r.width / 2, r.top + r.height / 2], mode = event.target.closest(".knobs-dial") ? "dial" : "scrub", startX = event.clientX, startValue = value, carried = 0, moved = !1, dragging = !0, g.start(), mode === "dial")
|
|
10808
|
-
moved = !0, row.classList.add("knobs-active"), g.set(snapTo(angleAt(event.clientX, event.clientY), !1));
|
|
10809
|
-
c.wake();
|
|
10810
|
-
}), control.addEventListener("pointermove", (event) => {
|
|
10811
|
-
if (!dragging)
|
|
10812
|
-
return;
|
|
10813
|
-
if (mode === "dial") {
|
|
10814
|
-
let a = angleAt(event.clientX, event.clientY);
|
|
10815
|
-
g.set(snapTo(f().wrap ? a : clamp(a, f().min, f().max), event.shiftKey));
|
|
10816
|
-
return;
|
|
10817
|
-
}
|
|
10818
|
-
if (!moved && Math.abs(event.clientX - startX) < 3)
|
|
10819
|
-
return;
|
|
10820
|
-
if (!moved)
|
|
10821
|
-
moved = !0, startX = event.clientX, rowRect = row.getBoundingClientRect(), row.classList.add("knobs-active");
|
|
10822
|
-
let r = rowRect, rate = precisionRate(offRow(event.clientY, r.top, r.bottom)) * (event.altKey ? 0.1 : 1);
|
|
10823
|
-
carried += (event.clientX - startX) * rate, startX = event.clientX, g.set(snapTo(startValue + carried * f().step, event.shiftKey));
|
|
10824
|
-
});
|
|
10825
|
-
let editor = inlineEdit(c.doc, row, `${c.display} value`, (v) => {
|
|
10826
|
-
g.start(), g.set(snapTo(v, !1));
|
|
10827
|
-
}, () => control), release = () => {
|
|
10828
|
-
if (!dragging)
|
|
10829
|
-
return;
|
|
10830
|
-
if (dragging = !1, row.classList.remove("knobs-active"), !moved)
|
|
10831
|
-
editor.start(mixed ? "" : fmt(value, places()));
|
|
10832
|
-
c.wake();
|
|
10833
|
-
};
|
|
10834
|
-
control.addEventListener("pointerup", release), control.addEventListener("pointercancel", release);
|
|
10835
|
-
let panAt, give = textGive(read, () => c.wake());
|
|
10836
|
-
onPan(control, {
|
|
10837
|
-
accept: () => !dragging,
|
|
10838
|
-
move(dx) {
|
|
10839
|
-
let step = f().step;
|
|
10840
|
-
if (panAt === void 0)
|
|
10841
|
-
g.start(), panAt = { at: value / step, give: 0 }, row.classList.add("knobs-active");
|
|
10842
|
-
if (panAt = f().wrap ? { at: panAt.at + dx, give: 0 } : band(panAt, dx, f().min / step, f().max / step), g.set(snapTo(panAt.at * step, !1)), panAt.give !== give.give)
|
|
10843
|
-
give.hold(panAt.give);
|
|
10844
|
-
},
|
|
10845
|
-
lift: () => give.release(),
|
|
10846
|
-
end() {
|
|
10847
|
-
panAt = void 0, give.release(), row.classList.remove("knobs-active"), c.wake();
|
|
10848
|
-
},
|
|
10849
|
-
step(direction) {
|
|
10850
|
-
g.start(), g.set(snapTo(value + direction * f().step, !1));
|
|
10851
|
-
}
|
|
10852
|
-
}), control.addEventListener("keydown", (event) => {
|
|
10853
|
-
if (event.target !== control || !plainKey(event))
|
|
10854
|
-
return;
|
|
10855
|
-
let dir = arrowOf(event), char = typed(event);
|
|
10856
|
-
if (dir)
|
|
10857
|
-
if (event.preventDefault(), event.stopPropagation(), g.start(), event.shiftKey) {
|
|
10858
|
-
let s = Math.max(15, f().step), k = dir > 0 ? Math.floor(value / s + 0.000000001) + 1 : Math.ceil(value / s - 0.000000001) - 1;
|
|
10859
|
-
g.set(snapTo(k * s, !1));
|
|
10860
|
-
} else
|
|
10861
|
-
g.set(snapTo(value + dir * f().step * (event.altKey ? 0.1 : 1), !1));
|
|
10862
|
-
else if (event.key === "Home" || event.key === "End")
|
|
10863
|
-
event.preventDefault(), g.start(), g.set(snapTo(event.key === "Home" ? f().min : f().max - (f().wrap ? f().step : 0), !1));
|
|
10864
|
-
else if (event.key === "Enter" && keyPrefs(control).edit)
|
|
10865
|
-
event.preventDefault(), event.stopPropagation(), editor.start(mixed ? "" : fmt(value, places()));
|
|
10866
|
-
else if (char && keyPrefs(control).edit)
|
|
10867
|
-
event.preventDefault(), event.stopPropagation(), editor.start(char, !1);
|
|
10868
|
-
});
|
|
10869
|
-
let first = !0, gpu = {
|
|
10870
|
-
kind: "angle",
|
|
10871
|
-
key: c.key,
|
|
10872
|
-
display: c.display,
|
|
10873
|
-
row,
|
|
10874
|
-
labelEl: label,
|
|
10875
|
-
control,
|
|
10876
|
-
read,
|
|
10877
|
-
dial,
|
|
10878
|
-
turn: () => mixed ? 0 : turn,
|
|
10879
|
-
dragging: () => dragging,
|
|
10880
|
-
editing: () => editor.open,
|
|
10881
|
-
wave: c.wave,
|
|
10882
|
-
isModified: c.isModified
|
|
10883
|
-
};
|
|
10884
|
-
return {
|
|
10885
|
-
row,
|
|
10886
|
-
labelEl: label,
|
|
10887
|
-
input: control,
|
|
10888
|
-
stops: () => [control],
|
|
10889
|
-
update(next, delay, instant, isMixed = !1) {
|
|
10890
|
-
if (mixed = isMixed, first || instant)
|
|
10891
|
-
value = turn = next;
|
|
10892
|
-
else
|
|
10893
|
-
follow(next);
|
|
10894
|
-
paint(first || Boolean(instant) || dragging, delay), first = !1;
|
|
10895
|
-
},
|
|
10896
|
-
dispose() {
|
|
10897
|
-
rolling.dispose();
|
|
10898
|
-
},
|
|
10899
|
-
tracks: [],
|
|
10900
|
-
gpu: [gpu]
|
|
10901
|
-
};
|
|
10902
|
-
}
|
|
10903
|
-
var SEED_STEP = 12, DICE_ROLL_MS = 620;
|
|
10904
|
-
function seedRow(c) {
|
|
10905
|
-
let { row, label, el } = shell(c, "seed"), f = () => c.field, control = el("span", "knobs-seed");
|
|
10906
|
-
control.tabIndex = 0, control.setAttribute("role", "spinbutton"), control.setAttribute("aria-label", c.display);
|
|
10907
|
-
let read = el("span", "knobs-seed-read");
|
|
10908
|
-
control.append(read);
|
|
10909
|
-
let reel = el("span", "knobs-seed-digits");
|
|
10910
|
-
read.append(reel);
|
|
10911
|
-
let roller = it(reel, {
|
|
10912
|
-
value: c.get(),
|
|
10913
|
-
format: { useGrouping: !1, maximumFractionDigits: 0 },
|
|
10914
|
-
duration: 1,
|
|
10915
|
-
motionBlur: !0
|
|
10916
|
-
}), places = [], initialized = !1, diced = !1, roll = el("button", "knobs-seed-roll");
|
|
10917
|
-
roll.type = "button", roll.tabIndex = -1, roll.setAttribute("aria-label", `Roll ${c.display}`);
|
|
10918
|
-
let die = createHeaderDie(c.doc, () => c.wake(), GROUP_DIE);
|
|
10919
|
-
roll.append(die.node), row.append(control, roll);
|
|
10920
|
-
let value = c.get(), mixed = !1, g = gesture(c), set = (v) => {
|
|
10921
|
-
stopCarry(), g.start(), g.set(Math.round(clamp(v, f().min, f().max)));
|
|
10922
|
-
}, reroll = () => {
|
|
10923
|
-
let { min, max } = f(), next = value;
|
|
10924
|
-
for (let i = 0;i < 8 && next === value; i++)
|
|
10925
|
-
next = min + Math.floor(Math.random() * (max - min + 1));
|
|
10926
|
-
die.roll(), diced = !0, set(next), diced = !1;
|
|
10927
|
-
};
|
|
10928
|
-
roll.onclick = () => reroll();
|
|
10929
|
-
let editor = inlineEdit(c.doc, row, `${c.display} value`, set, () => control), give = textGive(read, () => c.wake()), recent = moves(), panned, carry = [], stopCarry = () => {
|
|
10930
|
-
for (let t of carry)
|
|
10931
|
-
clearTimeout(t);
|
|
10932
|
-
carry = [];
|
|
10933
|
-
}, scrubBy = (steps) => {
|
|
10934
|
-
let { min, max } = f(), next = clamp(value + steps, min, max);
|
|
10935
|
-
if (next === value)
|
|
10936
|
-
return !1;
|
|
10937
|
-
let dir = next > value ? 1 : -1;
|
|
10938
|
-
for (let i = 0;i < Math.min(3, Math.abs(next - value)); i++)
|
|
10939
|
-
die.turn(dir);
|
|
10940
|
-
return g.set(next), tick(control), !0;
|
|
10941
|
-
}, letGo = () => {
|
|
10942
|
-
panned = void 0, give.release(), row.classList.remove("knobs-active"), c.wake();
|
|
10943
|
-
};
|
|
10944
|
-
onPan(row, {
|
|
10945
|
-
accept: () => !editor.open,
|
|
10946
|
-
move(dx) {
|
|
10947
|
-
if (!panned)
|
|
10948
|
-
stopCarry(), g.start(), recent.reset(), panned = { travel: 0, give: 0 }, row.classList.add("knobs-active"), c.wake();
|
|
10949
|
-
recent.add(dx);
|
|
10950
|
-
let { min, max } = f(), { next, steps } = stepBand(panned, dx, SEED_STEP, [value - min, max - value]);
|
|
10951
|
-
if (panned = next, steps)
|
|
10952
|
-
scrubBy(steps);
|
|
10953
|
-
if (next.give !== give.give)
|
|
10954
|
-
give.hold(next.give);
|
|
10955
|
-
},
|
|
10956
|
-
lift() {
|
|
10957
|
-
if (!panned)
|
|
10958
|
-
return;
|
|
10959
|
-
let n = carrySteps(recent.speed()), dir = Math.sign(recent.speed());
|
|
10960
|
-
letGo();
|
|
10961
|
-
for (let i = 0;i < n; i++)
|
|
10962
|
-
carry.push(setTimeout(() => {
|
|
10963
|
-
if (!scrubBy(dir))
|
|
10964
|
-
stopCarry();
|
|
10965
|
-
}, carryAt(i)));
|
|
10966
|
-
},
|
|
10967
|
-
end: letGo,
|
|
10968
|
-
step(direction) {
|
|
10969
|
-
stopCarry(), set(value + direction);
|
|
10970
|
-
}
|
|
10971
|
-
}), control.addEventListener("click", () => {
|
|
10972
|
-
if (!editor.open)
|
|
10973
|
-
editor.start(mixed ? "" : String(value));
|
|
10974
|
-
}), control.addEventListener("keydown", (event) => {
|
|
10975
|
-
if (event.target !== control || !plainKey(event))
|
|
10976
|
-
return;
|
|
10977
|
-
let dir = arrowOf(event), char = typed(event);
|
|
10978
|
-
if (dir)
|
|
10979
|
-
event.preventDefault(), event.stopPropagation(), set(value + dir * bigOf(event));
|
|
10980
|
-
else if (event.key === " ")
|
|
10981
|
-
event.preventDefault(), event.stopPropagation(), reroll();
|
|
10982
|
-
else if (event.key === "Enter" && keyPrefs(control).edit)
|
|
10983
|
-
event.preventDefault(), event.stopPropagation(), editor.start(mixed ? "" : String(value));
|
|
10984
|
-
else if (char && keyPrefs(control).edit)
|
|
10985
|
-
event.preventDefault(), event.stopPropagation(), editor.start(char, !1);
|
|
10986
|
-
});
|
|
10987
|
-
let paint = (previous, instant) => {
|
|
10988
|
-
read.toggleAttribute("data-mixed", mixed), control.setAttribute("aria-valuenow", String(value));
|
|
10989
|
-
let ms = !initialized || instant ? 0 : diced ? DICE_ROLL_MS : rollMs(row);
|
|
10990
|
-
initialized = !0, syncPlaces(places, String(value), diced ? 1 : Math.sign(value - previous), ms, 0);
|
|
10991
|
-
let dom = ms > 0 && row.closest('[data-gpu-active="true"]') === null;
|
|
10992
|
-
if (roller.update({
|
|
10993
|
-
value,
|
|
10994
|
-
animated: !0,
|
|
10995
|
-
duration: dom ? ms : 1,
|
|
10996
|
-
motionBlur: dom,
|
|
10997
|
-
direction: diced ? "up" : "auto"
|
|
10998
|
-
}), ms > 0)
|
|
10999
|
-
c.wake();
|
|
11000
|
-
}, gpu = {
|
|
11001
|
-
kind: "seed",
|
|
11002
|
-
key: c.key,
|
|
11003
|
-
display: c.display,
|
|
11004
|
-
row,
|
|
11005
|
-
labelEl: label,
|
|
11006
|
-
control,
|
|
11007
|
-
read,
|
|
11008
|
-
places,
|
|
11009
|
-
mixed: () => mixed,
|
|
11010
|
-
die: { button: roll, die },
|
|
11011
|
-
editing: () => editor.open,
|
|
11012
|
-
wave: c.wave,
|
|
11013
|
-
isModified: c.isModified
|
|
11014
|
-
};
|
|
11015
|
-
return {
|
|
11016
|
-
row,
|
|
11017
|
-
labelEl: label,
|
|
11018
|
-
input: control,
|
|
11019
|
-
stops: () => [control],
|
|
11020
|
-
update(next, _delay, instant, isMixed = !1) {
|
|
11021
|
-
let previous = value;
|
|
11022
|
-
value = next, mixed = isMixed, paint(previous, Boolean(instant));
|
|
11023
|
-
},
|
|
11024
|
-
dispose: () => {
|
|
11025
|
-
stopCarry(), die.dispose(), roller.destroy();
|
|
11026
|
-
},
|
|
11027
|
-
tracks: [],
|
|
11028
|
-
gpu: [gpu]
|
|
11029
|
-
};
|
|
11030
|
-
}
|
|
11031
|
-
var CAP_MORPH = springLinear(SPRINGS2.snappy);
|
|
11032
|
-
function keyCap(o) {
|
|
11033
|
-
let chip = o.doc.createElement("button");
|
|
11034
|
-
chip.className = "knobs-keys", chip.type = "button";
|
|
11035
|
-
let text = o.doc.createElement("span");
|
|
11036
|
-
text.className = "knobs-keys-text", chip.append(text);
|
|
11037
|
-
let value = "", capturing = !1, preview = "", morph, write = (shown) => {
|
|
11038
|
-
let glide = chip.isConnected && chip.offsetWidth > 0 && !chip.closest('[data-gpu-active="true"]') && !reducedMotion4(o.doc), from = glide ? chip.getBoundingClientRect().width : 0;
|
|
11039
|
-
if (morph?.cancel(), text.textContent = shown, !glide)
|
|
11040
|
-
return;
|
|
11041
|
-
let to = chip.getBoundingClientRect().width;
|
|
11042
|
-
if (text.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 150, easing: "ease-out" }), Math.abs(to - from) < 0.5)
|
|
11043
|
-
return;
|
|
11044
|
-
chip.dataset.morph = "", morph = chip.animate([{ width: `${from}px` }, { width: `${to}px` }], {
|
|
11045
|
-
duration: CAP_MORPH.ms,
|
|
11046
|
-
easing: CAP_MORPH.easing
|
|
11047
|
-
}), morph.onfinish = () => delete chip.dataset.morph, morph.oncancel = () => delete chip.dataset.morph;
|
|
11048
|
-
}, paint = () => {
|
|
11049
|
-
let shown = capturing ? preview || "Type keys…" : value === void 0 ? "—" : value ? comboLabel2(value) : o.empty;
|
|
11050
|
-
if (text.textContent !== shown)
|
|
11051
|
-
write(shown);
|
|
11052
|
-
chip.toggleAttribute("data-empty", !capturing && value === ""), chip.setAttribute("aria-pressed", String(capturing)), chip.setAttribute("aria-label", `${o.name()}: ${capturing ? "press a key combination" : value ? comboLabel2(value) : "none"}`), o.wake();
|
|
11053
|
-
}, capture = (on) => {
|
|
11054
|
-
if (capturing === on)
|
|
11055
|
-
return;
|
|
11056
|
-
if (on && o.row.closest("[data-disabled],[data-readonly]"))
|
|
11057
|
-
return;
|
|
11058
|
-
capturing = on, preview = "", o.row.classList.toggle("knobs-active", on), paint();
|
|
11059
|
-
}, held = (event) => {
|
|
11060
|
-
let mods = heldMods(event);
|
|
11061
|
-
preview = mods.length ? comboLabel2(`${mods.join("+")}+…`) : "", paint();
|
|
11062
|
-
};
|
|
11063
|
-
return chip.onclick = () => capture(!capturing), chip.addEventListener("keydown", (event) => {
|
|
11064
|
-
if (event.isComposing)
|
|
11065
|
-
return;
|
|
11066
|
-
if (!capturing) {
|
|
11067
|
-
if ((event.key === "Enter" || event.key === " ") && plainKey(event) && !event.altKey)
|
|
11068
|
-
event.preventDefault(), event.stopPropagation(), capture(!0);
|
|
11069
|
-
return;
|
|
11070
|
-
}
|
|
11071
|
-
if (event.key === "Tab")
|
|
11072
|
-
return capture(!1);
|
|
11073
|
-
event.preventDefault(), event.stopPropagation();
|
|
11074
|
-
let mods = heldMods(event);
|
|
11075
|
-
if (event.key === "Escape" && !mods.length)
|
|
11076
|
-
return capture(!1);
|
|
11077
|
-
let take = (combo) => {
|
|
11078
|
-
value = combo, capture(!1), o.set(combo);
|
|
11079
|
-
};
|
|
11080
|
-
if ((event.key === "Backspace" || event.key === "Delete") && !mods.length)
|
|
11081
|
-
return take("");
|
|
11082
|
-
let combo = comboFromEvent2(event);
|
|
11083
|
-
if (!combo)
|
|
11084
|
-
return held(event);
|
|
11085
|
-
take(combo);
|
|
11086
|
-
}), chip.addEventListener("keyup", (event) => {
|
|
11087
|
-
if (capturing)
|
|
11088
|
-
held(event);
|
|
11089
|
-
}), chip.addEventListener("blur", () => capture(!1)), paint(), {
|
|
11090
|
-
chip,
|
|
11091
|
-
text,
|
|
11092
|
-
capturing: () => capturing,
|
|
11093
|
-
show(combo) {
|
|
11094
|
-
value = combo, paint();
|
|
11095
|
-
}
|
|
11096
|
-
};
|
|
11097
|
-
}
|
|
11098
|
-
function keybindRow(c) {
|
|
11099
|
-
let { row, label } = shell(c, "keybind"), cap = keyCap({
|
|
11100
|
-
doc: c.doc,
|
|
11101
|
-
row,
|
|
11102
|
-
empty: "None",
|
|
11103
|
-
name: () => c.display,
|
|
11104
|
-
set: (combo) => c.set(combo),
|
|
11105
|
-
wake: c.wake
|
|
11106
|
-
}), { chip, text } = cap;
|
|
11107
|
-
row.append(chip), cap.show(c.get());
|
|
11108
|
-
let gpu = {
|
|
11109
|
-
kind: "keybind",
|
|
11110
|
-
key: c.key,
|
|
11111
|
-
display: c.display,
|
|
11112
|
-
row,
|
|
11113
|
-
labelEl: label,
|
|
11114
|
-
chip,
|
|
11115
|
-
text,
|
|
11116
|
-
capturing: cap.capturing,
|
|
11117
|
-
wave: c.wave,
|
|
11118
|
-
isModified: c.isModified
|
|
11119
|
-
};
|
|
11120
|
-
return {
|
|
11121
|
-
row,
|
|
11122
|
-
labelEl: label,
|
|
11123
|
-
input: chip,
|
|
11124
|
-
stops: () => [chip],
|
|
11125
|
-
update(next, _delay, _instant, isMixed = !1) {
|
|
11126
|
-
cap.show(isMixed ? void 0 : next);
|
|
11127
|
-
},
|
|
11128
|
-
dispose() {},
|
|
11129
|
-
tracks: [],
|
|
11130
|
-
gpu: [gpu]
|
|
11131
|
-
};
|
|
11132
|
-
}
|
|
11133
|
-
function naturalWidth(b) {
|
|
11134
|
-
let cs = getComputedStyle(b), w = (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0), parts = [...b.children];
|
|
11135
|
-
for (let part of parts) {
|
|
11136
|
-
let ps = getComputedStyle(part), margin = parseFloat(ps.marginRight) || 0;
|
|
11137
|
-
w += part instanceof HTMLElement ? part.scrollWidth + margin : parseFloat(ps.width) || 0;
|
|
11138
|
-
}
|
|
11139
|
-
return Math.ceil(w + (parseFloat(cs.columnGap) || 0) * Math.max(0, parts.length - 1));
|
|
11140
|
-
}
|
|
11141
|
-
function toolbarRow(c, press, keyOf = toolbarShortcut2) {
|
|
11142
|
-
let el = make(c.doc), row = el("div", "knobs-row knobs-toolbar");
|
|
11143
|
-
row.dataset.field = c.key, row.setAttribute("role", "toolbar"), row.setAttribute("aria-label", c.display);
|
|
11144
|
-
let field = c.field, buttons = [], last = 0, keys = "", keysNow = () => field.items.map((item) => keyOf(item)?.key ?? "").join("\x00"), layout = () => {
|
|
11145
|
-
let cs = getComputedStyle(row), avail = row.clientWidth - (parseFloat(cs.paddingLeft) || 0) - (parseFloat(cs.paddingRight) || 0);
|
|
11146
|
-
if (avail <= 0 || !buttons.length)
|
|
11147
|
-
return;
|
|
11148
|
-
let widest = Math.max(...buttons.map(naturalWidth)), cols = String(toolbarColumns(buttons.length, widest, avail, parseFloat(cs.columnGap) || 0));
|
|
11149
|
-
if (row.style.getPropertyValue("--k-tool-cols") !== cols)
|
|
11150
|
-
row.style.setProperty("--k-tool-cols", cols), c.wake();
|
|
11151
|
-
}, sizes = new ResizeObserver(layout);
|
|
11152
|
-
sizes.observe(row), c.doc.fonts?.ready.then(() => row.isConnected && layout());
|
|
11153
|
-
let gpu = {
|
|
11154
|
-
kind: "toolbar",
|
|
11155
|
-
key: c.key,
|
|
11156
|
-
display: c.display,
|
|
11157
|
-
row,
|
|
11158
|
-
items: [],
|
|
11159
|
-
wave: c.wave,
|
|
11160
|
-
isModified: () => !1
|
|
11161
|
-
}, build = () => {
|
|
11162
|
-
let items = [];
|
|
11163
|
-
if (buttons = field.items.map((item, i) => {
|
|
11164
|
-
let b = el("button", "knobs-tool");
|
|
11165
|
-
b.type = "button", b.tabIndex = -1, b.disabled = Boolean(item.disabled), b.dataset.item = item.id ?? item.label;
|
|
11166
|
-
let iconEl;
|
|
11167
|
-
if (item.icon)
|
|
11168
|
-
iconEl = iconSvg(c.doc, item.icon), b.append(iconEl);
|
|
11169
|
-
let name = el("span", "knobs-tool-label", item.label);
|
|
11170
|
-
b.append(name);
|
|
11171
|
-
let chip, key = keyOf(item);
|
|
11172
|
-
if (key) {
|
|
11173
|
-
if (chip = el("kbd", "knobs-tool-key", comboLabel2(key.key)), b.append(chip), key.scope !== "none")
|
|
11174
|
-
b.setAttribute("aria-keyshortcuts", key.key);
|
|
11175
|
-
}
|
|
11176
|
-
return b.onclick = () => {
|
|
11177
|
-
last = i, press(item);
|
|
11178
|
-
}, b.addEventListener("focus", () => last = i), items.push({
|
|
11179
|
-
button: b,
|
|
11180
|
-
...item.icon ? { icon: item.icon } : {},
|
|
11181
|
-
...iconEl ? { iconEl } : {},
|
|
11182
|
-
label: name,
|
|
11183
|
-
...chip ? { chip } : {}
|
|
11184
|
-
}), b;
|
|
11185
|
-
}), row.replaceChildren(...buttons), gpu.items = items, keys = keysNow(), row.isConnected)
|
|
11186
|
-
layout();
|
|
11187
|
-
};
|
|
11188
|
-
build(), row.addEventListener("keydown", (event) => {
|
|
11189
|
-
let at = buttons.indexOf(event.target), dir = arrowOf(event);
|
|
11190
|
-
if (at < 0 || !dir || !plainKey(event))
|
|
11191
|
-
return;
|
|
11192
|
-
event.preventDefault(), event.stopPropagation();
|
|
11193
|
-
let live = buttons.filter((b) => !b.disabled), i = live.indexOf(buttons[at]);
|
|
11194
|
-
live[(i + dir + live.length) % live.length]?.focus();
|
|
11195
|
-
});
|
|
11196
|
-
let first = () => buttons.find((b) => !b.disabled) ?? buttons[0];
|
|
11197
|
-
return {
|
|
11198
|
-
row,
|
|
11199
|
-
labelEl: row,
|
|
11200
|
-
get input() {
|
|
11201
|
-
let b = buttons[last];
|
|
11202
|
-
return b && !b.disabled ? b : first();
|
|
11203
|
-
},
|
|
11204
|
-
get field() {
|
|
11205
|
-
return field;
|
|
11206
|
-
},
|
|
11207
|
-
stops() {
|
|
11208
|
-
let b = buttons[last];
|
|
11209
|
-
return [b && !b.disabled ? b : first()];
|
|
11210
|
-
},
|
|
11211
|
-
update() {},
|
|
11212
|
-
refresh() {
|
|
11213
|
-
if (keysNow() === keys)
|
|
11214
|
-
return;
|
|
11215
|
-
let focused = buttons.indexOf(c.doc.activeElement);
|
|
11216
|
-
if (build(), focused >= 0)
|
|
11217
|
-
buttons[focused]?.focus({ preventScroll: !0 });
|
|
11218
|
-
c.wake();
|
|
11219
|
-
},
|
|
11220
|
-
match(event, global) {
|
|
11221
|
-
return field.items.find((item) => {
|
|
11222
|
-
let key = keyOf(item);
|
|
11223
|
-
return key !== void 0 && !item.disabled && key.scope === (global ? "page" : "panel") && matchesCombo2(key.key, event);
|
|
11224
|
-
});
|
|
11225
|
-
},
|
|
11226
|
-
press(item) {
|
|
11227
|
-
let i = field.items.indexOf(item), b = buttons[i];
|
|
11228
|
-
if (b && !reducedMotion4(c.doc))
|
|
11229
|
-
b.classList.add("knobs-pressed"), setTimeout(() => b.classList.remove("knobs-pressed"), 140), c.wake();
|
|
11230
|
-
press(item);
|
|
11231
|
-
},
|
|
11232
|
-
swap(next) {
|
|
11233
|
-
field = next, build(), c.wake();
|
|
11234
|
-
},
|
|
11235
|
-
dispose() {
|
|
11236
|
-
sizes.disconnect();
|
|
11237
|
-
},
|
|
11238
|
-
tracks: [],
|
|
11239
|
-
gpu: [gpu]
|
|
11240
|
-
};
|
|
11241
|
-
}
|
|
11242
|
-
|
|
11243
|
-
// src/panel/search.ts
|
|
11244
|
-
function createSearch(doc, options) {
|
|
11245
|
-
let element = doc.createElement("div");
|
|
11246
|
-
element.className = "knobs-search";
|
|
11247
|
-
let field = doc.createElement("label");
|
|
11248
|
-
field.className = "knobs-search-field", field.append(iconSvg(doc, "search"));
|
|
11249
|
-
let input = doc.createElement("input");
|
|
11250
|
-
input.type = "search", input.placeholder = options.placeholder, input.spellcheck = !1, input.autocomplete = "off", input.setAttribute("aria-label", "Search controls"), input.setAttribute("aria-keyshortcuts", "/"), field.append(input), element.append(field);
|
|
11251
|
-
let on = /* @__PURE__ */ new Set, chips = options.chips.map((spec) => {
|
|
11252
|
-
let b = doc.createElement("button");
|
|
11253
|
-
b.type = "button", b.className = "knobs-search-chip", b.tabIndex = -1, b.dataset.chip = spec.id, b.setAttribute("aria-pressed", "false");
|
|
11254
|
-
let name = doc.createElement("span");
|
|
11255
|
-
if (name.textContent = spec.label, b.append(name), spec.count) {
|
|
11256
|
-
let n = doc.createElement("span");
|
|
11257
|
-
n.className = "knobs-search-count", b.append(n);
|
|
11258
|
-
}
|
|
11259
|
-
return b.onclick = () => {
|
|
11260
|
-
if (on.has(spec.id))
|
|
11261
|
-
on.delete(spec.id);
|
|
11262
|
-
else
|
|
11263
|
-
on.add(spec.id);
|
|
11264
|
-
b.setAttribute("aria-pressed", String(on.has(spec.id))), options.change();
|
|
11265
|
-
}, element.append(b), b;
|
|
11266
|
-
});
|
|
11267
|
-
return input.addEventListener("input", () => options.change()), {
|
|
11268
|
-
element,
|
|
11269
|
-
input,
|
|
11270
|
-
chips,
|
|
11271
|
-
query: () => input.value.trim().toLowerCase(),
|
|
11272
|
-
active: () => on,
|
|
11273
|
-
filtering: () => input.value.trim() !== "" || on.size > 0,
|
|
11274
|
-
counts(counts) {
|
|
11275
|
-
for (let b of chips) {
|
|
11276
|
-
let n = b.querySelector(".knobs-search-count");
|
|
11277
|
-
if (!n)
|
|
11278
|
-
continue;
|
|
11279
|
-
let text = String(counts.get(b.dataset.chip) ?? 0);
|
|
11280
|
-
if (n.textContent !== text)
|
|
11281
|
-
n.textContent = text;
|
|
11282
|
-
let none = text === "0" && !on.has(b.dataset.chip);
|
|
11283
|
-
if (b.hasAttribute("data-none") !== none)
|
|
11284
|
-
b.toggleAttribute("data-none", none);
|
|
11285
|
-
}
|
|
11286
|
-
},
|
|
11287
|
-
set(query, next) {
|
|
11288
|
-
let changed = !1;
|
|
11289
|
-
if (query !== void 0 && input.value !== query)
|
|
11290
|
-
input.value = query, changed = !0;
|
|
11291
|
-
if (next) {
|
|
11292
|
-
let want = new Set(next.filter((id) => chips.some((b) => b.dataset.chip === id)));
|
|
11293
|
-
if (want.size !== on.size || [...want].some((id) => !on.has(id))) {
|
|
11294
|
-
on.clear();
|
|
11295
|
-
for (let id of want)
|
|
11296
|
-
on.add(id);
|
|
11297
|
-
for (let b of chips)
|
|
11298
|
-
b.setAttribute("aria-pressed", String(on.has(b.dataset.chip)));
|
|
11299
|
-
changed = !0;
|
|
11300
|
-
}
|
|
11301
|
-
}
|
|
11302
|
-
if (changed)
|
|
11303
|
-
options.change();
|
|
11304
|
-
},
|
|
11305
|
-
clear() {
|
|
11306
|
-
let had = input.value !== "" || on.size > 0;
|
|
11307
|
-
input.value = "", on.clear();
|
|
11308
|
-
for (let b of chips)
|
|
11309
|
-
b.setAttribute("aria-pressed", "false");
|
|
11310
|
-
if (had)
|
|
11311
|
-
options.change();
|
|
11312
|
-
},
|
|
11313
|
-
focus() {
|
|
11314
|
-
input.focus({ preventScroll: !0 }), input.select();
|
|
11315
|
-
}
|
|
11316
|
-
};
|
|
11317
|
-
}
|
|
11318
|
-
function matchSpan(text, query) {
|
|
11319
|
-
if (!query)
|
|
11320
|
-
return;
|
|
11321
|
-
let at = text.toLowerCase().indexOf(query);
|
|
11322
|
-
return at < 0 ? void 0 : [at, at + query.length];
|
|
11323
|
-
}
|
|
11324
|
-
function markLabel(label, text, span) {
|
|
11325
|
-
let doc = label.ownerDocument, parts = [];
|
|
11326
|
-
if (!span)
|
|
11327
|
-
parts.push(doc.createTextNode(text));
|
|
11328
|
-
else {
|
|
11329
|
-
if (span[0] > 0)
|
|
11330
|
-
parts.push(doc.createTextNode(text.slice(0, span[0])));
|
|
11331
|
-
let mark = doc.createElement("mark");
|
|
11332
|
-
if (mark.className = "knobs-match", mark.textContent = text.slice(span[0], span[1]), parts.push(mark), span[1] < text.length)
|
|
11333
|
-
parts.push(doc.createTextNode(text.slice(span[1])));
|
|
11334
|
-
}
|
|
11335
|
-
let current = [...label.childNodes].filter((c) => c.nodeType === 3 || c instanceof HTMLElement && c.classList.contains("knobs-match"));
|
|
11336
|
-
if (current.length === parts.length && current.every((c, i) => c.nodeName === parts[i].nodeName && c.textContent === parts[i].textContent))
|
|
11337
|
-
return;
|
|
11338
|
-
for (let c of current)
|
|
11339
|
-
c.remove();
|
|
11340
|
-
label.prepend(...parts);
|
|
11341
|
-
}
|
|
11342
|
-
|
|
11343
10427
|
// src/ui/activity-css.ts
|
|
11344
10428
|
var open = springLinear(SPRINGS2.snappy), activityCss = `
|
|
11345
10429
|
:where(.knobs-activity,.knobs-activity *){box-sizing:border-box}
|
|
@@ -12014,13 +11098,17 @@ var css = `
|
|
|
12014
11098
|
.knobs-tree-row[aria-expanded="true"]>.knobs-tree-caret{transform:rotate(90deg)}
|
|
12015
11099
|
.knobs-tree-row:not([aria-expanded])>.knobs-tree-caret{visibility:hidden}
|
|
12016
11100
|
.knobs-tree-icon{flex:none;display:flex;align-items:center;justify-content:center;width:14px;margin-right:6px;color:var(--_k-fg-3);font-size:calc(var(--_k-font-size) - 1px)}
|
|
12017
|
-
|
|
11101
|
+
/* The label wins the room: it keeps its width while the detail (which only takes what's left)
|
|
11102
|
+
fades out at its end, and gives way only once the detail is gone. Each fades where it's cut. */
|
|
11103
|
+
.knobs-tree-label{position:relative;flex:0 1 auto;min-width:0;overflow:hidden;font-weight:var(--_k-weight)}
|
|
11104
|
+
.knobs-tree-row[data-editing]>.knobs-tree-label{flex-grow:1}
|
|
12018
11105
|
.knobs-tree-row[data-ancestor] .knobs-tree-label{color:var(--_k-fg-2)}
|
|
12019
11106
|
.knobs-tree-label .knobs-tree-mark{color:var(--_k-accent)}
|
|
12020
11107
|
.knobs-tree-row[data-off~="visible"] :is(.knobs-tree-label,.knobs-tree-icon){opacity:.45}
|
|
12021
11108
|
.knobs-tree-row[data-off~="locked"] .knobs-tree-label{color:var(--_k-fg-2)}
|
|
12022
|
-
.knobs-tree-detail{flex:
|
|
12023
|
-
.knobs-tree-
|
|
11109
|
+
.knobs-tree-detail{flex:1 1 0;min-width:0;overflow:hidden;padding-left:6px;text-align:right;color:var(--_k-fg-3);font-variant-numeric:tabular-nums}
|
|
11110
|
+
.knobs-tree-row[data-editing]>.knobs-tree-detail{flex-grow:0;visibility:hidden}
|
|
11111
|
+
.knobs-tree-tools{flex:none;display:flex;align-items:center;gap:1px;margin-left:auto;padding-left:4px}
|
|
12024
11112
|
.knobs-ui .knobs-tree-toggle{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:calc(var(--_k-radius) * 999);color:var(--_k-fg-3);cursor:pointer;opacity:0;transition:opacity .12s,color .12s,background .12s}
|
|
12025
11113
|
.knobs-ui .knobs-tree-toggle svg{width:12px;height:12px}
|
|
12026
11114
|
.knobs-tree-row:is(:hover,[data-active],[aria-selected="true"]) .knobs-tree-toggle,.knobs-ui .knobs-tree-toggle[aria-pressed="false"]{opacity:1}
|
|
@@ -12137,47 +11225,1277 @@ function injectUiStyles(doc) {
|
|
|
12137
11225
|
let style = doc.createElement("style");
|
|
12138
11226
|
style.dataset.knobsUi = "", style.textContent = uiCss(), doc.head.append(style);
|
|
12139
11227
|
}
|
|
12140
|
-
function applyLook2(root, look) {
|
|
12141
|
-
injectUiStyles(root.ownerDocument), root.classList.add("knobs-root", "knobs-ui"), applyLook(root, resolveLook(look)), syncFrame(root);
|
|
11228
|
+
function applyLook2(root, look) {
|
|
11229
|
+
injectUiStyles(root.ownerDocument), root.classList.add("knobs-root", "knobs-ui"), applyLook(root, resolveLook(look)), syncFrame(root);
|
|
11230
|
+
}
|
|
11231
|
+
function syncFrame(root) {
|
|
11232
|
+
if (!root.isConnected)
|
|
11233
|
+
return;
|
|
11234
|
+
if (root.ownerDocument.defaultView?.getComputedStyle(root).getPropertyValue("--k-frame").trim() === "flat")
|
|
11235
|
+
root.dataset.frame = "flat";
|
|
11236
|
+
else
|
|
11237
|
+
delete root.dataset.frame;
|
|
11238
|
+
}
|
|
11239
|
+
var lookDefaults = { current: {} };
|
|
11240
|
+
function frameLoop(win, step) {
|
|
11241
|
+
let raf = 0, last = 0, tick = (now) => {
|
|
11242
|
+
let dt = last ? Math.min(0.064, (now - last) / 1000) : 0.016666666666666666;
|
|
11243
|
+
if (last = now, raf = step(dt) ? win.requestAnimationFrame(tick) : 0, !raf)
|
|
11244
|
+
last = 0;
|
|
11245
|
+
};
|
|
11246
|
+
return {
|
|
11247
|
+
wake() {
|
|
11248
|
+
if (!raf)
|
|
11249
|
+
raf = win.requestAnimationFrame(tick);
|
|
11250
|
+
},
|
|
11251
|
+
get running() {
|
|
11252
|
+
return raf !== 0;
|
|
11253
|
+
},
|
|
11254
|
+
stop() {
|
|
11255
|
+
if (raf)
|
|
11256
|
+
win.cancelAnimationFrame(raf);
|
|
11257
|
+
raf = 0, last = 0;
|
|
11258
|
+
}
|
|
11259
|
+
};
|
|
11260
|
+
}
|
|
11261
|
+
var svg = (body, box = 16) => `<svg viewBox="0 0 ${box} ${box}" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">${body}</svg>`, ICONS = {
|
|
11262
|
+
caret: svg('<path d="M6 3.5 10.5 8 6 12.5"/>'),
|
|
11263
|
+
chevronDown: svg('<path d="M3.5 6 8 10.5 12.5 6"/>'),
|
|
11264
|
+
eye: svg('<path d="M1.5 8s2.4-4.5 6.5-4.5S14.5 8 14.5 8 12.1 12.5 8 12.5 1.5 8 1.5 8Z"/><circle cx="8" cy="8" r="2"/>'),
|
|
11265
|
+
eyeOff: svg('<path d="M2.5 2.5l11 11M6.6 4.2A6.6 6.6 0 0 1 8 3.5c4.1 0 6.5 4.5 6.5 4.5a11 11 0 0 1-1.7 2.2M10.2 11.9A6 6 0 0 1 8 12.5C3.9 12.5 1.5 8 1.5 8a11 11 0 0 1 2.4-2.9"/>'),
|
|
11266
|
+
lock: svg('<rect x="3.5" y="7" width="9" height="6.5" rx="1.2"/><path d="M5.5 7V5a2.5 2.5 0 0 1 5 0v2"/>'),
|
|
11267
|
+
unlock: svg('<rect x="3.5" y="7" width="9" height="6.5" rx="1.2"/><path d="M5.5 7V5a2.5 2.5 0 0 1 4.8-1"/>')
|
|
11268
|
+
};
|
|
11269
|
+
|
|
11270
|
+
// src/ui/layer.ts
|
|
11271
|
+
var lookOf = (look) => ({ ...lookDefaults.current, ...look }), roots = /* @__PURE__ */ new WeakMap;
|
|
11272
|
+
function layerRoot(doc) {
|
|
11273
|
+
let root = roots.get(doc);
|
|
11274
|
+
if (root?.isConnected)
|
|
11275
|
+
return root;
|
|
11276
|
+
return root = doc.createElement("div"), root.className = "knobs-layers", doc.body.append(root), roots.set(doc, root), root;
|
|
11277
|
+
}
|
|
11278
|
+
function layerElement(doc, cls, look) {
|
|
11279
|
+
let el = doc.createElement("div");
|
|
11280
|
+
return el.className = cls, layerRoot(doc).append(el), applyLook2(el, lookOf(look)), el;
|
|
11281
|
+
}
|
|
11282
|
+
function presence(el, o = {}) {
|
|
11283
|
+
let win = el.ownerDocument.defaultView, spring = new Spring(0, 1, 1, 0.002), dx = o.dx ?? 0, dy = o.dy ?? 0, gone = [], shown = !1, render = () => {
|
|
11284
|
+
let reduced = reducedMotion(win), p = spring.x, q = Math.max(0, Math.min(1, p)), scale = reduced ? 1 : (o.scale ?? 0.94) + (1 - (o.scale ?? 0.94)) * p, blur = reduced ? 0 : (1 - q) * (o.blur ?? 6), t = reduced ? 0 : 1 - p;
|
|
11285
|
+
el.style.opacity = q.toFixed(3), el.style.transform = p === 1 ? "" : `translate(${(dx * t).toFixed(2)}px,${(dy * t).toFixed(2)}px) scale(${scale.toFixed(4)})`, el.style.filter = blur > 0.05 ? `blur(${blur.toFixed(2)}px)` : "", el.style.pointerEvents = shown ? "" : "none", o.onFrame?.(p);
|
|
11286
|
+
}, loop = frameLoop(win, (dt) => {
|
|
11287
|
+
if (spring.step(dt), render(), !spring.resting)
|
|
11288
|
+
return !0;
|
|
11289
|
+
if (!shown) {
|
|
11290
|
+
let done = gone;
|
|
11291
|
+
gone = [];
|
|
11292
|
+
for (let f of done)
|
|
11293
|
+
f();
|
|
11294
|
+
o.onGone?.();
|
|
11295
|
+
}
|
|
11296
|
+
return !1;
|
|
11297
|
+
}), tune = (seconds, zeta) => {
|
|
11298
|
+
let reduced = reducedMotion(win);
|
|
11299
|
+
spring.omega = 2 * Math.PI / (reduced ? FADE.duration : seconds), spring.zeta = reduced ? 1 : zeta;
|
|
11300
|
+
};
|
|
11301
|
+
return render(), {
|
|
11302
|
+
show() {
|
|
11303
|
+
shown = !0, gone = [], el.style.pointerEvents = "", tune(o.duration ?? 0.32, 1 - (o.bounce ?? 0.2)), spring.set(1), loop.wake();
|
|
11304
|
+
},
|
|
11305
|
+
hide() {
|
|
11306
|
+
return shown = !1, el.style.pointerEvents = "none", tune(o.exit ?? 0.2, 1), spring.set(0), loop.wake(), new Promise((resolve) => gone.push(resolve));
|
|
11307
|
+
},
|
|
11308
|
+
snap(to = 1) {
|
|
11309
|
+
if (shown = to === 1, spring.snap(to), loop.stop(), render(), !shown) {
|
|
11310
|
+
let done = gone;
|
|
11311
|
+
gone = [];
|
|
11312
|
+
for (let f of done)
|
|
11313
|
+
f();
|
|
11314
|
+
o.onGone?.();
|
|
11315
|
+
} else
|
|
11316
|
+
gone = [];
|
|
11317
|
+
},
|
|
11318
|
+
get shown() {
|
|
11319
|
+
return shown;
|
|
11320
|
+
},
|
|
11321
|
+
from(x, y) {
|
|
11322
|
+
dx = x, dy = y;
|
|
11323
|
+
},
|
|
11324
|
+
dispose() {
|
|
11325
|
+
loop.stop();
|
|
11326
|
+
for (let f of gone)
|
|
11327
|
+
f();
|
|
11328
|
+
gone = [];
|
|
11329
|
+
}
|
|
11330
|
+
};
|
|
11331
|
+
}
|
|
11332
|
+
var anchorBox = (a) => {
|
|
11333
|
+
if (typeof a.getBoundingClientRect === "function") {
|
|
11334
|
+
let r = a.getBoundingClientRect();
|
|
11335
|
+
return { x: r.left, y: r.top, w: r.width, h: r.height };
|
|
11336
|
+
}
|
|
11337
|
+
let r = a;
|
|
11338
|
+
return { x: r.x, y: r.y, w: r.width ?? 0, h: r.height ?? 0 };
|
|
11339
|
+
}, viewBox = (doc) => ({
|
|
11340
|
+
x: 0,
|
|
11341
|
+
y: 0,
|
|
11342
|
+
w: doc.documentElement.clientWidth,
|
|
11343
|
+
h: doc.documentElement.clientHeight
|
|
11344
|
+
});
|
|
11345
|
+
|
|
11346
|
+
// src/ui/overlay-model.ts
|
|
11347
|
+
var opposite = { top: "bottom", bottom: "top", left: "right", right: "left" };
|
|
11348
|
+
function place2(o) {
|
|
11349
|
+
let { anchor: a, size, view: v } = o, offset = o.offset ?? 6, margin = o.margin ?? 8, [want, align = "center"] = (o.placement ?? "bottom").split("-"), room = (s) => s === "top" ? a.y - v.y : s === "bottom" ? v.y + v.h - (a.y + a.h) : s === "left" ? a.x - v.x : v.x + v.w - (a.x + a.w), need = (s) => (s === "top" || s === "bottom" ? size.h : size.w) + offset + margin, side = want;
|
|
11350
|
+
if (room(want) < need(want) && room(opposite[want]) > room(want))
|
|
11351
|
+
side = opposite[want];
|
|
11352
|
+
let vertical = side === "top" || side === "bottom", x, y;
|
|
11353
|
+
if (vertical)
|
|
11354
|
+
y = side === "bottom" ? a.y + a.h + offset : a.y - offset - size.h, x = align === "start" ? a.x : align === "end" ? a.x + a.w - size.w : a.x + (a.w - size.w) / 2, x = clamp2(x, v.x + margin, v.x + v.w - margin - size.w);
|
|
11355
|
+
else
|
|
11356
|
+
x = side === "right" ? a.x + a.w + offset : a.x - offset - size.w, y = align === "start" ? a.y : align === "end" ? a.y + a.h - size.h : a.y + (a.h - size.h) / 2, y = clamp2(y, v.y + margin, v.y + v.h - margin - size.h);
|
|
11357
|
+
let origin = vertical ? { x: clamp2(a.x + a.w / 2 - x, 0, size.w), y: side === "bottom" ? 0 : size.h } : { x: side === "right" ? 0 : size.w, y: clamp2(a.y + a.h / 2 - y, 0, size.h) };
|
|
11358
|
+
return {
|
|
11359
|
+
x: Math.round(x),
|
|
11360
|
+
y: Math.round(y),
|
|
11361
|
+
placement: align === "center" ? side : `${side}-${align}`,
|
|
11362
|
+
origin
|
|
11363
|
+
};
|
|
11364
|
+
}
|
|
11365
|
+
var clamp2 = (v, lo, hi) => hi < lo ? lo : Math.max(lo, Math.min(hi, v));
|
|
11366
|
+
|
|
11367
|
+
// src/ui/tooltip.ts
|
|
11368
|
+
var tips = /* @__PURE__ */ new WeakMap, HANDOFF_MS = 400, controllers = /* @__PURE__ */ new WeakMap;
|
|
11369
|
+
function tipOf(start) {
|
|
11370
|
+
let node = start instanceof Element ? start : null;
|
|
11371
|
+
while (node) {
|
|
11372
|
+
let own = tips.get(node);
|
|
11373
|
+
if (own)
|
|
11374
|
+
return { el: node, tip: own };
|
|
11375
|
+
let data = node.getAttribute("data-tip");
|
|
11376
|
+
if (data) {
|
|
11377
|
+
let shortcut = node.getAttribute("data-tip-shortcut") ?? void 0, placement = node.getAttribute("data-tip-placement") ?? void 0;
|
|
11378
|
+
return {
|
|
11379
|
+
el: node,
|
|
11380
|
+
tip: {
|
|
11381
|
+
text: data,
|
|
11382
|
+
opts: { ...shortcut ? { shortcut } : {}, ...placement ? { placement } : {} }
|
|
11383
|
+
}
|
|
11384
|
+
};
|
|
11385
|
+
}
|
|
11386
|
+
node = node.parentElement;
|
|
11387
|
+
}
|
|
11388
|
+
return null;
|
|
11389
|
+
}
|
|
11390
|
+
function controllerOf(doc) {
|
|
11391
|
+
let existing = controllers.get(doc);
|
|
11392
|
+
if (existing)
|
|
11393
|
+
return existing;
|
|
11394
|
+
let win = doc.defaultView, layer, motion, text, keys, target = null, pending = null, timer = 0, hiddenAt = -1 / 0, quiet = null, keyboard = !1, build = (look) => {
|
|
11395
|
+
layer = layerElement(doc, "knobs-layer knobs-tooltip", look), layer.id = `knobs-tooltip-${Math.random().toString(36).slice(2, 8)}`, layer.setAttribute("role", "tooltip"), text = doc.createElement("span"), text.className = "knobs-tooltip-text", keys = doc.createElement("span"), keys.className = "knobs-tooltip-keys", layer.append(text, keys), motion = presence(layer, { scale: 0.96, blur: 3, duration: 0.24 });
|
|
11396
|
+
}, show = (el, tip, instant) => {
|
|
11397
|
+
if (!layer?.isConnected)
|
|
11398
|
+
build(tip.opts.look);
|
|
11399
|
+
target?.removeAttribute("aria-describedby"), target = el, text.textContent = typeof tip.text === "function" ? tip.text() : tip.text, keys.replaceChildren(...(tip.opts.shortcut ? comboParts2(tip.opts.shortcut) : []).map((k) => {
|
|
11400
|
+
let kbd = doc.createElement("kbd");
|
|
11401
|
+
return kbd.className = "knobs-kbd", kbd.textContent = k, kbd;
|
|
11402
|
+
})), keys.hidden = !tip.opts.shortcut;
|
|
11403
|
+
let p = place2({
|
|
11404
|
+
anchor: anchorBox(el),
|
|
11405
|
+
size: { w: layer.offsetWidth, h: layer.offsetHeight },
|
|
11406
|
+
view: viewBox(doc),
|
|
11407
|
+
placement: tip.opts.placement ?? "top",
|
|
11408
|
+
offset: 6
|
|
11409
|
+
});
|
|
11410
|
+
layer.style.left = `${p.x}px`, layer.style.top = `${p.y}px`, layer.style.transformOrigin = `${p.origin.x}px ${p.origin.y}px`;
|
|
11411
|
+
let side = p.placement.split("-")[0];
|
|
11412
|
+
if (motion.from(0, side === "top" ? 3 : side === "bottom" ? -3 : 0), el.setAttribute("aria-describedby", layer.id), instant)
|
|
11413
|
+
motion.snap(1);
|
|
11414
|
+
else
|
|
11415
|
+
motion.show();
|
|
11416
|
+
}, hide = (now = !1) => {
|
|
11417
|
+
if (win.clearTimeout(timer), pending = null, !target)
|
|
11418
|
+
return;
|
|
11419
|
+
if (target.removeAttribute("aria-describedby"), target = null, hiddenAt = performance.now(), now)
|
|
11420
|
+
motion?.snap(0);
|
|
11421
|
+
else
|
|
11422
|
+
motion?.hide();
|
|
11423
|
+
}, want = (found) => {
|
|
11424
|
+
if (!found)
|
|
11425
|
+
return hide();
|
|
11426
|
+
if (found.el === target || found.el === pending?.el)
|
|
11427
|
+
return;
|
|
11428
|
+
if (found.el === quiet)
|
|
11429
|
+
return;
|
|
11430
|
+
if (win.clearTimeout(timer), target !== null || performance.now() - hiddenAt < HANDOFF_MS) {
|
|
11431
|
+
pending = null, show(found.el, found.tip, !0);
|
|
11432
|
+
return;
|
|
11433
|
+
}
|
|
11434
|
+
if (target)
|
|
11435
|
+
hide();
|
|
11436
|
+
pending = found, timer = win.setTimeout(() => {
|
|
11437
|
+
if (pending = null, found.el.isConnected)
|
|
11438
|
+
show(found.el, found.tip, !1);
|
|
11439
|
+
}, found.tip.opts.delay ?? 500);
|
|
11440
|
+
};
|
|
11441
|
+
doc.addEventListener("pointerover", (e) => {
|
|
11442
|
+
if (e.pointerType === "touch")
|
|
11443
|
+
return;
|
|
11444
|
+
keyboard = !1, want(tipOf(e.target));
|
|
11445
|
+
}), doc.addEventListener("pointerout", (e) => {
|
|
11446
|
+
let to = e.relatedTarget, from = tipOf(e.target);
|
|
11447
|
+
if (!from)
|
|
11448
|
+
return;
|
|
11449
|
+
if (to && from.el.contains(to))
|
|
11450
|
+
return;
|
|
11451
|
+
if (quiet === from.el)
|
|
11452
|
+
quiet = null;
|
|
11453
|
+
if (!tipOf(to))
|
|
11454
|
+
hide();
|
|
11455
|
+
}), doc.addEventListener("pointerdown", (e) => {
|
|
11456
|
+
let found = tipOf(e.target);
|
|
11457
|
+
if (found)
|
|
11458
|
+
quiet = found.el;
|
|
11459
|
+
hide(!0);
|
|
11460
|
+
}, !0), doc.addEventListener("keydown", (e) => {
|
|
11461
|
+
if (keyboard = !0, e.key === "Escape" && target)
|
|
11462
|
+
hide();
|
|
11463
|
+
}, !0), doc.addEventListener("focusin", (e) => {
|
|
11464
|
+
let found = tipOf(e.target);
|
|
11465
|
+
if (found && keyboard && e.target.matches(":focus-visible"))
|
|
11466
|
+
want(found);
|
|
11467
|
+
}), doc.addEventListener("focusout", (e) => {
|
|
11468
|
+
if (target && target.contains(e.target))
|
|
11469
|
+
hide();
|
|
11470
|
+
}), doc.addEventListener("scroll", () => target && hide(!0), !0);
|
|
11471
|
+
let c = { hide };
|
|
11472
|
+
return controllers.set(doc, c), c;
|
|
11473
|
+
}
|
|
11474
|
+
function tooltip(el, content, options = {}) {
|
|
11475
|
+
let { text, ...rest } = typeof content === "string" || typeof content === "function" ? { text: content } : content;
|
|
11476
|
+
tips.set(el, { text, opts: { ...options, ...rest } });
|
|
11477
|
+
let c = controllerOf(el.ownerDocument), shortcut = rest.shortcut ?? options.shortcut;
|
|
11478
|
+
if (shortcut && !el.hasAttribute("aria-keyshortcuts"))
|
|
11479
|
+
el.setAttribute("aria-keyshortcuts", shortcut);
|
|
11480
|
+
return () => {
|
|
11481
|
+
tips.delete(el), c.hide(!0);
|
|
11482
|
+
};
|
|
11483
|
+
}
|
|
11484
|
+
|
|
11485
|
+
// src/panel/inspector.ts
|
|
11486
|
+
function make(doc) {
|
|
11487
|
+
return (tag, cls, text) => {
|
|
11488
|
+
let node = doc.createElement(tag);
|
|
11489
|
+
if (cls)
|
|
11490
|
+
node.className = cls;
|
|
11491
|
+
if (text !== void 0)
|
|
11492
|
+
node.textContent = text;
|
|
11493
|
+
return node;
|
|
11494
|
+
};
|
|
11495
|
+
}
|
|
11496
|
+
function shell(c, kind) {
|
|
11497
|
+
let el = make(c.doc), row = el("div", "knobs-row knobs-insp");
|
|
11498
|
+
row.dataset.field = c.key, row.dataset.kind = kind;
|
|
11499
|
+
let label = el("span", void 0, c.display);
|
|
11500
|
+
return row.append(label), { row, label, el };
|
|
11501
|
+
}
|
|
11502
|
+
var fmt = (v, places) => (Object.is(v, -0) ? 0 : v).toFixed(places);
|
|
11503
|
+
function inlineEdit(doc, host, label, commit, back) {
|
|
11504
|
+
let input = doc.createElement("input");
|
|
11505
|
+
input.className = "knobs-cell-edit", input.type = "text", input.inputMode = "decimal", input.spellcheck = !1, input.hidden = !0, input.setAttribute("aria-label", label), host.append(input);
|
|
11506
|
+
let open = !1, done = (keep) => {
|
|
11507
|
+
if (!open)
|
|
11508
|
+
return;
|
|
11509
|
+
open = !1;
|
|
11510
|
+
let next = Number(input.value.trim().replace(/[^\d.eE+-]/g, ""));
|
|
11511
|
+
if (input.hidden = !0, host.classList.remove("knobs-editing"), keep && input.value.trim() !== "" && Number.isFinite(next))
|
|
11512
|
+
commit(next);
|
|
11513
|
+
let target = back();
|
|
11514
|
+
if (doc.activeElement === input || doc.activeElement === doc.body)
|
|
11515
|
+
target.focus({ preventScroll: !0 });
|
|
11516
|
+
};
|
|
11517
|
+
return input.addEventListener("keydown", (event) => {
|
|
11518
|
+
if (event.key === "Enter" || event.key === "Escape")
|
|
11519
|
+
event.preventDefault(), event.stopPropagation(), done(event.key === "Enter");
|
|
11520
|
+
else
|
|
11521
|
+
event.stopPropagation();
|
|
11522
|
+
}), input.addEventListener("blur", () => done(!0)), {
|
|
11523
|
+
input,
|
|
11524
|
+
get open() {
|
|
11525
|
+
return open;
|
|
11526
|
+
},
|
|
11527
|
+
start(text, select = !0) {
|
|
11528
|
+
if (open = !0, input.value = text, input.hidden = !1, host.classList.add("knobs-editing"), input.focus({ preventScroll: !0 }), select)
|
|
11529
|
+
input.select();
|
|
11530
|
+
else
|
|
11531
|
+
input.setSelectionRange(text.length, text.length);
|
|
11532
|
+
},
|
|
11533
|
+
done
|
|
11534
|
+
};
|
|
11535
|
+
}
|
|
11536
|
+
var typed = (event) => plainKey(event) && !event.altKey && /^[0-9.\-]$/.test(event.key) ? event.key : void 0;
|
|
11537
|
+
function scrub(target, row, o) {
|
|
11538
|
+
let at, moved = !1, last = 0, carried = 0, rect;
|
|
11539
|
+
target.addEventListener("pointerdown", (event) => {
|
|
11540
|
+
if (event.button !== 0 || event.shiftKey || event.metaKey)
|
|
11541
|
+
return;
|
|
11542
|
+
event.preventDefault(), target.setPointerCapture(event.pointerId), target.focus({ preventScroll: !0, focusVisible: !1 }), at = last = event.clientX, carried = 0, moved = !1;
|
|
11543
|
+
}), target.addEventListener("pointermove", (event) => {
|
|
11544
|
+
if (at === void 0)
|
|
11545
|
+
return;
|
|
11546
|
+
if (!moved && Math.abs(event.clientX - at) < 3)
|
|
11547
|
+
return;
|
|
11548
|
+
if (!moved)
|
|
11549
|
+
moved = !0, last = event.clientX, rect = row.getBoundingClientRect(), row.classList.add("knobs-active"), o.start();
|
|
11550
|
+
let r = rect, rate = precisionRate(offRow(event.clientY, r.top, r.bottom)) * (event.altKey ? 0.1 : 1);
|
|
11551
|
+
carried += (event.clientX - last) * rate, last = event.clientX, o.move(carried, event.altKey, event.shiftKey);
|
|
11552
|
+
});
|
|
11553
|
+
let release = (event) => {
|
|
11554
|
+
if (at === void 0)
|
|
11555
|
+
return;
|
|
11556
|
+
at = void 0, rect = void 0, row.classList.remove("knobs-active"), o.end(moved, event);
|
|
11557
|
+
};
|
|
11558
|
+
return target.addEventListener("pointerup", release), target.addEventListener("pointercancel", release), { scrubbing: () => at !== void 0 && moved };
|
|
11559
|
+
}
|
|
11560
|
+
var rate = (min, max, step) => Math.max(step, (max - min) / 200), onGrid = (v, min, step) => Number((min + Math.round((v - min) / step) * step).toPrecision(12)), AXES = ["x", "y", "z"];
|
|
11561
|
+
function vecRow(c) {
|
|
11562
|
+
let { row, label, el } = shell(c, "vec"), f = () => c.field, places = () => f().decimals ?? decimals(f().step), axes = AXES.slice(0, c.field.axes), cells = el("span", "knobs-cells");
|
|
11563
|
+
if (axes.length > 2)
|
|
11564
|
+
cells.dataset.wide = "";
|
|
11565
|
+
let linked = Boolean(c.field.linked), link;
|
|
11566
|
+
if (c.field.link) {
|
|
11567
|
+
link = el("button", "knobs-link"), link.type = "button", link.tabIndex = -1;
|
|
11568
|
+
let paint = () => {
|
|
11569
|
+
link.replaceChildren(iconSvg(c.doc, linked ? "link" : "unlink")), link.setAttribute("aria-pressed", String(linked)), link.setAttribute("aria-label", linked ? "Unlink axes" : "Link axes");
|
|
11570
|
+
};
|
|
11571
|
+
paint(), link.onclick = () => {
|
|
11572
|
+
linked = !linked, paint(), c.wake();
|
|
11573
|
+
}, row.append(link);
|
|
11574
|
+
}
|
|
11575
|
+
row.append(cells);
|
|
11576
|
+
let shown = c.get(), mixed = !1, g = gesture(c), base = shown, withAxis = (from, axis, v) => {
|
|
11577
|
+
let { min, max, step } = f(), next = clamp(onGrid(v, min, step), min, max);
|
|
11578
|
+
if (!linked)
|
|
11579
|
+
return { ...from, [axis]: next };
|
|
11580
|
+
let was = from[axis] ?? 0, k = Math.abs(was) > 0.000000001 ? next / was : void 0, out = {};
|
|
11581
|
+
for (let a of axes) {
|
|
11582
|
+
let own = from[a] ?? 0;
|
|
11583
|
+
out[a] = a === axis ? next : clamp(Number((k !== void 0 ? own * k : own + (next - was)).toPrecision(12)), min, max);
|
|
11584
|
+
}
|
|
11585
|
+
return out;
|
|
11586
|
+
}, gpuCells = [], reads = [], rolls = [], stops = [];
|
|
11587
|
+
for (let axis of axes) {
|
|
11588
|
+
let cell = el("span", "knobs-cell");
|
|
11589
|
+
cell.tabIndex = 0, cell.dataset.axis = axis, cell.setAttribute("role", "spinbutton");
|
|
11590
|
+
let name = c.field.axisLabels?.[axes.indexOf(axis)] ?? axis;
|
|
11591
|
+
cell.setAttribute("aria-label", `${c.display} ${name}`);
|
|
11592
|
+
let letter = el("i", "knobs-cell-axis", name.toUpperCase());
|
|
11593
|
+
letter.setAttribute("aria-hidden", "true");
|
|
11594
|
+
let read = el("span", "knobs-cell-read");
|
|
11595
|
+
cell.append(letter, read), cells.append(cell), reads.push(read), rolls.push(rollingReadout(read)), stops.push(cell);
|
|
11596
|
+
let editor = inlineEdit(c.doc, cell, `${c.display} ${name} value`, (v) => {
|
|
11597
|
+
g.start(), g.set(withAxis(c.get(), axis, v));
|
|
11598
|
+
}, () => cell), drag = scrub(cell, row, {
|
|
11599
|
+
perPx: () => rate(f().min, f().max, f().step),
|
|
11600
|
+
start() {
|
|
11601
|
+
g.start(), base = c.get();
|
|
11602
|
+
},
|
|
11603
|
+
move(dx, _fine, coarse) {
|
|
11604
|
+
let by = dx * rate(f().min, f().max, f().step) * (coarse ? 10 : 1);
|
|
11605
|
+
g.set(withAxis(base, axis, (base[axis] ?? 0) + by));
|
|
11606
|
+
},
|
|
11607
|
+
end(moved) {
|
|
11608
|
+
if (!moved)
|
|
11609
|
+
editor.start(mixed ? "" : fmt(shown[axis] ?? 0, places()));
|
|
11610
|
+
c.wake();
|
|
11611
|
+
}
|
|
11612
|
+
}), panAt, give = textGive(read, () => c.wake());
|
|
11613
|
+
onPan(cell, {
|
|
11614
|
+
accept: () => !drag.scrubbing() && !editor.open,
|
|
11615
|
+
move(dx) {
|
|
11616
|
+
let perPx = rate(f().min, f().max, f().step);
|
|
11617
|
+
if (panAt === void 0)
|
|
11618
|
+
g.start(), base = c.get(), panAt = { at: 0, give: 0 }, row.classList.add("knobs-active"), cell.setAttribute("data-panned", "");
|
|
11619
|
+
let from = base[axis] ?? 0;
|
|
11620
|
+
if (panAt = band(panAt, dx, (f().min - from) / perPx, (f().max - from) / perPx), g.set(withAxis(base, axis, from + panAt.at * perPx)), panAt.give !== give.give)
|
|
11621
|
+
give.hold(panAt.give);
|
|
11622
|
+
},
|
|
11623
|
+
lift: () => give.release(),
|
|
11624
|
+
end() {
|
|
11625
|
+
panAt = void 0, give.release(), row.classList.remove("knobs-active"), cell.removeAttribute("data-panned"), c.wake();
|
|
11626
|
+
},
|
|
11627
|
+
step(direction) {
|
|
11628
|
+
g.start(), g.set(withAxis(c.get(), axis, (shown[axis] ?? 0) + direction * f().step));
|
|
11629
|
+
}
|
|
11630
|
+
}), cell.addEventListener("keydown", (event) => {
|
|
11631
|
+
if (event.target !== cell || !plainKey(event))
|
|
11632
|
+
return;
|
|
11633
|
+
let dir = arrowOf(event), char = typed(event);
|
|
11634
|
+
if (dir) {
|
|
11635
|
+
event.preventDefault(), event.stopPropagation();
|
|
11636
|
+
let by = f().step * (event.shiftKey ? bigOf(event) : event.altKey ? 0.1 : 1);
|
|
11637
|
+
g.start(), g.set(withAxis(c.get(), axis, (shown[axis] ?? 0) + dir * by));
|
|
11638
|
+
} else if (event.key === "Home" || event.key === "End")
|
|
11639
|
+
event.preventDefault(), g.start(), g.set(withAxis(c.get(), axis, event.key === "Home" ? f().min : f().max));
|
|
11640
|
+
else if (event.key === "Enter" && keyPrefs(cell).edit)
|
|
11641
|
+
event.preventDefault(), event.stopPropagation(), editor.start(mixed ? "" : fmt(shown[axis] ?? 0, places()));
|
|
11642
|
+
else if (char && keyPrefs(cell).edit)
|
|
11643
|
+
event.preventDefault(), event.stopPropagation(), editor.start(char, !1);
|
|
11644
|
+
}), gpuCells.push({
|
|
11645
|
+
el: cell,
|
|
11646
|
+
axis: letter,
|
|
11647
|
+
read,
|
|
11648
|
+
editing: () => editor.open,
|
|
11649
|
+
active: () => drag.scrubbing() || panAt !== void 0
|
|
11650
|
+
});
|
|
11651
|
+
}
|
|
11652
|
+
let paint = (ms = 0, delay = 0) => {
|
|
11653
|
+
axes.forEach((axis, i) => {
|
|
11654
|
+
let text = mixed ? "—" : fmt(shown[axis] ?? 0, places()), unit = f().unit && !mixed ? ` ${f().unit}` : "";
|
|
11655
|
+
rolls[i].show(mixed ? ["—"] : [{ value: shown[axis] ?? 0, decimals: places() }], ms, delay), stops[i].setAttribute("aria-valuetext", `${text}${unit}`);
|
|
11656
|
+
});
|
|
11657
|
+
};
|
|
11658
|
+
paint();
|
|
11659
|
+
let placed = !1, gpu = {
|
|
11660
|
+
kind: "vec",
|
|
11661
|
+
key: c.key,
|
|
11662
|
+
display: c.display,
|
|
11663
|
+
row,
|
|
11664
|
+
labelEl: label,
|
|
11665
|
+
cells: gpuCells,
|
|
11666
|
+
...link ? { link } : {},
|
|
11667
|
+
linked: () => linked,
|
|
11668
|
+
wave: c.wave,
|
|
11669
|
+
isModified: c.isModified
|
|
11670
|
+
};
|
|
11671
|
+
return {
|
|
11672
|
+
row,
|
|
11673
|
+
labelEl: label,
|
|
11674
|
+
input: stops[0],
|
|
11675
|
+
stops: () => stops,
|
|
11676
|
+
update(value, delay, instant, isMixed = !1) {
|
|
11677
|
+
shown = value, mixed = isMixed;
|
|
11678
|
+
let hand = row.classList.contains("knobs-active");
|
|
11679
|
+
paint(!placed || instant || hand ? 0 : rollMs(row), delay), placed = !0;
|
|
11680
|
+
},
|
|
11681
|
+
dispose() {
|
|
11682
|
+
for (let r of rolls)
|
|
11683
|
+
r.dispose();
|
|
11684
|
+
},
|
|
11685
|
+
tracks: [],
|
|
11686
|
+
gpu: [gpu]
|
|
11687
|
+
};
|
|
11688
|
+
}
|
|
11689
|
+
function rangeRow(c) {
|
|
11690
|
+
let el = make(c.doc), f = () => c.field, places = () => f().decimals ?? decimals(f().step), row = el("div", "knobs-row knobs-range");
|
|
11691
|
+
row.dataset.field = c.key;
|
|
11692
|
+
let track = el("div", "knobs-range-track"), fill = el("i", "knobs-range-fill"), label = el("span", "knobs-label", c.display), read = el("span", "knobs-range-read"), thumbs = ["lo", "hi"].map((end) => {
|
|
11693
|
+
let t = el("span", "knobs-range-thumb");
|
|
11694
|
+
return t.dataset.end = end, t.tabIndex = 0, t.setAttribute("role", "slider"), t.setAttribute("aria-label", `${c.display} ${end === "lo" ? "low" : "high"}`), t;
|
|
11695
|
+
}), words = el("span", "knobs-range-text");
|
|
11696
|
+
words.append(label, read);
|
|
11697
|
+
let band2 = el("i", "knobs-range-smear");
|
|
11698
|
+
track.append(fill, band2, ...thumbs, words), row.append(track);
|
|
11699
|
+
let shown = c.get(), mixed = !1, dragging = !1, smearFrame = 0, smearAt = 0, smearStrength = 0, lastEnds = [0, 0], smears = [0, 0], ends = () => {
|
|
11700
|
+
let cs = getComputedStyle(track);
|
|
11701
|
+
return [
|
|
11702
|
+
parseFloat(cs.getPropertyValue("--kr-lo")) || 0,
|
|
11703
|
+
parseFloat(cs.getPropertyValue("--kr-hi")) || 0
|
|
11704
|
+
];
|
|
11705
|
+
}, setSmears = (lo, hi) => {
|
|
11706
|
+
smears[0] = lo === 0 ? 0 : (smears[0] + lo) / 2, smears[1] = hi === 0 ? 0 : (smears[1] + hi) / 2, track.classList.toggle("knobs-range-smearing", smears[0] > 0 || smears[1] > 0), track.style.setProperty("--kr-smear-lo", smears[0].toFixed(2)), track.style.setProperty("--kr-smear-hi", smears[1].toFixed(2));
|
|
11707
|
+
}, runSmear = (now) => {
|
|
11708
|
+
let at = ends(), dt = (now - smearAt) / 1000, w = track.clientWidth, speeds = [0, 1].map((i) => dt > 0 ? Math.abs(at[i] - lastEnds[i]) * w / dt : 0);
|
|
11709
|
+
lastEnds = at, smearAt = now;
|
|
11710
|
+
let gliding = !dragging && track.getAnimations().length > 0;
|
|
11711
|
+
setSmears(gliding ? rangeSmear(speeds[0], smearStrength) : 0, gliding ? rangeSmear(speeds[1], smearStrength) : 0), smearFrame = gliding ? requestAnimationFrame(runSmear) : 0;
|
|
11712
|
+
};
|
|
11713
|
+
track.addEventListener("transitionrun", (event) => {
|
|
11714
|
+
if (event.target !== track || smearFrame || dragging)
|
|
11715
|
+
return;
|
|
11716
|
+
if (track.closest('[data-gpu-active="true"]'))
|
|
11717
|
+
return;
|
|
11718
|
+
smearStrength = clamp(parseFloat(getComputedStyle(track).getPropertyValue("--k-range-blur")) || 0, 0, 1);
|
|
11719
|
+
let reduced = c.doc.defaultView?.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
11720
|
+
if (smearStrength <= 0 || reduced)
|
|
11721
|
+
return;
|
|
11722
|
+
lastEnds = ends(), smearAt = performance.now(), smearFrame = requestAnimationFrame(runSmear);
|
|
11723
|
+
});
|
|
11724
|
+
let lastEnd = 0, g = gesture(c), span = () => f().max - f().min || 1, ratio = (v) => clamp((v - f().min) / span(), 0, 1), quant = (v, fine) => clamp(onGrid(v, f().min, fine ? f().step / 10 : f().step), f().min, f().max), withEnd = (from, end, v, fine = !1) => {
|
|
11725
|
+
let q = quant(v, fine);
|
|
11726
|
+
return end === 0 ? [Math.min(q, from[1]), from[1]] : [from[0], Math.max(q, from[0])];
|
|
11727
|
+
}, rolling = rollingReadout(read), showText = (ms, delay) => rolling.show(mixed ? ["—"] : [
|
|
11728
|
+
{ value: shown[0], decimals: places() },
|
|
11729
|
+
"–",
|
|
11730
|
+
{ value: shown[1], decimals: places() },
|
|
11731
|
+
f().unit ? ` ${f().unit}` : ""
|
|
11732
|
+
], ms, delay), place = (instant) => {
|
|
11733
|
+
let [a, b] = [ratio(shown[0]), ratio(shown[1])], nodes = [fill, track];
|
|
11734
|
+
if (instant)
|
|
11735
|
+
for (let n of nodes)
|
|
11736
|
+
n.style.transition = "none";
|
|
11737
|
+
if (fill.style.transform = `translateX(${(a * 100).toFixed(4)}%) scaleX(${Math.max(0, b - a).toFixed(5)})`, track.style.setProperty("--kr-lo", a.toFixed(6)), track.style.setProperty("--kr-hi", b.toFixed(6)), instant) {
|
|
11738
|
+
fill.offsetWidth;
|
|
11739
|
+
for (let n of nodes)
|
|
11740
|
+
n.style.transition = "";
|
|
11741
|
+
}
|
|
11742
|
+
}, paint = (instant, delay = 0) => {
|
|
11743
|
+
showText(instant ? 0 : rollMs(row), delay), thumbs.forEach((th, i) => {
|
|
11744
|
+
th.setAttribute("aria-valuenow", String(shown[i])), th.setAttribute("aria-valuemin", String(i === 0 ? f().min : shown[0])), th.setAttribute("aria-valuemax", String(i === 0 ? shown[1] : f().max));
|
|
11745
|
+
}), place(instant);
|
|
11746
|
+
}, grab = 0, startValue = shown, rect, lastX = 0, hand = { at: 0, give: 0 }, moved = 0, card = () => row.parentElement?.classList.contains("knobs-card") ? row.parentElement : null, give = textGive(row, () => c.wake(), {
|
|
11747
|
+
home: STRETCH_HOME_S,
|
|
11748
|
+
draw: (px) => drawStretch(row, px, 0, { w: track.clientWidth, h: 0 }, { thin: !0, unclip: card() })
|
|
11749
|
+
}), most = GIVE, fit = () => {
|
|
11750
|
+
let room = roomOf(row, card());
|
|
11751
|
+
most = giveRoom(Math.min(room.left, room.right) - 1, GIVE);
|
|
11752
|
+
}, valueAt = (x) => f().min + clamp((x - rect.left) / rect.width, 0, 1) * span();
|
|
11753
|
+
track.addEventListener("pointerdown", (event) => {
|
|
11754
|
+
if (event.button !== 0 || event.shiftKey || event.metaKey)
|
|
11755
|
+
return;
|
|
11756
|
+
if (event.target.closest(".knobs-cell-edit,.knobs-accessory"))
|
|
11757
|
+
return;
|
|
11758
|
+
event.preventDefault(), track.setPointerCapture(event.pointerId), rect = track.getBoundingClientRect();
|
|
11759
|
+
let x = event.clientX - rect.left, [ax, bx] = [ratio(shown[0]) * rect.width, ratio(shown[1]) * rect.width];
|
|
11760
|
+
if (grab = x > ax + 8 && x < bx - 8 && bx - ax > 24 ? 2 : Math.abs(x - ax) <= Math.abs(x - bx) && !(x > bx) ? 0 : 1, ax === bx)
|
|
11761
|
+
grab = x < ax ? 0 : 1;
|
|
11762
|
+
if (grab !== 2)
|
|
11763
|
+
lastEnd = grab;
|
|
11764
|
+
if (thumbs[grab === 2 ? lastEnd : grab].focus({
|
|
11765
|
+
preventScroll: !0,
|
|
11766
|
+
focusVisible: !1
|
|
11767
|
+
}), lastX = event.clientX, startValue = shown, moved = 0, fit(), hand = {
|
|
11768
|
+
at: grab === 2 || event.altKey ? ratio(shown[grab === 2 ? 0 : grab]) * rect.width : clamp(x, 0, rect.width),
|
|
11769
|
+
give: 0
|
|
11770
|
+
}, dragging = !0, row.classList.add("knobs-active"), g.start(), grab !== 2 && !event.altKey)
|
|
11771
|
+
g.set(withEnd(shown, grab, valueAt(event.clientX)));
|
|
11772
|
+
c.wake();
|
|
11773
|
+
}), track.addEventListener("pointermove", (event) => {
|
|
11774
|
+
if (!dragging || !rect)
|
|
11775
|
+
return;
|
|
11776
|
+
let rate = precisionRate(offRow(event.clientY, rect.top, rect.bottom)) * (event.altKey ? 0.1 : 1), dx = (event.clientX - lastX) * rate;
|
|
11777
|
+
if (lastX = event.clientX, grab === 2) {
|
|
11778
|
+
moved += dx;
|
|
11779
|
+
let width = startValue[1] - startValue[0], by = moved / rect.width * span(), lo = clamp(quant(startValue[0] + by, event.altKey), f().min, f().max - width);
|
|
11780
|
+
g.set([lo, Number((lo + width).toPrecision(12))]);
|
|
11781
|
+
return;
|
|
11782
|
+
}
|
|
11783
|
+
if (hand = band(hand, dx, 0, rect.width, most), g.set(withEnd(c.get(), grab, f().min + hand.at / rect.width * span(), event.altKey)), hand.give !== give.give)
|
|
11784
|
+
give.hold(hand.give);
|
|
11785
|
+
});
|
|
11786
|
+
let release = () => {
|
|
11787
|
+
if (!dragging)
|
|
11788
|
+
return;
|
|
11789
|
+
dragging = !1, rect = void 0, give.release(), row.classList.remove("knobs-active"), c.wake();
|
|
11790
|
+
};
|
|
11791
|
+
track.addEventListener("pointerup", release), track.addEventListener("pointercancel", release);
|
|
11792
|
+
let panAt;
|
|
11793
|
+
onPan(track, {
|
|
11794
|
+
accept: () => !dragging,
|
|
11795
|
+
move(dx) {
|
|
11796
|
+
let w = track.clientWidth;
|
|
11797
|
+
if (!w)
|
|
11798
|
+
return;
|
|
11799
|
+
if (panAt === void 0)
|
|
11800
|
+
g.start(), panAt = { at: (shown[lastEnd] - f().min) / span() * w, give: 0 }, fit(), dragging = !0, row.classList.add("knobs-active");
|
|
11801
|
+
if (panAt = band(panAt, dx, 0, w, most), g.set(withEnd(c.get(), lastEnd, f().min + panAt.at / w * span())), panAt.give !== give.give)
|
|
11802
|
+
give.hold(panAt.give);
|
|
11803
|
+
},
|
|
11804
|
+
lift: () => give.release(),
|
|
11805
|
+
end() {
|
|
11806
|
+
panAt = void 0, give.release(), dragging = !1, row.classList.remove("knobs-active"), c.wake();
|
|
11807
|
+
},
|
|
11808
|
+
step(direction) {
|
|
11809
|
+
g.start(), g.set(withEnd(shown, lastEnd, shown[lastEnd] + direction * f().step));
|
|
11810
|
+
}
|
|
11811
|
+
});
|
|
11812
|
+
let editors = thumbs.map((th, i) => inlineEdit(c.doc, row, `${c.display} ${i === 0 ? "low" : "high"} value`, (v) => {
|
|
11813
|
+
g.start(), g.set(withEnd(c.get(), i, v));
|
|
11814
|
+
}, () => th));
|
|
11815
|
+
thumbs.forEach((th, i) => {
|
|
11816
|
+
let end = i;
|
|
11817
|
+
th.addEventListener("focus", () => {
|
|
11818
|
+
lastEnd = end, row.dataset.endFocus = th.dataset.end, c.wake();
|
|
11819
|
+
}), th.addEventListener("blur", () => {
|
|
11820
|
+
if (row.dataset.endFocus === th.dataset.end)
|
|
11821
|
+
delete row.dataset.endFocus;
|
|
11822
|
+
}), th.addEventListener("keydown", (event) => {
|
|
11823
|
+
if (!plainKey(event))
|
|
11824
|
+
return;
|
|
11825
|
+
let dir = arrowOf(event), char = typed(event);
|
|
11826
|
+
if (dir) {
|
|
11827
|
+
event.preventDefault(), event.stopPropagation();
|
|
11828
|
+
let by = f().step * (event.shiftKey ? bigOf(event) : event.altKey ? 0.1 : 1);
|
|
11829
|
+
g.start(), g.set(withEnd(shown, end, shown[end] + dir * by, event.altKey));
|
|
11830
|
+
} else if (event.key === "Home" || event.key === "End")
|
|
11831
|
+
event.preventDefault(), g.start(), g.set(withEnd(shown, end, event.key === "Home" ? f().min : f().max));
|
|
11832
|
+
else if (event.key === "Enter" && keyPrefs(th).edit)
|
|
11833
|
+
event.preventDefault(), event.stopPropagation(), editors[end].start(mixed ? "" : fmt(shown[end], places()));
|
|
11834
|
+
else if (char && keyPrefs(th).edit)
|
|
11835
|
+
event.preventDefault(), event.stopPropagation(), editors[end].start(char, !1);
|
|
11836
|
+
});
|
|
11837
|
+
});
|
|
11838
|
+
let first = !0, gpu = {
|
|
11839
|
+
kind: "range",
|
|
11840
|
+
key: c.key,
|
|
11841
|
+
display: c.display,
|
|
11842
|
+
row,
|
|
11843
|
+
labelEl: label,
|
|
11844
|
+
track,
|
|
11845
|
+
read,
|
|
11846
|
+
thumbs,
|
|
11847
|
+
ratios: () => [ratio(shown[0]), ratio(shown[1])],
|
|
11848
|
+
dragging: () => dragging,
|
|
11849
|
+
editing: () => editors.some((e) => e.open),
|
|
11850
|
+
wave: c.wave,
|
|
11851
|
+
isModified: c.isModified
|
|
11852
|
+
};
|
|
11853
|
+
return {
|
|
11854
|
+
row,
|
|
11855
|
+
labelEl: label,
|
|
11856
|
+
input: thumbs[0],
|
|
11857
|
+
stops: () => thumbs,
|
|
11858
|
+
update(value, delay, instant, isMixed = !1) {
|
|
11859
|
+
shown = value, mixed = isMixed, paint(first || Boolean(instant) || dragging, delay), first = !1;
|
|
11860
|
+
},
|
|
11861
|
+
dispose() {
|
|
11862
|
+
cancelAnimationFrame(smearFrame), rolling.dispose();
|
|
11863
|
+
},
|
|
11864
|
+
tracks: [],
|
|
11865
|
+
gpu: [gpu]
|
|
11866
|
+
};
|
|
11867
|
+
}
|
|
11868
|
+
function angleRow(c) {
|
|
11869
|
+
let { row, label, el } = shell(c, "angle"), f = () => c.field, control = el("span", "knobs-angle");
|
|
11870
|
+
control.tabIndex = 0, control.setAttribute("role", "slider"), control.setAttribute("aria-label", c.display);
|
|
11871
|
+
let read = el("span", "knobs-angle-read"), dial = el("span", "knobs-dial"), hand = el("i", "knobs-dial-hand");
|
|
11872
|
+
dial.append(hand), control.append(read, dial), row.append(control);
|
|
11873
|
+
let value = c.get(), turn = value, mixed = !1, dragging = !1, g = gesture(c), places = () => decimals(f().step), snapTo = (v, coarse) => {
|
|
11874
|
+
let step = coarse ? Math.max(15, f().step) : f().step, q = Number((Math.round(v / step) * step).toPrecision(12));
|
|
11875
|
+
return f().wrap ? wrapAngle2(q, f().min, f().max) : clamp(q, f().min, f().max);
|
|
11876
|
+
}, rolling = rollingReadout(read), paint = (instant, delay = 0) => {
|
|
11877
|
+
let t = mixed ? "—" : `${fmt(value, places())}°`;
|
|
11878
|
+
if (rolling.show(mixed ? ["—"] : [{ value, decimals: places() }, "°"], instant || row.classList.contains("knobs-active") ? 0 : rollMs(row), delay), control.setAttribute("aria-valuenow", String(value)), control.setAttribute("aria-valuetext", t), instant || reducedMotion4(c.doc))
|
|
11879
|
+
hand.style.transition = "none";
|
|
11880
|
+
if (hand.style.rotate = `${turn.toFixed(3)}deg`, instant)
|
|
11881
|
+
hand.offsetWidth, hand.style.transition = "";
|
|
11882
|
+
}, follow = (next) => {
|
|
11883
|
+
let d = next - value;
|
|
11884
|
+
if (f().wrap) {
|
|
11885
|
+
let s = f().max - f().min;
|
|
11886
|
+
d = ((d + s / 2) % s + s) % s - s / 2;
|
|
11887
|
+
}
|
|
11888
|
+
turn += d, value = next;
|
|
11889
|
+
}, mode = "scrub", startX = 0, startValue = 0, carried = 0, rowRect, centre = [0, 0], moved = !1, angleAt = (x, y) => Math.atan2(x - centre[0], -(y - centre[1])) * 180 / Math.PI;
|
|
11890
|
+
control.addEventListener("pointerdown", (event) => {
|
|
11891
|
+
if (event.button !== 0 || event.shiftKey || event.metaKey)
|
|
11892
|
+
return;
|
|
11893
|
+
if (event.target.closest(".knobs-cell-edit"))
|
|
11894
|
+
return;
|
|
11895
|
+
event.preventDefault(), control.setPointerCapture(event.pointerId), control.focus({ preventScroll: !0, focusVisible: !1 });
|
|
11896
|
+
let r = dial.getBoundingClientRect();
|
|
11897
|
+
if (centre = [r.left + r.width / 2, r.top + r.height / 2], mode = event.target.closest(".knobs-dial") ? "dial" : "scrub", startX = event.clientX, startValue = value, carried = 0, moved = !1, dragging = !0, g.start(), mode === "dial")
|
|
11898
|
+
moved = !0, row.classList.add("knobs-active"), g.set(snapTo(angleAt(event.clientX, event.clientY), !1));
|
|
11899
|
+
c.wake();
|
|
11900
|
+
}), control.addEventListener("pointermove", (event) => {
|
|
11901
|
+
if (!dragging)
|
|
11902
|
+
return;
|
|
11903
|
+
if (mode === "dial") {
|
|
11904
|
+
let a = angleAt(event.clientX, event.clientY);
|
|
11905
|
+
g.set(snapTo(f().wrap ? a : clamp(a, f().min, f().max), event.shiftKey));
|
|
11906
|
+
return;
|
|
11907
|
+
}
|
|
11908
|
+
if (!moved && Math.abs(event.clientX - startX) < 3)
|
|
11909
|
+
return;
|
|
11910
|
+
if (!moved)
|
|
11911
|
+
moved = !0, startX = event.clientX, rowRect = row.getBoundingClientRect(), row.classList.add("knobs-active");
|
|
11912
|
+
let r = rowRect, rate = precisionRate(offRow(event.clientY, r.top, r.bottom)) * (event.altKey ? 0.1 : 1);
|
|
11913
|
+
carried += (event.clientX - startX) * rate, startX = event.clientX, g.set(snapTo(startValue + carried * f().step, event.shiftKey));
|
|
11914
|
+
});
|
|
11915
|
+
let editor = inlineEdit(c.doc, row, `${c.display} value`, (v) => {
|
|
11916
|
+
g.start(), g.set(snapTo(v, !1));
|
|
11917
|
+
}, () => control), release = () => {
|
|
11918
|
+
if (!dragging)
|
|
11919
|
+
return;
|
|
11920
|
+
if (dragging = !1, row.classList.remove("knobs-active"), !moved)
|
|
11921
|
+
editor.start(mixed ? "" : fmt(value, places()));
|
|
11922
|
+
c.wake();
|
|
11923
|
+
};
|
|
11924
|
+
control.addEventListener("pointerup", release), control.addEventListener("pointercancel", release);
|
|
11925
|
+
let panAt, give = textGive(read, () => c.wake());
|
|
11926
|
+
onPan(control, {
|
|
11927
|
+
accept: () => !dragging,
|
|
11928
|
+
move(dx) {
|
|
11929
|
+
let step = f().step;
|
|
11930
|
+
if (panAt === void 0)
|
|
11931
|
+
g.start(), panAt = { at: value / step, give: 0 }, row.classList.add("knobs-active");
|
|
11932
|
+
if (panAt = f().wrap ? { at: panAt.at + dx, give: 0 } : band(panAt, dx, f().min / step, f().max / step), g.set(snapTo(panAt.at * step, !1)), panAt.give !== give.give)
|
|
11933
|
+
give.hold(panAt.give);
|
|
11934
|
+
},
|
|
11935
|
+
lift: () => give.release(),
|
|
11936
|
+
end() {
|
|
11937
|
+
panAt = void 0, give.release(), row.classList.remove("knobs-active"), c.wake();
|
|
11938
|
+
},
|
|
11939
|
+
step(direction) {
|
|
11940
|
+
g.start(), g.set(snapTo(value + direction * f().step, !1));
|
|
11941
|
+
}
|
|
11942
|
+
}), control.addEventListener("keydown", (event) => {
|
|
11943
|
+
if (event.target !== control || !plainKey(event))
|
|
11944
|
+
return;
|
|
11945
|
+
let dir = arrowOf(event), char = typed(event);
|
|
11946
|
+
if (dir)
|
|
11947
|
+
if (event.preventDefault(), event.stopPropagation(), g.start(), event.shiftKey) {
|
|
11948
|
+
let s = Math.max(15, f().step), k = dir > 0 ? Math.floor(value / s + 0.000000001) + 1 : Math.ceil(value / s - 0.000000001) - 1;
|
|
11949
|
+
g.set(snapTo(k * s, !1));
|
|
11950
|
+
} else
|
|
11951
|
+
g.set(snapTo(value + dir * f().step * (event.altKey ? 0.1 : 1), !1));
|
|
11952
|
+
else if (event.key === "Home" || event.key === "End")
|
|
11953
|
+
event.preventDefault(), g.start(), g.set(snapTo(event.key === "Home" ? f().min : f().max - (f().wrap ? f().step : 0), !1));
|
|
11954
|
+
else if (event.key === "Enter" && keyPrefs(control).edit)
|
|
11955
|
+
event.preventDefault(), event.stopPropagation(), editor.start(mixed ? "" : fmt(value, places()));
|
|
11956
|
+
else if (char && keyPrefs(control).edit)
|
|
11957
|
+
event.preventDefault(), event.stopPropagation(), editor.start(char, !1);
|
|
11958
|
+
});
|
|
11959
|
+
let first = !0, gpu = {
|
|
11960
|
+
kind: "angle",
|
|
11961
|
+
key: c.key,
|
|
11962
|
+
display: c.display,
|
|
11963
|
+
row,
|
|
11964
|
+
labelEl: label,
|
|
11965
|
+
control,
|
|
11966
|
+
read,
|
|
11967
|
+
dial,
|
|
11968
|
+
turn: () => mixed ? 0 : turn,
|
|
11969
|
+
dragging: () => dragging,
|
|
11970
|
+
editing: () => editor.open,
|
|
11971
|
+
wave: c.wave,
|
|
11972
|
+
isModified: c.isModified
|
|
11973
|
+
};
|
|
11974
|
+
return {
|
|
11975
|
+
row,
|
|
11976
|
+
labelEl: label,
|
|
11977
|
+
input: control,
|
|
11978
|
+
stops: () => [control],
|
|
11979
|
+
update(next, delay, instant, isMixed = !1) {
|
|
11980
|
+
if (mixed = isMixed, first || instant)
|
|
11981
|
+
value = turn = next;
|
|
11982
|
+
else
|
|
11983
|
+
follow(next);
|
|
11984
|
+
paint(first || Boolean(instant) || dragging, delay), first = !1;
|
|
11985
|
+
},
|
|
11986
|
+
dispose() {
|
|
11987
|
+
rolling.dispose();
|
|
11988
|
+
},
|
|
11989
|
+
tracks: [],
|
|
11990
|
+
gpu: [gpu]
|
|
11991
|
+
};
|
|
11992
|
+
}
|
|
11993
|
+
var SEED_STEP = 12, DICE_ROLL_MS = 620;
|
|
11994
|
+
function seedRow(c) {
|
|
11995
|
+
let { row, label, el } = shell(c, "seed"), f = () => c.field, control = el("span", "knobs-seed");
|
|
11996
|
+
control.tabIndex = 0, control.setAttribute("role", "spinbutton"), control.setAttribute("aria-label", c.display);
|
|
11997
|
+
let read = el("span", "knobs-seed-read");
|
|
11998
|
+
control.append(read);
|
|
11999
|
+
let reel = el("span", "knobs-seed-digits");
|
|
12000
|
+
read.append(reel);
|
|
12001
|
+
let roller = it(reel, {
|
|
12002
|
+
value: c.get(),
|
|
12003
|
+
format: { useGrouping: !1, maximumFractionDigits: 0 },
|
|
12004
|
+
duration: 1,
|
|
12005
|
+
motionBlur: !0
|
|
12006
|
+
}), places = [], initialized = !1, diced = !1, roll = el("button", "knobs-seed-roll");
|
|
12007
|
+
roll.type = "button", roll.tabIndex = -1, roll.setAttribute("aria-label", `Roll ${c.display}`);
|
|
12008
|
+
let die = createHeaderDie(c.doc, () => c.wake(), GROUP_DIE);
|
|
12009
|
+
roll.append(die.node), row.append(control, roll);
|
|
12010
|
+
let value = c.get(), mixed = !1, g = gesture(c), set = (v) => {
|
|
12011
|
+
stopCarry(), g.start(), g.set(Math.round(clamp(v, f().min, f().max)));
|
|
12012
|
+
}, reroll = () => {
|
|
12013
|
+
let { min, max } = f(), next = value;
|
|
12014
|
+
for (let i = 0;i < 8 && next === value; i++)
|
|
12015
|
+
next = min + Math.floor(Math.random() * (max - min + 1));
|
|
12016
|
+
die.roll(), diced = !0, set(next), diced = !1;
|
|
12017
|
+
};
|
|
12018
|
+
roll.onclick = () => reroll();
|
|
12019
|
+
let editor = inlineEdit(c.doc, row, `${c.display} value`, set, () => control), give = textGive(read, () => c.wake()), recent = moves(), panned, carry = [], stopCarry = () => {
|
|
12020
|
+
for (let t of carry)
|
|
12021
|
+
clearTimeout(t);
|
|
12022
|
+
carry = [];
|
|
12023
|
+
}, scrubBy = (steps) => {
|
|
12024
|
+
let { min, max } = f(), next = clamp(value + steps, min, max);
|
|
12025
|
+
if (next === value)
|
|
12026
|
+
return !1;
|
|
12027
|
+
let dir = next > value ? 1 : -1;
|
|
12028
|
+
for (let i = 0;i < Math.min(3, Math.abs(next - value)); i++)
|
|
12029
|
+
die.turn(dir);
|
|
12030
|
+
return g.set(next), tick(control), !0;
|
|
12031
|
+
}, letGo = () => {
|
|
12032
|
+
panned = void 0, give.release(), row.classList.remove("knobs-active"), c.wake();
|
|
12033
|
+
};
|
|
12034
|
+
onPan(row, {
|
|
12035
|
+
accept: () => !editor.open,
|
|
12036
|
+
move(dx) {
|
|
12037
|
+
if (!panned)
|
|
12038
|
+
stopCarry(), g.start(), recent.reset(), panned = { travel: 0, give: 0 }, row.classList.add("knobs-active"), c.wake();
|
|
12039
|
+
recent.add(dx);
|
|
12040
|
+
let { min, max } = f(), { next, steps } = stepBand(panned, dx, SEED_STEP, [value - min, max - value]);
|
|
12041
|
+
if (panned = next, steps)
|
|
12042
|
+
scrubBy(steps);
|
|
12043
|
+
if (next.give !== give.give)
|
|
12044
|
+
give.hold(next.give);
|
|
12045
|
+
},
|
|
12046
|
+
lift() {
|
|
12047
|
+
if (!panned)
|
|
12048
|
+
return;
|
|
12049
|
+
let n = carrySteps(recent.speed()), dir = Math.sign(recent.speed());
|
|
12050
|
+
letGo();
|
|
12051
|
+
for (let i = 0;i < n; i++)
|
|
12052
|
+
carry.push(setTimeout(() => {
|
|
12053
|
+
if (!scrubBy(dir))
|
|
12054
|
+
stopCarry();
|
|
12055
|
+
}, carryAt(i)));
|
|
12056
|
+
},
|
|
12057
|
+
end: letGo,
|
|
12058
|
+
step(direction) {
|
|
12059
|
+
stopCarry(), set(value + direction);
|
|
12060
|
+
}
|
|
12061
|
+
}), control.addEventListener("click", () => {
|
|
12062
|
+
if (!editor.open)
|
|
12063
|
+
editor.start(mixed ? "" : String(value));
|
|
12064
|
+
}), control.addEventListener("keydown", (event) => {
|
|
12065
|
+
if (event.target !== control || !plainKey(event))
|
|
12066
|
+
return;
|
|
12067
|
+
let dir = arrowOf(event), char = typed(event);
|
|
12068
|
+
if (dir)
|
|
12069
|
+
event.preventDefault(), event.stopPropagation(), set(value + dir * bigOf(event));
|
|
12070
|
+
else if (event.key === " ")
|
|
12071
|
+
event.preventDefault(), event.stopPropagation(), reroll();
|
|
12072
|
+
else if (event.key === "Enter" && keyPrefs(control).edit)
|
|
12073
|
+
event.preventDefault(), event.stopPropagation(), editor.start(mixed ? "" : String(value));
|
|
12074
|
+
else if (char && keyPrefs(control).edit)
|
|
12075
|
+
event.preventDefault(), event.stopPropagation(), editor.start(char, !1);
|
|
12076
|
+
});
|
|
12077
|
+
let paint = (previous, instant) => {
|
|
12078
|
+
read.toggleAttribute("data-mixed", mixed), control.setAttribute("aria-valuenow", String(value));
|
|
12079
|
+
let ms = !initialized || instant ? 0 : diced ? DICE_ROLL_MS : rollMs(row);
|
|
12080
|
+
initialized = !0, syncPlaces(places, String(value), diced ? 1 : Math.sign(value - previous), ms, 0);
|
|
12081
|
+
let dom = ms > 0 && row.closest('[data-gpu-active="true"]') === null;
|
|
12082
|
+
if (roller.update({
|
|
12083
|
+
value,
|
|
12084
|
+
animated: !0,
|
|
12085
|
+
duration: dom ? ms : 1,
|
|
12086
|
+
motionBlur: dom,
|
|
12087
|
+
direction: diced ? "up" : "auto"
|
|
12088
|
+
}), ms > 0)
|
|
12089
|
+
c.wake();
|
|
12090
|
+
}, gpu = {
|
|
12091
|
+
kind: "seed",
|
|
12092
|
+
key: c.key,
|
|
12093
|
+
display: c.display,
|
|
12094
|
+
row,
|
|
12095
|
+
labelEl: label,
|
|
12096
|
+
control,
|
|
12097
|
+
read,
|
|
12098
|
+
places,
|
|
12099
|
+
mixed: () => mixed,
|
|
12100
|
+
die: { button: roll, die },
|
|
12101
|
+
editing: () => editor.open,
|
|
12102
|
+
wave: c.wave,
|
|
12103
|
+
isModified: c.isModified
|
|
12104
|
+
};
|
|
12105
|
+
return {
|
|
12106
|
+
row,
|
|
12107
|
+
labelEl: label,
|
|
12108
|
+
input: control,
|
|
12109
|
+
stops: () => [control],
|
|
12110
|
+
update(next, _delay, instant, isMixed = !1) {
|
|
12111
|
+
let previous = value;
|
|
12112
|
+
value = next, mixed = isMixed, paint(previous, Boolean(instant));
|
|
12113
|
+
},
|
|
12114
|
+
dispose: () => {
|
|
12115
|
+
stopCarry(), die.dispose(), roller.destroy();
|
|
12116
|
+
},
|
|
12117
|
+
tracks: [],
|
|
12118
|
+
gpu: [gpu]
|
|
12119
|
+
};
|
|
12120
|
+
}
|
|
12121
|
+
var CAP_MORPH = springLinear(SPRINGS2.snappy);
|
|
12122
|
+
function keyCap(o) {
|
|
12123
|
+
let chip = o.doc.createElement("button");
|
|
12124
|
+
chip.className = "knobs-keys", chip.type = "button";
|
|
12125
|
+
let text = o.doc.createElement("span");
|
|
12126
|
+
text.className = "knobs-keys-text", chip.append(text);
|
|
12127
|
+
let value = "", capturing = !1, preview = "", morph, write = (shown) => {
|
|
12128
|
+
let glide = chip.isConnected && chip.offsetWidth > 0 && !chip.closest('[data-gpu-active="true"]') && !reducedMotion4(o.doc), from = glide ? chip.getBoundingClientRect().width : 0;
|
|
12129
|
+
if (morph?.cancel(), text.textContent = shown, !glide)
|
|
12130
|
+
return;
|
|
12131
|
+
let to = chip.getBoundingClientRect().width;
|
|
12132
|
+
if (text.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 150, easing: "ease-out" }), Math.abs(to - from) < 0.5)
|
|
12133
|
+
return;
|
|
12134
|
+
chip.dataset.morph = "", morph = chip.animate([{ width: `${from}px` }, { width: `${to}px` }], {
|
|
12135
|
+
duration: CAP_MORPH.ms,
|
|
12136
|
+
easing: CAP_MORPH.easing
|
|
12137
|
+
}), morph.onfinish = () => delete chip.dataset.morph, morph.oncancel = () => delete chip.dataset.morph;
|
|
12138
|
+
}, paint = () => {
|
|
12139
|
+
let shown = capturing ? preview || "Type keys…" : value === void 0 ? "—" : value ? comboLabel2(value) : o.empty;
|
|
12140
|
+
if (text.textContent !== shown)
|
|
12141
|
+
write(shown);
|
|
12142
|
+
chip.toggleAttribute("data-empty", !capturing && value === ""), chip.setAttribute("aria-pressed", String(capturing)), chip.setAttribute("aria-label", `${o.name()}: ${capturing ? "press a key combination" : value ? comboLabel2(value) : "none"}`), o.wake();
|
|
12143
|
+
}, capture = (on) => {
|
|
12144
|
+
if (capturing === on)
|
|
12145
|
+
return;
|
|
12146
|
+
if (on && o.row.closest("[data-disabled],[data-readonly]"))
|
|
12147
|
+
return;
|
|
12148
|
+
capturing = on, preview = "", o.row.classList.toggle("knobs-active", on), paint();
|
|
12149
|
+
}, held = (event) => {
|
|
12150
|
+
let mods = heldMods(event);
|
|
12151
|
+
preview = mods.length ? comboLabel2(`${mods.join("+")}+…`) : "", paint();
|
|
12152
|
+
};
|
|
12153
|
+
return chip.onclick = () => capture(!capturing), chip.addEventListener("keydown", (event) => {
|
|
12154
|
+
if (event.isComposing)
|
|
12155
|
+
return;
|
|
12156
|
+
if (!capturing) {
|
|
12157
|
+
if ((event.key === "Enter" || event.key === " ") && plainKey(event) && !event.altKey)
|
|
12158
|
+
event.preventDefault(), event.stopPropagation(), capture(!0);
|
|
12159
|
+
return;
|
|
12160
|
+
}
|
|
12161
|
+
if (event.key === "Tab")
|
|
12162
|
+
return capture(!1);
|
|
12163
|
+
event.preventDefault(), event.stopPropagation();
|
|
12164
|
+
let mods = heldMods(event);
|
|
12165
|
+
if (event.key === "Escape" && !mods.length)
|
|
12166
|
+
return capture(!1);
|
|
12167
|
+
let take = (combo) => {
|
|
12168
|
+
value = combo, capture(!1), o.set(combo);
|
|
12169
|
+
};
|
|
12170
|
+
if ((event.key === "Backspace" || event.key === "Delete") && !mods.length)
|
|
12171
|
+
return take("");
|
|
12172
|
+
let combo = comboFromEvent2(event);
|
|
12173
|
+
if (!combo)
|
|
12174
|
+
return held(event);
|
|
12175
|
+
take(combo);
|
|
12176
|
+
}), chip.addEventListener("keyup", (event) => {
|
|
12177
|
+
if (capturing)
|
|
12178
|
+
held(event);
|
|
12179
|
+
}), chip.addEventListener("blur", () => capture(!1)), paint(), {
|
|
12180
|
+
chip,
|
|
12181
|
+
text,
|
|
12182
|
+
capturing: () => capturing,
|
|
12183
|
+
show(combo) {
|
|
12184
|
+
value = combo, paint();
|
|
12185
|
+
}
|
|
12186
|
+
};
|
|
12142
12187
|
}
|
|
12143
|
-
function
|
|
12144
|
-
|
|
12145
|
-
|
|
12146
|
-
|
|
12147
|
-
|
|
12148
|
-
|
|
12149
|
-
|
|
12188
|
+
function keybindRow(c) {
|
|
12189
|
+
let { row, label } = shell(c, "keybind"), cap = keyCap({
|
|
12190
|
+
doc: c.doc,
|
|
12191
|
+
row,
|
|
12192
|
+
empty: "None",
|
|
12193
|
+
name: () => c.display,
|
|
12194
|
+
set: (combo) => c.set(combo),
|
|
12195
|
+
wake: c.wake
|
|
12196
|
+
}), { chip, text } = cap;
|
|
12197
|
+
row.append(chip), cap.show(c.get());
|
|
12198
|
+
let gpu = {
|
|
12199
|
+
kind: "keybind",
|
|
12200
|
+
key: c.key,
|
|
12201
|
+
display: c.display,
|
|
12202
|
+
row,
|
|
12203
|
+
labelEl: label,
|
|
12204
|
+
chip,
|
|
12205
|
+
text,
|
|
12206
|
+
capturing: cap.capturing,
|
|
12207
|
+
wave: c.wave,
|
|
12208
|
+
isModified: c.isModified
|
|
12209
|
+
};
|
|
12210
|
+
return {
|
|
12211
|
+
row,
|
|
12212
|
+
labelEl: label,
|
|
12213
|
+
input: chip,
|
|
12214
|
+
stops: () => [chip],
|
|
12215
|
+
update(next, _delay, _instant, isMixed = !1) {
|
|
12216
|
+
cap.show(isMixed ? void 0 : next);
|
|
12217
|
+
},
|
|
12218
|
+
dispose() {},
|
|
12219
|
+
tracks: [],
|
|
12220
|
+
gpu: [gpu]
|
|
12221
|
+
};
|
|
12150
12222
|
}
|
|
12151
|
-
|
|
12152
|
-
|
|
12153
|
-
|
|
12154
|
-
|
|
12155
|
-
|
|
12156
|
-
|
|
12223
|
+
function textRow(c) {
|
|
12224
|
+
let { row, label, el } = shell(c, "text"), multiline = Boolean(c.field.multiline);
|
|
12225
|
+
row.toggleAttribute("data-multiline", multiline);
|
|
12226
|
+
let input = multiline ? Object.assign(el("textarea", "knobs-text"), { rows: 2 }) : Object.assign(el("input", "knobs-text"), { type: "text" });
|
|
12227
|
+
input.spellcheck = !1, input.autocomplete = "off", input.placeholder = c.field.placeholder ?? "", input.setAttribute("aria-label", c.display), input.value = c.get(), row.append(input);
|
|
12228
|
+
let typed = !1;
|
|
12229
|
+
input.addEventListener("focus", () => typed = !1), input.addEventListener("input", () => {
|
|
12230
|
+
c.set(input.value, { coalesce: typed }), typed = !0;
|
|
12231
|
+
}), input.addEventListener("keydown", (e) => {
|
|
12232
|
+
let event = e;
|
|
12233
|
+
if (event.isComposing)
|
|
12234
|
+
return;
|
|
12235
|
+
if (!(event.key === "Escape" || event.key === "Enter" && (!multiline || event.metaKey || event.ctrlKey)))
|
|
12236
|
+
return;
|
|
12237
|
+
event.preventDefault(), event.stopPropagation(), input.blur();
|
|
12238
|
+
});
|
|
12239
|
+
let gpu = {
|
|
12240
|
+
kind: "text",
|
|
12241
|
+
key: c.key,
|
|
12242
|
+
display: c.display,
|
|
12243
|
+
row,
|
|
12244
|
+
labelEl: label,
|
|
12245
|
+
wave: c.wave,
|
|
12246
|
+
isModified: c.isModified
|
|
12247
|
+
};
|
|
12248
|
+
return {
|
|
12249
|
+
row,
|
|
12250
|
+
labelEl: label,
|
|
12251
|
+
input,
|
|
12252
|
+
stops: () => [input],
|
|
12253
|
+
update(next, _delay, _instant, isMixed = !1) {
|
|
12254
|
+
input.placeholder = isMixed ? "—" : c.field.placeholder ?? "";
|
|
12255
|
+
let shown = isMixed ? "" : next;
|
|
12256
|
+
if (input.value !== shown)
|
|
12257
|
+
input.value = shown;
|
|
12258
|
+
},
|
|
12259
|
+
dispose() {},
|
|
12260
|
+
tracks: [],
|
|
12261
|
+
gpu: [gpu]
|
|
12262
|
+
};
|
|
12263
|
+
}
|
|
12264
|
+
function naturalWidth(b) {
|
|
12265
|
+
let cs = getComputedStyle(b), w = (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0), parts = [...b.children];
|
|
12266
|
+
for (let part of parts) {
|
|
12267
|
+
let ps = getComputedStyle(part), margin = parseFloat(ps.marginRight) || 0;
|
|
12268
|
+
w += part instanceof HTMLElement ? part.scrollWidth + margin : parseFloat(ps.width) || 0;
|
|
12269
|
+
}
|
|
12270
|
+
return Math.ceil(w + (parseFloat(cs.columnGap) || 0) * Math.max(0, parts.length - 1));
|
|
12271
|
+
}
|
|
12272
|
+
function toolbarRow(c, press, keyOf = toolbarShortcut2) {
|
|
12273
|
+
let el = make(c.doc), row = el("div", "knobs-row knobs-toolbar");
|
|
12274
|
+
row.dataset.field = c.key, row.setAttribute("role", "toolbar"), row.setAttribute("aria-label", c.display);
|
|
12275
|
+
let field = c.field, buttons = [], last = 0, keys = "", untips = [], keysNow = () => field.items.map((item) => keyOf(item)?.key ?? "").join("\x00"), showIcons = (on) => {
|
|
12276
|
+
if (row.hasAttribute("data-icons") === on && untips.length === (on ? buttons.length : 0))
|
|
12277
|
+
return;
|
|
12278
|
+
row.toggleAttribute("data-icons", on);
|
|
12279
|
+
for (let off of untips)
|
|
12280
|
+
off();
|
|
12281
|
+
untips = on ? field.items.map((item, i) => {
|
|
12282
|
+
let key = keyOf(item);
|
|
12283
|
+
return tooltip(buttons[i], item.label, key ? { shortcut: key.key } : {});
|
|
12284
|
+
}) : [];
|
|
12285
|
+
}, layout = () => {
|
|
12286
|
+
let cs = getComputedStyle(row), avail = row.clientWidth - (parseFloat(cs.paddingLeft) || 0) - (parseFloat(cs.paddingRight) || 0);
|
|
12287
|
+
if (avail <= 0 || !buttons.length)
|
|
12288
|
+
return;
|
|
12289
|
+
let gap = parseFloat(cs.columnGap) || 0, iconed = field.items.every((item) => item.icon), icons = iconed && field.labels === !1;
|
|
12290
|
+
if (iconed && field.labels === void 0) {
|
|
12291
|
+
let was = row.hasAttribute("data-icons");
|
|
12292
|
+
if (was)
|
|
12293
|
+
row.removeAttribute("data-icons");
|
|
12294
|
+
let widest = Math.max(...buttons.map(naturalWidth));
|
|
12295
|
+
if (was)
|
|
12296
|
+
row.setAttribute("data-icons", "");
|
|
12297
|
+
icons = toolbarColumns(buttons.length, widest, avail, gap) < buttons.length;
|
|
12298
|
+
}
|
|
12299
|
+
showIcons(icons);
|
|
12300
|
+
let cols = String(icons ? buttons.length : toolbarColumns(buttons.length, Math.max(...buttons.map(naturalWidth)), avail, gap));
|
|
12301
|
+
if (row.style.getPropertyValue("--k-tool-cols") !== cols)
|
|
12302
|
+
row.style.setProperty("--k-tool-cols", cols), c.wake();
|
|
12303
|
+
}, sizes = new ResizeObserver(layout);
|
|
12304
|
+
sizes.observe(row), c.doc.fonts?.ready.then(() => row.isConnected && layout());
|
|
12305
|
+
let gpu = {
|
|
12306
|
+
kind: "toolbar",
|
|
12307
|
+
key: c.key,
|
|
12308
|
+
display: c.display,
|
|
12309
|
+
row,
|
|
12310
|
+
items: [],
|
|
12311
|
+
wave: c.wave,
|
|
12312
|
+
isModified: () => !1
|
|
12313
|
+
}, build = () => {
|
|
12314
|
+
let items = [];
|
|
12315
|
+
buttons = field.items.map((item, i) => {
|
|
12316
|
+
let b = el("button", "knobs-tool");
|
|
12317
|
+
b.type = "button", b.tabIndex = -1, b.disabled = Boolean(item.disabled), b.dataset.item = item.id ?? item.label, b.setAttribute("aria-label", item.label);
|
|
12318
|
+
let iconEl;
|
|
12319
|
+
if (item.icon)
|
|
12320
|
+
iconEl = iconSvg(c.doc, item.icon), b.append(iconEl);
|
|
12321
|
+
let name = el("span", "knobs-tool-label", item.label);
|
|
12322
|
+
b.append(name);
|
|
12323
|
+
let chip, key = keyOf(item);
|
|
12324
|
+
if (key) {
|
|
12325
|
+
if (chip = el("kbd", "knobs-tool-key", comboLabel2(key.key)), b.append(chip), key.scope !== "none")
|
|
12326
|
+
b.setAttribute("aria-keyshortcuts", key.key);
|
|
12327
|
+
}
|
|
12328
|
+
return b.onclick = () => {
|
|
12329
|
+
last = i, press(item);
|
|
12330
|
+
}, b.addEventListener("focus", () => last = i), items.push({
|
|
12331
|
+
button: b,
|
|
12332
|
+
...item.icon ? { icon: item.icon } : {},
|
|
12333
|
+
...iconEl ? { iconEl } : {},
|
|
12334
|
+
label: name,
|
|
12335
|
+
...chip ? { chip } : {}
|
|
12336
|
+
}), b;
|
|
12337
|
+
}), row.replaceChildren(...buttons), gpu.items = items, keys = keysNow();
|
|
12338
|
+
for (let off of untips)
|
|
12339
|
+
off();
|
|
12340
|
+
if (untips = [], row.isConnected)
|
|
12341
|
+
layout();
|
|
12157
12342
|
};
|
|
12343
|
+
build(), row.addEventListener("keydown", (event) => {
|
|
12344
|
+
let at = buttons.indexOf(event.target), dir = arrowOf(event);
|
|
12345
|
+
if (at < 0 || !dir || !plainKey(event))
|
|
12346
|
+
return;
|
|
12347
|
+
event.preventDefault(), event.stopPropagation();
|
|
12348
|
+
let live = buttons.filter((b) => !b.disabled), i = live.indexOf(buttons[at]);
|
|
12349
|
+
live[(i + dir + live.length) % live.length]?.focus();
|
|
12350
|
+
});
|
|
12351
|
+
let first = () => buttons.find((b) => !b.disabled) ?? buttons[0];
|
|
12158
12352
|
return {
|
|
12159
|
-
|
|
12160
|
-
|
|
12161
|
-
|
|
12353
|
+
row,
|
|
12354
|
+
labelEl: row,
|
|
12355
|
+
get input() {
|
|
12356
|
+
let b = buttons[last];
|
|
12357
|
+
return b && !b.disabled ? b : first();
|
|
12162
12358
|
},
|
|
12163
|
-
get
|
|
12164
|
-
return
|
|
12359
|
+
get field() {
|
|
12360
|
+
return field;
|
|
12165
12361
|
},
|
|
12166
|
-
|
|
12167
|
-
|
|
12168
|
-
|
|
12169
|
-
|
|
12362
|
+
stops() {
|
|
12363
|
+
let b = buttons[last];
|
|
12364
|
+
return [b && !b.disabled ? b : first()];
|
|
12365
|
+
},
|
|
12366
|
+
update() {},
|
|
12367
|
+
refresh() {
|
|
12368
|
+
if (keysNow() === keys)
|
|
12369
|
+
return;
|
|
12370
|
+
let focused = buttons.indexOf(c.doc.activeElement);
|
|
12371
|
+
if (build(), focused >= 0)
|
|
12372
|
+
buttons[focused]?.focus({ preventScroll: !0 });
|
|
12373
|
+
c.wake();
|
|
12374
|
+
},
|
|
12375
|
+
match(event, global) {
|
|
12376
|
+
return field.items.find((item) => {
|
|
12377
|
+
let key = keyOf(item);
|
|
12378
|
+
return key !== void 0 && !item.disabled && key.scope === (global ? "page" : "panel") && matchesCombo2(key.key, event);
|
|
12379
|
+
});
|
|
12380
|
+
},
|
|
12381
|
+
press(item) {
|
|
12382
|
+
let i = field.items.indexOf(item), b = buttons[i];
|
|
12383
|
+
if (b && !reducedMotion4(c.doc))
|
|
12384
|
+
b.classList.add("knobs-pressed"), setTimeout(() => b.classList.remove("knobs-pressed"), 140), c.wake();
|
|
12385
|
+
press(item);
|
|
12386
|
+
},
|
|
12387
|
+
swap(next) {
|
|
12388
|
+
field = next, build(), c.wake();
|
|
12389
|
+
},
|
|
12390
|
+
dispose() {
|
|
12391
|
+
sizes.disconnect();
|
|
12392
|
+
for (let off of untips)
|
|
12393
|
+
off();
|
|
12394
|
+
},
|
|
12395
|
+
tracks: [],
|
|
12396
|
+
gpu: [gpu]
|
|
12397
|
+
};
|
|
12398
|
+
}
|
|
12399
|
+
|
|
12400
|
+
// src/panel/search.ts
|
|
12401
|
+
function createSearch(doc, options) {
|
|
12402
|
+
let element = doc.createElement("div");
|
|
12403
|
+
element.className = "knobs-search";
|
|
12404
|
+
let field = doc.createElement("label");
|
|
12405
|
+
field.className = "knobs-search-field", field.append(iconSvg(doc, "search"));
|
|
12406
|
+
let input = doc.createElement("input");
|
|
12407
|
+
input.type = "search", input.placeholder = options.placeholder, input.spellcheck = !1, input.autocomplete = "off", input.setAttribute("aria-label", "Search controls"), input.setAttribute("aria-keyshortcuts", "/"), field.append(input), element.append(field);
|
|
12408
|
+
let on = /* @__PURE__ */ new Set, chips = options.chips.map((spec) => {
|
|
12409
|
+
let b = doc.createElement("button");
|
|
12410
|
+
b.type = "button", b.className = "knobs-search-chip", b.tabIndex = -1, b.dataset.chip = spec.id, b.setAttribute("aria-pressed", "false");
|
|
12411
|
+
let name = doc.createElement("span");
|
|
12412
|
+
if (name.textContent = spec.label, b.append(name), spec.count) {
|
|
12413
|
+
let n = doc.createElement("span");
|
|
12414
|
+
n.className = "knobs-search-count", b.append(n);
|
|
12415
|
+
}
|
|
12416
|
+
return b.onclick = () => {
|
|
12417
|
+
if (on.has(spec.id))
|
|
12418
|
+
on.delete(spec.id);
|
|
12419
|
+
else
|
|
12420
|
+
on.add(spec.id);
|
|
12421
|
+
b.setAttribute("aria-pressed", String(on.has(spec.id))), options.change();
|
|
12422
|
+
}, element.append(b), b;
|
|
12423
|
+
});
|
|
12424
|
+
return input.addEventListener("input", () => options.change()), {
|
|
12425
|
+
element,
|
|
12426
|
+
input,
|
|
12427
|
+
chips,
|
|
12428
|
+
query: () => input.value.trim().toLowerCase(),
|
|
12429
|
+
active: () => on,
|
|
12430
|
+
filtering: () => input.value.trim() !== "" || on.size > 0,
|
|
12431
|
+
counts(counts) {
|
|
12432
|
+
for (let b of chips) {
|
|
12433
|
+
let n = b.querySelector(".knobs-search-count");
|
|
12434
|
+
if (!n)
|
|
12435
|
+
continue;
|
|
12436
|
+
let text = String(counts.get(b.dataset.chip) ?? 0);
|
|
12437
|
+
if (n.textContent !== text)
|
|
12438
|
+
n.textContent = text;
|
|
12439
|
+
let none = text === "0" && !on.has(b.dataset.chip);
|
|
12440
|
+
if (b.hasAttribute("data-none") !== none)
|
|
12441
|
+
b.toggleAttribute("data-none", none);
|
|
12442
|
+
}
|
|
12443
|
+
},
|
|
12444
|
+
set(query, next) {
|
|
12445
|
+
let changed = !1;
|
|
12446
|
+
if (query !== void 0 && input.value !== query)
|
|
12447
|
+
input.value = query, changed = !0;
|
|
12448
|
+
if (next) {
|
|
12449
|
+
let want = new Set(next.filter((id) => chips.some((b) => b.dataset.chip === id)));
|
|
12450
|
+
if (want.size !== on.size || [...want].some((id) => !on.has(id))) {
|
|
12451
|
+
on.clear();
|
|
12452
|
+
for (let id of want)
|
|
12453
|
+
on.add(id);
|
|
12454
|
+
for (let b of chips)
|
|
12455
|
+
b.setAttribute("aria-pressed", String(on.has(b.dataset.chip)));
|
|
12456
|
+
changed = !0;
|
|
12457
|
+
}
|
|
12458
|
+
}
|
|
12459
|
+
if (changed)
|
|
12460
|
+
options.change();
|
|
12461
|
+
},
|
|
12462
|
+
clear() {
|
|
12463
|
+
let had = input.value !== "" || on.size > 0;
|
|
12464
|
+
input.value = "", on.clear();
|
|
12465
|
+
for (let b of chips)
|
|
12466
|
+
b.setAttribute("aria-pressed", "false");
|
|
12467
|
+
if (had)
|
|
12468
|
+
options.change();
|
|
12469
|
+
},
|
|
12470
|
+
focus() {
|
|
12471
|
+
input.focus({ preventScroll: !0 }), input.select();
|
|
12170
12472
|
}
|
|
12171
12473
|
};
|
|
12172
12474
|
}
|
|
12173
|
-
|
|
12174
|
-
|
|
12175
|
-
|
|
12176
|
-
|
|
12177
|
-
|
|
12178
|
-
|
|
12179
|
-
|
|
12180
|
-
|
|
12475
|
+
function matchSpan(text, query) {
|
|
12476
|
+
if (!query)
|
|
12477
|
+
return;
|
|
12478
|
+
let at = text.toLowerCase().indexOf(query);
|
|
12479
|
+
return at < 0 ? void 0 : [at, at + query.length];
|
|
12480
|
+
}
|
|
12481
|
+
function markLabel(label, text, span) {
|
|
12482
|
+
let doc = label.ownerDocument, parts = [];
|
|
12483
|
+
if (!span)
|
|
12484
|
+
parts.push(doc.createTextNode(text));
|
|
12485
|
+
else {
|
|
12486
|
+
if (span[0] > 0)
|
|
12487
|
+
parts.push(doc.createTextNode(text.slice(0, span[0])));
|
|
12488
|
+
let mark = doc.createElement("mark");
|
|
12489
|
+
if (mark.className = "knobs-match", mark.textContent = text.slice(span[0], span[1]), parts.push(mark), span[1] < text.length)
|
|
12490
|
+
parts.push(doc.createTextNode(text.slice(span[1])));
|
|
12491
|
+
}
|
|
12492
|
+
let current = [...label.childNodes].filter((c) => c.nodeType === 3 || c instanceof HTMLElement && c.classList.contains("knobs-match"));
|
|
12493
|
+
if (current.length === parts.length && current.every((c, i) => c.nodeName === parts[i].nodeName && c.textContent === parts[i].textContent))
|
|
12494
|
+
return;
|
|
12495
|
+
for (let c of current)
|
|
12496
|
+
c.remove();
|
|
12497
|
+
label.prepend(...parts);
|
|
12498
|
+
}
|
|
12181
12499
|
|
|
12182
12500
|
// src/ui/readout-model.ts
|
|
12183
12501
|
var SERIES_TOKENS = [
|
|
@@ -13454,69 +13772,6 @@ function readoutRow(c) {
|
|
|
13454
13772
|
};
|
|
13455
13773
|
}
|
|
13456
13774
|
|
|
13457
|
-
// src/ui/layer.ts
|
|
13458
|
-
var lookOf = (look) => ({ ...lookDefaults.current, ...look }), roots = /* @__PURE__ */ new WeakMap;
|
|
13459
|
-
function layerRoot(doc) {
|
|
13460
|
-
let root = roots.get(doc);
|
|
13461
|
-
if (root?.isConnected)
|
|
13462
|
-
return root;
|
|
13463
|
-
return root = doc.createElement("div"), root.className = "knobs-layers", doc.body.append(root), roots.set(doc, root), root;
|
|
13464
|
-
}
|
|
13465
|
-
function layerElement(doc, cls, look) {
|
|
13466
|
-
let el = doc.createElement("div");
|
|
13467
|
-
return el.className = cls, layerRoot(doc).append(el), applyLook2(el, lookOf(look)), el;
|
|
13468
|
-
}
|
|
13469
|
-
function presence(el, o = {}) {
|
|
13470
|
-
let win = el.ownerDocument.defaultView, spring = new Spring(0, 1, 1, 0.002), dx = o.dx ?? 0, dy = o.dy ?? 0, gone = [], shown = !1, render = () => {
|
|
13471
|
-
let reduced = reducedMotion(win), p = spring.x, q = Math.max(0, Math.min(1, p)), scale = reduced ? 1 : (o.scale ?? 0.94) + (1 - (o.scale ?? 0.94)) * p, blur = reduced ? 0 : (1 - q) * (o.blur ?? 6), t = reduced ? 0 : 1 - p;
|
|
13472
|
-
el.style.opacity = q.toFixed(3), el.style.transform = p === 1 ? "" : `translate(${(dx * t).toFixed(2)}px,${(dy * t).toFixed(2)}px) scale(${scale.toFixed(4)})`, el.style.filter = blur > 0.05 ? `blur(${blur.toFixed(2)}px)` : "", el.style.pointerEvents = shown ? "" : "none", o.onFrame?.(p);
|
|
13473
|
-
}, loop = frameLoop(win, (dt) => {
|
|
13474
|
-
if (spring.step(dt), render(), !spring.resting)
|
|
13475
|
-
return !0;
|
|
13476
|
-
if (!shown) {
|
|
13477
|
-
let done = gone;
|
|
13478
|
-
gone = [];
|
|
13479
|
-
for (let f of done)
|
|
13480
|
-
f();
|
|
13481
|
-
o.onGone?.();
|
|
13482
|
-
}
|
|
13483
|
-
return !1;
|
|
13484
|
-
}), tune = (seconds, zeta) => {
|
|
13485
|
-
let reduced = reducedMotion(win);
|
|
13486
|
-
spring.omega = 2 * Math.PI / (reduced ? FADE.duration : seconds), spring.zeta = reduced ? 1 : zeta;
|
|
13487
|
-
};
|
|
13488
|
-
return render(), {
|
|
13489
|
-
show() {
|
|
13490
|
-
shown = !0, gone = [], el.style.pointerEvents = "", tune(o.duration ?? 0.32, 1 - (o.bounce ?? 0.2)), spring.set(1), loop.wake();
|
|
13491
|
-
},
|
|
13492
|
-
hide() {
|
|
13493
|
-
return shown = !1, el.style.pointerEvents = "none", tune(o.exit ?? 0.2, 1), spring.set(0), loop.wake(), new Promise((resolve) => gone.push(resolve));
|
|
13494
|
-
},
|
|
13495
|
-
snap(to = 1) {
|
|
13496
|
-
if (shown = to === 1, spring.snap(to), loop.stop(), render(), !shown) {
|
|
13497
|
-
let done = gone;
|
|
13498
|
-
gone = [];
|
|
13499
|
-
for (let f of done)
|
|
13500
|
-
f();
|
|
13501
|
-
o.onGone?.();
|
|
13502
|
-
} else
|
|
13503
|
-
gone = [];
|
|
13504
|
-
},
|
|
13505
|
-
get shown() {
|
|
13506
|
-
return shown;
|
|
13507
|
-
},
|
|
13508
|
-
from(x, y) {
|
|
13509
|
-
dx = x, dy = y;
|
|
13510
|
-
},
|
|
13511
|
-
dispose() {
|
|
13512
|
-
loop.stop();
|
|
13513
|
-
for (let f of gone)
|
|
13514
|
-
f();
|
|
13515
|
-
gone = [];
|
|
13516
|
-
}
|
|
13517
|
-
};
|
|
13518
|
-
}
|
|
13519
|
-
|
|
13520
13775
|
// src/ui/toast.ts
|
|
13521
13776
|
var regions = /* @__PURE__ */ new WeakMap;
|
|
13522
13777
|
function toast(message, options = {}) {
|
|
@@ -14496,6 +14751,17 @@ function positionPanel(panel, header, anchor, id, storage) {
|
|
|
14496
14751
|
};
|
|
14497
14752
|
}
|
|
14498
14753
|
|
|
14754
|
+
// src/panel/dock.ts
|
|
14755
|
+
function paneHeadOf(host) {
|
|
14756
|
+
let head = host.closest(".knobs-pane-body")?.parentElement?.querySelector(":scope > .knobs-pane-head");
|
|
14757
|
+
return head && !head.querySelector(":scope > [data-docked]") ? head : void 0;
|
|
14758
|
+
}
|
|
14759
|
+
function dock(actions, head) {
|
|
14760
|
+
return actions.dataset.docked = "", head.insertBefore(actions, head.querySelector(":scope > .knobs-pane-collapse")), () => {
|
|
14761
|
+
actions.remove(), delete actions.dataset.docked;
|
|
14762
|
+
};
|
|
14763
|
+
}
|
|
14764
|
+
|
|
14499
14765
|
// src/panel/presence.ts
|
|
14500
14766
|
var EXIT = springMotion2(SPRINGS2.snappy), ENTER = springMotion2(SPRINGS2.default), FADE2 = springMotion2(FADE), BLUR2 = 4, SCALE = 0.96, LEAD2 = 0.4, FOLDED = [
|
|
14501
14767
|
"height",
|
|
@@ -14821,7 +15087,7 @@ function buildPanel(controls, host, options) {
|
|
|
14821
15087
|
randomButton.hidden = !0;
|
|
14822
15088
|
randomButton.onclick = (event) => run(() => reroll(void 0, event.altKey)), randomButton.querySelector(".knobs-icon")?.replaceWith(die.node);
|
|
14823
15089
|
let resetAll = () => {
|
|
14824
|
-
if (!resetBtn.hidden && resetBtn.dataset.shown === "true" &&
|
|
15090
|
+
if (!resetBtn.hidden && resetBtn.dataset.shown === "true" && headerShown())
|
|
14825
15091
|
turn(resetBtn);
|
|
14826
15092
|
cue(root, "reset"), controls.reset();
|
|
14827
15093
|
}, turn = (button) => {
|
|
@@ -14894,6 +15160,19 @@ function buildPanel(controls, host, options) {
|
|
|
14894
15160
|
header.append(titleEl, headActions);
|
|
14895
15161
|
if (options.header === !1 && !page)
|
|
14896
15162
|
header.hidden = !0;
|
|
15163
|
+
let untitled = !page && !header.hidden && !titleEl.textContent, paneHead = untitled && inline ? paneHeadOf(host) : void 0, undock = paneHead ? dock(headActions, paneHead) : void 0;
|
|
15164
|
+
if (undock)
|
|
15165
|
+
header.hidden = !0;
|
|
15166
|
+
let headerShown = () => Boolean(undock) || !header.hidden, syncBand = (animate) => {
|
|
15167
|
+
if (!untitled || undock)
|
|
15168
|
+
return;
|
|
15169
|
+
let any = headerButtons.some((b) => !b.button.hidden && b.button.dataset.shown !== "false");
|
|
15170
|
+
if (!animate)
|
|
15171
|
+
header.hidden = !any;
|
|
15172
|
+
else if ((!header.hidden && header.dataset.leaving !== "true") !== any)
|
|
15173
|
+
reveal(header, any, () => wakeGpu());
|
|
15174
|
+
};
|
|
15175
|
+
presetStrip.display(page ? "chips" : options.presetDisplay ?? "auto");
|
|
14897
15176
|
let allActions = [
|
|
14898
15177
|
...controls.actions ?? [],
|
|
14899
15178
|
...options.actions ?? []
|
|
@@ -15186,6 +15465,8 @@ function buildPanel(controls, host, options) {
|
|
|
15186
15465
|
}
|
|
15187
15466
|
let specs = [], placed = /* @__PURE__ */ new Set;
|
|
15188
15467
|
for (let [key, field] of entries) {
|
|
15468
|
+
if (field.kind === "choice" && field.variants && !controls.isPinned(key))
|
|
15469
|
+
continue;
|
|
15189
15470
|
let pair = field.kind === "knob" && field.spring ? halves.get(field.spring.id) : void 0;
|
|
15190
15471
|
if (pair?.duration && pair.bounce && field.kind === "knob" && field.spring) {
|
|
15191
15472
|
if (placed.has(field.spring.id))
|
|
@@ -15501,7 +15782,7 @@ function buildPanel(controls, host, options) {
|
|
|
15501
15782
|
writeSession(controls.id, { expanded: open ? [...others, key] : others });
|
|
15502
15783
|
},
|
|
15503
15784
|
...spec.parts ? { parts: spec.parts } : {}
|
|
15504
|
-
}, live = { ...context, field }, editor = field.kind === "spring" ? springRow({ ...context, field }) : field.kind === "color" ? colorRow({ ...context, field }) : field.kind === "point" ? pointRow({ ...context, field }) : field.kind === "easing" ? easingRow({ ...context, field }) : field.kind === "gradient" ? gradientRow({ ...context, field }) : field.kind === "curve" ? curveRow({ ...context, field }) : field.kind === "vec" ? vecRow(live) : field.kind === "range" ? rangeRow(live) : field.kind === "angle" ? angleRow(live) : field.kind === "seed" ? seedRow(live) : keybindRow(live);
|
|
15785
|
+
}, live = { ...context, field }, editor = field.kind === "spring" ? springRow({ ...context, field }) : field.kind === "color" ? colorRow({ ...context, field }) : field.kind === "point" ? pointRow({ ...context, field }) : field.kind === "easing" ? easingRow({ ...context, field }) : field.kind === "gradient" ? gradientRow({ ...context, field }) : field.kind === "curve" ? curveRow({ ...context, field }) : field.kind === "vec" ? vecRow(live) : field.kind === "range" ? rangeRow(live) : field.kind === "angle" ? angleRow(live) : field.kind === "seed" ? seedRow(live) : field.kind === "text" ? textRow(live) : keybindRow(live);
|
|
15505
15786
|
if (field.shortcut)
|
|
15506
15787
|
editor.input.setAttribute("aria-keyshortcuts", field.shortcut);
|
|
15507
15788
|
editor.labelEl.ondblclick = resetRow;
|
|
@@ -15651,6 +15932,8 @@ function buildPanel(controls, host, options) {
|
|
|
15651
15932
|
else
|
|
15652
15933
|
input.removeAttribute("aria-readonly");
|
|
15653
15934
|
}
|
|
15935
|
+
if (row.input.classList.contains("knobs-text"))
|
|
15936
|
+
row.input.readOnly = disabled || readOnly;
|
|
15654
15937
|
}
|
|
15655
15938
|
let rows = [], leavingRows = /* @__PURE__ */ new Set, presenceRuns = 0, present = (node, show, delay, after) => {
|
|
15656
15939
|
if (presenceRuns++, node.dataset.presence = show ? "in" : "out", show)
|
|
@@ -15914,7 +16197,12 @@ function buildPanel(controls, host, options) {
|
|
|
15914
16197
|
let keys = rows.flatMap((r) => {
|
|
15915
16198
|
let tab = tabOf(r);
|
|
15916
16199
|
return !pinnedRow(r) && (tab === void 0 || tab === activeTab) ? r.keys : [];
|
|
15917
|
-
});
|
|
16200
|
+
}), v = variantsOf(controls.schema, controls.isPinned);
|
|
16201
|
+
if (v) {
|
|
16202
|
+
let tab = v.field.tab ?? (v.field.group !== void 0 ? groupTab(v.field.group) : void 0);
|
|
16203
|
+
if (tab === void 0 || tab === activeTab)
|
|
16204
|
+
keys.push(v.key);
|
|
16205
|
+
}
|
|
15918
16206
|
return presetsTouch(entries, keys, controls.locked);
|
|
15919
16207
|
}
|
|
15920
16208
|
function syncTabs() {
|
|
@@ -16148,7 +16436,7 @@ function buildPanel(controls, host, options) {
|
|
|
16148
16436
|
apply.className = "knobs-apply-btn", apply.setAttribute("aria-label", "Import JSON"), apply.hidden = !0;
|
|
16149
16437
|
let copy = async (value, inPlace = !0) => {
|
|
16150
16438
|
try {
|
|
16151
|
-
if (await doc.defaultView.navigator.clipboard.writeText(value), inPlace && !copyButton.hidden &&
|
|
16439
|
+
if (await doc.defaultView.navigator.clipboard.writeText(value), inPlace && !copyButton.hidden && headerShown())
|
|
16152
16440
|
copied();
|
|
16153
16441
|
else
|
|
16154
16442
|
say("Copied.");
|
|
@@ -16200,6 +16488,9 @@ function buildPanel(controls, host, options) {
|
|
|
16200
16488
|
root.append(customActions);
|
|
16201
16489
|
root.append(text, apply, status, live);
|
|
16202
16490
|
}
|
|
16491
|
+
let emptyEl = el("p", options.empty);
|
|
16492
|
+
if (emptyEl.className = "knobs-empty", emptyEl.hidden = !0, options.empty && !page)
|
|
16493
|
+
body.after(emptyEl);
|
|
16203
16494
|
let shown = controls.get(), initialized = !1, cascade = (changedCount) => {
|
|
16204
16495
|
if (changedCount < 2)
|
|
16205
16496
|
return 0;
|
|
@@ -16245,6 +16536,8 @@ function buildPanel(controls, host, options) {
|
|
|
16245
16536
|
land();
|
|
16246
16537
|
if (controls.schema !== shape)
|
|
16247
16538
|
shape = controls.schema, layoutRows(initialized && !landing);
|
|
16539
|
+
if (emptyEl.isConnected && emptyEl.hidden !== rows.length > 0)
|
|
16540
|
+
emptyEl.hidden = rows.length > 0;
|
|
16248
16541
|
let values = controls.get(), before = shown, fresh = (r) => r.row.dataset.shown === void 0, changed = (r) => fresh(r) || Boolean(r.mixed) !== isMixed(r) || r.keys.some((k) => !same(values[k], before[k])), changedCount = 0;
|
|
16249
16542
|
if (initialized && !landing) {
|
|
16250
16543
|
for (let r of rows)
|
|
@@ -16343,7 +16636,7 @@ function buildPanel(controls, host, options) {
|
|
|
16343
16636
|
let undoMoved = bloom(undoButton, controls.canUndo);
|
|
16344
16637
|
if (bloom(redoButton, controls.canRedo) || undoMoved)
|
|
16345
16638
|
wakeGpu();
|
|
16346
|
-
if (controls.error && status.textContent !== controls.error)
|
|
16639
|
+
if (syncBand(initialized), controls.error && status.textContent !== controls.error)
|
|
16347
16640
|
say(controls.error, 8000);
|
|
16348
16641
|
for (let [group, c] of groupChips)
|
|
16349
16642
|
c.show(String(controls.matchingGroupPreset(group)));
|
|
@@ -16929,7 +17222,7 @@ function buildPanel(controls, host, options) {
|
|
|
16929
17222
|
wasArmed = armed, root.toggleAttribute("data-k-armed", armed), wakeGpu();
|
|
16930
17223
|
if (queueLens(), !popover.hidden)
|
|
16931
17224
|
describeScope();
|
|
16932
|
-
optionKeys.show("keyboard" in root.dataset ? optionsAt(active) : void 0);
|
|
17225
|
+
optionKeys.show("keyboard" in root.dataset ? optionsAt(active) ?? stripOptionsAt(active) : void 0);
|
|
16933
17226
|
}, scopeQueued = !1, queueScope = () => {
|
|
16934
17227
|
if (scopeQueued)
|
|
16935
17228
|
return;
|
|
@@ -16962,6 +17255,17 @@ function buildPanel(controls, host, options) {
|
|
|
16962
17255
|
if (!r || r.row.closest("[data-disabled],[data-readonly]"))
|
|
16963
17256
|
return;
|
|
16964
17257
|
return optionsOf(r);
|
|
17258
|
+
}, stripDigits = () => visible(presetStrip.element) && presetStrip.getEntries().length > 1, stripOptions = {
|
|
17259
|
+
get count() {
|
|
17260
|
+
return presetStrip.getEntries().length;
|
|
17261
|
+
},
|
|
17262
|
+
choose: (i) => presetStrip.select(i),
|
|
17263
|
+
shown: () => presetStrip.getButtons(),
|
|
17264
|
+
anchor: presetStrip.element
|
|
17265
|
+
}, stripOptionsAt = (node) => {
|
|
17266
|
+
if (hintCtrl.isActive || !node || !stripDigits())
|
|
17267
|
+
return;
|
|
17268
|
+
return (presetStrip.element.contains(node) || focusLevel(node) === "panel") && !presetStrip.nameField() ? stripOptions : void 0;
|
|
16965
17269
|
}, pickOption = (event) => {
|
|
16966
17270
|
if (!/^[1-9]$/.test(event.key) || event.altKey || event.shiftKey)
|
|
16967
17271
|
return !1;
|
|
@@ -17166,12 +17470,20 @@ function buildPanel(controls, host, options) {
|
|
|
17166
17470
|
event.preventDefault(), searchReturn = target, search.focus();
|
|
17167
17471
|
return;
|
|
17168
17472
|
}
|
|
17169
|
-
if (
|
|
17170
|
-
let group = focusedGroup(target);
|
|
17171
|
-
if (group && groupChips.has(group)) {
|
|
17473
|
+
if (/^[1-9]$/.test(key)) {
|
|
17474
|
+
let group = page ? focusedGroup(target) : void 0;
|
|
17475
|
+
if (Boolean(group && groupChips.has(group))) {
|
|
17172
17476
|
event.preventDefault(), run(() => applyGroupPreset(group, Number(key) - 1));
|
|
17173
17477
|
return;
|
|
17174
17478
|
}
|
|
17479
|
+
if (digitRoute(key, {
|
|
17480
|
+
options: !1,
|
|
17481
|
+
keeps: tracks.has(target),
|
|
17482
|
+
presets: stripDigits() ? presetStrip.getEntries().length : 0
|
|
17483
|
+
}) === "presets") {
|
|
17484
|
+
event.preventDefault(), presetStrip.select(Number(key) - 1);
|
|
17485
|
+
return;
|
|
17486
|
+
}
|
|
17175
17487
|
}
|
|
17176
17488
|
if (pressed("hint", event)) {
|
|
17177
17489
|
if (event.preventDefault(), hintScrollY = win?.scrollY ?? 0, !unregisterHints || !pageHints(doc).start())
|
|
@@ -17575,8 +17887,8 @@ function buildPanel(controls, host, options) {
|
|
|
17575
17887
|
inline,
|
|
17576
17888
|
header,
|
|
17577
17889
|
titleEl,
|
|
17578
|
-
headerButtons,
|
|
17579
|
-
headerDie: { button: randomButton, die },
|
|
17890
|
+
headerButtons: undock ? [] : headerButtons,
|
|
17891
|
+
...undock ? {} : { headerDie: { button: randomButton, die } },
|
|
17580
17892
|
locks: lockIcons,
|
|
17581
17893
|
presetStrip,
|
|
17582
17894
|
tabs: tabStrip,
|
|
@@ -17699,7 +18011,7 @@ function buildPanel(controls, host, options) {
|
|
|
17699
18011
|
inHand.clear(), positioned?.dispose(), die.dispose();
|
|
17700
18012
|
for (let g of groupDice.values())
|
|
17701
18013
|
g.die.dispose();
|
|
17702
|
-
menu?.close(!1), doc.removeEventListener("keyup", endCompare, !0), doc.defaultView?.removeEventListener("blur", endCompare), controls.compare(!1), morph?.dispose(), toggled?.dispose(), presence.dispose(), untrackHas(), unsubscribeSound(), optionKeys.dispose(), root.remove();
|
|
18014
|
+
menu?.close(!1), doc.removeEventListener("keyup", endCompare, !0), doc.defaultView?.removeEventListener("blur", endCompare), controls.compare(!1), morph?.dispose(), toggled?.dispose(), presence.dispose(), untrackHas(), unsubscribeSound(), optionKeys.dispose(), undock?.(), root.remove();
|
|
17703
18015
|
}
|
|
17704
18016
|
};
|
|
17705
18017
|
if (!layout)
|