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,4 @@
import { NativeStackView as RNNativeStackView } from '@react-navigation/native-stack';
import { ComponentProps } from 'react';
export declare function NativeStackView(props: ComponentProps<typeof RNNativeStackView>): import("react").JSX.Element;
//# sourceMappingURL=NativeStackView.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NativeStackView.d.ts","sourceRoot":"","sources":["../../../src/fork/native-stack/NativeStackView.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,IAAI,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACtF,OAAO,EAAE,cAAc,EAAgB,MAAM,OAAO,CAAC;AAIrD,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,iBAAiB,CAAC,+BAM9E"}

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NativeStackView = NativeStackView;
const native_stack_1 = require("@react-navigation/native-stack");
const react_1 = require("react");
const RootModal_1 = require("../../layouts/RootModal");
function NativeStackView(props) {
return (<RootModal_1.RootModalProvider>
<NativeStackViewInner {...props}/>
</RootModal_1.RootModalProvider>);
}
function NativeStackViewInner(props) {
const rootModals = (0, react_1.use)(RootModal_1.RootModalContext);
// Append the root modals to the state
const state = (0, react_1.useMemo)(() => {
if (rootModals.routes.length === 0) {
return props.state;
}
return {
...props.state,
routes: props.state.routes.concat(rootModals.routes),
};
}, [props.state, rootModals.routes]);
return <native_stack_1.NativeStackView {...props} state={state}/>;
}
//# sourceMappingURL=NativeStackView.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NativeStackView.js","sourceRoot":"","sources":["../../../src/fork/native-stack/NativeStackView.tsx"],"names":[],"mappings":";;AAKA,0CAMC;AAXD,iEAAsF;AACtF,iCAAqD;AAErD,uDAA8E;AAE9E,SAAgB,eAAe,CAAC,KAA+C;IAC7E,OAAO,CACL,CAAC,6BAAiB,CAChB;MAAA,CAAC,oBAAoB,CAAC,IAAI,KAAK,CAAC,EAClC;IAAA,EAAE,6BAAiB,CAAC,CACrB,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,KAA+C;IAC3E,MAAM,UAAU,GAAG,IAAA,WAAG,EAAC,4BAAgB,CAAC,CAAC;IAEzC,sCAAsC;IACtC,MAAM,KAAK,GAAG,IAAA,eAAO,EAAC,GAAG,EAAE;QACzB,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC,KAAK,CAAC;QACrB,CAAC;QAED,OAAO;YACL,GAAG,KAAK,CAAC,KAAK;YACd,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;SACrD,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAErC,OAAO,CAAC,8BAAiB,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAG,CAAC;AACxD,CAAC","sourcesContent":["import { NativeStackView as RNNativeStackView } from '@react-navigation/native-stack';\nimport { ComponentProps, use, useMemo } from 'react';\n\nimport { RootModalContext, RootModalProvider } from '../../layouts/RootModal';\n\nexport function NativeStackView(props: ComponentProps<typeof RNNativeStackView>) {\n return (\n <RootModalProvider>\n <NativeStackViewInner {...props} />\n </RootModalProvider>\n );\n}\n\nfunction NativeStackViewInner(props: ComponentProps<typeof RNNativeStackView>) {\n const rootModals = use(RootModalContext);\n\n // Append the root modals to the state\n const state = useMemo(() => {\n if (rootModals.routes.length === 0) {\n return props.state;\n }\n\n return {\n ...props.state,\n routes: props.state.routes.concat(rootModals.routes),\n };\n }, [props.state, rootModals.routes]);\n\n return <RNNativeStackView {...props} state={state} />;\n}\n"]}

View File

@@ -0,0 +1,38 @@
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
import type { CompositionContextValue, CompositionRegistry } from './types';
/** @internal */
export declare const CompositionContext: import("react").Context<CompositionContextValue | null>;
type RegistryAction = {
type: 'set';
routeKey: string;
options: Partial<NativeStackNavigationOptions>;
} | {
type: 'unset';
routeKey: string;
options: Partial<NativeStackNavigationOptions>;
};
/** @internal */
export declare function registryReducer(state: CompositionRegistry, action: RegistryAction): CompositionRegistry;
/**
* Provides the composition registry to descendant composition components.
*
* Uses useReducer with immutable object updates for React Compiler compatibility.
* Each set/unset call produces a new object reference, which the compiler can
* track as a reactive dependency.
*/
export declare function useCompositionRegistry(): {
registry: CompositionRegistry;
contextValue: {
set: (routeKey: string, options: Partial<NativeStackNavigationOptions>) => void;
unset: (routeKey: string, options: Partial<NativeStackNavigationOptions>) => void;
};
};
/**
* Hook used by composition components to register their options in the composition registry.
*
* Registers options on mount/update via useSafeLayoutEffect, and unregisters on unmount.
* Callers should memoize the options object to avoid unnecessary re-registrations.
*/
export declare function useCompositionOption(options: Partial<NativeStackNavigationOptions>): void;
export {};
//# sourceMappingURL=CompositionOptionsContext.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CompositionOptionsContext.d.ts","sourceRoot":"","sources":["../../../../src/fork/native-stack/composition-options/CompositionOptionsContext.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAGnF,OAAO,KAAK,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAG5E,gBAAgB;AAChB,eAAO,MAAM,kBAAkB,yDAAsD,CAAC;AAEtF,KAAK,cAAc,GACf;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC,4BAA4B,CAAC,CAAC;CAChD,GACD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,4BAA4B,CAAC,CAAA;CAAE,CAAC;AAExF,gBAAgB;AAChB,wBAAgB,eAAe,CAC7B,KAAK,EAAE,mBAAmB,EAC1B,MAAM,EAAE,cAAc,GACrB,mBAAmB,CAuBrB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB;;;wBAGD,MAAM,WAAW,OAAO,CAAC,4BAA4B,CAAC;0BAIpD,MAAM,WAAW,OAAO,CAAC,4BAA4B,CAAC;;EAS5F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,4BAA4B,CAAC,QAiBlF"}

View File

@@ -0,0 +1,75 @@
"use strict";
'use client';
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompositionContext = void 0;
exports.registryReducer = registryReducer;
exports.useCompositionRegistry = useCompositionRegistry;
exports.useCompositionOption = useCompositionOption;
const native_1 = require("@react-navigation/native");
const react_1 = require("react");
const useSafeLayoutEffect_1 = require("../../../views/useSafeLayoutEffect");
/** @internal */
exports.CompositionContext = (0, react_1.createContext)(null);
/** @internal */
function registryReducer(state, action) {
if (action.type === 'set') {
const { routeKey, options } = action;
if (state[routeKey]?.includes(options)) {
return state;
}
return { ...state, [routeKey]: [...(state[routeKey] ?? []), options] };
}
if (action.type === 'unset') {
const { routeKey, options } = action;
const existing = state[routeKey];
const filtered = existing?.filter((o) => o !== options);
if (!existing || filtered?.length === existing.length) {
return state;
}
if (filtered.length === 0) {
const { [routeKey]: _, ...newState } = state;
return newState;
}
return { ...state, [routeKey]: filtered };
}
return state;
}
/**
* Provides the composition registry to descendant composition components.
*
* Uses useReducer with immutable object updates for React Compiler compatibility.
* Each set/unset call produces a new object reference, which the compiler can
* track as a reactive dependency.
*/
function useCompositionRegistry() {
const [registry, dispatch] = (0, react_1.useReducer)(registryReducer, {});
const set = (0, react_1.useCallback)((routeKey, options) => {
dispatch({ type: 'set', routeKey, options });
}, []);
const unset = (0, react_1.useCallback)((routeKey, options) => {
dispatch({ type: 'unset', routeKey, options });
}, []);
const contextValue = (0, react_1.useMemo)(() => ({ set, unset }), [set, unset]);
return { registry, contextValue };
}
/**
* Hook used by composition components to register their options in the composition registry.
*
* Registers options on mount/update via useSafeLayoutEffect, and unregisters on unmount.
* Callers should memoize the options object to avoid unnecessary re-registrations.
*/
function useCompositionOption(options) {
const context = (0, react_1.use)(exports.CompositionContext);
if (!context) {
throw new Error('useCompositionOption must be used within a RouterCompositionOptionsProvider. This is likely a bug in Expo Router.');
}
const route = (0, native_1.useRoute)();
const { set, unset } = context;
(0, useSafeLayoutEffect_1.useSafeLayoutEffect)(() => {
set(route.key, options);
return () => {
unset(route.key, options);
};
}, [route.key, set, unset, options]);
}
//# sourceMappingURL=CompositionOptionsContext.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
export { mergeOptions } from './mergeOptions';
export { CompositionContext, useCompositionRegistry, useCompositionOption, } from './CompositionOptionsContext';
export type { CompositionRegistry, CompositionContextValue } from './types';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/fork/native-stack/composition-options/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC"}

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useCompositionOption = exports.useCompositionRegistry = exports.CompositionContext = exports.mergeOptions = void 0;
var mergeOptions_1 = require("./mergeOptions");
Object.defineProperty(exports, "mergeOptions", { enumerable: true, get: function () { return mergeOptions_1.mergeOptions; } });
var CompositionOptionsContext_1 = require("./CompositionOptionsContext");
Object.defineProperty(exports, "CompositionContext", { enumerable: true, get: function () { return CompositionOptionsContext_1.CompositionContext; } });
Object.defineProperty(exports, "useCompositionRegistry", { enumerable: true, get: function () { return CompositionOptionsContext_1.useCompositionRegistry; } });
Object.defineProperty(exports, "useCompositionOption", { enumerable: true, get: function () { return CompositionOptionsContext_1.useCompositionOption; } });
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/fork/native-stack/composition-options/index.ts"],"names":[],"mappings":";;;AAAA,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AACrB,yEAIqC;AAHnC,+HAAA,kBAAkB,OAAA;AAClB,mIAAA,sBAAsB,OAAA;AACtB,iIAAA,oBAAoB,OAAA","sourcesContent":["export { mergeOptions } from './mergeOptions';\nexport {\n CompositionContext,\n useCompositionRegistry,\n useCompositionOption,\n} from './CompositionOptionsContext';\nexport type { CompositionRegistry, CompositionContextValue } from './types';\n"]}

View File

@@ -0,0 +1,13 @@
import type { ParamListBase, StackNavigationState } from '@react-navigation/native';
import type { NativeStackDescriptorMap } from '../descriptors-context';
import type { CompositionRegistry } from './types';
/**
* Merges composition component options into navigation descriptors.
*
* For each descriptor:
* 1. If no composition options registered → pass through unchanged
* 2. If route is preloaded AND not focused → skip composition (pass through)
* 3. Otherwise → merge descriptor.options with composition options (composition wins)
*/
export declare function mergeOptions(descriptors: NativeStackDescriptorMap, registry: CompositionRegistry, state: StackNavigationState<ParamListBase>): NativeStackDescriptorMap;
//# sourceMappingURL=mergeOptions.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"mergeOptions.d.ts","sourceRoot":"","sources":["../../../../src/fork/native-stack/composition-options/mergeOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEpF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,WAAW,EAAE,wBAAwB,EACrC,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,oBAAoB,CAAC,aAAa,CAAC,GACzC,wBAAwB,CAiC1B"}

View File

@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mergeOptions = mergeOptions;
/**
* Merges composition component options into navigation descriptors.
*
* For each descriptor:
* 1. If no composition options registered → pass through unchanged
* 2. If route is preloaded AND not focused → skip composition (pass through)
* 3. Otherwise → merge descriptor.options with composition options (composition wins)
*/
function mergeOptions(descriptors, registry, state) {
const result = {};
const focusedKey = state.routes[state.index]?.key;
for (const key in descriptors) {
const descriptor = descriptors[key];
const routeOptions = registry[key];
// No composition options or empty array → pass through
if (!routeOptions || routeOptions.length === 0) {
result[key] = descriptor;
continue;
}
// Check if route is preloaded and not focused → skip composition
const isPreloaded = state.preloadedRoutes?.some((r) => r.key === key) ?? false;
if (isPreloaded && key !== focusedKey) {
result[key] = descriptor;
continue;
}
// Merge: descriptor options as base, composition options override
const mergedOptions = Object.assign({}, descriptor.options, ...routeOptions);
const merged = {
...descriptor,
options: mergedOptions,
};
result[key] = merged;
}
return result;
}
//# sourceMappingURL=mergeOptions.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"mergeOptions.js","sourceRoot":"","sources":["../../../../src/fork/native-stack/composition-options/mergeOptions.ts"],"names":[],"mappings":";;AAaA,oCAqCC;AA7CD;;;;;;;GAOG;AACH,SAAgB,YAAY,CAC1B,WAAqC,EACrC,QAA6B,EAC7B,KAA0C;IAE1C,MAAM,MAAM,GAA6B,EAAE,CAAC;IAC5C,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC;IAElD,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAEnC,uDAAuD;QACvD,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/C,MAAM,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC;YACzB,SAAS;QACX,CAAC;QAED,iEAAiE;QACjE,MAAM,WAAW,GAAG,KAAK,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,IAAI,KAAK,CAAC;QAC/E,IAAI,WAAW,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACtC,MAAM,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC;YACzB,SAAS;QACX,CAAC;QAED,kEAAkE;QAClE,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,OAAO,EAAE,GAAG,YAAY,CAAC,CAAC;QAE7E,MAAM,MAAM,GAAG;YACb,GAAG,UAAU;YACb,OAAO,EAAE,aAAa;SACvB,CAAC;QAEF,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import type { ParamListBase, StackNavigationState } from '@react-navigation/native';\n\nimport type { NativeStackDescriptorMap } from '../descriptors-context';\nimport type { CompositionRegistry } from './types';\n\n/**\n * Merges composition component options into navigation descriptors.\n *\n * For each descriptor:\n * 1. If no composition options registered → pass through unchanged\n * 2. If route is preloaded AND not focused → skip composition (pass through)\n * 3. Otherwise → merge descriptor.options with composition options (composition wins)\n */\nexport function mergeOptions(\n descriptors: NativeStackDescriptorMap,\n registry: CompositionRegistry,\n state: StackNavigationState<ParamListBase>\n): NativeStackDescriptorMap {\n const result: NativeStackDescriptorMap = {};\n const focusedKey = state.routes[state.index]?.key;\n\n for (const key in descriptors) {\n const descriptor = descriptors[key];\n const routeOptions = registry[key];\n\n // No composition options or empty array → pass through\n if (!routeOptions || routeOptions.length === 0) {\n result[key] = descriptor;\n continue;\n }\n\n // Check if route is preloaded and not focused → skip composition\n const isPreloaded = state.preloadedRoutes?.some((r) => r.key === key) ?? false;\n if (isPreloaded && key !== focusedKey) {\n result[key] = descriptor;\n continue;\n }\n\n // Merge: descriptor options as base, composition options override\n const mergedOptions = Object.assign({}, descriptor.options, ...routeOptions);\n\n const merged = {\n ...descriptor,\n options: mergedOptions,\n };\n\n result[key] = merged;\n }\n\n return result;\n}\n"]}

View File

@@ -0,0 +1,25 @@
import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';
/**
* Registry mapping route keys to composition component options.
*
* Structure: Record<routeKey, options[]>
*
* Each composition component (Title, BackButton, Header, Toolbar) registers
* its memoized options object. Array order reflects registration order,
* so later registrations override earlier ones during merge.
*
* @internal
*/
export type CompositionRegistry = Record<string, Partial<NativeStackNavigationOptions>[]>;
/** @internal */
export interface CompositionContextValue {
/**
* Register or update options for a composition component.
*/
set(routeKey: string, options: Partial<NativeStackNavigationOptions>): void;
/**
* Remove a composition component's options by reference (should be called on unmount).
*/
unset(routeKey: string, options: Partial<NativeStackNavigationOptions>): void;
}
//# sourceMappingURL=types.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/fork/native-stack/composition-options/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAEnF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,4BAA4B,CAAC,EAAE,CAAC,CAAC;AAE1F,gBAAgB;AAChB,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,4BAA4B,CAAC,GAAG,IAAI,CAAC;IAE5E;;OAEG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,4BAA4B,CAAC,GAAG,IAAI,CAAC;CAC/E"}

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/fork/native-stack/composition-options/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { NativeStackNavigationOptions } from '@react-navigation/native-stack';\n\n/**\n * Registry mapping route keys to composition component options.\n *\n * Structure: Record<routeKey, options[]>\n *\n * Each composition component (Title, BackButton, Header, Toolbar) registers\n * its memoized options object. Array order reflects registration order,\n * so later registrations override earlier ones during merge.\n *\n * @internal\n */\nexport type CompositionRegistry = Record<string, Partial<NativeStackNavigationOptions>[]>;\n\n/** @internal */\nexport interface CompositionContextValue {\n /**\n * Register or update options for a composition component.\n */\n set(routeKey: string, options: Partial<NativeStackNavigationOptions>): void;\n\n /**\n * Remove a composition component's options by reference (should be called on unmount).\n */\n unset(routeKey: string, options: Partial<NativeStackNavigationOptions>): void;\n}\n"]}

View File

@@ -0,0 +1,17 @@
import { type NavigatorTypeBagBase, type ParamListBase, type StackNavigationState, type StaticConfig, type TypedNavigator } from '@react-navigation/native';
import { type NativeStackNavigationEventMap, type NativeStackNavigationOptions, type NativeStackNavigationProp, type NativeStackNavigatorProps } from '@react-navigation/native-stack';
import * as React from 'react';
declare function NativeStackNavigator({ id, initialRouteName, children, layout, screenListeners, screenOptions, screenLayout, UNSTABLE_router, ...rest }: NativeStackNavigatorProps): React.JSX.Element;
export declare function createNativeStackNavigator<const ParamList extends ParamListBase, const NavigatorID extends string | undefined = undefined, const TypeBag extends NavigatorTypeBagBase = {
ParamList: ParamList;
NavigatorID: NavigatorID;
State: StackNavigationState<ParamList>;
ScreenOptions: NativeStackNavigationOptions;
EventMap: NativeStackNavigationEventMap;
NavigationList: {
[RouteName in keyof ParamList]: NativeStackNavigationProp<ParamList, RouteName, NavigatorID>;
};
Navigator: typeof NativeStackNavigator;
}, const Config extends StaticConfig<TypeBag> = StaticConfig<TypeBag>>(config?: Config): TypedNavigator<TypeBag, Config>;
export {};
//# sourceMappingURL=createNativeStackNavigator.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"createNativeStackNavigator.d.ts","sourceRoot":"","sources":["../../../src/fork/native-stack/createNativeStackNavigator.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAGlB,KAAK,oBAAoB,EAGzB,KAAK,YAAY,EACjB,KAAK,cAAc,EAEpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,EAE9B,KAAK,yBAAyB,EAC/B,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,iBAAS,oBAAoB,CAAC,EAC5B,EAAE,EACF,gBAAgB,EAChB,QAAQ,EACR,MAAM,EACN,eAAe,EACf,aAAa,EACb,YAAY,EACZ,eAAe,EACf,GAAG,IAAI,EACR,EAAE,yBAAyB,qBAwH3B;AAED,wBAAgB,0BAA0B,CACxC,KAAK,CAAC,SAAS,SAAS,aAAa,EACrC,KAAK,CAAC,WAAW,SAAS,MAAM,GAAG,SAAS,GAAG,SAAS,EACxD,KAAK,CAAC,OAAO,SAAS,oBAAoB,GAAG;IAC3C,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACvC,aAAa,EAAE,4BAA4B,CAAC;IAC5C,QAAQ,EAAE,6BAA6B,CAAC;IACxC,cAAc,EAAE;SACb,SAAS,IAAI,MAAM,SAAS,GAAG,yBAAyB,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC;KAC7F,CAAC;IACF,SAAS,EAAE,OAAO,oBAAoB,CAAC;CACxC,EACD,KAAK,CAAC,MAAM,SAAS,YAAY,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,EAClE,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAElD"}

View File

@@ -0,0 +1,143 @@
"use strict";
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;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.createNativeStackNavigator = createNativeStackNavigator;
const native_1 = require("@react-navigation/native");
const native_stack_1 = require("@react-navigation/native-stack");
const expo_glass_effect_1 = require("expo-glass-effect");
const React = __importStar(require("react"));
const composition_options_1 = require("./composition-options");
const descriptors_context_1 = require("./descriptors-context");
const usePreviewTransition_1 = require("./usePreviewTransition");
const navigationParams_1 = require("../../navigationParams");
const GLASS = (0, expo_glass_effect_1.isLiquidGlassAvailable)();
function NativeStackNavigator({ id, initialRouteName, children, layout, screenListeners, screenOptions, screenLayout, UNSTABLE_router, ...rest }) {
const { state, describe, descriptors, navigation, NavigationContent } = (0, native_1.useNavigationBuilder)(native_1.StackRouter, {
id,
initialRouteName,
children,
layout,
screenListeners,
screenOptions,
screenLayout,
UNSTABLE_router,
});
React.useEffect(() =>
// @ts-expect-error: there may not be a tab navigator in parent
navigation?.addListener?.('tabPress', (e) => {
const isFocused = navigation.isFocused();
// Run the operation in the next frame so we're sure all listeners have been run
// This is necessary to know if preventDefault() has been called
requestAnimationFrame(() => {
if (state.index > 0 && isFocused && !e.defaultPrevented) {
// When user taps on already focused tab and we're inside the tab,
// reset the stack to replicate native behaviour
// START FORK
// navigation.dispatch({
// ...StackActions.popToTop(),
// target: state.key,
// });
// The popToTop will be automatically triggered on native side for native tabs
if (e.data?.__internalTabsType !== 'native') {
navigation.dispatch({
...native_1.StackActions.popToTop(),
target: state.key,
});
}
// END FORK
}
});
}), [navigation, state.index, state.key]);
// START FORK
const { computedState, computedDescriptors, navigationWrapper } = (0, usePreviewTransition_1.usePreviewTransition)(state, navigation, descriptors, describe);
// Map internal gesture option to React Navigation's gestureEnabled option
// This allows Expo Router to override gesture behavior without affecting user settings
const finalDescriptors = React.useMemo(() => {
let needsNewMap = false;
const result = {};
for (const key of Object.keys(computedDescriptors)) {
const descriptor = computedDescriptors[key];
const options = descriptor.options;
const internalGestureEnabled = options?.[navigationParams_1.INTERNAL_EXPO_ROUTER_GESTURE_ENABLED_OPTION_NAME];
const needsGestureFix = internalGestureEnabled !== undefined;
const needsGlassFix = GLASS && options?.presentation === 'formSheet';
if (needsGestureFix || needsGlassFix) {
needsNewMap = true;
const newOptions = { ...options };
if (needsGestureFix) {
newOptions.gestureEnabled = internalGestureEnabled;
}
if (needsGlassFix) {
newOptions.headerTransparent ??= true;
newOptions.contentStyle ??= { backgroundColor: 'transparent' };
newOptions.headerShadowVisible ??= false;
newOptions.headerLargeTitleShadowVisible ??= false;
}
result[key] = { ...descriptor, options: newOptions };
}
else {
result[key] = descriptor;
}
}
return needsNewMap ? result : computedDescriptors;
}, [computedDescriptors]);
const { registry, contextValue } = (0, composition_options_1.useCompositionRegistry)();
const mergedDescriptors = React.useMemo(() => (0, composition_options_1.mergeOptions)(finalDescriptors, registry, computedState), [finalDescriptors, computedState, registry]);
// END FORK
return (
// START FORK
<descriptors_context_1.DescriptorsContext value={descriptors}>
{/* END FORK */}
<NavigationContent>
<composition_options_1.CompositionContext value={contextValue}>
<native_stack_1.NativeStackView {...rest}
// START FORK
state={computedState} navigation={navigationWrapper} descriptors={mergedDescriptors}
// state={state}
// navigation={navigation}
// descriptors={descriptors}
// END FORK
describe={describe}/>
</composition_options_1.CompositionContext>
</NavigationContent>
{/* START FORK */}
</descriptors_context_1.DescriptorsContext>
// END FORK
);
}
function createNativeStackNavigator(config) {
return (0, native_1.createNavigatorFactory)(NativeStackNavigator)(config);
}
//# sourceMappingURL=createNativeStackNavigator.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
import type { Descriptor, ParamListBase, RouteProp } from '@react-navigation/native';
import type { NativeStackNavigationOptions, NativeStackNavigationProp } from '@react-navigation/native-stack';
export type NativeStackDescriptor = Descriptor<NativeStackNavigationOptions, NativeStackNavigationProp<ParamListBase>, RouteProp<ParamListBase>>;
export type NativeStackDescriptorMap = {
[key: string]: NativeStackDescriptor;
};
export declare const DescriptorsContext: import("react").Context<NativeStackDescriptorMap>;
//# sourceMappingURL=descriptors-context.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"descriptors-context.d.ts","sourceRoot":"","sources":["../../../src/fork/native-stack/descriptors-context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrF,OAAO,KAAK,EACV,4BAA4B,EAC5B,yBAAyB,EAC1B,MAAM,gCAAgC,CAAC;AAIxC,MAAM,MAAM,qBAAqB,GAAG,UAAU,CAC5C,4BAA4B,EAC5B,yBAAyB,CAAC,aAAa,CAAC,EACxC,SAAS,CAAC,aAAa,CAAC,CACzB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,CAAC;CACtC,CAAC;AAEF,eAAO,MAAM,kBAAkB,mDAA8C,CAAC"}

View File

@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DescriptorsContext = void 0;
const react_1 = require("react");
exports.DescriptorsContext = (0, react_1.createContext)({});
//# sourceMappingURL=descriptors-context.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"descriptors-context.js","sourceRoot":"","sources":["../../../src/fork/native-stack/descriptors-context.tsx"],"names":[],"mappings":";;;AAKA,iCAAsC;AAazB,QAAA,kBAAkB,GAAG,IAAA,qBAAa,EAA2B,EAAE,CAAC,CAAC","sourcesContent":["import type { Descriptor, ParamListBase, RouteProp } from '@react-navigation/native';\nimport type {\n NativeStackNavigationOptions,\n NativeStackNavigationProp,\n} from '@react-navigation/native-stack';\nimport { createContext } from 'react';\n\n// Copied from @react-navigation/native\nexport type NativeStackDescriptor = Descriptor<\n NativeStackNavigationOptions,\n NativeStackNavigationProp<ParamListBase>,\n RouteProp<ParamListBase>\n>;\n\nexport type NativeStackDescriptorMap = {\n [key: string]: NativeStackDescriptor;\n};\n\nexport const DescriptorsContext = createContext<NativeStackDescriptorMap>({});\n"]}

View File

@@ -0,0 +1,21 @@
import type { ParamListBase, StackNavigationState } from '@react-navigation/native';
import type { NativeStackDescriptor, NativeStackDescriptorMap } from './descriptors-context';
/** Mirrors the `describe` function returned by `useNavigationBuilder` */
type DescribeFn = (route: StackNavigationState<ParamListBase>['preloadedRoutes'][number], placeholder: boolean) => NativeStackDescriptor;
/**
* Manages the preview transition state for link previews.
*
* Tracks when a preloaded screen is transitioning on the native side (after
* the preview is committed) but before React Navigation state is updated.
* During this window, the hook synthesizes state/descriptors to keep native
* and JS state in sync.
*/
export declare function usePreviewTransition<TNavigation extends {
emit: (...args: any[]) => any;
}>(state: StackNavigationState<ParamListBase>, navigation: TNavigation, descriptors: NativeStackDescriptorMap, describe: DescribeFn): {
computedState: StackNavigationState<ParamListBase>;
computedDescriptors: NativeStackDescriptorMap;
navigationWrapper: TNavigation;
};
export {};
//# sourceMappingURL=usePreviewTransition.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"usePreviewTransition.d.ts","sourceRoot":"","sources":["../../../src/fork/native-stack/usePreviewTransition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAGpF,OAAO,KAAK,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAG7F,yEAAyE;AACzE,KAAK,UAAU,GAAG,CAChB,KAAK,EAAE,oBAAoB,CAAC,aAAa,CAAC,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,EACrE,WAAW,EAAE,OAAO,KACjB,qBAAqB,CAAC;AAE3B;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,SAAS;IAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAA;CAAE,EACxF,KAAK,EAAE,oBAAoB,CAAC,aAAa,CAAC,EAC1C,UAAU,EAAE,WAAW,EACvB,WAAW,EAAE,wBAAwB,EACrC,QAAQ,EAAE,UAAU;;;;EAuFrB"}

View File

@@ -0,0 +1,119 @@
"use strict";
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;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.usePreviewTransition = usePreviewTransition;
const React = __importStar(require("react"));
const LinkPreviewContext_1 = require("../../link/preview/LinkPreviewContext");
/**
* Manages the preview transition state for link previews.
*
* Tracks when a preloaded screen is transitioning on the native side (after
* the preview is committed) but before React Navigation state is updated.
* During this window, the hook synthesizes state/descriptors to keep native
* and JS state in sync.
*/
function usePreviewTransition(state, navigation, descriptors, describe) {
const { openPreviewKey, setOpenPreviewKey } = (0, LinkPreviewContext_1.useLinkPreviewContext)();
// Track the preview screen currently transitioning on the native side
const [previewTransitioningScreenId, setPreviewTransitioningScreenId] = React.useState();
React.useEffect(() => {
if (previewTransitioningScreenId) {
// State was updated after the preview transition
if (state.routes.some((route) => route.key === previewTransitioningScreenId)) {
// No longer need to track the preview transitioning screen
setPreviewTransitioningScreenId(undefined);
}
}
}, [state, previewTransitioningScreenId]);
const navigationWrapper = React.useMemo(() => {
if (openPreviewKey) {
const emit = (...args) => {
const { target, type, data } = args[0];
if (target === openPreviewKey && data && 'closing' in data && !data.closing) {
// onWillAppear
if (type === 'transitionStart') {
// The screen from preview will appear, so we need to start tracking it
setPreviewTransitioningScreenId(openPreviewKey);
}
// onAppear
else if (type === 'transitionEnd') {
// The screen from preview appeared.
// We can now restore the stack animation
setOpenPreviewKey(undefined);
}
}
return navigation.emit(...args);
};
return {
...navigation,
emit,
};
}
return navigation;
}, [navigation, openPreviewKey, setOpenPreviewKey]);
const { computedState, computedDescriptors } = React.useMemo(() => {
// The preview screen was pushed on the native side, but react-navigation state was not updated yet
if (previewTransitioningScreenId) {
const preloadedRoute = state.preloadedRoutes.find((route) => route.key === previewTransitioningScreenId);
if (preloadedRoute) {
const newState = {
...state,
// On native side the screen is already pushed, so we need to update the state
preloadedRoutes: state.preloadedRoutes.filter((route) => route.key !== previewTransitioningScreenId),
routes: [...state.routes, preloadedRoute],
index: state.index + 1,
};
const newDescriptors = previewTransitioningScreenId in descriptors
? descriptors
: {
...descriptors,
// We need to add the descriptor. For react-navigation this is still preloaded screen
// Replicating the logic from https://github.com/react-navigation/react-navigation/blob/eaf1100ac7d99cb93ba11a999549dd0752809a78/packages/native-stack/src/views/NativeStackView.native.tsx#L489
[previewTransitioningScreenId]: describe(preloadedRoute, true),
};
return {
computedState: newState,
computedDescriptors: newDescriptors,
};
}
}
return {
computedState: state,
computedDescriptors: descriptors,
};
}, [state, previewTransitioningScreenId, describe, descriptors]);
return { computedState, computedDescriptors, navigationWrapper };
}
//# sourceMappingURL=usePreviewTransition.js.map

File diff suppressed because one or more lines are too long