@hortonstudio/main 1.7.16 → 1.8.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.
- package/autoInit/accessibility.js +72 -0
- package/index.js +3 -0
- package/package.json +1 -1
|
@@ -661,6 +661,78 @@ export function init() {
|
|
|
661
661
|
tocList.appendChild(tocItem);
|
|
662
662
|
});
|
|
663
663
|
|
|
664
|
+
// Set up IntersectionObserver for active state
|
|
665
|
+
const sections = Array.from(h2Headings).map(heading => heading.parentElement);
|
|
666
|
+
const tocLinks = tocList.querySelectorAll('a');
|
|
667
|
+
let currentActiveId = null;
|
|
668
|
+
|
|
669
|
+
const observerOptions = {
|
|
670
|
+
rootMargin: '-10% 0px -50% 0px',
|
|
671
|
+
threshold: [0, 0.25, 0.5, 0.75, 1]
|
|
672
|
+
};
|
|
673
|
+
|
|
674
|
+
const observer = new IntersectionObserver((entries) => {
|
|
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
|
+
});
|
|
694
|
+
|
|
695
|
+
// Find all currently intersecting sections (not just from this batch)
|
|
696
|
+
const allIntersecting = sections
|
|
697
|
+
.filter(section => {
|
|
698
|
+
const rect = section.getBoundingClientRect();
|
|
699
|
+
const windowHeight = window.innerHeight;
|
|
700
|
+
// Check if section is in the active zone
|
|
701
|
+
return rect.top < windowHeight * 0.6 && rect.bottom > windowHeight * 0.1;
|
|
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
|
+
);
|
|
715
|
+
|
|
716
|
+
// Only update if the active section changed
|
|
717
|
+
if (currentActiveId !== topmost.id) {
|
|
718
|
+
currentActiveId = topmost.id;
|
|
719
|
+
|
|
720
|
+
// Remove is-active from all links
|
|
721
|
+
tocLinks.forEach(link => link.classList.remove('is-active'));
|
|
722
|
+
|
|
723
|
+
// Add is-active to the corresponding link
|
|
724
|
+
const activeLink = Array.from(tocLinks).find(link =>
|
|
725
|
+
link.getAttribute('href') === `#${topmost.id}`
|
|
726
|
+
);
|
|
727
|
+
if (activeLink) {
|
|
728
|
+
activeLink.classList.add('is-active');
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}, observerOptions);
|
|
732
|
+
|
|
733
|
+
// Observe all sections
|
|
734
|
+
sections.forEach(section => observer.observe(section));
|
|
735
|
+
|
|
664
736
|
});
|
|
665
737
|
}
|
|
666
738
|
|
package/index.js
CHANGED
|
@@ -9,6 +9,9 @@ const initializeHsMain = async () => {
|
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
// Add hs-main class to HTML element immediately
|
|
13
|
+
document.documentElement.classList.add('hs-main');
|
|
14
|
+
|
|
12
15
|
const queuedModules = Array.isArray(window[API_NAME]) ? window[API_NAME] : [];
|
|
13
16
|
|
|
14
17
|
const animationModules = {};
|