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 = ""; if (this.isActive) { activeClass = " direct-active active"; } else if (this.isAncestorActive) { activeClass = " active"; } return `${baseClass}${typeClass}${activeClass}`; } @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); } } }