Skip to content

Commit 0952e14

Browse files
authored
feat: enable client-side nav detection (#7) from gwendall/master
Enable client-side nav detection
2 parents 5261f51 + 0c56433 commit 0952e14

File tree

1 file changed

+54
-32
lines changed

1 file changed

+54
-32
lines changed

src/index.tsx

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* eslint-disable max-len */
2+
13
/**
24
*
35
* NextTopLoader
@@ -10,7 +12,7 @@
1012
import * as PropTypes from 'prop-types';
1113
import * as React from 'react';
1214
import * as NProgress from 'nprogress';
13-
export interface NextTopLoaderProps {
15+
export type NextTopLoaderProps = {
1416
/**
1517
* Color for the TopLoader.
1618
* @default "#29d"
@@ -115,38 +117,58 @@ const NextTopLoader = ({
115117

116118
// eslint-disable-next-line no-var
117119
var npgclass = document.querySelectorAll('html');
118-
let navLinks = document.querySelectorAll('a');
119-
navLinks.forEach((navLink) => {
120-
navLink.addEventListener('click', (event: MouseEvent) => {
121-
let currentUrl = window.location.href;
122-
let newUrl = (event.currentTarget as HTMLAnchorElement).href;
123-
const isExternalLink = (event.currentTarget as HTMLAnchorElement).target === '_blank';
124-
125-
const isAnchor = isAnchorOfCurrentUrl(currentUrl, newUrl);
126-
if (newUrl === currentUrl || isAnchor || isExternalLink) {
127-
NProgress.start();
128-
NProgress.done();
129-
[].forEach.call(npgclass, function (el: Element) {
130-
el.classList.remove('nprogress-busy');
131-
});
132-
} else {
133-
NProgress.start();
134-
(function (history) {
135-
// eslint-disable-next-line no-var
136-
var pushState = history.pushState;
137-
history.pushState = function () {
138-
NProgress.done();
139-
[].forEach.call(npgclass, function (el: Element) {
140-
el.classList.remove('nprogress-busy');
141-
});
142-
// eslint-disable-next-line prefer-rest-params
143-
return pushState.apply(history, arguments);
144-
};
145-
})(window.history);
120+
function findClosestAnchor(element: HTMLElement | null): HTMLAnchorElement | null {
121+
while (element && element.tagName.toLowerCase() !== 'a') {
122+
element = element.parentElement;
123+
}
124+
return element as HTMLAnchorElement;
125+
}
126+
function handleClick(event: MouseEvent) {
127+
try {
128+
const target = event.target as HTMLElement;
129+
const anchor = findClosestAnchor(target);
130+
if (anchor) {
131+
const currentUrl = window.location.href;
132+
const newUrl = (anchor as HTMLAnchorElement).href;
133+
const isExternalLink = (anchor as HTMLAnchorElement).target === "_blank";
134+
const isAnchor = isAnchorOfCurrentUrl(currentUrl, newUrl);
135+
if (newUrl === currentUrl || isAnchor || isExternalLink) {
136+
NProgress.start();
137+
NProgress.done();
138+
[].forEach.call(npgclass, function (el: Element) {
139+
el.classList.remove("nprogress-busy");
140+
});
141+
} else {
142+
NProgress.start();
143+
(function (history) {
144+
const pushState = history.pushState;
145+
history.pushState = function () {
146+
NProgress.done();
147+
[].forEach.call(npgclass, function (el: Element) {
148+
el.classList.remove("nprogress-busy");
149+
});
150+
// eslint-disable-next-line prefer-rest-params, @typescript-eslint/no-explicit-any
151+
return pushState.apply(history, arguments as any);
152+
};
153+
})(window.history);
154+
}
146155
}
147-
});
148-
});
149-
});
156+
} catch (err) {
157+
// Log the error in development only!
158+
// console.log('NextTopLoader error: ', err);
159+
NProgress.start();
160+
NProgress.done();
161+
}
162+
}
163+
164+
// Add the global click event listener
165+
document.addEventListener("click", handleClick);
166+
167+
// Clean up the global click event listener when the component is unmounted
168+
return () => {
169+
document.removeEventListener("click", handleClick);
170+
};
171+
}, []);
150172

151173
return styles;
152174
};

0 commit comments

Comments
 (0)