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

View File

@@ -0,0 +1,5 @@
import { Href } from '../../types';
export declare function HrefPreview({ href }: {
href: Href;
}): import("react").JSX.Element;
//# sourceMappingURL=HrefPreview.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"HrefPreview.d.ts","sourceRoot":"","sources":["../../../src/link/preview/HrefPreview.tsx"],"names":[],"mappings":"AAkBA,OAAO,EAAE,IAAI,EAAuB,MAAM,aAAa,CAAC;AAKxD,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,+BAyCnD"}

View File

@@ -0,0 +1,162 @@
"use strict";
'use client';
Object.defineProperty(exports, "__esModule", { value: true });
exports.HrefPreview = HrefPreview;
const native_1 = require("@react-navigation/native");
const react_1 = require("react");
const react_native_1 = require("react-native");
const PreviewRouteContext_1 = require("./PreviewRouteContext");
const constants_1 = require("../../constants");
const composition_options_1 = require("../../fork/native-stack/composition-options");
const router_store_1 = require("../../global-state/router-store");
const utils_1 = require("../../global-state/utils");
const hooks_1 = require("../../hooks");
const useNavigation_1 = require("../../useNavigation");
const useScreens_1 = require("../../useScreens");
const linking_1 = require("../linking");
function HrefPreview({ href }) {
const hrefState = (0, react_1.useMemo)(() => getHrefState(href), [href]);
const index = hrefState?.index ?? 0;
let isProtected = false;
if (hrefState?.routes[index]?.name === constants_1.INTERNAL_SLOT_NAME) {
let routerState = hrefState;
let rnState = router_store_1.store.state;
while (routerState && rnState) {
const routerRoute = routerState.routes[0];
// When the route we want to show is not present in react-navigation state
// Then most likely it is a protected route
if (rnState.stale === false && !rnState.routeNames?.includes(routerRoute.name)) {
isProtected = true;
break;
}
const rnIndex = rnState.routes.findIndex((route) => route.name === routerRoute.name);
if (rnIndex === -1) {
break;
}
routerState = routerRoute.state;
rnState = rnState.routes[rnIndex]?.state;
}
if (!isProtected) {
return <PreviewForRootHrefState hrefState={hrefState} href={href}/>;
}
}
const pathname = href.toString();
const segments = pathname.split('/').filter(Boolean);
return (<PreviewRouteContext_1.PreviewRouteContext.Provider value={{
params: {},
pathname,
segments,
}}>
<PreviewForInternalRoutes />
</PreviewRouteContext_1.PreviewRouteContext.Provider>);
}
function PreviewForRootHrefState({ hrefState, href }) {
const navigation = (0, useNavigation_1.useNavigation)();
const { routeNode, params, state } = getParamsAndNodeFromHref(hrefState);
const path = state ? (0, linking_1.getPathFromState)(state) : undefined;
const value = (0, react_1.useMemo)(() => ({
params,
pathname: href.toString(),
segments: path?.split('/').filter(Boolean) || [],
}), [params, href]);
// This can happen in a theoretical case where the state is not yet initialized or is incorrectly initialized.
// This check ensures TypeScript type safety as well.
if (!routeNode) {
return null;
}
const Component = (0, useScreens_1.getQualifiedRouteComponent)(routeNode);
return (<PreviewRouteContext_1.PreviewRouteContext value={value}>
<composition_options_1.CompositionContext value={{ set: () => { }, unset: () => { } }}>
{/* Using NavigationContext to override useNavigation */}
<native_1.NavigationContext value={navigationPropWithWarnings}>
<Component navigation={navigation}/>
</native_1.NavigationContext>
</composition_options_1.CompositionContext>
</PreviewRouteContext_1.PreviewRouteContext>);
}
function PreviewForInternalRoutes() {
const pathname = (0, hooks_1.usePathname)();
return (<react_native_1.View style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
gap: 8,
backgroundColor: 'white',
}}>
<react_native_1.Text style={{ fontWeight: '600', fontSize: 24 }}>Invalid preview</react_native_1.Text>
<react_native_1.Text style={{ fontWeight: '200', fontSize: 14 }}>{pathname}</react_native_1.Text>
</react_native_1.View>);
}
function getHrefState(href) {
const hrefState = router_store_1.store.getStateForHref(href);
return hrefState;
}
function getParamsAndNodeFromHref(hrefState) {
const index = hrefState?.index ?? 0;
if (hrefState?.routes[index] && hrefState.routes[index].name !== constants_1.INTERNAL_SLOT_NAME) {
const name = hrefState.routes[index].name;
if (name === constants_1.SITEMAP_ROUTE_NAME || name === constants_1.NOT_FOUND_ROUTE_NAME) {
console.log(router_store_1.store.routeNode);
console.log(hrefState);
}
const error = `Expo Router Error: Expected navigation state to begin with one of [${(0, utils_1.getRootStackRouteNames)().join(', ')}] routes`;
if (process.env.NODE_ENV !== 'production') {
throw new Error(error);
}
else {
console.warn(error);
}
}
const initialState = hrefState?.routes[index]?.state;
let state = initialState;
let routeNode = router_store_1.store.routeNode;
const params = {};
while (state && routeNode) {
const route = state.routes[state.index || state.routes.length - 1];
Object.assign(params, route.params);
state = route.state;
routeNode = routeNode.children.find((child) => child.route === route.name);
}
return { params, routeNode, state: initialState };
}
const displayWarningForProp = (prop) => {
if (process.env.NODE_ENV !== 'production') {
console.warn(`navigation.${prop} should not be used in a previewed screen. To fix this issue, wrap navigation calls with 'if (!isPreview) { ... }'.`);
}
};
const createNOOPWithWarning = (prop) => () => displayWarningForProp(prop);
const navigationPropWithWarnings = {
setParams: createNOOPWithWarning('setParams'),
setOptions: createNOOPWithWarning('setOptions'),
addListener: (() => () => { }),
removeListener: () => { },
isFocused: () => true,
canGoBack: () => false,
dispatch: createNOOPWithWarning('dispatch'),
navigate: createNOOPWithWarning('navigate'),
goBack: createNOOPWithWarning('goBack'),
reset: createNOOPWithWarning('reset'),
push: createNOOPWithWarning('push'),
pop: createNOOPWithWarning('pop'),
popToTop: createNOOPWithWarning('popToTop'),
navigateDeprecated: createNOOPWithWarning('navigateDeprecated'),
preload: createNOOPWithWarning('preload'),
getId: () => {
displayWarningForProp('getId');
return '';
},
// @ts-expect-error
getParent: createNOOPWithWarning('getParent'),
getState: () => {
displayWarningForProp('getState');
return {
key: '',
index: 0,
routeNames: [],
routes: [],
type: '',
stale: false,
};
},
};
//# sourceMappingURL=HrefPreview.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
import { PropsWithChildren } from 'react';
export declare function LinkPreviewContextProvider({ children }: PropsWithChildren): import("react").JSX.Element;
export declare const useLinkPreviewContext: () => {
isStackAnimationDisabled: boolean;
openPreviewKey: string | undefined;
setOpenPreviewKey: (openPreviewKey: string | undefined) => void;
};
//# sourceMappingURL=LinkPreviewContext.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"LinkPreviewContext.d.ts","sourceRoot":"","sources":["../../../src/link/preview/LinkPreviewContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,iBAAiB,EAAiB,MAAM,OAAO,CAAC;AAWxE,wBAAgB,0BAA0B,CAAC,EAAE,QAAQ,EAAE,EAAE,iBAAiB,+BASzE;AAED,eAAO,MAAM,qBAAqB;8BAlBF,OAAO;oBACjB,MAAM,GAAG,SAAS;uBACf,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI;CAwBpE,CAAC"}

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useLinkPreviewContext = void 0;
exports.LinkPreviewContextProvider = LinkPreviewContextProvider;
const react_1 = require("react");
const LinkPreviewContext = (0, react_1.createContext)(undefined);
function LinkPreviewContextProvider({ children }) {
const [openPreviewKey, setOpenPreviewKey] = (0, react_1.useState)(undefined);
const isStackAnimationDisabled = openPreviewKey !== undefined;
return (<LinkPreviewContext.Provider value={{ isStackAnimationDisabled, openPreviewKey, setOpenPreviewKey }}>
{children}
</LinkPreviewContext.Provider>);
}
const useLinkPreviewContext = () => {
const context = (0, react_1.use)(LinkPreviewContext);
if (context == null) {
throw new Error('useLinkPreviewContext must be used within a LinkPreviewContextProvider. This is likely a bug in Expo Router.');
}
return context;
};
exports.useLinkPreviewContext = useLinkPreviewContext;
//# sourceMappingURL=LinkPreviewContext.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"LinkPreviewContext.js","sourceRoot":"","sources":["../../../src/link/preview/LinkPreviewContext.tsx"],"names":[],"mappings":";;;AAWA,gEASC;AApBD,iCAAwE;AAExE,MAAM,kBAAkB,GAAG,IAAA,qBAAa,EAOtC,SAAS,CAAC,CAAC;AAEb,SAAgB,0BAA0B,CAAC,EAAE,QAAQ,EAAqB;IACxE,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,IAAA,gBAAQ,EAAqB,SAAS,CAAC,CAAC;IACpF,MAAM,wBAAwB,GAAG,cAAc,KAAK,SAAS,CAAC;IAC9D,OAAO,CACL,CAAC,kBAAkB,CAAC,QAAQ,CAC1B,KAAK,CAAC,CAAC,EAAE,wBAAwB,EAAE,cAAc,EAAE,iBAAiB,EAAE,CAAC,CACvE;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAC/B,CAAC;AACJ,CAAC;AAEM,MAAM,qBAAqB,GAAG,GAAG,EAAE;IACxC,MAAM,OAAO,GAAG,IAAA,WAAG,EAAC,kBAAkB,CAAC,CAAC;IACxC,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,8GAA8G,CAC/G,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AARW,QAAA,qBAAqB,yBAQhC","sourcesContent":["import { createContext, PropsWithChildren, use, useState } from 'react';\n\nconst LinkPreviewContext = createContext<\n | {\n isStackAnimationDisabled: boolean;\n openPreviewKey: string | undefined;\n setOpenPreviewKey: (openPreviewKey: string | undefined) => void;\n }\n | undefined\n>(undefined);\n\nexport function LinkPreviewContextProvider({ children }: PropsWithChildren) {\n const [openPreviewKey, setOpenPreviewKey] = useState<string | undefined>(undefined);\n const isStackAnimationDisabled = openPreviewKey !== undefined;\n return (\n <LinkPreviewContext.Provider\n value={{ isStackAnimationDisabled, openPreviewKey, setOpenPreviewKey }}>\n {children}\n </LinkPreviewContext.Provider>\n );\n}\n\nexport const useLinkPreviewContext = () => {\n const context = use(LinkPreviewContext);\n if (context == null) {\n throw new Error(\n 'useLinkPreviewContext must be used within a LinkPreviewContextProvider. This is likely a bug in Expo Router.'\n );\n }\n return context;\n};\n"]}

View File

@@ -0,0 +1,22 @@
import type { UnknownOutputParams } from '../../types';
export interface PreviewRouteContextType {
params: UnknownOutputParams;
pathname: string;
segments: string[];
}
export declare const PreviewRouteContext: import("react").Context<PreviewRouteContextType | undefined>;
type UsePreviewInfo = {
isPreview: boolean;
} & Partial<PreviewRouteContextType>;
/**
* Returns information about the current route if it is displayed in preview mode.
*/
export declare function usePreviewInfo(): UsePreviewInfo;
/**
* Hook to determine if the current route is rendered inside a preview.
*
* @returns {boolean} - True if the current route is rendered inside a preview, false otherwise.
*/
export declare function useIsPreview(): boolean;
export {};
//# sourceMappingURL=PreviewRouteContext.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"PreviewRouteContext.d.ts","sourceRoot":"","sources":["../../../src/link/preview/PreviewRouteContext.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,eAAO,MAAM,mBAAmB,8DAAgE,CAAC;AAEjG,KAAK,cAAc,GAAG;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;AAEhF;;GAEG;AACH,wBAAgB,cAAc,IAAI,cAAc,CAM/C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAGtC"}

View File

@@ -0,0 +1,28 @@
"use strict";
'use client';
Object.defineProperty(exports, "__esModule", { value: true });
exports.PreviewRouteContext = void 0;
exports.usePreviewInfo = usePreviewInfo;
exports.useIsPreview = useIsPreview;
const react_1 = require("react");
exports.PreviewRouteContext = (0, react_1.createContext)(undefined);
/**
* Returns information about the current route if it is displayed in preview mode.
*/
function usePreviewInfo() {
const paramsContext = (0, react_1.use)(exports.PreviewRouteContext);
return {
isPreview: !!paramsContext,
...paramsContext,
};
}
/**
* Hook to determine if the current route is rendered inside a preview.
*
* @returns {boolean} - True if the current route is rendered inside a preview, false otherwise.
*/
function useIsPreview() {
const { isPreview } = usePreviewInfo();
return isPreview;
}
//# sourceMappingURL=PreviewRouteContext.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"PreviewRouteContext.js","sourceRoot":"","sources":["../../../src/link/preview/PreviewRouteContext.ts"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;AAmBb,wCAMC;AAOD,oCAGC;AAjCD,iCAA2C;AAU9B,QAAA,mBAAmB,GAAG,IAAA,qBAAa,EAAsC,SAAS,CAAC,CAAC;AAIjG;;GAEG;AACH,SAAgB,cAAc;IAC5B,MAAM,aAAa,GAAG,IAAA,WAAG,EAAC,2BAAmB,CAAC,CAAC;IAC/C,OAAO;QACL,SAAS,EAAE,CAAC,CAAC,aAAa;QAC1B,GAAG,aAAa;KACjB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,YAAY;IAC1B,MAAM,EAAE,SAAS,EAAE,GAAG,cAAc,EAAE,CAAC;IACvC,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["'use client';\n\nimport { createContext, use } from 'react';\n\nimport type { UnknownOutputParams } from '../../types';\n\nexport interface PreviewRouteContextType {\n params: UnknownOutputParams;\n pathname: string;\n segments: string[];\n}\n\nexport const PreviewRouteContext = createContext<PreviewRouteContextType | undefined>(undefined);\n\ntype UsePreviewInfo = { isPreview: boolean } & Partial<PreviewRouteContextType>;\n\n/**\n * Returns information about the current route if it is displayed in preview mode.\n */\nexport function usePreviewInfo(): UsePreviewInfo {\n const paramsContext = use(PreviewRouteContext);\n return {\n isPreview: !!paramsContext,\n ...paramsContext,\n };\n}\n\n/**\n * Hook to determine if the current route is rendered inside a preview.\n *\n * @returns {boolean} - True if the current route is rendered inside a preview, false otherwise.\n */\nexport function useIsPreview(): boolean {\n const { isPreview } = usePreviewInfo();\n return isPreview;\n}\n"]}

View File

@@ -0,0 +1,87 @@
import type { ImageRef } from 'expo-image';
import { type PropsWithChildren } from 'react';
import { type ViewProps, type ColorValue } from 'react-native';
import type { BasicTextStyle } from '../../utils/font';
export interface NativeLinkPreviewActionProps {
identifier: string;
title: string;
label?: string;
icon?: string;
xcassetName?: string;
image?: ImageRef | null;
imageRenderingMode?: 'template' | 'original';
children?: React.ReactNode;
disabled?: boolean;
destructive?: boolean;
discoverabilityLabel?: string;
subtitle?: string;
accessibilityLabel?: string;
accessibilityHint?: string;
displayAsPalette?: boolean;
displayInline?: boolean;
preferredElementSize?: 'auto' | 'small' | 'medium' | 'large';
isOn?: boolean;
keepPresented?: boolean;
hidden?: boolean;
tintColor?: ColorValue;
barButtonItemStyle?: 'plain' | 'prominent';
sharesBackground?: boolean;
hidesSharedBackground?: boolean;
onSelected: () => void;
titleStyle?: BasicTextStyle;
}
export declare function NativeLinkPreviewAction(props: NativeLinkPreviewActionProps): import("react").JSX.Element | null;
export interface TabPath {
oldTabKey: string;
newTabKey: string;
}
export interface NativeLinkPreviewProps extends ViewProps {
nextScreenId: string | undefined;
tabPath: {
path: TabPath[];
} | undefined;
disableForceFlatten?: boolean;
onWillPreviewOpen?: () => void;
onDidPreviewOpen?: () => void;
onPreviewWillClose?: () => void;
onPreviewDidClose?: () => void;
onPreviewTapped?: () => void;
onPreviewTappedAnimationCompleted?: () => void;
children: React.ReactNode;
}
export declare function NativeLinkPreview(props: NativeLinkPreviewProps): import("react").JSX.Element | null;
export interface NativeLinkPreviewContentProps extends ViewProps {
preferredContentSize?: {
width: number;
height: number;
};
}
export declare function NativeLinkPreviewContent(props: NativeLinkPreviewContentProps): import("react").JSX.Element | null;
interface DismissalBoundsRect {
minX?: number;
maxX?: number;
minY?: number;
maxY?: number;
}
export declare function LinkZoomTransitionEnabler(props: {
zoomTransitionSourceIdentifier: string;
dismissalBoundsRect?: DismissalBoundsRect | null;
}): import("react").JSX.Element | null;
interface LinkSourceAlignmentRect {
x: number;
y: number;
width: number;
height: number;
}
interface LinkZoomTransitionSourceProps extends PropsWithChildren {
identifier: string;
alignment?: LinkSourceAlignmentRect;
animateAspectRatioChange?: boolean;
}
export declare function LinkZoomTransitionSource(props: LinkZoomTransitionSourceProps): import("react").JSX.Element | null;
export declare function LinkZoomTransitionAlignmentRectDetector(props: {
identifier: string;
children: React.ReactNode;
}): import("react").JSX.Element | null;
export {};
//# sourceMappingURL=native.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../src/link/preview/native.tsx"],"names":[],"mappings":"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"}

81
node_modules/expo-router/build/link/preview/native.js generated vendored Normal file
View File

@@ -0,0 +1,81 @@
"use strict";
'use client';
Object.defineProperty(exports, "__esModule", { value: true });
exports.NativeLinkPreviewAction = NativeLinkPreviewAction;
exports.NativeLinkPreview = NativeLinkPreview;
exports.NativeLinkPreviewContent = NativeLinkPreviewContent;
exports.LinkZoomTransitionEnabler = LinkZoomTransitionEnabler;
exports.LinkZoomTransitionSource = LinkZoomTransitionSource;
exports.LinkZoomTransitionAlignmentRectDetector = LinkZoomTransitionAlignmentRectDetector;
const expo_1 = require("expo");
const react_1 = require("react");
const react_native_1 = require("react-native");
const areNativeViewsAvailable = process.env.EXPO_OS === 'ios' && !react_native_1.Platform.isTV && global.RN$Bridgeless === true;
const LinkPreviewNativeActionView = areNativeViewsAvailable
? (0, expo_1.requireNativeView)('ExpoRouterNativeLinkPreview', 'LinkPreviewNativeActionView')
: null;
function NativeLinkPreviewAction(props) {
if (!LinkPreviewNativeActionView) {
return null;
}
// Needed to pass shared object ID to native side
const imageObjectId = props.image?.__expo_shared_object_id__;
return <LinkPreviewNativeActionView {...props} image={imageObjectId}/>;
}
const NativeLinkPreviewView = areNativeViewsAvailable
? (0, expo_1.requireNativeView)('ExpoRouterNativeLinkPreview', 'NativeLinkPreviewView')
: null;
function NativeLinkPreview(props) {
if (!NativeLinkPreviewView) {
return null;
}
return <NativeLinkPreviewView {...props}/>;
}
const NativeLinkPreviewContentView = areNativeViewsAvailable
? (0, expo_1.requireNativeView)('ExpoRouterNativeLinkPreview', 'NativeLinkPreviewContentView')
: null;
function NativeLinkPreviewContent(props) {
if (!NativeLinkPreviewContentView) {
return null;
}
const style = react_native_1.StyleSheet.flatten([
props.style,
{
position: 'absolute',
top: 0,
left: 0,
},
]);
return <NativeLinkPreviewContentView {...props} style={style}/>;
}
const LinkZoomTransitionEnablerNativeView = areNativeViewsAvailable
? (0, expo_1.requireNativeView)('ExpoRouterNativeLinkPreview', 'LinkZoomTransitionEnabler')
: null;
function LinkZoomTransitionEnabler(props) {
if (!LinkZoomTransitionEnablerNativeView) {
return null;
}
return (<LinkZoomTransitionEnablerNativeView {...props} disableForceFlatten style={{ display: 'contents' }}/>);
}
const LinkZoomTransitionSourceNativeView = areNativeViewsAvailable
? (0, expo_1.requireNativeView)('ExpoRouterNativeLinkPreview', 'LinkZoomTransitionSource')
: null;
function LinkZoomTransitionSource(props) {
if (!LinkZoomTransitionSourceNativeView) {
return null;
}
return (<LinkZoomTransitionSourceNativeView {...props} disableForceFlatten collapsable={false} collapsableChildren={false} style={{ display: 'contents' }}/>);
}
// #endregion
// #region Zoom transition rect detector
const LinkZoomTransitionAlignmentRectDetectorNative = areNativeViewsAvailable
? (0, expo_1.requireNativeView)('ExpoRouterNativeLinkPreview', 'LinkZoomTransitionAlignmentRectDetector')
: react_1.Fragment;
function LinkZoomTransitionAlignmentRectDetector(props) {
if (!LinkZoomTransitionAlignmentRectDetectorNative) {
return null;
}
return (<LinkZoomTransitionAlignmentRectDetectorNative {...props} disableForceFlatten collapsable={false} collapsableChildren={false} style={{ display: 'contents' }}/>);
}
// #endregion
//# sourceMappingURL=native.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
import { TabPath } from './native';
import { Href } from '../../types';
export declare function useNextScreenId(): [
{
nextScreenId: string | undefined;
tabPath: TabPath[];
},
(href: Href) => void
];
//# sourceMappingURL=useNextScreenId.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"useNextScreenId.d.ts","sourceRoot":"","sources":["../../../src/link/preview/useNextScreenId.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAInC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,wBAAgB,eAAe,IAAI;IACjC;QAAE,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,OAAO,EAAE,CAAA;KAAE;IACxD,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI;CACrB,CAyCA"}

View File

@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useNextScreenId = useNextScreenId;
const react_1 = require("react");
const LinkPreviewContext_1 = require("./LinkPreviewContext");
const utils_1 = require("./utils");
const router_store_1 = require("../../global-state/router-store");
const hooks_1 = require("../../hooks");
function useNextScreenId() {
const router = (0, hooks_1.useRouter)();
const { setOpenPreviewKey } = (0, LinkPreviewContext_1.useLinkPreviewContext)();
const [internalNextScreenId, internalSetNextScreenId] = (0, react_1.useState)();
const currentHref = (0, react_1.useRef)(undefined);
const [tabPath, setTabPath] = (0, react_1.useState)([]);
(0, react_1.useEffect)(() => {
// When screen is prefetched, then the root state is updated with the preloaded route.
return router_store_1.store.navigationRef.addListener('state', ({ data: { state } }) => {
// If we have the current href, it means that we prefetched the route
if (currentHref.current && state) {
const preloadedRoute = (0, utils_1.getPreloadedRouteFromRootStateByHref)(currentHref.current, state);
const routeKey = preloadedRoute?.key;
const tabPathFromRootState = (0, utils_1.getTabPathFromRootStateByHref)(currentHref.current, state);
// Without this timeout react-native does not have enough time to mount the new screen
// and thus it will not be found on the native side
if (routeKey || tabPathFromRootState.length) {
setTimeout(() => {
internalSetNextScreenId(routeKey);
setOpenPreviewKey(routeKey);
setTabPath(tabPathFromRootState);
});
}
// We got the preloaded state, so we can reset the currentHref
// to prevent unnecessary processing
currentHref.current = undefined;
}
});
}, []);
const prefetch = (0, react_1.useCallback)((href) => {
// Resetting the nextScreenId to undefined
internalSetNextScreenId(undefined);
router.prefetch(href);
currentHref.current = href;
}, [router.prefetch]);
return [{ nextScreenId: internalNextScreenId, tabPath }, prefetch];
}
//# sourceMappingURL=useNextScreenId.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"useNextScreenId.js","sourceRoot":"","sources":["../../../src/link/preview/useNextScreenId.ts"],"names":[],"mappings":";;AASA,0CA4CC;AArDD,iCAAiE;AAEjE,6DAA6D;AAE7D,mCAA8F;AAC9F,kEAAwD;AACxD,uCAAwC;AAGxC,SAAgB,eAAe;IAI7B,MAAM,MAAM,GAAG,IAAA,iBAAS,GAAE,CAAC;IAC3B,MAAM,EAAE,iBAAiB,EAAE,GAAG,IAAA,0CAAqB,GAAE,CAAC;IACtD,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,GAAG,IAAA,gBAAQ,GAAsB,CAAC;IACvF,MAAM,WAAW,GAAG,IAAA,cAAM,EAAmB,SAAS,CAAC,CAAC;IACxD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAY,EAAE,CAAC,CAAC;IAEtD,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,sFAAsF;QACtF,OAAO,oBAAK,CAAC,aAAa,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;YACtE,qEAAqE;YACrE,IAAI,WAAW,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC;gBACjC,MAAM,cAAc,GAAG,IAAA,4CAAoC,EAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBACxF,MAAM,QAAQ,GAAG,cAAc,EAAE,GAAG,CAAC;gBACrC,MAAM,oBAAoB,GAAG,IAAA,qCAA6B,EAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBACvF,sFAAsF;gBACtF,mDAAmD;gBACnD,IAAI,QAAQ,IAAI,oBAAoB,CAAC,MAAM,EAAE,CAAC;oBAC5C,UAAU,CAAC,GAAG,EAAE;wBACd,uBAAuB,CAAC,QAAQ,CAAC,CAAC;wBAClC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;wBAC5B,UAAU,CAAC,oBAAoB,CAAC,CAAC;oBACnC,CAAC,CAAC,CAAC;gBACL,CAAC;gBACD,8DAA8D;gBAC9D,oCAAoC;gBACpC,WAAW,CAAC,OAAO,GAAG,SAAS,CAAC;YAClC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,QAAQ,GAAG,IAAA,mBAAW,EAC1B,CAAC,IAAU,EAAQ,EAAE;QACnB,0CAA0C;QAC1C,uBAAuB,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;IAC7B,CAAC,EACD,CAAC,MAAM,CAAC,QAAQ,CAAC,CAClB,CAAC;IACF,OAAO,CAAC,EAAE,YAAY,EAAE,oBAAoB,EAAE,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACrE,CAAC","sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { useLinkPreviewContext } from './LinkPreviewContext';\nimport { TabPath } from './native';\nimport { getPreloadedRouteFromRootStateByHref, getTabPathFromRootStateByHref } from './utils';\nimport { store } from '../../global-state/router-store';\nimport { useRouter } from '../../hooks';\nimport { Href } from '../../types';\n\nexport function useNextScreenId(): [\n { nextScreenId: string | undefined; tabPath: TabPath[] },\n (href: Href) => void,\n] {\n const router = useRouter();\n const { setOpenPreviewKey } = useLinkPreviewContext();\n const [internalNextScreenId, internalSetNextScreenId] = useState<string | undefined>();\n const currentHref = useRef<Href | undefined>(undefined);\n const [tabPath, setTabPath] = useState<TabPath[]>([]);\n\n useEffect(() => {\n // When screen is prefetched, then the root state is updated with the preloaded route.\n return store.navigationRef.addListener('state', ({ data: { state } }) => {\n // If we have the current href, it means that we prefetched the route\n if (currentHref.current && state) {\n const preloadedRoute = getPreloadedRouteFromRootStateByHref(currentHref.current, state);\n const routeKey = preloadedRoute?.key;\n const tabPathFromRootState = getTabPathFromRootStateByHref(currentHref.current, state);\n // Without this timeout react-native does not have enough time to mount the new screen\n // and thus it will not be found on the native side\n if (routeKey || tabPathFromRootState.length) {\n setTimeout(() => {\n internalSetNextScreenId(routeKey);\n setOpenPreviewKey(routeKey);\n setTabPath(tabPathFromRootState);\n });\n }\n // We got the preloaded state, so we can reset the currentHref\n // to prevent unnecessary processing\n currentHref.current = undefined;\n }\n });\n }, []);\n\n const prefetch = useCallback(\n (href: Href): void => {\n // Resetting the nextScreenId to undefined\n internalSetNextScreenId(undefined);\n router.prefetch(href);\n currentHref.current = href;\n },\n [router.prefetch]\n );\n return [{ nextScreenId: internalNextScreenId, tabPath }, prefetch];\n}\n"]}

12
node_modules/expo-router/build/link/preview/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,12 @@
import { ParamListBase, type NavigationRoute } from '@react-navigation/native';
import { type ReactNavigationState } from '../../global-state/router-store';
import { Href } from '../../types';
import { TabPath } from './native';
export declare function getTabPathFromRootStateByHref(href: Href, rootState: ReactNavigationState): TabPath[];
export declare function getPreloadedRouteFromRootStateByHref(href: Href, rootState: ReactNavigationState): NavigationRoute<ParamListBase, string> | undefined;
export declare function deepEqual(a: {
[key: string]: any;
} | undefined, b: {
[key: string]: any;
} | undefined): boolean;
//# sourceMappingURL=utils.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/link/preview/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAEb,KAAK,eAAe,EAGrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAS,KAAK,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEnF,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAGnC,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,oBAAoB,GAC9B,OAAO,EAAE,CA6BX;AAED,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,oBAAoB,GAC9B,eAAe,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,SAAS,CAgDpD;AAED,wBAAgB,SAAS,CACvB,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,GAAG,SAAS,EACrC,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,GAAG,SAAS,GACpC,OAAO,CAYT"}

78
node_modules/expo-router/build/link/preview/utils.js generated vendored Normal file
View File

@@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTabPathFromRootStateByHref = getTabPathFromRootStateByHref;
exports.getPreloadedRouteFromRootStateByHref = getPreloadedRouteFromRootStateByHref;
exports.deepEqual = deepEqual;
const router_store_1 = require("../../global-state/router-store");
const routing_1 = require("../../global-state/routing");
const href_1 = require("../href");
const navigationParams_1 = require("../../navigationParams");
function getTabPathFromRootStateByHref(href, rootState) {
const hrefState = router_store_1.store.getStateForHref((0, href_1.resolveHref)(href));
const state = rootState;
if (!hrefState || !state) {
return [];
}
// Replicating the logic from `linkTo`
const { navigationRoutes } = (0, routing_1.findDivergentState)(hrefState, state, true);
if (!navigationRoutes.length) {
return [];
}
const tabPath = [];
navigationRoutes.forEach((route, i, arr) => {
if (route.state?.type === 'tab') {
const tabState = route.state;
const oldTabKey = tabState.routes[tabState.index].key;
// The next route will be either stack inside a tab or a new tab key
if (!arr[i + 1]) {
throw new Error(`New tab route is missing for ${route.key}. This is likely an internal Expo Router bug.`);
}
const newTabKey = arr[i + 1].key;
tabPath.push({ oldTabKey, newTabKey });
}
});
return tabPath;
}
function getPreloadedRouteFromRootStateByHref(href, rootState) {
const hrefState = router_store_1.store.getStateForHref((0, href_1.resolveHref)(href));
const state = rootState;
if (!hrefState || !state) {
return undefined;
}
// Replicating the logic from `linkTo`
const { navigationState, actionStateRoute } = (0, routing_1.findDivergentState)(hrefState, state, true);
if (!navigationState || !actionStateRoute) {
return undefined;
}
if (navigationState.type === 'stack') {
const stackState = navigationState;
const payload = (0, routing_1.getPayloadFromStateRoute)(actionStateRoute);
const preloadedRoute = stackState.preloadedRoutes.find((route) => route.name === actionStateRoute.name &&
deepEqual((0, navigationParams_1.removeInternalExpoRouterParams)(route.params), (0, navigationParams_1.removeInternalExpoRouterParams)(payload.params)));
const activeRoute = stackState.routes[stackState.index];
// When the active route is the same as the preloaded route,
// then we should not navigate. It aligns with base link behavior.
if (activeRoute.name === preloadedRoute?.name &&
deepEqual(
// using ?? {}, because from our perspective undefined === {}, as both mean no params
(0, navigationParams_1.removeInternalExpoRouterParams)(activeRoute.params ?? {}), (0, navigationParams_1.removeInternalExpoRouterParams)(payload.params ?? {}))) {
return undefined;
}
return preloadedRoute;
}
return undefined;
}
function deepEqual(a, b) {
if (a === b) {
return true;
}
if (a == null || b == null) {
return false;
}
if (typeof a !== 'object' || typeof b !== 'object') {
return false;
}
const keys = Object.keys(a);
return keys.length === Object.keys(b).length && keys.every((key) => deepEqual(a[key], b[key]));
}
//# sourceMappingURL=utils.js.map

File diff suppressed because one or more lines are too long