@kitlangton/knobs 0.2.0 → 0.3.0
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 +135 -17
- package/dist/dev/{chunk-gezhc24g.js → chunk-7xgkerd2.js} +14 -5
- package/dist/dev/{chunk-5cr85vv6.js → chunk-jx1ktap3.js} +7843 -7933
- package/dist/dev/{chunk-693jd1gj.js → chunk-pmkvb9ep.js} +1544 -160
- package/dist/dev/{chunk-4km87zfx.js → chunk-v8ssbcbk.js} +18 -7
- package/dist/dev/index.js +187 -31
- package/dist/index.js +197 -33
- package/dist/panel.js +20260 -18462
- package/dist/types/core/keys.d.ts +2 -0
- package/dist/types/core/remote.d.ts +2 -0
- package/dist/types/core/schema.d.ts +5 -0
- package/dist/types/core/store.d.ts +29 -2
- package/dist/types/core/unlock.d.ts +77 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/panel/attach.d.ts +2 -0
- package/dist/types/panel/crumbs.d.ts +19 -0
- package/dist/types/panel/editors.d.ts +9 -0
- package/dist/types/panel/feel.d.ts +103 -0
- package/dist/types/panel/give.d.ts +34 -1
- package/dist/types/panel/gpu/color.d.ts +4 -4
- package/dist/types/panel/gpu/renderer.d.ts +32 -0
- package/dist/types/panel/gpu/shader.wgsl.d.ts +1 -1
- package/dist/types/panel/index.d.ts +2 -1
- package/dist/types/panel/inspector.d.ts +1 -1
- package/dist/types/panel/lens.d.ts +113 -0
- package/dist/types/panel/motion.d.ts +2 -0
- package/dist/types/panel/page-hints.d.ts +2 -1
- package/dist/types/panel/prefs.d.ts +2 -2
- package/dist/types/panel/presence.d.ts +20 -0
- package/dist/types/panel/scope.d.ts +29 -0
- package/dist/types/panel/slider.d.ts +21 -4
- package/dist/types/panel/tab-transition.d.ts +15 -0
- package/dist/types/panel/tabs.d.ts +1 -1
- package/dist/types/panel/toggle.d.ts +27 -0
- package/dist/types/ui/look.d.ts +1 -1
- package/dist/types/ui/scrollbar.d.ts +12 -0
- package/dist/types/ui/split-model.d.ts +4 -3
- package/dist/types/ui/split.d.ts +8 -6
- package/dist/ui-react.js +232 -132
- package/dist/ui-solid.js +232 -132
- package/dist/ui.js +285 -174
- package/package.json +1 -1
package/dist/ui-react.js
CHANGED
|
@@ -1126,7 +1126,7 @@ var open = springEasing(2 * Math.PI / 0.22, 1);
|
|
|
1126
1126
|
var activityCss = `
|
|
1127
1127
|
:where(.knobs-activity,.knobs-activity *){box-sizing:border-box}
|
|
1128
1128
|
:where(.knobs-activity){color-scheme:dark}
|
|
1129
|
-
.knobs-ui.knobs-activity{position:relative;display:block;height:100%;overflow:auto;overflow-anchor:none;outline:none;scrollbar-width:
|
|
1129
|
+
.knobs-ui.knobs-activity{position:relative;display:block;height:100%;overflow:auto;overflow-anchor:none;outline:none;scrollbar-width:none;overscroll-behavior:contain;user-select:none;-webkit-user-select:none;
|
|
1130
1130
|
font:var(--ku-font-weight) var(--ku-font-size)/1.35 var(--ku-font);color:var(--ku-text);text-align:left;letter-spacing:normal;-webkit-font-smoothing:antialiased;
|
|
1131
1131
|
--ka-gutter:var(--k-activity-gutter,28px);--ka-row:var(--k-activity-row,var(--ku-row));--ka-row-child:var(--k-activity-row-child,calc(var(--ka-row) - 6px));
|
|
1132
1132
|
--ka-line:var(--k-activity-line,var(--ku-line-hi));--ka-select:var(--k-activity-select,var(--ku-wash-hi));--ka-hover:var(--k-activity-hover,var(--ku-wash));
|
|
@@ -1477,6 +1477,121 @@ var readoutCss = `
|
|
|
1477
1477
|
@media(prefers-reduced-motion:reduce){.knobs-rd :where(*){transition:none!important}}
|
|
1478
1478
|
`;
|
|
1479
1479
|
|
|
1480
|
+
// src/core/keys.ts
|
|
1481
|
+
var MODS = ["Ctrl", "Alt", "Shift", "Meta"];
|
|
1482
|
+
var ALIASES = {
|
|
1483
|
+
ctrl: "Ctrl",
|
|
1484
|
+
control: "Ctrl",
|
|
1485
|
+
"⌃": "Ctrl",
|
|
1486
|
+
alt: "Alt",
|
|
1487
|
+
option: "Alt",
|
|
1488
|
+
opt: "Alt",
|
|
1489
|
+
"⌥": "Alt",
|
|
1490
|
+
shift: "Shift",
|
|
1491
|
+
"⇧": "Shift",
|
|
1492
|
+
meta: "Meta",
|
|
1493
|
+
cmd: "Meta",
|
|
1494
|
+
command: "Meta",
|
|
1495
|
+
"⌘": "Meta",
|
|
1496
|
+
mod: "Mod"
|
|
1497
|
+
};
|
|
1498
|
+
var NAMED = {
|
|
1499
|
+
" ": "Space",
|
|
1500
|
+
space: "Space",
|
|
1501
|
+
spacebar: "Space",
|
|
1502
|
+
esc: "Escape",
|
|
1503
|
+
escape: "Escape",
|
|
1504
|
+
enter: "Enter",
|
|
1505
|
+
return: "Enter",
|
|
1506
|
+
tab: "Tab",
|
|
1507
|
+
backspace: "Backspace",
|
|
1508
|
+
delete: "Delete",
|
|
1509
|
+
del: "Delete",
|
|
1510
|
+
up: "ArrowUp",
|
|
1511
|
+
down: "ArrowDown",
|
|
1512
|
+
left: "ArrowLeft",
|
|
1513
|
+
right: "ArrowRight",
|
|
1514
|
+
arrowup: "ArrowUp",
|
|
1515
|
+
arrowdown: "ArrowDown",
|
|
1516
|
+
arrowleft: "ArrowLeft",
|
|
1517
|
+
arrowright: "ArrowRight",
|
|
1518
|
+
home: "Home",
|
|
1519
|
+
end: "End",
|
|
1520
|
+
pageup: "PageUp",
|
|
1521
|
+
pagedown: "PageDown"
|
|
1522
|
+
};
|
|
1523
|
+
var isApple = () => typeof navigator !== "undefined" && /mac|iphone|ipad|ipod/i.test(navigator.userAgentData?.platform ?? navigator.platform ?? "");
|
|
1524
|
+
var keyName = (raw) => {
|
|
1525
|
+
if (!raw)
|
|
1526
|
+
return "";
|
|
1527
|
+
const named = NAMED[raw.toLowerCase()];
|
|
1528
|
+
if (named)
|
|
1529
|
+
return named;
|
|
1530
|
+
if (raw.length === 1)
|
|
1531
|
+
return raw.toUpperCase();
|
|
1532
|
+
if (/^f\d{1,2}$/i.test(raw))
|
|
1533
|
+
return raw.toUpperCase();
|
|
1534
|
+
return raw.charAt(0).toUpperCase() + raw.slice(1);
|
|
1535
|
+
};
|
|
1536
|
+
function normalizeCombo(combo) {
|
|
1537
|
+
const trimmed = combo.trim();
|
|
1538
|
+
if (!trimmed)
|
|
1539
|
+
return "";
|
|
1540
|
+
const parts = trimmed === "+" ? ["+"] : trimmed.replace(/\+\+$/, "+plus").split("+");
|
|
1541
|
+
const mods = new Set;
|
|
1542
|
+
let key = "";
|
|
1543
|
+
for (const part of parts) {
|
|
1544
|
+
const alias = ALIASES[part.trim().toLowerCase()] ?? ALIASES[part.trim()];
|
|
1545
|
+
if (alias === "Mod")
|
|
1546
|
+
mods.add(isApple() ? "Meta" : "Ctrl");
|
|
1547
|
+
else if (alias)
|
|
1548
|
+
mods.add(alias);
|
|
1549
|
+
else
|
|
1550
|
+
key = part === "plus" ? "+" : keyName(part.trim() || part);
|
|
1551
|
+
}
|
|
1552
|
+
if (!key)
|
|
1553
|
+
return "";
|
|
1554
|
+
return [...MODS.filter((m) => mods.has(m)), key].join("+");
|
|
1555
|
+
}
|
|
1556
|
+
var GLYPHS = { Ctrl: "⌃", Alt: "⌥", Shift: "⇧", Meta: "⌘" };
|
|
1557
|
+
var WORDS = { Ctrl: "Ctrl", Alt: "Alt", Shift: "Shift", Meta: "Meta" };
|
|
1558
|
+
var KEY_GLYPHS = {
|
|
1559
|
+
ArrowUp: "↑",
|
|
1560
|
+
ArrowDown: "↓",
|
|
1561
|
+
ArrowLeft: "←",
|
|
1562
|
+
ArrowRight: "→",
|
|
1563
|
+
Backspace: "⌫",
|
|
1564
|
+
Delete: "⌦",
|
|
1565
|
+
Enter: "↩",
|
|
1566
|
+
Escape: "Esc",
|
|
1567
|
+
Tab: "⇥",
|
|
1568
|
+
PageUp: "PgUp",
|
|
1569
|
+
PageDown: "PgDn"
|
|
1570
|
+
};
|
|
1571
|
+
function comboParts(combo, apple = isApple()) {
|
|
1572
|
+
const norm = normalizeCombo(combo);
|
|
1573
|
+
if (!norm)
|
|
1574
|
+
return [];
|
|
1575
|
+
const parts = norm === "+" ? ["+"] : norm.split("+");
|
|
1576
|
+
if (norm.endsWith("++"))
|
|
1577
|
+
parts.splice(-2, 2, "+");
|
|
1578
|
+
const key = parts.pop();
|
|
1579
|
+
const mods = parts;
|
|
1580
|
+
const shown = KEY_GLYPHS[key] ?? key;
|
|
1581
|
+
return apple ? [...mods.map((m) => GLYPHS[m]), shown] : [...mods.map((m) => WORDS[m]), shown];
|
|
1582
|
+
}
|
|
1583
|
+
function isTypingTarget(target) {
|
|
1584
|
+
const el = target;
|
|
1585
|
+
if (!el || typeof el.tagName !== "string")
|
|
1586
|
+
return false;
|
|
1587
|
+
const tag = el.tagName;
|
|
1588
|
+
if (tag === "SELECT" || el.isContentEditable)
|
|
1589
|
+
return true;
|
|
1590
|
+
if (tag === "TEXTAREA")
|
|
1591
|
+
return !el.readOnly;
|
|
1592
|
+
return tag === "INPUT" && !el.readOnly && !["range", "checkbox", "radio", "button", "submit", "reset", "color"].includes(el.type);
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1480
1595
|
// src/ui/look.ts
|
|
1481
1596
|
var ease = springEasing(26, 1);
|
|
1482
1597
|
var TOKENS = {
|
|
@@ -1594,6 +1709,17 @@ var css = `
|
|
|
1594
1709
|
}
|
|
1595
1710
|
@supports not (animation-timeline:scroll()){.knobs-scroll-fade-x{text-overflow:ellipsis}}
|
|
1596
1711
|
|
|
1712
|
+
/* Overlay scrollbars (trees, activity rails): a thin thumb over the content, so the rows never
|
|
1713
|
+
give up width to a scrollbar as they start or stop overflowing. It shows while the content
|
|
1714
|
+
scrolls or the pointer is over it. */
|
|
1715
|
+
:is(.knobs-tree,.knobs-activity)::-webkit-scrollbar{display:none}
|
|
1716
|
+
.knobs-scrollbar{position:sticky;top:0;z-index:3;height:0;pointer-events:none}
|
|
1717
|
+
.knobs-scrollbar[hidden]{display:none}
|
|
1718
|
+
.knobs-scrollbar-thumb{position:absolute;top:0;right:2px;width:5px;border-radius:3px;background:color-mix(in srgb,var(--ku-text) 30%,transparent);opacity:0;
|
|
1719
|
+
transition:opacity .3s ease-out,background .15s}
|
|
1720
|
+
:hover>.knobs-scrollbar>.knobs-scrollbar-thumb,.knobs-scrollbar:is([data-active],[data-dragging])>.knobs-scrollbar-thumb{opacity:1;pointer-events:auto;transition-duration:.12s,.15s}
|
|
1721
|
+
.knobs-scrollbar-thumb:hover,.knobs-scrollbar[data-dragging]>.knobs-scrollbar-thumb{background:color-mix(in srgb,var(--ku-text) 48%,transparent)}
|
|
1722
|
+
|
|
1597
1723
|
/* Split: panes along a row or column, hairline dividers with a wider grip. */
|
|
1598
1724
|
.knobs-split{position:relative;display:flex;width:100%;height:100%;min-width:0;min-height:0;overflow:hidden}
|
|
1599
1725
|
.knobs-split[data-direction="column"]{flex-direction:column}
|
|
@@ -1630,7 +1756,11 @@ var css = `
|
|
|
1630
1756
|
.knobs-split[data-direction="column"]>.knobs-pane[data-edge="start"]>.knobs-pane-rail{bottom:0}
|
|
1631
1757
|
.knobs-split[data-direction="column"]>.knobs-pane[data-edge="end"]>.knobs-pane-rail{top:0}
|
|
1632
1758
|
.knobs-pane[data-collapsed]>.knobs-pane-rail{pointer-events:auto}
|
|
1633
|
-
|
|
1759
|
+
/* Its hover wash fades, rather than going in one frame as a click opens the pane. */
|
|
1760
|
+
.knobs-ui .knobs-pane-rail::before{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--ku-wash);opacity:0;transition:opacity .15s;pointer-events:none}
|
|
1761
|
+
.knobs-pane-rail>*{position:relative}
|
|
1762
|
+
.knobs-ui .knobs-pane[data-collapsed]>.knobs-pane-rail:is(:hover,:focus-visible){color:var(--ku-text)}
|
|
1763
|
+
.knobs-ui .knobs-pane[data-collapsed]>.knobs-pane-rail:is(:hover,:focus-visible)::before{opacity:1}
|
|
1634
1764
|
.knobs-pane-rail-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
1635
1765
|
.knobs-pane-chevron{display:flex;flex:none;width:11px;height:11px;writing-mode:horizontal-tb;color:var(--ku-dim)}
|
|
1636
1766
|
.knobs-pane-turn{display:flex;width:100%;height:100%;transform-origin:50% 50%}
|
|
@@ -1667,7 +1797,7 @@ var css = `
|
|
|
1667
1797
|
:root[data-knobs-resizing] :is(iframe,canvas:not(.knobs-gpu-canvas)){pointer-events:none}
|
|
1668
1798
|
|
|
1669
1799
|
/* Tree: one scroller, rows placed by transform, only those near the view in the DOM. */
|
|
1670
|
-
.knobs-tree{position:relative;overflow:auto;height:100%;outline:none;scrollbar-width:
|
|
1800
|
+
.knobs-tree{position:relative;overflow:auto;height:100%;outline:none;scrollbar-width:none;overscroll-behavior:contain;user-select:none;-webkit-user-select:none}
|
|
1671
1801
|
.knobs-tree-space{position:relative;width:100%;pointer-events:none}
|
|
1672
1802
|
.knobs-tree-row{position:absolute;left:var(--ku-row-x);right:var(--ku-row-x);top:0;display:flex;align-items:center;height:var(--ku-row);padding-right:calc(var(--ku-inset) - 4px);
|
|
1673
1803
|
color:var(--ku-text);white-space:nowrap;cursor:default;will-change:transform;contain:layout style}
|
|
@@ -1819,7 +1949,6 @@ var tune = (s, m) => {
|
|
|
1819
1949
|
s.zeta = m.zeta;
|
|
1820
1950
|
return s;
|
|
1821
1951
|
};
|
|
1822
|
-
var isTypingTarget = (t) => t instanceof HTMLElement && (t.isContentEditable || t instanceof HTMLSelectElement || t instanceof HTMLTextAreaElement || t instanceof HTMLInputElement && !t.readOnly && !["range", "checkbox", "radio", "button"].includes(t.type));
|
|
1823
1952
|
function notifyLayout(doc) {
|
|
1824
1953
|
doc.dispatchEvent(new Event("knobs-layout"));
|
|
1825
1954
|
}
|
|
@@ -1859,6 +1988,79 @@ var ICONS = {
|
|
|
1859
1988
|
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"/>')
|
|
1860
1989
|
};
|
|
1861
1990
|
|
|
1991
|
+
// src/ui/scrollbar.ts
|
|
1992
|
+
function overlayScrollbar(scroller, content) {
|
|
1993
|
+
const doc = scroller.ownerDocument;
|
|
1994
|
+
const win = doc.defaultView;
|
|
1995
|
+
const track = doc.createElement("div");
|
|
1996
|
+
track.className = "knobs-scrollbar";
|
|
1997
|
+
track.setAttribute("aria-hidden", "true");
|
|
1998
|
+
const thumb = doc.createElement("div");
|
|
1999
|
+
thumb.className = "knobs-scrollbar-thumb";
|
|
2000
|
+
track.append(thumb);
|
|
2001
|
+
scroller.prepend(track);
|
|
2002
|
+
let size = 0;
|
|
2003
|
+
const update = () => {
|
|
2004
|
+
const view = scroller.clientHeight;
|
|
2005
|
+
const over = scroller.scrollHeight - view;
|
|
2006
|
+
const shown = over > 1 && view > 0;
|
|
2007
|
+
track.hidden = !shown;
|
|
2008
|
+
if (!shown)
|
|
2009
|
+
return;
|
|
2010
|
+
size = Math.max(20, view * view / (view + over));
|
|
2011
|
+
const y = Math.min(over, Math.max(0, scroller.scrollTop)) / over * (view - size);
|
|
2012
|
+
thumb.style.height = `${size.toFixed(1)}px`;
|
|
2013
|
+
thumb.style.transform = `translate3d(0,${y.toFixed(1)}px,0)`;
|
|
2014
|
+
};
|
|
2015
|
+
let idle = 0;
|
|
2016
|
+
const onScroll = () => {
|
|
2017
|
+
update();
|
|
2018
|
+
track.dataset.active = "";
|
|
2019
|
+
win.clearTimeout(idle);
|
|
2020
|
+
idle = win.setTimeout(() => delete track.dataset.active, 800);
|
|
2021
|
+
};
|
|
2022
|
+
scroller.addEventListener("scroll", onScroll, { passive: true });
|
|
2023
|
+
let drag;
|
|
2024
|
+
thumb.addEventListener("pointerdown", (e) => {
|
|
2025
|
+
if (e.button !== 0)
|
|
2026
|
+
return;
|
|
2027
|
+
e.preventDefault();
|
|
2028
|
+
e.stopPropagation();
|
|
2029
|
+
drag = { y: e.clientY, top: scroller.scrollTop, pointer: e.pointerId };
|
|
2030
|
+
thumb.setPointerCapture(e.pointerId);
|
|
2031
|
+
track.dataset.dragging = "";
|
|
2032
|
+
});
|
|
2033
|
+
thumb.addEventListener("pointermove", (e) => {
|
|
2034
|
+
if (!drag || e.pointerId !== drag.pointer)
|
|
2035
|
+
return;
|
|
2036
|
+
const view = scroller.clientHeight;
|
|
2037
|
+
const over = scroller.scrollHeight - view;
|
|
2038
|
+
scroller.scrollTop = drag.top + (e.clientY - drag.y) * over / Math.max(1, view - size);
|
|
2039
|
+
});
|
|
2040
|
+
const end = (e) => {
|
|
2041
|
+
if (!drag || e.pointerId !== drag.pointer)
|
|
2042
|
+
return;
|
|
2043
|
+
drag = undefined;
|
|
2044
|
+
delete track.dataset.dragging;
|
|
2045
|
+
};
|
|
2046
|
+
thumb.addEventListener("pointerup", end);
|
|
2047
|
+
thumb.addEventListener("pointercancel", end);
|
|
2048
|
+
thumb.addEventListener("lostpointercapture", end);
|
|
2049
|
+
const ro = new ResizeObserver(update);
|
|
2050
|
+
ro.observe(scroller);
|
|
2051
|
+
ro.observe(content);
|
|
2052
|
+
update();
|
|
2053
|
+
return {
|
|
2054
|
+
update,
|
|
2055
|
+
dispose() {
|
|
2056
|
+
ro.disconnect();
|
|
2057
|
+
win.clearTimeout(idle);
|
|
2058
|
+
scroller.removeEventListener("scroll", onScroll);
|
|
2059
|
+
track.remove();
|
|
2060
|
+
}
|
|
2061
|
+
};
|
|
2062
|
+
}
|
|
2063
|
+
|
|
1862
2064
|
// src/ui/activity.ts
|
|
1863
2065
|
var ACTIVITY_ICONS = {
|
|
1864
2066
|
you: svg('<circle cx="8" cy="5.5" r="2.5"/><path d="M3.2 13.5c.8-2.4 2.6-3.8 4.8-3.8s4 1.4 4.8 3.8"/>'),
|
|
@@ -1871,7 +2073,7 @@ var ACTIVITY_ICONS = {
|
|
|
1871
2073
|
shipped: svg('<circle cx="8" cy="8" r="5.8"/><path d="m5.6 8.2 1.7 1.7 3.2-3.6"/>')
|
|
1872
2074
|
};
|
|
1873
2075
|
var PLAY = '<svg viewBox="0 0 8 8" aria-hidden="true"><path d="M1.5 1v6l5.2-3Z" fill="currentColor"/></svg>';
|
|
1874
|
-
var REFLOW = springMotion({ duration: 0.
|
|
2076
|
+
var REFLOW = springMotion({ duration: 0.3, bounce: 0 });
|
|
1875
2077
|
var OPEN = springMotion({ duration: 0.22, bounce: 0 });
|
|
1876
2078
|
var CLOSE = springMotion({ duration: 0.18, bounce: 0 });
|
|
1877
2079
|
var BLOOM = springMotion({ duration: 0.3, bounce: 0 });
|
|
@@ -1914,6 +2116,7 @@ function activity(container, options) {
|
|
|
1914
2116
|
space.append(hl, line);
|
|
1915
2117
|
root.append(empty, space);
|
|
1916
2118
|
container.append(root);
|
|
2119
|
+
const scrollbar = overlayScrollbar(root, space);
|
|
1917
2120
|
let heights = [32, 26];
|
|
1918
2121
|
const measure = () => {
|
|
1919
2122
|
syncFrame(root);
|
|
@@ -2537,6 +2740,7 @@ function activity(container, options) {
|
|
|
2537
2740
|
destroy() {
|
|
2538
2741
|
loop.stop();
|
|
2539
2742
|
ro.disconnect();
|
|
2743
|
+
scrollbar.dispose();
|
|
2540
2744
|
if (keysFrom === "page") {
|
|
2541
2745
|
win.removeEventListener("keydown", onKey);
|
|
2542
2746
|
win.removeEventListener("pointerdown", onPointer, true);
|
|
@@ -2883,11 +3087,7 @@ var SLIDE_BY = 0.12;
|
|
|
2883
3087
|
var EXIT_BLUR = 3;
|
|
2884
3088
|
var px = (x) => new Spring(x, LAYOUT.omega, LAYOUT.zeta, 0.05);
|
|
2885
3089
|
var unit = (x) => new Spring(x, ENTER.omega, ENTER.zeta, 0.0005);
|
|
2886
|
-
var drive = (s, m, target) =>
|
|
2887
|
-
s.omega = m.omega;
|
|
2888
|
-
s.zeta = m.zeta;
|
|
2889
|
-
return s.set(target);
|
|
2890
|
-
};
|
|
3090
|
+
var drive = (s, m, target) => tune(s, m).set(target);
|
|
2891
3091
|
var probed = new Map;
|
|
2892
3092
|
var smallest = (srcset) => {
|
|
2893
3093
|
let best;
|
|
@@ -3648,7 +3848,7 @@ function bento(container, options) {
|
|
|
3648
3848
|
}
|
|
3649
3849
|
zoomIn(t.id);
|
|
3650
3850
|
};
|
|
3651
|
-
const typing = (target) => target
|
|
3851
|
+
const typing = (target) => target !== root && isTypingTarget(target);
|
|
3652
3852
|
const reveal = (id) => {
|
|
3653
3853
|
const r = rectOf(id);
|
|
3654
3854
|
if (!r)
|
|
@@ -4637,15 +4837,7 @@ function claimsHintKey(doc, key) {
|
|
|
4637
4837
|
const holder = doc;
|
|
4638
4838
|
return key === PAGE_HINT_KEY && Boolean(holder[KEY]?.listening);
|
|
4639
4839
|
}
|
|
4640
|
-
var isTyping =
|
|
4641
|
-
const el = target;
|
|
4642
|
-
if (!el || typeof el.tagName !== "string")
|
|
4643
|
-
return false;
|
|
4644
|
-
const tag = el.tagName;
|
|
4645
|
-
if (tag === "TEXTAREA" || tag === "SELECT" || el.isContentEditable)
|
|
4646
|
-
return true;
|
|
4647
|
-
return tag === "INPUT" && !["range", "checkbox", "radio", "button", "submit", "reset", "color"].includes(el.type);
|
|
4648
|
-
};
|
|
4840
|
+
var isTyping = isTypingTarget;
|
|
4649
4841
|
var PRESSABLE = "button,a[href],summary,[role=button],[role=tab],[role=radio],[role=switch],[role=checkbox],[role=menuitem],[role=option]";
|
|
4650
4842
|
function activateElement(el) {
|
|
4651
4843
|
const pressable = el.matches(PRESSABLE) || el.tabIndex < 0 && !el.matches("input,select,textarea");
|
|
@@ -5025,110 +5217,6 @@ function layerPainter(doc, groups) {
|
|
|
5025
5217
|
};
|
|
5026
5218
|
}
|
|
5027
5219
|
|
|
5028
|
-
// src/core/keys.ts
|
|
5029
|
-
var MODS = ["Ctrl", "Alt", "Shift", "Meta"];
|
|
5030
|
-
var ALIASES = {
|
|
5031
|
-
ctrl: "Ctrl",
|
|
5032
|
-
control: "Ctrl",
|
|
5033
|
-
"⌃": "Ctrl",
|
|
5034
|
-
alt: "Alt",
|
|
5035
|
-
option: "Alt",
|
|
5036
|
-
opt: "Alt",
|
|
5037
|
-
"⌥": "Alt",
|
|
5038
|
-
shift: "Shift",
|
|
5039
|
-
"⇧": "Shift",
|
|
5040
|
-
meta: "Meta",
|
|
5041
|
-
cmd: "Meta",
|
|
5042
|
-
command: "Meta",
|
|
5043
|
-
"⌘": "Meta",
|
|
5044
|
-
mod: "Mod"
|
|
5045
|
-
};
|
|
5046
|
-
var NAMED = {
|
|
5047
|
-
" ": "Space",
|
|
5048
|
-
space: "Space",
|
|
5049
|
-
spacebar: "Space",
|
|
5050
|
-
esc: "Escape",
|
|
5051
|
-
escape: "Escape",
|
|
5052
|
-
enter: "Enter",
|
|
5053
|
-
return: "Enter",
|
|
5054
|
-
tab: "Tab",
|
|
5055
|
-
backspace: "Backspace",
|
|
5056
|
-
delete: "Delete",
|
|
5057
|
-
del: "Delete",
|
|
5058
|
-
up: "ArrowUp",
|
|
5059
|
-
down: "ArrowDown",
|
|
5060
|
-
left: "ArrowLeft",
|
|
5061
|
-
right: "ArrowRight",
|
|
5062
|
-
arrowup: "ArrowUp",
|
|
5063
|
-
arrowdown: "ArrowDown",
|
|
5064
|
-
arrowleft: "ArrowLeft",
|
|
5065
|
-
arrowright: "ArrowRight",
|
|
5066
|
-
home: "Home",
|
|
5067
|
-
end: "End",
|
|
5068
|
-
pageup: "PageUp",
|
|
5069
|
-
pagedown: "PageDown"
|
|
5070
|
-
};
|
|
5071
|
-
var isApple = () => typeof navigator !== "undefined" && /mac|iphone|ipad|ipod/i.test(navigator.userAgentData?.platform ?? navigator.platform ?? "");
|
|
5072
|
-
var keyName = (raw) => {
|
|
5073
|
-
if (!raw)
|
|
5074
|
-
return "";
|
|
5075
|
-
const named = NAMED[raw.toLowerCase()];
|
|
5076
|
-
if (named)
|
|
5077
|
-
return named;
|
|
5078
|
-
if (raw.length === 1)
|
|
5079
|
-
return raw.toUpperCase();
|
|
5080
|
-
if (/^f\d{1,2}$/i.test(raw))
|
|
5081
|
-
return raw.toUpperCase();
|
|
5082
|
-
return raw.charAt(0).toUpperCase() + raw.slice(1);
|
|
5083
|
-
};
|
|
5084
|
-
function normalizeCombo(combo) {
|
|
5085
|
-
const trimmed = combo.trim();
|
|
5086
|
-
if (!trimmed)
|
|
5087
|
-
return "";
|
|
5088
|
-
const parts = trimmed === "+" ? ["+"] : trimmed.replace(/\+\+$/, "+plus").split("+");
|
|
5089
|
-
const mods = new Set;
|
|
5090
|
-
let key = "";
|
|
5091
|
-
for (const part of parts) {
|
|
5092
|
-
const alias = ALIASES[part.trim().toLowerCase()] ?? ALIASES[part.trim()];
|
|
5093
|
-
if (alias === "Mod")
|
|
5094
|
-
mods.add(isApple() ? "Meta" : "Ctrl");
|
|
5095
|
-
else if (alias)
|
|
5096
|
-
mods.add(alias);
|
|
5097
|
-
else
|
|
5098
|
-
key = part === "plus" ? "+" : keyName(part.trim() || part);
|
|
5099
|
-
}
|
|
5100
|
-
if (!key)
|
|
5101
|
-
return "";
|
|
5102
|
-
return [...MODS.filter((m) => mods.has(m)), key].join("+");
|
|
5103
|
-
}
|
|
5104
|
-
var GLYPHS = { Ctrl: "⌃", Alt: "⌥", Shift: "⇧", Meta: "⌘" };
|
|
5105
|
-
var WORDS = { Ctrl: "Ctrl", Alt: "Alt", Shift: "Shift", Meta: "Meta" };
|
|
5106
|
-
var KEY_GLYPHS = {
|
|
5107
|
-
ArrowUp: "↑",
|
|
5108
|
-
ArrowDown: "↓",
|
|
5109
|
-
ArrowLeft: "←",
|
|
5110
|
-
ArrowRight: "→",
|
|
5111
|
-
Backspace: "⌫",
|
|
5112
|
-
Delete: "⌦",
|
|
5113
|
-
Enter: "↩",
|
|
5114
|
-
Escape: "Esc",
|
|
5115
|
-
Tab: "⇥",
|
|
5116
|
-
PageUp: "PgUp",
|
|
5117
|
-
PageDown: "PgDn"
|
|
5118
|
-
};
|
|
5119
|
-
function comboParts(combo, apple = isApple()) {
|
|
5120
|
-
const norm = normalizeCombo(combo);
|
|
5121
|
-
if (!norm)
|
|
5122
|
-
return [];
|
|
5123
|
-
const parts = norm === "+" ? ["+"] : norm.split("+");
|
|
5124
|
-
if (norm.endsWith("++"))
|
|
5125
|
-
parts.splice(-2, 2, "+");
|
|
5126
|
-
const key = parts.pop();
|
|
5127
|
-
const mods = parts;
|
|
5128
|
-
const shown = KEY_GLYPHS[key] ?? key;
|
|
5129
|
-
return apple ? [...mods.map((m) => GLYPHS[m]), shown] : [...mods.map((m) => WORDS[m]), shown];
|
|
5130
|
-
}
|
|
5131
|
-
|
|
5132
5220
|
// src/ui/layer.ts
|
|
5133
5221
|
var lookOf = (look) => ({ ...lookDefaults.current, ...look });
|
|
5134
5222
|
var roots = new WeakMap;
|
|
@@ -5701,10 +5789,10 @@ function foldFaces(prev, p) {
|
|
|
5701
5789
|
function chevronTurn(p, edge) {
|
|
5702
5790
|
return (edge === "start" ? 180 : -180) * (1 - clamp01(p));
|
|
5703
5791
|
}
|
|
5704
|
-
function chevronFlip(f) {
|
|
5705
|
-
return
|
|
5792
|
+
function chevronFlip(f, edge) {
|
|
5793
|
+
return chevronTurn(f, edge);
|
|
5706
5794
|
}
|
|
5707
|
-
var FOLD_STYLE = { chevron: "flip", title: "travel", duration: 0.
|
|
5795
|
+
var FOLD_STYLE = { chevron: "flip", title: "travel", duration: 0.25 };
|
|
5708
5796
|
function foldStyle(options = {}) {
|
|
5709
5797
|
const duration = options.duration;
|
|
5710
5798
|
return {
|
|
@@ -5745,10 +5833,12 @@ function serializeLayout(layout) {
|
|
|
5745
5833
|
}
|
|
5746
5834
|
|
|
5747
5835
|
// src/ui/split.ts
|
|
5748
|
-
var FLIP = springMotion({ duration: 0.
|
|
5836
|
+
var FLIP = springMotion({ duration: 0.25, bounce: 0 });
|
|
5837
|
+
var FLIP_DEPTH = 28;
|
|
5749
5838
|
var SETTLE = springMotion({ duration: 0.3, bounce: 0 });
|
|
5750
5839
|
var CONTENT_BLUR = 3;
|
|
5751
5840
|
var LABEL_BLUR = 2;
|
|
5841
|
+
var COUNT_CLEAR = 0.12;
|
|
5752
5842
|
var put = (el, prop, value) => {
|
|
5753
5843
|
if (el.style.getPropertyValue(prop) !== value)
|
|
5754
5844
|
el.style.setProperty(prop, value);
|
|
@@ -5885,7 +5975,12 @@ function split(container, options) {
|
|
|
5885
5975
|
if (!row) {
|
|
5886
5976
|
head.dataset.toggles = "";
|
|
5887
5977
|
head.addEventListener("click", () => setCollapsed(spec.id, !collapsed[spec.id]));
|
|
5888
|
-
}
|
|
5978
|
+
} else
|
|
5979
|
+
head.addEventListener("dblclick", (e) => {
|
|
5980
|
+
if (e.target.closest(".knobs-pane-btn"))
|
|
5981
|
+
return;
|
|
5982
|
+
setCollapsed(spec.id, true);
|
|
5983
|
+
});
|
|
5889
5984
|
}
|
|
5890
5985
|
inner.append(head);
|
|
5891
5986
|
view.head = head;
|
|
@@ -6054,6 +6149,8 @@ function split(container, options) {
|
|
|
6054
6149
|
const label = v.railLabel;
|
|
6055
6150
|
const travel = morph && style.title === "travel" && Boolean(v.titleEl) && label.textContent === v.titleEl.textContent;
|
|
6056
6151
|
v.el.toggleAttribute("data-travel", travel && folding);
|
|
6152
|
+
if (v.countEl)
|
|
6153
|
+
put(v.countEl, "opacity", travel && folding && p > 0 ? Math.max(0, 1 - p / COUNT_CLEAR).toFixed(3) : "");
|
|
6057
6154
|
const k = 1 - p;
|
|
6058
6155
|
if (travel && !folding) {
|
|
6059
6156
|
put(label, "opacity", "0");
|
|
@@ -6081,8 +6178,9 @@ function split(container, options) {
|
|
|
6081
6178
|
if (style.chevron === "turn")
|
|
6082
6179
|
put(v.turn, "transform", k === 0 ? "" : `${move} rotate(${chevronTurn(p, v.edge).toFixed(2)}deg) ${size}`);
|
|
6083
6180
|
else {
|
|
6084
|
-
const
|
|
6085
|
-
|
|
6181
|
+
const turn = chevronFlip(v.flip.x, v.edge);
|
|
6182
|
+
const over = v.flip.resting ? turn === 0 ? "" : "scaleX(-1)" : `perspective(${FLIP_DEPTH}px) rotateY(${turn.toFixed(2)}deg)`;
|
|
6183
|
+
put(v.turn, "transform", k === 0 && !over ? "" : `${move} ${size} ${over}`);
|
|
6086
6184
|
}
|
|
6087
6185
|
} else {
|
|
6088
6186
|
const a = v.faces.rail;
|
|
@@ -8086,7 +8184,7 @@ function virtualWindow(scrollTop, height, rowHeight, count, overscan = 6) {
|
|
|
8086
8184
|
}
|
|
8087
8185
|
|
|
8088
8186
|
// src/ui/tree.ts
|
|
8089
|
-
var MOVE = springMotion({ duration: 0.
|
|
8187
|
+
var MOVE = springMotion({ duration: 0.3, bounce: 0 });
|
|
8090
8188
|
var EDGE = 28;
|
|
8091
8189
|
function tree(container, options) {
|
|
8092
8190
|
const doc = container.ownerDocument;
|
|
@@ -8125,6 +8223,7 @@ function tree(container, options) {
|
|
|
8125
8223
|
empty.hidden = true;
|
|
8126
8224
|
root.append(space, line, empty);
|
|
8127
8225
|
container.append(root);
|
|
8226
|
+
const scrollbar = overlayScrollbar(root, space);
|
|
8128
8227
|
let h = 26;
|
|
8129
8228
|
let indent = 14;
|
|
8130
8229
|
let inset = 8;
|
|
@@ -8974,6 +9073,7 @@ function tree(container, options) {
|
|
|
8974
9073
|
loop.stop();
|
|
8975
9074
|
autoScroll.stop();
|
|
8976
9075
|
ro.disconnect();
|
|
9076
|
+
scrollbar.dispose();
|
|
8977
9077
|
dragging?.ghost.remove();
|
|
8978
9078
|
root.remove();
|
|
8979
9079
|
}
|