UNPKG

one

Version:

One is a React framework for web, iOS, and Android apps.

213 lines (210 loc) • 6.64 kB
import { useIsFocused } from "@react-navigation/core"; import { useContext, useEffect, useLayoutEffect } from "react"; import { RouteInfoContext } from "../router/RouteInfoContext.native.js"; import { setLastAction } from "../router/lastAction.native.js"; import { routeInfo, subscribeToLoadingState, subscribeToRootState } from "../router/router.native.js"; var KEY = "one-sr"; var GROUP_KEY = "one-sr-groups"; var getState = function getState2() { return JSON.parse(sessionStorage.getItem(KEY) || "{}"); }; var getGroupState = function getGroupState2() { return JSON.parse(sessionStorage.getItem(GROUP_KEY) || "{}"); }; var activeGroups = /* @__PURE__ */ new Set(); function registerScrollGroup(groupId) { activeGroups.add(groupId); return function() { activeGroups.delete(groupId); }; } function getGroupKey(pathname) { var longestMatch = null; var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0; try { for (var _iterator = activeGroups[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var group = _step.value; if ((pathname === group || pathname.startsWith(`${group}/`)) && (!longestMatch || group.length > longestMatch.length)) { longestMatch = group; } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return longestMatch; } function restorePosition(pathname) { try { var positions = getState(); var saved = positions[pathname]; if (typeof saved === "number") { setTimeout(function() { window.scrollTo(0, saved); }); } } catch (error) { console.error(`Error restoring scroll position`, error); sessionStorage.removeItem(KEY); } } function restoreGroupPosition(groupId) { try { var positions = getGroupState(); var saved = positions[groupId]; if (typeof saved === "number") { setTimeout(function() { window.scrollTo(0, saved); }); } } catch (error) { console.error(`Error restoring scroll position for group ${groupId}`, error); sessionStorage.removeItem(GROUP_KEY); } } var didPop = false; var previousPathname = null; function rememberScrollPosition() { didPop = false; var pathname = window.location.pathname; var state = getState(); state[pathname] = window.scrollY; sessionStorage.setItem(KEY, JSON.stringify(state)); var groupKey = getGroupKey(pathname); if (groupKey) { var groupState = getGroupState(); groupState[groupKey] = window.scrollY; sessionStorage.setItem(GROUP_KEY, JSON.stringify(groupState)); } previousPathname = pathname; } var disable = null; var pendingScroll = null; var committedHref; function ScrollBehaviorRouteCommit() { var info = useContext(RouteInfoContext); var href = info === null || info === void 0 ? void 0 : info.unstable_globalHref; var focused = useIsFocused(); useLayoutEffect(function() { if (!focused) return; committedHref = href; if (pendingScroll && pendingScroll.href === href) { var { apply } = pendingScroll; pendingScroll = null; apply(); } }); return null; } function configure(props) { if (typeof window === "undefined" || !window.addEventListener) { return; } disable === null || disable === void 0 ? void 0 : disable(); var initialLocation = `${window.location.pathname}${window.location.search}`; var isFirstStateChange = true; var handledLocation = initialLocation; previousPathname = window.location.pathname; var popStateController = new AbortController(); window.addEventListener("popstate", function() { didPop = true; setLastAction(); }, { signal: popStateController.signal }); var disposeOnLoadState = subscribeToLoadingState(function(state) { if (state === "loading") { rememberScrollPosition(); } }); var disposeOnRootState = subscribeToRootState(function(state) { var _ref, _ref1; var _state_linkOptions, _state_linkOptions1; var currentHref = (_ref = routeInfo === null || routeInfo === void 0 ? void 0 : routeInfo.unstable_globalHref) !== null && _ref !== void 0 ? _ref : ""; var currentPathname = (_ref1 = routeInfo === null || routeInfo === void 0 ? void 0 : routeInfo.pathname) !== null && _ref1 !== void 0 ? _ref1 : ""; if (isFirstStateChange) { isFirstStateChange = false; if (currentHref === initialLocation) { return; } } var { hash } = state; var location = `${currentHref}${hash || ""}`; if (location === handledLocation) { pendingScroll = null; return; } pendingScroll = null; if (((_state_linkOptions = state.linkOptions) === null || _state_linkOptions === void 0 ? void 0 : _state_linkOptions.scroll) === false) { handledLocation = location; previousPathname = currentPathname; return; } var restoring = didPop; var prevGroup = previousPathname ? getGroupKey(previousPathname) : null; var currentGroup = getGroupKey(currentPathname); var scrollGroup = (_state_linkOptions1 = state.linkOptions) === null || _state_linkOptions1 === void 0 ? void 0 : _state_linkOptions1.scrollGroup; pendingScroll = { href: currentHref, apply: function apply2() { handledLocation = location; previousPathname = currentPathname; if (hash) { scrollToHash(hash); } else if (restoring) { if (props.disable !== "restore") { restorePosition(currentPathname); } } else if (prevGroup && currentGroup && prevGroup === currentGroup) { restoreGroupPosition(currentGroup); } else if (scrollGroup) { restoreGroupPosition(scrollGroup); } else { window.scrollTo(0, 0); } } }; if (committedHref === currentHref) { var { apply } = pendingScroll; pendingScroll = null; apply(); } }); disable = function disable2() { pendingScroll = null; popStateController.abort(); disposeOnLoadState(); disposeOnRootState(); }; return disable; } function scrollToHash(hash) { if (!hash || !hash.startsWith("#")) return; var id = hash.slice(1); var el = document.getElementById(id); if (!el) return; el.scrollIntoView({ behavior: "instant" }); } function ScrollBehavior(props) { if (process.env.VITE_ENVIRONMENT === "client") { useEffect(function() { if (window.location.hash) { scrollToHash(window.location.hash); } }, []); useEffect(function() { return configure(props); }, [props.disable]); } return null; } export { ScrollBehavior, ScrollBehaviorRouteCommit, registerScrollGroup }; //# sourceMappingURL=ScrollBehavior.native.js.map