- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
151 lines
3.9 KiB
JavaScript
151 lines
3.9 KiB
JavaScript
// modules/core/click-manager.js
|
|
import { Logger } from './logger.js';
|
|
import { useEvent } from './useEvent.js';
|
|
import { navigateTo } from "./navigateTo";
|
|
import { LinkPrefetcher } from './LinkPrefetcher.js';
|
|
|
|
let callback = null;
|
|
let unsubscribes = [];
|
|
let prefetcher = null;
|
|
|
|
function isInternal(link) {
|
|
return link.origin === location.origin;
|
|
}
|
|
|
|
function handleClick(e) {
|
|
const link = e.target.closest('a');
|
|
if (!link || e.defaultPrevented) return;
|
|
|
|
const href = link.getAttribute('href');
|
|
if (!href || href.startsWith('#')) return;
|
|
|
|
// Skip conditions
|
|
if (
|
|
link.target === '_blank' ||
|
|
link.hasAttribute('download') ||
|
|
link.getAttribute('rel')?.includes('external') ||
|
|
link.hasAttribute('data-skip')
|
|
) {
|
|
Logger.info(`[click-manager] skipped: ${href}`);
|
|
return;
|
|
}
|
|
|
|
if (isInternal(link)) {
|
|
e.preventDefault();
|
|
|
|
const cached = prefetcher ? prefetcher.getCached(href) : null;
|
|
|
|
const options = {
|
|
viewTransition: link.hasAttribute('data-view-transition'),
|
|
replace: link.hasAttribute('data-replace'),
|
|
modal: link.hasAttribute('data-modal'),
|
|
prefetched: cached !== null,
|
|
data: cached,
|
|
};
|
|
|
|
Logger.info(`[click-manager] internal: ${href}`, options);
|
|
|
|
if(options.modal) {
|
|
callback?.(href, link, options);
|
|
} else {
|
|
navigateTo(href, options);
|
|
}
|
|
}
|
|
}
|
|
|
|
function handleMouseOver(e) {
|
|
const link = e.target.closest('a[href]');
|
|
if (!link || !prefetcher) return;
|
|
|
|
prefetcher.handleHover(link);
|
|
}
|
|
|
|
function handleMouseOut(e) {
|
|
const link = e.target.closest('a[href]');
|
|
if (!link || !prefetcher) return;
|
|
|
|
prefetcher.handleMouseLeave();
|
|
}
|
|
|
|
function handlePopState() {
|
|
const href = location.pathname;
|
|
Logger.info(`[click-manager] popstate: ${href}`);
|
|
navigateTo(href, { replace: true });
|
|
}
|
|
|
|
export function getPrefetched(href) {
|
|
return prefetcher ? prefetcher.getCached(href) : null;
|
|
}
|
|
|
|
export function prefetchHref(href) {
|
|
if (!href || !prefetcher) return;
|
|
prefetcher.prefetch(href, { priority: 'high' });
|
|
}
|
|
|
|
export function prefetchUrls(urls) {
|
|
if (!prefetcher) return;
|
|
prefetcher.prefetchEager(urls);
|
|
}
|
|
|
|
export function init(onNavigate, prefetchOptions = {}) {
|
|
callback = onNavigate;
|
|
|
|
// Initialize prefetcher with options
|
|
prefetcher = new LinkPrefetcher({
|
|
strategies: ['hover', 'visible'],
|
|
hoverDelay: 150,
|
|
observerMargin: '50px',
|
|
maxCacheSize: 20,
|
|
cacheTTL: 60000,
|
|
...prefetchOptions
|
|
});
|
|
|
|
unsubscribes = [
|
|
useEvent(document, 'click', handleClick),
|
|
useEvent(document, 'mouseover', handleMouseOver),
|
|
useEvent(document, 'mouseout', handleMouseOut),
|
|
useEvent(window, 'popstate', handlePopState),
|
|
];
|
|
|
|
// Observe all initial links if visible strategy is enabled
|
|
if (prefetchOptions.strategies?.includes('visible') !== false) {
|
|
// Wait for DOM to be ready
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
prefetcher.observeLinks();
|
|
});
|
|
} else {
|
|
prefetcher.observeLinks();
|
|
}
|
|
}
|
|
|
|
// Support for eager prefetching via data attributes
|
|
document.querySelectorAll('a[data-prefetch="eager"]').forEach(link => {
|
|
const href = link.getAttribute('href');
|
|
if (href) {
|
|
prefetcher.prefetch(href, { priority: 'high' });
|
|
}
|
|
});
|
|
|
|
Logger.info('[click-manager] ready with prefetching');
|
|
}
|
|
|
|
export function destroy() {
|
|
callback = null;
|
|
|
|
if (prefetcher) {
|
|
prefetcher.destroy();
|
|
prefetcher = null;
|
|
}
|
|
|
|
unsubscribes.forEach(unsub => unsub());
|
|
unsubscribes = [];
|
|
|
|
Logger.info('[click-manager] destroyed');
|
|
}
|
|
|
|
// Export prefetcher for advanced usage
|
|
export function getPrefetcher() {
|
|
return prefetcher;
|
|
}
|