zsbqb-static 0.1.7 → 0.1.9

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/css/app.css CHANGED
@@ -804,12 +804,12 @@ th { color: var(--muted); font-weight: 600; font-size: 13px; background: var(--b
804
804
  align-items: start;
805
805
  }
806
806
  .alpha-rail {
807
- /* 热区相对 28px 栏宽向外扩一截,便于鼠标/触屏滑动选字母 */
807
+ /* 热区相对 28px 栏宽向外扩一截,便于鼠标/触屏滑动选字母。
808
+ 高度由 JS 按「当前位置到视口底」写入 --alpha-rail-fit,避免 100vh
809
+ 从标题下方起算把字母拉长,点 B 实际打到 G。 */
808
810
  --alpha-rail-pad-start: 14px;
809
811
  --alpha-rail-pad-end: 20px;
810
812
  --alpha-rail-pad-y: 10px;
811
- --alpha-rail-viewport: calc(100vh - 16px);
812
- --alpha-rail-viewport: calc(100svh - 16px);
813
813
  position: sticky;
814
814
  top: 8px;
815
815
  z-index: 15;
@@ -818,9 +818,11 @@ th { color: var(--muted); font-weight: 600; font-size: 13px; background: var(--b
818
818
  justify-content: space-between;
819
819
  gap: 0;
820
820
  width: 28px;
821
- box-sizing: content-box;
822
- height: calc(var(--alpha-rail-viewport) - 2 * var(--alpha-rail-pad-y));
823
- max-height: calc(var(--alpha-rail-viewport) - 2 * var(--alpha-rail-pad-y));
821
+ box-sizing: border-box;
822
+ height: var(--alpha-rail-fit, auto);
823
+ max-height: calc(100vh - 16px);
824
+ max-height: calc(100svh - 16px);
825
+ max-height: calc(100dvh - 16px);
824
826
  overflow: hidden;
825
827
  overscroll-behavior: contain;
826
828
  padding: var(--alpha-rail-pad-y) var(--alpha-rail-pad-end) var(--alpha-rail-pad-y) var(--alpha-rail-pad-start);
@@ -849,13 +851,12 @@ th { color: var(--muted); font-weight: 600; font-size: 13px; background: var(--b
849
851
  display: grid;
850
852
  place-items: center;
851
853
  width: 28px;
852
- flex: 1 1 0;
853
- min-height: 0;
854
+ flex: 1 1 auto;
855
+ min-height: 1em;
854
856
  padding: 0;
855
857
  border-radius: 5px;
856
858
  color: var(--muted);
857
- font-size: clamp(10px, 2.2vh, 13px);
858
- font-size: clamp(10px, 2.2svh, 13px);
859
+ font-size: clamp(8px, calc((var(--alpha-rail-fit, 70svh) - 20px) / 36), 13px);
859
860
  font-weight: 600;
860
861
  font-family: var(--font-sans);
861
862
  font-variant-numeric: tabular-nums;
package/js/app.js CHANGED
@@ -1561,10 +1561,35 @@ function bindAlphaRail() {
1561
1561
 
1562
1562
  let dragging = false;
1563
1563
  let current = null;
1564
+ let downItem = null;
1565
+ let downY = 0;
1564
1566
  let navigating = false;
1565
1567
  let pointerHandled = false;
1568
+ let fitFrame = 0;
1569
+
1570
+ function fitRail() {
1571
+ const top = rail.getBoundingClientRect().top;
1572
+ const fit = Math.max(280, Math.round(window.innerHeight - top - 8));
1573
+ const next = `${fit}px`;
1574
+ if (rail.style.getPropertyValue("--alpha-rail-fit") !== next) {
1575
+ rail.style.setProperty("--alpha-rail-fit", next);
1576
+ }
1577
+ }
1578
+
1579
+ function requestFit() {
1580
+ if (fitFrame) return;
1581
+ fitFrame = window.requestAnimationFrame(() => {
1582
+ fitFrame = 0;
1583
+ fitRail();
1584
+ });
1585
+ }
1586
+
1587
+ function letterOf(item) {
1588
+ if (!item) return "";
1589
+ return (item.getAttribute("data-letter") || item.textContent || "").trim();
1590
+ }
1566
1591
 
1567
- function pickItem(clientY) {
1592
+ function pickItemByY(clientY) {
1568
1593
  let best = null;
1569
1594
  let bestDist = Infinity;
1570
1595
  for (const item of items) {
@@ -1580,6 +1605,29 @@ function bindAlphaRail() {
1580
1605
  return best;
1581
1606
  }
1582
1607
 
1608
+ function itemFromPoint(clientX, clientY) {
1609
+ const stack =
1610
+ typeof document.elementsFromPoint === "function"
1611
+ ? document.elementsFromPoint(clientX, clientY)
1612
+ : [document.elementFromPoint(clientX, clientY)];
1613
+ for (const node of stack) {
1614
+ if (!node || !node.closest) continue;
1615
+ const item = node.closest("[data-alpha-item]");
1616
+ if (item && rail.contains(item)) return item;
1617
+ }
1618
+ return pickItemByY(clientY);
1619
+ }
1620
+
1621
+ function itemFromEvent(event) {
1622
+ const raw = event.target;
1623
+ const el = raw && raw.nodeType === 1 ? raw : raw && raw.parentElement;
1624
+ if (el && el.closest) {
1625
+ const item = el.closest("[data-alpha-item]");
1626
+ if (item && rail.contains(item)) return item;
1627
+ }
1628
+ return itemFromPoint(event.clientX, event.clientY);
1629
+ }
1630
+
1583
1631
  function setScrub(item) {
1584
1632
  if (current === item) return;
1585
1633
  current = item;
@@ -1593,7 +1641,7 @@ function bindAlphaRail() {
1593
1641
 
1594
1642
  function goTo(item) {
1595
1643
  if (!item || navigating) return;
1596
- const label = item.textContent.trim();
1644
+ const label = letterOf(item);
1597
1645
  if (typeof window.__setQueryLetterFilter === "function") {
1598
1646
  window.__setQueryLetterFilter(label);
1599
1647
  return;
@@ -1607,7 +1655,9 @@ function bindAlphaRail() {
1607
1655
  function onPointerDown(event) {
1608
1656
  if (event.pointerType === "mouse" && event.button !== 0) return;
1609
1657
  dragging = true;
1610
- setScrub(pickItem(event.clientY));
1658
+ downY = event.clientY;
1659
+ downItem = itemFromEvent(event);
1660
+ setScrub(downItem);
1611
1661
  try {
1612
1662
  rail.setPointerCapture(event.pointerId);
1613
1663
  } catch (err) {
@@ -1618,14 +1668,16 @@ function bindAlphaRail() {
1618
1668
 
1619
1669
  function onPointerMove(event) {
1620
1670
  if (!dragging) return;
1621
- setScrub(pickItem(event.clientY));
1671
+ setScrub(itemFromPoint(event.clientX, event.clientY));
1622
1672
  event.preventDefault();
1623
1673
  }
1624
1674
 
1625
1675
  function onPointerUp(event) {
1626
1676
  if (!dragging) return;
1627
1677
  dragging = false;
1628
- const target = pickItem(event.clientY) || current;
1678
+ const moved = Math.abs(event.clientY - downY) > 8;
1679
+ const target = moved ? itemFromPoint(event.clientX, event.clientY) || current : downItem || itemFromEvent(event);
1680
+ downItem = null;
1629
1681
  clearScrub();
1630
1682
  pointerHandled = true;
1631
1683
  goTo(target);
@@ -1636,6 +1688,7 @@ function bindAlphaRail() {
1636
1688
 
1637
1689
  function onPointerCancel() {
1638
1690
  dragging = false;
1691
+ downItem = null;
1639
1692
  clearScrub();
1640
1693
  }
1641
1694
 
@@ -1651,6 +1704,11 @@ function bindAlphaRail() {
1651
1704
  goTo(item);
1652
1705
  });
1653
1706
  });
1707
+
1708
+ window.__fitQueryAlphaRail = fitRail;
1709
+ fitRail();
1710
+ window.addEventListener("resize", requestFit);
1711
+ window.addEventListener("scroll", requestFit, { passive: true });
1654
1712
  }
1655
1713
 
1656
1714
  function bindSearchClear() {
package/js/query-app.js CHANGED
@@ -310,11 +310,15 @@
310
310
  }
311
311
  applyFilters();
312
312
  const toolbar = document.querySelector(".query-toolbar");
313
- if (!toolbar) return;
314
- const nextTop = toolbar.getBoundingClientRect().top + window.scrollY;
315
- if (Math.abs(window.scrollY - nextTop) > 8) {
316
- window.scrollTo(0, Math.max(0, nextTop));
313
+ if (toolbar) {
314
+ const nextTop = toolbar.getBoundingClientRect().top + window.scrollY;
315
+ if (Math.abs(window.scrollY - nextTop) > 8) {
316
+ window.scrollTo(0, Math.max(0, nextTop));
317
+ }
317
318
  }
319
+ window.requestAnimationFrame(function () {
320
+ if (typeof window.__fitQueryAlphaRail === "function") window.__fitQueryAlphaRail();
321
+ });
318
322
  };
319
323
 
320
324
  window.__queryLoadFamily = function (nextFamily, nextStar) {