Files
DiscoTOC/javascripts/discourse/components/toc-heading.gjs
T
Martin Brennan d8b9292066 FEATURE: Add expand all button for TOC
This commit adds a button at the top of the TOC
headings list called "Expand all". This will expand
all of the subheadings in the list for easier searching.
Clicking the button again will hide all the subheadings except
the currently active one.
2025-01-21 16:27:21 +10:00

89 lines
2.4 KiB
Plaintext

import Component from "@glimmer/component";
import { concat } from "@ember/helper";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { headerOffset } from "discourse/lib/offset-calculator";
import { slugify } from "discourse/lib/utilities";
const SCROLL_BUFFER = 25;
export default class TocHeading extends Component {
@service tocProcessor;
get isActive() {
return this.args.activeHeadingId === this.args.item.id;
}
get isAncestorActive() {
return this.args.activeAncestorIds?.includes(this.args.item.id);
}
get classNames() {
const baseClass = "d-toc-item";
const typeClass = this.args.item.tagName
? ` d-toc-${this.args.item.tagName}`
: "";
let activeClass = "";
let expandAllClass = "";
if (this.isActive) {
activeClass = " direct-active active";
} else if (this.isAncestorActive) {
activeClass = " active";
}
if (this.args.expandAll) {
expandAllClass = " expand-all";
}
return `${baseClass}${typeClass}${activeClass}${expandAllClass}`;
}
@action
handleTocLinkClick(event) {
event.preventDefault();
const targetId = event.target.href?.split("#").pop();
if (!targetId) {
return;
}
const targetElement =
document.querySelector(`a[name="${targetId}"]`) ||
document.getElementById(targetId);
if (targetElement) {
const headerOffsetValue = headerOffset();
const elementPosition =
targetElement.getBoundingClientRect().top + window.pageYOffset;
const offsetPosition =
elementPosition - headerOffsetValue - SCROLL_BUFFER;
window.scrollTo({ top: offsetPosition, behavior: "smooth" });
// hide TOC overlay when navigating to link
this.tocProcessor.setOverlayVisible(false);
}
}
<template>
<li class={{this.classNames}}>
<a
href="#{{@item.id}}"
{{on "click" this.handleTocLinkClick}}
data-d-toc={{concat "toc-" @item.tagName "-" (slugify @item.text)}}
>
{{@item.text}}
</a>
{{#if @item.subItems}}
<ul class="d-toc-sublevel">
{{#each @item.subItems as |subItem|}}
<TocHeading
@item={{subItem}}
@activeHeadingId={{@activeHeadingId}}
@activeAncestorIds={{@activeAncestorIds}}
/>
{{/each}}
</ul>
{{/if}}
</li>
</template>
}