@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-solid.js
CHANGED
|
@@ -1155,7 +1155,7 @@ var open = springEasing(2 * Math.PI / 0.22, 1);
|
|
|
1155
1155
|
var activityCss = `
|
|
1156
1156
|
:where(.knobs-activity,.knobs-activity *){box-sizing:border-box}
|
|
1157
1157
|
:where(.knobs-activity){color-scheme:dark}
|
|
1158
|
-
.knobs-ui.knobs-activity{position:relative;display:block;height:100%;overflow:auto;overflow-anchor:none;outline:none;scrollbar-width:
|
|
1158
|
+
.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;
|
|
1159
1159
|
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;
|
|
1160
1160
|
--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));
|
|
1161
1161
|
--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));
|
|
@@ -1506,6 +1506,121 @@ var readoutCss = `
|
|
|
1506
1506
|
@media(prefers-reduced-motion:reduce){.knobs-rd :where(*){transition:none!important}}
|
|
1507
1507
|
`;
|
|
1508
1508
|
|
|
1509
|
+
// src/core/keys.ts
|
|
1510
|
+
var MODS = ["Ctrl", "Alt", "Shift", "Meta"];
|
|
1511
|
+
var ALIASES = {
|
|
1512
|
+
ctrl: "Ctrl",
|
|
1513
|
+
control: "Ctrl",
|
|
1514
|
+
"⌃": "Ctrl",
|
|
1515
|
+
alt: "Alt",
|
|
1516
|
+
option: "Alt",
|
|
1517
|
+
opt: "Alt",
|
|
1518
|
+
"⌥": "Alt",
|
|
1519
|
+
shift: "Shift",
|
|
1520
|
+
"⇧": "Shift",
|
|
1521
|
+
meta: "Meta",
|
|
1522
|
+
cmd: "Meta",
|
|
1523
|
+
command: "Meta",
|
|
1524
|
+
"⌘": "Meta",
|
|
1525
|
+
mod: "Mod"
|
|
1526
|
+
};
|
|
1527
|
+
var NAMED = {
|
|
1528
|
+
" ": "Space",
|
|
1529
|
+
space: "Space",
|
|
1530
|
+
spacebar: "Space",
|
|
1531
|
+
esc: "Escape",
|
|
1532
|
+
escape: "Escape",
|
|
1533
|
+
enter: "Enter",
|
|
1534
|
+
return: "Enter",
|
|
1535
|
+
tab: "Tab",
|
|
1536
|
+
backspace: "Backspace",
|
|
1537
|
+
delete: "Delete",
|
|
1538
|
+
del: "Delete",
|
|
1539
|
+
up: "ArrowUp",
|
|
1540
|
+
down: "ArrowDown",
|
|
1541
|
+
left: "ArrowLeft",
|
|
1542
|
+
right: "ArrowRight",
|
|
1543
|
+
arrowup: "ArrowUp",
|
|
1544
|
+
arrowdown: "ArrowDown",
|
|
1545
|
+
arrowleft: "ArrowLeft",
|
|
1546
|
+
arrowright: "ArrowRight",
|
|
1547
|
+
home: "Home",
|
|
1548
|
+
end: "End",
|
|
1549
|
+
pageup: "PageUp",
|
|
1550
|
+
pagedown: "PageDown"
|
|
1551
|
+
};
|
|
1552
|
+
var isApple = () => typeof navigator !== "undefined" && /mac|iphone|ipad|ipod/i.test(navigator.userAgentData?.platform ?? navigator.platform ?? "");
|
|
1553
|
+
var keyName = (raw) => {
|
|
1554
|
+
if (!raw)
|
|
1555
|
+
return "";
|
|
1556
|
+
const named = NAMED[raw.toLowerCase()];
|
|
1557
|
+
if (named)
|
|
1558
|
+
return named;
|
|
1559
|
+
if (raw.length === 1)
|
|
1560
|
+
return raw.toUpperCase();
|
|
1561
|
+
if (/^f\d{1,2}$/i.test(raw))
|
|
1562
|
+
return raw.toUpperCase();
|
|
1563
|
+
return raw.charAt(0).toUpperCase() + raw.slice(1);
|
|
1564
|
+
};
|
|
1565
|
+
function normalizeCombo(combo) {
|
|
1566
|
+
const trimmed = combo.trim();
|
|
1567
|
+
if (!trimmed)
|
|
1568
|
+
return "";
|
|
1569
|
+
const parts = trimmed === "+" ? ["+"] : trimmed.replace(/\+\+$/, "+plus").split("+");
|
|
1570
|
+
const mods = new Set;
|
|
1571
|
+
let key = "";
|
|
1572
|
+
for (const part of parts) {
|
|
1573
|
+
const alias = ALIASES[part.trim().toLowerCase()] ?? ALIASES[part.trim()];
|
|
1574
|
+
if (alias === "Mod")
|
|
1575
|
+
mods.add(isApple() ? "Meta" : "Ctrl");
|
|
1576
|
+
else if (alias)
|
|
1577
|
+
mods.add(alias);
|
|
1578
|
+
else
|
|
1579
|
+
key = part === "plus" ? "+" : keyName(part.trim() || part);
|
|
1580
|
+
}
|
|
1581
|
+
if (!key)
|
|
1582
|
+
return "";
|
|
1583
|
+
return [...MODS.filter((m) => mods.has(m)), key].join("+");
|
|
1584
|
+
}
|
|
1585
|
+
var GLYPHS = { Ctrl: "⌃", Alt: "⌥", Shift: "⇧", Meta: "⌘" };
|
|
1586
|
+
var WORDS = { Ctrl: "Ctrl", Alt: "Alt", Shift: "Shift", Meta: "Meta" };
|
|
1587
|
+
var KEY_GLYPHS = {
|
|
1588
|
+
ArrowUp: "↑",
|
|
1589
|
+
ArrowDown: "↓",
|
|
1590
|
+
ArrowLeft: "←",
|
|
1591
|
+
ArrowRight: "→",
|
|
1592
|
+
Backspace: "⌫",
|
|
1593
|
+
Delete: "⌦",
|
|
1594
|
+
Enter: "↩",
|
|
1595
|
+
Escape: "Esc",
|
|
1596
|
+
Tab: "⇥",
|
|
1597
|
+
PageUp: "PgUp",
|
|
1598
|
+
PageDown: "PgDn"
|
|
1599
|
+
};
|
|
1600
|
+
function comboParts(combo, apple = isApple()) {
|
|
1601
|
+
const norm = normalizeCombo(combo);
|
|
1602
|
+
if (!norm)
|
|
1603
|
+
return [];
|
|
1604
|
+
const parts = norm === "+" ? ["+"] : norm.split("+");
|
|
1605
|
+
if (norm.endsWith("++"))
|
|
1606
|
+
parts.splice(-2, 2, "+");
|
|
1607
|
+
const key = parts.pop();
|
|
1608
|
+
const mods = parts;
|
|
1609
|
+
const shown = KEY_GLYPHS[key] ?? key;
|
|
1610
|
+
return apple ? [...mods.map((m) => GLYPHS[m]), shown] : [...mods.map((m) => WORDS[m]), shown];
|
|
1611
|
+
}
|
|
1612
|
+
function isTypingTarget(target) {
|
|
1613
|
+
const el = target;
|
|
1614
|
+
if (!el || typeof el.tagName !== "string")
|
|
1615
|
+
return false;
|
|
1616
|
+
const tag = el.tagName;
|
|
1617
|
+
if (tag === "SELECT" || el.isContentEditable)
|
|
1618
|
+
return true;
|
|
1619
|
+
if (tag === "TEXTAREA")
|
|
1620
|
+
return !el.readOnly;
|
|
1621
|
+
return tag === "INPUT" && !el.readOnly && !["range", "checkbox", "radio", "button", "submit", "reset", "color"].includes(el.type);
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1509
1624
|
// src/ui/look.ts
|
|
1510
1625
|
var ease = springEasing(26, 1);
|
|
1511
1626
|
var TOKENS = {
|
|
@@ -1623,6 +1738,17 @@ var css = `
|
|
|
1623
1738
|
}
|
|
1624
1739
|
@supports not (animation-timeline:scroll()){.knobs-scroll-fade-x{text-overflow:ellipsis}}
|
|
1625
1740
|
|
|
1741
|
+
/* Overlay scrollbars (trees, activity rails): a thin thumb over the content, so the rows never
|
|
1742
|
+
give up width to a scrollbar as they start or stop overflowing. It shows while the content
|
|
1743
|
+
scrolls or the pointer is over it. */
|
|
1744
|
+
:is(.knobs-tree,.knobs-activity)::-webkit-scrollbar{display:none}
|
|
1745
|
+
.knobs-scrollbar{position:sticky;top:0;z-index:3;height:0;pointer-events:none}
|
|
1746
|
+
.knobs-scrollbar[hidden]{display:none}
|
|
1747
|
+
.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;
|
|
1748
|
+
transition:opacity .3s ease-out,background .15s}
|
|
1749
|
+
: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}
|
|
1750
|
+
.knobs-scrollbar-thumb:hover,.knobs-scrollbar[data-dragging]>.knobs-scrollbar-thumb{background:color-mix(in srgb,var(--ku-text) 48%,transparent)}
|
|
1751
|
+
|
|
1626
1752
|
/* Split: panes along a row or column, hairline dividers with a wider grip. */
|
|
1627
1753
|
.knobs-split{position:relative;display:flex;width:100%;height:100%;min-width:0;min-height:0;overflow:hidden}
|
|
1628
1754
|
.knobs-split[data-direction="column"]{flex-direction:column}
|
|
@@ -1659,7 +1785,11 @@ var css = `
|
|
|
1659
1785
|
.knobs-split[data-direction="column"]>.knobs-pane[data-edge="start"]>.knobs-pane-rail{bottom:0}
|
|
1660
1786
|
.knobs-split[data-direction="column"]>.knobs-pane[data-edge="end"]>.knobs-pane-rail{top:0}
|
|
1661
1787
|
.knobs-pane[data-collapsed]>.knobs-pane-rail{pointer-events:auto}
|
|
1662
|
-
|
|
1788
|
+
/* Its hover wash fades, rather than going in one frame as a click opens the pane. */
|
|
1789
|
+
.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}
|
|
1790
|
+
.knobs-pane-rail>*{position:relative}
|
|
1791
|
+
.knobs-ui .knobs-pane[data-collapsed]>.knobs-pane-rail:is(:hover,:focus-visible){color:var(--ku-text)}
|
|
1792
|
+
.knobs-ui .knobs-pane[data-collapsed]>.knobs-pane-rail:is(:hover,:focus-visible)::before{opacity:1}
|
|
1663
1793
|
.knobs-pane-rail-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
1664
1794
|
.knobs-pane-chevron{display:flex;flex:none;width:11px;height:11px;writing-mode:horizontal-tb;color:var(--ku-dim)}
|
|
1665
1795
|
.knobs-pane-turn{display:flex;width:100%;height:100%;transform-origin:50% 50%}
|
|
@@ -1696,7 +1826,7 @@ var css = `
|
|
|
1696
1826
|
:root[data-knobs-resizing] :is(iframe,canvas:not(.knobs-gpu-canvas)){pointer-events:none}
|
|
1697
1827
|
|
|
1698
1828
|
/* Tree: one scroller, rows placed by transform, only those near the view in the DOM. */
|
|
1699
|
-
.knobs-tree{position:relative;overflow:auto;height:100%;outline:none;scrollbar-width:
|
|
1829
|
+
.knobs-tree{position:relative;overflow:auto;height:100%;outline:none;scrollbar-width:none;overscroll-behavior:contain;user-select:none;-webkit-user-select:none}
|
|
1700
1830
|
.knobs-tree-space{position:relative;width:100%;pointer-events:none}
|
|
1701
1831
|
.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);
|
|
1702
1832
|
color:var(--ku-text);white-space:nowrap;cursor:default;will-change:transform;contain:layout style}
|
|
@@ -1848,7 +1978,6 @@ var tune = (s, m) => {
|
|
|
1848
1978
|
s.zeta = m.zeta;
|
|
1849
1979
|
return s;
|
|
1850
1980
|
};
|
|
1851
|
-
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));
|
|
1852
1981
|
function notifyLayout(doc) {
|
|
1853
1982
|
doc.dispatchEvent(new Event("knobs-layout"));
|
|
1854
1983
|
}
|
|
@@ -1888,6 +2017,79 @@ var ICONS = {
|
|
|
1888
2017
|
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"/>')
|
|
1889
2018
|
};
|
|
1890
2019
|
|
|
2020
|
+
// src/ui/scrollbar.ts
|
|
2021
|
+
function overlayScrollbar(scroller, content) {
|
|
2022
|
+
const doc = scroller.ownerDocument;
|
|
2023
|
+
const win = doc.defaultView;
|
|
2024
|
+
const track = doc.createElement("div");
|
|
2025
|
+
track.className = "knobs-scrollbar";
|
|
2026
|
+
track.setAttribute("aria-hidden", "true");
|
|
2027
|
+
const thumb = doc.createElement("div");
|
|
2028
|
+
thumb.className = "knobs-scrollbar-thumb";
|
|
2029
|
+
track.append(thumb);
|
|
2030
|
+
scroller.prepend(track);
|
|
2031
|
+
let size = 0;
|
|
2032
|
+
const update = () => {
|
|
2033
|
+
const view = scroller.clientHeight;
|
|
2034
|
+
const over = scroller.scrollHeight - view;
|
|
2035
|
+
const shown = over > 1 && view > 0;
|
|
2036
|
+
track.hidden = !shown;
|
|
2037
|
+
if (!shown)
|
|
2038
|
+
return;
|
|
2039
|
+
size = Math.max(20, view * view / (view + over));
|
|
2040
|
+
const y = Math.min(over, Math.max(0, scroller.scrollTop)) / over * (view - size);
|
|
2041
|
+
thumb.style.height = `${size.toFixed(1)}px`;
|
|
2042
|
+
thumb.style.transform = `translate3d(0,${y.toFixed(1)}px,0)`;
|
|
2043
|
+
};
|
|
2044
|
+
let idle = 0;
|
|
2045
|
+
const onScroll = () => {
|
|
2046
|
+
update();
|
|
2047
|
+
track.dataset.active = "";
|
|
2048
|
+
win.clearTimeout(idle);
|
|
2049
|
+
idle = win.setTimeout(() => delete track.dataset.active, 800);
|
|
2050
|
+
};
|
|
2051
|
+
scroller.addEventListener("scroll", onScroll, { passive: true });
|
|
2052
|
+
let drag;
|
|
2053
|
+
thumb.addEventListener("pointerdown", (e) => {
|
|
2054
|
+
if (e.button !== 0)
|
|
2055
|
+
return;
|
|
2056
|
+
e.preventDefault();
|
|
2057
|
+
e.stopPropagation();
|
|
2058
|
+
drag = { y: e.clientY, top: scroller.scrollTop, pointer: e.pointerId };
|
|
2059
|
+
thumb.setPointerCapture(e.pointerId);
|
|
2060
|
+
track.dataset.dragging = "";
|
|
2061
|
+
});
|
|
2062
|
+
thumb.addEventListener("pointermove", (e) => {
|
|
2063
|
+
if (!drag || e.pointerId !== drag.pointer)
|
|
2064
|
+
return;
|
|
2065
|
+
const view = scroller.clientHeight;
|
|
2066
|
+
const over = scroller.scrollHeight - view;
|
|
2067
|
+
scroller.scrollTop = drag.top + (e.clientY - drag.y) * over / Math.max(1, view - size);
|
|
2068
|
+
});
|
|
2069
|
+
const end = (e) => {
|
|
2070
|
+
if (!drag || e.pointerId !== drag.pointer)
|
|
2071
|
+
return;
|
|
2072
|
+
drag = undefined;
|
|
2073
|
+
delete track.dataset.dragging;
|
|
2074
|
+
};
|
|
2075
|
+
thumb.addEventListener("pointerup", end);
|
|
2076
|
+
thumb.addEventListener("pointercancel", end);
|
|
2077
|
+
thumb.addEventListener("lostpointercapture", end);
|
|
2078
|
+
const ro = new ResizeObserver(update);
|
|
2079
|
+
ro.observe(scroller);
|
|
2080
|
+
ro.observe(content);
|
|
2081
|
+
update();
|
|
2082
|
+
return {
|
|
2083
|
+
update,
|
|
2084
|
+
dispose() {
|
|
2085
|
+
ro.disconnect();
|
|
2086
|
+
win.clearTimeout(idle);
|
|
2087
|
+
scroller.removeEventListener("scroll", onScroll);
|
|
2088
|
+
track.remove();
|
|
2089
|
+
}
|
|
2090
|
+
};
|
|
2091
|
+
}
|
|
2092
|
+
|
|
1891
2093
|
// src/ui/activity.ts
|
|
1892
2094
|
var ACTIVITY_ICONS = {
|
|
1893
2095
|
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"/>'),
|
|
@@ -1900,7 +2102,7 @@ var ACTIVITY_ICONS = {
|
|
|
1900
2102
|
shipped: svg('<circle cx="8" cy="8" r="5.8"/><path d="m5.6 8.2 1.7 1.7 3.2-3.6"/>')
|
|
1901
2103
|
};
|
|
1902
2104
|
var PLAY = '<svg viewBox="0 0 8 8" aria-hidden="true"><path d="M1.5 1v6l5.2-3Z" fill="currentColor"/></svg>';
|
|
1903
|
-
var REFLOW = springMotion({ duration: 0.
|
|
2105
|
+
var REFLOW = springMotion({ duration: 0.3, bounce: 0 });
|
|
1904
2106
|
var OPEN = springMotion({ duration: 0.22, bounce: 0 });
|
|
1905
2107
|
var CLOSE = springMotion({ duration: 0.18, bounce: 0 });
|
|
1906
2108
|
var BLOOM = springMotion({ duration: 0.3, bounce: 0 });
|
|
@@ -1943,6 +2145,7 @@ function activity(container, options) {
|
|
|
1943
2145
|
space.append(hl, line);
|
|
1944
2146
|
root.append(empty, space);
|
|
1945
2147
|
container.append(root);
|
|
2148
|
+
const scrollbar = overlayScrollbar(root, space);
|
|
1946
2149
|
let heights = [32, 26];
|
|
1947
2150
|
const measure = () => {
|
|
1948
2151
|
syncFrame(root);
|
|
@@ -2566,6 +2769,7 @@ function activity(container, options) {
|
|
|
2566
2769
|
destroy() {
|
|
2567
2770
|
loop.stop();
|
|
2568
2771
|
ro.disconnect();
|
|
2772
|
+
scrollbar.dispose();
|
|
2569
2773
|
if (keysFrom === "page") {
|
|
2570
2774
|
win.removeEventListener("keydown", onKey);
|
|
2571
2775
|
win.removeEventListener("pointerdown", onPointer, true);
|
|
@@ -2912,11 +3116,7 @@ var SLIDE_BY = 0.12;
|
|
|
2912
3116
|
var EXIT_BLUR = 3;
|
|
2913
3117
|
var px = (x) => new Spring(x, LAYOUT.omega, LAYOUT.zeta, 0.05);
|
|
2914
3118
|
var unit = (x) => new Spring(x, ENTER.omega, ENTER.zeta, 0.0005);
|
|
2915
|
-
var drive = (s, m, target) =>
|
|
2916
|
-
s.omega = m.omega;
|
|
2917
|
-
s.zeta = m.zeta;
|
|
2918
|
-
return s.set(target);
|
|
2919
|
-
};
|
|
3119
|
+
var drive = (s, m, target) => tune(s, m).set(target);
|
|
2920
3120
|
var probed = new Map;
|
|
2921
3121
|
var smallest = (srcset) => {
|
|
2922
3122
|
let best;
|
|
@@ -3677,7 +3877,7 @@ function bento(container, options) {
|
|
|
3677
3877
|
}
|
|
3678
3878
|
zoomIn(t.id);
|
|
3679
3879
|
};
|
|
3680
|
-
const typing = (target) => target
|
|
3880
|
+
const typing = (target) => target !== root && isTypingTarget(target);
|
|
3681
3881
|
const reveal = (id) => {
|
|
3682
3882
|
const r = rectOf(id);
|
|
3683
3883
|
if (!r)
|
|
@@ -4636,15 +4836,7 @@ function claimsHintKey(doc, key) {
|
|
|
4636
4836
|
const holder = doc;
|
|
4637
4837
|
return key === PAGE_HINT_KEY && Boolean(holder[KEY]?.listening);
|
|
4638
4838
|
}
|
|
4639
|
-
var isTyping =
|
|
4640
|
-
const el = target;
|
|
4641
|
-
if (!el || typeof el.tagName !== "string")
|
|
4642
|
-
return false;
|
|
4643
|
-
const tag = el.tagName;
|
|
4644
|
-
if (tag === "TEXTAREA" || tag === "SELECT" || el.isContentEditable)
|
|
4645
|
-
return true;
|
|
4646
|
-
return tag === "INPUT" && !["range", "checkbox", "radio", "button", "submit", "reset", "color"].includes(el.type);
|
|
4647
|
-
};
|
|
4839
|
+
var isTyping = isTypingTarget;
|
|
4648
4840
|
var PRESSABLE = "button,a[href],summary,[role=button],[role=tab],[role=radio],[role=switch],[role=checkbox],[role=menuitem],[role=option]";
|
|
4649
4841
|
function activateElement(el) {
|
|
4650
4842
|
const pressable = el.matches(PRESSABLE) || el.tabIndex < 0 && !el.matches("input,select,textarea");
|
|
@@ -5024,110 +5216,6 @@ function layerPainter(doc, groups) {
|
|
|
5024
5216
|
};
|
|
5025
5217
|
}
|
|
5026
5218
|
|
|
5027
|
-
// src/core/keys.ts
|
|
5028
|
-
var MODS = ["Ctrl", "Alt", "Shift", "Meta"];
|
|
5029
|
-
var ALIASES = {
|
|
5030
|
-
ctrl: "Ctrl",
|
|
5031
|
-
control: "Ctrl",
|
|
5032
|
-
"⌃": "Ctrl",
|
|
5033
|
-
alt: "Alt",
|
|
5034
|
-
option: "Alt",
|
|
5035
|
-
opt: "Alt",
|
|
5036
|
-
"⌥": "Alt",
|
|
5037
|
-
shift: "Shift",
|
|
5038
|
-
"⇧": "Shift",
|
|
5039
|
-
meta: "Meta",
|
|
5040
|
-
cmd: "Meta",
|
|
5041
|
-
command: "Meta",
|
|
5042
|
-
"⌘": "Meta",
|
|
5043
|
-
mod: "Mod"
|
|
5044
|
-
};
|
|
5045
|
-
var NAMED = {
|
|
5046
|
-
" ": "Space",
|
|
5047
|
-
space: "Space",
|
|
5048
|
-
spacebar: "Space",
|
|
5049
|
-
esc: "Escape",
|
|
5050
|
-
escape: "Escape",
|
|
5051
|
-
enter: "Enter",
|
|
5052
|
-
return: "Enter",
|
|
5053
|
-
tab: "Tab",
|
|
5054
|
-
backspace: "Backspace",
|
|
5055
|
-
delete: "Delete",
|
|
5056
|
-
del: "Delete",
|
|
5057
|
-
up: "ArrowUp",
|
|
5058
|
-
down: "ArrowDown",
|
|
5059
|
-
left: "ArrowLeft",
|
|
5060
|
-
right: "ArrowRight",
|
|
5061
|
-
arrowup: "ArrowUp",
|
|
5062
|
-
arrowdown: "ArrowDown",
|
|
5063
|
-
arrowleft: "ArrowLeft",
|
|
5064
|
-
arrowright: "ArrowRight",
|
|
5065
|
-
home: "Home",
|
|
5066
|
-
end: "End",
|
|
5067
|
-
pageup: "PageUp",
|
|
5068
|
-
pagedown: "PageDown"
|
|
5069
|
-
};
|
|
5070
|
-
var isApple = () => typeof navigator !== "undefined" && /mac|iphone|ipad|ipod/i.test(navigator.userAgentData?.platform ?? navigator.platform ?? "");
|
|
5071
|
-
var keyName = (raw) => {
|
|
5072
|
-
if (!raw)
|
|
5073
|
-
return "";
|
|
5074
|
-
const named = NAMED[raw.toLowerCase()];
|
|
5075
|
-
if (named)
|
|
5076
|
-
return named;
|
|
5077
|
-
if (raw.length === 1)
|
|
5078
|
-
return raw.toUpperCase();
|
|
5079
|
-
if (/^f\d{1,2}$/i.test(raw))
|
|
5080
|
-
return raw.toUpperCase();
|
|
5081
|
-
return raw.charAt(0).toUpperCase() + raw.slice(1);
|
|
5082
|
-
};
|
|
5083
|
-
function normalizeCombo(combo) {
|
|
5084
|
-
const trimmed = combo.trim();
|
|
5085
|
-
if (!trimmed)
|
|
5086
|
-
return "";
|
|
5087
|
-
const parts = trimmed === "+" ? ["+"] : trimmed.replace(/\+\+$/, "+plus").split("+");
|
|
5088
|
-
const mods = new Set;
|
|
5089
|
-
let key = "";
|
|
5090
|
-
for (const part of parts) {
|
|
5091
|
-
const alias = ALIASES[part.trim().toLowerCase()] ?? ALIASES[part.trim()];
|
|
5092
|
-
if (alias === "Mod")
|
|
5093
|
-
mods.add(isApple() ? "Meta" : "Ctrl");
|
|
5094
|
-
else if (alias)
|
|
5095
|
-
mods.add(alias);
|
|
5096
|
-
else
|
|
5097
|
-
key = part === "plus" ? "+" : keyName(part.trim() || part);
|
|
5098
|
-
}
|
|
5099
|
-
if (!key)
|
|
5100
|
-
return "";
|
|
5101
|
-
return [...MODS.filter((m) => mods.has(m)), key].join("+");
|
|
5102
|
-
}
|
|
5103
|
-
var GLYPHS = { Ctrl: "⌃", Alt: "⌥", Shift: "⇧", Meta: "⌘" };
|
|
5104
|
-
var WORDS = { Ctrl: "Ctrl", Alt: "Alt", Shift: "Shift", Meta: "Meta" };
|
|
5105
|
-
var KEY_GLYPHS = {
|
|
5106
|
-
ArrowUp: "↑",
|
|
5107
|
-
ArrowDown: "↓",
|
|
5108
|
-
ArrowLeft: "←",
|
|
5109
|
-
ArrowRight: "→",
|
|
5110
|
-
Backspace: "⌫",
|
|
5111
|
-
Delete: "⌦",
|
|
5112
|
-
Enter: "↩",
|
|
5113
|
-
Escape: "Esc",
|
|
5114
|
-
Tab: "⇥",
|
|
5115
|
-
PageUp: "PgUp",
|
|
5116
|
-
PageDown: "PgDn"
|
|
5117
|
-
};
|
|
5118
|
-
function comboParts(combo, apple = isApple()) {
|
|
5119
|
-
const norm = normalizeCombo(combo);
|
|
5120
|
-
if (!norm)
|
|
5121
|
-
return [];
|
|
5122
|
-
const parts = norm === "+" ? ["+"] : norm.split("+");
|
|
5123
|
-
if (norm.endsWith("++"))
|
|
5124
|
-
parts.splice(-2, 2, "+");
|
|
5125
|
-
const key = parts.pop();
|
|
5126
|
-
const mods = parts;
|
|
5127
|
-
const shown = KEY_GLYPHS[key] ?? key;
|
|
5128
|
-
return apple ? [...mods.map((m) => GLYPHS[m]), shown] : [...mods.map((m) => WORDS[m]), shown];
|
|
5129
|
-
}
|
|
5130
|
-
|
|
5131
5219
|
// src/ui/layer.ts
|
|
5132
5220
|
var lookOf = (look) => ({ ...lookDefaults.current, ...look });
|
|
5133
5221
|
var roots = new WeakMap;
|
|
@@ -5700,10 +5788,10 @@ function foldFaces(prev, p) {
|
|
|
5700
5788
|
function chevronTurn(p, edge) {
|
|
5701
5789
|
return (edge === "start" ? 180 : -180) * (1 - clamp01(p));
|
|
5702
5790
|
}
|
|
5703
|
-
function chevronFlip(f) {
|
|
5704
|
-
return
|
|
5791
|
+
function chevronFlip(f, edge) {
|
|
5792
|
+
return chevronTurn(f, edge);
|
|
5705
5793
|
}
|
|
5706
|
-
var FOLD_STYLE = { chevron: "flip", title: "travel", duration: 0.
|
|
5794
|
+
var FOLD_STYLE = { chevron: "flip", title: "travel", duration: 0.25 };
|
|
5707
5795
|
function foldStyle(options = {}) {
|
|
5708
5796
|
const duration = options.duration;
|
|
5709
5797
|
return {
|
|
@@ -5744,10 +5832,12 @@ function serializeLayout(layout) {
|
|
|
5744
5832
|
}
|
|
5745
5833
|
|
|
5746
5834
|
// src/ui/split.ts
|
|
5747
|
-
var FLIP = springMotion({ duration: 0.
|
|
5835
|
+
var FLIP = springMotion({ duration: 0.25, bounce: 0 });
|
|
5836
|
+
var FLIP_DEPTH = 28;
|
|
5748
5837
|
var SETTLE = springMotion({ duration: 0.3, bounce: 0 });
|
|
5749
5838
|
var CONTENT_BLUR = 3;
|
|
5750
5839
|
var LABEL_BLUR = 2;
|
|
5840
|
+
var COUNT_CLEAR = 0.12;
|
|
5751
5841
|
var put = (el, prop, value) => {
|
|
5752
5842
|
if (el.style.getPropertyValue(prop) !== value)
|
|
5753
5843
|
el.style.setProperty(prop, value);
|
|
@@ -5884,7 +5974,12 @@ function split(container, options) {
|
|
|
5884
5974
|
if (!row) {
|
|
5885
5975
|
head.dataset.toggles = "";
|
|
5886
5976
|
head.addEventListener("click", () => setCollapsed(spec.id, !collapsed[spec.id]));
|
|
5887
|
-
}
|
|
5977
|
+
} else
|
|
5978
|
+
head.addEventListener("dblclick", (e) => {
|
|
5979
|
+
if (e.target.closest(".knobs-pane-btn"))
|
|
5980
|
+
return;
|
|
5981
|
+
setCollapsed(spec.id, true);
|
|
5982
|
+
});
|
|
5888
5983
|
}
|
|
5889
5984
|
inner.append(head);
|
|
5890
5985
|
view.head = head;
|
|
@@ -6053,6 +6148,8 @@ function split(container, options) {
|
|
|
6053
6148
|
const label = v.railLabel;
|
|
6054
6149
|
const travel = morph && style.title === "travel" && Boolean(v.titleEl) && label.textContent === v.titleEl.textContent;
|
|
6055
6150
|
v.el.toggleAttribute("data-travel", travel && folding);
|
|
6151
|
+
if (v.countEl)
|
|
6152
|
+
put(v.countEl, "opacity", travel && folding && p > 0 ? Math.max(0, 1 - p / COUNT_CLEAR).toFixed(3) : "");
|
|
6056
6153
|
const k = 1 - p;
|
|
6057
6154
|
if (travel && !folding) {
|
|
6058
6155
|
put(label, "opacity", "0");
|
|
@@ -6080,8 +6177,9 @@ function split(container, options) {
|
|
|
6080
6177
|
if (style.chevron === "turn")
|
|
6081
6178
|
put(v.turn, "transform", k === 0 ? "" : `${move} rotate(${chevronTurn(p, v.edge).toFixed(2)}deg) ${size}`);
|
|
6082
6179
|
else {
|
|
6083
|
-
const
|
|
6084
|
-
|
|
6180
|
+
const turn = chevronFlip(v.flip.x, v.edge);
|
|
6181
|
+
const over = v.flip.resting ? turn === 0 ? "" : "scaleX(-1)" : `perspective(${FLIP_DEPTH}px) rotateY(${turn.toFixed(2)}deg)`;
|
|
6182
|
+
put(v.turn, "transform", k === 0 && !over ? "" : `${move} ${size} ${over}`);
|
|
6085
6183
|
}
|
|
6086
6184
|
} else {
|
|
6087
6185
|
const a = v.faces.rail;
|
|
@@ -8085,7 +8183,7 @@ function virtualWindow(scrollTop, height, rowHeight, count, overscan = 6) {
|
|
|
8085
8183
|
}
|
|
8086
8184
|
|
|
8087
8185
|
// src/ui/tree.ts
|
|
8088
|
-
var MOVE = springMotion({ duration: 0.
|
|
8186
|
+
var MOVE = springMotion({ duration: 0.3, bounce: 0 });
|
|
8089
8187
|
var EDGE = 28;
|
|
8090
8188
|
function tree(container, options) {
|
|
8091
8189
|
const doc = container.ownerDocument;
|
|
@@ -8124,6 +8222,7 @@ function tree(container, options) {
|
|
|
8124
8222
|
empty.hidden = true;
|
|
8125
8223
|
root.append(space, line, empty);
|
|
8126
8224
|
container.append(root);
|
|
8225
|
+
const scrollbar = overlayScrollbar(root, space);
|
|
8127
8226
|
let h = 26;
|
|
8128
8227
|
let indent = 14;
|
|
8129
8228
|
let inset = 8;
|
|
@@ -8973,6 +9072,7 @@ function tree(container, options) {
|
|
|
8973
9072
|
loop.stop();
|
|
8974
9073
|
autoScroll.stop();
|
|
8975
9074
|
ro.disconnect();
|
|
9075
|
+
scrollbar.dispose();
|
|
8976
9076
|
dragging?.ghost.remove();
|
|
8977
9077
|
root.remove();
|
|
8978
9078
|
}
|