@hortonstudio/main 1.8.0 → 1.8.2
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/autoInit/accessibility.js +53 -59
- package/package.json +1 -1
|
@@ -593,10 +593,18 @@ export function init() {
|
|
|
593
593
|
}
|
|
594
594
|
|
|
595
595
|
|
|
596
|
-
const template = tocList.children[0];
|
|
596
|
+
const template = tocList.children[0].cloneNode(true);
|
|
597
|
+
// Remove is-active class from template if it exists
|
|
598
|
+
const templateLink = template.querySelector("a");
|
|
599
|
+
if (templateLink) {
|
|
600
|
+
templateLink.classList.remove('is-active');
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Clear all original TOC items
|
|
597
604
|
tocList.innerHTML = "";
|
|
605
|
+
|
|
598
606
|
const h2Headings = contentArea.querySelectorAll("h2");
|
|
599
|
-
|
|
607
|
+
|
|
600
608
|
|
|
601
609
|
// Create sections and wrap content
|
|
602
610
|
h2Headings.forEach((heading) => {
|
|
@@ -604,7 +612,7 @@ export function init() {
|
|
|
604
612
|
.toLowerCase()
|
|
605
613
|
.replace(/[^a-z0-9]+/g, "-")
|
|
606
614
|
.replace(/(^-|-$)/g, "");
|
|
607
|
-
|
|
615
|
+
|
|
608
616
|
const section = document.createElement("div");
|
|
609
617
|
section.id = sectionId;
|
|
610
618
|
heading.parentNode.insertBefore(section, heading);
|
|
@@ -661,78 +669,64 @@ export function init() {
|
|
|
661
669
|
tocList.appendChild(tocItem);
|
|
662
670
|
});
|
|
663
671
|
|
|
664
|
-
// Set up IntersectionObserver for active state
|
|
672
|
+
// Set up IntersectionObserver for active state (Webflow-style)
|
|
665
673
|
const sections = Array.from(h2Headings).map(heading => heading.parentElement);
|
|
666
674
|
const tocLinks = tocList.querySelectorAll('a');
|
|
667
|
-
let
|
|
675
|
+
let currentActive = null;
|
|
668
676
|
|
|
669
|
-
const
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
};
|
|
677
|
+
const updateActiveLink = () => {
|
|
678
|
+
const windowHeight = window.innerHeight;
|
|
679
|
+
const trigger = windowHeight * 0.75; // 25% from bottom
|
|
673
680
|
|
|
674
|
-
|
|
675
|
-
// Collect all currently intersecting sections
|
|
676
|
-
const intersectingSections = [];
|
|
677
|
-
|
|
678
|
-
entries.forEach(entry => {
|
|
679
|
-
const sectionId = entry.target.id;
|
|
680
|
-
const existingIndex = intersectingSections.findIndex(s => s.id === sectionId);
|
|
681
|
-
|
|
682
|
-
if (entry.isIntersecting) {
|
|
683
|
-
if (existingIndex === -1) {
|
|
684
|
-
intersectingSections.push({
|
|
685
|
-
id: sectionId,
|
|
686
|
-
ratio: entry.intersectionRatio,
|
|
687
|
-
element: entry.target
|
|
688
|
-
});
|
|
689
|
-
} else {
|
|
690
|
-
intersectingSections[existingIndex].ratio = entry.intersectionRatio;
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
});
|
|
681
|
+
let newActive = null;
|
|
694
682
|
|
|
695
|
-
// Find
|
|
696
|
-
|
|
697
|
-
.
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
.map(section => ({
|
|
704
|
-
id: section.id,
|
|
705
|
-
top: section.getBoundingClientRect().top,
|
|
706
|
-
element: section
|
|
707
|
-
}));
|
|
708
|
-
|
|
709
|
-
if (allIntersecting.length === 0) return;
|
|
710
|
-
|
|
711
|
-
// Pick the topmost section in the active zone
|
|
712
|
-
const topmost = allIntersecting.reduce((prev, curr) =>
|
|
713
|
-
curr.top < prev.top ? curr : prev
|
|
714
|
-
);
|
|
683
|
+
// Find the last section whose top is above the trigger point
|
|
684
|
+
for (let i = sections.length - 1; i >= 0; i--) {
|
|
685
|
+
const rect = sections[i].getBoundingClientRect();
|
|
686
|
+
if (rect.top <= trigger) {
|
|
687
|
+
newActive = sections[i].id;
|
|
688
|
+
break;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
715
691
|
|
|
716
|
-
// Only update if
|
|
717
|
-
if (
|
|
718
|
-
|
|
692
|
+
// Only update if active section changed
|
|
693
|
+
if (newActive !== currentActive) {
|
|
694
|
+
currentActive = newActive;
|
|
719
695
|
|
|
720
|
-
// Remove is-active
|
|
696
|
+
// Remove all is-active
|
|
721
697
|
tocLinks.forEach(link => link.classList.remove('is-active'));
|
|
722
698
|
|
|
723
|
-
// Add
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
activeLink
|
|
699
|
+
// Add to current
|
|
700
|
+
if (currentActive) {
|
|
701
|
+
const activeLink = Array.from(tocLinks).find(link =>
|
|
702
|
+
link.getAttribute('href') === `#${currentActive}`
|
|
703
|
+
);
|
|
704
|
+
if (activeLink) {
|
|
705
|
+
activeLink.classList.add('is-active');
|
|
706
|
+
}
|
|
729
707
|
}
|
|
730
708
|
}
|
|
709
|
+
};
|
|
710
|
+
|
|
711
|
+
const observerOptions = {
|
|
712
|
+
rootMargin: '0px 0px -75% 0px',
|
|
713
|
+
threshold: 0
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
const observer = new IntersectionObserver(() => {
|
|
717
|
+
updateActiveLink();
|
|
731
718
|
}, observerOptions);
|
|
732
719
|
|
|
733
720
|
// Observe all sections
|
|
734
721
|
sections.forEach(section => observer.observe(section));
|
|
735
722
|
|
|
723
|
+
// Also update on scroll for smoother tracking
|
|
724
|
+
let scrollTimeout;
|
|
725
|
+
window.addEventListener('scroll', () => {
|
|
726
|
+
if (scrollTimeout) clearTimeout(scrollTimeout);
|
|
727
|
+
scrollTimeout = setTimeout(updateActiveLink, 50);
|
|
728
|
+
});
|
|
729
|
+
|
|
736
730
|
});
|
|
737
731
|
}
|
|
738
732
|
|