UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

462 lines 17.8 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var useLinking_exports = {}; __export(useLinking_exports, { series: () => series, useLinking: () => useLinking }); module.exports = __toCommonJS(useLinking_exports); var import_core = require("@react-navigation/core"); var import_getStateFromPath = require("./getStateFromPath.cjs"); var import_fast_deep_equal = __toESM(require("fast-deep-equal"), 1); var React = __toESM(require("react"), 1); var import_matchers = require("../router/matchers.cjs"); var import_interceptRoutes = require("../router/interceptRoutes.cjs"); var import_router = require("../router/router.cjs"); var import_serverLocationContext = require("../router/serverLocationContext.cjs"); var import_Navigator = require("../views/Navigator.cjs"); var import_createMemoryHistory = require("./createMemoryHistory.cjs"); var import_getPathFromState_mods = require("./getPathFromState-mods.cjs"); const getPartialState = state => { if (!state) return void 0; const { key, routeNames, stale, routes, ...partial } = state; return { ...partial, stale: true, routes: routes.map(({ key: routeKey, state: childState, ...route }) => ({ ...route, ...(childState ? { state: getPartialState(childState) } : null) })) }; }; const findMatchingState = (a, b) => { if (a === void 0 || b === void 0 || a.key !== b.key) { return [void 0, void 0]; } const aHistoryLength = a.history ? a.history.length : a.routes.length; const bHistoryLength = b.history ? b.history.length : b.routes.length; const aRoute = a.routes[a.index]; const bRoute = b.routes[b.index]; const aChildState = aRoute.state; const bChildState = bRoute.state; if (aHistoryLength !== bHistoryLength || aRoute.key !== bRoute.key || aChildState === void 0 || bChildState === void 0 || aChildState.key !== bChildState.key) { return [a, b]; } return findMatchingState(aChildState, bChildState); }; const series = cb => { let queue = Promise.resolve(); const callback = () => { queue = queue.then(cb); }; return callback; }; const linkingHandlers = []; function useLinking(ref, { enabled = true, config, getStateFromPath = import_getStateFromPath.getStateFromPath, getPathFromState = import_core.getPathFromState, getActionFromState = import_core.getActionFromState }, onUnhandledLinking) { if (typeof window === "undefined") { const getInitialState2 = React.useCallback(() => { return { then(fn) { return Promise.resolve(fn ? fn(void 0) : void 0); }, catch() { return this; } }; }, []); return { getInitialState: getInitialState2 }; } const independent = (0, import_core.useNavigationIndependentTree)(); React.useEffect(() => { if (process.env.NODE_ENV === "production") { return void 0; } if (independent) { return void 0; } if (enabled !== false && linkingHandlers.length) { console.error(["Looks like you have configured linking in multiple places. This is likely an error since deep links should only be handled in one place to avoid conflicts. Make sure that:", "- You don't have multiple NavigationContainers in the app each with 'linking' enabled", "- Only a single instance of the root component is rendered"].join("\n").trim()); } const handler = Symbol(); if (enabled !== false) { linkingHandlers.push(handler); } return () => { const index = linkingHandlers.indexOf(handler); if (index > -1) { linkingHandlers.splice(index, 1); } }; }, [enabled, independent]); const [history] = React.useState(import_createMemoryHistory.createMemoryHistory); const enabledRef = React.useRef(enabled); const configRef = React.useRef(config); const getStateFromPathRef = React.useRef(getStateFromPath); const getPathFromStateRef = React.useRef(getPathFromState); const getActionFromStateRef = React.useRef(getActionFromState); const restoringFromTempLocationRef = React.useRef(false); const initialHistorySetupDoneRef = React.useRef(false); const maskedDisplayPathRef = React.useRef(void 0); React.useEffect(() => { enabledRef.current = enabled; configRef.current = config; getStateFromPathRef.current = getStateFromPath; getPathFromStateRef.current = getPathFromState; getActionFromStateRef.current = getActionFromState; }); const validateRoutesNotExistInRootState = React.useCallback(state => { const navigation = ref.current; const rootState = navigation?.getRootState(); const routeNames = rootState?.routeNames; if (!routeNames) { return false; } return state?.routes.some(r => !routeNames.includes(r.name)); }, [ref]); const location = React.useContext(import_serverLocationContext.ServerLocationContext); const server = { location }; const getInitialState = React.useCallback(() => { (0, import_interceptRoutes.setNavigationType)("hard"); (0, import_Navigator.clearAllSlotStates)(); let value; if (enabledRef.current) { const location2 = server?.location ?? (typeof window !== "undefined" ? window.location : void 0); let path = location2 ? location2.pathname + location2.search + (location2.hash ?? "") : void 0; if (location2 && typeof window !== "undefined") { const historyState = window.history.state; if (historyState) { const { __tempLocation, __tempKey } = historyState; if (__tempLocation?.pathname && !__tempKey) { path = __tempLocation.pathname + (__tempLocation.search || ""); restoringFromTempLocationRef.current = true; } } } if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F50D} getInitialState path=${path}`); } if (path) { value = getStateFromPathRef.current(path, configRef.current); } onUnhandledLinking(path); } const thenable = { // biome-ignore lint/suspicious/noThenProperty: don't check copied code then(onfulfilled) { return Promise.resolve(onfulfilled ? onfulfilled(value) : value); }, catch() { return thenable; } }; return thenable; }, []); const previousIndexRef = React.useRef(void 0); const previousStateRef = React.useRef(void 0); const pendingPopStatePathRef = React.useRef(void 0); React.useEffect(() => { previousIndexRef.current = history.index; return history.listen(() => { const navigation = ref.current; if (!navigation || !enabled) { return; } if ((0, import_interceptRoutes.isReturningFromIntercept)()) { (0, import_interceptRoutes.setReturningFromIntercept)(false); (0, import_Navigator.clearAllSlotStates)(); return; } if ((0, import_interceptRoutes.restoreInterceptFromHistory)()) { return; } (0, import_interceptRoutes.setNavigationType)("hard"); (0, import_Navigator.clearAllSlotStates)(); maskedDisplayPathRef.current = void 0; const { location: location2 } = window; const path = location2.pathname + location2.search; const index = history.index; const previousIndex = previousIndexRef.current ?? 0; if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} history.listen path=${path} index=${index} prevIndex=${previousIndex}`); } previousIndexRef.current = index; pendingPopStatePathRef.current = path; const record = history.get(index); const pathMatches = record?.path === path || record?.displayPath === path; if (pathMatches && record?.state) { if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} history record found, resetRoot to:`, record.state); } navigation.resetRoot(getPartialState(record.state)); return; } const state = getStateFromPathRef.current(path, configRef.current); if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} getStateFromPath result:`, state); } if (state) { onUnhandledLinking(path); if (validateRoutesNotExistInRootState(state)) { if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} routes not in root state, skipping`); } return; } if (index > previousIndex || index === previousIndex && (!record || `${record?.path}${location2.hash}` === path)) { const action = getActionFromStateRef.current(state, configRef.current); if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} dispatching action:`, action); } if (action !== void 0) { try { navigation.dispatch(action); } catch (e) { console.warn(`An error occurred when trying to handle the link '${path}': ${typeof e === "object" && e != null && "message" in e ? e.message : e}`); } } else { if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} no action, resetRoot`); } navigation.resetRoot(state); } } else { if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} going back, resetRoot`); } navigation.resetRoot(state); } } else { if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} no state for path, resetRoot to undefined`); } navigation.resetRoot(state); } }); }, [enabled, history, onUnhandledLinking, ref, validateRoutesNotExistInRootState]); React.useEffect(() => { if (!enabled) { return; } const getPathForRoute = (route, state) => { let path; if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} getPathForRoute - route:`, route); console.info(`[one] \u{1F4DC} getPathForRoute - state:`, JSON.stringify(state, null, 2)); } if (route?.path) { const stateForPath = getStateFromPathRef.current(route.path, configRef.current); if (stateForPath) { const focusedRoute = (0, import_core.findFocusedRoute)(stateForPath); if (focusedRoute && focusedRoute.name === route.name && (0, import_fast_deep_equal.default)(focusedRoute.params, route.params)) { path = (0, import_getPathFromState_mods.appendBaseUrl)(route.path); } } } if (path == null) { path = getPathFromStateRef.current(state, configRef.current); if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} getPathForRoute - computed from state:`, path); } } return path; }; if (ref.current) { const refState = ref.current.getRootState(); const state = import_router.rootState || refState; if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} useEffect initial state check - refState:`, JSON.stringify(refState, null, 2)); console.info(`[one] \u{1F4DC} useEffect initial state check - routerRootState:`, JSON.stringify(import_router.rootState, null, 2)); } if (state) { const route = (0, import_core.findFocusedRoute)(state); if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} useEffect focused route:`, route); } const path = getPathForRoute(route, state); if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} initial history.replace - state:`, JSON.stringify(state, null, 2)); console.info(`[one] \u{1F4DC} initial history.replace - focusedRoute:`, route); console.info(`[one] \u{1F4DC} initial history.replace - computed path:`, path); } if (previousStateRef.current === void 0) { previousStateRef.current = refState; } if (!initialHistorySetupDoneRef.current) { const historyState = window.history.state; const isRestoringFromMask = restoringFromTempLocationRef.current || historyState?.__tempLocation?.pathname && !historyState.__tempKey; if (isRestoringFromMask) { const displayPath = window.location.pathname + window.location.search; history.replace({ path, state, displayPath }); restoringFromTempLocationRef.current = false; maskedDisplayPathRef.current = { displayPath, actualPath: path }; } else { history.replace({ path, state }); } initialHistorySetupDoneRef.current = true; } } } const onStateChange = async () => { const navigation = ref.current; if (!navigation || !enabled) { return; } const previousState = previousStateRef.current; const refState = navigation.getRootState(); const state = import_router.rootState || refState; if (!state) { return; } const pendingPath = pendingPopStatePathRef.current; const route = (0, import_core.findFocusedRoute)(state); if (route && /^\(.*\)$/.test(route.name)) { if (process.env.ONE_DEBUG_ROUTER) { console.info(`[one] \u{1F4DC} onStateChange - skipping: focused route is a group`, route.name, `(child navigator not mounted yet)`); } return; } let path = getPathForRoute(route, state); if (typeof window !== "undefined" && !route?.params) { const currentSearch = window.location.search; if (currentSearch && !path.includes("?") && window.location.pathname === path) { path = path + currentSearch; } } const maskOptions = state.linkOptions?.mask; const maskHref = maskOptions?.href; const maskedInfo = maskedDisplayPathRef.current; let displayPath; if (maskedInfo) { if (path === maskedInfo.actualPath) { displayPath = maskedInfo.displayPath; } maskedDisplayPathRef.current = void 0; } if (!displayPath && maskHref) { displayPath = (0, import_getPathFromState_mods.appendBaseUrl)((0, import_matchers.stripGroupSegmentsFromPath)(maskHref) || "/"); } const unmaskOnReload = maskOptions?.unmaskOnReload; previousStateRef.current = refState; pendingPopStatePathRef.current = void 0; const [previousFocusedState, focusedState] = findMatchingState(previousState, state); if (previousFocusedState && focusedState && // We should only handle push/pop if path changed from what was in last `popstate` // Otherwise it's likely a change triggered by `popstate` path !== pendingPath) { const historyDelta = (focusedState.history ? focusedState.history.length : focusedState.routes.length) - (previousFocusedState.history ? previousFocusedState.history.length : previousFocusedState.routes.length); if (historyDelta > 0) { history.push({ path, state, displayPath, unmaskOnReload }); } else if (historyDelta < 0) { const nextIndex = history.backIndex({ path }); const currentIndex = history.index; try { if (nextIndex !== -1 && nextIndex < currentIndex && // We should only go back if the entry exists and it's less than current index history.get(nextIndex - currentIndex)) { await history.go(nextIndex - currentIndex); } else { await history.go(historyDelta); } history.replace({ path, state }); } catch (e) {} } else { history.replace({ path, state, displayPath, unmaskOnReload }); } } else { history.replace({ path, state, displayPath, unmaskOnReload }); } }; return ref.current?.addListener("state", series(onStateChange)); }, [enabled, history, ref]); return { getInitialState }; }