diff --git a/apps/mobile/deps/react-native-screens-5.0.0-t3.45.tgz b/apps/mobile/deps/react-native-screens-5.0.0-t3.45.tgz
deleted file mode 100644
index 2e076b177f3f..000000000000
Binary files a/apps/mobile/deps/react-native-screens-5.0.0-t3.45.tgz and /dev/null differ
diff --git a/apps/mobile/deps/react-native-screens-5.0.0-t3.48.tgz b/apps/mobile/deps/react-native-screens-5.0.0-t3.48.tgz
new file mode 100644
index 000000000000..f1eb3858e986
Binary files /dev/null and b/apps/mobile/deps/react-native-screens-5.0.0-t3.48.tgz differ
diff --git a/apps/mobile/package.json b/apps/mobile/package.json
index e91ec70d0ba1..f5e817165b95 100644
--- a/apps/mobile/package.json
+++ b/apps/mobile/package.json
@@ -127,7 +127,7 @@
"react-native-pdf-jsi": "5.0.0",
"react-native-reanimated": "4.7.1",
"react-native-safe-area-context": "~5.10.1",
- "react-native-screens": "file:deps/react-native-screens-5.0.0-t3.45.tgz",
+ "react-native-screens": "file:deps/react-native-screens-5.0.0-t3.48.tgz",
"react-native-svg": "15.16.0",
"react-native-webview": "14.0.1",
"react-native-worklets": "0.13.0",
diff --git a/apps/mobile/src/components/ui/AndroidScreenHeader.tsx b/apps/mobile/src/components/ui/AndroidScreenHeader.tsx
index 1b259f1ecbfa..7931717682fa 100644
--- a/apps/mobile/src/components/ui/AndroidScreenHeader.tsx
+++ b/apps/mobile/src/components/ui/AndroidScreenHeader.tsx
@@ -1,7 +1,7 @@
import { AppActivityIndicator } from "./AppActivityIndicator";
import { Column, Row, Text as NativeText, RNHostView } from "@expo/ui/jetpack-compose";
import { weight } from "@expo/ui/jetpack-compose/modifiers";
-import { useState, type ReactNode } from "react";
+import { use, useState, type ReactNode } from "react";
import { View } from "react-native";
import type { AppSymbolName } from "./AppSymbol";
@@ -12,6 +12,7 @@ import { splitAndroidHeaderActions } from "./headerMenu.android";
import { useScaledTextRole } from "../../features/settings/appearance/useScaledTextRole";
import { useToolbarLayout } from "./useToolbarLayout";
import { useControlTheme } from "./useControlTheme";
+import { RoutedFormSheetContext } from "./RoutedFormSheetContext";
export interface AndroidHeaderAction {
readonly accessibilityLabel: string;
@@ -50,7 +51,8 @@ export function AndroidScreenHeader(props: {
const { colors } = useControlTheme();
const titleTypography = useScaledTextRole("title");
const subtitleTypography = useScaledTextRole("label");
- const { paddingTop, paddingBottom } = useToolbarLayout(props.embedded);
+ const inFormSheet = use(RoutedFormSheetContext);
+ const { paddingTop, paddingBottom } = useToolbarLayout(props.embedded || inFormSheet);
const [headerWidth, setHeaderWidth] = useState(0);
const { visibleActions, overflowActions } = splitAndroidHeaderActions(
props.actions ?? [],
@@ -67,6 +69,12 @@ export function AndroidScreenHeader(props: {
borderBottomWidth: props.hideBottomBorder ? 0 : undefined,
}}
>
+ {inFormSheet ? (
+
+ ) : null}
- {/* Android FormSheet does not bound flex children. Material drags target the first scroll view, so place content before the header. */}
-
- {props.children}
- setIsOpen(false)} hideBottomBorder />
-
-
+
+ {/* Android FormSheet does not bound flex children. Material drags target the first scroll view, so place content before the header. */}
+
+ {props.children}
+ setIsOpen(false)}
+ hideBottomBorder
+ />
+
+
+
);
}
diff --git a/apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx b/apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx
index 98bd85d8d9e7..53d2fb3e1d71 100644
--- a/apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx
+++ b/apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx
@@ -1,3 +1,7 @@
+import {
+ WorkspaceColumnsRendererContext,
+ WorkspacePresentationHostContext,
+} from "./workspace-presentation-context";
import { useAndroidFloatingTabs } from "../settings/appearance/AppearancePreferencesProvider";
import { SafeAreaInsetsContext, useSafeAreaInsets } from "react-native-safe-area-context";
import { AdaptiveWorkspaceContext, useAdaptiveWorkspaceLayout } from "./adaptive-workspace-context";
@@ -176,6 +180,7 @@ function AdaptiveWorkspaceLayoutContent(
const floatingTabsEnabled = useAndroidFloatingTabs();
const projectGroupingMode = props.projectGroupingMode;
const nativeWorkspace = use(NativeWorkspaceModeContext);
+ const usesPresentationHost = use(WorkspacePresentationHostContext);
const windowDimensions = useWindowDimensions();
const nativeMetrics = useNativeLayoutMetrics();
const { width: viewportWidth, height } = nativeMetrics ?? windowDimensions;
@@ -839,181 +844,185 @@ function AdaptiveWorkspaceLayoutContent(
);
}
- return (
- (
+
-
-
-
-
- {shouldRenderNavigationRail ? (
-
- ) : null}
- {shouldRenderPrimarySidebar && layout.listPaneWidth !== null ? (
-
+ {shouldRenderNavigationRail ? (
+
+ ) : null}
+ {shouldRenderPrimarySidebar && layout.listPaneWidth !== null ? (
+
+
+ (
+
+ )}
+ >
+
-
- (
-
- )}
- >
-
-
-
-
-
-
- {/* Keep the pill under the content throughout the sidebar's clipping animation. */}
- {floatingTabsEnabled && !workspacePage ? (
-
- ) : null}
-
-
+
+
+
+
+
+ {/* Keep the pill under the content throughout the sidebar's clipping animation. */}
+ {floatingTabsEnabled && !workspacePage ? (
+
) : null}
-
+
+ ) : null}
+
+
+ {/* Android holds the content still, so its floating controls keep its width. */}
+
+
-
- {/* Android holds the content still, so its floating controls keep its width. */}
-
-
- {/* Compact Settings keeps the bottom navigation under all of its pages. */}
-
-
- {props.children}
-
-
- {floatingTabsEnabled &&
- (compactAndroidSettings || (layout.usesSplitView && workspacePage)) ? (
-
- ) : compactAndroidSettings ? (
-
- ) : null}
-
-
-
-
-
- {shouldRenderNavigationRail && navigationRailWidth > 0 ? (
- // The rail reserves its slot above and draws over the panes, so it can widen over
- // the list in place. It takes the whole workspace only while it is open.
-
-
+ {children}
+
+
+ {floatingTabsEnabled &&
+ (compactAndroidSettings || (layout.usesSplitView && workspacePage)) ? (
+
-
- ) : null}
-
+ ) : compactAndroidSettings ? (
+
+ ) : null}
+
+
+
+
+
+ {shouldRenderNavigationRail && navigationRailWidth > 0 ? (
+ // The rail reserves its slot above and draws over the panes, so it can widen over
+ // the list in place. It takes the whole workspace only while it is open.
+
+
+
+ ) : null}
+
+ );
+
+ return (
+
+
+
+ {usesPresentationHost ? (
+
+ {props.children}
+
+ ) : (
+ renderColumns(props.children)
+ )}
diff --git a/apps/mobile/src/features/layout/createWorkspaceStackNavigator.android.tsx b/apps/mobile/src/features/layout/createWorkspaceStackNavigator.android.tsx
new file mode 100644
index 000000000000..765b23243798
--- /dev/null
+++ b/apps/mobile/src/features/layout/createWorkspaceStackNavigator.android.tsx
@@ -0,0 +1,152 @@
+import {
+ createNavigatorFactory,
+ StackRouter,
+ useNavigationBuilder,
+ type NavigatorTypeBagBase,
+ type ParamListBase,
+ type StackActionHelpers,
+ type StackNavigationState,
+ type StackRouterOptions,
+ type StaticConfig,
+ type TypedNavigator,
+} from "@react-navigation/native";
+import {
+ NativeStackView,
+ type NativeStackNavigationEventMap,
+ type NativeStackNavigationOptions,
+ type NativeStackNavigatorProps,
+ type NativeStackTypeBag,
+} from "@react-navigation/native-stack";
+import { use, type ComponentProps } from "react";
+
+import { RoutedFormSheetContext } from "../../components/ui/RoutedFormSheetContext";
+
+import { projectStackPresentation } from "../../native/workspace-stack-projection";
+import {
+ WorkspaceColumnsRendererContext,
+ WorkspacePresentationHostContext,
+} from "./workspace-presentation-context";
+
+type ViewProps = ComponentProps;
+type Descriptor = ViewProps["descriptors"][string];
+type Route = ViewProps["state"]["routes"][number];
+
+function WorkspaceStackView(props: ViewProps) {
+ const renderColumns = use(WorkspaceColumnsRendererContext);
+ if (!renderColumns) return ;
+
+ const isOverlay = (route: Route) => {
+ const descriptor = props.descriptors[route.key] ?? props.describe(route, true);
+ const presentation = descriptor.options.presentation;
+ return presentation !== undefined && presentation !== "card";
+ };
+ const projection = projectStackPresentation(props.state, isOverlay);
+ const workspaceRoutes = projection.workspace;
+ const visibleRoute = workspaceRoutes.at(-1);
+ if (!visibleRoute) return ;
+
+ const visibleDescriptor = props.descriptors[visibleRoute.key]!;
+ const baseRoute = { key: `${props.state.key}:workspace`, name: "Workspace" };
+ const baseDescriptor: Descriptor = {
+ ...visibleDescriptor,
+ options: { headerShown: false, freezeOnBlur: false },
+ render: () =>
+ renderColumns(
+ !isOverlay(route)),
+ }}
+ />,
+ ),
+ };
+ const routes = [baseRoute, ...projection.overlays];
+ return (
+
+ );
+}
+
+function WorkspaceStackNavigator({
+ id,
+ initialRouteName,
+ UNSTABLE_routeNamesChangeBehavior,
+ children,
+ layout,
+ screenListeners,
+ screenOptions,
+ screenLayout,
+ UNSTABLE_router,
+ ...rest
+}: NativeStackNavigatorProps) {
+ const { state, describe, descriptors, navigation, NavigationContent } = useNavigationBuilder<
+ StackNavigationState,
+ StackRouterOptions,
+ StackActionHelpers,
+ NativeStackNavigationOptions,
+ NativeStackNavigationEventMap
+ >(StackRouter, {
+ id,
+ initialRouteName,
+ UNSTABLE_routeNamesChangeBehavior,
+ children,
+ layout,
+ screenListeners,
+ screenOptions,
+ screenLayout,
+ UNSTABLE_router,
+ });
+ return (
+
+
+ [
+ key,
+ descriptor.options.presentation === "formSheet"
+ ? {
+ ...descriptor,
+ render: () => (
+ {descriptor.render()}
+ ),
+ }
+ : descriptor,
+ ]),
+ )}
+ navigation={navigation}
+ />
+
+
+ );
+}
+
+type WorkspaceTypeBag<
+ ParamList extends ParamListBase,
+ NavigatorID extends string | undefined,
+> = Omit, "Navigator"> & {
+ Navigator: typeof WorkspaceStackNavigator;
+};
+
+export function createWorkspaceStackNavigator<
+ const ParamList extends ParamListBase,
+ const NavigatorID extends string | undefined = string | undefined,
+ const TypeBag extends NavigatorTypeBagBase = WorkspaceTypeBag,
+ const Config extends StaticConfig = StaticConfig,
+>(config?: Config): TypedNavigator {
+ return createNavigatorFactory(WorkspaceStackNavigator)(config);
+}
diff --git a/apps/mobile/src/features/layout/workspace-presentation-context.tsx b/apps/mobile/src/features/layout/workspace-presentation-context.tsx
new file mode 100644
index 000000000000..ec1544dce821
--- /dev/null
+++ b/apps/mobile/src/features/layout/workspace-presentation-context.tsx
@@ -0,0 +1,7 @@
+import { createContext, type ReactElement, type ReactNode } from "react";
+
+/** Android's native presentation stack surrounds all workspace columns. */
+export const WorkspacePresentationHostContext = createContext(false);
+export const WorkspaceColumnsRendererContext = createContext<
+ ((children: ReactNode) => ReactElement) | null
+>(null);
diff --git a/apps/mobile/src/features/threads/git/GitCommitSheet.tsx b/apps/mobile/src/features/threads/git/GitCommitSheet.tsx
index be0912a6ebea..68ea161b0110 100644
--- a/apps/mobile/src/features/threads/git/GitCommitSheet.tsx
+++ b/apps/mobile/src/features/threads/git/GitCommitSheet.tsx
@@ -1,3 +1,4 @@
+import { ScreenContent } from "../../../components/ui/ScreenContent";
import { SheetHeader } from "../../../components/ui/SheetHeader";
import { Button } from "../../../components/ui/Button";
import { useNavigation, type StaticScreenProps } from "@react-navigation/native";
@@ -84,145 +85,149 @@ export function GitCommitSheet(_props: GitCommitSheetProps) {
onCancel={() => navigation.goBack()}
accessibilityLabel="Cancel commit"
/>
-
- {isDefaultRef ? (
-
- You’re on the default branch. You can create a new branch when committing.
-
- ) : null}
-
- Commit message
-
-
- Leave empty to generate a message automatically.
-
-
-
-
-
- Changed files
-
- {selectedFiles.length} of {allFiles.length} selected · +
- {formatDiffCount(selectedInsertions)} −{formatDiffCount(selectedDeletions)}
-
-
- {allFiles.length > 0 ? (
-
-
-
- {name}
-
- {directory ? (
+ {included ? (
+
+ ) : null}
+
+
- {directory}
+ {name}
- ) : null}
-
-
-
- +{formatDiffCount(file.insertions)}
-
-
- −{formatDiffCount(file.deletions)}
-
-
-
- );
- })
- )}
-
-
- void runCommitAction(false)}
- />
- void runCommitAction(true)}
- />
-
-
+ {directory ? (
+
+ {directory}
+
+ ) : null}
+
+
+
+ +{formatDiffCount(file.insertions)}
+
+
+ −{formatDiffCount(file.deletions)}
+
+
+
+ );
+ })
+ )}
+
+
+ void runCommitAction(false)}
+ />
+ void runCommitAction(true)}
+ />
+
+
+
);
}
diff --git a/apps/mobile/src/native/workspace-stack-projection.test.ts b/apps/mobile/src/native/workspace-stack-projection.test.ts
index a3c44d16fb75..023afc637c01 100644
--- a/apps/mobile/src/native/workspace-stack-projection.test.ts
+++ b/apps/mobile/src/native/workspace-stack-projection.test.ts
@@ -7,6 +7,7 @@ import {
nativeStackPopAction,
nativeWorkspacePopAction,
nativeWorkspacePopCount,
+ projectStackPresentation,
projectWorkspaceStack,
partitionStackPresentations,
reconcileStackScreens,
@@ -40,6 +41,65 @@ function history(
};
}
+describe("workspace presentation envelope", () => {
+ const isOverlay = (route: { name: string }) => route.name === "ReviewSheet";
+
+ it("keeps card settings in the detail history and restores it after system Back closes a sheet", () => {
+ const router = StackRouter({});
+ const state = history([home, thread, settings]);
+ const routerOptions = {
+ routeNames: [...state.routeNames, "ReviewSheet", "ReviewDetails"],
+ routeParamList: {},
+ routeGetIdList: {},
+ };
+ const opened = router.getStateForAction(
+ { ...state, routeNames: routerOptions.routeNames },
+ { type: "PUSH", payload: { name: "ReviewSheet" } },
+ routerOptions,
+ );
+ if (!opened || opened.stale !== false) throw new Error("Expected an opened sheet history");
+ const projection = projectStackPresentation(opened, isOverlay);
+ expect(projection.workspace).toEqual(state.routes);
+ expect(projection.workspace.at(-1)).toBe(settings);
+ expect(projection.overlays.map((route) => route.name)).toEqual(["ReviewSheet"]);
+ const closed = router.getStateForAction(opened, { type: "GO_BACK" }, routerOptions);
+ if (!closed || closed.stale !== false) throw new Error("Expected a restored workspace history");
+ expect(projectStackPresentation(closed, isOverlay)).toEqual({
+ workspace: state.routes,
+ overlays: [],
+ });
+ });
+
+ it("keeps pushed sheet pages above the workspace and dismisses the entire sheet group", () => {
+ const sheet = { key: "review", name: "ReviewSheet" };
+ const page = { key: "review-details", name: "ReviewDetails" };
+ const state = history([home, thread, sheet, page]);
+ expect(projectStackPresentation(state, isOverlay)).toEqual({
+ workspace: [home, thread],
+ overlays: [sheet, page],
+ });
+ const closed = StackRouter({}).getStateForAction(
+ state,
+ nativeWorkspacePopAction(state, sheet.key)!,
+ { routeNames: state.routeNames, routeParamList: {}, routeGetIdList: {} },
+ );
+ if (!closed || closed.stale !== false) throw new Error("Expected a dismissed sheet history");
+ expect(projectStackPresentation(closed, isOverlay)).toEqual({
+ workspace: [home, thread],
+ overlays: [],
+ });
+ expect(closed.routes[1]).toBe(thread);
+ });
+
+ it("preserves a cold-linked detail history without requiring a Home route", () => {
+ const sheet = { key: "review", name: "ReviewSheet" };
+ expect(projectStackPresentation(history([thread, files, sheet]), isOverlay)).toEqual({
+ workspace: [thread, files],
+ overlays: [sheet],
+ });
+ });
+});
+
describe("workspace router projection", () => {
it("keeps workspace flows beside Home and restores them after a modal closes", () => {
const draft = { key: "draft", name: "Thread", params: { draft: {} } };
diff --git a/apps/mobile/src/native/workspace-stack-projection.ts b/apps/mobile/src/native/workspace-stack-projection.ts
index 341a432b66b3..7d12cc89a31c 100644
--- a/apps/mobile/src/native/workspace-stack-projection.ts
+++ b/apps/mobile/src/native/workspace-stack-projection.ts
@@ -6,18 +6,29 @@ import type {
type Route = StackNavigationState["routes"][number];
-export function projectWorkspaceStack(
+/** Keep the presenting history mounted while modal routes cover the whole workspace. */
+export function projectStackPresentation(
state: StackNavigationState,
isOverlay: (route: Route) => boolean,
) {
const firstOverlay = state.routes.findIndex(isOverlay);
- const workspaceRoutes = state.routes.slice(0, firstOverlay < 0 ? undefined : firstOverlay);
+ return {
+ workspace: state.routes.slice(0, firstOverlay < 0 ? undefined : firstOverlay),
+ overlays: firstOverlay < 0 ? [] : state.routes.slice(firstOverlay),
+ };
+}
+
+/** Project one router history into native columns and a modal presentation stack. */
+export function projectWorkspaceStack(
+ state: StackNavigationState,
+ isOverlay: (route: Route) => boolean,
+) {
+ const { workspace: workspaceRoutes, overlays } = projectStackPresentation(state, isOverlay);
const primary = workspaceRoutes.find((route) => route.name === "Home");
// The Settings tab's route only selects what Home shows; its pages are the detail.
const detail = workspaceRoutes.filter(
(route) => route.name !== "Home" && route.name !== "Settings",
);
- const overlays = firstOverlay < 0 ? [] : state.routes.slice(firstOverlay);
return { primary, detail, overlays };
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c854ee336471..a7b5b20aa210 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -560,7 +560,7 @@ importers:
version: 7.5.1(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0)
'@react-navigation/native-stack':
specifier: 7.21.0
- version: 7.21.0(patch_hash=990d575444c4af2ce8218b3b7a8280fe244c03abbdb32b822a2e862f791dbf42)(fedae76d040d2e46f454f147f7fa3a09)
+ version: 7.21.0(patch_hash=990d575444c4af2ce8218b3b7a8280fe244c03abbdb32b822a2e862f791dbf42)(c96dd4885eac0393fe69fdf9aeb7f361)
'@t3tools/client-runtime':
specifier: workspace:*
version: link:../../packages/client-runtime
@@ -742,8 +742,8 @@ importers:
specifier: ~5.10.1
version: 5.10.1(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0)
react-native-screens:
- specifier: file:deps/react-native-screens-5.0.0-t3.45.tgz
- version: file:apps/mobile/deps/react-native-screens-5.0.0-t3.45.tgz(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0)
+ specifier: file:deps/react-native-screens-5.0.0-t3.48.tgz
+ version: file:apps/mobile/deps/react-native-screens-5.0.0-t3.48.tgz(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0)
react-native-svg:
specifier: 15.16.0
version: 15.16.0(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0)
@@ -10914,9 +10914,9 @@ packages:
react: '*'
react-native: '*'
- react-native-screens@file:apps/mobile/deps/react-native-screens-5.0.0-t3.45.tgz:
- resolution: {integrity: sha512-FgmMB7T2tb0pEKgdsRs5sRCIRfIOHFqEk3lqaRA53dYb51rxlE9utrAoxbUPHcAROAAP2QA55KUTD9V71SoNqA==, tarball: file:apps/mobile/deps/react-native-screens-5.0.0-t3.45.tgz}
- version: 5.0.0-t3.45
+ react-native-screens@file:apps/mobile/deps/react-native-screens-5.0.0-t3.48.tgz:
+ resolution: {integrity: sha512-DQa7yVsOye72bUNH4UVC3D8QicmOm+LMFLpZui6ZEnwU5wtlyEsqFX26kKSvDkpByAffQVIqqJ3s0QNCGNwF1A==, tarball: file:apps/mobile/deps/react-native-screens-5.0.0-t3.48.tgz}
+ version: 5.0.0-t3.48
peerDependencies:
react: '*'
react-native: '*'
@@ -15896,7 +15896,7 @@ snapshots:
optionalDependencies:
'@react-native-masked-view/masked-view': 0.3.2(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0)
- '@react-navigation/native-stack@7.21.0(patch_hash=990d575444c4af2ce8218b3b7a8280fe244c03abbdb32b822a2e862f791dbf42)(fedae76d040d2e46f454f147f7fa3a09)':
+ '@react-navigation/native-stack@7.21.0(patch_hash=990d575444c4af2ce8218b3b7a8280fe244c03abbdb32b822a2e862f791dbf42)(c96dd4885eac0393fe69fdf9aeb7f361)':
dependencies:
'@react-navigation/elements': 2.9.45(d8845bac868f4d8a58c8a8f12ad0d4a5)
'@react-navigation/native': 7.5.1(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0)
@@ -15904,7 +15904,7 @@ snapshots:
react: 19.3.0
react-native: 0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6)
react-native-safe-area-context: 5.10.1(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0)
- react-native-screens: file:apps/mobile/deps/react-native-screens-5.0.0-t3.45.tgz(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0)
+ react-native-screens: file:apps/mobile/deps/react-native-screens-5.0.0-t3.48.tgz(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0)
sf-symbols-typescript: 2.2.0
warn-once: 0.1.1
transitivePeerDependencies:
@@ -21476,7 +21476,7 @@ snapshots:
react: 19.3.0
react-native: 0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6)
- react-native-screens@file:apps/mobile/deps/react-native-screens-5.0.0-t3.45.tgz(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0):
+ react-native-screens@file:apps/mobile/deps/react-native-screens-5.0.0-t3.48.tgz(react-native@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.0(@babel/core@7.29.7(supports-color@8.1.1))(bufferutil@4.1.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(@types/react@19.3.0)(bufferutil@4.1.0)(react@19.3.0)(supports-color@8.1.1)(utf-8-validate@6.0.6))(react@19.3.0):
dependencies:
react: 19.3.0
react-freeze: 1.0.4(react@19.3.0)