one
Version:
One is a new React Framework that makes Vite serve both native and web.
462 lines • 17.8 kB
JavaScript
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
};
}