first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

354
node_modules/expo-router/build/useScreens.js generated vendored Normal file
View File

@@ -0,0 +1,354 @@
"use strict";
'use client';
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useSortedScreens = useSortedScreens;
exports.getQualifiedRouteComponent = getQualifiedRouteComponent;
exports.screenOptionsFactory = screenOptionsFactory;
exports.routeToScreen = routeToScreen;
exports.getSingularId = getSingularId;
const native_1 = require("@react-navigation/native");
const react_1 = __importStar(require("react"));
const Route_1 = require("./Route");
const storeContext_1 = require("./global-state/storeContext");
const utils_1 = require("./global-state/utils");
const import_mode_1 = __importDefault(require("./import-mode"));
const ZoomTransitionEnabler_1 = require("./link/zoom/ZoomTransitionEnabler");
const zoom_transition_context_providers_1 = require("./link/zoom/zoom-transition-context-providers");
const navigationEvents_1 = require("./navigationEvents");
const utils_2 = require("./navigationEvents/utils");
const navigationParams_1 = require("./navigationParams");
const primitives_1 = require("./primitives");
const EmptyRoute_1 = require("./views/EmptyRoute");
const SuspenseFallback_1 = require("./views/SuspenseFallback");
const Try_1 = require("./views/Try");
function getSortedChildren(children, order = [], initialRouteName) {
if (!order?.length) {
return children
.sort((0, Route_1.sortRoutesWithInitial)(initialRouteName))
.map((route) => ({ route, props: {} }));
}
const entries = [...children];
const ordered = order
.map(({ name, redirect, initialParams, listeners, options, getId, dangerouslySingular: singular, }) => {
if (!entries.length) {
console.warn(`[Layout children]: Too many screens defined. Route "${name}" is extraneous.`);
return null;
}
const matchIndex = entries.findIndex((child) => child.route === name);
if (matchIndex === -1) {
console.warn(`[Layout children]: No route named "${name}" exists in nested children:`, children.map(({ route }) => route));
return null;
}
else {
// Get match and remove from entries
const match = entries[matchIndex];
entries.splice(matchIndex, 1);
// Ensure to return null after removing from entries.
if (redirect) {
if (typeof redirect === 'string') {
throw new Error(`Redirecting to a specific route is not supported yet.`);
}
return null;
}
if (getId) {
console.warn(`Deprecated: prop 'getId' on screen ${name} is deprecated. Please rename the prop to 'dangerouslySingular'`);
if (singular) {
console.warn(`Screen ${name} cannot use both getId and dangerouslySingular together.`);
}
}
else if (singular) {
// If singular is set, use it as the getId function.
if (typeof singular === 'string') {
getId = () => singular;
}
else if (typeof singular === 'function' && name) {
getId = (options) => singular(name, options.params || {});
}
else if (singular === true && name) {
getId = (options) => getSingularId(name, options);
}
}
return {
route: match,
props: { initialParams, listeners, options, getId },
};
}
})
.filter(Boolean);
// Add any remaining children
ordered.push(...entries.sort((0, Route_1.sortRoutesWithInitial)(initialRouteName)).map((route) => ({ route, props: {} })));
return ordered;
}
/**
* @returns React Navigation screens sorted by the `route` property.
*/
function useSortedScreens(order, protectedScreens, useOnlyUserDefinedScreens = false) {
const node = (0, Route_1.useRouteNode)();
const nodeChildren = node?.children ?? [];
const children = useOnlyUserDefinedScreens
? nodeChildren.filter((child) => order.some((userDefinedScreen) => userDefinedScreen.name === child.route))
: nodeChildren;
const sorted = children.length ? getSortedChildren(children, order, node?.initialRouteName) : [];
return react_1.default.useMemo(() => sorted
.filter((item) => !protectedScreens.has(item.route.route))
.map((value) => {
return routeToScreen(value.route, value.props);
}), [sorted, protectedScreens]);
}
function fromImport(value, { ErrorBoundary, ...component }) {
// If possible, add a more helpful display name for the component stack to improve debugging of React errors such as `Text strings must be rendered within a <Text> component.`.
if (component?.default && __DEV__) {
component.default.displayName ??= `${component.default.name ?? 'Route'}(${value.contextKey})`;
}
if (ErrorBoundary) {
const Wrapped = react_1.default.forwardRef((props, ref) => {
const children = react_1.default.createElement(component.default || EmptyRoute_1.EmptyRoute, {
...props,
ref,
});
return <Try_1.Try catch={ErrorBoundary}>{children}</Try_1.Try>;
});
if (__DEV__) {
Wrapped.displayName = `ErrorBoundary(${value.contextKey})`;
}
return {
default: Wrapped,
};
}
if (process.env.NODE_ENV !== 'production') {
if (typeof component.default === 'object' &&
component.default &&
Object.keys(component.default).length === 0) {
return { default: EmptyRoute_1.EmptyRoute };
}
}
return { default: component.default };
}
function fromLoadedRoute(value, res) {
if (!(res instanceof Promise)) {
return fromImport(value, res);
}
return res.then(fromImport.bind(null, value));
}
// TODO: Maybe there's a more React-y way to do this?
// Without this store, the process enters a recursive loop.
const qualifiedStore = new WeakMap();
/** Wrap the component with various enhancements and add access to child routes. */
function getQualifiedRouteComponent(value) {
if (qualifiedStore.has(value)) {
return qualifiedStore.get(value);
}
let ScreenComponent;
// TODO: This ensures sync doesn't use React.lazy, but it's not ideal.
if (import_mode_1.default === 'lazy') {
ScreenComponent = react_1.default.lazy(async () => {
const res = value.loadRoute();
return fromLoadedRoute(value, res);
});
if (__DEV__) {
ScreenComponent.displayName = `AsyncRoute(${value.route})`;
}
}
else {
const res = value.loadRoute();
ScreenComponent = fromImport(value, res).default;
}
const WrappedScreenComponent = (props) => {
(0, utils_1.useColorSchemeChangesIfNeeded)();
return <ScreenComponent {...props}/>;
};
function BaseRoute({
// Remove these React Navigation props to
// enforce usage of expo-router hooks (where the query params are correct).
route, navigation,
// Pass all other props to the component
...props }) {
const stateForPath = (0, native_1.useStateForPath)();
const isFocused = navigation.isFocused();
const store = (0, storeContext_1.useExpoRouterStore)();
if (isFocused) {
const state = navigation.getState();
const isLeaf = !(state && 'state' in state.routes[state.index]);
if (isLeaf && stateForPath)
store.setFocusedState(stateForPath);
}
(0, react_1.useEffect)(() => navigation.addListener('focus', () => {
const state = navigation.getState();
const isLeaf = !(state && 'state' in state.routes[state.index]);
// Because setFocusedState caches the route info, this call will only trigger rerenders
// if the component itself didnt rerender and the route info changed.
// Otherwise, the update from the `if` above will handle it,
// and this wont cause a redundant second update.
if (isLeaf && stateForPath)
store.setFocusedState(stateForPath);
}), [navigation]);
(0, react_1.useEffect)(() => {
return navigation.addListener('transitionEnd', (e) => {
if (!e?.data?.closing) {
// When navigating to a screen, remove the no animation param to re-enable animations
// Otherwise the navigation back would also have no animation
if ((0, navigationParams_1.hasParam)(route?.params, navigationParams_1.INTERNAL_EXPO_ROUTER_NO_ANIMATION_PARAM_NAME)) {
navigation.replaceParams((0, navigationParams_1.removeParams)(route?.params, [navigationParams_1.INTERNAL_EXPO_ROUTER_NO_ANIMATION_PARAM_NAME]));
}
}
});
}, [navigation]);
const isRouteType = value.type === 'route';
const hasRouteKey = !!route?.key;
return (<Route_1.Route node={value} params={route?.params}>
{navigationEvents_1.unstable_navigationEvents.isEnabled() && isRouteType && hasRouteKey && (<AnalyticsListeners navigation={navigation} screenId={route.key}/>)}
<zoom_transition_context_providers_1.ZoomTransitionTargetContextProvider route={route}>
<ZoomTransitionEnabler_1.ZoomTransitionEnabler route={route}/>
<react_1.default.Suspense fallback={<SuspenseFallback_1.SuspenseFallback route={value}/>}>
<WrappedScreenComponent {...props}
// Expose the template segment path, e.g. `(home)`, `[foo]`, `index`
// the intention is to make it possible to deduce shared routes.
segment={value.route}/>
</react_1.default.Suspense>
</zoom_transition_context_providers_1.ZoomTransitionTargetContextProvider>
</Route_1.Route>);
}
if (__DEV__) {
BaseRoute.displayName = `Route(${value.route})`;
}
qualifiedStore.set(value, BaseRoute);
return BaseRoute;
}
function AnalyticsListeners({ navigation, screenId, }) {
const stateForPath = (0, native_1.useStateForPath)();
const isFirstRenderRef = react_1.default.useRef(true);
const hasBlurredRef = react_1.default.useRef(true);
const stringUrl = (0, react_1.useMemo)(() => (0, utils_2.generateStringUrlForState)(stateForPath), [stateForPath]);
if (isFirstRenderRef.current) {
isFirstRenderRef.current = false;
if (stringUrl) {
navigationEvents_1.unstable_navigationEvents.emit('pageWillRender', {
...(0, utils_2.getPathAndParamsFromStringUrl)(stringUrl),
screenId,
});
}
}
(0, react_1.useEffect)(() => {
if (stringUrl) {
return () => {
navigationEvents_1.unstable_navigationEvents.emit('pageRemoved', {
...(0, utils_2.getPathAndParamsFromStringUrl)(stringUrl),
screenId,
});
};
}
return () => { };
}, [stringUrl, screenId]);
const isFocused = navigation.isFocused();
if (isFocused && stringUrl) {
navigationEvents_1.unstable_navigationEvents.emit('pageFocused', {
...(0, utils_2.getPathAndParamsFromStringUrl)(stringUrl),
screenId,
});
hasBlurredRef.current = false;
}
(0, react_1.useEffect)(() => {
if (stringUrl) {
const cleanFocus = navigation.addListener('focus', () => {
// If the screen was not blurred, don't emit focused again
// hasBlurredRef will be false when the screen was initially focused
if (hasBlurredRef.current) {
navigationEvents_1.unstable_navigationEvents.emit('pageFocused', {
...(0, utils_2.getPathAndParamsFromStringUrl)(stringUrl),
screenId,
});
hasBlurredRef.current = false;
}
});
const cleanBlur = navigation.addListener('blur', () => {
navigationEvents_1.unstable_navigationEvents.emit('pageBlurred', {
...(0, utils_2.getPathAndParamsFromStringUrl)(stringUrl),
screenId,
});
hasBlurredRef.current = true;
});
return () => {
cleanFocus();
cleanBlur();
};
}
return () => { };
}, [navigation, stringUrl, screenId]);
return null;
}
function screenOptionsFactory(route, options) {
return (args) => {
// Only eager load generated components
const staticOptions = route.generated ? route.loadRoute()?.getNavOptions : null;
const staticResult = typeof staticOptions === 'function' ? staticOptions(args) : staticOptions;
const dynamicResult = typeof options === 'function' ? options?.(args) : options;
const output = {
...staticResult,
...dynamicResult,
};
// Prevent generated screens from showing up in the tab bar.
if (route.internal) {
output.tabBarItemStyle = { display: 'none' };
output.tabBarButton = () => null;
// TODO: React Navigation doesn't provide a way to prevent rendering the drawer item.
output.drawerItemStyle = { height: 0, display: 'none' };
}
return output;
};
}
function routeToScreen(route, { options, getId, ...props } = {}) {
return (<primitives_1.Screen {...props} name={route.route} key={route.route} getId={getId} options={screenOptionsFactory(route, options)} getComponent={() => getQualifiedRouteComponent(route)}/>);
}
function getSingularId(name, options = {}) {
return name
.split('/')
.map((segment) => {
if (segment.startsWith('[...')) {
return options.params?.[segment.slice(4, -1)]?.join('/') || segment;
}
else if (segment.startsWith('[') && segment.endsWith(']')) {
return options.params?.[segment.slice(1, -1)] || segment;
}
else {
return segment;
}
})
.join('/');
}
//# sourceMappingURL=useScreens.js.map