@commentray/render 0.1.2 → 0.2.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.
@@ -488,6 +488,12 @@ function findSearchHitButton(leaf, searchResults) {
488
488
  }
489
489
  return null;
490
490
  }
491
+ function listSearchHitButtons(searchResults) {
492
+ return [...searchResults.querySelectorAll("button.hit")].filter((el) => el instanceof HTMLButtonElement);
493
+ }
494
+ function listDocumentedTreeFileLinks(treeHost) {
495
+ return [...treeHost.querySelectorAll("a.tree-file-link")].filter((el) => el instanceof HTMLAnchorElement);
496
+ }
491
497
  function scrollCodeHitToView(line) {
492
498
  const el = document.getElementById(`code-line-${String(line)}`);
493
499
  if (el)
@@ -561,12 +567,77 @@ function emptyBrowsePreviewInnerHtml(scope, filePathLabel, mutable) {
561
567
  const hint = emptyBrowsePreviewHint("commentray-and-paths", fb.length, fb.length, true);
562
568
  return emptySearchBrowsePreviewInnerHtml(hint, fb, hitCtx);
563
569
  }
570
+ function wireSearchResultsHitListKeyboard(searchResults, searchInput) {
571
+ searchResults.addEventListener("keydown", (e) => {
572
+ if (e.isComposing || searchResults.hidden)
573
+ return;
574
+ const hits = listSearchHitButtons(searchResults);
575
+ if (hits.length === 0)
576
+ return;
577
+ const active = document.activeElement;
578
+ if (!(active instanceof HTMLButtonElement) || !active.classList.contains("hit"))
579
+ return;
580
+ const idx = hits.indexOf(active);
581
+ if (idx < 0)
582
+ return;
583
+ if (e.key === "ArrowDown" && idx < hits.length - 1) {
584
+ hits[idx + 1].focus({ preventScroll: true });
585
+ e.preventDefault();
586
+ return;
587
+ }
588
+ if (e.key === "ArrowUp") {
589
+ if (idx > 0) {
590
+ hits[idx - 1].focus({ preventScroll: true });
591
+ e.preventDefault();
592
+ return;
593
+ }
594
+ searchInput.focus({ preventScroll: true });
595
+ e.preventDefault();
596
+ }
597
+ });
598
+ }
599
+ function wireSearchInputKeyboard(searchInput, searchResults, actions) {
600
+ const { renderEmptyBrowsePreview, runSearch, cancelDebounceTimer, hitClickDeps } = actions;
601
+ searchInput.addEventListener("keydown", (e) => {
602
+ if (e.isComposing)
603
+ return;
604
+ if (e.key === "ArrowDown") {
605
+ if (!searchResults.hidden) {
606
+ const hits = listSearchHitButtons(searchResults);
607
+ if (hits.length > 0 && document.activeElement === searchInput) {
608
+ hits[0].focus({ preventScroll: true });
609
+ e.preventDefault();
610
+ return;
611
+ }
612
+ }
613
+ if (tokenizeQuery(searchInput.value).length > 0)
614
+ return;
615
+ renderEmptyBrowsePreview();
616
+ e.preventDefault();
617
+ return;
618
+ }
619
+ if (e.key !== "Enter")
620
+ return;
621
+ cancelDebounceTimer();
622
+ if (tokenizeQuery(searchInput.value).length > 0) {
623
+ runSearch();
624
+ }
625
+ const hits = listSearchHitButtons(searchResults);
626
+ if (!searchResults.hidden && hits.length > 0 && document.activeElement === searchInput) {
627
+ e.preventDefault();
628
+ handleSearchHitButtonClick(hits[0], hitClickDeps);
629
+ }
630
+ });
631
+ }
564
632
  function wireSearchUi(ctx) {
565
633
  const { scope, filePathLabel, mutable, rawCode, searchInput, searchClear, searchResults, docScrollEl, } = ctx;
566
634
  let debounceTimer;
567
- function clearSearch() {
635
+ function cancelDebounceTimer() {
568
636
  clearTimeout(debounceTimer);
569
637
  debounceTimer = undefined;
638
+ }
639
+ function clearSearch() {
640
+ cancelDebounceTimer();
570
641
  searchInput.value = "";
571
642
  searchResults.innerHTML = "";
572
643
  searchResults.hidden = true;
@@ -610,17 +681,16 @@ function wireSearchUi(ctx) {
610
681
  return;
611
682
  handleSearchHitButtonClick(hit, hitClickDeps);
612
683
  });
684
+ wireSearchResultsHitListKeyboard(searchResults, searchInput);
613
685
  searchInput.addEventListener("input", () => {
614
686
  clearTimeout(debounceTimer);
615
687
  debounceTimer = setTimeout(runSearch, 200);
616
688
  });
617
- searchInput.addEventListener("keydown", (e) => {
618
- if (e.key !== "ArrowDown")
619
- return;
620
- if (tokenizeQuery(searchInput.value).length > 0)
621
- return;
622
- renderEmptyBrowsePreview();
623
- e.preventDefault();
689
+ wireSearchInputKeyboard(searchInput, searchResults, {
690
+ renderEmptyBrowsePreview,
691
+ runSearch,
692
+ cancelDebounceTimer,
693
+ hitClickDeps,
624
694
  });
625
695
  searchClear.addEventListener("click", clearSearch);
626
696
  document.addEventListener("keydown", (e) => {
@@ -1569,12 +1639,52 @@ function wireDocumentedFilesTree() {
1569
1639
  sum.focus({ preventScroll: true });
1570
1640
  }
1571
1641
  document.addEventListener("keydown", onDocumentedFilesHubEscape, true);
1642
+ treeMount.addEventListener("keydown", (e) => {
1643
+ if (!detailsHub.open || e.isComposing)
1644
+ return;
1645
+ const t = e.target;
1646
+ if (!(t instanceof HTMLAnchorElement) || !t.classList.contains("tree-file-link"))
1647
+ return;
1648
+ const links = listDocumentedTreeFileLinks(treeMount);
1649
+ if (links.length === 0)
1650
+ return;
1651
+ const idx = links.indexOf(t);
1652
+ if (idx < 0)
1653
+ return;
1654
+ if (e.key === "ArrowDown") {
1655
+ if (idx < links.length - 1) {
1656
+ links[idx + 1].focus({ preventScroll: true });
1657
+ e.preventDefault();
1658
+ }
1659
+ return;
1660
+ }
1661
+ if (e.key === "ArrowUp") {
1662
+ if (idx > 0) {
1663
+ links[idx - 1].focus({ preventScroll: true });
1664
+ e.preventDefault();
1665
+ return;
1666
+ }
1667
+ if (filterInput instanceof HTMLInputElement) {
1668
+ filterInput.focus({ preventScroll: true });
1669
+ e.preventDefault();
1670
+ }
1671
+ }
1672
+ });
1572
1673
  if (filterInput instanceof HTMLInputElement) {
1573
1674
  filterInput.addEventListener("input", () => {
1574
1675
  if (!detailsHub.open || cachedPairs === null)
1575
1676
  return;
1576
1677
  applyFilterAndRender();
1577
1678
  });
1679
+ filterInput.addEventListener("keydown", (e) => {
1680
+ if (!detailsHub.open || e.isComposing || e.key !== "ArrowDown")
1681
+ return;
1682
+ const links = listDocumentedTreeFileLinks(treeMount);
1683
+ if (links.length === 0)
1684
+ return;
1685
+ links[0].focus({ preventScroll: true });
1686
+ e.preventDefault();
1687
+ });
1578
1688
  }
1579
1689
  }
1580
1690
  function wireSplitter(storageSplit, shell, codePane, gutter, initialPct) {