197 lines
6.2 KiB
Plaintext
197 lines
6.2 KiB
Plaintext
import { functionalUpdate } from "./utils.js";
|
|
const storageKey = "tsr-scroll-restoration-v1_3";
|
|
let sessionsStorage = false;
|
|
try {
|
|
sessionsStorage = typeof window !== "undefined" && typeof window.sessionStorage === "object";
|
|
} catch {
|
|
}
|
|
const throttle = (fn, wait) => {
|
|
let timeout;
|
|
return (...args) => {
|
|
if (!timeout) {
|
|
timeout = setTimeout(() => {
|
|
fn(...args);
|
|
timeout = null;
|
|
}, wait);
|
|
}
|
|
};
|
|
};
|
|
const scrollRestorationCache = sessionsStorage ? (() => {
|
|
const state = JSON.parse(window.sessionStorage.getItem(storageKey) || "null") || {};
|
|
return {
|
|
state,
|
|
// This setter is simply to make sure that we set the sessionStorage right
|
|
// after the state is updated. It doesn't necessarily need to be a functional
|
|
// update.
|
|
set: (updater) => (scrollRestorationCache.state = functionalUpdate(updater, scrollRestorationCache.state) || scrollRestorationCache.state, window.sessionStorage.setItem(
|
|
storageKey,
|
|
JSON.stringify(scrollRestorationCache.state)
|
|
))
|
|
};
|
|
})() : void 0;
|
|
const defaultGetScrollRestorationKey = (location) => {
|
|
return location.state.key || location.href;
|
|
};
|
|
function getCssSelector(el) {
|
|
const path = [];
|
|
let parent;
|
|
while (parent = el.parentNode) {
|
|
path.unshift(
|
|
`${el.tagName}:nth-child(${[].indexOf.call(parent.children, el) + 1})`
|
|
);
|
|
el = parent;
|
|
}
|
|
return `${path.join(" > ")}`.toLowerCase();
|
|
}
|
|
let ignoreScroll = false;
|
|
function restoreScroll(storageKey2, key, behavior, shouldScrollRestoration, scrollToTopSelectors) {
|
|
var _a;
|
|
let byKey;
|
|
try {
|
|
byKey = JSON.parse(sessionStorage.getItem(storageKey2) || "{}");
|
|
} catch (error) {
|
|
console.error(error);
|
|
return;
|
|
}
|
|
const resolvedKey = key || ((_a = window.history.state) == null ? void 0 : _a.key);
|
|
const elementEntries = byKey[resolvedKey];
|
|
ignoreScroll = true;
|
|
(() => {
|
|
if (shouldScrollRestoration && elementEntries) {
|
|
for (const elementSelector in elementEntries) {
|
|
const entry = elementEntries[elementSelector];
|
|
if (elementSelector === "window") {
|
|
window.scrollTo({
|
|
top: entry.scrollY,
|
|
left: entry.scrollX,
|
|
behavior
|
|
});
|
|
} else if (elementSelector) {
|
|
const element = document.querySelector(elementSelector);
|
|
if (element) {
|
|
element.scrollLeft = entry.scrollX;
|
|
element.scrollTop = entry.scrollY;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
const hash = window.location.hash.split("#")[1];
|
|
if (hash) {
|
|
const hashScrollIntoViewOptions = (window.history.state || {}).__hashScrollIntoViewOptions ?? true;
|
|
if (hashScrollIntoViewOptions) {
|
|
const el = document.getElementById(hash);
|
|
if (el) {
|
|
el.scrollIntoView(hashScrollIntoViewOptions);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
[
|
|
"window",
|
|
...(scrollToTopSelectors == null ? void 0 : scrollToTopSelectors.filter((d) => d !== "window")) ?? []
|
|
].forEach((selector) => {
|
|
const element = selector === "window" ? window : document.querySelector(selector);
|
|
if (element) {
|
|
element.scrollTo({
|
|
top: 0,
|
|
left: 0,
|
|
behavior
|
|
});
|
|
}
|
|
});
|
|
})();
|
|
ignoreScroll = false;
|
|
}
|
|
function setupScrollRestoration(router, force) {
|
|
const shouldScrollRestoration = force ?? router.options.scrollRestoration ?? false;
|
|
if (shouldScrollRestoration) {
|
|
router.isScrollRestoring = true;
|
|
}
|
|
if (typeof document === "undefined" || router.isScrollRestorationSetup) {
|
|
return;
|
|
}
|
|
router.isScrollRestorationSetup = true;
|
|
ignoreScroll = false;
|
|
const getKey = router.options.getScrollRestorationKey || defaultGetScrollRestorationKey;
|
|
window.history.scrollRestoration = "manual";
|
|
const onScroll = (event) => {
|
|
if (ignoreScroll || !router.isScrollRestoring) {
|
|
return;
|
|
}
|
|
let elementSelector = "";
|
|
if (event.target === document || event.target === window) {
|
|
elementSelector = "window";
|
|
} else {
|
|
const attrId = event.target.getAttribute(
|
|
"data-scroll-restoration-id"
|
|
);
|
|
if (attrId) {
|
|
elementSelector = `[data-scroll-restoration-id="${attrId}"]`;
|
|
} else {
|
|
elementSelector = getCssSelector(event.target);
|
|
}
|
|
}
|
|
const restoreKey = getKey(router.state.location);
|
|
scrollRestorationCache.set((state) => {
|
|
const keyEntry = state[restoreKey] = state[restoreKey] || {};
|
|
const elementEntry = keyEntry[elementSelector] = keyEntry[elementSelector] || {};
|
|
if (elementSelector === "window") {
|
|
elementEntry.scrollX = window.scrollX || 0;
|
|
elementEntry.scrollY = window.scrollY || 0;
|
|
} else if (elementSelector) {
|
|
const element = document.querySelector(elementSelector);
|
|
if (element) {
|
|
elementEntry.scrollX = element.scrollLeft || 0;
|
|
elementEntry.scrollY = element.scrollTop || 0;
|
|
}
|
|
}
|
|
return state;
|
|
});
|
|
};
|
|
if (typeof document !== "undefined") {
|
|
document.addEventListener("scroll", throttle(onScroll, 100), true);
|
|
}
|
|
router.subscribe("onRendered", (event) => {
|
|
const cacheKey = getKey(event.toLocation);
|
|
if (!router.resetNextScroll) {
|
|
router.resetNextScroll = true;
|
|
return;
|
|
}
|
|
restoreScroll(
|
|
storageKey,
|
|
cacheKey,
|
|
router.options.scrollRestorationBehavior || void 0,
|
|
router.isScrollRestoring || void 0,
|
|
router.options.scrollToTopSelectors || void 0
|
|
);
|
|
if (router.isScrollRestoring) {
|
|
scrollRestorationCache.set((state) => {
|
|
state[cacheKey] = state[cacheKey] || {};
|
|
return state;
|
|
});
|
|
}
|
|
});
|
|
}
|
|
function handleHashScroll(router) {
|
|
if (typeof document !== "undefined" && document.querySelector) {
|
|
const hashScrollIntoViewOptions = router.state.location.state.__hashScrollIntoViewOptions ?? true;
|
|
if (hashScrollIntoViewOptions && router.state.location.hash !== "") {
|
|
const el = document.getElementById(router.state.location.hash);
|
|
if (el) {
|
|
el.scrollIntoView(hashScrollIntoViewOptions);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
export {
|
|
defaultGetScrollRestorationKey,
|
|
getCssSelector,
|
|
handleHashScroll,
|
|
restoreScroll,
|
|
scrollRestorationCache,
|
|
setupScrollRestoration,
|
|
storageKey
|
|
};
|
|
//# sourceMappingURL=scroll-restoration.js.map
|